test: add top-priority missing test coverage
Problem: several critical code paths had zero test coverage — parse.resolve_date (relative date resolution), store.snapshot (foundation of the undo stack), and the diff.apply invariant that unchanged tasks do not get their modified timestamp bumped. The diff.apply due/priority clearing paths were also untested. Solution: add six targeted test blocks across parse_spec, store_spec, and diff_spec: resolve_date happy/failure paths, parse.body with relative due tokens, snapshot copy-semantics and deleted-task exclusion, diff unchanged-modified invariant, due cleared on removal, priority cleared on ! removal.
This commit is contained in:
parent
586a8e81e3
commit
aae6989a19
3 changed files with 134 additions and 0 deletions
|
|
@ -135,5 +135,51 @@ describe('diff', function()
|
|||
local task = store.get(1)
|
||||
assert.are.equal('Work', task.category)
|
||||
end)
|
||||
|
||||
it('does not update modified when task is unchanged', function()
|
||||
store.add({ description = 'Stable task', category = 'Inbox' })
|
||||
store.save()
|
||||
local lines = {
|
||||
'Inbox',
|
||||
'/1/ Stable task',
|
||||
}
|
||||
diff.apply(lines)
|
||||
store.unload()
|
||||
store.load()
|
||||
local modified_after_first = store.get(1).modified
|
||||
diff.apply(lines)
|
||||
store.unload()
|
||||
store.load()
|
||||
local task = store.get(1)
|
||||
assert.are.equal(modified_after_first, task.modified)
|
||||
end)
|
||||
|
||||
it('clears due when removed from buffer line', function()
|
||||
store.add({ description = 'Pay bill', due = '2026-03-15' })
|
||||
store.save()
|
||||
local lines = {
|
||||
'Inbox',
|
||||
'/1/ Pay bill',
|
||||
}
|
||||
diff.apply(lines)
|
||||
store.unload()
|
||||
store.load()
|
||||
local task = store.get(1)
|
||||
assert.is_nil(task.due)
|
||||
end)
|
||||
|
||||
it('clears priority when ! is removed from buffer line', function()
|
||||
store.add({ description = 'Task name', priority = 1 })
|
||||
store.save()
|
||||
local lines = {
|
||||
'Inbox',
|
||||
'/1/ Task name',
|
||||
}
|
||||
diff.apply(lines)
|
||||
store.unload()
|
||||
store.load()
|
||||
local task = store.get(1)
|
||||
assert.are.equal(0, task.priority)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
|
|
|||
|
|
@ -87,6 +87,67 @@ describe('parse', function()
|
|||
assert.are.equal('Buy milk due:2026-03-15', desc)
|
||||
assert.is_nil(meta.due)
|
||||
end)
|
||||
|
||||
it('resolves due:today to today date', function()
|
||||
local desc, meta = parse.body('Buy milk due:today')
|
||||
assert.are.equal('Buy milk', desc)
|
||||
assert.are.equal(os.date('%Y-%m-%d'), meta.due)
|
||||
end)
|
||||
|
||||
it('resolves due:+2d to today plus 2 days', function()
|
||||
local today = os.date('*t') --[[@as osdate]]
|
||||
local expected = os.date('%Y-%m-%d', os.time({ year = today.year, month = today.month, day = today.day + 2 }))
|
||||
local desc, meta = parse.body('Task due:+2d')
|
||||
assert.are.equal('Task', desc)
|
||||
assert.are.equal(expected, meta.due)
|
||||
end)
|
||||
|
||||
it('leaves unresolvable due token in description', function()
|
||||
local desc, meta = parse.body('Task due:garbage')
|
||||
assert.is_nil(meta.due)
|
||||
assert.truthy(desc:find('due:garbage', 1, true))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('parse.resolve_date', function()
|
||||
it("returns today's date for 'today'", function()
|
||||
local result = parse.resolve_date('today')
|
||||
assert.are.equal(os.date('%Y-%m-%d'), result)
|
||||
end)
|
||||
|
||||
it("returns tomorrow's date for 'tomorrow'", function()
|
||||
local expected = os.date('%Y-%m-%d', os.time() + 86400)
|
||||
local result = parse.resolve_date('tomorrow')
|
||||
assert.are.equal(expected, result)
|
||||
end)
|
||||
|
||||
it("returns today + 3 days for '+3d'", function()
|
||||
local today = os.date('*t') --[[@as osdate]]
|
||||
local expected = os.date('%Y-%m-%d', os.time({ year = today.year, month = today.month, day = today.day + 3 }))
|
||||
local result = parse.resolve_date('+3d')
|
||||
assert.are.equal(expected, result)
|
||||
end)
|
||||
|
||||
it("returns today for '+0d'", function()
|
||||
local result = parse.resolve_date('+0d')
|
||||
assert.are.equal(os.date('%Y-%m-%d'), result)
|
||||
end)
|
||||
|
||||
it("returns a future Monday (or today) for 'mon'", function()
|
||||
local result = parse.resolve_date('mon')
|
||||
assert.is_not_nil(result)
|
||||
assert.truthy(result:match('^%d%d%d%d%-%d%d%-%d%d$'))
|
||||
end)
|
||||
|
||||
it("returns nil for garbage input", function()
|
||||
local result = parse.resolve_date('notadate')
|
||||
assert.is_nil(result)
|
||||
end)
|
||||
|
||||
it("returns nil for empty string", function()
|
||||
local result = parse.resolve_date('')
|
||||
assert.is_nil(result)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('command_add', function()
|
||||
|
|
|
|||
|
|
@ -186,4 +186,31 @@ describe('store', function()
|
|||
assert.are.equal('Active', active[1].description)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('snapshot', function()
|
||||
it('returns a table of tasks', function()
|
||||
store.load()
|
||||
store.add({ description = 'Snap one' })
|
||||
store.add({ description = 'Snap two' })
|
||||
local snap = store.snapshot()
|
||||
assert.are.equal(2, #snap)
|
||||
end)
|
||||
|
||||
it('returns a copy that does not affect the store', function()
|
||||
store.load()
|
||||
local t = store.add({ description = 'Original' })
|
||||
local snap = store.snapshot()
|
||||
snap[1].description = 'Mutated'
|
||||
local live = store.get(t.id)
|
||||
assert.are.equal('Original', live.description)
|
||||
end)
|
||||
|
||||
it('excludes deleted tasks', function()
|
||||
store.load()
|
||||
local t = store.add({ description = 'Will be deleted' })
|
||||
store.delete(t.id)
|
||||
local snap = store.snapshot()
|
||||
assert.are.equal(0, #snap)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue