---@diagnostic disable: duplicate-set-field, need-check-nil, param-type-mismatch, assign-type-mismatch local bridge = require 'bugabinga.pivi.bridge' local activity = require 'bugabinga.pivi.activity' local temp_file = function( lines ) local path = vim.fs.normalize( vim.fn.tempname() .. '.txt' ) vim.fn.writefile( lines, path ) return path end local open = function( path ) vim.cmd( 'edit! ' .. vim.fn.fnameescape( path ) ) return vim.api.nvim_get_current_buf() end describe( 'pivi bridge', function() after_each( function() vim.cmd 'silent! %bwipeout!' activity.clear_trail() vim.fn.setqflist( {}, 'r' ) end ) it( 'rejects an unknown action', function() local answer = bridge.handle { action = 'levitate', } assert.is_false( answer.ok ) assert.is_string( answer.error ) end ) it( 'rejects a malformed request', function() assert.is_false( bridge.handle( 'nonsense' ).ok ) end ) it( 'reads unsaved buffer content instead of disk content', function() local path = temp_file { 'on disk', } local bufnr = open( path ) vim.api.nvim_buf_set_lines( bufnr, 0, -1, false, { 'unsaved', } ) local answer = bridge.handle { action = 'read', path = path, } assert.is_true( answer.ok ) assert.equal( 'buffer', answer.source ) assert.equal( 'unsaved', answer.content ) end ) it( 'reads from disk when no buffer holds the file', function() local path = temp_file { 'from disk', } local answer = bridge.handle { action = 'read', path = path, } assert.equal( 'disk', answer.source ) assert.equal( 'from disk', answer.content ) end ) it( 'reports a missing file', function() local answer = bridge.handle { action = 'read', path = vim.fn.tempname() .. '.absent', } assert.is_false( answer.ok ) end ) it( 'writes through the loaded buffer and makes it visible on disk', function() local path = temp_file { 'before', } local bufnr = open( path ) local answer = bridge.handle { action = 'write', path = path, content = 'after', } assert.is_true( answer.ok ) assert.equal( 'buffer', answer.source ) assert.is_true( answer.persisted ) assert.same( { 'after', }, vim.api.nvim_buf_get_lines( bufnr, 0, -1, false ) ) assert.same( { 'after', }, vim.fn.readfile( path ) ) end ) it( 'writes straight to disk when no buffer holds the file', function() local path = temp_file { 'before', } local answer = bridge.handle { action = 'write', path = path, content = 'after', } assert.equal( 'disk', answer.source ) assert.same( { 'after', }, vim.fn.readfile( path ) ) end ) it( 'edits a loaded buffer and keeps the change undoable', function() local path = temp_file { 'local value = 1', 'return value', } local bufnr = open( path ) local before = vim.api.nvim_buf_get_lines( bufnr, 0, -1, false ) local answer = bridge.handle { action = 'edit', path = path, old_text = 'local value = 1', new_text = 'local value = 2', } assert.is_true( answer.ok ) assert.equal( 'buffer', answer.source ) assert.same( { 'local value = 2', 'return value', }, vim.api.nvim_buf_get_lines( bufnr, 0, -1, false ) ) vim.api.nvim_buf_call( bufnr, function() vim.cmd 'silent undo' end ) assert.same( before, vim.api.nvim_buf_get_lines( bufnr, 0, -1, false ) ) end ) it( 'edits a file that is not loaded', function() local path = temp_file { 'alpha', } local answer = bridge.handle { action = 'edit', path = path, old_text = 'alpha', new_text = 'omega', } assert.equal( 'disk', answer.source ) assert.same( { 'omega', }, vim.fn.readfile( path ) ) end ) it( 'refuses an edit whose text is absent', function() local path = temp_file { 'alpha', } open( path ) local answer = bridge.handle { action = 'edit', path = path, old_text = 'missing', new_text = 'x', } assert.is_false( answer.ok ) end ) it( 'reports live editor state', function() local path = temp_file { 'ambient', } local bufnr = open( path ) local answer = bridge.handle { action = 'state', } assert.is_true( answer.ok ) assert.equal( bufnr, answer.state.current_buffer ) assert.is_true( #answer.state.windows > 0 ) end ) it( 'answers a help tag from this neovim', function() local answer = bridge.handle { action = 'help', tag = 'quickfix', } assert.is_true( answer.ok ) assert.is_true( answer.found ) assert.equal( 'quickfix.txt', answer.file ) assert.is_true( answer.text:find( 'quickfix', 1, true ) ~= nil ) end ) it( 'offers candidates for an unknown help tag', function() local answer = bridge.handle { action = 'help', tag = 'quickf', } assert.is_true( answer.ok ) assert.is_false( answer.found ) assert.is_true( #answer.candidates > 0 ) end ) it( 'refuses a help request without a tag', function() assert.is_false( bridge.handle( { action = 'help', } ).ok ) end ) it( 'reports what the user currently sees', function() local path = temp_file { 'visible one', 'visible two', } open( path ) local answer = bridge.handle { action = 'view', } assert.is_true( answer.ok ) assert.equal( 2, answer.view.line_count ) assert.is_true( vim.list_contains( answer.view.lines, 'visible one' ) ) end ) it( 'executes arbitrary lua and returns the inspected result', function() local answer = bridge.handle { action = 'lua', code = 'return 1 + 1', } assert.is_true( answer.ok ) assert.equal( '2', answer.result ) end ) it( 'reports a lua failure instead of throwing', function() assert.is_false( bridge.handle( { action = 'lua', code = 'error("boom")', } ).ok ) assert.is_false( bridge.handle( { action = 'lua', code = 'this is not lua', } ).ok ) end ) it( 'publishes findings to the quickfix list', function() local answer = bridge.handle { action = 'findings', title = 'review', items = { { path = 'a.lua', line = 2, text = 'look here', }, }, } assert.is_true( answer.ok ) assert.equal( 1, #vim.fn.getqflist() ) end ) it( 'publishes diagnostics for a loaded buffer only', function() local path = temp_file { 'one', 'two', } local bufnr = open( path ) local answer = bridge.handle { action = 'diagnostics', path = path, items = { { line = 2, text = 'suspicious', severity = 'warning', }, }, } assert.is_true( answer.ok ) assert.equal( 1, #activity.diagnostics( bufnr ) ) assert.is_false( bridge.handle( { action = 'diagnostics', path = vim.fn.tempname() .. '.absent', items = {}, } ).ok ) activity.clear_diagnostics( bufnr ) end ) end )