mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-18 21:16:47 +00:00
test(client): dismiss the CTA-style support modal in e2e setup
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { test as setup, expect } from '@playwright/test'
|
||||
import { dismissSystemNotices } from './helpers'
|
||||
|
||||
// Relative to the config dir (client/), matching `storageState` in
|
||||
// playwright.config.ts. Playwright runs from the client workspace root.
|
||||
@@ -27,16 +28,12 @@ setup('authenticate the seeded admin (incl. forced password change)', async ({ p
|
||||
|
||||
await page.waitForURL('**/dashboard', { timeout: 30_000 })
|
||||
|
||||
// Dismiss the first-run "Welcome to TREK" system-notice modal(s). It renders
|
||||
// asynchronously (after the notices fetch), so wait for it before clicking.
|
||||
// Dismissal is recorded server-side against this user, so clearing it here
|
||||
// keeps it cleared for every authenticated flow in the run (shared test DB).
|
||||
const ok = page.getByRole('button', { name: 'OK', exact: true })
|
||||
await ok.waitFor({ state: 'visible', timeout: 10_000 }).catch(() => {})
|
||||
for (let i = 0; i < 8 && (await ok.isVisible().catch(() => false)); i++) {
|
||||
await ok.click()
|
||||
await page.waitForTimeout(400)
|
||||
}
|
||||
// Dismiss the first-run system-notice modal(s) — currently the thank-you /
|
||||
// support modal, which has NO "OK" button (only CTAs + the X). The shared
|
||||
// helper handles both notice shapes; dismissal is recorded server-side
|
||||
// against this user, so clearing it here keeps it cleared for every
|
||||
// authenticated flow in the run (shared test DB).
|
||||
await dismissSystemNotices(page, 10_000)
|
||||
|
||||
await page.context().storageState({ path: stateFile })
|
||||
})
|
||||
|
||||
+35
-14
@@ -1,22 +1,43 @@
|
||||
import type { Page } from '@playwright/test'
|
||||
|
||||
/**
|
||||
* Dismiss the release-notice modal (SystemNoticeHost), which greets a freshly seeded
|
||||
* user on first load and covers the dashboard — its backdrop swallows clicks aimed at
|
||||
* anything underneath, `.add-trip-card` included.
|
||||
* Dismiss the system-notice modal(s) (SystemNoticeHost), which greet a freshly
|
||||
* seeded user on first load and cover the dashboard — the backdrop swallows
|
||||
* clicks aimed at anything underneath, `.add-trip-card` included.
|
||||
*
|
||||
* The X only appears on the notice's last page, so page through first. Dismissal is
|
||||
* persisted server-side per user, but each spec gets a fresh DB, so every spec that
|
||||
* touches the dashboard has to clear it.
|
||||
* The host renders asynchronously (after the notices fetch), so wait for the
|
||||
* notice dialog before deciding there is nothing to clear. Every lookup is
|
||||
* scoped INSIDE the dialog — an unscoped /next/i can match dashboard buttons
|
||||
* (carousel arrows) and satisfy the wait before the modal even mounts.
|
||||
*
|
||||
* A notice closes one of two ways depending on its shape:
|
||||
* - CTA-bearing notices (e.g. the thank-you/support modal) only offer the
|
||||
* X button (`aria-label="Dismiss"`), shown on the last page.
|
||||
* - CTA-less notices show an "OK" button that pages forward and dismisses on
|
||||
* the last page.
|
||||
* Multi-page notices are paged through via the pager's Next button first.
|
||||
* Dismissal is persisted server-side per user, so clearing once keeps it
|
||||
* cleared for every later spec in the run (shared test DB).
|
||||
*/
|
||||
export async function dismissSystemNotices(page: Page): Promise<void> {
|
||||
const next = page.getByRole('button', { name: /next/i })
|
||||
for (let i = 0; i < 6 && (await next.isVisible().catch(() => false)); i++) {
|
||||
if (!(await next.isEnabled())) break
|
||||
await next.click()
|
||||
export async function dismissSystemNotices(page: Page, appearTimeoutMs = 3_000): Promise<void> {
|
||||
const dialog = page.getByRole('dialog').first()
|
||||
await dialog.waitFor({ state: 'visible', timeout: appearTimeoutMs }).catch(() => {})
|
||||
|
||||
// Clear up to a handful of queued notices.
|
||||
for (let notice = 0; notice < 4 && (await dialog.isVisible().catch(() => false)); notice++) {
|
||||
const next = dialog.getByRole('button', { name: /next/i })
|
||||
for (let i = 0; i < 8 && (await next.isVisible().catch(() => false)); i++) {
|
||||
if (!(await next.isEnabled().catch(() => false))) break
|
||||
await next.click()
|
||||
}
|
||||
const dismiss = dialog.getByRole('button', { name: 'Dismiss', exact: true })
|
||||
const ok = dialog.getByRole('button', { name: 'OK', exact: true })
|
||||
if (await dismiss.isVisible().catch(() => false)) await dismiss.click()
|
||||
else if (await ok.isVisible().catch(() => false)) await ok.click()
|
||||
else break
|
||||
// Exit animation + the next queued notice mounting.
|
||||
await page.waitForTimeout(400)
|
||||
}
|
||||
|
||||
const dismiss = page.getByRole('button', { name: 'Dismiss' })
|
||||
if (await dismiss.isVisible().catch(() => false)) await dismiss.click()
|
||||
await dismiss.waitFor({ state: 'detached' }).catch(() => {})
|
||||
await dialog.waitFor({ state: 'detached', timeout: 5_000 }).catch(() => {})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user