Add regression tests for the remaining psalmody Common categories

Covers common-of-an-angel (both hours, via Guardian Angels' First
Vespers/own day), common-of-a-dedication (Vespers, via its own day),
and the common-of-an-evangelist/several-women-martyrs aliases (one
date-based test via St. Mark where a real date is reachable, direct
unit tests where every carrier saint is below this override's rank
threshold or shadowed by an existing per-feast override).

Two pre-existing Vespers test dates had to move again for the same
reason as the previous session's fix: newly-correct category coverage
retroactively changed what a "clean ferial"/"own kept evening" date
actually resolves to. 2026-09-28 (anticipates St. Michael's own First
Vespers) moved to 2026-10-12; Guardian Angels' own day (Oct 2) moved to
Oct 1 (her First Vespers) once tracing resolveEveningDay showed she
doesn't keep her own Second Vespers there.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AHXJAWVAabCKX1JgmDh4Rn
This commit is contained in:
2026-08-28 21:33:14 -04:00
parent fbb3a2cfc7
commit ba4a5c70db
2 changed files with 114 additions and 8 deletions
+44
View File
@@ -1,5 +1,6 @@
import { describe, expect, it } from 'vitest';
import { resolveOrdo } from '../../src/hours';
import { getLaudsCommonOverride } from '../../src/hours/lauds-psalmody-overrides';
// Clean ferial dates, one per weekday — see data/psalter-distribution.yml
// and src/hours/lauds.ts's own generation-script provenance comments for
@@ -361,6 +362,49 @@ describe('resolveOrdo("lauds", ...)', () => {
expect(numbers).toEqual([66, 50, 63, 64, 148, 149, 150]);
});
it("uses Common-of-an-Angel's own psalmody (reusing St. Michael's own proper text) on Guardian Angels' own day", () => {
// Guardian Angels (Oct 2, Duplex Majus) has no proper text of her own
// -- live-verified (2026-08-28) that her real Lauds antiphons are St.
// Michael's own, byte-for-byte, which is exactly what this category's
// content is (see data/hours/lauds-psalmody-overrides/categories/
// common-of-an-angel.yml's own header). Psalm numbers stay the usual
// fixed Duplex-majus+ set (92, 99, 62), unlike this Common's Vespers
// psalmody, which substitutes "Psalmi Dominica" instead.
const ordo = resolveOrdo('lauds', '2026-10-02');
const numbers = ordo.parts.filter((p) => p.kind === 'psalm').map((p) => (p.kind === 'psalm' ? p.psalmNumber : undefined));
expect(numbers).toEqual([66, 92, 99, 62, 148, 149, 150]);
const secondPsalm = ordo.parts.filter((p) => p.kind === 'psalm')[1];
expect(secondPsalm?.kind === 'psalm' ? secondPsalm.antiphon?.text.la : undefined).toContain('Stetit Angelus');
});
it('aliases common-of-an-evangelist onto common-of-an-apostle for Lauds psalmody', () => {
// Every Evangelist on this calendar (St. John Apostle, St. Luke, St.
// Mark) already has their own per-feast Lauds override authored, so
// the Common-category tier can never actually surface via
// resolveOrdo/a real date for Lauds specifically (unlike Vespers, see
// vespers.test.ts's own St. Mark test) -- test the alias wiring
// directly instead. St. Mark's and St. Luke's own reference-engine
// rule files both say "ex C1a", and votive=C1a returned byte-identical
// Lauds psalmody to plain votive=C1 (2026-08-28).
const override = getLaudsCommonOverride('st-mark');
expect(override?.id).toBe('common-of-an-apostle');
expect(override?.groups.map((g) => g.psalms)).toEqual([[92], [99], [62]]);
});
it('aliases common-of-several-women-martyrs onto common-of-a-holy-woman for Lauds psalmody', () => {
// No majus+ saint on this calendar actually carries this Common yet
// (Ss. Perpetua and Felicity, the only one, are plain Duplex -- below
// this override's threshold), so this can't be exercised via
// resolveOrdo/a real date; test the alias wiring directly instead.
// Ss. Perpetua and Felicity's own reference-engine file says "vide
// C7b", and votive=C7b returned these same groups/canticle/Laudate
// antiphons as plain votive=C7 (2026-08-28) -- only the Benedictus
// antiphon differs, a separate mechanism from this psalmody table.
const override = getLaudsCommonOverride('ss-perpetua-and-felicity');
expect(override?.id).toBe('common-of-a-holy-woman');
expect(override?.groups.map((g) => g.psalms)).toEqual([[92], [99], [62]]);
});
it("resolves St. Gregory the Great's own proper chapter/hymn, not a Common fallback", () => {
// Live-verified against Divinum Officium (Monastic Tridentinum
// 1617), 2033-03-12 (clean year). See lauds-capitulum-st-gregory-