datajunction-ui 0.0.1-a1 → 0.0.1-a101
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/Makefile +7 -1
- package/package.json +18 -7
- package/public/index.html +1 -1
- package/src/app/components/AddNodeDropdown.jsx +44 -0
- package/src/app/components/ListGroupItem.jsx +2 -1
- package/src/app/components/NodeListActions.jsx +69 -0
- package/src/app/components/NodeMaterializationDelete.jsx +80 -0
- package/src/app/components/QueryInfo.jsx +96 -1
- package/src/app/components/Search.jsx +94 -0
- package/src/app/components/__tests__/NodeListActions.test.jsx +94 -0
- package/src/app/components/__tests__/Search.test.jsx +63 -0
- package/src/app/components/__tests__/__snapshots__/ListGroupItem.test.tsx.snap +5 -3
- package/src/app/components/djgraph/Collapse.jsx +3 -2
- package/src/app/components/djgraph/DJNode.jsx +1 -1
- package/src/app/components/djgraph/DJNodeColumns.jsx +5 -1
- package/src/app/components/djgraph/LayoutFlow.jsx +5 -3
- package/src/app/components/forms/Action.jsx +8 -0
- package/src/app/components/forms/NodeNameField.jsx +64 -0
- package/src/app/components/search.css +17 -0
- package/src/app/icons/AddItemIcon.jsx +16 -0
- package/src/app/icons/CommitIcon.jsx +45 -0
- package/src/app/icons/DiffIcon.jsx +63 -0
- package/src/app/icons/EyeIcon.jsx +20 -0
- package/src/app/icons/FilterIcon.jsx +7 -0
- package/src/app/icons/JupyterExportIcon.jsx +25 -0
- package/src/app/icons/LoadingIcon.jsx +10 -10
- package/src/app/icons/PythonIcon.jsx +6 -44
- package/src/app/index.tsx +24 -0
- package/src/app/pages/AddEditNodePage/AlertMessage.jsx +10 -0
- package/src/app/pages/AddEditNodePage/ColumnsSelect.jsx +84 -0
- package/src/app/pages/AddEditNodePage/DescriptionField.jsx +17 -0
- package/src/app/pages/AddEditNodePage/DisplayNameField.jsx +16 -0
- package/src/app/pages/AddEditNodePage/FormikSelect.jsx +5 -0
- package/src/app/pages/AddEditNodePage/FullNameField.jsx +3 -2
- package/src/app/pages/AddEditNodePage/Loadable.jsx +6 -2
- package/src/app/pages/AddEditNodePage/MetricMetadataFields.jsx +75 -0
- package/src/app/pages/AddEditNodePage/MetricQueryField.jsx +71 -0
- package/src/app/pages/AddEditNodePage/NamespaceField.jsx +40 -0
- package/src/app/pages/AddEditNodePage/NodeModeField.jsx +14 -0
- package/src/app/pages/AddEditNodePage/NodeQueryField.jsx +8 -3
- package/src/app/pages/AddEditNodePage/RequiredDimensionsSelect.jsx +54 -0
- package/src/app/pages/AddEditNodePage/TagsField.jsx +47 -0
- package/src/app/pages/AddEditNodePage/UpstreamNodeField.jsx +49 -0
- package/src/app/pages/AddEditNodePage/__tests__/AddEditNodePageFormFailed.test.jsx +15 -9
- package/src/app/pages/AddEditNodePage/__tests__/AddEditNodePageFormSuccess.test.jsx +167 -24
- package/src/app/pages/AddEditNodePage/__tests__/index.test.jsx +55 -25
- package/src/app/pages/AddEditNodePage/index.jsx +275 -194
- package/src/app/pages/CubeBuilderPage/DimensionsSelect.jsx +154 -0
- package/src/app/pages/CubeBuilderPage/Loadable.jsx +16 -0
- package/src/app/pages/CubeBuilderPage/MetricsSelect.jsx +77 -0
- package/src/app/pages/CubeBuilderPage/__tests__/index.test.jsx +405 -0
- package/src/app/pages/CubeBuilderPage/index.jsx +267 -0
- package/src/app/pages/NamespacePage/AddNamespacePopover.jsx +5 -5
- package/src/app/pages/NamespacePage/Explorer.jsx +6 -2
- package/src/app/pages/NamespacePage/FieldControl.jsx +21 -0
- package/src/app/pages/NamespacePage/NodeTypeSelect.jsx +30 -0
- package/src/app/pages/NamespacePage/TagSelect.jsx +44 -0
- package/src/app/pages/NamespacePage/UserSelect.jsx +47 -0
- package/src/app/pages/NamespacePage/__tests__/index.test.jsx +98 -19
- package/src/app/pages/NamespacePage/index.jsx +272 -89
- package/src/app/pages/NodePage/AddBackfillPopover.jsx +60 -61
- package/src/app/pages/NodePage/AddMaterializationPopover.jsx +104 -51
- package/src/app/pages/NodePage/ClientCodePopover.jsx +73 -25
- package/src/app/pages/NodePage/DimensionFilter.jsx +86 -0
- package/src/app/pages/NodePage/EditColumnDescriptionPopover.jsx +116 -0
- package/src/app/pages/NodePage/LinkDimensionPopover.jsx +38 -23
- package/src/app/pages/NodePage/MaterializationConfigField.jsx +60 -0
- package/src/app/pages/NodePage/NodeColumnTab.jsx +183 -113
- package/src/app/pages/NodePage/NodeDependenciesTab.jsx +153 -0
- package/src/app/pages/NodePage/NodeGraphTab.jsx +56 -29
- package/src/app/pages/NodePage/NodeHistory.jsx +165 -161
- package/src/app/pages/NodePage/NodeInfoTab.jsx +148 -14
- package/src/app/pages/NodePage/NodeMaterializationTab.jsx +201 -104
- package/src/app/pages/NodePage/NodeStatus.jsx +96 -21
- package/src/app/pages/NodePage/NodeValidateTab.jsx +367 -0
- package/src/app/pages/NodePage/NotebookDownload.jsx +36 -0
- package/src/app/pages/NodePage/PartitionColumnPopover.jsx +3 -5
- package/src/app/pages/NodePage/PartitionValueForm.jsx +60 -0
- package/src/app/pages/NodePage/RevisionDiff.jsx +209 -0
- package/src/app/pages/NodePage/WatchNodeButton.jsx +226 -0
- package/src/app/pages/NodePage/__tests__/AddBackfillPopover.test.jsx +13 -4
- package/src/app/pages/NodePage/__tests__/AddMaterializationPopover.test.jsx +87 -0
- package/src/app/pages/NodePage/__tests__/DimensionFilter.test.jsx +74 -0
- package/src/app/pages/NodePage/__tests__/EditColumnDescriptionPopover.test.jsx +149 -0
- package/src/app/pages/NodePage/__tests__/LinkDimensionPopover.test.jsx +10 -14
- package/src/app/pages/NodePage/__tests__/NodeColumnTab.test.jsx +166 -0
- package/src/app/pages/NodePage/__tests__/NodeDependenciesTab.test.jsx +151 -0
- package/src/app/pages/NodePage/__tests__/NodeGraphTab.test.jsx +6 -2
- package/src/app/pages/NodePage/__tests__/NodeLineageTab.test.jsx +3 -2
- package/src/app/pages/NodePage/__tests__/NodeMaterializationTab.test.jsx +148 -0
- package/src/app/pages/NodePage/__tests__/NodePage.test.jsx +159 -57
- package/src/app/pages/NodePage/__tests__/RevisionDiff.test.jsx +164 -0
- package/src/app/pages/NodePage/__tests__/__snapshots__/NodePage.test.jsx.snap +2 -386
- package/src/app/pages/NodePage/index.jsx +94 -57
- package/src/app/pages/Root/__tests__/index.test.jsx +3 -1
- package/src/app/pages/Root/index.tsx +62 -12
- package/src/app/services/DJService.js +587 -55
- package/src/app/services/__tests__/DJService.test.jsx +382 -45
- package/src/index.tsx +1 -0
- package/src/mocks/mockNodes.jsx +265 -227
- package/src/styles/dag.css +4 -2
- package/src/styles/index.css +474 -10
- package/src/styles/loading.css +1 -1
- package/src/styles/node-creation.scss +84 -5
- package/src/styles/node-list.css +4 -0
- package/src/styles/sorted-table.css +15 -0
- package/src/app/components/DeleteNode.jsx +0 -55
- package/src/app/components/__tests__/DeleteNode.test.jsx +0 -53
- package/src/app/pages/NodePage/NodeSQLTab.jsx +0 -82
- package/src/app/pages/NodePage/__tests__/ClientCodePopover.test.jsx +0 -49
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { render, waitFor, screen } from '@testing-library/react';
|
|
3
|
+
import NodeMaterializationTab from '../NodeMaterializationTab';
|
|
4
|
+
|
|
5
|
+
describe('<NodeMaterializationTab />', () => {
|
|
6
|
+
const mockDjClient = {
|
|
7
|
+
node: jest.fn(),
|
|
8
|
+
materializations: jest.fn(),
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const mockMaterializations = [
|
|
12
|
+
{
|
|
13
|
+
name: 'mat_one',
|
|
14
|
+
config: {},
|
|
15
|
+
schedule: '@daily',
|
|
16
|
+
job: 'SparkSqlMaterializationJob',
|
|
17
|
+
backfills: [
|
|
18
|
+
{
|
|
19
|
+
spec: [
|
|
20
|
+
{
|
|
21
|
+
column_name: 'date',
|
|
22
|
+
values: ['20200101'],
|
|
23
|
+
range: ['20201010'],
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
urls: ['https://example.com/'],
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
strategy: 'full',
|
|
30
|
+
output_tables: ['table1'],
|
|
31
|
+
urls: ['https://example.com/'],
|
|
32
|
+
},
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
const mockNode = {
|
|
36
|
+
node_revision_id: 1,
|
|
37
|
+
node_id: 1,
|
|
38
|
+
type: 'source',
|
|
39
|
+
name: 'default.repair_orders',
|
|
40
|
+
display_name: 'Default: Repair Orders',
|
|
41
|
+
version: 'v1.0',
|
|
42
|
+
status: 'valid',
|
|
43
|
+
mode: 'published',
|
|
44
|
+
catalog: {
|
|
45
|
+
id: 1,
|
|
46
|
+
uuid: '0fc18295-e1a2-4c3c-b72a-894725c12488',
|
|
47
|
+
created_at: '2023-08-21T16:48:51.146121+00:00',
|
|
48
|
+
updated_at: '2023-08-21T16:48:51.146122+00:00',
|
|
49
|
+
extra_params: {},
|
|
50
|
+
name: 'warehouse',
|
|
51
|
+
},
|
|
52
|
+
schema_: 'roads',
|
|
53
|
+
table: 'repair_orders',
|
|
54
|
+
description: 'Repair orders',
|
|
55
|
+
query: null,
|
|
56
|
+
availability: {
|
|
57
|
+
catalog: 'default',
|
|
58
|
+
categorical_partitions: [],
|
|
59
|
+
max_temporal_partition: ['2023', '01', '25'],
|
|
60
|
+
min_temporal_partition: ['2022', '01', '01'],
|
|
61
|
+
partitions: [],
|
|
62
|
+
schema_: 'foo',
|
|
63
|
+
table: 'bar',
|
|
64
|
+
temporal_partitions: [],
|
|
65
|
+
valid_through_ts: 1729667463,
|
|
66
|
+
url: 'https://www.table.com',
|
|
67
|
+
links: { dashboard: 'https://www.foobar.com/dashboard' },
|
|
68
|
+
},
|
|
69
|
+
columns: [
|
|
70
|
+
{
|
|
71
|
+
name: 'repair_order_id',
|
|
72
|
+
type: 'int',
|
|
73
|
+
attributes: [],
|
|
74
|
+
dimension: null,
|
|
75
|
+
partition: {
|
|
76
|
+
type_: 'temporal',
|
|
77
|
+
format: 'YYYYMMDD',
|
|
78
|
+
granularity: 'day',
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
name: 'municipality_id',
|
|
83
|
+
type: 'string',
|
|
84
|
+
attributes: [],
|
|
85
|
+
dimension: null,
|
|
86
|
+
partition: null,
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
name: 'hard_hat_id',
|
|
90
|
+
type: 'int',
|
|
91
|
+
attributes: [],
|
|
92
|
+
dimension: null,
|
|
93
|
+
partition: null,
|
|
94
|
+
},
|
|
95
|
+
],
|
|
96
|
+
updated_at: '2023-08-21T16:48:52.880498+00:00',
|
|
97
|
+
materializations: [
|
|
98
|
+
{
|
|
99
|
+
name: 'mat1',
|
|
100
|
+
config: {},
|
|
101
|
+
schedule: 'string',
|
|
102
|
+
job: 'string',
|
|
103
|
+
backfills: [
|
|
104
|
+
{
|
|
105
|
+
spec: [
|
|
106
|
+
{
|
|
107
|
+
column_name: 'string',
|
|
108
|
+
values: ['string'],
|
|
109
|
+
range: ['string'],
|
|
110
|
+
},
|
|
111
|
+
],
|
|
112
|
+
urls: ['string'],
|
|
113
|
+
},
|
|
114
|
+
],
|
|
115
|
+
strategy: 'string',
|
|
116
|
+
output_tables: ['string'],
|
|
117
|
+
urls: ['https://example.com/'],
|
|
118
|
+
},
|
|
119
|
+
],
|
|
120
|
+
parents: [],
|
|
121
|
+
dimension_links: [
|
|
122
|
+
{
|
|
123
|
+
dimension: {
|
|
124
|
+
name: 'default.contractor',
|
|
125
|
+
},
|
|
126
|
+
join_type: 'left',
|
|
127
|
+
join_sql:
|
|
128
|
+
'default.contractor.contractor_id = default.repair_orders.contractor_id',
|
|
129
|
+
join_cardinality: 'one_to_one',
|
|
130
|
+
role: 'contractor',
|
|
131
|
+
},
|
|
132
|
+
],
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
beforeEach(() => {
|
|
136
|
+
mockDjClient.materializations.mockReset();
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('renders NodeMaterializationTab tab correctly', async () => {
|
|
140
|
+
mockDjClient.materializations.mockReturnValue(mockMaterializations);
|
|
141
|
+
|
|
142
|
+
render(<NodeMaterializationTab node={mockNode} djClient={mockDjClient} />);
|
|
143
|
+
await waitFor(() => {
|
|
144
|
+
const link = screen.getByText('dashboard').closest('a');
|
|
145
|
+
expect(link).toHaveAttribute('href', `https://www.foobar.com/dashboard`);
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
});
|
|
@@ -23,12 +23,15 @@ describe('<NodePage />', () => {
|
|
|
23
23
|
DataJunctionAPI: {
|
|
24
24
|
node: jest.fn(),
|
|
25
25
|
metric: jest.fn(),
|
|
26
|
+
getMetric: jest.fn(),
|
|
27
|
+
revalidate: jest.fn().mockReturnValue({ status: 'valid' }),
|
|
26
28
|
node_dag: jest.fn().mockReturnValue(mocks.mockNodeDAG),
|
|
27
29
|
clientCode: jest.fn().mockReturnValue('dj_client = DJClient()'),
|
|
28
30
|
columns: jest.fn(),
|
|
29
31
|
history: jest.fn(),
|
|
30
32
|
revisions: jest.fn(),
|
|
31
33
|
materializations: jest.fn(),
|
|
34
|
+
materializationInfo: jest.fn(),
|
|
32
35
|
sql: jest.fn(),
|
|
33
36
|
cube: jest.fn(),
|
|
34
37
|
compiledSql: jest.fn(),
|
|
@@ -38,6 +41,8 @@ describe('<NodePage />', () => {
|
|
|
38
41
|
dimensions: jest.fn(),
|
|
39
42
|
setPartition: jest.fn(),
|
|
40
43
|
engines: jest.fn(),
|
|
44
|
+
streamNodeData: jest.fn(),
|
|
45
|
+
nodeDimensions: jest.fn(),
|
|
41
46
|
},
|
|
42
47
|
};
|
|
43
48
|
};
|
|
@@ -68,6 +73,7 @@ describe('<NodePage />', () => {
|
|
|
68
73
|
query:
|
|
69
74
|
'SELECT avg(price) default_DOT_avg_repair_price \n FROM default.repair_order_details\n\n',
|
|
70
75
|
availability: null,
|
|
76
|
+
dimension_links: [],
|
|
71
77
|
columns: [
|
|
72
78
|
{
|
|
73
79
|
name: 'default_DOT_avg_repair_price',
|
|
@@ -87,6 +93,7 @@ describe('<NodePage />', () => {
|
|
|
87
93
|
created_at: '2023-08-21T16:48:56.932162+00:00',
|
|
88
94
|
tags: [{ name: 'purpose', display_name: 'Purpose' }],
|
|
89
95
|
primary_key: [],
|
|
96
|
+
incompatible_druid_functions: ['IF'],
|
|
90
97
|
createNodeClientCode:
|
|
91
98
|
'dj = DJBuilder(DJ_URL)\n\navg_repair_price = dj.create_metric(\n description="Average repair price",\n display_name="Default: Avg Repair Price",\n name="default.avg_repair_price",\n primary_key=[],\n query="""SELECT avg(price) default_DOT_avg_repair_price \n FROM default.repair_order_details\n\n"""\n)',
|
|
92
99
|
dimensions: [
|
|
@@ -270,19 +277,21 @@ describe('<NodePage />', () => {
|
|
|
270
277
|
},
|
|
271
278
|
};
|
|
272
279
|
|
|
273
|
-
it('renders the NodeInfo tab correctly', async () => {
|
|
280
|
+
it('renders the NodeInfo tab correctly for a metric node', async () => {
|
|
274
281
|
const djClient = mockDJClient();
|
|
275
282
|
djClient.DataJunctionAPI.node.mockReturnValue(mocks.mockMetricNode);
|
|
276
|
-
djClient.DataJunctionAPI.
|
|
283
|
+
djClient.DataJunctionAPI.getMetric.mockReturnValue(
|
|
284
|
+
mocks.mockMetricNodeJson,
|
|
285
|
+
);
|
|
277
286
|
const element = (
|
|
278
287
|
<DJClientContext.Provider value={djClient}>
|
|
279
288
|
<NodePage {...defaultProps} />
|
|
280
289
|
</DJClientContext.Provider>
|
|
281
290
|
);
|
|
282
291
|
const { container } = render(
|
|
283
|
-
<MemoryRouter initialEntries={['/nodes/default.num_repair_orders']}>
|
|
292
|
+
<MemoryRouter initialEntries={['/nodes/default.num_repair_orders/info']}>
|
|
284
293
|
<Routes>
|
|
285
|
-
<Route path="nodes/:name" element={element} />
|
|
294
|
+
<Route path="nodes/:name/:tab" element={element} />
|
|
286
295
|
</Routes>
|
|
287
296
|
</MemoryRouter>,
|
|
288
297
|
);
|
|
@@ -291,7 +300,6 @@ describe('<NodePage />', () => {
|
|
|
291
300
|
expect(djClient.DataJunctionAPI.node).toHaveBeenCalledWith(
|
|
292
301
|
'default.num_repair_orders',
|
|
293
302
|
);
|
|
294
|
-
userEvent.click(screen.getByRole('button', { name: 'Info' }));
|
|
295
303
|
|
|
296
304
|
expect(
|
|
297
305
|
screen.getByRole('dialog', { name: 'NodeName' }),
|
|
@@ -315,8 +323,8 @@ describe('<NodePage />', () => {
|
|
|
315
323
|
);
|
|
316
324
|
|
|
317
325
|
expect(
|
|
318
|
-
screen.getByRole('dialog', { name: '
|
|
319
|
-
).toHaveTextContent('
|
|
326
|
+
screen.getByRole('dialog', { name: 'RequiredDimensions' }),
|
|
327
|
+
).toHaveTextContent('');
|
|
320
328
|
|
|
321
329
|
expect(
|
|
322
330
|
screen.getByRole('dialog', { name: 'DisplayName' }),
|
|
@@ -394,7 +402,9 @@ describe('<NodePage />', () => {
|
|
|
394
402
|
it('renders the NodeColumns tab correctly', async () => {
|
|
395
403
|
const djClient = mockDJClient();
|
|
396
404
|
djClient.DataJunctionAPI.node.mockReturnValue(mocks.mockMetricNode);
|
|
397
|
-
djClient.DataJunctionAPI.
|
|
405
|
+
djClient.DataJunctionAPI.getMetric.mockReturnValue(
|
|
406
|
+
mocks.mockMetricNodeJson,
|
|
407
|
+
);
|
|
398
408
|
djClient.DataJunctionAPI.columns.mockReturnValue(mocks.metricNodeColumns);
|
|
399
409
|
djClient.DataJunctionAPI.attributes.mockReturnValue(mocks.attributes);
|
|
400
410
|
djClient.DataJunctionAPI.dimensions.mockReturnValue(mocks.dimensions);
|
|
@@ -410,14 +420,15 @@ describe('<NodePage />', () => {
|
|
|
410
420
|
</DJClientContext.Provider>
|
|
411
421
|
);
|
|
412
422
|
render(
|
|
413
|
-
<MemoryRouter
|
|
423
|
+
<MemoryRouter
|
|
424
|
+
initialEntries={['/nodes/default.num_repair_orders/columns']}
|
|
425
|
+
>
|
|
414
426
|
<Routes>
|
|
415
|
-
<Route path="nodes/:name" element={element} />
|
|
427
|
+
<Route path="nodes/:name/:tab" element={element} />
|
|
416
428
|
</Routes>
|
|
417
429
|
</MemoryRouter>,
|
|
418
430
|
);
|
|
419
431
|
await waitFor(() => {
|
|
420
|
-
fireEvent.click(screen.getByRole('button', { name: 'Columns' }));
|
|
421
432
|
expect(djClient.DataJunctionAPI.columns).toHaveBeenCalledWith(
|
|
422
433
|
mocks.mockMetricNode,
|
|
423
434
|
);
|
|
@@ -464,13 +475,15 @@ describe('<NodePage />', () => {
|
|
|
464
475
|
fireEvent.click(savePartition);
|
|
465
476
|
expect(screen.getByText('Saved!'));
|
|
466
477
|
});
|
|
467
|
-
});
|
|
478
|
+
}, 60000);
|
|
468
479
|
// check compiled SQL on nodeInfo page
|
|
469
480
|
|
|
470
481
|
it('renders the NodeHistory tab correctly', async () => {
|
|
471
482
|
const djClient = mockDJClient();
|
|
472
483
|
djClient.DataJunctionAPI.node.mockReturnValue(mocks.mockMetricNode);
|
|
473
|
-
djClient.DataJunctionAPI.
|
|
484
|
+
djClient.DataJunctionAPI.getMetric.mockReturnValue(
|
|
485
|
+
mocks.mockMetricNodeJson,
|
|
486
|
+
);
|
|
474
487
|
djClient.DataJunctionAPI.columns.mockReturnValue(mocks.metricNodeColumns);
|
|
475
488
|
djClient.DataJunctionAPI.history.mockReturnValue(mocks.metricNodeHistory);
|
|
476
489
|
djClient.DataJunctionAPI.revisions.mockReturnValue(
|
|
@@ -483,9 +496,11 @@ describe('<NodePage />', () => {
|
|
|
483
496
|
</DJClientContext.Provider>
|
|
484
497
|
);
|
|
485
498
|
const { container } = render(
|
|
486
|
-
<MemoryRouter
|
|
499
|
+
<MemoryRouter
|
|
500
|
+
initialEntries={['/nodes/default.num_repair_orders/history']}
|
|
501
|
+
>
|
|
487
502
|
<Routes>
|
|
488
|
-
<Route path="nodes/:name" element={element} />
|
|
503
|
+
<Route path="nodes/:name/:tab" element={element} />
|
|
489
504
|
</Routes>
|
|
490
505
|
</MemoryRouter>,
|
|
491
506
|
);
|
|
@@ -498,15 +513,9 @@ describe('<NodePage />', () => {
|
|
|
498
513
|
'node',
|
|
499
514
|
mocks.mockMetricNode.name,
|
|
500
515
|
);
|
|
501
|
-
expect(djClient.DataJunctionAPI.revisions).toHaveBeenCalledWith(
|
|
502
|
-
mocks.mockMetricNode.name,
|
|
503
|
-
);
|
|
504
516
|
expect(
|
|
505
|
-
screen.getByRole('
|
|
506
|
-
).
|
|
507
|
-
expect(screen.getByRole('table', { name: 'Activity' })).toHaveTextContent(
|
|
508
|
-
'ActivityTypeNameUserTimestampDetailscreatenodedefault.avg_repair_priceunknown2023-08-21T16:48:56.950482+00:00',
|
|
509
|
-
);
|
|
517
|
+
screen.getByRole('list', { name: 'Activity' }),
|
|
518
|
+
).toBeInTheDocument();
|
|
510
519
|
screen
|
|
511
520
|
.queryAllByRole('cell', {
|
|
512
521
|
name: 'HistoryAttribute',
|
|
@@ -542,14 +551,12 @@ describe('<NodePage />', () => {
|
|
|
542
551
|
'Status changed from valid to invalid Caused by a change in upstream default.repair_order_details',
|
|
543
552
|
),
|
|
544
553
|
);
|
|
545
|
-
screen.debug();
|
|
546
554
|
});
|
|
547
555
|
});
|
|
548
556
|
|
|
549
557
|
it('renders compiled sql correctly', async () => {
|
|
550
558
|
const djClient = mockDJClient();
|
|
551
|
-
djClient.DataJunctionAPI.node.mockReturnValue(mocks.
|
|
552
|
-
djClient.DataJunctionAPI.metric.mockReturnValue(mocks.mockMetricNode);
|
|
559
|
+
djClient.DataJunctionAPI.node.mockReturnValue(mocks.mockTransformNode);
|
|
553
560
|
djClient.DataJunctionAPI.columns.mockReturnValue(mocks.metricNodeColumns);
|
|
554
561
|
djClient.DataJunctionAPI.compiledSql.mockReturnValue('select 1');
|
|
555
562
|
|
|
@@ -559,7 +566,7 @@ describe('<NodePage />', () => {
|
|
|
559
566
|
</DJClientContext.Provider>
|
|
560
567
|
);
|
|
561
568
|
render(
|
|
562
|
-
<MemoryRouter initialEntries={[
|
|
569
|
+
<MemoryRouter initialEntries={[`/nodes/${mocks.mockTransformNode.name}`]}>
|
|
563
570
|
<Routes>
|
|
564
571
|
<Route path="nodes/:name" element={element} />
|
|
565
572
|
</Routes>
|
|
@@ -568,7 +575,7 @@ describe('<NodePage />', () => {
|
|
|
568
575
|
await waitFor(() => {
|
|
569
576
|
fireEvent.click(screen.getByRole('checkbox', { name: 'ToggleSwitch' }));
|
|
570
577
|
expect(djClient.DataJunctionAPI.compiledSql).toHaveBeenCalledWith(
|
|
571
|
-
mocks.
|
|
578
|
+
mocks.mockTransformNode.name,
|
|
572
579
|
);
|
|
573
580
|
});
|
|
574
581
|
});
|
|
@@ -576,7 +583,9 @@ describe('<NodePage />', () => {
|
|
|
576
583
|
it('renders an empty NodeMaterialization tab correctly', async () => {
|
|
577
584
|
const djClient = mockDJClient();
|
|
578
585
|
djClient.DataJunctionAPI.node.mockReturnValue(mocks.mockMetricNode);
|
|
579
|
-
djClient.DataJunctionAPI.
|
|
586
|
+
djClient.DataJunctionAPI.getMetric.mockReturnValue(
|
|
587
|
+
mocks.mockMetricNodeJson,
|
|
588
|
+
);
|
|
580
589
|
djClient.DataJunctionAPI.columns.mockReturnValue(mocks.metricNodeColumns);
|
|
581
590
|
djClient.DataJunctionAPI.materializations.mockReturnValue([]);
|
|
582
591
|
|
|
@@ -586,9 +595,11 @@ describe('<NodePage />', () => {
|
|
|
586
595
|
</DJClientContext.Provider>
|
|
587
596
|
);
|
|
588
597
|
render(
|
|
589
|
-
<MemoryRouter
|
|
598
|
+
<MemoryRouter
|
|
599
|
+
initialEntries={['/nodes/default.num_repair_orders/materializations']}
|
|
600
|
+
>
|
|
590
601
|
<Routes>
|
|
591
|
-
<Route path="nodes/:name" element={element} />
|
|
602
|
+
<Route path="nodes/:name/:tab" element={element} />
|
|
592
603
|
</Routes>
|
|
593
604
|
</MemoryRouter>,
|
|
594
605
|
);
|
|
@@ -606,22 +617,32 @@ describe('<NodePage />', () => {
|
|
|
606
617
|
|
|
607
618
|
it('renders the NodeMaterialization tab with materializations correctly', async () => {
|
|
608
619
|
const djClient = mockDJClient();
|
|
609
|
-
djClient.DataJunctionAPI.node.mockReturnValue(mocks.
|
|
610
|
-
djClient.DataJunctionAPI.
|
|
620
|
+
djClient.DataJunctionAPI.node.mockReturnValue(mocks.mockTransformNode);
|
|
621
|
+
djClient.DataJunctionAPI.getMetric.mockReturnValue(
|
|
622
|
+
mocks.mockMetricNodeJson,
|
|
623
|
+
);
|
|
611
624
|
djClient.DataJunctionAPI.columns.mockReturnValue(mocks.metricNodeColumns);
|
|
612
625
|
djClient.DataJunctionAPI.materializations.mockReturnValue(
|
|
613
626
|
mocks.nodeMaterializations,
|
|
614
627
|
);
|
|
615
628
|
|
|
629
|
+
djClient.DataJunctionAPI.materializationInfo.mockReturnValue(
|
|
630
|
+
mocks.materializationInfo,
|
|
631
|
+
);
|
|
632
|
+
|
|
616
633
|
const element = (
|
|
617
634
|
<DJClientContext.Provider value={djClient}>
|
|
618
635
|
<NodePage />
|
|
619
636
|
</DJClientContext.Provider>
|
|
620
637
|
);
|
|
621
638
|
render(
|
|
622
|
-
<MemoryRouter
|
|
639
|
+
<MemoryRouter
|
|
640
|
+
initialEntries={[
|
|
641
|
+
'/nodes/default.repair_order_transform/materializations',
|
|
642
|
+
]}
|
|
643
|
+
>
|
|
623
644
|
<Routes>
|
|
624
|
-
<Route path="nodes/:name" element={element} />
|
|
645
|
+
<Route path="nodes/:name/:tab" element={element} />
|
|
625
646
|
</Routes>
|
|
626
647
|
</MemoryRouter>,
|
|
627
648
|
);
|
|
@@ -631,52 +652,129 @@ describe('<NodePage />', () => {
|
|
|
631
652
|
screen.getByRole('button', { name: 'Materializations' }),
|
|
632
653
|
);
|
|
633
654
|
expect(djClient.DataJunctionAPI.node).toHaveBeenCalledWith(
|
|
634
|
-
mocks.
|
|
655
|
+
mocks.mockTransformNode.name,
|
|
635
656
|
);
|
|
636
657
|
expect(djClient.DataJunctionAPI.materializations).toHaveBeenCalledWith(
|
|
637
|
-
mocks.
|
|
658
|
+
mocks.mockTransformNode.name,
|
|
638
659
|
);
|
|
639
|
-
|
|
640
|
-
expect(
|
|
641
|
-
screen.getByRole('table', { name: 'Materializations' }),
|
|
642
|
-
).toMatchSnapshot();
|
|
643
660
|
},
|
|
644
661
|
{ timeout: 3000 },
|
|
645
662
|
);
|
|
646
663
|
}, 60000);
|
|
647
664
|
|
|
648
|
-
it('renders the
|
|
665
|
+
it('renders the NodeValidate tab', async () => {
|
|
649
666
|
const djClient = mockDJClient();
|
|
667
|
+
window.scrollTo = jest.fn();
|
|
650
668
|
djClient.DataJunctionAPI.node.mockReturnValue(mocks.mockMetricNode);
|
|
651
|
-
djClient.DataJunctionAPI.
|
|
669
|
+
djClient.DataJunctionAPI.nodeDimensions.mockReturnValue([]);
|
|
670
|
+
djClient.DataJunctionAPI.getMetric.mockReturnValue(
|
|
671
|
+
mocks.mockMetricNodeJson,
|
|
672
|
+
);
|
|
652
673
|
djClient.DataJunctionAPI.columns.mockReturnValue(mocks.metricNodeColumns);
|
|
653
|
-
djClient.DataJunctionAPI.sql.mockReturnValue(
|
|
674
|
+
djClient.DataJunctionAPI.sql.mockReturnValue({
|
|
675
|
+
sql: 'SELECT * FROM testNode',
|
|
676
|
+
});
|
|
677
|
+
const streamNodeData = {
|
|
678
|
+
onmessage: jest.fn(),
|
|
679
|
+
onerror: jest.fn(),
|
|
680
|
+
close: jest.fn(),
|
|
681
|
+
};
|
|
682
|
+
djClient.DataJunctionAPI.streamNodeData.mockResolvedValue(streamNodeData);
|
|
683
|
+
djClient.DataJunctionAPI.streamNodeData.mockResolvedValueOnce({
|
|
684
|
+
state: 'FINISHED',
|
|
685
|
+
results: [
|
|
686
|
+
{
|
|
687
|
+
columns: [{ name: 'column1' }, { name: 'column2' }],
|
|
688
|
+
rows: [
|
|
689
|
+
[1, 'value1'],
|
|
690
|
+
[2, 'value2'],
|
|
691
|
+
],
|
|
692
|
+
},
|
|
693
|
+
],
|
|
694
|
+
});
|
|
695
|
+
|
|
654
696
|
const element = (
|
|
655
697
|
<DJClientContext.Provider value={djClient}>
|
|
656
698
|
<NodePage />
|
|
657
699
|
</DJClientContext.Provider>
|
|
658
700
|
);
|
|
659
701
|
render(
|
|
660
|
-
<MemoryRouter
|
|
702
|
+
<MemoryRouter
|
|
703
|
+
initialEntries={['/nodes/default.num_repair_orders/validate']}
|
|
704
|
+
>
|
|
661
705
|
<Routes>
|
|
662
|
-
<Route path="nodes/:name" element={element} />
|
|
706
|
+
<Route path="nodes/:name/:tab" element={element} />
|
|
663
707
|
</Routes>
|
|
664
708
|
</MemoryRouter>,
|
|
665
709
|
);
|
|
710
|
+
|
|
711
|
+
await waitFor(() => {
|
|
712
|
+
expect(screen.getByText('Group By')).toBeInTheDocument();
|
|
713
|
+
expect(screen.getByText('Add Filters')).toBeInTheDocument();
|
|
714
|
+
expect(screen.getByText('Generated Query')).toBeInTheDocument();
|
|
715
|
+
expect(screen.getByText('Results')).toBeInTheDocument();
|
|
716
|
+
});
|
|
717
|
+
// Click on the 'Validate' tab
|
|
718
|
+
fireEvent.click(screen.getByRole('button', { name: '► Validate' }));
|
|
719
|
+
|
|
666
720
|
await waitFor(() => {
|
|
667
|
-
|
|
668
|
-
|
|
721
|
+
expect(djClient.DataJunctionAPI.node).toHaveBeenCalledWith(
|
|
722
|
+
mocks.mockMetricNode.name,
|
|
723
|
+
);
|
|
669
724
|
expect(djClient.DataJunctionAPI.sql).toHaveBeenCalledWith(
|
|
670
|
-
|
|
725
|
+
mocks.mockMetricNode.name,
|
|
726
|
+
{ dimensions: [], filters: [] },
|
|
727
|
+
);
|
|
728
|
+
expect(djClient.DataJunctionAPI.nodeDimensions).toHaveBeenCalledWith(
|
|
729
|
+
mocks.mockMetricNode.name,
|
|
730
|
+
);
|
|
731
|
+
});
|
|
732
|
+
|
|
733
|
+
// Click on 'Run' to run the node query
|
|
734
|
+
const runButton = screen.getByText('► Run');
|
|
735
|
+
fireEvent.click(runButton);
|
|
736
|
+
|
|
737
|
+
await waitFor(() => {
|
|
738
|
+
expect(djClient.DataJunctionAPI.streamNodeData).toHaveBeenCalledWith(
|
|
739
|
+
mocks.mockMetricNode.name,
|
|
671
740
|
{ dimensions: [], filters: [] },
|
|
672
741
|
);
|
|
742
|
+
expect(streamNodeData.onmessage).toBeDefined();
|
|
743
|
+
expect(streamNodeData.onerror).toBeDefined();
|
|
744
|
+
});
|
|
745
|
+
|
|
746
|
+
const infoTab = screen.getByRole('button', { name: 'QueryInfo' });
|
|
747
|
+
const resultsTab = screen.getByText('Results');
|
|
748
|
+
|
|
749
|
+
// Initially, the Results tab should be active
|
|
750
|
+
expect(resultsTab).toHaveClass('active');
|
|
751
|
+
expect(infoTab).not.toHaveClass('active');
|
|
752
|
+
|
|
753
|
+
// Click on the Info tab first
|
|
754
|
+
fireEvent.click(infoTab);
|
|
755
|
+
|
|
756
|
+
await waitFor(() => {
|
|
757
|
+
// Now, the Info tab should be active
|
|
758
|
+
expect(infoTab).toHaveClass('active');
|
|
759
|
+
expect(resultsTab).not.toHaveClass('active');
|
|
760
|
+
});
|
|
761
|
+
|
|
762
|
+
// Click on the Results tab
|
|
763
|
+
fireEvent.click(resultsTab);
|
|
764
|
+
|
|
765
|
+
await waitFor(() => {
|
|
766
|
+
// Now, the Results tab should be active again
|
|
767
|
+
expect(resultsTab).toHaveClass('active');
|
|
768
|
+
expect(infoTab).not.toHaveClass('active');
|
|
673
769
|
});
|
|
674
770
|
});
|
|
675
771
|
|
|
676
772
|
it('renders a NodeColumnLineage tab correctly', async () => {
|
|
677
773
|
const djClient = mockDJClient();
|
|
678
774
|
djClient.DataJunctionAPI.node.mockReturnValue(mocks.mockMetricNode);
|
|
679
|
-
djClient.DataJunctionAPI.
|
|
775
|
+
djClient.DataJunctionAPI.getMetric.mockReturnValue(
|
|
776
|
+
mocks.mockMetricNodeJson,
|
|
777
|
+
);
|
|
680
778
|
djClient.DataJunctionAPI.columns.mockReturnValue(mocks.metricNodeColumns);
|
|
681
779
|
djClient.DataJunctionAPI.node_lineage.mockReturnValue(
|
|
682
780
|
mocks.mockNodeLineage,
|
|
@@ -688,9 +786,11 @@ describe('<NodePage />', () => {
|
|
|
688
786
|
</DJClientContext.Provider>
|
|
689
787
|
);
|
|
690
788
|
render(
|
|
691
|
-
<MemoryRouter
|
|
789
|
+
<MemoryRouter
|
|
790
|
+
initialEntries={['/nodes/default.num_repair_orders/lineage']}
|
|
791
|
+
>
|
|
692
792
|
<Routes>
|
|
693
|
-
<Route path="nodes/:name" element={element} />
|
|
793
|
+
<Route path="nodes/:name/:tab" element={element} />
|
|
694
794
|
</Routes>
|
|
695
795
|
</MemoryRouter>,
|
|
696
796
|
);
|
|
@@ -705,7 +805,9 @@ describe('<NodePage />', () => {
|
|
|
705
805
|
it('renders a NodeGraph tab correctly', async () => {
|
|
706
806
|
const djClient = mockDJClient();
|
|
707
807
|
djClient.DataJunctionAPI.node.mockReturnValue(mocks.mockMetricNode);
|
|
708
|
-
djClient.DataJunctionAPI.
|
|
808
|
+
djClient.DataJunctionAPI.getMetric.mockReturnValue(
|
|
809
|
+
mocks.mockMetricNodeJson,
|
|
810
|
+
);
|
|
709
811
|
djClient.DataJunctionAPI.columns.mockReturnValue(mocks.metricNodeColumns);
|
|
710
812
|
|
|
711
813
|
const element = (
|
|
@@ -714,9 +816,9 @@ describe('<NodePage />', () => {
|
|
|
714
816
|
</DJClientContext.Provider>
|
|
715
817
|
);
|
|
716
818
|
render(
|
|
717
|
-
<MemoryRouter initialEntries={['/nodes/default.num_repair_orders']}>
|
|
819
|
+
<MemoryRouter initialEntries={['/nodes/default.num_repair_orders/graph']}>
|
|
718
820
|
<Routes>
|
|
719
|
-
<Route path="nodes/:name" element={element} />
|
|
821
|
+
<Route path="nodes/:name/:tab" element={element} />
|
|
720
822
|
</Routes>
|
|
721
823
|
</MemoryRouter>,
|
|
722
824
|
);
|
|
@@ -741,9 +843,9 @@ describe('<NodePage />', () => {
|
|
|
741
843
|
</DJClientContext.Provider>
|
|
742
844
|
);
|
|
743
845
|
render(
|
|
744
|
-
<MemoryRouter initialEntries={['/nodes/default.dispatcher']}>
|
|
846
|
+
<MemoryRouter initialEntries={['/nodes/default.dispatcher/linked']}>
|
|
745
847
|
<Routes>
|
|
746
|
-
<Route path="nodes/:name" element={element} />
|
|
848
|
+
<Route path="nodes/:name/:tab" element={element} />
|
|
747
849
|
</Routes>
|
|
748
850
|
</MemoryRouter>,
|
|
749
851
|
);
|