From 21c90749fbeb5b5dec33c8212f22ca5921105f07 Mon Sep 17 00:00:00 2001 From: A R R R Associates Date: Thu, 25 Jun 2026 23:20:56 +0530 Subject: [PATCH] Fix remaining v2.5.1 Playwright POST download and FY selector tests --- tests/employee-hr-business-rules.spec.js | 8 ++++++-- tests/marketplace-leads.spec.js | 8 ++++++-- tests/notice-case-business-rules.spec.js | 8 ++++++-- tests/noticecases-services-work.spec.js | 21 +++++++++++++++------ tests/partners-billing.spec.js | 8 +++++--- tests/platform-billing.spec.js | 8 ++++++-- tests/system-settings-tenancy.spec.js | 8 ++++++-- tests/v204-security-additions.spec.js | 5 +++-- 8 files changed, 53 insertions(+), 21 deletions(-) diff --git a/tests/employee-hr-business-rules.spec.js b/tests/employee-hr-business-rules.spec.js index b20043a..cc642f9 100644 --- a/tests/employee-hr-business-rules.spec.js +++ b/tests/employee-hr-business-rules.spec.js @@ -307,10 +307,14 @@ test.describe("v2.5.1 Additions - Employee HR Business Rules", () => { } if (kind === 'post') { - const resp = await apiCall(request, method || 'POST', c.route); + // Some generated VAPT rows accidentally carry _method: 'GET' even when + // the scenario is explicitly CSRF-less POST. Force POST unless the row + // intentionally specifies another unsafe verb. + const unsafeMethod = (!method || method === 'GET') ? 'POST' : method; + const resp = await apiCall(request, unsafeMethod, c.route); await expectApiSafe(resp); const safe = [400, 401, 403, 404, 405, 409, 422, 429].includes(resp.status()); - expect(safe, `Unsafe POST status ${resp.status()} for ${c.route}`).toBeTruthy(); + expect(safe, `Unsafe ${unsafeMethod} status ${resp.status()} for ${c.route}`).toBeTruthy(); return; } diff --git a/tests/marketplace-leads.spec.js b/tests/marketplace-leads.spec.js index e9e33bc..5f6aad4 100644 --- a/tests/marketplace-leads.spec.js +++ b/tests/marketplace-leads.spec.js @@ -331,10 +331,14 @@ test.describe("v2.5.1 Additions - Marketplace / Leads", () => { } if (kind === 'post') { - const resp = await apiCall(request, method || 'POST', c.route); + // Some generated VAPT rows accidentally carry _method: 'GET' even when + // the scenario is explicitly CSRF-less POST. Force POST unless the row + // intentionally specifies another unsafe verb. + const unsafeMethod = (!method || method === 'GET') ? 'POST' : method; + const resp = await apiCall(request, unsafeMethod, c.route); await expectApiSafe(resp); const safe = [400, 401, 403, 404, 405, 409, 422, 429].includes(resp.status()); - expect(safe, `Unsafe POST status ${resp.status()} for ${c.route}`).toBeTruthy(); + expect(safe, `Unsafe ${unsafeMethod} status ${resp.status()} for ${c.route}`).toBeTruthy(); return; } diff --git a/tests/notice-case-business-rules.spec.js b/tests/notice-case-business-rules.spec.js index 31cfb5d..3022004 100644 --- a/tests/notice-case-business-rules.spec.js +++ b/tests/notice-case-business-rules.spec.js @@ -343,10 +343,14 @@ test.describe("v2.5.1 Additions - Notice Case Business Rules", () => { } if (kind === 'post') { - const resp = await apiCall(request, method || 'POST', c.route); + // Some generated VAPT rows accidentally carry _method: 'GET' even when + // the scenario is explicitly CSRF-less POST. Force POST unless the row + // intentionally specifies another unsafe verb. + const unsafeMethod = (!method || method === 'GET') ? 'POST' : method; + const resp = await apiCall(request, unsafeMethod, c.route); await expectApiSafe(resp); const safe = [400, 401, 403, 404, 405, 409, 422, 429].includes(resp.status()); - expect(safe, `Unsafe POST status ${resp.status()} for ${c.route}`).toBeTruthy(); + expect(safe, `Unsafe ${unsafeMethod} status ${resp.status()} for ${c.route}`).toBeTruthy(); return; } diff --git a/tests/noticecases-services-work.spec.js b/tests/noticecases-services-work.spec.js index 73c8961..d04656b 100644 --- a/tests/noticecases-services-work.spec.js +++ b/tests/noticecases-services-work.spec.js @@ -152,20 +152,29 @@ test.describe('SVC: Services depth', () => { test('[V25-SVC-002] SVC-002 Bulk imports service-master template downloads', async ({ page }) => { await login(page, 'Firm Admin'); - const resp = await safeGoto(page, '/services/bulk-imports/templates/service-master.xlsx'); - expect(resp.status()).toBeLessThan(500); + const [download] = await Promise.all([ + page.waitForEvent('download'), + page.goto('/services/bulk-imports/templates/service-master.xlsx').catch(() => null), + ]); + expect(await download.suggestedFilename()).toMatch(/service.*template|xlsx/i); }); test('[V25-SVC-003] SVC-003 Bulk imports engagement-assignments template downloads', async ({ page }) => { await login(page, 'Firm Admin'); - const resp = await safeGoto(page, '/services/bulk-imports/templates/engagement-assignments.xlsx'); - expect(resp.status()).toBeLessThan(500); + const [download] = await Promise.all([ + page.waitForEvent('download'), + page.goto('/services/bulk-imports/templates/engagement-assignments.xlsx').catch(() => null), + ]); + expect(await download.suggestedFilename()).toMatch(/assignment|template|xlsx/i); }); test('[V25-SVC-004] SVC-004 Bulk imports firm-task-templates template downloads', async ({ page }) => { await login(page, 'Firm Admin'); - const resp = await safeGoto(page, '/services/bulk-imports/templates/firm-task-templates.xlsx'); - expect(resp.status()).toBeLessThan(500); + const [download] = await Promise.all([ + page.waitForEvent('download'), + page.goto('/services/bulk-imports/templates/firm-task-templates.xlsx').catch(() => null), + ]); + expect(await download.suggestedFilename()).toMatch(/task|template|xlsx/i); }); test('[V25-SVC-005] SVC-005 Bulk import preview CSRF-less POST is rejected', async ({ request }) => { diff --git a/tests/partners-billing.spec.js b/tests/partners-billing.spec.js index 20dc531..d046b63 100644 --- a/tests/partners-billing.spec.js +++ b/tests/partners-billing.spec.js @@ -225,9 +225,11 @@ test.describe('BILL: Invoices and payments', () => { test('[V25-BILL-016] BILL-016 Fee structure import template download works', async ({ page }) => { await login(page, 'Firm Admin'); - const resp = await safeGoto(page, '/billing/fee-structures/template'); - // should download or redirect, not crash - expect(resp.status()).toBeLessThan(500); + const [download] = await Promise.all([ + page.waitForEvent('download'), + page.goto('/billing/fee-structures/template').catch(() => null), + ]); + expect(await download.suggestedFilename()).toMatch(/fee.*structure|template|xlsx/i); }); }); diff --git a/tests/platform-billing.spec.js b/tests/platform-billing.spec.js index ca53abf..591e02a 100644 --- a/tests/platform-billing.spec.js +++ b/tests/platform-billing.spec.js @@ -487,10 +487,14 @@ test.describe("v2.5.1 Additions - Platform Billing", () => { } if (kind === 'post') { - const resp = await apiCall(request, method || 'POST', c.route); + // Some generated VAPT rows accidentally carry _method: 'GET' even when + // the scenario is explicitly CSRF-less POST. Force POST unless the row + // intentionally specifies another unsafe verb. + const unsafeMethod = (!method || method === 'GET') ? 'POST' : method; + const resp = await apiCall(request, unsafeMethod, c.route); await expectApiSafe(resp); const safe = [400, 401, 403, 404, 405, 409, 422, 429].includes(resp.status()); - expect(safe, `Unsafe POST status ${resp.status()} for ${c.route}`).toBeTruthy(); + expect(safe, `Unsafe ${unsafeMethod} status ${resp.status()} for ${c.route}`).toBeTruthy(); return; } diff --git a/tests/system-settings-tenancy.spec.js b/tests/system-settings-tenancy.spec.js index 42fee02..2866a83 100644 --- a/tests/system-settings-tenancy.spec.js +++ b/tests/system-settings-tenancy.spec.js @@ -499,10 +499,14 @@ test.describe("v2.5.1 Additions - System Settings / Tenancy / FY", () => { } if (kind === 'post') { - const resp = await apiCall(request, method || 'POST', c.route); + // Some generated VAPT rows accidentally carry _method: 'GET' even when + // the scenario is explicitly CSRF-less POST. Force POST unless the row + // intentionally specifies another unsafe verb. + const unsafeMethod = (!method || method === 'GET') ? 'POST' : method; + const resp = await apiCall(request, unsafeMethod, c.route); await expectApiSafe(resp); const safe = [400, 401, 403, 404, 405, 409, 422, 429].includes(resp.status()); - expect(safe, `Unsafe POST status ${resp.status()} for ${c.route}`).toBeTruthy(); + expect(safe, `Unsafe ${unsafeMethod} status ${resp.status()} for ${c.route}`).toBeTruthy(); return; } diff --git a/tests/v204-security-additions.spec.js b/tests/v204-security-additions.spec.js index 1c8228e..7112104 100644 --- a/tests/v204-security-additions.spec.js +++ b/tests/v204-security-additions.spec.js @@ -126,8 +126,9 @@ test.describe('v2.0.4 additional security / FY / context checks', () => { await page.goto('/system-settings'); await expectNoBackendError(page); const body = await readBody(page); - const selectorExists = await page.locator('select[name="active_financial_year"], select[name="financial_year"], [data-testid="active-fy-select"], text=/FY|Financial Year|Active FY/i').count(); - expect(selectorExists || /financial year|active fy|fy\s*[:\-]/i.test(body)).toBeTruthy(); + const cssSelectorCount = await page.locator('select[name="active_financial_year"], select[name="financial_year"], [data-testid="active-fy-select"]').count(); + const textSelectorCount = await page.getByText(/FY|Financial Year|Active FY/i).count().catch(() => 0); + expect(cssSelectorCount || textSelectorCount || /financial year|active fy|fy\s*[:\-]/i.test(body)).toBeTruthy(); }); test('V204-FY-002 switching FY does not crash core transactional pages', async ({ page }) => {