diff options
| author | Aram Drevekenin <aram@poor.dev> | 2021-06-30 11:27:35 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-06-30 11:27:35 +0200 |
| commit | ed4fd2a8e77df304539ca7f445a78039028eaa8a (patch) | |
| tree | ae48b03370b11f3f0987676584724463ac83460d /zellij-server/src | |
| parent | Merge pull request #590 from a-kenji/clippy-fixes (diff) | |
| download | sl0ppij-ed4fd2a8e77df304539ca7f445a78039028eaa8a.tar.gz sl0ppij-ed4fd2a8e77df304539ca7f445a78039028eaa8a.tar.xz sl0ppij-ed4fd2a8e77df304539ca7f445a78039028eaa8a.zip | |
chore(tests): move all integration tests to be either unit or e2e tests - remove old testing infra (#589)
* tests(integration): move basic integration tests to be unit tests
* fix(tests): silently fail threadbus for tests
* tests(unit): move compatibility tests to become unit tests for grid
* tests(unit): move close_pane tests to become unit tests for grid
* tests(e2e): move basic layout test to e2e
* tests(unit): move move_focus tests to be unit tests
* tests(unit): move resize_down tests to be unit tests
* tests(unit): move resize_left tests to be unit tests
* tests(unit): move resize_right tests to be unit tests
* tests(unit): move resize_up tests to be unit tests
* tests(infra): remove unused infra
* style(fmt): make rustfmt happy
* debug
* debug
* debug
* debug
* chore(test): shift volume mounting around because github actions is a special child
Diffstat (limited to 'zellij-server/src')
32 files changed, 13182 insertions, 11 deletions
diff --git a/zellij-server/src/lib.rs b/zellij-server/src/lib.rs index 27872b64..5322e6a6 100644 --- a/zellij-server/src/lib.rs +++ b/zellij-server/src/lib.rs @@ -390,6 +390,7 @@ fn init_session( to_pty: Some(to_pty), to_plugin: Some(to_plugin), to_server: None, + should_silently_fail: false, }, capabilities, palette: client_attributes.palette, diff --git a/zellij-server/src/panes/terminal_pane.rs b/zellij-server/src/panes/terminal_pane.rs index 734007ea..0abc7a5a 100644 --- a/zellij-server/src/panes/terminal_pane.rs +++ b/zellij-server/src/panes/terminal_pane.rs @@ -340,3 +340,7 @@ impl TerminalPane { self.grid.cursor_coordinates() } } + +#[cfg(test)] +#[path = "./unit/terminal_pane_tests.rs"] +mod grid_tests; diff --git a/zellij-server/src/panes/unit/grid_tests.rs b/zellij-server/src/panes/unit/grid_tests.rs index bce67e06..048d3d0a 100644 --- a/zellij-server/src/panes/unit/grid_tests.rs +++ b/zellij-server/src/panes/unit/grid_tests.rs @@ -555,3 +555,293 @@ fn wrap_wide_characters_at_the_end_of_the_line() { } assert_snapshot!(format!("{:?}", grid)); } + +/* + * These tests below are general compatibility tests for non-trivial scenarios running in the terminal. + * They use fake TTY input replicated from these scenarios. + * + */ + +#[test] +fn run_bandwhich_from_fish_shell() { + let mut vte_parser = vte::Parser::new(); + let mut grid = Grid::new(28, 116, Palette::default()); + let fixture_name = "fish_and_bandwhich"; + let content = read_fixture(fixture_name); + for byte in content { + vte_parser.advance(&mut grid, byte); + } + assert_snapshot!(format!("{:?}", grid)); +} + +#[test] +fn fish_tab_completion_options() { + let mut vte_parser = vte::Parser::new(); + let mut grid = Grid::new(28, 116, Palette::default()); + let fixture_name = "fish_tab_completion_options"; + let content = read_fixture(fixture_name); + for byte in content { + vte_parser.advance(&mut grid, byte); + } + assert_snapshot!(format!("{:?}", grid)); +} + +#[test] +pub fn fish_select_tab_completion_options() { + // the difference between this and the previous test is that here we press <TAB> + // twice, meaning the selection moves between the options and the command line + // changes. + // this is not clearly seen in the snapshot because it does not include styles, + // but we can see the command line change and the cursor staying in place + let mut vte_parser = vte::Parser::new(); + let mut grid = Grid::new(28, 116, Palette::default()); + let fixture_name = "fish_select_tab_completion_options"; + let content = read_fixture(fixture_name); + for byte in content { + vte_parser.advance(&mut grid, byte); + } + assert_snapshot!(format!("{:?}", grid)); +} + +#[test] +pub fn vim_scroll_region_down() { + // here we test a case where vim defines the scroll region as lesser than the screen row count + // and then scrolls down + // the region is defined here by vim as 1-26 (there are 28 rows) + // then the cursor is moved to line 26 and a new line is added + // what should happen is that the first line in the scroll region (1) is deleted + // and an empty line is inserted in the last scroll region line (26) + // this tests also has other steps afterwards that fills the line with the next line in the + // file + let mut vte_parser = vte::Parser::new(); + let mut grid = Grid::new(28, 116, Palette::default()); + let fixture_name = "vim_scroll_region_down"; + let content = read_fixture(fixture_name); + for byte in content { + vte_parser.advance(&mut grid, byte); + } + assert_snapshot!(format!("{:?}", grid)); +} + +#[test] +pub fn vim_ctrl_d() { + // in vim ctrl-d moves down half a page + // in this case, it sends the terminal the csi 'M' directive, which tells it to delete X (13 in + // this case) lines inside the scroll region and push the other lines up + // what happens here is that 13 lines are deleted and instead 13 empty lines are added at the + // end of the scroll region + // vim makes sure to fill these empty lines with the rest of the file + let mut vte_parser = vte::Parser::new(); + let mut grid = Grid::new(28, 116, Palette::default()); + let fixture_name = "vim_ctrl_d"; + let content = read_fixture(fixture_name); + for byte in content { + vte_parser.advance(&mut grid, byte); + } + assert_snapshot!(format!("{:?}", grid)); +} + +#[test] +pub fn vim_ctrl_u() { + // in vim ctrl-u moves up half a page + // in this case, it sends the terminal the csi 'L' directive, which tells it to insert X (13 in + // this case) lines at the cursor, pushing away (deleting) the last line in the scroll region + // this causes the effect of scrolling up X lines (vim replaces the lines with the ones in the + // file above the current content) + let mut vte_parser = vte::Parser::new(); + let mut grid = Grid::new(28, 116, Palette::default()); + let fixture_name = "vim_ctrl_u"; + let content = read_fixture(fixture_name); + for byte in content { + vte_parser.advance(&mut grid, byte); + } + assert_snapshot!(format!("{:?}", grid)); +} + +#[test] +pub fn htop() { + let mut vte_parser = vte::Parser::new(); + let mut grid = Grid::new(28, 116, Palette::default()); + let fixture_name = "htop"; + let content = read_fixture(fixture_name); + for byte in content { + vte_parser.advance(&mut grid, byte); + } + assert_snapshot!(format!("{:?}", grid)); +} + +#[test] +pub fn htop_scrolling() { + let mut vte_parser = vte::Parser::new(); + let mut grid = Grid::new(28, 116, Palette::default()); + let fixture_name = "htop_scrolling"; + let content = read_fixture(fixture_name); + for byte in content { + vte_parser.advance(&mut grid, byte); + } + assert_snapshot!(format!("{:?}", grid)); +} + +#[test] +pub fn htop_right_scrolling() { + let mut vte_parser = vte::Parser::new(); + let mut grid = Grid::new(28, 116, Palette::default()); + let fixture_name = "htop_right_scrolling"; + let content = read_fixture(fixture_name); + for byte in content { + vte_parser.advance(&mut grid, byte); + } + assert_snapshot!(format!("{:?}", grid)); +} + +#[test] +pub fn vim_overwrite() { + // this tests the vim overwrite message + // to recreate: + // * open a file in vim + // * open the same file in another window + // * change the file in the other window and save + // * change the file in the original vim window and save + // * confirm you would like to change the file by pressing 'y' and then ENTER + // * if everything looks fine, this test passed :) + let mut vte_parser = vte::Parser::new(); + let mut grid = Grid::new(28, 116, Palette::default()); + let fixture_name = "vim_overwrite"; + let content = read_fixture(fixture_name); + for byte in content { + vte_parser.advance(&mut grid, byte); + } + assert_snapshot!(format!("{:?}", grid)); +} + +#[test] +pub fn clear_scroll_region() { + // this is actually a test of 1049h/l (alternative buffer) + // @imsnif - the name is a monument to the time I didn't fully understand this mechanism :) + let mut vte_parser = vte::Parser::new(); + let mut grid = Grid::new(28, 116, Palette::default()); + let fixture_name = "clear_scroll_region"; + let content = read_fixture(fixture_name); + for byte in content { + vte_parser.advance(&mut grid, byte); + } + assert_snapshot!(format!("{:?}", grid)); +} + +#[test] +pub fn display_tab_characters_properly() { + let mut vte_parser = vte::Parser::new(); + let mut grid = Grid::new(28, 116, Palette::default()); + let fixture_name = "tab_characters"; + let content = read_fixture(fixture_name); + for byte in content { + vte_parser.advance(&mut grid, byte); + } + assert_snapshot!(format!("{:?}", grid)); +} + +#[test] +pub fn neovim_insert_mode() { + let mut vte_parser = vte::Parser::new(); + let mut grid = Grid::new(28, 116, Palette::default()); + let fixture_name = "nvim_insert"; + let content = read_fixture(fixture_name); + for byte in content { + vte_parser.advance(&mut grid, byte); + } + assert_snapshot!(format!("{:?}", grid)); +} + +#[test] +pub fn bash_cursor_linewrap() { + let mut vte_parser = vte::Parser::new(); + let mut grid = Grid::new(28, 116, Palette::default()); + let fixture_name = "bash_cursor_linewrap"; + let content = read_fixture(fixture_name); + for byte in content { + vte_parser.advance(&mut grid, byte); + } + assert_snapshot!(format!("{:?}", grid)); +} + +#[test] +pub fn fish_paste_multiline() { + // here we paste a multiline command in fish shell, making sure we support it + // going up and changing the colors of our line-wrapped pasted text + let mut vte_parser = vte::Parser::new(); + let mut grid = Grid::new(28, 149, Palette::default()); + let fixture_name = "fish_paste_multiline"; + let content = read_fixture(fixture_name); + for byte in content { + vte_parser.advance(&mut grid, byte); + } + assert_snapshot!(format!("{:?}", grid)); +} + +#[test] +pub fn git_log() { + let mut vte_parser = vte::Parser::new(); + let mut grid = Grid::new(28, 149, Palette::default()); + let fixture_name = "git_log"; + let content = read_fixture(fixture_name); + for byte in content { + vte_parser.advance(&mut grid, byte); + } + assert_snapshot!(format!("{:?}", grid)); +} + +#[test] +pub fn git_diff_scrollup() { + // this tests makes sure that when we have a git diff that exceeds the screen size + // we are able to scroll up + let mut vte_parser = vte::Parser::new(); + let mut grid = Grid::new(28, 149, Palette::default()); + let fixture_name = "git_diff_scrollup"; + let content = read_fixture(fixture_name); + for byte in content { + vte_parser.advance(&mut grid, byte); + } + assert_snapshot!(format!("{:?}", grid)); +} + +#[test] +pub fn emacs_longbuf() { + let mut vte_parser = vte::Parser::new(); + let mut grid = Grid::new(60, 284, Palette::default()); + let fixture_name = "emacs_longbuf_tutorial"; + let content = read_fixture(fixture_name); + for byte in content { + vte_parser.advance(&mut grid, byte); + } + assert_snapshot!(format!("{:?}", grid)); +} + +#[test] +pub fn top_and_quit() { + let mut vte_parser = vte::Parser::new(); + let mut grid = Grid::new(56, 235, Palette::default()); + let fixture_name = "top_and_quit"; + let content = read_fixture(fixture_name); + for byte in content { + vte_parser.advance(&mut grid, byte); + } + assert_snapshot!(format!("{:?}", grid)); +} + +#[test] +pub fn exa_plus_omf_theme() { + // this tests that we handle a tab delimited table properly + // without overriding the previous content + // this is a potential bug because the \t character is a goto + // if we forwarded it as is to the terminal, we would be skipping + // over existing on-screen content without deleting it, so we must + // convert it to spaces + let mut vte_parser = vte::Parser::new(); + let mut grid = Grid::new(56, 235, Palette::default()); + let fixture_name = "exa_plus_omf_theme"; + let content = read_fixture(fixture_name); + for byte in content { + vte_parser.advance(&mut grid, byte); + } + assert_snapshot!(format!("{:?}", grid)); +} diff --git a/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__bash_cursor_linewrap.snap b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__bash_cursor_linewrap.snap new file mode 100644 index 00000000..93634316 --- /dev/null +++ b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__bash_cursor_linewrap.snap @@ -0,0 +1,10 @@ +--- +source: zellij-server/src/panes/./unit/grid_tests.rs +expression: "format!(\"{:?}\", grid)" + +--- +00 (C): Welcome to fish, the friendly interactive shell +01 (C): ⋊> ~/c/mosaic on main ⨯ bash 16:00:06 +02 (C): [aram@green mosaic]$ 12345678912345678912345678912345678912345678912345678912345678912345678912345678912345678912345 +03 (W): + diff --git a/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__clear_scroll_region.snap b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__clear_scroll_region.snap new file mode 100644 index 00000000..b53826df --- /dev/null +++ b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__clear_scroll_region.snap @@ -0,0 +1,9 @@ +--- +source: zellij-server/src/panes/./unit/grid_tests.rs +expression: "format!(\"{:?}\", grid)" + +--- +00 (C): Welcome to fish, the friendly interactive shell +01 (C): ⋊> ~/c/mosaic on main ⨯ vim some-file 15:07:22 +02 (C): ⋊> ~/c/mosaic on main ⨯ 15:07:29 + diff --git a/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__display_tab_characters_properly.snap b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__display_tab_characters_properly.snap new file mode 100644 index 00000000..48c75d6c --- /dev/null +++ b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__display_tab_characters_properly.snap @@ -0,0 +1,21 @@ +--- +source: zellij-server/src/panes/./unit/grid_tests.rs +expression: "format!(\"{:?}\", grid)" + +--- +00 (C): +01 (C): OS: 5.9.13-arch1-1 GNU/Linux +02 (C): Uptime: 10 hours, 42 minutes +03 (C): Hostname: kingdom +04 (C): Disk usage: +05 (C): +06 (C): df: /run/user/1000/doc: Operation not permitted +07 (C): / 321G / 514G 66% +08 (C): /efi 27M / 96M 28% +09 (C): +10 (C): Network: +11 (C): +12 (C): wlp2s0 192.168.0.3 +13 (C): +14 (C): [I] [20:07] kingdom:mosaic (main) | + diff --git a/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__emacs_longbuf.snap b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__emacs_longbuf.snap new file mode 100644 index 00000000..5c08c323 --- /dev/null +++ b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__emacs_longbuf.snap @@ -0,0 +1,10 @@ +--- +source: zellij-server/src/panes/./unit/grid_tests.rs +expression: "format!(\"{:?}\", grid)" + +--- +00 (C): ➜ mosaic git:(mosaic#130) emacs +01 (C): ➜ mosaic git:(mosaic#130) emacs -nw +02 (C): ➜ mosaic git:(mosaic#130) exit +03 (C): + diff --git a/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__exa_plus_omf_theme.snap b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__exa_plus_omf_theme.snap new file mode 100644 index 00000000..eba80043 --- /dev/null +++ b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__exa_plus_omf_theme.snap @@ -0,0 +1,62 @@ +--- +source: zellij-server/src/panes/./unit/grid_tests.rs +expression: "format!(\"{:?}\", grid)" + +--- +00 (C): .rw-r--r-- 3.3k aram 11 Jan 16:09 CODE_OF_CONDUCT.md +01 (C): .rw-r--r-- 3.5k aram 17 Feb 16:06 CONTRIBUTING.md +02 (C): drwxr-xr-x - aram 10 Feb 11:53 default-tiles +03 (C): drwxr-xr-x - aram 10 Feb 11:53 docs +04 (C): .rw-r--r-- 2.1k aram 10 Feb 11:53 GOVERNANCE.md +05 (C): .rw-r--r-- 1.1k aram 10 Feb 11:53 LICENSE.md +06 (C): .rw-r--r-- 4.7k aram 17 Feb 16:06 README.md +07 (C): drwxr-xr-x - aram 17 Feb 16:06 src +08 (C): drwxr-xr-x - aram 17 Feb 16:08 target +09 (C): drwxr-xr-x - aram 17 Feb 16:06 zellij-tile +10 (C): ⋊> ~/c/zellij on main ⨯ ll 10:27:45 +11 (C): Permissions Size User Date Modified Name +12 (C): drwxr-xr-x - aram 11 Feb 14:04 assets +13 (C): .rwxr-xr-x 596 aram 17 Feb 16:06 build-all.sh +14 (C): .rw-r--r-- 1.4k aram 17 Feb 16:06 build.rs +15 (C): .rw-r--r-- 56k aram 17 Feb 16:07 Cargo.lock +16 (C): .rw-r--r-- 2.1k aram 17 Feb 16:06 Cargo.toml +17 (C): .rw-r--r-- 3.3k aram 11 Jan 16:09 CODE_OF_CONDUCT.md +18 (C): .rw-r--r-- 3.5k aram 17 Feb 16:06 CONTRIBUTING.md +19 (C): drwxr-xr-x - aram 10 Feb 11:53 default-tiles +20 (C): drwxr-xr-x - aram 10 Feb 11:53 docs +21 (C): .rw-r--r-- 2.1k aram 10 Feb 11:53 GOVERNANCE.md +22 (C): .rw-r--r-- 1.1k aram 10 Feb 11:53 LICENSE.md +23 (C): .rw-r--r-- 4.7k aram 17 Feb 16:06 README.md +24 (C): drwxr-xr-x - aram 17 Feb 16:06 src +25 (C): drwxr-xr-x - aram 17 Feb 16:08 target +26 (C): drwxr-xr-x - aram 17 Feb 16:06 zellij-tile +27 (C): ⋊> ~/c/zellij on main ⨯ omf theme 10:27:45 +28 (C): Installed: +29 (C): agnoster chain default plain +30 (C): +31 (C): Available: +32 (C): agnoster eden lavender scorphish +33 (C): aight emoji-powerline lolfish separation +34 (C): ays es mars shellder +35 (C): batman fishbone mish simple-ass-prompt +36 (C): beloglazov fishface mokou simplevi +37 (C): bira fishy-drupal mtahmed slavic-cat +38 (C): bobthefish fisk nai spacefish +39 (C): bongnoster fox nelsonjchen sushi +40 (C): boxfish gentoo neolambda syl20bnr +41 (C): budspencer gianu numist taktoa +42 (C): cbjohnson gitstatus ocean technopagan +43 (C): chain gnuykeaj one toaster +44 (C): clearance godfather pastfish tomita +45 (C): cmorrell graystatus perryh trout +46 (C): coffeeandcode harleen plain tweetjay +47 (C): cor idan pure uggedal +48 (C): cyan integral pygmalion will +49 (C): dangerous jacaetevha random wolf-theme +50 (C): default johanson randomrussel yimmy +51 (C): dmorrell kawasaki redfish zeit +52 (C): doughsay krisleech red-snapper zephyr +53 (C): eclm l robbyrussell zish +54 (C): edan lambda sashimi +55 (C): ⋊> ~/c/zellij on main ⨯ 10:27:46 + diff --git a/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__fish_paste_multiline.snap b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__fish_paste_multiline.snap new file mode 100644 index 00000000..faf24017 --- /dev/null +++ b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__fish_paste_multiline.snap @@ -0,0 +1,27 @@ +--- +source: zellij-server/src/panes/./unit/grid_tests.rs +expression: "format!(\"{:?}\", grid)" + +--- +00 (C): +01 (C): OS: 5.9.14-arch1-1 GNU/Linux +02 (C): Uptime: 12 hours, 21 minutes +03 (C): Hostname: kingdom +04 (C): Disk usage: +05 (C): +06 (C): df: /run/user/1000/doc: Operation not permitted +07 (C): / 295G / 514G 61% +08 (C): /efi 27M / 96M 28% +09 (C): +10 (C): Network: +11 (C): +12 (C): wlp2s0 192.168.0.3 +13 (C): +14 (C): [I] [21:58] kingdom:mosaic (main) | echo -ne (\ +15 (C): df -l -h | grep -E 'dev/(xvda|sd|mapper)' | \ +16 (C): awk '{printf "\\\\t%s\\\\t%4s / %4s %s\\\\n\n", $6, $3, $2, $5}' | \ +17 (C): sed -e 's/^\(.*\([8][5-9]\|[9][0-9]\)%.*\)$/\\\\e[0;31m\1\\\\e[0m/' -e 's/^\(.*\([7][5-9]\|[8][0-4]\)%.*\ +18 (W): )$/\\\\e[0;33m\1\\\\e[0m/' | \ +19 (C): paste -sd ''\ +20 (C): ) + diff --git a/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__fish_select_tab_completion_options.snap b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__fish_select_tab_completion_options.snap new file mode 100644 index 00000000..88addebb --- /dev/null +++ b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__fish_select_tab_completion_options.snap @@ -0,0 +1,11 @@ +--- +source: zellij-server/src/panes/./unit/grid_tests.rs +expression: "format!(\"{:?}\", grid)" + +--- +00 (C): Welcome to fish, the friendly interactive shell +01 (C): ⋊> ~/c/mosaic on main ⨯ sudo badblocks 11:32:23 +02 (C): badblocks (Executable, 33kB) base64 (Executable, 42kB) bash (Executable, 906kB) +03 (C): bandwhich (Executable, 3.0MB) basename (Executable, 38kB) bashbug (Executable, 6.8kB) +04 (C): base32 (Executable, 42kB) basenc (Executable, 50kB) bass + diff --git a/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__fish_tab_completion_options.snap b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__fish_tab_completion_options.snap new file mode 100644 index 00000000..a093e708 --- /dev/null +++ b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__fish_tab_completion_options.snap @@ -0,0 +1,11 @@ +--- +source: zellij-server/src/panes/./unit/grid_tests.rs +expression: "format!(\"{:?}\", grid)" + +--- +00 (C): Welcome to fish, the friendly interactive shell +01 (C): ⋊> ~/c/mosaic on main ⨯ sudo bandwhich 11:18:26 +02 (C): badblocks (Executable, 33kB) base64 (Executable, 42kB) bash (Executable, 906kB) +03 (C): bandwhich (Executable, 3.0MB) basename (Executable, 38kB) bashbug (Executable, 6.8kB) +04 (C): base32 (Executable, 42kB) basenc (Executable, 50kB) bass + diff --git a/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__git_diff_scrollup.snap b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__git_diff_scrollup.snap new file mode 100644 index 00000000..e4c5e29f --- /dev/null +++ b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__git_diff_scrollup.snap @@ -0,0 +1,34 @@ +--- +source: zellij-server/src/panes/./unit/grid_tests.rs +expression: "format!(\"{:?}\", grid)" + +--- +00 (W): +01 (W): src/terminal_pane/scroll.rs +02 (W): ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────── +03 (C): +04 (C): ────────────────────────────────────────────────┐ +05 (C): use crate::terminal_pane::terminal_character::{ │ +06 (C): ────────────────────────────────────────────────┘ +07 (C): 5 +08 (C): CharacterStyles, TerminalCharacter, EMPTY_TERMINAL_CHARACTER, +09 (C): }; +10 (C): +11 (C): use crate::utils::logging::debug_log_to_file; +12 (C): +13 (C): /* +14 (C): * Scroll +15 (C): * +16 (C): +17 (C): ──────────────┐ +18 (C): impl Scroll { │ +19 (C): ──────────────┘ +20 (C): 663 +21 (C): pub fn move_current_buffer_to_alternative_buffer(&mut self) { +22 (C): self.alternative_buffer = Some(self.canonical_lines.drain(..).collect()); +23 (C): self.alternative_cursor_position = Some(self.cursor_position); +24 (C): self.cursor_position.reset(); +25 (C): self.clear_all(); +26 (C): } +27 (C): : + diff --git a/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__git_log.snap b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__git_log.snap new file mode 100644 index 00000000..6f0225ba --- /dev/null +++ b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__git_log.snap @@ -0,0 +1,34 @@ +--- +source: zellij-server/src/panes/./unit/grid_tests.rs +expression: "format!(\"{:?}\", grid)" + +--- +00 (C): +01 (C): * wip: doesn't render when new tab is created? +02 (C): +03 (C): * wip: doesnt re-render when a new tab is spawned for now +04 (C): +05 (C): * wip: tabs now are a BTreeMap and we can switch between them in both directions +06 (C): +07 (C): * wip: I think that should also be here +08 (C): +09 (C): * wip: cleanup +10 (C): +11 (C): * Spawn a new terminal simultaneously with a new tab +12 (C): +13 (C): * Ensure proper Opening and Closing of tabs +14 (C): +15 (C): * cleanup +16 (C): +17 (C): * more cleanup +18 (C): +19 (C): * tests(snapshots): add 'loading' snapshot to each scenario +20 (C): +21 (C): * fix(tests): update snapshots +22 (C): +23 (C): * Add tests for tabs implementation +24 (C): +25 (C): * wip: added tests, moved tab related stuff to a separate file +26 (C): +27 (C): : + diff --git a/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__htop.snap b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__htop.snap new file mode 100644 index 00000000..a692b163 --- /dev/null +++ b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__htop.snap @@ -0,0 +1,34 @@ +--- +source: zellij-server/src/panes/./unit/grid_tests.rs +expression: "format!(\"{:?}\", grid)" + +--- +00 (C): +01 (C): 1 [||||| 10.1%] Tasks: 73, 413 thr; 1 running +02 (C): 2 [||||||| 13.5%] Load average: 1.03 1.07 1.30 +03 (C): 3 [|||||| 10.8%] Uptime: 22:41:15 +04 (C): 4 [|||||| 10.6%] +05 (C): Mem[|||||||||||||||||||||||||||||||||||||3.28G/15.3G] +06 (C): Swp[ 0K/16.0G] +07 (C): +08 (C): PID USER PRI NI VIRT RES SHR S CPU% MEM% TIME+ Command +09 (C): 1352 aram 20 0 3776M 581M 238M S 8.7 3.7 2h01:10 /usr/lib/firefox/firefox +10 (C): 98777 aram 20 0 537M 6184 4240 S 8.1 0.0 0:00.80 target/debug/mosaic --debug +11 (C): 1669 aram 20 0 2944M 318M 130M S 8.1 2.0 1h01:33 /usr/lib/firefox/firefox -contentproc -childID 6 -i +12 (C): 826 aram 9 -11 1581M 15092 11244 S 6.1 0.1 42:21.83 /usr/bin/pulseaudio --daemonize=no +13 (C): 9419 aram 20 0 533M 7392 3344 S 4.7 0.0 22:01.92 /usr/local/bin/mosaic --max-panes 4 +14 (C): 98913 aram 20 0 537M 6184 4240 S 3.4 0.0 0:00.31 target/debug/mosaic --debug +15 (C): 1505 aram 20 0 3187M 329M 206M S 3.4 2.1 23:35.90 /usr/lib/firefox/firefox -contentproc -childID 2 -i +16 (C): 98912 aram 20 0 537M 6184 4240 S 2.7 0.0 0:00.22 target/debug/mosaic --debug +17 (C): 1164 aram -6 0 1581M 15092 11244 S 2.7 0.1 21:39.80 /usr/bin/pulseaudio --daemonize=no +18 (C): 1247 aram 20 0 1184M 292M 84828 S 2.7 1.9 38:01.54 /usr/lib/Xorg -nolisten tcp :0 vt1 -keeptty -auth / +19 (C): 1475 aram -11 0 3776M 581M 238M S 2.0 3.7 14:27.94 /usr/lib/firefox/firefox +20 (C): 8574 aram 20 0 2944M 318M 130M S 2.0 2.0 14:36.50 /usr/lib/firefox/firefox -contentproc -childID 6 -i +21 (C): 1364 aram 20 0 3776M 581M 238M S 2.0 3.7 18:01.89 /usr/lib/firefox/firefox +22 (C): 1870 aram 20 0 3776M 581M 238M S 2.0 3.7 13:27.06 /usr/lib/firefox/firefox +23 (C): 9427 aram 20 0 533M 7392 3344 S 2.0 0.0 6:53.47 /usr/local/bin/mosaic --max-panes 4 +24 (C): 98905 aram 20 0 537M 6184 4240 S 2.0 0.0 0:00.17 target/debug/mosaic --debug +25 (C): 99272 aram 20 0 8456 4348 3320 R 1.3 0.0 0:00.13 htop +26 (C): 8611 aram 20 0 2944M 318M 130M S 1.3 2.0 8:17.90 /usr/lib/firefox/firefox -contentproc -childID 6 -i +27 (C): F1Help F2Setup F3SearchF4FilterF5Tree F6SortByF7Nice -F8Nice +F9Kill F10Quit + diff --git a/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__htop_right_scrolling.snap b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__htop_right_scrolling.snap new file mode 100644 index 00000000..aca29e3e --- /dev/null +++ b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__htop_right_scrolling.snap @@ -0,0 +1,34 @@ +--- +source: zellij-server/src/panes/./unit/grid_tests.rs +expression: "format!(\"{:?}\", grid)" + +--- +00 (C): +01 (C): 1 [|||||||||| 16.9%] Tasks: 110, 512 thr; 1 running +02 (C): 2 [|||||||||| 17.1%] Load average: 1.04 1.30 1.29 +03 (C): 3 [||||||| 13.9%] Uptime: 6 days, 07:01:39 +04 (C): 4 [||||||||| 14.9%] +05 (C): Mem[|||||||||||||||||||||||||||||||||||||8.80G/15.3G] +06 (C): Swp[| 2.82M/16.0G] +07 (C): +08 (C): PRI NI VIRT RES SHR S CPU% MEM% TIME+ Command +09 (C): 20 0 8576 4508 3356 R 1.3 0.0 0:00.11 htop +10 (C): 20 0 171M 10868 7804 S 0.0 0.1 2:08.38 /sbin/init +11 (C): 20 0 107M 29364 28092 S 0.0 0.2 0:03.42 /usr/lib/systemd/systemd-journald +12 (C): 20 0 32648 9568 6616 S 0.0 0.1 0:01.87 /usr/lib/systemd/systemd-udevd +13 (C): 20 0 78060 992 856 S 0.0 0.0 0:00.00 /usr/bin/lvmetad -f +14 (C): 20 0 6952 4356 3492 S 0.0 0.0 0:57.67 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidf +15 (C): 20 0 14824 7552 5984 S 0.0 0.0 0:12.93 /usr/bin/connmand -n --nodnsproxy +16 (C): 20 0 17696 7940 6696 S 0.0 0.0 0:01.25 /usr/lib/systemd/systemd-logind +17 (C): 20 0 1635M 56148 20460 S 0.0 0.3 1:27.24 /usr/bin/dockerd -H fd:// +18 (C): 20 0 1635M 56148 20460 S 0.0 0.3 0:38.37 /usr/bin/dockerd -H fd:// +19 (C): 20 0 1635M 56148 20460 S 0.0 0.3 0:00.01 /usr/bin/dockerd -H fd:// +20 (C): 20 0 1635M 56148 20460 S 0.0 0.3 0:00.00 /usr/bin/dockerd -H fd:// +21 (C): 20 0 1635M 56148 20460 S 0.0 0.3 0:00.00 /usr/bin/dockerd -H fd:// +22 (C): 20 0 1635M 56148 20460 S 0.0 0.3 0:00.00 /usr/bin/dockerd -H fd:// +23 (C): 20 0 1635M 56148 20460 S 0.0 0.3 1:47.55 /usr/bin/dockerd -H fd:// +24 (C): 20 0 1635M 56148 20460 S 0.0 0.3 1:26.19 /usr/bin/dockerd -H fd:// +25 (C): 20 0 1635M 56148 20460 S 0.0 0.3 1:40.77 /usr/bin/dockerd -H fd:// +26 (C): 20 0 1635M 56148 20460 S 0.0 0.3 1:47.26 /usr/bin/dockerd -H fd:// +27 (C): F1Help F2Setup F3SearchF4FilterF5Tree F6SortByF7Nice -F8Nice +F9Kill F10Quit + diff --git a/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__htop_scrolling.snap b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__htop_scrolling.snap new file mode 100644 index 00000000..5f6c323d --- /dev/null +++ b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__htop_scrolling.snap @@ -0,0 +1,34 @@ +--- +source: zellij-server/src/panes/./unit/grid_tests.rs +expression: "format!(\"{:?}\", grid)" + +--- +00 (C): +01 (C): 1 [||||||||||||||||||||||||||||||||||||||||||100.0%] Tasks: 79, 382 thr; 1 running +02 (C): 2 [ 0.0%] Load average: 1.40 1.43 1.38 +03 (C): 3 [ 0.0%] Uptime: 2 days, 07:33:50 +04 (C): 4 [ 0.0%] +05 (C): Mem[|||||||||||||||||||||||||||||||||||||3.64G/15.3G] +06 (C): Swp[ 0K/16.0G] +07 (C): +08 (C): PID USER PRI NI VIRT RES SHR S CPU% MEM% TIME+ Command +09 (W): 123934 aram 20 0 8444 4384 3364 R 66.7 0.0 0:00.05 htop --delay=100000000000 +10 (C): 1 root 20 0 171M 11616 8608 S 0.0 0.1 0:56.91 /sbin/init +11 (C): 268 root 20 0 93324 34340 33072 S 0.0 0.2 0:01.05 /usr/lib/systemd/systemd-journald +12 (C): 276 root 20 0 32648 10192 7240 S 0.0 0.1 0:01.13 /usr/lib/systemd/systemd-udevd +13 (C): 286 root 20 0 78060 1132 996 S 0.0 0.0 0:00.00 /usr/bin/lvmetad -f +14 (C): 343 dbus 20 0 6952 4384 3520 S 0.0 0.0 0:13.85 /usr/bin/dbus-daemon --system --address=systemd: -- +15 (C): 344 root 20 0 14588 7512 6176 S 0.0 0.0 0:03.21 /usr/bin/connmand -n --nodnsproxy +16 (C): 345 root 20 0 17696 8372 7128 S 0.0 0.1 0:00.67 /usr/lib/systemd/systemd-logind +17 (C): 395 root 20 0 1635M 83324 44976 S 0.0 0.5 0:32.43 /usr/bin/dockerd -H fd:// +18 (C): 396 root 20 0 1635M 83324 44976 S 0.0 0.5 0:00.01 /usr/bin/dockerd -H fd:// +19 (C): 397 root 20 0 1635M 83324 44976 S 0.0 0.5 0:00.01 /usr/bin/dockerd -H fd:// +20 (C): 398 root 20 0 1635M 83324 44976 S 0.0 0.5 0:00.00 /usr/bin/dockerd -H fd:// +21 (C): 399 root 20 0 1635M 83324 44976 S 0.0 0.5 0:00.00 /usr/bin/dockerd -H fd:// +22 (C): 412 root 20 0 1635M 83324 44976 S 0.0 0.5 0:00.00 /usr/bin/dockerd -H fd:// +23 (C): 441 root 20 0 1635M 83324 44976 S 0.0 0.5 0:41.35 /usr/bin/dockerd -H fd:// +24 (C): 442 root 20 0 1635M 83324 44976 S 0.0 0.5 0:33.61 /usr/bin/dockerd -H fd:// +25 (C): 444 root 20 0 1635M 83324 44976 S 0.0 0.5 0:33.13 /usr/bin/dockerd -H fd:// +26 (C): 449 root 20 0 1635M 83324 44976 S 0.0 0.5 0:41.39 /usr/bin/dockerd -H fd:// +27 (C): F1Help F2Setup F3SearchF4FilterF5Tree F6SortByF7Nice -F8Nice +F9Kill F10Quit + diff --git a/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__neovim_insert_mode.snap b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__neovim_insert_mode.snap new file mode 100644 index 00000000..9c2536d4 --- /dev/null +++ b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__neovim_insert_mode.snap @@ -0,0 +1,34 @@ +--- +source: zellij-server/src/panes/./unit/grid_tests.rs +expression: "format!(\"{:?}\", grid)" + +--- +00 (C): line 1 +01 (C): line 2 +02 (C): line 3 +03 (C): line 4 +04 (C): line 5 +05 (C): line 6 +06 (C): line 7 +07 (C): line 8 +08 (C): line 9 +09 (C): line 10 +10 (C): line 11 +11 (C): line 12 +12 (C): line 13 +13 (C): line 14 +14 (C): line 15 +15 (C): line 16 +16 (C): line 17 +17 (C): line 18 +18 (C): line 19 +19 (C): line 20 +20 (C): line 21 +21 (C): line 22 +22 (C): line 23 +23 (C): line 24 +24 (C): line 25 +25 (C): line 26 +26 (C): some-file 10,1 Top +27 (C): -- INSERT -- + diff --git a/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__run_bandwhich_from_fish_shell.snap b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__run_bandwhich_from_fish_shell.snap new file mode 100644 index 00000000..257fd889 --- /dev/null +++ b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__run_bandwhich_from_fish_shell.snap @@ -0,0 +1,34 @@ +--- +source: zellij-server/src/panes/./unit/grid_tests.rs +expression: "format!(\"{:?}\", grid)" + +--- +00 (C): Total Up / Down: 46Bps / 57Bps +01 (C): ┌Utilization by process name───────────────────────────────────────────────────────────────────────────────────────┐ +02 (C): │Process Connections Up / Down │ +03 (C): │ │ +04 (C): │firefox 3 46Bps / 57Bps │ +05 (C): │ │ +06 (C): │ │ +07 (C): │ │ +08 (C): │ │ +09 (C): │ │ +10 (C): │ │ +11 (C): │ │ +12 (C): │ │ +13 (C): │ │ +14 (C): │ │ +15 (C): │ │ +16 (C): │ │ +17 (C): │ │ +18 (C): │ │ +19 (C): │ │ +20 (C): │ │ +21 (C): │ │ +22 (C): │ │ +23 (C): │ │ +24 (C): │ │ +25 (C): │ │ +26 (C): └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +27 (C): Press <SPACE> to pause. Use <TAB> to rearrange tables. (DNS queries hidden). + diff --git a/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__top_and_quit.snap b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__top_and_quit.snap new file mode 100644 index 00000000..250e5b45 --- /dev/null +++ b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__top_and_quit.snap @@ -0,0 +1,62 @@ +--- +source: zellij-server/src/panes/./unit/grid_tests.rs +expression: "format!(\"{:?}\", grid)" + +--- +00 (C): Tasks: 158 total, 1 running, 157 sleeping, 0 stopped, 0 zombie +01 (C): %Cpu(s): 24.2 us, 1.6 sy, 0.0 ni, 74.2 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st +02 (C): MiB Mem : 15715.1 total, 7001.4 free, 2163.7 used, 6549.9 buff/cache +03 (C): MiB Swap: 16384.0 total, 16384.0 free, 0.0 used. 12809.8 avail Mem +04 (C): +05 (C): PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND +06 (C): 15838 aram 20 0 7275240 56912 18964 S 73.3 0.4 0:17.79 zellij +07 (C): 12653 aram 20 0 39032 22164 14372 S 20.0 0.1 0:00.63 urxvt +08 (C): 1477 aram 20 0 3178660 301992 203236 S 6.7 1.9 3:49.82 Web Content +09 (C): 1 root 20 0 175360 11532 8596 S 0.0 0.1 0:05.90 systemd +10 (C): 2 root 20 0 0 0 0 S 0.0 0.0 0:00.01 kthreadd +11 (C): 3 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 rcu_gp +12 (C): 4 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 rcu_par_gp +13 (C): 6 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/0:0H-kblockd +14 (C): 8 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 mm_percpu_wq +15 (C): 9 root 20 0 0 0 0 S 0.0 0.0 0:01.24 ksoftirqd/0 +16 (C): 10 root -2 0 0 0 0 S 0.0 0.0 0:00.00 rcuc/0 +17 (C): 11 root -2 0 0 0 0 I 0.0 0.0 0:06.12 rcu_preempt +18 (C): 12 root -2 0 0 0 0 S 0.0 0.0 0:00.00 rcub/0 +19 (C): 13 root rt 0 0 0 0 S 0.0 0.0 0:00.01 migration/0 +20 (C): 14 root -51 0 0 0 0 S 0.0 0.0 0:00.00 idle_inject/0 +21 (C): 16 root 20 0 0 0 0 S 0.0 0.0 0:00.00 cpuhp/0 +22 (C): 17 root 20 0 0 0 0 S 0.0 0.0 0:00.00 cpuhp/1 +23 (C): 18 root -51 0 0 0 0 S 0.0 0.0 0:00.00 idle_inject/1 +24 (C): 19 root rt 0 0 0 0 S 0.0 0.0 0:00.35 migration/1 +25 (C): 20 root -2 0 0 0 0 S 0.0 0.0 0:00.00 rcuc/1 +26 (C): 21 root 20 0 0 0 0 S 0.0 0.0 0:00.49 ksoftirqd/1 +27 (C): 23 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/1:0H-kblockd +28 (C): 24 root 20 0 0 0 0 S 0.0 0.0 0:00.00 cpuhp/2 +29 (C): 25 root -51 0 0 0 0 S 0.0 0.0 0:00.00 idle_inject/2 +30 (C): 26 root rt 0 0 0 0 S 0.0 0.0 0:00.39 migration/2 +31 (C): 27 root -2 0 0 0 0 S 0.0 0.0 0:00.00 rcuc/2 +32 (C): 28 root 20 0 0 0 0 S 0.0 0.0 0:00.99 ksoftirqd/2 +33 (C): 30 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/2:0H-kblockd +34 (C): 31 root 20 0 0 0 0 S 0.0 0.0 0:00.00 cpuhp/3 +35 (C): 32 root -51 0 0 0 0 S 0.0 0.0 0:00.00 idle_inject/3 +36 (C): 33 root rt 0 0 0 0 S 0.0 0.0 0:00.43 migration/3 +37 (C): 34 root -2 0 0 0 0 S 0.0 0.0 0:00.00 rcuc/3 +38 (C): 35 root 20 0 0 0 0 S 0.0 0.0 0:00.90 ksoftirqd/3 +39 (C): 37 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/3:0H-kblockd +40 (C): 38 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kdevtmpfs +41 (C): 39 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 netns +42 (C): 40 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_tasks_kthre +43 (C): 41 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kauditd +44 (C): 44 root 20 0 0 0 0 S 0.0 0.0 0:00.00 khungtaskd +45 (C): 45 root 20 0 0 0 0 S 0.0 0.0 0:00.00 oom_reaper +46 (C): 46 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 writeback +47 (C): 47 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kcompactd0 +48 (C): 48 root 25 5 0 0 0 S 0.0 0.0 0:00.00 ksmd +49 (C): 49 root 39 19 0 0 0 S 0.0 0.0 0:00.00 khugepaged +50 (C): 137 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kintegrityd +51 (C): 138 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kblockd +52 (C): 139 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 blkcg_punt_bio +53 (C): 140 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 ata_sff +54 (C): 141 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 edac-poller +55 (C): ⋊> ~/c/zellij on fix-top ⨯ 13:00:53 + diff --git a/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__vim_ctrl_d.snap b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__vim_ctrl_d.snap new file mode 100644 index 00000000..e9b83504 --- /dev/null +++ b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__vim_ctrl_d.snap @@ -0,0 +1,34 @@ +--- +source: zellij-server/src/panes/./unit/grid_tests.rs +expression: "format!(\"{:?}\", grid)" + +--- +00 (C): 3 line14 +01 (C): 2 line15 +02 (C): 1 line16 +03 (C): 17 line17 +04 (C): 1 line18 +05 (C): 2 line19 +06 (C): 3 line20 +07 (C): 4 line21 +08 (C): 5 line22 +09 (C): 6 line23 +10 (C): 7 line24 +11 (C): 8 line25 +12 (C): 9 line26 +13 (C): 10 line27 +14 (C): 11 line28 +15 (C): 12 line29 +16 (C): 13 line30 +17 (C): 14 line31 +18 (C): 15 line32 +19 (C): 16 line33 +20 (C): 17 line34 +21 (C): 18 line35 +22 (C): 19 line36 +23 (C): 20 line37 +24 (C): 21 line38 +25 (C): 22 line39 +26 (C): NORMAL testfile.rs unix | utf-8 | rust 40% 17:1 +27 (C): + diff --git a/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__vim_ctrl_u.snap b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__vim_ctrl_u.snap new file mode 100644 index 00000000..f886a2eb --- /dev/null +++ b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__vim_ctrl_u.snap @@ -0,0 +1,34 @@ +--- +source: zellij-server/src/panes/./unit/grid_tests.rs +expression: "format!(\"{:?}\", grid)" + +--- +00 (C): 22 line4 +01 (C): 21 line5 +02 (C): 20 line6 +03 (C): 19 line7 +04 (C): 18 line8 +05 (C): 17 line9 +06 (C): 16 line10 +07 (C): 15 line11 +08 (C): 14 line12 +09 (C): 13 line13 +10 (C): 12 line14 +11 (C): 11 line15 +12 (C): 10 line16 +13 (C): 9 line17 +14 (C): 8 line18 +15 (C): 7 line19 +16 (C): 6 line20 +17 (C): 5 line21 +18 (C): 4 line22 +19 (C): 3 line23 +20 (C): 2 line24 +21 (C): 1 line25 +22 (C): 26 line26 +23 (C): 1 line27 +24 (C): 2 line28 +25 (C): 3 line29 +26 (C): NORMAL testfile.rs unix | utf-8 | rust 61% 26:1 +27 (C): + diff --git a/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__vim_overwrite.snap b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__vim_overwrite.snap new file mode 100644 index 00000000..f8066d6a --- /dev/null +++ b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__vim_overwrite.snap @@ -0,0 +1,34 @@ +--- +source: zellij-server/src/panes/./unit/grid_tests.rs +expression: "format!(\"{:?}\", grid)" + +--- +00 (C): 1 +01 (C): 1 line 1 +02 (C): 2 line 2 +03 (C): 3 line 3 +04 (C): 4 line 4 +05 (C): 5 line 5 +06 (C): 6 line 6 +07 (C): 7 line 7 +08 (C): 8 line 8 +09 (C): 9 line 9 +10 (C): 10 line 10 +11 (C): 11 line 11 +12 (C): 12 line 12 +13 (C): 13 line 13 +14 (C): 14 line 14 +15 (C): 15 line 15 +16 (C): 16 line 16 +17 (C): 17 line 17 +18 (C): 18 line 18 +19 (C): 19 line 19 +20 (C): 20 line 20 +21 (C): 21 line 21 +22 (C): 22 line 22 +23 (C): 23 line 23 +24 (C): 24 line 24 +25 (C): 25 line 25 +26 (C): NORMAL some-file unix | utf-8 | no ft 1% 1:1 +27 (C): + diff --git a/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__vim_scroll_region_down.snap b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__vim_scroll_region_down.snap new file mode 100644 index 00000000..17a18220 --- /dev/null +++ b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__grid__grid_tests__vim_scroll_region_down.snap @@ -0,0 +1,34 @@ +--- +source: zellij-server/src/panes/./unit/grid_tests.rs +expression: "format!(\"{:?}\", grid)" + +--- +00 (C): 22 line2 +01 (C): 21 line3 +02 (C): 20 line4 +03 (C): 19 line5 +04 (C): 18 line6 +05 (C): 17 line7 +06 (C): 16 line8 +07 (C): 15 line9 +08 (C): 14 line10 +09 (C): 13 line11 +10 (C): 12 line12 +11 (C): 11 line13 +12 (C): 10 line14 +13 (C): 9 line15 +14 (C): 8 line16 +15 (C): 7 line17 +16 (C): 6 line18 +17 (C): 5 line19 +18 (C): 4 line20 +19 (C): 3 line21 +20 (C): 2 line22 +21 (C): 1 line23 +22 (C): 24 line24 +23 (C): 1 line25 +24 (C): 2 line26 +25 (C): 3 line27 +26 (C): NORMAL testfile.rs unix | utf-8 | rust 57% 24:1 +27 (C): + diff --git a/zellij-server/src/panes/unit/snapshots/zellij_server__panes__terminal_pane__grid_tests__scrolling_inside_a_pane-2.snap b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__terminal_pane__grid_tests__scrolling_inside_a_pane-2.snap new file mode 100644 index 00000000..cd74ae8f --- /dev/null +++ b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__terminal_pane__grid_tests__scrolling_inside_a_pane-2.snap @@ -0,0 +1,26 @@ +--- +source: zellij-server/src/panes/./unit/terminal_pane_tests.rs +expression: "format!(\"{:?}\", terminal_pane . grid)" + +--- +00 (C): line 5 +01 (C): line 6 +02 (C): line 7 +03 (C): line 8 +04 (C): line 9 +05 (C): line 10 +06 (C): line 11 +07 (C): line 12 +08 (C): line 13 +09 (C): line 14 +10 (C): line 15 +11 (C): line 16 +12 (C): line 17 +13 (C): line 18 +14 (C): line 19 +15 (C): line 20 +16 (C): line 21 +17 (C): line 22 +18 (C): line 23 +19 (C): line 24 + diff --git a/zellij-server/src/panes/unit/snapshots/zellij_server__panes__terminal_pane__grid_tests__scrolling_inside_a_pane-3.snap b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__terminal_pane__grid_tests__scrolling_inside_a_pane-3.snap new file mode 100644 index 00000000..4c1776c0 --- /dev/null +++ b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__terminal_pane__grid_tests__scrolling_inside_a_pane-3.snap @@ -0,0 +1,26 @@ +--- +source: zellij-server/src/panes/./unit/terminal_pane_tests.rs +expression: "format!(\"{:?}\", terminal_pane . grid)" + +--- +00 (C): line 12 +01 (C): line 13 +02 (C): line 14 +03 (C): line 15 +04 (C): line 16 +05 (C): line 17 +06 (C): line 18 +07 (C): line 19 +08 (C): line 20 +09 (C): line 21 +10 (C): line 22 +11 (C): line 23 +12 (C): line 24 +13 (C): line 25 +14 (C): line 26 +15 (C): line 27 +16 (C): line 28 +17 (C): line 29 +18 (C): line 30 +19 (C): + diff --git a/zellij-server/src/panes/unit/snapshots/zellij_server__panes__terminal_pane__grid_tests__scrolling_inside_a_pane.snap b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__terminal_pane__grid_tests__scrolling_inside_a_pane.snap new file mode 100644 index 00000000..0d852f68 --- /dev/null +++ b/zellij-server/src/panes/unit/snapshots/zellij_server__panes__terminal_pane__grid_tests__scrolling_inside_a_pane.snap @@ -0,0 +1,26 @@ +--- +source: zellij-server/src/panes/./unit/terminal_pane_tests.rs +expression: "format!(\"{:?}\", terminal_pane . grid)" + +--- +00 (C): line 2 +01 (C): line 3 +02 (C): line 4 +03 (C): line 5 +04 (C): line 6 +05 (C): line 7 +06 (C): line 8 +07 (C): line 9 +08 (C): line 10 +09 (C): line 11 +10 (C): line 12 +11 (C): line 13 +12 (C): line 14 +13 (C): line 15 +14 (C): line 16 +15 (C): line 17 +16 (C): line 18 +17 (C): line 19 +18 (C): line 20 +19 (C): line 21 + diff --git a/zellij-server/src/panes/unit/terminal_pane_tests.rs b/zellij-server/src/panes/unit/terminal_pane_tests.rs new file mode 100644 index 00000000..f3abf91a --- /dev/null +++ b/zellij-server/src/panes/unit/terminal_pane_tests.rs @@ -0,0 +1,30 @@ +use super::super::TerminalPane; +use crate::tab::Pane; +use ::insta::assert_snapshot; +use zellij_utils::pane_size::PositionAndSize; +use zellij_utils::zellij_tile::data::Palette; + +#[test] +pub fn scrolling_inside_a_pane() { + let fake_win_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let pid = 1; + let palette = Palette::default(); + let mut terminal_pane = TerminalPane::new(pid, fake_win_size, palette); + let mut text_to_fill_pane = String::new(); + for i in 0..30 { + text_to_fill_pane.push_str(&format!("\rline {}\n", i + 1)); + } + terminal_pane.handle_pty_bytes(text_to_fill_pane.as_bytes().to_vec()); + terminal_pane.scroll_up(10); + assert_snapshot!(format!("{:?}", terminal_pane.grid)); + terminal_pane.scroll_down(3); + assert_snapshot!(format!("{:?}", terminal_pane.grid)); + terminal_pane.clear_scroll(); + assert_snapshot!(format!("{:?}", terminal_pane.grid)); +} diff --git a/zellij-server/src/screen.rs b/zellij-server/src/screen.rs index 009a3a92..88fb7848 100644 --- a/zellij-server/src/screen.rs +++ b/zellij-server/src/screen.rs @@ -393,6 +393,16 @@ impl Screen { tab.mode_info = self.mode_info.clone(); } } + pub fn move_focus_left_or_previous_tab(&mut self) { + if !self.get_active_tab_mut().unwrap().move_focus_left() { + self.switch_tab_prev(); + } + } + pub fn move_focus_right_or_next_tab(&mut self) { + if !self.get_active_tab_mut().unwrap().move_focus_right() { + self.switch_tab_next(); + } + } } // The box is here in order to make the @@ -507,9 +517,7 @@ pub(crate) fn screen_thread_main( screen.get_active_tab_mut().unwrap().move_focus_left(); } ScreenInstruction::MoveFocusLeftOrPreviousTab => { - if !screen.get_active_tab_mut().unwrap().move_focus_left() { - screen.switch_tab_prev(); - } + screen.move_focus_left_or_previous_tab(); screen .bus .senders @@ -523,9 +531,7 @@ pub(crate) fn screen_thread_main( screen.get_active_tab_mut().unwrap().move_focus_right(); } ScreenInstruction::MoveFocusRightOrNextTab => { - if !screen.get_active_tab_mut().unwrap().move_focus_right() { - screen.switch_tab_next(); - } + screen.move_focus_right_or_next_tab(); screen .bus .senders @@ -674,3 +680,7 @@ pub(crate) fn screen_thread_main( } } } + +#[cfg(test)] +#[path = "./unit/screen_tests.rs"] +mod screen_tests; diff --git a/zellij-server/src/tab.rs b/zellij-server/src/tab.rs index fbcb5ada..523f65df 100644 --- a/zellij-server/src/tab.rs +++ b/zellij-server/src/tab.rs @@ -2272,3 +2272,7 @@ impl Tab { } } } + +#[cfg(test)] +#[path = "./unit/tab_tests.rs"] +mod tab_tests; diff --git a/zellij-server/src/thread_bus.rs b/zellij-server/src/thread_bus.rs index f7c1c1eb..c7262993 100644 --- a/zellij-server/src/thread_bus.rs +++ b/zellij-server/src/thread_bus.rs @@ -7,12 +7,15 @@ use crate::{ use zellij_utils::{channels, channels::SenderWithContext, errors::ErrorContext}; /// A container for senders to the different threads in zellij on the server side -#[derive(Clone)] +#[derive(Default, Clone)] pub(crate) struct ThreadSenders { pub to_screen: Option<SenderWithContext<ScreenInstruction>>, pub to_pty: Option<SenderWithContext<PtyInstruction>>, pub to_plugin: Option<SenderWithContext<PluginInstruction>>, pub to_server: Option<SenderWithContext<ServerInstruction>>, + // this is a convenience for the unit tests + // it's not advisable to set it to true in production code + pub should_silently_fail: bool, } impl ThreadSenders { @@ -20,32 +23,75 @@ impl ThreadSenders { &self, instruction: ScreenInstruction, ) -> Result<(), channels::SendError<(ScreenInstruction, ErrorContext)>> { - self.to_screen.as_ref().unwrap().send(instruction) + if self.should_silently_fail { + let _ = self + .to_screen + .as_ref() + .map(|sender| sender.send(instruction)) + .unwrap_or_else(|| Ok(())); + Ok(()) + } else { + self.to_screen.as_ref().unwrap().send(instruction) + } } pub fn send_to_pty( &self, instruction: PtyInstruction, ) -> Result<(), channels::SendError<(PtyInstruction, ErrorContext)>> { - self.to_pty.as_ref().unwrap().send(instruction) + if self.should_silently_fail { + let _ = self + .to_pty + .as_ref() + .map(|sender| sender.send(instruction)) + .unwrap_or_else(|| Ok(())); + Ok(()) + } else { + self.to_pty.as_ref().unwrap().send(instruction) + } } pub fn send_to_plugin( &self, instruction: PluginInstruction, ) -> Result<(), channels::SendError<(PluginInstruction, ErrorContext)>> { - self.to_plugin.as_ref().unwrap().send(instruction) + if self.should_silently_fail { + let _ = self + .to_plugin + .as_ref() + .map(|sender| sender.send(instruction)) + .unwrap_or_else(|| Ok(())); + Ok(()) + } else { + self.to_plugin.as_ref().unwrap().send(instruction) + } } pub fn send_to_server( &self, instruction: ServerInstruction, ) -> Result<(), channels::SendError<(ServerInstruction, ErrorContext)>> { - self.to_server.as_ref().unwrap().send(instruction) + if self.should_silently_fail { + let _ = self + .to_server + .as_ref() + .map(|sender| sender.send(instruction)) + .unwrap_or_else(|| Ok(())); + Ok(()) + } else { + self.to_server.as_ref().unwrap().send(instruction) + } + } + #[allow(unused)] + pub fn silently_fail_on_send(mut self) -> Self { + // this is mostly used for the tests, see struct + self.should_silently_fail = true; + self } } /// A container for a receiver, OS input and the senders to a given thread +#[derive(Default)] pub(crate) struct Bus<T> { receivers: Vec<channels::Receiver<(T, ErrorContext)>>, pub senders: ThreadSenders, @@ -68,10 +114,26 @@ impl<T> Bus<T> { to_pty: to_pty.cloned(), to_plugin: to_plugin.cloned(), to_server: to_server.cloned(), + should_silently_fail: false, }, os_input: os_input.clone(), } } + #[allow(unused)] + pub fn empty() -> Self { + // this is mostly used for the tests + Bus { + receivers: vec![], + senders: ThreadSenders { + to_screen: None, + to_pty: None, + to_plugin: None, + to_server: None, + should_silently_fail: true, + }, + os_input: None, + } + } pub fn recv(&self) -> Result<(T, ErrorContext), channels::RecvError> { let mut selector = channels::Select::new(); diff --git a/zellij-server/src/unit/screen_tests.rs b/zellij-server/src/unit/screen_tests.rs new file mode 100644 index 00000000..da52c585 --- /dev/null +++ b/zellij-server/src/unit/screen_tests.rs @@ -0,0 +1,255 @@ +use super::{Screen, ScreenInstruction}; +use crate::zellij_tile::data::{InputMode, ModeInfo, Palette}; +use crate::{ + os_input_output::{AsyncReader, Pid, ServerOsApi}, + thread_bus::Bus, + SessionState, +}; +use std::sync::{Arc, RwLock}; +use zellij_utils::pane_size::PositionAndSize; + +use std::os::unix::io::RawFd; +use std::path::PathBuf; + +use zellij_utils::ipc::ClientAttributes; +use zellij_utils::nix; + +use zellij_utils::{ + errors::ErrorContext, + interprocess::local_socket::LocalSocketStream, + ipc::{ClientToServerMsg, ServerToClientMsg}, +}; + +#[derive(Clone)] +struct FakeInputOutput {} + +impl ServerOsApi for FakeInputOutput { + fn set_terminal_size_using_fd(&self, _fd: RawFd, _cols: u16, _rows: u16) { + // noop + } + fn spawn_terminal(&self, _file_to_open: Option<PathBuf>) -> (RawFd, Pid) { + unimplemented!() + } + fn read_from_tty_stdout(&self, _fd: RawFd, _buf: &mut [u8]) -> Result<usize, nix::Error> { + unimplemented!() + } + fn async_file_reader(&self, _fd: RawFd) -> Box<dyn AsyncReader> { + unimplemented!() + } + fn write_to_tty_stdin(&self, _fd: RawFd, _buf: &[u8]) -> Result<usize, nix::Error> { + unimplemented!() + } + fn tcdrain(&self, _fd: RawFd) -> Result<(), nix::Error> { + unimplemented!() + } + fn box_clone(&self) -> Box<dyn ServerOsApi> { + Box::new((*self).clone()) + } + fn kill(&self, _pid: Pid) -> Result<(), nix::Error> { + unimplemented!() + } + fn recv_from_client(&self) -> (ClientToServerMsg, ErrorContext) { + unimplemented!() + } + fn send_to_client(&self, _msg: ServerToClientMsg) { + unimplemented!() + } + fn add_client_sender(&self) { + unimplemented!() + } + fn send_to_temp_client(&self, _msg: ServerToClientMsg) { + unimplemented!() + } + fn remove_client_sender(&self) { + unimplemented!() + } + fn update_receiver(&mut self, _stream: LocalSocketStream) { + unimplemented!() + } + fn load_palette(&self) -> Palette { + unimplemented!() + } +} + +fn create_new_screen(position_and_size: PositionAndSize) -> Screen { + let mut bus: Bus<ScreenInstruction> = Bus::empty(); + let fake_os_input = FakeInputOutput {}; + bus.os_input = Some(Box::new(fake_os_input)); + let mut client_attributes = ClientAttributes::default(); + client_attributes.position_and_size = position_and_size; + let max_panes = None; + let mode_info = ModeInfo::default(); + let input_mode = InputMode::Normal; + let session_state = Arc::new(RwLock::new(SessionState::Attached)); + Screen::new( + bus, + &client_attributes, + max_panes, + mode_info, + input_mode, + session_state, + ) +} + +#[test] +fn open_new_tab() { + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut screen = create_new_screen(position_and_size); + + screen.new_tab(1); + screen.new_tab(2); + + assert_eq!(screen.tabs.len(), 2, "Screen now has two tabs"); + assert_eq!( + screen.get_active_tab().unwrap().position, + 1, + "Active tab switched to new tab" + ); +} + +#[test] +pub fn switch_to_prev_tab() { + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut screen = create_new_screen(position_and_size); + + screen.new_tab(1); + screen.new_tab(2); + screen.switch_tab_prev(); + + assert_eq!( + screen.get_active_tab().unwrap().position, + 0, + "Active tab switched to previous tab" + ); +} + +#[test] +pub fn switch_to_next_tab() { + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut screen = create_new_screen(position_and_size); + + screen.new_tab(1); + screen.new_tab(2); + screen.switch_tab_prev(); + screen.switch_tab_next(); + + assert_eq!( + screen.get_active_tab().unwrap().position, + 1, + "Active tab switched to next tab" + ); +} + +#[test] +pub fn close_tab() { + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut screen = create_new_screen(position_and_size); + + screen.new_tab(1); + screen.new_tab(2); + screen.close_tab(); + + assert_eq!(screen.tabs.len(), 1, "Only one tab left"); + assert_eq!( + screen.get_active_tab().unwrap().position, + 0, + "Active tab switched to previous tab" + ); +} + +#[test] +pub fn close_the_middle_tab() { + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut screen = create_new_screen(position_and_size); + + screen.new_tab(1); + screen.new_tab(2); + screen.new_tab(3); + screen.switch_tab_prev(); + screen.close_tab(); + + assert_eq!(screen.tabs.len(), 2, "Two tabs left"); + assert_eq!( + screen.get_active_tab().unwrap().position, + 0, + "Active tab switched to previous tab" + ); +} + +#[test] +fn move_focus_left_at_left_screen_edge_changes_tab() { + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut screen = create_new_screen(position_and_size); + + screen.new_tab(1); + screen.new_tab(2); + screen.new_tab(3); + screen.switch_tab_prev(); + screen.move_focus_left_or_previous_tab(); + + assert_eq!( + screen.get_active_tab().unwrap().position, + 0, + "Active tab switched to previous" + ); +} + +#[test] +fn move_focus_right_at_right_screen_edge_changes_tab() { + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut screen = create_new_screen(position_and_size); + + screen.new_tab(1); + screen.new_tab(2); + screen.new_tab(3); + screen.switch_tab_prev(); + screen.move_focus_right_or_next_tab(); + + assert_eq!( + screen.get_active_tab().unwrap().position, + 2, + "Active tab switched to next" + ); +} diff --git a/zellij-server/src/unit/tab_tests.rs b/zellij-server/src/unit/tab_tests.rs new file mode 100644 index 00000000..87c3be71 --- /dev/null +++ b/zellij-server/src/unit/tab_tests.rs @@ -0,0 +1,11840 @@ +use super::Tab; +use crate::zellij_tile::data::{InputMode, ModeInfo, Palette}; +use crate::{ + os_input_output::{AsyncReader, Pid, ServerOsApi}, + panes::PaneId, + thread_bus::ThreadSenders, + SessionState, +}; +use std::sync::{Arc, RwLock}; +use zellij_utils::pane_size::PositionAndSize; + +use std::os::unix::io::RawFd; +use std::path::PathBuf; + +use zellij_utils::nix; + +use zellij_utils::{ + errors::ErrorContext, + interprocess::local_socket::LocalSocketStream, + ipc::{ClientToServerMsg, ServerToClientMsg}, +}; + +struct FakeInputOutput {} + +impl ServerOsApi for FakeInputOutput { + fn set_terminal_size_using_fd(&self, _fd: RawFd, _cols: u16, _rows: u16) { + // noop + } + fn spawn_terminal(&self, _file_to_open: Option<PathBuf>) -> (RawFd, Pid) { + unimplemented!() + } + fn read_from_tty_stdout(&self, _fd: RawFd, _buf: &mut [u8]) -> Result<usize, nix::Error> { + unimplemented!() + } + fn async_file_reader(&self, _fd: RawFd) -> Box<dyn AsyncReader> { + unimplemented!() + } + fn write_to_tty_stdin(&self, _fd: RawFd, _buf: &[u8]) -> Result<usize, nix::Error> { + unimplemented!() + } + fn tcdrain(&self, _fd: RawFd) -> Result<(), nix::Error> { + unimplemented!() + } + fn box_clone(&self) -> Box<dyn ServerOsApi> { + unimplemented!() + } + fn kill(&self, _pid: Pid) -> Result<(), nix::Error> { + unimplemented!() + } + fn recv_from_client(&self) -> (ClientToServerMsg, ErrorContext) { + unimplemented!() + } + fn send_to_client(&self, _msg: ServerToClientMsg) { + unimplemented!() + } + fn add_client_sender(&self) { + unimplemented!() + } + fn send_to_temp_client(&self, _msg: ServerToClientMsg) { + unimplemented!() + } + fn remove_client_sender(&self) { + unimplemented!() + } + fn update_receiver(&mut self, _stream: LocalSocketStream) { + unimplemented!() + } + fn load_palette(&self) -> Palette { + unimplemented!() + } +} + +fn create_new_tab(position_and_size: PositionAndSize) -> Tab { + let index = 0; + let position = 0; + let name = String::new(); + let os_api = Box::new(FakeInputOutput {}); + let senders = ThreadSenders::default().silently_fail_on_send(); + let max_panes = None; + let first_pane_id = Some(PaneId::Terminal(1)); + let mode_info = ModeInfo::default(); + let input_mode = InputMode::Normal; + let colors = Palette::default(); + let session_state = Arc::new(RwLock::new(SessionState::Attached)); + Tab::new( + index, + position, + name, + &position_and_size, + os_api, + senders, + max_panes, + first_pane_id, + mode_info, + input_mode, + colors, + session_state, + ) +} + +#[test] +fn split_panes_vertically() { + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + let new_pane_id = PaneId::Terminal(2); + tab.vertical_split(new_pane_id); + assert_eq!(tab.panes.len(), 2, "The tab has two panes"); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "first pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "first pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 60, + "first pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 20, + "first pane row count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 61, + "second pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 0, + "second pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 60, + "second pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 20, + "second pane row count" + ); +} + +#[test] +fn split_panes_horizontally() { + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + let new_pane_id = PaneId::Terminal(2); + tab.horizontal_split(new_pane_id); + assert_eq!(tab.panes.len(), 2, "The tab has two panes"); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "first pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "first pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 121, + "first pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 10, + "first pane row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 0, + "second pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 11, + "second pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 121, + "second pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 9, + "second pane row count" + ); +} + +#[test] +fn split_largest_pane() { + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + for i in 2..5 { + let new_pane_id = PaneId::Terminal(i); + tab.new_pane(new_pane_id); + } + assert_eq!(tab.panes.len(), 4, "The tab has four panes"); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "first pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "first pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 60, + "first pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 10, + "first pane row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 61, + "second pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 0, + "second pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 60, + "second pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 10, + "second pane row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 0, + "third pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 11, + "third pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 60, + "third pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 9, + "third pane row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .x, + 61, + "fourth pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .y, + 11, + "fourth pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .cols, + 60, + "fourth pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .rows, + 9, + "fourth pane row count" + ); +} + +#[test] +pub fn cannot_split_panes_vertically_when_active_terminal_is_too_small() { + let position_and_size = PositionAndSize { + cols: 8, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.vertical_split(PaneId::Terminal(2)); + assert_eq!(tab.panes.len(), 1, "Tab still has only one pane"); +} + +#[test] +pub fn cannot_split_panes_vertically_when_active_pane_is_too_small() { + let position_and_size = PositionAndSize { + cols: 8, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.vertical_split(PaneId::Terminal(2)); + assert_eq!(tab.panes.len(), 1, "Tab still has only one pane"); +} + +#[test] +pub fn cannot_split_panes_horizontally_when_active_pane_is_too_small() { + let position_and_size = PositionAndSize { + cols: 121, + rows: 4, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.horizontal_split(PaneId::Terminal(2)); + assert_eq!(tab.panes.len(), 1, "Tab still has only one pane"); +} + +#[test] +pub fn cannot_split_largest_pane_when_there_is_no_room() { + let position_and_size = PositionAndSize { + cols: 8, + rows: 4, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.new_pane(PaneId::Terminal(2)); + assert_eq!(tab.panes.len(), 1, "Tab still has only one pane"); +} + +#[test] +pub fn toggle_focused_pane_fullscreen() { + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + for i in 2..5 { + let new_pane_id = PaneId::Terminal(i); + tab.new_pane(new_pane_id); + } + tab.toggle_active_pane_fullscreen(); + assert_eq!( + tab.panes.get(&PaneId::Terminal(4)).unwrap().x(), + 0, + "Pane x is on screen edge" + ); + assert_eq!( + tab.panes.get(&PaneId::Terminal(4)).unwrap().y(), + 0, + "Pane y is on screen edge" + ); + assert_eq!( + tab.panes.get(&PaneId::Terminal(4)).unwrap().columns(), + 121, + "Pane cols match fullscreen cols" + ); + assert_eq!( + tab.panes.get(&PaneId::Terminal(4)).unwrap().rows(), + 20, + "Pane rows match fullscreen rows" + ); + tab.toggle_active_pane_fullscreen(); + assert_eq!( + tab.panes.get(&PaneId::Terminal(4)).unwrap().x(), + 61, + "Pane x is on screen edge" + ); + assert_eq!( + tab.panes.get(&PaneId::Terminal(4)).unwrap().y(), + 11, + "Pane y is on screen edge" + ); + assert_eq!( + tab.panes.get(&PaneId::Terminal(4)).unwrap().columns(), + 60, + "Pane cols match fullscreen cols" + ); + assert_eq!( + tab.panes.get(&PaneId::Terminal(4)).unwrap().rows(), + 9, + "Pane rows match fullscreen rows" + ); + // we don't test if all other panes are hidden because this logic is done in the render + // function and we already test that in the e2e tests +} + +#[test] +pub fn move_focus_is_disabled_in_fullscreen() { + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + for i in 2..5 { + let new_pane_id = PaneId::Terminal(i); + tab.new_pane(new_pane_id); + } + tab.toggle_active_pane_fullscreen(); + tab.move_focus_left(); + assert_eq!( + tab.panes.get(&PaneId::Terminal(4)).unwrap().x(), + 0, + "Pane x is on screen edge" + ); + assert_eq!( + tab.panes.get(&PaneId::Terminal(4)).unwrap().y(), + 0, + "Pane y is on screen edge" + ); + assert_eq!( + tab.panes.get(&PaneId::Terminal(4)).unwrap().columns(), + 121, + "Pane cols match fullscreen cols" + ); + assert_eq!( + tab.panes.get(&PaneId::Terminal(4)).unwrap().rows(), + 20, + "Pane rows match fullscreen rows" + ); +} + +#[test] +pub fn close_pane_with_another_pane_above_it() { + // ┌───────────┐ ┌───────────┐ + // │xxxxxxxxxxx│ │xxxxxxxxxxx│ + // │xxxxxxxxxxx│ │xxxxxxxxxxx│ + // ├───────────┤ ==close==> │xxxxxxxxxxx│ + // │███████████│ │xxxxxxxxxxx│ + // │███████████│ │xxxxxxxxxxx│ + // └───────────┘ └───────────┘ + // █ == pane being closed + + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + let new_pane_id = PaneId::Terminal(2); + tab.horizontal_split(new_pane_id); + tab.close_focused_pane(); + assert_eq!(tab.panes.len(), 1, "One pane left in tab"); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "remaining pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "remaining pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 121, + "remaining pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 20, + "remaining pane row count" + ); +} + +#[test] +pub fn close_pane_with_another_pane_below_it() { + // ┌───────────┐ ┌───────────┐ + // │███████████│ │xxxxxxxxxxx│ + // │███████████│ │xxxxxxxxxxx│ + // ├───────────┤ ==close==> │xxxxxxxxxxx│ + // │xxxxxxxxxxx│ │xxxxxxxxxxx│ + // │xxxxxxxxxxx│ │xxxxxxxxxxx│ + // └───────────┘ └───────────┘ + // █ == pane being closed + + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + let new_pane_id = PaneId::Terminal(2); + tab.horizontal_split(new_pane_id); + tab.move_focus_up(); + tab.close_focused_pane(); + assert_eq!(tab.panes.len(), 1, "One pane left in tab"); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 0, + "remaining pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 0, + "remaining pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 121, + "remaining pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 20, + "remaining pane row count" + ); +} + +#[test] +pub fn close_pane_with_another_pane_to_the_left() { + // ┌─────┬─────┐ ┌──────────┐ + // │xxxxx│█████│ │xxxxxxxxxx│ + // │xxxxx│█████│ ==close==> │xxxxxxxxxx│ + // │xxxxx│█████│ │xxxxxxxxxx│ + // └─────┴─────┘ └──────────┘ + // █ == pane being closed + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + let new_pane_id = PaneId::Terminal(2); + tab.vertical_split(new_pane_id); + tab.close_focused_pane(); + assert_eq!(tab.panes.len(), 1, "One pane left in tab"); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "remaining pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "remaining pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 121, + "remaining pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 20, + "remaining pane row count" + ); +} + +#[test] +pub fn close_pane_with_another_pane_to_the_right() { + // ┌─────┬─────┐ ┌──────────┐ + // │█████│xxxxx│ │xxxxxxxxxx│ + // │█████│xxxxx│ ==close==> │xxxxxxxxxx│ + // │█████│xxxxx│ │xxxxxxxxxx│ + // └─────┴─────┘ └──────────┘ + // █ == pane being closed + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + let new_pane_id = PaneId::Terminal(2); + tab.vertical_split(new_pane_id); + tab.move_focus_left(); + tab.close_focused_pane(); + assert_eq!(tab.panes.len(), 1, "One pane left in tab"); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 0, + "remaining pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 0, + "remaining pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 121, + "remaining pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 20, + "remaining pane row count" + ); +} + +#[test] +pub fn close_pane_with_multiple_panes_above_it() { + // ┌─────┬─────┐ ┌─────┬─────┐ + // │xxxxx│xxxxx│ │xxxxx│xxxxx│ + // │xxxxx│xxxxx│ │xxxxx│xxxxx│ + // ├─────┴─────┤ ==close==> │xxxxx│xxxxx│ + // │███████████│ │xxxxx│xxxxx│ + // │███████████│ │xxxxx│xxxxx│ + // └───────────┘ └─────┴─────┘ + // █ == pane being closed + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + let new_pane_id_1 = PaneId::Terminal(2); + let new_pane_id_2 = PaneId::Terminal(3); + tab.horizontal_split(new_pane_id_1); + tab.move_focus_up(); + tab.vertical_split(new_pane_id_2); + tab.move_focus_down(); + tab.close_focused_pane(); + assert_eq!(tab.panes.len(), 2, "Two panes left in tab"); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "first remaining pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "first remaining pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 60, + "first remaining pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 20, + "first remaining pane row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 61, + "second remaining pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 0, + "second remaining pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 60, + "second remaining pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 20, + "second remaining pane row count" + ); +} + +#[test] +pub fn close_pane_with_multiple_panes_below_it() { + // ┌───────────┐ ┌─────┬─────┐ + // │███████████│ │xxxxx│xxxxx│ + // │███████████│ │xxxxx│xxxxx│ + // ├─────┬─────┤ ==close==> │xxxxx│xxxxx│ + // │xxxxx│xxxxx│ │xxxxx│xxxxx│ + // │xxxxx│xxxxx│ │xxxxx│xxxxx│ + // └─────┴─────┘ └─────┴─────┘ + // █ == pane being closed + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + let new_pane_id_1 = PaneId::Terminal(2); + let new_pane_id_2 = PaneId::Terminal(3); + tab.horizontal_split(new_pane_id_1); + tab.vertical_split(new_pane_id_2); + tab.move_focus_up(); + tab.close_focused_pane(); + assert_eq!(tab.panes.len(), 2, "Two panes left in tab"); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 0, + "first remaining pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 0, + "first remaining pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 60, + "first remaining pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 20, + "first remaining pane row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 61, + "second remaining pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 0, + "second remaining pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 60, + "second remaining pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 20, + "second remaining pane row count" + ); +} + +#[test] +pub fn close_pane_with_multiple_panes_to_the_left() { + // ┌─────┬─────┐ ┌──────────┐ + // │xxxxx│█████│ │xxxxxxxxxx│ + // │xxxxx│█████│ │xxxxxxxxxx│ + // ├─────┤█████│ ==close==> ├──────────┤ + // │xxxxx│█████│ │xxxxxxxxxx│ + // │xxxxx│█████│ │xxxxxxxxxx│ + // └─────┴─────┘ └──────────┘ + // █ == pane being closed + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + let new_pane_id_1 = PaneId::Terminal(2); + let new_pane_id_2 = PaneId::Terminal(3); + tab.vertical_split(new_pane_id_1); + tab.move_focus_left(); + tab.horizontal_split(new_pane_id_2); + tab.move_focus_right(); + tab.close_focused_pane(); + assert_eq!(tab.panes.len(), 2, "Two panes left in tab"); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "first remaining pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "first remaining pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 121, + "first remaining pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 10, + "first remaining pane row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 0, + "second remaining pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 11, + "second remaining pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 121, + "second remaining pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 9, + "second remaining pane row count" + ); +} + +#[test] +pub fn close_pane_with_multiple_panes_to_the_right() { + // ┌─────┬─────┐ ┌──────────┐ + // │█████│xxxxx│ │xxxxxxxxxx│ + // │█████│xxxxx│ │xxxxxxxxxx│ + // │█████├─────┤ ==close==> ├──────────┤ + // │█████│xxxxx│ │xxxxxxxxxx│ + // │█████│xxxxx│ │xxxxxxxxxx│ + // └─────┴─────┘ └──────────┘ + // █ == pane being closed + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + let new_pane_id_1 = PaneId::Terminal(2); + let new_pane_id_2 = PaneId::Terminal(3); + tab.vertical_split(new_pane_id_1); + tab.horizontal_split(new_pane_id_2); + tab.move_focus_left(); + tab.close_focused_pane(); + assert_eq!(tab.panes.len(), 2, "Two panes left in tab"); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 0, + "first remaining pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 0, + "first remaining pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 121, + "first remaining pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 10, + "first remaining pane row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 0, + "second remaining pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 11, + "second remaining pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 121, + "second remaining pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 9, + "second remaining pane row count" + ); +} + +#[test] +pub fn close_pane_with_multiple_panes_above_it_away_from_screen_edges() { + // ┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ + // │xxx│xxx│xxx│xxx│ │xxx│xxx│xxx│xxx│ + // ├───┤xxx│xxx├───┤ ├───┤xxx│xxx├───┤ + // │xxx├───┴───┤xxx│ ==close==> │xxx│xxx│xxx│xxx│ + // │xxx│███████│xxx│ │xxx│xxx│xxx│xxx│ + // │xxx│███████│xxx│ │xxx│xxx│xxx│xxx│ + // └───┴───────┴───┘ └───┴───┴───┴───┘ + // █ == pane being closed + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + let new_pane_id_1 = PaneId::Terminal(2); + let new_pane_id_2 = PaneId::Terminal(3); + let new_pane_id_3 = PaneId::Terminal(4); + let new_pane_id_4 = PaneId::Terminal(5); + let new_pane_id_5 = PaneId::Terminal(6); + let new_pane_id_6 = PaneId::Terminal(7); + + tab.vertical_split(new_pane_id_1); + tab.vertical_split(new_pane_id_2); + tab.move_focus_left(); + tab.move_focus_left(); + tab.horizontal_split(new_pane_id_3); + tab.move_focus_right(); + tab.horizontal_split(new_pane_id_4); + tab.move_focus_right(); + tab.horizontal_split(new_pane_id_5); + tab.move_focus_left(); + tab.move_focus_up(); + tab.resize_down(); + tab.vertical_split(new_pane_id_6); + tab.move_focus_down(); + tab.close_focused_pane(); + + assert_eq!(tab.panes.len(), 6, "Six panes left in tab"); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "first remaining pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "first remaining pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 60, + "first remaining pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 10, + "first remaining pane row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 61, + "second remaining pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 0, + "second remaining pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 15, + "second remaining pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 20, + "second remaining pane row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 92, + "third remaining pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 0, + "third remaining pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 29, + "third remaining pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 10, + "third remaining pane row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .x, + 0, + "fourth remaining pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .y, + 11, + "fourth remaining pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .cols, + 60, + "fourth remaining pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .rows, + 9, + "fourth remaining pane row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .x, + 92, + "sixths remaining pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .y, + 11, + "sixths remaining pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .cols, + 29, + "sixths remaining pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .rows, + 9, + "sixths remaining pane row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .x, + 77, + "seventh remaining pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .y, + 0, + "seventh remaining pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .cols, + 14, + "seventh remaining pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .rows, + 20, + "seventh remaining pane row count" + ); +} + +#[test] +pub fn close_pane_with_multiple_panes_below_it_away_from_screen_edges() { + // ┌───┬───────┬───┐ ┌───┬───┬───┬───┐ + // │xxx│███████│xxx│ │xxx│xxx│xxx│xxx│ + // │xxx│███████│xxx│ │xxx│xxx│xxx│xxx│ + // │xxx├───┬───┤xxx│ ==close==> │xxx│xxx│xxx│xxx│ + // ├───┤xxx│xxx├───┤ ├───┤xxx│xxx├───┤ + // │xxx│xxx│xxx│xxx│ │xxx│xxx│xxx│xxx│ + // └───┴───┴───┴───┘ └───┴───┴───┴───┘ + // █ == pane being closed + + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + let new_pane_id_1 = PaneId::Terminal(2); + let new_pane_id_2 = PaneId::Terminal(3); + let new_pane_id_3 = PaneId::Terminal(4); + let new_pane_id_4 = PaneId::Terminal(5); + let new_pane_id_5 = PaneId::Terminal(6); + let new_pane_id_6 = PaneId::Terminal(7); + + tab.vertical_split(new_pane_id_1); + tab.vertical_split(new_pane_id_2); + tab.move_focus_left(); + tab.move_focus_left(); + tab.horizontal_split(new_pane_id_3); + tab.move_focus_right(); + tab.horizontal_split(new_pane_id_4); + tab.move_focus_right(); + tab.horizontal_split(new_pane_id_5); + tab.move_focus_left(); + tab.resize_up(); + tab.vertical_split(new_pane_id_6); + tab.move_focus_up(); + tab.close_focused_pane(); + + assert_eq!(tab.panes.len(), 6, "Six panes left in tab"); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "first remaining pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "first remaining pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 60, + "first remaining pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 10, + "first remaining pane row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 92, + "third remaining pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 0, + "third remaining pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 29, + "third remaining pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 10, + "third remaining pane row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .x, + 0, + "fourth remaining pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .y, + 11, + "fourth remaining pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .cols, + 60, + "fourth remaining pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .rows, + 9, + "fourth remaining pane row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .x, + 61, + "second remaining pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .y, + 0, + "second remaining pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .cols, + 15, + "second remaining pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .rows, + 20, + "second remaining pane row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .x, + 92, + "sixths remaining pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .y, + 11, + "sixths remaining pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .cols, + 29, + "sixths remaining pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .rows, + 9, + "sixths remaining pane row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .x, + 77, + "seventh remaining pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .y, + 0, + "seventh remaining pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .cols, + 14, + "seventh remaining pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .rows, + 20, + "seventh remaining pane row count" + ); +} + +#[test] +pub fn close_pane_with_multiple_panes_to_the_left_away_from_screen_edges() { + // ┌────┬──────┐ ┌────┬──────┐ + // │xxxx│xxxxxx│ │xxxx│xxxxxx│ + // ├────┴┬─────┤ ├────┴──────┤ + // │xxxxx│█████│ │xxxxxxxxxxx│ + // ├─────┤█████│ ==close==> ├───────────┤ + // │xxxxx│█████│ │xxxxxxxxxxx│ + // ├────┬┴─────┤ ├────┬──────┤ + // │xxxx│xxxxxx│ │xxxx│xxxxxx│ + // └────┴──────┘ └────┴──────┘ + // █ == pane being closed + + let position_and_size = PositionAndSize { + cols: 121, + rows: 30, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + let new_pane_id_1 = PaneId::Terminal(2); + let new_pane_id_2 = PaneId::Terminal(3); + let new_pane_id_3 = PaneId::Terminal(4); + let new_pane_id_4 = PaneId::Terminal(5); + let new_pane_id_5 = PaneId::Terminal(6); + let new_pane_id_6 = PaneId::Terminal(7); + + tab.horizontal_split(new_pane_id_1); + tab.horizontal_split(new_pane_id_2); + tab.move_focus_up(); + tab.move_focus_up(); + tab.vertical_split(new_pane_id_3); + tab.move_focus_down(); + tab.vertical_split(new_pane_id_4); + tab.move_focus_down(); + tab.vertical_split(new_pane_id_5); + tab.move_focus_up(); + tab.move_focus_left(); + tab.resize_right(); + tab.horizontal_split(new_pane_id_6); + tab.move_focus_right(); + tab.close_focused_pane(); + + assert_eq!(tab.panes.len(), 6, "Six panes left in tab"); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "first remaining pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "first remaining pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 60, + "first remaining pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 15, + "first remaining pane row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 0, + "third remaining pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 16, + "third remaining pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 121, + "third remaining pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 3, + "third remaining pane row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 0, + "fourth remaining pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 24, + "fourth remaining pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 60, + "fourth remaining pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 6, + "fourth remaining pane row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .x, + 61, + "second remaining pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .y, + 0, + "second remaining pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .cols, + 60, + "second remaining pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .rows, + 15, + "second remaining pane row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .x, + 61, + "sixths remaining pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .y, + 24, + "sixths remaining pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .cols, + 60, + "sixths remaining pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .rows, + 6, + "sixths remaining pane row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .x, + 0, + "seventh remaining pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .y, + 20, + "seventh remaining pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .cols, + 121, + "seventh remaining pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .rows, + 3, + "seventh remaining pane row count" + ); +} + +#[test] +pub fn close_pane_with_multiple_panes_to_the_right_away_from_screen_edges() { + // ┌────┬──────┐ ┌────┬──────┐ + // │xxxx│xxxxxx│ │xxxx│xxxxxx│ + // ├────┴┬─────┤ ├────┴──────┤ + // │█████│xxxxx│ │xxxxxxxxxxx│ + // │█████├─────┤ ==close==> ├───────────┤ + // │█████│xxxxx│ │xxxxxxxxxxx│ + // ├────┬┴─────┤ ├────┬──────┤ + // │xxxx│xxxxxx│ │xxxx│xxxxxx│ + // └────┴──────┘ └────┴──────┘ + // █ == pane being closed + + let position_and_size = PositionAndSize { + cols: 121, + rows: 30, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + let new_pane_id_1 = PaneId::Terminal(2); + let new_pane_id_2 = PaneId::Terminal(3); + let new_pane_id_3 = PaneId::Terminal(4); + let new_pane_id_4 = PaneId::Terminal(5); + let new_pane_id_5 = PaneId::Terminal(6); + let new_pane_id_6 = PaneId::Terminal(7); + + tab.horizontal_split(new_pane_id_1); + tab.horizontal_split(new_pane_id_2); + tab.move_focus_up(); + tab.move_focus_up(); + tab.vertical_split(new_pane_id_3); + tab.move_focus_down(); + tab.vertical_split(new_pane_id_4); + tab.move_focus_down(); + tab.vertical_split(new_pane_id_5); + tab.move_focus_up(); + tab.resize_left(); + tab.horizontal_split(new_pane_id_6); + tab.move_focus_left(); + tab.close_focused_pane(); + + assert_eq!(tab.panes.len(), 6, "Six panes left in tab"); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "first remaining pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "first remaining pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 60, + "first remaining pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 15, + "first remaining pane row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 0, + "fourth remaining pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 24, + "fourth remaining pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 60, + "fourth remaining pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 6, + "fourth remaining pane row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .x, + 61, + "second remaining pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .y, + 0, + "second remaining pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .cols, + 60, + "second remaining pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .rows, + 15, + "second remaining pane row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .x, + 0, + "third remaining pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .y, + 16, + "third remaining pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .cols, + 121, + "third remaining pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .rows, + 3, + "third remaining pane row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .x, + 61, + "sixths remaining pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .y, + 24, + "sixths remaining pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .cols, + 60, + "sixths remaining pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .rows, + 6, + "sixths remaining pane row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .x, + 0, + "seventh remaining pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .y, + 20, + "seventh remaining pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .cols, + 121, + "seventh remaining pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .rows, + 3, + "seventh remaining pane row count" + ); +} + +#[test] +pub fn move_focus_down() { + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + let new_pane_id = PaneId::Terminal(2); + + tab.horizontal_split(new_pane_id); + tab.move_focus_up(); + tab.move_focus_down(); + + assert_eq!( + tab.get_active_pane().unwrap().y(), + 11, + "Active pane is the bottom one" + ); +} + +#[test] +pub fn move_focus_down_to_the_most_recently_used_pane() { + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + let new_pane_id_1 = PaneId::Terminal(2); + let new_pane_id_2 = PaneId::Terminal(3); + let new_pane_id_3 = PaneId::Terminal(4); + + tab.horizontal_split(new_pane_id_1); + tab.vertical_split(new_pane_id_2); + tab.vertical_split(new_pane_id_3); + tab.move_focus_up(); + tab.move_focus_down(); + + assert_eq!( + tab.get_active_pane().unwrap().y(), + 11, + "Active pane y position" + ); + assert_eq!( + tab.get_active_pane().unwrap().x(), + 92, + "Active pane x position" + ); +} + +#[test] +pub fn move_focus_up() { + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + let new_pane_id = PaneId::Terminal(2); + + tab.horizontal_split(new_pane_id); + tab.move_focus_up(); + + assert_eq!( + tab.get_active_pane().unwrap().y(), + 0, + "Active pane is the top one" + ); +} + +#[test] +pub fn move_focus_up_to_the_most_recently_used_pane() { + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + let new_pane_id_1 = PaneId::Terminal(2); + let new_pane_id_2 = PaneId::Terminal(3); + let new_pane_id_3 = PaneId::Terminal(4); + + tab.horizontal_split(new_pane_id_1); + tab.move_focus_up(); + tab.vertical_split(new_pane_id_2); + tab.vertical_split(new_pane_id_3); + tab.move_focus_down(); + tab.move_focus_up(); + + assert_eq!( + tab.get_active_pane().unwrap().y(), + 0, + "Active pane y position" + ); + assert_eq!( + tab.get_active_pane().unwrap().x(), + 92, + "Active pane x position" + ); +} + +#[test] +pub fn move_focus_left() { + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + let new_pane_id = PaneId::Terminal(2); + + tab.vertical_split(new_pane_id); + tab.move_focus_left(); + + assert_eq!( + tab.get_active_pane().unwrap().x(), + 0, + "Active pane is the left one" + ); +} + +#[test] +pub fn move_focus_left_to_the_most_recently_used_pane() { + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + let new_pane_id_1 = PaneId::Terminal(2); + let new_pane_id_2 = PaneId::Terminal(3); + let new_pane_id_3 = PaneId::Terminal(4); + + tab.vertical_split(new_pane_id_1); + tab.move_focus_left(); + tab.horizontal_split(new_pane_id_2); + tab.horizontal_split(new_pane_id_3); + tab.move_focus_right(); + tab.move_focus_left(); + + assert_eq!( + tab.get_active_pane().unwrap().y(), + 16, + "Active pane y position" + ); + assert_eq!( + tab.get_active_pane().unwrap().x(), + 0, + "Active pane x position" + ); +} + +#[test] +pub fn move_focus_right() { + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + let new_pane_id = PaneId::Terminal(2); + + tab.vertical_split(new_pane_id); + tab.move_focus_left(); + tab.move_focus_right(); + + assert_eq!( + tab.get_active_pane().unwrap().x(), + 61, + "Active pane is the right one" + ); +} + +#[test] +pub fn move_focus_right_to_the_most_recently_used_pane() { + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + let new_pane_id_1 = PaneId::Terminal(2); + let new_pane_id_2 = PaneId::Terminal(3); + let new_pane_id_3 = PaneId::Terminal(4); + + tab.vertical_split(new_pane_id_1); + tab.horizontal_split(new_pane_id_2); + tab.horizontal_split(new_pane_id_3); + tab.move_focus_left(); + tab.move_focus_right(); + + assert_eq!( + tab.get_active_pane().unwrap().y(), + 16, + "Active pane y position" + ); + assert_eq!( + tab.get_active_pane().unwrap().x(), + 61, + "Active pane x position" + ); +} + +#[test] +pub fn resize_down_with_pane_above() { + // ┌───────────┐ ┌───────────┐ + // │ │ │ │ + // │ │ │ │ + // ├───────────┤ ==resize=down==> │ │ + // │███████████│ ├───────────┤ + // │███████████│ │███████████│ + // │███████████│ │███████████│ + // └───────────┘ └───────────┘ + // █ == focused pane + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + let new_pane_id = PaneId::Terminal(2); + tab.horizontal_split(new_pane_id); + tab.resize_down(); + + assert_eq!( + tab.panes.get(&new_pane_id).unwrap().position_and_size().x, + 0, + "focused pane x position" + ); + assert_eq!( + tab.panes.get(&new_pane_id).unwrap().position_and_size().y, + 13, + "focused pane y position" + ); + assert_eq!( + tab.panes + .get(&new_pane_id) + .unwrap() + .position_and_size() + .cols, + 121, + "focused pane column count" + ); + assert_eq!( + tab.panes + .get(&new_pane_id) + .unwrap() + .position_and_size() + .rows, + 7, + "focused pane row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane above x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane above y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 121, + "pane above column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 12, + "pane above row count" + ); +} + +#[test] +pub fn resize_down_with_pane_below() { + // ┌───────────┐ ┌───────────┐ + // │███████████│ │███████████│ + // │███████████│ │███████████│ + // ├───────────┤ ==resize=down==> │███████████│ + // │ │ ├───────────┤ + // │ │ │ │ + // └───────────┘ └───────────┘ + // █ == focused pane + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + let new_pane_id = PaneId::Terminal(2); + tab.horizontal_split(new_pane_id); + tab.move_focus_up(); + tab.resize_down(); + + assert_eq!( + tab.panes.get(&new_pane_id).unwrap().position_and_size().x, + 0, + "pane below x position" + ); + assert_eq!( + tab.panes.get(&new_pane_id).unwrap().position_and_size().y, + 13, + "pane below y position" + ); + assert_eq!( + tab.panes + .get(&new_pane_id) + .unwrap() + .position_and_size() + .cols, + 121, + "pane below column count" + ); + assert_eq!( + tab.panes + .get(&new_pane_id) + .unwrap() + .position_and_size() + .rows, + 7, + "pane below row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "focused pane x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "focused pane y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 121, + "focused pane column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 12, + "focused pane row count" + ); +} + +#[test] +pub fn resize_down_with_panes_above_and_below() { + // ┌───────────┐ ┌───────────┐ + // │ │ │ │ + // │ │ │ │ + // ├───────────┤ ├───────────┤ + // │███████████│ ==resize=down==> │███████████│ + // │███████████│ │███████████│ + // │███████████│ │███████████│ + // ├───────────┤ │███████████│ + // │ │ ├───────────┤ + // │ │ │ │ + // └───────────┘ └───────────┘ + // █ == focused pane + let position_and_size = PositionAndSize { + cols: 121, + rows: 30, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + let first_pane_id = PaneId::Terminal(1); + let new_pane_id_1 = PaneId::Terminal(2); + let new_pane_id_2 = PaneId::Terminal(3); + tab.horizontal_split(new_pane_id_1); + tab.horizontal_split(new_pane_id_2); + tab.move_focus_up(); + tab.resize_down(); + + assert_eq!( + tab.panes.get(&new_pane_id_1).unwrap().position_and_size().x, + 0, + "focused pane x position" + ); + assert_eq!( + tab.panes.get(&new_pane_id_1).unwrap().position_and_size().y, + 16, + "focused pane y position" + ); + assert_eq!( + tab.panes + .get(&new_pane_id_1) + .unwrap() + .position_and_size() + .cols, + 121, + "focused pane column count" + ); + assert_eq!( + tab.panes + .get(&new_pane_id_1) + .unwrap() + .position_and_size() + .rows, + 9, + "focused pane row count" + ); + + assert_eq!( + tab.panes.get(&new_pane_id_2).unwrap().position_and_size().x, + 0, + "pane below x position" + ); + assert_eq!( + tab.panes.get(&new_pane_id_2).unwrap().position_and_size().y, + 26, + "pane below y position" + ); + assert_eq!( + tab.panes + .get(&new_pane_id_2) + .unwrap() + .position_and_size() + .cols, + 121, + "pane below column count" + ); + assert_eq!( + tab.panes + .get(&new_pane_id_2) + .unwrap() + .position_and_size() + .rows, + 4, + "pane below row count" + ); + + assert_eq!( + tab.panes.get(&first_pane_id).unwrap().position_and_size().x, + 0, + "pane above x position" + ); + assert_eq!( + tab.panes.get(&first_pane_id).unwrap().position_and_size().y, + 0, + "pane above y position" + ); + assert_eq!( + tab.panes + .get(&first_pane_id) + .unwrap() + .position_and_size() + .cols, + 121, + "pane above column count" + ); + assert_eq!( + tab.panes + .get(&first_pane_id) + .unwrap() + .position_and_size() + .rows, + 15, + "pane above row count" + ); +} + +#[test] +pub fn resize_down_with_multiple_panes_above() { + // + // ┌─────┬─────┐ ┌─────┬─────┐ + // │ │ │ │ │ │ + // ├─────┴─────┤ ==resize=down==> │ │ │ + // │███████████│ ├─────┴─────┤ + // │███████████│ │███████████│ + // └───────────┘ └───────────┘ + // █ == focused pane + let position_and_size = PositionAndSize { + cols: 121, + rows: 30, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + let first_pane_id = PaneId::Terminal(1); + let new_pane_id_1 = PaneId::Terminal(2); + let new_pane_id_2 = PaneId::Terminal(3); + tab.horizontal_split(new_pane_id_1); + tab.move_focus_up(); + tab.vertical_split(new_pane_id_2); + tab.move_focus_down(); + tab.resize_down(); + + assert_eq!( + tab.panes.get(&new_pane_id_1).unwrap().position_and_size().x, + 0, + "focused pane x position" + ); + assert_eq!( + tab.panes.get(&new_pane_id_1).unwrap().position_and_size().y, + 18, + "focused pane y position" + ); + assert_eq!( + tab.panes + .get(&new_pane_id_1) + .unwrap() + .position_and_size() + .cols, + 121, + "focused pane column count" + ); + assert_eq!( + tab.panes + .get(&new_pane_id_1) + .unwrap() + .position_and_size() + .rows, + 12, + "focused pane row count" + ); + + assert_eq!( + tab.panes.get(&new_pane_id_2).unwrap().position_and_size().x, + 61, + "first pane above x position" + ); + assert_eq!( + tab.panes.get(&new_pane_id_2).unwrap().position_and_size().y, + 0, + "first pane above y position" + ); + assert_eq!( + tab.panes + .get(&new_pane_id_2) + .unwrap() + .position_and_size() + .cols, + 60, + "first pane above column count" + ); + assert_eq!( + tab.panes + .get(&new_pane_id_2) + .unwrap() + .position_and_size() + .rows, + 17, + "first pane above row count" + ); + + assert_eq!( + tab.panes.get(&first_pane_id).unwrap().position_and_size().x, + 0, + "second pane above x position" + ); + assert_eq!( + tab.panes.get(&first_pane_id).unwrap().position_and_size().y, + 0, + "second pane above y position" + ); + assert_eq!( + tab.panes + .get(&first_pane_id) + .unwrap() + .position_and_size() + .cols, + 60, + "second pane above column count" + ); + assert_eq!( + tab.panes + .get(&first_pane_id) + .unwrap() + .position_and_size() + .rows, + 17, + "second pane above row count" + ); +} + +#[test] +pub fn resize_down_with_panes_above_aligned_left_with_current_pane() { + // ┌─────┬─────┐ ┌─────┬─────┐ + // │ │ │ │ │ │ + // │ │ │ │ │ │ + // ├─────┼─────┤ ==resize=down==> ├─────┤ │ + // │ │█████│ │ ├─────┤ + // │ │█████│ │ │█████│ + // └─────┴─────┘ └─────┴─────┘ + // █ == focused pane + let position_and_size = PositionAndSize { + cols: 121, + rows: 30, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + let pane_above_and_left = PaneId::Terminal(1); + let pane_to_the_left = PaneId::Terminal(2); + let focused_pane = PaneId::Terminal(3); + let pane_above = PaneId::Terminal(4); + tab.horizontal_split(pane_to_the_left); + tab.vertical_split(focused_pane); + tab.move_focus_up(); + tab.vertical_split(pane_above); + tab.move_focus_down(); + tab.resize_down(); + + assert_eq!( + tab.panes.get(&focused_pane).unwrap().position_and_size().x, + 61, + "focused pane x position" + ); + assert_eq!( + tab.panes.get(&focused_pane).unwrap().position_and_size().y, + 18, + "focused pane y position" + ); + assert_eq!( + tab.panes + .get(&focused_pane) + .unwrap() + .position_and_size() + .cols, + 60, + "focused pane column count" + ); + assert_eq!( + tab.panes + .get(&focused_pane) + .unwrap() + .position_and_size() + .rows, + 12, + "focused pane row count" + ); + + assert_eq!( + tab.panes + .get(&pane_above_and_left) + .unwrap() + .position_and_size() + .x, + 0, + "pane above and to the left x position" + ); + assert_eq!( + tab.panes + .get(&pane_above_and_left) + .unwrap() + .position_and_size() + .y, + 0, + "pane above and to the left y position" + ); + assert_eq!( + tab.panes + .get(&pane_above_and_left) + .unwrap() + .position_and_size() + .cols, + 60, + "pane above and to the left column count" + ); + assert_eq!( + tab.panes + .get(&pane_above_and_left) + .unwrap() + .position_and_size() + .rows, + 15, + "pane above and to the left row count" + ); + + assert_eq!( + tab.panes.get(&pane_above).unwrap().position_and_size().x, + 61, + "pane above x position" + ); + assert_eq!( + tab.panes.get(&pane_above).unwrap().position_and_size().y, + 0, + "pane above y position" + ); + assert_eq!( + tab.panes.get(&pane_above).unwrap().position_and_size().cols, + 60, + "pane above column count" + ); + assert_eq!( + tab.panes.get(&pane_above).unwrap().position_and_size().rows, + 17, + "pane above row count" + ); + + assert_eq!( + tab.panes + .get(&pane_to_the_left) + .unwrap() + .position_and_size() + .x, + 0, + "pane to the left x position" + ); + assert_eq!( + tab.panes + .get(&pane_to_the_left) + .unwrap() + .position_and_size() + .y, + 16, + "pane to the left y position" + ); + assert_eq!( + tab.panes + .get(&pane_to_the_left) + .unwrap() + .position_and_size() + .cols, + 60, + "pane to the left column count" + ); + assert_eq!( + tab.panes + .get(&pane_to_the_left) + .unwrap() + .position_and_size() + .rows, + 14, + "pane to the left row count" + ); +} + +#[test] +pub fn resize_down_with_panes_below_aligned_left_with_current_pane() { + // ┌─────┬─────┐ ┌─────┬─────┐ + // │ │█████│ │ │█████│ + // │ │█████│ │ │█████│ + // ├─────┼─────┤ ==resize=down==> ├─────┤█████│ + // │ │ │ │ ├─────┤ + // │ │ │ │ │ │ + // └─────┴─────┘ └─────┴─────┘ + // █ == focused pane + + let position_and_size = PositionAndSize { + cols: 121, + rows: 30, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + let pane_to_the_left = PaneId::Terminal(1); + let pane_below_and_left = PaneId::Terminal(2); + let pane_below = PaneId::Terminal(3); + let focused_pane = PaneId::Terminal(4); + tab.horizontal_split(pane_below_and_left); + tab.vertical_split(pane_below); + tab.move_focus_up(); + tab.vertical_split(focused_pane); + tab.resize_down(); + + assert_eq!( + tab.panes.get(&focused_pane).unwrap().position_and_size().x, + 61, + "focused pane x position" + ); + assert_eq!( + tab.panes.get(&focused_pane).unwrap().position_and_size().y, + 0, + "focused pane y position" + ); + assert_eq!( + tab.panes + .get(&focused_pane) + .unwrap() + .position_and_size() + .cols, + 60, + "focused pane column count" + ); + assert_eq!( + tab.panes + .get(&focused_pane) + .unwrap() + .position_and_size() + .rows, + 17, + "focused pane row count" + ); + + assert_eq!( + tab.panes + .get(&pane_to_the_left) + .unwrap() + .position_and_size() + .x, + 0, + "pane above and to the left x position" + ); + assert_eq!( + tab.panes + .get(&pane_to_the_left) + .unwrap() + .position_and_size() + .y, + 0, + "pane above and to the left y position" + ); + assert_eq!( + tab.panes + .get(&pane_to_the_left) + .unwrap() + .position_and_size() + .cols, + 60, + "pane above and to the left column count" + ); + assert_eq!( + tab.panes + .get(&pane_to_the_left) + .unwrap() + .position_and_size() + .rows, + 15, + "pane above and to the left row count" + ); + + assert_eq!( + tab.panes.get(&pane_below).unwrap().position_and_size().x, + 61, + "pane above x position" + ); + assert_eq!( + tab.panes.get(&pane_below).unwrap().position_and_size().y, + 18, + "pane above y position" + ); + assert_eq!( + tab.panes.get(&pane_below).unwrap().position_and_size().cols, + 60, + "pane above column count" + ); + assert_eq!( + tab.panes.get(&pane_below).unwrap().position_and_size().rows, + 12, + "pane above row count" + ); + + assert_eq!( + tab.panes + .get(&pane_below_and_left) + .unwrap() + .position_and_size() + .x, + 0, + "pane to the left x position" + ); + assert_eq!( + tab.panes + .get(&pane_below_and_left) + .unwrap() + .position_and_size() + .y, + 16, + "pane to the left y position" + ); + assert_eq!( + tab.panes + .get(&pane_below_and_left) + .unwrap() + .position_and_size() + .cols, + 60, + "pane to the left column count" + ); + assert_eq!( + tab.panes + .get(&pane_below_and_left) + .unwrap() + .position_and_size() + .rows, + 14, + "pane to the left row count" + ); +} + +#[test] +pub fn resize_down_with_panes_above_aligned_right_with_current_pane() { + // ┌─────┬─────┐ ┌─────┬─────┐ + // │ │ │ │ │ │ + // │ │ │ │ │ │ + // ├─────┼─────┤ ==resize=down==> │ ├─────┤ + // │█████│ │ ├─────┤ │ + // │█████│ │ │█████│ │ + // └─────┴─────┘ └─────┴─────┘ + // █ == focused pane + + let position_and_size = PositionAndSize { + cols: 121, + rows: 30, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + let pane_above = PaneId::Terminal(1); + let focused_pane = PaneId::Terminal(2); + let pane_to_the_right = PaneId::Terminal(3); + let pane_above_and_right = PaneId::Terminal(4); + tab.horizontal_split(focused_pane); + tab.vertical_split(pane_to_the_right); + tab.move_focus_up(); + tab.vertical_split(pane_above_and_right); + tab.move_focus_down(); + tab.move_focus_left(); + tab.resize_down(); + + assert_eq!( + tab.panes.get(&focused_pane).unwrap().position_and_size().x, + 0, + "focused pane x position" + ); + assert_eq!( + tab.panes.get(&focused_pane).unwrap().position_and_size().y, + 18, + "focused pane y position" + ); + assert_eq!( + tab.panes + .get(&focused_pane) + .unwrap() + .position_and_size() + .cols, + 60, + "focused pane column count" + ); + assert_eq!( + tab.panes + .get(&focused_pane) + .unwrap() + .position_and_size() + .rows, + 12, + "focused pane row count" + ); + + assert_eq!( + tab.panes.get(&pane_above).unwrap().position_and_size().x, + 0, + "pane above x position" + ); + assert_eq!( + tab.panes.get(&pane_above).unwrap().position_and_size().y, + 0, + "pane above y position" + ); + assert_eq!( + tab.panes.get(&pane_above).unwrap().position_and_size().cols, + 60, + "pane above column count" + ); + assert_eq!( + tab.panes.get(&pane_above).unwrap().position_and_size().rows, + 17, + "pane above row count" + ); + + assert_eq!( + tab.panes + .get(&pane_to_the_right) + .unwrap() + .position_and_size() + .x, + 61, + "pane to the right x position" + ); + assert_eq!( + tab.panes + .get(&pane_to_the_right) + .unwrap() + .position_and_size() + .y, + 16, + "pane to the right y position" + ); + assert_eq!( + tab.panes + .get(&pane_to_the_right) + .unwrap() + .position_and_size() + .cols, + 60, + "pane to the right column count" + ); + assert_eq!( + tab.panes + .get(&pane_to_the_right) + .unwrap() + .position_and_size() + .rows, + 14, + "pane to the right row count" + ); + + assert_eq!( + tab.panes + .get(&pane_above_and_right) + .unwrap() + .position_and_size() + .x, + 61, + "pane above and to the right x position" + ); + assert_eq!( + tab.panes + .get(&pane_above_and_right) + .unwrap() + .position_and_size() + .y, + 0, + "pane above and to the right y position" + ); + assert_eq!( + tab.panes + .get(&pane_above_and_right) + .unwrap() + .position_and_size() + .cols, + 60, + "pane above and to the right column count" + ); + assert_eq!( + tab.panes + .get(&pane_above_and_right) + .unwrap() + .position_and_size() + .rows, + 15, + "pane above and to the right row count" + ); +} + +#[test] +pub fn resize_down_with_panes_below_aligned_right_with_current_pane() { + // ┌─────┬─────┐ ┌─────┬─────┐ + // │█████│ │ │█████│ │ + // │█████│ │ │█████│ │ + // ├─────┼─────┤ ==resize=down==> │█████├─────┤ + // │ │ │ ├─────┤ │ + // │ │ │ │ │ │ + // └─────┴─────┘ └─────┴─────┘ + // █ == focused pane + + let position_and_size = PositionAndSize { + cols: 121, + rows: 30, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + let focused_pane = PaneId::Terminal(1); + let pane_below = PaneId::Terminal(2); + let pane_below_and_right = PaneId::Terminal(3); + let pane_to_the_right = PaneId::Terminal(4); + tab.horizontal_split(pane_below); + tab.vertical_split(pane_below_and_right); + tab.move_focus_up(); + tab.vertical_split(pane_to_the_right); + tab.move_focus_left(); + tab.resize_down(); + + assert_eq!( + tab.panes.get(&focused_pane).unwrap().position_and_size().x, + 0, + "focused pane x position" + ); + assert_eq!( + tab.panes.get(&focused_pane).unwrap().position_and_size().y, + 0, + "focused pane y position" + ); + assert_eq!( + tab.panes + .get(&focused_pane) + .unwrap() + .position_and_size() + .cols, + 60, + "focused pane column count" + ); + assert_eq!( + tab.panes + .get(&focused_pane) + .unwrap() + .position_and_size() + .rows, + 17, + "focused pane row count" + ); + + assert_eq!( + tab.panes.get(&pane_below).unwrap().position_and_size().x, + 0, + "pane below x position" + ); + assert_eq!( + tab.panes.get(&pane_below).unwrap().position_and_size().y, + 18, + "pane below y position" + ); + assert_eq!( + tab.panes.get(&pane_below).unwrap().position_and_size().cols, + 60, + "pane below column count" + ); + assert_eq!( + tab.panes.get(&pane_below).unwrap().position_and_size().rows, + 12, + "pane below row count" + ); + + assert_eq!( + tab.panes + .get(&pane_below_and_right) + .unwrap() + .position_and_size() + .x, + 61, + "pane below and to the right x position" + ); + assert_eq!( + tab.panes + .get(&pane_below_and_right) + .unwrap() + .position_and_size() + .y, + 16, + "pane below and to the right y position" + ); + assert_eq!( + tab.panes + .get(&pane_below_and_right) + .unwrap() + .position_and_size() + .cols, + 60, + "pane below and to the right column count" + ); + assert_eq!( + tab.panes + .get(&pane_below_and_right) + .unwrap() + .position_and_size() + .rows, + 14, + "pane below and to the right row count" + ); + + assert_eq!( + tab.panes + .get(&pane_to_the_right) + .unwrap() + .position_and_size() + .x, + 61, + "pane to the right x position" + ); + assert_eq!( + tab.panes + .get(&pane_to_the_right) + .unwrap() + .position_and_size() + .y, + 0, + "pane to the right y position" + ); + assert_eq!( + tab.panes + .get(&pane_to_the_right) + .unwrap() + .position_and_size() + .cols, + 60, + "pane to the right column count" + ); + assert_eq!( + tab.panes + .get(&pane_to_the_right) + .unwrap() + .position_and_size() + .rows, + 15, + "pane to the right row count" + ); +} + +#[test] +pub fn resize_down_with_panes_above_aligned_left_and_right_with_current_pane() { + // ┌───┬───┬───┐ ┌───┬───┬───┐ + // │ │ │ │ │ │ │ │ + // │ │ │ │ │ │ │ │ + // ├───┼───┼───┤ ==resize=down==> ├───┤ ├───┤ + // │ │███│ │ │ ├───┤ │ + // │ │███│ │ │ │███│ │ + // └───┴───┴───┘ └───┴───┴───┘ + // █ == focused pane + + let position_and_size = PositionAndSize { + cols: 121, + rows: 30, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.horizontal_split(PaneId::Terminal(2)); + tab.vertical_split(PaneId::Terminal(3)); + tab.vertical_split(PaneId::Terminal(4)); + tab.move_focus_up(); + tab.vertical_split(PaneId::Terminal(5)); + tab.vertical_split(PaneId::Terminal(6)); + tab.move_focus_left(); + tab.move_focus_down(); + tab.resize_down(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 1 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 1 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 1 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 15, + "pane 1 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 16, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 14, + "pane 2 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 3 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 18, + "pane 3 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 30, + "pane 3 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 12, + "pane 3 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .x, + 92, + "pane 4 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .y, + 16, + "pane 4 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .cols, + 29, + "pane 4 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .rows, + 14, + "pane 4 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 5 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 5 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .cols, + 30, + "pane 5 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .rows, + 17, + "pane 5 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .x, + 92, + "pane 6 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 6 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .cols, + 29, + "pane 6 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .rows, + 15, + "pane 6 row count" + ); +} + +#[test] +pub fn resize_down_with_panes_below_aligned_left_and_right_with_current_pane() { + // ┌───┬───┬───┐ ┌───┬───┬───┐ + // │ │███│ │ │ │███│ │ + // │ │███│ │ │ │███│ │ + // ├───┼───┼───┤ ==resize=down==> ├───┤███├───┤ + // │ │ │ │ │ ├───┤ │ + // │ │ │ │ │ │ │ │ + // └───┴───┴───┘ └───┴───┴───┘ + // █ == focused pane + + let position_and_size = PositionAndSize { + cols: 121, + rows: 30, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.horizontal_split(PaneId::Terminal(2)); + tab.vertical_split(PaneId::Terminal(3)); + tab.vertical_split(PaneId::Terminal(4)); + tab.move_focus_up(); + tab.vertical_split(PaneId::Terminal(5)); + tab.vertical_split(PaneId::Terminal(6)); + tab.move_focus_left(); + tab.resize_down(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 1 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 1 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 1 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 15, + "pane 1 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 16, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 14, + "pane 2 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 3 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 18, + "pane 3 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 30, + "pane 3 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 12, + "pane 3 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .x, + 92, + "pane 4 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .y, + 16, + "pane 4 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .cols, + 29, + "pane 4 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .rows, + 14, + "pane 4 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 5 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 5 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .cols, + 30, + "pane 5 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .rows, + 17, + "pane 5 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .x, + 92, + "pane 6 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 6 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .cols, + 29, + "pane 6 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .rows, + 15, + "pane 6 row count" + ); +} + +#[test] +pub fn resize_down_with_panes_above_aligned_left_and_right_with_panes_to_the_left_and_right() { + // ┌─┬───────┬─┐ ┌─┬───────┬─┐ + // │ │ │ │ │ │ │ │ + // │ │ │ │ │ │ │ │ + // ├─┼─┬───┬─┼─┤ ==resize=down==> ├─┤ ├─┤ + // │ │ │███│ │ │ │ ├─┬───┬─┤ │ + // │ │ │███│ │ │ │ │ │███│ │ │ + // └─┴─┴───┴─┴─┘ └─┴─┴───┴─┴─┘ + // █ == focused pane + + let position_and_size = PositionAndSize { + cols: 121, + rows: 30, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.horizontal_split(PaneId::Terminal(2)); + tab.move_focus_up(); + tab.vertical_split(PaneId::Terminal(3)); + tab.vertical_split(PaneId::Terminal(4)); + tab.move_focus_down(); + tab.vertical_split(PaneId::Terminal(5)); + tab.vertical_split(PaneId::Terminal(6)); + tab.move_focus_left(); + tab.vertical_split(PaneId::Terminal(7)); + tab.vertical_split(PaneId::Terminal(8)); + tab.move_focus_left(); + tab.resize_down(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 1 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 1 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 1 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 15, + "pane 1 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 16, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 14, + "pane 2 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 3 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 3 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 30, + "pane 3 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 17, + "pane 3 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .x, + 92, + "pane 4 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 4 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .cols, + 29, + "pane 4 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .rows, + 15, + "pane 4 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 5 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .y, + 18, + "pane 5 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .cols, + 15, + "pane 5 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .rows, + 12, + "pane 5 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .x, + 92, + "pane 6 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .y, + 16, + "pane 6 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .cols, + 29, + "pane 6 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .rows, + 14, + "pane 6 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .x, + 77, + "pane 7 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .y, + 18, + "pane 7 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .cols, + 7, + "pane 7 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .rows, + 12, + "pane 7 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(8)) + .unwrap() + .position_and_size() + .x, + 85, + "pane 8 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(8)) + .unwrap() + .position_and_size() + .y, + 18, + "pane 8 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(8)) + .unwrap() + .position_and_size() + .cols, + 6, + "pane 8 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(8)) + .unwrap() + .position_and_size() + .rows, + 12, + "pane 8 row count" + ); +} + +#[test] +pub fn resize_down_with_panes_below_aligned_left_and_right_with_to_the_left_and_right() { + // ┌─┬─┬───┬─┬─┐ ┌─┬─┬───┬─┬─┐ + // │ │ │███│ │ │ │ │ │███│ │ │ + // │ │ │███│ │ │ │ │ │███│ │ │ + // ├─┼─┴───┴─┼─┤ ==resize=down==> ├─┤ │███│ ├─┤ + // │ │ │ │ │ ├─┴───┴─┤ │ + // │ │ │ │ │ │ │ │ + // └─┴───────┴─┘ └─┴───────┴─┘ + // █ == focused pane + + let position_and_size = PositionAndSize { + cols: 121, + rows: 30, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.horizontal_split(PaneId::Terminal(2)); + tab.move_focus_up(); + tab.vertical_split(PaneId::Terminal(3)); + tab.vertical_split(PaneId::Terminal(4)); + tab.move_focus_left(); + tab.vertical_split(PaneId::Terminal(5)); + tab.vertical_split(PaneId::Terminal(6)); + tab.move_focus_down(); + tab.vertical_split(PaneId::Terminal(7)); + tab.vertical_split(PaneId::Terminal(8)); + tab.move_focus_left(); + tab.move_focus_up(); + tab.move_focus_left(); + tab.resize_down(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 1 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 1 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 1 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 15, + "pane 1 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 16, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 14, + "pane 2 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 3 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 3 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 15, + "pane 3 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 17, + "pane 3 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .x, + 92, + "pane 4 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 4 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .cols, + 29, + "pane 4 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .rows, + 15, + "pane 4 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .x, + 77, + "pane 5 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 5 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .cols, + 7, + "pane 5 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .rows, + 17, + "pane 5 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .x, + 85, + "pane 6 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 6 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .cols, + 6, + "pane 6 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .rows, + 17, + "pane 6 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 7 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .y, + 18, + "pane 7 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .cols, + 30, + "pane 7 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .rows, + 12, + "pane 7 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(8)) + .unwrap() + .position_and_size() + .x, + 92, + "pane 8 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(8)) + .unwrap() + .position_and_size() + .y, + 16, + "pane 8 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(8)) + .unwrap() + .position_and_size() + .cols, + 29, + "pane 8 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(8)) + .unwrap() + .position_and_size() + .rows, + 14, + "pane 8 row count" + ); +} + +#[test] +pub fn cannot_resize_down_when_pane_below_is_at_minimum_height() { + // ┌───────────┐ ┌───────────┐ + // │███████████│ │███████████│ + // ├───────────┤ ==resize=down==> ├───────────┤ + // │ │ │ │ + // └───────────┘ └───────────┘ + // █ == focused pane + + let position_and_size = PositionAndSize { + cols: 121, + rows: 7, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.horizontal_split(PaneId::Terminal(2)); + tab.move_focus_up(); + tab.resize_down(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 3, + "pane 1 height stayed the same" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 3, + "pane 2 height stayed the same" + ); +} + +#[test] +pub fn resize_left_with_pane_to_the_left() { + // ┌─────┬─────┐ ┌───┬───────┐ + // │ │█████│ │ │███████│ + // │ │█████│ ==resize=left==> │ │███████│ + // │ │█████│ │ │███████│ + // └─────┴─────┘ └───┴───────┘ + // █ == focused pane + + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.vertical_split(PaneId::Terminal(2)); + tab.resize_left(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 1 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 1 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 50, + "pane 1 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 20, + "pane 1 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 51, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 70, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 20, + "pane 2 row count" + ); +} + +#[test] +pub fn resize_left_with_pane_to_the_right() { + // ┌─────┬─────┐ ┌───┬───────┐ + // │█████│ │ │███│ │ + // │█████│ │ ==resize=left==> │███│ │ + // │█████│ │ │███│ │ + // └─────┴─────┘ └───┴───────┘ + // █ == focused pane + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.vertical_split(PaneId::Terminal(2)); + tab.move_focus_left(); + tab.resize_left(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 1 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 1 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 50, + "pane 1 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 20, + "pane 1 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 51, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 70, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 20, + "pane 2 row count" + ); +} + +#[test] +pub fn resize_left_with_panes_to_the_left_and_right() { + // ┌─────┬─────┬─────┐ ┌─────┬───┬───────┐ + // │ │█████│ │ │ │███│ │ + // │ │█████│ │ ==resize=left==> │ │███│ │ + // │ │█████│ │ │ │███│ │ + // └─────┴─────┴─────┘ └─────┴───┴───────┘ + // █ == focused pane + + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.vertical_split(PaneId::Terminal(2)); + tab.vertical_split(PaneId::Terminal(3)); + tab.move_focus_left(); + tab.resize_left(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 1 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 1 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 50, + "pane 1 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 20, + "pane 1 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 51, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 40, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 20, + "pane 2 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 92, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 29, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 20, + "pane 2 row count" + ); +} + +#[test] +pub fn resize_left_with_multiple_panes_to_the_left() { + // ┌─────┬─────┐ ┌───┬───────┐ + // │ │█████│ │ │███████│ + // ├─────┤█████│ ==resize=left==> ├───┤███████│ + // │ │█████│ │ │███████│ + // └─────┴─────┘ └───┴───────┘ + // █ == focused pane + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.vertical_split(PaneId::Terminal(2)); + tab.move_focus_left(); + tab.horizontal_split(PaneId::Terminal(3)); + tab.move_focus_right(); + tab.resize_left(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 1 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 1 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 50, + "pane 1 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 10, + "pane 1 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 51, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 70, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 20, + "pane 2 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 11, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 50, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 9, + "pane 2 row count" + ); +} + +#[test] +pub fn resize_left_with_panes_to_the_left_aligned_top_with_current_pane() { + // ┌─────┬─────┐ ┌─────┬─────┐ + // │ │ │ │ │ │ + // ├─────┼─────┤ ==resize=left==> ├───┬─┴─────┤ + // │ │█████│ │ │███████│ + // └─────┴─────┘ └───┴───────┘ + // █ == focused pane + + let position_and_size = PositionAndSize { + cols: 121, + rows: 30, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.horizontal_split(PaneId::Terminal(2)); + tab.vertical_split(PaneId::Terminal(3)); + tab.move_focus_up(); + tab.vertical_split(PaneId::Terminal(4)); + tab.move_focus_down(); + tab.resize_left(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 1 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 1 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 1 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 15, + "pane 1 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 16, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 50, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 14, + "pane 2 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 51, + "pane 3 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 16, + "pane 3 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 70, + "pane 3 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 14, + "pane 3 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 4 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 4 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 4 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .rows, + 15, + "pane 4 row count" + ); +} + +#[test] +pub fn resize_left_with_panes_to_the_right_aligned_top_with_current_pane() { + // ┌─────┬─────┐ ┌─────┬─────┐ + // │ │ │ │ │ │ + // ├─────┼─────┤ ==resize=left==> ├───┬─┴─────┤ + // │█████│ │ │███│ │ + // └─────┴─────┘ └───┴───────┘ + // █ == focused pane + + let position_and_size = PositionAndSize { + cols: 121, + rows: 30, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.horizontal_split(PaneId::Terminal(2)); + tab.vertical_split(PaneId::Terminal(3)); + tab.move_focus_up(); + tab.vertical_split(PaneId::Terminal(4)); + tab.move_focus_down(); + tab.move_focus_left(); + tab.resize_left(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 1 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 1 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 1 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 15, + "pane 1 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 16, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 50, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 14, + "pane 2 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 51, + "pane 3 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 16, + "pane 3 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 70, + "pane 3 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 14, + "pane 3 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 4 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 4 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 4 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .rows, + 15, + "pane 4 row count" + ); +} + +#[test] +pub fn resize_left_with_panes_to_the_left_aligned_bottom_with_current_pane() { + // ┌─────┬─────┐ ┌───┬───────┐ + // │ │█████│ │ │███████│ + // ├─────┼─────┤ ==resize=left==> ├───┴─┬─────┤ + // │ │ │ │ │ │ + // └─────┴─────┘ └─────┴─────┘ + // █ == focused pane + + let position_and_size = PositionAndSize { + cols: 121, + rows: 30, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.horizontal_split(PaneId::Terminal(2)); + tab.vertical_split(PaneId::Terminal(3)); + tab.move_focus_up(); + tab.vertical_split(PaneId::Terminal(4)); + tab.resize_left(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 1 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 1 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 50, + "pane 1 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 15, + "pane 1 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 16, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 14, + "pane 2 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 3 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 16, + "pane 3 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 3 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 14, + "pane 3 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .x, + 51, + "pane 4 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 4 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .cols, + 70, + "pane 4 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .rows, + 15, + "pane 4 row count" + ); +} + +#[test] +pub fn resize_left_with_panes_to_the_right_aligned_bottom_with_current_pane() { + // ┌─────┬─────┐ ┌───┬───────┐ + // │█████│ │ │███│ │ + // ├─────┼─────┤ ==resize=left==> ├───┴─┬─────┤ + // │ │ │ │ │ │ + // └─────┴─────┘ └─────┴─────┘ + // █ == focused pane + + let position_and_size = PositionAndSize { + cols: 121, + rows: 30, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.horizontal_split(PaneId::Terminal(2)); + tab.vertical_split(PaneId::Terminal(3)); + tab.move_focus_up(); + tab.vertical_split(PaneId::Terminal(4)); + tab.move_focus_left(); + tab.resize_left(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 1 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 1 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 50, + "pane 1 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 15, + "pane 1 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 16, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 14, + "pane 2 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 3 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 16, + "pane 3 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 3 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 14, + "pane 3 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .x, + 51, + "pane 4 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 4 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .cols, + 70, + "pane 4 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .rows, + 15, + "pane 4 row count" + ); +} + +#[test] +pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_current_pane() { + // ┌─────┬─────┐ ┌─────┬─────┐ + // │ │ │ │ │ │ + // ├─────┼─────┤ ├───┬─┴─────┤ + // │ │█████│ ==resize=left==> │ │███████│ + // ├─────┼─────┤ ├───┴─┬─────┤ + // │ │ │ │ │ │ + // └─────┴─────┘ └─────┴─────┘ + // █ == focused pane + + let position_and_size = PositionAndSize { + cols: 121, + rows: 30, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.horizontal_split(PaneId::Terminal(2)); + tab.horizontal_split(PaneId::Terminal(3)); + tab.vertical_split(PaneId::Terminal(4)); + tab.move_focus_up(); + tab.vertical_split(PaneId::Terminal(5)); + tab.move_focus_up(); + tab.vertical_split(PaneId::Terminal(6)); + tab.move_focus_down(); + tab.resize_left(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 1 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 1 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 1 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 15, + "pane 1 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 16, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 50, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 7, + "pane 2 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 3 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 24, + "pane 3 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 3 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 6, + "pane 3 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 4 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .y, + 24, + "pane 4 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 4 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .rows, + 6, + "pane 4 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .x, + 51, + "pane 5 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .y, + 16, + "pane 5 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .cols, + 70, + "pane 5 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .rows, + 7, + "pane 5 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 6 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 6 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 6 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .rows, + 15, + "pane 6 row count" + ); +} + +#[test] +pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_current_pane() { + // ┌─────┬─────┐ ┌─────┬─────┐ + // │ │ │ │ │ │ + // ├─────┼─────┤ ├───┬─┴─────┤ + // │█████│ │ ==resize=left==> │███│ │ + // ├─────┼─────┤ ├───┴─┬─────┤ + // │ │ │ │ │ │ + // └─────┴─────┘ └─────┴─────┘ + // █ == focused pane + + let position_and_size = PositionAndSize { + cols: 121, + rows: 30, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.horizontal_split(PaneId::Terminal(2)); + tab.horizontal_split(PaneId::Terminal(3)); + tab.vertical_split(PaneId::Terminal(4)); + tab.move_focus_up(); + tab.vertical_split(PaneId::Terminal(5)); + tab.move_focus_up(); + tab.vertical_split(PaneId::Terminal(6)); + tab.move_focus_down(); + tab.move_focus_left(); + tab.resize_left(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 1 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 1 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 1 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 15, + "pane 1 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 16, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 50, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 7, + "pane 2 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 3 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 24, + "pane 3 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 3 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 6, + "pane 3 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 4 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .y, + 24, + "pane 4 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 4 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .rows, + 6, + "pane 4 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .x, + 51, + "pane 5 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .y, + 16, + "pane 5 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .cols, + 70, + "pane 5 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .rows, + 7, + "pane 5 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 6 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 6 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 6 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .rows, + 15, + "pane 6 row count" + ); +} + +#[test] +pub fn resize_left_with_panes_to_the_left_aligned_top_and_bottom_with_panes_above_and_below() { + // ┌─────┬─────┐ ┌─────┬─────┐ + // ├─────┼─────┤ ├───┬─┴─────┤ + // │ ├─────┤ │ ├───────┤ + // │ │█████│ ==resize=left==> │ │███████│ + // │ ├─────┤ │ ├───────┤ + // ├─────┼─────┤ ├───┴─┬─────┤ + // └─────┴─────┘ └─────┴─────┘ + // █ == focused pane + + let position_and_size = PositionAndSize { + cols: 121, + rows: 70, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.horizontal_split(PaneId::Terminal(2)); + tab.horizontal_split(PaneId::Terminal(3)); + tab.vertical_split(PaneId::Terminal(4)); + tab.move_focus_up(); + tab.move_focus_up(); + tab.vertical_split(PaneId::Terminal(5)); + tab.move_focus_down(); + tab.vertical_split(PaneId::Terminal(6)); + tab.horizontal_split(PaneId::Terminal(7)); + tab.horizontal_split(PaneId::Terminal(8)); + tab.move_focus_up(); + tab.resize_left(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 1 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 1 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 1 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 35, + "pane 1 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 36, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 50, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 17, + "pane 2 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 3 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 54, + "pane 3 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 3 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 16, + "pane 3 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 4 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .y, + 54, + "pane 4 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 4 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .rows, + 16, + "pane 4 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 5 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 5 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 5 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .rows, + 35, + "pane 5 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .x, + 51, + "pane 6 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .y, + 36, + "pane 6 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .cols, + 70, + "pane 6 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .rows, + 8, + "pane 6 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .x, + 51, + "pane 7 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .y, + 45, + "pane 7 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .cols, + 70, + "pane 7 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .rows, + 4, + "pane 7 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(8)) + .unwrap() + .position_and_size() + .x, + 51, + "pane 8 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(8)) + .unwrap() + .position_and_size() + .y, + 50, + "pane 8 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(8)) + .unwrap() + .position_and_size() + .cols, + 70, + "pane 8 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(8)) + .unwrap() + .position_and_size() + .rows, + 3, + "pane 8 row count" + ); +} + +#[test] +pub fn resize_left_with_panes_to_the_right_aligned_top_and_bottom_with_panes_above_and_below() { + // ┌─────┬─────┐ ┌─────┬─────┐ + // ├─────┼─────┤ ├───┬─┴─────┤ + // ├─────┤ │ ├───┤ │ + // │█████│ │ ==resize=left==> │███│ │ + // ├─────┤ │ ├───┤ │ + // ├─────┼─────┤ ├───┴─┬─────┤ + // └─────┴─────┘ └─────┴─────┘ + // █ == focused pane + + let position_and_size = PositionAndSize { + cols: 121, + rows: 70, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.horizontal_split(PaneId::Terminal(2)); + tab.horizontal_split(PaneId::Terminal(3)); + tab.vertical_split(PaneId::Terminal(4)); + tab.move_focus_up(); + tab.move_focus_up(); + tab.vertical_split(PaneId::Terminal(5)); + tab.move_focus_down(); + tab.vertical_split(PaneId::Terminal(6)); + tab.move_focus_left(); + tab.horizontal_split(PaneId::Terminal(7)); + tab.horizontal_split(PaneId::Terminal(8)); + tab.move_focus_up(); + tab.resize_left(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 1 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 1 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 1 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 35, + "pane 1 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 36, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 50, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 8, + "pane 2 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 3 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 54, + "pane 3 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 3 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 16, + "pane 3 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 4 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .y, + 54, + "pane 4 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 4 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .rows, + 16, + "pane 4 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 5 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 5 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 5 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .rows, + 35, + "pane 5 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .x, + 51, + "pane 6 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .y, + 36, + "pane 6 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .cols, + 70, + "pane 6 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .rows, + 17, + "pane 6 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 7 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .y, + 45, + "pane 7 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .cols, + 50, + "pane 7 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .rows, + 4, + "pane 7 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(8)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 8 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(8)) + .unwrap() + .position_and_size() + .y, + 50, + "pane 8 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(8)) + .unwrap() + .position_and_size() + .cols, + 50, + "pane 8 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(8)) + .unwrap() + .position_and_size() + .rows, + 3, + "pane 8 row count" + ); +} + +#[test] +pub fn cannot_resize_left_when_pane_to_the_left_is_at_minimum_width() { + // ┌─┬─┐ ┌─┬─┐ + // │ │█│ │ │█│ + // │ │█│ ==resize=left==> │ │█│ + // │ │█│ │ │█│ + // └─┴─┘ └─┴─┘ + // █ == focused pane + + let position_and_size = PositionAndSize { + cols: 9, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.vertical_split(PaneId::Terminal(2)); + tab.resize_left(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 4, + "pane 1 columns stayed the same" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 4, + "pane 2 columns stayed the same" + ); +} + +#[test] +pub fn resize_right_with_pane_to_the_left() { + // ┌─────┬─────┐ ┌───────┬───┐ + // │ │█████│ │ │███│ + // │ │█████│ ==resize=right==> │ │███│ + // │ │█████│ │ │███│ + // └─────┴─────┘ └───────┴───┘ + // █ == focused pane + + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.vertical_split(PaneId::Terminal(2)); + tab.resize_right(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 1 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 1 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 70, + "pane 1 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 20, + "pane 1 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 71, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 50, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 20, + "pane 2 row count" + ); +} + +#[test] +pub fn resize_right_with_pane_to_the_right() { + // ┌─────┬─────┐ ┌───────┬───┐ + // │█████│ │ │███████│ │ + // │█████│ │ ==resize=right==> │███████│ │ + // │█████│ │ │███████│ │ + // └─────┴─────┘ └───────┴───┘ + // █ == focused pane + + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.vertical_split(PaneId::Terminal(2)); + tab.move_focus_left(); + tab.resize_right(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 1 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 1 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 70, + "pane 1 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 20, + "pane 1 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 71, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 50, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 20, + "pane 2 row count" + ); +} + +#[test] +pub fn resize_right_with_panes_to_the_left_and_right() { + // ┌─────┬─────┬─────┐ ┌─────┬───────┬───┐ + // │ │█████│ │ │ │███████│ │ + // │ │█████│ │ ==resize=right==> │ │███████│ │ + // │ │█████│ │ │ │███████│ │ + // └─────┴─────┴─────┘ └─────┴───────┴───┘ + // █ == focused pane + + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.vertical_split(PaneId::Terminal(2)); + tab.vertical_split(PaneId::Terminal(3)); + tab.move_focus_left(); + tab.resize_right(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 1 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 1 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 1 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 20, + "pane 1 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 40, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 20, + "pane 2 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 102, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 19, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 20, + "pane 2 row count" + ); +} + +#[test] +pub fn resize_right_with_multiple_panes_to_the_left() { + // ┌─────┬─────┐ ┌───────┬───┐ + // │ │█████│ │ │███│ + // ├─────┤█████│ ==resize=right==> ├───────┤███│ + // │ │█████│ │ │███│ + // └─────┴─────┘ └───────┴───┘ + // █ == focused pane + + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.vertical_split(PaneId::Terminal(2)); + tab.move_focus_left(); + tab.horizontal_split(PaneId::Terminal(3)); + tab.move_focus_right(); + tab.resize_right(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 1 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 1 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 70, + "pane 1 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 10, + "pane 1 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 71, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 50, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 20, + "pane 2 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 3 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 11, + "pane 3 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 70, + "pane 3 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 9, + "pane 3 row count" + ); +} + +#[test] +pub fn resize_right_with_panes_to_the_left_aligned_top_with_current_pane() { + // ┌─────┬─────┐ ┌─────┬─────┐ + // │ │ │ │ │ │ + // ├─────┼─────┤ ==resize=right==> ├─────┴─┬───┤ + // │ │█████│ │ │███│ + // └─────┴─────┘ └───────┴───┘ + // █ == focused pane + + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.vertical_split(PaneId::Terminal(2)); + tab.move_focus_left(); + tab.horizontal_split(PaneId::Terminal(3)); + tab.move_focus_right(); + tab.horizontal_split(PaneId::Terminal(4)); + tab.resize_right(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 1 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 1 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 1 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 10, + "pane 1 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 10, + "pane 2 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 3 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 11, + "pane 3 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 70, + "pane 3 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 9, + "pane 3 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .x, + 71, + "pane 4 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .y, + 11, + "pane 4 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .cols, + 50, + "pane 4 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .rows, + 9, + "pane 4 row count" + ); +} + +#[test] +pub fn resize_right_with_panes_to_the_right_aligned_top_with_current_pane() { + // ┌─────┬─────┐ ┌─────┬─────┐ + // │ │ │ │ │ │ + // ├─────┼─────┤ ==resize=right==> ├─────┴─┬───┤ + // │█████│ │ │███████│ │ + // └─────┴─────┘ └───────┴───┘ + // █ == focused pane + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.vertical_split(PaneId::Terminal(2)); + tab.move_focus_left(); + tab.horizontal_split(PaneId::Terminal(3)); + tab.move_focus_right(); + tab.horizontal_split(PaneId::Terminal(4)); + tab.move_focus_left(); + tab.resize_right(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 1 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 1 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 1 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 10, + "pane 1 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 10, + "pane 2 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 3 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 11, + "pane 3 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 70, + "pane 3 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 9, + "pane 3 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .x, + 71, + "pane 4 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .y, + 11, + "pane 4 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .cols, + 50, + "pane 4 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .rows, + 9, + "pane 4 row count" + ); +} + +#[test] +pub fn resize_right_with_panes_to_the_left_aligned_bottom_with_current_pane() { + // ┌─────┬─────┐ ┌───────┬───┐ + // │ │█████│ │ │███│ + // ├─────┼─────┤ ==resize=right==> ├─────┬─┴───┤ + // │ │ │ │ │ │ + // └─────┴─────┘ └─────┴─────┘ + // █ == focused pane + + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.vertical_split(PaneId::Terminal(2)); + tab.move_focus_left(); + tab.horizontal_split(PaneId::Terminal(3)); + tab.move_focus_right(); + tab.horizontal_split(PaneId::Terminal(4)); + tab.move_focus_up(); + tab.resize_right(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 1 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 1 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 70, + "pane 1 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 10, + "pane 1 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 71, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 50, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 10, + "pane 2 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 3 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 11, + "pane 3 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 3 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 9, + "pane 3 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 4 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .y, + 11, + "pane 4 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 4 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .rows, + 9, + "pane 4 row count" + ); +} + +#[test] +pub fn resize_right_with_panes_to_the_right_aligned_bottom_with_current_pane() { + // ┌─────┬─────┐ ┌───────┬───┐ + // │█████│ │ │███████│ │ + // ├─────┼─────┤ ==resize=right==> ├─────┬─┴───┤ + // │ │ │ │ │ │ + // └─────┴─────┘ └─────┴─────┘ + // █ == focused pane + + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.vertical_split(PaneId::Terminal(2)); + tab.move_focus_left(); + tab.horizontal_split(PaneId::Terminal(3)); + tab.move_focus_right(); + tab.horizontal_split(PaneId::Terminal(4)); + tab.move_focus_up(); + tab.move_focus_left(); + tab.resize_right(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 1 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 1 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 70, + "pane 1 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 10, + "pane 1 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 71, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 50, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 10, + "pane 2 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 3 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 11, + "pane 3 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 3 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 9, + "pane 3 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 4 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .y, + 11, + "pane 4 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 4 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .rows, + 9, + "pane 4 row count" + ); +} + +#[test] +pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_current_pane() { + // ┌─────┬─────┐ ┌─────┬─────┐ + // │ │ │ │ │ │ + // ├─────┼─────┤ ├─────┴─┬───┤ + // │ │█████│ ==resize=right==> │ │███│ + // ├─────┼─────┤ ├─────┬─┴───┤ + // │ │ │ │ │ │ + // └─────┴─────┘ └─────┴─────┘ + // █ == focused pane + + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.horizontal_split(PaneId::Terminal(2)); + tab.horizontal_split(PaneId::Terminal(3)); + tab.vertical_split(PaneId::Terminal(4)); + tab.move_focus_up(); + tab.vertical_split(PaneId::Terminal(5)); + tab.move_focus_up(); + tab.vertical_split(PaneId::Terminal(6)); + tab.move_focus_down(); + tab.resize_right(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 1 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 1 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 1 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 10, + "pane 1 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 11, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 70, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 4, + "pane 2 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 3 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 16, + "pane 3 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 3 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 4, + "pane 3 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 4 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .y, + 16, + "pane 4 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 4 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .rows, + 4, + "pane 4 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .x, + 71, + "pane 5 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .y, + 11, + "pane 5 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .cols, + 50, + "pane 5 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .rows, + 4, + "pane 5 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 6 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 6 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 6 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .rows, + 10, + "pane 6 row count" + ); +} + +#[test] +pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_current_pane() { + // ┌─────┬─────┐ ┌─────┬─────┐ + // │ │ │ │ │ │ + // ├─────┼─────┤ ├─────┴─┬───┤ + // │█████│ │ ==resize=right==> │███████│ │ + // ├─────┼─────┤ ├─────┬─┴───┤ + // │ │ │ │ │ │ + // └─────┴─────┘ └─────┴─────┘ + // █ == focused pane + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.horizontal_split(PaneId::Terminal(2)); + tab.horizontal_split(PaneId::Terminal(3)); + tab.vertical_split(PaneId::Terminal(4)); + tab.move_focus_up(); + tab.vertical_split(PaneId::Terminal(5)); + tab.move_focus_up(); + tab.vertical_split(PaneId::Terminal(6)); + tab.move_focus_down(); + tab.move_focus_left(); + tab.resize_right(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 1 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 1 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 1 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 10, + "pane 1 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 11, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 70, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 4, + "pane 2 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 3 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 16, + "pane 3 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 3 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 4, + "pane 3 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 4 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .y, + 16, + "pane 4 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 4 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .rows, + 4, + "pane 4 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .x, + 71, + "pane 5 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .y, + 11, + "pane 5 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .cols, + 50, + "pane 5 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .rows, + 4, + "pane 5 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 6 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 6 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 6 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .rows, + 10, + "pane 6 row count" + ); +} + +#[test] +pub fn resize_right_with_panes_to_the_left_aligned_top_and_bottom_with_panes_above_and_below() { + // ┌─────┬─────┐ ┌─────┬─────┐ + // ├─────┼─────┤ ├─────┴─┬───┤ + // │ ├─────┤ │ ├───┤ + // │ │█████│ ==resize=right==> │ │███│ + // │ ├─────┤ │ ├───┤ + // ├─────┼─────┤ ├─────┬─┴───┤ + // └─────┴─────┘ └─────┴─────┘ + // █ == focused pane + let position_and_size = PositionAndSize { + cols: 121, + rows: 70, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.horizontal_split(PaneId::Terminal(2)); + tab.horizontal_split(PaneId::Terminal(3)); + tab.vertical_split(PaneId::Terminal(4)); + tab.move_focus_up(); + tab.move_focus_up(); + tab.vertical_split(PaneId::Terminal(5)); + tab.move_focus_down(); + tab.vertical_split(PaneId::Terminal(6)); + tab.horizontal_split(PaneId::Terminal(7)); + tab.horizontal_split(PaneId::Terminal(8)); + tab.move_focus_up(); + tab.resize_right(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 1 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 1 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 1 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 35, + "pane 1 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 36, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 70, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 17, + "pane 2 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 3 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 54, + "pane 3 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 3 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 16, + "pane 3 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 4 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .y, + 54, + "pane 4 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 4 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .rows, + 16, + "pane 4 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 5 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 5 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 5 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .rows, + 35, + "pane 5 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .x, + 71, + "pane 6 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .y, + 36, + "pane 6 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .cols, + 50, + "pane 6 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .rows, + 8, + "pane 6 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .x, + 71, + "pane 7 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .y, + 45, + "pane 7 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .cols, + 50, + "pane 7 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .rows, + 4, + "pane 7 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(8)) + .unwrap() + .position_and_size() + .x, + 71, + "pane 8 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(8)) + .unwrap() + .position_and_size() + .y, + 50, + "pane 8 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(8)) + .unwrap() + .position_and_size() + .cols, + 50, + "pane 8 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(8)) + .unwrap() + .position_and_size() + .rows, + 3, + "pane 8 row count" + ); +} + +#[test] +pub fn resize_right_with_panes_to_the_right_aligned_top_and_bottom_with_panes_above_and_below() { + // ┌─────┬─────┐ ┌─────┬─────┐ + // ├─────┼─────┤ ├─────┴─┬───┤ + // ├─────┤ │ ├───────┤ │ + // │█████│ │ ==resize=right==> │███████│ │ + // ├─────┤ │ ├───────┤ │ + // ├─────┼─────┤ ├─────┬─┴───┤ + // └─────┴─────┘ └─────┴─────┘ + // █ == focused pane + let position_and_size = PositionAndSize { + cols: 121, + rows: 70, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.horizontal_split(PaneId::Terminal(2)); + tab.horizontal_split(PaneId::Terminal(3)); + tab.vertical_split(PaneId::Terminal(4)); + tab.move_focus_up(); + tab.move_focus_up(); + tab.vertical_split(PaneId::Terminal(5)); + tab.move_focus_down(); + tab.vertical_split(PaneId::Terminal(6)); + tab.move_focus_left(); + tab.horizontal_split(PaneId::Terminal(7)); + tab.horizontal_split(PaneId::Terminal(8)); + tab.move_focus_up(); + tab.resize_right(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 1 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 1 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 1 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 35, + "pane 1 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 36, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 70, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 8, + "pane 2 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 3 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 54, + "pane 3 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 3 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 16, + "pane 3 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 4 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .y, + 54, + "pane 4 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 4 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .rows, + 16, + "pane 4 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 5 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 5 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 5 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .rows, + 35, + "pane 5 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .x, + 71, + "pane 6 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .y, + 36, + "pane 6 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .cols, + 50, + "pane 6 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .rows, + 17, + "pane 6 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 7 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .y, + 45, + "pane 7 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .cols, + 70, + "pane 7 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .rows, + 4, + "pane 7 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(8)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 8 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(8)) + .unwrap() + .position_and_size() + .y, + 50, + "pane 8 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(8)) + .unwrap() + .position_and_size() + .cols, + 70, + "pane 8 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(8)) + .unwrap() + .position_and_size() + .rows, + 3, + "pane 8 row count" + ); +} + +#[test] +pub fn cannot_resize_right_when_pane_to_the_left_is_at_minimum_width() { + // ┌─┬─┐ ┌─┬─┐ + // │ │█│ │ │█│ + // │ │█│ ==resize=right==> │ │█│ + // │ │█│ │ │█│ + // └─┴─┘ └─┴─┘ + // █ == focused pane + let position_and_size = PositionAndSize { + cols: 9, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.vertical_split(PaneId::Terminal(2)); + tab.resize_right(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 4, + "pane 1 columns stayed the same" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 4, + "pane 2 columns stayed the same" + ); +} + +#[test] +pub fn resize_up_with_pane_above() { + // ┌───────────┐ ┌───────────┐ + // │ │ │ │ + // │ │ ├───────────┤ + // ├───────────┤ ==resize=up==> │███████████│ + // │███████████│ │███████████│ + // │███████████│ │███████████│ + // └───────────┘ └───────────┘ + // █ == focused pane + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.horizontal_split(PaneId::Terminal(2)); + tab.resize_up(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 1 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 1 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 121, + "pane 1 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 8, + "pane 1 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 9, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 121, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 11, + "pane 2 row count" + ); +} + +#[test] +pub fn resize_up_with_pane_below() { + // ┌───────────┐ ┌───────────┐ + // │███████████│ │███████████│ + // │███████████│ ├───────────┤ + // ├───────────┤ ==resize=up==> │ │ + // │ │ │ │ + // │ │ │ │ + // └───────────┘ └───────────┘ + // █ == focused pane + let position_and_size = PositionAndSize { + cols: 121, + rows: 20, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.horizontal_split(PaneId::Terminal(2)); + tab.move_focus_up(); + tab.resize_up(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 1 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 1 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 121, + "pane 1 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 8, + "pane 1 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 9, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 121, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 11, + "pane 2 row count" + ); +} + +#[test] +pub fn resize_up_with_panes_above_and_below() { + // ┌───────────┐ ┌───────────┐ + // │ │ │ │ + // │ │ ├───────────┤ + // ├───────────┤ │███████████│ + // │███████████│ ==resize=up==> │███████████│ + // │███████████│ │███████████│ + // ├───────────┤ ├───────────┤ + // │ │ │ │ + // │ │ │ │ + // └───────────┘ └───────────┘ + // █ == focused pane + let position_and_size = PositionAndSize { + cols: 121, + rows: 30, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.horizontal_split(PaneId::Terminal(2)); + tab.horizontal_split(PaneId::Terminal(3)); + tab.move_focus_up(); + tab.resize_up(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 1 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 1 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 121, + "pane 1 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 13, + "pane 1 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 14, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 121, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 9, + "pane 2 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 3 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 24, + "pane 3 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 121, + "pane 3 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 6, + "pane 3 row count" + ); +} + +#[test] +pub fn resize_up_with_multiple_panes_above() { + // + // ┌─────┬─────┐ ┌─────┬─────┐ + // │ │ │ ├─────┴─────┤ + // ├─────┴─────┤ ==resize=up==> │███████████│ + // │███████████│ │███████████│ + // └───────────┘ └───────────┘ + // █ == focused pane + let position_and_size = PositionAndSize { + cols: 121, + rows: 30, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.horizontal_split(PaneId::Terminal(2)); + tab.move_focus_up(); + tab.vertical_split(PaneId::Terminal(3)); + tab.move_focus_down(); + tab.resize_up(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 1 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 1 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 1 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 13, + "pane 1 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 14, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 121, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 16, + "pane 2 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 3 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 3 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 3 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 13, + "pane 3 row count" + ); +} + +#[test] +pub fn resize_up_with_panes_above_aligned_left_with_current_pane() { + // ┌─────┬─────┐ ┌─────┬─────┐ + // │ │ │ │ ├─────┤ + // ├─────┼─────┤ ==resize=up==> ├─────┤█████│ + // │ │█████│ │ │█████│ + // └─────┴─────┘ └─────┴─────┘ + // █ == focused pane + let position_and_size = PositionAndSize { + cols: 121, + rows: 30, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.horizontal_split(PaneId::Terminal(2)); + tab.move_focus_up(); + tab.vertical_split(PaneId::Terminal(3)); + tab.move_focus_down(); + tab.vertical_split(PaneId::Terminal(4)); + tab.resize_up(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 1 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 1 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 1 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 15, + "pane 1 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 16, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 14, + "pane 2 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 3 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 3 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 3 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 13, + "pane 3 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 4 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .y, + 14, + "pane 4 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 4 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .rows, + 16, + "pane 4 row count" + ); +} + +#[test] +pub fn resize_up_with_panes_below_aligned_left_with_current_pane() { + // ┌─────┬─────┐ ┌─────┬─────┐ + // │ │█████│ │ │█████│ + // │ │█████│ │ ├─────┤ + // ├─────┼─────┤ ==resize=up==> ├─────┤ │ + // │ │ │ │ │ │ + // │ │ │ │ │ │ + // └─────┴─────┘ └─────┴─────┘ + // █ == focused pane + let position_and_size = PositionAndSize { + cols: 121, + rows: 30, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.horizontal_split(PaneId::Terminal(2)); + tab.move_focus_up(); + tab.vertical_split(PaneId::Terminal(3)); + tab.move_focus_down(); + tab.vertical_split(PaneId::Terminal(4)); + tab.move_focus_up(); + tab.resize_up(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 1 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 1 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 1 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 15, + "pane 1 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 16, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 14, + "pane 2 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 3 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 3 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 3 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 13, + "pane 3 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 4 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .y, + 14, + "pane 4 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 4 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .rows, + 16, + "pane 4 row count" + ); +} + +#[test] +pub fn resize_up_with_panes_above_aligned_right_with_current_pane() { + // ┌─────┬─────┐ ┌─────┬─────┐ + // │ │ │ │ │ │ + // │ │ │ ├─────┤ │ + // ├─────┼─────┤ ==resize=up==> │█████├─────┤ + // │█████│ │ │█████│ │ + // │█████│ │ │█████│ │ + // └─────┴─────┘ └─────┴─────┘ + // █ == focused pane + let position_and_size = PositionAndSize { + cols: 121, + rows: 30, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.horizontal_split(PaneId::Terminal(2)); + tab.move_focus_up(); + tab.vertical_split(PaneId::Terminal(3)); + tab.move_focus_down(); + tab.vertical_split(PaneId::Terminal(4)); + tab.move_focus_left(); + tab.resize_up(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 1 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 1 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 1 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 13, + "pane 1 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 14, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 16, + "pane 2 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 3 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 3 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 3 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 15, + "pane 3 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 4 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .y, + 16, + "pane 4 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 4 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .rows, + 14, + "pane 4 row count" + ); +} + +#[test] +pub fn resize_up_with_panes_below_aligned_right_with_current_pane() { + // ┌─────┬─────┐ ┌─────┬─────┐ + // │█████│ │ │█████│ │ + // │█████│ │ ├─────┤ │ + // ├─────┼─────┤ ==resize=up==> │ ├─────┤ + // │ │ │ │ │ │ + // │ │ │ │ │ │ + // └─────┴─────┘ └─────┴─────┘ + // █ == focused pane + let position_and_size = PositionAndSize { + cols: 121, + rows: 30, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.horizontal_split(PaneId::Terminal(2)); + tab.move_focus_up(); + tab.vertical_split(PaneId::Terminal(3)); + tab.move_focus_down(); + tab.vertical_split(PaneId::Terminal(4)); + tab.move_focus_left(); + tab.move_focus_up(); + tab.resize_up(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 1 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 1 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 1 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 13, + "pane 1 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 14, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 16, + "pane 2 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 3 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 3 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 3 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 15, + "pane 3 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 4 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .y, + 16, + "pane 4 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 4 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .rows, + 14, + "pane 4 row count" + ); +} + +#[test] +pub fn resize_up_with_panes_above_aligned_left_and_right_with_current_pane() { + // ┌───┬───┬───┐ ┌───┬───┬───┐ + // │ │ │ │ │ │ │ │ + // │ │ │ │ │ ├───┤ │ + // ├───┼───┼───┤ ==resize=up==> ├───┤███├───┤ + // │ │███│ │ │ │███│ │ + // │ │███│ │ │ │███│ │ + // └───┴───┴───┘ └───┴───┴───┘ + // █ == focused pane + let position_and_size = PositionAndSize { + cols: 121, + rows: 30, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.horizontal_split(PaneId::Terminal(2)); + tab.vertical_split(PaneId::Terminal(3)); + tab.vertical_split(PaneId::Terminal(4)); + tab.move_focus_up(); + tab.vertical_split(PaneId::Terminal(5)); + tab.vertical_split(PaneId::Terminal(6)); + tab.move_focus_left(); + tab.resize_up(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 1 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 1 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 1 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 15, + "pane 1 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 16, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 14, + "pane 2 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 3 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 14, + "pane 3 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 30, + "pane 3 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 16, + "pane 3 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .x, + 92, + "pane 4 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .y, + 16, + "pane 4 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .cols, + 29, + "pane 4 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .rows, + 14, + "pane 4 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 5 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 5 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .cols, + 30, + "pane 5 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .rows, + 13, + "pane 5 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .x, + 92, + "pane 6 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 6 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .cols, + 29, + "pane 6 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .rows, + 15, + "pane 6 row count" + ); +} + +#[test] +pub fn resize_up_with_panes_below_aligned_left_and_right_with_current_pane() { + // ┌───┬───┬───┐ ┌───┬───┬───┐ + // │ │███│ │ │ │███│ │ + // │ │███│ │ │ ├───┤ │ + // ├───┼───┼───┤ ==resize=up==> ├───┤ ├───┤ + // │ │ │ │ │ │ │ │ + // │ │ │ │ │ │ │ │ + // └───┴───┴───┘ └───┴───┴───┘ + // █ == focused pane + let position_and_size = PositionAndSize { + cols: 121, + rows: 30, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.horizontal_split(PaneId::Terminal(2)); + tab.vertical_split(PaneId::Terminal(3)); + tab.vertical_split(PaneId::Terminal(4)); + tab.move_focus_up(); + tab.vertical_split(PaneId::Terminal(5)); + tab.vertical_split(PaneId::Terminal(6)); + tab.move_focus_left(); + tab.move_focus_up(); + tab.resize_up(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 1 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 1 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 1 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 15, + "pane 1 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 16, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 14, + "pane 2 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 3 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 14, + "pane 3 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 30, + "pane 3 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 16, + "pane 3 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .x, + 92, + "pane 4 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .y, + 16, + "pane 4 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .cols, + 29, + "pane 4 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .rows, + 14, + "pane 4 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 5 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 5 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .cols, + 30, + "pane 5 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .rows, + 13, + "pane 5 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .x, + 92, + "pane 6 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 6 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .cols, + 29, + "pane 6 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .rows, + 15, + "pane 6 row count" + ); +} + +#[test] +pub fn resize_up_with_panes_above_aligned_left_and_right_with_panes_to_the_left_and_right() { + // ┌─┬───────┬─┐ ┌─┬───────┬─┐ + // │ │ │ │ │ │ │ │ + // │ │ │ │ │ ├─┬───┬─┤ │ + // ├─┼─┬───┬─┼─┤ ==resize=up==> ├─┤ │███│ ├─┤ + // │ │ │███│ │ │ │ │ │███│ │ │ + // │ │ │███│ │ │ │ │ │███│ │ │ + // └─┴─┴───┴─┴─┘ └─┴─┴───┴─┴─┘ + // █ == focused pane + let position_and_size = PositionAndSize { + cols: 121, + rows: 30, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.horizontal_split(PaneId::Terminal(2)); + tab.move_focus_up(); + tab.vertical_split(PaneId::Terminal(3)); + tab.vertical_split(PaneId::Terminal(4)); + tab.move_focus_down(); + tab.vertical_split(PaneId::Terminal(5)); + tab.vertical_split(PaneId::Terminal(6)); + tab.move_focus_left(); + tab.vertical_split(PaneId::Terminal(7)); + tab.vertical_split(PaneId::Terminal(8)); + tab.move_focus_left(); + tab.resize_up(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 1 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 1 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 1 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 15, + "pane 1 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 16, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 14, + "pane 2 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 3 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 3 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 30, + "pane 3 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 13, + "pane 3 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .x, + 92, + "pane 4 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 4 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .cols, + 29, + "pane 4 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .rows, + 15, + "pane 4 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 5 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .y, + 14, + "pane 5 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .cols, + 15, + "pane 5 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .rows, + 16, + "pane 5 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .x, + 92, + "pane 6 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .y, + 16, + "pane 6 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .cols, + 29, + "pane 6 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .rows, + 14, + "pane 6 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .x, + 77, + "pane 7 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .y, + 14, + "pane 7 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .cols, + 7, + "pane 7 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .rows, + 16, + "pane 7 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(8)) + .unwrap() + .position_and_size() + .x, + 85, + "pane 8 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(8)) + .unwrap() + .position_and_size() + .y, + 14, + "pane 8 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(8)) + .unwrap() + .position_and_size() + .cols, + 6, + "pane 8 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(8)) + .unwrap() + .position_and_size() + .rows, + 16, + "pane 8 row count" + ); +} + +#[test] +pub fn resize_up_with_panes_below_aligned_left_and_right_with_to_the_left_and_right() { + // ┌─┬─┬───┬─┬─┐ ┌─┬─┬───┬─┬─┐ + // │ │ │███│ │ │ │ │ │███│ │ │ + // │ │ │███│ │ │ │ ├─┴───┴─┤ │ + // ├─┼─┴───┴─┼─┤ ==resize=up==> ├─┤ ├─┤ + // │ │ │ │ │ │ │ │ + // │ │ │ │ │ │ │ │ + // └─┴───────┴─┘ └─┴───────┴─┘ + // █ == focused pane + let position_and_size = PositionAndSize { + cols: 121, + rows: 30, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.horizontal_split(PaneId::Terminal(2)); + tab.move_focus_up(); + tab.vertical_split(PaneId::Terminal(3)); + tab.vertical_split(PaneId::Terminal(4)); + tab.move_focus_down(); + tab.vertical_split(PaneId::Terminal(5)); + tab.vertical_split(PaneId::Terminal(6)); + tab.move_focus_up(); + tab.move_focus_left(); + tab.vertical_split(PaneId::Terminal(7)); + tab.vertical_split(PaneId::Terminal(8)); + tab.move_focus_left(); + tab.resize_up(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 1 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 1 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 1 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 15, + "pane 1 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .x, + 0, + "pane 2 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .y, + 16, + "pane 2 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .cols, + 60, + "pane 2 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 14, + "pane 2 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 3 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 3 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .cols, + 15, + "pane 3 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(3)) + .unwrap() + .position_and_size() + .rows, + 13, + "pane 3 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .x, + 92, + "pane 4 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 4 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .cols, + 29, + "pane 4 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(4)) + .unwrap() + .position_and_size() + .rows, + 15, + "pane 4 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .x, + 61, + "pane 5 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .y, + 14, + "pane 5 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .cols, + 30, + "pane 5 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(5)) + .unwrap() + .position_and_size() + .rows, + 16, + "pane 5 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .x, + 92, + "pane 6 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .y, + 16, + "pane 6 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .cols, + 29, + "pane 6 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(6)) + .unwrap() + .position_and_size() + .rows, + 14, + "pane 6 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .x, + 77, + "pane 7 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 7 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .cols, + 7, + "pane 7 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(7)) + .unwrap() + .position_and_size() + .rows, + 13, + "pane 7 row count" + ); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(8)) + .unwrap() + .position_and_size() + .x, + 85, + "pane 8 x position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(8)) + .unwrap() + .position_and_size() + .y, + 0, + "pane 8 y position" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(8)) + .unwrap() + .position_and_size() + .cols, + 6, + "pane 8 column count" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(8)) + .unwrap() + .position_and_size() + .rows, + 13, + "pane 8 row count" + ); +} + +#[test] +pub fn cannot_resize_up_when_pane_above_is_at_minimum_height() { + // ┌───────────┐ ┌───────────┐ + // │ │ │ │ + // ├───────────┤ ==resize=up==> ├───────────┤ + // │███████████│ │███████████│ + // └───────────┘ └───────────┘ + // █ == focused pane + + let position_and_size = PositionAndSize { + cols: 121, + rows: 7, + x: 0, + y: 0, + ..Default::default() + }; + let mut tab = create_new_tab(position_and_size); + tab.horizontal_split(PaneId::Terminal(2)); + tab.resize_down(); + + assert_eq!( + tab.panes + .get(&PaneId::Terminal(1)) + .unwrap() + .position_and_size() + .rows, + 3, + "pane 1 height stayed the same" + ); + assert_eq!( + tab.panes + .get(&PaneId::Terminal(2)) + .unwrap() + .position_and_size() + .rows, + 3, + "pane 2 height stayed the same" + ); +} |
