test: harden champion/manager spec against post-login session timing
All checks were successful
Build and Push Docker Image / build (push) Successful in 23s
All checks were successful
Build and Push Docker Image / build (push) Successful in 23s
ensureAuth() probes an auth-required endpoint after each login() and re-logs-in if the session hasn't settled (occasionally needed under slowMo after rapid role swaps). Also observes the HTTP status of every second-pass POST so any auth bounce is visible. App logic unchanged (verified via the test client).
This commit is contained in:
parent
ef53f69833
commit
17981fdf82
@ -70,6 +70,25 @@ async function postForm(page: import('@playwright/test').Page, url: string, data
|
||||
});
|
||||
}
|
||||
|
||||
/** POST and observe the HTTP status (used where we need to see a step's outcome). */
|
||||
async function postObs(page: import('@playwright/test').Page, url: string, data: Record<string, string>, step: string, role?: string) {
|
||||
const r = await postForm(page, url, data);
|
||||
const loc = r.headers()['location'] || '';
|
||||
const loginBounce = loc.includes('/accounts/login');
|
||||
observe(M, step, r.status() < 400 && !loginBounce ? 'PASS' : 'FAIL',
|
||||
`HTTP ${r.status()}${loc ? ` -> ${loc.slice(0, 60)}` : ''}${loginBounce ? ' (auth bounce!)' : ''}`, { role, http: r.status() });
|
||||
return r;
|
||||
}
|
||||
|
||||
/** Ensure the page is actually authenticated as `role` before POSTing; re-login if bounced. */
|
||||
async function ensureAuth(page: import('@playwright/test').Page, role: RoleName) {
|
||||
// probe an auth-required page via the APIRequestContext
|
||||
const probe = await page.context().request.get(`${BASE_URL}/complaints/?__probe=1`, { maxRedirects: 0 });
|
||||
if (probe.status() === 302 && (probe.headers()['location'] || '').includes('/accounts/login')) {
|
||||
await login(page, role); // re-establish session
|
||||
}
|
||||
}
|
||||
|
||||
async function login(page: import('@playwright/test').Page, role: RoleName) {
|
||||
await page.context().clearCookies();
|
||||
await loginAndScope(page, role, M);
|
||||
@ -265,13 +284,13 @@ test.describe('Champion/Manager workflow', () => {
|
||||
`after reject: response_submitted=${sAfterReject.idept_response_submitted} (want False)`, { role: MGR });
|
||||
|
||||
// champion re-responds -> manager approves -> PX accepts -> resolve
|
||||
await login(page, CHAMP);
|
||||
await postForm(page, `${BASE_URL}/complaints/departments/${ideptId}/response/`, { response_notes_en: 'C1 revised response' });
|
||||
await login(page, MGR);
|
||||
await postForm(page, `${BASE_URL}/organizations/departments/${seed.deptId}/manager-review/${ideptId}/`, { review_action: 'approve' });
|
||||
await login(page, PXT);
|
||||
await postForm(page, `${BASE_URL}/complaints/departments/${ideptId}/review-response/`, { acceptance_status: 'acceptable' });
|
||||
await postForm(page, `${BASE_URL}/complaints/${cid}/change-status/`, { status: 'resolved', resolution: 'C1 resolved' });
|
||||
await login(page, CHAMP); await ensureAuth(page, CHAMP);
|
||||
await postObs(page, `${BASE_URL}/complaints/departments/${ideptId}/response/`, { response_notes_en: 'C1 revised response' }, 'C1-re-response', CHAMP);
|
||||
await login(page, MGR); await ensureAuth(page, MGR);
|
||||
await postObs(page, `${BASE_URL}/organizations/departments/${seed.deptId}/manager-review/${ideptId}/`, { review_action: 'approve' }, 'C1-re-approve', MGR);
|
||||
await login(page, PXT); await ensureAuth(page, PXT);
|
||||
await postObs(page, `${BASE_URL}/complaints/departments/${ideptId}/review-response/`, { acceptance_status: 'acceptable' }, 'C1-accept', PXT);
|
||||
await postObs(page, `${BASE_URL}/complaints/${cid}/change-status/`, { status: 'resolved', resolution: 'C1 resolved' }, 'C1-resolve', PXT);
|
||||
assertState(cid, { complaint_status: 'resolved', idept_acceptance_status: 'acceptable' }, 'C1-final-state', PXT);
|
||||
} catch (e) {
|
||||
observe(M, 'C1-flow', 'FAIL', `exception: ${(e as Error).message}`, { role: MGR });
|
||||
@ -308,13 +327,13 @@ test.describe('Champion/Manager workflow', () => {
|
||||
`after not-acceptable: response_submitted=${sAfterNA.idept_response_submitted} (want False)`, { role: PXT });
|
||||
|
||||
// champion re-responds -> manager approves -> PX accepts -> resolve
|
||||
await login(page, CHAMP);
|
||||
await postForm(page, `${BASE_URL}/complaints/departments/${ideptId}/response/`, { response_notes_en: 'C2 revised response' });
|
||||
await login(page, MGR);
|
||||
await postForm(page, `${BASE_URL}/organizations/departments/${seed.deptId}/manager-review/${ideptId}/`, { review_action: 'approve' });
|
||||
await login(page, PXT);
|
||||
await postForm(page, `${BASE_URL}/complaints/departments/${ideptId}/review-response/`, { acceptance_status: 'acceptable' });
|
||||
await postForm(page, `${BASE_URL}/complaints/${cid}/change-status/`, { status: 'resolved', resolution: 'C2 resolved' });
|
||||
await login(page, CHAMP); await ensureAuth(page, CHAMP);
|
||||
await postObs(page, `${BASE_URL}/complaints/departments/${ideptId}/response/`, { response_notes_en: 'C2 revised response' }, 'C2-re-response', CHAMP);
|
||||
await login(page, MGR); await ensureAuth(page, MGR);
|
||||
await postObs(page, `${BASE_URL}/organizations/departments/${seed.deptId}/manager-review/${ideptId}/`, { review_action: 'approve' }, 'C2-re-approve', MGR);
|
||||
await login(page, PXT); await ensureAuth(page, PXT);
|
||||
await postObs(page, `${BASE_URL}/complaints/departments/${ideptId}/review-response/`, { acceptance_status: 'acceptable' }, 'C2-accept', PXT);
|
||||
await postObs(page, `${BASE_URL}/complaints/${cid}/change-status/`, { status: 'resolved', resolution: 'C2 resolved' }, 'C2-resolve', PXT);
|
||||
assertState(cid, { complaint_status: 'resolved', idept_acceptance_status: 'acceptable' }, 'C2-final-state', PXT);
|
||||
} catch (e) {
|
||||
observe(M, 'C2-flow', 'FAIL', `exception: ${(e as Error).message}`, { role: PXT });
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user