@auto-engineer/narrative 0.13.0 → 0.13.2
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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +22 -0
- package/dist/src/commands/export-schema-runner.js +1 -1
- package/dist/src/commands/export-schema-runner.js.map +1 -1
- package/dist/src/fluent-builder.js +3 -3
- package/dist/src/fluent-builder.js.map +1 -1
- package/dist/src/getNarratives.specs.js +149 -153
- package/dist/src/getNarratives.specs.js.map +1 -1
- package/dist/src/id/addAutoIds.d.ts.map +1 -1
- package/dist/src/id/addAutoIds.js +50 -12
- package/dist/src/id/addAutoIds.js.map +1 -1
- package/dist/src/id/addAutoIds.specs.js +396 -45
- package/dist/src/id/addAutoIds.specs.js.map +1 -1
- package/dist/src/id/hasAllIds.d.ts.map +1 -1
- package/dist/src/id/hasAllIds.js +28 -5
- package/dist/src/id/hasAllIds.js.map +1 -1
- package/dist/src/id/hasAllIds.specs.js +407 -214
- package/dist/src/id/hasAllIds.specs.js.map +1 -1
- package/dist/src/index.d.ts +6 -8
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -3
- package/dist/src/index.js.map +1 -1
- package/dist/src/loader/graph.d.ts.map +1 -1
- package/dist/src/loader/graph.js +13 -6
- package/dist/src/loader/graph.js.map +1 -1
- package/dist/src/loader/ts-utils.d.ts +1 -0
- package/dist/src/loader/ts-utils.d.ts.map +1 -1
- package/dist/src/loader/ts-utils.js +95 -16
- package/dist/src/loader/ts-utils.js.map +1 -1
- package/dist/src/model-to-narrative.specs.js +531 -449
- package/dist/src/model-to-narrative.specs.js.map +1 -1
- package/dist/src/narrative-context.d.ts +8 -8
- package/dist/src/narrative-context.d.ts.map +1 -1
- package/dist/src/narrative-context.js +111 -301
- package/dist/src/narrative-context.js.map +1 -1
- package/dist/src/narrative-context.specs.js +15 -55
- package/dist/src/narrative-context.specs.js.map +1 -1
- package/dist/src/narrative.d.ts +19 -22
- package/dist/src/narrative.d.ts.map +1 -1
- package/dist/src/narrative.js +42 -71
- package/dist/src/narrative.js.map +1 -1
- package/dist/src/samples/test-with-ids.narrative.js +13 -29
- package/dist/src/samples/test-with-ids.narrative.js.map +1 -1
- package/dist/src/schema.d.ts +3205 -8287
- package/dist/src/schema.d.ts.map +1 -1
- package/dist/src/schema.js +29 -47
- package/dist/src/schema.js.map +1 -1
- package/dist/src/slice-builder.js +3 -3
- package/dist/src/slice-builder.js.map +1 -1
- package/dist/src/transformers/model-to-narrative/generators/flow.d.ts.map +1 -1
- package/dist/src/transformers/model-to-narrative/generators/flow.js +118 -74
- package/dist/src/transformers/model-to-narrative/generators/flow.js.map +1 -1
- package/dist/src/transformers/model-to-narrative/generators/gwt.d.ts +9 -1
- package/dist/src/transformers/model-to-narrative/generators/gwt.d.ts.map +1 -1
- package/dist/src/transformers/model-to-narrative/generators/gwt.js +112 -112
- package/dist/src/transformers/model-to-narrative/generators/gwt.js.map +1 -1
- package/dist/src/transformers/model-to-narrative/generators/imports.d.ts +1 -1
- package/dist/src/transformers/model-to-narrative/generators/imports.d.ts.map +1 -1
- package/dist/src/transformers/model-to-narrative/generators/imports.js +13 -9
- package/dist/src/transformers/model-to-narrative/generators/imports.js.map +1 -1
- package/dist/src/transformers/narrative-to-model/index.d.ts.map +1 -1
- package/dist/src/transformers/narrative-to-model/index.js +50 -23
- package/dist/src/transformers/narrative-to-model/index.js.map +1 -1
- package/dist/src/transformers/narrative-to-model/type-inference.specs.js +100 -90
- package/dist/src/transformers/narrative-to-model/type-inference.specs.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -5
- package/src/commands/export-schema-runner.ts +3 -1
- package/src/fluent-builder.ts +3 -3
- package/src/getNarratives.specs.ts +168 -176
- package/src/id/addAutoIds.specs.ts +424 -47
- package/src/id/addAutoIds.ts +57 -13
- package/src/id/hasAllIds.specs.ts +400 -223
- package/src/id/hasAllIds.ts +32 -6
- package/src/index.ts +9 -12
- package/src/loader/graph.ts +23 -6
- package/src/loader/ts-utils.ts +169 -26
- package/src/model-to-narrative.specs.ts +531 -449
- package/src/narrative-context.specs.ts +73 -116
- package/src/narrative-context.ts +127 -374
- package/src/narrative.ts +70 -120
- package/src/samples/test-with-ids.narrative.ts +23 -31
- package/src/schema.ts +36 -52
- package/src/slice-builder.ts +3 -3
- package/src/transformers/model-to-narrative/generators/flow.ts +191 -85
- package/src/transformers/model-to-narrative/generators/gwt.ts +195 -178
- package/src/transformers/model-to-narrative/generators/imports.ts +13 -9
- package/src/transformers/narrative-to-model/index.ts +87 -26
- package/src/transformers/narrative-to-model/type-inference.specs.ts +100 -90
|
@@ -15,20 +15,23 @@ describe('addAutoIds', () => {
|
|
|
15
15
|
client: { specs: [] },
|
|
16
16
|
server: {
|
|
17
17
|
description: 'Test server',
|
|
18
|
-
specs:
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
18
|
+
specs: [
|
|
19
|
+
{
|
|
20
|
+
type: 'gherkin',
|
|
21
|
+
feature: 'Test Specs',
|
|
22
|
+
rules: [
|
|
23
|
+
{
|
|
24
|
+
name: 'Test rule without ID',
|
|
25
|
+
examples: [],
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
id: 'EXISTING-RULE-001',
|
|
29
|
+
name: 'Test rule with existing ID',
|
|
30
|
+
examples: [],
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
},
|
|
34
|
+
],
|
|
32
35
|
},
|
|
33
36
|
},
|
|
34
37
|
{
|
|
@@ -38,10 +41,13 @@ describe('addAutoIds', () => {
|
|
|
38
41
|
client: { specs: [] },
|
|
39
42
|
server: {
|
|
40
43
|
description: 'Test server',
|
|
41
|
-
specs:
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
specs: [
|
|
45
|
+
{
|
|
46
|
+
type: 'gherkin',
|
|
47
|
+
feature: 'Test Specs',
|
|
48
|
+
rules: [],
|
|
49
|
+
},
|
|
50
|
+
],
|
|
45
51
|
},
|
|
46
52
|
},
|
|
47
53
|
],
|
|
@@ -54,16 +60,18 @@ describe('addAutoIds', () => {
|
|
|
54
60
|
type: 'react',
|
|
55
61
|
name: 'React Slice',
|
|
56
62
|
server: {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
63
|
+
specs: [
|
|
64
|
+
{
|
|
65
|
+
type: 'gherkin',
|
|
66
|
+
feature: 'React Specs',
|
|
67
|
+
rules: [
|
|
68
|
+
{
|
|
69
|
+
name: 'React rule',
|
|
70
|
+
examples: [],
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
},
|
|
74
|
+
],
|
|
67
75
|
},
|
|
68
76
|
},
|
|
69
77
|
],
|
|
@@ -86,13 +94,13 @@ describe('addAutoIds', () => {
|
|
|
86
94
|
const slice0 = result.narratives[0].slices[0];
|
|
87
95
|
const slice1 = result.narratives[1].slices[0];
|
|
88
96
|
|
|
89
|
-
if ('server' in slice0 && slice0.server?.specs
|
|
90
|
-
expect(slice0.server.specs.rules[0].id).toMatch(AUTO_ID_REGEX);
|
|
91
|
-
expect(slice0.server.specs.rules[1].id).toBe('EXISTING-RULE-001');
|
|
97
|
+
if ('server' in slice0 && slice0.server?.specs != null && Array.isArray(slice0.server.specs)) {
|
|
98
|
+
expect(slice0.server.specs[0].rules[0].id).toMatch(AUTO_ID_REGEX);
|
|
99
|
+
expect(slice0.server.specs[0].rules[1].id).toBe('EXISTING-RULE-001');
|
|
92
100
|
}
|
|
93
101
|
|
|
94
|
-
if ('server' in slice1 && slice1.server?.specs
|
|
95
|
-
expect(slice1.server.specs.rules[0].id).toMatch(AUTO_ID_REGEX);
|
|
102
|
+
if ('server' in slice1 && slice1.server?.specs != null && Array.isArray(slice1.server.specs)) {
|
|
103
|
+
expect(slice1.server.specs[0].rules[0].id).toMatch(AUTO_ID_REGEX);
|
|
96
104
|
}
|
|
97
105
|
});
|
|
98
106
|
|
|
@@ -106,10 +114,11 @@ describe('addAutoIds', () => {
|
|
|
106
114
|
expect(originalSlice.id).toBeUndefined();
|
|
107
115
|
if (
|
|
108
116
|
'server' in originalSlice &&
|
|
109
|
-
originalSlice.server?.specs
|
|
110
|
-
originalSlice.server.specs
|
|
117
|
+
originalSlice.server?.specs !== undefined &&
|
|
118
|
+
Array.isArray(originalSlice.server.specs) &&
|
|
119
|
+
originalSlice.server.specs.length > 0
|
|
111
120
|
) {
|
|
112
|
-
expect(originalSlice.server.specs.rules[0].id).toBeUndefined();
|
|
121
|
+
expect(originalSlice.server.specs[0].rules[0].id).toBeUndefined();
|
|
113
122
|
}
|
|
114
123
|
});
|
|
115
124
|
|
|
@@ -120,8 +129,8 @@ describe('addAutoIds', () => {
|
|
|
120
129
|
expect(result.narratives[0].slices[1].id).toBe('EXISTING-SLICE-001');
|
|
121
130
|
|
|
122
131
|
const testSlice = result.narratives[0].slices[0];
|
|
123
|
-
if ('server' in testSlice && testSlice.server?.specs
|
|
124
|
-
expect(testSlice.server.specs.rules[1].id).toBe('EXISTING-RULE-001');
|
|
132
|
+
if ('server' in testSlice && testSlice.server?.specs != null && Array.isArray(testSlice.server.specs)) {
|
|
133
|
+
expect(testSlice.server.specs[0].rules[1].id).toBe('EXISTING-RULE-001');
|
|
125
134
|
}
|
|
126
135
|
});
|
|
127
136
|
|
|
@@ -138,10 +147,13 @@ describe('addAutoIds', () => {
|
|
|
138
147
|
client: { specs: [] },
|
|
139
148
|
server: {
|
|
140
149
|
description: 'Simple server',
|
|
141
|
-
specs:
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
150
|
+
specs: [
|
|
151
|
+
{
|
|
152
|
+
type: 'gherkin',
|
|
153
|
+
feature: 'Simple specs',
|
|
154
|
+
rules: [],
|
|
155
|
+
},
|
|
156
|
+
],
|
|
145
157
|
},
|
|
146
158
|
},
|
|
147
159
|
],
|
|
@@ -199,14 +211,9 @@ describe('addAutoIds', () => {
|
|
|
199
211
|
|
|
200
212
|
const result = addAutoIds(modelWithExperienceSlice);
|
|
201
213
|
|
|
202
|
-
// Flow should get an auto ID
|
|
203
214
|
expect(result.narratives[0].id).toMatch(AUTO_ID_REGEX);
|
|
204
|
-
|
|
205
|
-
// Experience slices should get auto IDs where missing
|
|
206
215
|
expect(result.narratives[0].slices[0].id).toMatch(AUTO_ID_REGEX);
|
|
207
216
|
expect(result.narratives[0].slices[1].id).toBe('EXISTING-EXPERIENCE-SLICE-001');
|
|
208
|
-
|
|
209
|
-
// Experience slices only have client specs (no server specs to test)
|
|
210
217
|
});
|
|
211
218
|
|
|
212
219
|
it('should assign unique IDs to multiple flows with same sourceFile', () => {
|
|
@@ -279,4 +286,374 @@ describe('addAutoIds', () => {
|
|
|
279
286
|
expect(result.narratives[1].sourceFile).toBe('/path/to/homepage.narrative.ts');
|
|
280
287
|
expect(result.narratives[2].sourceFile).toBe('/path/to/homepage.narrative.ts');
|
|
281
288
|
});
|
|
289
|
+
|
|
290
|
+
it('should assign IDs to specs', () => {
|
|
291
|
+
const modelWithSpecs: Model = {
|
|
292
|
+
variant: 'specs',
|
|
293
|
+
narratives: [
|
|
294
|
+
{
|
|
295
|
+
name: 'Test Flow',
|
|
296
|
+
slices: [
|
|
297
|
+
{
|
|
298
|
+
type: 'command',
|
|
299
|
+
name: 'Test Command',
|
|
300
|
+
client: { specs: [] },
|
|
301
|
+
server: {
|
|
302
|
+
description: 'Test server',
|
|
303
|
+
specs: [
|
|
304
|
+
{
|
|
305
|
+
type: 'gherkin',
|
|
306
|
+
feature: 'Test Feature',
|
|
307
|
+
rules: [],
|
|
308
|
+
},
|
|
309
|
+
{
|
|
310
|
+
id: 'EXISTING-SPEC-001',
|
|
311
|
+
type: 'gherkin',
|
|
312
|
+
feature: 'Existing Feature',
|
|
313
|
+
rules: [],
|
|
314
|
+
},
|
|
315
|
+
],
|
|
316
|
+
},
|
|
317
|
+
},
|
|
318
|
+
],
|
|
319
|
+
},
|
|
320
|
+
],
|
|
321
|
+
messages: [],
|
|
322
|
+
integrations: [],
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
const result = addAutoIds(modelWithSpecs);
|
|
326
|
+
const slice = result.narratives[0].slices[0];
|
|
327
|
+
|
|
328
|
+
if ('server' in slice && slice.server?.specs != null && Array.isArray(slice.server.specs)) {
|
|
329
|
+
expect(slice.server.specs[0].id).toMatch(AUTO_ID_REGEX);
|
|
330
|
+
expect(slice.server.specs[1].id).toBe('EXISTING-SPEC-001');
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
it('should assign IDs to steps', () => {
|
|
335
|
+
const modelWithSteps: Model = {
|
|
336
|
+
variant: 'specs',
|
|
337
|
+
narratives: [
|
|
338
|
+
{
|
|
339
|
+
name: 'Test Flow',
|
|
340
|
+
slices: [
|
|
341
|
+
{
|
|
342
|
+
type: 'command',
|
|
343
|
+
name: 'Test Command',
|
|
344
|
+
client: { specs: [] },
|
|
345
|
+
server: {
|
|
346
|
+
description: 'Test server',
|
|
347
|
+
specs: [
|
|
348
|
+
{
|
|
349
|
+
type: 'gherkin',
|
|
350
|
+
feature: 'Test Feature',
|
|
351
|
+
rules: [
|
|
352
|
+
{
|
|
353
|
+
name: 'Test Rule',
|
|
354
|
+
examples: [
|
|
355
|
+
{
|
|
356
|
+
name: 'Test Example',
|
|
357
|
+
steps: [
|
|
358
|
+
{ keyword: 'Given', text: 'TestState', docString: { value: 'test' } },
|
|
359
|
+
{ keyword: 'When', text: 'TestCommand' },
|
|
360
|
+
{ id: 'EXISTING-STEP-001', keyword: 'Then', text: 'TestEvent' },
|
|
361
|
+
],
|
|
362
|
+
},
|
|
363
|
+
],
|
|
364
|
+
},
|
|
365
|
+
],
|
|
366
|
+
},
|
|
367
|
+
],
|
|
368
|
+
},
|
|
369
|
+
},
|
|
370
|
+
],
|
|
371
|
+
},
|
|
372
|
+
],
|
|
373
|
+
messages: [],
|
|
374
|
+
integrations: [],
|
|
375
|
+
};
|
|
376
|
+
|
|
377
|
+
const result = addAutoIds(modelWithSteps);
|
|
378
|
+
const slice = result.narratives[0].slices[0];
|
|
379
|
+
|
|
380
|
+
if ('server' in slice && slice.server?.specs != null && Array.isArray(slice.server.specs)) {
|
|
381
|
+
const steps = slice.server.specs[0].rules[0].examples[0].steps;
|
|
382
|
+
expect(steps[0].id).toMatch(AUTO_ID_REGEX);
|
|
383
|
+
expect(steps[1].id).toMatch(AUTO_ID_REGEX);
|
|
384
|
+
expect(steps[2].id).toBe('EXISTING-STEP-001');
|
|
385
|
+
}
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
it('should preserve existing example IDs', () => {
|
|
389
|
+
const modelWithExistingExampleId: Model = {
|
|
390
|
+
variant: 'specs',
|
|
391
|
+
narratives: [
|
|
392
|
+
{
|
|
393
|
+
name: 'Test Flow',
|
|
394
|
+
slices: [
|
|
395
|
+
{
|
|
396
|
+
type: 'command',
|
|
397
|
+
name: 'Test Command',
|
|
398
|
+
client: { specs: [] },
|
|
399
|
+
server: {
|
|
400
|
+
description: 'Test server',
|
|
401
|
+
specs: [
|
|
402
|
+
{
|
|
403
|
+
type: 'gherkin',
|
|
404
|
+
feature: 'Test Feature',
|
|
405
|
+
rules: [
|
|
406
|
+
{
|
|
407
|
+
name: 'Test Rule',
|
|
408
|
+
examples: [
|
|
409
|
+
{
|
|
410
|
+
name: 'Example without id',
|
|
411
|
+
steps: [{ keyword: 'Given', text: 'TestState' }],
|
|
412
|
+
},
|
|
413
|
+
{
|
|
414
|
+
id: 'EXISTING-EXAMPLE-001',
|
|
415
|
+
name: 'Example with existing id',
|
|
416
|
+
steps: [{ keyword: 'Given', text: 'TestState' }],
|
|
417
|
+
},
|
|
418
|
+
],
|
|
419
|
+
},
|
|
420
|
+
],
|
|
421
|
+
},
|
|
422
|
+
],
|
|
423
|
+
},
|
|
424
|
+
},
|
|
425
|
+
],
|
|
426
|
+
},
|
|
427
|
+
],
|
|
428
|
+
messages: [],
|
|
429
|
+
integrations: [],
|
|
430
|
+
};
|
|
431
|
+
|
|
432
|
+
const result = addAutoIds(modelWithExistingExampleId);
|
|
433
|
+
const slice = result.narratives[0].slices[0];
|
|
434
|
+
|
|
435
|
+
if ('server' in slice && slice.server?.specs != null && Array.isArray(slice.server.specs)) {
|
|
436
|
+
const examples = slice.server.specs[0].rules[0].examples;
|
|
437
|
+
expect(examples[0].id).toMatch(AUTO_ID_REGEX);
|
|
438
|
+
expect(examples[1].id).toBe('EXISTING-EXAMPLE-001');
|
|
439
|
+
}
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
it('should assign IDs to steps with errors', () => {
|
|
443
|
+
const modelWithErrorSteps: Model = {
|
|
444
|
+
variant: 'specs',
|
|
445
|
+
narratives: [
|
|
446
|
+
{
|
|
447
|
+
name: 'Test Flow',
|
|
448
|
+
slices: [
|
|
449
|
+
{
|
|
450
|
+
type: 'command',
|
|
451
|
+
name: 'Test Command',
|
|
452
|
+
client: { specs: [] },
|
|
453
|
+
server: {
|
|
454
|
+
description: 'Test server',
|
|
455
|
+
specs: [
|
|
456
|
+
{
|
|
457
|
+
type: 'gherkin',
|
|
458
|
+
feature: 'Test Feature',
|
|
459
|
+
rules: [
|
|
460
|
+
{
|
|
461
|
+
name: 'Error Rule',
|
|
462
|
+
examples: [
|
|
463
|
+
{
|
|
464
|
+
name: 'Error Example',
|
|
465
|
+
steps: [
|
|
466
|
+
{ keyword: 'Given', text: 'TestState' },
|
|
467
|
+
{ keyword: 'When', text: 'InvalidCommand' },
|
|
468
|
+
{ keyword: 'Then', error: { type: 'ValidationError', message: 'Invalid input' } },
|
|
469
|
+
],
|
|
470
|
+
},
|
|
471
|
+
],
|
|
472
|
+
},
|
|
473
|
+
],
|
|
474
|
+
},
|
|
475
|
+
],
|
|
476
|
+
},
|
|
477
|
+
},
|
|
478
|
+
],
|
|
479
|
+
},
|
|
480
|
+
],
|
|
481
|
+
messages: [],
|
|
482
|
+
integrations: [],
|
|
483
|
+
};
|
|
484
|
+
|
|
485
|
+
const result = addAutoIds(modelWithErrorSteps);
|
|
486
|
+
const slice = result.narratives[0].slices[0];
|
|
487
|
+
|
|
488
|
+
if ('server' in slice && slice.server?.specs != null && Array.isArray(slice.server.specs)) {
|
|
489
|
+
const steps = slice.server.specs[0].rules[0].examples[0].steps;
|
|
490
|
+
expect(steps[0].id).toMatch(AUTO_ID_REGEX);
|
|
491
|
+
expect(steps[1].id).toMatch(AUTO_ID_REGEX);
|
|
492
|
+
expect(steps[2].id).toMatch(AUTO_ID_REGEX);
|
|
493
|
+
}
|
|
494
|
+
});
|
|
495
|
+
|
|
496
|
+
it('should assign IDs to client it specs', () => {
|
|
497
|
+
const modelWithClientSpecs: Model = {
|
|
498
|
+
variant: 'specs',
|
|
499
|
+
narratives: [
|
|
500
|
+
{
|
|
501
|
+
name: 'Test Flow',
|
|
502
|
+
slices: [
|
|
503
|
+
{
|
|
504
|
+
type: 'experience',
|
|
505
|
+
name: 'Test Experience',
|
|
506
|
+
client: {
|
|
507
|
+
specs: [
|
|
508
|
+
{ type: 'it', title: 'first test' },
|
|
509
|
+
{ type: 'it', id: 'EXISTING-IT-001', title: 'second test with id' },
|
|
510
|
+
],
|
|
511
|
+
},
|
|
512
|
+
},
|
|
513
|
+
],
|
|
514
|
+
},
|
|
515
|
+
],
|
|
516
|
+
messages: [],
|
|
517
|
+
integrations: [],
|
|
518
|
+
};
|
|
519
|
+
|
|
520
|
+
const result = addAutoIds(modelWithClientSpecs);
|
|
521
|
+
const slice = result.narratives[0].slices[0];
|
|
522
|
+
|
|
523
|
+
if ('client' in slice && slice.client?.specs != null) {
|
|
524
|
+
expect(slice.client.specs[0].id).toMatch(AUTO_ID_REGEX);
|
|
525
|
+
expect(slice.client.specs[1].id).toBe('EXISTING-IT-001');
|
|
526
|
+
}
|
|
527
|
+
});
|
|
528
|
+
|
|
529
|
+
it('should assign IDs to client describe specs', () => {
|
|
530
|
+
const modelWithDescribe: Model = {
|
|
531
|
+
variant: 'specs',
|
|
532
|
+
narratives: [
|
|
533
|
+
{
|
|
534
|
+
name: 'Test Flow',
|
|
535
|
+
slices: [
|
|
536
|
+
{
|
|
537
|
+
type: 'experience',
|
|
538
|
+
name: 'Test Experience',
|
|
539
|
+
client: {
|
|
540
|
+
specs: [
|
|
541
|
+
{
|
|
542
|
+
type: 'describe',
|
|
543
|
+
title: 'describe without id',
|
|
544
|
+
children: [{ type: 'it', title: 'nested it' }],
|
|
545
|
+
},
|
|
546
|
+
{
|
|
547
|
+
type: 'describe',
|
|
548
|
+
id: 'EXISTING-DESC-001',
|
|
549
|
+
title: 'describe with id',
|
|
550
|
+
children: [],
|
|
551
|
+
},
|
|
552
|
+
],
|
|
553
|
+
},
|
|
554
|
+
},
|
|
555
|
+
],
|
|
556
|
+
},
|
|
557
|
+
],
|
|
558
|
+
messages: [],
|
|
559
|
+
integrations: [],
|
|
560
|
+
};
|
|
561
|
+
|
|
562
|
+
const result = addAutoIds(modelWithDescribe);
|
|
563
|
+
const slice = result.narratives[0].slices[0];
|
|
564
|
+
|
|
565
|
+
if ('client' in slice && slice.client?.specs != null) {
|
|
566
|
+
expect(slice.client.specs[0].id).toMatch(AUTO_ID_REGEX);
|
|
567
|
+
expect(slice.client.specs[1].id).toBe('EXISTING-DESC-001');
|
|
568
|
+
}
|
|
569
|
+
});
|
|
570
|
+
|
|
571
|
+
it('should assign IDs to nested client specs', () => {
|
|
572
|
+
const modelWithNestedSpecs: Model = {
|
|
573
|
+
variant: 'specs',
|
|
574
|
+
narratives: [
|
|
575
|
+
{
|
|
576
|
+
name: 'Test Flow',
|
|
577
|
+
slices: [
|
|
578
|
+
{
|
|
579
|
+
type: 'experience',
|
|
580
|
+
name: 'Test Experience',
|
|
581
|
+
client: {
|
|
582
|
+
specs: [
|
|
583
|
+
{
|
|
584
|
+
type: 'describe',
|
|
585
|
+
title: 'outer describe',
|
|
586
|
+
children: [
|
|
587
|
+
{ type: 'it', title: 'outer it' },
|
|
588
|
+
{
|
|
589
|
+
type: 'describe',
|
|
590
|
+
title: 'inner describe',
|
|
591
|
+
children: [
|
|
592
|
+
{ type: 'it', title: 'inner it 1' },
|
|
593
|
+
{ type: 'it', title: 'inner it 2' },
|
|
594
|
+
],
|
|
595
|
+
},
|
|
596
|
+
],
|
|
597
|
+
},
|
|
598
|
+
],
|
|
599
|
+
},
|
|
600
|
+
},
|
|
601
|
+
],
|
|
602
|
+
},
|
|
603
|
+
],
|
|
604
|
+
messages: [],
|
|
605
|
+
integrations: [],
|
|
606
|
+
};
|
|
607
|
+
|
|
608
|
+
const result = addAutoIds(modelWithNestedSpecs);
|
|
609
|
+
const slice = result.narratives[0].slices[0];
|
|
610
|
+
|
|
611
|
+
if ('client' in slice && slice.client?.specs != null) {
|
|
612
|
+
const outerDescribe = slice.client.specs[0];
|
|
613
|
+
expect(outerDescribe.id).toMatch(AUTO_ID_REGEX);
|
|
614
|
+
|
|
615
|
+
if (outerDescribe.type === 'describe' && outerDescribe.children) {
|
|
616
|
+
expect(outerDescribe.children[0].id).toMatch(AUTO_ID_REGEX);
|
|
617
|
+
|
|
618
|
+
const innerDescribe = outerDescribe.children[1];
|
|
619
|
+
expect(innerDescribe.id).toMatch(AUTO_ID_REGEX);
|
|
620
|
+
|
|
621
|
+
if (innerDescribe.type === 'describe' && innerDescribe.children) {
|
|
622
|
+
expect(innerDescribe.children[0].id).toMatch(AUTO_ID_REGEX);
|
|
623
|
+
expect(innerDescribe.children[1].id).toMatch(AUTO_ID_REGEX);
|
|
624
|
+
|
|
625
|
+
expect(innerDescribe.children[0].id).not.toBe(innerDescribe.children[1].id);
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
});
|
|
630
|
+
|
|
631
|
+
it('should not mutate original client specs', () => {
|
|
632
|
+
const modelWithClientSpecs: Model = {
|
|
633
|
+
variant: 'specs',
|
|
634
|
+
narratives: [
|
|
635
|
+
{
|
|
636
|
+
name: 'Test Flow',
|
|
637
|
+
slices: [
|
|
638
|
+
{
|
|
639
|
+
type: 'experience',
|
|
640
|
+
name: 'Test Experience',
|
|
641
|
+
client: {
|
|
642
|
+
specs: [{ type: 'it', title: 'test' }],
|
|
643
|
+
},
|
|
644
|
+
},
|
|
645
|
+
],
|
|
646
|
+
},
|
|
647
|
+
],
|
|
648
|
+
messages: [],
|
|
649
|
+
integrations: [],
|
|
650
|
+
};
|
|
651
|
+
|
|
652
|
+
const originalSpec = modelWithClientSpecs.narratives[0].slices[0];
|
|
653
|
+
addAutoIds(modelWithClientSpecs);
|
|
654
|
+
|
|
655
|
+
if ('client' in originalSpec && originalSpec.client?.specs != null) {
|
|
656
|
+
expect(originalSpec.client.specs[0].id).toBeUndefined();
|
|
657
|
+
}
|
|
658
|
+
});
|
|
282
659
|
});
|
package/src/id/addAutoIds.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { generateAutoId } from './generators';
|
|
2
|
-
import { Model, Slice } from '../index';
|
|
2
|
+
import { Model, Slice, Spec, Rule, Example, Step, ClientSpecNode } from '../index';
|
|
3
3
|
|
|
4
4
|
function ensureId(item: { id?: string }): void {
|
|
5
5
|
if (item.id === undefined || item.id === '') {
|
|
@@ -7,30 +7,74 @@ function ensureId(item: { id?: string }): void {
|
|
|
7
7
|
}
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
function
|
|
10
|
+
function processSteps(steps: Step[]): Step[] {
|
|
11
|
+
return steps.map((step) => {
|
|
12
|
+
const stepCopy = { ...step };
|
|
13
|
+
ensureId(stepCopy);
|
|
14
|
+
return stepCopy;
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function processExamples(examples: Example[]): Example[] {
|
|
19
|
+
return examples.map((example) => {
|
|
20
|
+
const exampleCopy = { ...example };
|
|
21
|
+
ensureId(exampleCopy);
|
|
22
|
+
exampleCopy.steps = processSteps(example.steps);
|
|
23
|
+
return exampleCopy;
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function processRules(rules: Rule[]): Rule[] {
|
|
11
28
|
return rules.map((rule) => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
29
|
+
const ruleCopy = { ...rule };
|
|
30
|
+
ensureId(ruleCopy);
|
|
31
|
+
ruleCopy.examples = processExamples(rule.examples);
|
|
32
|
+
return ruleCopy;
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function processSpecs(specs: Spec[]): Spec[] {
|
|
37
|
+
return specs.map((spec) => {
|
|
38
|
+
const specCopy = { ...spec };
|
|
39
|
+
ensureId(specCopy);
|
|
40
|
+
specCopy.rules = processRules(spec.rules);
|
|
41
|
+
return specCopy;
|
|
18
42
|
});
|
|
19
43
|
}
|
|
20
44
|
|
|
21
45
|
function processServerSpecs(slice: Slice): Slice {
|
|
22
|
-
if (!('server' in slice) || slice.server?.specs
|
|
46
|
+
if (!('server' in slice) || slice.server?.specs === undefined || !Array.isArray(slice.server.specs)) return slice;
|
|
23
47
|
|
|
24
48
|
const modifiedSlice = structuredClone(slice);
|
|
25
|
-
if (
|
|
26
|
-
|
|
49
|
+
if (
|
|
50
|
+
'server' in modifiedSlice &&
|
|
51
|
+
modifiedSlice.server?.specs !== undefined &&
|
|
52
|
+
Array.isArray(modifiedSlice.server.specs)
|
|
53
|
+
) {
|
|
54
|
+
modifiedSlice.server.specs = processSpecs(modifiedSlice.server.specs);
|
|
27
55
|
}
|
|
28
56
|
return modifiedSlice;
|
|
29
57
|
}
|
|
30
58
|
|
|
59
|
+
function processClientSpecNodes(nodes: ClientSpecNode[]): ClientSpecNode[] {
|
|
60
|
+
return nodes.map((node) => {
|
|
61
|
+
const nodeCopy = { ...node };
|
|
62
|
+
ensureId(nodeCopy);
|
|
63
|
+
if (nodeCopy.type === 'describe' && nodeCopy.children) {
|
|
64
|
+
nodeCopy.children = processClientSpecNodes(nodeCopy.children);
|
|
65
|
+
}
|
|
66
|
+
return nodeCopy;
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
31
70
|
function processClientSpecs(slice: Slice): Slice {
|
|
32
|
-
|
|
33
|
-
|
|
71
|
+
if (!('client' in slice) || slice.client?.specs === undefined || !Array.isArray(slice.client.specs)) return slice;
|
|
72
|
+
|
|
73
|
+
const modifiedSlice = structuredClone(slice);
|
|
74
|
+
if ('client' in modifiedSlice && modifiedSlice.client?.specs !== undefined) {
|
|
75
|
+
modifiedSlice.client.specs = processClientSpecNodes(modifiedSlice.client.specs);
|
|
76
|
+
}
|
|
77
|
+
return modifiedSlice;
|
|
34
78
|
}
|
|
35
79
|
|
|
36
80
|
function processSlice(slice: Slice): Slice {
|