diff --git a/.github/workflows/build_test_lint.yml b/.github/workflows/build_test_lint.yml index ef1065150..1495888f5 100644 --- a/.github/workflows/build_test_lint.yml +++ b/.github/workflows/build_test_lint.yml @@ -153,7 +153,6 @@ jobs: - name: Build workspace packages run: | npm run build -w packages/sdc-populate - npm run build -w packages/testing-toolkit - name: Install Playwright browsers run: npx playwright install --with-deps diff --git a/apps/smart-forms-app/package.json b/apps/smart-forms-app/package.json index cb51064fd..574ce2f7a 100644 --- a/apps/smart-forms-app/package.json +++ b/apps/smart-forms-app/package.json @@ -28,7 +28,6 @@ "@aehrc/sdc-populate": "^4.6.2", "@aehrc/sdc-template-extract": "^1.0.9", "@aehrc/smart-forms-renderer": "^1.0.0-alpha.107", - "@aehrc/testing-toolkit": "^1.0.0", "@dnd-kit/core": "^6.3.1", "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.1", diff --git a/package-lock.json b/package-lock.json index fae05c761..dff1c1d1c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -34,7 +34,6 @@ "@aehrc/sdc-populate": "^4.6.2", "@aehrc/sdc-template-extract": "^1.0.9", "@aehrc/smart-forms-renderer": "^1.0.0-alpha.107", - "@aehrc/testing-toolkit": "^1.0.0", "@dnd-kit/core": "^6.3.1", "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.1", @@ -1071,10 +1070,6 @@ "resolved": "packages/smart-forms-renderer", "link": true }, - "node_modules/@aehrc/testing-toolkit": { - "resolved": "packages/testing-toolkit", - "link": true - }, "node_modules/@algolia/abtesting": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@algolia/abtesting/-/abtesting-1.3.0.tgz", @@ -12118,6 +12113,7 @@ "version": "10.4.0", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz", "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==", + "dev": true, "peer": true, "dependencies": { "@babel/code-frame": "^7.10.4", @@ -12163,6 +12159,7 @@ "version": "16.3.0", "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.3.0.tgz", "integrity": "sha512-kFSyxiEDwv1WLl2fgsq6pPBbw5aWKrsY2/noi1Id0TK0UParSF62oFQFGHXIyaG4pp2tEub/Zlel+fjjZILDsw==", + "dev": true, "license": "MIT", "dependencies": { "@babel/runtime": "^7.12.5" @@ -12244,6 +12241,7 @@ "version": "5.0.4", "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "dev": true, "peer": true }, "node_modules/@types/babel__core": { @@ -12797,7 +12795,7 @@ "version": "18.3.7", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", - "devOptional": true, + "dev": true, "license": "MIT", "peerDependencies": { "@types/react": "^18.0.0" @@ -14143,6 +14141,7 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, "dependencies": { "dequal": "^2.0.3" } @@ -18018,6 +18017,7 @@ "version": "0.5.16", "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "dev": true, "peer": true }, "node_modules/dom-converter": { @@ -25598,6 +25598,7 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "dev": true, "peer": true, "bin": { "lz-string": "bin/bin.js" @@ -32135,6 +32136,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, "peer": true, "dependencies": { "ansi-regex": "^5.0.1", @@ -32149,6 +32151,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, "peer": true, "engines": { "node": ">=10" @@ -32161,6 +32164,7 @@ "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true, "peer": true }, "node_modules/pretty-time": { @@ -41210,21 +41214,6 @@ "url": "https://opencollective.com/unified" } }, - "packages/testing-toolkit": { - "name": "@aehrc/testing-toolkit", - "version": "1.0.0", - "license": "Apache-2.0", - "dependencies": { - "@testing-library/react": "^16.3.0" - }, - "devDependencies": { - "zustand": "^5.0.8" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, "services/assemble-express": { "version": "2.0.0", "license": "Apache-2.0", diff --git a/packages/smart-forms-renderer/src/components/FormComponents/QuantityItem/QuantityUnitField.tsx b/packages/smart-forms-renderer/src/components/FormComponents/QuantityItem/QuantityUnitField.tsx index b8e9b0577..ece4da84b 100644 --- a/packages/smart-forms-renderer/src/components/FormComponents/QuantityItem/QuantityUnitField.tsx +++ b/packages/smart-forms-renderer/src/components/FormComponents/QuantityItem/QuantityUnitField.tsx @@ -55,7 +55,12 @@ function QuantityUnitField(props: QuantityUnitFieldProps) { readOnly={readOnly && readOnlyVisualStyle === 'readonly'} size="small" renderInput={(params) => ( - + )} /> ); diff --git a/packages/smart-forms-renderer/src/stories/assets/questionnaires/QBehaviorCalculations.ts b/packages/smart-forms-renderer/src/stories/assets/questionnaires/QBehaviorCalculations.ts index eb887559c..272722697 100644 --- a/packages/smart-forms-renderer/src/stories/assets/questionnaires/QBehaviorCalculations.ts +++ b/packages/smart-forms-renderer/src/stories/assets/questionnaires/QBehaviorCalculations.ts @@ -104,105 +104,6 @@ export const qInitialExpression: Questionnaire = { ] }; -export const qCalculatedExpressionBMICalculator: Questionnaire = { - resourceType: 'Questionnaire', - id: 'CalculatedExpressionBMICalculator', - name: 'CalculatedExpressionBMICalculator', - title: 'Calculated Expression BMI Calculator', - version: '0.1.0', - status: 'draft', - publisher: 'AEHRC CSIRO', - date: '2024-05-01', - url: 'https://smartforms.csiro.au/docs/behavior/choice-restrictions/calculated-expression-1', - item: [ - { - linkId: 'bmi-calculation', - text: 'BMI Calculation', - type: 'group', - repeats: false, - extension: [ - { - url: 'http://hl7.org/fhir/StructureDefinition/variable', - valueExpression: { - name: 'height', - language: 'text/fhirpath', - expression: "item.where(linkId='patient-height').answer.value" - } - }, - { - url: 'http://hl7.org/fhir/StructureDefinition/variable', - valueExpression: { - name: 'weight', - language: 'text/fhirpath', - expression: "item.where(linkId='patient-weight').answer.value" - } - } - ], - item: [ - { - extension: [ - { - url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-unit', - valueCoding: { - system: 'http://unitsofmeasure.org', - code: 'cm', - display: 'cm' - } - } - ], - linkId: 'patient-height', - text: 'Height', - type: 'decimal', - repeats: false, - readOnly: false - }, - { - extension: [ - { - url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-unit', - valueCoding: { - system: 'http://unitsofmeasure.org', - code: 'kg', - display: 'kg' - } - } - ], - linkId: 'patient-weight', - text: 'Weight', - type: 'decimal', - repeats: false, - readOnly: false - }, - { - extension: [ - { - url: 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-calculatedExpression', - valueExpression: { - description: 'BMI calculation', - language: 'text/fhirpath', - expression: '(%weight/((%height/100).power(2))).round(1)' - } - }, - { - url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-unit', - valueCoding: { - system: 'http://unitsofmeasure.org', - code: 'kg/m2', - display: 'kg/m2' - } - } - ], - linkId: 'bmi-result', - text: 'Value', - type: 'decimal', - repeats: false, - readOnly: true - } - ] - } - ] -}; - export const qCalculatedExpressionCvdRiskCalculator: Questionnaire = { resourceType: 'Questionnaire', id: 'CalculatedExpressionCvdRiskCalculator', diff --git a/packages/smart-forms-renderer/src/stories/assets/questionnaires/QBoolean.ts b/packages/smart-forms-renderer/src/stories/assets/questionnaires/QBoolean.ts index 3d27dd5e4..1ff0aa4ff 100644 --- a/packages/smart-forms-renderer/src/stories/assets/questionnaires/QBoolean.ts +++ b/packages/smart-forms-renderer/src/stories/assets/questionnaires/QBoolean.ts @@ -103,78 +103,3 @@ export const qrBooleanCheckboxResponse: QuestionnaireResponse = { ], questionnaire: 'https://smartforms.csiro.au/docs/components/boolean/checkbox' }; - -export const qBooleanCalculation: Questionnaire = { - resourceType: 'Questionnaire', - id: 'BooleanCalculation', - name: 'BooleanCalculation', - title: 'Boolean Calculation', - version: '0.1.0', - status: 'draft', - publisher: 'AEHRC CSIRO', - date: '2024-05-01', - url: 'https://smartforms.csiro.au/docs/components/boolean/calculation', - extension: [ - { - url: 'http://hl7.org/fhir/StructureDefinition/variable', - valueExpression: { - name: 'gender', - language: 'text/fhirpath', - expression: "item.where(linkId = 'gender-controller').answer.valueCoding.code" - } - } - ], - item: [ - { - linkId: 'gender-controller', - text: 'Gender', - type: 'choice', - repeats: false, - answerOption: [ - { - valueCoding: { - system: 'http://hl7.org/fhir/administrative-gender', - code: 'female', - display: 'Female' - } - }, - { - valueCoding: { - system: 'http://hl7.org/fhir/administrative-gender', - code: 'male', - display: 'Male' - } - }, - { - valueCoding: { - system: 'http://hl7.org/fhir/administrative-gender', - code: 'other', - display: 'Other' - } - }, - { - valueCoding: { - system: 'http://hl7.org/fhir/administrative-gender', - code: 'unknown', - display: 'Unknown' - } - } - ] - }, - { - extension: [ - { - url: 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-calculatedExpression', - valueExpression: { - language: 'text/fhirpath', - expression: "%gender = 'female'" - } - } - ], - linkId: 'gender-is-female', - text: 'Gender is female?', - type: 'boolean', - readOnly: true - } - ] -}; diff --git a/packages/smart-forms-renderer/src/stories/assets/questionnaires/QChoice.ts b/packages/smart-forms-renderer/src/stories/assets/questionnaires/QChoice.ts index 7ce55921a..d1519e677 100644 --- a/packages/smart-forms-renderer/src/stories/assets/questionnaires/QChoice.ts +++ b/packages/smart-forms-renderer/src/stories/assets/questionnaires/QChoice.ts @@ -136,362 +136,6 @@ export const qrChoiceAnswerValueSetBasicResponse: QuestionnaireResponse = { questionnaire: 'https://smartforms.csiro.au/docs/components/choice/answervalueset-basic' }; -export const qChoiceAnswerOptionCalculation: Questionnaire = { - resourceType: 'Questionnaire', - id: 'ChoiceAnswerOptionCalculation', - name: 'ChoiceAnswerOptionCalculation', - title: 'Choice AnswerOption Calculation', - version: '0.1.0', - status: 'draft', - publisher: 'AEHRC CSIRO', - date: '2024-05-01', - url: 'https://smartforms.csiro.au/docs/components/choice/answeroption-calculation', - extension: [ - { - url: 'http://hl7.org/fhir/StructureDefinition/variable', - valueExpression: { - name: 'painLevel', - language: 'text/fhirpath', - expression: "item.where(linkId = 'pain-level').answer.value" - } - } - ], - item: [ - { - extension: [ - { - url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl', - valueCodeableConcept: { - coding: [ - { - system: 'http://hl7.org/fhir/questionnaire-item-control', - code: 'slider' - } - ] - } - }, - { - url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-sliderStepValue', - valueInteger: 1 - }, - { - url: 'http://hl7.org/fhir/StructureDefinition/minValue', - valueInteger: 0 - }, - { - url: 'http://hl7.org/fhir/StructureDefinition/maxValue', - valueInteger: 10 - } - ], - linkId: 'pain-level', - text: 'Pain level', - type: 'integer', - repeats: false, - item: [ - { - extension: [ - { - url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl', - valueCodeableConcept: { - coding: [ - { - system: 'http://hl7.org/fhir/questionnaire-item-control', - code: 'lower' - } - ] - } - } - ], - linkId: 'pain-level-lower', - text: 'No pain', - type: 'display' - }, - { - extension: [ - { - url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl', - valueCodeableConcept: { - coding: [ - { - system: 'http://hl7.org/fhir/questionnaire-item-control', - code: 'upper' - } - ] - } - } - ], - linkId: 'pain-level-upper', - text: 'Unbearable pain', - type: 'display' - } - ] - }, - { - extension: [ - { - url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl', - valueCodeableConcept: { - coding: [ - { - system: 'http://hl7.org/fhir/questionnaire-item-control', - code: 'radio-button' - } - ] - } - }, - { - url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-choiceOrientation', - valueCode: 'horizontal' - }, - { - url: 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-calculatedExpression', - valueExpression: { - language: 'text/fhirpath', - expression: "iif(%painLevel.empty(), 'Y', iif(%painLevel < 5, 'Y', 'N'))" - } - } - ], - linkId: 'pain-low', - text: 'Low pain (Level < 5)', - type: 'choice', - repeats: false, - readOnly: true, - answerOption: [ - { - valueCoding: { - system: 'http://terminology.hl7.org/CodeSystem/v2-0532', - code: 'Y', - display: 'Yes' - } - }, - { - valueCoding: { - system: 'http://terminology.hl7.org/CodeSystem/v2-0532', - code: 'N', - display: 'No' - } - } - ] - } - ] -}; - -export const qChoiceAnswerValueSetCalculation: Questionnaire = { - resourceType: 'Questionnaire', - id: 'ChoiceAnswerValueSetCalculation', - name: 'ChoiceAnswerValueSetCalculation', - title: 'Choice AnswerValueSet Calculation', - version: '0.1.0', - status: 'draft', - publisher: 'AEHRC CSIRO', - date: '2024-05-01', - url: 'https://smartforms.csiro.au/docs/components/choice/answervalueset-calculation', - contained: [ - { - resourceType: 'ValueSet', - id: 'australian-states-territories-2', - meta: { - profile: [ - 'http://hl7.org/fhir/StructureDefinition/shareablevalueset', - 'https://healthterminologies.gov.au/fhir/StructureDefinition/composed-value-set-4' - ] - }, - url: 'https://healthterminologies.gov.au/fhir/ValueSet/australian-states-territories-2', - identifier: [ - { - system: 'urn:ietf:rfc:3986', - value: 'urn:oid:1.2.36.1.2001.1004.201.10026' - } - ], - version: '2.0.2', - name: 'AustralianStatesAndTerritories', - title: 'Australian States and Territories', - status: 'active', - experimental: false, - date: '2020-05-31', - publisher: 'Australian Digital Health Agency', - contact: [ - { - telecom: [ - { - system: 'email', - value: 'help@digitalhealth.gov.au' - } - ] - } - ], - description: - 'The Australian States and Territories value set includes values that represent the Australian states and territories.', - copyright: - 'Copyright © 2018 Australian Digital Health Agency - All rights reserved. Except for the material identified below, this content is licensed under a Creative Commons Attribution 4.0 International License. See https://creativecommons.org/licenses/by/4.0/. \n\nThis resource includes material that is based on Australian Institute of Health and Welfare material. \n\nAll copies of this resource must include this copyright statement and all information contained in this statement.', - compose: { - include: [ - { - system: - 'https://healthterminologies.gov.au/fhir/CodeSystem/australian-states-territories-1', - concept: [ - { - code: 'ACT' - }, - { - code: 'NSW' - }, - { - code: 'NT' - }, - { - code: 'OTHER' - }, - { - code: 'QLD' - }, - { - code: 'SA' - }, - { - code: 'TAS' - }, - { - code: 'VIC' - }, - { - code: 'WA' - } - ] - } - ] - }, - expansion: { - identifier: 'e9439195-c1d8-4069-a349-98c1d552a351', - timestamp: '2023-06-20T04:20:58+00:00', - total: 9, - offset: 0, - parameter: [ - { - name: 'version', - valueUri: - 'https://healthterminologies.gov.au/fhir/CodeSystem/australian-states-territories-1|1.1.3' - }, - { - name: 'count', - valueInteger: 2147483647 - }, - { - name: 'offset', - valueInteger: 0 - } - ], - contains: [ - { - system: - 'https://healthterminologies.gov.au/fhir/CodeSystem/australian-states-territories-1', - code: 'ACT', - display: 'Australian Capital Territory' - }, - { - system: - 'https://healthterminologies.gov.au/fhir/CodeSystem/australian-states-territories-1', - code: 'NSW', - display: 'New South Wales' - }, - { - system: - 'https://healthterminologies.gov.au/fhir/CodeSystem/australian-states-territories-1', - code: 'NT', - display: 'Northern Territory' - }, - { - system: - 'https://healthterminologies.gov.au/fhir/CodeSystem/australian-states-territories-1', - code: 'OTHER', - display: 'Other territories' - }, - { - system: - 'https://healthterminologies.gov.au/fhir/CodeSystem/australian-states-territories-1', - code: 'QLD', - display: 'Queensland' - }, - { - system: - 'https://healthterminologies.gov.au/fhir/CodeSystem/australian-states-territories-1', - code: 'SA', - display: 'South Australia' - }, - { - system: - 'https://healthterminologies.gov.au/fhir/CodeSystem/australian-states-territories-1', - code: 'TAS', - display: 'Tasmania' - }, - { - system: - 'https://healthterminologies.gov.au/fhir/CodeSystem/australian-states-territories-1', - code: 'VIC', - display: 'Victoria' - }, - { - system: - 'https://healthterminologies.gov.au/fhir/CodeSystem/australian-states-territories-1', - code: 'WA', - display: 'Western Australia' - } - ] - } - } - ], - extension: [ - { - url: 'http://hl7.org/fhir/StructureDefinition/variable', - valueExpression: { - name: 'stateCode', - language: 'text/fhirpath', - expression: "item.where(linkId = 'state-controller').answer.value" - } - } - ], - item: [ - { - linkId: 'state-controller-instructions', - text: 'Feel free to play around with the following state codes: ACT, NSW, NT, OTHER, QLD, SA, TAS, VIC, WA', - _text: { - extension: [ - { - url: 'http://hl7.org/fhir/StructureDefinition/rendering-xhtml', - valueString: - '
\r\n
Feel free to play around with the following state codes:
\r\n
    \r\n
  • ACT
  • \r\n
  • NSW
  • \r\n
  • NT
  • \r\n
  • OTHER
  • \r\n
  • QLD
  • \r\n
  • SA
  • \r\n
  • TAS
  • \r\n
  • VIC
  • \r\n
  • WA
  • \r\n
\r\n
' - } - ] - }, - type: 'display', - repeats: false - }, - { - linkId: 'state-controller', - text: 'State (string)', - type: 'string', - repeats: false - }, - { - extension: [ - { - url: 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-calculatedExpression', - valueExpression: { - language: 'text/fhirpath', - expression: '%stateCode' - } - } - ], - linkId: 'state-choice', - text: 'State (choice)', - type: 'choice', - repeats: false, - readOnly: true, - answerValueSet: '#australian-states-territories-2' - } - ] -}; - export const qChoiceAnswerInitialSelected: Questionnaire = { resourceType: 'Questionnaire', id: 'TestChoiceSelectAnswerOptionsUsingInitialSelected', diff --git a/packages/smart-forms-renderer/src/stories/assets/questionnaires/QDisplay.ts b/packages/smart-forms-renderer/src/stories/assets/questionnaires/QDisplay.ts index 64f8fb9c2..cbfa924ef 100644 --- a/packages/smart-forms-renderer/src/stories/assets/questionnaires/QDisplay.ts +++ b/packages/smart-forms-renderer/src/stories/assets/questionnaires/QDisplay.ts @@ -37,83 +37,6 @@ export const qDisplayBasic: Questionnaire = { ] }; -export const qDisplayCalculation: Questionnaire = { - resourceType: 'Questionnaire', - id: 'DisplayCalculation', - name: 'DisplayCalculation', - title: 'Display Calculation', - version: '0.1.0', - status: 'draft', - publisher: 'AEHRC CSIRO', - date: '2024-05-01', - url: 'https://smartforms.csiro.au/docs/components/display/calculation', - extension: [ - { - url: 'http://hl7.org/fhir/StructureDefinition/variable', - valueExpression: { - name: 'gender', - language: 'text/fhirpath', - expression: "item.where(linkId = 'gender-controller').answer.valueCoding.code" - } - } - ], - item: [ - { - linkId: 'gender-controller', - text: 'Gender', - type: 'choice', - repeats: false, - answerOption: [ - { - valueCoding: { - system: 'http://hl7.org/fhir/administrative-gender', - code: 'female', - display: 'Female' - } - }, - { - valueCoding: { - system: 'http://hl7.org/fhir/administrative-gender', - code: 'male', - display: 'Male' - } - }, - { - valueCoding: { - system: 'http://hl7.org/fhir/administrative-gender', - code: 'other', - display: 'Other' - } - }, - { - valueCoding: { - system: 'http://hl7.org/fhir/administrative-gender', - code: 'unknown', - display: 'Unknown' - } - } - ] - }, - { - linkId: 'gender-display', - type: 'display', - repeats: false, - _text: { - extension: [ - { - url: 'http://hl7.org/fhir/StructureDefinition/cqf-expression', - valueExpression: { - language: 'text/fhirpath', - expression: "'Gender: '+ %gender" - } - } - ] - }, - text: '' - } - ] -}; - export const qDisplayCalculationStyled: Questionnaire = { resourceType: 'Questionnaire', id: 'DisplayCalculationStyled', diff --git a/packages/smart-forms-renderer/src/stories/assets/questionnaires/QInteger.ts b/packages/smart-forms-renderer/src/stories/assets/questionnaires/QInteger.ts deleted file mode 100644 index 7802db3e5..000000000 --- a/packages/smart-forms-renderer/src/stories/assets/questionnaires/QInteger.ts +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright 2025 Commonwealth Scientific and Industrial Research - * Organisation (CSIRO) ABN 41 687 119 230. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import type { Questionnaire } from 'fhir/r4'; -import type { QuestionnaireResponse } from 'fhir/r4'; - -export const qIntegerBasic: Questionnaire = { - resourceType: 'Questionnaire', - id: 'IntegerBasic', - name: 'IntegerBasic', - title: 'Integer Basic', - version: '0.1.0', - status: 'draft', - publisher: 'AEHRC CSIRO', - date: '2024-05-01', - url: 'https://smartforms.csiro.au/docs/components/integer/basic', - item: [ - { - linkId: 'age', - type: 'integer', - repeats: false, - text: 'Age' - } - ] -}; - -export const qrIntegerBasicResponse: QuestionnaireResponse = { - resourceType: 'QuestionnaireResponse', - status: 'in-progress', - item: [ - { - linkId: 'age', - text: 'Age', - answer: [ - { - valueInteger: 40 - } - ] - } - ], - questionnaire: 'https://smartforms.csiro.au/docs/components/integer/basic' -}; - -export const qIntegerCalculation: Questionnaire = { - resourceType: 'Questionnaire', - id: 'IntegerCalculation', - name: 'IntegerCalculation', - title: 'Integer Calculation', - version: '0.1.0', - status: 'draft', - publisher: 'AEHRC CSIRO', - date: '2024-05-01', - url: 'https://smartforms.csiro.au/docs/components/integer/calculation', - extension: [ - { - url: 'http://hl7.org/fhir/StructureDefinition/variable', - valueExpression: { - name: 'length', - language: 'text/fhirpath', - expression: "item.where(linkId = 'length-controller').answer.value" - } - } - ], - item: [ - { - extension: [ - { - url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-unit', - valueCoding: { - system: 'http://unitsofmeasure.org', - code: 'cm', - display: 'cm' - } - } - ], - linkId: 'length-controller', - text: 'Length (cm)', - type: 'integer', - repeats: false - }, - { - extension: [ - { - url: 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-calculatedExpression', - valueExpression: { - language: 'text/fhirpath', - expression: '%length.power(2)' - } - }, - { - url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-unit', - valueCoding: { - system: 'http://unitsofmeasure.org', - code: 'cm2', - display: 'cm^2' - } - } - ], - linkId: 'length-squared', - text: 'Length squared (cm^2)', - type: 'integer', - readOnly: true - } - ] -}; diff --git a/packages/smart-forms-renderer/src/stories/assets/questionnaires/QQuantity.ts b/packages/smart-forms-renderer/src/stories/assets/questionnaires/QQuantity.ts deleted file mode 100644 index 4aee9ae8e..000000000 --- a/packages/smart-forms-renderer/src/stories/assets/questionnaires/QQuantity.ts +++ /dev/null @@ -1,365 +0,0 @@ -/* - * Copyright 2025 Commonwealth Scientific and Industrial Research - * Organisation (CSIRO) ABN 41 687 119 230. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import type { Questionnaire, QuestionnaireResponse } from 'fhir/r4'; - -export const qQuantityBasic: Questionnaire = { - resourceType: 'Questionnaire', - id: 'QuantityBasic', - name: 'QuantityBasic', - title: 'Quantity Basic', - version: '0.1.0', - status: 'draft', - publisher: 'AEHRC CSIRO', - date: '2024-05-01', - url: 'https://smartforms.csiro.au/docs/components/quantity/basic', - item: [ - { - extension: [ - { - url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-unit', - valueCoding: { system: 'http://unitsofmeasure.org', code: 'kg', display: 'kg' } - } - ], - linkId: 'body-weight', - type: 'quantity', - repeats: false, - text: 'Body Weight' - }, - { - extension: [ - { - url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-unit', - valueCoding: { system: 'http://unitsofmeasure.org', code: 'kg', display: 'kg' } - } - ], - linkId: 'body-weight-comparator', - type: 'quantity', - repeats: false, - text: 'Body Weight (with comparator symbol)' - } - ] -}; - -export const qrQuantityBasicResponse: QuestionnaireResponse = { - resourceType: 'QuestionnaireResponse', - status: 'in-progress', - item: [ - { - linkId: 'body-weight', - answer: [ - { - valueQuantity: { - value: 80, - unit: 'kg', - system: 'http://unitsofmeasure.org', - code: 'kg' - } - } - ], - text: 'Body Weight' - }, - { - linkId: 'body-weight-comparator', - answer: [ - { - valueQuantity: { - value: 90, - comparator: '<', - unit: 'kg', - system: 'http://unitsofmeasure.org', - code: 'kg' - } - } - ], - text: 'Body Weight (with comparator symbol)' - } - ], - questionnaire: 'https://smartforms.csiro.au/docs/components/quantity/basic' -}; - -export const qQuantityUnitOption: Questionnaire = { - resourceType: 'Questionnaire', - id: 'QuantityUnitOption', - name: 'QuantityUnitOption', - title: 'Quantity UnitOption', - version: '0.1.0', - status: 'draft', - publisher: 'AEHRC CSIRO', - date: '2024-07-27', - url: 'https://smartforms.csiro.au/docs/components/quantity/unit-option', - item: [ - { - linkId: 'duration-single-unit-guidance', - text: 'If there is only one unitOption, it will be rendered as if a "http://hl7.org/fhir/StructureDefinition/questionnaire-unit" extension is used.', - type: 'display' - }, - { - linkId: 'duration-single-unit', - text: 'Duration (single unit)', - type: 'quantity', - extension: [ - { - url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-unitOption', - valueCoding: { - system: 'http://unitsofmeasure.org', - code: 'd', - display: 'Day(s)' - } - } - ] - }, - { - linkId: 'duration-multi-unit-guidance', - text: 'If there are multiple unitOptions, they will be rendered in a separate dropdown field.', - type: 'display' - }, - { - linkId: 'duration-multi-unit', - text: 'Duration (multiple units)', - type: 'quantity', - extension: [ - { - url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-unitOption', - valueCoding: { - system: 'http://unitsofmeasure.org', - code: 'd', - display: 'Day(s)' - } - }, - { - url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-unitOption', - valueCoding: { - system: 'http://unitsofmeasure.org', - code: 'wk', - display: 'Week(s)' - } - }, - { - url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-unitOption', - valueCoding: { - system: 'http://unitsofmeasure.org', - code: 'mo', - display: 'Month(s)' - } - }, - { - url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-unitOption', - valueCoding: { - system: 'http://unitsofmeasure.org', - code: 'a', - display: 'Year(s)' - } - }, - { - url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-unitOption', - valueCoding: { - system: 'http://unitsofmeasure.org', - code: 's', - display: 'Second(s)' - } - }, - { - url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-unitOption', - valueCoding: { - system: 'http://unitsofmeasure.org', - code: 'min', - display: 'Minute(s)' - } - }, - { - url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-unitOption', - valueCoding: { - system: 'http://unitsofmeasure.org', - code: 'hour', - display: 'Hour(s)' - } - } - ] - }, - { - linkId: 'duration-multi-unit-comparator', - text: 'Duration (multiple units, with comparator symbol)', - type: 'quantity', - extension: [ - { - url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-unitOption', - valueCoding: { - system: 'http://unitsofmeasure.org', - code: 'd', - display: 'Day(s)' - } - }, - { - url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-unitOption', - valueCoding: { - system: 'http://unitsofmeasure.org', - code: 'wk', - display: 'Week(s)' - } - }, - { - url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-unitOption', - valueCoding: { - system: 'http://unitsofmeasure.org', - code: 'mo', - display: 'Month(s)' - } - }, - { - url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-unitOption', - valueCoding: { - system: 'http://unitsofmeasure.org', - code: 'a', - display: 'Year(s)' - } - }, - { - url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-unitOption', - valueCoding: { - system: 'http://unitsofmeasure.org', - code: 's', - display: 'Second(s)' - } - }, - { - url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-unitOption', - valueCoding: { - system: 'http://unitsofmeasure.org', - code: 'min', - display: 'Minute(s)' - } - }, - { - url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-unitOption', - valueCoding: { - system: 'http://unitsofmeasure.org', - code: 'hour', - display: 'Hour(s)' - } - } - ] - } - ] -}; - -export const qrQuantityUnitOptionResponse: QuestionnaireResponse = { - resourceType: 'QuestionnaireResponse', - status: 'in-progress', - item: [ - { - linkId: 'duration-single-unit', - answer: [ - { - valueQuantity: { - value: 2, - unit: 'Day(s)', - system: 'http://unitsofmeasure.org', - code: 'd' - } - } - ], - text: 'Duration' - }, - { - linkId: 'duration-multi-unit', - answer: [ - { - valueQuantity: { - value: 48, - unit: 'Hour(s)', - system: 'http://unitsofmeasure.org', - code: 'hour' - } - } - ], - text: 'Duration' - }, - { - linkId: 'duration-multi-unit-comparator', - answer: [ - { - valueQuantity: { - value: 48, - comparator: '>=', - unit: 'Hour(s)', - system: 'http://unitsofmeasure.org', - code: 'hour' - } - } - ], - text: 'Duration' - } - ], - questionnaire: 'https://smartforms.csiro.au/docs/components/quantity/unit-option' -}; - -export const qQuantityCalculation: Questionnaire = { - resourceType: 'Questionnaire', - id: 'QuantityCalculation', - name: 'QuantityCalculation', - title: 'Quantity Calculation', - version: '0.1.0', - status: 'draft', - publisher: 'AEHRC CSIRO', - date: '2024-05-01', - url: 'https://smartforms.csiro.au/docs/components/quantity/calculation', - extension: [ - { - url: 'http://hl7.org/fhir/StructureDefinition/variable', - valueExpression: { - name: 'durationInDays', - language: 'text/fhirpath', - expression: "item.where(linkId='duration-in-days').answer.value" - } - } - ], - item: [ - { - extension: [ - { - url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-unit', - valueCoding: { system: 'http://unitsofmeasure.org', code: 'd', display: 'days' } - } - ], - linkId: 'duration-in-days', - type: 'quantity', - repeats: false, - text: 'Duration in Days' - }, - { - extension: [ - { - url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-unit', - valueCoding: { system: 'http://unitsofmeasure.org', code: 'h', display: 'hours' } - }, - { - url: 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-calculatedExpression', - valueExpression: { - description: 'Duration In Hours', - language: 'text/fhirpath', - expression: '%durationInDays.value * 24' - } - } - ], - linkId: 'duration-in-hours', - type: 'quantity', - repeats: false, - text: 'Duration in Hours' - } - ] -}; diff --git a/packages/smart-forms-renderer/src/stories/assets/questionnaires/QString.ts b/packages/smart-forms-renderer/src/stories/assets/questionnaires/QString.ts deleted file mode 100644 index 3eef94cd1..000000000 --- a/packages/smart-forms-renderer/src/stories/assets/questionnaires/QString.ts +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright 2025 Commonwealth Scientific and Industrial Research - * Organisation (CSIRO) ABN 41 687 119 230. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import type { Questionnaire } from 'fhir/r4'; -import type { QuestionnaireResponse } from 'fhir/r4'; - -export const qStringBasic: Questionnaire = { - resourceType: 'Questionnaire', - id: 'StringBasic', - name: 'StringBasic', - title: 'String Basic', - version: '0.1.0', - status: 'draft', - publisher: 'AEHRC CSIRO', - date: '2024-05-01', - url: 'https://smartforms.csiro.au/docs/components/string/basic', - item: [ - { - linkId: 'name', - type: 'string', - repeats: false, - text: 'Name' - } - ] -}; - -export const qrStringBasicResponse: QuestionnaireResponse = { - resourceType: 'QuestionnaireResponse', - status: 'in-progress', - item: [ - { - linkId: 'name', - text: 'Name', - answer: [ - { - valueString: 'John Doe' - } - ] - } - ], - questionnaire: 'https://smartforms.csiro.au/docs/components/string/basic' -}; - -export const qStringCalculation: Questionnaire = { - resourceType: 'Questionnaire', - id: 'StringCalculation', - name: 'StringCalculation', - title: 'String Calculation', - version: '0.1.0', - status: 'draft', - publisher: 'AEHRC CSIRO', - date: '2024-05-01', - url: 'https://smartforms.csiro.au/docs/components/string/calculation', - extension: [ - { - url: 'http://hl7.org/fhir/StructureDefinition/variable', - valueExpression: { - name: 'gender', - language: 'text/fhirpath', - expression: "item.where(linkId = 'gender-controller').answer.valueCoding.code" - } - } - ], - item: [ - { - linkId: 'gender-controller', - text: 'Gender', - type: 'choice', - repeats: false, - answerOption: [ - { - valueCoding: { - system: 'http://hl7.org/fhir/administrative-gender', - code: 'female', - display: 'Female' - } - }, - { - valueCoding: { - system: 'http://hl7.org/fhir/administrative-gender', - code: 'male', - display: 'Male' - } - }, - { - valueCoding: { - system: 'http://hl7.org/fhir/administrative-gender', - code: 'other', - display: 'Other' - } - }, - { - valueCoding: { - system: 'http://hl7.org/fhir/administrative-gender', - code: 'unknown', - display: 'Unknown' - } - } - ] - }, - { - extension: [ - { - url: 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-calculatedExpression', - valueExpression: { - language: 'text/fhirpath', - expression: '%gender' - } - } - ], - linkId: 'gender-string', - text: 'Gender code', - type: 'string', - readOnly: true - } - ] -}; diff --git a/packages/smart-forms-renderer/src/stories/assets/questionnaires/QText.ts b/packages/smart-forms-renderer/src/stories/assets/questionnaires/QText.ts deleted file mode 100644 index 40af2544b..000000000 --- a/packages/smart-forms-renderer/src/stories/assets/questionnaires/QText.ts +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright 2025 Commonwealth Scientific and Industrial Research - * Organisation (CSIRO) ABN 41 687 119 230. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import type { Questionnaire } from 'fhir/r4'; -import type { QuestionnaireResponse } from 'fhir/r4'; - -export const qTextBasic: Questionnaire = { - resourceType: 'Questionnaire', - id: 'TextBasic', - name: 'TextBasic', - title: 'Text Basic', - version: '0.1.0', - status: 'draft', - publisher: 'AEHRC CSIRO', - date: '2024-05-01', - url: 'https://smartforms.csiro.au/docs/components/text/basic', - item: [ - { - linkId: 'details', - type: 'text', - repeats: false, - text: 'Details of intermittent fasting' - } - ] -}; - -export const qrTextBasicResponse: QuestionnaireResponse = { - resourceType: 'QuestionnaireResponse', - status: 'in-progress', - item: [ - { - linkId: 'details', - text: 'Details of intermittent fasting', - answer: [ - { - valueString: - '- 8 hour eating window\n- Cup of black coffee in the morning\n- Small portions of lunch and dinner' - } - ] - } - ], - questionnaire: 'https://smartforms.csiro.au/docs/components/text/basic' -}; - -export const qTextCalculation: Questionnaire = { - resourceType: 'Questionnaire', - id: 'TextCalculation', - name: 'TextCalculation', - title: 'Text Calculation', - version: '0.1.0', - status: 'draft', - publisher: 'AEHRC CSIRO', - date: '2024-05-01', - url: 'https://smartforms.csiro.au/docs/components/text/calculation', - extension: [ - { - url: 'http://hl7.org/fhir/StructureDefinition/variable', - valueExpression: { - name: 'earHealthDetails', - language: 'text/fhirpath', - expression: - "item.where(linkId = 'ear-health-group').item.where(linkId = 'ear-health-details').answer.value" - } - }, - { - url: 'http://hl7.org/fhir/StructureDefinition/variable', - valueExpression: { - name: 'medicationDetails', - language: 'text/fhirpath', - expression: - "item.where(linkId = 'medications-group').item.where(linkId = 'medications-details').answer.value" - } - } - ], - item: [ - { - linkId: 'ear-health-group', - text: 'Ear Health', - type: 'group', - repeats: false, - item: [ - { - linkId: 'ear-health-other', - text: '... (other questions)', - type: 'display', - readOnly: false - }, - { - linkId: 'ear-health-details', - text: 'Details', - type: 'text', - readOnly: false - } - ] - }, - { - linkId: 'medications-group', - text: 'Medications', - type: 'group', - repeats: false, - item: [ - { - linkId: 'medications-other', - text: '... (other questions)', - type: 'display', - readOnly: false - }, - { - linkId: 'medications-details', - text: 'Details', - type: 'text', - readOnly: false - } - ] - }, - { - linkId: 'summaries-group', - text: 'Health Check Summaries', - type: 'group', - repeats: false, - item: [ - { - extension: [ - { - url: 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-calculatedExpression', - valueExpression: { - language: 'text/fhirpath', - expression: '%earHealthDetails' - } - } - ], - linkId: 'ear-health-summary', - text: 'Ear Health', - type: 'text', - readOnly: true - }, - { - extension: [ - { - url: 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-calculatedExpression', - valueExpression: { - language: 'text/fhirpath', - expression: '%medicationDetails' - } - } - ], - linkId: 'medication-summary', - text: 'Medications', - type: 'text', - readOnly: true - } - ] - } - ] -}; diff --git a/packages/smart-forms-renderer/src/stories/assets/questionnaires/index.ts b/packages/smart-forms-renderer/src/stories/assets/questionnaires/index.ts index 91fedcadd..10a4898da 100644 --- a/packages/smart-forms-renderer/src/stories/assets/questionnaires/index.ts +++ b/packages/smart-forms-renderer/src/stories/assets/questionnaires/index.ts @@ -17,18 +17,15 @@ export * from './QBoolean'; export * from './QDecimal'; -export * from './QInteger'; export * from './QDate'; export * from './QDateTime'; export * from './QTime'; -export * from './QString'; -export * from './QText'; + export * from './QUrl'; export * from './QChoice'; export * from './QOpenChoice'; export * from './QAttachment'; export * from './QReference'; -export * from './QQuantity'; export * from './QAdvancedAdditionalDisplayContent'; export * from './QAdvancedControlAppearance'; export * from './QAdvancedOther'; diff --git a/packages/smart-forms-renderer/src/stories/itemTypes/AllCalculations.stories.tsx b/packages/smart-forms-renderer/src/stories/itemTypes/AllCalculations.stories.tsx new file mode 100644 index 000000000..150ba6b8d --- /dev/null +++ b/packages/smart-forms-renderer/src/stories/itemTypes/AllCalculations.stories.tsx @@ -0,0 +1,438 @@ +import type { Meta, StoryObj } from '@storybook/react-vite'; + +import BuildFormWrapperForStorybook from '../storybookWrappers/BuildFormWrapperForStorybook'; +import { + calculatedExpressionExtFactory, + getAnswers, + getGroupAnswers, + itemControlExtFactory, + questionnaireFactory, + variableExtFactory, + chooseSelectOption, + inputInteger, + inputQuantity, + inputDecimal, + inputText +} from '../testUtils'; + +import { expect, waitFor } from 'storybook/test'; + +// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export +const meta = { + title: 'ItemType/CalculationScenario', + component: BuildFormWrapperForStorybook, + // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs + tags: [] +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +const booleanTargetCoding = { + system: 'http://hl7.org/fhir/administrative-gender', + code: 'female', + display: 'Female' +}; +const booleanTargetlinkId = 'gender-controller'; +const booleanTargetlinkIdCalc = 'gender-is-female'; +const qBooleanCalculation = questionnaireFactory( + [ + { + linkId: booleanTargetlinkId, + text: 'Gender', + type: 'choice', + repeats: false, + answerOption: [ + { valueCoding: booleanTargetCoding }, + { + valueCoding: { + system: 'http://hl7.org/fhir/administrative-gender', + code: 'male', + display: 'Male' + } + } + ] + }, + { + extension: [calculatedExpressionExtFactory("%gender = 'female'")], + linkId: booleanTargetlinkIdCalc, + text: 'Gender is female?', + type: 'boolean', + readOnly: true + } + ], + { + extension: [ + variableExtFactory( + 'gender', + `item.where(linkId = '${booleanTargetlinkId}').answer.valueCoding.code` + ) + ] + } +); + +export const BooleanCalculation: Story = { + args: { + questionnaire: qBooleanCalculation + }, + play: async ({ canvasElement }) => { + await chooseSelectOption(canvasElement, booleanTargetlinkId, booleanTargetCoding.display); + + await waitFor(async () => { + const result = await getAnswers(booleanTargetlinkIdCalc); + expect(result).toHaveLength(1); + expect(result[0].valueBoolean).toBe(true); + }); + } +}; + +const choiceTargetLinkId = 'pain-level'; +const targetChoiceCoding = { + system: 'http://terminology.hl7.org/CodeSystem/v2-0532', + code: 'Y', + display: 'Yes' +}; +const choiceTargetLinkIdCalc = 'pain-low'; +const qChoiceAnswerOptionCalculation = questionnaireFactory( + [ + { + linkId: choiceTargetLinkId, + type: 'integer' + }, + { + extension: [ + itemControlExtFactory('radio-button'), + calculatedExpressionExtFactory( + "iif(%painLevel.empty(), 'Y', iif(%painLevel < 5, 'Y', 'N'))" + ) + ], + linkId: choiceTargetLinkIdCalc, + text: 'Low pain (Level < 5)', + type: 'choice', + readOnly: true, + answerOption: [ + { + valueCoding: targetChoiceCoding + }, + { + valueCoding: { + system: 'http://terminology.hl7.org/CodeSystem/v2-0532', + code: 'N', + display: 'No' + } + } + ] + } + ], + { + extension: [ + variableExtFactory('painLevel', `item.where(linkId = '${choiceTargetLinkId}').answer.value`) + ] + } +); +const choiceTargetNumber = 3; + +export const ChoiceAnswerOptionCalculation: Story = { + args: { + questionnaire: qChoiceAnswerOptionCalculation + }, + play: async ({ canvasElement }) => { + await inputText(canvasElement, choiceTargetLinkId, choiceTargetNumber); + + await waitFor(async () => { + const result = await getAnswers(choiceTargetLinkIdCalc); + expect(result).toHaveLength(1); + expect(result[0].valueCoding).toEqual(expect.objectContaining(targetChoiceCoding)); + }); + } +}; + +const choiceValueSetTargetLinkId = 'gender-string'; +const choiceValueSetTargetLinkIdCalc = 'gender-choice'; + +const choiceValueSetTargetCoding = { + system: 'http://hl7.org/fhir/administrative-gender', + code: 'male', + display: 'Male' +}; + +const qChoiceAnswerValueSetCalculation = questionnaireFactory( + [ + { + linkId: choiceValueSetTargetLinkId, + type: 'string', + text: 'Enter gender code' + }, + { + extension: [calculatedExpressionExtFactory('%gender')], + linkId: choiceValueSetTargetLinkIdCalc, + type: 'choice', + readOnly: true, + answerValueSet: 'http://hl7.org/fhir/ValueSet/administrative-gender' + } + ], + { + extension: [ + variableExtFactory( + 'gender', + `item.where((linkId = '${choiceValueSetTargetLinkId}')).answer.value` + ) + ] + } +); + +export const ChoiceAnswerValueSetCalculation: Story = { + args: { + questionnaire: qChoiceAnswerValueSetCalculation + }, + play: async ({ canvasElement }) => { + await inputText(canvasElement, choiceValueSetTargetLinkId, choiceValueSetTargetCoding.code); + + await waitFor(async () => { + const result = await getAnswers(choiceValueSetTargetLinkIdCalc); + expect(result).toHaveLength(1); + expect(result[0].valueCoding).toEqual(expect.objectContaining(choiceValueSetTargetCoding)); + }); + } +}; + +const integerLinkId = 'length-controller'; +const integerLinkIdCalc = 'length-squared'; +const qIntegerCalculation = questionnaireFactory( + [ + { + linkId: integerLinkId, + type: 'integer' + }, + { + extension: [calculatedExpressionExtFactory('%length.power(2)')], + linkId: integerLinkIdCalc, + type: 'integer', + readOnly: true + } + ], + { + extension: [ + variableExtFactory('length', `item.where(linkId = '${integerLinkId}').answer.value`) + ] + } +); +const integerTargetNumber = 2; +const integerTargetNumberCalc = 4; + +export const IntegerCalculation: Story = { + args: { + questionnaire: qIntegerCalculation + }, + play: async ({ canvasElement }) => { + await inputInteger(canvasElement, integerLinkId, integerTargetNumber); + + await waitFor(async () => { + const result = await getAnswers(integerLinkIdCalc); + expect(result).toHaveLength(1); + expect(result[0].valueInteger).toBe(integerTargetNumberCalc); + }); + } +}; + +const quantityDaysLinkId = 'duration-in-days'; +const quantityHoursLinkId = 'duration-in-hours'; +const quantityTargetDays = 1; +const quantityTargetHours = 24; +const qQuantityCalculation = questionnaireFactory( + [ + { + linkId: quantityDaysLinkId, + type: 'quantity' + }, + { + extension: [calculatedExpressionExtFactory('%durationInDays.value * 24')], + linkId: quantityHoursLinkId, + type: 'quantity' + } + ], + { + extension: [ + variableExtFactory( + 'durationInDays', + `item.where(linkId='${quantityDaysLinkId}').answer.value` + ) + ] + } +); +const quantityTarget = { + unit: undefined, + value: quantityTargetHours, + code: undefined, + system: undefined +}; + +export const QuantityCalculation: Story = { + args: { + questionnaire: qQuantityCalculation + }, + play: async ({ canvasElement }) => { + await inputQuantity(canvasElement, quantityDaysLinkId, quantityTargetDays); + + await waitFor(async () => { + const result = await getAnswers(quantityHoursLinkId); + expect(result).toHaveLength(1); + expect(result[0].valueQuantity).toEqual(expect.objectContaining(quantityTarget)); + }); + } +}; +const heightLinkId = 'patient-height'; +const weightLinkId = 'patient-weight'; +const bmiLinkIdCalc = 'bmi-result'; +const bmiGroupLinkId = 'bmi-calculation'; + +const qCalculatedExpressionBMICalculator = questionnaireFactory([ + { + linkId: bmiGroupLinkId, + type: 'group', + extension: [ + variableExtFactory('height', `item.where(linkId='${heightLinkId}').answer.value`), + variableExtFactory('weight', `item.where(linkId='${weightLinkId}').answer.value`) + ], + item: [ + { + linkId: heightLinkId, + text: 'Height', + type: 'decimal', + readOnly: false + }, + { + linkId: weightLinkId, + text: 'Weight', + type: 'decimal', + readOnly: false + }, + { + extension: [calculatedExpressionExtFactory('(%weight/((%height/100).power(2))).round(1)')], + linkId: bmiLinkIdCalc, + text: 'Value', + type: 'decimal', + readOnly: true + } + ] + } +]); +const heightTarget = 100; +const weightTarget = 10; +const bmiResultCalc = 10; + +export const DecimalCalculation: Story = { + args: { + questionnaire: qCalculatedExpressionBMICalculator + }, + play: async ({ canvasElement }) => { + await inputDecimal(canvasElement, heightLinkId, heightTarget); + await inputDecimal(canvasElement, weightLinkId, weightTarget); + + await waitFor(async () => { + const result = await getGroupAnswers(bmiGroupLinkId, bmiLinkIdCalc); + expect(result).toHaveLength(1); + expect(result[0].valueDecimal).toBe(bmiResultCalc); + }); + } +}; + +const stringCalculationLinkId = 'gender-controller'; +const stringCalcCalculationLinkId = 'gender-string'; +const stringTargetCoding = { + system: 'http://hl7.org/fhir/administrative-gender', + code: 'Male', + display: 'Male' +}; +const qStringCalculation = questionnaireFactory( + [ + { + linkId: stringCalculationLinkId, + type: 'choice', + answerOption: [ + { + valueCoding: { + system: 'http://hl7.org/fhir/administrative-gender', + code: 'Female', + display: 'Female' + } + }, + { + valueCoding: stringTargetCoding + } + ] + }, + { + extension: [calculatedExpressionExtFactory('%gender')], + linkId: stringCalcCalculationLinkId, + type: 'string', + readOnly: true + } + ], + { + extension: [ + variableExtFactory( + 'gender', + `item.where(linkId = '${stringCalculationLinkId}').answer.valueCoding.code` + ) + ] + } +); + +export const StringCalculation: Story = { + args: { + questionnaire: qStringCalculation + }, + play: async ({ canvasElement }) => { + await chooseSelectOption(canvasElement, stringCalculationLinkId, stringTargetCoding.display); + + await waitFor(async () => { + const result = await getAnswers(stringCalcCalculationLinkId); + expect(result).toHaveLength(1); + expect(result[0].valueString).toBe(stringTargetCoding.display); + }); + } +}; + +const detailsLinkId = 'medications-details'; +const detailsCalcLinkId = 'medication-summary'; +const textTargetText = 'Hello world'; + +const qTextCalculation = questionnaireFactory( + [ + { + linkId: detailsLinkId, + type: 'text', + readOnly: false + }, + { + extension: [calculatedExpressionExtFactory('%medicationDetails')], + linkId: detailsCalcLinkId, + type: 'text', + readOnly: true + } + ], + { + extension: [ + variableExtFactory( + 'medicationDetails', + `item.where((linkId = '${detailsLinkId}')).answer.value` + ) + ] + } +); + +export const TextCalculation: Story = { + args: { + questionnaire: qTextCalculation + }, + play: async ({ canvasElement }) => { + await inputText(canvasElement, detailsLinkId, textTargetText); + + await waitFor(async () => { + const result = await getAnswers(detailsCalcLinkId); + expect(result).toHaveLength(1); + expect(result[0].valueString).toBe(textTargetText); + }); + } +}; diff --git a/packages/smart-forms-renderer/src/stories/itemTypes/AllCqfExpressions.stories.tsx b/packages/smart-forms-renderer/src/stories/itemTypes/AllCqfExpressions.stories.tsx new file mode 100644 index 000000000..d92197c9f --- /dev/null +++ b/packages/smart-forms-renderer/src/stories/itemTypes/AllCqfExpressions.stories.tsx @@ -0,0 +1,93 @@ +/* + * Copyright 2025 Commonwealth Scientific and Industrial Research + * Organisation (CSIRO) ABN 41 687 119 230. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { Meta, StoryObj } from '@storybook/react-vite'; +import { expect, within } from 'storybook/test'; +import BuildFormWrapperForStorybook from '../storybookWrappers/BuildFormWrapperForStorybook'; + +import { + chooseSelectOption, + questionnaireFactory, + variableExtFactory, + сqfExpressionFactory +} from '../testUtils'; + +// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export +const meta = { + title: 'ItemType/CqfExpressionScenario', + component: BuildFormWrapperForStorybook, + // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs + tags: [] +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +const displayTargetLinkId = 'gender-controller'; +const genderTargetCoding = { + system: 'http://hl7.org/fhir/administrative-gender', + code: 'Female', + display: 'Female' +}; +const qDisplayCalculation = questionnaireFactory( + [ + { + linkId: displayTargetLinkId, + type: 'choice', + answerOption: [ + { + valueCoding: genderTargetCoding + }, + { + valueCoding: { + system: 'http://hl7.org/fhir/administrative-gender', + code: 'Male', + display: 'Male' + } + } + ] + }, + { + linkId: 'gender-display', + type: 'display', + _text: { + extension: [сqfExpressionFactory("'Gender: '+ %gender")] + } + } + ], + { + extension: [ + variableExtFactory( + 'gender', + `item.where(linkId = '${displayTargetLinkId}').answer.valueCoding.code` + ) + ] + } +); +const displayTargetText = 'Gender: ' + genderTargetCoding.display; + +export const DisplayCalculation: Story = { + args: { + questionnaire: qDisplayCalculation + }, + play: async ({ canvasElement }) => { + await chooseSelectOption(canvasElement, displayTargetLinkId, genderTargetCoding.display); + + const element = within(canvasElement); + expect(element.queryAllByText(displayTargetText)).toBeDefined(); + } +}; diff --git a/packages/smart-forms-renderer/src/stories/itemTypes/Boolean.stories.tsx b/packages/smart-forms-renderer/src/stories/itemTypes/Boolean.stories.tsx index 52c6cdaf0..3a840cf59 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/Boolean.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/Boolean.stories.tsx @@ -16,7 +16,6 @@ */ import type { Meta, StoryObj } from '@storybook/react-vite'; -import { qBooleanCalculation } from '../assets/questionnaires'; import BuildFormWrapperForStorybook from '../storybookWrappers/BuildFormWrapperForStorybook'; // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export import { checkCheckBox, @@ -163,9 +162,3 @@ export const BooleanCheckboxResponse: Story = { expect(input).toBeChecked(); } }; - -export const BooleanCalculation: Story = { - args: { - questionnaire: qBooleanCalculation - } -}; diff --git a/packages/smart-forms-renderer/src/stories/itemTypes/Choice.stories.tsx b/packages/smart-forms-renderer/src/stories/itemTypes/Choice.stories.tsx index ceb4334fd..4aa24a11c 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/Choice.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/Choice.stories.tsx @@ -17,10 +17,6 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; import BuildFormWrapperForStorybook from '../storybookWrappers/BuildFormWrapperForStorybook'; -import { - qChoiceAnswerOptionCalculation, - qChoiceAnswerValueSetCalculation -} from '../assets/questionnaires'; import { chooseSelectOption, findByLinkId, @@ -205,17 +201,3 @@ export const ChoiceAnswerOptionsUsingInitialSelected: Story = { expect(inputText).toBe(initialTargetCoding.display); } }; - -// TODO: Move to separate storybook -export const ChoiceAnswerOptionCalculation: Story = { - args: { - questionnaire: qChoiceAnswerOptionCalculation - } -}; - -// TODO: Move to separate storybook -export const ChoiceAnswerValueSetCalculation: Story = { - args: { - questionnaire: qChoiceAnswerValueSetCalculation - } -}; diff --git a/packages/smart-forms-renderer/src/stories/itemTypes/Decimal.stories.tsx b/packages/smart-forms-renderer/src/stories/itemTypes/Decimal.stories.tsx index c947fc45e..d610d0269 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/Decimal.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/Decimal.stories.tsx @@ -17,7 +17,7 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; import BuildFormWrapperForStorybook from '../storybookWrappers/BuildFormWrapperForStorybook'; -import { qCalculatedExpressionBMICalculator } from '../assets/questionnaires'; + import { findByLinkId, getAnswers, @@ -101,9 +101,3 @@ export const DecimalBasicResponse: Story = { expect(input).toBe(targetWeight.toString()); } }; - -export const DecimalCalculation: Story = { - args: { - questionnaire: qCalculatedExpressionBMICalculator - } -}; diff --git a/packages/smart-forms-renderer/src/stories/itemTypes/Display.stories.tsx b/packages/smart-forms-renderer/src/stories/itemTypes/Display.stories.tsx index a486b28e3..8495ba931 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/Display.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/Display.stories.tsx @@ -17,7 +17,7 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; import BuildFormWrapperForStorybook from '../storybookWrappers/BuildFormWrapperForStorybook'; -import { qDisplayCalculation, qDisplayCalculationStyled } from '../assets/questionnaires/QDisplay'; +import { qDisplayCalculationStyled } from '../assets/questionnaires/QDisplay'; import { questionnaireFactory } from '../testUtils'; import { expect, screen } from 'storybook/test'; @@ -54,12 +54,6 @@ export const DisplayBasic: Story = { } }; -export const DisplayCalculation: Story = { - args: { - questionnaire: qDisplayCalculation - } -}; - export const DisplayCalculationStyled: Story = { args: { questionnaire: qDisplayCalculationStyled diff --git a/packages/smart-forms-renderer/src/stories/itemTypes/Integer.stories.tsx b/packages/smart-forms-renderer/src/stories/itemTypes/Integer.stories.tsx index 5170115d8..b5f64d742 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/Integer.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/Integer.stories.tsx @@ -17,7 +17,7 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; import BuildFormWrapperForStorybook from '../storybookWrappers/BuildFormWrapperForStorybook'; -import { qIntegerCalculation } from '../assets/questionnaires'; + import { findByLinkId, getAnswers, @@ -99,9 +99,3 @@ export const IntegerBasicResponse: Story = { expect(input).toBe(targetAge.toString()); } }; - -export const IntegerCalculation: Story = { - args: { - questionnaire: qIntegerCalculation - } -}; diff --git a/packages/smart-forms-renderer/src/stories/itemTypes/Quantity.stories.tsx b/packages/smart-forms-renderer/src/stories/itemTypes/Quantity.stories.tsx index 4fa34e4f5..c52fae8f8 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/Quantity.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/Quantity.stories.tsx @@ -16,14 +16,20 @@ */ import type { Meta, StoryObj } from '@storybook/react-vite'; +import { expect, waitFor } from 'storybook/test'; import BuildFormWrapperForStorybook from '../storybookWrappers/BuildFormWrapperForStorybook'; import { - qQuantityBasic, - qQuantityCalculation, - qQuantityUnitOption, - qrQuantityBasicResponse, - qrQuantityUnitOptionResponse -} from '../assets/questionnaires'; + getAnswers, + qrFactory, + questionnaireFactory, + ucumSystem, + unitExtFactory, + unitOptionExtFactory, + inputQuantity, + getQuantityTextValues +} from '../testUtils'; + +import type { Quantity } from 'fhir/r4'; // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export const meta = { @@ -37,35 +43,366 @@ export default meta; type Story = StoryObj; // More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args +const basicLinkId = 'body-weight'; +const basicUnit = 'kg'; +const basicCode = 'kg'; +const qQuantityBasic = questionnaireFactory([ + { + linkId: basicLinkId, + extension: [unitExtFactory(basicUnit, basicCode)], + type: 'quantity' + } +]); +const basicTargetNumber = 10; export const QuantityBasic: Story = { args: { questionnaire: qQuantityBasic + }, + play: async ({ canvasElement }) => { + await inputQuantity(canvasElement, basicLinkId, basicTargetNumber); + + await waitFor(async () => { + const result = await getAnswers(basicLinkId); + expect(result).toHaveLength(1); + expect(result[0].valueQuantity).toEqual( + expect.objectContaining({ + value: basicTargetNumber, + comparator: undefined, + unit: basicUnit, + code: basicCode, + system: ucumSystem + }) + ); + }); + } +}; + +const basicComparatorLinkId = 'body-weight-comparator'; +const basicComparatorUnit = 'kg'; +const basicComparatorCode = 'kg'; +const qQuantityBasicComparator = questionnaireFactory([ + { + linkId: basicComparatorLinkId, + extension: [unitExtFactory(basicComparatorUnit, basicComparatorCode)], + type: 'quantity' + } +]); +const basicComparatorTargetNumber = 20; +const basicTargetComparator = '<' as const; + +export const QuantityBasicComparator: Story = { + args: { + questionnaire: qQuantityBasicComparator + }, + play: async ({ canvasElement }) => { + await inputQuantity( + canvasElement, + basicComparatorLinkId, + basicComparatorTargetNumber, + undefined, + basicTargetComparator + ); + + await waitFor(async () => { + const result = await getAnswers(basicComparatorLinkId); + expect(result).toHaveLength(1); + expect(result[0].valueQuantity).toEqual( + expect.objectContaining({ + value: basicComparatorTargetNumber, + comparator: basicTargetComparator, + system: ucumSystem, + unit: basicComparatorUnit, + code: basicComparatorCode + }) + ); + }); } }; +const basicResTargetLinkId = 'body-weight'; +const basicResTargetWeight = 80; + +const qrQuantityBasicResponse = qrFactory([ + { + linkId: basicResTargetLinkId, + answer: [ + { + valueQuantity: { + value: basicResTargetWeight, + system: ucumSystem + } + } + ] + } +]); + export const QuantityBasicResponse: Story = { args: { questionnaire: qQuantityBasic, questionnaireResponse: qrQuantityBasicResponse + }, + play: async ({ canvasElement }) => { + const result = await getQuantityTextValues(canvasElement, basicResTargetLinkId, false); + + expect(result).toEqual( + expect.objectContaining({ + value: basicResTargetWeight.toString(), + comparator: '', + unit: undefined + }) + ); } }; -export const QuantityUnitOption: Story = { +const basicResComparatorLinkId = 'body-weight-comparator'; +const basicResComparatorTargetWeight = 100; +const basicResTargetComparator = '<' as const; + +const qrQuantityBasicComparatorResponse = qrFactory([ + { + linkId: basicResComparatorLinkId, + answer: [ + { + valueQuantity: { + value: basicResComparatorTargetWeight, + comparator: basicResTargetComparator, + system: ucumSystem + } + } + ] + } +]); + +export const QuantityBasicComparatorResponse: Story = { args: { - questionnaire: qQuantityUnitOption + questionnaire: qQuantityBasicComparator, + questionnaireResponse: qrQuantityBasicComparatorResponse + }, + play: async ({ canvasElement }) => { + const resultComparator = await getQuantityTextValues( + canvasElement, + basicResComparatorLinkId, + false + ); + + expect(resultComparator).toEqual( + expect.objectContaining({ + value: basicResComparatorTargetWeight.toString(), + comparator: basicResTargetComparator, + unit: undefined + }) + ); } }; -export const QuantityUnitOptionResponse: Story = { +const singleUnitLinkId = 'duration-single-unit'; +const singleTargetNumber = 10; +const singleTargetUnit = 'Day(s)'; +const qQuantitySingle = questionnaireFactory([ + { + linkId: singleUnitLinkId, + type: 'quantity', + extension: [unitExtFactory('d', singleTargetUnit)] + } +]); + +export const QuantitySingleUnit: Story = { args: { - questionnaire: qQuantityUnitOption, - questionnaireResponse: qrQuantityUnitOptionResponse + questionnaire: qQuantitySingle + }, + play: async ({ canvasElement }) => { + await inputQuantity(canvasElement, singleUnitLinkId, singleTargetNumber); + + await waitFor(async () => { + const result = await getAnswers(singleUnitLinkId); + expect(result).toHaveLength(1); + expect(result[0].valueQuantity).toEqual( + expect.objectContaining({ + value: singleTargetNumber, + unit: singleTargetUnit, + code: 'd', + comparator: undefined, + system: ucumSystem + }) + ); + }); } }; -export const QuantityCalculation: Story = { +const multiLinkId = 'duration-multi-unit'; +const multiTargetNumber = 20; +const multiTargetUnit = 'Week(s)'; + +const qQuantityMulti = questionnaireFactory([ + { + linkId: multiLinkId, + type: 'quantity', + extension: [unitOptionExtFactory('d', 'Day(s)'), unitOptionExtFactory('wk', multiTargetUnit)] + } +]); + +export const QuantityMultiUnit: Story = { + args: { + questionnaire: qQuantityMulti + }, + play: async ({ canvasElement }) => { + await inputQuantity(canvasElement, multiLinkId, multiTargetNumber, multiTargetUnit); + + await waitFor(async () => { + const result = await getAnswers(multiLinkId); + expect(result).toHaveLength(1); + expect(result[0].valueQuantity).toEqual( + expect.objectContaining({ + value: multiTargetNumber, + unit: multiTargetUnit, + comparator: undefined, + system: ucumSystem + }) + ); + }); + } +}; + +const multiComparatorLinkId = 'duration-multi-unit-comparator'; +const multiComparatorTargetNumber = 30; +const multiComparatorTargetUnit = 'Day(s)'; +const multiComparatorTargetComparator = '>'; + +const qQuantityMultiComparator = questionnaireFactory([ + { + linkId: multiComparatorLinkId, + type: 'quantity', + extension: [ + unitOptionExtFactory('d', multiComparatorTargetUnit), + unitOptionExtFactory('wk', 'Week(s)') + ] + } +]); + +export const QuantityMultiUnitComparator: Story = { + args: { + questionnaire: qQuantityMultiComparator + }, + play: async ({ canvasElement }) => { + await inputQuantity( + canvasElement, + multiComparatorLinkId, + multiComparatorTargetNumber, + multiComparatorTargetUnit, + multiComparatorTargetComparator + ); + + await waitFor(async () => { + const result = await getAnswers(multiComparatorLinkId); + expect(result).toHaveLength(1); + expect(result[0].valueQuantity).toEqual( + expect.objectContaining({ + value: multiComparatorTargetNumber, + unit: multiComparatorTargetUnit, + comparator: multiComparatorTargetComparator, + system: ucumSystem + }) + ); + }); + } +}; +const unitsingleResLinkId = 'duration-single-unit'; +const unitsingleQuantity: Quantity = { + value: 2, + unit: 'Day(s)', + system: ucumSystem, + code: 'd' +}; +const qrQuantityUnitOptionSingleResponse = qrFactory([ + { + linkId: unitsingleResLinkId, + answer: [{ valueQuantity: unitsingleQuantity }] + } +]); + +export const QuantitySingleUnitOptionResponse: Story = { + args: { + questionnaire: qQuantitySingle, + questionnaireResponse: qrQuantityUnitOptionSingleResponse + }, + play: async ({ canvasElement }) => { + const resultSingle = await getQuantityTextValues(canvasElement, unitsingleResLinkId, false); + + expect(resultSingle).toEqual( + expect.objectContaining({ + value: unitsingleQuantity?.value?.toString(), + unit: undefined, + comparator: '' + }) + ); + } +}; + +const unitmultiResLinkId = 'duration-multi-unit'; +const unitmultiResQuantity: Quantity = { + value: 48, + unit: 'Hour(s)', + system: ucumSystem, + code: 'hour' +}; +const qrQuantityUnitOptionMultiResponse = qrFactory([ + { + linkId: unitmultiResLinkId, + answer: [{ valueQuantity: unitmultiResQuantity }] + } +]); + +export const QuantityMultiUnitOptionResponse: Story = { + args: { + questionnaire: qQuantityMulti, + questionnaireResponse: qrQuantityUnitOptionMultiResponse + }, + play: async ({ canvasElement }) => { + const resultMulti = await getQuantityTextValues(canvasElement, unitmultiResLinkId, true); + expect(resultMulti).toEqual( + expect.objectContaining({ + value: unitmultiResQuantity?.value?.toString(), + unit: unitmultiResQuantity.unit, + comparator: '' + }) + ); + } +}; + +const unitmultiComparatorResLinkId = 'duration-multi-unit-comparator'; +const unitMultiComparatorQuantity: Quantity = { + value: 48, + comparator: '>=', + unit: 'Hour(s)', + system: ucumSystem, + code: 'hour' +}; + +const qrQuantityUnitOptionMultiComparatorResponse = qrFactory([ + { + linkId: unitmultiComparatorResLinkId, + answer: [{ valueQuantity: unitMultiComparatorQuantity }] + } +]); + +export const QuantityMultiUnitOptionComparatorResponse: Story = { args: { - questionnaire: qQuantityCalculation + questionnaire: qQuantityMultiComparator, + questionnaireResponse: qrQuantityUnitOptionMultiComparatorResponse + }, + play: async ({ canvasElement }) => { + const resultMultiComparator = await getQuantityTextValues( + canvasElement, + unitmultiComparatorResLinkId, + true + ); + expect(resultMultiComparator).toEqual( + expect.objectContaining({ + value: unitMultiComparatorQuantity.value?.toString(), + unit: unitMultiComparatorQuantity.unit, + comparator: unitMultiComparatorQuantity.comparator + }) + ); } }; diff --git a/packages/smart-forms-renderer/src/stories/itemTypes/String.stories.tsx b/packages/smart-forms-renderer/src/stories/itemTypes/String.stories.tsx index 552350446..cd3258c53 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/String.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/String.stories.tsx @@ -17,7 +17,6 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; import BuildFormWrapperForStorybook from '../storybookWrappers/BuildFormWrapperForStorybook'; -import { qStringCalculation } from '../assets/questionnaires'; import { findByLinkId, getAnswers, @@ -98,9 +97,3 @@ export const StringBasicResponse: Story = { expect(inputText).toBe(targetText); } }; - -export const StringCalculation: Story = { - args: { - questionnaire: qStringCalculation - } -}; diff --git a/packages/smart-forms-renderer/src/stories/itemTypes/Text.stories.tsx b/packages/smart-forms-renderer/src/stories/itemTypes/Text.stories.tsx index 58ba50f62..a108ccc74 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/Text.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/Text.stories.tsx @@ -17,7 +17,6 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; import BuildFormWrapperForStorybook from '../storybookWrappers/BuildFormWrapperForStorybook'; -import { qTextCalculation } from '../assets/questionnaires'; import { findByLinkId, getAnswers, @@ -85,10 +84,3 @@ export const TextBasicResponse: Story = { expect(inputText).toBe(targetText); } }; - -// TODO: Move to separate storybook -export const TextCalculation: Story = { - args: { - questionnaire: qTextCalculation - } -}; diff --git a/packages/smart-forms-renderer/src/stories/sdc/BehaviorCalculations.stories.tsx b/packages/smart-forms-renderer/src/stories/sdc/BehaviorCalculations.stories.tsx index 46811f39f..a3320d323 100644 --- a/packages/smart-forms-renderer/src/stories/sdc/BehaviorCalculations.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/sdc/BehaviorCalculations.stories.tsx @@ -18,12 +18,16 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; import BuildFormWrapperForStorybook from '../storybookWrappers/BuildFormWrapperForStorybook'; import { - qCalculatedExpressionBMICalculator, qCalculatedExpressionCvdRiskCalculator, qInitialExpression, qLaunchContext, qVariable } from '../assets/questionnaires'; +import { + calculatedExpressionExtFactory, + questionnaireFactory, + variableExtFactory +} from '../testUtils'; // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export const meta = { @@ -56,6 +60,43 @@ export const InitialExpression: Story = { } }; +const heightLinkId = 'patient-height'; +const weightLinkId = 'patient-weight'; +const bmiLinkIdCalc = 'bmi-result'; +const bmiGroupLinkId = 'bmi-calculation'; + +const qCalculatedExpressionBMICalculator = questionnaireFactory([ + { + linkId: bmiGroupLinkId, + type: 'group', + extension: [ + variableExtFactory('height', `item.where(linkId='${heightLinkId}').answer.value`), + variableExtFactory('weight', `item.where(linkId='${weightLinkId}').answer.value`) + ], + item: [ + { + linkId: heightLinkId, + text: 'Height', + type: 'decimal', + readOnly: false + }, + { + linkId: weightLinkId, + text: 'Weight', + type: 'decimal', + readOnly: false + }, + { + extension: [calculatedExpressionExtFactory('(%weight/((%height/100).power(2))).round(1)')], + linkId: bmiLinkIdCalc, + text: 'Value', + type: 'decimal', + readOnly: true + } + ] + } +]); + export const CalculatedExpressionBMICalculator: Story = { args: { questionnaire: qCalculatedExpressionBMICalculator diff --git a/packages/smart-forms-renderer/src/stories/testUtils.ts b/packages/smart-forms-renderer/src/stories/testUtils.ts index d5fa0b0dd..0c1d8d1c7 100644 --- a/packages/smart-forms-renderer/src/stories/testUtils.ts +++ b/packages/smart-forms-renderer/src/stories/testUtils.ts @@ -7,8 +7,85 @@ import type { QuestionnaireResponse, QuestionnaireResponseItem } from 'fhir/r4'; -import { fireEvent, screen, waitFor } from '@testing-library/react'; -import { userEvent } from '@testing-library/user-event'; +import { fireEvent, screen, userEvent, waitFor } from 'storybook/internal/test'; + +export async function getQuantityTextValues( + canvasElement: HTMLElement, + linkId: string, + unit: boolean +) { + const element = await findByLinkId(canvasElement, linkId); + const quantityComparator = element.querySelector( + 'div[data-test="q-item-quantity-comparator"] input' + ); + const quantityInput = element.querySelector('div[data-test="q-item-quantity-field"] input'); + const quantityUnit = element.querySelector('div[data-test="q-item-unit-field"] input'); + + // Error section + if (!quantityComparator) { + throw new Error( + `File input was not found inside [data-test="q-item-quantity-comparator"] block` + ); + } + if (!quantityInput) { + throw new Error(`File input was not found inside [data-test="q-item-quantity-field"] block`); + } + if (!quantityUnit && unit) { + throw new Error(`File input was not found inside [data-test="q-item-unit-field"] block`); + } + + return { + comparator: quantityComparator?.getAttribute('value'), + value: quantityInput?.getAttribute('value'), + unit: quantityUnit?.getAttribute('value') + }; +} + +export async function inputQuantity( + canvasElement: HTMLElement, + linkId: string, + quantity: number, + unit?: string, + comparator?: string +) { + const questionElement = await findByLinkId(canvasElement, linkId); + + const comparatorInput = questionElement?.querySelector( + `div[data-test="q-item-quantity-comparator"] input` + ); + const quantityInput = questionElement?.querySelector( + `div[data-test="q-item-quantity-field"] input` + ); + const unitInput = questionElement?.querySelector(`div[data-test="q-item-unit-field"] input`); + + // Error section + if (comparator && !comparatorInput) { + throw new Error(`Input was not found inside [data-test="q-item-quantity-comparator"] block`); + } + if (!quantityInput) { + throw new Error(`Input was not found inside [data-test="q-item-quantity-field"] block`); + } + if (!unitInput && unit) { + throw new Error(`Input was not found inside [data-test="q-item-unit-field"] block`); + } + + if (comparator && comparatorInput) { + fireEvent.focus(comparatorInput); + fireEvent.keyDown(comparatorInput, { key: 'ArrowDown', code: 'ArrowDown' }); + const option = await screen.findByText(comparator); + fireEvent.click(option); + } + if (unit && unitInput) { + fireEvent.focus(unitInput); + fireEvent.keyDown(unitInput, { key: 'ArrowDown', code: 'ArrowDown' }); + const option = await screen.findByText(unit); + fireEvent.click(option); + } + fireEvent.change(quantityInput, { target: { value: quantity } }); + + // Here we await for debounced store update + await new Promise((resolve) => setTimeout(resolve, 500)); +} export async function getAnswers(linkId: string) { const qr = questionnaireResponseStore.getState().updatableResponse; @@ -28,11 +105,15 @@ export async function getGroupAnswers(groupLinkid: string, answerLinkid: string) return result; } -export function questionnaireFactory(items: QuestionnaireItem[]): Questionnaire { +export function questionnaireFactory( + items: QuestionnaireItem[], + extra?: Omit +): Questionnaire { return { resourceType: 'Questionnaire', status: 'active', - item: items + item: items, + ...extra }; } @@ -63,6 +144,60 @@ export function openLabelExtFactory(text: string): Extension { }; } +export function calculatedExpressionExtFactory(text: string): Extension { + return { + url: 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-calculatedExpression', + valueExpression: { + language: 'text/fhirpath', + expression: text + } + }; +} + +export function variableExtFactory(name: string, text: string): Extension { + return { + url: 'http://hl7.org/fhir/StructureDefinition/variable', + valueExpression: { + name: name, + language: 'text/fhirpath', + expression: text + } + }; +} + +export function unitOptionExtFactory(code: string, display: string): Extension { + return { + url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-unitOption', + valueCoding: { + system: 'http://unitsofmeasure.org', + code: code, + display: display + } + }; +} +export function unitExtFactory(code: string, display: string): Extension { + return { + url: 'http://hl7.org/fhir/StructureDefinition/questionnaire-unit', + valueCoding: { + system: 'http://unitsofmeasure.org', + code: code, + display: display + } + }; +} + +export function сqfExpressionFactory(text: string) { + return { + url: 'http://hl7.org/fhir/StructureDefinition/cqf-expression', + valueExpression: { + language: 'text/fhirpath', + expression: text + } + }; +} + +export const ucumSystem = 'http://unitsofmeasure.org'; + export async function inputText( canvasElement: HTMLElement, linkId: string, diff --git a/packages/testing-toolkit/.gitignore b/packages/testing-toolkit/.gitignore deleted file mode 100644 index 945ef5a39..000000000 --- a/packages/testing-toolkit/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -node_modules -lib -dist -temp - diff --git a/packages/testing-toolkit/package.json b/packages/testing-toolkit/package.json deleted file mode 100644 index eb7132831..000000000 --- a/packages/testing-toolkit/package.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "name": "@aehrc/testing-toolkit", - "version": "1.0.0", - "description": "Testing toolkit for Smart Forms", - "main": "lib/index.js", - "scripts": { - "compile": "tsc", - "watch": "tsc -w", - "build": "npm run compile", - "test": "jest", - "test:watch": "jest --watch", - "storybook": "storybook dev -p 6006", - "storybook-watch": "concurrently -n \"STORYBOOK,TSC\" -c \"cyan.bold,green.bold\" \"storybook dev -p 6006\" \"tsc -w\"", - "build-storybook": "storybook build", - "chromatic": "chromatic --exit-zero-on-changes" - }, - "license": "Apache-2.0", - "homepage": "https://github.com/aehrc/smart-forms#readme", - "dependencies": { - "@testing-library/react": "^16.3.0" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - }, - "devDependencies": { - "zustand": "^5.0.8" - } -} diff --git a/packages/testing-toolkit/src/index.ts b/packages/testing-toolkit/src/index.ts deleted file mode 100644 index adf1f8078..000000000 --- a/packages/testing-toolkit/src/index.ts +++ /dev/null @@ -1,245 +0,0 @@ -import { fireEvent, screen, waitFor } from '@testing-library/react'; -import { userEvent } from '@testing-library/user-event'; - -export async function inputText( - canvasElement: HTMLElement, - linkId: string, - text: string | boolean | number -) { - const questionElement = await findByLinkId(canvasElement, linkId); - - const input = - questionElement?.querySelector('input') ?? questionElement?.querySelector('textarea'); - - if (!input) { - throw new Error(`Input or textarea was not found inside ${`[data-linkid=${linkId}] block`}`); - } - - fireEvent.change(input, { target: { value: text } }); - - // Here we await for debounced store update - await new Promise((resolve) => setTimeout(resolve, 500)); -} -export async function checkCheckBox(canvasElement: HTMLElement, linkId: string) { - const questionElement = await findByLinkId(canvasElement, linkId); - const input = - questionElement?.querySelector('input') ?? questionElement?.querySelector('textarea'); - - if (!input) { - throw new Error(`Input or textarea was not found inside ${`[data-linkid=${linkId}] block`}`); - } - - fireEvent.click(input); - - // Here we await for debounced store update - await new Promise((resolve) => setTimeout(resolve, 500)); -} - -export async function inputFile( - canvasElement: HTMLElement, - linkId: string, - files: File | File[], - url: string, - filename: string -) { - const questionElement = await findByLinkId(canvasElement, linkId); - const input = questionElement?.querySelector('input'); - - const textareaUrl = questionElement?.querySelector(`textarea[data-test="q-item-attachment-url"]`); - const textareaName = questionElement?.querySelector( - `textarea[data-test="q-item-attachment-file-name"]` - ); - - if (!input) { - throw new Error(`File input was not found inside [data-linkid=${linkId}] block`); - } - if (!textareaUrl) { - throw new Error(`File input was not found inside [data-linkid="URL"] block`); - } - if (!textareaName) { - throw new Error(`File input was not found inside [data-linkid="File name (optional)"] block`); - } - - const fileList = Array.isArray(files) ? files : [files]; - await userEvent.upload(input, fileList); - - fireEvent.change(textareaUrl, { target: { value: url } }); - fireEvent.change(textareaName, { target: { value: filename } }); - // Here we await for debounced store update - await new Promise((resolve) => setTimeout(resolve, 500)); -} - -export async function inputDate( - canvasElement: HTMLElement, - linkId: string, - text: string | boolean -) { - return await inputText(canvasElement, linkId, text); -} - -export async function inputTime( - canvasElement: HTMLElement, - linkId: string, - text: string | boolean -) { - return await inputText(canvasElement, linkId, text); -} - -export async function inputReference( - canvasElement: HTMLElement, - linkId: string, - text: string | boolean -) { - return await inputText(canvasElement, linkId, text); -} - -export async function inputDecimal(canvasElement: HTMLElement, linkId: string, text: number) { - return await inputText(canvasElement, linkId, text); -} - -export async function inputUrl(canvasElement: HTMLElement, linkId: string, text: string) { - return await inputText(canvasElement, linkId, text); -} - -export async function inputInteger(canvasElement: HTMLElement, linkId: string, text: number) { - return await inputText(canvasElement, linkId, text); -} - -export async function inputDateTime( - canvasElement: HTMLElement, - linkId: string, - date: string, - time: string, - amPm: string -) { - const questionElement = await findByLinkId(canvasElement, linkId); - console.log(questionElement, 777); - const inputDate = questionElement?.querySelector('div[data-test="date"] input'); - const inputTime = questionElement?.querySelector('div[data-test="time"] input'); - const inputAmPm = questionElement?.querySelector('div[data-test="ampm"] input'); - - if (!inputTime) { - throw new Error(`Input or textarea was not found inside ${`[data-linkid=${linkId}] block`}`); - } - if (!inputDate) { - throw new Error(`Input or textarea was not found inside ${`[data-linkid=${linkId}] block`}`); - } - if (!inputAmPm) { - throw new Error(`Input or textarea was not found inside ${`[data-linkid=${linkId}] block`}`); - } - - fireEvent.change(inputDate, { target: { value: date } }); - fireEvent.change(inputTime, { target: { value: time } }); - fireEvent.change(inputAmPm, { target: { value: amPm } }); - - // Here we await for debounced store update - await new Promise((resolve) => setTimeout(resolve, 500)); -} - -export async function checkRadioOption(canvasElement: HTMLElement, linkId: string, text: string) { - const questionElement = await findByLinkId(canvasElement, linkId); - const radio = questionElement?.querySelector(`span[data-test="radio-single-${text}"] input`); - - if (!radio) { - throw new Error(`Input or textarea was not found inside ${`[data-linkid=${linkId}] block`}`); - } - - fireEvent.click(radio); - // Here we await for debounced store update - await new Promise((resolve) => setTimeout(resolve, 500)); -} - -export async function getInputText(canvasElement: HTMLElement, linkId: string) { - const questionElement = await findByLinkId(canvasElement, linkId); - const input = - questionElement?.querySelector('input') ?? questionElement?.querySelector('textarea'); - - if (!input) { - throw new Error(`Input or textarea was not found inside ${`[data-linkid=${linkId}] block`}`); - } - - return input.value; -} - -export async function chooseSelectOption( - canvasElement: HTMLElement, - linkId: string, - optionLabel: string -) { - const questionElement = await findByLinkId(canvasElement, linkId); - - const input = questionElement.querySelector('input, textarea'); - if (!input) { - throw new Error(`There is no input inside ${linkId}`); - } - - fireEvent.focus(input); - fireEvent.keyDown(input, { key: 'ArrowDown', code: 'ArrowDown' }); - - const option = await screen.findByText(optionLabel); - fireEvent.click(option); -} -export async function chooseQuantityOption( - canvasElement: HTMLElement, - linkId: string, - quantity: number | string, - quantityComparator?: string -) { - const questionElement = await findByLinkId(canvasElement, linkId); - - const inputComaparator = questionElement.querySelector( - 'div[data-test=""q-item-quantity-comparator""] input' - ); - const inputWeight = questionElement.querySelector('div[data-test="q-item-quantity-field"] input'); - - if (!inputComaparator) { - throw new Error(`There is no input inside ${linkId}`); - } - if (!inputWeight) { - throw new Error(`There is no input inside ${linkId}`); - } - - fireEvent.focus(inputComaparator); - fireEvent.keyDown(inputComaparator, { key: 'ArrowDown', code: 'ArrowDown' }); - - if (quantityComparator) { - const option = await screen.findByText(quantityComparator); - fireEvent.click(option); - fireEvent.change(inputComaparator, { target: { value: quantityComparator } }); - } - - fireEvent.change(inputWeight, { target: { value: quantity } }); - // Here we await for debounced store update - await new Promise((resolve) => setTimeout(resolve, 500)); -} - -export async function findByLinkId(canvasElement: HTMLElement, linkId: string) { - const selector = `[data-linkid="${linkId}"]`; - return await waitFor(() => { - const el = canvasElement.querySelector(selector); - if (!el) { - throw new Error(`Element ${selector} not found`); - } - return el; - }); -} -export async function inputOpenChoiceOtherText( - canvasElement: HTMLElement, - linkId: string, - text: string -) { - const questionElement = await findByLinkId(canvasElement, linkId); - - const textarea = questionElement?.querySelector( - 'div[data-test="q-item-radio-open-label-box"] textarea' - ); - - if (!textarea) { - throw new Error(`Input or textarea was not found inside ${`[data-test=${linkId}] block`}`); - } - - fireEvent.change(textarea, { target: { value: text } }); - - // Here we await for debounced store update - await new Promise((resolve) => setTimeout(resolve, 500)); -} diff --git a/packages/testing-toolkit/src/vite-env.d.ts b/packages/testing-toolkit/src/vite-env.d.ts deleted file mode 100644 index 9921b7f24..000000000 --- a/packages/testing-toolkit/src/vite-env.d.ts +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2023 Commonwealth Scientific and Industrial Research - * Organisation (CSIRO) ABN 41 687 119 230. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/// -// Vite is only used for Storybook - -interface ImportMetaEnv { - readonly VITE_RENDERER_VERSION: string; -} - -interface ImportMeta { - readonly env: ImportMetaEnv; -} diff --git a/packages/testing-toolkit/tsconfig.json b/packages/testing-toolkit/tsconfig.json deleted file mode 100644 index 7508ed78e..000000000 --- a/packages/testing-toolkit/tsconfig.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "compilerOptions": { - "target": "ES6", - "module": "ES6", - "allowSyntheticDefaultImports": true, - "esModuleInterop": true, - "moduleResolution": "node", - "forceConsistentCasingInFileNames": true, - "useUnknownInCatchVariables": false, - "strict": true, - "skipLibCheck": true, - "jsx": "react-jsx", - "sourceMap": true, - "allowJs": true, - "outDir": "lib", - "declaration": true, - "checkJs": true, - "resolveJsonModule": true - }, - "include": ["src"], - "exclude": ["lib", "dist"] -} diff --git a/packages/testing-toolkit/vite.config.ts b/packages/testing-toolkit/vite.config.ts deleted file mode 100644 index bf414cad3..000000000 --- a/packages/testing-toolkit/vite.config.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2025 Commonwealth Scientific and Industrial Research - * Organisation (CSIRO) ABN 41 687 119 230. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { defineConfig } from 'vite'; -// @ts-ignore -import { version } from './package.json'; - -// This Vite config is for storybook usage only. -// https://vitejs.dev/config/ -export default defineConfig({ - define: { - 'import.meta.env.VITE_RENDERER_VERSION': JSON.stringify(version ?? 'unspecified') - } -});