Skip to content

Commit 18a9ffb

Browse files
committed
review updates
1 parent c504101 commit 18a9ffb

8 files changed

Lines changed: 100 additions & 13 deletions

File tree

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ You can then create a new table, or amend the existing table or selected rows.
6464

6565
The spec is a paragraph of text where each line is either a 'name' or a 'rule':
6666

67+
### Schema Formatting
68+
69+
- **Comments**: lines starting with `#` (optionally prefixed by whitespace) are treated as comments.
70+
- **Blank lines**: blank lines are allowed and ignored, so you can separate column groups for readability.
71+
- **Column definitions**: each column is defined as `name` followed by `rule` on the next logical content line.
72+
6773
```
6874
# optional comment
6975

docs-src/docs/040-test-data/050-pairwise-testing.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,14 @@ Pairwise testing is most effective when:
3131

3232
## How to Generate Pairwise Data
3333

34+
## Schema Formatting
35+
36+
Schema text supports:
37+
38+
- **Comments**: lines starting with `#` (after optional leading whitespace) are treated as comments.
39+
- **Blank lines**: allowed and ignored, useful for readability between column groups.
40+
- **Column definitions**: each column name must be followed by its generation rule on the next logical content line.
41+
3442
### In the Main App (app.html)
3543

3644
1. **Open the Test Data section** by clicking the "Test Data" header

docs-src/docs/070-interfaces-and-deployment/030-rest-api.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,14 @@ Use endpoints at `http://localhost:8082`.
137137

138138
Both endpoints generate data from the same schema language and output formats. The key difference is request shape and content type, not generation capability.
139139

140+
## Schema Formatting
141+
142+
Schema text supports:
143+
144+
- **Comments**: lines starting with `#` (after optional leading whitespace) are treated as comments.
145+
- **Blank lines**: allowed and ignored, useful for readability between column groups.
146+
- **Column definitions**: each column name must be followed by its generation rule on the next logical content line.
147+
140148
## API Examples
141149

142150
Health check:

docs-src/docs/070-interfaces-and-deployment/050-cli-node-and-bun.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@ Parameter guide for the examples:
4848
- `--unsafe-faker-expressions`: opt-in to expression-style faker arguments (unsafe for untrusted input).
4949
- `--help`: show CLI usage and options.
5050

51+
## Schema Formatting
52+
53+
Schema text supports:
54+
55+
- **Comments**: lines starting with `#` (after optional leading whitespace) are treated as comments.
56+
- **Blank lines**: allowed and ignored, useful for readability between column groups.
57+
- **Column definitions**: each column name must be followed by its generation rule on the next logical content line.
58+
5159
## Behavior Notes
5260

5361
- `--testMode` always forces generation to a single row (`rowCount = 1`) and prints diagnostic/example output.

