learning_ai_invt_trdg/web/e2e/feedback.spec.ts
Saravana Achu Mac 79f00214a9 test(ui): add comprehensive Playwright E2E test suite
- Created e2e/alert-positioning.spec.ts for critical alerts positioning tests
- Created e2e/assistant-positioning.spec.ts for assistant widget positioning tests
- Created e2e/destructive-actions.spec.ts for destructive actions confirmation tests
- Created e2e/feedback.spec.ts for save/delete/update feedback tests
- Created e2e/page-states.spec.ts for loading/empty/error/success states tests
- Created e2e/form-validation.spec.ts for form validation tests
- Created e2e/keyboard-navigation.spec.ts for keyboard navigation tests
- Created scripts/tests/run-e2e.sh test runner script with health check
- Updated LAUNCH_READY_UI_UX_ROADMAP.md checklist - all items complete
- All testing infrastructure complete (CI integration replaced with local test runner)
2026-05-09 13:28:20 -07:00

142 lines
4.7 KiB
TypeScript

import { test, expect } from '@playwright/test';
/**
* Save/Delete/Update Feedback Tests
*
* Tests that all saves/deletes/updates produce feedback
*/
test.describe('Save/Delete/Update Feedback', () => {
test('Save action produces feedback', async ({ page }) => {
await page.goto('/plans');
await page.waitForLoadState('networkidle');
// Look for save buttons
const saveButtons = page.locator('button:has-text("Save"), button:has-text("Apply"), button[type="submit"]');
const saveCount = await saveButtons.count();
if (saveCount > 0) {
// Take screenshot before action
await page.screenshot({ path: 'before-save.png' });
// Click save button
await saveButtons.first().click();
// Wait for feedback
await page.waitForTimeout(2000);
// Look for toast notifications or success messages
const toast = page.locator('[role="status"], .toast, .notification, [class*="toast"], [class*="notification"]');
const toastCount = await toast.count();
// Look for success messages
const successMessage = page.locator(':text("saved"), :text("success"), :text("updated")');
const successCount = await successMessage.count();
// At least one form of feedback should be present
const hasFeedback = toastCount > 0 || successCount > 0;
expect(hasFeedback).toBe(true);
// Take screenshot after action
await page.screenshot({ path: 'after-save.png' });
}
});
test('Delete action produces feedback', async ({ page }) => {
await page.goto('/plans');
await page.waitForLoadState('networkidle');
const deleteButtons = page.locator('button:has-text("Delete")');
const deleteCount = await deleteButtons.count();
if (deleteCount > 0) {
// Set up dialog handler
page.on('dialog', async (dialog) => {
dialog.accept();
});
// Take screenshot before
await page.screenshot({ path: 'before-delete.png' });
// Click delete
await deleteButtons.first().click();
// Wait for feedback
await page.waitForTimeout(2000);
// Look for feedback
const toast = page.locator('[role="status"], .toast, .notification');
const toastCount = await toast.count();
const deletedMessage = page.locator(':text("deleted"), :text("removed")');
const deletedCount = await deletedMessage.count();
const hasFeedback = toastCount > 0 || deletedCount > 0;
expect(hasFeedback).toBe(true);
// Take screenshot after
await page.screenshot({ path: 'after-delete.png' });
}
});
test('Update action produces feedback', async ({ page }) => {
await page.goto('/plans');
await page.waitForLoadState('networkidle');
// Look for update buttons or form fields
const updateButtons = page.locator('button:has-text("Update"), button:has-text("Apply")');
const updateCount = await updateButtons.count();
if (updateCount > 0) {
await page.screenshot({ path: 'before-update.png' });
await updateButtons.first().click();
await page.waitForTimeout(2000);
const toast = page.locator('[role="status"], .toast, .notification');
const toastCount = await toast.count();
const updatedMessage = page.locator(':text("updated"), :text("saved")');
const updatedCount = await updatedMessage.count();
const hasFeedback = toastCount > 0 || updatedCount > 0;
expect(hasFeedback).toBe(true);
await page.screenshot({ path: 'after-update.png' });
}
});
test('Feedback is visible and accessible', async ({ page }) => {
await page.goto('/plans');
await page.waitForLoadState('networkidle');
const saveButtons = page.locator('button:has-text("Save")');
const saveCount = await saveButtons.count();
if (saveCount > 0) {
await saveButtons.first().click();
await page.waitForTimeout(2000);
const toast = page.locator('[role="status"], .toast, .notification');
const toastCount = await toast.count();
if (toastCount > 0) {
// Check visibility
await expect(toast.first()).toBeVisible();
// Check ARIA attributes
const role = await toast.first().getAttribute('role');
expect(role).toMatch(/status|alert|log/i);
// Check that feedback disappears after a reasonable time
await page.waitForTimeout(5000);
const isVisible = await toast.first().isVisible();
// Toast should auto-dismiss (this is optional behavior)
// expect(isVisible).toBe(false);
}
}
});
});