Milestone v1.0: FamilySync MVP #1

Merged
luckberg merged 376 commits from gsd/v1.0-milestone into main 2026-06-10 17:39:19 -04:00
Showing only changes of commit 16cdbf3d7c - Show all commits
+62 -1
View File
@@ -13,7 +13,7 @@
*/
import { describe, it, expect } from 'vitest'
import { serializeEventDateTime, localWallClockToUtcIso } from './eventDateTime.js'
import { serializeEventDateTime, localWallClockToUtcIso, computeNewTimedEnd, computeNewAllDayEnd } from './eventDateTime.js'
describe('serializeEventDateTime (BUG A — write-path TZ)', () => {
it('serializes a timed start to a UTC instant (ends in Z)', () => {
@@ -51,3 +51,64 @@ describe('serializeEventDateTime (BUG A — write-path TZ)', () => {
expect(new Date(iso).getHours()).toBe(9)
})
})
describe('computeNewTimedEnd (D-04 — end-tracking)', () => {
it('preserves a 1-hour timed delta when start moves forward', () => {
// Old: 2026-06-11 09:00 → 10:00 (1h duration)
// New start: 2026-06-11 11:00 → new end should be 12:00
const result = computeNewTimedEnd(
'2026-06-11', '11:00',
'2026-06-11', '09:00',
'2026-06-11', '10:00',
)
expect(result.endDate).toBe('2026-06-11')
expect(result.endTime).toBe('12:00')
})
it('preserves a multi-day timed delta (26h) when start moves', () => {
// Old: 2026-06-11 08:00 → 2026-06-12 10:00 (26h duration)
// New start: 2026-06-13 08:00 → new end should be 2026-06-14 10:00
const result = computeNewTimedEnd(
'2026-06-13', '08:00',
'2026-06-11', '08:00',
'2026-06-12', '10:00',
)
expect(result.endDate).toBe('2026-06-14')
expect(result.endTime).toBe('10:00')
})
it('floors to 1h when old end was already behind old start', () => {
// Old end (10:00) <= old start (11:00) — stale/invalid state
// New start: 2026-06-11 14:00 → new end should snap to +1h = 15:00
const result = computeNewTimedEnd(
'2026-06-11', '14:00',
'2026-06-11', '11:00',
'2026-06-11', '10:00',
)
expect(result.endDate).toBe('2026-06-11')
expect(result.endTime).toBe('15:00')
})
})
describe('computeNewAllDayEnd (D-04 — all-day end-tracking)', () => {
it('preserves a 0-day span (single-day all-day event)', () => {
// Old: 2026-06-11 → 2026-06-11 (0-day span, single day)
// New start: 2026-06-15 → new end should be 2026-06-15
const result = computeNewAllDayEnd('2026-06-15', '2026-06-11', '2026-06-11')
expect(result).toBe('2026-06-15')
})
it('preserves a 3-day span when start moves', () => {
// Old: 2026-06-11 → 2026-06-14 (3-day span)
// New start: 2026-06-20 → new end should be 2026-06-23
const result = computeNewAllDayEnd('2026-06-20', '2026-06-11', '2026-06-14')
expect(result).toBe('2026-06-23')
})
it('floors to same day when old end was already behind old start', () => {
// Old end (2026-06-10) < old start (2026-06-11) — stale/invalid state
// New start: 2026-06-15 → new end should snap to same day 2026-06-15
const result = computeNewAllDayEnd('2026-06-15', '2026-06-11', '2026-06-10')
expect(result).toBe('2026-06-15')
})
})