Files
arti-pack/tests/lock_spec.lua
T
unkin-agent 11ce1fed9d
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/lint Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
Save the lockfile through a temp file and a rename
An interrupted save could leave a truncated lock.json.
2026-09-08 23:32:04 +10:00

105 lines
3.1 KiB
Lua

local t = require('tests.harness')
local Lock = require('arti-pack.lock')
local spec = require('arti-pack.spec')
local function tmpdir()
local dir = vim.fn.tempname()
vim.fn.mkdir(dir, 'p')
return dir
end
local function write(path, contents)
local fd = assert(io.open(path, 'w'))
fd:write(contents)
fd:close()
end
t.describe('lock', function()
t.it('round-trips entries through the state file', function()
local path = tmpdir() .. '/nested/lock.json'
local lock = Lock.new(path)
lock:set('plenary.nvim', { tag = 'v0.1.4', opt = false })
t.truthy(lock:save())
local reloaded = Lock.new(path):load()
t.eq({ tag = 'v0.1.4', opt = false }, reloaded:get('plenary.nvim'))
end)
t.it('starts empty when the state file does not exist', function()
local lock = Lock.new(tmpdir() .. '/absent.json'):load()
t.eq({}, lock:names())
end)
t.it('starts empty when the state file is corrupt', function()
local path = tmpdir() .. '/lock.json'
write(path, 'not json at all')
t.eq({}, Lock.new(path):load():names())
end)
t.it('starts empty when the state file has no plugins table', function()
local path = tmpdir() .. '/lock.json'
write(path, '{"version":1}')
t.eq({}, Lock.new(path):load():names())
end)
t.it('leaves no temporary file beside the state file', function()
local dir = tmpdir()
local lock = Lock.new(dir .. '/lock.json')
lock:set('plenary.nvim', { tag = 'v0.1.4' })
t.truthy(lock:save())
local names = {}
for _, entry in ipairs(vim.fn.readdir(dir)) do
table.insert(names, entry)
end
t.eq({ 'lock.json' }, names)
end)
t.it('lists names in sorted order', function()
local lock = Lock.new(tmpdir() .. '/lock.json')
lock:set('zebra', { tag = 'v1' })
lock:set('alpha', { tag = 'v1' })
t.eq({ 'alpha', 'zebra' }, lock:names())
end)
t.it('drops removed entries from a saved file', function()
local path = tmpdir() .. '/lock.json'
local lock = Lock.new(path)
lock:set('gone', { tag = 'v1' })
lock:set('kept', { tag = 'v1' })
lock:remove('gone')
lock:save()
t.eq({ 'kept' }, Lock.new(path):load():names())
end)
end)
t.describe('lock.is_current', function()
local function make(entry)
local lock = Lock.new(tmpdir() .. '/lock.json')
if entry then
lock:set('repo', entry)
end
return lock
end
t.it('is false for a plugin that was never installed', function()
local s = assert(spec.parse({ 'owner/repo', tag = 'v1' }))
t.falsy(make(nil):is_current(s))
end)
t.it('is true when the tag and load style both match', function()
local s = assert(spec.parse({ 'owner/repo', tag = 'v1' }))
t.truthy(make({ tag = 'v1', opt = false }):is_current(s))
end)
t.it('is false when the tag changed', function()
local s = assert(spec.parse({ 'owner/repo', tag = 'v2' }))
t.falsy(make({ tag = 'v1', opt = false }):is_current(s))
end)
t.it('is false when the plugin moved between start and opt', function()
local s = assert(spec.parse({ 'owner/repo', tag = 'v1', opt = true }))
t.falsy(make({ tag = 'v1', opt = false }):is_current(s))
end)
end)