@truedat/qx 7.13.7 → 7.13.9

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.
Files changed (74) hide show
  1. package/package.json +3 -3
  2. package/src/components/QxRoutes.js +8 -6
  3. package/src/components/common/ResourceSelector.js +25 -6
  4. package/src/components/common/TypeSelector.js +14 -9
  5. package/src/components/common/__tests__/__snapshots__/ResourceSelector.spec.js.snap +269 -241
  6. package/src/components/common/__tests__/__snapshots__/TypeSelector.spec.js.snap +198 -190
  7. package/src/components/common/expressions/Clauses.js +19 -11
  8. package/src/components/common/expressions/Condition.js +32 -31
  9. package/src/components/common/expressions/FieldSelector.js +30 -16
  10. package/src/components/common/expressions/FunctionSelector.js +38 -23
  11. package/src/components/common/expressions/ShapeSelector.js +6 -5
  12. package/src/components/common/expressions/__tests__/ShapeSelector.spec.js +1 -1
  13. package/src/components/common/expressions/__tests__/__snapshots__/Clauses.spec.js.snap +36 -12
  14. package/src/components/common/expressions/__tests__/__snapshots__/Condition.spec.js.snap +87 -75
  15. package/src/components/common/expressions/__tests__/__snapshots__/ConstantSelector.spec.js.snap +99 -97
  16. package/src/components/common/expressions/__tests__/__snapshots__/Expression.spec.js.snap +236 -216
  17. package/src/components/common/expressions/__tests__/__snapshots__/FunctionArgs.spec.js.snap +97 -89
  18. package/src/components/common/expressions/__tests__/__snapshots__/FunctionSelector.spec.js.snap +373 -345
  19. package/src/components/common/expressions/constantInputs/AnySelector.js +2 -1
  20. package/src/components/common/expressions/constantInputs/BooleanSelector.js +20 -15
  21. package/src/components/common/expressions/constantInputs/DefaultSelector.js +0 -1
  22. package/src/components/common/expressions/constantInputs/__tests__/__snapshots__/AnySelector.spec.js.snap +189 -182
  23. package/src/components/common/expressions/constantInputs/__tests__/__snapshots__/BooleanSelector.spec.js.snap +74 -66
  24. package/src/components/common/expressions/constantInputs/__tests__/__snapshots__/DefaultSelector.spec.js.snap +2 -4
  25. package/src/components/common/resourceSelectors/DataStructureSelector.js +5 -4
  26. package/src/components/common/resourceSelectors/DataViewSelector.js +4 -3
  27. package/src/components/common/resourceSelectors/ReferenceDatasetSelector.js +4 -3
  28. package/src/components/common/resourceSelectors/__tests__/__snapshots__/DataStructureSelector.spec.js.snap +65 -61
  29. package/src/components/common/resourceSelectors/__tests__/__snapshots__/DataViewSelector.spec.js.snap +38 -34
  30. package/src/components/common/resourceSelectors/__tests__/__snapshots__/ReferenceDatasetSelector.spec.js.snap +38 -34
  31. package/src/components/dataViews/BreadCrumb.js +20 -0
  32. package/src/components/dataViews/DataViewEditor.js +169 -178
  33. package/src/components/dataViews/DataViews.js +113 -135
  34. package/src/components/dataViews/__tests__/AdvancedDataViewEditor.spec.js +260 -0
  35. package/src/components/dataViews/__tests__/DataViewEditor.spec.js +173 -239
  36. package/src/components/dataViews/__tests__/DataViewSelect.spec.js +1 -1
  37. package/src/components/dataViews/__tests__/DataViews.spec.js +124 -51
  38. package/src/components/dataViews/__tests__/Queryable.spec.js +1 -1
  39. package/src/components/dataViews/__tests__/Queryables.spec.js +1 -1
  40. package/src/components/dataViews/__tests__/SimpleDataViewEditor.spec.js +164 -0
  41. package/src/components/dataViews/__tests__/__snapshots__/{DataViewEditor.spec.js.snap → AdvancedDataViewEditor.spec.js.snap} +230 -200
  42. package/src/components/dataViews/__tests__/__snapshots__/DataViews.spec.js.snap +141 -29
  43. package/src/components/dataViews/__tests__/__snapshots__/Queryable.spec.js.snap +184 -141
  44. package/src/components/dataViews/__tests__/__snapshots__/Queryables.spec.js.snap +126 -91
  45. package/src/components/dataViews/actions/CancelButton.js +33 -0
  46. package/src/components/dataViews/actions/DeleteButton.js +33 -0
  47. package/src/components/dataViews/advancedForm/AdvancedDataViewEditor.js +159 -0
  48. package/src/components/dataViews/{DataViewSelect.js → advancedForm/DataViewSelect.js} +2 -2
  49. package/src/components/dataViews/{Queryable.js → advancedForm/Queryable.js} +2 -2
  50. package/src/components/dataViews/queryableFunctions.js +7 -0
  51. package/src/components/dataViews/queryableProperties/GroupBy.js +23 -27
  52. package/src/components/dataViews/queryableProperties/Join.js +0 -3
  53. package/src/components/dataViews/queryableProperties/__tests__/__snapshots__/From.spec.js.snap +30 -26
  54. package/src/components/dataViews/queryableProperties/__tests__/__snapshots__/GroupBy.spec.js.snap +130 -102
  55. package/src/components/dataViews/queryableProperties/__tests__/__snapshots__/Join.spec.js.snap +42 -31
  56. package/src/components/dataViews/queryableProperties/__tests__/__snapshots__/Select.spec.js.snap +81 -69
  57. package/src/components/dataViews/queryableProperties/__tests__/__snapshots__/SelectField.spec.js.snap +62 -54
  58. package/src/components/dataViews/queryableProperties/__tests__/__snapshots__/Where.spec.js.snap +12 -4
  59. package/src/components/dataViews/simpleForm/AggregationForm.js +179 -0
  60. package/src/components/dataViews/simpleForm/DatasetForm.js +199 -0
  61. package/src/components/dataViews/simpleForm/FormQueryable.js +114 -0
  62. package/src/components/dataViews/simpleForm/InformationForm.js +107 -0
  63. package/src/components/dataViews/simpleForm/SelectionForm.js +50 -0
  64. package/src/components/dataViews/simpleForm/SimpleDataViewEditor.js +265 -0
  65. package/src/components/functions/__tests__/__snapshots__/FunctionEditor.spec.js.snap +663 -631
  66. package/src/components/functions/__tests__/__snapshots__/FunctionParams.spec.js.snap +113 -109
  67. package/src/components/qualityControls/__tests__/__snapshots__/ControlProperties.spec.js.snap +92 -76
  68. package/src/components/qualityControls/__tests__/__snapshots__/EditQualityControl.spec.js.snap +108 -80
  69. package/src/components/qualityControls/__tests__/__snapshots__/NewDraftQualityControl.spec.js.snap +108 -80
  70. package/src/components/qualityControls/__tests__/__snapshots__/QualityControlEditor.spec.js.snap +108 -80
  71. package/src/components/qualityControls/controlProperties/__tests__/__snapshots__/Count.spec.js.snap +40 -36
  72. package/src/components/qualityControls/controlProperties/__tests__/__snapshots__/Ratio.spec.js.snap +92 -76
  73. package/src/hooks/useDataViews.js +7 -0
  74. /package/src/components/dataViews/{Queryables.js → advancedForm/Queryables.js} +0 -0
