6f8f6618b9
Demote St. John Eudes (Aug 19) from Duplex to Semiduplex -- too minor a confessor to keep outranking the Assumption's octave. To make that demotion actually cede the day, raise the Assumption's octave to `wins: duplex` (same pattern already used by Pentecost's octave), so an ordinary-day tie no longer automatically favors the occurring saint. Promote St. Thomas of Canterbury (Dec 29) to Duplex so he keeps winning against the Christmas octave stack now that ordinary-day ties are no longer a given. Also add a closing-day tie-break to octave-vs-octave precedence (pickWinningOctave): when two active octaves tie in rank, the one on its own closing day now wins the label contest, ahead of the existing "more recently started" tie-break. Needed because Assumption's day 3 and St. Lawrence's own closing day (Aug 17) now tie at Duplex, and the closing day should still govern that date's label. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
120 lines
5.2 KiB
TypeScript
120 lines
5.2 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import { resolveDay } from '../../src/calendar';
|
|
|
|
// Per direct instruction: within Dec 26-30 inclusive, exactly one date is
|
|
// genuinely the Sunday within the Octave of the Nativity each year. That
|
|
// date always wins outright as Nat1-0 (christmas-octave-sunday), no rank
|
|
// check at all -- a deliberate departure from Monastic 1617 itself, which
|
|
// lets a Duplex-II-classis saint (Stephen/John/Innocents) beat the Sunday
|
|
// there (see tests/calendar/december-sanctoral.test.ts's own Dec 31/St.
|
|
// Silvester test for where that live-verified rule is still real, outside
|
|
// this window). The displaced saint isn't commemorated in place -- he
|
|
// reappears in full on Dec 30, the block's one date with no fixed saint of
|
|
// its own.
|
|
describe('applyChristmasOctaveSunday', () => {
|
|
it('Sunday on Dec 26 (St. Stephen, Duplex II. classis): Nat1-0 wins outright, Stephen not even commemorated, and reappears in full on Dec 30', () => {
|
|
const sunday = resolveDay('2021-12-26');
|
|
expect(sunday.weekday).toBe('sunday');
|
|
expect(sunday.winner).toEqual({ kind: 'temporal', id: 'christmas-octave-sunday' });
|
|
expect(sunday.commemorations.some((c) => c.kind === 'sanctoral')).toBe(false);
|
|
|
|
const dec30 = resolveDay('2021-12-30');
|
|
expect(dec30.winner).toEqual({
|
|
kind: 'sanctoral',
|
|
id: 'st-stephen-protomartyr',
|
|
name: 'St. Stephen, Protomartyr',
|
|
rank: 'duplex-2-classis',
|
|
});
|
|
// The now-redundant "Octave of St. Stephen" commemoration (which
|
|
// would otherwise have been pushed by applyOctaves, using Dec 30's
|
|
// *original* temporal winner) is dropped -- he's the day's own
|
|
// winner now, not merely commemorated alongside himself.
|
|
expect(dec30.commemorations.some((c) => c.kind === 'octave' && c.id === 'st-stephen-protomartyr')).toBe(false);
|
|
// The other, still-genuinely-separate octaves remain.
|
|
expect(dec30.commemorations.map((c) => (c.kind === 'octave' ? c.id : undefined))).toEqual([
|
|
'christmas-day',
|
|
'st-john-apostle',
|
|
'holy-innocents',
|
|
]);
|
|
});
|
|
|
|
it('Sunday on Dec 27 (St. John, Duplex II. classis): same shape', () => {
|
|
const sunday = resolveDay('2020-12-27');
|
|
expect(sunday.winner).toEqual({ kind: 'temporal', id: 'christmas-octave-sunday' });
|
|
|
|
const dec30 = resolveDay('2020-12-30');
|
|
expect(dec30.winner).toEqual({
|
|
kind: 'sanctoral',
|
|
id: 'st-john-apostle',
|
|
name: 'St. John, Apostle and Evangelist',
|
|
rank: 'duplex-2-classis',
|
|
});
|
|
expect(dec30.commemorations.some((c) => c.kind === 'octave' && c.id === 'st-john-apostle')).toBe(false);
|
|
});
|
|
|
|
it('Sunday on Dec 28 (Holy Innocents, Duplex II. classis): same shape', () => {
|
|
const sunday = resolveDay('2025-12-28');
|
|
expect(sunday.winner).toEqual({ kind: 'temporal', id: 'christmas-octave-sunday' });
|
|
|
|
const dec30 = resolveDay('2025-12-30');
|
|
expect(dec30.winner).toEqual({
|
|
kind: 'sanctoral',
|
|
id: 'holy-innocents',
|
|
name: 'The Holy Innocents, Martyrs',
|
|
rank: 'duplex-2-classis',
|
|
});
|
|
expect(dec30.commemorations.some((c) => c.kind === 'octave' && c.id === 'holy-innocents')).toBe(false);
|
|
});
|
|
|
|
it('Sunday on Dec 29 (St. Thomas Becket): still fully displaced to Dec 30, same as the Duplex-II-classis saints -- rank never matters for this rule', () => {
|
|
const sunday = resolveDay('2024-12-29');
|
|
expect(sunday.winner).toEqual({ kind: 'temporal', id: 'christmas-octave-sunday' });
|
|
|
|
const dec30 = resolveDay('2024-12-30');
|
|
expect(dec30.winner).toEqual({
|
|
kind: 'sanctoral',
|
|
id: 'st-thomas-becket',
|
|
name: 'St. Thomas of Canterbury, Bishop and Martyr',
|
|
rank: 'duplex',
|
|
});
|
|
});
|
|
|
|
it('Sunday on Dec 30 itself: nothing to displace, resolves clean', () => {
|
|
const dec30 = resolveDay('2029-12-30');
|
|
expect(dec30.weekday).toBe('sunday');
|
|
expect(dec30.winner).toEqual({ kind: 'temporal', id: 'christmas-octave-sunday' });
|
|
// All four octaves still commemorated normally -- nothing was ever
|
|
// assigned to Dec 30 itself, so there's nothing to drop.
|
|
expect(dec30.commemorations.map((c) => (c.kind === 'octave' ? c.id : undefined))).toEqual([
|
|
'christmas-day',
|
|
'st-stephen-protomartyr',
|
|
'st-john-apostle',
|
|
'holy-innocents',
|
|
]);
|
|
});
|
|
|
|
it('Dec 26-29 keep their own fixed saint outright on a year none of them is the Sunday, unaffected by this rule at all', () => {
|
|
// 2029: the Sunday is Dec 30, so Dec 26-29 each just resolve normally.
|
|
expect(resolveDay('2029-12-26').winner).toEqual({
|
|
kind: 'sanctoral',
|
|
id: 'st-stephen-protomartyr',
|
|
name: 'St. Stephen, Protomartyr',
|
|
rank: 'duplex-2-classis',
|
|
});
|
|
expect(resolveDay('2029-12-29').winner).toEqual({
|
|
kind: 'sanctoral',
|
|
id: 'st-thomas-becket',
|
|
name: 'St. Thomas of Canterbury, Bishop and Martyr',
|
|
rank: 'duplex',
|
|
});
|
|
});
|
|
|
|
it('never touches Dec 31 or Jan 1, outside its own Dec 26-30 scope', () => {
|
|
// St. Silvester (Dec 31) still wins outright via the plain
|
|
// ordinary-sunday rule even in a year Dec 31 is the Sunday -- see
|
|
// tests/calendar/december-sanctoral.test.ts for this one directly.
|
|
const dec31 = resolveDay('2023-12-31');
|
|
expect(dec31.winner.kind).toBe('sanctoral');
|
|
});
|
|
});
|