//! Matrix coverage for app-lifecycle commands (ADR-0003): //! quit, help, rebuild, save / save as, new, load, export, //! import, mode, messages. //! //! App commands don't touch the schema, so the empty schema is //! sufficient. use crate::typing_surface::*; use rdbms_playground::input_render::InputState; #[test] fn quit_parses() { let a = assess_at_end("quit", &schema_empty()); assert!(matches!(a.state, InputState::Valid)); assert_eq!(a.parse_result.as_deref(), Ok("App(Quit)")); crate::snap!("quit", a); } #[test] fn help_parses() { let a = assess_at_end("help", &schema_empty()); assert!(matches!(a.state, InputState::Valid)); assert_eq!(a.parse_result.as_deref(), Ok("App(Help)")); crate::snap!("help", a); } #[test] fn rebuild_parses() { let a = assess_at_end("rebuild", &schema_empty()); assert!(matches!(a.state, InputState::Valid)); crate::snap!("rebuild", a); } #[test] fn save_parses() { let a = assess_at_end("save", &schema_empty()); assert!(matches!(a.state, InputState::Valid)); assert_eq!(a.parse_result.as_deref(), Ok("App(Save)")); crate::snap!("save", a); } #[test] fn save_space_offers_as_keyword() { // Handoff-12 §3 smoke item: `save ` then Tab offers `as`. let a = assess_at_end("save ", &schema_empty()); assert_candidate_present(&a, &["as"]); crate::snap!("save_space", a); } #[test] fn save_as_parses() { let a = assess_at_end("save as", &schema_empty()); assert!(matches!(a.state, InputState::Valid)); assert_eq!(a.parse_result.as_deref(), Ok("App(SaveAs)")); crate::snap!("save_as", a); } #[test] fn new_parses() { let a = assess_at_end("new", &schema_empty()); assert!(matches!(a.state, InputState::Valid)); crate::snap!("new", a); } #[test] fn load_parses() { let a = assess_at_end("load", &schema_empty()); assert!(matches!(a.state, InputState::Valid)); crate::snap!("load", a); } #[test] fn export_with_no_path_parses() { // Export path is optional — `export` alone opens the modal. let a = assess_at_end("export", &schema_empty()); assert!(matches!(a.state, InputState::Valid)); crate::snap!("export_no_path", a); } #[test] fn export_with_path_parses() { let a = assess_at_end("export myproject.zip", &schema_empty()); assert!(matches!(a.state, InputState::Valid)); crate::snap!("export_with_path", a); } #[test] fn import_with_path_parses() { let a = assess_at_end("import bundle.zip", &schema_empty()); assert!(matches!(a.state, InputState::Valid)); crate::snap!("import_with_path", a); } #[test] fn mode_with_value_parses() { let a = assess_at_end("mode advanced", &schema_empty()); assert!(matches!(a.state, InputState::Valid)); crate::snap!("mode_advanced", a); } #[test] fn mode_space_offers_simple_and_advanced() { let a = assess_at_end("mode ", &schema_empty()); assert!(matches!(a.state, InputState::IncompleteAtEof)); assert_candidate_present(&a, &["simple", "advanced"]); crate::snap!("mode_space", a); } #[test] fn messages_with_no_value_parses() { // Messages value is optional — `messages` alone shows the // current verbosity. let a = assess_at_end("messages", &schema_empty()); assert!(matches!(a.state, InputState::Valid)); crate::snap!("messages_no_value", a); } #[test] fn messages_space_offers_short_and_verbose() { let a = assess_at_end("messages ", &schema_empty()); assert_candidate_present(&a, &["short", "verbose"]); crate::snap!("messages_space", a); } #[test] fn messages_with_value_parses() { let a = assess_at_end("messages verbose", &schema_empty()); assert!(matches!(a.state, InputState::Valid)); crate::snap!("messages_verbose", a); } #[test] fn partial_entry_word_classifies_as_definite_error_but_completes() { // `qu` — mid-typing the `quit` entry word. // // KNOWN UX WRINKLE (handoff-13 finding): a partial entry // word is currently classified `DefiniteErrorAt(0)` — the // same as a genuinely unknown command (`frobulate`). The // walker only engages once a *complete* registered entry // word is present; until then `try_walker_route` returns // None and the router emits the synthetic unknown-command // error. So the input pane shows `qu` in error-red even // though it is a valid prefix of `quit`. // // Completion still works (Tab at `qu` → `quit`), so the // user can recover, but the red overlay while typing the // first word is jarring. This test documents the current // behaviour; flagged to the user for a decision rather // than silently asserting it as correct. let a = assess_at_end("qu", &schema_empty()); assert!( matches!(a.state, InputState::DefiniteErrorAt(_)), "documents current behaviour, got {:?}", a.state, ); // Completion recovers — `quit` is offered. assert_candidate_present(&a, &["quit"]); crate::snap!("partial_quit", a); }