@auto-engineer/narrative 0.12.1 → 0.13.1
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 +24 -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 +157 -161
- 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 +23 -10
- package/dist/src/id/addAutoIds.js.map +1 -1
- package/dist/src/id/addAutoIds.specs.js +55 -46
- package/dist/src/id/addAutoIds.specs.js.map +1 -1
- package/dist/src/id/generators.js +1 -1
- package/dist/src/id/generators.js.map +1 -1
- package/dist/src/id/hasAllIds.d.ts.map +1 -1
- package/dist/src/id/hasAllIds.js +8 -3
- package/dist/src/id/hasAllIds.js.map +1 -1
- package/dist/src/id/hasAllIds.specs.js +142 -215
- package/dist/src/id/hasAllIds.specs.js.map +1 -1
- package/dist/src/index.d.ts +7 -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 +548 -466
- 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/questionnaires.narrative.js +10 -10
- package/dist/src/samples/questionnaires.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 +2704 -8293
- package/dist/src/schema.d.ts.map +1 -1
- package/dist/src/schema.js +26 -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 +176 -184
- package/src/id/addAutoIds.specs.ts +55 -48
- package/src/id/addAutoIds.ts +28 -11
- package/src/id/generators.ts +1 -1
- package/src/id/hasAllIds.specs.ts +147 -245
- package/src/id/hasAllIds.ts +11 -4
- package/src/index.ts +11 -12
- package/src/loader/graph.ts +23 -6
- package/src/loader/ts-utils.ts +169 -26
- package/src/model-to-narrative.specs.ts +548 -466
- package/src/narrative-context.specs.ts +73 -116
- package/src/narrative-context.ts +127 -374
- package/src/narrative.ts +70 -120
- package/src/samples/questionnaires.narrative.ts +10 -10
- package/src/samples/test-with-ids.narrative.ts +23 -31
- package/src/schema.ts +33 -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
|
@@ -12,6 +12,7 @@ describe('modelToNarrative', () => {
|
|
|
12
12
|
data,
|
|
13
13
|
describe,
|
|
14
14
|
example,
|
|
15
|
+
given,
|
|
15
16
|
gql,
|
|
16
17
|
it,
|
|
17
18
|
narrative,
|
|
@@ -21,6 +22,8 @@ describe('modelToNarrative', () => {
|
|
|
21
22
|
sink,
|
|
22
23
|
source,
|
|
23
24
|
specs,
|
|
25
|
+
then,
|
|
26
|
+
when,
|
|
24
27
|
} from '@auto-engineer/narrative';
|
|
25
28
|
import type { Command, Event, State } from '@auto-engineer/narrative';
|
|
26
29
|
import { AI, ProductCatalog } from '../server/src/integrations';
|
|
@@ -117,34 +120,36 @@ narrative('Seasonal Assistant', () => {
|
|
|
117
120
|
data([sink().event('ShoppingCriteriaEntered').toStream('shopping-session-\${sessionId}')]);
|
|
118
121
|
specs('When shopper submits criteria, a shopping session is started', () => {
|
|
119
122
|
rule('Valid criteria should start a shopping session', () => {
|
|
120
|
-
example('User submits shopping criteria for children')
|
|
121
|
-
|
|
123
|
+
example('User submits shopping criteria for children', () => {
|
|
124
|
+
when<EnterShoppingCriteria>({
|
|
122
125
|
sessionId: 'shopper-123',
|
|
123
126
|
criteria:
|
|
124
127
|
'I need back-to-school items for my 7-year-old daughter who loves soccer and crafts, and my 12-year-old son who is into computers and Magic the Gathering.',
|
|
125
|
-
})
|
|
126
|
-
|
|
128
|
+
});
|
|
129
|
+
then<ShoppingCriteriaEntered>({
|
|
127
130
|
sessionId: 'shopper-123',
|
|
128
131
|
criteria:
|
|
129
132
|
'I need back-to-school items for my 7-year-old daughter who loves soccer and crafts, and my 12-year-old son who is into computers and Magic the Gathering.',
|
|
130
133
|
});
|
|
134
|
+
});
|
|
131
135
|
});
|
|
132
136
|
});
|
|
133
137
|
});
|
|
134
138
|
react('creates a chat session').server(() => {
|
|
135
139
|
specs('When shopping criteria are entered, request wishlist creation', () => {
|
|
136
140
|
rule('Shopping criteria should trigger item suggestion', () => {
|
|
137
|
-
example('Criteria entered triggers wishlist creation')
|
|
138
|
-
|
|
141
|
+
example('Criteria entered triggers wishlist creation', () => {
|
|
142
|
+
when<ShoppingCriteriaEntered>({
|
|
139
143
|
sessionId: 'session-abc',
|
|
140
144
|
criteria:
|
|
141
145
|
'I need back-to-school items for my 7-year-old daughter who loves soccer and crafts, and my 12-year-old son who is into computers and Magic the Gathering.',
|
|
142
|
-
})
|
|
143
|
-
|
|
146
|
+
});
|
|
147
|
+
then<SuggestShoppingItems>({
|
|
144
148
|
sessionId: 'session-abc',
|
|
145
149
|
prompt:
|
|
146
150
|
'I need back-to-school items for my 7-year-old daughter who loves soccer and crafts, and my 12-year-old son who is into computers and Magic the Gathering.',
|
|
147
151
|
});
|
|
152
|
+
});
|
|
148
153
|
});
|
|
149
154
|
});
|
|
150
155
|
});
|
|
@@ -161,8 +166,8 @@ narrative('Seasonal Assistant', () => {
|
|
|
161
166
|
]);
|
|
162
167
|
specs('When chat is triggered, AI suggests items based on product catalog', () => {
|
|
163
168
|
rule('AI should suggest relevant items from available products', () => {
|
|
164
|
-
example('Product catalog with matching items generates suggestions')
|
|
165
|
-
|
|
169
|
+
example('Product catalog with matching items generates suggestions', () => {
|
|
170
|
+
given<Products>({
|
|
166
171
|
products: [
|
|
167
172
|
{
|
|
168
173
|
productId: 'prod-soccer-ball',
|
|
@@ -197,13 +202,13 @@ narrative('Seasonal Assistant', () => {
|
|
|
197
202
|
imageUrl: 'https://example.com/mtg-starter.jpg',
|
|
198
203
|
},
|
|
199
204
|
],
|
|
200
|
-
})
|
|
201
|
-
|
|
205
|
+
});
|
|
206
|
+
when<SuggestShoppingItems>({
|
|
202
207
|
sessionId: 'session-abc',
|
|
203
208
|
prompt:
|
|
204
209
|
'I need back-to-school items for my 7-year-old daughter who loves soccer and crafts, and my 12-year-old son who is into computers and Magic the Gathering.',
|
|
205
|
-
})
|
|
206
|
-
|
|
210
|
+
});
|
|
211
|
+
then<ShoppingItemsSuggested>({
|
|
207
212
|
sessionId: 'session-abc',
|
|
208
213
|
suggestedItems: [
|
|
209
214
|
{
|
|
@@ -232,6 +237,7 @@ narrative('Seasonal Assistant', () => {
|
|
|
232
237
|
},
|
|
233
238
|
],
|
|
234
239
|
});
|
|
240
|
+
});
|
|
235
241
|
});
|
|
236
242
|
});
|
|
237
243
|
});
|
|
@@ -260,8 +266,8 @@ narrative('Seasonal Assistant', () => {
|
|
|
260
266
|
data([source().state('SuggestedItems').fromProjection('SuggestedItemsProjection', 'sessionId')]);
|
|
261
267
|
specs('Suggested items are available for viewing', () => {
|
|
262
268
|
rule('Items should be available for viewing after suggestion', () => {
|
|
263
|
-
example('Item becomes available after AI suggestion event')
|
|
264
|
-
|
|
269
|
+
example('Item becomes available after AI suggestion event', () => {
|
|
270
|
+
when<ShoppingItemsSuggested>({
|
|
265
271
|
sessionId: 'session-abc',
|
|
266
272
|
suggestedItems: [
|
|
267
273
|
{
|
|
@@ -289,8 +295,8 @@ narrative('Seasonal Assistant', () => {
|
|
|
289
295
|
reason: 'Ideal starter set for Magic the Gathering enthusiasts',
|
|
290
296
|
},
|
|
291
297
|
],
|
|
292
|
-
})
|
|
293
|
-
|
|
298
|
+
});
|
|
299
|
+
then<SuggestedItems>({
|
|
294
300
|
sessionId: 'session-abc',
|
|
295
301
|
items: [
|
|
296
302
|
{
|
|
@@ -319,6 +325,7 @@ narrative('Seasonal Assistant', () => {
|
|
|
319
325
|
},
|
|
320
326
|
],
|
|
321
327
|
});
|
|
328
|
+
});
|
|
322
329
|
});
|
|
323
330
|
});
|
|
324
331
|
});
|
|
@@ -334,8 +341,8 @@ narrative('Seasonal Assistant', () => {
|
|
|
334
341
|
data([sink().event('ItemsAddedToCart').toStream('shopping-session-\${sessionId}')]);
|
|
335
342
|
specs('When shopper accepts items, they are added to cart', () => {
|
|
336
343
|
rule('Accepted items should be added to the shopping cart', () => {
|
|
337
|
-
example('User selects all suggested items for cart')
|
|
338
|
-
|
|
344
|
+
example('User selects all suggested items for cart', () => {
|
|
345
|
+
when<AddItemsToCart>({
|
|
339
346
|
sessionId: 'session-abc',
|
|
340
347
|
items: [
|
|
341
348
|
{ productId: 'prod-soccer-ball', quantity: 1 },
|
|
@@ -343,8 +350,8 @@ narrative('Seasonal Assistant', () => {
|
|
|
343
350
|
{ productId: 'prod-laptop-bag', quantity: 1 },
|
|
344
351
|
{ productId: 'prod-mtg-starter', quantity: 1 },
|
|
345
352
|
],
|
|
346
|
-
})
|
|
347
|
-
|
|
353
|
+
});
|
|
354
|
+
then<ItemsAddedToCart>({
|
|
348
355
|
sessionId: 'session-abc',
|
|
349
356
|
items: [
|
|
350
357
|
{ productId: 'prod-soccer-ball', quantity: 1 },
|
|
@@ -353,6 +360,7 @@ narrative('Seasonal Assistant', () => {
|
|
|
353
360
|
{ productId: 'prod-mtg-starter', quantity: 1 },
|
|
354
361
|
],
|
|
355
362
|
});
|
|
363
|
+
});
|
|
356
364
|
});
|
|
357
365
|
});
|
|
358
366
|
});
|
|
@@ -487,10 +495,13 @@ narrative('Test Flow without IDs', () => {
|
|
|
487
495
|
},
|
|
488
496
|
server: {
|
|
489
497
|
description: 'Product query server',
|
|
490
|
-
specs:
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
498
|
+
specs: [
|
|
499
|
+
{
|
|
500
|
+
type: 'gherkin',
|
|
501
|
+
feature: 'Product data specs',
|
|
502
|
+
rules: [],
|
|
503
|
+
},
|
|
504
|
+
],
|
|
494
505
|
},
|
|
495
506
|
},
|
|
496
507
|
],
|
|
@@ -541,30 +552,36 @@ narrative('Test Flow with IDs', 'FLOW-123', () => {
|
|
|
541
552
|
},
|
|
542
553
|
server: {
|
|
543
554
|
description: 'Command processing server',
|
|
544
|
-
specs:
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
555
|
+
specs: [
|
|
556
|
+
{
|
|
557
|
+
type: 'gherkin',
|
|
558
|
+
feature: 'Command Processing',
|
|
559
|
+
rules: [
|
|
560
|
+
{
|
|
561
|
+
id: 'RULE-ABC',
|
|
562
|
+
name: 'Valid commands should be processed',
|
|
563
|
+
examples: [
|
|
564
|
+
{
|
|
565
|
+
id: 'EX-001',
|
|
566
|
+
name: 'User submits valid command',
|
|
567
|
+
steps: [
|
|
568
|
+
{
|
|
569
|
+
keyword: 'When',
|
|
570
|
+
text: 'ProcessCommand',
|
|
571
|
+
docString: { id: 'cmd-123', action: 'create' },
|
|
572
|
+
},
|
|
573
|
+
{
|
|
574
|
+
keyword: 'Then',
|
|
575
|
+
text: 'CommandProcessed',
|
|
576
|
+
docString: { id: 'cmd-123', status: 'success' },
|
|
577
|
+
},
|
|
578
|
+
],
|
|
556
579
|
},
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
],
|
|
563
|
-
},
|
|
564
|
-
],
|
|
565
|
-
},
|
|
566
|
-
],
|
|
567
|
-
},
|
|
580
|
+
],
|
|
581
|
+
},
|
|
582
|
+
],
|
|
583
|
+
},
|
|
584
|
+
],
|
|
568
585
|
},
|
|
569
586
|
},
|
|
570
587
|
],
|
|
@@ -596,7 +613,8 @@ narrative('Test Flow with IDs', 'FLOW-123', () => {
|
|
|
596
613
|
|
|
597
614
|
const code = await modelToNarrative(modelWithRuleIds);
|
|
598
615
|
|
|
599
|
-
expect(code)
|
|
616
|
+
expect(code)
|
|
617
|
+
.toEqual(`import { command, example, narrative, rule, specs, then, when } from '@auto-engineer/narrative';
|
|
600
618
|
import type { Command, Event } from '@auto-engineer/narrative';
|
|
601
619
|
type ProcessCommand = Command<
|
|
602
620
|
'ProcessCommand',
|
|
@@ -616,9 +634,10 @@ narrative('Test Flow with Rule IDs', 'FLOW-456', () => {
|
|
|
616
634
|
command('process command', 'SLICE-789').server(() => {
|
|
617
635
|
specs('Command Processing', () => {
|
|
618
636
|
rule('Valid commands should be processed', 'RULE-ABC', () => {
|
|
619
|
-
example('User submits valid command')
|
|
620
|
-
|
|
621
|
-
|
|
637
|
+
example('User submits valid command', () => {
|
|
638
|
+
when<ProcessCommand>({ id: 'cmd-123', action: 'create' });
|
|
639
|
+
then<CommandProcessed>({ id: 'cmd-123', status: 'success' });
|
|
640
|
+
});
|
|
622
641
|
});
|
|
623
642
|
});
|
|
624
643
|
});
|
|
@@ -699,11 +718,11 @@ narrative('Questionnaire Flow', 'QUEST-001', () => {});
|
|
|
699
718
|
narratives: [
|
|
700
719
|
{
|
|
701
720
|
name: 'Questionnaires',
|
|
702
|
-
id: '
|
|
721
|
+
id: 'Q9m2Kp4Lx',
|
|
703
722
|
slices: [
|
|
704
723
|
{
|
|
705
724
|
name: 'Homepage',
|
|
706
|
-
id: '
|
|
725
|
+
id: 'H1a4Bn6Cy',
|
|
707
726
|
type: 'experience',
|
|
708
727
|
client: {
|
|
709
728
|
specs: [
|
|
@@ -714,7 +733,7 @@ narrative('Questionnaire Flow', 'QUEST-001', () => {});
|
|
|
714
733
|
},
|
|
715
734
|
{
|
|
716
735
|
name: 'views the questionnaire',
|
|
717
|
-
id: '
|
|
736
|
+
id: 'V7n8Rq5M',
|
|
718
737
|
type: 'query',
|
|
719
738
|
client: {
|
|
720
739
|
specs: [
|
|
@@ -747,59 +766,64 @@ narrative('Questionnaire Flow', 'QUEST-001', () => {});
|
|
|
747
766
|
},
|
|
748
767
|
},
|
|
749
768
|
],
|
|
750
|
-
specs:
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
769
|
+
specs: [
|
|
770
|
+
{
|
|
771
|
+
type: 'gherkin',
|
|
772
|
+
feature: '',
|
|
773
|
+
rules: [
|
|
774
|
+
{
|
|
775
|
+
id: 'r1A3Bp9W',
|
|
776
|
+
name: 'questionnaires show current progress',
|
|
777
|
+
examples: [
|
|
778
|
+
{
|
|
779
|
+
id: 'EX-001',
|
|
780
|
+
name: 'a question has already been answered',
|
|
781
|
+
steps: [
|
|
782
|
+
{
|
|
783
|
+
keyword: 'Given',
|
|
784
|
+
text: 'QuestionnaireLinkSent',
|
|
785
|
+
docString: {
|
|
786
|
+
questionnaireId: 'q-001',
|
|
787
|
+
participantId: 'participant-abc',
|
|
788
|
+
link: 'https://app.example.com/q/q-001?participant=participant-abc',
|
|
789
|
+
sentAt: new Date('2030-01-01T09:00:00.000Z'),
|
|
790
|
+
},
|
|
767
791
|
},
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
eventRef: 'QuestionAnswered',
|
|
779
|
-
},
|
|
780
|
-
then: [
|
|
781
|
-
{
|
|
782
|
-
stateRef: 'QuestionnaireProgress',
|
|
783
|
-
exampleData: {
|
|
784
|
-
questionnaireId: 'q-001',
|
|
785
|
-
participantId: 'participant-abc',
|
|
786
|
-
status: 'in_progress',
|
|
787
|
-
currentQuestionId: 'q2',
|
|
788
|
-
remainingQuestions: ['q2', 'q3'],
|
|
789
|
-
answers: [
|
|
790
|
-
{
|
|
791
|
-
questionId: 'q1',
|
|
792
|
-
value: 'Yes',
|
|
793
|
-
},
|
|
794
|
-
],
|
|
792
|
+
{
|
|
793
|
+
keyword: 'When',
|
|
794
|
+
text: 'QuestionAnswered',
|
|
795
|
+
docString: {
|
|
796
|
+
questionnaireId: 'q-001',
|
|
797
|
+
participantId: 'participant-abc',
|
|
798
|
+
questionId: 'q1',
|
|
799
|
+
answer: 'Yes',
|
|
800
|
+
savedAt: new Date('2030-01-01T09:05:00.000Z'),
|
|
801
|
+
},
|
|
795
802
|
},
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
+
{
|
|
804
|
+
keyword: 'Then',
|
|
805
|
+
text: 'QuestionnaireProgress',
|
|
806
|
+
docString: {
|
|
807
|
+
questionnaireId: 'q-001',
|
|
808
|
+
participantId: 'participant-abc',
|
|
809
|
+
status: 'in_progress',
|
|
810
|
+
currentQuestionId: 'q2',
|
|
811
|
+
remainingQuestions: ['q2', 'q3'],
|
|
812
|
+
answers: [
|
|
813
|
+
{
|
|
814
|
+
questionId: 'q1',
|
|
815
|
+
value: 'Yes',
|
|
816
|
+
},
|
|
817
|
+
],
|
|
818
|
+
},
|
|
819
|
+
},
|
|
820
|
+
],
|
|
821
|
+
},
|
|
822
|
+
],
|
|
823
|
+
},
|
|
824
|
+
],
|
|
825
|
+
},
|
|
826
|
+
],
|
|
803
827
|
},
|
|
804
828
|
},
|
|
805
829
|
],
|
|
@@ -921,6 +945,7 @@ narrative('Questionnaire Flow', 'QUEST-001', () => {});
|
|
|
921
945
|
describe,
|
|
922
946
|
example,
|
|
923
947
|
experience,
|
|
948
|
+
given,
|
|
924
949
|
gql,
|
|
925
950
|
it,
|
|
926
951
|
narrative,
|
|
@@ -928,6 +953,8 @@ narrative('Questionnaire Flow', 'QUEST-001', () => {});
|
|
|
928
953
|
rule,
|
|
929
954
|
source,
|
|
930
955
|
specs,
|
|
956
|
+
then,
|
|
957
|
+
when,
|
|
931
958
|
} from '@auto-engineer/narrative';
|
|
932
959
|
import type { Event, State } from '@auto-engineer/narrative';
|
|
933
960
|
type QuestionnaireLinkSent = Event<
|
|
@@ -963,12 +990,12 @@ type QuestionnaireProgress = State<
|
|
|
963
990
|
}[];
|
|
964
991
|
}
|
|
965
992
|
>;
|
|
966
|
-
narrative('Questionnaires', '
|
|
967
|
-
experience('Homepage', '
|
|
993
|
+
narrative('Questionnaires', 'Q9m2Kp4Lx', () => {
|
|
994
|
+
experience('Homepage', 'H1a4Bn6Cy').client(() => {
|
|
968
995
|
it('show a hero section with a welcome message');
|
|
969
996
|
it('allow user to start the questionnaire');
|
|
970
997
|
});
|
|
971
|
-
query('views the questionnaire', '
|
|
998
|
+
query('views the questionnaire', 'V7n8Rq5M')
|
|
972
999
|
.client(() => {
|
|
973
1000
|
describe('Questionnaire Progress', () => {
|
|
974
1001
|
it('focus on the current question based on the progress state');
|
|
@@ -995,22 +1022,22 @@ narrative('Questionnaires', 'AUTO-Q9m2Kp4Lx', () => {
|
|
|
995
1022
|
.server(() => {
|
|
996
1023
|
data([source().state('QuestionnaireProgress').fromProjection('Questionnaires', 'questionnaire-participantId')]);
|
|
997
1024
|
specs(() => {
|
|
998
|
-
rule('questionnaires show current progress', '
|
|
999
|
-
example('a question has already been answered')
|
|
1000
|
-
|
|
1025
|
+
rule('questionnaires show current progress', 'r1A3Bp9W', () => {
|
|
1026
|
+
example('a question has already been answered', () => {
|
|
1027
|
+
given<QuestionnaireLinkSent>({
|
|
1001
1028
|
questionnaireId: 'q-001',
|
|
1002
1029
|
participantId: 'participant-abc',
|
|
1003
1030
|
link: 'https://app.example.com/q/q-001?participant=participant-abc',
|
|
1004
1031
|
sentAt: new Date('2030-01-01T09:00:00.000Z'),
|
|
1005
|
-
})
|
|
1006
|
-
|
|
1032
|
+
});
|
|
1033
|
+
when<QuestionAnswered>({
|
|
1007
1034
|
questionnaireId: 'q-001',
|
|
1008
1035
|
participantId: 'participant-abc',
|
|
1009
1036
|
questionId: 'q1',
|
|
1010
1037
|
answer: 'Yes',
|
|
1011
1038
|
savedAt: new Date('2030-01-01T09:05:00.000Z'),
|
|
1012
|
-
})
|
|
1013
|
-
|
|
1039
|
+
});
|
|
1040
|
+
then<QuestionnaireProgress>({
|
|
1014
1041
|
questionnaireId: 'q-001',
|
|
1015
1042
|
participantId: 'participant-abc',
|
|
1016
1043
|
status: 'in_progress',
|
|
@@ -1018,6 +1045,7 @@ narrative('Questionnaires', 'AUTO-Q9m2Kp4Lx', () => {
|
|
|
1018
1045
|
remainingQuestions: ['q2', 'q3'],
|
|
1019
1046
|
answers: [{ questionId: 'q1', value: 'Yes' }],
|
|
1020
1047
|
});
|
|
1048
|
+
});
|
|
1021
1049
|
});
|
|
1022
1050
|
});
|
|
1023
1051
|
});
|
|
@@ -1042,71 +1070,78 @@ narrative('Questionnaires', 'AUTO-Q9m2Kp4Lx', () => {
|
|
|
1042
1070
|
},
|
|
1043
1071
|
server: {
|
|
1044
1072
|
description: 'Test server for duplicate rules',
|
|
1045
|
-
specs:
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1073
|
+
specs: [
|
|
1074
|
+
{
|
|
1075
|
+
type: 'gherkin',
|
|
1076
|
+
feature: 'Test Rules',
|
|
1077
|
+
rules: [
|
|
1078
|
+
{
|
|
1079
|
+
id: 'r1A3Bp9W',
|
|
1080
|
+
name: 'questionnaires show current progress',
|
|
1081
|
+
examples: [
|
|
1082
|
+
{
|
|
1083
|
+
id: 'EX-001',
|
|
1084
|
+
name: 'a question has already been answered',
|
|
1085
|
+
steps: [
|
|
1086
|
+
{
|
|
1087
|
+
keyword: 'Given',
|
|
1088
|
+
text: 'QuestionnaireLinkSent',
|
|
1089
|
+
docString: {
|
|
1090
|
+
questionnaireId: 'q-001',
|
|
1091
|
+
participantId: 'participant-abc',
|
|
1092
|
+
},
|
|
1060
1093
|
},
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
},
|
|
1070
|
-
},
|
|
1071
|
-
then: [
|
|
1072
|
-
{
|
|
1073
|
-
stateRef: 'QuestionnaireProgress',
|
|
1074
|
-
exampleData: {
|
|
1075
|
-
questionnaireId: 'q-001',
|
|
1076
|
-
status: 'in_progress',
|
|
1094
|
+
{
|
|
1095
|
+
keyword: 'When',
|
|
1096
|
+
text: 'QuestionAnswered',
|
|
1097
|
+
docString: {
|
|
1098
|
+
questionnaireId: 'q-001',
|
|
1099
|
+
questionId: 'q1',
|
|
1100
|
+
answer: 'Yes',
|
|
1101
|
+
},
|
|
1077
1102
|
},
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
eventRef: 'QuestionnaireLinkSent',
|
|
1086
|
-
exampleData: {
|
|
1087
|
-
questionnaireId: 'q-001',
|
|
1088
|
-
participantId: 'participant-abc',
|
|
1103
|
+
{
|
|
1104
|
+
keyword: 'Then',
|
|
1105
|
+
text: 'QuestionnaireProgress',
|
|
1106
|
+
docString: {
|
|
1107
|
+
questionnaireId: 'q-001',
|
|
1108
|
+
status: 'in_progress',
|
|
1109
|
+
},
|
|
1089
1110
|
},
|
|
1090
|
-
|
|
1091
|
-
],
|
|
1092
|
-
when: {
|
|
1093
|
-
eventRef: 'QuestionnaireLinkSent',
|
|
1094
|
-
exampleData: {},
|
|
1111
|
+
],
|
|
1095
1112
|
},
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1113
|
+
{
|
|
1114
|
+
id: 'EX-002',
|
|
1115
|
+
name: 'no questions have been answered yet',
|
|
1116
|
+
steps: [
|
|
1117
|
+
{
|
|
1118
|
+
keyword: 'Given',
|
|
1119
|
+
text: 'QuestionnaireLinkSent',
|
|
1120
|
+
docString: {
|
|
1121
|
+
questionnaireId: 'q-001',
|
|
1122
|
+
participantId: 'participant-abc',
|
|
1123
|
+
},
|
|
1102
1124
|
},
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1125
|
+
{
|
|
1126
|
+
keyword: 'When',
|
|
1127
|
+
text: 'QuestionnaireLinkSent',
|
|
1128
|
+
docString: {},
|
|
1129
|
+
},
|
|
1130
|
+
{
|
|
1131
|
+
keyword: 'Then',
|
|
1132
|
+
text: 'QuestionnaireProgress',
|
|
1133
|
+
docString: {
|
|
1134
|
+
questionnaireId: 'q-001',
|
|
1135
|
+
status: 'in_progress',
|
|
1136
|
+
},
|
|
1137
|
+
},
|
|
1138
|
+
],
|
|
1139
|
+
},
|
|
1140
|
+
],
|
|
1141
|
+
},
|
|
1142
|
+
],
|
|
1143
|
+
},
|
|
1144
|
+
],
|
|
1110
1145
|
},
|
|
1111
1146
|
},
|
|
1112
1147
|
],
|
|
@@ -1149,7 +1184,8 @@ narrative('Questionnaires', 'AUTO-Q9m2Kp4Lx', () => {
|
|
|
1149
1184
|
|
|
1150
1185
|
const code = await modelToNarrative(modelWithDuplicateRules);
|
|
1151
1186
|
|
|
1152
|
-
expect(code)
|
|
1187
|
+
expect(code)
|
|
1188
|
+
.toEqual(`import { example, given, narrative, query, rule, specs, then, when } from '@auto-engineer/narrative';
|
|
1153
1189
|
import type { Event, State } from '@auto-engineer/narrative';
|
|
1154
1190
|
type QuestionnaireLinkSent = Event<
|
|
1155
1191
|
'QuestionnaireLinkSent',
|
|
@@ -1176,15 +1212,16 @@ type QuestionnaireProgress = State<
|
|
|
1176
1212
|
narrative('Test Flow', 'TEST-FLOW', () => {
|
|
1177
1213
|
query('test slice', 'TEST-SLICE').server(() => {
|
|
1178
1214
|
specs('Test Rules', () => {
|
|
1179
|
-
rule('questionnaires show current progress', '
|
|
1180
|
-
example('a question has already been answered')
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1215
|
+
rule('questionnaires show current progress', 'r1A3Bp9W', () => {
|
|
1216
|
+
example('a question has already been answered', () => {
|
|
1217
|
+
given<QuestionnaireLinkSent>({ questionnaireId: 'q-001', participantId: 'participant-abc' });
|
|
1218
|
+
when<QuestionAnswered>({ questionnaireId: 'q-001', questionId: 'q1', answer: 'Yes' });
|
|
1219
|
+
then<QuestionnaireProgress>({ questionnaireId: 'q-001', status: 'in_progress' });
|
|
1220
|
+
});
|
|
1221
|
+
example('no questions have been answered yet', () => {
|
|
1222
|
+
given<QuestionnaireLinkSent>({ questionnaireId: 'q-001', participantId: 'participant-abc' });
|
|
1223
|
+
then<QuestionnaireProgress>({ questionnaireId: 'q-001', status: 'in_progress' });
|
|
1224
|
+
});
|
|
1188
1225
|
});
|
|
1189
1226
|
});
|
|
1190
1227
|
});
|
|
@@ -1192,7 +1229,7 @@ narrative('Test Flow', 'TEST-FLOW', () => {
|
|
|
1192
1229
|
`);
|
|
1193
1230
|
});
|
|
1194
1231
|
|
|
1195
|
-
it('should chain multiple given examples with
|
|
1232
|
+
it('should chain multiple given examples with and() syntax', async () => {
|
|
1196
1233
|
const modelWithMultiGiven: Model = {
|
|
1197
1234
|
variant: 'specs',
|
|
1198
1235
|
narratives: [
|
|
@@ -1209,84 +1246,92 @@ narrative('Test Flow', 'TEST-FLOW', () => {
|
|
|
1209
1246
|
},
|
|
1210
1247
|
server: {
|
|
1211
1248
|
description: 'Multi given server rules',
|
|
1212
|
-
specs:
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1249
|
+
specs: [
|
|
1250
|
+
{
|
|
1251
|
+
type: 'gherkin',
|
|
1252
|
+
feature: 'Multi Given Rules',
|
|
1253
|
+
rules: [
|
|
1254
|
+
{
|
|
1255
|
+
id: 'MultiGiven',
|
|
1256
|
+
name: 'all questions have been answered',
|
|
1257
|
+
examples: [
|
|
1258
|
+
{
|
|
1259
|
+
id: 'EX-001',
|
|
1260
|
+
name: 'questionnaire with multiple events',
|
|
1261
|
+
steps: [
|
|
1262
|
+
{
|
|
1263
|
+
keyword: 'Given',
|
|
1264
|
+
text: 'QuestionnaireConfig',
|
|
1265
|
+
docString: {
|
|
1266
|
+
questionnaireId: 'q-001',
|
|
1267
|
+
numberOfQuestions: 3,
|
|
1268
|
+
},
|
|
1227
1269
|
},
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1270
|
+
{
|
|
1271
|
+
keyword: 'And',
|
|
1272
|
+
text: 'QuestionnaireLinkSent',
|
|
1273
|
+
docString: {
|
|
1274
|
+
questionnaireId: 'q-001',
|
|
1275
|
+
participantId: 'participant-abc',
|
|
1276
|
+
link: 'https://example.com/q/q-001',
|
|
1277
|
+
sentAt: new Date('2030-01-01T09:00:00.000Z'),
|
|
1278
|
+
},
|
|
1236
1279
|
},
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1280
|
+
{
|
|
1281
|
+
keyword: 'And',
|
|
1282
|
+
text: 'QuestionAnswered',
|
|
1283
|
+
docString: {
|
|
1284
|
+
questionnaireId: 'q-001',
|
|
1285
|
+
participantId: 'participant-abc',
|
|
1286
|
+
questionId: 'q1',
|
|
1287
|
+
answer: 'Yes',
|
|
1288
|
+
savedAt: new Date('2030-01-01T09:05:00.000Z'),
|
|
1289
|
+
},
|
|
1246
1290
|
},
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1291
|
+
{
|
|
1292
|
+
keyword: 'And',
|
|
1293
|
+
text: 'QuestionAnswered',
|
|
1294
|
+
docString: {
|
|
1295
|
+
questionnaireId: 'q-001',
|
|
1296
|
+
participantId: 'participant-abc',
|
|
1297
|
+
questionId: 'q2',
|
|
1298
|
+
answer: 'No',
|
|
1299
|
+
savedAt: new Date('2030-01-01T09:10:00.000Z'),
|
|
1300
|
+
},
|
|
1256
1301
|
},
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
},
|
|
1268
|
-
},
|
|
1269
|
-
then: [
|
|
1270
|
-
{
|
|
1271
|
-
stateRef: 'QuestionnaireProgress',
|
|
1272
|
-
exampleData: {
|
|
1273
|
-
questionnaireId: 'q-001',
|
|
1274
|
-
participantId: 'participant-abc',
|
|
1275
|
-
status: 'ready_to_submit',
|
|
1276
|
-
currentQuestionId: null,
|
|
1277
|
-
remainingQuestions: [],
|
|
1278
|
-
answers: [
|
|
1279
|
-
{ questionId: 'q1', value: 'Yes' },
|
|
1280
|
-
{ questionId: 'q2', value: 'No' },
|
|
1281
|
-
],
|
|
1302
|
+
{
|
|
1303
|
+
keyword: 'When',
|
|
1304
|
+
text: 'QuestionAnswered',
|
|
1305
|
+
docString: {
|
|
1306
|
+
questionnaireId: 'q-001',
|
|
1307
|
+
participantId: 'participant-abc',
|
|
1308
|
+
questionId: 'q3',
|
|
1309
|
+
answer: 'Maybe',
|
|
1310
|
+
savedAt: new Date('2030-01-01T09:15:00.000Z'),
|
|
1311
|
+
},
|
|
1282
1312
|
},
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1313
|
+
{
|
|
1314
|
+
keyword: 'Then',
|
|
1315
|
+
text: 'QuestionnaireProgress',
|
|
1316
|
+
docString: {
|
|
1317
|
+
questionnaireId: 'q-001',
|
|
1318
|
+
participantId: 'participant-abc',
|
|
1319
|
+
status: 'ready_to_submit',
|
|
1320
|
+
currentQuestionId: null,
|
|
1321
|
+
remainingQuestions: [],
|
|
1322
|
+
answers: [
|
|
1323
|
+
{ questionId: 'q1', value: 'Yes' },
|
|
1324
|
+
{ questionId: 'q2', value: 'No' },
|
|
1325
|
+
],
|
|
1326
|
+
},
|
|
1327
|
+
},
|
|
1328
|
+
],
|
|
1329
|
+
},
|
|
1330
|
+
],
|
|
1331
|
+
},
|
|
1332
|
+
],
|
|
1333
|
+
},
|
|
1334
|
+
],
|
|
1290
1335
|
},
|
|
1291
1336
|
},
|
|
1292
1337
|
],
|
|
@@ -1346,7 +1391,8 @@ narrative('Test Flow', 'TEST-FLOW', () => {
|
|
|
1346
1391
|
|
|
1347
1392
|
const code = await modelToNarrative(modelWithMultiGiven);
|
|
1348
1393
|
|
|
1349
|
-
expect(code)
|
|
1394
|
+
expect(code)
|
|
1395
|
+
.toEqual(`import { and, example, given, narrative, query, rule, specs, then, when } from '@auto-engineer/narrative';
|
|
1350
1396
|
import type { Event, State } from '@auto-engineer/narrative';
|
|
1351
1397
|
type QuestionnaireConfig = State<
|
|
1352
1398
|
'QuestionnaireConfig',
|
|
@@ -1391,37 +1437,37 @@ type QuestionnaireProgress = State<
|
|
|
1391
1437
|
narrative('Multi Given Flow', 'MULTI-GIVEN', () => {
|
|
1392
1438
|
query('multi given slice', 'MULTI-SLICE').server(() => {
|
|
1393
1439
|
specs('Multi Given Rules', () => {
|
|
1394
|
-
rule('all questions have been answered', '
|
|
1395
|
-
example('questionnaire with multiple events')
|
|
1396
|
-
|
|
1397
|
-
|
|
1440
|
+
rule('all questions have been answered', 'MultiGiven', () => {
|
|
1441
|
+
example('questionnaire with multiple events', () => {
|
|
1442
|
+
given<QuestionnaireConfig>({ questionnaireId: 'q-001', numberOfQuestions: 3 });
|
|
1443
|
+
and<QuestionnaireLinkSent>({
|
|
1398
1444
|
questionnaireId: 'q-001',
|
|
1399
1445
|
participantId: 'participant-abc',
|
|
1400
1446
|
link: 'https://example.com/q/q-001',
|
|
1401
1447
|
sentAt: new Date('2030-01-01T09:00:00.000Z'),
|
|
1402
|
-
})
|
|
1403
|
-
|
|
1448
|
+
});
|
|
1449
|
+
and<QuestionAnswered>({
|
|
1404
1450
|
questionnaireId: 'q-001',
|
|
1405
1451
|
participantId: 'participant-abc',
|
|
1406
1452
|
questionId: 'q1',
|
|
1407
1453
|
answer: 'Yes',
|
|
1408
1454
|
savedAt: new Date('2030-01-01T09:05:00.000Z'),
|
|
1409
|
-
})
|
|
1410
|
-
|
|
1455
|
+
});
|
|
1456
|
+
and<QuestionAnswered>({
|
|
1411
1457
|
questionnaireId: 'q-001',
|
|
1412
1458
|
participantId: 'participant-abc',
|
|
1413
1459
|
questionId: 'q2',
|
|
1414
1460
|
answer: 'No',
|
|
1415
1461
|
savedAt: new Date('2030-01-01T09:10:00.000Z'),
|
|
1416
|
-
})
|
|
1417
|
-
|
|
1462
|
+
});
|
|
1463
|
+
when<QuestionAnswered>({
|
|
1418
1464
|
questionnaireId: 'q-001',
|
|
1419
1465
|
participantId: 'participant-abc',
|
|
1420
1466
|
questionId: 'q3',
|
|
1421
1467
|
answer: 'Maybe',
|
|
1422
1468
|
savedAt: new Date('2030-01-01T09:15:00.000Z'),
|
|
1423
|
-
})
|
|
1424
|
-
|
|
1469
|
+
});
|
|
1470
|
+
then<QuestionnaireProgress>({
|
|
1425
1471
|
questionnaireId: 'q-001',
|
|
1426
1472
|
participantId: 'participant-abc',
|
|
1427
1473
|
status: 'ready_to_submit',
|
|
@@ -1432,6 +1478,7 @@ narrative('Multi Given Flow', 'MULTI-GIVEN', () => {
|
|
|
1432
1478
|
{ questionId: 'q2', value: 'No' },
|
|
1433
1479
|
],
|
|
1434
1480
|
});
|
|
1481
|
+
});
|
|
1435
1482
|
});
|
|
1436
1483
|
});
|
|
1437
1484
|
});
|
|
@@ -1480,45 +1527,50 @@ narrative('Multi Given Flow', 'MULTI-GIVEN', () => {
|
|
|
1480
1527
|
},
|
|
1481
1528
|
},
|
|
1482
1529
|
],
|
|
1483
|
-
specs:
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1530
|
+
specs: [
|
|
1531
|
+
{
|
|
1532
|
+
type: 'gherkin',
|
|
1533
|
+
feature: 'Database State Rules',
|
|
1534
|
+
rules: [
|
|
1535
|
+
{
|
|
1536
|
+
id: 'RefState',
|
|
1537
|
+
name: 'questionnaire config is available when referenced',
|
|
1538
|
+
examples: [
|
|
1539
|
+
{
|
|
1540
|
+
id: 'EX-001',
|
|
1541
|
+
name: 'config from database is accessible',
|
|
1542
|
+
steps: [
|
|
1543
|
+
{
|
|
1544
|
+
keyword: 'Given',
|
|
1545
|
+
text: 'QuestionnaireConfig',
|
|
1546
|
+
docString: {
|
|
1547
|
+
questionnaireId: 'q-001',
|
|
1548
|
+
numberOfQuestions: 5,
|
|
1549
|
+
title: 'Customer Satisfaction Survey',
|
|
1550
|
+
},
|
|
1499
1551
|
},
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
exampleData: {},
|
|
1505
|
-
},
|
|
1506
|
-
then: [
|
|
1507
|
-
{
|
|
1508
|
-
stateRef: 'QuestionnaireProgress',
|
|
1509
|
-
exampleData: {
|
|
1510
|
-
questionnaireId: 'q-001',
|
|
1511
|
-
participantId: 'participant-abc',
|
|
1512
|
-
status: 'in_progress',
|
|
1513
|
-
totalQuestions: 5,
|
|
1552
|
+
{
|
|
1553
|
+
keyword: 'When',
|
|
1554
|
+
text: 'QuestionnaireProgress',
|
|
1555
|
+
docString: {},
|
|
1514
1556
|
},
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1557
|
+
{
|
|
1558
|
+
keyword: 'Then',
|
|
1559
|
+
text: 'QuestionnaireProgress',
|
|
1560
|
+
docString: {
|
|
1561
|
+
questionnaireId: 'q-001',
|
|
1562
|
+
participantId: 'participant-abc',
|
|
1563
|
+
status: 'in_progress',
|
|
1564
|
+
totalQuestions: 5,
|
|
1565
|
+
},
|
|
1566
|
+
},
|
|
1567
|
+
],
|
|
1568
|
+
},
|
|
1569
|
+
],
|
|
1570
|
+
},
|
|
1571
|
+
],
|
|
1572
|
+
},
|
|
1573
|
+
],
|
|
1522
1574
|
},
|
|
1523
1575
|
},
|
|
1524
1576
|
],
|
|
@@ -1553,7 +1605,7 @@ narrative('Multi Given Flow', 'MULTI-GIVEN', () => {
|
|
|
1553
1605
|
const code = await modelToNarrative(modelWithReferencedStates);
|
|
1554
1606
|
|
|
1555
1607
|
expect(code)
|
|
1556
|
-
.toEqual(`import { data, example, narrative, query, rule, source, specs } from '@auto-engineer/narrative';
|
|
1608
|
+
.toEqual(`import { data, example, given, narrative, query, rule, source, specs, then } from '@auto-engineer/narrative';
|
|
1557
1609
|
import type { State } from '@auto-engineer/narrative';
|
|
1558
1610
|
type QuestionnaireProgress = State<
|
|
1559
1611
|
'QuestionnaireProgress',
|
|
@@ -1579,20 +1631,20 @@ narrative('Referenced States Flow', 'REF-STATES', () => {
|
|
|
1579
1631
|
source().state('QuestionnaireConfig').fromDatabase('ConfigStore', { questionnaireId: '$questionnaireId' }),
|
|
1580
1632
|
]);
|
|
1581
1633
|
specs('Database State Rules', () => {
|
|
1582
|
-
rule('questionnaire config is available when referenced', '
|
|
1583
|
-
example('config from database is accessible')
|
|
1584
|
-
|
|
1634
|
+
rule('questionnaire config is available when referenced', 'RefState', () => {
|
|
1635
|
+
example('config from database is accessible', () => {
|
|
1636
|
+
given<QuestionnaireConfig>({
|
|
1585
1637
|
questionnaireId: 'q-001',
|
|
1586
1638
|
numberOfQuestions: 5,
|
|
1587
1639
|
title: 'Customer Satisfaction Survey',
|
|
1588
|
-
})
|
|
1589
|
-
|
|
1590
|
-
.then<QuestionnaireProgress>({
|
|
1640
|
+
});
|
|
1641
|
+
then<QuestionnaireProgress>({
|
|
1591
1642
|
questionnaireId: 'q-001',
|
|
1592
1643
|
participantId: 'participant-abc',
|
|
1593
1644
|
status: 'in_progress',
|
|
1594
1645
|
totalQuestions: 5,
|
|
1595
1646
|
});
|
|
1647
|
+
});
|
|
1596
1648
|
});
|
|
1597
1649
|
});
|
|
1598
1650
|
});
|
|
@@ -1617,48 +1669,53 @@ narrative('Referenced States Flow', 'REF-STATES', () => {
|
|
|
1617
1669
|
},
|
|
1618
1670
|
server: {
|
|
1619
1671
|
description: 'Date server with Date fields',
|
|
1620
|
-
specs:
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1672
|
+
specs: [
|
|
1673
|
+
{
|
|
1674
|
+
type: 'gherkin',
|
|
1675
|
+
feature: 'Date Field Rules',
|
|
1676
|
+
rules: [
|
|
1677
|
+
{
|
|
1678
|
+
id: 'DateRule',
|
|
1679
|
+
name: 'handles Date fields correctly',
|
|
1680
|
+
examples: [
|
|
1681
|
+
{
|
|
1682
|
+
id: 'EX-001',
|
|
1683
|
+
name: 'event with Date fields',
|
|
1684
|
+
steps: [
|
|
1685
|
+
{
|
|
1686
|
+
keyword: 'Given',
|
|
1687
|
+
text: 'TimestampedEvent',
|
|
1688
|
+
docString: {
|
|
1689
|
+
id: 'event-123',
|
|
1690
|
+
sentAt: new Date('2030-01-01T09:00:00.000Z'),
|
|
1691
|
+
savedAt: new Date('2030-01-01T09:05:00.000Z'),
|
|
1692
|
+
attemptedAt: '2030-01-01T09:10:00.000Z',
|
|
1693
|
+
submittedAt: '2030-01-01T09:15:00.000Z',
|
|
1694
|
+
},
|
|
1638
1695
|
},
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
},
|
|
1646
|
-
},
|
|
1647
|
-
then: [
|
|
1648
|
-
{
|
|
1649
|
-
stateRef: 'ProcessState',
|
|
1650
|
-
exampleData: {
|
|
1651
|
-
id: 'state-123',
|
|
1652
|
-
completedAt: '2030-01-01T11:00:00.000Z',
|
|
1653
|
-
status: 'completed',
|
|
1696
|
+
{
|
|
1697
|
+
keyword: 'When',
|
|
1698
|
+
text: 'ProcessEvent',
|
|
1699
|
+
docString: {
|
|
1700
|
+
processedAt: '2030-01-01T10:00:00.000Z',
|
|
1701
|
+
},
|
|
1654
1702
|
},
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1703
|
+
{
|
|
1704
|
+
keyword: 'Then',
|
|
1705
|
+
text: 'ProcessState',
|
|
1706
|
+
docString: {
|
|
1707
|
+
id: 'state-123',
|
|
1708
|
+
completedAt: '2030-01-01T11:00:00.000Z',
|
|
1709
|
+
status: 'completed',
|
|
1710
|
+
},
|
|
1711
|
+
},
|
|
1712
|
+
],
|
|
1713
|
+
},
|
|
1714
|
+
],
|
|
1715
|
+
},
|
|
1716
|
+
],
|
|
1717
|
+
},
|
|
1718
|
+
],
|
|
1662
1719
|
},
|
|
1663
1720
|
},
|
|
1664
1721
|
],
|
|
@@ -1701,7 +1758,8 @@ narrative('Referenced States Flow', 'REF-STATES', () => {
|
|
|
1701
1758
|
|
|
1702
1759
|
const code = await modelToNarrative(modelWithDateFields);
|
|
1703
1760
|
|
|
1704
|
-
expect(code)
|
|
1761
|
+
expect(code)
|
|
1762
|
+
.toEqual(`import { example, given, narrative, query, rule, specs, then, when } from '@auto-engineer/narrative';
|
|
1705
1763
|
import type { Event, State } from '@auto-engineer/narrative';
|
|
1706
1764
|
type TimestampedEvent = Event<
|
|
1707
1765
|
'TimestampedEvent',
|
|
@@ -1730,21 +1788,22 @@ type ProcessState = State<
|
|
|
1730
1788
|
narrative('Date Handling Flow', 'DATE-FLOW', () => {
|
|
1731
1789
|
query('date handling slice', 'DATE-SLICE').server(() => {
|
|
1732
1790
|
specs('Date Field Rules', () => {
|
|
1733
|
-
rule('handles Date fields correctly', '
|
|
1734
|
-
example('event with Date fields')
|
|
1735
|
-
|
|
1791
|
+
rule('handles Date fields correctly', 'DateRule', () => {
|
|
1792
|
+
example('event with Date fields', () => {
|
|
1793
|
+
given<TimestampedEvent>({
|
|
1736
1794
|
id: 'event-123',
|
|
1737
1795
|
sentAt: new Date('2030-01-01T09:00:00.000Z'),
|
|
1738
1796
|
savedAt: new Date('2030-01-01T09:05:00.000Z'),
|
|
1739
1797
|
attemptedAt: new Date('2030-01-01T09:10:00.000Z'),
|
|
1740
1798
|
submittedAt: new Date('2030-01-01T09:15:00.000Z'),
|
|
1741
|
-
})
|
|
1742
|
-
|
|
1743
|
-
|
|
1799
|
+
});
|
|
1800
|
+
when<ProcessEvent>({ processedAt: new Date('2030-01-01T10:00:00.000Z') });
|
|
1801
|
+
then<ProcessState>({
|
|
1744
1802
|
id: 'state-123',
|
|
1745
1803
|
completedAt: new Date('2030-01-01T11:00:00.000Z'),
|
|
1746
1804
|
status: 'completed',
|
|
1747
1805
|
});
|
|
1806
|
+
});
|
|
1748
1807
|
});
|
|
1749
1808
|
});
|
|
1750
1809
|
});
|
|
@@ -1762,7 +1821,7 @@ narrative('Date Handling Flow', 'DATE-FLOW', () => {
|
|
|
1762
1821
|
slices: [
|
|
1763
1822
|
{
|
|
1764
1823
|
name: 'Active Surveys Summary',
|
|
1765
|
-
id: '
|
|
1824
|
+
id: 'aifPcU3hw',
|
|
1766
1825
|
type: 'experience',
|
|
1767
1826
|
client: {
|
|
1768
1827
|
specs: [{ type: 'it', title: 'show active surveys summary' }],
|
|
@@ -1776,7 +1835,7 @@ narrative('Date Handling Flow', 'DATE-FLOW', () => {
|
|
|
1776
1835
|
slices: [
|
|
1777
1836
|
{
|
|
1778
1837
|
name: 'Create Survey Form',
|
|
1779
|
-
id: '
|
|
1838
|
+
id: 'MPviTMrQC',
|
|
1780
1839
|
type: 'experience',
|
|
1781
1840
|
client: {
|
|
1782
1841
|
specs: [{ type: 'it', title: 'allow entering survey title' }],
|
|
@@ -1790,7 +1849,7 @@ narrative('Date Handling Flow', 'DATE-FLOW', () => {
|
|
|
1790
1849
|
slices: [
|
|
1791
1850
|
{
|
|
1792
1851
|
name: 'Response Rate Charts',
|
|
1793
|
-
id: '
|
|
1852
|
+
id: 'eME978Euk',
|
|
1794
1853
|
type: 'experience',
|
|
1795
1854
|
client: {
|
|
1796
1855
|
specs: [{ type: 'it', title: 'show daily response rate charts' }],
|
|
@@ -1807,17 +1866,17 @@ narrative('Date Handling Flow', 'DATE-FLOW', () => {
|
|
|
1807
1866
|
|
|
1808
1867
|
expect(code).toEqual(`import { experience, it, narrative } from '@auto-engineer/narrative';
|
|
1809
1868
|
narrative('Home Screen', () => {
|
|
1810
|
-
experience('Active Surveys Summary', '
|
|
1869
|
+
experience('Active Surveys Summary', 'aifPcU3hw').client(() => {
|
|
1811
1870
|
it('show active surveys summary');
|
|
1812
1871
|
});
|
|
1813
1872
|
});
|
|
1814
1873
|
narrative('Create Survey', () => {
|
|
1815
|
-
experience('Create Survey Form', '
|
|
1874
|
+
experience('Create Survey Form', 'MPviTMrQC').client(() => {
|
|
1816
1875
|
it('allow entering survey title');
|
|
1817
1876
|
});
|
|
1818
1877
|
});
|
|
1819
1878
|
narrative('Response Analytics', () => {
|
|
1820
|
-
experience('Response Rate Charts', '
|
|
1879
|
+
experience('Response Rate Charts', 'eME978Euk').client(() => {
|
|
1821
1880
|
it('show daily response rate charts');
|
|
1822
1881
|
});
|
|
1823
1882
|
});
|
|
@@ -1841,71 +1900,74 @@ narrative('Response Analytics', () => {
|
|
|
1841
1900
|
},
|
|
1842
1901
|
server: {
|
|
1843
1902
|
description: 'Summary calculation server',
|
|
1844
|
-
specs:
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1903
|
+
specs: [
|
|
1904
|
+
{
|
|
1905
|
+
type: 'gherkin',
|
|
1906
|
+
feature: 'Summary Statistics',
|
|
1907
|
+
rules: [
|
|
1908
|
+
{
|
|
1909
|
+
id: 'RULE-SUMMARY',
|
|
1910
|
+
name: 'summary shows overall todo list statistics',
|
|
1911
|
+
examples: [
|
|
1912
|
+
{
|
|
1913
|
+
id: 'EX-001',
|
|
1914
|
+
name: 'calculates summary from multiple todos',
|
|
1915
|
+
steps: [
|
|
1916
|
+
{
|
|
1917
|
+
keyword: 'Given',
|
|
1918
|
+
text: 'TodoAdded',
|
|
1919
|
+
docString: {
|
|
1920
|
+
todoId: 'todo-001',
|
|
1921
|
+
description: 'Buy groceries',
|
|
1922
|
+
status: 'pending',
|
|
1923
|
+
addedAt: new Date('2030-01-01T09:00:00.000Z'),
|
|
1924
|
+
},
|
|
1861
1925
|
},
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1926
|
+
{
|
|
1927
|
+
keyword: 'And',
|
|
1928
|
+
text: 'TodoAdded',
|
|
1929
|
+
docString: {
|
|
1930
|
+
todoId: 'todo-002',
|
|
1931
|
+
description: 'Write report',
|
|
1932
|
+
status: 'pending',
|
|
1933
|
+
addedAt: new Date('2030-01-01T09:10:00.000Z'),
|
|
1934
|
+
},
|
|
1870
1935
|
},
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1936
|
+
{
|
|
1937
|
+
keyword: 'And',
|
|
1938
|
+
text: 'TodoMarkedInProgress',
|
|
1939
|
+
docString: {
|
|
1940
|
+
todoId: 'todo-001',
|
|
1941
|
+
markedAt: new Date('2030-01-01T10:00:00.000Z'),
|
|
1942
|
+
},
|
|
1877
1943
|
},
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1944
|
+
{
|
|
1945
|
+
keyword: 'And',
|
|
1946
|
+
text: 'TodoMarkedComplete',
|
|
1947
|
+
docString: {
|
|
1948
|
+
todoId: 'todo-002',
|
|
1949
|
+
completedAt: new Date('2030-01-01T11:00:00.000Z'),
|
|
1950
|
+
},
|
|
1884
1951
|
},
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
totalTodos: 2,
|
|
1897
|
-
pendingCount: 0,
|
|
1898
|
-
inProgressCount: 1,
|
|
1899
|
-
completedCount: 1,
|
|
1900
|
-
completionPercentage: 50,
|
|
1952
|
+
{
|
|
1953
|
+
keyword: 'Then',
|
|
1954
|
+
text: 'TodoListSummary',
|
|
1955
|
+
docString: {
|
|
1956
|
+
summaryId: 'main-summary',
|
|
1957
|
+
totalTodos: 2,
|
|
1958
|
+
pendingCount: 0,
|
|
1959
|
+
inProgressCount: 1,
|
|
1960
|
+
completedCount: 1,
|
|
1961
|
+
completionPercentage: 50,
|
|
1962
|
+
},
|
|
1901
1963
|
},
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1964
|
+
],
|
|
1965
|
+
},
|
|
1966
|
+
],
|
|
1967
|
+
},
|
|
1968
|
+
],
|
|
1969
|
+
},
|
|
1970
|
+
],
|
|
1909
1971
|
},
|
|
1910
1972
|
},
|
|
1911
1973
|
],
|
|
@@ -1963,7 +2025,8 @@ narrative('Response Analytics', () => {
|
|
|
1963
2025
|
|
|
1964
2026
|
const code = await modelToNarrative(modelWithEmptyWhen);
|
|
1965
2027
|
|
|
1966
|
-
expect(code)
|
|
2028
|
+
expect(code)
|
|
2029
|
+
.toEqual(`import { and, example, given, narrative, query, rule, specs, then } from '@auto-engineer/narrative';
|
|
1967
2030
|
import type { Event, State } from '@auto-engineer/narrative';
|
|
1968
2031
|
type TodoAdded = Event<
|
|
1969
2032
|
'TodoAdded',
|
|
@@ -2003,22 +2066,22 @@ narrative('Todo List Summary', 'TODO-001', () => {
|
|
|
2003
2066
|
query('views completion summary', 'SUMMARY-001').server(() => {
|
|
2004
2067
|
specs('Summary Statistics', () => {
|
|
2005
2068
|
rule('summary shows overall todo list statistics', 'RULE-SUMMARY', () => {
|
|
2006
|
-
example('calculates summary from multiple todos')
|
|
2007
|
-
|
|
2069
|
+
example('calculates summary from multiple todos', () => {
|
|
2070
|
+
given<TodoAdded>({
|
|
2008
2071
|
todoId: 'todo-001',
|
|
2009
2072
|
description: 'Buy groceries',
|
|
2010
2073
|
status: 'pending',
|
|
2011
2074
|
addedAt: new Date('2030-01-01T09:00:00.000Z'),
|
|
2012
|
-
})
|
|
2013
|
-
|
|
2075
|
+
});
|
|
2076
|
+
and<TodoAdded>({
|
|
2014
2077
|
todoId: 'todo-002',
|
|
2015
2078
|
description: 'Write report',
|
|
2016
2079
|
status: 'pending',
|
|
2017
2080
|
addedAt: new Date('2030-01-01T09:10:00.000Z'),
|
|
2018
|
-
})
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2081
|
+
});
|
|
2082
|
+
and<TodoMarkedInProgress>({ todoId: 'todo-001', markedAt: new Date('2030-01-01T10:00:00.000Z') });
|
|
2083
|
+
and<TodoMarkedComplete>({ todoId: 'todo-002', completedAt: new Date('2030-01-01T11:00:00.000Z') });
|
|
2084
|
+
then<TodoListSummary>({
|
|
2022
2085
|
summaryId: 'main-summary',
|
|
2023
2086
|
totalTodos: 2,
|
|
2024
2087
|
pendingCount: 0,
|
|
@@ -2026,14 +2089,15 @@ narrative('Todo List Summary', 'TODO-001', () => {
|
|
|
2026
2089
|
completedCount: 1,
|
|
2027
2090
|
completionPercentage: 50,
|
|
2028
2091
|
});
|
|
2092
|
+
});
|
|
2029
2093
|
});
|
|
2030
2094
|
});
|
|
2031
2095
|
});
|
|
2032
2096
|
});
|
|
2033
2097
|
`);
|
|
2034
2098
|
|
|
2035
|
-
expect(code).not.toContain('
|
|
2036
|
-
expect(code).not.toContain('
|
|
2099
|
+
expect(code).not.toContain('when({})');
|
|
2100
|
+
expect(code).not.toContain('when<');
|
|
2037
2101
|
});
|
|
2038
2102
|
|
|
2039
2103
|
describe('projection DSL generation', () => {
|
|
@@ -2067,10 +2131,13 @@ narrative('Todo List Summary', 'TODO-001', () => {
|
|
|
2067
2131
|
},
|
|
2068
2132
|
},
|
|
2069
2133
|
],
|
|
2070
|
-
specs:
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2134
|
+
specs: [
|
|
2135
|
+
{
|
|
2136
|
+
type: 'gherkin',
|
|
2137
|
+
feature: 'Summary Rules',
|
|
2138
|
+
rules: [],
|
|
2139
|
+
},
|
|
2140
|
+
],
|
|
2074
2141
|
},
|
|
2075
2142
|
},
|
|
2076
2143
|
],
|
|
@@ -2140,10 +2207,13 @@ narrative('Todo Summary Flow', 'TODO-SUMMARY', () => {
|
|
|
2140
2207
|
},
|
|
2141
2208
|
},
|
|
2142
2209
|
],
|
|
2143
|
-
specs:
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2210
|
+
specs: [
|
|
2211
|
+
{
|
|
2212
|
+
type: 'gherkin',
|
|
2213
|
+
feature: 'Todo Rules',
|
|
2214
|
+
rules: [],
|
|
2215
|
+
},
|
|
2216
|
+
],
|
|
2147
2217
|
},
|
|
2148
2218
|
},
|
|
2149
2219
|
],
|
|
@@ -2213,10 +2283,13 @@ narrative('Todo Flow', 'TODO-FLOW', () => {
|
|
|
2213
2283
|
},
|
|
2214
2284
|
},
|
|
2215
2285
|
],
|
|
2216
|
-
specs:
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2286
|
+
specs: [
|
|
2287
|
+
{
|
|
2288
|
+
type: 'gherkin',
|
|
2289
|
+
feature: 'User Project Rules',
|
|
2290
|
+
rules: [],
|
|
2291
|
+
},
|
|
2292
|
+
],
|
|
2220
2293
|
},
|
|
2221
2294
|
},
|
|
2222
2295
|
],
|
|
@@ -2288,10 +2361,13 @@ narrative('User Project Flow', 'USER-PROJECT-FLOW', () => {
|
|
|
2288
2361
|
},
|
|
2289
2362
|
},
|
|
2290
2363
|
],
|
|
2291
|
-
specs:
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2364
|
+
specs: [
|
|
2365
|
+
{
|
|
2366
|
+
type: 'gherkin',
|
|
2367
|
+
feature: 'Summary Rules',
|
|
2368
|
+
rules: [],
|
|
2369
|
+
},
|
|
2370
|
+
],
|
|
2295
2371
|
},
|
|
2296
2372
|
},
|
|
2297
2373
|
{
|
|
@@ -2316,10 +2392,13 @@ narrative('User Project Flow', 'USER-PROJECT-FLOW', () => {
|
|
|
2316
2392
|
},
|
|
2317
2393
|
},
|
|
2318
2394
|
],
|
|
2319
|
-
specs:
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2395
|
+
specs: [
|
|
2396
|
+
{
|
|
2397
|
+
type: 'gherkin',
|
|
2398
|
+
feature: 'Todo Rules',
|
|
2399
|
+
rules: [],
|
|
2400
|
+
},
|
|
2401
|
+
],
|
|
2323
2402
|
},
|
|
2324
2403
|
},
|
|
2325
2404
|
{
|
|
@@ -2344,10 +2423,13 @@ narrative('User Project Flow', 'USER-PROJECT-FLOW', () => {
|
|
|
2344
2423
|
},
|
|
2345
2424
|
},
|
|
2346
2425
|
],
|
|
2347
|
-
specs:
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2426
|
+
specs: [
|
|
2427
|
+
{
|
|
2428
|
+
type: 'gherkin',
|
|
2429
|
+
feature: 'User Project Rules',
|
|
2430
|
+
rules: [],
|
|
2431
|
+
},
|
|
2432
|
+
],
|
|
2351
2433
|
},
|
|
2352
2434
|
},
|
|
2353
2435
|
],
|