@@ -0,0 +1,260 @@
1
+ import userEvent from "@testing-library/user-event";
2
+ import { act, waitFor } from "@testing-library/react";
3
+ import { render, waitForLoad } from "@truedat/test/render";
4
+ import { SOURCE_OPTIONS_QUERY } from "@truedat/cx/sources/api/queries";
5
+ import { sources } from "@truedat/qx/components/qualityControls/__tests__/__fixtures__/qualityControlHelper";
6
+ import AdvancedDataViewEditor from "../advancedForm/AdvancedDataViewEditor";
7
+
8
+ const sourcesMock = {
9
+ request: { query: SOURCE_OPTIONS_QUERY },
10
+ result: { data: { sources } },
11
+ };
12
+
13
+ const defaultProps = {
14
+ selectedDataView: null,
15
+ context: { sourceId: 10 },
16
+ onSubmit: jest.fn(),
17
+ onCancel: jest.fn(),
18
+ onDelete: jest.fn(),
19
+ isSubmitting: false,
20
+ setDirty: jest.fn(),
21
+ };
22
+
23
+ describe("<AdvancedDataViewEditor />", () => {
24
+ it("matches the latest snapshot for empty", async () => {
25
+ const rendered = render(<AdvancedDataViewEditor {...defaultProps} />, {
26
+ mocks: [sourcesMock],
27
+ });
28
+ await waitForLoad(rendered);
29
+ expect(rendered.container).toMatchSnapshot();
30
+ });
31
+
32
+ it("matches the latest snapshot with content", async () => {
33
+ const props = {
34
+ ...defaultProps,
35
+ selectedDataView: {
36
+ id: 4,
37
+ source_id: 10,
38
+ description: "Description",
39
+ name: "StructureView",
40
+ queryables: [
41
+ {
42
+ id: 0,
43
+ properties: {
44
+ resource: {
45
+ embedded: {
46
+ fields: [
47
+ {
48
+ id: 8,
49
+ name: "Column1",
50
+ parent_name: "ParentTable",
51
+ type: "string",
52
+ },
53
+ ],
54
+ id: 123,
55
+ name: "ParentTable",
56
+ },
57
+ id: 123,
58
+ type: "data_structure",
59
+ },
60
+ },
61
+ type: "from",
62
+ },
63
+ ],
64
+ select: {
65
+ properties: {
66
+ fields: [
67
+ {
68
+ alias: "Column1",
69
+ expression: {
70
+ shape: "field",
71
+ value: {
72
+ id: 8,
73
+ name: "Column1",
74
+ parent_id: 0,
75
+ type: "string",
76
+ },
77
+ },
78
+ id: 8,
79
+ },
80
+ ],
81
+ },
82
+ type: "select",
83
+ },
84
+ },
85
+ };
86
+
87
+ const rendered = render(<AdvancedDataViewEditor {...props} />, {
88
+ mocks: [sourcesMock],
89
+ });
90
+ await waitForLoad(rendered);
91
+ expect(rendered.container).toMatchSnapshot();
92
+ });
93
+
94
+ it("handles user interaction", async () => {
95
+ const onSubmit = jest.fn();
96
+ const props = {
97
+ ...defaultProps,
98
+ onSubmit,
99
+ selectedDataView: {
100
+ name: "",
101
+ source_id: 10,
102
+ description: "",
103
+ queryables: [
104
+ {
105
+ id: 0,
106
+ alias: "",
107
+ type: "from",
108
+ properties: {
109
+ resource: null,
110
+ },
111
+ },
112
+ ],
113
+ select: {
114
+ type: "select",
115
+ },
116
+ },
117
+ context: {
118
+ dataViews: [
119
+ {
120
+ id: 4,
121
+ source_id: 10,
122
+ description: "Description",
123
+ name: "AnotherDataView",
124
+ select: {
125
+ properties: {
126
+ fields: [
127
+ {
128
+ alias: "Column1",
129
+ expression: {
130
+ shape: "field",
131
+ value: {
132
+ id: 8,
133
+ name: "Column1",
134
+ parent_id: 0,
135
+ type: "string",
136
+ },
137
+ },
138
+ id: 8,
139
+ },
140
+ ],
141
+ },
142
+ type: "select",
143
+ },
144
+ },
145
+ ],
146
+ },
147
+ };
148
+
149
+ const rendered = render(<AdvancedDataViewEditor {...props} />, {
150
+ mocks: [sourcesMock],
151
+ });
152
+ await waitForLoad(rendered);
153
+
154
+ const user = userEvent.setup({ delay: null, skipHover: true });
155
+
156
+ // Insert name
157
+ await user.type(rendered.getAllByRole("textbox")[0], "data_view_name");
158
+
159
+ // Insert description
160
+ await user.type(rendered.getAllByRole("textbox")[1], "data_view_description");
161
+
162
+ // Insert From information
163
+ await user.type(rendered.getByPlaceholderText(/alias/i), "from_alias");
164
+ await user.click(rendered.getByRole("option", { name: /data_view/i }));
165
+ await user.click(
166
+ rendered.getByRole("option", { name: /anotherdataview/i })
167
+ );
168
+
169
+ expect(rendered.getByRole("button", { name: /save/i })).toBeDisabled();
170
+
171
+ await user.click(
172
+ rendered.getByRole("button", { name: /add_all_select_fields/i })
173
+ );
174
+
175
+ await waitFor(() => {
176
+ expect(rendered.getByRole("button", { name: /save/i })).toBeEnabled();
177
+ });
178
+
179
+ expect(rendered.container).toMatchSnapshot();
180
+
181
+ await user.click(rendered.getByRole("button", { name: /cancel/i }));
182
+ await act(async () => {
183
+ await user.click(rendered.getByRole("button", { name: /save/i }));
184
+ });
185
+
186
+ await waitForLoad(rendered);
187
+ expect(onSubmit).toHaveBeenCalledWith({
188
+ description: "data_view_description",
189
+ source_id: 10,
190
+ name: "data_view_name",
191
+ queryables: [
192
+ {
193
+ alias: "from_alias",
194
+ id: 0,
195
+ properties: {
196
+ resource: {
197
+ embedded: {
198
+ description: "Description",
199
+ fields: [
200
+ {
201
+ id: 0,
202
+ name: "Column1",
203
+ parent_name: "AnotherDataView",
204
+ type: "string",
205
+ },
206
+ ],
207
+ id: 4,
208
+ name: "AnotherDataView",
209
+ select: {
210
+ properties: {
211
+ fields: [
212
+ {
213
+ alias: "Column1",
214
+ expression: {
215
+ shape: "field",
216
+ value: {
217
+ id: 8,
218
+ name: "Column1",
219
+ parent_id: 0,
220
+ type: "string",
221
+ },
222
+ },
223
+ id: 8,
224
+ },
225
+ ],
226
+ },
227
+ type: "select",
228
+ },
229
+ source_id: 10,
230
+ },
231
+ id: 4,
232
+ type: "data_view",
233
+ },
234
+ },
235
+ type: "from",
236
+ },
237
+ ],
238
+ select: {
239
+ properties: {
240
+ fields: [
241
+ {
242
+ alias: "Column1",
243
+ expression: {
244
+ shape: "field",
245
+ value: {
246
+ id: 0,
247
+ name: "Column1",
248
+ parent_id: 0,
249
+ type: "string",
250
+ },
251
+ },
252
+ id: 0,
253
+ },
254
+ ],
255
+ },
256
+ type: "select",
257
+ },
258
+ });
259
+ });
260
+ });
@@ -1,260 +1,194 @@
1
- import userEvent from "@testing-library/user-event";
2
- import { act, waitFor } from "@testing-library/react";
1
+ import React from "react";
3
2
  import { render, waitForLoad } from "@truedat/test/render";
