From 316fb21c8ff114355b0ff4218e573dbdf83314aa Mon Sep 17 00:00:00 2001 From: Quentin Ruhier Date: Mon, 20 Apr 2026 17:06:38 +0200 Subject: [PATCH 1/3] fix: generate max length 249 for ucq (even in table) & mcq --- .../src/model/transformations/component.spec.jsx | 2 +- .../model/transformations/questionnaire.spec.jsx | 2 +- .../transformations/response-format-multiple.ts | 2 +- .../response-format-single.spec.ts | 6 +++--- .../transformations/response-format-single.ts | 2 +- .../transformations/response-format-table.jsx | 2 +- .../variables/collected-variables-multiple.js | 2 +- .../variables/collected-variables-single.js | 4 ++-- .../variables/collected-variables-single.spec.js | 16 ++++++++-------- .../utils/variables/collected-variables-table.js | 2 +- .../variables/collected-variables-table.spec.js | 6 +++--- legacy/src/vite-env.d.ts | 7 +++++++ 12 files changed, 30 insertions(+), 23 deletions(-) diff --git a/legacy/src/model/transformations/component.spec.jsx b/legacy/src/model/transformations/component.spec.jsx index 0cccf2e60..774f2a632 100644 --- a/legacy/src/model/transformations/component.spec.jsx +++ b/legacy/src/model/transformations/component.spec.jsx @@ -532,7 +532,7 @@ describe('component tranformations', () => { Datatype: { typeName: 'TEXT', type: 'TextDatatypeType', - MaxLength: 1, + MaxLength: 249, visualizationHint: 'DROPDOWN', }, id: 'my-q-pairwise-response-id', diff --git a/legacy/src/model/transformations/questionnaire.spec.jsx b/legacy/src/model/transformations/questionnaire.spec.jsx index d1707a7e6..460784919 100644 --- a/legacy/src/model/transformations/questionnaire.spec.jsx +++ b/legacy/src/model/transformations/questionnaire.spec.jsx @@ -304,7 +304,7 @@ describe('questionnaire', () => { CodeListReference: 'jf0w3fab', CollectedVariableReference: 'jf0vqq4j', Datatype: { - MaxLength: 1, + MaxLength: 249, type: 'TextDatatypeType', typeName: 'TEXT', visualizationHint: 'CHECKBOX', diff --git a/legacy/src/model/transformations/response-format-multiple.ts b/legacy/src/model/transformations/response-format-multiple.ts index 1a3c119ec..8677e7dbc 100644 --- a/legacy/src/model/transformations/response-format-multiple.ts +++ b/legacy/src/model/transformations/response-format-multiple.ts @@ -161,7 +161,7 @@ export function stateToRemote( typeName: DATATYPE_NAME.TEXT, visHint, choiceType, - maxLength: 1, + maxLength: 249, }; } else { responseState = { diff --git a/legacy/src/model/transformations/response-format-single.spec.ts b/legacy/src/model/transformations/response-format-single.spec.ts index 640d07c80..22ca52ba4 100644 --- a/legacy/src/model/transformations/response-format-single.spec.ts +++ b/legacy/src/model/transformations/response-format-single.spec.ts @@ -117,7 +117,7 @@ describe('stateToRemote', () => { CodeListReference: 'my-cl-id', CollectedVariableReference: 'my-var-id', Datatype: { - MaxLength: 1, + MaxLength: 249, type: 'TextDatatypeType', typeName: 'TEXT', visualizationHint: 'RADIO', @@ -147,7 +147,7 @@ describe('stateToRemote', () => { CodeListReference: 'my-cl-id', CollectedVariableReference: 'my-var-id', Datatype: { - MaxLength: 1, + MaxLength: 249, type: 'TextDatatypeType', typeName: 'TEXT', visualizationHint: 'SUGGESTER', @@ -177,7 +177,7 @@ describe('stateToRemote', () => { VariableReference: 'my-variable-id', CollectedVariableReference: 'my-var-id', Datatype: { - MaxLength: 1, + MaxLength: 249, type: 'TextDatatypeType', typeName: 'TEXT', visualizationHint: 'RADIO', diff --git a/legacy/src/model/transformations/response-format-single.ts b/legacy/src/model/transformations/response-format-single.ts index 0b9540bd7..616864253 100644 --- a/legacy/src/model/transformations/response-format-single.ts +++ b/legacy/src/model/transformations/response-format-single.ts @@ -146,7 +146,7 @@ export function stateToRemote( nomenclatureId, variableReferenceId, typeName: DATATYPE_NAME.TEXT, - maxLength: 1, + maxLength: 249, collectedVariable: collectedVariables[0], }), ], diff --git a/legacy/src/model/transformations/response-format-table.jsx b/legacy/src/model/transformations/response-format-table.jsx index 66f397596..8655b08c8 100644 --- a/legacy/src/model/transformations/response-format-table.jsx +++ b/legacy/src/model/transformations/response-format-table.jsx @@ -378,7 +378,7 @@ function stateToResponseState(state, primaryType) { nomenclatureId, variableReferenceId, typeName: TEXT, - maxLength: 1, + maxLength: 249, visHint, choiceType, }; diff --git a/legacy/src/utils/variables/collected-variables-multiple.js b/legacy/src/utils/variables/collected-variables-multiple.js index 4987fcd20..637b55405 100644 --- a/legacy/src/utils/variables/collected-variables-multiple.js +++ b/legacy/src/utils/variables/collected-variables-multiple.js @@ -45,7 +45,7 @@ export function getCollectedVariablesMultiple( codeListReference: form[MEASURE][CODES_LIST].CodesList.id, codeListReferenceLabel: form[MEASURE][CODES_LIST].CodesList.label, type: TEXT, - [TEXT]: { maxLength: 1 }, + [TEXT]: { maxLength: 249 }, }; } else { reponseFormatValues = { diff --git a/legacy/src/utils/variables/collected-variables-single.js b/legacy/src/utils/variables/collected-variables-single.js index 19dd799d9..25b45343a 100644 --- a/legacy/src/utils/variables/collected-variables-single.js +++ b/legacy/src/utils/variables/collected-variables-single.js @@ -38,7 +38,7 @@ export function getCollectedVariablesSingle( variableReferenceLabel: desiredVarLabel, type: TEXT, choiceType: form.choiceType, - [TEXT]: { maxLength: 1 }, + [TEXT]: { maxLength: 249 }, }, ); } else { @@ -50,7 +50,7 @@ export function getCollectedVariablesSingle( ...getReference(form), type: TEXT, choiceType: form.choiceType, - [TEXT]: { maxLength: 1 }, + [TEXT]: { maxLength: 249 }, }, ); } diff --git a/legacy/src/utils/variables/collected-variables-single.spec.js b/legacy/src/utils/variables/collected-variables-single.spec.js index daa11b719..5f81b841e 100644 --- a/legacy/src/utils/variables/collected-variables-single.spec.js +++ b/legacy/src/utils/variables/collected-variables-single.spec.js @@ -28,7 +28,7 @@ describe('getCollectedVariablesSingle', () => { codeListReferenceLabel: 'my-cl', choiceType: 'CODE_LIST', type: 'TEXT', - TEXT: { maxLength: 1 }, + TEXT: { maxLength: 249 }, }, ]); }); @@ -65,7 +65,7 @@ describe('getCollectedVariablesSingle', () => { codeListReference: 'my-cl-id', codeListReferenceLabel: 'my-cl', type: 'TEXT', - TEXT: { maxLength: 1 }, + TEXT: { maxLength: 249 }, }, { id: expect.any(String), @@ -124,7 +124,7 @@ describe('getCollectedVariablesSingle', () => { codeListReferenceLabel: 'my-cl', choiceType: 'CODE_LIST', type: 'TEXT', - TEXT: { maxLength: 1 }, + TEXT: { maxLength: 249 }, }, { id: 'var2', @@ -186,7 +186,7 @@ describe('getCollectedVariablesSingle', () => { codeListReferenceLabel: 'my-cl', choiceType: 'CODE_LIST', type: 'TEXT', - TEXT: { maxLength: 1 }, + TEXT: { maxLength: 249 }, }, { id: 'var2', @@ -246,7 +246,7 @@ describe('getCollectedVariablesSingle', () => { codeListReferenceLabel: 'my-cl', choiceType: 'CODE_LIST', type: 'TEXT', - TEXT: { maxLength: 1 }, + TEXT: { maxLength: 249 }, }, ]); }); @@ -269,7 +269,7 @@ describe('getCollectedVariablesSingle', () => { codeListReferenceLabel: 'my-nomenclature', choiceType: 'SUGGESTER', type: 'TEXT', - TEXT: { maxLength: 1 }, + TEXT: { maxLength: 249 }, }, { id: expect.any(String), @@ -301,7 +301,7 @@ describe('getCollectedVariablesSingle', () => { codeListReferenceLabel: 'my-nomenclature', choiceType: 'SUGGESTER', type: 'TEXT', - TEXT: { maxLength: 1 }, + TEXT: { maxLength: 249 }, }, ]); }); @@ -329,7 +329,7 @@ describe('getCollectedVariablesSingle', () => { variableReferenceLabel: 'my-variableRef', choiceType: 'VARIABLE', type: 'TEXT', - TEXT: { maxLength: 1 }, + TEXT: { maxLength: 249 }, }, ]); }); diff --git a/legacy/src/utils/variables/collected-variables-table.js b/legacy/src/utils/variables/collected-variables-table.js index 45b093b01..ed156f413 100644 --- a/legacy/src/utils/variables/collected-variables-table.js +++ b/legacy/src/utils/variables/collected-variables-table.js @@ -162,7 +162,7 @@ export function getReponsesValues(measure) { ? measure[SINGLE_CHOICE][listPath].label : '', type: TEXT, - [TEXT]: { maxLength: 1 }, + [TEXT]: { maxLength: 249 }, variableReference: choiceType === CHOICE_TYPE.VARIABLE ? measure[SINGLE_CHOICE][listPath].id diff --git a/legacy/src/utils/variables/collected-variables-table.spec.js b/legacy/src/utils/variables/collected-variables-table.spec.js index 56a6ba8ef..a23140583 100644 --- a/legacy/src/utils/variables/collected-variables-table.spec.js +++ b/legacy/src/utils/variables/collected-variables-table.spec.js @@ -393,7 +393,7 @@ describe('getReponsesValues', () => { variableReferenceLabel: '', choiceType: 'CODE_LIST', type: 'TEXT', - TEXT: { maxLength: 1 }, + TEXT: { maxLength: 249 }, }; expect(getReponsesValues(measure)).toEqual(output); @@ -433,7 +433,7 @@ describe('getReponsesValues', () => { variableReferenceLabel: 'my-variable-label', choiceType: 'VARIABLE', type: 'TEXT', - TEXT: { maxLength: 1 }, + TEXT: { maxLength: 249 }, }; expect(getReponsesValues(measure)).toEqual(output); @@ -467,7 +467,7 @@ describe('getReponsesValues', () => { variableReferenceLabel: '', choiceType: 'CODE_LIST', type: 'TEXT', - TEXT: { maxLength: 1 }, + TEXT: { maxLength: 249 }, }; expect(getReponsesValues(measure)).toEqual(output); diff --git a/legacy/src/vite-env.d.ts b/legacy/src/vite-env.d.ts index fe2ef5b90..18efaf4f0 100644 --- a/legacy/src/vite-env.d.ts +++ b/legacy/src/vite-env.d.ts @@ -8,6 +8,13 @@ type ImportMetaEnv = { VITE_OIDC_CLIENT_ID: string VITE_OIDC_SCOPES: string VITE_ENABLE_PAIRING_RECAP: string + VITE_ACTIVE_NAMESPACES: string + VITE_CUSTOMIZE_URL: string + VITE_TROMBI_URL: string + VITE_DEFAULT_USER_ID: string + VITE_DEFAULT_USER_NAME: string + VITE_DEFAULT_USER_STAMP: string + VITE_LOG_LEVEL: string BASE_URL: string MODE: string DEV: boolean From 71c65108d3ed1960fda245d2eb892fd67de285a2 Mon Sep 17 00:00:00 2001 From: Quentin Ruhier Date: Mon, 20 Apr 2026 17:15:36 +0200 Subject: [PATCH 2/3] docs: changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a2a73547..8629092bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Questionnaire loading no longer crash when a question uses a code list (or nomenclature) that does not exist anymore. It could happen when an existing question used a previous version of a nomenclature. - nginx.conf: disable cache on remote-entry (to ensure keeping last legacy version) +- For unique choice questions (inside or outside a table) and multiple choice questions, the variable max length is now 249 instead of 1. ### Changed From dec25c3eaaa86d46a138a445cd2d0d6f60f92a0d Mon Sep 17 00:00:00 2001 From: Quentin Ruhier Date: Tue, 21 Apr 2026 11:24:35 +0200 Subject: [PATCH 3/3] test: improve tests --- .../response-format-multiple.spec.ts | 128 ++++++++++++++++++ .../response-format-table.spec.jsx | 45 +++++- .../collected-variables-multiple.spec.js | 83 ++++++++++++ 3 files changed, 249 insertions(+), 7 deletions(-) diff --git a/legacy/src/model/transformations/response-format-multiple.spec.ts b/legacy/src/model/transformations/response-format-multiple.spec.ts index a4e07ada8..466f25efa 100644 --- a/legacy/src/model/transformations/response-format-multiple.spec.ts +++ b/legacy/src/model/transformations/response-format-multiple.spec.ts @@ -1,5 +1,12 @@ import { describe, expect, it } from 'vitest'; +import { + CHOICE_TYPE, + DATATYPE_VIS_HINT, + DEFAULT_CODES_LIST_SELECTOR_PATH, + DIMENSION_FORMATS, +} from '@/constants/pogues-constants'; + import { remoteToState, stateToRemote } from './response-format-multiple'; describe('response format multiple', () => { @@ -239,5 +246,126 @@ describe('response format multiple', () => { ], }); }); + + it('Correctly compute remote data for CODES_LIST measure type', () => { + const state = { + mandatory: true, + PRIMARY: { CodesList: { id: 'my-cl-id' } }, + MEASURE: { + type: DIMENSION_FORMATS.CODES_LIST, + [DIMENSION_FORMATS.CODES_LIST]: { + [DEFAULT_CODES_LIST_SELECTOR_PATH]: { id: 'codes-list-id' }, + choiceType: CHOICE_TYPE.CODE_LIST, + visHint: DATATYPE_VIS_HINT.RADIO, + }, + }, + }; + const collectedVariables = ['my-var-id-1', 'my-var-id-2']; + const collectedVariablesStore = { + 'my-var-id-2': { + BOOLEAN: {}, + DATE: undefined, + DURATION: undefined, + NUMERIC: undefined, + TEXT: { maxLength: 249 }, + codeListReference: 'codes-list-id', + codeListReferenceLabel: 'codes-list-label', + id: 'my-var-id-2', + isCollected: '1', + label: '2 - lib2', + mesureLevel: undefined, + name: 'QUESTIONTA2', + type: 'TEXT', + x: 2, + y: Number.NaN, + z: undefined, + }, + 'my-var-id-1': { + BOOLEAN: {}, + DATE: undefined, + DURATION: undefined, + NUMERIC: undefined, + TEXT: { maxLength: 249 }, + codeListReference: 'codes-list-id', + codeListReferenceLabel: 'codes-list-label', + id: 'my-var-id-1', + isCollected: '1', + label: '1 - lib1', + mesureLevel: undefined, + name: 'QUESTIONTA1', + type: 'TEXT', + x: 1, + y: Number.NaN, + z: undefined, + }, + }; + const response = [ + { + CollectedVariableReference: 'my-var-id-1', + Datatype: { + typeName: 'TEXT', + type: 'TextDatatypeType', + }, + id: 'my-response-id-1', + }, + { + CollectedVariableReference: 'my-var-id-2', + Datatype: { + typeName: 'TEXT', + type: 'TextDatatypeType', + }, + id: 'my-response-id-2', + }, + ]; + + const output = stateToRemote( + state, + collectedVariables, + collectedVariablesStore, + response, + ); + + expect(output).toEqual({ + Attribute: [], + Dimension: [ + { + CodeListReference: 'my-cl-id', + dimensionType: 'PRIMARY', + dynamic: 'NON_DYNAMIC', + }, + { dimensionType: 'MEASURE' }, + ], + Mapping: [ + { MappingSource: 'my-response-id-1', MappingTarget: '1' }, + { MappingSource: 'my-response-id-2', MappingTarget: '2' }, + ], + Response: [ + { + id: 'my-response-id-1', + CollectedVariableReference: 'my-var-id-1', + Datatype: { + type: 'TextDatatypeType', + typeName: 'TEXT', + MaxLength: 249, + visualizationHint: DATATYPE_VIS_HINT.RADIO, + }, + choiceType: CHOICE_TYPE.CODE_LIST, + CodeListReference: 'codes-list-id', + }, + { + id: 'my-response-id-2', + CollectedVariableReference: 'my-var-id-2', + Datatype: { + type: 'TextDatatypeType', + typeName: 'TEXT', + MaxLength: 249, + visualizationHint: DATATYPE_VIS_HINT.RADIO, + }, + choiceType: CHOICE_TYPE.CODE_LIST, + CodeListReference: 'codes-list-id', + }, + ], + }); + }); }); }); diff --git a/legacy/src/model/transformations/response-format-table.spec.jsx b/legacy/src/model/transformations/response-format-table.spec.jsx index 32aa17db0..9f3837cd4 100644 --- a/legacy/src/model/transformations/response-format-table.spec.jsx +++ b/legacy/src/model/transformations/response-format-table.spec.jsx @@ -647,7 +647,7 @@ describe('stateToRemote', () => { const state = { PRIMARY: { type: 'CODES_LIST', - CODES_LIST: { CodesList: { id: 'jf0vbzj9' } }, + CODES_LIST: { CodesList: { id: 'jf0vbzj9', label: 'my-code-list-1' } }, }, LIST_MEASURE: [ { @@ -658,8 +658,12 @@ describe('stateToRemote', () => { }, { label: 'measure 2', - type: 'SIMPLE', - SIMPLE: { type: 'TEXT', TEXT: { maxLength: 249 } }, + type: 'SINGLE_CHOICE', + SINGLE_CHOICE: { + CodesList: { id: 'mlz1qdq0', label: 'my-code-list-2' }, + choiceType: 'CODE_LIST', + visHint: 'RADIO', + }, }, ], }; @@ -712,8 +716,8 @@ describe('stateToRemote', () => { DATE: { maximum: '', minimum: '', format: '' }, BOOLEAN: {}, isCollected: '0', - codeListReference: '', - codeListReferenceLabel: '', + codeListReference: 'mlz1qdq0', + codeListReferenceLabel: 'my-code-list-2', }, jk8h32gm: { id: 'jk8h32gm', @@ -728,8 +732,8 @@ describe('stateToRemote', () => { DATE: { maximum: '', minimum: '', format: '' }, BOOLEAN: {}, isCollected: '0', - codeListReference: '', - codeListReferenceLabel: '', + codeListReference: 'mlz1qdq0', + codeListReferenceLabel: 'my-code-list-2', }, }; const result = stateToRemote( @@ -783,6 +787,7 @@ describe('stateToRemote', () => { expect(item.conditionFilter).toBeUndefined(); }); + // measure 1 : simple response expect(outputResponse[0].Datatype).toEqual({ MaxLength: 249, type: 'TextDatatypeType', @@ -796,6 +801,32 @@ describe('stateToRemote', () => { }); expect(outputMapping[0].MappingTarget).toEqual('1 1'); expect(outputMapping[1].MappingTarget).toEqual('2 1'); + + // measure 2 : single response (codeList, radio) + expect(outputResponse[2]).toEqual({ + id: expect.anything(), + Datatype: { + typeName: 'TEXT', + type: 'TextDatatypeType', + visualizationHint: 'RADIO', + MaxLength: 249, + }, + choiceType: 'CODE_LIST', + CodeListReference: 'mlz1qdq0', + CollectedVariableReference: 'jg4v561m', + }); + expect(outputResponse[3]).toEqual({ + id: expect.anything(), + Datatype: { + typeName: 'TEXT', + type: 'TextDatatypeType', + visualizationHint: 'RADIO', + MaxLength: 249, + }, + choiceType: 'CODE_LIST', + CodeListReference: 'mlz1qdq0', + CollectedVariableReference: 'jk8h32gm', + }); }); it('works with non dynamic table, with secondary axes', () => { diff --git a/legacy/src/utils/variables/collected-variables-multiple.spec.js b/legacy/src/utils/variables/collected-variables-multiple.spec.js index 7032a570f..149873c74 100644 --- a/legacy/src/utils/variables/collected-variables-multiple.spec.js +++ b/legacy/src/utils/variables/collected-variables-multiple.spec.js @@ -248,4 +248,87 @@ describe('getCollectedVariablesMultiple', () => { }, ]); }); + + test('computes variables when typeMeasure is CODES_LIST', () => { + const questionName = 'questionName'; + const form = { + PRIMARY: { + CodesList: { + id: 'id', + label: 'label', + codes: [ + { + value: 'value1', + label: 'label1', + weight: 1, + }, + { + value: 'value2', + label: 'label2', + weight: 2, + }, + ], + }, + }, + MEASURE: { + type: 'CODES_LIST', + CODES_LIST: { + CodesList: { + id: 'codesListId', + label: 'codesListLabel', + }, + }, + }, + }; + const codesListStore = { + id: { + id: 'id', + label: 'label', + codes: [ + { + value: 'value1', + label: 'label1', + weight: 1, + }, + { + value: 'value2', + label: 'label2', + weight: 2, + }, + ], + }, + }; + const result = getCollectedVariablesMultiple( + questionName, + form, + codesListStore, + ); + + expect(result).toEqual([ + { + type: 'TEXT', + TEXT: { maxLength: 249 }, + id: result[0].id, + name: 'questionName1', + label: 'value1 - label1', + x: 1, + isCollected: '1', + alternativeLabel: '', + codeListReference: 'codesListId', + codeListReferenceLabel: 'codesListLabel', + }, + { + type: 'TEXT', + TEXT: { maxLength: 249 }, + id: result[1].id, + name: 'questionName2', + label: 'value2 - label2', + x: 2, + isCollected: '1', + alternativeLabel: '', + codeListReference: 'codesListId', + codeListReferenceLabel: 'codesListLabel', + }, + ]); + }); });