Skip to content

Commit

Permalink
🧪 test(patients): Cover creating a new patient from eid.
Browse files Browse the repository at this point in the history
  • Loading branch information
make-github-pseudonymous-again committed Jan 6, 2025
1 parent fa981ea commit 580b749
Show file tree
Hide file tree
Showing 5 changed files with 213 additions and 5 deletions.
2 changes: 2 additions & 0 deletions imports/_test/png.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import pngDataURL from '../lib/png/dataURL';
const base64Encoded =
'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=';

export const randomPNGBase64 = () => base64Encoded;

export const randomPNGBuffer = async () => {
const {Buffer} = await import('buffer');
return Buffer.from(base64Encoded, 'base64');
Expand Down
57 changes: 57 additions & 0 deletions imports/api/_dev/populate/eids.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {faker} from '@faker-js/faker';
import format from 'date-fns/format';

import {makeTemplate} from '../../../_test/fixtures';
import {randomPNGBase64} from '../../../_test/png';

const DATE_FORMAT = 'yyyyMMdd';
const AGE_MAX = 130;
Expand Down Expand Up @@ -51,3 +52,59 @@ export const newEidData = makeTemplate({
zip: () => faker.location.zipCode(),
},
});

export const exampleEidXML = (options?: {
name?: string;
firstname?: string;
middlenames?: string;
nationality?: string;
placeofbirth?: string;
}) => {
const {name, firstname, middlenames, nationality, placeofbirth} = {
name: 'Name',
firstname: 'First Name',
middlenames: 'M',
nationality: 'Belge',
placeofbirth: 'Bruxelles',
...options,
};
// TODO: Generalizes and escape values.
return `<?xml version="1.0" encoding="UTF-8"?>
<eid version="4.3" graphpersoversion="00">
<identity
nationalnumber="70010112345"
dateofbirth="19700101"
gender="male"
specialstatus="NO_STATUS"
>
<name>${name}</name>
<firstname>${firstname}</firstname>
<middlenames>${middlenames}</middlenames>
<nationality>${nationality}</nationality>
<placeofbirth>${placeofbirth}</placeofbirth>
<photo>${randomPNGBase64()}</photo>
</identity>
<card
documenttype="belgian_citizen"
carddata_appl_version="17"
cardnumber="012345678901"
chipnumber="0123456789ABCDEF0123456789ABCDEF"
validitydatebegin="20200101"
validitydateend="20300101"
>
<deliverymunicipality>Bruxelles</deliverymunicipality>
</card>
<address>
<streetandnumber>Rue de la montagne 58 </streetandnumber>
<zip>1000</zip>
<municipality>Bruxelles</municipality>
</address>
<certificates>
<root>ROOT</root>
<citizenca>CITIZENCA</citizenca>
<authentication>AUTHENTICATION</authentication>
<signing>SIGNING</signing>
<rrn>RRN</rrn>
</certificates>
</eid>`;
};
6 changes: 5 additions & 1 deletion imports/ui/patients/SelectablePatientCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import RadioButtonUncheckedOutlinedIcon from '@mui/icons-material/RadioButtonUnc

import type PropsOf from '../../lib/types/PropsOf';

import useUniqueId from '../hooks/useUniqueId';

import GenericStaticPatientCard from './GenericStaticPatientCard';

