@auto-engineer/narrative 0.20.0 → 0.21.0

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.
Files changed (31) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/.turbo/turbo-format.log +1 -1
  3. package/.turbo/turbo-lint.log +1 -1
  4. package/.turbo/turbo-test.log +6 -6
  5. package/.turbo/turbo-type-check.log +5 -4
  6. package/CHANGELOG.md +13 -0
  7. package/dist/src/commands/export-schema-runner.js +6 -1
  8. package/dist/src/commands/export-schema-runner.js.map +1 -1
  9. package/dist/src/fluent-builder.specs.js +2 -2
  10. package/dist/src/fluent-builder.specs.js.map +1 -1
  11. package/dist/src/getNarratives.cache.specs.js +5 -5
  12. package/dist/src/getNarratives.cache.specs.js.map +1 -1
  13. package/dist/src/getNarratives.specs.js +194 -207
  14. package/dist/src/getNarratives.specs.js.map +1 -1
  15. package/dist/src/id/addAutoIds.specs.js +72 -409
  16. package/dist/src/id/addAutoIds.specs.js.map +1 -1
  17. package/dist/src/id/hasAllIds.specs.js +215 -408
  18. package/dist/src/id/hasAllIds.specs.js.map +1 -1
  19. package/dist/src/model-to-narrative.specs.js +505 -564
  20. package/dist/src/model-to-narrative.specs.js.map +1 -1
  21. package/dist/src/narrative-context.specs.js +58 -133
  22. package/dist/src/narrative-context.specs.js.map +1 -1
  23. package/dist/src/schema.d.ts +302 -302
  24. package/dist/src/transformers/narrative-to-model/type-inference.specs.js +94 -104
  25. package/dist/src/transformers/narrative-to-model/type-inference.specs.js.map +1 -1
  26. package/dist/tsconfig.tsbuildinfo +1 -1
  27. package/package.json +4 -4
  28. package/dist/src/transformers/model-to-narrative/generators/gwt.specs.d.ts +0 -2
  29. package/dist/src/transformers/model-to-narrative/generators/gwt.specs.d.ts.map +0 -1
  30. package/dist/src/transformers/model-to-narrative/generators/gwt.specs.js +0 -142
  31. package/dist/src/transformers/model-to-narrative/generators/gwt.specs.js.map +0 -1
@@ -1,4 +1,4 @@
1
- import { describe, expect, it } from 'vitest';
1
+ import { describe, it, expect } from 'vitest';
2
2
  import schema from './samples/seasonal-assistant.schema.json.js';
3
3
  import { modelToNarrative } from './transformers/model-to-narrative/index.js';
