]> git.proxmox.com Git - ceph.git/blob - ceph/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-tabs/cephfs-tabs.component.spec.ts
93853889a674b1d2ad72fab19ee5d0e316a96600
[ceph.git] / ceph / src / pybind / mgr / dashboard / frontend / src / app / ceph / cephfs / cephfs-tabs / cephfs-tabs.component.spec.ts
1 import { HttpClientTestingModule } from '@angular/common/http/testing';
2 import { Component, Input } from '@angular/core';
3 import { ComponentFixture, TestBed } from '@angular/core/testing';
4
5 import { TreeModule } from 'angular-tree-component';
6 import * as _ from 'lodash';
7 import { TabsModule } from 'ngx-bootstrap/tabs';
8 import { ToastrModule } from 'ngx-toastr';
9 import { of } from 'rxjs';
10
11 import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
12 import { CephfsService } from '../../../shared/api/cephfs.service';
13 import { ViewCacheStatus } from '../../../shared/enum/view-cache-status.enum';
14 import { CdTableSelection } from '../../../shared/models/cd-table-selection';
15 import { SharedModule } from '../../../shared/shared.module';
16 import { CephfsClientsComponent } from '../cephfs-clients/cephfs-clients.component';
17 import { CephfsDetailComponent } from '../cephfs-detail/cephfs-detail.component';
18 import { CephfsDirectoriesComponent } from '../cephfs-directories/cephfs-directories.component';
19 import { CephfsTabsComponent } from './cephfs-tabs.component';
20
21 describe('CephfsTabsComponent', () => {
22 let component: CephfsTabsComponent;
23 let fixture: ComponentFixture<CephfsTabsComponent>;
24 let service: CephfsService;
25 let data: {
26 standbys: string;
27 pools: any[];
28 ranks: any[];
29 mdsCounters: object;
30 name: string;
31 clients: { status: ViewCacheStatus; data: any[] };
32 };
33
34 let old: any;
35 const getReload: any = () => component['reloadSubscriber'];
36 const setReload = (sth?: any) => (component['reloadSubscriber'] = sth);
37 const mockRunOutside = () => {
38 component['subscribeInterval'] = () => {
39 // It's mocked because the rxjs timer subscription ins't called through the use of 'tick'.
40 setReload({
41 unsubscribed: false,
42 unsubscribe: () => {
43 old = getReload();
44 getReload().unsubscribed = true;
45 setReload();
46 }
47 });
48 component.refresh();
49 };
50 };
51
52 const setSelection = (selection: object[]) => {
53 component.selection.selected = selection;
54 component.ngOnChanges();
55 };
56
57 const selectFs = (id: number, name: string) => {
58 setSelection([
59 {
60 id,
61 mdsmap: {
62 info: {
63 something: {
64 name
65 }
66 }
67 }
68 }
69 ]);
70 };
71
72 const updateData = () => {
73 component['data'] = _.cloneDeep(data);
74 component.softRefresh();
75 };
76
77 @Component({ selector: 'cd-cephfs-chart', template: '' })
78 class CephfsChartStubComponent {
79 @Input()
80 mdsCounter: any;
81 }
82
83 configureTestBed({
84 imports: [
85 SharedModule,
86 TabsModule.forRoot(),
87 HttpClientTestingModule,
88 TreeModule,
89 ToastrModule.forRoot()
90 ],
91 declarations: [
92 CephfsTabsComponent,
93 CephfsChartStubComponent,
94 CephfsDetailComponent,
95 CephfsDirectoriesComponent,
96 CephfsClientsComponent
97 ],
98 providers: [i18nProviders]
99 });
100
101 beforeEach(() => {
102 fixture = TestBed.createComponent(CephfsTabsComponent);
103 component = fixture.componentInstance;
104 component.selection = new CdTableSelection();
105 data = {
106 standbys: 'b',
107 pools: [{}, {}],
108 ranks: [{}, {}, {}],
109 mdsCounters: { a: { name: 'a', x: [], y: [] } },
110 name: 'someFs',
111 clients: {
112 status: ViewCacheStatus.ValueOk,
113 data: [{}, {}, {}, {}]
114 }
115 };
116 service = TestBed.get(CephfsService);
117 spyOn(service, 'getTabs').and.callFake(() => of(data));
118
119 fixture.detectChanges();
120 mockRunOutside();
121 setReload(); // Clears rxjs timer subscription
122 });
123
124 it('should create', () => {
125 expect(component).toBeTruthy();
126 });
127
128 it('should resist invalid mds info', () => {
129 setSelection([
130 {
131 id: 3,
132 mdsmap: {
133 info: {}
134 }
135 }
136 ]);
137 expect(component.grafanaId).toBe(undefined);
138 });
139
140 it('should find out the grafana id', () => {
141 selectFs(2, 'otherMds');
142 expect(component.grafanaId).toBe('otherMds');
143 });
144
145 it('should set default values on id change before api request', () => {
146 const defaultDetails: Record<string, any> = {
147 standbys: '',
148 pools: [],
149 ranks: [],
150 mdsCounters: {},
151 name: ''
152 };
153 const defaultClients: Record<string, any> = {
154 data: [],
155 status: ViewCacheStatus.ValueNone
156 };
157 component['subscribeInterval'] = () => {};
158 updateData();
159 expect(component.clients).not.toEqual(defaultClients);
160 expect(component.details).not.toEqual(defaultDetails);
161 selectFs(2, 'otherMds');
162 expect(component.clients).toEqual(defaultClients);
163 expect(component.details).toEqual(defaultDetails);
164 });
165
166 it('should force data updates on tab change without api requests', () => {
167 const oldClients = component.clients;
168 const oldDetails = component.details;
169 updateData();
170 expect(service.getTabs).toHaveBeenCalledTimes(0);
171 expect(component.details).not.toBe(oldDetails);
172 expect(component.clients).not.toBe(oldClients);
173 });
174
175 describe('handling of id change', () => {
176 beforeEach(() => {
177 setReload(); // Clears rxjs timer subscription
178 selectFs(2, 'otherMds');
179 old = getReload(); // Gets current subscription
180 });
181
182 it('should have called getDetails once', () => {
183 expect(component.details.pools.length).toBe(2);
184 expect(service.getTabs).toHaveBeenCalledTimes(1);
185 });
186
187 it('should not subscribe to an new interval for the same selection', () => {
188 expect(component.id).toBe(2);
189 expect(component.grafanaId).toBe('otherMds');
190 selectFs(2, 'otherMds');
191 expect(component.id).toBe(2);
192 expect(component.grafanaId).toBe('otherMds');
193 expect(getReload()).toBe(old);
194 });
195
196 it('should subscribe to an new interval', () => {
197 selectFs(3, 'anotherMds');
198 expect(getReload()).not.toBe(old); // Holds an new object
199 });
200
201 it('should unsubscribe the old interval if it exists', () => {
202 selectFs(3, 'anotherMds');
203 expect(old.unsubscribed).toBe(true);
204 });
205
206 it('should not unsubscribe if no interval exists', () => {
207 expect(() => component.ngOnDestroy()).not.toThrow();
208 });
209
210 it('should request the details of the new id', () => {
211 expect(service.getTabs).toHaveBeenCalledWith(2);
212 });
213
214 it('should should unsubscribe on deselect', () => {
215 setSelection([]);
216 expect(old.unsubscribed).toBe(true);
217 expect(getReload()).toBe(undefined); // Cleared timer subscription
218 });
219 });
220 });