Fix Playwright OTP login and UAT security tests
This commit is contained in:
@@ -19,7 +19,7 @@ function unauthorizedRole(v) {
|
||||
|
||||
async function safeGoto(page, route) {
|
||||
const resp = await page.goto(route || '/employee/dashboard');
|
||||
await page.waitForLoadState('domcontentloaded');
|
||||
await page.waitForLoadState('domcontentloaded').catch(() => {});
|
||||
return resp;
|
||||
}
|
||||
|
||||
@@ -38,12 +38,71 @@ async function boundaryInputIfAny(page) {
|
||||
await submitBlankFormIfAny(page);
|
||||
}
|
||||
|
||||
function sec101TenantBCaseId() {
|
||||
return process.env.TENANT_B_NOTICE_CASE_ID || process.env.CROSS_TENANT_NOTICE_CASE_ID || '7';
|
||||
}
|
||||
|
||||
async function expectNoTenantBNoticeLeak(page, resp) {
|
||||
// A correct ERP may reject with 401/403/404/405/422 or redirect away.
|
||||
// If it returns 200/303, the page still must not disclose Tenant B notice data.
|
||||
await expectBlockedOrSafe(page, resp);
|
||||
|
||||
const body = await page.locator('body').innerText().catch(() => '');
|
||||
expect(body).not.toMatch(/Tenant B SEC-101 Cross Tenant Notice/i);
|
||||
expect(body).not.toMatch(/UAT-B-NOTICE-SEC101/i);
|
||||
expect(body).not.toMatch(/UAT-NC-B-SEC101/i);
|
||||
expect(body).not.toMatch(/Traceback|Internal Server Error|Exception/i);
|
||||
}
|
||||
|
||||
async function runSec101CrossTenant(page, context, v) {
|
||||
const tenantBNoticeCaseId = sec101TenantBCaseId();
|
||||
|
||||
await login(page, 'System Admin'); // Tenant A system admin from env, e.g. uat.admin@vavalam.com.
|
||||
|
||||
const variant = String(v.variantType || '').toLowerCase();
|
||||
const probes = [];
|
||||
|
||||
if (variant === 'negative') {
|
||||
probes.push(`/notice-cases/${tenantBNoticeCaseId}?tamper=1`);
|
||||
probes.push(`/notice-cases/${tenantBNoticeCaseId}/../../${tenantBNoticeCaseId}`);
|
||||
} else if (variant === 'rbac') {
|
||||
await logout(page);
|
||||
await login(page, 'Staff');
|
||||
probes.push(`/notice-cases/${tenantBNoticeCaseId}`);
|
||||
} else if (variant === 'idor') {
|
||||
probes.push(`/notice-cases/${tenantBNoticeCaseId}`);
|
||||
probes.push(`/notice-cases/${tenantBNoticeCaseId}/edit`);
|
||||
probes.push(`/notice-cases/${tenantBNoticeCaseId}/documents`);
|
||||
} else if (variant === 'headers') {
|
||||
await context.setExtraHTTPHeaders({
|
||||
'X-Tenant-ID': '3',
|
||||
'X-Branch-ID': '3',
|
||||
'X-Tenant-Code': 'UAT-B',
|
||||
'X-Branch-Code': 'UAT-BB',
|
||||
});
|
||||
probes.push(`/notice-cases/${tenantBNoticeCaseId}`);
|
||||
} else {
|
||||
probes.push(`/notice-cases/${tenantBNoticeCaseId}`);
|
||||
}
|
||||
|
||||
for (const route of probes) {
|
||||
const resp = await safeGoto(page, route);
|
||||
await expectNoTenantBNoticeLeak(page, resp);
|
||||
}
|
||||
}
|
||||
|
||||
async function runSecuritySpecific(page, context, v) {
|
||||
const id = v.sourceId;
|
||||
|
||||
if (/SEC-101/i.test(id)) {
|
||||
await runSec101CrossTenant(page, context, v);
|
||||
return;
|
||||
}
|
||||
|
||||
if (/SEC-001/i.test(id)) {
|
||||
await page.goto('/login');
|
||||
for (let i = 0; i < 5; i++) {
|
||||
await fillFirst(page, ['input[name="email"]','input[name="login_id"]','input[type="email"]'], process.env.SYSTEM_ADMIN_EMAIL || 'admin@auditfirm.local');
|
||||
await fillFirst(page, ['input[name="email"]','input[name="login_id"]','input[type="email"]'], process.env.SYSTEM_ADMIN_EMAIL || 'uat.admin@vavalam.com');
|
||||
await fillFirst(page, ['input[name="password"]','input[type="password"]'], 'wrong-password-' + i);
|
||||
await clickFirst(page, ['button[type="submit"]','input[type="submit"]']);
|
||||
await page.waitForLoadState('domcontentloaded').catch(() => {});
|
||||
@@ -95,6 +154,14 @@ for (const v of matrix) {
|
||||
test.info().annotations.push({ type: 'variantType', description: v.variantType });
|
||||
test.info().annotations.push({ type: 'expected', description: String(v.expected || '').slice(0, 250) });
|
||||
|
||||
// SEC-101 was marked manual in the generated matrix, but it is now automated here
|
||||
// using a seeded Tenant B notice case. This keeps ERP features unchanged and only
|
||||
// replaces the scaffold/manual handling for these five variants.
|
||||
if (/SEC-101/i.test(v.sourceId || '')) {
|
||||
await runSec101CrossTenant(page, context, v);
|
||||
return;
|
||||
}
|
||||
|
||||
if (v.automation === 'manual') {
|
||||
test.skip(true, v.manualReason || 'Marked manual in generated matrix');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user