@inseefr/lunatic 3.4.13-rc.0 → 3.4.14

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.
@@ -103,6 +103,7 @@ export type ComponentPropsByType = {
103
103
  components: LunaticComponentProps[];
104
104
  componentType?: 'Question';
105
105
  iteration?: number;
106
+ value: Record<string, unknown>;
106
107
  };
107
108
  RosterForLoop: LunaticBaseProps<unknown> & LunaticExtraProps & {
108
109
  lines: {
@@ -103,6 +103,7 @@ export type ComponentPropsByType = {
103
103
  components: LunaticComponentProps[];
104
104
  componentType?: 'Question';
105
105
  iteration?: number;
106
+ value: Record<string, unknown>;
106
107
  };
107
108
  RosterForLoop: LunaticBaseProps<unknown> & LunaticExtraProps & {
108
109
  lines: {
@@ -5,44 +5,54 @@ import { isObject } from '../../utils/is-object';
5
5
  */
6
6
  export function usePageHasResponse(components, executeExpression) {
7
7
  return useCallback(() => {
8
- var _a;
9
- if (!Array.isArray(components) || components.length === 0) {
8
+ return hasOneResponse(components, executeExpression);
9
+ }, [components, executeExpression]);
10
+ }
11
+ function hasOneResponse(components, executeExpression) {
12
+ var _a;
13
+ if (!Array.isArray(components) || components.length === 0) {
14
+ return true;
15
+ }
16
+ for (const component of components) {
17
+ // Some components are considered as "filled" by default
18
+ // We assume they are not in the same page has other components
19
+ if (['PairwiseLinks', 'Roundabout', 'Sequence', 'Subsequence'].includes((_a = component.componentType) !== null && _a !== void 0 ? _a : '')) {
10
20
  return true;
11
21
  }
12
- for (const component of components) {
13
- // Some components are considered as "filled" by default
14
- // We assume they are not in the same page has other components
15
- if (['PairwiseLinks', 'Roundabout', 'Sequence', 'Subsequence'].includes((_a = component.componentType) !== null && _a !== void 0 ? _a : '')) {
16
- return true;
17
- }
18
- // We have a missing response for this component
19
- if ('missingResponse' in component &&
20
- component.missingResponse &&
21
- component.missingResponse.value) {
22
- return true;
23
- }
24
- // For Table, we have to extract components from its body and apply isSubComponentsEmpty function
25
- if (component.componentType === 'Table') {
26
- // Body is array for array (row), each "cell" could be an Label or Component, so we filter array.
27
- const childrenComponent = component.body.reduce((_, row) => {
28
- const componentsInRow = row.filter((cell) => isObject(cell) && 'componentType' in cell);
29
- return [..._, ...componentsInRow];
30
- }, []);
31
- return !isSubComponentsEmpty(childrenComponent, executeExpression);
32
- }
33
- // We found a value in one of the root component
34
- if ('value' in component && !isEmpty(component.value)) {
35
- return true;
36
- }
37
- // For rosterForLoop we need to inspect child components
38
- if ('components' in component &&
39
- Array.isArray(component.components) &&
40
- !isSubComponentsEmpty(component.components, executeExpression)) {
41
- return true;
42
- }
22
+ // We have a missing response for this component
23
+ if ('missingResponse' in component &&
24
+ component.missingResponse &&
25
+ component.missingResponse.value) {
26
+ return true;
43
27
  }
44
- return false;
45
- }, [components, executeExpression]);
28
+ // For Table, we have to extract components from its body and apply isSubComponentsEmpty function
29
+ if (component.componentType === 'Table') {
30
+ // Body is array for array (row), each "cell" could be an Label or Component, so we filter array.
31
+ const childrenComponent = component.body.reduce((_, row) => {
32
+ const componentsInRow = row.filter((cell) => isObject(cell) && 'componentType' in cell);
33
+ return [..._, ...componentsInRow];
34
+ }, []);
35
+ return !isSubComponentsEmpty(childrenComponent, executeExpression);
36
+ }
37
+ // We found a value in one of the root component
38
+ if ('value' in component && !isEmpty(component.value)) {
39
+ return true;
40
+ }
41
+ // For Question, we need to check subcomponents
42
+ if (component.componentType === 'Question' &&
43
+ 'components' in component &&
44
+ Array.isArray(component.components) &&
45
+ hasOneResponse(component.components, executeExpression)) {
46
+ return true;
47
+ }
48
+ // For rosterForLoop we need to inspect child components
49
+ if ('components' in component &&
50
+ Array.isArray(component.components) &&
51
+ !isSubComponentsEmpty(component.components, executeExpression)) {
52
+ return true;
53
+ }
54
+ }
55
+ return false;
46
56
  }
47
57
  /**
48
58
  * Check if a value is empty.
@@ -1 +1 @@
1
- {"version":3,"file":"use-page-has-response.js","sourceRoot":"","sources":["../../../src/use-lunatic/hooks/use-page-has-response.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"use-page-has-response.js","sourceRoot":"","sources":["../../../src/use-lunatic/hooks/use-page-has-response.ts"],"names":[],"mappings":"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"}
@@ -188,6 +188,7 @@ export declare function getComponentTypeProps(component: DeepTranslateExpression
188
188
  components: import("../..").LunaticComponentProps[];
189
189
  componentType?: "Question";
190
190
  iteration?: number;
191
+ value: Record<string, unknown>;
191
192
  } & {
192
193
  conditionFilter?: boolean;
193
194
  }) | (import("../../components/type").LunaticBaseProps<string | null> & import("../..").LunaticExtraProps & {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inseefr/lunatic",
3
- "version": "3.4.13-rc.0",
3
+ "version": "3.4.14",
4
4
  "description": "Library of questionnaire components",
5
5
  "repository": {
6
6
  "type": "git",
@@ -414,6 +414,7 @@
414
414
  "src/use-lunatic/commons/variables/lunatic-variables-store.spec.ts",
415
415
  "src/use-lunatic/commons/variables/lunatic-variables-store.ts",
416
416
  "src/use-lunatic/hooks/use-loop-variables.ts",
417
+ "src/use-lunatic/hooks/use-page-has-response.test.ts",
417
418
  "src/use-lunatic/hooks/use-page-has-response.ts",
418
419
  "src/use-lunatic/hooks/useOverview.ts",
419
420
  "src/use-lunatic/hooks/useWarnDepChange.ts",
@@ -126,6 +126,7 @@ export type ComponentPropsByType = {
126
126
  components: LunaticComponentProps[];
127
127
  componentType?: 'Question';
128
128
  iteration?: number;
129
+ value: Record<string, unknown>;
129
130
  };
130
131
  RosterForLoop: LunaticBaseProps<unknown> &
131
132
  LunaticExtraProps & {
@@ -0,0 +1,143 @@
1
+ import { describe, expect, it, vi } from 'vitest';
2
+ import { usePageHasResponse } from './use-page-has-response';
3
+ import { type LunaticComponentProps } from '../../components/type';
4
+ import { renderHook } from '@testing-library/react';
5
+
6
+ const defaultComponentValues = {
7
+ id: 'a',
8
+ value: null,
9
+ handleChanges: vi.fn(),
10
+ };
11
+
12
+ describe('usePageHasResponse', () => {
13
+ it('should be true when there are no components', () => {
14
+ const components: LunaticComponentProps[] = [];
15
+ const { result } = renderHook(() =>
16
+ usePageHasResponse(components, vi.fn())
17
+ );
18
+ expect(result.current()).toBeTruthy();
19
+ });
20
+
21
+ it('should be false when there is no value', () => {
22
+ const components: LunaticComponentProps[] = [
23
+ { ...defaultComponentValues, componentType: 'Text' },
24
+ ];
25
+ const { result } = renderHook(() =>
26
+ usePageHasResponse(components, vi.fn())
27
+ );
28
+ expect(result.current()).toBeFalsy();
29
+ });
30
+
31
+ it('should be true when there is a value', () => {
32
+ const components: LunaticComponentProps[] = [
33
+ {
34
+ ...defaultComponentValues,
35
+ componentType: 'Text',
36
+ value: 'my awesome value',
37
+ },
38
+ ];
39
+ const { result } = renderHook(() =>
40
+ usePageHasResponse(components, vi.fn())
41
+ );
42
+ expect(result.current()).toBeTruthy();
43
+ });
44
+
45
+ it('should be true for a Question component', () => {
46
+ const components: LunaticComponentProps[] = [
47
+ {
48
+ ...defaultComponentValues,
49
+ componentType: 'Question',
50
+ components: [
51
+ {
52
+ ...defaultComponentValues,
53
+ componentType: 'Text',
54
+ },
55
+ ],
56
+ value: { t1: 'my awesome value' },
57
+ },
58
+ ];
59
+ const { result } = renderHook(() =>
60
+ usePageHasResponse(components, vi.fn())
61
+ );
62
+ expect(result.current()).toBeTruthy();
63
+ });
64
+
65
+ it('should be true when there is a missing response', () => {
66
+ const components: LunaticComponentProps[] = [
67
+ {
68
+ ...defaultComponentValues,
69
+ componentType: 'Text',
70
+ missingResponse: { name: 'a_MISSING', value: 'my missing value' },
71
+ },
72
+ ];
73
+ const { result } = renderHook(() =>
74
+ usePageHasResponse(components, vi.fn())
75
+ );
76
+ expect(result.current()).toBeTruthy();
77
+ });
78
+
79
+ it('should be true for a QCM table', () => {
80
+ const mockExecuteExpression = vi.fn();
81
+ mockExecuteExpression.mockReturnValueOnce('my value');
82
+ const components: LunaticComponentProps[] = [
83
+ {
84
+ ...defaultComponentValues,
85
+ componentType: 'Table',
86
+ body: [
87
+ [
88
+ {
89
+ ...defaultComponentValues,
90
+ id: 't1',
91
+ componentType: 'CheckboxBoolean',
92
+ response: { name: 't1' },
93
+ },
94
+ ],
95
+ ],
96
+ header: [{ label: 'my label' }],
97
+ executeExpression: vi.fn(),
98
+ iteration: 0,
99
+ value: {},
100
+ },
101
+ ];
102
+ const { result } = renderHook(() =>
103
+ usePageHasResponse(components, mockExecuteExpression)
104
+ );
105
+ expect(result.current()).toBeTruthy();
106
+ });
107
+
108
+ it('should be true for a QCM table in a Question', () => {
109
+ const mockExecuteExpression = vi.fn();
110
+ mockExecuteExpression.mockReturnValueOnce('my value');
111
+ const components: LunaticComponentProps[] = [
112
+ {
113
+ ...defaultComponentValues,
114
+ componentType: 'Question',
115
+ components: [
116
+ {
117
+ ...defaultComponentValues,
118
+ componentType: 'Table',
119
+ body: [
120
+ [
121
+ {
122
+ ...defaultComponentValues,
123
+ id: 't1',
124
+ componentType: 'CheckboxBoolean',
125
+ response: { name: 't1' },
126
+ },
127
+ ],
128
+ ],
129
+ header: [{ label: 'my label' }],
130
+ executeExpression: vi.fn(),
131
+ iteration: 0,
132
+ value: { t1: true },
133
+ },
134
+ ],
135
+ value: {},
136
+ },
137
+ ];
138
+ const { result } = renderHook(() =>
139
+ usePageHasResponse(components, mockExecuteExpression)
140
+ );
141
+ expect(result.current()).toBeTruthy();
142
+ });
143
+ });
@@ -11,59 +11,76 @@ export function usePageHasResponse(
11
11
  executeExpression: LunaticReducerState['executeExpression']
12
12
  ): () => boolean {
13
13
  return useCallback(() => {
14
- if (!Array.isArray(components) || components.length === 0) {
14
+ return hasOneResponse(components, executeExpression);
15
+ }, [components, executeExpression]);
16
+ }
17
+
18
+ function hasOneResponse(
19
+ components: LunaticComponentProps[],
20
+ executeExpression: LunaticReducerState['executeExpression']
21
+ ): boolean {
22
+ if (!Array.isArray(components) || components.length === 0) {
23
+ return true;
24
+ }
25
+
26
+ for (const component of components) {
27
+ // Some components are considered as "filled" by default
28
+ // We assume they are not in the same page has other components
29
+ if (
30
+ ['PairwiseLinks', 'Roundabout', 'Sequence', 'Subsequence'].includes(
31
+ component.componentType ?? ''
32
+ )
33
+ ) {
15
34
  return true;
16
35
  }
17
36
 
18
- for (const component of components) {
19
- // Some components are considered as "filled" by default
20
- // We assume they are not in the same page has other components
21
- if (
22
- ['PairwiseLinks', 'Roundabout', 'Sequence', 'Subsequence'].includes(
23
- component.componentType ?? ''
24
- )
25
- ) {
26
- return true;
27
- }
37
+ // We have a missing response for this component
38
+ if (
39
+ 'missingResponse' in component &&
40
+ component.missingResponse &&
41
+ component.missingResponse.value
42
+ ) {
43
+ return true;
44
+ }
28
45
 
29
- // We have a missing response for this component
30
- if (
31
- 'missingResponse' in component &&
32
- component.missingResponse &&
33
- component.missingResponse.value
34
- ) {
35
- return true;
36
- }
46
+ // For Table, we have to extract components from its body and apply isSubComponentsEmpty function
47
+ if (component.componentType === 'Table') {
48
+ // Body is array for array (row), each "cell" could be an Label or Component, so we filter array.
49
+ const childrenComponent = component.body.reduce((_, row) => {
50
+ const componentsInRow = row.filter(
51
+ (cell) => isObject(cell) && 'componentType' in cell
52
+ );
53
+ return [..._, ...componentsInRow];
54
+ }, [] as LunaticComponentProps[]);
55
+ return !isSubComponentsEmpty(childrenComponent, executeExpression);
56
+ }
37
57
 
38
- // For Table, we have to extract components from its body and apply isSubComponentsEmpty function
39
- if (component.componentType === 'Table') {
40
- // Body is array for array (row), each "cell" could be an Label or Component, so we filter array.
41
- const childrenComponent = component.body.reduce((_, row) => {
42
- const componentsInRow = row.filter(
43
- (cell) => isObject(cell) && 'componentType' in cell
44
- );
45
- return [..._, ...componentsInRow];
46
- }, [] as LunaticComponentProps[]);
47
- return !isSubComponentsEmpty(childrenComponent, executeExpression);
48
- }
58
+ // We found a value in one of the root component
59
+ if ('value' in component && !isEmpty(component.value)) {
60
+ return true;
61
+ }
49
62
 
50
- // We found a value in one of the root component
51
- if ('value' in component && !isEmpty(component.value)) {
52
- return true;
53
- }
63
+ // For Question, we need to check subcomponents
64
+ if (
65
+ component.componentType === 'Question' &&
66
+ 'components' in component &&
67
+ Array.isArray(component.components) &&
68
+ hasOneResponse(component.components, executeExpression)
69
+ ) {
70
+ return true;
71
+ }
54
72
 
55
- // For rosterForLoop we need to inspect child components
56
- if (
57
- 'components' in component &&
58
- Array.isArray(component.components) &&
59
- !isSubComponentsEmpty(component.components, executeExpression)
60
- ) {
61
- return true;
62
- }
73
+ // For rosterForLoop we need to inspect child components
74
+ if (
75
+ 'components' in component &&
76
+ Array.isArray(component.components) &&
77
+ !isSubComponentsEmpty(component.components, executeExpression)
78
+ ) {
79
+ return true;
63
80
  }
81
+ }
64
82
 
65
- return false;
66
- }, [components, executeExpression]);
83
+ return false;
67
84
  }
68
85
 
69
86
  /**