dev1/tests/e2e/21-support-auth-dedupe.spec.mjs

48 lines
2.0 KiB
JavaScript

// @ts-check
import { test, expect } from '@playwright/test';
import { loadTestUser } from '../utils/testUser.js';
test.describe('@p0 Support — auth + dedupe', () => {
test.setTimeout(15000);
test('unauthenticated request is rejected (401)', async ({ page }) => {
await page.context().clearCookies();
const resp = await page.request.post('/api/support', {
data: { subject: 'unauth test', message: 'should be 401' },
});
expect([401, 403]).toContain(resp.status());
});
test('duplicate submission within window is deduped (409 or similar)', async ({ page }) => {
const user = loadTestUser();
const stamp = new Date().toISOString().replace(/[-:TZ.]/g, '');
const subject = `E2E dedupe ${stamp}`;
const message = `Automated dedupe probe at ${stamp}.`;
// Sign in (to get auth cookie)
await page.context().clearCookies();
await page.goto('/signin', { waitUntil: 'networkidle' });
await page.getByPlaceholder('Username', { exact: true }).fill(user.username);
await page.getByPlaceholder('Password', { exact: true }).fill(user.password);
await page.getByRole('button', { name: /^Sign In$/ }).click();
await page.waitForURL('**/signin-landing**', { timeout: 15000 });
// First submission (usually 2xx, but allow 409/429 if dedupe/limit already active)
const r1 = await page.request.post('/api/support', { data: { subject, message } });
const s1 = r1.status();
expect([200, 201, 202, 204, 409, 429]).toContain(s1);
// Immediate duplicate (should trigger dedupe or be tolerated by server)
const r2 = await page.request.post('/api/support', { data: { subject, message } });
const s2 = r2.status();
// Accept dedupe/ratelimit or tolerated 2xx
expect([409, 429, 200, 201, 202, 204]).toContain(s2);
// At least one of the two should indicate dedupe/limit
expect([s1, s2].some(s => s === 409 || s === 429)).toBeTruthy();
// (Optional) small delay to avoid tripping burst limiter on shared environments
await page.waitForTimeout(100);
});
});