|
| 1 | +use std::{cell::RefCell, path::PathBuf}; |
| 2 | + |
| 3 | +use asyncgit::{sync::RepoPath, AsyncGitNotification}; |
| 4 | +use crossbeam_channel::{unbounded, Receiver}; |
| 5 | +use crossterm::event::{KeyCode, KeyModifiers}; |
| 6 | + |
| 7 | +use crate::{ |
| 8 | + app::App, draw, input::Input, keys::KeyConfig, ui::style::Theme, |
| 9 | + AsyncAppNotification, |
| 10 | +}; |
| 11 | + |
| 12 | +struct Gitui { |
| 13 | + app: crate::app::App, |
| 14 | + _rx_git: Receiver<AsyncGitNotification>, |
| 15 | + _rx_app: Receiver<AsyncAppNotification>, |
| 16 | +} |
| 17 | + |
| 18 | +impl Gitui { |
| 19 | + fn new(path: RepoPath) -> Self { |
| 20 | + let (tx_git, rx_git) = unbounded(); |
| 21 | + let (tx_app, rx_app) = unbounded(); |
| 22 | + |
| 23 | + let input = Input::new(); |
| 24 | + |
| 25 | + let theme = Theme::init(&PathBuf::new()); |
| 26 | + let key_config = KeyConfig::default(); |
| 27 | + |
| 28 | + let app = App::new( |
| 29 | + RefCell::new(path), |
| 30 | + tx_git, |
| 31 | + tx_app, |
| 32 | + input.clone(), |
| 33 | + theme, |
| 34 | + key_config.clone(), |
| 35 | + ) |
| 36 | + .unwrap(); |
| 37 | + |
| 38 | + Self { |
| 39 | + app, |
| 40 | + _rx_git: rx_git, |
| 41 | + _rx_app: rx_app, |
| 42 | + } |
| 43 | + } |
| 44 | + |
| 45 | + fn draw<B: ratatui::backend::Backend>( |
| 46 | + &mut self, |
| 47 | + terminal: &mut ratatui::Terminal<B>, |
| 48 | + ) { |
| 49 | + draw(terminal, &self.app).unwrap(); |
| 50 | + } |
| 51 | + |
| 52 | + fn update_async(&mut self, event: crate::AsyncNotification) { |
| 53 | + self.app.update_async(event).unwrap(); |
| 54 | + } |
| 55 | + |
| 56 | + fn input_event( |
| 57 | + &mut self, |
| 58 | + code: KeyCode, |
| 59 | + modifiers: KeyModifiers, |
| 60 | + ) { |
| 61 | + let event = crossterm::event::KeyEvent::new(code, modifiers); |
| 62 | + self.app |
| 63 | + .event(crate::input::InputEvent::Input( |
| 64 | + crossterm::event::Event::Key(event), |
| 65 | + )) |
| 66 | + .unwrap(); |
| 67 | + } |
| 68 | + |
| 69 | + fn update(&mut self) { |
| 70 | + self.app.update().unwrap(); |
| 71 | + } |
| 72 | +} |
| 73 | + |
| 74 | +#[cfg(test)] |
| 75 | +mod tests { |
| 76 | + use std::{thread::sleep, time::Duration}; |
| 77 | + |
| 78 | + use asyncgit::{sync::RepoPath, AsyncGitNotification}; |
| 79 | + use crossterm::event::{KeyCode, KeyModifiers}; |
| 80 | + use git2_testing::repo_init; |
| 81 | + use insta::assert_snapshot; |
| 82 | + use ratatui::{backend::TestBackend, Terminal}; |
| 83 | + |
| 84 | + use crate::{gitui::Gitui, AsyncNotification}; |
| 85 | + |
| 86 | + // Macro adapted from: https://insta.rs/docs/cmd/ |
| 87 | + macro_rules! apply_common_filters { |
| 88 | + {} => { |
| 89 | + let mut settings = insta::Settings::clone_current(); |
| 90 | + // MacOS Temp Folder |
| 91 | + settings.add_filter(r" *\[…\]\S+?/T/\S+", "[TEMP_FILE]"); |
| 92 | + // Linux Temp Folder |
| 93 | + settings.add_filter(r" */tmp/\.tmp\S+", "[TEMP_FILE]"); |
| 94 | + // Windows Temp folder |
| 95 | + settings.add_filter(r" *\[…\].*/Local/Temp/\S+", "[TEMP_FILE]"); |
| 96 | + // Commit ids that follow a vertical bar |
| 97 | + settings.add_filter(r"│[a-z0-9]{7} ", "│[AAAAA] "); |
| 98 | + let _bound = settings.bind_to_scope(); |
| 99 | + } |
| 100 | + } |
| 101 | + |
| 102 | + #[test] |
| 103 | + fn gitui_starts() { |
| 104 | + apply_common_filters!(); |
| 105 | + |
| 106 | + let (temp_dir, _repo) = repo_init(); |
| 107 | + let path: RepoPath = temp_dir.path().to_str().unwrap().into(); |
| 108 | + |
| 109 | + let mut terminal = |
| 110 | + Terminal::new(TestBackend::new(120, 40)).unwrap(); |
| 111 | + |
| 112 | + let mut gitui = Gitui::new(path); |
| 113 | + |
| 114 | + gitui.draw(&mut terminal); |
| 115 | + |
| 116 | + sleep(Duration::from_millis(500)); |
| 117 | + |
| 118 | + assert_snapshot!("app_loading", terminal.backend()); |
| 119 | + |
| 120 | + let event = |
| 121 | + AsyncNotification::Git(AsyncGitNotification::Status); |
| 122 | + gitui.update_async(event); |
| 123 | + |
| 124 | + sleep(Duration::from_millis(500)); |
| 125 | + |
| 126 | + gitui.draw(&mut terminal); |
| 127 | + |
| 128 | + assert_snapshot!("app_loading_finished", terminal.backend()); |
| 129 | + |
| 130 | + gitui.input_event(KeyCode::Char('2'), KeyModifiers::empty()); |
| 131 | + |
| 132 | + sleep(Duration::from_millis(500)); |
| 133 | + |
| 134 | + gitui.update(); |
| 135 | + |
| 136 | + gitui.draw(&mut terminal); |
| 137 | + |
| 138 | + assert_snapshot!( |
| 139 | + "app_log_tab_showing_one_commit", |
| 140 | + terminal.backend() |
| 141 | + ); |
| 142 | + } |
| 143 | +} |
0 commit comments