@squiz/resource-browser 1.69.2 → 2.1.9-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +89 -38
- package/LICENSE.md +15 -0
- package/README.md +9 -0
- package/jest.config.ts +22 -21
- package/lib/Hooks/useSelectedState.d.ts +15 -0
- package/lib/Hooks/useSelectedState.js +16 -0
- package/lib/Hooks/useSources.d.ts +6 -6
- package/lib/Hooks/useSources.js +26 -1
- package/lib/MainContainer/MainContainer.d.ts +17 -0
- package/lib/MainContainer/MainContainer.js +61 -0
- package/lib/Plugin/Plugin.d.ts +13 -0
- package/lib/Plugin/Plugin.js +17 -0
- package/lib/ResourceBrowserContext/ResourceBrowserContext.d.ts +2 -3
- package/lib/ResourceBrowserContext/ResourceBrowserContext.js +4 -17
- package/lib/ResourceBrowserInput/ResourceBrowserInput.d.ts +24 -0
- package/lib/ResourceBrowserInput/ResourceBrowserInput.js +16 -0
- package/lib/ResourcePicker/ResourcePicker.d.ts +6 -4
- package/lib/ResourcePicker/ResourcePicker.js +14 -8
- package/lib/ResourcePicker/States/Selected.d.ts +10 -4
- package/lib/ResourcePicker/States/Selected.js +11 -32
- package/lib/SourceDropdown/SourceDropdown.d.ts +5 -11
- package/lib/SourceDropdown/SourceDropdown.js +20 -99
- package/lib/SourceList/SourceList.d.ts +5 -16
- package/lib/SourceList/SourceList.js +14 -75
- package/lib/index.css +42 -202
- package/lib/index.d.ts +7 -7
- package/lib/index.js +69 -13
- package/lib/types.d.ts +41 -59
- package/package.json +82 -80
- package/src/Hooks/useSelectedState.spec.ts +46 -0
- package/src/Hooks/useSelectedState.ts +22 -0
- package/src/Hooks/useSources.spec.ts +60 -13
- package/src/Hooks/useSources.ts +35 -5
- package/src/Icons/CircledLoopIcon.tsx +8 -8
- package/src/MainContainer/MainContainer.spec.tsx +203 -0
- package/src/MainContainer/MainContainer.stories.tsx +62 -0
- package/src/MainContainer/MainContainer.tsx +101 -0
- package/src/Plugin/Plugin.spec.tsx +46 -0
- package/src/Plugin/Plugin.tsx +20 -0
- package/src/ResourceBrowserContext/ResourceBrowserContext.spec.tsx +65 -106
- package/src/ResourceBrowserContext/ResourceBrowserContext.tsx +24 -39
- package/src/ResourceBrowserInput/ResourceBrowserInput.spec.tsx +192 -0
- package/src/ResourceBrowserInput/ResourceBrowserInput.tsx +81 -0
- package/src/ResourcePicker/ResourcePicker.spec.tsx +159 -116
- package/src/ResourcePicker/ResourcePicker.stories.tsx +28 -24
- package/src/ResourcePicker/ResourcePicker.tsx +79 -59
- package/src/ResourcePicker/States/Error.tsx +8 -8
- package/src/ResourcePicker/States/Loading.tsx +3 -3
- package/src/ResourcePicker/States/Selected.tsx +66 -73
- package/src/ResourcePicker/mock-image-resource.json +25 -47
- package/src/ResourcePicker/mock-resource.json +11 -13
- package/src/ResourcePicker/resource-picker.scss +13 -13
- package/src/SourceDropdown/SourceDropdown.spec.tsx +65 -391
- package/src/SourceDropdown/SourceDropdown.stories.tsx +21 -24
- package/src/SourceDropdown/SourceDropdown.tsx +80 -258
- package/src/SourceList/SourceList.spec.tsx +37 -430
- package/src/SourceList/SourceList.stories.tsx +17 -37
- package/src/SourceList/SourceList.tsx +28 -155
- package/src/__mocks__/MockModels.ts +56 -25
- package/src/__mocks__/PluginExample.tsx +98 -0
- package/src/__mocks__/StorybookHelpers.tsx +141 -0
- package/src/__mocks__/renderWithContext.tsx +14 -18
- package/src/__mocks__/sample-sources.json +32 -0
- package/src/index.scss +18 -8
- package/src/index.spec.tsx +277 -99
- package/src/index.stories.tsx +65 -39
- package/src/index.tsx +119 -57
- package/src/types.ts +54 -63
- package/tailwind.config.cjs +92 -92
- package/vite.config.js +12 -12
- package/lib/Hooks/useCategorisedSources.d.ts +0 -14
- package/lib/Hooks/useCategorisedSources.js +0 -38
- package/lib/Hooks/useChildResources.d.ts +0 -16
- package/lib/Hooks/useChildResources.js +0 -13
- package/lib/Hooks/usePreselectedResourcePath.d.ts +0 -20
- package/lib/Hooks/usePreselectedResourcePath.js +0 -31
- package/lib/Hooks/useRecentLocations.d.ts +0 -5
- package/lib/Hooks/useRecentLocations.js +0 -38
- package/lib/Hooks/useRecentResourcesPaths.d.ts +0 -20
- package/lib/Hooks/useRecentResourcesPaths.js +0 -30
- package/lib/Hooks/useResource.d.ts +0 -28
- package/lib/Hooks/useResource.js +0 -25
- package/lib/Hooks/useResourcePath.d.ts +0 -16
- package/lib/Hooks/useResourcePath.js +0 -64
- package/lib/Icons/HistoryIcon.d.ts +0 -4
- package/lib/Icons/HistoryIcon.js +0 -13
- package/lib/PreviewPanel/PreviewPanel.d.ts +0 -5
- package/lib/PreviewPanel/PreviewPanel.js +0 -8
- package/lib/PreviewPanel/details/MatrixResource.d.ts +0 -7
- package/lib/PreviewPanel/details/MatrixResource.js +0 -35
- package/lib/ResourceBreadcrumb/ResourceBreadcrumb.d.ts +0 -9
- package/lib/ResourceBreadcrumb/ResourceBreadcrumb.js +0 -54
- package/lib/ResourceList/ResourceList.d.ts +0 -18
- package/lib/ResourceList/ResourceList.js +0 -49
- package/lib/ResourcePickerContainer/ResourcePickerContainer.d.ts +0 -17
- package/lib/ResourcePickerContainer/ResourcePickerContainer.js +0 -166
- package/lib/StatusIndicator/StatusIndicator.d.ts +0 -8
- package/lib/StatusIndicator/StatusIndicator.js +0 -27
- package/lib/utils/findBestMatchLineage.d.ts +0 -2
- package/lib/utils/findBestMatchLineage.js +0 -28
- package/lib/utils/uuid.d.ts +0 -1
- package/lib/utils/uuid.js +0 -6
- package/src/Hooks/useCategorisedSources.spec.ts +0 -39
- package/src/Hooks/useCategorisedSources.ts +0 -46
- package/src/Hooks/useChildResources.spec.ts +0 -29
- package/src/Hooks/useChildResources.ts +0 -21
- package/src/Hooks/usePreselectedResourcePath.ts +0 -54
- package/src/Hooks/useRecentLocations.spec.ts +0 -81
- package/src/Hooks/useRecentLocations.ts +0 -44
- package/src/Hooks/useRecentResourcesPaths.ts +0 -54
- package/src/Hooks/useResource.spec.ts +0 -61
- package/src/Hooks/useResource.ts +0 -40
- package/src/Hooks/useResourcePath.spec.ts +0 -120
- package/src/Hooks/useResourcePath.ts +0 -76
- package/src/Icons/HistoryIcon.tsx +0 -17
- package/src/PreviewPanel/PreviewPanel.spec.tsx +0 -198
- package/src/PreviewPanel/PreviewPanel.stories.tsx +0 -76
- package/src/PreviewPanel/PreviewPanel.tsx +0 -6
- package/src/PreviewPanel/details/MatrixResource.tsx +0 -54
- package/src/PreviewPanel/details/matrix-resource.scss +0 -16
- package/src/ResourceBreadcrumb/ResourceBreadcrumb.spec.tsx +0 -133
- package/src/ResourceBreadcrumb/ResourceBreadcrumb.stories.tsx +0 -24
- package/src/ResourceBreadcrumb/ResourceBreadcrumb.tsx +0 -79
- package/src/ResourceBreadcrumb/resource-breadcrumb.scss +0 -28
- package/src/ResourceBreadcrumb/sample-hierarchy.json +0 -27
- package/src/ResourceList/ResourceList.spec.tsx +0 -202
- package/src/ResourceList/ResourceList.stories.tsx +0 -40
- package/src/ResourceList/ResourceList.tsx +0 -83
- package/src/ResourceList/sample-resources.json +0 -851
- package/src/ResourcePickerContainer/ResourcePickerContainer.spec.tsx +0 -780
- package/src/ResourcePickerContainer/ResourcePickerContainer.stories.tsx +0 -45
- package/src/ResourcePickerContainer/ResourcePickerContainer.tsx +0 -290
- package/src/SourceList/sample-sources.json +0 -251
- package/src/StatusIndicator/StatusIndicator.stories.tsx +0 -83
- package/src/StatusIndicator/StatusIndicator.tsx +0 -38
- package/src/__mocks__/JestHelpers.ts +0 -65
- package/src/__mocks__/StorybookHelpers.ts +0 -128
- package/src/__mocks__/jestHelpers.spec.ts +0 -38
- package/src/utils/findBestMatchLineage.spec.ts +0 -81
- package/src/utils/findBestMatchLineage.ts +0 -30
- package/src/utils/uuid.ts +0 -5
@@ -1,780 +0,0 @@
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-empty-function */
|
2
|
-
import React from 'react';
|
3
|
-
import { screen, render, waitFor, within, act } from '@testing-library/react';
|
4
|
-
import userEvent from '@testing-library/user-event';
|
5
|
-
import { mockResource, mockSource } from '../__mocks__/MockModels';
|
6
|
-
import { Resource, Source, Hierarchy, ResourceReference } from '../types';
|
7
|
-
import { Context as ResponsiveContext } from 'react-responsive';
|
8
|
-
import { OverlayTriggerState } from 'react-stately';
|
9
|
-
|
10
|
-
import ResourcePickerContainer from './ResourcePickerContainer';
|
11
|
-
|
12
|
-
import SourceList, { SourceListProps } from '../SourceList/SourceList'; // Import Functional Component
|
13
|
-
jest.mock('../SourceList/SourceList'); // Mock the Functional Component
|
14
|
-
const ActualSourceList = jest.requireActual('../SourceList/SourceList').default; // Grab the real copy of it as normally we don't want the mock
|
15
|
-
const MockSourceList = SourceList as jest.MockedFunction<typeof SourceList>; // Cast the mocked function so TS stops complaining
|
16
|
-
MockSourceList.mockImplementation(ActualSourceList); // Return the actual function unless overridden
|
17
|
-
|
18
|
-
import ResourceList, { ResourceListProps } from '../ResourceList/ResourceList'; // Import Functional Component
|
19
|
-
jest.mock('../ResourceList/ResourceList'); // Mock the Functional Component
|
20
|
-
const ActualResourceList = jest.requireActual('../ResourceList/ResourceList').default; // Grab the real copy of it as normally we don't want the mock
|
21
|
-
const MockResourceList = ResourceList as jest.MockedFunction<typeof ResourceList>; // Cast the mocked function so TS stops complaining
|
22
|
-
MockResourceList.mockImplementation(ActualResourceList); // Return the actual function unless overridden
|
23
|
-
|
24
|
-
import PreviewPanel, { PreviewPanelProps } from '../PreviewPanel/PreviewPanel'; // Import Functional Component
|
25
|
-
jest.mock('../PreviewPanel/PreviewPanel'); // Mock the Functional Component
|
26
|
-
const ActualPreviewPanel = jest.requireActual('../PreviewPanel/PreviewPanel').default; // Grab the real copy of it as normally we don't want the mock
|
27
|
-
const MockPreviewPanel = PreviewPanel as jest.MockedFunction<typeof PreviewPanel>; // Cast the mocked function so TS stops complaining
|
28
|
-
MockPreviewPanel.mockImplementation(ActualPreviewPanel); // Return the actual function unless overridden
|
29
|
-
|
30
|
-
import ResourceBreadcrumb, { ResourceBreadcrumbProps } from '../ResourceBreadcrumb/ResourceBreadcrumb'; // Import Functional Component
|
31
|
-
jest.mock('../ResourceBreadcrumb/ResourceBreadcrumb'); // Mock the Functional Component
|
32
|
-
const ActualResourceBreadcrumb = jest.requireActual('../ResourceBreadcrumb/ResourceBreadcrumb').default; // Grab the real copy of it as normally we don't want the mock
|
33
|
-
const MockResourceBreadcrumb = ResourceBreadcrumb as jest.MockedFunction<typeof ResourceBreadcrumb>; // Cast the mocked function so TS stops complaining
|
34
|
-
MockResourceBreadcrumb.mockImplementation(ActualResourceBreadcrumb); // Return the actual function unless overridden
|
35
|
-
|
36
|
-
const baseProps = {
|
37
|
-
title: 'Testing',
|
38
|
-
titleAriaProps: {},
|
39
|
-
allowedTypes: undefined,
|
40
|
-
onClose: jest.fn(),
|
41
|
-
onRequestSources: jest.fn().mockResolvedValue([
|
42
|
-
mockSource({
|
43
|
-
id: '1',
|
44
|
-
name: 'Test system',
|
45
|
-
nodes: [
|
46
|
-
{
|
47
|
-
id: '1',
|
48
|
-
type: {
|
49
|
-
code: 'site',
|
50
|
-
name: 'Site',
|
51
|
-
},
|
52
|
-
name: 'Test Website',
|
53
|
-
childCount: 21,
|
54
|
-
},
|
55
|
-
],
|
56
|
-
}),
|
57
|
-
]),
|
58
|
-
onRequestResource: jest.fn().mockRejectedValue(new Error('onRequestResource has not been mocked.')),
|
59
|
-
onRequestChildren: jest.fn().mockResolvedValue([
|
60
|
-
mockResource({
|
61
|
-
id: '123',
|
62
|
-
type: {
|
63
|
-
code: 'page',
|
64
|
-
name: 'Mocked Page',
|
65
|
-
},
|
66
|
-
name: 'Test Page',
|
67
|
-
childCount: 0,
|
68
|
-
}),
|
69
|
-
]),
|
70
|
-
onChange: jest.fn(),
|
71
|
-
};
|
72
|
-
|
73
|
-
describe('ResourcePickerContainer', () => {
|
74
|
-
beforeEach(() => {
|
75
|
-
localStorage.setItem(
|
76
|
-
'rb_recent_locations',
|
77
|
-
JSON.stringify([
|
78
|
-
{ resource: '32', source: '1' },
|
79
|
-
{ resource: '20', source: '1' },
|
80
|
-
]),
|
81
|
-
);
|
82
|
-
});
|
83
|
-
|
84
|
-
it('Queries onRequestSources for source list on startup', async () => {
|
85
|
-
const onRequestSources = jest.fn(() => {
|
86
|
-
return Promise.resolve([]);
|
87
|
-
});
|
88
|
-
|
89
|
-
const { getByLabelText } = render(<ResourcePickerContainer {...baseProps} onRequestSources={onRequestSources} />);
|
90
|
-
await waitFor(() => {
|
91
|
-
expect(getByLabelText('Source list')).toBeInTheDocument();
|
92
|
-
});
|
93
|
-
|
94
|
-
expect(onRequestSources).toHaveBeenCalled();
|
95
|
-
});
|
96
|
-
|
97
|
-
it('Renders provided sources from onRequestSources', async () => {
|
98
|
-
const onRequestSources = jest.fn().mockResolvedValue([
|
99
|
-
mockSource({
|
100
|
-
id: '1',
|
101
|
-
name: 'Test system 1',
|
102
|
-
nodes: [
|
103
|
-
{
|
104
|
-
id: '1',
|
105
|
-
type: {
|
106
|
-
code: 'site',
|
107
|
-
name: 'Site',
|
108
|
-
},
|
109
|
-
name: 'Test Website 1',
|
110
|
-
childCount: 21,
|
111
|
-
},
|
112
|
-
],
|
113
|
-
}),
|
114
|
-
mockSource({
|
115
|
-
id: '2',
|
116
|
-
name: 'Test system 2',
|
117
|
-
nodes: [
|
118
|
-
{
|
119
|
-
id: '1',
|
120
|
-
type: {
|
121
|
-
code: 'site',
|
122
|
-
name: 'Site',
|
123
|
-
},
|
124
|
-
name: 'Test Website 2',
|
125
|
-
childCount: 21,
|
126
|
-
},
|
127
|
-
{
|
128
|
-
id: '2',
|
129
|
-
type: {
|
130
|
-
code: 'site',
|
131
|
-
name: 'Site',
|
132
|
-
},
|
133
|
-
name: 'Test Website 3',
|
134
|
-
childCount: 21,
|
135
|
-
},
|
136
|
-
],
|
137
|
-
}),
|
138
|
-
]);
|
139
|
-
|
140
|
-
const { getAllByText } = render(<ResourcePickerContainer {...baseProps} onRequestSources={onRequestSources} />);
|
141
|
-
await waitFor(() => {
|
142
|
-
expect(getAllByText('Test system 1')[0]).toBeInTheDocument();
|
143
|
-
});
|
144
|
-
|
145
|
-
await waitFor(() => {
|
146
|
-
const sourceList = screen.getByLabelText('Source list');
|
147
|
-
expect(within(sourceList).getByText('Test system 1')).toBeInTheDocument();
|
148
|
-
expect(within(sourceList).getByText('Test Website 1')).toBeInTheDocument();
|
149
|
-
|
150
|
-
expect(within(sourceList).getByText('Test system 2')).toBeInTheDocument();
|
151
|
-
expect(within(sourceList).getByText('Test Website 2')).toBeInTheDocument();
|
152
|
-
expect(within(sourceList).getByText('Test Website 3')).toBeInTheDocument();
|
153
|
-
});
|
154
|
-
});
|
155
|
-
|
156
|
-
it('The preselected resource is selected', async () => {
|
157
|
-
const resources: Record<string, Resource> = {
|
158
|
-
1: mockResource({ id: '1', name: 'Root Folder' }),
|
159
|
-
100: mockResource({ id: '100', name: 'Source root node #1' }),
|
160
|
-
200: mockResource({ id: '200', name: 'Source root node #2' }),
|
161
|
-
201: mockResource({ id: '201', name: 'Child #1' }),
|
162
|
-
202: mockResource({ id: '202', name: 'Child #2' }),
|
163
|
-
203: mockResource({
|
164
|
-
id: '203',
|
165
|
-
name: 'Leaf',
|
166
|
-
lineages: [
|
167
|
-
{
|
168
|
-
resourceIds: ['1', '200', '201', '202', '203'],
|
169
|
-
},
|
170
|
-
],
|
171
|
-
}),
|
172
|
-
204: mockResource({ id: '204', name: 'Another leaf' }),
|
173
|
-
300: mockResource({ id: '300', name: 'Source root node #3' }),
|
174
|
-
};
|
175
|
-
const sources: Record<string, Source> = {
|
176
|
-
1: mockSource({
|
177
|
-
id: '1',
|
178
|
-
name: 'Test system 1',
|
179
|
-
nodes: [resources[100]],
|
180
|
-
}),
|
181
|
-
2: mockSource({
|
182
|
-
id: '2',
|
183
|
-
name: 'Test system 2',
|
184
|
-
nodes: [resources[200], resources[300]],
|
185
|
-
}),
|
186
|
-
};
|
187
|
-
|
188
|
-
const onRequestSources = jest.fn().mockResolvedValue(Object.values(sources));
|
189
|
-
const onRequestResource = jest.fn((reference: ResourceReference) => Promise.resolve(resources[reference.resource]));
|
190
|
-
const onRequestChildren = jest.fn().mockResolvedValue([resources[203], resources[204]]);
|
191
|
-
const preselectedSourceId = '2';
|
192
|
-
const preselectedResource = resources[203];
|
193
|
-
|
194
|
-
render(
|
195
|
-
<ResourcePickerContainer
|
196
|
-
{...baseProps}
|
197
|
-
onRequestSources={onRequestSources}
|
198
|
-
onRequestResource={onRequestResource}
|
199
|
-
onRequestChildren={onRequestChildren}
|
200
|
-
preselectedSourceId={preselectedSourceId}
|
201
|
-
preselectedResource={preselectedResource}
|
202
|
-
/>,
|
203
|
-
);
|
204
|
-
|
205
|
-
await waitFor(() => expect(screen.getByRole('button', { name: 'folder Leaf selected' })).toBeInTheDocument());
|
206
|
-
|
207
|
-
const breadcrumbs = within(screen.getByLabelText('Resource breadcrumb')).getAllByRole('listitem');
|
208
|
-
|
209
|
-
// Breadcrumbs should be populated, source should be populated.
|
210
|
-
// "Leaf" resource should be selected, "Another leaf" resource should not be selected.
|
211
|
-
expect(breadcrumbs.map((item) => item.textContent)).toEqual(['', 'Source root node #2', 'Child #1', 'Child #2']);
|
212
|
-
expect(screen.getByLabelText('Source quick select')).toHaveTextContent(/Source root node #2/);
|
213
|
-
expect(screen.getByRole('button', { name: 'folder Leaf selected' })).toBeInTheDocument();
|
214
|
-
expect(screen.getByRole('button', { name: 'folder Another leaf' })).toBeInTheDocument();
|
215
|
-
});
|
216
|
-
|
217
|
-
it.each([
|
218
|
-
['the preselected resource is a root node', 10],
|
219
|
-
['the preselected resource lineage does not exist under a root node', 100],
|
220
|
-
['the preselected resource lineage does not appear under a root node', 200],
|
221
|
-
])('The source list is displayed if %s', async (description: string, preselectedResourceId: number) => {
|
222
|
-
localStorage.clear();
|
223
|
-
|
224
|
-
const resources: Record<string, Resource> = {
|
225
|
-
10: mockResource({
|
226
|
-
id: '100',
|
227
|
-
name: 'Source root node #1',
|
228
|
-
lineages: [{ resourceIds: ['1', '10'] }],
|
229
|
-
}),
|
230
|
-
100: mockResource({
|
231
|
-
id: '100',
|
232
|
-
name: 'Resource without lineages',
|
233
|
-
lineages: undefined,
|
234
|
-
}),
|
235
|
-
200: mockResource({
|
236
|
-
id: '200',
|
237
|
-
name: 'Resource not available under a root node',
|
238
|
-
lineages: [{ resourceIds: ['1', '20', '200'] }],
|
239
|
-
}),
|
240
|
-
};
|
241
|
-
const sources: Record<string, Source> = {
|
242
|
-
1: mockSource({
|
243
|
-
id: '1',
|
244
|
-
name: 'Test system 1',
|
245
|
-
nodes: [resources[10]],
|
246
|
-
}),
|
247
|
-
};
|
248
|
-
|
249
|
-
const onRequestSources = jest.fn().mockResolvedValue(Object.values(sources));
|
250
|
-
const onRequestResource = jest.fn((reference: ResourceReference) => Promise.resolve(resources[reference.resource]));
|
251
|
-
const onRequestChildren = jest.fn().mockResolvedValue([]);
|
252
|
-
const preselectedSourceId = '1';
|
253
|
-
const preselectedResource = resources[preselectedResourceId];
|
254
|
-
|
255
|
-
render(
|
256
|
-
<ResourcePickerContainer
|
257
|
-
{...baseProps}
|
258
|
-
onRequestSources={onRequestSources}
|
259
|
-
onRequestResource={onRequestResource}
|
260
|
-
onRequestChildren={onRequestChildren}
|
261
|
-
preselectedSourceId={preselectedSourceId}
|
262
|
-
preselectedResource={preselectedResource}
|
263
|
-
/>,
|
264
|
-
);
|
265
|
-
|
266
|
-
await waitFor(() => expect(screen.queryByRole('list', { name: 'Source list' })).toBeInTheDocument());
|
267
|
-
|
268
|
-
// Breadcrumbs should not be displayed.
|
269
|
-
// Source list should be displayed.
|
270
|
-
// "Leaf" resource should be selected, "Another leaf" resource should not be selected.
|
271
|
-
await waitFor(() => expect(screen.queryByLabelText('Resource breadcrumb')).not.toBeInTheDocument());
|
272
|
-
await waitFor(() =>
|
273
|
-
expect(screen.getByRole('button', { name: 'Drill down to Source root node #1 children' })).toBeInTheDocument(),
|
274
|
-
);
|
275
|
-
});
|
276
|
-
|
277
|
-
it('Selecting a child count drills down', async () => {
|
278
|
-
const onRequestChildren = jest.fn(() => {
|
279
|
-
return Promise.resolve([]);
|
280
|
-
});
|
281
|
-
|
282
|
-
// Component has finished initial render
|
283
|
-
const { getAllByText } = render(<ResourcePickerContainer {...baseProps} onRequestChildren={onRequestChildren} />);
|
284
|
-
await waitFor(() => {
|
285
|
-
expect(getAllByText('Test system')[0]).toBeInTheDocument();
|
286
|
-
});
|
287
|
-
|
288
|
-
// Click the drill down counter
|
289
|
-
const user = userEvent.setup();
|
290
|
-
user.click(screen.getByRole('button', { name: 'Drill down to Test Website children' }));
|
291
|
-
|
292
|
-
await waitFor(() => {
|
293
|
-
expect(onRequestChildren).toHaveBeenCalled();
|
294
|
-
});
|
295
|
-
});
|
296
|
-
|
297
|
-
it('Drill down renders provided resources from onRequestChildren', async () => {
|
298
|
-
const onRequestChildren = jest
|
299
|
-
.fn()
|
300
|
-
.mockResolvedValue([
|
301
|
-
mockResource({ id: '1', name: 'Test Page 1' }),
|
302
|
-
mockResource({ id: '2', name: 'Test Page 2' }),
|
303
|
-
mockResource({ id: '3', name: 'Test Page 3' }),
|
304
|
-
]);
|
305
|
-
|
306
|
-
const { getAllByText } = await act(async () => {
|
307
|
-
// Component has finished initial render
|
308
|
-
return render(<ResourcePickerContainer {...baseProps} onRequestChildren={onRequestChildren} />);
|
309
|
-
});
|
310
|
-
await waitFor(() => {
|
311
|
-
expect(getAllByText('Test system')[0]).toBeInTheDocument();
|
312
|
-
});
|
313
|
-
|
314
|
-
// Click the drill down counter
|
315
|
-
const user = userEvent.setup();
|
316
|
-
user.click(screen.getByRole('button', { name: 'Drill down to Test Website children' }));
|
317
|
-
|
318
|
-
await waitFor(() => {
|
319
|
-
expect(screen.getByText('Test Page 1')).toBeInTheDocument();
|
320
|
-
expect(screen.getByText('Test Page 2')).toBeInTheDocument();
|
321
|
-
expect(screen.getByText('Test Page 3')).toBeInTheDocument();
|
322
|
-
});
|
323
|
-
});
|
324
|
-
|
325
|
-
it.each([
|
326
|
-
['mobile', 360, 1],
|
327
|
-
['desktop', 1920, 0],
|
328
|
-
])(
|
329
|
-
'Selecting a node on %s shows its properties in the details panel',
|
330
|
-
async (description: string, width: number, expectedPreviewPanelCloseButtons: number) => {
|
331
|
-
await act(async () =>
|
332
|
-
render(
|
333
|
-
<ResponsiveContext.Provider value={{ width }}>
|
334
|
-
<ResourcePickerContainer {...baseProps} />
|
335
|
-
</ResponsiveContext.Provider>,
|
336
|
-
),
|
337
|
-
);
|
338
|
-
await waitFor(() => {
|
339
|
-
expect(screen.getByRole('button', { name: 'Drill down to Test Website children' })).toBeInTheDocument();
|
340
|
-
});
|
341
|
-
|
342
|
-
// Is on base page
|
343
|
-
expect(screen.getByLabelText('Source list')).toBeInTheDocument();
|
344
|
-
|
345
|
-
// Drill into the source
|
346
|
-
const user = userEvent.setup();
|
347
|
-
user.click(screen.getByRole('button', { name: 'Drill down to Test Website children' }));
|
348
|
-
await waitFor(() => expect(screen.getByRole('button', { name: 'page Test Page' })).toBeInTheDocument());
|
349
|
-
|
350
|
-
// Select the resource
|
351
|
-
user.click(screen.getByRole('button', { name: 'page Test Page' }));
|
352
|
-
|
353
|
-
// Asset that the preview panel containing the asset type/ID/etc. is visible
|
354
|
-
await waitFor(() => expect(screen.getByText('Asset ID')).toBeInTheDocument());
|
355
|
-
expect(screen.getByText('Mocked Page')).toBeInTheDocument();
|
356
|
-
expect(screen.getByText('#123')).toBeInTheDocument();
|
357
|
-
expect(screen.queryAllByRole('button', { name: 'Close details' })).toHaveLength(expectedPreviewPanelCloseButtons);
|
358
|
-
},
|
359
|
-
);
|
360
|
-
|
361
|
-
it('Closing the details panel deselects the node', async () => {
|
362
|
-
render(
|
363
|
-
<ResponsiveContext.Provider value={{ width: 360 }}>
|
364
|
-
<ResourcePickerContainer {...baseProps} />
|
365
|
-
</ResponsiveContext.Provider>,
|
366
|
-
);
|
367
|
-
await waitFor(() => {
|
368
|
-
expect(screen.getByRole('button', { name: 'Drill down to Test Website children' })).toBeInTheDocument();
|
369
|
-
});
|
370
|
-
|
371
|
-
// Drill into the source
|
372
|
-
const user = userEvent.setup();
|
373
|
-
user.click(screen.getByRole('button', { name: 'Drill down to Test Website children' }));
|
374
|
-
await waitFor(() => expect(screen.getByRole('button', { name: 'page Test Page' })).toBeInTheDocument());
|
375
|
-
|
376
|
-
// Select the resource
|
377
|
-
user.click(screen.getByRole('button', { name: 'page Test Page' }));
|
378
|
-
|
379
|
-
// Wait for the preview panel to open
|
380
|
-
await waitFor(() => expect(screen.getByText('Mocked Page')).toBeInTheDocument());
|
381
|
-
await waitFor(() => expect(screen.getByText('#123')).toBeInTheDocument());
|
382
|
-
|
383
|
-
// Close the preview panel
|
384
|
-
user.click(screen.getByRole('button', { name: 'Close details' }));
|
385
|
-
|
386
|
-
await waitFor(() => {
|
387
|
-
// Resource should be unselected and preview modal should disappear
|
388
|
-
expect(screen.getByText('Mocked Page')).toBeInTheDocument();
|
389
|
-
expect(screen.getByText('#123')).toBeInTheDocument();
|
390
|
-
});
|
391
|
-
});
|
392
|
-
|
393
|
-
it('Passes modal state down to child components: SourceList', async () => {
|
394
|
-
let mockModalState: OverlayTriggerState | null = null;
|
395
|
-
|
396
|
-
MockSourceList.mockImplementation((args: SourceListProps) => {
|
397
|
-
mockModalState = args.previewModalState;
|
398
|
-
return ActualSourceList(args);
|
399
|
-
});
|
400
|
-
|
401
|
-
render(<ResourcePickerContainer {...baseProps} />);
|
402
|
-
|
403
|
-
expect(mockModalState).toEqual(
|
404
|
-
expect.objectContaining({
|
405
|
-
close: expect.any(Function),
|
406
|
-
isOpen: expect.any(Boolean),
|
407
|
-
open: expect.any(Function),
|
408
|
-
setOpen: expect.any(Function),
|
409
|
-
toggle: expect.any(Function),
|
410
|
-
}),
|
411
|
-
);
|
412
|
-
});
|
413
|
-
|
414
|
-
it('Passes modal state down to child components: ResourceList', async () => {
|
415
|
-
let mockModalState: OverlayTriggerState | null = null;
|
416
|
-
|
417
|
-
MockResourceList.mockImplementation((args: ResourceListProps) => {
|
418
|
-
mockModalState = args.previewModalState;
|
419
|
-
return ActualResourceList(args);
|
420
|
-
});
|
421
|
-
|
422
|
-
const { getByText, getAllByText } = render(<ResourcePickerContainer {...baseProps} />);
|
423
|
-
await waitFor(() => {
|
424
|
-
expect(getAllByText('Test system')[0]).toBeInTheDocument();
|
425
|
-
});
|
426
|
-
|
427
|
-
// Click the drill down counter
|
428
|
-
const user = userEvent.setup();
|
429
|
-
user.click(screen.getByRole('button', { name: 'Drill down to Test Website children' }));
|
430
|
-
await waitFor(() => {
|
431
|
-
expect(getByText('Test Page')).toBeInTheDocument();
|
432
|
-
});
|
433
|
-
|
434
|
-
expect(mockModalState).toEqual(
|
435
|
-
expect.objectContaining({
|
436
|
-
close: expect.any(Function),
|
437
|
-
isOpen: expect.any(Boolean),
|
438
|
-
open: expect.any(Function),
|
439
|
-
setOpen: expect.any(Function),
|
440
|
-
toggle: expect.any(Function),
|
441
|
-
}),
|
442
|
-
);
|
443
|
-
});
|
444
|
-
|
445
|
-
it('Passes modal state down to child components: Details Panel', async () => {
|
446
|
-
let mockModalState: OverlayTriggerState | null = null;
|
447
|
-
|
448
|
-
MockPreviewPanel.mockImplementation((args: PreviewPanelProps) => {
|
449
|
-
mockModalState = args.modalState;
|
450
|
-
return ActualPreviewPanel(args);
|
451
|
-
});
|
452
|
-
|
453
|
-
const { getAllByText } = render(<ResourcePickerContainer {...baseProps} />);
|
454
|
-
await waitFor(() => {
|
455
|
-
expect(getAllByText('Test system')[0]).toBeInTheDocument();
|
456
|
-
});
|
457
|
-
|
458
|
-
const user = userEvent.setup();
|
459
|
-
user.click(screen.getByRole('button', { name: 'Drill down to Test Website children' }));
|
460
|
-
|
461
|
-
expect(mockModalState).toEqual(
|
462
|
-
expect.objectContaining({
|
463
|
-
close: expect.any(Function),
|
464
|
-
isOpen: expect.any(Boolean),
|
465
|
-
open: expect.any(Function),
|
466
|
-
setOpen: expect.any(Function),
|
467
|
-
toggle: expect.any(Function),
|
468
|
-
}),
|
469
|
-
);
|
470
|
-
});
|
471
|
-
|
472
|
-
it('Breadcrumb hierarchy is added to on drill down', async () => {
|
473
|
-
let mockHierarchy: Hierarchy<Source | Resource> = [];
|
474
|
-
|
475
|
-
MockResourceBreadcrumb.mockImplementation((args: ResourceBreadcrumbProps<unknown>) => {
|
476
|
-
mockHierarchy = args.hierarchy as Hierarchy<Source | Resource>;
|
477
|
-
return ActualResourceBreadcrumb(args);
|
478
|
-
});
|
479
|
-
|
480
|
-
const { getByLabelText, getAllByText } = render(<ResourcePickerContainer {...baseProps} />);
|
481
|
-
await waitFor(() => {
|
482
|
-
expect(getAllByText('Test system')[0]).toBeInTheDocument();
|
483
|
-
});
|
484
|
-
|
485
|
-
const user = userEvent.setup();
|
486
|
-
user.click(screen.getByRole('button', { name: 'Drill down to Test Website children' }));
|
487
|
-
|
488
|
-
// Breadcrumb is showing
|
489
|
-
await waitFor(() => {
|
490
|
-
expect(getByLabelText('Resource breadcrumb')).toBeInTheDocument();
|
491
|
-
});
|
492
|
-
|
493
|
-
// Expect the clicked child was added to breadcrumb
|
494
|
-
expect(mockHierarchy).toEqual([
|
495
|
-
{
|
496
|
-
key: 'source:1-resource:1',
|
497
|
-
label: 'Test Website',
|
498
|
-
node: expect.any(Object),
|
499
|
-
},
|
500
|
-
]);
|
501
|
-
});
|
502
|
-
|
503
|
-
it('Multiple hierarchy is tracked on on drill down', async () => {
|
504
|
-
let mockHierarchy: Hierarchy<Source | Resource> = [];
|
505
|
-
|
506
|
-
MockResourceBreadcrumb.mockImplementation((args: ResourceBreadcrumbProps<unknown>) => {
|
507
|
-
mockHierarchy = args.hierarchy as Hierarchy<Source | Resource>;
|
508
|
-
return ActualResourceBreadcrumb(args);
|
509
|
-
});
|
510
|
-
|
511
|
-
const onRequestChildren = jest
|
512
|
-
.fn()
|
513
|
-
.mockResolvedValueOnce([
|
514
|
-
mockResource({
|
515
|
-
id: '11',
|
516
|
-
name: 'Test Page',
|
517
|
-
childCount: 4,
|
518
|
-
}),
|
519
|
-
])
|
520
|
-
.mockResolvedValueOnce([
|
521
|
-
mockResource({
|
522
|
-
id: '111',
|
523
|
-
name: 'Second Page',
|
524
|
-
childCount: 0,
|
525
|
-
}),
|
526
|
-
]);
|
527
|
-
|
528
|
-
const { getByLabelText, getByText, getAllByText, queryAllByText } = render(
|
529
|
-
<ResourcePickerContainer {...baseProps} onRequestChildren={onRequestChildren} />,
|
530
|
-
);
|
531
|
-
await waitFor(() => {
|
532
|
-
expect(getAllByText('Test system')[0]).toBeInTheDocument();
|
533
|
-
});
|
534
|
-
|
535
|
-
const user = userEvent.setup();
|
536
|
-
user.click(screen.getByRole('button', { name: 'Drill down to Test Website children' }));
|
537
|
-
|
538
|
-
// Breadcrumb is showing
|
539
|
-
await waitFor(() => {
|
540
|
-
expect(getByLabelText('Resource breadcrumb')).toBeInTheDocument();
|
541
|
-
});
|
542
|
-
|
543
|
-
// Loading is done
|
544
|
-
await waitFor(() => {
|
545
|
-
expect(queryAllByText('loading Resource list')).toHaveLength(0);
|
546
|
-
});
|
547
|
-
|
548
|
-
// Drill down again
|
549
|
-
user.click(screen.getByRole('button', { name: 'Drill down to Test Page children' }));
|
550
|
-
|
551
|
-
await waitFor(() => {
|
552
|
-
expect(getByText('Second Page')).toBeInTheDocument();
|
553
|
-
});
|
554
|
-
|
555
|
-
// Expect the clicked child was added to breadcrumb
|
556
|
-
expect(mockHierarchy).toEqual([
|
557
|
-
{
|
558
|
-
key: 'source:1-resource:1',
|
559
|
-
label: 'Test Website',
|
560
|
-
node: expect.any(Object),
|
561
|
-
},
|
562
|
-
{
|
563
|
-
key: '11',
|
564
|
-
label: 'Test Page',
|
565
|
-
node: expect.any(Object),
|
566
|
-
},
|
567
|
-
]);
|
568
|
-
});
|
569
|
-
|
570
|
-
it('Can track multiple hierarchy jumping back', async () => {
|
571
|
-
let mockHierarchy: Hierarchy<Source | Resource> = [];
|
572
|
-
|
573
|
-
MockResourceBreadcrumb.mockImplementation((args: ResourceBreadcrumbProps<unknown>) => {
|
574
|
-
mockHierarchy = args.hierarchy as Hierarchy<Source | Resource>;
|
575
|
-
return ActualResourceBreadcrumb(args);
|
576
|
-
});
|
577
|
-
|
578
|
-
const onRequestChildren = jest
|
579
|
-
.fn()
|
580
|
-
.mockResolvedValueOnce([
|
581
|
-
mockResource({
|
582
|
-
id: '11',
|
583
|
-
name: 'First Level',
|
584
|
-
childCount: 4,
|
585
|
-
}),
|
586
|
-
])
|
587
|
-
.mockResolvedValueOnce([
|
588
|
-
mockResource({
|
589
|
-
id: '111',
|
590
|
-
name: 'Second Level',
|
591
|
-
childCount: 0,
|
592
|
-
}),
|
593
|
-
])
|
594
|
-
.mockResolvedValueOnce([
|
595
|
-
mockResource({
|
596
|
-
id: '11',
|
597
|
-
name: 'First Level',
|
598
|
-
childCount: 4,
|
599
|
-
}),
|
600
|
-
]);
|
601
|
-
|
602
|
-
const { getByText, getAllByText, queryByText } = render(
|
603
|
-
<ResourcePickerContainer {...baseProps} onRequestChildren={onRequestChildren} />,
|
604
|
-
);
|
605
|
-
await waitFor(() => {
|
606
|
-
expect(getAllByText('Test system')[0]).toBeInTheDocument();
|
607
|
-
});
|
608
|
-
|
609
|
-
const user = userEvent.setup();
|
610
|
-
user.click(screen.getByRole('button', { name: 'Drill down to Test Website children' }));
|
611
|
-
|
612
|
-
// Breadcrumb is showing
|
613
|
-
await waitFor(() => {
|
614
|
-
expect(getByText('First Level')).toBeInTheDocument();
|
615
|
-
});
|
616
|
-
|
617
|
-
// Drill down again
|
618
|
-
user.click(screen.getByRole('button', { name: 'Drill down to First Level children' }));
|
619
|
-
|
620
|
-
await waitFor(() => {
|
621
|
-
expect(getByText('Second Level')).toBeInTheDocument();
|
622
|
-
});
|
623
|
-
|
624
|
-
// Click on previous breadcrumb item
|
625
|
-
const breadcrumb = screen.getByLabelText('Resource breadcrumb');
|
626
|
-
user.click(within(breadcrumb).getByRole('button', { name: 'Test Website' }));
|
627
|
-
|
628
|
-
await waitFor(() => {
|
629
|
-
expect(queryByText('Second Level')).not.toBeInTheDocument();
|
630
|
-
});
|
631
|
-
|
632
|
-
// Expect the clicked child was added to breadcrumb
|
633
|
-
expect(mockHierarchy).toEqual([
|
634
|
-
{
|
635
|
-
key: 'source:1-resource:1',
|
636
|
-
label: 'Test Website',
|
637
|
-
node: expect.any(Object),
|
638
|
-
},
|
639
|
-
]);
|
640
|
-
});
|
641
|
-
|
642
|
-
it('Multiple hierarchy can handle reset to new source', async () => {
|
643
|
-
let mockHierarchy: Hierarchy<Source | Resource> = [];
|
644
|
-
|
645
|
-
MockResourceBreadcrumb.mockImplementation((args: ResourceBreadcrumbProps<unknown>) => {
|
646
|
-
mockHierarchy = args.hierarchy as Hierarchy<Source | Resource>;
|
647
|
-
return ActualResourceBreadcrumb(args);
|
648
|
-
});
|
649
|
-
|
650
|
-
const onRequestChildren = jest
|
651
|
-
.fn()
|
652
|
-
.mockResolvedValueOnce([mockResource({ name: 'Test Page' })])
|
653
|
-
.mockResolvedValueOnce([mockResource({ name: 'Second Page' })]);
|
654
|
-
|
655
|
-
const onRequestSources = jest.fn().mockImplementation(() => {
|
656
|
-
return Promise.resolve([
|
657
|
-
mockSource({
|
658
|
-
id: '1',
|
659
|
-
name: 'Test system',
|
660
|
-
nodes: [
|
661
|
-
{
|
662
|
-
id: '1',
|
663
|
-
type: {
|
664
|
-
code: 'site',
|
665
|
-
name: 'Site',
|
666
|
-
},
|
667
|
-
name: 'Test Website',
|
668
|
-
childCount: 21,
|
669
|
-
},
|
670
|
-
{
|
671
|
-
id: '2',
|
672
|
-
type: {
|
673
|
-
code: 'site',
|
674
|
-
name: 'Site',
|
675
|
-
},
|
676
|
-
name: 'Second Website',
|
677
|
-
childCount: 21,
|
678
|
-
},
|
679
|
-
],
|
680
|
-
}),
|
681
|
-
]);
|
682
|
-
});
|
683
|
-
|
684
|
-
const { getByLabelText, getAllByText, getByText, getByRole } = render(
|
685
|
-
<ResourcePickerContainer
|
686
|
-
{...baseProps}
|
687
|
-
onRequestSources={onRequestSources}
|
688
|
-
onRequestChildren={onRequestChildren}
|
689
|
-
/>,
|
690
|
-
);
|
691
|
-
await waitFor(() => {
|
692
|
-
expect(getAllByText('Test system')[0]).toBeInTheDocument();
|
693
|
-
});
|
694
|
-
|
695
|
-
const user = userEvent.setup();
|
696
|
-
user.click(screen.getByRole('button', { name: 'Drill down to Test Website children' }));
|
697
|
-
|
698
|
-
// Breadcrumb is showing
|
699
|
-
await waitFor(() => {
|
700
|
-
expect(getByLabelText('Resource breadcrumb')).toBeInTheDocument();
|
701
|
-
});
|
702
|
-
|
703
|
-
user.click(screen.getByRole('button', { name: 'Source quick select' }));
|
704
|
-
|
705
|
-
await waitFor(() => {
|
706
|
-
expect(getByRole('button', { name: 'Site Second Website' })).toBeInTheDocument();
|
707
|
-
});
|
708
|
-
|
709
|
-
user.click(getByRole('button', { name: 'Site Second Website' }));
|
710
|
-
|
711
|
-
await waitFor(() => {
|
712
|
-
expect(getByText('Second Page')).toBeInTheDocument();
|
713
|
-
});
|
714
|
-
|
715
|
-
// Expect the clicked child was added to breadcrumb
|
716
|
-
expect(mockHierarchy).toEqual([
|
717
|
-
{
|
718
|
-
key: 'source:1-resource:2',
|
719
|
-
label: 'Second Website',
|
720
|
-
node: expect.any(Object),
|
721
|
-
},
|
722
|
-
]);
|
723
|
-
});
|
724
|
-
|
725
|
-
describe('handleDetailSelect() tests', () => {
|
726
|
-
it('Source select works', async () => {
|
727
|
-
const onChangeMock = jest.fn();
|
728
|
-
const onCloseMock = jest.fn();
|
729
|
-
const { getAllByText } = render(
|
730
|
-
<ResourcePickerContainer {...baseProps} onChange={onChangeMock} onClose={onCloseMock} />,
|
731
|
-
);
|
732
|
-
|
733
|
-
await waitFor(() => {
|
734
|
-
expect(getAllByText('Test system')[0]).toBeInTheDocument();
|
735
|
-
});
|
736
|
-
|
737
|
-
const user = userEvent.setup();
|
738
|
-
|
739
|
-
// Select the resource
|
740
|
-
user.click(screen.getByRole('button', { name: 'site Test Website' }));
|
741
|
-
|
742
|
-
// Wait for the preview panel to open
|
743
|
-
await waitFor(() => expect(screen.getByText('Site')).toBeInTheDocument());
|
744
|
-
await waitFor(() => expect(screen.getByText('#1')).toBeInTheDocument());
|
745
|
-
|
746
|
-
user.click(screen.getByRole('button', { name: 'Select' }));
|
747
|
-
|
748
|
-
await waitFor(() => expect(onChangeMock).toHaveBeenCalled());
|
749
|
-
await waitFor(() => expect(onCloseMock).toHaveBeenCalled());
|
750
|
-
});
|
751
|
-
|
752
|
-
it('Resource select works', async () => {
|
753
|
-
const onChangeMock = jest.fn();
|
754
|
-
const onCloseMock = jest.fn();
|
755
|
-
const { getAllByText } = render(
|
756
|
-
<ResourcePickerContainer {...baseProps} onChange={onChangeMock} onClose={onCloseMock} />,
|
757
|
-
);
|
758
|
-
|
759
|
-
await waitFor(() => {
|
760
|
-
expect(getAllByText('Test system')[0]).toBeInTheDocument();
|
761
|
-
});
|
762
|
-
|
763
|
-
const user = userEvent.setup();
|
764
|
-
user.click(screen.getByRole('button', { name: 'Drill down to Test Website children' }));
|
765
|
-
await waitFor(() => expect(screen.getByRole('button', { name: 'page Test Page' })).toBeInTheDocument());
|
766
|
-
|
767
|
-
// Select the resource
|
768
|
-
user.click(screen.getByRole('button', { name: 'page Test Page' }));
|
769
|
-
|
770
|
-
// Wait for the preview panel to open
|
771
|
-
await waitFor(() => expect(screen.getByText('Mocked Page')).toBeInTheDocument());
|
772
|
-
await waitFor(() => expect(screen.getByText('#123')).toBeInTheDocument());
|
773
|
-
|
774
|
-
user.click(screen.getByRole('button', { name: 'Select' }));
|
775
|
-
|
776
|
-
await waitFor(() => expect(onChangeMock).toHaveBeenCalled());
|
777
|
-
await waitFor(() => expect(onCloseMock).toHaveBeenCalled());
|
778
|
-
});
|
779
|
-
});
|
780
|
-
});
|