Skip to content

Commit 31f27bc

Browse files
committed
minor review fixes
1 parent ca387e5 commit 31f27bc

8 files changed

Lines changed: 278 additions & 88 deletions

File tree

packages/core-ui/js/gui_components/app/test-data-grid/generation/test-data-generation-service.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,7 @@ function createTestDataGenerationService({
6767
});
6868
}
6969

70-
function getRulesParserFromTextArea() {
71-
const rowValidation = getCurrentSchemaRowValidation({ syncFromText: false });
70+
function getRulesParserFromTextArea(rowValidation = getCurrentSchemaRowValidation({ syncFromText: false })) {
7271
if (rowValidation.errors.length > 0) {
7372
return { generator: null, errors: rowValidation.errors };
7473
}
@@ -121,7 +120,7 @@ function createTestDataGenerationService({
121120
return;
122121
}
123122

124-
const { generator, errors } = getRulesParserFromTextArea();
123+
const { generator, errors } = getRulesParserFromTextArea(rowValidation);
125124

126125
if (errors.length > 0 || !generator) {
127126
const errorMessages = schemaErrorsToText(errors);
@@ -196,7 +195,7 @@ function createTestDataGenerationService({
196195
return;
197196
}
198197

199-
const { generator, errors } = getRulesParserFromTextArea();
198+
const { generator, errors } = getRulesParserFromTextArea(rowValidation);
200199

201200
if (errors.length > 0 || !generator) {
202201
const errorMessages = schemaErrorsToText(errors);

packages/core-ui/js/gui_components/generator/controller/data-generator-page-controller.js

Lines changed: 1 addition & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import {
2727
schemaErrorsToText,
2828
TEST_DATA_GRID_SAMPLE_SCHEMA_TEXT as GENERATOR_DEFAULT_EXAMPLE_SCHEMA_TEXT,
2929
} from '../../shared/test-data/schema/index.js';
30+
import { captureActiveFieldState, restoreActiveFieldState } from '../../shared/test-data/schema/schema-focus-state.js';
3031
import {
3132
buildSchemaHelpModel,
3233
renderSchemaHelpHtml,
@@ -101,47 +102,6 @@ function validateSchemaRows(schemaRows) {
101102
});
102103
}
103104

104-
function captureActiveFieldState(documentObj) {
105-
const activeElement = documentObj?.activeElement;
106-
const fieldName = activeElement?.getAttribute?.('data-field');
107-
const rowId = activeElement?.closest?.('.generator-schema-row')?.getAttribute?.('data-row-id');
108-
if (!rowId || !fieldName) {
109-
return null;
110-
}
111-
return {
112-
rowId,
113-
fieldName,
114-
selectionStart: typeof activeElement.selectionStart === 'number' ? activeElement.selectionStart : null,
115-
selectionEnd: typeof activeElement.selectionEnd === 'number' ? activeElement.selectionEnd : null,
116-
selectionDirection:
117-
typeof activeElement.selectionDirection === 'string' ? activeElement.selectionDirection : 'none',
118-
};
119-
}
120-
121-
function restoreActiveFieldState(documentObj, state) {
122-
if (!state?.rowId || !state?.fieldName) {
123-
return;
124-
}
125-
const nextField = documentObj?.querySelector?.(
126-
`.generator-schema-row[data-row-id="${state.rowId}"] [data-field="${state.fieldName}"]`
127-
);
128-
if (!nextField) {
129-
return;
130-
}
131-
try {
132-
nextField.focus({ preventScroll: true });
133-
} catch {
134-
nextField.focus?.();
135-
}
136-
if (
137-
typeof nextField.setSelectionRange === 'function' &&
138-
state.selectionStart !== null &&
139-
state.selectionEnd !== null
140-
) {
141-
nextField.setSelectionRange(state.selectionStart, state.selectionEnd, state.selectionDirection || 'none');
142-
}
143-
}
144-
145105
class DataGeneratorPage {
146106
constructor({
147107
parentElement,

packages/core-ui/js/gui_components/shared/test-data/schema/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export {
1515
schemaRowsToSpecWithTokens,
1616
} from './schema-editor-core.js';
1717
export { schemaErrorsToText } from './schema-error-text.js';
18+
export { captureActiveFieldState, restoreActiveFieldState } from './schema-focus-state.js';
1819
export {
1920
createSchemaRowValidation,
2021
getSchemaRowValidationIssues,

packages/core-ui/js/gui_components/shared/test-data/schema/schema-controller.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ import { mapParsedRulesToRows } from './schema-editor-core.js';
88
import { parseSchemaText } from './schema-runtime.js';
99
import { preservePreviousMethodLikeSourceType } from './schema-row-mapper.js';
1010

11+
function isRecoverableSchemaParseError(error) {
12+
return error?.code === 'compiler_validation_error';
13+
}
14+
1115
function parseSchemaTextToRows({ schemaTextToDataRules, schemaText, faker, RandExp, mapRuleToRow, previousRows = [] }) {
1216
const parseResult = parseSchemaText({
1317
schemaTextToDataRules,
@@ -17,8 +21,10 @@ function parseSchemaTextToRows({ schemaTextToDataRules, schemaText, faker, RandE
1721
});
1822

1923
const tokens = Array.isArray(parseResult.schemaTokens) ? parseResult.schemaTokens : [];
20-
if (parseResult.errors.length > 0 && (!Array.isArray(parseResult.dataRules) || parseResult.dataRules.length === 0)) {
21-
return { rows: [], errors: parseResult.errors, tokens };
24+
const parseErrors = Array.isArray(parseResult.errors) ? parseResult.errors : [];
25+
const blockingErrors = parseErrors.filter((error) => !isRecoverableSchemaParseError(error));
26+
if (blockingErrors.length > 0) {
27+
return { rows: [], errors: blockingErrors, tokens };
2228
}
2329

2430
const parsedRows = mapParsedRulesToRows({
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
function captureActiveFieldState(documentObj) {
2+
const activeElement = documentObj?.activeElement;
3+
const fieldName = activeElement?.getAttribute?.('data-field');
4+
const rowId = activeElement?.closest?.('.generator-schema-row')?.getAttribute?.('data-row-id');
5+
if (!rowId || !fieldName) {
6+
return null;
7+
}
8+
return {
9+
rowId,
10+
fieldName,
11+
selectionStart: typeof activeElement.selectionStart === 'number' ? activeElement.selectionStart : null,
12+
selectionEnd: typeof activeElement.selectionEnd === 'number' ? activeElement.selectionEnd : null,
13+
selectionDirection:
14+
typeof activeElement.selectionDirection === 'string' ? activeElement.selectionDirection : 'none',
15+
};
16+
}
17+
18+
function restoreActiveFieldState(documentObj, state) {
19+
if (!state?.rowId || !state?.fieldName) {
20+
return;
21+
}
22+
const nextField = documentObj?.querySelector?.(
23+
`.generator-schema-row[data-row-id="${state.rowId}"] [data-field="${state.fieldName}"]`
24+
);
25+
if (!nextField) {
26+
return;
27+
}
28+
try {
29+
nextField.focus({ preventScroll: true });
30+
} catch {
31+
nextField.focus?.();
32+
}
33+
if (
34+
typeof nextField.setSelectionRange === 'function' &&
35+
state.selectionStart !== null &&
36+
state.selectionEnd !== null
37+
) {
38+
nextField.setSelectionRange(state.selectionStart, state.selectionEnd, state.selectionDirection || 'none');
39+
}
40+
}
41+
42+
export { captureActiveFieldState, restoreActiveFieldState };

packages/core-ui/js/gui_components/shared/test-data/schema/shared-schema-editor-controller.js

Lines changed: 1 addition & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { applySchemaCommandSelection } from './schema-row-mapper.js';
1515
import { schemaRowsToSpecWithTokens } from './schema-editor-core.js';
1616
import { schemaErrorsToText } from './schema-error-text.js';
1717
import { getSchemaRowSemanticValidationIssues } from './schema-row-validation.js';
18+
import { captureActiveFieldState, restoreActiveFieldState } from './schema-focus-state.js';
1819
import {
1920
renderGeneratorSchemaRows,
2021
clearSchemaRowDragClasses,
@@ -34,47 +35,6 @@ function createSchemaDomAdapter(documentObj, idMap = {}) {
3435
};
3536
}
3637

37-
function captureActiveFieldState(documentObj) {
38-
const activeElement = documentObj?.activeElement;
39-
const fieldName = activeElement?.getAttribute?.('data-field');
40-
const rowId = activeElement?.closest?.('.generator-schema-row')?.getAttribute?.('data-row-id');
41-
if (!rowId || !fieldName) {
42-
return null;
43-
}
44-
return {
45-
rowId,
46-
fieldName,
47-
selectionStart: typeof activeElement.selectionStart === 'number' ? activeElement.selectionStart : null,
48-
selectionEnd: typeof activeElement.selectionEnd === 'number' ? activeElement.selectionEnd : null,
49-
selectionDirection:
50-
typeof activeElement.selectionDirection === 'string' ? activeElement.selectionDirection : 'none',
51-
};
52-
}
53-
54-
function restoreActiveFieldState(documentObj, state) {
55-
if (!state?.rowId || !state?.fieldName) {
56-
return;
57-
}
58-
const nextField = documentObj?.querySelector?.(
59-
`.generator-schema-row[data-row-id="${state.rowId}"] [data-field="${state.fieldName}"]`
60-
);
61-
if (!nextField) {
62-
return;
63-
}
64-
try {
65-
nextField.focus({ preventScroll: true });
66-
} catch {
67-
nextField.focus?.();
68-
}
69-
if (
70-
typeof nextField.setSelectionRange === 'function' &&
71-
state.selectionStart !== null &&
72-
state.selectionEnd !== null
73-
) {
74-
nextField.setSelectionRange(state.selectionStart, state.selectionEnd, state.selectionDirection || 'none');
75-
}
76-
}
77-
7838
function createSharedSchemaEditorController({
7939
documentObj = document,
8040
schemaTextToDataRules,
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
import { jest } from '@jest/globals';
2+
import { JSDOM } from 'jsdom';
3+
import { createTestDataGenerationService } from '../../../../js/gui_components/app/test-data-grid/generation/test-data-generation-service.js';
4+
5+
describe('test-data-generation-service', () => {
6+
let dom;
7+
8+
beforeEach(() => {
9+
dom = new JSDOM('<!doctype html><html><body></body></html>');
10+
global.window = dom.window;
11+
global.document = dom.window.document;
12+
document.body.innerHTML = `
13+
<button id="generatedata"></button>
14+
<button id="generateallpairs"></button>
15+
<input id="generateCount" value="3">
16+
`;
17+
});
18+
19+
afterEach(() => {
20+
dom.window.close();
21+
});
22+
23+
test('generateTestData validates schema rows once before creating the generator', async () => {
24+
const validateCurrentSchemaRows = jest.fn(() => ({
25+
errors: [],
26+
rows: [{ name: 'Status', sourceType: 'literal', value: 'Active' }],
27+
}));
28+
29+
const generator = {
30+
importSpec: jest.fn(),
31+
compile: jest.fn(),
32+
compiler: { validate: jest.fn() },
33+
testDataRules: () => [{}],
34+
isValid: () => true,
35+
errors: () => [],
36+
generateHeadersArray: () => ['Status'],
37+
generateRow: () => ['Active'],
38+
};
39+
40+
const service = createTestDataGenerationService({
41+
TestDataGeneratorClass: function TestDataGeneratorClass() {
42+
return generator;
43+
},
44+
PairwiseTestDataGeneratorClass: class {},
45+
GenericDataTableClass: class {},
46+
TEST_DATA_MODES: {
47+
NEW_TABLE: 'new-table',
48+
AMEND_TABLE: 'amend-table',
49+
AMEND_SELECTED: 'amend-selected',
50+
},
51+
normaliseCount: () => 3,
52+
createTableFromGenerator: jest.fn(() => ({
53+
getRowCount: () => 3,
54+
})),
55+
createAmendedTable: jest.fn(),
56+
schemaRowsToSpec: jest.fn(() => 'Status\nliteral(Active)'),
57+
faker: {},
58+
RandExp: function RandExp() {},
59+
debouncer: { clear: jest.fn() },
60+
syncSchemaTextFromGridBeforeGenerate: jest.fn(),
61+
setTestDataStatus: jest.fn(),
62+
showSchemaError: jest.fn(),
63+
yieldToUi: jest.fn(() => Promise.resolve()),
64+
validateCurrentSchemaRows,
65+
getImporter: () => ({ setGridFromGenericDataTable: jest.fn() }),
66+
getTextPreviewRenderer: jest.fn(),
67+
getMainGridExtras: jest.fn(),
68+
getGenerationMode: () => 'new-table',
69+
});
70+
71+
await service.generateTestData();
72+
73+
expect(validateCurrentSchemaRows).toHaveBeenCalledTimes(1);
74+
expect(validateCurrentSchemaRows).toHaveBeenCalledWith(undefined);
75+
});
76+
77+
test('generatePairwiseTestData validates schema rows once before creating the generator', async () => {
78+
const validateCurrentSchemaRows = jest.fn(() => ({
79+
errors: [],
80+
rows: [
81+
{ name: 'Status', sourceType: 'enum', value: 'a,b' },
82+
{ name: 'Type', sourceType: 'enum', value: 'x,y' },
83+
],
84+
}));
85+
86+
const generator = {
87+
importSpec: jest.fn(),
88+
compile: jest.fn(),
89+
compiler: { validate: jest.fn() },
90+
testDataRules: () => [{ type: 'enum' }, { type: 'enum' }],
91+
isValid: () => true,
92+
errors: () => [],
93+
};
94+
95+
const service = createTestDataGenerationService({
96+
TestDataGeneratorClass: function TestDataGeneratorClass() {
97+
return generator;
98+
},
99+
PairwiseTestDataGeneratorClass: class FakePairwiseTestDataGenerator {
100+
initializeFromRules() {
101+
return { isError: false };
102+
}
103+
generateAllDataRecordsAsRows() {
104+
return {
105+
isError: false,
106+
data: {
107+
data: [
108+
['Status', 'Type'],
109+
['a', 'x'],
110+
],
111+
},
112+
};
113+
}
114+
},
115+
GenericDataTableClass: class FakeGenericDataTable {
116+
constructor() {
117+
this.headers = [];
118+
this.rows = [];
119+
}
120+
setHeaders(headers) {
121+
this.headers = headers;
122+
}
123+
appendDataRow(row) {
124+
this.rows.push(row);
125+
}
126+
getRowCount() {
127+
return this.rows.length;
128+
}
129+
},
130+
TEST_DATA_MODES: {
131+
NEW_TABLE: 'new-table',
132+
AMEND_TABLE: 'amend-table',
133+
AMEND_SELECTED: 'amend-selected',
134+
},
135+
normaliseCount: () => 3,
136+
createTableFromGenerator: jest.fn(),
137+
createAmendedTable: jest.fn(),
138+
schemaRowsToSpec: jest.fn(() => 'Status\nenum(a,b)\nType\nenum(x,y)'),
139+
faker: {},
140+
RandExp: function RandExp() {},
141+
debouncer: { clear: jest.fn() },
142+
syncSchemaTextFromGridBeforeGenerate: jest.fn(),
143+
setTestDataStatus: jest.fn(),
144+
showSchemaError: jest.fn(),
145+
yieldToUi: jest.fn(() => Promise.resolve()),
146+
validateCurrentSchemaRows,
147+
getImporter: () => ({ setGridFromGenericDataTable: jest.fn() }),
148+
getTextPreviewRenderer: jest.fn(),
149+
getMainGridExtras: jest.fn(),
150+
getGenerationMode: () => 'new-table',
151+
});
152+
153+
await service.generatePairwiseTestData();
154+
155+
expect(validateCurrentSchemaRows).toHaveBeenCalledTimes(1);
156+
expect(validateCurrentSchemaRows).toHaveBeenCalledWith(undefined);
157+
});
158+
});

0 commit comments

Comments
 (0)