PPPAIMT-Crest/backend/test/consent.test.js

133 lines
3.3 KiB
JavaScript

import { afterEach, describe, expect, it } from 'vitest';
import { createServer } from '../src/app.js';
import { db } from '../src/db/knex.js';
import { clearOutbox, outbox } from '../src/services/mail.js';
import { truncateTables } from './truncate.js';
const email = 'consent-doctor@example.com';
const answers = {
voluntary_withdraw: true,
mou_required: true,
eligibility_six_months: true,
confidential_research: true,
web_questionnaire: true,
no_intervention: true,
aggregated_reporting: true,
honorarium: true,
agree_participate: true,
};
/**
* @param {import('@hapi/hapi').ServerInjectResponse} response
*/
function userCookie(response) {
const raw = response.headers['set-cookie'];
const headers = Array.isArray(raw) ? raw : raw ? [raw] : [];
const match = headers.find((header) => header.startsWith('user_token='));
return match ? match.split(';')[0] : null;
}
describe('consent', () => {
/** @type {import('@hapi/hapi').Server | undefined} */
let server;
afterEach(async () => {
clearOutbox();
await server?.stop();
await truncateTables();
});
async function start() {
server = await createServer();
return server;
}
async function login(api) {
await api.inject({
method: 'POST',
url: '/api/auth/otp/request',
payload: { email },
});
const verified = await api.inject({
method: 'POST',
url: '/api/auth/otp/verify',
payload: { email, otp: outbox[0].otp },
});
return userCookie(verified);
}
it('submits consent and advances nextStep to agreement', async () => {
const api = await start();
const cookie = await login(api);
const before = await api.inject({
method: 'GET',
url: '/api/me',
headers: { cookie },
});
expect(before.result.nextStep).toBe('consent');
const submitted = await api.inject({
method: 'POST',
url: '/api/consent',
headers: { cookie },
payload: {
participant_name: 'Dr Consent Test',
consent_date: '2026-10-16',
answers,
},
});
expect(submitted.statusCode).toBe(200);
expect(submitted.result).toMatchObject({
participant_name: 'Dr Consent Test',
consent_date: '2026-10-16',
});
const me = await api.inject({
method: 'GET',
url: '/api/me',
headers: { cookie },
});
expect(me.result.steps.consent.done).toBe(true);
expect(me.result.nextStep).toBe('agreement');
expect(me.result.user.name).toBe('Dr Consent Test');
const again = await api.inject({
method: 'POST',
url: '/api/consent',
headers: { cookie },
payload: {
participant_name: 'Dr Consent Test',
consent_date: '2026-10-16',
answers,
},
});
expect(again.statusCode).toBe(409);
const row = await db('consents').where({ participant_name: 'Dr Consent Test' }).first();
expect(row).toBeTruthy();
});
it('rejects incomplete consent answers', async () => {
const api = await start();
const cookie = await login(api);
const response = await api.inject({
method: 'POST',
url: '/api/consent',
headers: { cookie },
payload: {
participant_name: 'Dr Consent Test',
consent_date: '2026-10-16',
answers: { ...answers, eligibility_six_months: false },
},
});
expect(response.statusCode).toBe(400);
});
});