From 0556614b3106e9656575aa920193b0f9a3f7710a Mon Sep 17 00:00:00 2001 From: Vadim Laletin Date: Sun, 17 Aug 2025 11:35:37 +0200 Subject: [PATCH 01/12] Migrate smart-forms-app to vitest --- apps/smart-forms-app/jest.config.js | 5 - apps/smart-forms-app/jest.config.ts | 34 -- apps/smart-forms-app/package.json | 8 +- .../src/tests/extractedBundleSelector.test.ts | 2 +- .../src/tests/questionnaireRenderer.test.tsx | 7 + apps/smart-forms-app/vitest.config.ts | 15 + package-lock.json | 330 ++++++++++++++++-- 7 files changed, 334 insertions(+), 67 deletions(-) delete mode 100644 apps/smart-forms-app/jest.config.js delete mode 100644 apps/smart-forms-app/jest.config.ts create mode 100644 apps/smart-forms-app/src/tests/questionnaireRenderer.test.tsx create mode 100644 apps/smart-forms-app/vitest.config.ts diff --git a/apps/smart-forms-app/jest.config.js b/apps/smart-forms-app/jest.config.js deleted file mode 100644 index a58c252f8..000000000 --- a/apps/smart-forms-app/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -/** @type {import('ts-jest').JestConfigWithTsJest} */ -module.exports = { - preset: 'ts-jest', - testEnvironment: 'node' -}; diff --git a/apps/smart-forms-app/jest.config.ts b/apps/smart-forms-app/jest.config.ts deleted file mode 100644 index 3a3f238ba..000000000 --- a/apps/smart-forms-app/jest.config.ts +++ /dev/null @@ -1,34 +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 { Config } from 'jest'; - -const config: Config = { - verbose: true, - roots: [''], - transform: { - '^.+\\.ts?$': 'ts-jest' - }, - // Exclude "spec" folder - testRegex: '(/__tests__/.*|(\\.|/)(test))\\.ts?$', - moduleFileExtensions: ['ts', 'js', 'json', 'node'], - collectCoverage: true, - clearMocks: true, - coverageDirectory: 'coverage' -}; - -export default config; diff --git a/apps/smart-forms-app/package.json b/apps/smart-forms-app/package.json index bf9d7d5e8..02275be06 100644 --- a/apps/smart-forms-app/package.json +++ b/apps/smart-forms-app/package.json @@ -8,7 +8,7 @@ "dev": "vite", "start": "vite", "build": "tsc && CI=false vite build", - "test": "jest --config ./jest.config.ts", + "test": "vitest run", "preview": "vite preview --port 4173", "playwright": "npx playwright test", "playwright-ui": "npx playwright test --ui" @@ -74,10 +74,8 @@ "zustand": "^5.0.5" }, "devDependencies": { - "@jest/globals": "^30.0.4", "@playwright/test": "^1.54.1", "@sentry/cli": "^2.42.2", - "@testing-library/jest-dom": "^6.6.3", "@testing-library/react": "^16.3.0", "@testing-library/user-event": "^14.6.1", "@types/fhir": "^0.0.41", @@ -91,18 +89,18 @@ "@types/react-helmet": "^6.1.11", "@types/react-syntax-highlighter": "^15.5.13", "@vitejs/plugin-react": "^4.6.0", + "@vitest/ui": "^3.2.4", "eslint": "^9.31.0", "eslint-plugin-react": "^7.37.5", "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-refresh": "^0.4.20", "eslint-plugin-storybook": "^9.0.15", - "jest": "^29.7.0", "jsdom": "^26.1.0", "prettier": "^3.6.2", - "ts-jest": "^29.4.0", "typescript": "^5.8.3", "vite": "^5.4.19", "vite-plugin-svgr": "^4.3.0", + "vitest": "^3.2.4", "yui-lint": "^0.2.0" }, "eslintConfig": { diff --git a/apps/smart-forms-app/src/tests/extractedBundleSelector.test.ts b/apps/smart-forms-app/src/tests/extractedBundleSelector.test.ts index d3df9a3d0..d1b50c630 100644 --- a/apps/smart-forms-app/src/tests/extractedBundleSelector.test.ts +++ b/apps/smart-forms-app/src/tests/extractedBundleSelector.test.ts @@ -1,4 +1,4 @@ -import { describe, expect } from '@jest/globals'; +import { describe, expect } from 'vitest'; import { createSelectionKey, getEntriesValidKeys, diff --git a/apps/smart-forms-app/src/tests/questionnaireRenderer.test.tsx b/apps/smart-forms-app/src/tests/questionnaireRenderer.test.tsx new file mode 100644 index 000000000..f1d54fbc2 --- /dev/null +++ b/apps/smart-forms-app/src/tests/questionnaireRenderer.test.tsx @@ -0,0 +1,7 @@ +import { render } from '@testing-library/react'; +import { test } from 'vitest'; +import { BaseRenderer } from '@aehrc/smart-forms-renderer'; + +test('Basic component renders correctly', async () => { + render(); +}); diff --git a/apps/smart-forms-app/vitest.config.ts b/apps/smart-forms-app/vitest.config.ts new file mode 100644 index 000000000..6722783a6 --- /dev/null +++ b/apps/smart-forms-app/vitest.config.ts @@ -0,0 +1,15 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + globals: true, + environment: 'jsdom', + include: ['**/__tests__/**/*.{test,spec}.{js,ts,jsx,tsx}', '**/*.{test,spec}.{js,ts,jsx,tsx}'], + exclude: ['**/e2e/**', '**/node_modules/**'], + coverage: { + provider: 'v8', + reporter: ['text', 'json', 'html'], + exclude: ['**/e2e/**', '**/node_modules/**'], + }, + }, +}); diff --git a/package-lock.json b/package-lock.json index 46bf3502a..e362046ed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -40,6 +40,7 @@ "@emotion/styled": "^11.14.0", "@fontsource/material-icons": "^5.2.5", "@fontsource/roboto": "^5.2.6", + "@iconify/react": "^5.2.0", "@microlink/react-json-view": "^1.26.2", "@monaco-editor/react": "^4.7.0", "@mui/icons-material": "^7.1.1", @@ -79,10 +80,8 @@ "zustand": "^5.0.5" }, "devDependencies": { - "@jest/globals": "^30.0.4", "@playwright/test": "^1.54.1", "@sentry/cli": "^2.42.2", - "@testing-library/jest-dom": "^6.6.3", "@testing-library/react": "^16.3.0", "@testing-library/user-event": "^14.6.1", "@types/fhir": "^0.0.41", @@ -95,19 +94,19 @@ "@types/react-dom": "^18.3.5", "@types/react-helmet": "^6.1.11", "@types/react-syntax-highlighter": "^15.5.13", - "@vitejs/plugin-react": "^4.7.0", + "@vitejs/plugin-react": "^4.6.0", + "@vitest/ui": "^3.2.4", "eslint": "^9.31.0", "eslint-plugin-react": "^7.37.5", "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-refresh": "^0.4.20", - "eslint-plugin-storybook": "^9.1.2", - "jest": "^29.7.0", + "eslint-plugin-storybook": "^9.0.15", "jsdom": "^26.1.0", "prettier": "^3.6.2", - "ts-jest": "^29.4.0", "typescript": "^5.8.3", "vite": "^5.4.19", "vite-plugin-svgr": "^4.3.0", + "vitest": "^3.2.4", "yui-lint": "^0.2.0" } }, @@ -8492,6 +8491,27 @@ "url": "https://github.com/sponsors/nzakas" } }, + "node_modules/@iconify/react": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/@iconify/react/-/react-5.2.1.tgz", + "integrity": "sha512-37GDR3fYDZmnmUn9RagyaX+zca24jfVOMY8E1IXTqJuE8pxNtN51KWPQe3VODOWvuUurq7q9uUu3CFrpqj5Iqg==", + "license": "MIT", + "dependencies": { + "@iconify/types": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/cyberalien" + }, + "peerDependencies": { + "react": ">=16" + } + }, + "node_modules/@iconify/types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", + "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", + "license": "MIT" + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -13889,6 +13909,46 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/@vitest/runner": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.4.tgz", + "integrity": "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "3.2.4", + "pathe": "^2.0.3", + "strip-literal": "^3.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.4.tgz", + "integrity": "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "3.2.4", + "magic-string": "^0.30.17", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot/node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, "node_modules/@vitest/spy": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.4.tgz", @@ -13902,6 +13962,43 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/@vitest/ui": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-3.2.4.tgz", + "integrity": "sha512-hGISOaP18plkzbWEcP/QvtRW1xDXF2+96HbEX6byqQhAUbiS5oH6/9JwW+QsQCIYON2bI6QZBF+2PvOmrRZ9wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "3.2.4", + "fflate": "^0.8.2", + "flatted": "^3.3.3", + "pathe": "^2.0.3", + "sirv": "^3.0.1", + "tinyglobby": "^0.2.14", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "vitest": "3.2.4" + } + }, + "node_modules/@vitest/ui/node_modules/sirv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.1.tgz", + "integrity": "sha512-FoqMu0NCGBLCcAkS1qA+XJIQTR6/JHfQXl+uGteNCQ76T91DMUjPa9xfmeqMY3z80nLSg9yQmNjK0Px6RWsH/A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@vitest/utils": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.4.tgz", @@ -18587,9 +18684,10 @@ } }, "node_modules/es-module-lexer": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz", - "integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==" + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "license": "MIT" }, "node_modules/es-object-atoms": { "version": "1.1.1", @@ -19426,6 +19524,16 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/expect-type": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.2.tgz", + "integrity": "sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/expo-modules-autolinking": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-0.0.3.tgz", @@ -19768,10 +19876,14 @@ "peer": true }, "node_modules/fdir": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.3.tgz", - "integrity": "sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==", + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, "peerDependencies": { "picomatch": "^3 || ^4" }, @@ -19799,6 +19911,13 @@ "optional": true, "peer": true }, + "node_modules/fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", + "dev": true, + "license": "MIT" + }, "node_modules/fhir-extension-helpers": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/fhir-extension-helpers/-/fhir-extension-helpers-0.3.0.tgz", @@ -34472,6 +34591,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -34779,6 +34905,13 @@ "node": ">=8" } }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, "node_modules/stackframe": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", @@ -34823,9 +34956,10 @@ } }, "node_modules/std-env": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.8.0.tgz", - "integrity": "sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==" + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.9.0.tgz", + "integrity": "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==", + "license": "MIT" }, "node_modules/storybook": { "version": "9.1.2", @@ -35217,6 +35351,26 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strip-literal": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.0.0.tgz", + "integrity": "sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-tokens": "^9.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/strip-literal/node_modules/js-tokens": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", + "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", + "dev": true, + "license": "MIT" + }, "node_modules/structured-headers": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/structured-headers/-/structured-headers-0.4.1.tgz", @@ -35864,6 +36018,13 @@ "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, "node_modules/tinyexec": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", @@ -35871,12 +36032,13 @@ "dev": true }, "node_modules/tinyglobby": { - "version": "0.2.12", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.12.tgz", - "integrity": "sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==", + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", + "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", "dev": true, + "license": "MIT", "dependencies": { - "fdir": "^6.4.3", + "fdir": "^6.4.4", "picomatch": "^4.0.2" }, "engines": { @@ -35887,9 +36049,9 @@ } }, "node_modules/tinypool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.0.tgz", - "integrity": "sha512-7CotroY9a8DKsKprEy/a14aCCm8jYVmR7aFy4fpkZM8sdpNJbKkixuNjgM50yCmip2ezc8z4N7k3oe2+rfRJCQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", + "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", "license": "MIT", "engines": { "node": "^18.0.0 || >=20.0.0" @@ -37369,6 +37531,29 @@ } } }, + "node_modules/vite-node": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.4.tgz", + "integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.4.1", + "es-module-lexer": "^1.7.0", + "pathe": "^2.0.3", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, "node_modules/vite-plugin-svgr": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/vite-plugin-svgr/-/vite-plugin-svgr-4.3.0.tgz", @@ -37827,6 +38012,89 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/vitest": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.4.tgz", + "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/chai": "^5.2.2", + "@vitest/expect": "3.2.4", + "@vitest/mocker": "3.2.4", + "@vitest/pretty-format": "^3.2.4", + "@vitest/runner": "3.2.4", + "@vitest/snapshot": "3.2.4", + "@vitest/spy": "3.2.4", + "@vitest/utils": "3.2.4", + "chai": "^5.2.0", + "debug": "^4.4.1", + "expect-type": "^1.2.1", + "magic-string": "^0.30.17", + "pathe": "^2.0.3", + "picomatch": "^4.0.2", + "std-env": "^3.9.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.2", + "tinyglobby": "^0.2.14", + "tinypool": "^1.1.1", + "tinyrainbow": "^2.0.0", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", + "vite-node": "3.2.4", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/debug": "^4.1.12", + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "@vitest/browser": "3.2.4", + "@vitest/ui": "3.2.4", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/debug": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/vitest/node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, "node_modules/vlq": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/vlq/-/vlq-1.0.1.tgz", @@ -38772,6 +39040,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/widest-line": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", @@ -39354,6 +39639,7 @@ "@fontsource/inter": "^5.2.6", "@fontsource/material-icons": "^5.2.5", "@fontsource/roboto": "^5.2.6", + "@iconify/react": "^5.2.1", "@mui/icons-material": "^7.1.1", "@mui/lab": "^7.0.0-beta.13", "@mui/material": "^7.1.1", From 5629100d6ce9da52c440bb4707f9fe562738ba24 Mon Sep 17 00:00:00 2001 From: Vadim Laletin Date: Sun, 17 Aug 2025 11:45:29 +0200 Subject: [PATCH 02/12] Update lock --- apps/smart-forms-app/package.json | 1 - package-lock.json | 27 ++------------------------- 2 files changed, 2 insertions(+), 26 deletions(-) diff --git a/apps/smart-forms-app/package.json b/apps/smart-forms-app/package.json index 2739a8066..11150fbb5 100644 --- a/apps/smart-forms-app/package.json +++ b/apps/smart-forms-app/package.json @@ -87,7 +87,6 @@ "@types/react-dom": "^18.3.5", "@types/react-helmet": "^6.1.11", "@types/react-syntax-highlighter": "^15.5.13", - "@vitejs/plugin-react": "^4.6.0", "@vitest/ui": "^3.2.4", "@vitejs/plugin-react": "^4.7.0", "eslint": "^9.31.0", diff --git a/package-lock.json b/package-lock.json index e362046ed..b7dd26ed6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -40,7 +40,6 @@ "@emotion/styled": "^11.14.0", "@fontsource/material-icons": "^5.2.5", "@fontsource/roboto": "^5.2.6", - "@iconify/react": "^5.2.0", "@microlink/react-json-view": "^1.26.2", "@monaco-editor/react": "^4.7.0", "@mui/icons-material": "^7.1.1", @@ -94,13 +93,13 @@ "@types/react-dom": "^18.3.5", "@types/react-helmet": "^6.1.11", "@types/react-syntax-highlighter": "^15.5.13", - "@vitejs/plugin-react": "^4.6.0", + "@vitejs/plugin-react": "^4.7.0", "@vitest/ui": "^3.2.4", "eslint": "^9.31.0", "eslint-plugin-react": "^7.37.5", "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-refresh": "^0.4.20", - "eslint-plugin-storybook": "^9.0.15", + "eslint-plugin-storybook": "^9.1.2", "jsdom": "^26.1.0", "prettier": "^3.6.2", "typescript": "^5.8.3", @@ -8491,27 +8490,6 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@iconify/react": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/@iconify/react/-/react-5.2.1.tgz", - "integrity": "sha512-37GDR3fYDZmnmUn9RagyaX+zca24jfVOMY8E1IXTqJuE8pxNtN51KWPQe3VODOWvuUurq7q9uUu3CFrpqj5Iqg==", - "license": "MIT", - "dependencies": { - "@iconify/types": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/cyberalien" - }, - "peerDependencies": { - "react": ">=16" - } - }, - "node_modules/@iconify/types": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", - "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", - "license": "MIT" - }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -39639,7 +39617,6 @@ "@fontsource/inter": "^5.2.6", "@fontsource/material-icons": "^5.2.5", "@fontsource/roboto": "^5.2.6", - "@iconify/react": "^5.2.1", "@mui/icons-material": "^7.1.1", "@mui/lab": "^7.0.0-beta.13", "@mui/material": "^7.1.1", From 6f98983abc02820fd7c729207d209f47ad78b00e Mon Sep 17 00:00:00 2001 From: Prosvirin Vladimir Date: Tue, 19 Aug 2025 16:02:25 +0300 Subject: [PATCH 03/12] Update behaviour test --- .../src/tests/questionnaireRenderer.test.tsx | 51 +++++++++++++++++-- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/apps/smart-forms-app/src/tests/questionnaireRenderer.test.tsx b/apps/smart-forms-app/src/tests/questionnaireRenderer.test.tsx index f1d54fbc2..199f64bf2 100644 --- a/apps/smart-forms-app/src/tests/questionnaireRenderer.test.tsx +++ b/apps/smart-forms-app/src/tests/questionnaireRenderer.test.tsx @@ -1,7 +1,52 @@ +import { test, vi } from 'vitest'; import { render } from '@testing-library/react'; -import { test } from 'vitest'; -import { BaseRenderer } from '@aehrc/smart-forms-renderer'; +import type { Questionnaire, QuestionnaireResponse } from 'fhir/r4'; +import aboriginalForm from '../data/resources/Questionnaire/Questionnaire-AboriginalTorresStraitIslanderHealthCheckAssembled-0.1.0.json'; +import { QueryClientProvider } from '@tanstack/react-query'; + + +import { + BaseRenderer, + RendererThemeProvider, + useBuildForm, + useRendererQueryClient +} from '@aehrc/smart-forms-renderer'; + +vi.mock('fhirclient', () => ({ + client: () => ({ + request: vi.fn(() => Promise.resolve({})) + }) +})); test('Basic component renders correctly', async () => { - render(); + const form = aboriginalForm as Questionnaire; + + const { container } = render(); + await new Promise((resolve) => setTimeout(resolve, 1000)); + expect(container.innerHTML).toContain('Patient Details') + }); + +interface BuildFormWrapperForStorybookProps { + questionnaire: Questionnaire; + questionnaireResponse?: QuestionnaireResponse; +} + +function BuildFormWrapperForStorybook(props: BuildFormWrapperForStorybookProps) { + const { questionnaire, questionnaireResponse } = props; + + const queryClient = useRendererQueryClient(); + const isBuilding = useBuildForm(questionnaire, questionnaireResponse, undefined, 'https://r4.ontoserver.csiro.au/fhir'); + + if (isBuilding) { + return
Loading...
; + } + + return ( + + + + + + ); +} From 6a6ff603820bb87ac5c855960ec28e47f9176c71 Mon Sep 17 00:00:00 2001 From: Prosvirin Vladimir Date: Wed, 17 Sep 2025 20:43:22 +0300 Subject: [PATCH 04/12] Update behaviout test --- .../src/tests/questionnaireRenderer.test.tsx | 87 +++++++++++++++++-- 1 file changed, 81 insertions(+), 6 deletions(-) diff --git a/apps/smart-forms-app/src/tests/questionnaireRenderer.test.tsx b/apps/smart-forms-app/src/tests/questionnaireRenderer.test.tsx index 199f64bf2..ac0732eed 100644 --- a/apps/smart-forms-app/src/tests/questionnaireRenderer.test.tsx +++ b/apps/smart-forms-app/src/tests/questionnaireRenderer.test.tsx @@ -1,12 +1,13 @@ import { test, vi } from 'vitest'; import { render } from '@testing-library/react'; +import { evaluate } from 'fhirpath'; import type { Questionnaire, QuestionnaireResponse } from 'fhir/r4'; import aboriginalForm from '../data/resources/Questionnaire/Questionnaire-AboriginalTorresStraitIslanderHealthCheckAssembled-0.1.0.json'; import { QueryClientProvider } from '@tanstack/react-query'; - - +import { inputText, inputDate, inputInteger, checkRadioOption } from '@aehrc/testing-toolkit'; import { BaseRenderer, + questionnaireResponseStore, RendererThemeProvider, useBuildForm, useRendererQueryClient @@ -18,13 +19,82 @@ vi.mock('fhirclient', () => ({ }) })); +export async function getAnswerRecurcise(linkId: string) { + const qr = questionnaireResponseStore.getState().updatableResponse; + + const result = await evaluate( + qr, + `QuestionnaireResponse.repeat(item).where(linkId='${linkId}').answer` + ); + return result; +} + test('Basic component renders correctly', async () => { const form = aboriginalForm as Questionnaire; - const { container } = render(); await new Promise((resolve) => setTimeout(resolve, 1000)); - expect(container.innerHTML).toContain('Patient Details') + expect(container.innerHTML).toContain('Patient Details'); +}); + +test('Add name into name field', async () => { + const form = aboriginalForm as Questionnaire; + const { container } = render(); + const nameLinkId = '17596726-34cf-4133-9960-7081e1d63558'; + const nameText = 'David'; + + await inputText(container, nameLinkId, nameText); + + const result = await getAnswerRecurcise(nameLinkId); + expect(result).toHaveLength(1); + expect(result[0]).toEqual(expect.objectContaining({ valueString: nameText })); +}); + +test('Add date into date field', async () => { + const form = aboriginalForm as Questionnaire; + const { container } = render(); + const dateLinkId = '90ad8f16-16e4-4438-a7aa-b3189f510da2'; + const date = '11/11/2021'; + const dateText = '2021-11-11'; + + await inputDate(container, dateLinkId, date); + + const result = await getAnswerRecurcise(dateLinkId); + expect(result).toHaveLength(1); + expect(result[0]).toEqual(expect.objectContaining({ valueDate: dateText })); +}); + +test('Add age into age field', async () => { + const form = aboriginalForm as Questionnaire; + const { container } = render(); + const ageLinkId = 'e2a16e4d-2765-4b61-b286-82cfc6356b30'; + const ageText = 24; + + await inputInteger(container, ageLinkId, ageText); + + const result = await getAnswerRecurcise(ageLinkId); + expect(result).toHaveLength(1); + expect(result[0]).toEqual(expect.objectContaining({ valueInteger: ageText })); +}); + +test('Registered for NDIS openning NDIS number field', async () => { + const form = aboriginalForm as Questionnaire; + const { container } = render(); + const answerCoding = { + code: 'Y', + display: 'Yes', + system: 'http://terminology.hl7.org/CodeSystem/v2-0532' + }; + const radioLinkId = '924b4500-53ac-4c4e-831b-7ab5569ff981'; + const inputLinkId = '7379a0fd-d95b-4ecb-a781-9f43d1394f10'; + const inputTargetText = 'Some text'; + + await checkRadioOption(container, radioLinkId, answerCoding.display); + await inputText(container, inputLinkId, inputTargetText); + + const result = await getAnswerRecurcise(inputLinkId); + expect(result).toHaveLength(1); + expect(result[0]).toEqual(expect.objectContaining({ valueString: inputTargetText })); }); interface BuildFormWrapperForStorybookProps { @@ -36,7 +106,12 @@ function BuildFormWrapperForStorybook(props: BuildFormWrapperForStorybookProps) const { questionnaire, questionnaireResponse } = props; const queryClient = useRendererQueryClient(); - const isBuilding = useBuildForm(questionnaire, questionnaireResponse, undefined, 'https://r4.ontoserver.csiro.au/fhir'); + const isBuilding = useBuildForm( + questionnaire, + questionnaireResponse, + undefined, + 'https://r4.ontoserver.csiro.au/fhir' + ); if (isBuilding) { return
Loading...
; @@ -49,4 +124,4 @@ function BuildFormWrapperForStorybook(props: BuildFormWrapperForStorybookProps) ); -} +} From 296a5bef47020986d9da4fd86da679ab9b568ff8 Mon Sep 17 00:00:00 2001 From: Prosvirin Vladimir Date: Thu, 18 Sep 2025 15:34:21 +0300 Subject: [PATCH 05/12] Update folder for behaviour test --- .../src/{tests => test}/questionnaireRenderer.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename apps/smart-forms-app/src/{tests => test}/questionnaireRenderer.test.tsx (98%) diff --git a/apps/smart-forms-app/src/tests/questionnaireRenderer.test.tsx b/apps/smart-forms-app/src/test/questionnaireRenderer.test.tsx similarity index 98% rename from apps/smart-forms-app/src/tests/questionnaireRenderer.test.tsx rename to apps/smart-forms-app/src/test/questionnaireRenderer.test.tsx index ac0732eed..fc6fd31b8 100644 --- a/apps/smart-forms-app/src/tests/questionnaireRenderer.test.tsx +++ b/apps/smart-forms-app/src/test/questionnaireRenderer.test.tsx @@ -77,7 +77,7 @@ test('Add age into age field', async () => { expect(result[0]).toEqual(expect.objectContaining({ valueInteger: ageText })); }); -test('Registered for NDIS openning NDIS number field', async () => { +test('Registered for NDIS opening NDIS number field', async () => { const form = aboriginalForm as Questionnaire; const { container } = render(); const answerCoding = { From 76b59412f6f99694d800fac08414c94a2f089e77 Mon Sep 17 00:00:00 2001 From: Prosvirin Vladimir Date: Tue, 23 Sep 2025 18:44:47 +0300 Subject: [PATCH 06/12] Add ne attribute data-label --- .../AttachmentItem/AttachmentFieldWrapper.tsx | 1 + .../BooleanItem/BooleanItem.tsx | 1 + .../ChoiceItems/ChoiceAutocompleteItem.tsx | 1 + .../ChoiceCheckboxAnswerOptionItem.tsx | 1 + .../ChoiceCheckboxAnswerValueSetItem.tsx | 1 + .../ChoiceRadioAnswerOptionView.tsx | 1 + .../ChoiceRadioAnswerValueSetItem.tsx | 1 + .../ChoiceSelectAnswerOptionView.tsx | 1 + .../ChoiceSelectAnswerValueSetFields.tsx | 1 + .../CustomDateItem/CustomDateItem.tsx | 1 + .../CustomDateTimeItem/CustomDateTimeItem.tsx | 1 + .../DecimalItem/DecimalItem.tsx | 1 + .../DisplayItem/DisplayItem.tsx | 1 + .../FormComponents/GridGroup/GridGroup.tsx | 1 + .../IntegerItem/IntegerItem.tsx | 1 + .../OpenChoiceAutocompleteItem.tsx | 1 + .../OpenChoiceCheckboxAnswerOptionItem.tsx | 1 + .../OpenChoiceCheckboxAnswerValueSetItem.tsx | 1 + .../OpenChoiceRadioAnswerOptionItem.tsx | 1 + .../OpenChoiceRadioAnswerValueSetItem.tsx | 1 + .../OpenChoiceSelectAnswerOptionItem.tsx | 1 + .../OpenChoiceSelectAnswerValueSetItem.tsx | 1 + .../QuantityItem/QuantityItem.tsx | 1 + .../FormComponents/RepeatItem/RepeatItem.tsx | 1 + .../FormComponents/SliderItem/SliderItem.tsx | 1 + .../FormComponents/StringItem/StringItem.tsx | 1 + .../FormComponents/Tables/GroupTableView.tsx | 1 + .../FormComponents/TextItem/TextItem.tsx | 1 + .../FormComponents/TimeItem/TimeItem.tsx | 1 + .../FormComponents/UrlItem/UrlItem.tsx | 1 + packages/testing-toolkit/src/index.ts | 20 +++++++++++++++---- 31 files changed, 46 insertions(+), 4 deletions(-) diff --git a/packages/smart-forms-renderer/src/components/FormComponents/AttachmentItem/AttachmentFieldWrapper.tsx b/packages/smart-forms-renderer/src/components/FormComponents/AttachmentItem/AttachmentFieldWrapper.tsx index 4996025fa..e4004acb9 100644 --- a/packages/smart-forms-renderer/src/components/FormComponents/AttachmentItem/AttachmentFieldWrapper.tsx +++ b/packages/smart-forms-renderer/src/components/FormComponents/AttachmentItem/AttachmentFieldWrapper.tsx @@ -75,6 +75,7 @@ function AttachmentFieldWrapper(props: AttachmentFieldWrapperProps) { onFocusLinkId(qItem.linkId)}> onFocusLinkId(qItem.linkId)}> onFocusLinkId(qItem.linkId)}> onFocusLinkId(qItem.linkId)}> onFocusLinkId(qItem.linkId)}> onFocusLinkId(qItem.linkId)}> )} /> diff --git a/packages/smart-forms-renderer/src/components/FormComponents/DateTimeItems/CustomDateItem/CustomDateItem.tsx b/packages/smart-forms-renderer/src/components/FormComponents/DateTimeItems/CustomDateItem/CustomDateItem.tsx index 111859bdf..c249c3c15 100644 --- a/packages/smart-forms-renderer/src/components/FormComponents/DateTimeItems/CustomDateItem/CustomDateItem.tsx +++ b/packages/smart-forms-renderer/src/components/FormComponents/DateTimeItems/CustomDateItem/CustomDateItem.tsx @@ -152,6 +152,7 @@ function CustomDateItem(props: BaseItemProps) { onFocusLinkId(qItem.linkId)}> onFocusLinkId(qItem.linkId)}> onFocusLinkId(qItem.linkId)}> onFocusLinkId(qItem.linkId)}> onFocusLinkId(qItem.linkId)} style={parentStyles || undefined}> {itemTextToDisplay ? ( diff --git a/packages/smart-forms-renderer/src/components/FormComponents/IntegerItem/IntegerItem.tsx b/packages/smart-forms-renderer/src/components/FormComponents/IntegerItem/IntegerItem.tsx index 8af37052f..cb5d33396 100644 --- a/packages/smart-forms-renderer/src/components/FormComponents/IntegerItem/IntegerItem.tsx +++ b/packages/smart-forms-renderer/src/components/FormComponents/IntegerItem/IntegerItem.tsx @@ -157,6 +157,7 @@ function IntegerItem(props: BaseItemProps) { onFocusLinkId(qItem.linkId)}> onFocusLinkId(qItem.linkId)}> onFocusLinkId(qItem.linkId)}> onFocusLinkId(qItem.linkId)}> onFocusLinkId(qItem.linkId)}> onFocusLinkId(qItem.linkId)}> onFocusLinkId(qItem.linkId)}> onFocusLinkId(qItem.linkId)}> onFocusLinkId(qItem.linkId)}> onFocusLinkId(qItem.linkId)}> onFocusLinkId(qItem.linkId)}> onFocusLinkId(qItem.linkId)}> onFocusLinkId(qItem.linkId)} style={parentStyles || undefined}> {itemTextToDisplay ? ( diff --git a/packages/smart-forms-renderer/src/components/FormComponents/TextItem/TextItem.tsx b/packages/smart-forms-renderer/src/components/FormComponents/TextItem/TextItem.tsx index 42bf9d044..2f91d178f 100644 --- a/packages/smart-forms-renderer/src/components/FormComponents/TextItem/TextItem.tsx +++ b/packages/smart-forms-renderer/src/components/FormComponents/TextItem/TextItem.tsx @@ -150,6 +150,7 @@ function TextItem(props: BaseItemProps) { onFocusLinkId(qItem.linkId)}> onFocusLinkId(qItem.linkId)}> onFocusLinkId(qItem.linkId)}> setTimeout(resolve, 500)); } -export async function findByLinkId(canvasElement: HTMLElement, linkId: string) { - const selector = `[data-linkid="${linkId}"]`; +export async function findByLinkId( + canvasElement: HTMLElement, + linkId: string +): Promise { + const selectorByLinkId = `[data-linkid="${linkId}"]`; + const selectorByLabel = `[data-label="${linkId}"]`; + return await waitFor(() => { - const el = canvasElement.querySelector(selector); + const el = + canvasElement.querySelector(selectorByLinkId) ?? + canvasElement.querySelector(selectorByLabel); + if (!el) { - throw new Error(`Element ${selector} not found`); + throw new Error( + `Element with selectors "${selectorByLinkId}" or "${selectorByLabel}" not found` + ); } + return el; }); } + export async function inputOpenChoiceOtherText( canvasElement: HTMLElement, linkId: string, From 346d829d09da3fc5217dccd8a3116ad14827bc90 Mon Sep 17 00:00:00 2001 From: Prosvirin Vladimir Date: Tue, 23 Sep 2025 18:54:10 +0300 Subject: [PATCH 07/12] Update findByLinkId --- .../src/stories/itemTypes/Boolean.stories.tsx | 8 ++++---- .../src/stories/itemTypes/Choice.stories.tsx | 4 ++-- .../src/stories/itemTypes/Decimal.stories.tsx | 4 ++-- .../src/stories/itemTypes/Integer.stories.tsx | 4 ++-- .../stories/itemTypes/OpenChoice.stories.tsx | 10 +++++----- .../stories/itemTypes/Reference.stories.tsx | 4 ++-- .../src/stories/itemTypes/String.stories.tsx | 4 ++-- .../src/stories/itemTypes/Text.stories.tsx | 4 ++-- .../src/stories/itemTypes/Url.stories.tsx | 4 ++-- packages/testing-toolkit/src/index.ts | 20 +++++++++---------- 10 files changed, 33 insertions(+), 33 deletions(-) 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 43aefa9b8..4ed386759 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/Boolean.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/Boolean.stories.tsx @@ -23,7 +23,7 @@ import { getInputText, checkCheckBox, checkRadioOption, - findByLinkId + findByLinkIdAndLabel } from '@aehrc/testing-toolkit'; import { expect, fireEvent } from 'storybook/test'; @@ -83,7 +83,7 @@ export const BooleanBasic: Story = { const resultAfterClear = await getAnswers(targetlinkId); expect(resultAfterClear).toHaveLength(0); - const elementAfterClear = await findByLinkId(canvasElement, targetlinkId); + const elementAfterClear = await findByLinkIdAndLabel(canvasElement, targetlinkId); const input = elementAfterClear.querySelector('input'); expect(input).not.toBeChecked(); } @@ -142,7 +142,7 @@ export const BooleanCheckboxBasic: Story = { const resultAfterClear = await getAnswers(targetlinkId); expect(resultAfterClear).toHaveLength(0); - const elementAfterClear = await findByLinkId(canvasElement, targetlinkId); + const elementAfterClear = await findByLinkIdAndLabel(canvasElement, targetlinkId); const input = elementAfterClear.querySelector('input'); expect(input).not.toBeChecked(); } @@ -154,7 +154,7 @@ export const BooleanCheckboxResponse: Story = { questionnaireResponse: qrBooleanCheckboxResponse }, play: async ({ canvasElement }) => { - const element = await findByLinkId(canvasElement, targetlinkId); + const element = await findByLinkIdAndLabel(canvasElement, targetlinkId); const input = element.querySelector('input'); expect(input).toBeChecked(); 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 eb6d36e4f..2c33407a6 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/Choice.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/Choice.stories.tsx @@ -21,7 +21,7 @@ import { qChoiceAnswerOptionCalculation, qChoiceAnswerValueSetCalculation } from '../assets/questionnaires'; -import { chooseSelectOption, findByLinkId, getInputText } from '@aehrc/testing-toolkit'; +import { chooseSelectOption, findByLinkIdAndLabel, getInputText } from '@aehrc/testing-toolkit'; import { getAnswers, qrFactory, questionnaireFactory } from '../testUtils'; import { expect, fireEvent } from 'storybook/test'; @@ -94,7 +94,7 @@ export const ChoiceAnswerOptionBasic: Story = { const resultAfterClear = await getAnswers(targetlinkId); expect(resultAfterClear).toHaveLength(0); - const elementAfterClear = await findByLinkId(canvasElement, targetlinkId); + const elementAfterClear = await findByLinkIdAndLabel(canvasElement, targetlinkId); const input = elementAfterClear.querySelector('textarea'); expect(input?.value).toBe(''); } 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 39b9dbbd0..13fe5935e 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/Decimal.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/Decimal.stories.tsx @@ -19,7 +19,7 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; import BuildFormWrapperForStorybook from '../storybookWrappers/BuildFormWrapperForStorybook'; import { qCalculatedExpressionBMICalculator } from '../assets/questionnaires'; import { getAnswers, qrFactory, questionnaireFactory } from '../testUtils'; -import { findByLinkId, getInputText, inputDecimal } from '@aehrc/testing-toolkit'; +import { findByLinkIdAndLabel, getInputText, inputDecimal } from '@aehrc/testing-toolkit'; import { expect, fireEvent } from 'storybook/test'; // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export @@ -78,7 +78,7 @@ export const DecimalBasic: Story = { const resultAfterClear = await getAnswers(targetlinkId); expect(resultAfterClear).toHaveLength(0); - const elementAfterClear = await findByLinkId(canvasElement, targetlinkId); + const elementAfterClear = await findByLinkIdAndLabel(canvasElement, targetlinkId); const input = elementAfterClear.querySelector('input'); expect(input?.getAttribute('value')).toBe(''); } 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 f7b61714f..e45d29787 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/Integer.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/Integer.stories.tsx @@ -18,7 +18,7 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; import BuildFormWrapperForStorybook from '../storybookWrappers/BuildFormWrapperForStorybook'; import { qIntegerCalculation } from '../assets/questionnaires'; -import { findByLinkId, getInputText, inputInteger } from '@aehrc/testing-toolkit'; +import { findByLinkIdAndLabel, getInputText, inputInteger } from '@aehrc/testing-toolkit'; import { expect, fireEvent } from 'storybook/test'; import { getAnswers, qrFactory, questionnaireFactory } from '../testUtils'; @@ -77,7 +77,7 @@ export const IntegerBasic: Story = { await new Promise((resolve) => setTimeout(resolve, 500)); const resultAfterClear = await getAnswers(targetlinkId); expect(resultAfterClear).toHaveLength(0); - const elementAfterClear = await findByLinkId(canvasElement, targetlinkId); + const elementAfterClear = await findByLinkIdAndLabel(canvasElement, targetlinkId); const input = elementAfterClear.querySelector('input'); expect(input?.getAttribute('value')).toBe(''); } diff --git a/packages/smart-forms-renderer/src/stories/itemTypes/OpenChoice.stories.tsx b/packages/smart-forms-renderer/src/stories/itemTypes/OpenChoice.stories.tsx index d24425467..dc04b7891 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/OpenChoice.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/OpenChoice.stories.tsx @@ -29,7 +29,7 @@ import { checkRadioOption, inputOpenChoiceOtherText, chooseSelectOption, - findByLinkId + findByLinkIdAndLabel } from '@aehrc/testing-toolkit'; import { expect, fireEvent, screen } from 'storybook/test'; @@ -99,7 +99,7 @@ export const OpenChoiceAnswerOptionBasic: Story = { await new Promise((resolve) => setTimeout(resolve, 500)); const resultAfterClear = await getAnswers(targetlinkId); expect(resultAfterClear).toHaveLength(0); - const elementAfterClear = await findByLinkId(canvasElement, targetlinkId); + const elementAfterClear = await findByLinkIdAndLabel(canvasElement, targetlinkId); const input = elementAfterClear.querySelector('input'); expect(input).not.toBeChecked(); @@ -129,7 +129,7 @@ export const OpenChoiceAnswerOptionBasicOther: Story = { const qrAfterClear = await getAnswers(targetOtherLinkid); expect(qrAfterClear).toHaveLength(0); - const resultAfterClear = await findByLinkId(canvasElement, targetlinkId); + const resultAfterClear = await findByLinkIdAndLabel(canvasElement, targetlinkId); const input = resultAfterClear.querySelector('textarea'); expect(input?.value).toBe(''); } @@ -185,7 +185,7 @@ export const OpenChoiceAnswerValueSetBasic: Story = { const qrAfterClear = await getAnswers('state'); expect(qrAfterClear).toHaveLength(0); - const resultAfterClear = await findByLinkId(canvasElement, targetOperResId); + const resultAfterClear = await findByLinkIdAndLabel(canvasElement, targetOperResId); const input = resultAfterClear.querySelector('input'); expect(input).not.toBeChecked(); } @@ -208,7 +208,7 @@ export const OpenChoiceAnswerValueSetBasicResponse: Story = { questionnaireResponse: qrOpenChoiceAnswerValueSetBasicResponse }, play: async ({ canvasElement }) => { - const element = await findByLinkId(canvasElement, targetOperResId); + const element = await findByLinkIdAndLabel(canvasElement, targetOperResId); const input = element.querySelector( 'div[data-test="q-item-radio-open-label-box"] textarea' ) as HTMLTextAreaElement; diff --git a/packages/smart-forms-renderer/src/stories/itemTypes/Reference.stories.tsx b/packages/smart-forms-renderer/src/stories/itemTypes/Reference.stories.tsx index 46ccfc6e2..b0c862f25 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/Reference.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/Reference.stories.tsx @@ -19,7 +19,7 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; import BuildFormWrapperForStorybook from '../storybookWrappers/BuildFormWrapperForStorybook'; import { getAnswers, questionnaireFactory } from '../testUtils'; -import { findByLinkId, inputReference } from '@aehrc/testing-toolkit'; +import { findByLinkIdAndLabel, inputReference } from '@aehrc/testing-toolkit'; import { expect, fireEvent } from 'storybook/test'; // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export @@ -65,7 +65,7 @@ export const ReferenceBasic: Story = { await new Promise((resolve) => setTimeout(resolve, 500)); const resultAfterClear = await getAnswers(targetlinkId); expect(resultAfterClear).toHaveLength(0); - const elementAfterClear = await findByLinkId(canvasElement, targetlinkId); + const elementAfterClear = await findByLinkIdAndLabel(canvasElement, targetlinkId); const input = elementAfterClear.querySelector('textarea'); expect(input?.value).toBe(''); } 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 6e5921b36..92fdf9a0e 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/String.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/String.stories.tsx @@ -19,7 +19,7 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; import BuildFormWrapperForStorybook from '../storybookWrappers/BuildFormWrapperForStorybook'; import { qStringCalculation } from '../assets/questionnaires'; import { getAnswers, qrFactory, questionnaireFactory } from '../testUtils'; -import { findByLinkId, getInputText, inputText } from '@aehrc/testing-toolkit'; +import { findByLinkIdAndLabel, getInputText, inputText } from '@aehrc/testing-toolkit'; import { expect, fireEvent } from 'storybook/test'; // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export @@ -76,7 +76,7 @@ export const StringBasic: Story = { await new Promise((resolve) => setTimeout(resolve, 500)); const resultAfterClear = await getAnswers(targetlinkId); expect(resultAfterClear).toHaveLength(0); - const elementAfterClear = await findByLinkId(canvasElement, targetlinkId); + const elementAfterClear = await findByLinkIdAndLabel(canvasElement, targetlinkId); const input = elementAfterClear.querySelector('textarea'); expect(input?.value).toBe(''); } 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 19cd9fe00..edc5c036b 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/Text.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/Text.stories.tsx @@ -18,7 +18,7 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; import BuildFormWrapperForStorybook from '../storybookWrappers/BuildFormWrapperForStorybook'; import { qTextCalculation } from '../assets/questionnaires'; -import { inputText, getInputText, findByLinkId } from '@aehrc/testing-toolkit'; +import { inputText, getInputText, findByLinkIdAndLabel } from '@aehrc/testing-toolkit'; import { expect, fireEvent } from 'storybook/test'; import { getAnswers, qrFactory, questionnaireFactory } from '../testUtils'; @@ -62,7 +62,7 @@ export const TextBasic: Story = { await new Promise((resolve) => setTimeout(resolve, 500)); const resultAfterClear = await getAnswers(targetlinkId); expect(resultAfterClear).toHaveLength(0); - const elementAfterClear = await findByLinkId(canvasElement, targetlinkId); + const elementAfterClear = await findByLinkIdAndLabel(canvasElement, targetlinkId); const input = elementAfterClear.querySelector('textarea'); expect(input?.value).toBe(''); } diff --git a/packages/smart-forms-renderer/src/stories/itemTypes/Url.stories.tsx b/packages/smart-forms-renderer/src/stories/itemTypes/Url.stories.tsx index 12f61cec2..e42e77df7 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/Url.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/Url.stories.tsx @@ -19,7 +19,7 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; import BuildFormWrapperForStorybook from '../storybookWrappers/BuildFormWrapperForStorybook'; import { getAnswers, questionnaireFactory } from '../testUtils'; -import { findByLinkId, inputUrl } from '@aehrc/testing-toolkit'; +import { findByLinkIdAndLabel, inputUrl } from '@aehrc/testing-toolkit'; import { expect, fireEvent } from 'storybook/test'; // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export @@ -65,7 +65,7 @@ export const UrlBasic: Story = { await new Promise((resolve) => setTimeout(resolve, 500)); const resultAfterClear = await getAnswers(targetlinkId); expect(resultAfterClear).toHaveLength(0); - const elementAfterClear = await findByLinkId(canvasElement, targetlinkId); + const elementAfterClear = await findByLinkIdAndLabel(canvasElement, targetlinkId); const input = elementAfterClear.querySelector('textarea'); expect(input?.value).toBe(''); } diff --git a/packages/testing-toolkit/src/index.ts b/packages/testing-toolkit/src/index.ts index a9c742690..bfa62d6ac 100644 --- a/packages/testing-toolkit/src/index.ts +++ b/packages/testing-toolkit/src/index.ts @@ -6,7 +6,7 @@ export async function inputText( linkId: string, text: string | boolean | number ) { - const questionElement = await findByLinkId(canvasElement, linkId); + const questionElement = await findByLinkIdAndLabel(canvasElement, linkId); const input = questionElement?.querySelector('input') ?? questionElement?.querySelector('textarea'); @@ -21,7 +21,7 @@ export async function inputText( await new Promise((resolve) => setTimeout(resolve, 500)); } export async function checkCheckBox(canvasElement: HTMLElement, linkId: string) { - const questionElement = await findByLinkId(canvasElement, linkId); + const questionElement = await findByLinkIdAndLabel(canvasElement, linkId); const input = questionElement?.querySelector('input') ?? questionElement?.querySelector('textarea'); @@ -42,7 +42,7 @@ export async function inputFile( url: string, filename: string ) { - const questionElement = await findByLinkId(canvasElement, linkId); + const questionElement = await findByLinkIdAndLabel(canvasElement, linkId); const input = questionElement?.querySelector('input'); const textareaUrl = questionElement?.querySelector(`textarea[data-test="q-item-attachment-url"]`); @@ -112,7 +112,7 @@ export async function inputDateTime( time: string, amPm: string ) { - const questionElement = await findByLinkId(canvasElement, linkId); + const questionElement = await findByLinkIdAndLabel(canvasElement, linkId); console.log(questionElement, 777); const inputDate = questionElement?.querySelector('div[data-test="date"] input'); const inputTime = questionElement?.querySelector('div[data-test="time"] input'); @@ -137,7 +137,7 @@ export async function inputDateTime( } export async function checkRadioOption(canvasElement: HTMLElement, linkId: string, text: string) { - const questionElement = await findByLinkId(canvasElement, linkId); + const questionElement = await findByLinkIdAndLabel(canvasElement, linkId); const radio = questionElement?.querySelector(`span[data-test="radio-single-${text}"] input`); if (!radio) { @@ -150,7 +150,7 @@ export async function checkRadioOption(canvasElement: HTMLElement, linkId: strin } export async function getInputText(canvasElement: HTMLElement, linkId: string) { - const questionElement = await findByLinkId(canvasElement, linkId); + const questionElement = await findByLinkIdAndLabel(canvasElement, linkId); const input = questionElement?.querySelector('input') ?? questionElement?.querySelector('textarea'); @@ -166,7 +166,7 @@ export async function chooseSelectOption( linkId: string, optionLabel: string ) { - const questionElement = await findByLinkId(canvasElement, linkId); + const questionElement = await findByLinkIdAndLabel(canvasElement, linkId); const input = questionElement.querySelector('input, textarea'); if (!input) { @@ -185,7 +185,7 @@ export async function chooseQuantityOption( quantity: number | string, quantityComparator?: string ) { - const questionElement = await findByLinkId(canvasElement, linkId); + const questionElement = await findByLinkIdAndLabel(canvasElement, linkId); const inputComaparator = questionElement.querySelector( 'div[data-test=""q-item-quantity-comparator""] input' @@ -213,7 +213,7 @@ export async function chooseQuantityOption( await new Promise((resolve) => setTimeout(resolve, 500)); } -export async function findByLinkId( +export async function findByLinkIdAndLabel( canvasElement: HTMLElement, linkId: string ): Promise { @@ -240,7 +240,7 @@ export async function inputOpenChoiceOtherText( linkId: string, text: string ) { - const questionElement = await findByLinkId(canvasElement, linkId); + const questionElement = await findByLinkIdAndLabel(canvasElement, linkId); const textarea = questionElement?.querySelector( 'div[data-test="q-item-radio-open-label-box"] textarea' From 8b12bc77c336de2ec1c26b73e665d7eee2c86f6c Mon Sep 17 00:00:00 2001 From: Prosvirin Vladimir Date: Thu, 25 Sep 2025 23:20:05 +0300 Subject: [PATCH 08/12] Update imports in item types --- .../src/stories/itemTypes/Boolean.stories.tsx | 8 ++++---- .../src/stories/itemTypes/Choice.stories.tsx | 4 ++-- .../src/stories/itemTypes/Decimal.stories.tsx | 4 ++-- .../src/stories/itemTypes/Integer.stories.tsx | 4 ++-- .../stories/itemTypes/OpenChoice.stories.tsx | 10 +++++----- .../stories/itemTypes/Reference.stories.tsx | 9 +++++++-- .../src/stories/itemTypes/String.stories.tsx | 4 ++-- .../src/stories/itemTypes/Text.stories.tsx | 4 ++-- .../src/stories/itemTypes/Url.stories.tsx | 4 ++-- .../src/stories/testUtils.ts | 20 +++++++++---------- 10 files changed, 38 insertions(+), 33 deletions(-) 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..42d844e04 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/Boolean.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/Boolean.stories.tsx @@ -21,7 +21,7 @@ import BuildFormWrapperForStorybook from '../storybookWrappers/BuildFormWrapperF import { checkCheckBox, checkRadioOption, - findByLinkId, + findByLinkIdOrLabel, getAnswers, getInputText, itemControlExtFactory, @@ -86,7 +86,7 @@ export const BooleanBasic: Story = { const resultAfterClear = await getAnswers(targetLinkId); expect(resultAfterClear).toHaveLength(0); - const elementAfterClear = await findByLinkId(canvasElement, targetLinkId); + const elementAfterClear = await findByLinkIdOrLabel(canvasElement, targetLinkId); const input = elementAfterClear.querySelector('input'); expect(input).not.toBeChecked(); } @@ -145,7 +145,7 @@ export const BooleanCheckboxBasic: Story = { const resultAfterClear = await getAnswers(targetLinkId); expect(resultAfterClear).toHaveLength(0); - const elementAfterClear = await findByLinkId(canvasElement, targetLinkId); + const elementAfterClear = await findByLinkIdOrLabel(canvasElement, targetLinkId); const input = elementAfterClear.querySelector('input'); expect(input).not.toBeChecked(); } @@ -157,7 +157,7 @@ export const BooleanCheckboxResponse: Story = { questionnaireResponse: qrBooleanCheckboxResponse }, play: async ({ canvasElement }) => { - const element = await findByLinkId(canvasElement, targetLinkId); + const element = await findByLinkIdOrLabel(canvasElement, targetLinkId); const input = element.querySelector('input'); expect(input).toBeChecked(); 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..8f60a0f31 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/Choice.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/Choice.stories.tsx @@ -23,7 +23,7 @@ import { } from '../assets/questionnaires'; import { chooseSelectOption, - findByLinkId, + findByLinkIdOrLabel, getAnswers, getInputText, qrFactory, @@ -100,7 +100,7 @@ export const ChoiceAnswerOptionBasic: Story = { const resultAfterClear = await getAnswers(targetLinkId); expect(resultAfterClear).toHaveLength(0); - const elementAfterClear = await findByLinkId(canvasElement, targetLinkId); + const elementAfterClear = await findByLinkIdOrLabel(canvasElement, targetLinkId); const input = elementAfterClear.querySelector('textarea'); expect(input?.value).toBe(''); } 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..a8d2918fa 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/Decimal.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/Decimal.stories.tsx @@ -19,7 +19,7 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; import BuildFormWrapperForStorybook from '../storybookWrappers/BuildFormWrapperForStorybook'; import { qCalculatedExpressionBMICalculator } from '../assets/questionnaires'; import { - findByLinkId, + findByLinkIdOrLabel, getAnswers, getInputText, inputDecimal, @@ -84,7 +84,7 @@ export const DecimalBasic: Story = { const resultAfterClear = await getAnswers(targetLinkId); expect(resultAfterClear).toHaveLength(0); - const elementAfterClear = await findByLinkId(canvasElement, targetLinkId); + const elementAfterClear = await findByLinkIdOrLabel(canvasElement, targetLinkId); const input = elementAfterClear.querySelector('input'); expect(input?.getAttribute('value')).toBe(''); } 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..3a3920a1e 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/Integer.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/Integer.stories.tsx @@ -19,7 +19,7 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; import BuildFormWrapperForStorybook from '../storybookWrappers/BuildFormWrapperForStorybook'; import { qIntegerCalculation } from '../assets/questionnaires'; import { - findByLinkId, + findByLinkIdOrLabel, getAnswers, getInputText, inputInteger, @@ -83,7 +83,7 @@ export const IntegerBasic: Story = { await new Promise((resolve) => setTimeout(resolve, 500)); const resultAfterClear = await getAnswers(targetLinkId); expect(resultAfterClear).toHaveLength(0); - const elementAfterClear = await findByLinkId(canvasElement, targetLinkId); + const elementAfterClear = await findByLinkIdOrLabel(canvasElement, targetLinkId); const input = elementAfterClear.querySelector('input'); expect(input?.getAttribute('value')).toBe(''); } diff --git a/packages/smart-forms-renderer/src/stories/itemTypes/OpenChoice.stories.tsx b/packages/smart-forms-renderer/src/stories/itemTypes/OpenChoice.stories.tsx index 3f71c1d7d..adc849f3e 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/OpenChoice.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/OpenChoice.stories.tsx @@ -21,7 +21,7 @@ import { qOpenChoiceAnswerAutoCompleteFromValueSet } from '../assets/questionnai import { checkRadioOption, chooseSelectOption, - findByLinkId, + findByLinkIdOrLabel, getAnswers, inputOpenChoiceOtherText, itemControlExtFactory, @@ -97,7 +97,7 @@ export const OpenChoiceAnswerOptionBasic: Story = { await new Promise((resolve) => setTimeout(resolve, 500)); const resultAfterClear = await getAnswers(targetLinkId); expect(resultAfterClear).toHaveLength(0); - const elementAfterClear = await findByLinkId(canvasElement, targetLinkId); + const elementAfterClear = await findByLinkIdOrLabel(canvasElement, targetLinkId); const input = elementAfterClear.querySelector('input'); expect(input).not.toBeChecked(); @@ -127,7 +127,7 @@ export const OpenChoiceAnswerOptionBasicOther: Story = { const qrAfterClear = await getAnswers(targetOtherLinkid); expect(qrAfterClear).toHaveLength(0); - const resultAfterClear = await findByLinkId(canvasElement, targetLinkId); + const resultAfterClear = await findByLinkIdOrLabel(canvasElement, targetLinkId); const input = resultAfterClear.querySelector('textarea'); expect(input?.value).toBe(''); } @@ -183,7 +183,7 @@ export const OpenChoiceAnswerValueSetBasic: Story = { const qrAfterClear = await getAnswers('state'); expect(qrAfterClear).toHaveLength(0); - const resultAfterClear = await findByLinkIdAndLabel(canvasElement, targetOperResId); + const resultAfterClear = await findByLinkIdOrLabel(canvasElement, targetOperResId); const input = resultAfterClear.querySelector('input'); expect(input).not.toBeChecked(); } @@ -206,7 +206,7 @@ export const OpenChoiceAnswerValueSetBasicResponse: Story = { questionnaireResponse: qrOpenChoiceAnswerValueSetBasicResponse }, play: async ({ canvasElement }) => { - const element = await findByLinkIdAndLabel(canvasElement, targetOperResId); + const element = await findByLinkIdOrLabel(canvasElement, targetOperResId); const input = element.querySelector( 'div[data-test="q-item-radio-open-label-box"] textarea' ) as HTMLTextAreaElement; diff --git a/packages/smart-forms-renderer/src/stories/itemTypes/Reference.stories.tsx b/packages/smart-forms-renderer/src/stories/itemTypes/Reference.stories.tsx index 5070d16e7..e77827da5 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/Reference.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/Reference.stories.tsx @@ -18,7 +18,12 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; import BuildFormWrapperForStorybook from '../storybookWrappers/BuildFormWrapperForStorybook'; -import { findByLinkId, getAnswers, inputReference, questionnaireFactory } from '../testUtils'; +import { + findByLinkIdOrLabel, + getAnswers, + inputReference, + questionnaireFactory +} from '../testUtils'; import { expect, fireEvent } from 'storybook/test'; // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export @@ -64,7 +69,7 @@ export const ReferenceBasic: Story = { await new Promise((resolve) => setTimeout(resolve, 500)); const resultAfterClear = await getAnswers(targetLinkId); expect(resultAfterClear).toHaveLength(0); - const elementAfterClear = await findByLinkId(canvasElement, targetLinkId); + const elementAfterClear = await findByLinkIdOrLabel(canvasElement, targetLinkId); const input = elementAfterClear.querySelector('textarea'); expect(input?.value).toBe(''); } 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..cb493a542 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/String.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/String.stories.tsx @@ -19,7 +19,7 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; import BuildFormWrapperForStorybook from '../storybookWrappers/BuildFormWrapperForStorybook'; import { qStringCalculation } from '../assets/questionnaires'; import { - findByLinkId, + findByLinkIdOrLabel, getAnswers, getInputText, inputText, @@ -82,7 +82,7 @@ export const StringBasic: Story = { await new Promise((resolve) => setTimeout(resolve, 500)); const resultAfterClear = await getAnswers(targetLinkId); expect(resultAfterClear).toHaveLength(0); - const elementAfterClear = await findByLinkId(canvasElement, targetLinkId); + const elementAfterClear = await findByLinkIdOrLabel(canvasElement, targetLinkId); const input = elementAfterClear.querySelector('textarea'); expect(input?.value).toBe(''); } 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..9ff57e5cd 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/Text.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/Text.stories.tsx @@ -19,7 +19,7 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; import BuildFormWrapperForStorybook from '../storybookWrappers/BuildFormWrapperForStorybook'; import { qTextCalculation } from '../assets/questionnaires'; import { - findByLinkId, + findByLinkIdOrLabel, getAnswers, getInputText, inputText, @@ -68,7 +68,7 @@ export const TextBasic: Story = { await new Promise((resolve) => setTimeout(resolve, 500)); const resultAfterClear = await getAnswers(targetLinkId); expect(resultAfterClear).toHaveLength(0); - const elementAfterClear = await findByLinkId(canvasElement, targetLinkId); + const elementAfterClear = await findByLinkIdOrLabel(canvasElement, targetLinkId); const input = elementAfterClear.querySelector('textarea'); expect(input?.value).toBe(''); } diff --git a/packages/smart-forms-renderer/src/stories/itemTypes/Url.stories.tsx b/packages/smart-forms-renderer/src/stories/itemTypes/Url.stories.tsx index e10cc1c12..4c614c1f4 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/Url.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/Url.stories.tsx @@ -18,7 +18,7 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; import BuildFormWrapperForStorybook from '../storybookWrappers/BuildFormWrapperForStorybook'; -import { findByLinkId, getAnswers, inputUrl, questionnaireFactory } from '../testUtils'; +import { findByLinkIdOrLabel, getAnswers, inputUrl, questionnaireFactory } from '../testUtils'; import { expect, fireEvent } from 'storybook/test'; // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export @@ -64,7 +64,7 @@ export const UrlBasic: Story = { await new Promise((resolve) => setTimeout(resolve, 500)); const resultAfterClear = await getAnswers(targetLinkId); expect(resultAfterClear).toHaveLength(0); - const elementAfterClear = await findByLinkId(canvasElement, targetLinkId); + const elementAfterClear = await findByLinkIdOrLabel(canvasElement, targetLinkId); const input = elementAfterClear.querySelector('textarea'); expect(input?.value).toBe(''); } diff --git a/packages/smart-forms-renderer/src/stories/testUtils.ts b/packages/smart-forms-renderer/src/stories/testUtils.ts index d5fa0b0dd..e21f39ba0 100644 --- a/packages/smart-forms-renderer/src/stories/testUtils.ts +++ b/packages/smart-forms-renderer/src/stories/testUtils.ts @@ -68,7 +68,7 @@ export async function inputText( linkId: string, text: string | boolean | number ) { - const questionElement = await findByLinkId(canvasElement, linkId); + const questionElement = await findByLinkIdOrLabel(canvasElement, linkId); const input = questionElement?.querySelector('input') ?? questionElement?.querySelector('textarea'); @@ -83,7 +83,7 @@ export async function inputText( await new Promise((resolve) => setTimeout(resolve, 500)); } export async function checkCheckBox(canvasElement: HTMLElement, linkId: string) { - const questionElement = await findByLinkId(canvasElement, linkId); + const questionElement = await findByLinkIdOrLabel(canvasElement, linkId); const input = questionElement?.querySelector('input') ?? questionElement?.querySelector('textarea'); @@ -104,7 +104,7 @@ export async function inputFile( url: string, filename: string ) { - const questionElement = await findByLinkId(canvasElement, linkId); + const questionElement = await findByLinkIdOrLabel(canvasElement, linkId); const input = questionElement?.querySelector('input'); const textareaUrl = questionElement?.querySelector(`textarea[data-test="q-item-attachment-url"]`); @@ -174,7 +174,7 @@ export async function inputDateTime( time: string, amPm: string ) { - const questionElement = await findByLinkId(canvasElement, linkId); + const questionElement = await findByLinkIdOrLabel(canvasElement, linkId); console.log(questionElement, 777); const inputDate = questionElement?.querySelector('div[data-test="date"] input'); const inputTime = questionElement?.querySelector('div[data-test="time"] input'); @@ -199,7 +199,7 @@ export async function inputDateTime( } export async function checkRadioOption(canvasElement: HTMLElement, linkId: string, text: string) { - const questionElement = await findByLinkId(canvasElement, linkId); + const questionElement = await findByLinkIdOrLabel(canvasElement, linkId); const radio = questionElement?.querySelector(`span[data-test="radio-single-${text}"] input`); if (!radio) { @@ -212,7 +212,7 @@ export async function checkRadioOption(canvasElement: HTMLElement, linkId: strin } export async function getInputText(canvasElement: HTMLElement, linkId: string) { - const questionElement = await findByLinkId(canvasElement, linkId); + const questionElement = await findByLinkIdOrLabel(canvasElement, linkId); const input = questionElement?.querySelector('input') ?? questionElement?.querySelector('textarea'); @@ -228,7 +228,7 @@ export async function chooseSelectOption( linkId: string, optionLabel: string ) { - const questionElement = await findByLinkId(canvasElement, linkId); + const questionElement = await findByLinkIdOrLabel(canvasElement, linkId); const input = questionElement.querySelector('input, textarea'); if (!input) { @@ -247,7 +247,7 @@ export async function chooseQuantityOption( quantity: number | string, quantityComparator?: string ) { - const questionElement = await findByLinkId(canvasElement, linkId); + const questionElement = await findByLinkIdOrLabel(canvasElement, linkId); const inputComaparator = questionElement.querySelector( 'div[data-test="q-item-quantity-comparator"] input' @@ -275,7 +275,7 @@ export async function chooseQuantityOption( await new Promise((resolve) => setTimeout(resolve, 500)); } -export async function findByLinkId(canvasElement: HTMLElement, linkId: string) { +export async function findByLinkIdOrLabel(canvasElement: HTMLElement, linkId: string) { const selector = `[data-linkid="${linkId}"]`; return await waitFor(() => { const el = canvasElement.querySelector(selector); @@ -290,7 +290,7 @@ export async function inputOpenChoiceOtherText( linkId: string, text: string ) { - const questionElement = await findByLinkId(canvasElement, linkId); + const questionElement = await findByLinkIdOrLabel(canvasElement, linkId); const textarea = questionElement?.querySelector( 'div[data-test="q-item-radio-open-label-box"] textarea' From 977f7f4349cf7106d32f77c33297d513dc1280f8 Mon Sep 17 00:00:00 2001 From: Prosvirin Vladimir Date: Fri, 26 Sep 2025 00:23:50 +0300 Subject: [PATCH 09/12] Update behaviour test and vitest.config --- .../src/test/questionnaireRenderer.test.tsx | 63 +++++-------------- apps/smart-forms-app/vitest.config.ts | 1 + 2 files changed, 17 insertions(+), 47 deletions(-) diff --git a/apps/smart-forms-app/src/test/questionnaireRenderer.test.tsx b/apps/smart-forms-app/src/test/questionnaireRenderer.test.tsx index fc6fd31b8..b473b482a 100644 --- a/apps/smart-forms-app/src/test/questionnaireRenderer.test.tsx +++ b/apps/smart-forms-app/src/test/questionnaireRenderer.test.tsx @@ -19,80 +19,50 @@ vi.mock('fhirclient', () => ({ }) })); -export async function getAnswerRecurcise(linkId: string) { +export async function getAnswerRecurciseByLabel(text: string) { const qr = questionnaireResponseStore.getState().updatableResponse; - + console.log(qr); const result = await evaluate( qr, - `QuestionnaireResponse.repeat(item).where(linkId='${linkId}').answer` + `QuestionnaireResponse.repeat(item).where((text = '${text}')).answer` ); return result; } -test('Basic component renders correctly', async () => { +test('Behavior test', async () => { const form = aboriginalForm as Questionnaire; + const { container } = render(); await new Promise((resolve) => setTimeout(resolve, 1000)); - expect(container.innerHTML).toContain('Patient Details'); -}); - -test('Add name into name field', async () => { - const form = aboriginalForm as Questionnaire; - const { container } = render(); - const nameLinkId = '17596726-34cf-4133-9960-7081e1d63558'; - const nameText = 'David'; - - await inputText(container, nameLinkId, nameText); - - const result = await getAnswerRecurcise(nameLinkId); + const nameTex = 'David'; + await inputText(container, 'Name', nameTex); + let result = await getAnswerRecurciseByLabel('Name'); expect(result).toHaveLength(1); - expect(result[0]).toEqual(expect.objectContaining({ valueString: nameText })); -}); + expect(result[0]).toEqual(expect.objectContaining({ valueString: nameTex })); -test('Add date into date field', async () => { - const form = aboriginalForm as Questionnaire; - const { container } = render(); - const dateLinkId = '90ad8f16-16e4-4438-a7aa-b3189f510da2'; const date = '11/11/2021'; const dateText = '2021-11-11'; - - await inputDate(container, dateLinkId, date); - - const result = await getAnswerRecurcise(dateLinkId); + await inputDate(container, 'Date of birth', date); + result = await getAnswerRecurciseByLabel('Date of birth'); expect(result).toHaveLength(1); expect(result[0]).toEqual(expect.objectContaining({ valueDate: dateText })); -}); -test('Add age into age field', async () => { - const form = aboriginalForm as Questionnaire; - const { container } = render(); - const ageLinkId = 'e2a16e4d-2765-4b61-b286-82cfc6356b30'; const ageText = 24; - - await inputInteger(container, ageLinkId, ageText); - - const result = await getAnswerRecurcise(ageLinkId); + await inputInteger(container, 'Age', ageText); + result = await getAnswerRecurciseByLabel('Age'); expect(result).toHaveLength(1); expect(result[0]).toEqual(expect.objectContaining({ valueInteger: ageText })); -}); -test('Registered for NDIS opening NDIS number field', async () => { - const form = aboriginalForm as Questionnaire; - const { container } = render(); const answerCoding = { code: 'Y', display: 'Yes', system: 'http://terminology.hl7.org/CodeSystem/v2-0532' }; - const radioLinkId = '924b4500-53ac-4c4e-831b-7ab5569ff981'; - const inputLinkId = '7379a0fd-d95b-4ecb-a781-9f43d1394f10'; const inputTargetText = 'Some text'; - - await checkRadioOption(container, radioLinkId, answerCoding.display); - await inputText(container, inputLinkId, inputTargetText); - - const result = await getAnswerRecurcise(inputLinkId); + await checkRadioOption(container, 'Registered for NDIS', answerCoding.display); + await inputText(container, 'NDIS Number', inputTargetText); + result = await getAnswerRecurciseByLabel('NDIS Number'); expect(result).toHaveLength(1); expect(result[0]).toEqual(expect.objectContaining({ valueString: inputTargetText })); }); @@ -104,7 +74,6 @@ interface BuildFormWrapperForStorybookProps { function BuildFormWrapperForStorybook(props: BuildFormWrapperForStorybookProps) { const { questionnaire, questionnaireResponse } = props; - const queryClient = useRendererQueryClient(); const isBuilding = useBuildForm( questionnaire, diff --git a/apps/smart-forms-app/vitest.config.ts b/apps/smart-forms-app/vitest.config.ts index 6722783a6..6ce6c75bb 100644 --- a/apps/smart-forms-app/vitest.config.ts +++ b/apps/smart-forms-app/vitest.config.ts @@ -3,6 +3,7 @@ import { defineConfig } from 'vitest/config'; export default defineConfig({ test: { globals: true, + testTimeout:40000, environment: 'jsdom', include: ['**/__tests__/**/*.{test,spec}.{js,ts,jsx,tsx}', '**/*.{test,spec}.{js,ts,jsx,tsx}'], exclude: ['**/e2e/**', '**/node_modules/**'], From 63c8f151a32452ac1c61651c02c09013755e1248 Mon Sep 17 00:00:00 2001 From: Prosvirin Vladimir Date: Tue, 30 Sep 2025 13:26:08 +0300 Subject: [PATCH 10/12] Update imports tests in app --- .github/workflows/build_test_lint.yml | 1 - .../src/test/questionnaireRenderer.test.tsx | 4 +++- package-lock.json | 8 +++++++- packages/smart-forms-renderer/src/index.ts | 2 ++ 4 files changed, 12 insertions(+), 3 deletions(-) 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/src/test/questionnaireRenderer.test.tsx b/apps/smart-forms-app/src/test/questionnaireRenderer.test.tsx index b473b482a..eb2111500 100644 --- a/apps/smart-forms-app/src/test/questionnaireRenderer.test.tsx +++ b/apps/smart-forms-app/src/test/questionnaireRenderer.test.tsx @@ -4,7 +4,8 @@ import { evaluate } from 'fhirpath'; import type { Questionnaire, QuestionnaireResponse } from 'fhir/r4'; import aboriginalForm from '../data/resources/Questionnaire/Questionnaire-AboriginalTorresStraitIslanderHealthCheckAssembled-0.1.0.json'; import { QueryClientProvider } from '@tanstack/react-query'; -import { inputText, inputDate, inputInteger, checkRadioOption } from '@aehrc/testing-toolkit'; +import { testUtils } from '@aehrc/smart-forms-renderer'; + import { BaseRenderer, questionnaireResponseStore, @@ -13,6 +14,7 @@ import { useRendererQueryClient } from '@aehrc/smart-forms-renderer'; +const { inputText, inputDate, inputInteger, checkRadioOption } = testUtils; vi.mock('fhirclient', () => ({ client: () => ({ request: vi.fn(() => Promise.resolve({})) diff --git a/package-lock.json b/package-lock.json index 5603632cf..dc1d38326 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13595,6 +13595,8 @@ "integrity": "sha512-hGISOaP18plkzbWEcP/QvtRW1xDXF2+96HbEX6byqQhAUbiS5oH6/9JwW+QsQCIYON2bI6QZBF+2PvOmrRZ9wA==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "@vitest/utils": "3.2.4", "fflate": "^0.8.2", @@ -13617,6 +13619,8 @@ "integrity": "sha512-FoqMu0NCGBLCcAkS1qA+XJIQTR6/JHfQXl+uGteNCQ76T91DMUjPa9xfmeqMY3z80nLSg9yQmNjK0Px6RWsH/A==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "@polka/url": "^1.0.0-next.24", "mrmime": "^2.0.0", @@ -19768,7 +19772,9 @@ "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/fhir-extension-helpers": { "version": "0.3.0", diff --git a/packages/smart-forms-renderer/src/index.ts b/packages/smart-forms-renderer/src/index.ts index fde989845..1438c485e 100644 --- a/packages/smart-forms-renderer/src/index.ts +++ b/packages/smart-forms-renderer/src/index.ts @@ -1,6 +1,8 @@ // Import self-host typography Inter font import '@fontsource/inter'; +import * as testUtils from './stories/testUtils'; +export { testUtils }; // interface exports export type { Tab, From 1e89ba329c4d5adb90f0708eefe091e6208b4b98 Mon Sep 17 00:00:00 2001 From: Prosvirin Vladimir Date: Tue, 30 Sep 2025 23:35:22 +0300 Subject: [PATCH 11/12] Add expect type dep, add vitest types in tsconfig and update behaviour test --- apps/smart-forms-app/package.json | 1 + .../src/test/questionnaireRenderer.test.tsx | 42 ++++--------------- apps/smart-forms-app/tsconfig.json | 1 + package-lock.json | 11 +++++ .../src/stories/testUtils.ts | 20 +++++++-- 5 files changed, 38 insertions(+), 37 deletions(-) diff --git a/apps/smart-forms-app/package.json b/apps/smart-forms-app/package.json index 10c453834..427811bf4 100644 --- a/apps/smart-forms-app/package.json +++ b/apps/smart-forms-app/package.json @@ -95,6 +95,7 @@ "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-refresh": "^0.4.20", "eslint-plugin-storybook": "^9.1.6", + "expect-type": "^1.2.2", "jest": "^29.7.0", "jsdom": "^26.1.0", "prettier": "^3.6.2", diff --git a/apps/smart-forms-app/src/test/questionnaireRenderer.test.tsx b/apps/smart-forms-app/src/test/questionnaireRenderer.test.tsx index eb2111500..2b1165b6d 100644 --- a/apps/smart-forms-app/src/test/questionnaireRenderer.test.tsx +++ b/apps/smart-forms-app/src/test/questionnaireRenderer.test.tsx @@ -1,10 +1,10 @@ -import { test, vi } from 'vitest'; import { render } from '@testing-library/react'; import { evaluate } from 'fhirpath'; import type { Questionnaire, QuestionnaireResponse } from 'fhir/r4'; import aboriginalForm from '../data/resources/Questionnaire/Questionnaire-AboriginalTorresStraitIslanderHealthCheckAssembled-0.1.0.json'; import { QueryClientProvider } from '@tanstack/react-query'; import { testUtils } from '@aehrc/smart-forms-renderer'; +import { vi } from 'vitest'; import { BaseRenderer, @@ -21,9 +21,9 @@ vi.mock('fhirclient', () => ({ }) })); -export async function getAnswerRecurciseByLabel(text: string) { +export async function getAnswerRecursiveByLabel(text: string) { const qr = questionnaireResponseStore.getState().updatableResponse; - console.log(qr); + console.log(1); const result = await evaluate( qr, `QuestionnaireResponse.repeat(item).where((text = '${text}')).answer` @@ -31,42 +31,18 @@ export async function getAnswerRecurciseByLabel(text: string) { return result; } -test('Behavior test', async () => { +test('behaviour-test-example', async () => { const form = aboriginalForm as Questionnaire; const { container } = render(); await new Promise((resolve) => setTimeout(resolve, 1000)); expect(container.innerHTML).toContain('Patient Details'); - const nameTex = 'David'; - await inputText(container, 'Name', nameTex); - let result = await getAnswerRecurciseByLabel('Name'); - expect(result).toHaveLength(1); - expect(result[0]).toEqual(expect.objectContaining({ valueString: nameTex })); - const date = '11/11/2021'; - const dateText = '2021-11-11'; - await inputDate(container, 'Date of birth', date); - result = await getAnswerRecurciseByLabel('Date of birth'); - expect(result).toHaveLength(1); - expect(result[0]).toEqual(expect.objectContaining({ valueDate: dateText })); - - const ageText = 24; - await inputInteger(container, 'Age', ageText); - result = await getAnswerRecurciseByLabel('Age'); - expect(result).toHaveLength(1); - expect(result[0]).toEqual(expect.objectContaining({ valueInteger: ageText })); - - const answerCoding = { - code: 'Y', - display: 'Yes', - system: 'http://terminology.hl7.org/CodeSystem/v2-0532' - }; - const inputTargetText = 'Some text'; - await checkRadioOption(container, 'Registered for NDIS', answerCoding.display); - await inputText(container, 'NDIS Number', inputTargetText); - result = await getAnswerRecurciseByLabel('NDIS Number'); - expect(result).toHaveLength(1); - expect(result[0]).toEqual(expect.objectContaining({ valueString: inputTargetText })); + await inputText(container, 'Name', 'David'); + await inputDate(container, 'Date of birth', '11/11/2021'); + await inputInteger(container, 'Age', 24); + await checkRadioOption(container, 'Registered for NDIS', 'Yes'); + await inputText(container, 'NDIS Number', 'Some text'); }); interface BuildFormWrapperForStorybookProps { diff --git a/apps/smart-forms-app/tsconfig.json b/apps/smart-forms-app/tsconfig.json index 44691a80b..4fbacca15 100644 --- a/apps/smart-forms-app/tsconfig.json +++ b/apps/smart-forms-app/tsconfig.json @@ -1,5 +1,6 @@ { "compilerOptions": { + "types": ["vitest", "node"], "target": "ESNext", "module": "ESNext", "lib": ["DOM", "DOM.Iterable", "ESNext"], diff --git a/package-lock.json b/package-lock.json index dc1d38326..6662a6402 100644 --- a/package-lock.json +++ b/package-lock.json @@ -101,6 +101,7 @@ "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-refresh": "^0.4.20", "eslint-plugin-storybook": "^9.1.6", + "expect-type": "^1.2.2", "jest": "^29.7.0", "jsdom": "^26.1.0", "prettier": "^3.6.2", @@ -19389,6 +19390,16 @@ "dev": true, "license": "MIT" }, + "node_modules/expect-type": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.2.tgz", + "integrity": "sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/expo-modules-autolinking": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-0.0.3.tgz", diff --git a/packages/smart-forms-renderer/src/stories/testUtils.ts b/packages/smart-forms-renderer/src/stories/testUtils.ts index e21f39ba0..f457af238 100644 --- a/packages/smart-forms-renderer/src/stories/testUtils.ts +++ b/packages/smart-forms-renderer/src/stories/testUtils.ts @@ -275,16 +275,28 @@ export async function chooseQuantityOption( await new Promise((resolve) => setTimeout(resolve, 500)); } -export async function findByLinkIdOrLabel(canvasElement: HTMLElement, linkId: string) { - const selector = `[data-linkid="${linkId}"]`; +export async function findByLinkIdOrLabel( + canvasElement: HTMLElement, + linkId: string +): Promise { + const selectorByLinkId = `[data-linkid="${linkId}"]`; + const selectorByLabel = `[data-label="${linkId}"]`; + return await waitFor(() => { - const el = canvasElement.querySelector(selector); + const el = + canvasElement.querySelector(selectorByLinkId) ?? + canvasElement.querySelector(selectorByLabel); + if (!el) { - throw new Error(`Element ${selector} not found`); + throw new Error( + `Element with selectors "${selectorByLinkId}" or "${selectorByLabel}" not found` + ); } + return el; }); } + export async function inputOpenChoiceOtherText( canvasElement: HTMLElement, linkId: string, From ded24aa12ce16e207c34c162d936e28c223f7c62 Mon Sep 17 00:00:00 2001 From: Prosvirin Vladimir Date: Wed, 1 Oct 2025 10:58:29 +0300 Subject: [PATCH 12/12] Delete type vitest from tsconfig and add vitest to dep --- apps/smart-forms-app/package.json | 3 ++- apps/smart-forms-app/tsconfig.json | 1 - package-lock.json | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/smart-forms-app/package.json b/apps/smart-forms-app/package.json index 427811bf4..f18fba2f9 100644 --- a/apps/smart-forms-app/package.json +++ b/apps/smart-forms-app/package.json @@ -8,7 +8,7 @@ "dev": "vite", "start": "vite", "build": "tsc && CI=false vite build", - "test": "vitest run", + "test": "TZ=Australia/Sydney vitest run", "preview": "vite preview --port 4173", "playwright": "npx playwright test", "playwright-ui": "npx playwright test --ui" @@ -70,6 +70,7 @@ "react-syntax-highlighter": "^15.6.6", "react-to-print": "^3.1.1", "usehooks-ts": "^3.1.1", + "vitest": "^3.2.4", "zustand": "^5.0.8" }, "devDependencies": { diff --git a/apps/smart-forms-app/tsconfig.json b/apps/smart-forms-app/tsconfig.json index 4fbacca15..44691a80b 100644 --- a/apps/smart-forms-app/tsconfig.json +++ b/apps/smart-forms-app/tsconfig.json @@ -1,6 +1,5 @@ { "compilerOptions": { - "types": ["vitest", "node"], "target": "ESNext", "module": "ESNext", "lib": ["DOM", "DOM.Iterable", "ESNext"], diff --git a/package-lock.json b/package-lock.json index 6662a6402..fad4c3a22 100644 --- a/package-lock.json +++ b/package-lock.json @@ -76,6 +76,7 @@ "react-syntax-highlighter": "^15.6.6", "react-to-print": "^3.1.1", "usehooks-ts": "^3.1.1", + "vitest": "^3.2.4", "zustand": "^5.0.8" }, "devDependencies": {