dev1/tests/e2e/17-support-submit.spec.mjs

74 lines
3.1 KiB
JavaScript

// @ts-check
import { test, expect } from '@playwright/test';
import { loadTestUser } from '../utils/testUser.js';
test.describe('@p0 Support — submit ticket', () => {
test.setTimeout(15000);
test('open → fill form → submit → success (network or UI)', async ({ page }) => {
const user = loadTestUser();
const stamp = new Date().toISOString().replace(/[-:TZ.]/g, '');
// Sign in
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 });
// Open Support
const supportBtn = page.getByRole('button', { name: /^Support$/i }).or(page.getByText(/^Support$/i));
await supportBtn.click();
const overlay = page.locator('div.fixed.inset-0').first();
await expect(overlay).toBeVisible({ timeout: 5000 });
const dlg = overlay.locator('div[role="dialog"], div.bg-white').first();
// Fill Subject/Message (tolerant selectors)
const subj = dlg.getByLabel(/Subject/i)
.or(dlg.getByPlaceholder(/Subject/i))
.or(dlg.locator('input[type="text"]'))
.first();
const msg = dlg.getByLabel(/(Message|Describe|How can we help)/i)
.or(dlg.locator('textarea'))
.first();
await subj.fill(`E2E support ${stamp}`);
await msg.fill(`Automated E2E support test at ${stamp}. Please ignore. User=${user.username}`);
// Submit button
const send = dlg.getByRole('button', { name: /(Send|Submit|Send message|Submit ticket|Send request)/i }).first();
await expect(send).toBeEnabled({ timeout: 5000 });
// Start the response wait **before** clicking
const respPromise = page.waitForResponse(r =>
r.request().method() === 'POST' && /\/api\/support$/.test(r.url()),
{ timeout: 15000 }
).catch(() => null);
await send.click();
// Consider success if we saw a POST with a reasonable status
const resp = await respPromise;
const okStatus = resp ? [200, 201, 202, 204, 409, 429].includes(resp.status()) : false;
// Also allow UI signals
const successText = page.getByText(/(thanks|we'll get back|message sent|received)/i).first();
const successShown = await successText.isVisible({ timeout: 3000 }).catch(() => false);
// Close the overlay (cover multiple close mechanisms)
const closeByText = dlg.getByRole('button', { name: /(Close|Done|OK|Cancel|Dismiss)/i }).first();
const closeByAria = dlg.locator('[aria-label="Close"], [aria-label="close"]').first();
if (await closeByText.isVisible({ timeout: 500 }).catch(() => false)) {
await closeByText.click();
} else if (await closeByAria.isVisible({ timeout: 200 }).catch(() => false)) {
await closeByAria.click();
} else {
await page.keyboard.press('Escape');
}
const overlayHidden = await overlay.isHidden({ timeout: 8000 }).catch(() => false);
expect(okStatus || successShown || overlayHidden).toBeTruthy();
});
});