test(model): cover the authored plan span
Add coverage for start/end extending, snapping, never-clipping, and the empty-plan case. The bundled sample now demonstrates the keys, so its expected week range moves to the authored bounds.
This commit is contained in:
@@ -3,6 +3,12 @@
|
||||
// an overdue Feature, and a Milestone with unmet required Features.
|
||||
export const SAMPLE_PLAN = `title = "Q3 — Checkout revamp"
|
||||
|
||||
# Optional plan span: pad the plan with lead-in / trailing weeks.
|
||||
# Rule: start ≤ every Feature's start, and end ≥ every Feature's last week.
|
||||
# Omit both to auto-fit the columns to the Features and Milestones.
|
||||
start = 2026-05-25
|
||||
end = 2026-08-03
|
||||
|
||||
# A Feature: start week, Original Estimate (the immovable baseline), then any
|
||||
# Re-estimates, an optional Delivery, and an optional Learning / Status.
|
||||
# Dates are TOML date literals; any day is snapped to that week's Monday.
|
||||
|
||||
@@ -111,8 +111,8 @@ describe('bar extent relative to now', () => {
|
||||
describe('plan derivation', () => {
|
||||
it('derives a contiguous week range and places the now line', () => {
|
||||
const plan = buildPlan(parseMacroplan(SAMPLE_PLAN), TODAY)
|
||||
expect(plan.weeks[0]).toBe('2026-06-01') // earliest start
|
||||
expect(plan.weeks.at(-1)).toBe('2026-07-20') // latest marker (Payments delivery)
|
||||
expect(plan.weeks[0]).toBe('2026-05-25') // authored span start (lead-in before earliest Feature)
|
||||
expect(plan.weeks.at(-1)).toBe('2026-08-03') // authored span end (trailing past last marker)
|
||||
// contiguous, weekly
|
||||
expect(plan.weeks).toContain('2026-06-29')
|
||||
expect(plan.nowWeek).toBe('2026-06-15')
|
||||
@@ -128,6 +128,40 @@ describe('plan derivation', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('authored plan span (start / end)', () => {
|
||||
const body = '[[feature]]\nname="X"\nstart=2026-06-08\noriginal=2026-06-15\ndelivered=2026-06-15\n'
|
||||
|
||||
it('extends the range earlier to `start` and later to `end`', () => {
|
||||
const plan = buildPlan(parseMacroplan(`start = 2026-06-01\nend = 2026-06-29\n${body}`), TODAY)
|
||||
expect(plan.weeks).toEqual(weekRange('2026-06-01', '2026-06-29'))
|
||||
expect(plan.weeks[0]).toBe('2026-06-01') // before the earliest Feature week (06-08)
|
||||
expect(plan.weeks.at(-1)).toBe('2026-06-29') // after the last marker (06-15)
|
||||
})
|
||||
|
||||
it('snaps authored bounds to their Monday', () => {
|
||||
const plan = buildPlan(parseMacroplan(`start = 2026-06-03\nend = 2026-06-24\n${body}`), TODAY)
|
||||
expect(plan.weeks[0]).toBe('2026-06-01') // Wed 06-03 → Mon 06-01
|
||||
expect(plan.weeks.at(-1)).toBe('2026-06-22') // Wed 06-24 → Mon 06-22
|
||||
})
|
||||
|
||||
it('only extends — a marker outside the authored bounds is never clipped', () => {
|
||||
// end 06-08 is before the Feature's 06-15 delivery → the range still includes it
|
||||
const plan = buildPlan(parseMacroplan(`start = 2026-06-08\nend = 2026-06-08\n${body}`), TODAY)
|
||||
expect(plan.weeks[0]).toBe('2026-06-08')
|
||||
expect(plan.weeks.at(-1)).toBe('2026-06-15')
|
||||
})
|
||||
|
||||
it('renders an empty plan across the authored bounds when there are no Features', () => {
|
||||
const plan = buildPlan(parseMacroplan('start = 2026-06-01\nend = 2026-06-22\n'), TODAY)
|
||||
expect(plan.rows).toHaveLength(0)
|
||||
expect(plan.weeks).toEqual(weekRange('2026-06-01', '2026-06-22'))
|
||||
})
|
||||
|
||||
it('rejects a non-date span bound', () => {
|
||||
expect(() => parseMacroplan('start = 123\n')).toThrow(/start/)
|
||||
})
|
||||
})
|
||||
|
||||
describe('parse validation', () => {
|
||||
it('rejects a feature missing its Original Estimate', () => {
|
||||
expect(() => parseMacroplan('[[feature]]\nname = "A"\nstart = 2026-06-01\n')).toThrow(
|
||||
|
||||
Reference in New Issue
Block a user