1module view23import src.events4import src.fmt5import src.history6import src.snapshot78fn save(id string, message string, checkpoint bool) history.Save {9 return history.Save{10 id: id11 message: message12 created_at: 179000000013 size_bytes: 102414 is_checkpoint: checkpoint15 }16}1718fn line_map(ids []string) map[string]bool {19 mut out := map[string]bool{}20 for id in ids {21 out[id] = true22 }23 return out24}2526fn test_tabs_filter_by_what_is_on_the_line() {27 28 29 on_the_line := line_map(['aaa', 'ccc', 'ddd'])30 mut copy := save('ddd', 'my work, replayed', false)31 copy.replayed_from = 'bbb'32 items := [save('aaa', 'first', false), save('bbb', 'my work', false),33 save('ccc', 'before things', true), copy]3435 assert filter_saves(items, .all, on_the_line, '').len == 436 37 38 assert filter_saves(items, .saves, on_the_line, '').map(it.id) == ['aaa', 'ccc', 'ddd']39 assert filter_saves(items, .checkpoints, on_the_line, '').map(it.id) == ['ccc']40}4142fn test_only_the_replayed_away_original_is_marked() {43 on_the_line := line_map(['ddd'])44 mut copy := save('ddd', 'my work, replayed', false)45 copy.replayed_from = 'bbb'46 screen := Screen{47 on_line: on_the_line48 }49 assert fmt.strip_ansi(save_mark(save('bbb', 'my work', false), screen)) == '↪'50 assert fmt.strip_ansi(save_mark(copy, screen)) == ' '51 assert entry_line(save('bbb', 'my work', false), false, screen).contains('replayed away')52 assert !entry_line(copy, false, screen).contains('replayed away')53}5455fn test_search_is_case_insensitive_across_the_fields() {56 on_the_line := line_map(['aaa', 'bbb', 'ccc'])57 mut with_agent := save('bbb', 'fix chunk boundary', false)58 with_agent.agent = 'DeepSeek/Flash'59 mut with_session := save('ccc', 'other work', false)60 with_session.session = 'phase one'61 items := [save('aaa', 'add storage', false), with_agent, with_session]6263 assert filter_saves(items, .all, on_the_line, 'STORAGE').map(it.id) == ['aaa']64 assert filter_saves(items, .all, on_the_line, 'chunk').map(it.id) == ['bbb']65 assert filter_saves(items, .all, on_the_line, 'deepseek').map(it.id) == ['bbb']66 assert filter_saves(items, .all, on_the_line, 'PHASE').map(it.id) == ['ccc']67 assert filter_saves(items, .all, on_the_line, 'nothing here').len == 068}6970fn test_move_selection_clamps_at_both_ends() {71 assert move_selection(0, 1, 3) == 172 assert move_selection(2, 1, 3) == 273 assert move_selection(0, -1, 3) == 074 assert move_selection(0, 0, 0) == 075 assert move_selection(5, 1, 0) == 076 77 assert move_selection(3, -1, 3) == 278}7980fn test_detail_lists_files_with_stats_and_notes_binaries() {81 target := save('aaa', 'change two files', false)82 flag := events.Flag{83 save_id: 'aaa'84 flagged: true85 reason: 'sketchy'86 }87 deltas := [88 snapshot.Delta{89 path: 'src/main.v'90 kind: 'modified'91 added: 492 removed: 293 },94 snapshot.Delta{95 path: 'logo.png'96 kind: 'added'97 binary: true98 },99 ]100 text := detail_lines(target, deltas, flag).join('\n')101 assert text.contains('checksum aaa')102 assert text.contains('flag sketchy')103 assert text.contains('src/main.v')104 assert text.contains('+4')105 assert text.contains('-2')106 assert text.contains('logo.png')107 assert text.contains('(binary)')108 assert text.contains('2 files changed against the parent')109}110111fn test_detail_says_so_when_nothing_changed() {112 target := save('aaa', 'first save', false)113 text := detail_lines(target, [], events.Flag{114 save_id: 'aaa'115 }).join('\n')116 assert text.contains('nothing changed against the parent')117}118119fn test_frame_shows_counts_the_selected_entry_and_the_status_bar() {120 on_the_line := line_map(['aaa', 'ccc'])121 items := [save('aaa', 'first', false), save('ccc', 'before storage', true)]122 screen := Screen{123 tab: .all124 items: items125 selected: 1126 on_line: on_the_line127 counts: count_tabs(items, on_the_line)128 rows: 24129 cols: 100130 status: '3 shown'131 }132 text := frame_lines(screen).join('\n')133 assert text.contains('all (2)')134 assert text.contains('checkpoints (1)')135 assert text.contains('before storage')136 assert text.contains('aaa')137 138 assert text.contains('agent')139 assert text.contains('◐')140 assert text.contains('3 shown')141}142143fn test_frame_says_no_results_when_the_search_matches_nothing() {144 screen := Screen{145 tab: .all146 rows: 24147 cols: 80148 query: 'nothing matches this'149 counts: TabCounts{}150 }151 text := frame_lines(screen).join('\n')152 assert text.contains('no results')153 assert text.contains('/nothing matches this')154}155156fn test_render_clears_each_line_before_drawing_it() {157 screen := Screen{158 tab: .saves159 rows: 6160 cols: 60161 }162 frame := render(screen)163 assert frame.starts_with('\x1b[H')164 165 166 assert frame.count('\x1b[2K') == frame_lines(screen).len167}