4
4
  describe('modelToNarrative', () => {
@@ -7,14 +7,13 @@ describe('modelToNarrative', () => {
7
7
  expect(code).toEqual(`import {
8
8
  command,
9
9
  data,
10
- describe,
11
10
  example,
12
11
  gql,
13
- it,
14
12
  narrative,
15
13
  query,
16
14
  react,
17
15
  rule,
16
+ should,
18
17
  sink,
19
18
  source,
20
19
  specs,
@@ -90,13 +89,13 @@ type ItemsAddedToCart = Event<
90
89
  narrative('Seasonal Assistant', () => {
91
90
  command('enters shopping criteria into assistant')
92
91
  .client(() => {
93
- describe('Assistant Chat Interface', () => {
94
- it('allow shopper to describe their shopping needs in natural language');
95
- it('provide a text input for entering criteria');
96
- it('show examples of what to include (age, interests, budget)');
97
- it('show a button to submit the criteria');
98
- it('generate a persisted session id for a visit');
99
- it('show the header on top of the page');
92
+ specs('Assistant Chat Interface', () => {
93
+ should('allow shopper to describe their shopping needs in natural language');
94
+ should('provide a text input for entering criteria');
95
+ should('show examples of what to include (age, interests, budget)');
96
+ should('show a button to submit the criteria');
97
+ should('generate a persisted session id for a visit');
98
+ should('show the header on top of the page');
100
99
  });
101
100
  })
102
101
  .request(
@@ -234,11 +233,11 @@ narrative('Seasonal Assistant', () => {
234
233
  });
235
234
  query('views suggested items')
236
235
  .client(() => {
237
- describe('Suggested Items Screen', () => {
238
- it('display all suggested items with names and reasons');
239
- it('show quantity selectors for each item');
240
- it('have an "Add to Cart" button for selected items');
241
- it('allow removing items from the suggestions');
236
+ specs('Suggested Items Screen', () => {
237
+ should('display all suggested items with names and reasons');
238
+ should('show quantity selectors for each item');
239
+ should('have an "Add to Cart" button for selected items');
240
+ should('allow removing items from the suggestions');
242
241
  });
243
242
  })
244
243
  .request(
@@ -321,10 +320,10 @@ narrative('Seasonal Assistant', () => {
321
320
  });
322
321
  command('accepts items and adds to their cart')
323
322
  .client(() => {
324
- describe('Suggested Items Screen', () => {
325
- it('allow selecting specific items to add');
326
- it('update quantities before adding to cart');
327
- it('provide feedback when items are added');
323
+ specs('Suggested Items Screen', () => {
324
+ should('allow selecting specific items to add');
325
+ should('update quantities before adding to cart');
326
+ should('provide feedback when items are added');
328
327
  });
329
328
  })
330
329
  .server(() => {
@@ -369,10 +368,10 @@ narrative('Seasonal Assistant', () => {
369
368
  id: 'EXP-001',
370
369
  type: 'experience',
371
370
  client: {
372
- specs: [
373
- { type: 'it', title: 'show a hero section with a welcome message' },
374
- { type: 'it', title: 'allow user to start the questionnaire' },
375
- ],
371
+ specs: {
372
+ name: '',
373
+ rules: ['show a hero section with a welcome message', 'allow user to start the questionnaire'],
374
+ },
376
375
  },
377
376
  },
378
377
  ],
@@ -382,11 +381,13 @@ narrative('Seasonal Assistant', () => {
382
381
  integrations: [],
383
382
  };
384
383
  const code = await modelToNarrative(experienceModel);
385
- expect(code).toEqual(`import { experience, it, narrative } from '@auto-engineer/narrative';
384
+ expect(code).toEqual(`import { experience, narrative, should, specs } from '@auto-engineer/narrative';
386
385
  narrative('Test Experience Flow', 'TEST-001', () => {
387
386
  experience('Homepage', 'EXP-001').client(() => {
388
- it('show a hero section with a welcome message');
389
- it('allow user to start the questionnaire');
387
+ specs(() => {
388
+ should('show a hero section with a welcome message');
389
+ should('allow user to start the questionnaire');
390
+ });
390
391
  });
391
392
  });
392
393
  `);
@@ -404,16 +405,10 @@ narrative('Test Experience Flow', 'TEST-001', () => {
404
405
  // id: undefined - no ID
405
406
  type: 'experience',
406
407
  client: {
407
- specs: [
408
- {
409
- type: 'describe',
410
- title: 'Homepage specs',
411
- children: [
412
- { type: 'it', title: 'show welcome message' },
413
- { type: 'it', title: 'display navigation' },
414
- ],
415
- },
416
- ],
408
+ specs: {
409
+ name: 'Homepage specs',
410
+ rules: ['show welcome message', 'display navigation'],
411
+ },
417
412
  },
418
413
  },
419
414
  ],
@@ -423,12 +418,12 @@ narrative('Test Experience Flow', 'TEST-001', () => {
423
418
  integrations: [],
424
419
  };
425
420
  const code = await modelToNarrative(modelWithoutIds);
426
- expect(code).toEqual(`import { describe, experience, it, narrative } from '@auto-engineer/narrative';
421
+ expect(code).toEqual(`import { experience, narrative, should, specs } from '@auto-engineer/narrative';
427
422
  narrative('Test Flow without IDs', () => {
428
423
  experience('Homepage').client(() => {
429
- describe('Homepage specs', () => {
430
- it('show welcome message');
431
- it('display navigation');
424
+ specs('Homepage specs', () => {
425
+ should('show welcome message');
426
+ should('display navigation');
432
427
  });
433
428
  });
434
429
  });
@@ -447,16 +442,10 @@ narrative('Test Flow without IDs', () => {
447
442
  id: 'SLICE-ABC',
448
443
  type: 'experience',
449
444
  client: {
450
- specs: [
451
- {
452
- type: 'describe',
453
- title: 'Homepage specs',
454
- children: [
455
- { type: 'it', title: 'show welcome message' },
456
- { type: 'it', title: 'display navigation' },
457
- ],
458
- },
459
- ],
445
+ specs: {
446
+ name: 'Homepage specs',
447
+ rules: ['show welcome message', 'display navigation'],
448
+ },
460
449
  },
461
450
  },
462
451
  {
@@ -464,26 +453,18 @@ narrative('Test Flow without IDs', () => {
464
453
  id: 'SLICE-XYZ',
465
454
  type: 'query',
466
455
  client: {
467
- specs: [
468
- {
469
- type: 'describe',
470
- title: 'Product list specs',
471
- children: [
472
- { type: 'it', title: 'display all products' },
473
- { type: 'it', title: 'allow filtering' },
474
- ],
475
- },
476
- ],
456
+ description: 'Product query client',
457
+ specs: {
458
+ name: 'Product list specs',
459
+ rules: ['display all products', 'allow filtering'],
460
+ },
477
461
  },
478
462
  server: {
479
463
  description: 'Product query server',
480
- specs: [
481
- {
482
- type: 'gherkin',
483
- feature: 'Product data specs',
484
- rules: [],
485
- },
486
- ],
464
+ specs: {
465
+ name: 'Product data specs',
466
+ rules: [],
467
+ },
487
468
  },
488
469
  },
489
470
  ],
@@ -493,19 +474,19 @@ narrative('Test Flow without IDs', () => {
493
474
  integrations: [],
494
475
  };
495
476
  const code = await modelToNarrative(modelWithIds);
496
- expect(code).toEqual(`import { describe, experience, it, narrative, query, specs } from '@auto-engineer/narrative';
477
+ expect(code).toEqual(`import { experience, narrative, query, should, specs } from '@auto-engineer/narrative';
497
478
  narrative('Test Flow with IDs', 'FLOW-123', () => {
498
479
  experience('Homepage', 'SLICE-ABC').client(() => {
499
- describe('Homepage specs', () => {
500
- it('show welcome message');
501
- it('display navigation');
480
+ specs('Homepage specs', () => {
481
+ should('show welcome message');
482
+ should('display navigation');
502
483
  });
503
484
  });
504
485
  query('view products', 'SLICE-XYZ')
505
486
  .client(() => {
506
- describe('Product list specs', () => {
507
- it('display all products');
508
- it('allow filtering');
487
+ specs('Product list specs', () => {
488
+ should('display all products');
489
+ should('allow filtering');
509
490
  });
510
491
  })
511
492
  .server(() => {
@@ -527,40 +508,34 @@ narrative('Test Flow with IDs', 'FLOW-123', () => {
527
508
  id: 'SLICE-789',
528
509
  type: 'command',
529
510
  client: {
530
- specs: [],
511
+ description: 'Command processing client',
531
512
  },
532
513
  server: {
533
514
  description: 'Command processing server',
534
- specs: [
535
- {
536
- type: 'gherkin',
537
- feature: 'Command Processing',
538
- rules: [
539
- {
540
- id: 'RULE-ABC',
541
- name: 'Valid commands should be processed',
542
- examples: [
543
- {
544
- id: 'EX-001',
545
- name: 'User submits valid command',
546
- steps: [
547
- {
548
- keyword: 'When',
549
- text: 'ProcessCommand',
550
- docString: { id: 'cmd-123', action: 'create' },
551
- },
552
- {
553
- keyword: 'Then',
554
- text: 'CommandProcessed',
555
- docString: { id: 'cmd-123', status: 'success' },
556
- },
557
- ],
515
+ specs: {
516
+ name: 'Command Processing',
517
+ rules: [
518
+ {
519
+ id: 'RULE-ABC',
520
+ description: 'Valid commands should be processed',
521
+ examples: [
522
+ {
523
+ description: 'User submits valid command',
524
+ when: {
525
+ commandRef: 'ProcessCommand',
526
+ exampleData: { id: 'cmd-123', action: 'create' },
558
527
  },
559
- ],
560
- },
561
- ],
562
- },
563
- ],
528
+ then: [
529
+ {
530
+ eventRef: 'CommandProcessed',
531
+ exampleData: { id: 'cmd-123', status: 'success' },
532
+ },
533
+ ],
534
+ },
535
+ ],
536
+ },
537
+ ],
538
+ },
564
539
  },
565
540
  },
566
541
  ],
@@ -689,36 +664,34 @@ narrative('Questionnaire Flow', 'QUEST-001', () => {});
689
664
  narratives: [
690
665
  {
691
666
  name: 'Questionnaires',
692
- id: 'Q9m2Kp4Lx',
667
+ id: 'AUTO-Q9m2Kp4Lx',
693
668
  slices: [
694
669
  {
695
670
  name: 'Homepage',
696
- id: 'H1a4Bn6Cy',
671
+ id: 'AUTO-H1a4Bn6Cy',
697
672
  type: 'experience',
698
673
  client: {
699
- specs: [
700
- { type: 'it', title: 'show a hero section with a welcome message' },
701
- { type: 'it', title: 'allow user to start the questionnaire' },
702
- ],
674
+ specs: {
675
+ name: '',
676
+ rules: ['show a hero section with a welcome message', 'allow user to start the questionnaire'],
677
+ },
703
678
  },
704
679
  },
705
680
  {
706
681
  name: 'views the questionnaire',
707
- id: 'V7n8Rq5M',
682
+ id: 'AUTO-V7n8Rq5M',
708
683
  type: 'query',
709
684
  client: {
710
- specs: [
711
- {
712
- type: 'describe',
713
- title: 'Questionnaire Progress',
714
- children: [
715
- { type: 'it', title: 'focus on the current question based on the progress state' },
716
- { type: 'it', title: 'display the list of answered questions' },
717
- { type: 'it', title: 'display the list of remaining questions' },
718
- { type: 'it', title: 'show a progress indicator that is always visible as the user scrolls' },
719
- ],
720
- },
721
- ],
685
+ description: '',
686
+ specs: {
687
+ name: 'Questionnaire Progress',
688
+ rules: [
689
+ 'focus on the current question based on the progress state',
690
+ 'display the list of answered questions',
691
+ 'display the list of remaining questions',
692
+ 'show a progress indicator that is always visible as the user scrolls',
693
+ ],
694
+ },
722
695
  },
723
696
  request: 'query QuestionnaireProgress($participantId: ID!) {\n questionnaireProgress(participantId: $participantId) {\n questionnaireId\n participantId\n currentQuestionId\n remainingQuestions\n status\n answers {\n questionId\n value\n }\n }\n}',
724
697
  server: {
@@ -736,64 +709,59 @@ narrative('Questionnaire Flow', 'QUEST-001', () => {});
736
709
  },
737
710
  },
738
711
  ],
739
- specs: [
740
- {
741
- type: 'gherkin',
742
- feature: '',
743
- rules: [
744
- {
745
- id: 'r1A3Bp9W',
746
- name: 'questionnaires show current progress',
747
- examples: [
748
- {
749
- id: 'EX-001',
750
- name: 'a question has already been answered',
751
- steps: [
752
- {
753
- keyword: 'Given',
754
- text: 'QuestionnaireLinkSent',
755
- docString: {
756
- questionnaireId: 'q-001',
757
- participantId: 'participant-abc',
758
- link: 'https://app.example.com/q/q-001?participant=participant-abc',
759
- sentAt: new Date('2030-01-01T09:00:00.000Z'),
760
- },
761
- },
762
- {
763
- keyword: 'When',
764
- text: 'QuestionAnswered',
765
- docString: {
766
- questionnaireId: 'q-001',
767
- participantId: 'participant-abc',
768
- questionId: 'q1',
769
- answer: 'Yes',
770
- savedAt: new Date('2030-01-01T09:05:00.000Z'),
771
- },
772
- },
773
- {
774
- keyword: 'Then',
775
- text: 'QuestionnaireProgress',
776
- docString: {
777
- questionnaireId: 'q-001',
778
- participantId: 'participant-abc',
779
- status: 'in_progress',
780
- currentQuestionId: 'q2',
781
- remainingQuestions: ['q2', 'q3'],
782
- answers: [
783
- {
784
- questionId: 'q1',
785
- value: 'Yes',
786
- },
787
- ],
788
- },
712
+ specs: {
713
+ name: '',
714
+ rules: [
715
+ {
716
+ id: 'AUTO-r1A3Bp9W',
717
+ description: 'questionnaires show current progress',
718
+ examples: [
719
+ {
720
+ description: 'a question has already been answered',
721
+ given: [
722
+ {
723
+ eventRef: 'QuestionnaireLinkSent',
724
+ exampleData: {
725
+ questionnaireId: 'q-001',
726
+ participantId: 'participant-abc',
727
+ link: 'https://app.example.com/q/q-001?participant=participant-abc',
728
+ sentAt: new Date('2030-01-01T09:00:00.000Z'),
789
729
  },
790
- ],
730
+ },
731
+ ],
732
+ when: {
733
+ exampleData: {
734
+ questionnaireId: 'q-001',
735
+ participantId: 'participant-abc',
736
+ questionId: 'q1',
737
+ answer: 'Yes',
738
+ savedAt: new Date('2030-01-01T09:05:00.000Z'),
739
+ },
740
+ eventRef: 'QuestionAnswered',
791
741
  },
792
- ],
793
- },
794
- ],
795
- },
796
- ],
742
+ then: [
743
+ {
744
+ stateRef: 'QuestionnaireProgress',
745
+ exampleData: {
746
+ questionnaireId: 'q-001',
747
+ participantId: 'participant-abc',
748
+ status: 'in_progress',
749
+ currentQuestionId: 'q2',
750
+ remainingQuestions: ['q2', 'q3'],
751
+ answers: [
752
+ {
753
+ questionId: 'q1',
754
+ value: 'Yes',
755
+ },
756
+ ],
757
+ },
758
+ },
759
+ ],
760
+ },
761
+ ],
762
+ },
763
+ ],
764
+ },
797
765
  },
798
766
  },
799
767
  ],
@@ -910,14 +878,13 @@ narrative('Questionnaire Flow', 'QUEST-001', () => {});
910
878
  const code = await modelToNarrative(questionnairesModel);
911
879
  expect(code).toEqual(`import {
912
880
  data,
913
- describe,
914
881
  example,
915
882
  experience,
916
883
  gql,
917
- it,
918
884
  narrative,
919
885
  query,
920
886
  rule,
887
+ should,
921
888
  source,
922
889
  specs,
923
890
  } from '@auto-engineer/narrative';
@@ -955,18 +922,20 @@ type QuestionnaireProgress = State<
955
922
  }[];
956
923
  }
957
924
  >;
958
- narrative('Questionnaires', 'Q9m2Kp4Lx', () => {
959
- experience('Homepage', 'H1a4Bn6Cy').client(() => {
960
- it('show a hero section with a welcome message');
961
- it('allow user to start the questionnaire');
925
+ narrative('Questionnaires', 'AUTO-Q9m2Kp4Lx', () => {
926
+ experience('Homepage', 'AUTO-H1a4Bn6Cy').client(() => {
927
+ specs(() => {
928
+ should('show a hero section with a welcome message');
929
+ should('allow user to start the questionnaire');
930
+ });
962
931
  });
963
- query('views the questionnaire', 'V7n8Rq5M')
932
+ query('views the questionnaire', 'AUTO-V7n8Rq5M')
964
933
  .client(() => {
965
- describe('Questionnaire Progress', () => {
966
- it('focus on the current question based on the progress state');
967
- it('display the list of answered questions');
968
- it('display the list of remaining questions');
969
- it('show a progress indicator that is always visible as the user scrolls');
934
+ specs('Questionnaire Progress', () => {
935
+ should('focus on the current question based on the progress state');
936
+ should('display the list of answered questions');
937
+ should('display the list of remaining questions');
938
+ should('show a progress indicator that is always visible as the user scrolls');
970
939
  });
971
940
  })
972
941
  .request(
@@ -987,7 +956,7 @@ narrative('Questionnaires', 'Q9m2Kp4Lx', () => {
987
956
  .server(() => {
988
957
  data([source().state('QuestionnaireProgress').fromProjection('Questionnaires', 'questionnaire-participantId')]);
989
958
  specs(() => {
990
- rule('questionnaires show current progress', 'r1A3Bp9W', () => {
959
+ rule('questionnaires show current progress', 'AUTO-r1A3Bp9W', () => {
991
960
  example('a question has already been answered')
992
961
  .given<QuestionnaireLinkSent>({
993
962
  questionnaireId: 'q-001',
@@ -1029,82 +998,75 @@ narrative('Questionnaires', 'Q9m2Kp4Lx', () => {
1029
998
  id: 'TEST-SLICE',
1030
999
  type: 'query',
1031
1000
  client: {
1032
- specs: [],
1001
+ description: 'Test client for duplicate rules',
1033
1002
  },
1034
1003
  server: {
1035
1004
  description: 'Test server for duplicate rules',
1036
- specs: [
1037
- {
1038
- type: 'gherkin',
1039
- feature: 'Test Rules',
1040
- rules: [
1041
- {
1042
- id: 'r1A3Bp9W',
1043
- name: 'questionnaires show current progress',
1044
- examples: [
1045
- {
1046
- id: 'EX-001',
1047
- name: 'a question has already been answered',
1048
- steps: [
1049
- {
1050
- keyword: 'Given',
1051
- text: 'QuestionnaireLinkSent',
1052
- docString: {
1053
- questionnaireId: 'q-001',
1054
- participantId: 'participant-abc',
1055
- },
1056
- },
1057
- {
1058
- keyword: 'When',
1059
- text: 'QuestionAnswered',
1060
- docString: {
1061
- questionnaireId: 'q-001',
1062
- questionId: 'q1',
1063
- answer: 'Yes',
1064
- },
1065
- },
1066
- {
1067
- keyword: 'Then',
1068
- text: 'QuestionnaireProgress',
1069
- docString: {
1070
- questionnaireId: 'q-001',
1071
- status: 'in_progress',
1072
- },
1005
+ specs: {
1006
+ name: 'Test Rules',
1007
+ rules: [
1008
+ {
1009
+ id: 'AUTO-r1A3Bp9W',
1010
+ description: 'questionnaires show current progress',
1011
+ examples: [
1012
+ {
1013
+ description: 'a question has already been answered',
1014
+ given: [
1015
+ {
1016
+ eventRef: 'QuestionnaireLinkSent',
1017
+ exampleData: {
1018
+ questionnaireId: 'q-001',
1019
+ participantId: 'participant-abc',
1073
1020
  },
1074
- ],
1021
+ },
1022
+ ],
1023
+ when: {
1024
+ eventRef: 'QuestionAnswered',
1025
+ exampleData: {
1026
+ questionnaireId: 'q-001',
1027
+ questionId: 'q1',
1028
+ answer: 'Yes',
1029
+ },
1075
1030
  },
1076
- {
1077
- id: 'EX-002',
1078
- name: 'no questions have been answered yet',
1079
- steps: [
1080
- {
1081
- keyword: 'Given',
1082
- text: 'QuestionnaireLinkSent',
1083
- docString: {
1084
- questionnaireId: 'q-001',
1085
- participantId: 'participant-abc',
1086
- },
1031
+ then: [
1032
+ {
1033
+ stateRef: 'QuestionnaireProgress',
1034
+ exampleData: {
1035
+ questionnaireId: 'q-001',
1036
+ status: 'in_progress',
1087
1037
  },
1088
- {
1089
- keyword: 'When',
1090
- text: 'QuestionnaireLinkSent',
1091
- docString: {},
1038
+ },
1039
+ ],
1040
+ },
1041
+ {
1042
+ description: 'no questions have been answered yet',
1043
+ given: [
1044
+ {
1045
+ eventRef: 'QuestionnaireLinkSent',
1046
+ exampleData: {
1047
+ questionnaireId: 'q-001',
1048
+ participantId: 'participant-abc',
1092
1049
  },
1093
- {
1094
- keyword: 'Then',
1095
- text: 'QuestionnaireProgress',
1096
- docString: {
1097
- questionnaireId: 'q-001',
1098
- status: 'in_progress',
1099
- },
1100
- },
1101
- ],
1050
+ },
1051
+ ],
1052
+ when: {
1053
+ eventRef: 'QuestionnaireLinkSent',
1054
+ exampleData: {},
1102
1055
  },
1103
- ],
1104
- },
1105
- ],
1106
- },
1107
- ],
1056
+ then: [
1057
+ {
1058
+ stateRef: 'QuestionnaireProgress',
1059
+ exampleData: {
1060
+ questionnaireId: 'q-001',
1061
+ status: 'in_progress',
1062
+ },
1063
+ },
1064
+ ],
1065
+ },
1066
+ ],
1067
+ },
1068
+ ],
1069
+ },
1108
1070
  },
1109
1071
  },
1110
1072
  ],
@@ -1172,13 +1134,14 @@ type QuestionnaireProgress = State<
1172
1134
  narrative('Test Flow', 'TEST-FLOW', () => {
1173
1135
  query('test slice', 'TEST-SLICE').server(() => {
1174
1136
  specs('Test Rules', () => {
1175
- rule('questionnaires show current progress', 'r1A3Bp9W', () => {
1137
+ rule('questionnaires show current progress', 'AUTO-r1A3Bp9W', () => {
1176
1138
  example('a question has already been answered')
1177
1139
  .given<QuestionnaireLinkSent>({ questionnaireId: 'q-001', participantId: 'participant-abc' })
1178
1140
  .when<QuestionAnswered>({ questionnaireId: 'q-001', questionId: 'q1', answer: 'Yes' })
1179
1141
  .then<QuestionnaireProgress>({ questionnaireId: 'q-001', status: 'in_progress' });
1180
1142
  example('no questions have been answered yet')
1181
1143
  .given<QuestionnaireLinkSent>({ questionnaireId: 'q-001', participantId: 'participant-abc' })
1144
+ .when<QuestionnaireLinkSent>({})
1182
1145
  .then<QuestionnaireProgress>({ questionnaireId: 'q-001', status: 'in_progress' });
1183
1146
  });
1184
1147
  });
@@ -1186,7 +1149,7 @@ narrative('Test Flow', 'TEST-FLOW', () => {
1186
1149
  });
1187
1150
  `);
1188
1151
  });
1189
- it('should chain multiple given examples with and() syntax', async () => {
1152
+ it('should chain multiple given examples with .and() syntax', async () => {
1190
1153
  const modelWithMultiGiven = {
1191
1154
  variant: 'specs',
1192
1155
  narratives: [
@@ -1199,96 +1162,88 @@ narrative('Test Flow', 'TEST-FLOW', () => {
1199
1162
  id: 'MULTI-SLICE',
1200
1163
  type: 'query',
1201
1164
  client: {
1202
- specs: [],
1165
+ description: 'Multi given client',
1203
1166
  },
1204
1167
  server: {
1205
1168
  description: 'Multi given server rules',
1206
- specs: [
1207
- {
1208
- type: 'gherkin',
1209
- feature: 'Multi Given Rules',
1210
- rules: [
1211
- {
1212
- id: 'MultiGiven',
1213
- name: 'all questions have been answered',
1214
- examples: [
1215
- {
1216
- id: 'EX-001',
1217
- name: 'questionnaire with multiple events',
1218
- steps: [
1219
- {
1220
- keyword: 'Given',
1221
- text: 'QuestionnaireConfig',
1222
- docString: {
1223
- questionnaireId: 'q-001',
1224
- numberOfQuestions: 3,
1225
- },
1226
- },
1227
- {
1228
- keyword: 'And',
1229
- text: 'QuestionnaireLinkSent',
1230
- docString: {
1231
- questionnaireId: 'q-001',
1232
- participantId: 'participant-abc',
1233
- link: 'https://example.com/q/q-001',
1234
- sentAt: new Date('2030-01-01T09:00:00.000Z'),
1235
- },
1236
- },
1237
- {
1238
- keyword: 'And',
1239
- text: 'QuestionAnswered',
1240
- docString: {
1241
- questionnaireId: 'q-001',
1242
- participantId: 'participant-abc',
1243
- questionId: 'q1',
1244
- answer: 'Yes',
1245
- savedAt: new Date('2030-01-01T09:05:00.000Z'),
1246
- },
1169
+ specs: {
1170
+ name: 'Multi Given Rules',
1171
+ rules: [
1172
+ {
1173
+ id: 'AUTO-MultiGiven',
1174
+ description: 'all questions have been answered',
1175
+ examples: [
1176
+ {
1177
+ description: 'questionnaire with multiple events',
1178
+ given: [
1179
+ {
1180
+ stateRef: 'QuestionnaireConfig',
1181
+ exampleData: {
1182
+ questionnaireId: 'q-001',
1183
+ numberOfQuestions: 3,
1247
1184
  },
1248
- {
1249
- keyword: 'And',
1250
- text: 'QuestionAnswered',
1251
- docString: {
1252
- questionnaireId: 'q-001',
1253
- participantId: 'participant-abc',
1254
- questionId: 'q2',
1255
- answer: 'No',
1256
- savedAt: new Date('2030-01-01T09:10:00.000Z'),
1257
- },
1185
+ },
1186
+ {
1187
+ eventRef: 'QuestionnaireLinkSent',
1188
+ exampleData: {
1189
+ questionnaireId: 'q-001',
1190
+ participantId: 'participant-abc',
1191
+ link: 'https://example.com/q/q-001',
1192
+ sentAt: new Date('2030-01-01T09:00:00.000Z'),
1258
1193
  },
1259
- {
1260
- keyword: 'When',
1261
- text: 'QuestionAnswered',
1262
- docString: {
1263
- questionnaireId: 'q-001',
1264
- participantId: 'participant-abc',
1265
- questionId: 'q3',
1266
- answer: 'Maybe',
1267
- savedAt: new Date('2030-01-01T09:15:00.000Z'),
1268
- },
1194
+ },
1195
+ {
1196
+ eventRef: 'QuestionAnswered',
1197
+ exampleData: {
1198
+ questionnaireId: 'q-001',
1199
+ participantId: 'participant-abc',
1200
+ questionId: 'q1',
1201
+ answer: 'Yes',
1202
+ savedAt: new Date('2030-01-01T09:05:00.000Z'),
1269
1203
  },
1270
- {
1271
- keyword: 'Then',
1272
- text: 'QuestionnaireProgress',
1273
- docString: {
1274
- questionnaireId: 'q-001',
1275
- participantId: 'participant-abc',
1276
- status: 'ready_to_submit',
1277
- currentQuestionId: null,
1278
- remainingQuestions: [],
1279
- answers: [
1280
- { questionId: 'q1', value: 'Yes' },
1281
- { questionId: 'q2', value: 'No' },
1282
- ],
1283
- },
1204
+ },
1205
+ {
1206
+ eventRef: 'QuestionAnswered',
1207
+ exampleData: {
1208
+ questionnaireId: 'q-001',
1209
+ participantId: 'participant-abc',
1210
+ questionId: 'q2',
1211
+ answer: 'No',
1212
+ savedAt: new Date('2030-01-01T09:10:00.000Z'),
1284
1213
  },
1285
- ],
1214
+ },
1215
+ ],
1216
+ when: {
1217
+ eventRef: 'QuestionAnswered',
1218
+ exampleData: {
1219
+ questionnaireId: 'q-001',
1220
+ participantId: 'participant-abc',
1221
+ questionId: 'q3',
1222
+ answer: 'Maybe',
1223
+ savedAt: new Date('2030-01-01T09:15:00.000Z'),
1224
+ },
1286
1225
  },
1287
- ],
1288
- },
1289
- ],
1290
- },
1291
- ],
1226
+ then: [
1227
+ {
1228
+ stateRef: 'QuestionnaireProgress',
1229
+ exampleData: {
1230
+ questionnaireId: 'q-001',
1231
+ participantId: 'participant-abc',
1232
+ status: 'ready_to_submit',
1233
+ currentQuestionId: null,
1234
+ remainingQuestions: [],
1235
+ answers: [
1236
+ { questionId: 'q1', value: 'Yes' },
1237
+ { questionId: 'q2', value: 'No' },
1238
+ ],
1239
+ },
1240
+ },
1241
+ ],
1242
+ },
1243
+ ],
1244
+ },
1245
+ ],
1246
+ },
1292
1247
  },
1293
1248
  },
1294
1249
  ],
@@ -1391,7 +1346,7 @@ type QuestionnaireProgress = State<
1391
1346
  narrative('Multi Given Flow', 'MULTI-GIVEN', () => {
1392
1347
  query('multi given slice', 'MULTI-SLICE').server(() => {
1393
1348
  specs('Multi Given Rules', () => {
1394
- rule('all questions have been answered', 'MultiGiven', () => {
1349
+ rule('all questions have been answered', 'AUTO-MultiGiven', () => {
1395
1350
  example('questionnaire with multiple events')
1396
1351
  .given<QuestionnaireConfig>({ questionnaireId: 'q-001', numberOfQuestions: 3 })
1397
1352
  .and<QuestionnaireLinkSent>({
@@ -1451,7 +1406,7 @@ narrative('Multi Given Flow', 'MULTI-GIVEN', () => {
1451
1406
  id: 'REF-SLICE',
1452
1407
  type: 'query',
1453
1408
  client: {
1454
- specs: [],
1409
+ description: 'Client for referenced states',
1455
1410
  },
1456
1411
  server: {
1457
1412
  description: 'Server for referenced states',
@@ -1479,50 +1434,45 @@ narrative('Multi Given Flow', 'MULTI-GIVEN', () => {
1479
1434
  },
1480
1435
  },
1481
1436
  ],
1482
- specs: [
1483
- {
1484
- type: 'gherkin',
1485
- feature: 'Database State Rules',
1486
- rules: [
1487
- {
1488
- id: 'RefState',
1489
- name: 'questionnaire config is available when referenced',
1490
- examples: [
1491
- {
1492
- id: 'EX-001',
1493
- name: 'config from database is accessible',
1494
- steps: [
1495
- {
1496
- keyword: 'Given',
1497
- text: 'QuestionnaireConfig',
1498
- docString: {
1499
- questionnaireId: 'q-001',
1500
- numberOfQuestions: 5,
1501
- title: 'Customer Satisfaction Survey',
1502
- },
1503
- },
1504
- {
1505
- keyword: 'When',
1506
- text: 'QuestionnaireProgress',
1507
- docString: {},
1508
- },
1509
- {
1510
- keyword: 'Then',
1511
- text: 'QuestionnaireProgress',
1512
- docString: {
1513
- questionnaireId: 'q-001',
1514
- participantId: 'participant-abc',
1515
- status: 'in_progress',
1516
- totalQuestions: 5,
1517
- },
1437
+ specs: {
1438
+ name: 'Database State Rules',
1439
+ rules: [
1440
+ {
1441
+ id: 'AUTO-RefState',
1442
+ description: 'questionnaire config is available when referenced',
1443
+ examples: [
1444
+ {
1445
+ description: 'config from database is accessible',
1446
+ given: [
1447
+ {
1448
+ stateRef: 'QuestionnaireConfig',
1449
+ exampleData: {
1450
+ questionnaireId: 'q-001',
1451
+ numberOfQuestions: 5,
1452
+ title: 'Customer Satisfaction Survey',
1518
1453
  },
1519
- ],
1454
+ },
1455
+ ],
1456
+ when: {
1457
+ eventRef: 'QuestionnaireProgress',
1458
+ exampleData: {},
1520
1459
  },
1521
- ],
1522
- },
1523
- ],
1524
- },
1525
- ],
1460
+ then: [
1461
+ {
1462
+ stateRef: 'QuestionnaireProgress',
1463
+ exampleData: {
1464
+ questionnaireId: 'q-001',
1465
+ participantId: 'participant-abc',
1466
+ status: 'in_progress',
1467
+ totalQuestions: 5,
1468
+ },
1469
+ },
1470
+ ],
1471
+ },
1472
+ ],
1473
+ },
1474
+ ],
1475
+ },
1526
1476
  },
1527
1477
  },
1528
1478
  ],
@@ -1554,7 +1504,8 @@ narrative('Multi Given Flow', 'MULTI-GIVEN', () => {
1554
1504
  integrations: [],
1555
1505
  };
1556
1506
  const code = await modelToNarrative(modelWithReferencedStates);
1557
- expect(code).toEqual(`import { data, example, narrative, query, rule, source, specs } from '@auto-engineer/narrative';
1507
+ expect(code)
1508
+ .toEqual(`import { data, example, narrative, query, rule, source, specs } from '@auto-engineer/narrative';
1558
1509
  import type { State } from '@auto-engineer/narrative';
1559
1510
  type QuestionnaireProgress = State<
1560
1511
  'QuestionnaireProgress',
@@ -1580,13 +1531,14 @@ narrative('Referenced States Flow', 'REF-STATES', () => {
1580
1531
  source().state('QuestionnaireConfig').fromDatabase('ConfigStore', { questionnaireId: '$questionnaireId' }),
1581
1532
  ]);
1582
1533
  specs('Database State Rules', () => {
1583
- rule('questionnaire config is available when referenced', 'RefState', () => {
1534
+ rule('questionnaire config is available when referenced', 'AUTO-RefState', () => {
1584
1535
  example('config from database is accessible')
1585
1536
  .given<QuestionnaireConfig>({
1586
1537
  questionnaireId: 'q-001',
1587
1538
  numberOfQuestions: 5,
1588
1539
  title: 'Customer Satisfaction Survey',
1589
1540
  })
1541
+ .when<QuestionnaireProgress>({})
1590
1542
  .then<QuestionnaireProgress>({
1591
1543
  questionnaireId: 'q-001',
1592
1544
  participantId: 'participant-abc',
@@ -1612,57 +1564,52 @@ narrative('Referenced States Flow', 'REF-STATES', () => {
1612
1564
  id: 'DATE-SLICE',
1613
1565
  type: 'query',
1614
1566
  client: {
1615
- specs: [],
1567
+ description: 'Date client',
1616
1568
  },
1617
1569
  server: {
1618
1570
  description: 'Date server with Date fields',
1619
- specs: [
1620
- {
1621
- type: 'gherkin',
1622
- feature: 'Date Field Rules',
1623
- rules: [
1624
- {
1625
- id: 'DateRule',
1626
- name: 'handles Date fields correctly',
1627
- examples: [
1628
- {
1629
- id: 'EX-001',
1630
- name: 'event with Date fields',
1631
- steps: [
1632
- {
1633
- keyword: 'Given',
1634
- text: 'TimestampedEvent',
1635
- docString: {
1636
- id: 'event-123',
1637
- sentAt: new Date('2030-01-01T09:00:00.000Z'),
1638
- savedAt: new Date('2030-01-01T09:05:00.000Z'),
1639
- attemptedAt: '2030-01-01T09:10:00.000Z',
1640
- submittedAt: '2030-01-01T09:15:00.000Z',
1641
- },
1642
- },
1643
- {
1644
- keyword: 'When',
1645
- text: 'ProcessEvent',
1646
- docString: {
1647
- processedAt: '2030-01-01T10:00:00.000Z',
1648
- },
1649
- },
1650
- {
1651
- keyword: 'Then',
1652
- text: 'ProcessState',
1653
- docString: {
1654
- id: 'state-123',
1655
- completedAt: '2030-01-01T11:00:00.000Z',
1656
- status: 'completed',
1657
- },
1571
+ specs: {
1572
+ name: 'Date Field Rules',
1573
+ rules: [
1574
+ {
1575
+ id: 'AUTO-DateRule',
1576
+ description: 'handles Date fields correctly',
1577
+ examples: [
1578
+ {
1579
+ description: 'event with Date fields',
1580
+ given: [
1581
+ {
1582
+ eventRef: 'TimestampedEvent',
1583
+ exampleData: {
1584
+ id: 'event-123',
1585
+ sentAt: new Date('2030-01-01T09:00:00.000Z'),
1586
+ savedAt: new Date('2030-01-01T09:05:00.000Z'),
1587
+ attemptedAt: '2030-01-01T09:10:00.000Z',
1588
+ submittedAt: '2030-01-01T09:15:00.000Z',
1658
1589
  },
1659
- ],
1590
+ },
1591
+ ],
1592
+ when: {
1593
+ eventRef: 'ProcessEvent',
1594
+ exampleData: {
1595
+ processedAt: '2030-01-01T10:00:00.000Z',
1596
+ },
1660
1597
  },
1661
- ],
1662
- },
1663
- ],
1664
- },
1665
- ],
1598
+ then: [
1599
+ {
1600
+ stateRef: 'ProcessState',
1601
+ exampleData: {
1602
+ id: 'state-123',
1603
+ completedAt: '2030-01-01T11:00:00.000Z',
1604
+ status: 'completed',
1605
+ },
1606
+ },
1607
+ ],
1608
+ },
1609
+ ],
1610
+ },
1611
+ ],
1612
+ },
1666
1613
  },
1667
1614
  },
1668
1615
  ],
@@ -1732,7 +1679,7 @@ type ProcessState = State<
1732
1679
  narrative('Date Handling Flow', 'DATE-FLOW', () => {
1733
1680
  query('date handling slice', 'DATE-SLICE').server(() => {
1734
1681
  specs('Date Field Rules', () => {
1735
- rule('handles Date fields correctly', 'DateRule', () => {
1682
+ rule('handles Date fields correctly', 'AUTO-DateRule', () => {
1736
1683
  example('event with Date fields')
1737
1684
  .given<TimestampedEvent>({
1738
1685
  id: 'event-123',
@@ -1763,10 +1710,13 @@ narrative('Date Handling Flow', 'DATE-FLOW', () => {
1763
1710
  slices: [
1764
1711
  {
1765
1712
  name: 'Active Surveys Summary',
1766
- id: 'aifPcU3hw',
1713
+ id: 'AUTO-aifPcU3hw',
1767
1714
  type: 'experience',
1768
1715
  client: {
1769
- specs: [{ type: 'it', title: 'show active surveys summary' }],
1716
+ specs: {
1717
+ name: '',
1718
+ rules: ['show active surveys summary'],
1719
+ },
1770
1720
  },
1771
1721
  },
1772
1722
  ],
@@ -1777,10 +1727,13 @@ narrative('Date Handling Flow', 'DATE-FLOW', () => {
1777
1727
  slices: [
1778
1728
  {
1779
1729
  name: 'Create Survey Form',
1780
- id: 'MPviTMrQC',
1730
+ id: 'AUTO-MPviTMrQC',
1781
1731
  type: 'experience',
1782
1732
  client: {
1783
- specs: [{ type: 'it', title: 'allow entering survey title' }],
1733
+ specs: {
1734
+ name: '',
1735
+ rules: ['allow entering survey title'],
1736
+ },
1784
1737
  },
1785
1738
  },
1786
1739
  ],
@@ -1791,10 +1744,13 @@ narrative('Date Handling Flow', 'DATE-FLOW', () => {
1791
1744
  slices: [
1792
1745
  {
1793
1746
  name: 'Response Rate Charts',
1794
- id: 'eME978Euk',
1747
+ id: 'AUTO-eME978Euk',
1795
1748
  type: 'experience',
1796
1749
  client: {
1797
- specs: [{ type: 'it', title: 'show daily response rate charts' }],
1750
+ specs: {
1751
+ name: '',
1752
+ rules: ['show daily response rate charts'],
1753
+ },
1798
1754
  },
1799
1755
  },
1800
1756
  ],
@@ -1804,20 +1760,26 @@ narrative('Date Handling Flow', 'DATE-FLOW', () => {
1804
1760
  integrations: [],
1805
1761
  };
1806
1762
  const code = await modelToNarrative(modelWithMultipleFlowsSameSource);
1807
- expect(code).toEqual(`import { experience, it, narrative } from '@auto-engineer/narrative';
1763
+ expect(code).toEqual(`import { experience, narrative, should, specs } from '@auto-engineer/narrative';
1808
1764
  narrative('Home Screen', () => {
1809
- experience('Active Surveys Summary', 'aifPcU3hw').client(() => {
1810
- it('show active surveys summary');
1765
+ experience('Active Surveys Summary', 'AUTO-aifPcU3hw').client(() => {
1766
+ specs(() => {
1767
+ should('show active surveys summary');
1768
+ });
1811
1769
  });
1812
1770
  });
1813
1771
  narrative('Create Survey', () => {
1814
- experience('Create Survey Form', 'MPviTMrQC').client(() => {
1815
- it('allow entering survey title');
1772
+ experience('Create Survey Form', 'AUTO-MPviTMrQC').client(() => {
1773
+ specs(() => {
1774
+ should('allow entering survey title');
1775
+ });
1816
1776
  });
1817
1777
  });
1818
1778
  narrative('Response Analytics', () => {
1819
- experience('Response Rate Charts', 'eME978Euk').client(() => {
1820
- it('show daily response rate charts');
1779
+ experience('Response Rate Charts', 'AUTO-eME978Euk').client(() => {
1780
+ specs(() => {
1781
+ should('show daily response rate charts');
1782
+ });
1821
1783
  });
1822
1784
  });
1823
1785
  `);
@@ -1835,78 +1797,75 @@ narrative('Response Analytics', () => {
1835
1797
  id: 'SUMMARY-001',
1836
1798
  type: 'query',
1837
1799
  client: {
1838
- specs: [],
1800
+ description: 'Summary view client',
1839
1801
  },
1840
1802
  server: {
1841
1803
  description: 'Summary calculation server',
1842
- specs: [
1843
- {
1844
- type: 'gherkin',
1845
- feature: 'Summary Statistics',
1846
- rules: [
1847
- {
1848
- id: 'RULE-SUMMARY',
1849
- name: 'summary shows overall todo list statistics',
1850
- examples: [
1851
- {
1852
- id: 'EX-001',
1853
- name: 'calculates summary from multiple todos',
1854
- steps: [
1855
- {
1856
- keyword: 'Given',
1857
- text: 'TodoAdded',
1858
- docString: {
1859
- todoId: 'todo-001',
1860
- description: 'Buy groceries',
1861
- status: 'pending',
1862
- addedAt: new Date('2030-01-01T09:00:00.000Z'),
1863
- },
1864
- },
1865
- {
1866
- keyword: 'And',
1867
- text: 'TodoAdded',
1868
- docString: {
1869
- todoId: 'todo-002',
1870
- description: 'Write report',
1871
- status: 'pending',
1872
- addedAt: new Date('2030-01-01T09:10:00.000Z'),
1873
- },
1804
+ specs: {
1805
+ name: 'Summary Statistics',
1806
+ rules: [
1807
+ {
1808
+ id: 'RULE-SUMMARY',
1809
+ description: 'summary shows overall todo list statistics',
1810
+ examples: [
1811
+ {
1812
+ description: 'calculates summary from multiple todos',
1813
+ given: [
1814
+ {
1815
+ eventRef: 'TodoAdded',
1816
+ exampleData: {
1817
+ todoId: 'todo-001',
1818
+ description: 'Buy groceries',
1819
+ status: 'pending',
1820
+ addedAt: new Date('2030-01-01T09:00:00.000Z'),
1874
1821
  },
1875
- {
1876
- keyword: 'And',
1877
- text: 'TodoMarkedInProgress',
1878
- docString: {
1879
- todoId: 'todo-001',
1880
- markedAt: new Date('2030-01-01T10:00:00.000Z'),
1881
- },
1822
+ },
1823
+ {
1824
+ eventRef: 'TodoAdded',
1825
+ exampleData: {
1826
+ todoId: 'todo-002',
1827
+ description: 'Write report',
1828
+ status: 'pending',
1829
+ addedAt: new Date('2030-01-01T09:10:00.000Z'),
1882
1830
  },
1883
- {
1884
- keyword: 'And',
1885
- text: 'TodoMarkedComplete',
1886
- docString: {
1887
- todoId: 'todo-002',
1888
- completedAt: new Date('2030-01-01T11:00:00.000Z'),
1889
- },
1831
+ },
1832
+ {
1833
+ eventRef: 'TodoMarkedInProgress',
1834
+ exampleData: {
1835
+ todoId: 'todo-001',
1836
+ markedAt: new Date('2030-01-01T10:00:00.000Z'),
1890
1837
  },
1891
- {
1892
- keyword: 'Then',
1893
- text: 'TodoListSummary',
1894
- docString: {
1895
- summaryId: 'main-summary',
1896
- totalTodos: 2,
1897
- pendingCount: 0,
1898
- inProgressCount: 1,
1899
- completedCount: 1,
1900
- completionPercentage: 50,
1901
- },
1838
+ },
1839
+ {
1840
+ eventRef: 'TodoMarkedComplete',
1841
+ exampleData: {
1842
+ todoId: 'todo-002',
1843
+ completedAt: new Date('2030-01-01T11:00:00.000Z'),
1902
1844
  },
1903
- ],
1845
+ },
1846
+ ],
1847
+ when: {
1848
+ eventRef: '',
1849
+ exampleData: {},
1904
1850
  },
1905
- ],
1906
- },
1907
- ],
1908
- },
1909
- ],
1851
+ then: [
1852
+ {
1853
+ stateRef: 'TodoListSummary',
1854
+ exampleData: {
1855
+ summaryId: 'main-summary',
1856
+ totalTodos: 2,
1857
+ pendingCount: 0,
1858
+ inProgressCount: 1,
1859
+ completedCount: 1,
1860
+ completionPercentage: 50,
1861
+ },
1862
+ },
1863
+ ],
1864
+ },
1865
+ ],
1866
+ },
1867
+ ],
1868
+ },
1910
1869
  },
1911
1870
  },
1912
1871
  ],
@@ -2030,8 +1989,8 @@ narrative('Todo List Summary', 'TODO-001', () => {
2030
1989
  });
2031
1990
  });
2032
1991
  `);
2033
- expect(code).not.toContain('when({})');
2034
- expect(code).not.toContain('when<');
1992
+ expect(code).not.toContain('.when({})');
1993
+ expect(code).not.toContain('.when<');
2035
1994
  });
2036
1995
  describe('projection DSL generation', () => {
2037
1996
  it('should generate fromSingletonProjection for singleton projections', async () => {
@@ -2047,7 +2006,7 @@ narrative('Todo List Summary', 'TODO-001', () => {
2047
2006
  id: 'SUMMARY-SLICE',
2048
2007
  type: 'query',
2049
2008
  client: {
2050
- specs: [],
2009
+ description: 'Summary client',
2051
2010
  },
2052
2011
  server: {
2053
2012
  description: 'Summary server',
@@ -2064,13 +2023,10 @@ narrative('Todo List Summary', 'TODO-001', () => {
2064
2023
  },
2065
2024
  },
2066
2025
  ],
2067
- specs: [
2068
- {
2069
- type: 'gherkin',
2070
- feature: 'Summary Rules',
2071
- rules: [],
2072
- },
2073
- ],
2026
+ specs: {
2027
+ name: 'Summary Rules',
2028
+ rules: [],
2029
+ },
2074
2030
  },
2075
2031
  },
2076
2032
  ],
@@ -2120,7 +2076,7 @@ narrative('Todo Summary Flow', 'TODO-SUMMARY', () => {
2120
2076
  id: 'TODO-SLICE',
2121
2077
  type: 'query',
2122
2078
  client: {
2123
- specs: [],
2079
+ description: 'Todo client',
2124
2080
  },
2125
2081
  server: {
2126
2082
  description: 'Todo server',
@@ -2137,13 +2093,10 @@ narrative('Todo Summary Flow', 'TODO-SUMMARY', () => {
2137
2093
  },
2138
2094
  },
2139
2095
  ],
2140
- specs: [
2141
- {
2142
- type: 'gherkin',
2143
- feature: 'Todo Rules',
2144
- rules: [],
2145
- },
2146
- ],
2096
+ specs: {
2097
+ name: 'Todo Rules',
2098
+ rules: [],
2099
+ },
2147
2100
  },
2148
2101
  },
2149
2102
  ],
@@ -2193,7 +2146,7 @@ narrative('Todo Flow', 'TODO-FLOW', () => {
2193
2146
  id: 'USER-PROJECT-SLICE',
2194
2147
  type: 'query',
2195
2148
  client: {
2196
- specs: [],
2149
+ description: 'User project client',
2197
2150
  },
2198
2151
  server: {
2199
2152
  description: 'User project server',
@@ -2210,13 +2163,10 @@ narrative('Todo Flow', 'TODO-FLOW', () => {
2210
2163
  },
2211
2164
  },
2212
2165
  ],
2213
- specs: [
2214
- {
2215
- type: 'gherkin',
2216
- feature: 'User Project Rules',
2217
- rules: [],
2218
- },
2219
- ],
2166
+ specs: {
2167
+ name: 'User Project Rules',
2168
+ rules: [],
2169
+ },
2220
2170
  },
2221
2171
  },
2222
2172
  ],
@@ -2268,7 +2218,7 @@ narrative('User Project Flow', 'USER-PROJECT-FLOW', () => {
2268
2218
  id: 'SUMMARY-SLICE',
2269
2219
  type: 'query',
2270
2220
  client: {
2271
- specs: [],
2221
+ description: 'Summary client',
2272
2222
  },
2273
2223
  server: {
2274
2224
  description: 'Summary server',
@@ -2285,13 +2235,10 @@ narrative('User Project Flow', 'USER-PROJECT-FLOW', () => {
2285
2235
  },
2286
2236
  },
2287
2237
  ],
2288
- specs: [
2289
- {
2290
- type: 'gherkin',
2291
- feature: 'Summary Rules',
2292
- rules: [],
2293
- },
2294
- ],
2238
+ specs: {
2239
+ name: 'Summary Rules',
2240
+ rules: [],
2241
+ },
2295
2242
  },
2296
2243
  },
2297
2244
  {
@@ -2299,7 +2246,7 @@ narrative('User Project Flow', 'USER-PROJECT-FLOW', () => {
2299
2246
  id: 'TODO-SLICE',
2300
2247
  type: 'query',
2301
2248
  client: {
2302
- specs: [],
2249
+ description: 'Todo client',
2303
2250
  },
2304
2251
  server: {
2305
2252
  description: 'Todo server',
@@ -2316,13 +2263,10 @@ narrative('User Project Flow', 'USER-PROJECT-FLOW', () => {
2316
2263
  },
2317
2264
  },
2318
2265
  ],
2319
- specs: [
2320
- {
2321
- type: 'gherkin',
2322
- feature: 'Todo Rules',
2323
- rules: [],
2324
- },
2325
- ],
2266
+ specs: {
2267
+ name: 'Todo Rules',
2268
+ rules: [],
2269
+ },
2326
2270
  },
2327
2271
  },
2328
2272
  {
@@ -2330,7 +2274,7 @@ narrative('User Project Flow', 'USER-PROJECT-FLOW', () => {
2330
2274
  id: 'USER-PROJECT-SLICE',
2331
2275
  type: 'query',
2332
2276
  client: {
2333
- specs: [],
2277
+ description: 'User project client',
2334
2278
  },
2335
2279
  server: {
2336
2280
  description: 'User project server',
@@ -2347,13 +2291,10 @@ narrative('User Project Flow', 'USER-PROJECT-FLOW', () => {
2347
2291
  },
2348
2292
  },
2349
2293
  ],
2350
- specs: [
2351
- {
2352
- type: 'gherkin',
2353
- feature: 'User Project Rules',
2354
- rules: [],
2355
- },
2356
- ],
2294
+ specs: {
2295
+ name: 'User Project Rules',
2296
+ rules: [],
2297
+ },
2357
2298
  },
2358
2299
  },
2359
2300
  ],