oficina / calendar Public

Clone
git clone https://amadan.net/oficina/calendar

Plain git — no account needed to clone.

Download

Download this file

1// week.mjs — B8 and B9 measured in a real browser.
2//
3// Driven by TestWeekAndAllDayFormInARealBrowser, which seeds the week
4// of 5 October 2026 with an all-day note and two timed events on the
5// Wednesday, plus an all-day event whose edit URL it passes in.
6//
7// 1. Every timed column starts at the same height, whatever sits in
8// the all-day row above it.
9// 2. The 10:00 chip is drawn at the 10:00 line, not an hour down.
10// 3. A 30-minute chip's title is painted inside the chip.
11// 4. An all-day event's edit form holds its dates — checked through
12// input.value, which is what a submit sends.
13import { chromium } from 'playwright';
14
15const [origin, cookieName, cookieValue, editPath] = process.argv.slice(2);
16if (!origin || !cookieName || !cookieValue || !editPath) {
17 console.error('usage: week.mjs <origin> <cookieName> <cookieValue> <editPath>');
18 process.exit(2);
19}
20
21const failures = [];
22function check(ok, what) {
23 if (ok) { console.log('ok: ' + what); return; }
24 failures.push(what);
25 console.error('FAIL: ' + what);
26}
27
28const browser = await chromium.launch();
29const ctx = await browser.newContext({ viewport: { width: 1440, height: 900 } });
30await ctx.addCookies([{ name: cookieName, value: cookieValue, url: origin, httpOnly: true }]);
31const page = await ctx.newPage();
32
33// ── 1–3. The week ─────────────────────────────────────────────────────
34await page.goto(origin + '/week/2026-10-07', { waitUntil: 'networkidle' });
35const geo = await page.evaluate(() => {
36 const cols = [...document.querySelectorAll('[cal-column]')].map((c) => c.getBoundingClientRect().top);
37 const hourPx = document.querySelector('[cal-hour]').getBoundingClientRect().height;
38 const chip = (title) => {
39 const t = [...document.querySelectorAll('[cal-placed] [cal-chip-title]')].find((s) => s.textContent.includes(title));
40 if (!t) return null;
41 const chipBox = t.closest('[cal-chip]').getBoundingClientRect();
42 const titleBox = t.getBoundingClientRect();
43 const colTop = t.closest('[cal-column]').getBoundingClientRect().top;
44 return { chipTop: chipBox.top, chipBottom: chipBox.bottom, titleTop: titleBox.top, titleBottom: titleBox.bottom, titleWidth: titleBox.width, colTop };
45 };
46 // Where the 10:00 LABEL draws its line: the label box minus the
47 // translate that lifts it onto the rule it names.
48 const label = document.querySelectorAll('[cal-hour]')[10];
49 const lift = new DOMMatrix(getComputedStyle(label).transform).m42;
50 const tenLine = label.getBoundingClientRect().top - lift;
51 return { cols, hourPx, tenLine, focus: chip('Focus time'), quick: chip('Quick sync') };
52});
53console.log(JSON.stringify(geo));
54check(geo.cols.length === 7, `seven timed columns (got ${geo.cols.length})`);
55check(geo.cols.every((top) => Math.abs(top - geo.cols[0]) < 0.5), `every timed column starts at the same height (${geo.cols.join(', ')})`);
56check(geo.focus && Math.abs(geo.focus.chipTop - geo.tenLine) < 2,
57 `the 10:00 chip is beside the 10:00 label (chip ${geo.focus?.chipTop}, label line ${geo.tenLine})`);
58check(geo.quick && geo.quick.titleWidth > 8 && geo.quick.titleBottom - geo.quick.titleTop >= 12 &&
59 geo.quick.titleTop >= geo.quick.chipTop - 0.5 && geo.quick.titleBottom <= geo.quick.chipBottom + 0.5,
60 `the 30-minute chip paints its title inside itself (${JSON.stringify(geo.quick)})`);
61await page.screenshot({ path: '/tmp/calendar-week-allday.png', fullPage: false });
62
63// ── 4. The all-day edit form, with and without script ─────────────────
64for (const js of [true, false]) {
65 const c = await browser.newContext({ javaScriptEnabled: js });
66 await c.addCookies([{ name: cookieName, value: cookieValue, url: origin, httpOnly: true }]);
67 const p = await c.newPage();
68 await p.goto(origin + editPath, { waitUntil: 'networkidle' });
69 const values = await p.evaluate(() => ({
70 start: document.querySelector('input[name="start"]').value,
71 end: document.querySelector('input[name="end"]').value,
72 }));
73 check(values.start === '2026-10-12' && values.end === '2026-10-14',
74 `all-day edit form holds its dates, js=${js} (${JSON.stringify(values)})`);
75 await c.close();
76}
77
78await browser.close();
79if (failures.length) {
80 console.error(`${failures.length} check(s) failed`);
81 process.exit(1);
82}
83console.log('all week/all-day checks passed');
84