21910: Merge branch 'main' into 21910-remove-api_client_id
[arvados.git] / services / workbench2 / src / views-components / data-explorer / renderers.test.tsx
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import React from 'react';
6 import { mount, configure } from 'enzyme';
7 import { GroupMembersCount, ProcessStatus, ResourceFileSize } from './renderers';
8 import Adapter from "enzyme-adapter-react-16";
9 import { Provider } from 'react-redux';
10 import configureMockStore from 'redux-mock-store'
11 import { ResourceKind } from '../../models/resource';
12 import { ContainerRequestState as CR } from '../../models/container-request';
13 import { ContainerState as C } from '../../models/container';
14 import { ProcessStatus as PS } from '../../store/processes/process';
15 import { MuiThemeProvider } from '@material-ui/core';
16 import { CustomTheme } from 'common/custom-theme';
17 import { InlinePulser} from 'components/loading/inline-pulser';
18 import { ErrorIcon } from "components/icon/icon";
19
20 const middlewares = [];
21 const mockStore = configureMockStore(middlewares);
22
23 configure({ adapter: new Adapter() });
24
25 describe('renderers', () => {
26     let props: any = null;
27
28     describe('ProcessStatus', () => {
29         props = {
30             uuid: 'zzzzz-xvhdp-zzzzzzzzzzzzzzz',
31             theme: {
32                 customs: {
33                     colors: {
34                         // Color values are arbitrary, but they should be
35                         // representative of the colors used in the UI.
36                         green800: 'rgb(0, 255, 0)',
37                         red900: 'rgb(255, 0, 0)',
38                         orange: 'rgb(240, 173, 78)',
39                         grey600: 'rgb(128, 128, 128)',
40                     }
41                 },
42                 spacing: {
43                     unit: 8,
44                 },
45                 palette: {
46                     common: {
47                         white: 'rgb(255, 255, 255)',
48                     },
49                 },
50             },
51         };
52
53         [
54             // CR Status ; Priority ; C Status ; Exit Code ; C RuntimeStatus ; Expected label ; Expected bg color ; Expected fg color
55             [CR.COMMITTED, 1, C.RUNNING, null, {}, PS.RUNNING, props.theme.palette.common.white, props.theme.customs.colors.green800],
56             [CR.COMMITTED, 1, C.RUNNING, null, { error: 'whoops' }, PS.FAILING, props.theme.palette.common.white, props.theme.customs.colors.red900],
57             [CR.COMMITTED, 1, C.RUNNING, null, { warning: 'watch out!' }, PS.WARNING, props.theme.palette.common.white, props.theme.customs.colors.green800],
58             [CR.FINAL, 1, C.CANCELLED, null, {}, PS.CANCELLED, props.theme.customs.colors.red900, props.theme.palette.common.white],
59             [CR.FINAL, 1, C.COMPLETE, 137, {}, PS.FAILED, props.theme.customs.colors.red900, props.theme.palette.common.white],
60             [CR.FINAL, 1, C.COMPLETE, 0, {}, PS.COMPLETED, props.theme.customs.colors.green800, props.theme.palette.common.white],
61             [CR.COMMITTED, 0, C.LOCKED, null, {}, PS.ONHOLD, props.theme.customs.colors.grey600, props.theme.palette.common.white],
62             [CR.COMMITTED, 0, C.QUEUED, null, {}, PS.ONHOLD, props.theme.customs.colors.grey600, props.theme.palette.common.white],
63             [CR.COMMITTED, 1, C.LOCKED, null, {}, PS.QUEUED, props.theme.palette.common.white, props.theme.customs.colors.grey600],
64             [CR.COMMITTED, 1, C.QUEUED, null, {}, PS.QUEUED, props.theme.palette.common.white, props.theme.customs.colors.grey600],
65         ].forEach(([crState, crPrio, cState, exitCode, rs, eLabel, eColor, tColor]) => {
66             it(`should render the state label '${eLabel}' and color '${eColor}' for CR state=${crState}, priority=${crPrio}, C state=${cState}, exitCode=${exitCode} and RuntimeStatus=${JSON.stringify(rs)}`, () => {
67                 const containerUuid = 'zzzzz-dz642-zzzzzzzzzzzzzzz';
68                 const store = mockStore({
69                     resources: {
70                         [props.uuid]: {
71                             kind: ResourceKind.CONTAINER_REQUEST,
72                             state: crState,
73                             containerUuid: containerUuid,
74                             priority: crPrio,
75                         },
76                         [containerUuid]: {
77                             kind: ResourceKind.CONTAINER,
78                             state: cState,
79                             runtimeStatus: rs,
80                             exitCode: exitCode,
81                         },
82                     }
83                 });
84
85                 const wrapper = mount(<Provider store={store}>
86                     <ProcessStatus {...props} />
87                 </Provider>);
88
89                 expect(wrapper.text()).toEqual(eLabel);
90                 expect(getComputedStyle(wrapper.getDOMNode())
91                     .getPropertyValue('color')).toEqual(tColor);
92                 expect(getComputedStyle(wrapper.getDOMNode())
93                     .getPropertyValue('background-color')).toEqual(eColor);
94             });
95         })
96     });
97
98     describe('ResourceFileSize', () => {
99         beforeEach(() => {
100             props = {
101                 uuid: 'UUID',
102             };
103         });
104
105         it('should render collection fileSizeTotal', () => {
106             // given
107             const store = mockStore({
108                 resources: {
109                     [props.uuid]: {
110                         kind: ResourceKind.COLLECTION,
111                         fileSizeTotal: 100,
112                     }
113                 }
114             });
115
116             // when
117             const wrapper = mount(<Provider store={store}>
118                 <ResourceFileSize {...props}></ResourceFileSize>
119             </Provider>);
120
121             // then
122             expect(wrapper.text()).toContain('100 B');
123         });
124
125         it('should render 0 B as file size', () => {
126             // given
127             const store = mockStore({ resources: {} });
128
129             // when
130             const wrapper = mount(<Provider store={store}>
131                 <ResourceFileSize {...props}></ResourceFileSize>
132             </Provider>);
133
134             // then
135             expect(wrapper.text()).toContain('0 B');
136         });
137
138         it('should render empty string for non collection resource', () => {
139             // given
140             const store1 = mockStore({
141                 resources: {
142                     [props.uuid]: {
143                         kind: ResourceKind.PROJECT,
144                     }
145                 }
146             });
147             const store2 = mockStore({
148                 resources: {
149                     [props.uuid]: {
150                         kind: ResourceKind.PROJECT,
151                     }
152                 }
153             });
154
155             // when
156             const wrapper1 = mount(<Provider store={store1}>
157                 <ResourceFileSize {...props}></ResourceFileSize>
158             </Provider>);
159             const wrapper2 = mount(<Provider store={store2}>
160                 <ResourceFileSize {...props}></ResourceFileSize>
161             </Provider>);
162
163             // then
164             expect(wrapper1.text()).toContain('');
165             expect(wrapper2.text()).toContain('');
166         });
167     });
168
169     describe('GroupMembersCount', () => {
170         let fakeGroup;
171         beforeEach(() => {
172             props = {
173                 uuid: 'zzzzz-j7d0g-000000000000000',
174             };
175             fakeGroup = {
176                 "canManage": true,
177                 "canWrite": true,
178                 "createdAt": "2020-09-24T22:52:57.546521000Z",
179                 "deleteAt": null,
180                 "description": "Test Group",
181                 "etag": "0000000000000000000000000",
182                 "frozenByUuid": null,
183                 "groupClass": "role",
184                 "href": `/groups/${props.uuid}`,
185                 "isTrashed": false,
186                 "kind": ResourceKind.GROUP,
187                 "modifiedAt": "2020-09-24T22:52:57.545669000Z",
188                 "modifiedByUserUuid": "zzzzz-tpzed-000000000000000",
189                 "name": "System group",
190                 "ownerUuid": "zzzzz-tpzed-000000000000000",
191                 "properties": {},
192                 "trashAt": null,
193                 "uuid": props.uuid,
194                 "writableBy": [
195                     "zzzzz-tpzed-000000000000000",
196                 ]
197             };
198         });
199
200         it('shows loading group count when no memberCount', () => {
201             // Given
202             const store = mockStore({resources: {
203                 [props.uuid]: fakeGroup,
204             }});
205
206             const wrapper = mount(<Provider store={store}>
207                 <MuiThemeProvider theme={CustomTheme}>
208                     <GroupMembersCount {...props} />
209                 </MuiThemeProvider>
210             </Provider>);
211
212             expect(wrapper.find(InlinePulser)).toHaveLength(1);
213         });
214
215         it('shows group count when memberCount present', () => {
216             // Given
217             const store = mockStore({resources: {
218                 [props.uuid]: {
219                     ...fakeGroup,
220                     "memberCount": 765,
221                 }
222             }});
223
224             const wrapper = mount(<Provider store={store}>
225                 <MuiThemeProvider theme={CustomTheme}>
226                     <GroupMembersCount {...props} />
227                 </MuiThemeProvider>
228             </Provider>);
229
230             expect(wrapper.text()).toBe("765");
231         });
232
233         it('shows group count error icon when memberCount is null', () => {
234             // Given
235             const store = mockStore({resources: {
236                 [props.uuid]: {
237                     ...fakeGroup,
238                     "memberCount": null,
239                 }
240             }});
241
242             const wrapper = mount(<Provider store={store}>
243                 <MuiThemeProvider theme={CustomTheme}>
244                     <GroupMembersCount {...props} />
245                 </MuiThemeProvider>
246             </Provider>);
247
248             expect(wrapper.find(ErrorIcon)).toHaveLength(1);
249         });
250
251     });
252
253 });