1c19d97dc8
- Added smoke.spec.js with Playwright test for full user flow: 1. Sign up (fill form, submit, click 'Go to Dashboard') 2. Create household (fill name, submit) 3. Create chore (fill name + date, submit) 4. Verify session persistence (revisit dashboard) - Server now supports --db flag for temp databases and SIS_FRESH_DB env to delete the db file on startup (for clean test runs) - Server reads SIS_PORT env var for port configuration - scripts/test-e2e: starts server with fresh db, runs tests, cleans up - playwright.config.js: minimal config pointing at test/e2e/
98 lines
4.2 KiB
JavaScript
98 lines
4.2 KiB
JavaScript
// @ts-check
|
|
const { test, expect } = require('@playwright/test');
|
|
|
|
const BASE_URL = process.env.SIS_URL || 'http://localhost:8080';
|
|
|
|
// Hyperbole lowercases constructor names for URLs: RDashboard -> /rdashboard
|
|
const URLS = {
|
|
signup: `${BASE_URL}/rsignup`,
|
|
login: `${BASE_URL}/rlogin`,
|
|
dashboard: `${BASE_URL}/rdashboard`,
|
|
chores: `${BASE_URL}/rchores`,
|
|
household: `${BASE_URL}/rhousehold`,
|
|
activity: `${BASE_URL}/ractivity`,
|
|
};
|
|
|
|
test.describe('Sis app smoke test', () => {
|
|
|
|
test('full flow: signup → login → create household → create chore', async ({ page }) => {
|
|
const unique = Date.now();
|
|
const email = `test-${unique}@example.com`;
|
|
const displayName = 'James Brechtel';
|
|
const password = 'password123';
|
|
const householdName = 'Test Casa';
|
|
const choreName = 'Take out the trash';
|
|
|
|
// ── 1. Sign up ──────────────────────────────────────────────
|
|
await page.goto(URLS.signup);
|
|
await page.waitForSelector('input[name="sfDisplayName"]', { timeout: 5000 });
|
|
|
|
// Fill out the signup form
|
|
await page.fill('input[name="sfDisplayName"]', displayName);
|
|
await page.fill('input[name="sfEmail"]', email);
|
|
await page.fill('input[name="sfPassword"]', password);
|
|
await page.fill('input[name="sfConfirm"]', password);
|
|
await page.check('input[name="sfAgree"]');
|
|
|
|
// Submit (Hyperbole replaces content in-place, no navigation)
|
|
await Promise.all([
|
|
page.waitForResponse(resp => resp.url().includes('/rsignup') && resp.status() === 200),
|
|
page.click('button[type="submit"]'),
|
|
]);
|
|
|
|
// Signup success page has a "Go to Dashboard" link
|
|
await expect(page.getByText('Account Created!')).toBeVisible({ timeout: 10000 });
|
|
await page.click('a:has-text("Go to Dashboard")');
|
|
|
|
// Now on dashboard or household page (no household yet)
|
|
await expect(page.locator('.nb-navbar-brand')).toBeVisible({ timeout: 10000 });
|
|
|
|
// ── 2. Create household ─────────────────────────────────────
|
|
const householdLink = page.locator('.nb-navbar-link', { hasText: 'Household' });
|
|
await householdLink.click();
|
|
|
|
// Should see the "Create Your Household" form
|
|
await expect(page.getByText('Create Your Household')).toBeVisible({ timeout: 10000 });
|
|
|
|
await page.fill('input[name="hfdName"]', householdName);
|
|
await Promise.all([
|
|
page.waitForResponse(resp => resp.url().includes('/rhousehold') && resp.status() === 200),
|
|
page.click('button[type="submit"]'),
|
|
]);
|
|
|
|
// Should see the household view with member count
|
|
await expect(page.getByText('1 members')).toBeVisible({ timeout: 10000 });
|
|
await expect(page.getByText(householdName)).toBeVisible();
|
|
|
|
// ── 3. Create chore ─────────────────────────────────────────
|
|
const choresLink = page.locator('.nb-navbar-link', { hasText: 'Chores' });
|
|
await choresLink.click();
|
|
|
|
// Click "+ New Chore" to open the form
|
|
const newChoreBtn = page.getByRole('button', { name: '+ New Chore' });
|
|
await newChoreBtn.click();
|
|
|
|
// Fill out the chore form
|
|
await expect(page.getByText('New Chore')).toBeVisible({ timeout: 10000 });
|
|
await page.fill('input[name="cfdName"]', choreName);
|
|
await page.fill('input[name="cfdStartDate"]', '2026-12-25');
|
|
|
|
// Submit
|
|
await Promise.all([
|
|
page.waitForResponse(resp => resp.url().includes('/rchores') && resp.status() === 200),
|
|
page.click('button[type="submit"]'),
|
|
]);
|
|
|
|
// Should appear in the chores list
|
|
await expect(page.getByText(choreName)).toBeVisible({ timeout: 10000 });
|
|
await expect(page.getByText('One-off on 2026-12-25')).toBeVisible();
|
|
|
|
// ── 4. Verify we're still authenticated ────────────────────
|
|
// Navigate to dashboard — should work since we have a session cookie
|
|
await page.goto(URLS.dashboard);
|
|
await expect(page.locator('.nb-navbar-brand')).toBeVisible({ timeout: 10000 });
|
|
await expect(page.getByText('Dashboard')).toBeVisible({ timeout: 5000 });
|
|
});
|
|
|
|
});
|