datajunction-ui 0.0.1-a42.dev0 → 0.0.1-a43.dev0
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/package.json +1 -1
- package/src/app/index.tsx +1 -0
- package/src/app/pages/AddEditNodePage/AlertMessage.jsx +10 -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 +2 -0
- package/src/app/pages/AddEditNodePage/FullNameField.jsx +3 -2
- package/src/app/pages/AddEditNodePage/MetricMetadataFields.jsx +60 -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 +5 -3
- package/src/app/pages/AddEditNodePage/PrimaryKeySelect.jsx +61 -0
- 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 +2 -1
- package/src/app/pages/AddEditNodePage/__tests__/AddEditNodePageFormSuccess.test.jsx +150 -14
- package/src/app/pages/AddEditNodePage/__tests__/index.test.jsx +35 -8
- package/src/app/pages/AddEditNodePage/index.jsx +177 -232
- package/src/app/pages/CubeBuilderPage/MetricsSelect.jsx +0 -1
- package/src/app/pages/CubeBuilderPage/__tests__/index.test.jsx +1 -1
- package/src/app/pages/CubeBuilderPage/index.jsx +1 -1
- package/src/app/pages/NodePage/AddMaterializationPopover.jsx +0 -1
- package/src/app/pages/NodePage/NodeHistory.jsx +1 -1
- package/src/app/pages/NodePage/NodeInfoTab.jsx +54 -13
- package/src/app/pages/NodePage/__tests__/NodePage.test.jsx +34 -28
- package/src/app/pages/NodePage/__tests__/__snapshots__/NodePage.test.jsx.snap +2 -18
- package/src/app/pages/NodePage/index.jsx +30 -27
- package/src/app/pages/Root/index.tsx +3 -2
- package/src/app/services/DJService.js +37 -0
- package/src/app/services/__tests__/DJService.test.jsx +23 -0
- package/src/mocks/mockNodes.jsx +63 -0
- package/src/styles/index.css +6 -0
- package/src/styles/node-creation.scss +63 -5
- package/dj.internal.db +0 -0
|
@@ -4,8 +4,10 @@ import fetchMock from 'jest-fetch-mock';
|
|
|
4
4
|
import userEvent from '@testing-library/user-event';
|
|
5
5
|
import {
|
|
6
6
|
initializeMockDJClient,
|
|
7
|
+
renderCreateMetric,
|
|
7
8
|
renderCreateNode,
|
|
8
9
|
renderEditNode,
|
|
10
|
+
renderEditTransformNode,
|
|
9
11
|
testElement,
|
|
10
12
|
} from './index.test';
|
|
11
13
|
import { mocks } from '../../../../mocks/mockNodes';
|
|
@@ -21,11 +23,11 @@ describe('AddEditNodePage submission succeeded', () => {
|
|
|
21
23
|
window.scrollTo = jest.fn();
|
|
22
24
|
});
|
|
23
25
|
|
|
24
|
-
it('for creating a node', async () => {
|
|
26
|
+
it('for creating a dimension/transform node', async () => {
|
|
25
27
|
const mockDjClient = initializeMockDJClient();
|
|
26
28
|
mockDjClient.DataJunctionAPI.createNode.mockReturnValue({
|
|
27
29
|
status: 200,
|
|
28
|
-
json: { name: 'default.
|
|
30
|
+
json: { name: 'default.some_test_dim' },
|
|
29
31
|
});
|
|
30
32
|
|
|
31
33
|
mockDjClient.DataJunctionAPI.tagsNode.mockReturnValue({
|
|
@@ -43,11 +45,11 @@ describe('AddEditNodePage submission succeeded', () => {
|
|
|
43
45
|
|
|
44
46
|
await userEvent.type(
|
|
45
47
|
screen.getByLabelText('Display Name *'),
|
|
46
|
-
'Some Test
|
|
48
|
+
'Some Test Dim',
|
|
47
49
|
);
|
|
48
50
|
await userEvent.type(
|
|
49
51
|
screen.getByLabelText('Query *'),
|
|
50
|
-
'SELECT
|
|
52
|
+
'SELECT a, b, c FROM test',
|
|
51
53
|
);
|
|
52
54
|
await userEvent.click(screen.getByText('Create dimension'));
|
|
53
55
|
|
|
@@ -55,29 +57,162 @@ describe('AddEditNodePage submission succeeded', () => {
|
|
|
55
57
|
expect(mockDjClient.DataJunctionAPI.createNode).toBeCalled();
|
|
56
58
|
expect(mockDjClient.DataJunctionAPI.createNode).toBeCalledWith(
|
|
57
59
|
'dimension',
|
|
58
|
-
'default.
|
|
59
|
-
'Some Test
|
|
60
|
+
'default.some_test_dim',
|
|
61
|
+
'Some Test Dim',
|
|
60
62
|
'',
|
|
61
|
-
'SELECT
|
|
62
|
-
'
|
|
63
|
+
'SELECT a, b, c FROM test',
|
|
64
|
+
'published',
|
|
63
65
|
'default',
|
|
64
66
|
null,
|
|
65
67
|
undefined,
|
|
66
68
|
undefined,
|
|
69
|
+
undefined,
|
|
67
70
|
);
|
|
68
|
-
expect(screen.getByText(/default.
|
|
71
|
+
expect(screen.getByText(/default.some_test_dim/)).toBeInTheDocument();
|
|
69
72
|
});
|
|
70
73
|
|
|
74
|
+
// After successful creation, it should return a success message
|
|
75
|
+
expect(screen.getByTestId('success')).toHaveTextContent(
|
|
76
|
+
'Successfully created node default.some_test_dim',
|
|
77
|
+
);
|
|
78
|
+
}, 60000);
|
|
79
|
+
|
|
80
|
+
it('for creating a metric node', async () => {
|
|
81
|
+
const mockDjClient = initializeMockDJClient();
|
|
82
|
+
mockDjClient.DataJunctionAPI.createNode.mockReturnValue({
|
|
83
|
+
status: 200,
|
|
84
|
+
json: { name: 'default.some_test_metric' },
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
mockDjClient.DataJunctionAPI.tagsNode.mockReturnValue({
|
|
88
|
+
status: 200,
|
|
89
|
+
json: { message: 'Success' },
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
mockDjClient.DataJunctionAPI.nodesWithType
|
|
93
|
+
.mockReturnValueOnce(['default.test1'])
|
|
94
|
+
.mockReturnValueOnce(['default.test2'])
|
|
95
|
+
.mockReturnValueOnce([]);
|
|
96
|
+
|
|
97
|
+
mockDjClient.DataJunctionAPI.listTags.mockReturnValue([
|
|
98
|
+
{ name: 'purpose', display_name: 'Purpose' },
|
|
99
|
+
{ name: 'intent', display_name: 'Intent' },
|
|
100
|
+
]);
|
|
101
|
+
|
|
102
|
+
mockDjClient.DataJunctionAPI.listMetricMetadata.mockReturnValue(
|
|
103
|
+
mocks.metricMetadata,
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
const element = testElement(mockDjClient);
|
|
107
|
+
const { container } = renderCreateMetric(element);
|
|
108
|
+
|
|
109
|
+
await userEvent.type(
|
|
110
|
+
screen.getByLabelText('Display Name *'),
|
|
111
|
+
'Some Test Metric',
|
|
112
|
+
);
|
|
113
|
+
const selectUpstream = screen.getByTestId('select-upstream-node');
|
|
114
|
+
fireEvent.keyDown(selectUpstream.firstChild, { key: 'ArrowDown' });
|
|
115
|
+
fireEvent.click(screen.getByText('default.repair_orders'));
|
|
116
|
+
|
|
117
|
+
await userEvent.type(
|
|
118
|
+
screen.getByLabelText('Aggregate Expression *'),
|
|
119
|
+
'SUM(a)',
|
|
120
|
+
);
|
|
121
|
+
await userEvent.click(screen.getByText('Create metric'));
|
|
122
|
+
|
|
123
|
+
await waitFor(
|
|
124
|
+
() => {
|
|
125
|
+
expect(mockDjClient.DataJunctionAPI.createNode).toBeCalled();
|
|
126
|
+
expect(mockDjClient.DataJunctionAPI.createNode).toBeCalledWith(
|
|
127
|
+
'metric',
|
|
128
|
+
'default.some_test_metric',
|
|
129
|
+
'Some Test Metric',
|
|
130
|
+
'',
|
|
131
|
+
'SELECT SUM(a) FROM default.repair_orders',
|
|
132
|
+
'published',
|
|
133
|
+
'default',
|
|
134
|
+
null,
|
|
135
|
+
undefined,
|
|
136
|
+
undefined,
|
|
137
|
+
undefined,
|
|
138
|
+
);
|
|
139
|
+
expect(
|
|
140
|
+
screen.getByText(/default.some_test_metric/),
|
|
141
|
+
).toBeInTheDocument();
|
|
142
|
+
},
|
|
143
|
+
{ timeout: 10000 },
|
|
144
|
+
);
|
|
145
|
+
|
|
71
146
|
// After successful creation, it should return a success message
|
|
72
147
|
expect(screen.getByTestId('success')).toHaveTextContent(
|
|
73
148
|
'Successfully created node default.some_test_metric',
|
|
74
149
|
);
|
|
75
150
|
}, 60000);
|
|
76
151
|
|
|
77
|
-
it('for editing a node', async () => {
|
|
152
|
+
it('for editing a transform or dimension node', async () => {
|
|
153
|
+
const mockDjClient = initializeMockDJClient();
|
|
154
|
+
|
|
155
|
+
mockDjClient.DataJunctionAPI.node.mockReturnValue(mocks.mockTransformNode);
|
|
156
|
+
mockDjClient.DataJunctionAPI.patchNode = jest.fn();
|
|
157
|
+
mockDjClient.DataJunctionAPI.patchNode.mockReturnValue({
|
|
158
|
+
status: 201,
|
|
159
|
+
json: { name: 'default.repair_order_transform', type: 'transform' },
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
mockDjClient.DataJunctionAPI.tagsNode.mockReturnValue({
|
|
163
|
+
status: 200,
|
|
164
|
+
json: { message: 'Success' },
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
mockDjClient.DataJunctionAPI.listTags.mockReturnValue([
|
|
168
|
+
{ name: 'purpose', display_name: 'Purpose' },
|
|
169
|
+
{ name: 'intent', display_name: 'Intent' },
|
|
170
|
+
]);
|
|
171
|
+
|
|
172
|
+
const element = testElement(mockDjClient);
|
|
173
|
+
const { getByTestId } = renderEditTransformNode(element);
|
|
174
|
+
|
|
175
|
+
await userEvent.type(screen.getByLabelText('Display Name *'), '!!!');
|
|
176
|
+
await userEvent.type(screen.getByLabelText('Description'), '!!!');
|
|
177
|
+
await userEvent.click(screen.getByText('Save'));
|
|
178
|
+
|
|
179
|
+
const selectTags = getByTestId('select-tags');
|
|
180
|
+
fireEvent.keyDown(selectTags.firstChild, { key: 'ArrowDown' });
|
|
181
|
+
fireEvent.click(screen.getByText('Purpose'));
|
|
182
|
+
|
|
183
|
+
await waitFor(async () => {
|
|
184
|
+
expect(mockDjClient.DataJunctionAPI.patchNode).toBeCalledTimes(1);
|
|
185
|
+
expect(mockDjClient.DataJunctionAPI.patchNode).toBeCalledWith(
|
|
186
|
+
'default.repair_order_transform',
|
|
187
|
+
'Default: Repair Order Transform!!!',
|
|
188
|
+
'Repair order dimension!!!',
|
|
189
|
+
'SELECT repair_order_id, municipality_id, hard_hat_id, dispatcher_id FROM default.repair_orders',
|
|
190
|
+
'published',
|
|
191
|
+
[],
|
|
192
|
+
undefined,
|
|
193
|
+
undefined,
|
|
194
|
+
undefined,
|
|
195
|
+
);
|
|
196
|
+
expect(mockDjClient.DataJunctionAPI.tagsNode).toBeCalledTimes(1);
|
|
197
|
+
expect(mockDjClient.DataJunctionAPI.tagsNode).toBeCalledWith(
|
|
198
|
+
'default.repair_order_transform',
|
|
199
|
+
[],
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
expect(mockDjClient.DataJunctionAPI.listMetricMetadata).toBeCalledTimes(
|
|
203
|
+
0,
|
|
204
|
+
);
|
|
205
|
+
expect(
|
|
206
|
+
await screen.getByText(/Successfully updated transform node/),
|
|
207
|
+
).toBeInTheDocument();
|
|
208
|
+
});
|
|
209
|
+
}, 1000000);
|
|
210
|
+
|
|
211
|
+
it('for editing a metric node', async () => {
|
|
78
212
|
const mockDjClient = initializeMockDJClient();
|
|
79
213
|
|
|
80
214
|
mockDjClient.DataJunctionAPI.node.mockReturnValue(mocks.mockMetricNode);
|
|
215
|
+
mockDjClient.DataJunctionAPI.metric.mockReturnValue(mocks.mockMetricNode);
|
|
81
216
|
mockDjClient.DataJunctionAPI.patchNode = jest.fn();
|
|
82
217
|
mockDjClient.DataJunctionAPI.patchNode.mockReturnValue({
|
|
83
218
|
status: 201,
|
|
@@ -102,8 +237,8 @@ describe('AddEditNodePage submission succeeded', () => {
|
|
|
102
237
|
await userEvent.click(screen.getByText('Save'));
|
|
103
238
|
|
|
104
239
|
const selectTags = getByTestId('select-tags');
|
|
105
|
-
|
|
106
|
-
|
|
240
|
+
fireEvent.keyDown(selectTags.firstChild, { key: 'ArrowDown' });
|
|
241
|
+
fireEvent.click(screen.getByText('Purpose'));
|
|
107
242
|
|
|
108
243
|
await waitFor(async () => {
|
|
109
244
|
expect(mockDjClient.DataJunctionAPI.patchNode).toBeCalledTimes(1);
|
|
@@ -111,11 +246,12 @@ describe('AddEditNodePage submission succeeded', () => {
|
|
|
111
246
|
'default.num_repair_orders',
|
|
112
247
|
'Default: Num Repair Orders!!!',
|
|
113
248
|
'Number of repair orders!!!',
|
|
114
|
-
'SELECT count(repair_order_id)
|
|
249
|
+
'SELECT count(repair_order_id) FROM default.repair_orders',
|
|
115
250
|
'published',
|
|
116
|
-
|
|
251
|
+
[],
|
|
117
252
|
'neutral',
|
|
118
253
|
'unitless',
|
|
254
|
+
undefined,
|
|
119
255
|
);
|
|
120
256
|
expect(mockDjClient.DataJunctionAPI.tagsNode).toBeCalledTimes(1);
|
|
121
257
|
expect(mockDjClient.DataJunctionAPI.tagsNode).toBeCalledWith(
|
|
@@ -6,7 +6,6 @@ import fetchMock from 'jest-fetch-mock';
|
|
|
6
6
|
import { AddEditNodePage } from '../index.jsx';
|
|
7
7
|
import { mocks } from '../../../../mocks/mockNodes';
|
|
8
8
|
import DJClientContext from '../../../providers/djclient';
|
|
9
|
-
import userEvent from '@testing-library/user-event';
|
|
10
9
|
|
|
11
10
|
fetchMock.enableMocks();
|
|
12
11
|
|
|
@@ -52,7 +51,13 @@ export const initializeMockDJClient = () => {
|
|
|
52
51
|
patchNode: jest.fn(),
|
|
53
52
|
node: jest.fn(),
|
|
54
53
|
tagsNode: jest.fn(),
|
|
55
|
-
listTags: jest.fn(),
|
|
54
|
+
listTags: jest.fn().mockReturnValue([]),
|
|
55
|
+
metric: jest.fn().mockReturnValue(mocks.mockMetricNode),
|
|
56
|
+
nodesWithType: jest
|
|
57
|
+
.fn()
|
|
58
|
+
.mockReturnValueOnce(['a'])
|
|
59
|
+
.mockReturnValueOnce(['b'])
|
|
60
|
+
.mockReturnValueOnce(['default.repair_orders']),
|
|
56
61
|
listMetricMetadata: jest.fn().mockReturnValue({
|
|
57
62
|
directions: ['higher_is_better', 'lower_is_better', 'neutral'],
|
|
58
63
|
units: [
|
|
@@ -82,6 +87,16 @@ export const renderCreateNode = element => {
|
|
|
82
87
|
);
|
|
83
88
|
};
|
|
84
89
|
|
|
90
|
+
export const renderCreateMetric = element => {
|
|
91
|
+
return render(
|
|
92
|
+
<MemoryRouter initialEntries={['/create/metric/default']}>
|
|
93
|
+
<Routes>
|
|
94
|
+
<Route path="create/:nodeType/:initialNamespace" element={element} />
|
|
95
|
+
</Routes>
|
|
96
|
+
</MemoryRouter>,
|
|
97
|
+
);
|
|
98
|
+
};
|
|
99
|
+
|
|
85
100
|
export const renderEditNode = element => {
|
|
86
101
|
return render(
|
|
87
102
|
<MemoryRouter initialEntries={['/nodes/default.num_repair_orders/edit']}>
|
|
@@ -92,6 +107,18 @@ export const renderEditNode = element => {
|
|
|
92
107
|
);
|
|
93
108
|
};
|
|
94
109
|
|
|
110
|
+
export const renderEditTransformNode = element => {
|
|
111
|
+
return render(
|
|
112
|
+
<MemoryRouter
|
|
113
|
+
initialEntries={['/nodes/default.repair_order_transform/edit']}
|
|
114
|
+
>
|
|
115
|
+
<Routes>
|
|
116
|
+
<Route path="nodes/:name/edit" element={element} />
|
|
117
|
+
</Routes>
|
|
118
|
+
</MemoryRouter>,
|
|
119
|
+
);
|
|
120
|
+
};
|
|
121
|
+
|
|
95
122
|
describe('AddEditNodePage', () => {
|
|
96
123
|
beforeEach(() => {
|
|
97
124
|
fetchMock.resetMocks();
|
|
@@ -135,12 +162,12 @@ describe('AddEditNodePage', () => {
|
|
|
135
162
|
// The description should be populated
|
|
136
163
|
expect(screen.getByText('Number of repair orders')).toBeInTheDocument();
|
|
137
164
|
|
|
138
|
-
// The
|
|
139
|
-
expect(
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
).toBeInTheDocument();
|
|
165
|
+
// The upstream node should be populated
|
|
166
|
+
expect(screen.getByText('default.repair_orders')).toBeInTheDocument();
|
|
167
|
+
|
|
168
|
+
// The aggregate expression should be populated
|
|
169
|
+
expect(screen.getByText('count')).toBeInTheDocument();
|
|
170
|
+
expect(screen.getByText('(repair_order_id)')).toBeInTheDocument();
|
|
144
171
|
});
|
|
145
172
|
});
|
|
146
173
|
|