Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .github/workflows/vitest_gpccmp.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Vitest GP CCMP Behaviour Tests

on: [workflow_dispatch, push, pull_request, workflow_call]

jobs:
vitest-gpccmp-tests:
name: Vitest Questionnaire Behaviour Tests - GP CCMP
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- name: Use Node.js 20.x
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- name: Install dependencies
run: npm ci

- name: Build workspace packages (monorepo dependencies)
run: |
npm run build -w packages/sdc-assemble
npm run build -w packages/sdc-populate
npm run build -w packages/sdc-template-extract
npm run build -w packages/smart-forms-renderer

- name: Typecheck
run: npm run typecheck -w forms/gpccmp

- name: Run vitest tests
run: npm run test -w forms/gpccmp
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@ changelog_guide.md
.DS_STORE

# GitHub copilot instructions
.github/copilot-instructions.md
.github/copilot-instructions.md

.scratch
3 changes: 3 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@ storybook-static
*.js
*.config.*
*.html

# Assembled questionnaire snapshots are artifacts, not source — see questionnaire/PROVENANCE.md
forms/*/questionnaire/*.json
4 changes: 3 additions & 1 deletion apps/smart-forms-app/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Dockerfile

# Step 1: Use a Node.js image to build the app
FROM --platform=$BUILDPLATFORM node:18 AS builder
FROM --platform=$BUILDPLATFORM node:20 AS builder

# Set working directory inside the container
WORKDIR /app
Expand All @@ -21,6 +21,7 @@ COPY packages/sdc-assemble/package*.json ./packages/sdc-assemble/
COPY packages/sdc-populate/package*.json ./packages/sdc-populate/
COPY packages/sdc-template-extract/package*.json ./packages/sdc-template-extract/
COPY packages/smart-forms-renderer/package*.json ./packages/smart-forms-renderer/
COPY packages/questionnaire-test-toolkit/package*.json ./packages/questionnaire-test-toolkit/
COPY apps/smart-forms-app/package*.json ./apps/smart-forms-app/

# Install all workspace dependencies from the root
Expand All @@ -31,6 +32,7 @@ COPY packages/sdc-assemble/ ./packages/sdc-assemble/
COPY packages/sdc-populate/ ./packages/sdc-populate/
COPY packages/sdc-template-extract/ ./packages/sdc-template-extract/
COPY packages/smart-forms-renderer/ ./packages/smart-forms-renderer/
COPY packages/questionnaire-test-toolkit/ ./packages/questionnaire-test-toolkit/
COPY apps/smart-forms-app/ ./apps/smart-forms-app/

# Build packages in dependency order (mirrors deploy_app.yml)
Expand Down
1 change: 1 addition & 0 deletions apps/smart-forms-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
"zustand": "^5.0.14"
},
"devDependencies": {
"@aehrc/questionnaire-test-toolkit": "^0.1.0",
"@jest/globals": "^30.3.0",
"@playwright/test": "^1.60.0",
"@sentry/cli": "^2.57.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
inputDecimal,
getVisibleTab,
checkRadioOption
} from './testUtils.ts';
} from '@aehrc/questionnaire-test-toolkit';
import { AboriginalForm } from './aboriginalFormUtils.tsx';

vi.mock('fhirclient', () => ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
inputDecimal,
getVisibleTab,
inputDateTime
} from './testUtils.ts';
} from '@aehrc/questionnaire-test-toolkit';
import { AboriginalForm } from './aboriginalFormUtils.tsx';

vi.mock('fhirclient', () => ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
inputDecimal,
getVisibleTab,
inputDateTime
} from './testUtils.ts';
} from '@aehrc/questionnaire-test-toolkit';
import { AboriginalForm } from './aboriginalFormUtils.tsx';

vi.mock('fhirclient', () => ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
inputDecimal,
getVisibleTab,
inputDateTime
} from './testUtils.ts';
} from '@aehrc/questionnaire-test-toolkit';
import { AboriginalForm } from './aboriginalFormUtils.tsx';

vi.mock('fhirclient', () => ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
inputDecimal,
getVisibleTab,
inputDateTime
} from './testUtils.ts';
} from '@aehrc/questionnaire-test-toolkit';
import { AboriginalForm } from './aboriginalFormUtils.tsx';

vi.mock('fhirclient', () => ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
inputDecimal,
getVisibleTab,
inputDateTime
} from './testUtils.ts';
} from '@aehrc/questionnaire-test-toolkit';
import { AboriginalForm } from './aboriginalFormUtils.tsx';

vi.mock('fhirclient', () => ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
inputDecimal,
getVisibleTab,
inputDateTime
} from './testUtils.ts';
} from '@aehrc/questionnaire-test-toolkit';
import { AboriginalForm } from './aboriginalFormUtils.tsx';

vi.mock('fhirclient', () => ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
findByLinkIdOrLabel,
checkCheckBox,
checkCheckboxOption
} from './testUtils.ts';
} from '@aehrc/questionnaire-test-toolkit';
import { AboriginalForm } from './aboriginalFormUtils.tsx';

vi.mock('fhirclient', () => ({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { vi, beforeAll } from 'vitest';
import { render, waitFor } from '@testing-library/react';
import { AboriginalForm, terminologyServerUrl } from './aboriginalFormUtils';
import { AboriginalForm } from './aboriginalFormUtils';
import { terminologyServerUrl } from '@aehrc/questionnaire-test-toolkit';
import {
nonSnomedCondition,
patient,
Expand Down Expand Up @@ -30,7 +31,7 @@ import {
selectTab,
chooseSelectOption,
checkRadioOption
} from './testUtils';
} from '@aehrc/questionnaire-test-toolkit';
import { FhirResource, MedicationStatement } from 'fhir/r4';

vi.mock('fhirclient', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import type {
Patient,
QuestionnaireResponse
} from 'fhir/r4';
import { getBirthDateForAge } from './testUtils';
import { getBirthDateForAge } from '@aehrc/questionnaire-test-toolkit';

export const patient: Patient = {
resourceType: 'Patient',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
findAllByLinkIdOrLabel,
getSelectText,
getRadioValue
} from './testUtils.ts';
} from '@aehrc/questionnaire-test-toolkit';
import {
aboutTheHealthCheckInProgressQuestionnaireResponse,
aboutTheHealthCheckQuestionnaireResponse,
Expand Down
155 changes: 4 additions & 151 deletions apps/smart-forms-app/src/test/aboriginalFormUtils.tsx
Original file line number Diff line number Diff line change
@@ -1,155 +1,8 @@
import {
BaseRenderer,
buildForm,
RendererThemeProvider,
useQuestionnaireResponseStore,
useQuestionnaireStore,
useRendererQueryClient
} from '@aehrc/smart-forms-renderer';

import type { BehavioralTestWrapperProps } from '@aehrc/questionnaire-test-toolkit';
import { BehavioralTestWrapper } from '@aehrc/questionnaire-test-toolkit';
import aboriginalForm from '../data/resources/Questionnaire/Questionnaire-AboriginalTorresStraitIslanderHealthCheckAssembled-0.4.0.json';
import type { Questionnaire } from 'fhir/r4';
import { QueryClientProvider } from '@tanstack/react-query';
import type { Patient } from 'fhir/r4';
import { populateQuestionnaire } from '@aehrc/sdc-populate';
import { useEffect, useState } from 'react';
import { inAppExtract, type InAppExtractOutput } from '@aehrc/sdc-template-extract';
import Button from '@mui/material/Button';

export const terminologyServerUrl = 'https://r4.ontoserver.csiro.au/fhir';

export type RequestDefinition = {
urlPrefix: string;
params?: Record<string, string>;
responseBody: any;
};

interface AboriginalFormProps {
patient?: Patient;
requestDefinitions?: RequestDefinition[];
onExtractResult?: (extractResult: InAppExtractOutput) => void;
}

export function AboriginalForm(props: AboriginalFormProps) {
return (
<BuildFormWrapperWithPopulate questionnaire={aboriginalForm as Questionnaire} {...props} />
);
}

interface BuildFormWrapperWithPopulateProps extends AboriginalFormProps {
questionnaire: Questionnaire;
}

function BuildFormWrapperWithPopulate(props: BuildFormWrapperWithPopulateProps) {
const { questionnaire, patient, requestDefinitions } = props;
const queryClient = useRendererQueryClient();

const [isPopulating, setIsPopulating] = useState(false);

useEffect(() => {
const load = async () => {
setIsPopulating(true);

if (patient && requestDefinitions) {
const result = await populateQuestionnaire({
questionnaire: questionnaire,
patient: patient,
fetchResourceCallback: buildFetchResourceCallback(requestDefinitions),
fetchResourceRequestConfig: { sourceServerUrl: 'http://mock.example' }
});

const { populateSuccess, populateResult } = result;
if (!populateSuccess || !populateResult) {
setIsPopulating(false);
return;
}

const { populatedResponse, populatedContext } = populateResult;

await buildForm({
questionnaire: questionnaire,
questionnaireResponse: populatedResponse,
terminologyServerUrl,
additionalContext: {
patient: patient,
...populatedContext
}
});
} else {
await buildForm({
questionnaire: questionnaire,
terminologyServerUrl
});
}

setIsPopulating(false);
};

load();
}, [questionnaire, patient, requestDefinitions]);

if (isPopulating) {
return <div>Loading...</div>;
}

return (
<RendererThemeProvider>
<QueryClientProvider client={queryClient}>
<BaseRenderer />
<SaveControl onExtractResult={props.onExtractResult} />
</QueryClientProvider>
</RendererThemeProvider>
);
}

function buildFetchResourceCallback(requestDefinitions: RequestDefinition[]) {
return async (url: string) => {
const requestUrl = url;
const [path, queryString] = requestUrl.split('?');

const searchParams = new URLSearchParams(queryString ?? '');
const paramsObject: Record<string, string> = {};
searchParams.forEach((value, key) => {
paramsObject[key] = value;
});

const match = requestDefinitions.find((def) => {
if (!path.startsWith(def.urlPrefix)) {
return false;
}

if (!def.params) {
return true;
}

return Object.entries(def.params).every(([key, value]) => paramsObject[key] === value);
});

if (match) {
return Promise.resolve(match.responseBody);
}

return Promise.resolve({});
};
}

function SaveControl({
onExtractResult
}: {
onExtractResult?: (extractResult: InAppExtractOutput) => void;
}) {
const qr = useQuestionnaireResponseStore.use.updatableResponse();
const q = useQuestionnaireStore.use.sourceQuestionnaire();

return (
<Button
data-testid="save-button"
onClick={async () => {
const result = await inAppExtract(qr, q, null);

onExtractResult?.(result);
}}>
Save
</Button>
);
export function AboriginalForm(props: Omit<BehavioralTestWrapperProps, 'questionnaire'>) {
return <BehavioralTestWrapper questionnaire={aboriginalForm as Questionnaire} {...props} />;
}
Loading
Loading