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:
@@ -12,12 +12,12 @@
|
||||
* They will turn GREEN in Plan 03-02 when the implementation is added.
|
||||
*/
|
||||
|
||||
import { describe, it, expect } from 'vitest'
|
||||
import { describe, it, expect } from 'vitest';
|
||||
|
||||
// This import fails (RED) — broker/vevent.ts does not exist yet.
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore intentional RED import
|
||||
import { buildVeventString } from '../../src/broker/vevent.js'
|
||||
import { buildVeventString } from '../../src/broker/vevent.js';
|
||||
|
||||
describe('buildVeventString', () => {
|
||||
it('produces a VCALENDAR string containing a VEVENT for a timed event', () => {
|
||||
@@ -26,16 +26,16 @@ describe('buildVeventString', () => {
|
||||
allDay: false,
|
||||
dtstart: new Date('2026-06-10T09:00:00Z'),
|
||||
dtend: new Date('2026-06-10T09:30:00Z'),
|
||||
})
|
||||
});
|
||||
|
||||
expect(result).toHaveProperty('uid')
|
||||
expect(result).toHaveProperty('icsString')
|
||||
expect(result.icsString).toContain('BEGIN:VCALENDAR')
|
||||
expect(result.icsString).toContain('BEGIN:VEVENT')
|
||||
expect(result.icsString).toContain('SUMMARY:Team standup')
|
||||
expect(result.icsString).toContain('END:VEVENT')
|
||||
expect(result.icsString).toContain('END:VCALENDAR')
|
||||
})
|
||||
expect(result).toHaveProperty('uid');
|
||||
expect(result).toHaveProperty('icsString');
|
||||
expect(result.icsString).toContain('BEGIN:VCALENDAR');
|
||||
expect(result.icsString).toContain('BEGIN:VEVENT');
|
||||
expect(result.icsString).toContain('SUMMARY:Team standup');
|
||||
expect(result.icsString).toContain('END:VEVENT');
|
||||
expect(result.icsString).toContain('END:VCALENDAR');
|
||||
});
|
||||
|
||||
it('produces DTSTART with Z suffix (UTC) for a timed event — not TZID', () => {
|
||||
const result = buildVeventString({
|
||||
@@ -43,12 +43,12 @@ describe('buildVeventString', () => {
|
||||
allDay: false,
|
||||
dtstart: new Date('2026-06-10T14:00:00Z'),
|
||||
dtend: new Date('2026-06-10T15:00:00Z'),
|
||||
})
|
||||
});
|
||||
|
||||
// D-13 timed contract: DATETIME in UTC → 'Z' suffix, no TZID
|
||||
expect(result.icsString).toMatch(/DTSTART:\d{8}T\d{6}Z/)
|
||||
expect(result.icsString).not.toMatch(/DTSTART;TZID=/)
|
||||
})
|
||||
expect(result.icsString).toMatch(/DTSTART:\d{8}T\d{6}Z/);
|
||||
expect(result.icsString).not.toMatch(/DTSTART;TZID=/);
|
||||
});
|
||||
|
||||
it('produces DTSTART as DATE (no time, no TZID) for an all-day event', () => {
|
||||
const result = buildVeventString({
|
||||
@@ -56,16 +56,16 @@ describe('buildVeventString', () => {
|
||||
allDay: true,
|
||||
dtstart: '2026-06-15',
|
||||
dtend: '2026-06-16',
|
||||
})
|
||||
});
|
||||
|
||||
// D-13 all-day contract: VALUE=DATE, no time component, no TZID
|
||||
// ical.js represents DATE as DTSTART;VALUE=DATE:YYYYMMDD
|
||||
expect(result.icsString).toMatch(/DTSTART[^:]*:20260615/)
|
||||
expect(result.icsString).toMatch(/DTSTART[^:]*:20260615/);
|
||||
// Must NOT contain a time component (no 'T' after the date)
|
||||
expect(result.icsString).not.toMatch(/DTSTART[^:]*:20260615T/)
|
||||
expect(result.icsString).not.toMatch(/DTSTART[^:]*:20260615T/);
|
||||
// Must NOT contain TZID on the DTSTART property
|
||||
expect(result.icsString).not.toMatch(/DTSTART;TZID=/)
|
||||
})
|
||||
expect(result.icsString).not.toMatch(/DTSTART;TZID=/);
|
||||
});
|
||||
|
||||
it('includes an RRULE property when rruleString is provided (CAL-07)', () => {
|
||||
const result = buildVeventString({
|
||||
@@ -74,10 +74,10 @@ describe('buildVeventString', () => {
|
||||
dtstart: new Date('2026-06-09T10:00:00Z'),
|
||||
dtend: new Date('2026-06-09T11:00:00Z'),
|
||||
rruleString: 'FREQ=WEEKLY;BYDAY=MO',
|
||||
})
|
||||
});
|
||||
|
||||
expect(result.icsString).toContain('RRULE:FREQ=WEEKLY;BYDAY=MO')
|
||||
})
|
||||
expect(result.icsString).toContain('RRULE:FREQ=WEEKLY;BYDAY=MO');
|
||||
});
|
||||
|
||||
it('does NOT include RRULE when rruleString is omitted', () => {
|
||||
const result = buildVeventString({
|
||||
@@ -85,10 +85,10 @@ describe('buildVeventString', () => {
|
||||
allDay: false,
|
||||
dtstart: new Date('2026-06-10T12:00:00Z'),
|
||||
dtend: new Date('2026-06-10T13:00:00Z'),
|
||||
})
|
||||
});
|
||||
|
||||
expect(result.icsString).not.toContain('RRULE:')
|
||||
})
|
||||
expect(result.icsString).not.toContain('RRULE:');
|
||||
});
|
||||
|
||||
// D-06: RRULE COUNT — verified ical.js 2.2.1 output
|
||||
it('serializes COUNT in RRULE for a timed event (D-06)', () => {
|
||||
@@ -98,9 +98,9 @@ describe('buildVeventString', () => {
|
||||
dtstart: new Date('2026-06-10T09:00:00Z'),
|
||||
dtend: new Date('2026-06-10T10:00:00Z'),
|
||||
rruleString: 'FREQ=WEEKLY;COUNT=5',
|
||||
})
|
||||
expect(result.icsString).toContain('RRULE:FREQ=WEEKLY;COUNT=5')
|
||||
})
|
||||
});
|
||||
expect(result.icsString).toContain('RRULE:FREQ=WEEKLY;COUNT=5');
|
||||
});
|
||||
|
||||
// D-06: RRULE UNTIL DATE form — all-day event must NOT contain T235959Z
|
||||
it('serializes UNTIL as DATE form for all-day events (D-06)', () => {
|
||||
@@ -110,10 +110,10 @@ describe('buildVeventString', () => {
|
||||
dtstart: '2026-06-10',
|
||||
dtend: '2026-06-11',
|
||||
rruleString: 'FREQ=DAILY;UNTIL=20260630',
|
||||
})
|
||||
expect(result.icsString).toContain('RRULE:FREQ=DAILY;UNTIL=20260630')
|
||||
expect(result.icsString).not.toContain('T235959Z')
|
||||
})
|
||||
});
|
||||
expect(result.icsString).toContain('RRULE:FREQ=DAILY;UNTIL=20260630');
|
||||
expect(result.icsString).not.toContain('T235959Z');
|
||||
});
|
||||
|
||||
// D-06: RRULE UNTIL DATETIME UTC form — timed event
|
||||
it('serializes UNTIL as DATETIME UTC form for timed events (D-06)', () => {
|
||||
@@ -123,23 +123,23 @@ describe('buildVeventString', () => {
|
||||
dtstart: new Date('2026-06-10T09:00:00Z'),
|
||||
dtend: new Date('2026-06-10T10:00:00Z'),
|
||||
rruleString: 'FREQ=WEEKLY;UNTIL=20260630T235959Z',
|
||||
})
|
||||
expect(result.icsString).toContain('RRULE:FREQ=WEEKLY;UNTIL=20260630T235959Z')
|
||||
})
|
||||
});
|
||||
expect(result.icsString).toContain('RRULE:FREQ=WEEKLY;UNTIL=20260630T235959Z');
|
||||
});
|
||||
|
||||
it('uses the provided uid when given', () => {
|
||||
const uid = 'custom-uid-001@familysync'
|
||||
const uid = 'custom-uid-001@familysync';
|
||||
const result = buildVeventString({
|
||||
uid,
|
||||
summary: 'Test event',
|
||||
allDay: false,
|
||||
dtstart: new Date('2026-06-10T09:00:00Z'),
|
||||
dtend: new Date('2026-06-10T10:00:00Z'),
|
||||
})
|
||||
});
|
||||
|
||||
expect(result.uid).toBe(uid)
|
||||
expect(result.icsString).toContain(`UID:${uid}`)
|
||||
})
|
||||
expect(result.uid).toBe(uid);
|
||||
expect(result.icsString).toContain(`UID:${uid}`);
|
||||
});
|
||||
|
||||
it('generates a uid when none is provided', () => {
|
||||
const result = buildVeventString({
|
||||
@@ -147,12 +147,12 @@ describe('buildVeventString', () => {
|
||||
allDay: false,
|
||||
dtstart: new Date('2026-06-10T09:00:00Z'),
|
||||
dtend: new Date('2026-06-10T10:00:00Z'),
|
||||
})
|
||||
});
|
||||
|
||||
expect(result.uid).toBeTruthy()
|
||||
expect(result.uid.length).toBeGreaterThan(10)
|
||||
})
|
||||
})
|
||||
expect(result.uid).toBeTruthy();
|
||||
expect(result.uid.length).toBeGreaterThan(10);
|
||||
});
|
||||
});
|
||||
|
||||
describe('buildVeventString — D-13 form-parsed contract', () => {
|
||||
it('timed event: produces BEGIN:VCALENDAR, SUMMARY, UID, timed DTSTART (Z suffix), and DTEND', () => {
|
||||
@@ -163,16 +163,16 @@ describe('buildVeventString — D-13 form-parsed contract', () => {
|
||||
allDay: false,
|
||||
dtstart: new Date('2026-06-10T12:00:00Z'),
|
||||
dtend: new Date('2026-06-10T13:00:00Z'),
|
||||
})
|
||||
});
|
||||
|
||||
expect(result.icsString).toContain('BEGIN:VCALENDAR')
|
||||
expect(result.icsString).toContain('SUMMARY:Lunch')
|
||||
expect(result.icsString).toContain('UID:u1@familysync')
|
||||
expect(result.icsString).toContain('BEGIN:VCALENDAR');
|
||||
expect(result.icsString).toContain('SUMMARY:Lunch');
|
||||
expect(result.icsString).toContain('UID:u1@familysync');
|
||||
// D-13 timed contract: DATETIME in UTC → 'Z' suffix, no TZID
|
||||
expect(result.icsString).toMatch(/DTSTART:\d{8}T\d{6}Z/)
|
||||
expect(result.icsString).toMatch(/DTSTART:\d{8}T\d{6}Z/);
|
||||
// DTEND must be present
|
||||
expect(result.icsString).toMatch(/DTEND:\d{8}T\d{6}Z/)
|
||||
})
|
||||
expect(result.icsString).toMatch(/DTEND:\d{8}T\d{6}Z/);
|
||||
});
|
||||
|
||||
it('single-day all-day event: DTSTART is DATE format and DTEND = DTSTART + 1 day (RFC-5545 exclusive end, WR-04)', () => {
|
||||
// Simulates a single-day all-day event where start and end are the same calendar day.
|
||||
@@ -182,17 +182,17 @@ describe('buildVeventString — D-13 form-parsed contract', () => {
|
||||
allDay: true,
|
||||
dtstart: '2026-06-10',
|
||||
dtend: '2026-06-10',
|
||||
})
|
||||
});
|
||||
|
||||
// DTSTART must be DATE format (no time component, no TZID) — D-13 all-day contract
|
||||
expect(result.icsString).toMatch(/DTSTART[^:]*:20260610/)
|
||||
expect(result.icsString).not.toMatch(/DTSTART[^:]*:20260610T/)
|
||||
expect(result.icsString).toMatch(/DTSTART[^:]*:20260610/);
|
||||
expect(result.icsString).not.toMatch(/DTSTART[^:]*:20260610T/);
|
||||
|
||||
// WR-04: DTEND must be DTSTART + 1 day (RFC-5545 exclusive end)
|
||||
expect(result.icsString).toMatch(/DTEND[^:]*:20260611/)
|
||||
expect(result.icsString).toMatch(/DTEND[^:]*:20260611/);
|
||||
// DTEND date string must NOT equal DTSTART date string (owning-boundary assertion)
|
||||
const dtendMatch = result.icsString.match(/DTEND[^:]*:(\d{8})/)
|
||||
const dtstartMatch = result.icsString.match(/DTSTART[^:]*:(\d{8})/)
|
||||
expect(dtendMatch?.[1]).not.toBe(dtstartMatch?.[1])
|
||||
})
|
||||
})
|
||||
const dtendMatch = result.icsString.match(/DTEND[^:]*:(\d{8})/);
|
||||
const dtstartMatch = result.icsString.match(/DTSTART[^:]*:(\d{8})/);
|
||||
expect(dtendMatch?.[1]).not.toBe(dtstartMatch?.[1]);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user