@inseefr/lunatic 3.8.1-rc.1 → 3.9.1-rc-react19.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 (48) hide show
  1. package/README.md +7 -13
  2. package/components/Input/Input.spec.js +1 -1
  3. package/components/Input/Input.spec.js.map +1 -1
  4. package/components/Roundabout/roundabout.spec.js +1 -1
  5. package/components/Roundabout/roundabout.spec.js.map +1 -1
  6. package/components/Suggester/Suggester.js +4 -11
  7. package/components/Suggester/Suggester.js.map +1 -1
  8. package/components/Suggester/Suggester.spec.js +1 -1
  9. package/components/Suggester/Suggester.spec.js.map +1 -1
  10. package/components/Suggester/useSuggestions.js +1 -1
  11. package/components/Suggester/useSuggestions.js.map +1 -1
  12. package/components/Textarea/Textarea.spec.js +1 -1
  13. package/components/Textarea/Textarea.spec.js.map +1 -1
  14. package/esm/components/Input/Input.spec.js +1 -1
  15. package/esm/components/Input/Input.spec.js.map +1 -1
  16. package/esm/components/Roundabout/roundabout.spec.js +1 -1
  17. package/esm/components/Roundabout/roundabout.spec.js.map +1 -1
  18. package/esm/components/Suggester/Suggester.js +4 -11
  19. package/esm/components/Suggester/Suggester.js.map +1 -1
  20. package/esm/components/Suggester/Suggester.spec.js +1 -1
  21. package/esm/components/Suggester/Suggester.spec.js.map +1 -1
  22. package/esm/components/Suggester/useSuggestions.js +1 -1
  23. package/esm/components/Suggester/useSuggestions.js.map +1 -1
  24. package/esm/components/Textarea/Textarea.spec.js +1 -1
  25. package/esm/components/Textarea/Textarea.spec.js.map +1 -1
  26. package/esm/hooks/useRefSync.d.ts +1 -1
  27. package/esm/use-lunatic/commons/variables/lunatic-variables-store.js +23 -23
  28. package/esm/use-lunatic/commons/variables/lunatic-variables-store.js.map +1 -1
  29. package/esm/use-lunatic/commons/variables/lunatic-variables-store.spec.js +95 -0
  30. package/esm/use-lunatic/commons/variables/lunatic-variables-store.spec.js.map +1 -1
  31. package/hooks/useRefSync.d.ts +1 -1
  32. package/package.json +8 -6
  33. package/src/components/Input/Input.spec.tsx +1 -1
  34. package/src/components/Roundabout/roundabout.spec.tsx +1 -1
  35. package/src/components/Suggester/Suggester.spec.tsx +2 -1
  36. package/src/components/Suggester/Suggester.tsx +4 -12
  37. package/src/components/Suggester/useSuggestions.ts +1 -1
  38. package/src/components/Textarea/Textarea.spec.tsx +1 -1
  39. package/src/stories/behaviour/overview/sourceLoop.json +306 -1228
  40. package/src/use-lunatic/__snapshots__/use-lunatic.test.ts.snap +0 -646
  41. package/src/use-lunatic/commons/variables/lunatic-variables-store.spec.ts +106 -0
  42. package/src/use-lunatic/commons/variables/lunatic-variables-store.ts +24 -29
  43. package/src/use-lunatic/use-lunatic.test.ts +33 -25
  44. package/tsconfig.build.tsbuildinfo +1 -1
  45. package/use-lunatic/commons/variables/lunatic-variables-store.js +21 -25
  46. package/use-lunatic/commons/variables/lunatic-variables-store.js.map +1 -1
  47. package/use-lunatic/commons/variables/lunatic-variables-store.spec.js +95 -0
  48. package/use-lunatic/commons/variables/lunatic-variables-store.spec.js.map +1 -1
