use super::claims::{self, Chord, Platform};
use par_term_settings_ui::input_tab::actions_table::AVAILABLE_ACTIONS;
const KNOWN_MISMATCHES: &[(&str, &str)] = &[];
const CLAIMED_BUT_ADVERTISED_AS_NONE: &[&str] = &[];
fn advertised() -> Vec<(&'static str, Chord)> {
AVAILABLE_ACTIONS
.iter()
.filter_map(|(action, _, default)| default.map(|d| (*action, d)))
.map(|(action, d)| {
let chord = claims::parse_chord(d)
.unwrap_or_else(|e| panic!("AVAILABLE_ACTIONS row {action:?}: {e}"));
(action, chord)
})
.collect()
}
#[test]
fn every_advertised_chord_parses() {
let bad: Vec<String> = AVAILABLE_ACTIONS
.iter()
.filter_map(|(action, _, default)| {
let d = (*default)?;
claims::parse_chord(d)
.err()
.map(|e| format!("{action}: {e}"))
})
.collect();
assert!(
bad.is_empty(),
"advertised default chords that do not parse: {bad:#?}"
);
}
#[test]
fn advertised_chord_is_dispatched_by_its_own_action() {
let mut violations: Vec<(String, String)> = Vec::new();
for (action, chord) in advertised() {
match claims::first_claimer(chord) {
None => violations.push((action.to_string(), NOTHING_CLAIMS_IT.to_string())),
Some((source, claimed)) if claimed != action => {
violations.push((action.to_string(), format!("{source}/{claimed}")));
}
Some(_) => {}
}
}
violations.sort();
let mut expected: Vec<(String, String)> = KNOWN_MISMATCHES
.iter()
.map(|(a, s)| (a.to_string(), s.to_string()))
.collect();
expected.sort();
assert_eq!(
violations, expected,
"advertised chords whose first claimer is not the advertising action \
changed. {NOTHING_CLAIMS_IT:?} means the shortcut does nothing at all; \
a `source/action` value means a higher-precedence layer eats the chord \
first. A new entry is a defect; a disappeared entry means a known one \
was fixed and KNOWN_MISMATCHES should shrink."
);
}
const NOTHING_CLAIMS_IT: &str = "<nothing>";
#[test]
fn advertised_chord_agrees_with_the_shipped_default() {
let defaults = par_term_config::Config::default().keybindings;
assert!(
!defaults.is_empty(),
"Config::default() shipped no keybindings — this test would be vacuous"
);
let mut checked = 0usize;
let mut wrong: Vec<String> = Vec::new();
for (action, default) in AVAILABLE_ACTIONS
.iter()
.filter_map(|(action, _, default)| default.map(|default| (*action, default)))
{
let shipped: Vec<claims::Chord> = defaults
.iter()
.filter(|kb| kb.action == action)
.map(|kb| {
claims::parse_chord(&kb.key)
.unwrap_or_else(|e| panic!("shipped default {:?}: {e}", kb.key))
})
.collect();
if shipped.is_empty() {
continue;
}
let shown = claims::parse_chord(default)
.unwrap_or_else(|e| panic!("AVAILABLE_ACTIONS row {action:?}: {e}"));
checked += 1;
if !shipped.contains(&shown) {
wrong.push(format!(
"{action}: table says {default:?}, shipped defaults are {:?}",
defaults
.iter()
.filter(|kb| kb.action == action)
.map(|kb| kb.key.as_str())
.collect::<Vec<_>>()
));
}
}
assert!(checked > 0, "no advertised action has a shipped default");
assert!(
wrong.is_empty(),
"advertised chords that disagree with Config::default().keybindings: {wrong:#?}"
);
}
#[test]
fn paste_copy_is_the_only_hardcoded_source() {
let sources: Vec<&str> = claims::LAYER_CLAIMS.iter().map(|(name, _)| *name).collect();
assert_eq!(
sources,
["paste_copy"],
"the only hardcoded chord source is the inline paste/copy branch, the \
one deliberate exemption from the registry-only rule"
);
}
#[test]
fn the_profile_shortcut_layer_is_gone() {
let handler = include_str!("mod.rs");
for gone in [
"handle_profile_shortcuts",
"KEY_LAYERS:",
"build_shortcut_string",
] {
assert!(
!handler.contains(gone),
"{gone} came back in key_handler/mod.rs"
);
}
assert!(
!std::path::Path::new(concat!(
env!("CARGO_MANIFEST_DIR"),
"/src/app/input_events/key_handler/profiles.rs"
))
.exists(),
"key_handler/profiles.rs (the B59 layer, with its key.leak()) came back"
);
}
#[test]
fn claim_action_names_are_advertised_or_explicitly_internal() {
let unknown: Vec<&str> = claims::LAYER_CLAIMS
.iter()
.flat_map(|(_, cs)| cs.iter())
.map(|c| c.action)
.filter(|a| {
!a.starts_with("internal:") && !AVAILABLE_ACTIONS.iter().any(|(name, _, _)| name == a)
})
.collect();
assert!(
unknown.is_empty(),
"layer claims naming an action that is neither advertised nor prefixed \
`internal:`: {unknown:?}"
);
}
#[test]
fn claimed_actions_advertised_as_having_no_default() {
let unadvertised: Vec<&str> = AVAILABLE_ACTIONS
.iter()
.filter(|(_, _, default)| default.is_none())
.map(|(action, _, _)| *action)
.collect();
let mut found: Vec<String> = claims::claim_chain()
.iter()
.filter(|rule| unadvertised.contains(&rule.action.as_str()))
.map(|rule| format!("{} ({})", rule.action, rule.source))
.collect();
found.sort();
found.dedup();
let mut expected: Vec<String> = CLAIMED_BUT_ADVERTISED_AS_NONE
.iter()
.map(|s| (*s).to_string())
.collect();
expected.sort();
assert_eq!(
found, expected,
"the set of actions that are dispatchable but advertised as having no \
default changed. This is under-advertisement, not a dispatch defect — \
update the list deliberately."
);
}
#[test]
fn chord_parser_rejects_what_it_does_not_understand() {
assert!(claims::parse_chord("Cmd+Nonsense").is_err());
assert!(claims::parse_chord("Cmd+").is_err());
assert!(claims::parse_chord("Cmd+A+B").is_err());
assert!(claims::parse_chord("Shift").is_err());
let plus = claims::parse_chord("Cmd+Plus").expect("Plus is part of the vocabulary");
let equal = claims::parse_chord("Cmd+Equal").expect("Equal is part of the vocabulary");
assert_ne!(
plus, equal,
"`Plus` and `Equal` are different logical keys and must not collapse"
);
}
#[test]
fn cmd_or_ctrl_expands_per_platform() {
let c = claims::parse_chord("CmdOrCtrl+Shift+B").expect("parses");
if Platform::HOST.is_mac() {
assert!(c.mods.sup && !c.mods.ctrl, "CmdOrCtrl is Cmd on macOS");
} else {
assert!(c.mods.ctrl && !c.mods.sup, "CmdOrCtrl is Ctrl elsewhere");
}
assert!(c.mods.shift);
}
#[test]
fn exited_tab_keypress_closes_the_tab_not_the_app() {
use super::{ExitedTabKeypress, exited_tab_keypress_action};
assert_eq!(
exited_tab_keypress_action(false, 3),
ExitedTabKeypress::CloseTab,
"other tabs stay open — the dead tab alone closes"
);
assert_eq!(
exited_tab_keypress_action(false, 1),
ExitedTabKeypress::CloseWindow,
"last tab closes the window, the shell_exit Close path's own rule"
);
assert_eq!(
exited_tab_keypress_action(true, 3),
ExitedTabKeypress::Keep,
"a pending restart prompt owns the key — Enter must reach its handler"
);
assert_eq!(
exited_tab_keypress_action(true, 1),
ExitedTabKeypress::Keep,
"restart pending outranks even the last-tab window close"
);
}
#[test]
fn stray_keypress_cannot_exit_the_event_loop_outside_the_last_tab_arm() {
let source = include_str!("mod.rs").replace("\r\n", "\n");
let exit_lines: Vec<usize> = source
.lines()
.enumerate()
.filter(|(_, line)| {
let trimmed = line.trim_start();
trimmed.contains("event_loop.exit()") && !trimmed.starts_with("//")
})
.map(|(i, _)| i)
.collect();
assert_eq!(
exit_lines.len(),
1,
"handle_key_event must have exactly one event_loop.exit(), and only \
in the ExitedTabKeypress::CloseWindow arm"
);
let exit_pos = source
.lines()
.take(exit_lines[0] + 1)
.map(|l| l.len() + 1)
.sum::<usize>()
.saturating_sub(1);
let window_arm = source.find("ExitedTabKeypress::CloseWindow").expect(
"the exited-tab branch must dispatch through ExitedTabKeypress, not \
call the event loop directly",
);
assert!(
window_arm < exit_pos,
"the exit call must live inside the CloseWindow arm"
);
assert!(
source[..exit_pos].contains("is_shutting_down = true"),
"window close must go through the is_shutting_down path \
handle_shell_exit uses, not a bare loop exit"
);
}
#[test]
fn unconsumed_keys_never_reach_the_pty_tail_while_a_modal_is_open() {
let source = include_str!("mod.rs");
let tail_guard_pos = source
.rfind("if self.any_modal_ui_visible()")
.expect("the modal-guard tail consumption is missing from handle_key_event");
let encode_pos = source
.rfind("handle_key_event_with_mode(")
.expect("handle_key_event must keep its PTY encoding call");
assert!(
tail_guard_pos < encode_pos,
"the tail consumption must precede the PTY encoding call"
);
}