Luigit
repositories / dotfiles

dotfiles

bugabingas dorkfiles

owned by admin

neovim/tests/bugabinga/cycle_spec.lua

Raw
require 'bugabinga.cycle'

describe('bugabinga.cycle', function()
	local function create_buffer(name)
		vim.api.nvim_command('new ' .. name)
		local bufnr = vim.api.nvim_get_current_buf()
		return bufnr
	end

	before_each(function()
		package.loaded['bugabinga.cycle'] = nil
	end)

	after_each(function()
		BugabingaCycle.cancel()
		for _, bufnr in ipairs(vim.api.nvim_list_bufs()) do
			if vim.api.nvim_buf_is_valid(bufnr) then
				pcall(vim.api.nvim_buf_delete, bufnr, { force = true })
			end
		end
		if BugabingaCycle.history then
			for i = #BugabingaCycle.history, 1, -1 do
				BugabingaCycle.history[i] = nil
			end
		end
	end)

	describe('history tracking', function()
		it('should track buffers on BufEnter', function()
			local bufnr1 = create_buffer('test1.lua')
			vim.api.nvim_set_current_buf(bufnr1)
			local bufnr2 = create_buffer('test2.lua')
			vim.api.nvim_set_current_buf(bufnr2)
			local bufnr3 = create_buffer('test3.lua')
			vim.api.nvim_set_current_buf(bufnr3)
			assert.is_true(#BugabingaCycle.history >= 1)
		end)

		it('should skip unnamed buffers', function()
			vim.api.nvim_command('enew')
			local bufnr = vim.api.nvim_get_current_buf()
			vim.api.nvim_set_current_buf(bufnr)
			for _, b in ipairs(BugabingaCycle.history) do
				assert.are_not_equal(bufnr, b)
			end
		end)

		it('should skip unlisted buffers', function()
			vim.api.nvim_command('new')
			local bufnr = vim.api.nvim_get_current_buf()
			vim.bo[bufnr].buflisted = false
			vim.api.nvim_set_current_buf(bufnr)
			for _, b in ipairs(BugabingaCycle.history) do
				assert.are_not_equal(bufnr, b)
			end
		end)

		it('should move revisited buffer to end of history', function()
			local bufnr1 = create_buffer('mruseq1.lua')
			vim.api.nvim_set_current_buf(bufnr1)
			local bufnr2 = create_buffer('mruseq2.lua')
			vim.api.nvim_set_current_buf(bufnr2)
			local bufnr3 = create_buffer('mruseq3.lua')
			vim.api.nvim_set_current_buf(bufnr3)
			local last = BugabingaCycle.history[#BugabingaCycle.history]
			assert.equal(bufnr3, last)
		end)

		it('should remove deleted buffers from history', function()
			local bufnr1 = create_buffer('del1.lua')
			vim.api.nvim_set_current_buf(bufnr1)
			local bufnr2 = create_buffer('del2.lua')
			vim.api.nvim_set_current_buf(bufnr2)
			local bufnr3 = create_buffer('del3.lua')
			vim.api.nvim_set_current_buf(bufnr3)
			vim.api.nvim_buf_delete(bufnr2, { force = true })
			for _, b in ipairs(BugabingaCycle.history) do
				assert.are_not_equal(bufnr2, b)
			end
		end)
	end)

	describe('cycling', function()
		it('should open popup with buffer list when multiple buffers exist', function()
			local bufnr1 = create_buffer('cycle1.lua')
			vim.api.nvim_set_current_buf(bufnr1)
			local bufnr2 = create_buffer('cycle2.lua')
			vim.api.nvim_set_current_buf(bufnr2)
			local win_count_before = #vim.api.nvim_list_wins()
			BugabingaCycle.cycle(1)
			local win_count_after = #vim.api.nvim_list_wins()
			assert.is_true(win_count_after > win_count_before)
			BugabingaCycle.cancel()
		end)

		it('should open popup with current buffer included in list', function()
			local bufnr1 = create_buffer('single1.lua')
			vim.api.nvim_set_current_buf(bufnr1)
			local win_count_before = #vim.api.nvim_list_wins()
			BugabingaCycle.cycle(1)
			local win_count_after = #vim.api.nvim_list_wins()
			assert(win_count_after > win_count_before, 'popup should open')
		end)

		it('should cycle forward through buffer list', function()
			local bufnr1 = create_buffer('fwd1.lua')
			vim.api.nvim_set_current_buf(bufnr1)
			local bufnr2 = create_buffer('fwd2.lua')
			vim.api.nvim_set_current_buf(bufnr2)
			local bufnr3 = create_buffer('fwd3.lua')
			vim.api.nvim_set_current_buf(bufnr3)
			BugabingaCycle.cycle(1)
			assert.is_not_nil(BugabingaCycle.cancel)
			BugabingaCycle.cancel()
		end)

		it('should not crash when cycling second time with multiple buffers', function()
			local bufnr1 = create_buffer('multifwd1.lua')
			vim.api.nvim_set_current_buf(bufnr1)
			local bufnr2 = create_buffer('multifwd2.lua')
			vim.api.nvim_set_current_buf(bufnr2)
			local bufnr3 = create_buffer('multifwd3.lua')
			vim.api.nvim_set_current_buf(bufnr3)
			BugabingaCycle.cycle(1)
			local ok, err = pcall(BugabingaCycle.cycle, 1)
			assert(ok, 'second cycle should not error: ' .. tostring(err))
			BugabingaCycle.cancel()
		end)

		it('should cycle backward through buffer list', function()
			local bufnr1 = create_buffer('bwd1.lua')
			vim.api.nvim_set_current_buf(bufnr1)
			local bufnr2 = create_buffer('bwd2.lua')
			vim.api.nvim_set_current_buf(bufnr2)
			BugabingaCycle.cycle(-1)
			assert.is_not_nil(BugabingaCycle.cancel)
			BugabingaCycle.cancel()
		end)

		it('should wrap from first to last when cycling forward', function()
			local bufnr1 = create_buffer('wrap1.lua')
			vim.api.nvim_set_current_buf(bufnr1)
			local bufnr2 = create_buffer('wrap2.lua')
			vim.api.nvim_set_current_buf(bufnr2)
			BugabingaCycle.cycle(1)
			BugabingaCycle.cancel()
		end)
	end)

	describe('cancel', function()
		it('should restore original buffer after cancel', function()
			local bufnr1 = create_buffer('rest1.lua')
			vim.api.nvim_set_current_buf(bufnr1)
			local bufnr2 = create_buffer('rest2.lua')
			vim.api.nvim_set_current_buf(bufnr2)
			local original = vim.api.nvim_get_current_buf()
			BugabingaCycle.cycle(1)
			BugabingaCycle.cancel()
			local restored = vim.api.nvim_get_current_buf()
			assert.equal(original, restored)
		end)

		it('should not crash when timer is already nil', function()
			local bufnr1 = create_buffer('nocancel1.lua')
			vim.api.nvim_set_current_buf(bufnr1)
			local bufnr2 = create_buffer('nocancel2.lua')
			vim.api.nvim_set_current_buf(bufnr2)
			BugabingaCycle.cancel()
		end)

		it('should stop and clear timer on cancel', function()
			local bufnr1 = create_buffer('timerclear1.lua')
			vim.api.nvim_set_current_buf(bufnr1)
			local bufnr2 = create_buffer('timerclear2.lua')
			vim.api.nvim_set_current_buf(bufnr2)
			BugabingaCycle.cycle(1)
			BugabingaCycle.cancel()
		end)
	end)

	describe('commit_switch', function()
		it('should switch to highlighted buffer after timer fires', function()
			local bufnr1 = create_buffer('commit1.lua')
			vim.api.nvim_set_current_buf(bufnr1)
			local bufnr2 = create_buffer('commit2.lua')
			vim.api.nvim_set_current_buf(bufnr2)
			BugabingaCycle.cycle(1)
			vim.wait(1100)
			local current = vim.api.nvim_get_current_buf()
			assert.equal(bufnr1, current)
		end)

		it('should not switch when no popup was opened', function()
			vim.api.nvim_command('enew')
			local bufnr = vim.api.nvim_get_current_buf()
			vim.api.nvim_set_current_buf(bufnr)
			local original = vim.api.nvim_get_current_buf()
			BugabingaCycle.cycle(1)
			local current = vim.api.nvim_get_current_buf()
			assert.equal(original, current)
		end)
	end)

	describe('rendering', function()
		it('shorten_path should return basename for paths outside cwd', function()
			local short = '/a/b/c.lua'
			local result = BugabingaCycle.shorten_path(short, 50)
			assert.equal('c.lua', result)
		end)

		it('shorten_path should keep full relative path when it fits', function()
			local path = '/home/user/project/file.lua'
			local result = BugabingaCycle.shorten_path(path, 30)
			assert(#result <= 30, 'should fit: ' .. result .. ' (' .. #result .. ')')
			assert(result:find('file.lua', 1, true) ~= nil, 'basename must be present: ' .. result)
		end)

		it('shorten_path should return basename for paths outside cwd', function()
			local long = '/home/user/very/deep/nested/path/to/file.lua'
			local result = BugabingaCycle.shorten_path(long, 25)
			local basename = 'file.lua'
			assert.equal(basename, result, 'should return basename: ' .. result)
		end)

		it('shorten_path should truncate dirname, result may exceed max if basename is long', function()
			local path = '/home/user/very/deep/nested/path/to/file.lua'
			local result = BugabingaCycle.shorten_path(path, 15)
			local basename = vim.fn.fnamemodify(path, ':t')
			assert(result:find(basename, 1, true) ~= nil, 'basename should be present: ' .. result)
			assert(#result <= 20, 'should be shortened: ' .. result .. ' (' .. #result .. ')')
		end)

		it('get_icon should return a string', function()
			local icon, _ = BugabingaCycle.get_icon('test.lua')
			assert.is_string(icon)
			assert.is_true(#icon > 0)
		end)
	end)

	describe('module API', function()
		it('should export cycle, cancel, and history', function()
			assert.is_function(BugabingaCycle.cycle)
			assert.is_function(BugabingaCycle.cancel)
			assert.is_table(BugabingaCycle.history)
		end)
	end)
end)