@@ -984,5 +984,111 @@ describe('lunatic-variables-store', () => {
984
984
 
985
985
  expect(store.get('GLOBAL_ENFANTS_PRENOMS', [4])).toBe(undefined);
986
986
  });
987
+
988
+ it('should compute correctly GLOBAL array variable across calculated variables, even if not intialize', () => {
989
+ // Given a source with a pairwise component
990
+ const pairwiseComponent = {
991
+ id: 'm8ob5u9l',
992
+ page: '3',
993
+ symLinks: {
994
+ LINKS: {
995
+ '1': '1',
996
+ '2': '3',
997
+ '3': '2',
998
+ },
999
+ },
1000
+ components: [
1001
+ {
1002
+ id: 'm8ob5u9l-pairwise-dropdown',
1003
+ label: {
1004
+ type: 'VTL|MD',
1005
+ value: '"Qui est " || yAxis || " pour " || xAxis || " ?"',
1006
+ },
1007
+ options: [
1008
+ {
1009
+ label: {
1010
+ type: 'VTL',
1011
+ value: '"Son conjoint, sa conjointe"',
1012
+ },
1013
+ value: '1',
1014
+ },
1015
+ {
1016
+ label: { type: 'VTL', value: '"Sa mère, son père"' },
1017
+ value: '2',
1018
+ },
1019
+ {
1020
+ label: { type: 'VTL', value: '"Sa fille, son fils"' },
1021
+ value: '3',
1022
+ },
1023
+ ],
1024
+ response: { name: 'LINKS' },
1025
+ isMandatory: false,
1026
+ componentType: 'Dropdown',
1027
+ conditionFilter: {
1028
+ type: 'VTL',
1029
+ value: '(nvl(xAxis, "") <> "") and (nvl(yAxis, "") <> "")',
1030
+ },
1031
+ },
1032
+ ],
1033
+ sourceVariables: {
1034
+ name: 'PRENOM',
1035
+ gender: 'SEXE',
1036
+ },
1037
+ componentType: 'PairwiseLinks',
1038
+ xAxisIterations: { type: 'VTL', value: 'count(PRENOM)' },
1039
+ yAxisIterations: { type: 'VTL', value: 'count(PRENOM)' },
1040
+ } as ComponentDefinitionWithPage;
1041
+
1042
+ // When we create the store
1043
+ const store = LunaticVariablesStore.makeFromSource(
1044
+ {
1045
+ components: [pairwiseComponent],
1046
+ variables: [
1047
+ {
1048
+ name: 'PRENOM',
1049
+ values: { COLLECTED: [] },
1050
+ dimension: 1,
1051
+ variableType: 'COLLECTED',
1052
+ iterationReference: 'm8ob7c76',
1053
+ },
1054
+ {
1055
+ name: 'SEXE',
1056
+ values: { COLLECTED: [] },
1057
+ dimension: 1,
1058
+ variableType: 'COLLECTED',
1059
+ iterationReference: 'm8ob7c76',
1060
+ },
1061
+ {
1062
+ name: 'LINKS',
1063
+ values: { COLLECTED: [[]] },
1064
+ dimension: 2,
1065
+ variableType: 'COLLECTED',
1066
+ iterationReference: 'm8ob7c76',
1067
+ },
1068
+ ],
1069
+ },
1070
+ {},
1071
+ { changeHandler: { current: () => {} } }
1072
+ );
1073
+
1074
+ // When pairwise link is updated
1075
+ store.set('PRENOM', ['Child', 'Dad']);
1076
+ store.set('SEXE', ['1', '1']);
1077
+ store.set('LINKS', [
1078
+ [null, '2'],
1079
+ ['3', null],
1080
+ ]);
1081
+ store.commit();
1082
+ expect(
1083
+ store.run('"Your children are : " || GLOBAL_ENFANTS_PRENOMS', {
1084
+ iteration: [0],
1085
+ })
1086
+ ).toBe('Your children are : null');
1087
+ expect(
1088
+ store.run('"Your children are : " || GLOBAL_ENFANTS_PRENOMS', {
1089
+ iteration: [1],
1090
+ })
1091
+ ).toBe('Your children are : Child');
1092
+ });
987
1093
  });
