style(13-03): apply Prettier formatting across repo

Mechanical reformat — no logic changes. 398 files changed, 19125
insertions(+), 16457 deletions(-). Prettier 3.8.4 with .prettierrc
(singleQuote:true, semi:true, tabWidth:2, trailingComma:all,
printWidth:100). Isolated per D-13-08 for reviewability.
This commit is contained in:
Lucas Berger
2026-06-11 20:35:18 -04:00
parent 4bc0445173
commit 982438dc10
398 changed files with 19050 additions and 16382 deletions
+58 -57
View File
@@ -18,28 +18,29 @@
* pnpm --filter @familysync/pwa test:e2e
* pnpm --filter @familysync/pwa exec playwright test --project=pixel calendar.spec.ts
*/
import { test, expect } from '@playwright/test'
import { test, expect } from '@playwright/test';
// ── TEST-02 preconditions: DEV_AUTH_BYPASS + no SW controller ─────────────────
test.describe('TEST-02 preconditions — auth bypass and SW block', () => {
test('DEV_AUTH_BYPASS reached authed PWA without OIDC mock', async ({ page }) => {
await page.goto('/calendar')
await page.goto('/calendar');
// Wait for the authed content to appear — DEV_AUTH_BYPASS should resolve immediately
// without Authelia redirect. The BottomTabBar nav landmark is only rendered after auth.
const nav = page.getByRole('navigation', { name: 'Main navigation' })
await expect(nav).toBeVisible()
const nav = page.getByRole('navigation', { name: 'Main navigation' });
await expect(nav).toBeVisible();
// Confirm we are NOT on an external auth host (Authelia login page would redirect the URL)
const url = new URL(page.url())
expect(url.hostname, `Expected to remain on localhost or 127.0.0.1, got: ${url.hostname}`).toMatch(
/^(localhost|127\.0\.0\.1)$/,
)
})
const url = new URL(page.url());
expect(
url.hostname,
`Expected to remain on localhost or 127.0.0.1, got: ${url.hostname}`,
).toMatch(/^(localhost|127\.0\.0\.1)$/);
});
test('no service-worker registration (serviceWorkers: block enforced)', async ({ page }) => {
await page.goto('/calendar')
await page.goto('/calendar');
// serviceWorkers: 'block' in playwright.config.ts prevents SW registration.
//
@@ -54,28 +55,28 @@ test.describe('TEST-02 preconditions — auth bypass and SW block', () => {
// entirely (WebKit/http), skip rather than let an unavailable API masquerade as a pass.
const swAvailable = await page.evaluate(
() => typeof navigator !== 'undefined' && 'serviceWorker' in navigator,
)
);
test.skip(
!swAvailable,
'navigator.serviceWorker is unavailable in this context (e.g. WebKit over http://localhost) — block is unobservable here',
)
);
const registration = await page.evaluate(() => navigator.serviceWorker.getRegistration())
const registration = await page.evaluate(() => navigator.serviceWorker.getRegistration());
expect(
registration,
'No service worker should be registered (serviceWorkers:block enforced)',
).toBeUndefined()
})
})
).toBeUndefined();
});
});
// ── Rule 5: Populated state ───────────────────────────────────────────────────
test.describe('Rule 5 — populated calendar state', () => {
test.beforeEach(async ({ page }) => {
await page.goto('/calendar')
await page.goto('/calendar');
// Wait for auth and Schedule-X to render before asserting
await expect(page.getByRole('navigation', { name: 'Main navigation' })).toBeVisible()
})
await expect(page.getByRole('navigation', { name: 'Main navigation' })).toBeVisible();
});
test('Schedule-X calendar grid is visible after seeding', async ({ page }) => {
// The Schedule-X React adapter emits a div.sx-react-calendar-wrapper.
@@ -83,30 +84,32 @@ test.describe('Rule 5 — populated calendar state', () => {
// No semantic role exists for the widget wrapper, so CSS class is the documented fallback.
// NOTE: the wrapper renders on any successful auth — this proves the grid mounts, NOT that
// the seed reached the UI. The DB→UI proof is the separate "seeded event is rendered" test.
const calendarGrid = page.locator('.sx-react-calendar-wrapper')
await expect(calendarGrid).toBeVisible()
})
const calendarGrid = page.locator('.sx-react-calendar-wrapper');
await expect(calendarGrid).toBeVisible();
});
test('seeded event "Seeded Test Event" is rendered in the grid (DB→UI proof)', async ({ page }) => {
test('seeded event "Seeded Test Event" is rendered in the grid (DB→UI proof)', async ({
page,
}) => {
// The one assertion that actually proves the seeded row flows DB → API → query → grid.
// global-setup seeds a timed event titled 'Seeded Test Event' (noon today) on calendar 10.
// Schedule-X renders the event with its title text inside the grid. If the seed broke, the
// /api/events join regressed, or hydration dropped events, THIS fails (unlike a wrapper /
// dead-EmptyState check, which would stay green). Deep-review BL-01.
await expect(page.getByText('Seeded Test Event').first()).toBeVisible()
})
await expect(page.getByText('Seeded Test Event').first()).toBeVisible();
});
test('no horizontal overflow on populated /calendar (Rule 2)', async ({ page }) => {
const overflow = await page.evaluate(() => ({
scrollWidth: document.documentElement.scrollWidth,
clientWidth: document.documentElement.clientWidth,
}))
}));
expect(
overflow.scrollWidth,
`scrollWidth (${overflow.scrollWidth}) must be ≤ clientWidth (${overflow.clientWidth}) on populated /calendar`,
).toBeLessThanOrEqual(overflow.clientWidth)
})
})
).toBeLessThanOrEqual(overflow.clientWidth);
});
});
// ── Rule 5: Error state ───────────────────────────────────────────────────────
@@ -116,63 +119,61 @@ test.describe('Rule 5 — calendar error state (API mocked to 500)', () => {
// so the very first events request is caught (Pattern 5).
await page.route('/api/events*', (route) =>
route.fulfill({ status: 500, body: JSON.stringify({ error: 'simulated' }) }),
)
);
await page.goto('/calendar')
await page.goto('/calendar');
// Wait for auth (DEV_AUTH_BYPASS)
await expect(page.getByRole('navigation', { name: 'Main navigation' })).toBeVisible()
await expect(page.getByRole('navigation', { name: 'Main navigation' })).toBeVisible();
// eventsQuery has retry:2 so Playwright may need to wait for all retries before
// the error branch renders. Use default Playwright timeout.
const errorHeading = page.getByRole('heading', { name: "Couldn't load events" })
await expect(errorHeading).toBeVisible()
const errorHeading = page.getByRole('heading', { name: "Couldn't load events" });
await expect(errorHeading).toBeVisible();
const retryBtn = page.getByRole('button', { name: 'Retry' })
await expect(retryBtn).toBeVisible()
const retryBtn = page.getByRole('button', { name: 'Retry' });
await expect(retryBtn).toBeVisible();
// No manual unroute (WR-05): Playwright gives each test a fresh page/context, so route
// handlers do not leak across tests. A trailing unroute also never runs if an `expect`
// above throws — it was misleading "cleanup" that guaranteed nothing.
})
});
test('Retry button meets 44px touch-target minimum in error state (Rule 1)', async ({
page,
}) => {
test('Retry button meets 44px touch-target minimum in error state (Rule 1)', async ({ page }) => {
await page.route('/api/events*', (route) =>
route.fulfill({ status: 500, body: JSON.stringify({ error: 'simulated' }) }),
)
);
await page.goto('/calendar')
await expect(page.getByRole('navigation', { name: 'Main navigation' })).toBeVisible()
await page.goto('/calendar');
await expect(page.getByRole('navigation', { name: 'Main navigation' })).toBeVisible();
const retryBtn = page.getByRole('button', { name: 'Retry' })
await expect(retryBtn).toBeVisible()
const retryBtn = page.getByRole('button', { name: 'Retry' });
await expect(retryBtn).toBeVisible();
const box = await retryBtn.boundingBox()
expect(box, 'Retry button bounding box must not be null').not.toBeNull()
expect(box!.height, 'Retry button height must be ≥ 44px (Rule 1)').toBeGreaterThanOrEqual(44)
const box = await retryBtn.boundingBox();
expect(box, 'Retry button bounding box must not be null').not.toBeNull();
expect(box!.height, 'Retry button height must be ≥ 44px (Rule 1)').toBeGreaterThanOrEqual(44);
// No manual unroute (WR-05): per-test context isolation handles route cleanup.
})
});
test('no horizontal overflow in error state (Rule 2)', async ({ page }) => {
await page.route('/api/events*', (route) =>
route.fulfill({ status: 500, body: JSON.stringify({ error: 'simulated' }) }),
)
);
await page.goto('/calendar')
await expect(page.getByRole('navigation', { name: 'Main navigation' })).toBeVisible()
await page.goto('/calendar');
await expect(page.getByRole('navigation', { name: 'Main navigation' })).toBeVisible();
// Wait for error heading to confirm the error branch has rendered
await expect(page.getByRole('heading', { name: "Couldn't load events" })).toBeVisible()
await expect(page.getByRole('heading', { name: "Couldn't load events" })).toBeVisible();
const overflow = await page.evaluate(() => ({
scrollWidth: document.documentElement.scrollWidth,
clientWidth: document.documentElement.clientWidth,
}))
}));
expect(
overflow.scrollWidth,
`scrollWidth (${overflow.scrollWidth}) must be ≤ clientWidth (${overflow.clientWidth}) in error state`,
).toBeLessThanOrEqual(overflow.clientWidth)
).toBeLessThanOrEqual(overflow.clientWidth);
// No manual unroute (WR-05): per-test context isolation handles route cleanup.
})
})
});
});