mirror of
https://github.com/Tria-plc/emaui.git
synced 2026-08-26 19:12:50 +00:00
- Created error context markdown files for failed tests in seafarer registration, detailing validation errors related to profile details. - Added binary files (PNG, ZIP, WEBM) for test results, including snapshots and traces for debugging purposes. - Updated test cases to include new error context and media files for better analysis of failures.
100 lines
3.4 KiB
TypeScript
100 lines
3.4 KiB
TypeScript
import { APIRequestContext, request } from '@playwright/test';
|
|
import { E2E } from '../../playwright.config';
|
|
import { OFFICER } from './officer';
|
|
|
|
/**
|
|
* The workflow endpoints, called as the officer.
|
|
*
|
|
* Used where a test's subject is what an approval *does* — the seafarer
|
|
* number, the activated record, the two child applications — rather than which
|
|
* buttons produce it. Driving six sections of wizard and a review screen to
|
|
* reach a completion effect would make those tests about forms.
|
|
*
|
|
* Nothing here writes to the database directly. The completion effect runs
|
|
* inside the API's approval transaction, so a test that faked the status would
|
|
* assert against an approval that never happened.
|
|
*/
|
|
|
|
/** Routes served by the applicant-facing controller rather than the review one. */
|
|
const APPLICANT_STEPS = new Set(['submit', 'resubmit']);
|
|
|
|
async function officerContext(): Promise<APIRequestContext> {
|
|
const context = await request.newContext({ baseURL: E2E.apiUrl });
|
|
const response = await context.post('/auth/login', {
|
|
data: { email: OFFICER.email, password: OFFICER.password },
|
|
});
|
|
if (!response.ok()) {
|
|
throw new Error(
|
|
`Officer login failed (${response.status()}): ${await response.text()}`,
|
|
);
|
|
}
|
|
const body = await response.json();
|
|
const token = body?.token ?? body?.accessToken ?? body?.access_token;
|
|
if (!token) {
|
|
throw new Error(`No access token in login response: ${JSON.stringify(body)}`);
|
|
}
|
|
|
|
await context.dispose();
|
|
return request.newContext({
|
|
baseURL: E2E.apiUrl,
|
|
extraHTTPHeaders: { Authorization: `Bearer ${token}` },
|
|
});
|
|
}
|
|
|
|
export interface WorkflowStep {
|
|
/** Route under the review controller, e.g. `claim`, `final-approve`. */
|
|
path: string;
|
|
data?: Record<string, unknown>;
|
|
/** Set when a step is expected to be refused — the refusal is the assertion. */
|
|
expectFailure?: boolean;
|
|
}
|
|
|
|
/**
|
|
* Runs a sequence of workflow calls against one application.
|
|
*
|
|
* Returns each step's status code so a caller can assert on a refusal as
|
|
* readily as on a success — "an officer may not evaluate a registration" is a
|
|
* result worth checking, not an error to swallow.
|
|
*/
|
|
export async function runWorkflow(
|
|
applicationId: string,
|
|
steps: WorkflowStep[],
|
|
): Promise<number[]> {
|
|
const api = await officerContext();
|
|
const codes: number[] = [];
|
|
|
|
try {
|
|
for (const step of steps) {
|
|
// Applicant-side actions (`submit`, `resubmit`) live on the
|
|
// applications controller; everything an officer does is on the review
|
|
// controller. Routing by step keeps callers from having to know.
|
|
const base = APPLICANT_STEPS.has(step.path)
|
|
? 'license-applications'
|
|
: 'license-application-review';
|
|
const response = await api.post(
|
|
`/${base}/${applicationId}/${step.path}`,
|
|
{ data: step.data ?? {} },
|
|
);
|
|
codes.push(response.status());
|
|
|
|
if (!step.expectFailure && !response.ok()) {
|
|
throw new Error(
|
|
`Step "${step.path}" failed (${response.status()}): ${await response.text()}`,
|
|
);
|
|
}
|
|
}
|
|
} finally {
|
|
await api.dispose();
|
|
}
|
|
|
|
return codes;
|
|
}
|
|
|
|
/** Claim then final-approve — the whole officer path for a registration. */
|
|
export async function approveRegistration(applicationId: string): Promise<void> {
|
|
await runWorkflow(applicationId, [
|
|
{ path: 'claim' },
|
|
{ path: 'final-approve', data: { remark: 'E2E approval' } },
|
|
]);
|
|
}
|