4
- import { SOURCE_OPTIONS_QUERY } from "@truedat/cx/sources/api/queries";
5
- import { sources } from "@truedat/qx/components/qualityControls/__tests__/__fixtures__/qualityControlHelper";
6
- import DataViewEditor from "../DataViewEditor";
7
-
8
- const sourcesMock = {
9
- request: { query: SOURCE_OPTIONS_QUERY },
10
- result: { data: { sources } },
11
- };
12
-
13
- const defaultProps = {
14
- selectedDataView: null,
15
- context: { sourceId: 10 },
16
- onSubmit: jest.fn(),
17
- onCancel: jest.fn(),
18
- onDelete: jest.fn(),
19
- isSubmitting: false,
20
- setDirty: jest.fn(),
21
- };
22
-
23
- describe("<DataViewEditor />", () => {
24
- it("matches the latest snapshot for empty", async () => {
25
- const rendered = render(<DataViewEditor {...defaultProps} />, {
26
- mocks: [sourcesMock],
27
- });
28
- await waitForLoad(rendered);
29
- expect(rendered.container).toMatchSnapshot();
30
- });
31
-
32
- it("matches the latest snapshot with content", async () => {
33
- const props = {
34
- ...defaultProps,
35
- selectedDataView: {
36
- id: 4,
37
- source_id: 10,
38
- description: "Description",
39
- name: "StructureView",
40
- queryables: [
41
- {
42
- id: 0,
43
- properties: {
44
- resource: {
45
- embedded: {
46
- fields: [
47
- {
48
- id: 8,
49
- name: "Column1",
50
- parent_name: "ParentTable",
51
- type: "string",
52
- },
53
- ],
54
- id: 123,
55
- name: "ParentTable",
56
- },
57
- id: 123,
58
- type: "data_structure",
59
- },
60
- },
61
- type: "from",
62
- },
63
- ],
64
- select: {
65
- properties: {
66
- fields: [
67
- {
68
- alias: "Column1",
69
- expression: {
70
- shape: "field",
71
- value: {
72
- id: 8,
73
- name: "Column1",
74
- parent_id: 0,
75
- type: "string",
76
- },
77
- },
78
- id: 8,
79
- },
3
+ import userEvent from "@testing-library/user-event";
4
+ import { useParams } from "react-router";
5
+ import DataViewEditor, { DataViewDetailEditor } from "../DataViewEditor";
6
+
7
+ const mockFormatMessage = jest.fn(({ id }) => id);
8
+ jest.mock("react-intl", () => ({
9
+ ...jest.requireActual("react-intl"),
10
+ useIntl: () => ({ formatMessage: mockFormatMessage }),
11
+ }));
12
+
13
+ jest.mock("@truedat/core/routes", () => ({
14
+ DATA_VIEWS: "/dataviews",
15
+ }));
16
+
17
+ jest.mock("react-router", () => ({
18
+ ...jest.requireActual("react-router"),
19
+ useParams: jest.fn(),
20
+ }));
21
+
22
+ jest.mock("@apollo/client", () => ({
23
+ ...jest.requireActual("@apollo/client"),
24
+ useQuery: jest.fn(() => ({
25
+ data: {
26
+ referenceDatasets: [
27
+ { id: "10", name: "Álpha" },
28
+ { id: "2", name: "Beta" },
80
29
  ],
81
- },
82
- type: "select",
83
30
  },
84
- },
85
- };
31
+ loading: false,
32
+ })),
33
+ }));
34
+
35
+ const mockUseDataViews = jest.fn();
36
+ const mockUseDataViewFetch = jest.fn();
37
+
38
+ jest.mock("@truedat/qx/hooks/useDataViews", () => ({
39
+ useDataViews: () => mockUseDataViews(),
40
+ useDataViewFetch: (...args) => mockUseDataViewFetch(...args),
41
+ // mutation hooks are irrelevant here; don’t assert on them
42
+ useDataViewCreate: () => ({ trigger: jest.fn(), isMutating: false }),
43
+ useDataViewUpdate: () => ({ trigger: jest.fn(), isMutating: false }),
44
+ useDataViewDelete: () => ({ trigger: jest.fn(), isMutating: false }),
45
+ }));
46
+
47
+ const mockUseFunctions = jest.fn(() => ({ data: { data: [] }, loading: false }));
48
+
49
+ jest.mock("@truedat/qx/hooks/useFunctions", () => ({
50
+ useFunctions: () => mockUseFunctions(),
51
+ }));
52
+
53
+ jest.mock("@truedat/core/components", () => ({
54
+ Loading: () => <div data-testid="loading">loading…</div>,
55
+ ConfirmModal: ({ trigger, onConfirm }) => <div data-testid="confirm-trigger" onClick={onConfirm}>{trigger}</div>
56
+ }));
57
+
58
+ jest.mock("../advancedForm/AdvancedDataViewEditor", () => () => (
59
+ <div data-testid="advanced-editor" />
60
+ ));
61
+ jest.mock("../simpleForm/SimpleDataViewEditor", () => () => (
62
+ <div data-testid="simple-editor" />
63
+ ));
64
+ jest.mock("../BreadCrumb", () => ({ text }) => (
65
+ <div data-testid="breadcrumb">{text}</div>
66
+ ));
67
+
68
+ beforeEach(() => {
69
+ jest.clearAllMocks();
70
+ useParams.mockReturnValue({});
71
+ require("@apollo/client").useQuery.mockImplementation(() => ({
72
+ data: {
73
+ referenceDatasets: [
74
+ { id: "10", name: "Álpha" },
75
+ { id: "2", name: "Beta" },
76
+ ],
77
+ },
78
+ loading: false,
79
+ }));
80
+ mockUseDataViews.mockReturnValue({ data: { data: [] }, loading: false });
81
+ mockUseDataViewFetch.mockReset();
82
+ });
86
83
 
87
- const rendered = render(<DataViewEditor {...props} />, {
88
- mocks: [sourcesMock],
84
+ describe("<DataViewDetailEditor /> (render behavior only)", () => {
85
+ it("renders Simple editor by default (guided)", async () => {
86
+ const rendered = render(<DataViewDetailEditor dataView={undefined} />);
87
+ await waitForLoad(rendered);
88
+
89
+ expect(rendered.getByTestId("simple-editor")).toBeInTheDocument();
90
+ expect(rendered.queryByTestId("advanced-editor")).not.toBeInTheDocument();
91
+ expect(rendered.container.querySelector(".ui.segment.loading")).toBeNull();
92
+
93
+ const guidedBtn = rendered.getByRole("button", { name: /actions.mode.guided/i });
94
+ const advancedBtn = rendered.getByRole("button", { name: /actions.mode.advanced/i });
95
+
96
+ expect(guidedBtn).toBeDisabled();
97
+ expect(advancedBtn).not.toBeDisabled();
89
98
  });
90
- await waitForLoad(rendered);
91
- expect(rendered.container).toMatchSnapshot();
92
- });
93
-
94
- it("handles user interaction", async () => {
95
- const onSubmit = jest.fn();
96
- const props = {
97
- ...defaultProps,
98
- onSubmit,
99
- selectedDataView: {
100
- name: "",
101
- source_id: 10,
102
- description: "",
103
- queryables: [
104
- {
105
- id: 0,
106
- alias: "",
107
- type: "from",
108
- properties: {
109
- resource: null,
110
- },
111
- },
112
- ],
113
- select: {
114
- type: "select",
115
- },
116
- },
117
- context: {
118
- dataViews: [
119
- {
120
- id: 4,
121
- source_id: 10,
122
- description: "Description",
123
- name: "AnotherDataView",
124
- select: {
125
- properties: {
126
- fields: [
127
- {
128
- alias: "Column1",
129
- expression: {
130
- shape: "field",
131
- value: {
132
- id: 8,
133
- name: "Column1",
134
- parent_id: 0,
135
- type: "string",
136
- },
137
- },
138
- id: 8,
139
- },
140
- ],
141
- },
142
- type: "select",
143
- },
144
- },
145
- ],
146
- },
147
- };
148
99
 
149
- const rendered = render(<DataViewEditor {...props} />, {
150
- mocks: [sourcesMock],
100
+ it("switches to Advanced editor when advanced toggle is confirmed (state managed here)", async () => {
101
+ const user = userEvent.setup({ delay: null });
102
+ const rendered = render(<DataViewDetailEditor dataView={undefined} />);
103
+ await waitForLoad(rendered);
104
+
105
+ const advancedBtn = rendered.getByRole("button", { name: /actions.mode.advanced/i });
106
+ expect(advancedBtn).not.toBeDisabled();
107
+ await user.click(advancedBtn);
108
+
109
+ expect(rendered.getByTestId("advanced-editor")).toBeInTheDocument();
110
+ expect(rendered.queryByTestId("simple-editor")).not.toBeInTheDocument();
111
+
112
+ expect(rendered.getByRole("button", { name: /actions.mode.advanced/i })).toBeDisabled();
113
+ expect(rendered.getByRole("button", { name: /actions.mode.guided/i })).not.toBeDisabled();
151
114
  });
152
- await waitForLoad(rendered);
153
115
 
154
- const user = userEvent.setup({ delay: null, skipHover: true });
116
+ it("when incoming dataView is advanced, shows Advanced editor and disables switching back to guided", async () => {
117
+ const dataView = {
118
+ id: 7,
119
+ name: "Adv View",
120
+ description: "",
121
+ mode: "advanced",
122
+ queryables: [],
123
+ select: { type: "select" },
124
+ };
125
+ const rendered = render(<DataViewDetailEditor dataView={dataView} />);
126
+ await waitForLoad(rendered);
127
+
128
+ expect(rendered.getByTestId("advanced-editor")).toBeInTheDocument();
129
+ expect(rendered.queryByTestId("simple-editor")).not.toBeInTheDocument();
130
+
131
+ expect(rendered.getByRole("button", { name: /actions.mode.advanced/i })).toBeDisabled();
132
+ expect(rendered.getByRole("button", { name: /actions.mode.guided/i })).toBeDisabled();
133
+ });
155
134
 
156
- // Insert name
157
- await user.type(rendered.getAllByRole("textbox")[0], "data_view_name");
135
+ it("shows loading state when any dependency is loading", () => {
136
+ mockUseDataViews.mockReturnValue({ data: { data: [] }, loading: true });
137
+ const rendered = render(<DataViewDetailEditor dataView={undefined} />);
158
138
 
159
- // Insert From information
160
- await user.type(rendered.getByPlaceholderText(/alias/i), "from_alias");
161
- await user.click(rendered.getByRole("option", { name: /data_view/i }));
162
- await user.click(
163
- rendered.getByRole("option", { name: /anotherdataview/i })
164
- );
139
+ expect(rendered.container.querySelector(".ui.segment.loading")).not.toBeNull();
140
+ });
141
+ });
142
+
143
+ describe("<DataViewEditor /> (render branches only)", () => {
144
+ it("renders 'new' breadcrumb and detail editor when there is no id param", async () => {
145
+ const rendered = render(<DataViewEditor />);
146
+ await waitForLoad(rendered);
165
147
 
166
- expect(rendered.getByRole("button", { name: /save/i })).toBeDisabled();
148
+ expect(rendered.getByTestId("breadcrumb")).toHaveTextContent("dataViews.new");
149
+ expect(rendered.getByTestId("simple-editor")).toBeInTheDocument();
150
+ });
167
151
 
168
- await user.click(
169
- rendered.getByRole("button", { name: /add_all_select_fields/i })
170
- );
152
+ it("shows Loading while fetching an existing dataview", async () => {
153
+ useParams.mockReturnValue({ id: 1 });
154
+ mockUseDataViewFetch.mockReturnValue({ dataView: null, loading: true, error: undefined });
155
+ const rendered = render(<DataViewEditor />);
171
156
 
172
- await waitFor(() => {
173
- expect(rendered.getByRole("button", { name: /save/i })).toBeEnabled();
157
+ expect(rendered.getByTestId("loading")).toBeInTheDocument();
174
158
  });
175
159
 
176
- expect(rendered.container).toMatchSnapshot();
160
+ it("renders nothing when fetch returns error", async () => {
161
+ useParams.mockReturnValue({ id: 1 });
162
+ mockUseDataViewFetch.mockReturnValue({ dataView: null, loading: false, error: { foo: "bar" } });
177
163
 
178
- await user.click(rendered.getByRole("button", { name: /cancel/i }));
179
- await user.click(
180
- rendered.getByRole("button", { name: /modal-negative-action/i })
181
- );
182
- await act(async () => {
183
- await user.click(rendered.getByRole("button", { name: /save/i }));
164
+ const rendered = render(<DataViewEditor />);
165
+ await waitForLoad(rendered);
166
+
167
+ expect(rendered.queryByTestId("breadcrumb")).toBeNull();
168
+ expect(rendered.queryByTestId("simple-editor")).toBeNull();
169
+ expect(rendered.queryByTestId("advanced-editor")).toBeNull();
184
170
  });
185
171
 
186
- await waitForLoad(rendered);
187
- expect(onSubmit).toHaveBeenCalledWith({
188
- description: "",
189
- source_id: 10,
190
- name: "data_view_name",
191
- queryables: [
192
- {
193
- alias: "from_alias",
194
- id: 0,
195
- properties: {
196
- resource: {
197
- embedded: {
198
- description: "Description",
199
- fields: [
200
- {
201
- id: 0,
202
- name: "Column1",
203
- parent_name: "AnotherDataView",
204
- type: "string",
205
- },
206
- ],
207
- id: 4,
208
- name: "AnotherDataView",
209
- select: {
210
- properties: {
211
- fields: [
212
- {
213
- alias: "Column1",
214
- expression: {
215
- shape: "field",
216
- value: {
217
- id: 8,
218
- name: "Column1",
219
- parent_id: 0,
220
- type: "string",
221
- },
222
- },
223
- id: 8,
224
- },
225
- ],
226
- },
227
- type: "select",
228
- },
229
- source_id: 10,
230
- },
231
- id: 4,
232
- type: "data_view",
233
- },
234
- },
235
- type: "from",
236
- },
237
- ],
238
- select: {
239
- properties: {
240
- fields: [
241
- {
242
- alias: "Column1",
243
- expression: {
244
- shape: "field",
245
- value: {
246
- id: 0,
247
- name: "Column1",
248
- parent_id: 0,
249
- type: "string",
250
- },
251
- },
252
- id: 0,
172
+ it("renders breadcrumb with existing name and advanced editor when mode is advanced", async () => {
173
+ useParams.mockReturnValue({ id: 42 });
174
+ mockUseDataViewFetch.mockReturnValue({
175
+ dataView: {
176
+ id: 42,
177
+ name: "Existing View Name",
178
+ description: "desc",
179
+ mode: "advanced",
180
+ queryables: [],
181
+ select: { type: "select" },
253
182
  },
254
- ],
255
- },
256
- type: "select",
257
- },
183
+ loading: false,
184
+ error: undefined,
185
+ });
186
+
187
+ const rendered = render(<DataViewEditor />);
188
+ await waitForLoad(rendered);
189
+
190
+ expect(rendered.getByTestId("breadcrumb")).toHaveTextContent("Existing View Name");
191
+ expect(rendered.getByTestId("advanced-editor")).toBeInTheDocument();
192
+ expect(rendered.queryByTestId("simple-editor")).toBeNull();
258
193
  });
259
- });
260
194
  });