zellij/zellij-utils/src/input/unit/layout_test.rs
Aram Drevekenin 799fa5de8d
Floating panes in layouts (#2047)
* work

* tests passing

* tests: floating panes in layouts

* panes(plugins): floating plugins working

* refactor(tab): layout applier

* style(comment): remove outdated

* style(fmt): rustfmt
2022-12-24 15:48:04 +01:00

1746 lines
48 KiB
Rust

use super::super::layout::*;
use insta::assert_snapshot;
#[test]
fn empty_layout() {
let kdl_layout = "layout";
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
let expected_layout = Layout {
template: Some(PaneLayout::default()),
..Default::default()
};
assert_eq!(layout, expected_layout);
}
#[test]
fn layout_with_one_pane() {
let kdl_layout = r#"
layout {
pane
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
let expected_layout = Layout {
template: Some(PaneLayout {
children: vec![PaneLayout::default()],
..Default::default()
}),
..Default::default()
};
assert_eq!(layout, expected_layout);
}
#[test]
fn layout_with_multiple_panes() {
let kdl_layout = r#"
layout {
pane
pane
pane
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
let expected_layout = Layout {
template: Some(PaneLayout {
children: vec![
PaneLayout::default(),
PaneLayout::default(),
PaneLayout::default(),
],
..Default::default()
}),
..Default::default()
};
assert_eq!(layout, expected_layout);
}
#[test]
fn layout_with_nested_panes() {
let kdl_layout = r#"
layout {
pane split_direction="Vertical" {
pane
pane
}
pane {
pane
pane
}
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
let expected_layout = Layout {
template: Some(PaneLayout {
children: vec![
PaneLayout {
children_split_direction: SplitDirection::Vertical,
children: vec![PaneLayout::default(), PaneLayout::default()],
..Default::default()
},
PaneLayout {
children: vec![PaneLayout::default(), PaneLayout::default()],
..Default::default()
},
],
..Default::default()
}),
..Default::default()
};
assert_eq!(layout, expected_layout);
}
#[test]
fn layout_with_floating_panes() {
let kdl_layout = r#"
layout {
floating_panes {
pane
pane {
x 10
y "10%"
width 10
height "10%"
}
pane x=10 y="10%"
pane command="htop"
}
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
let expected_layout = Layout {
template: Some(PaneLayout::default()),
floating_panes_template: vec![
FloatingPanesLayout::default(),
FloatingPanesLayout {
x: Some(PercentOrFixed::Fixed(10)),
y: Some(PercentOrFixed::Percent(10)),
width: Some(PercentOrFixed::Fixed(10)),
height: Some(PercentOrFixed::Percent(10)),
..Default::default()
},
FloatingPanesLayout {
x: Some(PercentOrFixed::Fixed(10)),
y: Some(PercentOrFixed::Percent(10)),
..Default::default()
},
FloatingPanesLayout {
run: Some(Run::Command(RunCommand {
command: PathBuf::from("htop"),
hold_on_close: true,
..Default::default()
})),
..Default::default()
},
],
..Default::default()
};
assert_eq!(layout, expected_layout);
}
#[test]
fn layout_with_mixed_panes_and_floating_panes() {
let kdl_layout = r#"
layout {
pane
pane
floating_panes {
pane
}
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
let expected_layout = Layout {
template: Some(PaneLayout {
children: vec![PaneLayout::default(), PaneLayout::default()],
..Default::default()
}),
floating_panes_template: vec![FloatingPanesLayout::default()],
..Default::default()
};
assert_eq!(layout, expected_layout);
}
#[test]
fn layout_with_floating_panes_template() {
let kdl_layout = r#"
layout {
pane_template name="my_cool_template" {
x 10
y "10%"
}
pane
floating_panes {
pane
my_cool_template
}
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
let expected_layout = Layout {
template: Some(PaneLayout {
children: vec![PaneLayout::default()],
..Default::default()
}),
floating_panes_template: vec![
FloatingPanesLayout::default(),
FloatingPanesLayout {
x: Some(PercentOrFixed::Fixed(10)),
y: Some(PercentOrFixed::Percent(10)),
..Default::default()
},
],
..Default::default()
};
assert_eq!(layout, expected_layout);
}
#[test]
fn layout_with_shared_tiled_and_floating_panes_template() {
let kdl_layout = r#"
layout {
pane_template name="htop" {
command "htop"
}
htop
floating_panes {
pane
htop
}
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
let expected_layout = Layout {
template: Some(PaneLayout {
children: vec![PaneLayout {
run: Some(Run::Command(RunCommand {
command: PathBuf::from("htop"),
hold_on_close: true,
..Default::default()
})),
..Default::default()
}],
..Default::default()
}),
floating_panes_template: vec![
FloatingPanesLayout::default(),
FloatingPanesLayout {
run: Some(Run::Command(RunCommand {
command: PathBuf::from("htop"),
hold_on_close: true,
..Default::default()
})),
..Default::default()
},
],
..Default::default()
};
assert_eq!(layout, expected_layout);
}
#[test]
fn layout_with_tabs_and_floating_panes() {
let kdl_layout = r#"
layout {
tab {
floating_panes {
pane
}
}
tab {
floating_panes {
pane
pane
}
}
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
assert_snapshot!(format!("{:#?}", layout));
}
#[test]
fn layout_with_tabs() {
let kdl_layout = r#"
layout {
tab
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
let expected_layout = Layout {
tabs: vec![(None, PaneLayout::default(), vec![])],
template: Some(PaneLayout::default()),
..Default::default()
};
assert_eq!(layout, expected_layout);
}
#[test]
fn layout_with_nested_differing_tabs() {
let kdl_layout = r#"
layout {
tab split_direction="Vertical" {
pane
pane
pane
}
tab {
pane
pane
}
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
let expected_layout = Layout {
tabs: vec![
(
None,
PaneLayout {
children_split_direction: SplitDirection::Vertical,
children: vec![
PaneLayout::default(),
PaneLayout::default(),
PaneLayout::default(),
],
..Default::default()
},
vec![], // floating panes
),
(
None,
PaneLayout {
children_split_direction: SplitDirection::Horizontal,
children: vec![PaneLayout::default(), PaneLayout::default()],
..Default::default()
},
vec![], // floating panes
),
],
template: Some(PaneLayout::default()),
..Default::default()
};
assert_eq!(layout, expected_layout);
}
#[test]
fn layout_with_panes_in_different_mixed_split_sizes() {
let kdl_layout = r#"
layout {
pane size=1;
pane size="10%";
pane;
pane size=2;
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
let expected_layout = Layout {
template: Some(PaneLayout {
children: vec![
PaneLayout {
split_size: Some(SplitSize::Fixed(1)),
..Default::default()
},
PaneLayout {
split_size: Some(SplitSize::Percent(10)),
..Default::default()
},
PaneLayout {
split_size: None,
..Default::default()
},
PaneLayout {
split_size: Some(SplitSize::Fixed(2)),
..Default::default()
},
],
..Default::default()
}),
..Default::default()
};
assert_eq!(layout, expected_layout);
}
#[test]
fn layout_with_command_panes() {
let kdl_layout = r#"
layout {
pane command="htop"
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
let expected_layout = Layout {
template: Some(PaneLayout {
children: vec![PaneLayout {
run: Some(Run::Command(RunCommand {
command: PathBuf::from("htop"),
hold_on_close: true,
..Default::default()
})),
..Default::default()
}],
..Default::default()
}),
..Default::default()
};
assert_eq!(layout, expected_layout);
}
#[test]
fn layout_with_command_panes_and_cwd() {
let kdl_layout = r#"
layout {
pane command="htop" cwd="/path/to/my/cwd"
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
let expected_layout = Layout {
template: Some(PaneLayout {
children: vec![PaneLayout {
run: Some(Run::Command(RunCommand {
command: PathBuf::from("htop"),
cwd: Some(PathBuf::from("/path/to/my/cwd")),
hold_on_close: true,
..Default::default()
})),
..Default::default()
}],
..Default::default()
}),
..Default::default()
};
assert_eq!(layout, expected_layout);
}
#[test]
fn layout_with_command_panes_and_cwd_and_args() {
let kdl_layout = r#"
layout {
pane command="htop" cwd="/path/to/my/cwd" {
args "-h" "-v"
}
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
let expected_layout = Layout {
template: Some(PaneLayout {
children: vec![PaneLayout {
run: Some(Run::Command(RunCommand {
command: PathBuf::from("htop"),
cwd: Some(PathBuf::from("/path/to/my/cwd")),
args: vec![String::from("-h"), String::from("-v")],
hold_on_close: true,
..Default::default()
})),
..Default::default()
}],
..Default::default()
}),
..Default::default()
};
assert_eq!(layout, expected_layout);
}
#[test]
fn layout_with_command_panes_and_close_on_exit() {
let kdl_layout = r#"
layout {
pane command="htop" {
close_on_exit true
}
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
assert_snapshot!(format!("{:#?}", layout));
}
#[test]
fn layout_with_command_panes_and_start_suspended() {
let kdl_layout = r#"
layout {
pane command="htop" {
start_suspended true
}
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
assert_snapshot!(format!("{:#?}", layout));
}
#[test]
fn layout_with_plugin_panes() {
let kdl_layout = r#"
layout {
pane {
plugin location="zellij:tab-bar"
}
pane {
plugin location="file:/path/to/my/plugin.wasm"
}
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
let expected_layout = Layout {
template: Some(PaneLayout {
children: vec![
PaneLayout {
run: Some(Run::Plugin(RunPlugin {
location: RunPluginLocation::Zellij(PluginTag::new("tab-bar")),
_allow_exec_host_cmd: false,
})),
..Default::default()
},
PaneLayout {
run: Some(Run::Plugin(RunPlugin {
location: RunPluginLocation::File(PathBuf::from("/path/to/my/plugin.wasm")),
_allow_exec_host_cmd: false,
})),
..Default::default()
},
],
..Default::default()
}),
..Default::default()
};
assert_eq!(layout, expected_layout);
}
#[test]
fn layout_with_borderless_panes() {
let kdl_layout = r#"
layout {
pane borderless=true
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
let expected_layout = Layout {
template: Some(PaneLayout {
children: vec![PaneLayout {
borderless: true,
..Default::default()
}],
..Default::default()
}),
..Default::default()
};
assert_eq!(layout, expected_layout);
}
#[test]
fn layout_with_focused_panes() {
let kdl_layout = r#"
layout {
pane focus=true
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
let expected_layout = Layout {
template: Some(PaneLayout {
children: vec![PaneLayout {
focus: Some(true),
..Default::default()
}],
..Default::default()
}),
..Default::default()
};
assert_eq!(layout, expected_layout);
}
#[test]
fn layout_with_pane_names() {
let kdl_layout = r#"
layout {
pane name="my awesome pane"
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
let expected_layout = Layout {
template: Some(PaneLayout {
children: vec![PaneLayout {
name: Some("my awesome pane".into()),
..Default::default()
}],
..Default::default()
}),
..Default::default()
};
assert_eq!(layout, expected_layout);
}
#[test]
fn layout_with_tab_names() {
let kdl_layout = r#"
layout {
tab name="my cool tab name 1"
tab name="my cool tab name 2"
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
let expected_layout = Layout {
tabs: vec![
(
Some("my cool tab name 1".into()),
PaneLayout {
children: vec![],
..Default::default()
},
vec![], // floating panes
),
(
Some("my cool tab name 2".into()),
PaneLayout {
children: vec![],
..Default::default()
},
vec![], // floating panes
),
],
template: Some(PaneLayout::default()),
..Default::default()
};
assert_eq!(layout, expected_layout);
}
#[test]
fn layout_with_focused_tab() {
let kdl_layout = r#"
layout {
tab
tab focus=true
tab
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
let expected_layout = Layout {
tabs: vec![
(None, PaneLayout::default(), vec![]),
(None, PaneLayout::default(), vec![]),
(None, PaneLayout::default(), vec![]),
],
template: Some(PaneLayout::default()),
focused_tab_index: Some(1),
..Default::default()
};
assert_eq!(layout, expected_layout);
}
#[test]
fn layout_with_tab_templates() {
let kdl_layout = r#"
layout {
tab_template name="one-above-one-below" {
pane
children
pane
}
one-above-one-below name="my first tab" split_direction="Vertical" {
pane
pane
}
one-above-one-below name="my second tab" {
pane
pane
}
one-above-one-below
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
let expected_layout = Layout {
tabs: vec![
(
Some("my first tab".into()),
PaneLayout {
children_split_direction: SplitDirection::Horizontal,
children: vec![
PaneLayout::default(),
PaneLayout {
children_split_direction: SplitDirection::Vertical,
children: vec![PaneLayout::default(), PaneLayout::default()],
..Default::default()
},
PaneLayout::default(),
],
..Default::default()
},
vec![], // floating panes
),
(
Some("my second tab".into()),
PaneLayout {
children_split_direction: SplitDirection::Horizontal,
children: vec![
PaneLayout::default(),
PaneLayout {
children_split_direction: SplitDirection::Horizontal,
children: vec![PaneLayout::default(), PaneLayout::default()],
..Default::default()
},
PaneLayout::default(),
],
..Default::default()
},
vec![], // floating panes
),
(
None,
PaneLayout {
children_split_direction: SplitDirection::Horizontal,
children: vec![
PaneLayout::default(),
PaneLayout::default(),
PaneLayout::default(),
],
..Default::default()
},
vec![], // floating panes
),
],
template: Some(PaneLayout::default()),
..Default::default()
};
assert_eq!(layout, expected_layout);
}
#[test]
fn layout_with_default_tab_template() {
let kdl_layout = r#"
layout {
default_tab_template {
pane
children
pane
}
tab name="my first tab" split_direction="Vertical" {
pane
pane
}
tab name="my second tab" {
pane
pane
}
tab
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
assert_snapshot!(format!("{:#?}", layout));
}
#[test]
fn layout_with_pane_templates() {
let kdl_layout = r#"
layout {
pane_template name="left-and-right" split_direction="Vertical" {
pane
children
pane
}
left-and-right {
pane
}
left-and-right {
pane
pane
}
left-and-right split_direction="Vertical" {
pane
pane
}
left-and-right
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
assert_snapshot!(format!("{:#?}", layout));
}
#[test]
fn layout_with_tab_and_pane_templates() {
let kdl_layout = r#"
layout {
tab_template name="left-right-and-htop" {
left-and-right {
pane command="htop"
}
}
pane_template name="left-and-right" split_direction="Vertical" {
pane
children
pane
}
left-right-and-htop
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
assert_snapshot!(format!("{:#?}", layout));
}
#[test]
fn layout_with_nested_pane_templates() {
let kdl_layout = r#"
layout {
pane_template name="left-and-right" split_direction="Vertical" {
pane
children
up-and-down
pane
}
pane_template name="up-and-down" split_direction="Horizontal" {
pane
pane
}
left-and-right
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
assert_snapshot!(format!("{:#?}", layout));
}
#[test]
fn layout_with_nested_branched_pane_templates() {
let kdl_layout = r#"
layout {
pane_template name="left-and-right" split_direction="Vertical" {
pane
children
up-and-down
three-horizontal-panes
}
pane_template name="three-horizontal-panes" split_direction="Horizontal" {
pane
pane
pane
}
pane_template name="up-and-down" split_direction="Horizontal" {
pane
pane
}
left-and-right
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
assert_snapshot!(format!("{:#?}", layout));
}
#[test]
fn circular_dependency_pane_templates_error() {
let kdl_layout = r#"
layout {
pane_template name="one" split_direction="Vertical" {
pane
children
two
}
pane_template name="two" split_direction="Horizontal" {
pane
three
pane
}
pane_template name="three" split_direction="Horizontal" {
one
}
one
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None);
assert!(layout.is_err(), "circular dependency detected");
}
#[test]
fn children_not_as_first_child_of_tab_template() {
let kdl_layout = r#"
layout {
tab_template name="horizontal-with-vertical-top" {
pane split_direction="Vertical" {
pane
children
}
pane
}
horizontal-with-vertical-top name="my tab" {
pane
pane
}
horizontal-with-vertical-top
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
assert_snapshot!(format!("{:#?}", layout));
}
#[test]
fn error_on_more_than_one_children_block_in_tab_template() {
let kdl_layout = r#"
layout {
tab_template name="horizontal-with-vertical-top" {
pane split_direction="Vertical" {
pane
children
}
children
pane
}
horizontal-with-vertical-top name="my tab" {
pane
pane
}
horizontal-with-vertical-top
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None);
assert!(
layout.is_err(),
"error provided for more than one children block"
);
}
#[test]
fn children_not_as_first_child_of_pane_template() {
let kdl_layout = r#"
layout {
pane_template name="horizontal-with-vertical-top" {
pane split_direction="Vertical" {
pane
children
}
pane
}
horizontal-with-vertical-top name="my pane" {
pane
pane
}
horizontal-with-vertical-top
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
assert_snapshot!(format!("{:#?}", layout));
}
#[test]
fn error_on_more_than_one_children_block_in_pane_template() {
let kdl_layout = r#"
layout {
pane_template name="horizontal-with-vertical-top" {
pane split_direction="Vertical" {
pane
children
}
children
pane
}
horizontal-with-vertical-top name="my tab" {
pane
pane
}
horizontal-with-vertical-top
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None);
assert!(
layout.is_err(),
"error provided for more than one children block"
);
}
#[test]
fn combined_tab_and_pane_template_both_with_children() {
let kdl_layout = r#"
layout {
tab_template name="horizontal-with-vertical-top" {
vertical-sandwich {
pane name="middle"
}
children
}
pane_template name="vertical-sandwich" split_direction="Vertical" {
pane
children
pane
}
horizontal-with-vertical-top name="my tab" {
pane
pane
}
horizontal-with-vertical-top
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
assert_snapshot!(format!("{:#?}", layout));
}
#[test]
fn cannot_define_tab_template_name_with_space() {
let kdl_layout = r#"
layout {
tab_template name="with space" {
pane
children
pane
}
pane
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None);
assert!(layout.is_err(), "error provided for tab name with space");
}
#[test]
fn cannot_define_pane_template_name_with_space() {
let kdl_layout = r#"
layout {
pane_template name="with space" {
pane
children
pane
}
pane
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None);
assert!(layout.is_err(), "error provided for tab name with space");
}
#[test]
fn cannot_define_panes_and_tabs_on_same_level() {
let kdl_layout = r#"
layout {
pane
tab {
pane
}
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None);
assert!(
layout.is_err(),
"error provided for tab and pane on the same level"
);
}
#[test]
fn cannot_define_tab_template_names_as_keywords() {
let keywords = vec![
"pane",
"layout",
"pane_template",
"tab_template",
"default_tab_template",
"command",
"plugin",
"children",
"tab",
];
for keyword in keywords {
let kdl_layout = format!(
"
layout {{
tab_template name=\"{}\" {{
pane
children
pane
}}
pane
}}
",
keyword
);
let layout = Layout::from_kdl(&kdl_layout, "layout_file_name".into(), None);
assert!(
layout.is_err(),
"{}",
format!(
"error provided for tab template name with keyword: {}",
keyword
)
);
}
}
#[test]
fn cannot_define_pane_template_names_as_keywords() {
let keywords = vec![
"pane",
"layout",
"pane_template",
"tab_template",
"command",
"plugin",
"children",
"tab",
];
for keyword in keywords {
let kdl_layout = format!(
"
layout {{
pane_template name=\"{}\" {{
pane
children
pane
}}
pane
}}
",
keyword
);
let layout = Layout::from_kdl(&kdl_layout, "layout_file_name".into(), None);
assert!(
layout.is_err(),
"{}",
format!(
"error provided for pane template name with keyword: {}",
keyword
)
);
}
}
#[test]
fn error_on_multiple_layout_nodes_in_file() {
let kdl_layout = format!(
"
layout
layout
"
);
let layout_error = Layout::from_kdl(&kdl_layout, "layout_file_name".into(), None).unwrap_err();
assert_snapshot!(format!("{:?}", layout_error));
}
#[test]
fn error_on_unknown_layout_node() {
let kdl_layout = format!(
"
layout {{
pane
i_am_not_a_proper_node
pane
}}
"
);
let layout_error = Layout::from_kdl(&kdl_layout, "layout_file_name".into(), None).unwrap_err();
assert_snapshot!(format!("{:?}", layout_error));
}
#[test]
fn error_on_unknown_layout_pane_property() {
let kdl_layout = format!(
"
layout {{
pane spit_size=1
}}
"
);
let layout_error = Layout::from_kdl(&kdl_layout, "layout_file_name".into(), None).unwrap_err();
assert_snapshot!(format!("{:?}", layout_error));
}
#[test]
fn error_on_unknown_layout_pane_template_property() {
let kdl_layout = format!(
"
layout {{
pane_template name=\"my_cool_template\" spit_size=1
}}
"
);
let layout_error = Layout::from_kdl(&kdl_layout, "layout_file_name".into(), None).unwrap_err();
assert_snapshot!(format!("{:?}", layout_error));
}
#[test]
fn error_on_unknown_layout_tab_property() {
let kdl_layout = format!(
"
layout {{
tab spit_size=1
}}
"
);
let layout_error = Layout::from_kdl(&kdl_layout, "layout_file_name".into(), None).unwrap_err();
assert_snapshot!(format!("{:?}", layout_error));
}
#[test]
fn error_on_unknown_layout_tab_template_property() {
let kdl_layout = format!(
"
layout {{
tab_template name=\"my_cool_template\" spit_size=1
}}
"
);
let layout_error = Layout::from_kdl(&kdl_layout, "layout_file_name".into(), None).unwrap_err();
assert_snapshot!(format!("{:?}", layout_error));
}
#[test]
fn error_on_pane_templates_without_a_name() {
let kdl_layout = format!(
"
layout {{
pane_template {{
pane
children
pane
}}
}}
"
);
let layout_error = Layout::from_kdl(&kdl_layout, "layout_file_name".into(), None).unwrap_err();
assert_snapshot!(format!("{:?}", layout_error));
}
#[test]
fn error_on_tab_templates_without_a_name() {
let kdl_layout = format!(
"
layout {{
tab_template {{
pane
children
pane
}}
}}
"
);
let layout_error = Layout::from_kdl(&kdl_layout, "layout_file_name".into(), None).unwrap_err();
assert_snapshot!(format!("{:?}", layout_error));
}
#[test]
fn error_on_more_than_one_focused_tab() {
let kdl_layout = r#"
layout {
tab focus=true
tab focus=true
tab
}
"#;
let layout_error = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap_err();
assert_snapshot!(format!("{:?}", layout_error));
}
#[test]
fn args_override_args_in_template() {
let kdl_layout = r#"
layout {
pane_template name="tail" {
command "tail"
args "-f" "/tmp/foo"
}
tail
tail {
args "-f" "/tmp/bar"
}
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
assert_snapshot!(format!("{:#?}", layout));
}
#[test]
fn close_on_exit_overrides_close_on_exit_in_template() {
let kdl_layout = r#"
layout {
pane_template name="tail" {
command "tail"
close_on_exit false
}
tail
tail {
close_on_exit true
}
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
assert_snapshot!(format!("{:#?}", layout));
}
#[test]
fn args_added_to_args_in_template() {
let kdl_layout = r#"
layout {
pane_template name="tail" {
command "tail"
}
tail
tail {
args "-f" "/tmp/bar"
}
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
assert_snapshot!(format!("{:#?}", layout));
}
#[test]
fn close_on_exit_added_to_close_on_exit_in_template() {
let kdl_layout = r#"
layout {
pane_template name="tail" {
command "tail"
}
tail
tail {
close_on_exit true
}
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
assert_snapshot!(format!("{:#?}", layout));
}
#[test]
fn cwd_override_cwd_in_template() {
let kdl_layout = r#"
layout {
pane_template name="tail" {
command "tail"
cwd "/tmp"
}
tail
tail {
cwd "/"
}
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
assert_snapshot!(format!("{:#?}", layout));
}
#[test]
fn cwd_added_to_cwd_in_template() {
let kdl_layout = r#"
layout {
pane_template name="tail" {
command "tail"
}
tail
tail {
cwd "/home"
}
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
assert_snapshot!(format!("{:#?}", layout));
}
#[test]
fn error_on_mixed_command_and_child_panes() {
let kdl_layout = r#"
layout {
pane command="tail" {
pane
}
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None);
assert!(layout.is_err(), "error provided");
}
#[test]
fn error_on_mixed_cwd_and_child_panes() {
let kdl_layout = r#"
layout {
pane cwd="/tmp" {
pane
pane
}
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None);
assert!(layout.is_err(), "error provided");
}
#[test]
fn error_on_bare_args_without_command() {
let kdl_layout = r#"
layout {
pane {
args "-f"
}
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None);
assert!(layout.is_err(), "error provided");
}
#[test]
fn error_on_bare_close_on_exit_without_command() {
let kdl_layout = r#"
layout {
pane {
close_on_exit true
}
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None);
assert!(layout.is_err(), "error provided");
}
#[test]
fn error_on_bare_args_in_template_without_command() {
let kdl_layout = r#"
layout {
pane_template name="my_template"
my_template {
args "--help"
}
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None);
assert!(layout.is_err(), "error provided");
}
#[test]
fn error_on_bare_close_on_exit_in_template_without_command() {
let kdl_layout = r#"
layout {
pane_template name="my_template"
my_template {
close_on_exit true
}
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None);
assert!(layout.is_err(), "error provided");
}
#[test]
fn pane_template_command_with_cwd_overriden_by_its_consumers_command_cwd() {
let kdl_layout = r#"
layout {
cwd "/tmp"
pane_template name="tail" {
command "tail"
cwd "bar"
}
tail command="pwd" {
cwd "foo"
}
// pane should have /tmp/foo and not /tmp/bar as cwd
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
assert_snapshot!(format!("{:#?}", layout));
}
#[test]
fn pane_template_command_with_cwd_remains_when_its_consumer_command_does_not_have_a_cwd() {
let kdl_layout = r#"
layout {
cwd "/tmp"
pane_template name="tail" {
command "tail"
cwd "bar"
}
tail command="pwd"
// pane should have /tmp/bar as its cwd with the pwd command
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
assert_snapshot!(format!("{:#?}", layout));
}
#[test]
fn pane_template_command_without_cwd_is_overriden_by_its_consumers_cwd() {
let kdl_layout = r#"
layout {
cwd "/tmp"
pane_template name="tail" {
command "tail"
}
tail command="pwd" {
cwd "bar"
}
// pane should have /tmp/bar as its cwd with the pwd command
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
assert_snapshot!(format!("{:#?}", layout));
}
#[test]
fn pane_template_command_with_cwd_is_overriden_by_its_consumers_bare_cwd() {
let kdl_layout = r#"
layout {
cwd "/tmp"
pane_template name="tail" {
command "tail"
cwd "foo"
}
tail {
cwd "bar"
}
// pane should have /tmp/bar as its cwd with the tail command
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
assert_snapshot!(format!("{:#?}", layout));
}
#[test]
fn pane_template_command_without_cwd_receives_its_consumers_bare_cwd() {
let kdl_layout = r#"
layout {
cwd "/tmp"
pane_template name="tail" {
command "tail"
}
tail {
cwd "bar"
}
// pane should have /tmp/bar as its cwd with the tail command
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
assert_snapshot!(format!("{:#?}", layout));
}
#[test]
fn pane_template_with_bare_cwd_overriden_by_its_consumers_bare_cwd() {
let kdl_layout = r#"
layout {
cwd "/tmp"
pane_template name="tail" {
cwd "foo"
}
tail {
cwd "bar"
}
// pane should have /tmp/foo without a command
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
assert_snapshot!(format!("{:#?}", layout));
}
#[test]
fn pane_template_with_bare_propagated_to_its_consumer_command_without_cwd() {
let kdl_layout = r#"
layout {
cwd "/tmp"
pane_template name="tail" {
cwd "foo"
}
tail command="tail"
// pane should have /tmp/foo with the tail command
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
assert_snapshot!(format!("{:#?}", layout));
}
#[test]
fn pane_template_with_bare_propagated_to_its_consumer_command_with_cwd() {
let kdl_layout = r#"
layout {
cwd "/tmp"
pane_template name="tail" {
cwd "foo"
}
tail command="tail" {
cwd "bar"
}
// pane should have /tmp/bar with the tail command
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
assert_snapshot!(format!("{:#?}", layout));
}
#[test]
fn pane_template_with_bare_propagated_to_its_consumer_edit() {
let kdl_layout = r#"
layout {
cwd "/tmp"
pane_template name="tail" {
cwd "foo"
}
tail edit="bar"
// pane should have /tmp/foo/bar with the edit file variant
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
assert_snapshot!(format!("{:#?}", layout));
}
#[test]
fn pane_template_with_command_propagated_to_its_consumer_edit() {
let kdl_layout = r#"
layout {
cwd "/tmp"
pane_template name="tail" command="not-vim" {
cwd "foo"
}
tail edit="bar"
// pane should have /tmp/foo/bar with the edit file variant
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
assert_snapshot!(format!("{:#?}", layout));
}
#[test]
fn global_cwd_given_to_panes_without_cwd() {
let kdl_layout = r#"
layout {
cwd "/tmp"
pane
pane command="tail"
// both should have the /tmp cwd
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
assert_snapshot!(format!("{:#?}", layout));
}
#[test]
fn global_cwd_prepended_to_panes_with_cwd() {
let kdl_layout = r#"
layout {
cwd "/tmp"
pane cwd="foo" // should be /tmp/foo
pane command="tail" cwd="/home/foo" // should be /home/foo because its an absolute path
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
assert_snapshot!(format!("{:#?}", layout));
}
#[test]
fn global_cwd_passed_from_layout_constructor() {
// this is used by the new-tab cli action with --cwd
let kdl_layout = r#"
layout {
pane
pane command="tail"
// both should have the /tmp cwd
}
"#;
let layout = Layout::from_kdl(
kdl_layout,
"layout_file_name".into(),
Some(PathBuf::from("/tmp")),
)
.unwrap();
assert_snapshot!(format!("{:#?}", layout));
}
#[test]
fn global_cwd_passed_from_layout_constructor_overrides_global_cwd_in_layout_file() {
// this is used by the new-tab cli action with --cwd
let kdl_layout = r#"
layout {
cwd "/home"
pane
pane command="tail"
// both should have the /tmp cwd
}
"#;
let layout = Layout::from_kdl(
kdl_layout,
"layout_file_name".into(),
Some(PathBuf::from("/tmp")),
)
.unwrap();
assert_snapshot!(format!("{:#?}", layout));
}
#[test]
fn global_cwd_with_tab_cwd_given_to_panes_without_cwd() {
let kdl_layout = r#"
layout {
cwd "/tmp"
tab cwd="./foo" {
pane
pane command="tail"
}
// both should have the /tmp/foo cwd
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
assert_snapshot!(format!("{:#?}", layout));
}
#[test]
fn tab_cwd_given_to_panes_without_cwd() {
let kdl_layout = r#"
layout {
tab cwd="/tmp" {
pane
pane command="tail"
}
// both should have the /tmp cwd
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
assert_snapshot!(format!("{:#?}", layout));
}
#[test]
fn tab_cwd_prepended_to_panes_with_cwd() {
let kdl_layout = r#"
layout {
tab cwd="/tmp" {
pane cwd="./foo"
pane command="tail" cwd="./foo"
}
// both should have the /tmp/foo cwd
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
assert_snapshot!(format!("{:#?}", layout));
}
#[test]
fn global_cwd_and_tab_cwd_prepended_to_panes_with_and_without_cwd() {
let kdl_layout = r#"
layout {
cwd "/tmp"
tab cwd="./foo" {
pane // should have /tmp/foo
pane command="tail" cwd="./bar" // should have /tmp/foo/bar
}
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
assert_snapshot!(format!("{:#?}", layout));
}
#[test]
fn global_cwd_and_tab_cwd_prepended_to_panes_with_and_without_cwd_in_pane_templates() {
let kdl_layout = r#"
layout {
cwd "/tmp"
pane_template name="my_pane_template" {
pane // should have /tmp/foo
pane command="tail" cwd="./bar" // should have /tmp/foo/bar
children
}
tab cwd="./foo" {
my_pane_template {
pane // should have /tmp/foo
}
}
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
assert_snapshot!(format!("{:#?}", layout));
}
#[test]
fn global_cwd_and_tab_cwd_prepended_to_panes_with_and_without_cwd_in_tab_templates() {
let kdl_layout = r#"
layout {
cwd "/tmp"
tab_template name="my_tab_template" {
pane // should have /tmp/foo
pane command="tail" cwd="./bar" // should have /tmp/foo/bar
children
}
my_tab_template cwd="./foo" {
pane // should have /tmp/foo
}
}
"#;
let layout = Layout::from_kdl(kdl_layout, "layout_file_name".into(), None).unwrap();
assert_snapshot!(format!("{:#?}", layout));
}