packages/core-ui/src/tests/generator/data-generator-page.test.js

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,18 +81,23 @@ class FakeTestDataGenerator {
8181
importSpec(text) {
8282
const lines = text.split('\n');
8383
this.rules = [];
84+
this._errors = [];
8485
this._tokens = [];
8586
let pendingName = null;
8687
let pendingComments = [];
8788
for (let i = 0; i < lines.length; i += 1) {
8889
const line = lines[i];
8990
const trimmed = String(line ?? '').trim();
9091
if (trimmed.length === 0) {
92+
if (pendingName !== null) {
93+
this._errors.push(`ERROR: Missing Rule Definition for ${pendingName}`);
94+
return;
95+
}
9196
this._tokens.push({ kind: 'blank', text: line });
9297
pendingComments.push(line);
9398
continue;
9499
}
95-
if (/^\s*#/.test(line)) {
100+
if (pendingName === null && /^\s*#/.test(line)) {
96101
this._tokens.push({ kind: 'comment', text: line });
97102
pendingComments.push(line);
98103
continue;
@@ -111,6 +116,13 @@ class FakeTestDataGenerator {
111116
pendingName = null;
112117
pendingComments = [];
113118
}
119+
if (pendingName !== null) {
120+
this._errors.push(`ERROR: Missing Rule Definition for ${pendingName}`);
121+
return;
122+
}
123+
if (this.rules.length === 0) {
124+
this._errors.push('ERROR: No Rules Defined');
125+
}
114126
}
115127

116128
compile() {
@@ -860,6 +872,34 @@ describe('DataGeneratorPage', () => {
860872
expect(document.getElementById('generatorSchemaText').value).toContain('# note');
861873
});
862874

875+
test('text mode accepts hash-prefixed rule text after a column name', () => {
876+
const page = new DataGeneratorPage({
877+
parentElement: document.getElementById('app'),
878+
documentObj: document,
879+
alertFn,
880+
faker: { word: { noun: () => 'x' } },
881+
RandExp: function RandExp() {},
882+
TabulatorCtor: FakeTabulator,
883+
GridExtensionClass: FakeGridExtension,
884+
ExporterClass: FakeExporter,
885+
DownloadClass: FakeDownload,
886+
TestDataGeneratorClass: FakeTestDataGenerator,
887+
});
888+
page.init();
889+
890+
const toggle = document.getElementById('schemaModeToggleButton');
891+
toggle.click();
892+
893+
const textArea = document.getElementById('generatorSchemaText');
894+
textArea.value = 'Color\n#[A-F0-9]{6}';
895+
toggle.click();
896+
897+
expect(alertFn).not.toHaveBeenCalled();
898+
expect(page.schemaRows.length).toBe(1);
899+
expect(page.schemaRows[0].name).toBe('Color');
900+
expect(page.schemaRows[0].value).toBe('#[A-F0-9]{6}');
901+
});
902+
863903
test('adding schema rows does not discard existing parsed comments', () => {
864904
const page = new DataGeneratorPage({
865905
parentElement: document.getElementById('app'),

packages/core/js/data_generation/rulesParser.js

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,17 +39,12 @@ export class RulesParser {
3939
continue;
4040
}
4141

42-
if (/^\s*#/.test(line)) {
43-
if (pendingName !== null) {
44-
this.errors.push(`ERROR: Missing Rule Definition for ${pendingName}`);
45-
return;
46-
}
47-
this.schemaTokens.push({ kind: 'comment', text: line, line: index + 1 });
48-
pendingLeadingTextLines.push(line);
49-
continue;
50-
}
51-
5242
if (pendingName === null) {
43+
if (/^\s*#/.test(line)) {
44+
this.schemaTokens.push({ kind: 'comment', text: line, line: index + 1 });
45+
pendingLeadingTextLines.push(line);
46+
continue;
47+
}
5348
pendingName = trimmed;
5449
pendingNameLine = index + 1;
5550
continue;

packages/core/src/tests/core-api/generateFromTextSpec.test.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,17 @@ test('generateFromTextSpec accepts comments and blank lines in spec', () => {
2424
expect(result.rows.length).toBe(2);
2525
});
2626

27+
test('generateFromTextSpec accepts # prefixed rule content lines', () => {
28+
const result = generateFromTextSpec({
29+
textSpec: 'Color\n#[A-F0-9]{6}',
30+
rowCount: 2,
31+
outputFormat: 'json',
32+
});
33+
expect(result.ok).toBe(true);
34+
expect(result.headers).toEqual(['Color']);
35+
expect(result.rows).toHaveLength(2);
36+
});
37+
2738
test('generateFromTextSpec renders test framework output', () => {
2839
const result = generateFromTextSpec({ textSpec: 'Name\nBob', rowCount: 1, outputFormat: 'pytest' });
2940
expect(result.ok).toBe(true);

packages/core/src/tests/data_generation/unit/rulesParser.test.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,26 @@ enum(active,inactive,pending)
6565
expect(parser.testDataRules.rules).toHaveLength(0);
6666
});
6767

68-
test('rejects comment lines between header and rule definition', () => {
68+
test('rejects blank lines between header and rule definition', () => {
6969
const parser = new RulesParser(faker, RandExp);
70-
parser.parseText('Priority\n# not allowed here\nenum(high,medium,low)');
70+
parser.parseText('Priority\n\nenum(high,medium,low)');
7171

7272
expect(parser.isValid()).toBe(false);
7373
expect(parser.errors).toContain('ERROR: Missing Rule Definition for Priority');
7474
expect(parser.testDataRules.rules).toHaveLength(0);
7575
});
7676

77+
test('accepts rule lines that begin with # when header is pending', () => {
78+
const parser = new RulesParser(faker, RandExp);
79+
parser.parseText('Color\n#[A-F0-9]{6}');
80+
81+
expect(parser.isValid()).toBe(true);
82+
expect(parser.errors).toHaveLength(0);
83+
expect(parser.testDataRules.rules).toHaveLength(1);
84+
expect(parser.testDataRules.rules[0].name).toBe('Color');
85+
expect(parser.testDataRules.rules[0].ruleSpec).toBe('#[A-F0-9]{6}');
86+
});
87+
7788
test('preserves comments and blank lines when rebuilding from parsed tokens', () => {
7889
const inputText = `# a comment that should be skipped
7990
Priority

0 commit comments

Comments
 (0)