test(tui): expand UX regression snapshots
This commit is contained in:
@@ -33,6 +33,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Inline guidance overlay adds a three-step onboarding tour, keymap-aware cheat sheets (F1 / `?`), and persists completion state via `ui.guidance`.
|
- Inline guidance overlay adds a three-step onboarding tour, keymap-aware cheat sheets (F1 / `?`), and persists completion state via `ui.guidance`.
|
||||||
- Status surface renders a layered HUD with streaming/tool indicators, contextual gauges, and redesigned toast cards featuring icons, countdown timers, and a compact history log.
|
- Status surface renders a layered HUD with streaming/tool indicators, contextual gauges, and redesigned toast cards featuring icons, countdown timers, and a compact history log.
|
||||||
- Published a TUI UX & keybinding playbook documenting modal ergonomics, command metadata, theming tokens, and animation policy.
|
- Published a TUI UX & keybinding playbook documenting modal ergonomics, command metadata, theming tokens, and animation policy.
|
||||||
|
- Automated TUI regression snapshots now cover mode transitions, keymap variants, accessibility presets, and multiple terminal breakpoints.
|
||||||
- Cloud usage tracker persists hourly/weekly token totals, adds a `:limits` command, shows live header badges, and raises toast warnings at 80 %/95 % of the configured quotas.
|
- Cloud usage tracker persists hourly/weekly token totals, adds a `:limits` command, shows live header badges, and raises toast warnings at 80 %/95 % of the configured quotas.
|
||||||
- Message rendering caches wrapped lines and throttles streaming redraws to keep the TUI responsive on long sessions.
|
- Message rendering caches wrapped lines and throttles streaming redraws to keep the TUI responsive on long sessions.
|
||||||
- Model picker badges now inspect provider capabilities so vision/audio/thinking models surface the correct icons even when descriptions are sparse.
|
- Model picker badges now inspect provider capabilities so vision/audio/thinking models surface the correct icons even when descriptions are sparse.
|
||||||
|
|||||||
@@ -10,6 +10,18 @@ use ratatui::{Terminal, backend::TestBackend};
|
|||||||
|
|
||||||
use common::build_chat_app;
|
use common::build_chat_app;
|
||||||
|
|
||||||
|
async fn send_key(app: &mut ChatApp, code: KeyCode, modifiers: KeyModifiers) {
|
||||||
|
app.handle_event(Event::Key(KeyEvent::new(code, modifiers)))
|
||||||
|
.await
|
||||||
|
.expect("send key event");
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn type_text(app: &mut ChatApp, text: &str) {
|
||||||
|
for ch in text.chars() {
|
||||||
|
send_key(app, KeyCode::Char(ch), KeyModifiers::NONE).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn buffer_to_string(buffer: &ratatui::buffer::Buffer) -> String {
|
fn buffer_to_string(buffer: &ratatui::buffer::Buffer) -> String {
|
||||||
let mut output = String::new();
|
let mut output = String::new();
|
||||||
|
|
||||||
@@ -213,3 +225,98 @@ async fn render_guidance_cheatsheet_snapshot() {
|
|||||||
assert_snapshot!("guidance_cheatsheet", snapshot);
|
assert_snapshot!("guidance_cheatsheet", snapshot);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn render_mode_states_snapshots() {
|
||||||
|
let mut normal = build_chat_app(|_| {}, |_| {}).await;
|
||||||
|
with_settings!({ snapshot_suffix => "normal-90x28" }, {
|
||||||
|
let snapshot = render_snapshot(&mut normal, 90, 28);
|
||||||
|
assert_snapshot!("mode_states", snapshot);
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut editing = build_chat_app(|_| {}, |_| {}).await;
|
||||||
|
send_key(&mut editing, KeyCode::Char('i'), KeyModifiers::NONE).await;
|
||||||
|
type_text(&mut editing, "Typing in editing mode").await;
|
||||||
|
with_settings!({ snapshot_suffix => "editing-90x28" }, {
|
||||||
|
let snapshot = render_snapshot(&mut editing, 90, 28);
|
||||||
|
assert_snapshot!("mode_states", snapshot);
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut visual = build_chat_app(
|
||||||
|
|_| {},
|
||||||
|
|session| {
|
||||||
|
let conversation = session.conversation_mut();
|
||||||
|
conversation.push_user_message("Render visual selection across multiple lines.");
|
||||||
|
conversation.push_message(Message::assistant(
|
||||||
|
"Assistant reply for visual mode highlighting.".into(),
|
||||||
|
));
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
send_key(&mut visual, KeyCode::Char('v'), KeyModifiers::NONE).await;
|
||||||
|
send_key(&mut visual, KeyCode::Char('j'), KeyModifiers::NONE).await;
|
||||||
|
send_key(&mut visual, KeyCode::Char('j'), KeyModifiers::NONE).await;
|
||||||
|
with_settings!({ snapshot_suffix => "visual-90x28" }, {
|
||||||
|
let snapshot = render_snapshot(&mut visual, 90, 28);
|
||||||
|
assert_snapshot!("mode_states", snapshot);
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut command = build_chat_app(|_| {}, |_| {}).await;
|
||||||
|
send_key(&mut command, KeyCode::Char(':'), KeyModifiers::NONE).await;
|
||||||
|
type_text(&mut command, "session save").await;
|
||||||
|
with_settings!({ snapshot_suffix => "command-90x28" }, {
|
||||||
|
let snapshot = render_snapshot(&mut command, 90, 28);
|
||||||
|
assert_snapshot!("mode_states", snapshot);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn render_emacs_profile_snapshot() {
|
||||||
|
let mut app = build_chat_app(
|
||||||
|
|cfg| {
|
||||||
|
cfg.ui.keymap_profile = Some("emacs".into());
|
||||||
|
cfg.ui.guidance.coach_marks_complete = true;
|
||||||
|
},
|
||||||
|
|_| {},
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
send_key(&mut app, KeyCode::Char(':'), KeyModifiers::NONE).await;
|
||||||
|
type_text(&mut app, "help").await;
|
||||||
|
|
||||||
|
with_settings!({ snapshot_suffix => "emacs-110x30" }, {
|
||||||
|
let snapshot = render_snapshot(&mut app, 110, 30);
|
||||||
|
assert_snapshot!("emacs_profile", snapshot);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn render_accessibility_snapshots() {
|
||||||
|
let mut high_contrast = build_chat_app(
|
||||||
|
|cfg| {
|
||||||
|
cfg.ui.accessibility.high_contrast = true;
|
||||||
|
cfg.ui.guidance.coach_marks_complete = true;
|
||||||
|
},
|
||||||
|
|_| {},
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
with_settings!({ snapshot_suffix => "high-contrast-100x32" }, {
|
||||||
|
let snapshot = render_snapshot(&mut high_contrast, 100, 32);
|
||||||
|
assert_snapshot!("accessibility_modes", snapshot);
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut reduced_chrome = build_chat_app(
|
||||||
|
|cfg| {
|
||||||
|
cfg.ui.accessibility.reduced_chrome = true;
|
||||||
|
cfg.ui.guidance.coach_marks_complete = true;
|
||||||
|
},
|
||||||
|
|_| {},
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
with_settings!({ snapshot_suffix => "reduced-chrome-100x32" }, {
|
||||||
|
let snapshot = render_snapshot(&mut reduced_chrome, 100, 32);
|
||||||
|
assert_snapshot!("accessibility_modes", snapshot);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
---
|
||||||
|
source: crates/owlen-tui/tests/chat_snapshots.rs
|
||||||
|
expression: snapshot
|
||||||
|
---
|
||||||
|
" "
|
||||||
|
" 🦉 OWLEN v0.2.0 · Mode Chat · Focus Input ollama_local · stub-model · Accessibil "
|
||||||
|
" "
|
||||||
|
" Context metrics not available Cloud usage pending "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" ▌ Chat · stub-model PgUp/PgDn scroll · g/G jump · s save · Ctrl+2 focus "
|
||||||
|
" "
|
||||||
|
" No messages yet. Press 'i' to start typing. "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" Input Press i to start typing · Ctrl+5 focus "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" System/Status "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" NORMAL CHAT Focus INPUT · ⓘ Normal mode • Press F1 for help owlen-tui "
|
||||||
|
" Ctrl+5 Icons: Nerd (auto) 1:1 · Plain Text · UTF-8 "
|
||||||
|
" F1 Help ? Guidance F12 DebugUsage metrics pending · run :limits "
|
||||||
|
" "
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
---
|
||||||
|
source: crates/owlen-tui/tests/chat_snapshots.rs
|
||||||
|
expression: snapshot
|
||||||
|
---
|
||||||
|
" 🦉 OWLEN v0.2.0 · Mode Chat · Focus Input ollama_local · stub-model · Accessibili "
|
||||||
|
" "
|
||||||
|
" Context metrics not available Cloud usage pending "
|
||||||
|
" "
|
||||||
|
" Legend · Normal <60% · Warning 60–85% · Critical >85% · Modes RC "
|
||||||
|
" ▌ Chat · stub-model PgUp/PgDn scroll · g/G jump · s save · Ctrl+2 focus "
|
||||||
|
" No messages yet. Press 'i' to start typing. "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" Input Press i to start typing · Ctrl+5 focus "
|
||||||
|
" Press 'i' to start typing "
|
||||||
|
" "
|
||||||
|
" System/Status "
|
||||||
|
" Icons: Nerd (auto) "
|
||||||
|
" "
|
||||||
|
" NORMAL CHAT Focus INPUT · ⓘ Normal mode • Press F1 for help owlen-tui "
|
||||||
|
" Ctrl+5 Icons: Nerd (auto) 1:1 · Plain Text · UTF-8 "
|
||||||
|
" F1 Help ? Guidance F12 DebugUsage metrics pending · run :limits "
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
---
|
||||||
|
source: crates/owlen-tui/tests/chat_snapshots.rs
|
||||||
|
expression: snapshot
|
||||||
|
---
|
||||||
|
" "
|
||||||
|
" 🦉 OWLEN v0.2.0 · Mode Chat · Focus Input ollama_local · stub-model "
|
||||||
|
" "
|
||||||
|
" Context metri Command Palette Ctrl+P "
|
||||||
|
" "
|
||||||
|
" :help "
|
||||||
|
" ▌ Chat · stub "
|
||||||
|
" "
|
||||||
|
" No messages Commands "
|
||||||
|
" › help F1 / ? "
|
||||||
|
" Open the help overlay "
|
||||||
|
" Support · Modes: Normal, Command · #help #docs #support "
|
||||||
|
" tutorial "
|
||||||
|
" Show keybinding tutorial "
|
||||||
|
" Support · Modes: Command · #help #tutorial #onboarding "
|
||||||
|
" h F1 / ? "
|
||||||
|
" Open the help overlay "
|
||||||
|
" Support · Modes: Normal, Command · #help #docs #support "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" ▌ Command En Enter: run · Tab: autocomplete · /tag filter · Esc: cancel "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" System/Status "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" COMMAND CHAT Focus INPUT ·ⓘ :help owlen-tui "
|
||||||
|
" Ctrl+5 Icons: Nerd (auto) 1:1 · Plain Text · UTF-8 "
|
||||||
|
" F1 Help ? Guidance F12 DebugUsage metrics pending · run :limits "
|
||||||
|
" "
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
---
|
||||||
|
source: crates/owlen-tui/tests/chat_snapshots.rs
|
||||||
|
expression: snapshot
|
||||||
|
---
|
||||||
|
" "
|
||||||
|
" 🦉 OWLEN v0.2.0 · Mode Chat · Focus Input ollama_local · stub-model "
|
||||||
|
" "
|
||||||
|
" Con Command Palette Ctrl+P "
|
||||||
|
" "
|
||||||
|
" :session save "
|
||||||
|
" ▌ C "
|
||||||
|
" "
|
||||||
|
" N Commands "
|
||||||
|
" › session save "
|
||||||
|
" Save the current conversation "
|
||||||
|
" Sessions · Modes: Command · #session #save #history "
|
||||||
|
" sessions "
|
||||||
|
" List saved sessions "
|
||||||
|
" Sessions · Modes: Command · #session #history #browse "
|
||||||
|
" load "
|
||||||
|
" Load a saved conversation "
|
||||||
|
" Sessions · Modes: Command · #session #restore #history "
|
||||||
|
" ▌ C Enter: run · Tab: autocomplete · /tag filter · Esc: cancel "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" System/Status "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" COMMAND CHAT Focus INPUT ·ⓘ :session save owlen-tui "
|
||||||
|
" Ctrl+5 Icons: Nerd (auto) 1:1 · Plain Text "
|
||||||
|
" F1 Help ? Guidance F12 DebugUsage metrics pending · run :limits · UTF-8 "
|
||||||
|
" "
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
---
|
||||||
|
source: crates/owlen-tui/tests/chat_snapshots.rs
|
||||||
|
expression: snapshot
|
||||||
|
---
|
||||||
|
" "
|
||||||
|
" 🦉 OWLEN v0.2.0 · Mode Chat · Focus Input ollama_local · stub-model "
|
||||||
|
" "
|
||||||
|
" Context metrics not available Cloud usage pending "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" ▌ Chat · stub-model PgUp/PgDn scroll · g/G jump · s save · Ctrl+2 focus "
|
||||||
|
" "
|
||||||
|
" No messages yet. Press 'i' to start typing. "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" ▌ Input Enter send · Shift+Enter newline · Esc normal · Ctrl+5 focus "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" System/Status "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" INSERT CHAT Focus INPUT · ⓘ Normal mode • Press F1 for help owlen-tui "
|
||||||
|
" Ctrl+5 Icons: Nerd (auto) 1:20 · Plain "
|
||||||
|
" F1 Help ? Guidance F12 DebugUsage metrics pending · run :limits Text · UTF-8 "
|
||||||
|
" "
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
---
|
||||||
|
source: crates/owlen-tui/tests/chat_snapshots.rs
|
||||||
|
expression: snapshot
|
||||||
|
---
|
||||||
|
" "
|
||||||
|
" 🦉 OWLEN v0.2.0 · Mode Chat · Focus Input ollama_local · stub-model "
|
||||||
|
" "
|
||||||
|
" Context metrics not available Cloud usage pending "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" ▌ Chat · stub-model PgUp/PgDn scroll · g/G jump · s save · Ctrl+2 focus "
|
||||||
|
" "
|
||||||
|
" No messages yet. Press 'i' to start typing. "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" Input Press i to start typing · Ctrl+5 focus "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" System/Status "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" NORMAL CHAT Focus INPUT · ⓘ Normal mode • Press F1 for help owlen-tui "
|
||||||
|
" Ctrl+5 Icons: Nerd (auto) 1:1 · Plain Text "
|
||||||
|
" F1 Help ? Guidance F12 DebugUsage metrics pending · run :limits · UTF-8 "
|
||||||
|
" "
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
---
|
||||||
|
source: crates/owlen-tui/tests/chat_snapshots.rs
|
||||||
|
expression: snapshot
|
||||||
|
---
|
||||||
|
" "
|
||||||
|
" 🦉 OWLEN v0.2.0 · Mode Chat · Focus Input ollama_local · stub-model "
|
||||||
|
" "
|
||||||
|
" Context metrics not available Cloud usage pending "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" ▌ Chat · stub-model PgUp/PgDn scroll · g/G jump · s save · Ctrl+2 focus "
|
||||||
|
" "
|
||||||
|
" ┌ 👤 You ────────────────────────────────────────────────────────────────────────┐ "
|
||||||
|
" │ Render visual selection across multiple lines. │ "
|
||||||
|
" └────────────────────────────────────────────────────────────────────────────────┘ "
|
||||||
|
" ┌ 🤖 Assistant ──────────────────────────────────────────────────────────────────┐ "
|
||||||
|
" │ Assistant reply for visual mode highlighting. │ "
|
||||||
|
" └────────────────────────────────────────────────────────────────────────────────┘ "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" ▌ Visual Select y yank · d cut · Esc cancel · Ctrl+5 focus "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" System/Status "
|
||||||
|
" "
|
||||||
|
" "
|
||||||
|
" VISUAL CHAT Focus INPUT · ⓘ -- VISUAL -- (move with j/k, yankowlen-tui "
|
||||||
|
" Ctrl+5 Icons: Nerd (auto) 1:1 · Plain Text "
|
||||||
|
" F1 Help ? Guidance F12 DebugUsage metrics pending · run :limits · UTF-8 "
|
||||||
|
" "
|
||||||
Reference in New Issue
Block a user