99 lines
4.6 KiB
TypeScript
99 lines
4.6 KiB
TypeScript
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
import { test, expect } from '@playwright/test';
|
|
|
|
|
|
test.describe('Sleep Timetable Timezone Alignment', () => {
|
|
test.use({
|
|
timezoneId: 'America/Los_Angeles',
|
|
locale: 'en-US'
|
|
});
|
|
|
|
test('red marker (current time) should align with the correct grid column/row for sleeping sessions', async ({ page }) => {
|
|
// 1. Mock the current time to be 08:00 AM local (PDT/PST)
|
|
// Since we can't easily mock system time in Playwright without extra tools,
|
|
// we will rely on the fact that 'new Date()' is called in the component.
|
|
// We can use `page.addInitScript` to mock Date.
|
|
const mockDate = new Date('2026-05-17T08:00:00-07:00');
|
|
await page.addInitScript((date) => {
|
|
const originalDate = globalThis.Date;
|
|
function MockDate(...args: any[]) {
|
|
if (args.length === 0) return new originalDate(date.getTime());
|
|
return new originalDate(...args);
|
|
}
|
|
MockDate.prototype = originalDate.prototype;
|
|
MockDate.now = () => date.getTime();
|
|
globalThis.Date = MockDate as any;
|
|
}, mockDate);
|
|
|
|
// 2. Mock the API response for timetable
|
|
// We want to simulate a session that is currently happening in local time.
|
|
// If it's 08:00 AM now, and they are sleeping, the slot for 08:00 should be green.
|
|
// The API returns slots with 'sleeping: true'.
|
|
// Note: the component's logic uses `timetable.slots` and checks `isSleepingInInterval`.
|
|
// The slots come from the backend with 'slot_start' and 'slot_end'.
|
|
await page.route('**/api/stats/timetable*', async (route) => {
|
|
const json = {
|
|
slots: [
|
|
// A session that covers 07:00 to 09:00 on May 17th
|
|
{ date: '2026-05-17', slot_start: '07:00', slot_end: '07:15', sleeping: true },
|
|
{ date: '2026-05-17', slot_start: '07:15', slot_end: '07:30', sleeping: true },
|
|
{ date: '2026-05-17', slot_start: '07:30', slot_end: '07:45', sleeping: true },
|
|
{ date: '2026-05-17', slot_start: '07:45', slot_end: '08:00', sleeping: true },
|
|
{ date: '2026-05-17', slot_start: '08:00', slot_end: '08:15', sleeping: true },
|
|
{ date: '2026-05-17', slot_start: '08:15', slot_end: '08:30', sleeping: true },
|
|
{ date: '2026-05-17', slot_start: '08:30', slot_end: '08:45', sleeping: true },
|
|
{ date: '2026-05-17', slot_start: '08:45', slot_end: '09:00', sleeping: true },
|
|
]
|
|
};
|
|
await route.fulfill({ json });
|
|
});
|
|
|
|
// Also mock the daily summary as it's used by useStats
|
|
await page.route('**/api/stats/daily-summary*', async (route) => {
|
|
await route.fulfill({ json: { days: [] } });
|
|
});
|
|
|
|
// Also mock wake-sleep times as it's used by useStats
|
|
await page.route('**/api/stats/wake-sleep-times*', async (route) => {
|
|
await route.fulfill({ json: { days: [] } });
|
|
});
|
|
|
|
// 3. Navigate to the stats page
|
|
await page.goto('/stats'); // Assuming /stats is the route for StatsPage
|
|
|
|
// 4. Verify that the red marker (at 08:00) is inside a green cell
|
|
// The red marker has class 'bg-red-500'
|
|
const redMarker = page.locator('.bg-red-500');
|
|
await expect(redMarker).toBeVisible();
|
|
|
|
// We want to check if the cell at 08:00 is green.
|
|
// In our mocked data, the slots for 08:00 are sleeping: true.
|
|
// The component renders cells with className={`h-8 w-full ${sleeping ? 'bg-green-500' : 'bg-gray-50'}`}
|
|
// Since we can't easily target a specific "cell" by index in a grid without more info,
|
|
// we check if there's at least one green cell that matches our criteria.
|
|
const greenCells = page.locator('.bg-green-500');
|
|
await expect(greenCells.count()).toBeGreaterThan(0);
|
|
|
|
// To be really precise, we can check the position of the red marker
|
|
// and see if there is a green cell at that same vertical position.
|
|
const markerBox = await redMarker.boundingBox();
|
|
if (markerBox) {
|
|
// The marker is at 08:00, which is (8*60)/1440 = 33.33% from the top of the container
|
|
// We can check if the cell at that height is green.
|
|
const allGreenCells = page.locator('.bg-green-500');
|
|
const count = await allGreenCells.count();
|
|
let foundAlignedCell = false;
|
|
for (let i = 0; i < count; i++) {
|
|
const cellBox = await allGreenCells.nth(i).boundingBox();
|
|
if (cellBox && markerBox.y >= cellBox.y - 2 && markerBox.y <= cellBox.y + cellBox.height + 2) {
|
|
foundAlignedCell = true;
|
|
break;
|
|
}
|
|
}
|
|
expect(foundAlignedCell).toBe(true);
|
|
} else {
|
|
throw new Error('Could not get bounding box for red marker');
|
|
}
|
|
});
|
|
});
|