988
1094
  });
@@ -540,21 +540,28 @@ export class LunaticVariable {
540
540
  opts: { iteration?: IterationLevel; ignoreIterationOnScalar?: boolean }
541
541
  ): boolean {
542
542
  const { iteration, ignoreIterationOnScalar } = opts;
543
- if (value === this.getSavedValue(iteration)) {
544
- return false;
545
- }
546
- // Decompose arrays, to only update items that changed
547
- if (Array.isArray(value) && !Array.isArray(iteration)) {
548
- return this.setValueForArray(value);
549
- }
550
- // We want to save a value at a specific iteration, but the value is not an array yet
543
+
544
+ // We want to save a value at a specific iteration
545
+ // but the value is not an array yet
546
+ // we have to initialize the array even if we want to set an `null` or `undefined` value
547
+ // (if no, issue with getCalculatedAt that check if this.value is an array, it return global updatedValue instead of the iteration one)
551
548
  if (iteration !== undefined && !Array.isArray(this.value)) {
552
549
  // Ignore the iteration since the value is not an array
553
550
  if (ignoreIterationOnScalar) {
554
551
  return this.setValue(value, {});
555
552
  }
553
+ // we have to set empty array at first before compare the with the SavedValue
556
554
  this.value = [];
557
555
  }
556
+
557
+ if (value === this.getSavedValue(iteration)) {
558
+ return false;
559
+ }
560
+ // Decompose arrays, to only update items that changed
561
+ if (Array.isArray(value) && !Array.isArray(iteration)) {
562
+ return this.setValueForArray(value);
563
+ }
564
+
558
565
  this.value = !Array.isArray(iteration)
559
566
  ? value
560
567
  : setAtIndex(this.value, iteration, value);
@@ -680,33 +687,21 @@ export class LunaticVariable {
680
687
  }
681
688
 
682
689
  public getUpdatedAt(iteration?: IterationLevel): number {
683
- if (this.dimension === 0) {
684
- return this.updatedAt.get(undefined) ?? 0;
685
- }
686
690
  // The value is an array, do not look at the root updatedAt if an iteration is provided
687
- if (Array.isArray(this.value)) {
688
- return this.updatedAt.get(iteration?.join('.')) ?? 0;
691
+ if (iteration !== undefined && Array.isArray(this.value)) {
692
+ return this.updatedAt.get(iteration.join('.')) ?? 0;
689
693
  }
690
- return (
691
- this.updatedAt.get(iteration?.join('.')) ??
692
- this.updatedAt.get(undefined) ??
693
- 0
694
- );
694
+ // undefined key is for root level
695
+ return this.updatedAt.get(undefined) ?? 0;
695
696
  }
696
697
 
697
698
  public getCalculatedAt(iteration?: IterationLevel): number {
698
- if (this.dimension === 0) {
699
- return this.calculatedAt.get(undefined) ?? 0;
699
+ // The value is an array, do not look at the root calculatedAt if an iteration is provided
700
+ if (iteration !== undefined && Array.isArray(this.value)) {
701
+ return this.calculatedAt.get(iteration.join('.')) ?? 0;
700
702
  }
701
- // The value is an array, do not look at the root updatedAt if an iteration is provided
702
- if (Array.isArray(this.value)) {
703
- return this.calculatedAt.get(iteration?.join('.')) ?? 0;
704
- }
705
- return (
706
- this.calculatedAt.get(iteration?.join('.')) ??
707
- this.calculatedAt.get(undefined) ??
708
- 0
709
- );
703
+ // undefined key is for root level
704
+ return this.calculatedAt.get(undefined) ?? 0;
710
705
  }
711
706
  }
712
707
 
@@ -188,46 +188,54 @@ describe('use-lunatic()', () => {
188
188
 
189
189
  describe('with loop', function () {
190
190
  const data = dataFromObject({
191
- ETAT: '1',
192
- SATISFAIT: '1',
193
191
  T_NHAB: 3,
194
192
  T_PRENOM: ['Quentin', 'Luna', 'Paul'],
195
- COMMCOMPO: 'super',
196
- T_SEXE: ['1', '2', '1'],
197
- T_DATENAIS: [null, null, null],
198
- REMARQUES: [null, 'a', 'b'],
199
- SUPERQUEST: ['ok', 'ok', null],
200
- AUTRESUPERQUEST: ['a', 'c', 'ras'],
201
- ENCOREUNEQ: ['wow', 'b', null],
202
- COMMENT_QE: null,
203
- ETAT_MISSING: null,
204
- SATISFAIT_MISSING: null,
205
- T_NHAB_MISSING: null,
206
- T_PRENOM_MISSING: null,
207
- COMMCOMPO_MISSING: null,
208
- T_SEXE_MISSING: null,
209
- T_DATENAIS_MISSING: [null, 'DK', 'RF'],
210
- REMARQUES_MISSING: [null, null, null],
211
- SUPERQUEST_MISSING: [null, null, 'DK'],
212
- ENCOREUNEQ_MISSING: [null, null, 'RF'],
213
- AUTRESUPERQUEST_MISSING: null,
214
- COMMENT_QE_MISSING: null,
215
193
  });
216
194
 
217
195
  it('should work with loop', async () => {
218
196
  const { result } = renderHook(() =>
219
197
  useLunatic(sourceOverview, data, lunaticConfiguration)
220
198
  );
221
- expect(result.current.overview).toMatchSnapshot();
199
+
200
+ // 4 sequences, and we loop twice on the second one
201
+ expect(result.current.overview.length).toBe(5);
202
+ expect(result.current.overview[0].label).toBe(
203
+ 'I - Habitants du logement'
204
+ );
205
+ expect(result.current.overview[0].page).toBe('1');
206
+ expect(result.current.overview[1].label).toBe(
207
+ 'II - Boucle sur séquence pour Luna (qui filtre la première itération)'
208
+ );
209
+ expect(result.current.overview[1].page).toBe('4.1#2');
210
+ expect(result.current.overview[2].label).toBe(
211
+ 'II - Boucle sur séquence pour Paul (qui filtre la première itération)'
212
+ );
213
+ expect(result.current.overview[2].page).toBe('4.1#3');
214
+
215
+ // 3rd sequence has only one subsequence, and we loop over it
216
+ expect(result.current.overview[3].children.length).toBe(2);
217
+ expect(result.current.overview[3].children[0].page).toBe('6.1#2');
218
+ expect(result.current.overview[3].children[1].page).toBe('6.1#3');
219
+
220
+ // It would be nice to test that each label is correct, currently we have issue about expression execution in subsequence in tests only.
222
221
  });
223
222
  it('should handle initialPage', async () => {
224
223
  const { result } = renderHook(() =>
225
224
  useLunatic(sourceOverview, data, {
226
225
  ...lunaticConfiguration,
227
- initialPage: '10.1#1',
226
+ initialPage: '6.1#2',
228
227
  })
229
228
  );
230
- expect(result.current.overview).toMatchSnapshot();
229
+
230
+ // 4 sequences, and we loop twice on the second one
231
+ expect(result.current.overview.length).toBe(5);
232
+ expect(result.current.overview[1].reached).toBe(true);
233
+ expect(result.current.overview[3].children[0].reached).toBe(true);
234
+ expect(result.current.overview[3].children[1].reached).toBe(false);
235
+ expect(result.current.overview[4].reached).toBe(false);
236
+
237
+ expect(result.current.overview[3].current).toBe(true);
238
+ expect(result.current.overview[3].children[0].current).toBe(true);
231
239
  });
232
240
  });
233
241
  });