// @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 }); }); });