Skip to content

Commit 7e3f84d

Browse files
authored
Merge pull request #144 from eviltester/139-remove-datagrid-based-schema-editor-from-code
139 remove datagrid based schema editor from code
2 parents 0e3cffa + 31f27bc commit 7e3f84d

54 files changed

Lines changed: 2369 additions & 735 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

apps/web/src/tests/browser/app/functional/test-data/schema-grid-row-controls.spec.js

Lines changed: 0 additions & 45 deletions
This file was deleted.

apps/web/src/tests/browser/app/functional/test-data/text-schema-grid-sync.spec.js

Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,172 @@ test.describe('7. Test Data Generation', () => {
5656
expectNoPageErrors(pageErrors);
5757
});
5858

59+
test('invalid domain command text preserves the domain row type in the app editor', async ({ page }) => {
60+
const { appPage, pageErrors } = await openApp(page);
61+
62+
await appPage.testDataPanel.expand();
63+
await appPage.testDataPanel.expectExpanded();
64+
65+
await appPage.testDataPanel.setSchemaText('Name\nperson.fullName');
66+
await expect.poll(async () => appPage.testDataPanel.getSchemaRowCount()).toBe(1);
67+
await expect.poll(async () => appPage.testDataPanel.getSchemaCell(0, 'type')).toBe('person.fullName');
68+
await expect
69+
.poll(async () =>
70+
appPage.testDataPanel.page
71+
.locator('#testDataSchemaRows .generator-schema-row')
72+
.first()
73+
.locator('select[data-field="sourceType"]')
74+
.inputValue()
75+
)
76+
.toBe('domain');
77+
78+
await appPage.testDataPanel.setSchemaText('Name\nperson.fullNam');
79+
80+
await expect.poll(async () => appPage.testDataPanel.getSchemaCell(0, 'type')).toBe('person.fullNam');
81+
await expect
82+
.poll(async () =>
83+
appPage.testDataPanel.page
84+
.locator('#testDataSchemaRows .generator-schema-row')
85+
.first()
86+
.locator('select[data-field="sourceType"]')
87+
.inputValue()
88+
)
89+
.toBe('domain');
90+
91+
await expect(appPage.testDataPanel.page.locator('#testDataSchemaRows .generator-schema-row').first()).toHaveClass(
92+
/generator-schema-row-invalid/
93+
);
94+
95+
await appPage.testDataPanel.clickGenerate();
96+
await expect
97+
.poll(async () => appPage.testDataPanel.getSchemaErrorText())
98+
.toContain('Row 1: unknown domain command "person.fullNam".');
99+
100+
expectNoPageErrors(pageErrors);
101+
});
102+
103+
test('domain rows with invalid params stay domain after text mode round-trip in the app editor', async ({ page }) => {
104+
const { appPage, pageErrors } = await openApp(page);
105+
106+
await appPage.testDataPanel.expand();
107+
await appPage.testDataPanel.expectExpanded();
108+
109+
await appPage.testDataPanel.addSchemaRow();
110+
await expect.poll(async () => appPage.testDataPanel.getSchemaRowCount()).toBe(1);
111+
await appPage.testDataPanel.setSchemaCell(0, 'columnName', 'Name');
112+
await appPage.testDataPanel.setSchemaTypeValue(0, 'person.fullName');
113+
await appPage.testDataPanel.setSchemaCell(0, 'params', '(10)');
114+
115+
await appPage.testDataPanel.setSchemaTextMode(true);
116+
await appPage.testDataPanel.setSchemaTextMode(false);
117+
118+
await expect.poll(async () => appPage.testDataPanel.getSchemaCell(0, 'type')).toBe('person.fullName');
119+
await expect
120+
.poll(async () =>
121+
appPage.testDataPanel.page
122+
.locator('#testDataSchemaRows .generator-schema-row')
123+
.first()
124+
.locator('select[data-field="sourceType"]')
125+
.inputValue()
126+
)
127+
.toBe('domain');
128+
await expect.poll(async () => appPage.testDataPanel.getSchemaCell(0, 'params')).toBe('(10)');
129+
await expect(
130+
appPage.testDataPanel.page
131+
.locator('#testDataSchemaRows .generator-schema-row')
132+
.first()
133+
.locator('.generator-schema-row-validation')
134+
).toContainText('invalid domain params');
135+
136+
expectNoPageErrors(pageErrors);
137+
});
138+
139+
test('debounced semantic validation appears after typing stops in the app editor', async ({ page }) => {
140+
const { appPage, pageErrors } = await openApp(page);
141+
142+
await appPage.testDataPanel.expand();
143+
await appPage.testDataPanel.expectExpanded();
144+
145+
await appPage.testDataPanel.addSchemaRow();
146+
await expect.poll(async () => appPage.testDataPanel.getSchemaRowCount()).toBe(1);
147+
await appPage.testDataPanel.setSchemaCell(0, 'columnName', 'Name');
148+
await appPage.testDataPanel.setSchemaTypeValue(0, 'person.fullName');
149+
150+
const paramsInput = appPage.testDataPanel.page
151+
.locator('#testDataSchemaRows .generator-schema-row')
152+
.first()
153+
.locator('input[data-field="params"]');
154+
await paramsInput.fill('(10)');
155+
156+
await expect
157+
.poll(
158+
async () =>
159+
await appPage.testDataPanel.page
160+
.locator('#testDataSchemaRows .generator-schema-row')
161+
.first()
162+
.locator('.generator-schema-row-validation')
163+
.textContent(),
164+
{ timeout: 2500 }
165+
)
166+
.toContain('invalid domain params');
167+
168+
expectNoPageErrors(pageErrors);
169+
});
170+
171+
test('row validation clears when name editing blurs into the next field in the app editor', async ({ page }) => {
172+
const { appPage, pageErrors } = await openApp(page);
173+
174+
await appPage.testDataPanel.expand();
175+
await appPage.testDataPanel.expectExpanded();
176+
177+
await appPage.testDataPanel.addSchemaRow();
178+
await expect.poll(async () => appPage.testDataPanel.getSchemaRowCount()).toBe(1);
179+
const row = appPage.testDataPanel.page.locator('#testDataSchemaRows .generator-schema-row').first();
180+
await appPage.testDataPanel.setSchemaTypeValue(0, 'literal');
181+
await appPage.testDataPanel.setSchemaCell(0, 'value', 'Active');
182+
await appPage.testDataPanel.clickGenerate();
183+
await expect(row.locator('.generator-schema-row-validation')).toContainText('column name is required');
184+
185+
const nameInput = row.locator('input[data-field="name"]');
186+
const valueInput = row.locator('input[data-field="value"]');
187+
await nameInput.fill('Status');
188+
await valueInput.click();
189+
190+
await expect(row.locator('.generator-schema-row-validation')).toHaveCount(0);
191+
expectNoPageErrors(pageErrors);
192+
});
193+
194+
test('domain params without brackets are normalized and preserved in the app editor', async ({ page }) => {
195+
const { appPage, pageErrors } = await openApp(page);
196+
197+
await appPage.testDataPanel.expand();
198+
await appPage.testDataPanel.expectExpanded();
199+
200+
await appPage.testDataPanel.addSchemaRow();
201+
await expect.poll(async () => appPage.testDataPanel.getSchemaRowCount()).toBe(1);
202+
await appPage.testDataPanel.setSchemaCell(0, 'columnName', 'Phone');
203+
await appPage.testDataPanel.setSchemaTypeValue(0, 'phone.number');
204+
await appPage.testDataPanel.setSchemaCell(0, 'params', 'style=13');
205+
206+
await appPage.testDataPanel.setSchemaTextMode(true);
207+
await expect.poll(async () => appPage.testDataPanel.getSchemaText()).toContain('phone.number(style=13)');
208+
await appPage.testDataPanel.setSchemaTextMode(false);
209+
210+
await expect.poll(async () => appPage.testDataPanel.getSchemaCell(0, 'type')).toBe('phone.number');
211+
await expect
212+
.poll(async () =>
213+
appPage.testDataPanel.page
214+
.locator('#testDataSchemaRows .generator-schema-row')
215+
.first()
216+
.locator('select[data-field="sourceType"]')
217+
.inputValue()
218+
)
219+
.toBe('domain');
220+
await expect.poll(async () => appPage.testDataPanel.getSchemaCell(0, 'params')).toBe('(style=13)');
221+
222+
expectNoPageErrors(pageErrors);
223+
});
224+
59225
test('Schema grid edits after initial sync are reflected in the text schema', async ({ page }) => {
60226
const { appPage, pageErrors } = await openApp(page);
61227

@@ -78,6 +244,50 @@ test.describe('7. Test Data Generation', () => {
78244
expectNoPageErrors(pageErrors);
79245
});
80246

247+
test('schema rows can be dragged to the top and bottom in the app editor', async ({ page }) => {
248+
const { appPage, pageErrors } = await openApp(page);
249+
250+
await appPage.testDataPanel.expand();
251+
await appPage.testDataPanel.expectExpanded();
252+
253+
await appPage.testDataPanel.setSchemaText('A\nliteral(a)\n\nB\nliteral(b)\n\nC\nliteral(c)\n\nD\nliteral(d)');
254+
await expect.poll(async () => appPage.testDataPanel.getSchemaRowCount()).toBe(4);
255+
256+
await appPage.testDataPanel.schemaEditor.dragRowToIndex(3, 0, { placement: 'before' });
257+
await expect.poll(async () => appPage.testDataPanel.getSchemaCell(0, 'columnName')).toBe('D');
258+
await expect.poll(async () => appPage.testDataPanel.getSchemaCell(1, 'columnName')).toBe('A');
259+
260+
await appPage.testDataPanel.schemaEditor.dragRowToIndex(0, 3, { placement: 'after' });
261+
await expect.poll(async () => appPage.testDataPanel.getSchemaCell(0, 'columnName')).toBe('A');
262+
await expect.poll(async () => appPage.testDataPanel.getSchemaCell(3, 'columnName')).toBe('D');
263+
264+
await expect
265+
.poll(async () => appPage.testDataPanel.getSchemaText())
266+
.toContain('A\nliteral(a)\nB\nliteral(b)\nC\nliteral(c)\nD\nliteral(d)');
267+
expectNoPageErrors(pageErrors);
268+
});
269+
270+
test('switching enum rows to domain datatype.enum preserves the enum params in the app editor', async ({ page }) => {
271+
const { appPage, pageErrors } = await openApp(page);
272+
273+
await appPage.testDataPanel.expand();
274+
await appPage.testDataPanel.expectExpanded();
275+
276+
await appPage.testDataPanel.addSchemaRow();
277+
await expect.poll(async () => appPage.testDataPanel.getSchemaRowCount()).toBe(1);
278+
await appPage.testDataPanel.setSchemaCell(0, 'columnName', 'Status');
279+
await appPage.testDataPanel.setSchemaTypeValue(0, 'enum', { assertSchemaTextIncludesType: false });
280+
await appPage.testDataPanel.setSchemaCell(0, 'value', 'active,inactive,pending');
281+
282+
await appPage.testDataPanel.setSchemaTypeValue(0, 'datatype.enum', { assertSchemaTextIncludesType: false });
283+
284+
await expect.poll(async () => appPage.testDataPanel.getSchemaCell(0, 'type')).toBe('datatype.enum');
285+
await expect.poll(async () => appPage.testDataPanel.getSchemaCell(0, 'value')).toBe('active,inactive,pending');
286+
await expect.poll(async () => appPage.testDataPanel.getSchemaText()).toContain('enum(active,inactive,pending)');
287+
288+
expectNoPageErrors(pageErrors);
289+
});
290+
81291
test('empty schema text can switch back to schema mode without locking', async ({ page }) => {
82292
const { appPage, pageErrors } = await openApp(page);
83293

0 commit comments

Comments
 (0)