78 lines
2.9 KiB
Markdown
78 lines
2.9 KiB
Markdown
---
|
|
type: Task
|
|
status: AI Gen TODO
|
|
category: QA
|
|
isAgentGenerated: "true"
|
|
---
|
|
|
|
# Test: Toast Notification Timing and Dismissal
|
|
|
|
## Description
|
|
|
|
Verify that toast notifications appear with correct error/success styling, auto-dismiss after the expected duration (~1.3s), and multiple toasts stack properly when triggered in rapid succession.
|
|
|
|
## Rationale
|
|
|
|
The Build Calculator shows toast notifications for errors ("Missing Requirements", "Not Enough Ether") and potentially for success/addition confirmations. The existing toast test (`tests/buildCalculator.spec.js`) only checks whether a toast **appears** within 3 seconds; it does not validate:
|
|
- The toast's CSS class (`.error` vs `.success`).
|
|
- The exact display duration.
|
|
- Stacking behavior when multiple errors are triggered rapidly.
|
|
- Whether a toast persists if the condition that triggered it is resolved.
|
|
|
|
## Playwright Feature
|
|
|
|
This test uses **`page.clock`** (Playwright's clock API) to control time without waiting real seconds, plus **`page.waitForSelector`** with exact timeout values and **`page.evaluate`** to inspect DOM classes.
|
|
|
|
### Clock-based Timing Test
|
|
|
|
```js
|
|
// Install fake timers before navigation
|
|
await page.clock.install();
|
|
await page.clock.fastForward(5000); // Simulate WASM loading delay
|
|
await calc.goto();
|
|
|
|
// Trigger a toast by clicking E (Soul Foundry without Legion Hall)
|
|
await calc.hotkeys.clickKey('E');
|
|
await page.clock.fastForward(500); // small delay for render
|
|
|
|
// Assert toast appears with error styling
|
|
const toast = page.locator('.toastsContainer .toastContainer');
|
|
await expect(toast).toHaveClass(/error/);
|
|
|
|
// Fast-forward to just before auto-dismiss
|
|
await page.clock.fastForward(1200);
|
|
await expect(toast).toBeVisible(); // still visible at ~1.2s
|
|
|
|
// Fast-forward past dismissal
|
|
await page.clock.fastForward(200);
|
|
await expect(toast).not.toBeVisible(); // gone by ~1.4s
|
|
```
|
|
|
|
### Stacking Test
|
|
|
|
```js
|
|
// Trigger two toasts in rapid succession
|
|
calc.filter.selectFaction("Q'Rath");
|
|
await calc.hotkeys.clickKey('E'); // Missing Requirements
|
|
|
|
// Without waiting, trigger another (e.g., click an entity with zero ether)
|
|
await calc.hotkeys.clickKey('Q');
|
|
await calc.hotkeys.clickKey('E'); // Not Enough Ether
|
|
|
|
await page.waitForTimeout(300);
|
|
// Assert TWO toasts are visible, stacked
|
|
const toasts = page.locator('.toastsContainer .toastContainer');
|
|
await expect(toasts).toHaveCount(2);
|
|
// Assert the first toast has error styling and correct title
|
|
await expect(toasts.nth(0).locator('.toastTitle')).toHaveText('Missing Requirements');
|
|
await expect(toasts.nth(1).locator('.toastTitle')).toHaveText('Not Enough Ether');
|
|
```
|
|
|
|
### What This Test Catches
|
|
|
|
- Auto-dismiss timer drift (toast stays too long or disappears too early).
|
|
- Success vs. error CSS class mismatch (all toasts get the same styling).
|
|
- Stacking order (new toasts should appear above or below older ones).
|
|
- Memory leaks (stale toast DOM nodes that never get removed).
|
|
- Race conditions between `ToastService.AddToast` and `StateHasChanged`.
|