// Rôle : vérifie la lisibilité et la zone cliquable des événements calendrier denses. /* global getComputedStyle */ import { test, expect } from "@playwright/test"; import { resetSokkoStorage } from "./helpers/storage.js"; async function seedCalendars(page) { await resetSokkoStorage(page); await page.evaluate(async () => { const db = await import("/src/utils/indexedDbStorage.js"); const dateKey = (day) => { const now = new Date(); return `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}-${String(day).padStart(2, "0")}`; }; await db.setToolboxSnapshot([{ id: "calendar-layout", name: "Calendar layout", moduleColumns: 1, modules: [ { id: "week", type: "calendar", title: "Week" }, { id: "month", type: "calendar", title: "Month" } ] }], {}, { "calendar-layout:week": { initialized: true, viewMode: "week", events: [30, 60, 120].map((duration, index) => ({ id: `week-${index}`, title: `Raid ${duration}`, dayIndex: index, startMinutes: 600, endMinutes: 600 + duration, color: "violet" })) }, "calendar-layout:month": { initialized: true, viewMode: "month", events: [0, 1, 2, 3].map((index) => ({ id: `month-${index}`, title: `Event ${index}`, repeat: "none", startDate: dateKey(index < 3 ? 10 : 20), endDate: dateKey(index < 3 ? 10 : 20), color: "gold" })) } }); }); await page.goto("/#/toolbox/calendar-layout"); await page.reload(); } async function expectTitleFits(surface) { await surface.scrollIntoViewIfNeeded(); const box = await surface.evaluate((element) => { const button = element.querySelector("button"); const title = button.querySelector("strong"); const outer = element.getBoundingClientRect(); const inner = button.getBoundingClientRect(); const text = title.getBoundingClientRect(); const style = getComputedStyle(element); return { height: outer.height, buttonHeight: inner.height, titleHeight: text.height, topSpace: text.top - outer.top - parseFloat(style.borderTopWidth), bottomSpace: outer.bottom - parseFloat(style.borderBottomWidth) - text.bottom, buttonTopSpace: text.top - inner.top, buttonBottomSpace: inner.bottom - text.bottom }; }); expect(box.titleHeight).toBeGreaterThan(0); expect(box.buttonHeight).toBeGreaterThanOrEqual(box.height - 2); for (const gap of [box.topSpace, box.bottomSpace, box.buttonTopSpace, box.buttonBottomSpace]) { expect(gap, JSON.stringify(box)).toBeGreaterThanOrEqual(-0.5); } } for (const width of [1440, 390]) { test(`dense calendar titles fit and remain editable at ${width}px`, async ({ page }, testInfo) => { await page.setViewportSize({ width, height: 900 }); await page.clock.setFixedTime(new Date("2026-09-01T12:00:00Z")); const errors = []; page.on("pageerror", (error) => errors.push(error.message)); await seedCalendars(page); const week = page.locator('[data-module-type="calendar"]').first(); const month = page.locator('[data-module-type="calendar"]').last(); await expect(week.locator(".calendar-event")).toHaveCount(3); await expect(month.locator(".calendar-month-bar")).toHaveCount(4); for (const size of ["xs", "sm", "md"]) { const surface = week.locator(`.calendar-event[data-size="${size}"]`); await expect(surface).toHaveCount(1); await expectTitleFits(surface); } for (const size of ["xs", "sm"]) { const surfaces = month.locator(`.calendar-month-bar[data-size="${size}"]`); await expect(surfaces).toHaveCount(size === "xs" ? 3 : 1); for (const surface of await surfaces.all()) await expectTitleFits(surface); } await month.screenshot({ path: testInfo.outputPath("month.png") }); await week.screenshot({ path: testInfo.outputPath("week.png") }); for (const [module, selector, title] of [ [week, ".calendar-event", "Raid 30"], [month, ".calendar-month-bar", "Event 0"] ]) { const button = module.locator(`${selector}[data-size="xs"] button`).first(); await button.click(); await expect(module.getByLabel("Titre", { exact: true })).toHaveValue(title); await module.getByRole("button", { name: "Annuler", exact: true }).click(); } expect(errors).toEqual([]); }); }