type Props = {
Expand Down Expand Up @@ -75,12 +77,14 @@ const SelectablePatientCard = ({
patient,
...rest
}: Props) => {
const labelId = useUniqueId('selectable-patient-card');
return (
<Root>
<Card patient={patient} {...rest} />
<Card id={labelId} role="none" patient={patient} {...rest} />
<SelectionStateIcon selected={selected} />
<ClickableArea
focusRipple
aria-labelledby={labelId}
selected={selected}
onClick={() => {
onClick(patient);
Expand Down
14 changes: 10 additions & 4 deletions test/app/client/fixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,21 +204,27 @@ export const createNewPatient = async (app: App, {firstname, lastname}) => {
};

export const searchResultsForQuery = async (
{userWithoutPointerEventsCheck, findByRole, getByRole}: App,
{userWithoutPointerEventsCheck, findByRole}: App,
query,
) => {
await userWithoutPointerEventsCheck.type(
getByRole('searchbox', {name: 'Patient search'}),
await findByRole('searchbox', {name: 'Patient search'}),
query,
);
await findByRole('heading', {name: /^Results for query/}, {timeout: 5000});
};

export const searchForPatient = async (app: App, query, {name, id}) => {
export const searchForPatient = async (
app: App,
query: string,
{name, id}: {name: string; id?: string},
) => {
const {findByRole, user} = app;
await searchResultsForQuery(app, query);
await user.click(await findByRole('link', {name}, {timeout: 5000}));
await findByRole('heading', {name: `/patient/${id}`}, {timeout: 10_000});
if (id !== undefined) {
await findByRole('heading', {name: `/patient/${id}`}, {timeout: 10_000});
}
};

type EditConsultationOptions = {
Expand Down
139 changes: 139 additions & 0 deletions test/app/client/patient/eids.app-tests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import {fireEvent} from '@testing-library/dom';

import {exampleEidXML} from '../../../../imports/api/_dev/populate/eids';

import {
client,
randomPassword,
randomUserId,
} from '../../../../imports/_test/fixtures';
import {
setupApp,
createUserWithPasswordAndLogin,
searchForPatient,
} from '../fixtures';

type Item = string | File;

const createFileList = (files: File[]): FileList => {
const list: FileList & Iterable<File> = {
...files,
length: files.length,
item: (index: number) => list[index]!,
[Symbol.iterator]: () => files[Symbol.iterator](),
};
list.constructor = FileList;
Object.setPrototypeOf(list, FileList.prototype);
Object.freeze(list);

return list;
};

const itemToDataTransferItem = (item: Item) =>
item instanceof File
? {
kind: 'file',
type: item.type,
getAsFile: () => item,
}
: {
kind: 'string',
type: 'text/plain',
getAsString(resolve: (value: string) => void) {
resolve(item);
},
};

const createItemList = (items: Item[]): DataTransferItemList => {
const list: DataTransferItemList & Iterable<DataTransferItem> = {
...items.map(itemToDataTransferItem),
length: items.length,
add() {
throw new Error('not-implemented');
},
remove() {
throw new Error('not-implemented');
},
clear() {
throw new Error('not-implemented');
},
*[Symbol.iterator]() {
// eslint-disable-next-line unicorn/no-for-loop,@typescript-eslint/prefer-for-of
for (let i = 0; i < list.length; ++i) {
yield list[i]!;
}
},
};

list.constructor = DataTransferItemList;
Object.setPrototypeOf(list, DataTransferItemList.prototype);
Object.freeze(list);

return list;
};

const createDataTransferFromFiles = (items: Item[] = []): DataTransfer => {
const dt = new DataTransfer();
Object.defineProperty(dt, 'files', {
get: () =>
createFileList(
items.filter((item: Item): item is File => item instanceof File),
),
});
Object.defineProperty(dt, 'items', {get: () => createItemList(items)});
return dt;
};

const dropFiles = async ({findByLabelText}, item: Item) => {
fireEvent.drop(await findByLabelText(/drop contents here/i), {
dataTransfer: createDataTransferFromFiles([item]),
});
};

client(__filename, () => {
it('should allow to open and close eid dialog', async () => {
const username = randomUserId();
const password = randomPassword();
const app = setupApp();
await createUserWithPasswordAndLogin(app, username, password);

const {findByRole, findByText, user} = app;

await dropFiles(app, exampleEidXML());

await findByRole('heading', {name: 'Select record to work with.'});

await user.click(await findByRole('button', {name: 'Cancel'}));

await findByText('Closed eid dialog.');
});

it('should allow to create a patient from eid', async () => {
const username = randomUserId();
const password = randomPassword();
const app = setupApp();
await createUserWithPasswordAndLogin(app, username, password);

const {findByRole, user} = app;

const eidXML = exampleEidXML({name: 'Doe', firstname: 'Jane'});

await dropFiles(app, eidXML);

await findByRole('heading', {name: 'Select record to work with.'});

await user.click(await findByRole('button', {name: 'Add a new patient'}));

await user.click(await findByRole('button', {name: 'Next (1)'}));

await user.click(await findByRole('button', {name: 'Next'}));

await user.click(
await findByRole('button', {name: 'Create a new patient'}),
);

await searchForPatient(app, `Jane Doe`, {
name: `Jane Doe`,
});
});
});

0 comments on commit 580b749

Please sign in to comment.