---@diagnostic disable: duplicate-set-field, need-check-nil, param-type-mismatch, assign-type-mismatch, redundant-parameter local diff = require 'bugabinga.pivi.diff' local entry = require 'bugabinga.pivi.entry' local follow = require 'bugabinga.pivi.follow' local transcript = require 'bugabinga.pivi.transcript' local fake = dofile 'tests/helpers/pivi_fake.lua' local temp_file = function( lines ) local path = vim.fs.normalize( vim.fn.tempname() .. '.lua' ) vim.fn.writefile( lines, path ) return path end -- A change as the edit tool formats it: every changed line carries its number. local CHANGE = table.concat( { ' 1 one', '-2 two', '+2 TWO', ' 3 three', }, '\n' ) local recorded = function( bufnr, path, change ) local id = entry.open( bufnr, 'tool', { tool = 'edit', args = { path = path, }, result = { details = { diff = change, firstChangedLine = 2, }, }, } ) entry.line( bufnr, id, 'edit ' .. vim.fs.basename( path ) ) for _, line in ipairs( vim.split( change, '\n', { plain = true, } ) ) do entry.line( bufnr, id, line ) end entry.close( bufnr, id ) return id end describe( 'pivi diff', function() local bufnr, win before_each( function() bufnr = transcript.ensure 'comparing' transcript.clear( bufnr ) win = transcript.show( bufnr ) vim.api.nvim_set_current_win( win ) end ) after_each( function() diff.close() follow.reset() transcript.forget_all() fake.close_extra_windows() vim.cmd 'silent! %bwipeout!' end ) describe( 'reading a reported change', function() it( 'separates what was added from what was removed', function() local removed, added = diff.parse( CHANGE ) assert.same( { { line = 2, text = 'two', }, }, removed ) assert.same( { { line = 2, text = 'TWO', }, }, added ) end ) it( 'ignores context lines', function() local removed, added = diff.parse ' 1 untouched' assert.same( {}, removed ) assert.same( {}, added ) end ) it( 'rebuilds the content that existed before the change', function() local original, faithful = diff.before( { 'one', 'TWO', 'three', }, CHANGE ) assert.same( { 'one', 'two', 'three', }, original ) assert.is_true( faithful ) end ) it( 'rebuilds a change that only added lines', function() local original = diff.before( { 'one', 'two', }, '+2 two' ) assert.same( { 'one', }, original ) end ) it( 'rebuilds a change that only removed lines', function() local original = diff.before( { 'one', }, '-2 two' ) assert.same( { 'one', 'two', }, original ) end ) it( 'says so when the content no longer matches the change', function() local _, faithful = diff.before( { 'one', 'something else', 'three', }, CHANGE ) assert.is_false( faithful ) end ) end ) describe( 'comparing', function() it( 'opens the change as an editor comparison', function() local path = temp_file { 'one', 'TWO', 'three', } local id = recorded( bufnr, path, CHANGE ) local first = select( 1, entry.range( bufnr, id ) ) local changed, original, faithful = diff.open( bufnr, first ) assert.is_number( changed ) assert.is_number( original ) assert.is_true( faithful ) assert.is_true( vim.wo[changed].diff ) assert.is_true( vim.wo[original].diff ) assert.same( { 'one', 'two', 'three', }, vim.api.nvim_buf_get_lines( vim.api.nvim_win_get_buf( original ), 0, -1, false ) ) end ) it( 'keeps the working window and leaves the transcript untouched', function() local path = temp_file { 'one', 'TWO', 'three', } local id = recorded( bufnr, path, CHANGE ) local first = select( 1, entry.range( bufnr, id ) ) local before_text = transcript.lines( bufnr ) diff.open( bufnr, first ) assert.equal( win, vim.api.nvim_get_current_win() ) assert.same( before_text, transcript.lines( bufnr ) ) end ) it( 'states that the file has moved on', function() local path = temp_file { 'one', 'something else', 'three', } local id = recorded( bufnr, path, CHANGE ) local first = select( 1, entry.range( bufnr, id ) ) local _, original, faithful = diff.open( bufnr, first ) assert.is_false( faithful ) assert.is_true( vim.api.nvim_buf_get_name( vim.api.nvim_win_get_buf( original ) ):find( 'moved on', 1, true ) ~= nil ) end ) it( 'compares nothing for an entry that reports no change', function() local id = entry.open( bufnr, 'tool', { tool = 'read', args = { path = temp_file { 'one', }, }, } ) entry.line( bufnr, id, 'read a.lua' ) entry.close( bufnr, id ) assert.is_nil( diff.open( bufnr, select( 1, entry.range( bufnr, id ) ) ) ) end ) it( 'compares nothing outside a tool entry', function() local id = entry.open( bufnr, 'answer' ) entry.line( bufnr, id, 'just words' ) entry.close( bufnr, id ) assert.is_nil( diff.open( bufnr, select( 1, entry.range( bufnr, id ) ) ) ) end ) it( 'can be left again', function() local path = temp_file { 'one', 'TWO', 'three', } local id = recorded( bufnr, path, CHANGE ) local _, original = diff.open( bufnr, select( 1, entry.range( bufnr, id ) ) ) diff.close() assert.is_false( vim.api.nvim_win_is_valid( original ) ) assert.equal( win, vim.api.nvim_get_current_win() ) end ) it( 'publishes comparison as an intent', function() local published for _, mapping in ipairs( vim.api.nvim_buf_get_keymap( bufnr, 'n' ) ) do if mapping.lhs == '(pivi-compare-change)' then published = mapping end end assert.is_table( published ) end ) end ) end )