Codex System Handbook

TUI interaction and rendering tests

stage-23.552 files

This stage is the safety net for the terminal user interface, or TUI: the text screen users see in a terminal. It is shared behind-the-scenes support, not product startup or shutdown code. The test support files provide fake paths, fake models, ready-made App objects, and a fake terminal screen so tests can draw UI into memory instead of a real window. The main app tests check startup, session resume, thread handling, summaries, update prompts, configuration changes, authentication, and status feeds. The chat widget tests act like a workshop for the main chat screen: they send fake server events, press keys, open popups, submit messages, approve commands, replay history, test slash commands, permissions, goals, planning, reviews, side chats, usage, and layout. Rendering-focused tests protect Markdown, history cells, token charts, status panels, colors, titles, and flexible layouts. The integration tests tie everything together, including simulated VT100 terminals, resize behavior, scrollback history, ANSI cleanup, and dependency tripwires.

Files in this stage52

Shared TUI test infrastructure

These files define the common test harnesses, backend shims, and aggregate integration-test entry points that the rest of the TUI test suites build on.

tui/src/test_support.rssource ↗
testtest setup and test execution

Tests often need the same kind of setup again and again: a path that is safe to compare on any machine, a known list of model presets, or a value shaped like it came from another part of the system. This file gathers those test-only conveniences in one place so individual tests can stay focused on what they are checking.

One important shared item is TEST_MODEL_PRESETS. It loads the bundled models file, sorts the models by priority, converts them into the preset type used by the TUI, and marks the default models the same way the picker would. The LazyLock means this work happens only the first time a test asks for it, like opening a shared toolbox only when someone needs a tool.

The path helpers re-export test path utilities from another crate, and test_path_display turns one of those test paths into the exact display string a test can compare against. The session and skill-scope helpers create legacy test values by first serializing newer app-server protocol values into JSON and then deserializing them into the requested type. That checks that the wire format, meaning the data shape passed between components, still matches what older helper types expect. If this file were missing, many tests would either duplicate fragile setup code or disagree about the exact test data they use.

Function details5
test_path_display21–23 ↗
fn test_path_display(path: &str) -> String

Purpose: This function turns a test path string into the display form used in assertions. It helps tests compare paths without depending on a developer's real machine layout.

Data flow: It takes a path written as a string, passes it to the shared test path builder, then asks that path how it should be shown as text. The result is a String ready for a test expectation.

Call relations: Tests use this when they need a stable path display value. It delegates the actual path construction to test_path_buf from the shared path test-support code, then only adds the final conversion to display text.

Call graph: 1 external calls (test_path_buf).

session_source_cli25–30 ↗
fn session_source_cli() -> T

Purpose: This function creates a test value meaning “the session came from the command line.” It is useful when tests need that value in whatever compatible legacy type they are checking.

Data flow: It starts with the app-server protocol value for a CLI session source. It sends that value through from_app_server_wire, which converts it through JSON into the caller's requested type. The caller receives that converted test value, or the test panics if the conversion no longer works.

Call relations: Telemetry-related tests call this when building session data. Rather than doing the conversion itself, it hands the protocol value to from_app_server_wire so the same compatibility check is used consistently.

Call graph: calls 1 internal fn (from_app_server_wire); called by 2 (test_session_telemetry, test_session_telemetry).

skill_scope_user32–37 ↗
fn skill_scope_user() -> T

Purpose: This function creates a test value meaning “this skill belongs to the user scope.” It lets tests ask for that value in the legacy type they already use.

Data flow: It takes the app-server protocol's User skill-scope value, converts it through the shared JSON-based bridge, and returns the requested output type. If the protocol value cannot be represented as that type, the test fails immediately.

Call relations: This is a small named shortcut around from_app_server_wire. It exists so tests can clearly say they want the user skill scope without repeating protocol conversion details.

Call graph: calls 1 internal fn (from_app_server_wire).

skill_scope_repo39–44 ↗
fn skill_scope_repo() -> T

Purpose: This function creates a test value meaning “this skill belongs to the repository scope.” It keeps tests readable while still using the app-server protocol as the source of truth.

Data flow: It starts with the app-server protocol's Repo skill-scope value. It passes that value into from_app_server_wire, which serializes and deserializes it into the caller's requested type, then returns the converted value.

Call relations: Like skill_scope_user, this is a convenience wrapper over from_app_server_wire. It gives tests a clear way to request the repository skill scope while relying on the shared conversion path.

Call graph: calls 1 internal fn (from_app_server_wire).

from_app_server_wire46–55 ↗
fn from_app_server_wire(value: impl Serialize) -> T

Purpose: This helper converts an app-server protocol value into another compatible type by using JSON as the shared middle format. It is mainly a test guard: if the new protocol shape stops matching the legacy helper type, the test fails loudly.

Data flow: It receives any value that can be serialized, turns it into a JSON value, then tries to read that JSON back as the requested output type. On success it returns the converted value; on failure it panics with a message explaining that the wire value no longer maps correctly.

Call relations: The session and skill-scope helper functions all call this instead of duplicating conversion code. It sits at the center of those helpers, acting like an adapter between app-server protocol values and the older types that some TUI tests still expect.

Call graph: called by 3 (session_source_cli, skill_scope_repo, skill_scope_user); 1 external calls (to_value).

tui/src/test_backend.rssource ↗
testtest rendering and snapshot checks

The app uses Ratatui and Crossterm to draw a terminal user interface. In normal use, those libraries talk to the real terminal. That is awkward in tests, because tests need a stable, inspectable screen and must not move the developer’s cursor or ask the operating system for the real terminal size. This file solves that by building VT100Backend, a test backend that looks like a real terminal to Ratatui but is actually powered by a vt100::Parser, which records terminal escape codes into an in-memory screen. Think of it like a stage set: the actors behave as if they are on a real stage, but the test can pause and inspect exactly what the audience would see. Most methods simply pass drawing commands through to Ratatui’s normal CrosstermBackend. The important difference is that size and cursor position are read from the in-memory vt100 screen, not from the real terminal. The file also implements Display, so tests can turn the fake screen into plain text for snapshot comparisons. Without this wrapper, UI tests could accidentally depend on the machine running them, or write control codes to real stdout.

Function details17
VT100Backend::new27–32 ↗
fn new(width: u16, height: u16) -> Self

Purpose: Creates a new in-memory terminal with a chosen width and height. Tests use it when they need a predictable fake screen to render into.

Data flow: The caller gives a width and height. The function turns on forced color output, creates a vt100 parser sized like that terminal, wraps it in a Crossterm backend, and returns a VT100Backend ready for drawing.

Call relations: Snapshot and rendering tests call this at the start of a UI check. After creation, the returned backend is handed to Ratatui code, which draws into the vt100 parser instead of the real terminal.

Call graph: called by 61 (thread_goal_ephemeral_error_message_renders_snapshot, render_footer_with_mode_indicator_and_context, chained_config_error_wraps_in_history_snapshot, approval_modal_exec_multiline_prefix_hides_execpolicy_option_snapshot, approval_modal_exec_snapshot, approval_modal_exec_without_reason_snapshot, approval_modal_patch_snapshot, app_server_guardian_review_denied_renders_denied_request_snapshot, app_server_guardian_review_timed_out_renders_timed_out_request_snapshot, guardian_approved_exec_renders_approved_request (+15 more)); 3 external calls (new, force_color_output, new).

VT100Backend::vt10034–36 ↗
fn vt100(&self) -> &vt100::Parser

Purpose: Gives read-only access to the underlying in-memory terminal parser. This is used when code needs to inspect what the fake terminal currently thinks is on screen.

Data flow: It reads the wrapped Crossterm backend and returns a reference to its writer, which is the vt100 parser. Nothing is changed.

Call relations: Other methods in this file call it when they need safe terminal facts, such as cursor position or screen size, without asking the real operating system terminal.

Call graph: called by 3 (get_cursor_position, size, window_size); 1 external calls (writer).

VT100Backend::write40–42 ↗
fn write(&mut self, buf: &[u8]) -> io::Result<usize>

Purpose: Lets raw bytes be written into the fake terminal. This is what makes the backend usable anywhere a normal writable output stream is expected.

Data flow: It receives a byte buffer, forwards those bytes into the vt100 parser through the wrapped backend, and returns how many bytes were accepted or an input/output error.

Call relations: This is part of Rust’s Write trait, meaning outside code can treat VT100Backend like an output destination. The bytes ultimately feed the in-memory terminal state.

Call graph: 1 external calls (writer_mut).

VT100Backend::fmt50–52 ↗
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result

Purpose: Turns the fake terminal’s visible screen into text. Tests can use this to compare the rendered UI with an expected snapshot.

Data flow: It reads the vt100 screen contents and writes that plain text into the formatter supplied by Rust’s display system. It does not change the terminal.

Call relations: This supports formatting such as format!("{}", backend). It is the bridge from the simulated terminal screen to human-readable test output.

Call graph: 1 external calls (write!).

VT100Backend::draw56–62 ↗
fn draw(&mut self, content: I) -> io::Result<()>

Purpose: Draws Ratatui cells into the fake terminal. A cell is one screen position with its character and style information.

Data flow: It receives an iterator of screen coordinates and cells, passes them to the wrapped Crossterm backend, and returns success or an input/output error. The in-memory terminal changes to reflect the drawn content.

Call relations: Ratatui calls this through the Backend trait during rendering. This method keeps the normal drawing path while ensuring the output lands in the vt100 parser.

Call graph: 1 external calls (draw).

VT100Backend::hide_cursor64–67 ↗
fn hide_cursor(&mut self) -> io::Result<()>

Purpose: Records a request to hide the cursor in the fake terminal. This lets tests exercise the same cursor behavior as the real UI.

Data flow: It takes no extra input, forwards the hide-cursor command to the wrapped backend, and returns whether that worked. The fake terminal receives the corresponding terminal command.

Call relations: Ratatui or UI code calls this through the backend interface when the interface should not show a cursor. The work is delegated to Crossterm’s backend using the in-memory writer.

Call graph: 1 external calls (hide_cursor).

VT100Backend::show_cursor69–72 ↗
fn show_cursor(&mut self) -> io::Result<()>

Purpose: Records a request to show the cursor in the fake terminal. This mirrors what would happen on a real terminal at the end of a draw or interaction.

Data flow: It takes no extra input, forwards the show-cursor command, and returns success or an input/output error. The fake terminal state receives that command.

Call relations: Ratatui or UI code calls this through the backend interface when the cursor should become visible again. The command is passed on to Crossterm, but still writes only into memory.

Call graph: 1 external calls (show_cursor).

VT100Backend::get_cursor_position74–76 ↗
fn get_cursor_position(&mut self) -> io::Result<Position>

Purpose: Reports the cursor position from the fake terminal instead of querying the real terminal. This is important because real cursor queries can write to stdout and make tests unreliable.

Data flow: It reads the cursor position from the vt100 screen, converts it into Ratatui’s Position type, and returns it. It does not change anything.

Call relations: When Ratatui asks the backend where the cursor is, this method answers from VT100Backend::vt100. That keeps tests self-contained and avoids Crossterm calls that would talk to the actual terminal.

Call graph: calls 1 internal fn (vt100).

VT100Backend::set_cursor_position78–80 ↗
fn set_cursor_position(&mut self, position: P) -> io::Result<()>

Purpose: Moves the cursor inside the fake terminal. Rendering code uses this the same way it would move the cursor on a real screen.

Data flow: It receives a target position, forwards that position to the wrapped Crossterm backend, and returns success or an input/output error. The in-memory terminal receives cursor movement instructions.

Call relations: Ratatui calls this through the backend trait while drawing. This method delegates the command to Crossterm’s backend, which writes the terminal control sequence into the vt100 parser.

Call graph: 1 external calls (set_cursor_position).

VT100Backend::clear82–84 ↗
fn clear(&mut self) -> io::Result<()>

Purpose: Clears the fake terminal screen. Tests need this because UI rendering often starts by wiping old content.

Data flow: It receives no extra input, forwards a clear command to the wrapped backend, and returns whether it succeeded. The vt100 screen is updated as if a real terminal had been cleared.

Call relations: Ratatui or UI setup code calls this through the backend interface. The method preserves the normal clear behavior while keeping all output inside the test backend.

Call graph: 1 external calls (clear).

VT100Backend::clear_region86–88 ↗
fn clear_region(&mut self, clear_type: ClearType) -> io::Result<()>

Purpose: Clears a specific part of the fake terminal, such as from the cursor to the end of a line or screen. This supports more precise terminal updates during rendering.

Data flow: It receives a ClearType, which describes what area should be cleared, forwards that request to Crossterm’s backend, and returns success or an input/output error. The matching region in the in-memory terminal is affected.

Call relations: Ratatui calls this when it wants a partial clear rather than a full-screen clear. This method hands the command to the wrapped backend so the vt100 parser sees the same escape codes a real terminal would.

Call graph: 1 external calls (clear_region).

VT100Backend::append_lines90–92 ↗
fn append_lines(&mut self, line_count: u16) -> io::Result<()>

Purpose: Adds blank lines below the current terminal content in the fake screen. This supports terminal behavior where output causes the screen to grow or scroll.

Data flow: It receives a number of lines, forwards that number to the wrapped backend, and returns success or an error. The in-memory terminal is updated according to the generated terminal commands.

Call relations: Ratatui can call this through the backend trait when it needs to append lines. The method delegates to Crossterm’s implementation while keeping the result testable in memory.

Call graph: 1 external calls (append_lines).

VT100Backend::size94–97 ↗
fn size(&self) -> io::Result<Size>

Purpose: Reports the fake terminal’s size. It deliberately avoids asking the real terminal, so tests get the width and height they requested when creating the backend.

Data flow: It reads rows and columns from the vt100 screen, converts them into Ratatui’s Size type using width as columns and height as rows, and returns that size.

Call relations: Ratatui asks for this through the backend interface when laying out the UI. This method gets the answer from VT100Backend::vt100, keeping layout decisions stable across different machines.

Call graph: calls 1 internal fn (vt100); 1 external calls (new).

VT100Backend::window_size99–108 ↗
fn window_size(&mut self) -> io::Result<WindowSize>

Purpose: Reports the fake terminal’s character size plus a placeholder pixel size. The character size matters for tests; the pixel size is arbitrary because these tests do not depend on it.

Data flow: It reads the fake screen’s rows and columns, places them into a WindowSize, fills in a fixed 640 by 480 pixel value, and returns the result.

Call relations: Code that asks for full window dimensions calls this through the backend trait. It uses VT100Backend::vt100 for the meaningful terminal size and avoids a real Crossterm window-size query.

Call graph: calls 1 internal fn (vt100).

VT100Backend::flush110–112 ↗
fn flush(&mut self) -> io::Result<()>

Purpose: Flushes pending output into the in-memory terminal writer. Flushing means asking the output stream to finish sending anything it has buffered.

Data flow: It takes no extra input, calls flush on the vt100 writer inside the wrapped backend, and returns success or an input/output error. It does not produce a new value beyond that status.

Call relations: Ratatui or other output code calls this through the backend interface after writing commands. This makes the fake backend behave like a normal terminal output stream.

Call graph: 1 external calls (writer_mut).

VT100Backend::scroll_region_up114–116 ↗
fn scroll_region_up(&mut self, region: std::ops::Range<u16>, scroll_by: u16) -> io::Result<()>

Purpose: Scrolls a selected vertical region of the fake terminal upward. This supports terminal UIs that move part of the screen without redrawing everything.

Data flow: It receives a range of rows and a number of rows to scroll by, forwards both to the wrapped backend, and returns success or an error. The vt100 screen changes as if that region had scrolled up.

Call relations: Ratatui calls this through the backend trait when it uses terminal scrolling commands. The method passes the request to Crossterm so the vt100 parser can interpret the same command sequence used in real output.

Call graph: 1 external calls (scroll_region_up).

VT100Backend::scroll_region_down118–124 ↗
fn scroll_region_down(
        &mut self,
        region: std::ops::Range<u16>,
        scroll_by: u16,
    ) -> io::Result<()>

Purpose: Scrolls a selected vertical region of the fake terminal downward. This is the downward counterpart to scrolling a region up.

Data flow: It receives a row range and a scroll amount, forwards them to the wrapped backend, and returns success or an input/output error. The fake terminal screen is updated to reflect the downward scroll.

Call relations: Ratatui calls this through the backend trait when drawing code needs downward scrolling. This method delegates the actual terminal command generation to Crossterm while keeping the effect inside the vt100 test screen.

Call graph: 1 external calls (scroll_region_down).

tui/src/chatwidget/tests.rssource ↗
testtest run

The chat widget is the main conversation area of the terminal app, so small visual or event-handling changes can easily break the user experience. This file supports tests that catch those breaks. Think of it as the test workshop for the chat screen: it lays out all the tools on the bench, points snapshot tests to the right folder, and includes many smaller test files for specific behaviors such as approvals, slash commands, permissions, status displays, goal editing, and server events.

A large part of the file is shared imports. These bring in app events, server notification shapes, configuration objects, terminal test backends, and helper types so the nearby test modules can build realistic chat scenarios without repeating setup code. The file also defines a snapshot helper macro. A snapshot test compares rendered output against a saved “golden” text image, so layout or wording changes show up as reviewable diffs instead of being missed.

Two small helper functions matter here. One finds the folder where chat widget snapshots live. The other pulls events from a test event channel until it sees the expected goal-draft update. Without this file, the many chat widget tests would lose their shared setup, snapshot location, and common event-checking helpers, making the test suite more scattered and easier to get wrong.

Function details2
chatwidget_snapshot_dir183–192 ↗
fn chatwidget_snapshot_dir() -> PathBuf

Purpose: Finds the directory that contains the saved snapshot files for chat widget tests. Test code uses this so snapshot comparisons always look in the same known place, even when tests are run from different working directories.

Data flow: It starts with the known path of one snapshot resource inside the project. It asks the build/resource helper to locate that file, takes the file’s parent folder, and returns that folder as a path. If the snapshot file or its parent folder cannot be found, the test fails immediately because snapshot comparisons would not be trustworthy.

Call relations: The snapshot assertion helper in this file relies on this function when setting up the snapshot test settings. It hands the resolved folder path to the snapshot library so rendered chat widget output is compared against the correct saved files.

Call graph: 1 external calls (find_resource!).

next_goal_draft217–231 ↗
fn next_goal_draft(
    rx: &mut tokio::sync::mpsc::UnboundedReceiver<AppEvent>,
    expected_thread_id: ThreadId,
) -> crate::goal_files::GoalDraft

Purpose: Waits through pending test events until it finds the next event that updates a thread’s goal draft. It also checks that the update belongs to the thread the test expected.

Data flow: It receives a test event receiver and the thread identifier that should own the goal draft. It repeatedly pulls the next available event from the receiver. When it finds a goal-draft update event, it compares the event’s thread identifier with the expected one and then returns the draft from that event. Any missing event or wrong thread causes the test to fail.

Call relations: Goal-related chat widget tests use this as a focused checker after user actions or widget logic send events. It reads from the app event channel, filters for the goal-draft update, verifies the thread match with an equality assertion, and gives the draft back to the test so the test can inspect the result.

Call graph: 2 external calls (try_recv, assert_eq!).

tui/src/chatwidget/tests/helpers.rssource ↗
testtest execution

The ChatWidget is the terminal chat interface, and testing it requires a lot of setup: a clean configuration, fake model information, event channels, server notifications, command results, plugin listings, hook runs, and rendered screen snapshots. This file keeps that setup out of individual tests so each test can focus on the behavior it cares about. Think of it like a stage crew for a play: it builds the set, hands actors their props, triggers the cues, and records what the audience would see. The helpers create isolated temporary config so tests do not depend on the developer’s real machine. They also normalize file paths so snapshots look the same on Unix and Windows. Many helpers simulate messages from the app server, such as “the assistant streamed text,” “a command started,” “a patch finished,” or “a hook completed.” Others inspect what the widget sent out, such as submit and interrupt operations. The plugin helpers build realistic marketplace responses, while rendering helpers turn terminal buffers into plain strings for snapshot assertions. Without this file, ChatWidget tests would be longer, more fragile, and more likely to accidentally depend on real user settings or platform-specific paths.

Function details90
test_config5–23 ↗
async fn test_config() -> Config

Purpose: Builds a clean Config for tests. It avoids using the real machine’s Codex settings by creating a temporary home folder and resetting test-sensitive fields.

Data flow: It starts with a new temporary directory, loads default configuration using that directory, then rewrites paths such as Codex home, SQLite home, log directory, and current working directory to known test values. It returns a Config that is safe and predictable for tests.

Call relations: The main ChatWidget builder, make_chatwidget_manual_with_auth, calls this first so every fake widget starts from the same isolated environment.

Call graph: called by 1 (make_chatwidget_manual_with_auth); 5 external calls (from, new, load_default_with_cli_overrides_for_codex_home, default, new).

test_project_path25–27 ↗
fn test_project_path() -> PathBuf

Purpose: Returns the standard fake project path used by tests. This gives tests one shared idea of where the project lives.

Data flow: It takes no input, converts the test path string for the current platform, and returns it as a PathBuf.

Call relations: Tests can call this directly when they need to compare or build paths that match the helper-created ChatWidget configuration.

Call graph: 1 external calls (from).

truncated_path_variants29–34 ↗
fn truncated_path_variants(path: &str) -> Vec<String>

Purpose: Creates all shortened prefixes of a path string. This is useful when snapshot text contains a path that was shortened with an ellipsis.

Data flow: It receives a path, splits it into characters, then returns every prefix except the full path. The output is a list from shortest to longest prefix.

Call relations: normalize_snapshot_paths uses it when converting platform-specific shortened paths back to the Unix-style paths expected in snapshots.

Call graph: called by 1 (normalize_snapshot_paths).

normalize_snapshot_paths36–63 ↗
fn normalize_snapshot_paths(text: impl Into<String>) -> String

Purpose: Makes snapshot text stable across operating systems by replacing platform-specific test paths with Unix-style paths. This prevents Windows path separators or drive formatting from breaking snapshots.

Data flow: It receives text, replaces known platform paths such as the fake project and hooks file with canonical Unix-looking versions, and also fixes shortened path-with-ellipsis forms. It returns the normalized text.

Call relations: Snapshot-oriented helpers and tests use this when rendered output may include file paths. It relies on truncated_path_variants for shortened path cases.

Call graph: calls 1 internal fn (truncated_path_variants); 3 external calls (into, replace, format!).

normalized_backend_snapshot65–89 ↗
fn normalized_backend_snapshot(value: &T) -> String

Purpose: Normalizes backend-rendered snapshot text while preserving quoted-line padding. This keeps visual alignment intact after path replacement.

Data flow: It formats the input value as text. If the platform path already matches the expected Unix path, it returns that text. Otherwise, it normalizes each line and keeps quoted content padded to its original width.

Call relations: Tests use this when comparing backend display output that may contain paths and fixed-width quoted text.

Call graph: 1 external calls (format!).

invalid_value91–101 ↗
fn invalid_value(
    candidate: impl Into<String>,
    allowed: impl Into<String>,
) -> ConstraintError

Purpose: Builds a standard constraint error for tests that need an invalid setting value. It saves each test from spelling out the same error fields.

Data flow: It receives the rejected value and a description of allowed values, puts them into a ConstraintError::InvalidValue with placeholder metadata, and returns the error.

Call relations: Tests can use this as ready-made expected data when checking validation behavior.

Call graph: 1 external calls (into).

snapshot103–118 ↗
fn snapshot(percent: f64) -> RateLimitSnapshot

Purpose: Creates a simple rate-limit snapshot with one primary usage percentage. Tests use it to exercise UI around usage limits without building the full structure each time.

Data flow: It receives a percent value, rounds it to an integer, places it into a one-hour rate-limit window, and returns a RateLimitSnapshot with other fields empty.

Call relations: Tests can pass its result into ChatWidget code that displays or reacts to rate-limit state.

test_session_telemetry120–135 ↗
fn test_session_telemetry(config: &Config, model: &str) -> SessionTelemetry

Purpose: Creates fake session telemetry for a test chat session. Telemetry here means metadata about the session, such as model and source, not real reporting.

Data flow: It reads the test Config and model name, constructs offline model information, then creates a SessionTelemetry object with test-only identifiers and no account details.

Call relations: make_chatwidget_manual_with_auth calls this while assembling the ChatWidget initialization data.

Call graph: calls 3 internal fn (new, new, session_source_cli); called by 1 (make_chatwidget_manual_with_auth); 1 external calls (to_models_manager_config).

test_model_catalog137–141 ↗
fn test_model_catalog(_config: &Config) -> Arc<ModelCatalog>

Purpose: Builds a shared catalog of test model presets. This gives the widget realistic model choices without contacting a service.

Data flow: It ignores the config, clones predefined test model presets, wraps them in a ModelCatalog, and returns it in an Arc, which is a shared reference-counted pointer.

Call relations: Widget builders and authentication helpers use this to populate or reset the ChatWidget’s model list.

Call graph: calls 1 internal fn (new); called by 2 (make_chatwidget_manual_with_auth, set_chatgpt_auth); 1 external calls (new).

make_chatwidget_manual144–157 ↗
async fn make_chatwidget_manual(
    model_override: Option<&str>,
) -> (
    ChatWidget,
    tokio::sync::mpsc::UnboundedReceiver<AppEvent>,
    tokio::sync::mpsc::UnboundedReceiver<Op>,
)

Purpose: Creates a basic ChatWidget test instance without authenticated-account flags. It is the simplest entry point for tests that need to drive the widget directly.

Data flow: It receives an optional model override and forwards it with both authentication flags set to false. It returns the widget plus receivers for app events and operations.

Call relations: Many tests and helper builders call this when they do not need special authentication behavior. It delegates all real setup to make_chatwidget_manual_with_auth.

Call graph: calls 1 internal fn (make_chatwidget_manual_with_auth); called by 3 (assert_hook_events_snapshot, assert_shift_left_edits_most_recent_queued_message_for_terminal, make_chatwidget_manual_with_sender).

make_chatwidget_manual_with_auth159–212 ↗
async fn make_chatwidget_manual_with_auth(
    model_override: Option<&str>,
    has_chatgpt_account: bool,
    has_codex_backend_auth: bool,
) -> (
    ChatWidget,
    tokio::sync::mpsc::UnboundedRec

Purpose: Builds a fully usable ChatWidget for tests, with optional model and authentication settings. It also exposes the channels where the widget sends events and operations.

Data flow: It creates event and operation channels, loads a clean test config, resolves the model, builds telemetry and model catalog data, constructs ChatWidgetInit, creates the widget, resets some visual state, sets placeholder text, and returns the widget with channel receivers.

Call relations: make_chatwidget_manual calls this for normal setup. Other helpers depend on the widget it produces to simulate server events and inspect outgoing operations.

Call graph: calls 6 internal fn (new, new, test_config, test_model_catalog, test_session_telemetry, test_dummy); called by 1 (make_chatwidget_manual); 4 external calls (new, new, new_with_op_target, Direct).

next_submit_op216–225 ↗
fn next_submit_op(op_rx: &mut tokio::sync::mpsc::UnboundedReceiver<Op>) -> Op

Purpose: Pulls the next user-submission operation from the operation channel. It skips unrelated operations so tests can focus on whether a submit happened.

Data flow: It repeatedly tries to receive from the channel. If it sees a UserTurn operation, it returns it; if it sees another operation, it ignores it; if the queue is empty or closed, it panics because the test expected a submission.

Call relations: Tests use this after triggering input in the widget to verify the widget sent a user turn.

Call graph: 2 external calls (try_recv, panic!).

next_interrupt_op227–236 ↗
fn next_interrupt_op(op_rx: &mut tokio::sync::mpsc::UnboundedReceiver<Op>)

Purpose: Checks that the widget emitted an interrupt operation. This is used when a test expects the user action to stop a running task.

Data flow: It reads operations until it finds Interrupt, ignores unrelated operations, and panics if the channel is empty or closed first. It returns nothing because finding the operation is the assertion.

Call relations: Tests call it after simulating an interrupt action such as a cancel key.

Call graph: 2 external calls (try_recv, panic!).

assert_no_submit_op238–245 ↗
fn assert_no_submit_op(op_rx: &mut tokio::sync::mpsc::UnboundedReceiver<Op>)

Purpose: Verifies that no user-submission operation is waiting in the operation channel. This protects tests from accidental sends.

Data flow: It drains currently available operations. If any operation is UserTurn, it fails the test; otherwise it leaves with no result.

Call relations: Tests use it after actions that should edit UI state or queue text but should not submit a message.

Call graph: 2 external calls (try_recv, assert!).

set_chatgpt_auth247–251 ↗
fn set_chatgpt_auth(chat: &mut ChatWidget)

Purpose: Marks a test ChatWidget as having both ChatGPT and Codex backend authentication. This lets tests exercise account-gated behavior.

Data flow: It mutates the widget by setting both auth flags to true and replacing the model catalog with the standard test catalog.

Call relations: Tests call this after creating a widget when they need the authenticated version of model or account behavior.

Call graph: calls 1 internal fn (test_model_catalog).

test_model_info253–290 ↗
fn test_model_info(slug: &str, priority: i32, supports_fast_mode: bool) -> ModelInfo

Purpose: Creates detailed fake information for one model. It can optionally mark the model as supporting fast mode.

Data flow: It receives a model slug, priority, and fast-mode flag, builds JSON-like model metadata, then deserializes it into a ModelInfo. The returned model info is realistic enough for catalog tests.

Call relations: set_fast_mode_test_catalog uses it to build a catalog with both fast-mode and non-fast-mode models.

Call graph: 3 external calls (new, json!, from_value).

set_fast_mode_test_catalog292–311 ↗
fn set_fast_mode_test_catalog(chat: &mut ChatWidget)

Purpose: Replaces a ChatWidget’s model catalog with two test models, one that supports fast mode and one that does not. This helps tests check fast-mode UI decisions.

Data flow: It builds two ModelInfo records, converts them into model presets, wraps them in a ModelCatalog, and stores that catalog on the widget.

Call relations: Tests call this when they need controlled fast-mode availability rather than the default test model list.

Call graph: calls 1 internal fn (new); 2 external calls (new, vec!).

make_chatwidget_manual_with_sender313–322 ↗
async fn make_chatwidget_manual_with_sender() -> (
    ChatWidget,
    AppEventSender,
    tokio::sync::mpsc::UnboundedReceiver<AppEvent>,
    tokio::sync::mpsc::UnboundedReceiver<Op>,
)

Purpose: Creates a test ChatWidget and also returns its AppEventSender. This lets tests both drive and observe app events.

Data flow: It builds a normal manual widget, clones the widget’s event sender, and returns the widget, sender, app-event receiver, and operation receiver.

Call relations: It builds on make_chatwidget_manual and is useful for tests that need to inject events through the same sender the widget uses.

Call graph: calls 1 internal fn (make_chatwidget_manual).

drain_insert_history324–338 ↗
fn drain_insert_history(
    rx: &mut tokio::sync::mpsc::UnboundedReceiver<AppEvent>,
) -> Vec<Vec<ratatui::text::Line<'static>>>

Purpose: Collects all pending history-cell insert events from the app event channel. It converts them into display lines for easy snapshot checking.

Data flow: It drains currently available app events, keeps only InsertHistoryCell events, renders each cell at width 80, inserts a blank separator where needed, and returns a list of rendered line groups.

Call relations: assert_hook_events_snapshot uses it to check that hook output moved from the live area into history at the right time.

Call graph: called by 1 (assert_hook_events_snapshot); 2 external calls (try_recv, new).

lines_to_single_string340–349 ↗
fn lines_to_single_string(lines: &[ratatui::text::Line<'static>]) -> String

Purpose: Turns rendered terminal lines into one plain string. This makes snapshot assertions easy to read.

Data flow: It receives a slice of ratatui Lines, concatenates the text from each span in each line, adds newline characters, and returns the combined string.

Call relations: active_blob and active_hook_blob use it after asking cells to render themselves.

Call graph: called by 2 (active_blob, active_hook_blob); 1 external calls (new).

status_line_text351–353 ↗
fn status_line_text(chat: &ChatWidget) -> Option<String>

Purpose: Reads the current status-line text from a ChatWidget. It is a small wrapper used by tests.

Data flow: It receives a widget reference, calls the widget’s status-line accessor, and returns the optional text.

Call relations: Tests use this helper instead of reaching deeper into widget internals.

Call graph: calls 1 internal fn (status_line_text).

make_token_info355–368 ↗
fn make_token_info(total_tokens: i64, context_window: i64) -> TokenUsageInfo

Purpose: Creates token usage information for tests. Tokens are the small pieces of text counted against a model’s context window.

Data flow: It receives total token count and context-window size, fills both total and last-turn usage with that count, and returns a TokenUsageInfo object.

Call relations: Tests can pass its result to handle_token_count to simulate server updates about context usage.

thread_id370–372 ↗
fn thread_id(chat: &ChatWidget) -> String

Purpose: Gets the widget’s thread id as a string, or an empty string if none exists. A thread id identifies the conversation.

Data flow: It reads chat.thread_id, converts it to text when present, and otherwise returns an empty string.

Call relations: Most server-notification helpers call this so their fake events look like they belong to the current chat thread.

Call graph: called by 21 (handle_agent_message_delta, handle_agent_reasoning_delta, handle_agent_reasoning_final, handle_entered_review_mode, handle_error, handle_exec_begin, handle_exec_end, handle_exited_review_mode, handle_hook_completed, handle_hook_started (+11 more)).

token_usage_breakdown374–382 ↗
fn token_usage_breakdown(usage: TokenUsage) -> codex_app_server_protocol::TokenUsageBreakdown

Purpose: Converts the UI-side token usage structure into the protocol-side token usage structure. This lets tests send usage updates through the same path as the server.

Data flow: It receives TokenUsage, copies each token count field into a codex_app_server_protocol::TokenUsageBreakdown, and returns it.

Call relations: handle_token_count uses it when building a fake ThreadTokenUsageUpdated notification.

Call graph: called by 1 (handle_token_count).

handle_token_count384–408 ↗
fn handle_token_count(chat: &mut ChatWidget, info: Option<TokenUsageInfo>)

Purpose: Simulates the server telling the widget that token usage changed. It can also clear token information.

Data flow: If given usage info, it builds a ThreadTokenUsageUpdated notification with thread and turn ids, converts token details, and sends it into the widget. If given None, it directly clears the widget’s token info.

Call relations: Tests use this to drive the same update path the widget uses during real conversations.

Call graph: calls 3 internal fn (set_token_info, thread_id, token_usage_breakdown); 2 external calls (ThreadTokenUsageUpdated, handle_server_notification).

handle_error410–432 ↗
fn handle_error(
    chat: &mut ChatWidget,
    message: impl Into<String>,
    codex_error_info: Option<CodexErrorInfo>,
)

Purpose: Simulates a non-retrying error from the server. This tests how the widget displays or reacts to failures.

Data flow: It receives a message and optional Codex error details, wraps them in an Error notification with the current thread and turn, and sends it to the widget.

Call relations: Tests call it when they need the widget to process a final error for the current turn.

Call graph: calls 1 internal fn (thread_id); 3 external calls (into, Error, handle_server_notification).

handle_stream_error434–440 ↗
fn handle_stream_error(
    chat: &mut ChatWidget,
    message: impl Into<String>,
    additional_details: Option<String>,
)

Purpose: Simulates a retrying stream error without replay metadata. A stream error is a failure while output is still arriving.

Data flow: It accepts a message and optional details, then forwards them to handle_stream_error_with_replay with no replay kind. It returns nothing after the widget processes the event.

Call relations: It is the convenient form for tests that do not care about replay behavior.

Call graph: calls 1 internal fn (handle_stream_error_with_replay).

handle_stream_error_with_replay442–465 ↗
fn handle_stream_error_with_replay(
    chat: &mut ChatWidget,
    message: impl Into<String>,
    additional_details: Option<String>,
    replay_kind: Option<ReplayKind>,
)

Purpose: Simulates a retrying stream error and optionally marks it as replayed history. This lets tests cover both live and replay paths.

Data flow: It builds an Error notification with will_retry set to true, fills in thread and turn ids, includes optional details, and sends it to the widget with the supplied replay kind.

Call relations: handle_stream_error delegates to it. Tests call it directly when they need to specify replay behavior.

Call graph: calls 1 internal fn (thread_id); called by 1 (handle_stream_error); 3 external calls (into, Error, handle_server_notification).

handle_warning467–475 ↗
fn handle_warning(chat: &mut ChatWidget, message: impl Into<String>)

Purpose: Simulates a warning from the server. Warnings are messages the user should see but that do not necessarily stop the turn.

Data flow: It receives warning text, builds a Warning notification with the current thread id, and sends it into the widget.

Call relations: Tests use it to check warning rendering and history behavior.

Call graph: calls 1 internal fn (thread_id); 3 external calls (into, Warning, handle_server_notification).

handle_model_verification477–493 ↗
fn handle_model_verification(
    chat: &mut ChatWidget,
    verifications: Vec<AppServerModelVerification>,
)

Purpose: Simulates the server reporting model-verification results. This supports tests around model availability or compatibility messages.

Data flow: It receives verification records, attaches them to the current thread and turn, builds a ModelVerification notification, and sends it to the widget.

Call relations: Tests call it when they need the ChatWidget to react as if the backend checked the chosen model.

Call graph: calls 1 internal fn (thread_id); 2 external calls (ModelVerification, handle_server_notification).

handle_agent_message_delta495–511 ↗
fn handle_agent_message_delta(chat: &mut ChatWidget, delta: impl Into<String>)

Purpose: Simulates one streamed chunk of assistant text. A delta is a small piece of a message that arrives before the full answer is complete.

Data flow: It receives text, wraps it with fixed item id msg-1 plus current thread and turn ids, and sends an AgentMessageDelta notification to the widget.

Call relations: Tests use it to build up live assistant output through the normal server-notification path.

Call graph: calls 1 internal fn (thread_id); 3 external calls (into, AgentMessageDelta, handle_server_notification).

handle_agent_reasoning_delta513–528 ↗
fn handle_agent_reasoning_delta(chat: &mut ChatWidget, delta: impl Into<String>)

Purpose: Simulates one streamed chunk of the assistant’s reasoning summary. This is separate from the final answer text.

Data flow: It receives text, builds a ReasoningSummaryTextDelta notification for item reasoning-1, and sends it to the widget.

Call relations: Tests use it to check how live reasoning summary text appears or changes.

Call graph: calls 1 internal fn (thread_id); 3 external calls (into, ReasoningSummaryTextDelta, handle_server_notification).

handle_agent_reasoning_final530–548 ↗
fn handle_agent_reasoning_final(chat: &mut ChatWidget)

Purpose: Simulates completion of a reasoning item. This tells the widget that the reasoning stream is done.

Data flow: It builds an ItemCompleted notification for a Reasoning item with id reasoning-1 and empty final content, then sends it to the widget.

Call relations: Tests call it after reasoning deltas when they need to close out the reasoning cell.

Call graph: calls 1 internal fn (thread_id); 3 external calls (ItemCompleted, new, handle_server_notification).

handle_entered_review_mode550–567 ↗
fn handle_entered_review_mode(chat: &mut ChatWidget, review: impl Into<String>)

Purpose: Simulates the server starting review mode. Review mode is represented as a thread item that begins at a point in the turn.

Data flow: It receives review text, creates an EnteredReviewMode item inside an ItemStarted notification, and sends it to the widget.

Call relations: Tests use it to verify the widget’s live display when review mode begins.

Call graph: calls 1 internal fn (thread_id); 3 external calls (into, ItemStarted, handle_server_notification).

replay_entered_review_mode569–578 ↗
fn replay_entered_review_mode(chat: &mut ChatWidget, review: impl Into<String>)

Purpose: Replays an already-existing review-mode entry into the widget. Replaying means rebuilding UI from saved thread history rather than receiving a live event.

Data flow: It creates an EnteredReviewMode thread item with fixed id and turn id, then asks the widget to replay it as a thread snapshot.

Call relations: Tests use this when they need to compare live handling with restored-history handling.

Call graph: 2 external calls (into, replay_thread_item).

handle_exited_review_mode580–597 ↗
fn handle_exited_review_mode(chat: &mut ChatWidget)

Purpose: Simulates the server completing review mode. It marks the review-mode item as ended.

Data flow: It builds an ItemCompleted notification with an ExitedReviewMode item and sends it to the widget.

Call relations: Tests call it after entering review mode to check transition and final rendering behavior.

Call graph: calls 1 internal fn (thread_id); 3 external calls (ItemCompleted, new, handle_server_notification).

handle_exec_approval_request599–605 ↗
fn handle_exec_approval_request(
    chat: &mut ChatWidget,
    id: impl Into<String>,
    event: ExecApprovalRequestEvent,
)

Purpose: Feeds a command-execution approval request into the widget. This simulates the backend asking whether it may run a command.

Data flow: It receives an id and approval event, converts the id to a string, and calls the widget’s approval-request method. The widget state is updated to show or track the request.

Call relations: Tests use it to drive the same path as a real command permission prompt.

Call graph: 2 external calls (into, on_exec_approval_request).

handle_apply_patch_approval_request607–613 ↗
fn handle_apply_patch_approval_request(
    chat: &mut ChatWidget,
    id: impl Into<String>,
    event: ApplyPatchApprovalRequestEvent,
)

Purpose: Feeds a patch-application approval request into the widget. This simulates asking the user before changing files.

Data flow: It receives an id and patch approval event, converts the id to text, and calls the widget’s patch approval-request method.

Call relations: Tests use it to check UI behavior around approving or denying file changes.

Call graph: 2 external calls (into, on_apply_patch_approval_request).

file_update_changes_from_tui615–634 ↗
fn file_update_changes_from_tui(changes: HashMap<PathBuf, FileChange>) -> Vec<FileUpdateChange>

Purpose: Converts test-side file-change descriptions into protocol file-update changes. This bridges the UI test type and the server item type.

Data flow: It receives a map from file paths to add, delete, or update changes. For each entry, it chooses the matching protocol change kind, converts the path to display text, and returns a list of FileUpdateChange records.

Call relations: handle_patch_apply_begin and handle_patch_apply_end use it before sending patch events to the widget.

Call graph: called by 2 (handle_patch_apply_begin, handle_patch_apply_end).

handle_patch_apply_begin636–655 ↗
fn handle_patch_apply_begin(
    chat: &mut ChatWidget,
    call_id: impl Into<String>,
    turn_id: impl Into<String>,
    changes: HashMap<PathBuf, FileChange>,
)

Purpose: Simulates the start of applying a patch to files. This lets tests check how in-progress file changes are shown.

Data flow: It receives call id, turn id, and file changes, converts the changes to protocol form, wraps them in an in-progress FileChange item, and sends an ItemStarted notification.

Call relations: It uses file_update_changes_from_tui to prepare the payload before passing it through the widget’s normal server-notification handler.

Call graph: calls 2 internal fn (file_update_changes_from_tui, thread_id); 3 external calls (into, ItemStarted, handle_server_notification).

handle_patch_apply_end657–677 ↗
fn handle_patch_apply_end(
    chat: &mut ChatWidget,
    call_id: impl Into<String>,
    turn_id: impl Into<String>,
    changes: HashMap<PathBuf, FileChange>,
    status: AppServerPatchApplyStatus,

Purpose: Simulates the completion of applying a patch. It can represent success, failure, or another final patch status.

Data flow: It receives ids, file changes, and status, converts the changes, builds a completed FileChange item, and sends an ItemCompleted notification to the widget.

Call relations: Tests pair it with handle_patch_apply_begin when checking patch lifecycle display.

Call graph: calls 2 internal fn (file_update_changes_from_tui, thread_id); 3 external calls (into, ItemCompleted, handle_server_notification).

handle_view_image_tool_call679–696 ↗
fn handle_view_image_tool_call(
    chat: &mut ChatWidget,
    call_id: impl Into<String>,
    path: AbsolutePathBuf,
)

Purpose: Simulates completion of a tool call that views an image. This tests image-view entries in the transcript.

Data flow: It receives a call id and absolute image path, wraps them in an ImageView item for turn-1, and sends an ItemCompleted notification.

Call relations: Tests use it when verifying how image-view tool results are rendered.

Call graph: calls 1 internal fn (thread_id); 3 external calls (into, ItemCompleted, handle_server_notification).

handle_image_generation_end698–720 ↗
fn handle_image_generation_end(
    chat: &mut ChatWidget,
    call_id: impl Into<String>,
    status: impl Into<String>,
    revised_prompt: Option<String>,
    saved_path: Option<AbsolutePathBuf>,
)

Purpose: Simulates completion of an image-generation tool call. It includes status, optional revised prompt, and optional saved file path.

Data flow: It receives image-generation details, builds an ImageGeneration item with an empty result string, and sends it as a completed item to the widget.

Call relations: Tests call it to verify image-generation result display and saved-path behavior.

Call graph: calls 1 internal fn (thread_id); 4 external calls (into, ItemCompleted, new, handle_server_notification).

replay_user_message_inputs722–737 ↗
fn replay_user_message_inputs(
    chat: &mut ChatWidget,
    item_id: &str,
    content: Vec<AppServerUserInput>,
    replay_kind: ReplayKind,
)

Purpose: Replays a saved user message with arbitrary input parts. Inputs may include text or other supported user content.

Data flow: It receives an item id, content list, and replay kind, creates a UserMessage thread item, and asks the widget to replay it for turn-1.

Call relations: replay_user_message_text uses it for the common text-only case. Tests use it for restored-history scenarios.

Call graph: called by 1 (replay_user_message_text); 1 external calls (replay_thread_item).

replay_user_message_text739–754 ↗
fn replay_user_message_text(
    chat: &mut ChatWidget,
    item_id: &str,
    text: impl Into<String>,
    replay_kind: ReplayKind,
)

Purpose: Replays a saved text-only user message. This is the simple wrapper for common history tests.

Data flow: It receives an item id, text, and replay kind, wraps the text in a single text input, and forwards everything to replay_user_message_inputs.

Call relations: It reduces boilerplate for tests that do not need mixed input types.

Call graph: calls 1 internal fn (replay_user_message_inputs); 1 external calls (vec!).

replay_agent_message756–772 ↗
fn replay_agent_message(
    chat: &mut ChatWidget,
    item_id: &str,
    text: impl Into<String>,
    replay_kind: ReplayKind,
)

Purpose: Replays a saved assistant message. It marks the message as a final answer.

Data flow: It receives an item id, text, and replay kind, creates an AgentMessage thread item with FinalAnswer phase, and asks the widget to replay it for turn-1.

Call relations: Tests use it to rebuild transcript state from history without simulating live streaming.

Call graph: 2 external calls (into, replay_thread_item).

replay_turn_started774–787 ↗
fn replay_turn_started(chat: &mut ChatWidget, replay_kind: ReplayKind)

Purpose: Replays a turn-started notification. A turn is one request-response cycle in the conversation.

Data flow: It builds an in-progress AppServerTurn for turn-1, wraps it in a TurnStarted notification, and sends it to the widget with replay metadata.

Call relations: It uses app_server_turn to create the standard turn object used by both live and replay helpers.

Call graph: calls 2 internal fn (app_server_turn, thread_id); 2 external calls (TurnStarted, handle_server_notification).

replay_agent_message_delta789–805 ↗
fn replay_agent_message_delta(
    chat: &mut ChatWidget,
    delta: impl Into<String>,
    replay_kind: ReplayKind,
)

Purpose: Replays a streamed assistant message chunk. This is useful for tests that restore an in-progress or previously streamed message.

Data flow: It receives text and replay kind, creates an AgentMessageDelta notification for msg-1 on turn-1, and sends it to the widget with replay metadata.

Call relations: Tests use it when they need replay behavior but still want to exercise the delta-handling path.

Call graph: calls 1 internal fn (thread_id); 3 external calls (into, AgentMessageDelta, handle_server_notification).

begin_exec_with_source808–835 ↗
fn begin_exec_with_source(
    chat: &mut ChatWidget,
    call_id: &str,
    raw_cmd: &str,
    source: ExecCommandSource,
) -> AppServerThreadItem

Purpose: Starts a fake command execution with a chosen source. The source says why the command is running, such as from the agent or startup flow.

Data flow: It receives a widget, call id, raw shell command, and source. It builds a bash command, parses it into command actions, creates an in-progress CommandExecution item, sends a begin event, and returns the item for later completion.

Call relations: begin_exec calls it with the normal agent source. It hands the item to handle_exec_begin so the widget sees the same event shape as a real command start.

Call graph: calls 3 internal fn (parse_command, shlex_join, handle_exec_begin); called by 1 (begin_exec); 1 external calls (vec!).

begin_unified_exec_startup837–858 ↗
fn begin_unified_exec_startup(
    chat: &mut ChatWidget,
    call_id: &str,
    process_id: &str,
    raw_cmd: &str,
) -> AppServerThreadItem

Purpose: Starts a fake command execution for unified-exec startup behavior. It includes a process id and uses a startup-specific source.

Data flow: It receives ids and raw command text, builds the shell command item with in-progress status and no parsed actions, sends it as a begin event, and returns the item.

Call relations: It delegates delivery to handle_exec_begin and is used by tests for this special startup command path.

Call graph: calls 2 internal fn (shlex_join, handle_exec_begin); 2 external calls (new, vec!).

handle_exec_begin860–874 ↗
fn handle_exec_begin(chat: &mut ChatWidget, item: AppServerThreadItem)

Purpose: Sends a command or other started thread item into the widget. It represents the server saying an item has begun.

Data flow: It receives a thread item, wraps it in an ItemStarted notification with current thread and turn ids, and passes it to the widget.

Call relations: begin_exec_with_source and begin_unified_exec_startup use it after constructing command-execution items.

Call graph: calls 1 internal fn (thread_id); called by 2 (begin_exec_with_source, begin_unified_exec_startup); 2 external calls (ItemStarted, handle_server_notification).

terminal_interaction876–898 ↗
fn terminal_interaction(
    chat: &mut ChatWidget,
    call_id: &str,
    process_id: &str,
    stdin: &str,
)

Purpose: Simulates user input being sent to a running terminal process. This tests transcript and state around interactive commands.

Data flow: It receives call id, process id, and stdin text, builds a TerminalInteraction notification with current thread and turn ids, and sends it to the widget.

Call relations: Tests use it after starting a command when they need to show or process input sent to that command.

Call graph: calls 1 internal fn (thread_id); 2 external calls (TerminalInteraction, handle_server_notification).

complete_assistant_message900–920 ↗
fn complete_assistant_message(
    chat: &mut ChatWidget,
    item_id: &str,
    text: &str,
    phase: Option<MessagePhase>,
)

Purpose: Simulates a completed assistant message. It can optionally specify the message phase.

Data flow: It receives item id, message text, and phase, creates an AgentMessage item, wraps it in an ItemCompleted notification for turn-1, and sends it to the widget.

Call relations: Tests use it when they want a full assistant message without streaming deltas first.

Call graph: 2 external calls (ItemCompleted, handle_server_notification).

pending_steer922–931 ↗
fn pending_steer(text: &str) -> PendingSteer

Purpose: Creates a pending steer from text. A steer is a queued user instruction meant to guide an ongoing conversation.

Data flow: It receives text, builds a UserMessage, a matching history record type, and a compare key with zero images, then returns the PendingSteer.

Call relations: Tests use it as compact setup for input-queue or steering behavior.

Call graph: calls 1 internal fn (from).

complete_user_message933–942 ↗
fn complete_user_message(chat: &mut ChatWidget, item_id: &str, text: &str)

Purpose: Simulates completion of a text-only user message. This is the common wrapper around the more general input helper.

Data flow: It receives a widget, item id, and text, wraps the text as one UserInput::Text, and forwards it to complete_user_message_for_inputs.

Call relations: It delegates to complete_user_message_for_inputs, which sends the actual notification.

Call graph: calls 1 internal fn (complete_user_message_for_inputs); 1 external calls (vec!).

complete_user_message_for_inputs944–962 ↗
fn complete_user_message_for_inputs(
    chat: &mut ChatWidget,
    item_id: &str,
    content: Vec<UserInput>,
)

Purpose: Simulates completion of a user message with arbitrary input parts. This tests how the widget records submitted user content.

Data flow: It receives content inputs, creates a UserMessage item with no client id, wraps it in an ItemCompleted notification for turn-1, and sends it to the widget.

Call relations: complete_user_message uses it for the text-only case. Tests call it directly for richer user input.

Call graph: called by 1 (complete_user_message); 2 external calls (ItemCompleted, handle_server_notification).

app_server_turn964–980 ↗
fn app_server_turn(
    turn_id: &str,
    status: AppServerTurnStatus,
    duration_ms: Option<i64>,
    error: Option<AppServerTurnError>,
) -> AppServerTurn

Purpose: Builds a standard AppServerTurn object for tests. It fills only the fields tests usually need.

Data flow: It receives turn id, status, optional duration, and optional error, then returns a turn with full item view, no items, and empty timestamps.

Call relations: Turn-start, turn-complete, interrupted, and replay helpers all use this to keep turn objects consistent.

Call graph: called by 4 (handle_turn_completed, handle_turn_interrupted, handle_turn_started, replay_turn_started); 1 external calls (new).

handle_turn_started982–995 ↗
fn handle_turn_started(chat: &mut ChatWidget, turn_id: &str)

Purpose: Simulates the server starting a turn. This tells the widget a new request-response cycle is in progress.

Data flow: It receives a turn id, builds an in-progress turn, wraps it in a TurnStarted notification, and sends it to the widget.

Call relations: It uses app_server_turn for the payload and feeds the result through the normal server-notification path.

Call graph: calls 1 internal fn (app_server_turn); 2 external calls (TurnStarted, handle_server_notification).

handle_turn_completed997–1014 ↗
fn handle_turn_completed(
    chat: &mut ChatWidget,
    turn_id: &str,
    duration_ms: Option<i64>,
)

Purpose: Simulates a turn finishing successfully. It can include how long the turn took.

Data flow: It receives a turn id and optional duration, builds a completed turn with no error, wraps it in a TurnCompleted notification, and sends it to the widget.

Call relations: Tests call it at the end of simulated conversations to verify final state and display.

Call graph: calls 1 internal fn (app_server_turn); 2 external calls (TurnCompleted, handle_server_notification).

handle_turn_interrupted1016–1029 ↗
fn handle_turn_interrupted(chat: &mut ChatWidget, turn_id: &str)

Purpose: Simulates a turn ending because it was interrupted. This is different from normal completion.

Data flow: It receives a turn id, builds an interrupted turn, wraps it in a TurnCompleted notification, and sends it to the widget.

Call relations: handle_budget_limited_turn calls it after marking the turn as budget-limited. Tests also call it directly for cancel-like flows.

Call graph: calls 1 internal fn (app_server_turn); called by 1 (handle_budget_limited_turn); 2 external calls (TurnCompleted, handle_server_notification).

handle_budget_limited_turn1031–1034 ↗
fn handle_budget_limited_turn(chat: &mut ChatWidget, turn_id: &str)

Purpose: Marks a turn as stopped because of a budget limit, then sends the interrupted-turn event. This tests the special UI for budget-limited interruptions.

Data flow: It receives a widget and turn id, records the budget-limited state in the widget’s turn lifecycle, then calls handle_turn_interrupted.

Call relations: It builds on handle_turn_interrupted but adds the extra state needed for budget-limit behavior.

Call graph: calls 1 internal fn (handle_turn_interrupted).

begin_exec1036–1042 ↗
fn begin_exec(
    chat: &mut ChatWidget,
    call_id: &str,
    raw_cmd: &str,
) -> AppServerThreadItem

Purpose: Starts a normal fake agent command execution. It is the simplest command-start helper.

Data flow: It receives a widget, call id, and raw command, then forwards them to begin_exec_with_source with the Agent source. It returns the started command item.

Call relations: Tests use it before calling end_exec when they want a full command lifecycle.

Call graph: calls 1 internal fn (begin_exec_with_source).

end_exec1044–1087 ↗
fn end_exec(
    chat: &mut ChatWidget,
    begin_item: AppServerThreadItem,
    stdout: &str,
    stderr: &str,
    exit_code: i32,
)

Purpose: Completes a fake command execution that was previously started. It chooses success or failure based on the exit code.

Data flow: It receives the original command item plus stdout, stderr, and exit code. It combines output, extracts command fields from the started item, builds a completed or failed CommandExecution item with duration and output, and sends it through handle_exec_end.

Call relations: Tests usually call it after begin_exec or begin_exec_with_source. It requires a command-execution item and panics if given the wrong kind.

Call graph: calls 1 internal fn (handle_exec_end); 2 external calls (format!, panic!).

handle_exec_end1089–1103 ↗
fn handle_exec_end(chat: &mut ChatWidget, item: AppServerThreadItem)

Purpose: Sends a completed thread item into the widget. For command tests, this represents the server saying the command finished.

Data flow: It receives an item, wraps it in an ItemCompleted notification with current thread and turn ids, and sends it to the widget.

Call relations: end_exec uses it after constructing the final command item. Other tests can call it with any completed item they build.

Call graph: calls 1 internal fn (thread_id); called by 1 (end_exec); 2 external calls (ItemCompleted, handle_server_notification).

active_blob1105–1113 ↗
fn active_blob(chat: &ChatWidget) -> String

Purpose: Returns the current active transcript cell as plain text. The active cell is the live item currently being updated.

Data flow: It reads the widget’s active cell, renders it at width 80, converts the rendered lines into one string, and returns it. It fails if there is no active cell.

Call relations: It uses lines_to_single_string and is used by tests to snapshot live assistant, command, or tool output.

Call graph: calls 1 internal fn (lines_to_single_string).

active_hook_blob1115–1121 ↗
fn active_hook_blob(chat: &ChatWidget) -> String

Purpose: Returns the current live hook cell as plain text. If there is no hook cell, it returns a clear empty marker.

Data flow: It checks chat.active_hook_cell. If present, it renders the cell at width 80 and converts it to a string; otherwise it returns "<empty>\n".

Call relations: Hook tests use it to inspect hook display before hook output is committed to history.

Call graph: calls 1 internal fn (lines_to_single_string).

expire_quiet_hook_linger1123–1128 ↗
fn expire_quiet_hook_linger(chat: &mut ChatWidget)

Purpose: Forces quiet hook display linger time to expire in tests. This avoids waiting for real time to pass.

Data flow: It mutates the active hook cell, if present, to expire quiet runs immediately, then calls pre_draw_tick so the widget refreshes its display state.

Call relations: Tests use it when they need deterministic hook visibility timing.

Call graph: calls 1 internal fn (pre_draw_tick).

reveal_running_hooks1130–1135 ↗
fn reveal_running_hooks(chat: &mut ChatWidget)

Purpose: Forces running hooks to become visible immediately. This makes hook tests deterministic.

Data flow: It mutates the active hook cell, if present, to reveal running runs now, then asks the widget to do its pre-draw update.

Call relations: assert_hook_events_snapshot uses it after starting a hook so the live hook cell can be asserted without waiting.

Call graph: calls 1 internal fn (pre_draw_tick); called by 1 (assert_hook_events_snapshot).

reveal_running_hooks_after_delayed_redraw1137–1142 ↗
fn reveal_running_hooks_after_delayed_redraw(chat: &mut ChatWidget)

Purpose: Forces running hooks to reveal as if a delayed redraw happened. This tests the delayed-display path without real waiting.

Data flow: It updates the active hook cell’s test timing state, then calls pre_draw_tick so the widget applies the change.

Call relations: Tests use it for hook timing behavior that depends on redraw scheduling.

Call graph: calls 1 internal fn (pre_draw_tick).

get_available_model1144–1154 ↗
fn get_available_model(chat: &ChatWidget, model: &str) -> ModelPreset

Purpose: Finds a named model preset in the widget’s catalog. It fails loudly if the model is missing.

Data flow: It reads the catalog’s model list, searches for the requested model name, clones the matching preset, and returns it. If the catalog cannot be read or the model is absent, the test fails.

Call relations: Tests use it after setting up or modifying the catalog to inspect exact model properties.

assert_shift_left_edits_most_recent_queued_message_for_terminal1156–1191 ↗
async fn assert_shift_left_edits_most_recent_queued_message_for_terminal(
    terminal_info: TerminalInfo,
)

Purpose: Runs a full assertion that Shift+Left edits the newest queued message for a given terminal type. It captures a specific keyboard behavior test.

Data flow: It creates a widget, configures the queued-message edit key binding for the terminal, marks a task as running, queues two messages, simulates Shift+Left, and asserts that the composer now contains the newest message while the older one remains queued.

Call relations: It uses make_chatwidget_manual for setup and is called by terminal-specific tests that want the same behavior checked across terminal environments.

Call graph: calls 2 internal fn (make_chatwidget_manual, from); 2 external calls (new, assert_eq!).

render_bottom_first_row1193–1213 ↗
fn render_bottom_first_row(chat: &ChatWidget, width: u16) -> String

Purpose: Renders the widget and returns the first non-empty row. This helps tests inspect compact bottom-pane output.

Data flow: It asks the widget for its desired height at a given width, renders into an in-memory terminal buffer, scans rows from top to bottom, and returns the first row with visible text.

Call relations: Tests use it when they only care about the first visible line rather than the whole rendered popup.

Call graph: 5 external calls (empty, new, new, desired_height, render).

render_bottom_popup1215–1244 ↗
fn render_bottom_popup(chat: &ChatWidget, width: u16) -> String

Purpose: Renders the widget’s bottom area and returns the visible popup text. It trims empty border space around the output.

Data flow: It creates a buffer sized from the widget’s desired height and supplied width, renders the widget, converts every buffer row to text, trims empty leading and trailing rows, and joins the remaining rows with newlines.

Call relations: render_loaded_plugins_popup uses it after loading plugin data. Other tests use it for snapshotting popup UI.

Call graph: called by 1 (render_loaded_plugins_popup); 4 external calls (empty, new, desired_height, render).

strip_osc8_for_snapshot1246–1278 ↗
fn strip_osc8_for_snapshot(text: &str) -> String

Purpose: Removes terminal hyperlink escape sequences from text before snapshot comparison. OSC 8 is a terminal control format for clickable links.

Data flow: It walks through the string byte by byte. When it sees an OSC 8 escape sequence, it skips it until its terminator; otherwise it copies visible characters into a new string.

Call relations: Tests use it when snapshots should compare what a user sees, not hidden terminal hyperlink codes.

Call graph: 1 external calls (with_capacity).

plugins_test_absolute_path1280–1285 ↗
fn plugins_test_absolute_path(path: &str) -> AbsolutePathBuf

Purpose: Builds an absolute temporary path for plugin-related test data. This avoids using real plugin directories.

Data flow: It starts from the system temporary directory, appends a fixed plugin-test folder and the requested relative path, converts it to an absolute path, and returns it.

Call relations: Plugin summary, detail, and marketplace helpers call this to create realistic but safe paths.

Call graph: called by 4 (plugins_test_curated_marketplace, plugins_test_detail, plugins_test_repo_marketplace, plugins_test_summary); 1 external calls (temp_dir).

plugins_test_interface1287–1311 ↗
fn plugins_test_interface(
    display_name: Option<&str>,
    short_description: Option<&str>,
    long_description: Option<&str>,
) -> PluginInterface

Purpose: Creates plugin interface metadata for tests. Interface metadata is the user-facing name, descriptions, icons, links, and similar fields.

Data flow: It receives optional display name and descriptions, converts present values to strings, fills all other interface fields with empty or None values, and returns the PluginInterface.

Call relations: Plugin summary helpers use it to attach display metadata to fake plugins.

Call graph: called by 2 (plugins_test_remote_summary, plugins_test_summary); 1 external calls (new).

plugins_test_summary1313–1343 ↗
fn plugins_test_summary(
    id: &str,
    name: &str,
    display_name: Option<&str>,
    description: Option<&str>,
    installed: bool,
    enabled: bool,
    install_policy: PluginInstallPolicy,
)

Purpose: Creates a fake local plugin summary. A summary is the short listing shown in plugin menus or marketplaces.

Data flow: It receives identity, display, install, enabled, and policy details, builds a local plugin source path, attaches interface metadata, and returns a PluginSummary.

Call relations: Tests use it to build local plugin lists, often before wrapping them in marketplace or response helpers.

Call graph: calls 2 internal fn (plugins_test_absolute_path, plugins_test_interface); 2 external calls (new, format!).

plugins_test_remote_summary1345–1371 ↗
fn plugins_test_remote_summary(
    remote_plugin_id: &str,
    name: &str,
    display_name: Option<&str>,
    description: Option<&str>,
    installed: bool,
) -> PluginSummary

Purpose: Creates a fake remote plugin summary. Remote plugins come from a marketplace rather than a local path.

Data flow: It receives remote id, name, optional display fields, and installed flag, fills the summary with remote source and available policy, and returns it.

Call relations: Tests use it when checking marketplace behavior for plugins that may need installation.

Call graph: calls 1 internal fn (plugins_test_interface); 1 external calls (new).

plugins_test_curated_marketplace1373–1384 ↗
fn plugins_test_curated_marketplace(
    plugins: Vec<PluginSummary>,
) -> PluginMarketplaceEntry

Purpose: Wraps plugins in a fake curated ChatGPT marketplace entry. This represents the official curated marketplace in tests.

Data flow: It receives plugin summaries, creates a marketplace name, path, display name, and plugin list, then returns the PluginMarketplaceEntry.

Call relations: Tests combine this with plugins_test_response to simulate a loaded curated marketplace.

Call graph: calls 1 internal fn (plugins_test_absolute_path).

plugins_test_repo_marketplace1386–1395 ↗
fn plugins_test_repo_marketplace(plugins: Vec<PluginSummary>) -> PluginMarketplaceEntry

Purpose: Wraps plugins in a fake repository marketplace entry. This represents plugins found from the project or repo.

Data flow: It receives plugin summaries, assigns a repo marketplace name and path, adds display metadata, and returns the entry.

Call relations: Tests use it alongside curated marketplace helpers to check how multiple plugin sources are shown.

Call graph: calls 1 internal fn (plugins_test_absolute_path).

plugins_test_response1397–1405 ↗
fn plugins_test_response(
    marketplaces: Vec<PluginMarketplaceEntry>,
) -> PluginListResponse

Purpose: Creates a fake plugin-list response from marketplace entries. This is the server-style response the widget expects.

Data flow: It receives marketplaces, places them into a PluginListResponse, and fills errors and featured plugin ids as empty lists.

Call relations: render_loaded_plugins_popup and plugin menu tests use it as input to the widget’s plugin-loading path.

Call graph: 1 external calls (new).

render_loaded_plugins_popup1407–1415 ↗
fn render_loaded_plugins_popup(
    chat: &mut ChatWidget,
    response: PluginListResponse,
) -> String

Purpose: Loads fake plugin data into a ChatWidget and returns the rendered plugin popup. This combines setup, widget update, and rendering in one helper.

Data flow: It receives a mutable widget and plugin response, tells the widget plugins loaded for the current working directory, asks it to add plugin output, renders the bottom popup at width 100, and returns the text.

Call relations: It uses render_bottom_popup after driving the widget through on_plugins_loaded and add_plugins_output.

Call graph: calls 1 internal fn (render_bottom_popup); 2 external calls (add_plugins_output, on_plugins_loaded).

plugins_test_detail1417–1469 ↗
fn plugins_test_detail(
    summary: PluginSummary,
    description: Option<&str>,
    skills: &[&str],
    hooks: &[(codex_app_server_protocol::HookEventName, usize)],
    apps: &[&str],
    mcp_serv

Purpose: Creates detailed fake plugin information. Details include description, skills, hooks, apps, and MCP server names.

Data flow: It receives a summary and lists of detail fields, builds skill summaries with paths, expands hook event counts into hook summaries, creates app summaries, copies MCP server names, and returns a PluginDetail.

Call relations: Plugin detail tests use it after selecting a plugin summary to simulate the richer information shown on a detail screen.

Call graph: calls 1 internal fn (plugins_test_absolute_path); 2 external calls (new, iter).

plugins_test_popup_row_position1471–1475 ↗
fn plugins_test_popup_row_position(popup: &str, needle: &str) -> usize

Purpose: Finds where a piece of text appears inside a rendered plugin popup. It fails if the text is missing.

Data flow: It receives popup text and a search string, returns the byte position where the search string begins, or panics with the full popup for easier debugging.

Call relations: Tests use positions from this helper to assert ordering inside rendered plugin popups.

type_plugins_search_query1477–1481 ↗
fn type_plugins_search_query(chat: &mut ChatWidget, query: &str)

Purpose: Types a search query into the ChatWidget one character at a time. This simulates real keyboard input.

Data flow: It receives a mutable widget and query string, turns each character into a key event, and feeds each event to the widget.

Call relations: Plugin search tests use it after opening a plugin popup to filter results through the normal key-handling path.

Call graph: 3 external calls (Char, from, handle_key_event).

handle_hook_started1483–1492 ↗
fn handle_hook_started(chat: &mut ChatWidget, run: AppServerHookRunSummary)

Purpose: Simulates a hook run starting. Hooks are configured actions that run at certain chat or tool events.

Data flow: It receives a hook run summary, wraps it in a HookStarted notification with current thread id and no turn id, and sends it to the widget.

Call relations: assert_hook_events_snapshot calls it to start the hook lifecycle before checking live hook display.

Call graph: calls 1 internal fn (thread_id); called by 1 (assert_hook_events_snapshot); 2 external calls (HookStarted, handle_server_notification).

handle_hook_completed1494–1503 ↗
fn handle_hook_completed(chat: &mut ChatWidget, run: AppServerHookRunSummary)

Purpose: Simulates a hook run completing. This lets tests check how hook results move into history or warnings.

Data flow: It receives a hook run summary, wraps it in a HookCompleted notification with current thread id, and sends it to the widget.

Call relations: assert_hook_events_snapshot calls it after a started hook to finish the lifecycle.

Call graph: calls 1 internal fn (thread_id); called by 1 (assert_hook_events_snapshot); 2 external calls (HookCompleted, handle_server_notification).

hook_run1505–1542 ↗
fn hook_run(
    run_id: &str,
    event_name: codex_app_server_protocol::HookEventName,
    status: codex_app_server_protocol::HookRunStatus,
    status_message: &str,
    entries: Vec<codex_app_serv

Purpose: Builds a fake hook run summary with realistic timing and output entries. It can represent running, completed, failed, blocked, or stopped runs.

Data flow: It receives run id, event name, status, status message, and output entries. It fills source, handler, mode, scope, timestamps, duration for final states, and returns the HookRunSummary.

Call relations: assert_hook_events_snapshot uses it to create both running and completed versions of the same hook run.

Call graph: called by 1 (assert_hook_events_snapshot); 2 external calls (from, matches!).

assert_hook_events_snapshot1544–1601 ↗
async fn assert_hook_events_snapshot(
    event_name: codex_app_server_protocol::HookEventName,
    run_id: &str,
    status_message: &str,
    snapshot_name: &str,
)

Purpose: Runs a complete hook-event snapshot test. It verifies both live hook display and final history output for one hook event type.

Data flow: It creates a widget, sends a running hook event, confirms no history cell was inserted yet, forces the live hook visible, checks the live text, then sends a completed hook with warning and context entries, drains history, and snapshots the combined rendered output.

Call relations: It orchestrates make_chatwidget_manual, hook_run, handle_hook_started, reveal_running_hooks, handle_hook_completed, drain_insert_history, and rendering helpers into one reusable assertion.

Call graph: calls 6 internal fn (drain_insert_history, handle_hook_completed, handle_hook_started, hook_run, make_chatwidget_manual, reveal_running_hooks); 4 external calls (new, assert!, assert_chatwidget_snapshot!, vec!).

hook_event_label1603–1616 ↗
fn hook_event_label(event_name: codex_app_server_protocol::HookEventName) -> &'static str

Purpose: Returns the display label for a hook event name. This keeps expected hook text in tests aligned with event variants.

Data flow: It receives a HookEventName enum value and returns the matching static string such as PreToolUse or SessionStart.

Call relations: assert_hook_events_snapshot uses it when checking that the live hook cell contains the expected running-hook label.

tui/tests/all.rssource ↗
testtest run

This file acts like a table of contents for the terminal user interface tests. Instead of putting all tests directly here, the project keeps them in separate modules, mostly under tests/suite/, and this file pulls those modules into one integration test binary. That matters because Rust treats each file in tests/ as a separate test program; by using one shared test program, the suite can share setup code and test helpers more easily.

It also includes test_backend, which is likely support code used by the tests, and suite, which contains the actual grouped test cases. The line importing codex_cli as _ looks unused on purpose: it keeps the codex_cli development dependency visible to tooling that checks for unused dependencies. The comment explains that the tests spawn the codex binary, so the dependency is still needed even if this file does not call it directly.

The Clippy allowance at the top permits expect(...) in tests. That is common in test code because a failed expectation should stop the test with a clear message.

tui/tests/suite/mod.rssource ↗
testtest discovery

This is a small but important organizing file for the terminal user interface tests. In Rust, a mod line tells the compiler to include another source file as a module, a named section of code. Here, the file acts like a table of contents for tests that used to stand alone: resizing and text reflow, status indicators, terminal history, and live terminal updates.

Without this file, those test files would not be pulled into this particular test suite, so the test runner might skip them. Nothing here performs the tests directly. Instead, it connects the separate test files to the suite, much like putting several chapters into one book so they can be read in order by the same reader.

The comment explains the intent: these are former standalone integration tests now grouped as modules. That keeps related terminal behavior checks in one place while still allowing each test topic to live in its own focused file.

tui/tests/test_backend.rssource ↗
testtest setup

Rust integration tests live in a separate place from the main source code, so they cannot always see helper code in the same way normal project files can. This file solves that by explicitly pulling in src/test_backend.rs and then re-exporting VT100Backend for tests to use.

VT100Backend is likely a fake or controlled terminal backend used in tests. Instead of talking to a real terminal, tests can use it to check what the text user interface would draw. This is like using a practice stage instead of a live theater: the program can perform normally, but the test can safely inspect the result.

The file does not define new behavior itself. The #[path = "../src/test_backend.rs"] line tells Rust where to find the real helper module, and pub use inner::VT100Backend; makes the backend available from this test module. Without this bridge, test files would need to duplicate setup code or would not be able to easily use the shared backend.

App orchestration and support tests

This group covers top-level App behavior, startup and session helpers, transcript rendering, and a handful of focused TUI support regressions outside the chat widget.

tui/src/app/test_support.rssource ↗
testtest setup and test assertions

The App type is the central object for the terminal user interface, so testing app behavior usually needs a lot of surrounding pieces: a chat widget, configuration, model information, telemetry, file search, event channels, and many bits of runtime state. This file acts like a prepared test workbench. It builds an App that is complete enough for tests, but uses offline and test-only pieces so the tests do not need real network access, real managed configuration, or a live user session.

The main helper, make_test_app, first creates a manual chat widget fixture, then copies its configuration and wires up related parts such as file search and session telemetry. It fills the rest of the App fields with safe defaults, empty collections, or test-specific versions. This matters because app tests can focus on the behavior they care about, rather than a long list of setup details.

The file also includes a small helper for creating test telemetry, and another helper for reading whether an app is enabled in the effective configuration. That last helper is useful for tests that need to check what the final merged configuration says after overrides and layers have been applied.

Function details3
make_test_app12–70 ↗
async fn make_test_app() -> App

Purpose: Builds a ready-to-use App for unit tests. It gives tests a realistic app-shaped object while replacing outside-world dependencies with offline or test-safe versions.

Data flow: It starts by making a test chat widget and taking its configuration and event sender. From that configuration it creates file search, picks an offline test model, and builds test telemetry. It then returns a full App with those real test pieces plus many default, empty, or disabled fields, so the result is usable without launching the real terminal app.

Call relations: Many app tests call this when they need a complete App before checking behavior such as config refresh, resume fallback, thread inventory, or app enablement rules. During construction it asks test_session_telemetry to create the telemetry portion, and it also relies on test-support constructors and default builders from nearby modules to keep the fixture isolated from real services.

Call graph: calls 8 internal fn (default, without_managed_config_for_tests, default_for_tests, new, get_model_offline_for_tests, test_session_telemetry, new, defaults); called by 18 (mcp_inventory_omits_thread_id_for_closed_agent_thread, overridden_disabled_guardian_does_not_apply_auto_review_companions, rebuild_config_for_resume_or_fallback_errors_when_cwd_changes, rebuild_config_for_resume_or_fallback_uses_current_config_on_same_cwd_error, refresh_in_memory_config_from_disk_best_effort_keeps_current_config_on_error, refresh_in_memory_config_from_disk_keeps_cloud_requirements_for_thread_transitions, refresh_in_memory_config_from_disk_loads_latest_apps_state, refresh_in_memory_config_from_disk_updates_resize_reflow_config, refresh_in_memory_config_from_disk_uses_active_chat_widget_cwd, sync_tui_pet_disabled_updates_chat_widget_config_copy (+8 more)); 13 external calls (new, new, new, new, new, default, make_chatwidget_manual_with_sender, default, default, default (+3 more)).

test_session_telemetry72–88 ↗
fn test_session_telemetry(config: &Config, model: &str) -> SessionTelemetry

Purpose: Creates session telemetry suitable for tests. Telemetry here means the identifying information the app would normally attach to a session, but filled with harmless test values.

Data flow: It receives the current Config and a model name. It converts the config into the form needed by the model manager, builds offline model information, then creates and returns a SessionTelemetry value with a fresh thread ID, the model details, no account information, a test originator, and a fixed session source.

Call relations: This helper is used by make_test_app while assembling the test App. It hands back the telemetry object that the app expects to have, without requiring a logged-in account or a real model lookup.

Call graph: calls 3 internal fn (construct_model_info_offline_for_tests, new, new); called by 1 (make_test_app); 3 external calls (to_models_manager_config, from_value, json!).

app_enabled_in_effective_config90–101 ↗
fn app_enabled_in_effective_config(config: &Config, app_id: &str) -> Option<bool>

Purpose: Looks up whether a named app is marked as enabled in the final, effective configuration. Tests use it to confirm what the configuration says after all config layers have been combined.

Data flow: It receives a Config and an app ID string. It walks through the effective configuration as nested TOML tables, looking for apps, then the named app, then its enabled value. It returns Some(true) or Some(false) if that boolean is present, and None if any part of the path is missing or not the expected shape.

Call relations: This is a small assertion helper for tests that inspect app configuration. Unlike make_test_app, it does not build anything; it reads the already-merged config and gives tests a simple answer about one app's enabled flag.

tui/src/app/tests.rssource ↗
testtest run

The app tested here is the conductor for a terminal chat interface: it receives events from an app server, updates the chat widget, stores per-thread history, shows approval prompts, and lets users switch between main, agent, and side conversations. These tests protect that orchestration. Without them, subtle bugs could appear, such as an approval from one thread showing in another, a queued message being submitted too early, a side conversation inheriting the wrong context, or a UI clear losing the current draft. The file builds small test apps with fake channels and offline model data, then simulates server notifications, user key presses, config writes, thread switching, and replay from stored snapshots. Many tests focus on timing-like behavior: buffered events arriving before a thread is attached, channels filling up, replay catching up to a running turn, and shutdown or interrupt races. Helper functions at the bottom create common test data, such as thread sessions, turn notifications, approval requests, and rendered text. In plain terms, this file is the safety net for the TUI’s “traffic control” layer: it makes sure messages, prompts, settings, and history go to the right place at the right time.

Function details145
test_absolute_path119–121 ↗
fn test_absolute_path(path: &str) -> AbsolutePathBuf

Purpose: Creates an absolute path value for tests. It is used when a test needs to feed the app a path in the same strict format the real code expects.

Data flow: A path string goes in, it is turned into a path buffer and checked as absolute, and an absolute-path object comes out.

Call relations: Permission and settings tests call this helper when building fake server requests that include file-system paths.

Call graph: calls 1 internal fn (try_from); called by 2 (inactive_thread_permissions_approval_preserves_file_system_permissions, inactive_thread_settings_notification_updates_cached_collaboration_mode); 1 external calls (from).

next_thread_settings_updated123–144 ↗
async fn next_thread_settings_updated(
    app_server: &mut AppServerSession,
    thread_id: ThreadId,
) -> ThreadSettingsUpdatedNotification

Purpose: Waits for the next thread-settings update notification for a specific thread. It helps tests ignore unrelated app-server events.

Data flow: An app-server session and thread id go in; the function reads events until it finds the matching settings update, then returns that notification or panics if it never appears.

Call relations: The thread-settings override test uses this after submitting a settings change, so it can verify the server emitted the expected update.

Call graph: calls 1 internal fn (next_event); called by 1 (override_turn_context_sends_thread_settings_update); 4 external calls (panic!, to_string, from_secs, timeout).

handle_mcp_inventory_result_respects_origin_thread147–182 ↗
async fn handle_mcp_inventory_result_respects_origin_thread()

Purpose: Checks that MCP inventory results only affect the thread they belong to. MCP means Model Context Protocol, a way external tool servers are reported to the app.

Data flow: The test creates loading UI cells, sends inventory results with and without matching thread ids, and checks whether the loading cell is removed.

Call relations: It exercises the app’s MCP inventory result path directly to make sure cross-thread results do not erase another thread’s UI.

Call graph: calls 2 internal fn (new, make_test_app); 5 external calls (new, new, assert_eq!, new_mcp_inventory_loading, vec!).

bypass_hook_trust_startup_warning_snapshot185–195 ↗
fn bypass_hook_trust_startup_warning_snapshot()

Purpose: Locks down the exact warning text shown when hook trust is dangerously bypassed. The snapshot catches accidental wording or formatting changes.

Data flow: A warning history cell is rendered to plain text, then compared with a saved snapshot.

Call relations: It relies on the shared line-rendering helper and the snapshot macro used throughout this test file.

Call graph: calls 1 internal fn (lines_to_single_string); 2 external calls (assert_app_snapshot!, new_warning_event).

enqueue_primary_thread_session_replays_buffered_approval_after_attach197–248 ↗
async fn enqueue_primary_thread_session_replays_buffered_approval_after_attach() -> Result<()>

Purpose: Verifies that an approval request received before the primary thread is attached is replayed afterward and can still be answered.

Data flow: A fake approval is buffered, a thread session is attached, the buffered event is read, and pressing y produces a thread-scoped operation.

Call relations: It combines the test-app builder, approval helper, and thread-session helper to test the app’s primary-thread attach flow.

Call graph: calls 4 internal fn (new, exec_approval_request, make_test_app_with_channels, test_thread_session); 8 external calls (from_millis, Char, new, new, assert!, assert_eq!, panic!, timeout).

resolved_buffered_approval_does_not_become_actionable_after_drain251–308 ↗
async fn resolved_buffered_approval_does_not_become_actionable_after_drain() -> Result<()>

Purpose: Ensures an approval that was already resolved does not become clickable again when its buffered event is later drained.

Data flow: The test enqueues and resolves an approval, drains the buffered event, simulates accepting it, and confirms no submit operation is emitted.

Call relations: It checks the same buffering path as the prior approval test, but covers the resolved-request edge case.

Call graph: calls 4 internal fn (new, exec_approval_request, make_test_app_with_channels, test_thread_session); 8 external calls (Integer, from_millis, Char, new, new, assert!, assert_eq!, timeout).

enqueue_primary_thread_session_replays_turns_before_initial_prompt_submit311–394 ↗
async fn enqueue_primary_thread_session_replays_turns_before_initial_prompt_submit() -> Result<()>

Purpose: Checks that restored history appears before an initial prompt is submitted. This prevents the first visible action from looking out of order.

Data flow: A new chat widget with an initial prompt is installed, a previous turn is replayed, and emitted events are inspected for both history insertion and prompt submission.

Call relations: It uses the model and thread helpers to exercise primary thread startup replay plus initial user-message submission.

Call graph: calls 7 internal fn (new, get_model_offline_for_tests, new, lines_to_single_string, make_test_app_with_channels, test_thread_session, test_dummy); 6 external calls (new, assert!, assert_eq!, create_initial_user_message, new_with_app_event, vec!).

reset_thread_event_state_aborts_listener_tasks397–429 ↗
async fn reset_thread_event_state_aborts_listener_tasks()

Purpose: Confirms that resetting thread event state stops background listener tasks. A listener task is an async job waiting for thread events.

Data flow: A never-ending task is inserted, reset is called, and a drop notification proves the task was aborted and removed.

Call relations: It directly tests cleanup behavior that protects the app from leaving old event readers running.

Call graph: calls 2 internal fn (new, make_test_app); 5 external calls (from_millis, assert_eq!, timeout, spawn, channel).

history_lookup_response_is_routed_to_requesting_thread432–457 ↗
async fn history_lookup_response_is_routed_to_requesting_thread() -> Result<()>

Purpose: Checks that a message-history lookup response keeps the thread id that requested it.

Data flow: The app starts a lookup for one thread, receives an app event, and verifies the response event names the same thread and lookup details.

Call relations: It exercises the app event routing path used when the UI asks for older history.

Call graph: calls 2 internal fn (new, make_test_app_with_channels); 5 external calls (from_secs, assert!, assert_eq!, panic!, timeout).

enqueue_thread_event_does_not_block_when_channel_full460–496 ↗
async fn enqueue_thread_event_does_not_block_when_channel_full() -> Result<()>

Purpose: Ensures adding thread events will not hang if a per-thread channel is full.

Data flow: A tiny channel is filled, another event is enqueued under a timeout, and both events are later read back.

Call relations: It tests the thread-notification enqueue path using the thread-closed notification helper.

Call graph: calls 4 internal fn (new, make_test_app, thread_closed_notification, new); 2 external calls (from_millis, timeout).

replay_thread_snapshot_restores_draft_and_queued_input499–557 ↗
async fn replay_thread_snapshot_restores_draft_and_queued_input()

Purpose: Verifies that switching away from and back to a thread restores the draft text without accidentally submitting queued input.

Data flow: The test captures input state, stores it in a thread snapshot, replaces the chat widget, replays the snapshot, and checks the composer and outgoing operations.

Call relations: It uses the thread-session helper and manual chat-widget factory to test snapshot replay in isolation.

Call graph: calls 4 internal fn (new, make_test_app, test_thread_session, new_with_session); 4 external calls (new, assert!, assert_eq!, make_chatwidget_manual_with_sender).

active_turn_id_for_thread_uses_snapshot_turns560–577 ↗
async fn active_turn_id_for_thread_uses_snapshot_turns()

Purpose: Checks that the app can find a thread’s active turn from cached snapshot data.

Data flow: A thread channel is seeded with an in-progress turn, and the lookup returns that turn id.

Call relations: It relies on the shared test session and turn helper to validate per-thread state lookup.

Call graph: calls 4 internal fn (new, make_test_app, test_thread_session, new_with_session); 2 external calls (assert_eq!, vec!).

replayed_turn_complete_submits_restored_queued_follow_up580–629 ↗
async fn replayed_turn_complete_submits_restored_queued_follow_up()

Purpose: Ensures a queued follow-up message is submitted after replay proves the prior turn completed.

Data flow: A running turn and queued input are captured, replayed with a completion event, and the outgoing user-turn operation is checked.

Call relations: It uses notification helpers and next_user_turn_op to verify replay triggers the same submission path as live completion.

Call graph: calls 6 internal fn (new, agent_message_delta_notification, make_test_app_with_channels, next_user_turn_op, test_thread_session, turn_started_notification); 6 external calls (new, new, assert_eq!, make_chatwidget_manual_with_sender, panic!, vec!).

replay_only_thread_keeps_restored_queue_visible632–680 ↗
async fn replay_only_thread_keeps_restored_queue_visible()

Purpose: Checks that replay-only threads show restored queued input but do not submit it.

Data flow: A queued follow-up is captured, replayed with completion while auto-resume is disabled, and the queue remains visible with no outgoing operation.

Call relations: It tests snapshot replay behavior for read-only or non-live thread views.

Call graph: calls 5 internal fn (new, agent_message_delta_notification, make_test_app_with_channels, test_thread_session, turn_started_notification); 6 external calls (new, new, assert!, assert_eq!, make_chatwidget_manual_with_sender, vec!).

replay_thread_snapshot_keeps_queue_when_running_state_only_comes_from_snapshot683–729 ↗
async fn replay_thread_snapshot_keeps_queue_when_running_state_only_comes_from_snapshot()

Purpose: Ensures queued input stays queued if replay does not show the running turn has finished.

Data flow: Captured queued input is replayed without completion evidence, and the test checks that nothing is submitted.

Call relations: It guards the replay logic against treating missing events as permission to send a queued message.

Call graph: calls 5 internal fn (new, agent_message_delta_notification, make_test_app_with_channels, test_thread_session, turn_started_notification); 6 external calls (new, new, assert!, assert_eq!, make_chatwidget_manual_with_sender, vec!).

replay_thread_snapshot_in_progress_turn_restores_running_queue_state732–778 ↗
async fn replay_thread_snapshot_in_progress_turn_restores_running_queue_state()

Purpose: Verifies that an in-progress turn in snapshot data keeps follow-up input queued.

Data flow: A snapshot with an in-progress turn and saved queue state is replayed, leaving the queued text in place and producing no user-turn operation.

Call relations: It covers the snapshot-turn version of the same running-state decision tested elsewhere with replayed events.

Call graph: calls 5 internal fn (new, agent_message_delta_notification, make_test_app_with_channels, test_thread_session, turn_started_notification); 6 external calls (new, new, assert!, assert_eq!, make_chatwidget_manual_with_sender, vec!).

replay_thread_snapshot_in_progress_turn_restores_running_state_without_input_state781–800 ↗
async fn replay_thread_snapshot_in_progress_turn_restores_running_state_without_input_state()

Purpose: Checks that replaying an in-progress turn marks the chat widget as running even if no draft or queue was saved.

Data flow: A fresh widget receives a snapshot containing only an in-progress turn, and the test confirms the task-running flag is set.

Call relations: It focuses on the chat widget state restored by app snapshot replay.

Call graph: calls 3 internal fn (new, make_test_app_with_channels, test_thread_session); 4 external calls (new, assert!, make_chatwidget_manual_with_sender, vec!).

replay_thread_snapshot_does_not_submit_queue_before_replay_catches_up803–872 ↗
async fn replay_thread_snapshot_does_not_submit_queue_before_replay_catches_up()

Purpose: Ensures queued input waits for the latest replayed turn to complete, not just any earlier turn.

Data flow: Replay includes an older completion and a newer start, the queue remains held, then a live completion submits the follow-up.

Call relations: It combines replay helpers with live notification handling to test the handoff from replay to active thread updates.

Call graph: calls 7 internal fn (new, agent_message_delta_notification, make_test_app_with_channels, next_user_turn_op, test_thread_session, turn_completed_notification, turn_started_notification); 7 external calls (new, new, assert!, assert_eq!, make_chatwidget_manual_with_sender, panic!, vec!).

replay_thread_snapshot_restores_pending_pastes_for_submit875–929 ↗
async fn replay_thread_snapshot_restores_pending_pastes_for_submit()

Purpose: Verifies that a large pasted draft survives thread switching and can be submitted afterward.

Data flow: A large paste is captured in input state, replayed into a new widget, then Enter produces a user-turn operation containing the pasted text.

Call relations: It uses next_user_turn_op to confirm restored paste data flows into normal submission.

Call graph: calls 5 internal fn (new, make_test_app_with_channels, next_user_turn_op, test_thread_session, new_with_session); 5 external calls (new, new, assert_eq!, make_chatwidget_manual_with_sender, panic!).

replay_thread_snapshot_restores_collaboration_mode_for_draft_submit932–1013 ↗
async fn replay_thread_snapshot_restores_collaboration_mode_for_draft_submit()

Purpose: Checks that a saved draft remembers its collaboration mode, model, and reasoning effort when later submitted.

Data flow: A draft is saved under one mode, replayed into a widget currently set to another mode, and submission uses the restored mode settings.

Call relations: It protects thread-specific input state from being overwritten by whichever settings are active at replay time.

Call graph: calls 4 internal fn (new, make_test_app_with_channels, next_user_turn_op, test_thread_session); 6 external calls (new, new, assert_eq!, make_chatwidget_manual_with_sender, panic!, vec!).

replay_thread_snapshot_restores_collaboration_mode_without_input1016–1069 ↗
async fn replay_thread_snapshot_restores_collaboration_mode_without_input()

Purpose: Ensures collaboration settings restore even when there is no text draft.

Data flow: A settings-only input state is replayed, and the widget’s active mode, model, and effort are checked.

Call relations: It complements the draft-submit test by covering pure settings restoration.

Call graph: calls 3 internal fn (new, make_test_app_with_channels, test_thread_session); 4 external calls (new, assert_eq!, make_chatwidget_manual_with_sender, vec!).

replayed_interrupted_turn_restores_queued_input_to_composer1072–1121 ↗
async fn replayed_interrupted_turn_restores_queued_input_to_composer()

Purpose: Checks that if a turn was interrupted, queued follow-up text returns to the composer for editing instead of being submitted.

Data flow: Queued input is captured, replay reports the turn interrupted, and the text appears in the composer with no outgoing operation.

Call relations: It tests the replay branch for interrupted turns using the same notification and session helpers as the queue tests.

Call graph: calls 5 internal fn (new, agent_message_delta_notification, make_test_app_with_channels, test_thread_session, turn_started_notification); 6 external calls (new, new, assert!, assert_eq!, make_chatwidget_manual_with_sender, vec!).

token_usage_update_refreshes_status_line_with_runtime_context_window1124–1143 ↗
async fn token_usage_update_refreshes_status_line_with_runtime_context_window()

Purpose: Verifies that token-usage notifications update the status line with the model’s context-window size.

Data flow: The status line starts empty, a token-usage event with a context window is handled, and the status text changes.

Call relations: It uses the token-usage notification helper to exercise live thread event handling.

Call graph: calls 3 internal fn (new, make_test_app, token_usage_notification); 3 external calls (assert_eq!, Notification, vec!).

collab_receiver_notification_caches_thread_without_app_server_read1146–1180 ↗
async fn collab_receiver_notification_caches_thread_without_app_server_read()

Purpose: Checks that a collaboration tool call mentioning a receiver thread creates navigation metadata without reading that thread from the server.

Data flow: A fake collab item-started notification is handled, and the receiver thread appears in agent navigation with placeholder metadata.

Call relations: It tests passive discovery of agent threads from collaboration notifications.

Call graph: calls 3 internal fn (from_string, new, make_test_app); 5 external calls (new, ItemStarted, assert_eq!, Notification, vec!).

collab_receiver_notification_does_not_cache_not_found_thread1183–1214 ↗
async fn collab_receiver_notification_does_not_cache_not_found_thread()

Purpose: Ensures a receiver thread marked not found is not added to agent navigation.

Data flow: A failed collab item-completed notification with a not-found receiver is handled, and navigation remains empty for that thread.

Call relations: It covers the negative case for the collaboration receiver caching logic.

Call graph: calls 3 internal fn (from_string, new, make_test_app); 5 external calls (from, ItemCompleted, assert_eq!, Notification, vec!).

open_agent_picker_keeps_missing_threads_for_replay1217–1243 ↗
async fn open_agent_picker_keeps_missing_threads_for_replay() -> Result<()>

Purpose: Checks that opening the agent picker keeps locally cached threads even if the server cannot currently read them.

Data flow: A local thread channel is inserted, the picker opens, and the thread remains listed as closed for replay.

Call relations: It exercises the picker refresh path with an embedded test app server.

Call graph: calls 3 internal fn (new, make_test_app, new); 3 external calls (pin, assert_eq!, start_embedded_app_server_for_picker).

open_agent_picker_preserves_cached_metadata_for_replay_threads1246–1277 ↗
async fn open_agent_picker_preserves_cached_metadata_for_replay_threads() -> Result<()>

Purpose: Ensures replay-only agent threads keep their cached nickname and role when the picker refreshes.

Data flow: Cached metadata is inserted, the picker opens, and the metadata is still present.

Call relations: It protects user-facing labels from being erased during agent-picker refresh.

Call graph: calls 3 internal fn (new, make_test_app, new); 3 external calls (pin, assert_eq!, start_embedded_app_server_for_picker).

open_agent_picker_clears_completed_path_backed_agent_running_state1280–1319 ↗
async fn open_agent_picker_clears_completed_path_backed_agent_running_state() -> Result<()>

Purpose: Checks that an agent thread with completed cached turns is no longer shown as running.

Data flow: A channel is seeded with start and completion events, agent activity says running, and picker refresh clears the running flag.

Call relations: It ties thread snapshot liveness to the agent navigation display.

Call graph: calls 5 internal fn (new, make_test_app, turn_completed_notification, turn_started_notification, new); 3 external calls (pin, assert_eq!, start_embedded_app_server_for_picker).

open_agent_picker_refreshes_replay_only_path_backed_liveness1322–1357 ↗
async fn open_agent_picker_refreshes_replay_only_path_backed_liveness() -> Result<()>

Purpose: Ensures replay-only path-backed agents are shown as closed even if their cached events suggest they were running.

Data flow: A replay-only channel with a started turn is refreshed through the picker, and navigation marks it closed and not running.

Call relations: It tests how replay-only status overrides cached activity hints.

Call graph: calls 4 internal fn (new, make_test_app, turn_started_notification, new); 3 external calls (pin, assert_eq!, start_embedded_app_server_for_picker).

open_agent_picker_prunes_terminal_metadata_only_threads1360–1380 ↗
async fn open_agent_picker_prunes_terminal_metadata_only_threads() -> Result<()>

Purpose: Checks that stale agent metadata with no backing thread state is removed.

Data flow: Navigation is seeded with a ghost thread, picker refresh runs, and the entry disappears.

Call relations: It covers cleanup in the agent picker’s refresh cycle.

Call graph: calls 2 internal fn (new, make_test_app); 4 external calls (pin, assert!, assert_eq!, start_embedded_app_server_for_picker).

open_agent_picker_marks_terminal_read_errors_closed1383–1413 ↗
async fn open_agent_picker_marks_terminal_read_errors_closed() -> Result<()>

Purpose: Verifies that a thread read failure leaves the cached thread available as closed rather than active.

Data flow: A local channel and metadata are inserted, picker refresh fails to load it, and the entry is marked closed.

Call relations: It protects replay access for threads the server cannot read live.

Call graph: calls 3 internal fn (new, make_test_app, new); 3 external calls (pin, assert_eq!, start_embedded_app_server_for_picker).

open_agent_picker_marks_loaded_threads_open1416–1454 ↗
fn open_agent_picker_marks_loaded_threads_open() -> Result<()>

Purpose: Checks that a thread successfully loaded from the server is marked open in the picker.

Data flow: A real embedded-server thread is started, locally cached, picker refresh runs, and navigation marks it not closed.

Call relations: It uses its own Tokio runtime to test the app-server-backed picker flow.

Call graph: calls 2 internal fn (make_test_app, new); 4 external calls (pin, assert_eq!, start_embedded_app_server_for_picker, new_multi_thread).

attach_live_thread_for_selection_rejects_empty_non_ephemeral_fallback_threads1457–1497 ↗
fn attach_live_thread_for_selection_rejects_empty_non_ephemeral_fallback_threads() -> Result<()>

Purpose: Ensures the app does not attach a blank fallback for a live non-ephemeral thread that has no replay material yet.

Data flow: A server thread is created but not materialized in local state, attach is attempted, and an explanatory error is returned.

Call relations: It tests agent-picker selection attach behavior against a real embedded server.

Call graph: calls 1 internal fn (make_test_app); 4 external calls (assert!, assert_eq!, start_embedded_app_server_for_picker, new_multi_thread).

attach_live_thread_for_selection_rejects_unmaterialized_fallback_threads1500–1537 ↗
fn attach_live_thread_for_selection_rejects_unmaterialized_fallback_threads() -> Result<()>

Purpose: Ensures an ephemeral fallback thread also cannot be attached as a blank live view.

Data flow: An ephemeral server thread is started, attach is attempted, and the app rejects it without adding a local channel.

Call relations: It complements the non-ephemeral rejection test for side or temporary threads.

Call graph: calls 1 internal fn (make_test_app); 4 external calls (assert!, assert_eq!, start_embedded_app_server_for_picker, new_multi_thread).

should_attach_live_thread_for_selection_skips_closed_metadata_only_threads1540–1563 ↗
async fn should_attach_live_thread_for_selection_skips_closed_metadata_only_threads()

Purpose: Checks the quick decision for whether picker selection should try a live attach.

Data flow: The test toggles metadata between closed, open, and already cached states, and checks the boolean decision each time.

Call relations: It directly exercises the lightweight guard used before attempting a server attach.

Call graph: calls 3 internal fn (new, make_test_app, new); 1 external calls (assert!).

refresh_agent_picker_thread_liveness_prunes_closed_metadata_only_threads1566–1588 ↗
async fn refresh_agent_picker_thread_liveness_prunes_closed_metadata_only_threads() -> Result<()>

Purpose: Verifies that refreshing a metadata-only thread removes it when it is not available.

Data flow: A ghost navigation entry is refreshed against the server, returns unavailable, and is removed from navigation and channels.

Call relations: It tests the single-thread refresh helper used by the picker.

Call graph: calls 2 internal fn (new, make_test_app); 4 external calls (pin, assert!, assert_eq!, start_embedded_app_server_for_picker).

open_agent_picker_prompts_to_enable_multi_agent_when_disabled1591–1620 ↗
async fn open_agent_picker_prompts_to_enable_multi_agent_when_disabled() -> Result<()>

Purpose: Checks that opening the agent picker while multi-agent support is disabled offers to enable it.

Data flow: The feature is disabled, the picker opens, Enter is pressed, and events request enabling plus show an informational history cell.

Call relations: It exercises picker UI behavior through the chat widget and app event channel.

Call graph: calls 1 internal fn (make_test_app_with_channels); 6 external calls (pin, new, assert!, assert_matches!, start_embedded_app_server_for_picker, panic!).

update_memory_settings_persists_and_updates_widget_config1623–1663 ↗
async fn update_memory_settings_persists_and_updates_widget_config() -> Result<()>

Purpose: Verifies memory settings are written to config and reflected in both app and widget state.

Data flow: A temp config home is used, settings are changed through the app server, and the in-memory config plus written TOML file are checked.

Call relations: It tests the settings menu path that updates memory behavior.

Call graph: calls 1 internal fn (make_test_app_with_channels); 6 external calls (pin, assert!, assert_eq!, start_embedded_app_server_for_picker, read_to_string, tempdir).

update_memory_settings_updates_current_thread_memory_mode1666–1712 ↗
fn update_memory_settings_updates_current_thread_memory_mode() -> Result<()>

Purpose: Checks that changing memory generation updates the current thread’s stored memory mode.

Data flow: A thread is started, memory generation is disabled, and the state database records the thread mode as disabled.

Call relations: It combines config writing, app-server thread state, and the state database.

Call graph: calls 2 internal fn (init, make_test_app_with_channels); 5 external calls (pin, assert_eq!, start_embedded_app_server_for_picker, tempdir, new_multi_thread).

reset_memories_clears_local_memory_directories1715–1744 ↗
async fn reset_memories_clears_local_memory_directories() -> Result<()>

Purpose: Ensures the reset-memories action deletes local memory files and folders.

Data flow: Fake memory files are created under a temp home, reset runs through the app server, and the memory root becomes empty.

Call relations: It tests the destructive cleanup path used by the UI memory reset command.

Call graph: calls 1 internal fn (make_test_app_with_channels); 6 external calls (pin, assert_eq!, start_embedded_app_server_for_picker, create_dir_all, write, tempdir).

apply_permission_profile_selection_preserves_loader_overrides1747–1829 ↗
async fn apply_permission_profile_selection_preserves_loader_overrides() -> Result<()>

Purpose: Checks that selecting a permission profile respects the config file path chosen by the loader.

Data flow: A temp config defines a profile, runtime overrides are set, selection is applied, and app/widget config plus emitted operation are verified.

Call relations: It exercises permission profile selection and its notification to the running conversation.

Call graph: calls 2 internal fn (workspace_write, make_test_app_with_channels); 5 external calls (assert!, assert_eq!, panic!, write, tempdir).

update_feature_flags_enabling_guardian_selects_auto_review1832–1930 ↗
async fn update_feature_flags_enabling_guardian_selects_auto_review() -> Result<()>

Purpose: Verifies enabling Guardian Approval also selects the auto-review permission mode.

Data flow: The feature flag is enabled, app and widget configs update, an override operation is emitted, history shows the change, and config TOML is written.

Call relations: It uses the config-write app-server helper shared by Guardian feature tests.

Call graph: calls 2 internal fn (make_test_app_with_channels, start_config_write_test_app_server); 6 external calls (assert!, assert_eq!, panic!, read_to_string, tempdir, vec!).

update_feature_flags_disabling_guardian_clears_review_policy_and_restores_default1933–2025 ↗
async fn update_feature_flags_disabling_guardian_clears_review_policy_and_restores_default() -> Result<()>

Purpose: Checks that disabling Guardian Approval removes the reviewer setting and restores user approval behavior.

Data flow: A config with Guardian enabled is seeded, the feature is disabled, runtime state and written TOML are inspected.

Call relations: It validates the rollback side of the Guardian feature toggle flow.

Call graph: calls 4 internal fn (legacy, workspace_write, make_test_app_with_channels, start_config_write_test_app_server); 7 external calls (assert!, assert_eq!, panic!, read_to_string, write, tempdir, vec!).

update_feature_flags_enabling_guardian_overrides_explicit_manual_review_policy2028–2095 ↗
async fn update_feature_flags_enabling_guardian_overrides_explicit_manual_review_policy() -> Result<()>

Purpose: Ensures enabling Guardian overrides an explicit manual reviewer setting.

Data flow: A config with manual review is seeded, Guardian is enabled, and the resulting config, widget state, operation, and file contents use auto review.

Call relations: It covers precedence rules in the same feature-flag update path.

Call graph: calls 2 internal fn (make_test_app_with_channels, start_config_write_test_app_server); 6 external calls (assert!, assert_eq!, read_to_string, write, tempdir, vec!).

update_feature_flags_disabling_guardian_clears_manual_review_policy_without_history2098–2157 ↗
async fn update_feature_flags_disabling_guardian_clears_manual_review_policy_without_history() -> Result<()>

Purpose: Checks that disabling Guardian does not add a history notice when the effective review mode remains the default.

Data flow: Guardian is disabled from a manual-review config, an override operation is emitted, no history event appears, and TOML removes the feature and reviewer keys.

Call relations: It guards against noisy UI updates in the Guardian toggle path.

Call graph: calls 2 internal fn (make_test_app_with_channels, start_config_write_test_app_server); 6 external calls (assert!, assert_eq!, read_to_string, write, tempdir, vec!).

open_agent_picker_allows_existing_agent_threads_when_feature_is_disabled2160–2180 ↗
async fn open_agent_picker_allows_existing_agent_threads_when_feature_is_disabled() -> Result<()>

Purpose: Ensures existing agent threads remain selectable even when the multi-agent feature is disabled.

Data flow: A thread channel is present, the picker opens, Enter selects the thread, and a selection app event is emitted.

Call relations: It distinguishes existing replay data from starting new multi-agent functionality.

Call graph: calls 3 internal fn (new, make_test_app_with_channels, new); 4 external calls (pin, new, assert_matches!, start_embedded_app_server_for_picker).

refresh_pending_thread_approvals_only_lists_inactive_threads2183–2223 ↗
async fn refresh_pending_thread_approvals_only_lists_inactive_threads()

Purpose: Checks that the pending-approval badge lists only approvals from inactive threads.

Data flow: A main and agent thread are created, the agent has a pending approval, and the badge appears until that agent becomes active.

Call relations: It tests the badge refresh logic using the approval helper.

Call graph: calls 4 internal fn (from_string, exec_approval_request, make_test_app, new); 2 external calls (assert!, assert_eq!).

inactive_thread_approval_bubbles_into_active_view2226–2275 ↗
async fn inactive_thread_approval_bubbles_into_active_view() -> Result<()>

Purpose: Verifies an approval in an inactive agent thread can surface in the active view as an actionable prompt.

Data flow: An agent thread with approval-capable settings gets an approval request, and the active chat widget shows an approval view plus badge text.

Call relations: It exercises inactive-thread request queuing and surfacing.

Call graph: calls 7 internal fn (workspace_write, from_string, exec_approval_request, make_test_app, test_thread_session, new, new_with_session); 2 external calls (new, assert_eq!).

side_defers_parent_approval_overlay_until_parent_replay2278–2333 ↗
async fn side_defers_parent_approval_overlay_until_parent_replay() -> Result<()>

Purpose: Checks that while in a side conversation, a parent-thread approval is noted but not shown until returning to the parent.

Data flow: A parent approval is queued while a side thread is active, side state records needing approval, then parent replay shows the active view.

Call relations: It tests the side-conversation deferral path for parent interactive requests.

Call graph: calls 6 internal fn (from_string, new, exec_approval_request, make_test_app, test_thread_session, new_with_session); 3 external calls (new, assert!, assert_eq!).

replay_snapshot_with_pending_request_suppresses_replay_notices2336–2380 ↗
async fn replay_snapshot_with_pending_request_suppresses_replay_notices()

Purpose: Ensures replay notices do not cover an approval prompt when a snapshot contains a pending request.

Data flow: A snapshot with a warning and approval request is replayed, the approval view appears, and no replayed warning history is emitted.

Call relations: It guards the replay display order around interactive requests.

Call graph: calls 4 internal fn (from_string, lines_to_single_string, make_test_app_with_channels, test_thread_session); 5 external calls (new, new, assert!, assert_eq!, vec!).

side_defers_subagent_approval_overlay_until_side_exits2383–2441 ↗
async fn side_defers_subagent_approval_overlay_until_side_exits() -> Result<()>

Purpose: Checks that a subagent approval is not shown as an overlay while a side conversation is active, but appears after leaving side mode.

Data flow: An agent approval is queued during side mode, only the badge appears, then after side exit the pending request surfaces.

Call relations: It exercises inactive-thread approval surfacing with side-thread suppression.

Call graph: calls 7 internal fn (workspace_write, from_string, new, exec_approval_request, make_test_app, test_thread_session, new_with_session); 2 external calls (new, assert_eq!).

inactive_thread_exec_approval_preserves_context2444–2524 ↗
async fn inactive_thread_exec_approval_preserves_context()

Purpose: Verifies command-execution approvals keep network and extra permission details when converted for an inactive thread.

Data flow: A fake exec approval is enriched with network and file permissions, converted into a UI request, and all details are checked.

Call relations: It tests the app’s request-localization logic for inactive-thread approvals.

Call graph: calls 3 internal fn (new, exec_approval_request, make_test_app); 3 external calls (assert_eq!, panic!, vec!).

inactive_thread_exec_approval_splits_shell_wrapped_command2527–2559 ↗
async fn inactive_thread_exec_approval_splits_shell_wrapped_command()

Purpose: Checks that a shell-wrapped command is split into meaningful command parts for display.

Data flow: A joined shell command string goes into an exec approval, conversion produces a vector of command arguments, and the pieces are checked.

Call relations: It covers command formatting in the inactive approval conversion path.

Call graph: calls 3 internal fn (new, exec_approval_request, make_test_app); 3 external calls (assert_eq!, panic!, try_join).

inactive_thread_file_change_approval_recovers_buffered_changes2562–2631 ↗
async fn inactive_thread_file_change_approval_recovers_buffered_changes()

Purpose: Ensures a file-change approval can recover the patch preview from earlier buffered file-change events.

Data flow: A file-change item is buffered, an approval request is converted, recovered changes and reason are checked, then the preview cell is rendered.

Call relations: It ties the event store to the approval UI for patch requests.

Call graph: calls 3 internal fn (new, lines_to_single_string, make_test_app_with_channels); 6 external calls (Integer, ItemStarted, assert!, assert_eq!, panic!, vec!).

inactive_thread_permissions_approval_preserves_file_system_permissions2634–2686 ↗
async fn inactive_thread_permissions_approval_preserves_file_system_permissions()

Purpose: Checks that permission approval requests preserve read and write path permissions.

Data flow: A permissions request with network and file-system entries is converted, and the UI request contains equivalent permission data.

Call relations: It uses test_absolute_path to build strict path values for conversion.

Call graph: calls 3 internal fn (new, make_test_app, test_absolute_path); 4 external calls (Integer, assert_eq!, panic!, vec!).

inactive_thread_invalid_url_elicitation_is_declined2729–2766 ↗
async fn inactive_thread_invalid_url_elicitation_is_declined()

Purpose: Ensures an unsafe or invalid MCP URL elicitation is declined automatically.

Data flow: A request with an HTTP URL is converted, no UI prompt is returned, and a decline operation is sent for that thread.

Call relations: It covers the safety branch paired with the valid app-link test.

Call graph: calls 2 internal fn (new, make_test_app_with_channels); 3 external calls (Integer, assert!, assert_matches!).

inactive_thread_approval_badge_clears_after_turn_completion_notification2769–2827 ↗
async fn inactive_thread_approval_badge_clears_after_turn_completion_notification() -> Result<()>

Purpose: Checks that an inactive-thread approval badge disappears as soon as that turn completes.

Data flow: An agent approval creates a badge, a completion notification for the same turn is queued, and the badge list becomes empty.

Call relations: It verifies immediate badge cleanup during inactive-thread event handling.

Call graph: calls 8 internal fn (workspace_write, from_string, exec_approval_request, make_test_app, test_thread_session, turn_completed_notification, new, new_with_session); 3 external calls (new, assert!, assert_eq!).

inactive_thread_started_notification_initializes_replay_session2830–2933 ↗
async fn inactive_thread_started_notification_initializes_replay_session() -> Result<()>

Purpose: Ensures a thread-started notification for an inactive agent builds enough session state for later replay.

Data flow: Primary session state and a rollout file are seeded, a thread-started notification arrives, and the cached session inherits model, permissions, roots, path, and agent metadata correctly.

Call relations: It tests session inference for agent threads discovered through notifications.

Call graph: calls 5 internal fn (workspace_write, from_string, make_test_app, test_thread_session, new_with_session); 8 external calls (ThreadStarted, new, assert_eq!, format!, json!, write, tempdir, vec!).

inactive_thread_started_notification_preserves_primary_model_when_path_missing2936–3004 ↗
async fn inactive_thread_started_notification_preserves_primary_model_when_path_missing() -> Result<()>

Purpose: Checks that if a started agent thread has no rollout path, the cached session keeps the primary model fallback.

Data flow: A primary session is cached, an agent thread-started notification without a path arrives, and the inferred agent session model matches the primary model.

Call relations: It covers a missing-data case in the same session-inference path.

Call graph: calls 5 internal fn (workspace_write, from_string, make_test_app, test_thread_session, new_with_session); 4 external calls (ThreadStarted, new, assert_eq!, vec!).

thread_read_session_state_does_not_reuse_primary_permission_profile3010–3069 ↗
async fn thread_read_session_state_does_not_reuse_primary_permission_profile()

Purpose: Verifies thread/read fallback session state does not reuse the primary thread’s permission profile after changing cwd.

Data flow: A primary session is cached, a separate read thread is converted to session state, and its permission profile comes from active widget config instead.

Call relations: It protects replay hydration from carrying unsafe permissions across workspaces.

Call graph: calls 4 internal fn (workspace_write, from_string, make_test_app, test_thread_session); 3 external calls (new, assert_eq!, vec!).

agent_picker_item_name_snapshot3072–3122 ↗
fn agent_picker_item_name_snapshot()

Purpose: Locks down how agent picker display names are formatted.

Data flow: Several nickname/role/primary combinations are formatted with a thread id and compared to a snapshot.

Call relations: It tests the small formatting function used by the picker UI.

Call graph: calls 1 internal fn (from_string); 2 external calls (assert_app_snapshot!, format!).

side_fork_config_is_ephemeral_and_appends_developer_guardrails3125–3167 ↗
async fn side_fork_config_is_ephemeral_and_appends_developer_guardrails()

Purpose: Checks that a side-conversation fork is temporary and includes safety instructions.

Data flow: The side fork config is created, and the test confirms it is ephemeral, keeps permissions, and contains guardrail text.

Call relations: It directly tests the config builder used when starting side conversations.

Call graph: calls 1 internal fn (make_test_app); 2 external calls (assert!, assert_eq!).

side_fork_config_inherits_parent_thread_runtime_settings3170–3212 ↗
async fn side_fork_config_inherits_parent_thread_runtime_settings()

Purpose: Ensures side conversations inherit the parent thread’s current runtime model, effort, service tier, permissions, and reviewer.

Data flow: The chat widget is set to parent runtime values, a side fork config is built, and those values are checked.

Call relations: It complements the guardrail test by checking inherited settings.

Call graph: calls 3 internal fn (legacy, workspace_write, make_test_app); 1 external calls (assert_eq!).

side_start_block_message_tracks_open_side_conversation3215–3239 ↗
async fn side_start_block_message_tracks_open_side_conversation()

Purpose: Checks the message that explains why /side is unavailable.

Data flow: The app starts with no primary thread, then with a primary thread, then with an active side thread, and the block message changes accordingly.

Call relations: It tests the guard used before starting a side conversation.

Call graph: calls 3 internal fn (new, new, make_test_app); 1 external calls (assert_eq!).

side_parent_status_tracks_parent_turn_lifecycle3242–3288 ↗
async fn side_parent_status_tracks_parent_turn_lifecycle() -> Result<()>

Purpose: Verifies side-thread status notices track whether the parent turn finished, restarted, or failed.

Data flow: Parent turn completion, start, and failure notifications are queued, and side state changes between finished, none, and failed.

Call relations: It uses turn notification helpers to test side-parent status updates.

Call graph: calls 5 internal fn (new, new, make_test_app, turn_completed_notification, turn_started_notification); 1 external calls (assert_eq!).

side_parent_status_prioritizes_input_over_approval3291–3364 ↗
async fn side_parent_status_prioritizes_input_over_approval() -> Result<()>

Purpose: Checks that when the parent needs both approval and input, the side status shows input as more important.

Data flow: An approval request is queued, then an input request, then each is resolved; the parent status moves from approval to input, back to approval, then clear.

Call relations: It exercises side-parent status updates for server requests and their resolution notifications.

Call graph: calls 5 internal fn (new, new, exec_approval_request, make_test_app, request_user_input_request); 3 external calls (Integer, ServerRequestResolved, assert_eq!).

side_thread_snapshot_hides_forked_parent_transcript3367–3396 ↗
async fn side_thread_snapshot_hides_forked_parent_transcript()

Purpose: Ensures a side thread snapshot does not replay the parent transcript it was forked from.

Data flow: A side session with a parent turn is installed into an event store, and the stored session has no fork marker or parent turns.

Call relations: It tests the static snapshot installer used for side threads.

Call graph: calls 4 internal fn (new, test_thread_session, test_turn, new); 3 external calls (assert_eq!, install_side_thread_snapshot, vec!).

side_thread_snapshot_does_not_refresh_from_fork_history3399–3421 ↗
async fn side_thread_snapshot_does_not_refresh_from_fork_history()

Purpose: Checks that side-thread snapshots are not refreshed from fork history.

Data flow: A side thread is registered, a snapshot with no rollout path is examined, and the app decides not to refresh it.

Call relations: It protects side conversations from pulling in parent history during replay.

Call graph: calls 4 internal fn (new, new, make_test_app, test_thread_session); 2 external calls (new, assert!).

side_thread_snapshot_skips_session_header_preamble3424–3459 ↗
async fn side_thread_snapshot_skips_session_header_preamble()

Purpose: Ensures replaying a side-thread snapshot does not insert the usual session header preamble.

Data flow: A side snapshot is replayed, emitted history cells are collected, and no header or active transcript appears.

Call relations: It tests side-specific replay display behavior through the app event channel.

Call graph: calls 5 internal fn (new, new, lines_to_single_string, make_test_app_with_channels, test_thread_session); 2 external calls (new, assert_eq!).

primary_thread_ignores_child_mcp_startup_notifications3462–3542 ↗
async fn primary_thread_ignores_child_mcp_startup_notifications()

Purpose: Checks that MCP startup failures for a child thread do not render in the active primary thread.

Data flow: A child-thread MCP failure is handled, no primary UI event appears, the child buffer stores it, and replaying the child shows the warning once.

Call relations: It tests app-server event routing plus later child-thread replay.

Call graph: calls 4 internal fn (new, lines_to_single_string, make_test_app_with_channels, test_thread_session); 7 external calls (McpServerStatusUpdated, new, ServerNotification, assert!, assert_eq!, start_embedded_app_server_for_picker, from).

app_scoped_mcp_startup_notifications_do_not_render_in_active_thread3545–3573 ↗
async fn app_scoped_mcp_startup_notifications_do_not_render_in_active_thread()

Purpose: Ensures app-wide MCP startup notifications do not appear as active-thread transcript messages.

Data flow: An MCP status notification without a thread id is handled, and no history or active transcript output appears.

Call relations: It covers the app-scoped branch of MCP startup handling.

Call graph: calls 2 internal fn (new, make_test_app_with_channels); 5 external calls (McpServerStatusUpdated, ServerNotification, assert!, assert_eq!, start_embedded_app_server_for_picker).

active_side_thread_renders_live_mcp_startup_notifications3576–3660 ↗
async fn active_side_thread_renders_live_mcp_startup_notifications()

Purpose: Verifies an active side thread does render its own live MCP startup notifications.

Data flow: A side thread is activated, MCP starting and failed notifications for that side thread are handled, queued events are processed, and warning text is rendered once.

Call relations: It pairs with the primary-thread ignore test to prove thread-specific routing works.

Call graph: calls 5 internal fn (new, new, lines_to_single_string, make_test_app_with_channels, test_thread_session); 8 external calls (McpServerStatusUpdated, new, ServerNotification, assert!, assert_eq!, start_embedded_app_server_for_picker, matches!, from).

side_restore_user_message_puts_inline_question_back_in_composer3663–3673 ↗
async fn side_restore_user_message_puts_inline_question_back_in_composer()

Purpose: Checks that restoring a side user message places its text back in the composer.

Data flow: A user message goes into the restore function, and the composer text becomes that message.

Call relations: It directly tests side-conversation prompt restoration.

Call graph: calls 2 internal fn (make_test_app, from); 1 external calls (assert_eq!).

side_discard_selection_keeps_current_side_thread3676–3692 ↗
async fn side_discard_selection_keeps_current_side_thread()

Purpose: Checks which side thread should be discarded when switching selections.

Data flow: With a side thread active, selecting that same thread returns no discard target, while selecting the parent returns the side thread id.

Call relations: It tests the selection guard used around side-thread switching.

Call graph: calls 3 internal fn (new, new, make_test_app); 1 external calls (assert_eq!).

discard_side_thread_removes_agent_navigation_entry3695–3723 ↗
async fn discard_side_thread_removes_agent_navigation_entry() -> Result<()>

Purpose: Verifies discarding a live side thread removes its side state and agent navigation entry.

Data flow: An ephemeral server thread is started and registered as side state, discard succeeds, and local navigation/state entries disappear.

Call relations: It uses the embedded app server to test the successful discard path.

Call graph: calls 3 internal fn (new, new, make_test_app); 4 external calls (pin, assert!, assert_eq!, start_embedded_app_server_for_picker).

discard_side_thread_keeps_local_state_when_server_close_fails3726–3759 ↗
async fn discard_side_thread_keeps_local_state_when_server_close_fails() -> Result<()>

Purpose: Ensures local side-thread state is kept if the server cannot close that thread.

Data flow: A fake side thread is registered without a real server thread, discard fails, and active id, side state, and navigation remain.

Call relations: It tests the failure branch of side discard.

Call graph: calls 3 internal fn (new, new, make_test_app); 4 external calls (pin, assert!, assert_eq!, start_embedded_app_server_for_picker).

discard_closed_side_thread_removes_local_state_without_server_rpc3762–3784 ↗
async fn discard_closed_side_thread_removes_local_state_without_server_rpc()

Purpose: Checks that already-closed side threads can be removed locally without a server call.

Data flow: Local side state, channel, and navigation are seeded; discard-closed runs and removes all local records.

Call relations: It covers cleanup for replay-only or closed side threads.

Call graph: calls 4 internal fn (new, new, make_test_app, new); 2 external calls (assert!, assert_eq!).

active_non_primary_shutdown_target_returns_none_for_non_shutdown_event3787–3799 ↗
async fn active_non_primary_shutdown_target_returns_none_for_non_shutdown_event() -> Result<()>

Purpose: Checks that non-shutdown notifications do not trigger a switch back to the primary thread.

Data flow: Active and primary thread ids are set differently, a non-shutdown notification is inspected, and no target is returned.

Call relations: It tests the shutdown-target helper’s filtering.

Call graph: calls 2 internal fn (new, make_test_app); 1 external calls (assert_eq!).

active_non_primary_shutdown_target_returns_none_for_primary_thread_shutdown3802–3814 ↗
async fn active_non_primary_shutdown_target_returns_none_for_primary_thread_shutdown() -> Result<()>

Purpose: Checks that shutting down the primary active thread does not produce a non-primary switch target.

Data flow: The active and primary ids are the same, a thread-closed notification is inspected, and no target is returned.

Call relations: It covers the primary-thread branch of shutdown-target logic.

Call graph: calls 2 internal fn (new, make_test_app); 1 external calls (assert_eq!).

active_non_primary_shutdown_target_returns_ids_for_non_primary_shutdown3817–3829 ↗
async fn active_non_primary_shutdown_target_returns_ids_for_non_primary_shutdown() -> Result<()>

Purpose: Verifies that closing an active non-primary thread returns both the closing thread and primary thread ids.

Data flow: Different active and primary ids are set, the active thread close notification is inspected, and the expected pair is returned.

Call relations: It tests the normal switch-back case after a side or agent thread closes.

Call graph: calls 2 internal fn (new, make_test_app); 1 external calls (assert_eq!).

active_non_primary_shutdown_target_returns_none_when_shutdown_exit_is_pending3832–3846 ↗
async fn active_non_primary_shutdown_target_returns_none_when_shutdown_exit_is_pending() -> Result<()>

Purpose: Ensures pending shutdown-exit suppresses automatic switching for that same thread.

Data flow: A pending shutdown exit id is set to the active thread, the close notification is inspected, and no target is returned.

Call relations: It protects explicit exit handling from being interrupted by thread-switch behavior.

Call graph: calls 2 internal fn (new, make_test_app); 1 external calls (assert_eq!).

active_non_primary_shutdown_target_still_switches_for_other_pending_exit_thread3849–3863 ↗
async fn active_non_primary_shutdown_target_still_switches_for_other_pending_exit_thread() -> Result<()>

Purpose: Checks that a pending shutdown for some other thread does not suppress switching for the active thread.

Data flow: The pending shutdown id differs from the active id, the active close notification is inspected, and the switch target is returned.

Call relations: It completes the shutdown-target edge cases.

Call graph: calls 2 internal fn (new, make_test_app); 1 external calls (assert_eq!).

render_clear_ui_header_after_long_transcript_for_snapshot3865–3979 ↗
async fn render_clear_ui_header_after_long_transcript_for_snapshot() -> String

Purpose: Builds a long fake transcript and renders the fresh header shown after clearing the UI.

Data flow: A test app with long user and agent cells is created, clear-header lines are rendered to text, and assertions ensure old notices and transcript text are absent.

Call relations: Two snapshot tests call this helper so both clear paths compare against the same expected header.

Call graph: calls 1 internal fn (make_test_app); called by 2 (clear_ui_after_long_transcript_snapshots_fresh_header_only, ctrl_l_clear_ui_after_long_transcript_reuses_clear_header_snapshot); 2 external calls (assert!, vec!).

clear_ui_after_long_transcript_snapshots_fresh_header_only3986–3989 ↗
async fn clear_ui_after_long_transcript_snapshots_fresh_header_only()

Purpose: Snapshots the header shown after clearing a long transcript.

Data flow: The shared clear-header renderer produces text, and the snapshot assertion compares it to the saved output.

Call relations: It depends on render_clear_ui_header_after_long_transcript_for_snapshot for setup.

Call graph: calls 1 internal fn (render_clear_ui_header_after_long_transcript_for_snapshot); 1 external calls (assert_app_snapshot!).

ctrl_l_clear_ui_after_long_transcript_reuses_clear_header_snapshot3996–3999 ↗
async fn ctrl_l_clear_ui_after_long_transcript_reuses_clear_header_snapshot()

Purpose: Ensures the Ctrl+L clear path uses the same fresh-header rendering as the general clear path.

Data flow: The shared renderer produces text and the same snapshot name is checked.

Call relations: It reuses the clear-header helper to keep both user actions aligned.

Call graph: calls 1 internal fn (render_clear_ui_header_after_long_transcript_for_snapshot); 1 external calls (assert_app_snapshot!).

clear_ui_header_shows_fast_status_for_fast_capable_models4006–4034 ↗
async fn clear_ui_header_shows_fast_status_for_fast_capable_models()

Purpose: Checks that the clear header shows fast-mode status when the selected model and account support it.

Data flow: A model, effort, service tier, auth state, and model catalog are configured, then header text is snapshot-tested.

Call relations: It uses chat-widget test helpers for fast-mode catalog and authentication state.

Call graph: calls 1 internal fn (make_test_app); 3 external calls (assert_app_snapshot!, set_chatgpt_auth, set_fast_mode_test_catalog).

make_test_app4036–4094 ↗
make_test_app_with_channels4096–4162 ↗
async fn make_test_app_with_channels() -> (
    App,
    tokio::sync::mpsc::UnboundedReceiver<AppEvent>,
    tokio::sync::mpsc::UnboundedReceiver<Op>,
)

Purpose: Creates a test App and also returns receivers for app events and outgoing operations.

Data flow: It builds the same app as make_test_app, but keeps the event and operation receivers so tests can inspect what the app emits.

Call relations: Tests that need to assert submitted operations or inserted history cells use this helper.

Call graph: calls 8 internal fn (default, without_managed_config_for_tests, default_for_tests, new, get_model_offline_for_tests, test_session_telemetry, new, defaults); called by 52 (active_side_thread_renders_live_mcp_startup_notifications, app_scoped_mcp_startup_notifications_do_not_render_in_active_thread, apply_permission_profile_selection_preserves_loader_overrides, backtrack_remote_image_only_selection_clears_existing_composer_draft, backtrack_resubmit_preserves_data_image_urls_in_user_turn, backtrack_selection_with_duplicate_history_targets_unique_turn, cancelled_turn_edit_restores_prompt_and_rolls_back_latest_turn, capped_resize_reflow_renders_recent_suffix_only, enqueue_primary_thread_session_replays_buffered_approval_after_attach, enqueue_primary_thread_session_replays_turns_before_initial_prompt_submit (+15 more)); 13 external calls (new, new, new, new, new, default, make_chatwidget_manual_with_sender, default, default, default (+3 more)).

set_thread_goal_draft_materializes_long_objective_and_confirms_before_paste4165–4366 ↗
async fn set_thread_goal_draft_materializes_long_objective_and_confirms_before_paste() -> Result<()>

Purpose: Tests the thread-goal editor for long objectives, pasted text, stale paste placeholders, whitespace paste, and image attachments.

Data flow: A live thread is started, several goal drafts are applied, and server goal state plus attachment files are checked after each case.

Call relations: It exercises goal-file helpers through the app-server-backed set_thread_goal_draft flow.

Call graph: calls 2 internal fn (from_app_server, make_test_app); 9 external calls (default, assert!, assert_eq!, start_embedded_app_server_for_picker, format!, read_dir, write, tempdir, vec!).

replace_goal_confirmation_snapshot4369–4382 ↗
async fn replace_goal_confirmation_snapshot()

Purpose: Snapshots the confirmation popup shown when replacing an existing thread goal.

Data flow: The confirmation UI is shown with a new goal draft, the bottom popup is rendered, and the snapshot is checked.

Call relations: It validates the visible prompt produced before goal replacement.

Call graph: calls 2 internal fn (new, make_test_app); 2 external calls (default, assert_app_snapshot!).

test_thread_session4384–4407 ↗
fn test_thread_session(thread_id: ThreadId, cwd: PathBuf) -> ThreadSessionState

Purpose: Builds a standard fake thread session for tests.

Data flow: A thread id and working directory go in; a session state with default model, permissions, and metadata comes out.

Call relations: Many replay, picker, side-thread, and feedback tests use this to avoid repeating session setup.

Call graph: calls 1 internal fn (read_only); called by 32 (active_side_thread_renders_live_mcp_startup_notifications, active_turn_id_for_thread_uses_snapshot_turns, enqueue_primary_thread_session_replays_buffered_approval_after_attach, enqueue_primary_thread_session_replays_turns_before_initial_prompt_submit, feedback_submission_for_inactive_thread_replays_into_origin_thread, inactive_thread_approval_badge_clears_after_turn_completion_notification, inactive_thread_approval_bubbles_into_active_view, inactive_thread_settings_notification_updates_cached_collaboration_mode, inactive_thread_started_notification_initializes_replay_session, inactive_thread_started_notification_preserves_primary_model_when_path_missing (+15 more)); 3 external calls (abs, new, new).

plain_line_cell4409–4411 ↗
fn plain_line_cell(text: impl Into<String>) -> Arc<dyn HistoryCell>

Purpose: Creates a simple transcript history cell containing one line of plain text.

Data flow: Text goes in and a boxed history cell comes out.

Call relations: Resize reflow tests use it to build predictable transcripts.

Call graph: calls 1 internal fn (new); 2 external calls (new, vec!).

rendered_line_text4413–4419 ↗
fn rendered_line_text(line: &crate::terminal_hyperlinks::HyperlinkLine) -> String

Purpose: Extracts plain text from a rendered terminal hyperlink line.

Data flow: A rendered line with spans goes in, span contents are joined, and a plain string comes out.

Call relations: Transcript reflow tests use it to compare rendered lines without styling details.

capped_resize_reflow_renders_recent_suffix_only4422–4446 ↗
async fn capped_resize_reflow_renders_recent_suffix_only()

Purpose: Checks that resize reflow respects a row cap by rendering only the recent transcript tail.

Data flow: Twenty simple cells are rendered with a five-row limit, and only the expected last rows appear.

Call relations: It uses plain_line_cell and rendered_line_text to inspect reflow output.

Call graph: calls 1 internal fn (make_test_app_with_channels); 2 external calls (assert_eq!, Limit).

uncapped_resize_reflow_renders_all_cells_when_row_cap_absent4449–4461 ↗
async fn uncapped_resize_reflow_renders_all_cells_when_row_cap_absent()

Purpose: Ensures disabling the resize row cap renders the full transcript.

Data flow: Twenty cells are rendered with the cap disabled, and the first and last rendered lines are checked.

Call relations: It covers the opposite branch of the capped reflow test.

Call graph: calls 1 internal fn (make_test_app_with_channels); 1 external calls (assert_eq!).

resize_reflow_wraps_transcript_early_when_pet_is_enabled4464–4487 ↗
async fn resize_reflow_wraps_transcript_early_when_pet_is_enabled()

Purpose: Checks that enabling the terminal pet reduces available text width and causes earlier wrapping.

Data flow: A markdown cell is rendered before and after installing a test pet, and the pet version produces more wrapped lines.

Call relations: It tests the interaction between decorative pet UI and transcript reflow.

Call graph: calls 1 internal fn (make_test_app_with_channels); 3 external calls (assert!, Supported, vec!).

uncapped_resize_reflow_renders_all_cells_under_row_limit4490–4513 ↗
async fn uncapped_resize_reflow_renders_all_cells_under_row_limit()

Purpose: Verifies that when content fits under the row cap, all cells are rendered.

Data flow: Three simple cells are rendered with a large limit, and all expected lines appear.

Call relations: It covers the non-truncating case of capped reflow.

Call graph: calls 1 internal fn (make_test_app_with_channels); 2 external calls (assert_eq!, Limit).

initial_replay_buffer_keeps_recent_rows_when_row_cap_present4516–4547 ↗
async fn initial_replay_buffer_keeps_recent_rows_when_row_cap_present()

Purpose: Checks that the initial replay buffer keeps only the newest rows when a row cap exists.

Data flow: Five lines are buffered with a three-row limit, and only lines two through four remain.

Call relations: It directly tests the app’s replay-buffer trimming helper.

Call graph: calls 1 internal fn (make_test_app_with_channels); 4 external calls (assert_eq!, buffer_initial_history_replay_display_lines, Limit, vec!).

thread_switch_replay_buffer_uses_transcript_tail_mode_when_row_cap_present4550–4562 ↗
async fn thread_switch_replay_buffer_uses_transcript_tail_mode_when_row_cap_present()

Purpose: Ensures thread-switch replay uses transcript-tail mode when row capping is enabled.

Data flow: Thread-switch replay buffering starts with a three-row cap, and the buffer is marked to render from transcript tail.

Call relations: It tests setup behavior before replaying a switched thread.

Call graph: calls 1 internal fn (make_test_app_with_channels); 2 external calls (assert!, Limit).

thread_switch_replay_buffer_is_disabled_without_row_cap4565–4572 ↗
async fn thread_switch_replay_buffer_is_disabled_without_row_cap()

Purpose: Checks that thread-switch replay buffering is not used when there is no row cap.

Data flow: Thread-switch replay buffering starts with the cap disabled, and no buffer is created.

Call relations: It pairs with the row-cap thread-switch buffer test.

Call graph: calls 1 internal fn (make_test_app_with_channels); 1 external calls (assert!).

height_shrink_schedules_resize_reflow4575–4591 ↗
async fn height_shrink_schedules_resize_reflow()

Purpose: Verifies that shrinking terminal height schedules transcript reflow.

Data flow: The app sees an unchanged draw size first, then a shorter one, and the second call marks reflow pending.

Call relations: It tests draw-size change handling with a dummy frame requester.

Call graph: calls 2 internal fn (make_test_app_with_channels, test_dummy); 1 external calls (assert!).

test_turn4593–4604 ↗
fn test_turn(turn_id: &str, status: TurnStatus, items: Vec<ThreadItem>) -> Turn

Purpose: Builds a fake app-server turn for tests.

Data flow: A turn id, status, and items go in; a turn object with default timing and error fields comes out.

Call relations: Turn notification helpers and side snapshot tests use this to create consistent turn data.

Call graph: called by 3 (side_thread_snapshot_hides_forked_parent_transcript, turn_completed_notification, turn_started_notification).

turn_started_notification4606–4614 ↗
fn turn_started_notification(thread_id: ThreadId, turn_id: &str) -> ServerNotification

Purpose: Creates a fake server notification saying a turn started.

Data flow: A thread id and turn id go in; a notification containing an in-progress turn comes out.

Call relations: Replay, picker, and side-parent lifecycle tests use it to simulate live server progress.

Call graph: calls 1 internal fn (test_turn); called by 9 (open_agent_picker_clears_completed_path_backed_agent_running_state, open_agent_picker_refreshes_replay_only_path_backed_liveness, replay_only_thread_keeps_restored_queue_visible, replay_thread_snapshot_does_not_submit_queue_before_replay_catches_up, replay_thread_snapshot_in_progress_turn_restores_running_queue_state, replay_thread_snapshot_keeps_queue_when_running_state_only_comes_from_snapshot, replayed_interrupted_turn_restores_queued_input_to_composer, replayed_turn_complete_submits_restored_queued_follow_up, side_parent_status_tracks_parent_turn_lifecycle); 3 external calls (TurnStarted, new, to_string).

turn_completed_notification4616–4629 ↗
fn turn_completed_notification(
    thread_id: ThreadId,
    turn_id: &str,
    status: TurnStatus,
) -> ServerNotification

Purpose: Creates a fake server notification saying a turn completed with a given status.

Data flow: A thread id, turn id, and final status go in; a completion notification with timing fields comes out.

Call relations: Queue replay, picker liveness, approval badge, and side lifecycle tests use it.

Call graph: calls 1 internal fn (test_turn); called by 4 (inactive_thread_approval_badge_clears_after_turn_completion_notification, open_agent_picker_clears_completed_path_backed_agent_running_state, replay_thread_snapshot_does_not_submit_queue_before_replay_catches_up, side_parent_status_tracks_parent_turn_lifecycle); 3 external calls (TurnCompleted, new, to_string).

thread_closed_notification4631–4635 ↗
fn thread_closed_notification(thread_id: ThreadId) -> ServerNotification

Purpose: Creates a fake server notification that a thread closed.

Data flow: A thread id goes in and a thread-closed notification comes out.

Call relations: Channel and shutdown-target tests use it to simulate thread shutdown.

Call graph: called by 1 (enqueue_thread_event_does_not_block_when_channel_full); 2 external calls (ThreadClosed, to_string).

token_usage_notification4637–4663 ↗
fn token_usage_notification(
    thread_id: ThreadId,
    turn_id: &str,
    model_context_window: Option<i64>,
) -> ServerNotification

Purpose: Creates a fake token-usage update notification.

Data flow: A thread id, turn id, and optional context-window size go in; a notification with token counts comes out.

Call relations: The status-line token usage test uses it to drive thread event handling.

Call graph: called by 1 (token_usage_update_refreshes_status_line_with_runtime_context_window); 2 external calls (ThreadTokenUsageUpdated, to_string).

agent_message_delta_notification4665–4677 ↗
fn agent_message_delta_notification(
    thread_id: ThreadId,
    turn_id: &str,
    item_id: &str,
    delta: &str,
) -> ServerNotification

Purpose: Creates a fake streaming agent-message update.

Data flow: A thread id, turn id, item id, and text delta go in; an agent-message delta notification comes out.

Call relations: Queue replay tests use it to make the chat widget think a turn is actively streaming.

Call graph: called by 6 (replay_only_thread_keeps_restored_queue_visible, replay_thread_snapshot_does_not_submit_queue_before_replay_catches_up, replay_thread_snapshot_in_progress_turn_restores_running_queue_state, replay_thread_snapshot_keeps_queue_when_running_state_only_comes_from_snapshot, replayed_interrupted_turn_restores_queued_input_to_composer, replayed_turn_complete_submits_restored_queued_follow_up); 2 external calls (AgentMessageDelta, to_string).

exec_approval_request4679–4704 ↗
fn exec_approval_request(
    thread_id: ThreadId,
    turn_id: &str,
    item_id: &str,
    approval_id: Option<&str>,
) -> ServerRequest

Purpose: Builds a standard fake command-execution approval request.

Data flow: Thread, turn, item, and optional approval ids go in; a server request asking approval for echo hello comes out.

Call relations: Approval buffering, inactive approval, side status, and badge tests reuse this helper.

Call graph: called by 10 (enqueue_primary_thread_session_replays_buffered_approval_after_attach, inactive_thread_approval_badge_clears_after_turn_completion_notification, inactive_thread_approval_bubbles_into_active_view, inactive_thread_exec_approval_preserves_context, inactive_thread_exec_approval_splits_shell_wrapped_command, refresh_pending_thread_approvals_only_lists_inactive_threads, resolved_buffered_approval_does_not_become_actionable_after_drain, side_defers_parent_approval_overlay_until_parent_replay, side_defers_subagent_approval_overlay_until_side_exits, side_parent_status_prioritizes_input_over_approval); 2 external calls (Integer, to_string).

request_user_input_request4706–4717 ↗
fn request_user_input_request(thread_id: ThreadId, turn_id: &str, item_id: &str) -> ServerRequest

Purpose: Builds a fake request asking the user for tool input.

Data flow: Thread, turn, and item ids go in; a tool-input server request comes out.

Call relations: The side-parent priority test uses it to compare input requests against approval requests.

Call graph: called by 1 (side_parent_status_prioritizes_input_over_approval); 3 external calls (Integer, new, to_string).

feedback_submission_without_thread_emits_error_history_cell4720–4739 ↗
async fn feedback_submission_without_thread_emits_error_history_cell()

Purpose: Checks that a feedback upload failure with no origin thread shows an error history cell.

Data flow: The app handles a failed feedback result, and the emitted history cell text is compared.

Call relations: It tests feedback result display through the app event channel.

Call graph: calls 1 internal fn (make_test_app_with_channels); 2 external calls (assert_eq!, panic!).

feedback_submission_for_inactive_thread_replays_into_origin_thread4742–4806 ↗
async fn feedback_submission_for_inactive_thread_replays_into_origin_thread()

Purpose: Ensures feedback results for an inactive thread are stored with that thread and appear when it is replayed.

Data flow: Origin and active threads are set up, feedback success is handled for the origin, no active UI event appears, then replaying origin shows the upload link.

Call relations: It tests thread-local feedback event buffering and replay.

Call graph: calls 5 internal fn (new, lines_to_single_string, make_test_app_with_channels, test_thread_session, new_with_session); 3 external calls (new, assert!, assert_matches!).

next_user_turn_op4808–4817 ↗
fn next_user_turn_op(op_rx: &mut tokio::sync::mpsc::UnboundedReceiver<Op>) -> Op

Purpose: Pulls the next user-turn operation from an operation receiver, ignoring unrelated operations.

Data flow: An operation receiver goes in; it drains available operations until it finds a user turn, returns it, or panics with what it saw.

Call relations: Queue and draft replay tests use this helper after simulating a submit.

Call graph: called by 4 (replay_thread_snapshot_does_not_submit_queue_before_replay_catches_up, replay_thread_snapshot_restores_collaboration_mode_for_draft_submit, replay_thread_snapshot_restores_pending_pastes_for_submit, replayed_turn_complete_submits_restored_queued_follow_up); 5 external calls (try_recv, new, format!, matches!, panic!).

lines_to_single_string4819–4830 ↗
fn lines_to_single_string(lines: &[Line<'_>]) -> String

Purpose: Turns rendered UI lines into plain text for assertions.

Data flow: A slice of styled lines goes in; span text is joined line by line into one newline-separated string.

Call relations: Many snapshot and rendering tests use it to ignore styling while checking visible text.

Call graph: called by 9 (active_side_thread_renders_live_mcp_startup_notifications, bypass_hook_trust_startup_warning_snapshot, enqueue_primary_thread_session_replays_turns_before_initial_prompt_submit, feedback_submission_for_inactive_thread_replays_into_origin_thread, inactive_thread_file_change_approval_recovers_buffered_changes, primary_thread_ignores_child_mcp_startup_notifications, replace_chat_widget_reseeds_collab_agent_metadata_for_replay, replay_snapshot_with_pending_request_suppresses_replay_notices, side_thread_snapshot_skips_session_header_preamble); 1 external calls (iter).

test_session_telemetry4832–4847 ↗
fn test_session_telemetry(config: &Config, model: &str) -> SessionTelemetry

Purpose: Creates fake telemetry metadata for a test session.

Data flow: A config and model name go in; offline model info is looked up and a session telemetry object comes out.

Call relations: make_test_app and make_test_app_with_channels use it while building test apps.

Call graph: calls 4 internal fn (construct_model_info_offline_for_tests, new, new, session_source_cli); called by 2 (make_test_app, make_test_app_with_channels); 1 external calls (to_models_manager_config).

active_turn_not_steerable_turn_error_extracts_structured_server_error4850–4871 ↗
fn active_turn_not_steerable_turn_error_extracts_structured_server_error()

Purpose: Checks that a structured server error for a non-steerable active turn can be extracted.

Data flow: A JSON-RPC error containing serialized turn-error data is built, and the extractor returns the original turn error.

Call relations: It tests error parsing used when steering an active turn fails.

Call graph: 2 external calls (assert_eq!, to_value).

session_start_error_surfaces_archived_guidance_without_rollout_path4874–4897 ↗
fn session_start_error_surfaces_archived_guidance_without_rollout_path()

Purpose: Verifies archived-session startup errors show clear unarchive guidance without leaking rollout-path details.

Data flow: Fake resume and fork errors are wrapped, passed through session_start_error, and compared with the expected user-facing message.

Call relations: It tests startup error cleanup for archived sessions.

Call graph: calls 1 internal fn (from_string); 4 external calls (assert_eq!, eyre!, format!, from).

active_turn_steer_race_detects_missing_active_turn4900–4915 ↗
fn active_turn_steer_race_detects_missing_active_turn()

Purpose: Checks that a steer request failing because there is no active turn is recognized as a race.

Data flow: A JSON-RPC error with the missing-active-turn message is parsed and returns the missing-race marker.

Call relations: It tests one branch of active-turn race detection.

Call graph: 1 external calls (assert_eq!).

active_turn_steer_race_extracts_actual_turn_id_from_mismatch4918–4934 ↗
fn active_turn_steer_race_extracts_actual_turn_id_from_mismatch()

Purpose: Checks that a steer race error extracts the actual active turn id from the server message.

Data flow: A mismatch error string is parsed, and the actual turn id is returned in the race result.

Call relations: It covers the mismatch branch of steer race detection.

Call graph: 1 external calls (assert_eq!).

active_turn_interrupt_race_extracts_actual_turn_id_from_mismatch4937–4951 ↗
fn active_turn_interrupt_race_extracts_actual_turn_id_from_mismatch()

Purpose: Checks that an interrupt race error extracts the actual active turn id.

Data flow: A mismatch error string from turn interrupt is parsed and returns the actual turn id.

Call relations: It tests the interrupt-specific race parser.

Call graph: 1 external calls (assert_eq!).

fresh_session_config_uses_current_service_tier4954–4972 ↗
async fn fresh_session_config_uses_current_service_tier()

Purpose: Ensures new session configs use the chat widget’s current service tier.

Data flow: The widget is set to Fast service tier, fresh session config is built, and the tier is present.

Call relations: It tests session-start config generation from runtime UI state.

Call graph: calls 1 internal fn (make_test_app); 1 external calls (assert_eq!).

backtrack_selection_with_duplicate_history_targets_unique_turn4975–5117 ↗
async fn backtrack_selection_with_duplicate_history_targets_unique_turn()

Purpose: Checks that backtrack selection targets the correct user turn even when history contains duplicated earlier turns.

Data flow: A transcript with duplicate sections and an edited later prompt is built, selection is confirmed, rollback is applied, and rollback count plus restored attachments are checked.

Call relations: It exercises backtrack selection, composer restoration, and rollback operation emission.

Call graph: calls 4 internal fn (read_only, new, make_test_app_with_channels, user_count); 5 external calls (new, new, assert_eq!, format!, vec!).

backtrack_remote_image_only_selection_clears_existing_composer_draft5120–5151 ↗
async fn backtrack_remote_image_only_selection_clears_existing_composer_draft()

Purpose: Ensures backtracking to a message with only a remote image clears stale composer text.

Data flow: A stale draft is set, a remote-image-only backtrack selection is applied, and the composer is empty while the image remains.

Call relations: It tests a backtrack edge case around image-only prompts.

Call graph: calls 1 internal fn (make_test_app_with_channels); 4 external calls (new, new, assert_eq!, vec!).

cancelled_turn_edit_restores_prompt_and_rolls_back_latest_turn5154–5182 ↗
async fn cancelled_turn_edit_restores_prompt_and_rolls_back_latest_turn()

Purpose: Checks that canceling a turn edit restores the prompt and rolls back the latest turn.

Data flow: A prompt with a remote image is applied as a cancelled edit, composer and images are restored, and a one-turn rollback operation is emitted.

Call relations: It tests cancelled edit recovery for non-empty local history.

Call graph: calls 1 internal fn (make_test_app_with_channels); 5 external calls (new, assert_eq!, assert_matches!, assert_snapshot!, vec!).

first_cancelled_turn_edit_restores_prompt_without_local_history5185–5206 ↗
async fn first_cancelled_turn_edit_restores_prompt_without_local_history()

Purpose: Ensures cancelling the first turn edit works even when there is no transcript history.

Data flow: A prompt is restored into an empty-history app and a one-turn rollback operation is emitted.

Call relations: It covers the first-turn branch of cancelled edit recovery.

Call graph: calls 1 internal fn (make_test_app_with_channels); 4 external calls (new, assert_eq!, assert_matches!, vec!).

backtrack_resubmit_preserves_data_image_urls_in_user_turn5209–5274 ↗
async fn backtrack_resubmit_preserves_data_image_urls_in_user_turn()

Purpose: Verifies that resubmitting after backtrack preserves inline data-image URLs.

Data flow: A transcript user message with a data URL is backtracked, Enter submits it, and the outgoing user turn includes the image URL.

Call relations: It links backtrack restoration to normal chat-widget submission.

Call graph: calls 3 internal fn (read_only, new, make_test_app_with_channels); 5 external calls (new, new, new, assert!, vec!).

replay_thread_snapshot_replays_turn_history_in_order5277–5356 ↗
async fn replay_thread_snapshot_replays_turn_history_in_order()

Purpose: Checks that replaying stored turns inserts user messages in their original order.

Data flow: A snapshot with two completed turns is replayed, emitted history cells are collected, and user messages match the expected sequence.

Call relations: It tests snapshot turn replay using the shared session helper.

Call graph: calls 3 internal fn (new, make_test_app_with_channels, test_thread_session); 3 external calls (new, assert_eq!, vec!).

replace_chat_widget_reseeds_collab_agent_metadata_for_replay5359–5438 ↗
async fn replace_chat_widget_reseeds_collab_agent_metadata_for_replay()

Purpose: Ensures replacing the chat widget keeps collaboration agent names available during replay.

Data flow: Agent navigation metadata is seeded, a replacement widget is installed, a collab wait item is replayed, and rendered text still contains the agent label.

Call relations: It tests replace_chat_widget together with later snapshot replay.

Call graph: calls 4 internal fn (from_string, lines_to_single_string, make_test_app_with_channels, test_dummy); 4 external calls (new, assert!, new_with_app_event, vec!).

refreshed_snapshot_session_persists_resumed_turns5441–5502 ↗
async fn refreshed_snapshot_session_persists_resumed_turns()

Purpose: Checks that refreshing a snapshot with resumed server data updates both the snapshot and cached store.

Data flow: A cached session is replaced with a refreshed session and turns, and both the in-memory snapshot and store contain the new data.

Call relations: It tests the snapshot refresh path used before replaying resumed threads.

Call graph: calls 4 internal fn (new, make_test_app, test_thread_session, new_with_session); 3 external calls (new, assert_eq!, vec!).

queued_rollback_syncs_overlay_and_clears_deferred_history5505–5580 ↗
async fn queued_rollback_syncs_overlay_and_clears_deferred_history()

Purpose: Verifies a rollback on a non-pending thread updates transcript, overlay, deferred lines, and pending UI state together.

Data flow: A transcript, overlay, deferred line, and pending usage cell are seeded; rollback removes the latest turn and clears stale UI pieces.

Call relations: It exercises backtrack rollback cleanup across several app UI fields.

Call graph: calls 2 internal fn (make_test_app, new_transcript); 6 external calls (new, new, assert!, assert_eq!, panic!, vec!).

late_usage_result_can_follow_finalized_plan5583–5612 ↗
async fn late_usage_result_can_follow_finalized_plan()

Purpose: Checks that a late token-activity result can still be accepted after a streamed plan was finalized.

Data flow: A token activity refresh starts, a plan stream is consolidated, then the token result finishes and is available for insertion.

Call relations: It tests ordering between usage refresh output and plan stream consolidation.

Call graph: calls 1 internal fn (make_test_app_with_channels); 5 external calls (new, assert!, new_proposed_plan_stream, panic!, vec!).

thread_rollback_response_discards_queued_active_thread_events5615–5667 ↗
async fn thread_rollback_response_discards_queued_active_thread_events()

Purpose: Ensures stale active-thread events queued before a rollback response are discarded.

Data flow: A warning event is queued in the active receiver, rollback response is handled, and the receiver is empty afterward.

Call relations: It protects rollback replay from being polluted by old channel events.

Call graph: calls 2 internal fn (new, make_test_app); 6 external calls (ConfigWarning, new, new, assert!, channel, Notification).

new_session_requests_shutdown_for_previous_conversation5670–5716 ↗
async fn new_session_requests_shutdown_for_previous_conversation()

Purpose: Checks that shutting down the current conversation through the app server does not submit the old local shutdown operation.

Data flow: A thread session is installed, channels are drained, shutdown is requested, and no Op::Shutdown appears.

Call relations: It tests the new app-server shutdown path for starting a new session.

Call graph: calls 3 internal fn (read_only, new, make_test_app_with_channels); 5 external calls (pin, new, new, assert!, start_embedded_app_server_for_picker).

shutdown_first_exit_returns_immediate_exit_when_shutdown_submit_fails5719–5736 ↗
async fn shutdown_first_exit_returns_immediate_exit_when_shutdown_submit_fails()

Purpose: Ensures shutdown-first exit falls back to immediate exit if shutdown submission cannot proceed.

Data flow: An active thread id is set without a real server thread, exit handling runs, and it returns user-requested exit with no pending shutdown id.

Call relations: It tests failure handling in exit-mode orchestration.

Call graph: calls 2 internal fn (new, make_test_app); 4 external calls (pin, assert!, assert_eq!, start_embedded_app_server_for_picker).

shutdown_first_exit_uses_app_server_shutdown_without_submitting_op5739–5760 ↗
async fn shutdown_first_exit_uses_app_server_shutdown_without_submitting_op()

Purpose: Verifies shutdown-first exit uses the app server and does not emit a local shutdown operation.

Data flow: Exit handling runs with an active thread, returns immediate exit in the test setup, and the operation channel stays empty.

Call relations: It complements the shutdown submission failure test with channel inspection.

Call graph: calls 2 internal fn (new, make_test_app_with_channels); 4 external calls (pin, assert!, assert_eq!, start_embedded_app_server_for_picker).

interrupt_without_active_turn_is_treated_as_handled5763–5792 ↗
async fn interrupt_without_active_turn_is_treated_as_handled()

Purpose: Checks that interrupting when no turn is active is considered successfully handled.

Data flow: A real thread is started, an interrupt operation is submitted through the app server, and the result is handled.

Call relations: It tests app-server operation submission for a harmless interrupt race.

Call graph: calls 1 internal fn (make_test_app); 4 external calls (pin, assert_eq!, interrupt, start_embedded_app_server_for_picker).

override_turn_context_sends_thread_settings_update5795–5929 ↗
async fn override_turn_context_sends_thread_settings_update()

Purpose: Verifies a turn-context override sends a thread settings update to the server and later updates cached session state from the notification.

Data flow: A thread starts, an override operation with permissions, model, service tier, collaboration mode, and personality is submitted, the server notification is checked, then handled by the app.

Call relations: It uses next_thread_settings_updated to wait for the app-server notification.

Call graph: calls 3 internal fn (new, make_test_app, next_thread_settings_updated); 6 external calls (pin, ThreadSettingsUpdated, ServerNotification, assert_eq!, override_turn_context, start_embedded_app_server_for_picker).

thread_setting_update_params_sync_model_and_default_reasoning5932–5980 ↗
async fn thread_setting_update_params_sync_model_and_default_reasoning()

Purpose: Checks that model and reasoning-effort changes produce thread-settings update parameters that also sync collaboration mode.

Data flow: The active thread and widget settings are changed, update params are requested, and model, effort, and collaboration settings are inspected.

Call relations: It directly tests parameter creation for active-thread settings updates.

Call graph: calls 2 internal fn (new, make_test_app); 1 external calls (assert_eq!).

inactive_thread_settings_notification_updates_cached_collaboration_mode5983–6081 ↗
async fn inactive_thread_settings_notification_updates_cached_collaboration_mode()

Purpose: Ensures settings notifications for inactive threads update cached collaboration mode and personality without overwriting the session model.

Data flow: An inactive thread session is cached, a settings update notification is queued, cached state is inspected, then applied to the widget and checked.

Call relations: It tests inactive-thread settings caching and later widget restoration.

Call graph: calls 6 internal fn (read_only, new, make_test_app, test_absolute_path, test_thread_session, new_with_session); 3 external calls (ThreadSettingsUpdated, new, assert_eq!).

clear_only_ui_reset_preserves_chat_session_state6084–6141 ↗
async fn clear_only_ui_reset_preserves_chat_session_state()

Purpose: Checks that clearing only the UI removes transcript and overlays but keeps the active chat session and draft.

Data flow: Session, draft, transcript, overlay, deferred lines, and backtrack state are seeded; reset runs and only UI display state is cleared.

Call relations: It protects Ctrl+L-style clearing from losing conversation state.

Call graph: calls 5 internal fn (read_only, new, make_test_app, defaults, new_transcript); 5 external calls (new, new, assert!, assert_eq!, vec!).

clear_only_ui_reset_allows_active_skill_warning_to_render_again6144–6169 ↗
async fn clear_only_ui_reset_allows_active_skill_warning_to_render_again()

Purpose: Ensures clearing the UI also resets remembered skill warnings so active errors can be shown again.

Data flow: A skill error is recorded once, suppressed the second time, UI reset runs, and the same error is considered new again.

Call relations: It tests clear-state interaction with skill warning deduplication.

Call graph: calls 1 internal fn (make_test_app); 1 external calls (assert_eq!).

backtrack_esc_does_not_steal_empty_vim_insert_escape6172–6195 ↗
async fn backtrack_esc_does_not_steal_empty_vim_insert_escape()

Purpose: Checks that backtrack Escape handling does not interfere with Vim insert-mode Escape.

Data flow: The test toggles Vim mode, enters insert mode, checks Escape handling priority, sends Escape, and verifies backtrack remains unprimed.

Call relations: It tests keyboard dispatch between backtrack and Vim editing modes.

Call graph: calls 1 internal fn (make_test_app); 3 external calls (assert!, Char, new).

side_conversations_reject_backtrack_esc_without_stealing_vim_insert_escape6198–6218 ↗
async fn side_conversations_reject_backtrack_esc_without_stealing_vim_insert_escape()

Purpose: Ensures side conversations reject backtrack Escape, but still let Vim insert-mode Escape work.

Data flow: Side mode is activated, Escape handling decisions are checked before and after entering Vim insert mode.

Call relations: It tests keyboard priority for side conversations.

Call graph: calls 1 internal fn (make_test_app); 3 external calls (assert!, Char, new).

side_backtrack_rejection_reports_unavailable_message_snapshot6221–6242 ↗
async fn side_backtrack_rejection_reports_unavailable_message_snapshot()

Purpose: Snapshots the message shown when backtrack is rejected in a side conversation.

Data flow: Backtrack is marked primed, rejection runs, the emitted history cell is rendered, and the snapshot is checked.

Call relations: It tests the user-facing feedback path for side backtrack rejection.

Call graph: calls 1 internal fn (make_test_app_with_channels); 3 external calls (assert!, assert_app_snapshot!, panic!).

start_config_write_test_app_server6243–6245 ↗
async fn start_config_write_test_app_server(app: &App) -> Result<AppServerSession>

Purpose: Starts an embedded app server for tests that need to write configuration.

Data flow: A test app goes in; an app-server session configured from the app’s config comes out.

Call relations: Guardian feature-flag tests call this helper before exercising config writes.

Call graph: called by 4 (update_feature_flags_disabling_guardian_clears_manual_review_policy_without_history, update_feature_flags_disabling_guardian_clears_review_policy_and_restores_default, update_feature_flags_enabling_guardian_overrides_explicit_manual_review_policy, update_feature_flags_enabling_guardian_selects_auto_review); 2 external calls (pin, start_embedded_app_server_for_picker).

tui/src/app/tests/model_catalog.rssource ↗
testtest run

This is a test file for the app’s model catalog behavior. The model catalog is the app’s list of available AI models, including which ones should appear in the picker, which ones are deprecated, and which ones have upgrade messages. These tests check two user-facing flows. First, they verify the “new user experience” tooltip, often shortened to NUX, which is a small startup message telling the user that a model is available. The tests make sure only eligible models are picked, models that have already shown their message too many times are skipped, and the show count is saved to disk so the app remembers it next time. Second, they verify model migration prompts. A migration prompt is like a helpful notice saying, “You are using an older model; would you like to move to this newer one?” The tests confirm that prompts appear only for the right old models, do not appear after the user has dismissed them, ignore missing or hidden upgrade targets, and still work when the current old model is hidden from the picker. One test also checks that accepting a migration updates the selected model, updates the reasoning effort setting, and sends the right app events so the rest of the interface and configuration can catch up.

Function details13
all_model_presets8–10 ↗
fn all_model_presets() -> Vec<ModelPreset>

Purpose: Provides a fresh copy of the shared test model list. Tests use it as their starting point so they can safely edit model visibility, upgrade data, or tooltip data without changing the original fixture.

Data flow: It reads the project’s test model preset fixture, clones it, and returns the clone. The result is a list of model presets that each test can freely modify.

Call relations: This helper is called by most of the tests that need a realistic model catalog. It acts like a clean sample shelf of models that each test can rearrange before asking the production selection or migration logic what it would do.

Call graph: called by 7 (model_migration_prompt_shows_for_hidden_model, model_migration_prompt_skips_when_target_missing_or_hidden, prepare_startup_tooltip_override_persists_model_availability_nux_count, select_model_availability_nux_picks_only_eligible_model, select_model_availability_nux_returns_none_when_all_models_are_exhausted, select_model_availability_nux_skips_missing_and_exhausted_models, select_model_availability_nux_uses_existing_model_order_as_priority).

model_availability_nux_config12–19 ↗
fn model_availability_nux_config(shown_count: &[(&str, u32)]) -> ModelAvailabilityNuxConfig

Purpose: Builds a small configuration object that records how many times each model’s availability tooltip has already been shown. Tests use it to simulate a user who has or has not already seen certain messages.

Data flow: It receives pairs of model name and show count, turns the model names into owned strings, and collects them into the configuration map. It returns a ModelAvailabilityNuxConfig ready to pass into the tooltip selection code.

Call relations: The NUX selection tests call this helper when they need to control the app’s memory of past tooltip displays. The helper feeds that simulated memory into the code under test so the tests can check whether exhausted models are skipped.

Call graph: called by 4 (select_model_availability_nux_picks_only_eligible_model, select_model_availability_nux_returns_none_when_all_models_are_exhausted, select_model_availability_nux_skips_missing_and_exhausted_models, select_model_availability_nux_uses_existing_model_order_as_priority).

model_migration_copy_to_plain_text21–38 ↗
fn model_migration_copy_to_plain_text(copy: &crate::model_migration::ModelMigrationCopy) -> String

Purpose: Turns rich migration prompt copy into plain text so a snapshot test can compare it easily. This avoids testing visual formatting details while still checking the words the user would read.

Data flow: It receives a ModelMigrationCopy value. If that value already has markdown text, it returns that text. Otherwise it builds a string by joining the heading spans, adding blank space, then appending each content line’s spans. The output is one plain string representing the prompt.

Call relations: The hidden-model migration prompt test uses this helper just before taking a snapshot. Internally it creates a new string when markdown is not present, then hands the simplified text to the snapshot assertion.

Call graph: 1 external calls (new).

model_migration_prompt_only_shows_for_deprecated_models41–61 ↗
async fn model_migration_prompt_only_shows_for_deprecated_models()

Purpose: Checks that the app only offers a migration prompt when the current model is actually meant to move to a newer target. This prevents users from being nagged when they are already on the right model.

Data flow: The test starts with an empty record of already-seen migrations. It asks the migration decision function about older models pointing to a newer model, then asks about a model pointing to itself. The expected outcome is true for deprecated upgrade cases and false for the self-target case.

Call relations: This async test sets up minimal state and then calls the migration prompt decision logic directly. Its assertions tell the larger test suite whether the basic “should we show this prompt?” rule is still working.

Call graph: 2 external calls (new, assert!).

select_model_availability_nux_picks_only_eligible_model64–86 ↗
fn select_model_availability_nux_picks_only_eligible_model()

Purpose: Checks that the startup availability tooltip is selected when exactly one model has a NUX message. This confirms the app can find the one model that should announce itself.

Data flow: The test gets the full model preset list, clears all availability messages, adds one message to the gpt-5.4 preset, and gives the selector an empty show-count config. It expects the selector to return a tooltip override containing that model slug and message.

Call relations: It uses all_model_presets to get realistic input and model_availability_nux_config to say no messages have been shown yet. Then it calls the selection logic and compares the result with the expected tooltip.

Call graph: calls 2 internal fn (all_model_presets, model_availability_nux_config); 1 external calls (assert_eq!).

select_model_availability_nux_skips_missing_and_exhausted_models89–121 ↗
fn select_model_availability_nux_skips_missing_and_exhausted_models()

Purpose: Checks that a model whose tooltip has already been shown the maximum number of times is skipped in favor of another eligible model. This keeps users from seeing the same availability notice forever.

Data flow: The test clears all messages, gives two models availability messages, and marks one model as already shown up to the maximum count. It then asks the selector for a tooltip. The expected output is the other model’s message.

Call relations: It builds its test catalog with all_model_presets and builds the simulated show-count memory with model_availability_nux_config. The selected result is then compared against the tooltip for the still-eligible model.

Call graph: calls 2 internal fn (all_model_presets, model_availability_nux_config); 1 external calls (assert_eq!).

select_model_availability_nux_uses_existing_model_order_as_priority124–153 ↗
fn select_model_availability_nux_uses_existing_model_order_as_priority()

Purpose: Checks that when more than one model could show an availability tooltip, the app uses the existing model order as its priority. This makes prompt choice predictable instead of depending on incidental setup order inside the test.

Data flow: The test clears all messages, assigns messages to two models, and passes an empty show-count config. It expects the selector to choose the model that comes first according to the catalog’s built-in ordering, returning that model’s slug and message.

Call relations: It relies on all_model_presets for the catalog order and model_availability_nux_config for a clean display history. It then exercises the selector and verifies that priority follows the catalog order.

Call graph: calls 2 internal fn (all_model_presets, model_availability_nux_config); 1 external calls (assert_eq!).

select_model_availability_nux_returns_none_when_all_models_are_exhausted156–175 ↗
fn select_model_availability_nux_returns_none_when_all_models_are_exhausted()

Purpose: Checks that no startup availability tooltip is shown when every available message has already reached its allowed display count. This protects the app from showing stale repeated announcements.

Data flow: The test creates a catalog with one model availability message and a config saying that model has already been shown the maximum number of times. It asks the selector for a tooltip and expects no result.

Call relations: It uses all_model_presets to create the model list and model_availability_nux_config to simulate an exhausted message. The selection logic should hand back nothing, which the test confirms.

Call graph: calls 2 internal fn (all_model_presets, model_availability_nux_config); 1 external calls (assert_eq!).

prepare_startup_tooltip_override_persists_model_availability_nux_count178–215 ↗
async fn prepare_startup_tooltip_override_persists_model_availability_nux_count()

Purpose: Checks the full startup tooltip preparation path, including saving the updated display count to configuration storage. This matters because the app must remember that it already showed a NUX message across restarts.

Data flow: The test creates a temporary Codex home folder, builds a config from it, prepares a catalog with one availability message, and runs the startup tooltip preparation function. It expects the tooltip text to be returned, the in-memory show count to become 1, and a freshly reloaded config from the same folder to also contain that count.

Call relations: This test uses all_model_presets for model data and the config builder for temporary real configuration storage. It exercises the higher-level startup helper rather than only the selector, then reloads configuration to prove the change was persisted.

Call graph: calls 1 internal fn (all_model_presets); 2 external calls (assert_eq!, default).

accepted_model_migration_persists_target_default_reasoning_effort218–270 ↗
async fn accepted_model_migration_persists_target_default_reasoning_effort()

Purpose: Checks what happens after a user accepts a model migration. It verifies that the chosen target model and its default reasoning effort are stored and that the rest of the app is notified through events.

Data flow: The test creates a temporary config with an old model and a previous reasoning effort, then creates an unbounded channel, which is a message pipe with no fixed queue limit for this test. It applies an accepted migration from gpt-5.2 to gpt-5.4 with Medium reasoning effort. Afterward, the config should contain the new model and effort, and the receiving side of the channel should contain the expected acknowledgement, model update, effort update, and persistence events.

Call relations: This test creates an AppEventSender around the channel and passes it into the migration-acceptance function. The function under test changes the config and sends events; the test then reads those events back from the channel to confirm each handoff happened.

Call graph: calls 1 internal fn (new); 4 external calls (assert_eq!, assert_matches!, default, unbounded_channel).

model_migration_prompt_respects_hide_flag_and_self_target273–288 ↗
async fn model_migration_prompt_respects_hide_flag_and_self_target()

Purpose: Checks that a migration prompt is not shown when the user has already hidden or acknowledged that migration, and also not shown when the source and target are the same model. This prevents repeated or pointless prompts.

Data flow: The test creates a map saying the migration from gpt-5.2 to gpt-5.4 has already been seen. It asks the prompt decision function about that same migration and about a model targeting itself. Both checks should return false.

Call relations: This test supplies the seen-migration record directly to the migration decision logic. Its assertions cover two early-stop cases that should block the larger migration prompt flow.

Call graph: 2 external calls (new, assert!).

model_migration_prompt_skips_when_target_missing_or_hidden291–331 ↗
async fn model_migration_prompt_skips_when_target_missing_or_hidden()

Purpose: Checks that the app does not show a migration prompt when the upgrade target cannot actually be selected. This avoids inviting the user to move to a model that is missing from the catalog or hidden from the picker.

Data flow: First, the test edits a current model so its upgrade points to a missing target, then verifies that the prompt decision is false and that no target preset can be found. Next, it hides the normal target model from the picker and again verifies that the prompt is blocked and the target lookup returns none.

Call relations: It starts from all_model_presets, mutates the catalog into two bad states, and then calls the migration decision and target lookup logic. The test confirms those helpers agree that there is no valid target to offer.

Call graph: calls 1 internal fn (all_model_presets); 1 external calls (assert!).

model_migration_prompt_shows_for_hidden_model334–389 ↗
async fn model_migration_prompt_shows_for_hidden_model()

Purpose: Checks a subtle case: the current old model may be hidden from the model picker, but the app should still be able to show its migration prompt if the upgrade target is visible. This lets users on an old hidden model move forward cleanly.

Data flow: The test creates a temporary config, gets the model presets, hides the current gpt-5.3-codex model, and ensures its upgrade target is visible. It verifies that the migration prompt is eligible, finds the target preset, builds the migration copy using the current and target model details, converts that copy to plain text, and compares it to a stored snapshot.

Call relations: It uses all_model_presets to create the catalog, calls the migration decision and target lookup logic, then passes the resulting model details into the copy-building logic. Finally, model_migration_copy_to_plain_text prepares the output for the snapshot assertion so wording changes are caught by the test suite.

Call graph: calls 1 internal fn (all_model_presets); 3 external calls (assert!, assert_snapshot!, default).

tui/src/app/tests/session_summary.rssource ↗
testtest run

These tests protect the behavior of session_summary, the code that decides what to show when a chat session ends. The summary is useful only if there is something meaningful to say, such as token usage or a safe way to resume the conversation later. Without these tests, the app could annoy users with empty summaries, or worse, suggest a resume command before the conversation has actually been saved.

The file checks four everyday cases. First, if there is no token usage and no saved conversation information, no summary should appear. Second, even if there is a conversation ID, the resume hint is still hidden until the rollout file exists. A rollout file is the saved record of the session; it is like a receipt proving there is something to resume. Third, once token usage exists and the rollout file has been written, the summary includes both a readable token count and a direct codex resume ... command. Fourth, if the conversation also has a human-friendly name, the resume hint tells the user to resume and pick that named item instead of only showing the raw ID.

The tests use temporary folders so they can safely create or omit rollout files without touching real user data.

Function details4
session_summary_skips_when_no_usage_or_resume_hint5–15 ↗
async fn session_summary_skips_when_no_usage_or_resume_hint()

Purpose: This test proves that the app does not show an empty session summary. If there are no tokens to report and no saved conversation to resume, the correct result is no summary at all.

Data flow: It starts with default token usage, meaning all counts are zero, and passes no thread ID, no thread name, and no rollout file path into session_summary. The function under test returns either a summary or nothing; the test expects nothing. If a summary appears, the assertion fails.

Call relations: During the test run, the test calls session_summary for the most minimal end-of-session case. It then uses an assertion to make sure the result is absent, confirming that later user-facing code would have nothing extra to display.

Call graph: 1 external calls (assert!).

session_summary_skips_resume_hint_until_rollout_exists18–33 ↗
async fn session_summary_skips_resume_hint_until_rollout_exists()

Purpose: This test checks that the app does not offer a resume command before the saved session file exists. That prevents the interface from giving users a command that cannot work yet.

Data flow: It creates zero token usage, builds a thread ID from a string, and chooses a rollout file path inside a temporary directory without actually creating the file. It passes those values into session_summary. Because the rollout file is missing, the expected output is still no summary.

Call relations: The test sets up a conversation that has an ID but has not been persisted to disk. It relies on thread ID parsing and default token usage setup, then asks session_summary what it would show. The final assertion confirms that no resume hint is handed back until the file system proves the session was saved.

Call graph: calls 1 internal fn (from_string); 2 external calls (assert!, default).

session_summary_includes_resume_hint_for_persisted_rollout36–63 ↗
async fn session_summary_includes_resume_hint_for_persisted_rollout()

Purpose: This test proves that a saved session with token usage produces a useful summary. The summary should include both the token counts and a command the user can run to resume the conversation.

Data flow: It creates token usage with 10 input tokens, 2 output tokens, and 12 total tokens. It parses a thread ID, creates a temporary rollout file, writes a small line into that file, and calls session_summary with the usage, thread ID, and path. The result should be a summary whose usage line reports the counts and whose resume hint is codex resume followed by the thread ID.

Call relations: This test represents the normal successful shutdown path after a conversation has been saved. It writes the rollout file first so session_summary can safely produce a resume hint, then uses equality checks to verify the exact user-facing text that would be displayed.

Call graph: calls 1 internal fn (from_string); 3 external calls (default, assert_eq!, write).

session_summary_names_picker_item_when_thread_has_name66–92 ↗
async fn session_summary_names_picker_item_when_thread_has_name()

Purpose: This test checks the friendlier resume message used when a saved conversation has a name. Instead of only telling the user to resume by raw ID, the summary should mention the named picker item they can select.

Data flow: It creates nonzero token usage, parses a thread ID, creates and writes a temporary rollout file, and passes a thread name of my-session into session_summary. The returned summary should contain a resume hint that says to run codex resume and then select my-session, with the thread ID shown in parentheses.

Call relations: This test covers the path where the app has enough information to give a more human-friendly resume instruction. After setting up a persisted rollout, it calls session_summary and checks the exact hint text, making sure the named-session flow stays clear for users.

Call graph: calls 1 internal fn (from_string); 3 external calls (default, assert_eq!, write).

tui/src/app/tests/startup.rssource ↗
testtest run, covering startup and resume behavior

This is a test file for the TUI, meaning the text-based user interface. Its focus is the fragile period when the app first opens and decides which conversation session, or “thread,” it should show. Startup has several paths: start fresh, exit, resume an old session, or fork from an old session. The app must treat these differently. For example, a brand-new session has to wait until the server creates a real thread before thread events can be processed, but a resume already has a known thread and should not be blocked the same way.

The tests also check what happens to text the user types before startup finishes. That input should be safely queued, like putting a letter in an outbox, then submitted once the session is ready. If starting the fresh thread fails, the app should return a clear error instead of sitting half-configured.

The last group of tests checks routing state. The app keeps local channels and navigation entries for different threads. If a stale startup result arrives for a thread that is no longer the active one, those leftovers should be removed. The file also verifies that resuming the thread already on screen is treated as a no-op with a friendly message, while reattaching an inactive displayed thread is still allowed.

Function details9
startup_waiting_gate_is_only_for_fresh_or_exit_session_selection8–35 ↗
fn startup_waiting_gate_is_only_for_fresh_or_exit_session_selection()

Purpose: This test checks which startup choices make the app wait before processing the initial session. Starting fresh and exiting require the waiting gate, while resuming or forking an existing session should not.

Data flow: It creates several session-selection examples: fresh start, exit, resume, and fork. Each one is passed into the app’s startup-wait decision helper. The expected result is compared with the actual result, proving that only fresh or exit selections turn the wait flag on.

Call relations: This test exercises the small decision point that later startup code relies on before allowing thread events through. It does not drive the full app; it verifies the rule that other startup paths depend on.

Call graph: 1 external calls (assert_eq!).

startup_paused_goal_prompt_gate_is_only_for_quiet_resume38–71 ↗
fn startup_paused_goal_prompt_gate_is_only_for_quiet_resume()

Purpose: This test checks when the app should ask the user for a goal after resuming a paused session. It should only prompt during a plain resume with no initial text and no images attached.

Data flow: It builds resume and fork session targets, then tries combinations of optional startup text and optional image paths. The app’s prompt-decision helper receives those inputs and returns true or false. The test confirms that only a quiet resume, with no message and no images, asks for a paused goal.

Call relations: This protects the startup flow from showing an unnecessary prompt when the user has already supplied a request or when the action is not a normal resume. It checks the decision used before the chat view continues after startup.

Call graph: calls 1 internal fn (new); 6 external calls (from, new, assert!, Fork, Resume, vec!).

startup_waiting_gate_holds_active_thread_events_until_primary_thread_configured74–106 ↗
fn startup_waiting_gate_holds_active_thread_events_until_primary_thread_configured()

Purpose: This test verifies that, during a fresh start, active thread events are held back until the app knows its primary thread. This prevents events from being routed before the main conversation is ready.

Data flow: It starts with the wait flag turned on for a fresh session and asks whether active thread events should be handled. The answer is false. It then checks that the app should not stop waiting when there is no primary thread, but should stop when a primary thread id appears. After the wait flag is cleared, active thread events are allowed.

Call relations: This test covers the gate between startup setup and normal event processing. It links the wait decision, the stop-waiting decision, and the event-handling decision into one expected sequence.

Call graph: calls 1 internal fn (new); 3 external calls (assert_eq!, should_stop_waiting_for_initial_session, should_wait_for_initial_session).

startup_waiting_gate_not_applied_for_resume_or_fork_session_selection109–136 ↗
fn startup_waiting_gate_not_applied_for_resume_or_fork_session_selection()

Purpose: This test confirms that resumed and forked sessions do not use the fresh-start waiting gate. Those paths already point at an existing thread target, so event processing should not be blocked in the same way.

Data flow: It creates resume and fork selections, asks whether each should wait for an initial session, and then asks whether active thread events should be handled. In both cases, the wait value allows event handling to continue.

Call relations: This test complements the fresh-start gate tests by checking the opposite paths. It protects resume and fork startup from accidentally being slowed or frozen by logic meant only for brand-new sessions.

Call graph: calls 1 internal fn (new); 5 external calls (from, assert_eq!, should_wait_for_initial_session, Fork, Resume).

startup_thread_started_submits_queued_startup_input139–180 ↗
async fn startup_thread_started_submits_queued_startup_input()

Purpose: This asynchronous test checks that text typed before the startup thread is ready is not lost. Once the server reports that the startup thread exists, the queued message should be submitted as the first user turn.

Data flow: It creates a test app with communication channels, marks startup as pending, tells the chat widget to queue submissions, inserts text as if the user typed it, and simulates pressing Enter. The text first appears in the chat widget’s queue. Then a test app server is started, a new thread-started result is delivered, and the test reads the outgoing operation channel. The result should be a user-turn operation containing the queued text.

Call relations: This test drives the realistic handoff from early user input to server-backed session startup. It checks that handle_startup_thread_started drains the chat widget’s queued message into the normal operation stream after the thread is attached.

Call graph: calls 1 internal fn (new); 6 external calls (pin, new, new, assert_eq!, start_embedded_app_server_for_picker, panic!).

startup_thread_start_failure_returns_error183–203 ↗
async fn startup_thread_start_failure_returns_error()

Purpose: This asynchronous test checks that a failed fresh-session start produces a clear error and leaves the app in a safe state. The app should not remain stuck thinking startup is still pending.

Data flow: It creates a test app, marks startup as pending, starts a test embedded server, and then calls the startup-thread completion path with an error string instead of a successful thread. The result should be an error message that includes the server failure. The app’s pending flag is cleared and no primary thread is set.

Call relations: This test covers the failure branch of the same startup-thread handler used by successful startup. It ensures that callers get a real error back instead of continuing with a half-created chat session.

Call graph: 4 external calls (pin, assert!, assert_eq!, start_embedded_app_server_for_picker).

stale_startup_thread_started_removes_local_routing_state206–251 ↗
fn stale_startup_thread_started_removes_local_routing_state() -> Result<()>

Purpose: This test verifies that if an outdated startup-thread result arrives for a thread that is no longer the active primary thread, the app removes local routing data for that stale thread. This avoids sending future events to the wrong place.

Data flow: It builds a test runtime, creates an app and server, assigns one thread as the primary active thread, and separately inserts local channel and navigation state for another stale thread. Then it delivers a startup-thread-started result for the stale thread. Afterward, the stale thread’s channel and navigation entry are gone, while the active thread remains the original primary thread.

Call relations: This test exercises cleanup inside the startup-thread completion path. It matters when timing is awkward: a late result for an old thread should not disturb the currently active conversation.

Call graph: calls 2 internal fn (new, new); 5 external calls (new, assert!, assert_eq!, start_embedded_app_server_for_picker, new_multi_thread).

ignore_same_thread_resume_reports_noop_for_current_thread254–281 ↗
async fn ignore_same_thread_resume_reports_noop_for_current_thread()

Purpose: This asynchronous test checks that trying to resume the exact thread already being viewed is ignored and reported politely. The user should get an informational message rather than causing a duplicate reattach.

Data flow: It creates a test app with event channels, creates a thread session, loads it into the chat widget, registers the matching thread channel, and makes it active. After clearing old app events, it asks the app whether the resume target should be ignored. The answer is true, and the app emits a history cell saying the user is already viewing that project.

Call relations: This test focuses on the resume shortcut that runs before doing heavier resume work. It confirms that the app detects the current active thread and sends a small user-facing message through the app event stream.

Call graph: calls 2 internal fn (new, new_with_session); 3 external calls (new, assert!, panic!).

ignore_same_thread_resume_allows_reattaching_displayed_inactive_thread284–297 ↗
async fn ignore_same_thread_resume_allows_reattaching_displayed_inactive_thread()

Purpose: This asynchronous test checks that the app does not ignore every resume target that happens to be displayed. If the thread is shown in the chat widget but is not the active routed thread, reattaching should still be allowed.

Data flow: It creates a test app, creates a thread session, and loads that session into the chat widget without registering and activating the matching thread channel. It then asks whether resuming that target should be ignored. The result is false, and no informational transcript cell is added.

Call relations: This test covers the boundary case for the same-thread resume check. It ensures the no-op behavior is reserved for the truly current active thread, while inactive displayed sessions can still go through the normal reattach path.

Call graph: calls 1 internal fn (new); 1 external calls (assert!).

tui/src/app/agent_status_feed_tests.rssource ↗
testtest run

This test file protects a small but important part of the terminal user interface: the /agent status feed. That feed gives the user a quick preview of what sub-agents are doing, like a dashboard showing recent activity from helper workers.

The tests build a fake thread event history, add completed items to it, turn that history into an AgentStatusThreadPreview, and render it through AgentStatusHistoryCell. Then they compare the rendered text against a saved snapshot. A snapshot is a known-good text result, used here like a photograph of what the UI should look like.

The first test checks that command activity is summarized safely. It creates a command whose captured output is intentionally enormous, then verifies that the UI shows only the command line and the later agent message, not the full output. Without this, the status feed could become slow, unreadable, or memory-heavy.

The second test checks privacy and clarity for reasoning items. It confirms that only reasoning summaries are displayed, while raw reasoning content is not shown. This matters because raw reasoning may be internal detail that should not appear in the user-facing status feed.

Function details2
agent_status_uses_bounded_buffered_activity8–61 ↗
fn agent_status_uses_bounded_buffered_activity()

Purpose: This test verifies that the agent status display does not include unlimited command output. It should show the command that ran and a concise agent message, but not flood the UI with the command's captured output.

Data flow: The test starts with an empty ThreadEventStore, which is a bounded record of recent thread events. It adds a completed command event containing a very large aggregated_output, then adds a completed agent message. It converts the store into a preview, renders that preview into display lines, joins those lines into plain text, and checks the final text against the expected snapshot. The final assertion confirms that the huge output text never appears.

Call relations: During the test run, the Rust test runner calls this function. Inside it, the test creates the event store with ThreadEventStore::new, records completed notifications, builds the user-facing preview with AgentStatusThreadPreview::from_store, wraps it in AgentStatusHistoryCell::new, and asks the cell to render its lines. The snapshot assertion checks the intended UI text, while the explicit assertion guards against accidentally showing the oversized command output.

Call graph: calls 4 internal fn (new, from_store, new, try_from); 5 external calls (ItemCompleted, new, assert!, assert_snapshot!, vec!).

agent_status_uses_reasoning_summaries_only64–109 ↗
fn agent_status_uses_reasoning_summaries_only()

Purpose: This test verifies that the agent status display shows only safe reasoning summaries, not raw reasoning content. It protects the UI from exposing internal reasoning text when a shorter summary is available, and from showing raw-only reasoning when no summary exists.

Data flow: The test creates an empty ThreadEventStore and adds two completed reasoning items. One has both a summary and raw content; the other has only raw content. The store is turned into an agent preview, rendered as display text, and compared with a snapshot that contains only the safe summary. The final assertions confirm that neither piece of raw reasoning text appears in the rendered output.

Call relations: The Rust test runner calls this function as part of the test suite. The function follows the same path the real UI uses: events go into ThreadEventStore, AgentStatusThreadPreview::from_store extracts what should be shown, and AgentStatusHistoryCell::new prepares it for rendering. The snapshot checks the visible result, and the explicit assertions make the privacy rule clear: summaries may be shown, raw reasoning must not be.

Call graph: calls 3 internal fn (new, from_store, new); 5 external calls (ItemCompleted, new, assert!, assert_snapshot!, vec!).

tui/src/app/history_ui_tests.rssource ↗
testtest run

This file protects a small but visible part of the terminal user interface: the history entries shown when a desktop thread is opened, or when opening it fails. In a text interface, even small wording or spacing changes can confuse users or make the screen harder to read. These tests act like taking a photograph of the expected output and comparing future runs against that photograph.

Each test builds a history cell, which is one item in the app’s history list. One test builds a normal informational message for a successfully opened desktop thread. The other builds an error message for a failed launch. Both then pass the cell through the same rendering helper, so the test compares the final text exactly as a user would see it.

The render_cell helper asks the history cell for its display lines at a fixed width of 80 characters, turns each line into plain text, and joins them with newline characters. This keeps the snapshot stable and easy to review. If the UI output changes, the snapshot test will fail, prompting a developer to decide whether the change was intentional or a bug.

Function details3
desktop_thread_opened_history_snapshot6–13 ↗
fn desktop_thread_opened_history_snapshot()

Purpose: This test verifies the displayed history entry for the normal “desktop thread opened” message. It helps catch accidental changes to the wording, spacing, or formatting of that success message.

Data flow: It starts with the standard desktop-thread-opened text and creates an informational history cell from it. That cell is rendered into a plain multiline string, and the string is compared against the saved snapshot named desktop_thread_opened_history. Nothing is returned; the test either passes or reports a mismatch.

Call relations: During the test run, this function creates its test data by calling new_info_event. It then relies on the snapshot assertion to compare the rendered result with the stored expected output.

Call graph: 2 external calls (new_info_event, assert_snapshot!).

desktop_thread_open_error_history_snapshot16–20 ↗
fn desktop_thread_open_error_history_snapshot()

Purpose: This test verifies the displayed history entry for an error that happens while opening a desktop thread. It makes sure the failure message remains readable and formatted as expected.

Data flow: It starts with the sample failure detail launch failed, turns that into the app’s desktop-thread-open-error message, and wraps it in an error history cell. The cell is rendered into plain text and compared with the saved snapshot named desktop_thread_open_error_history. The test changes no application state; it only succeeds or fails based on the comparison.

Call relations: During the test run, this function builds the error cell by calling new_error_event. It then hands the rendered text to the snapshot assertion so any unexpected UI change is caught.

Call graph: 2 external calls (new_error_event, assert_snapshot!).

render_cell22–29 ↗
fn render_cell(cell: &impl HistoryCell) -> String

Purpose: This helper turns a history cell into the exact multiline text used by the snapshot tests. It keeps the tests focused on what the user would actually see.

Data flow: It receives a history cell as input. It asks the cell for its display lines at a fixed width of 80 characters, converts each line to a string, and joins those strings with newline characters. The output is one plain String containing the rendered cell.

Call relations: The snapshot tests use this helper before comparing output. Internally, it calls the cell’s display_lines method, which supplies the formatted lines that represent the cell on screen.

Call graph: 1 external calls (display_lines).

tui/src/config_update_tests.rssource ↗
testtest run

This is a test file for configuration-edit helpers used by the text user interface, or TUI (the terminal-based interface). The helpers being tested turn human actions into precise configuration paths, like writing an address on an envelope so the update reaches exactly the right setting.

The first test makes sure an app ID containing a dot, such as "plugin.linear", is quoted before being placed into a configuration path. That matters because dots usually mean “go one level deeper” in many configuration formats. Without the quotes, the system might read the app ID as two nested keys instead of one app name.

The second test checks that marking a project as trusted creates a configuration edit aimed at that project’s trust level, with the value set to "trusted" and using replacement rather than merging.

The third test checks error wording. If the server rejects a configuration change, the TUI wraps that error with extra context. This test makes sure the original validation message is still visible, so users and developers can see the real reason the change failed.

Function details3
app_scoped_key_path_quotes_dotted_app_ids7–12 ↗
fn app_scoped_key_path_quotes_dotted_app_ids()

Purpose: This test confirms that app IDs containing dots are treated as one app name, not as nested configuration sections. It protects configuration updates for plugins or apps whose identifiers include periods.

Data flow: It starts with the app ID "plugin.linear" and the setting name "enabled". It asks the configuration helper to build the key path, then compares the result with the expected string apps."plugin.linear".enabled. Nothing is changed outside the test; the output is simply pass or fail.

Call relations: During the test run, this function calls the external assert_eq! comparison macro. The story is: build the path, compare it to the known-correct path, and fail the test if quoting was lost.

Call graph: 1 external calls (assert_eq!).

trusted_project_edit_targets_project_trust_level15–24 ↗
fn trusted_project_edit_targets_project_trust_level()

Purpose: This test confirms that the helper for trusting a project creates the exact configuration edit needed to mark that project as trusted. It matters because a wrong key path could change the wrong project or the wrong setting.

Data flow: It starts with the project path /workspace/team.project. It passes that path into the helper, receives a ConfigEdit, and compares it to the expected edit: the project path is quoted inside the configuration key, the target field is trust_level, the value is trusted, and the update replaces the old value. The test only checks the returned data; it does not write any configuration.

Call relations: When the test suite runs, this function calls the external assert_eq! macro to compare the produced edit with the expected one. It verifies the helper’s output before any real configuration update code would rely on it.

Call graph: 1 external calls (assert_eq!).

format_config_error_preserves_server_validation_message27–40 ↗
fn format_config_error_preserves_server_validation_message()

Purpose: This test makes sure a formatted configuration error keeps the server’s original validation message. That is important because the server often explains exactly why a setting was rejected.

Data flow: It creates an example error saying that a batch configuration write failed because features.fast_mode=true violates managed requirements. It then wraps that error with extra TUI context, formats it, and compares the final message with the expected full text. The result is a pass or fail showing whether the useful underlying error was preserved.

Call relations: During the test run, this function uses the external eyre! macro to create the sample error and assert_eq! to check the final formatted text. It exercises the error-formatting path that would be used after a real failed configuration write.

Call graph: 2 external calls (assert_eq!, eyre!).

tui/src/external_agent_config_migration_flow_tests.rssource ↗
testtest run

This is a small test file for the terminal user interface. Its job is to make sure the text shown to users during an external agent configuration migration stays consistent. A migration is the process of moving or importing older configuration into the newer format the app expects.

The test gathers several possible messages: success messages for different numbers of migrated items, plus fixed messages for cases like migration finished, no items found, remote service unavailable, daemon unavailable, and an import already being in progress. It joins all of these messages into one block of text.

Then it uses a snapshot test. A snapshot test is like taking a photo of expected output and checking later runs against that photo. If someone changes the wording, punctuation, or formatting, the test will fail until the saved snapshot is deliberately updated. This matters because these strings are what users read when something important is happening. Without this test, a small wording change could slip in unnoticed and make the migration flow confusing or inconsistent.

Function details1
external_agent_config_migration_messages_snapshot4–21 ↗
fn external_agent_config_migration_messages_snapshot()

Purpose: This test checks that all migration-related user messages match the approved saved version. It is used to catch accidental changes to text that appears in the terminal interface.

Data flow: It starts with three sample item counts: 0, 1, and 2. It turns those counts into success messages, adds several fixed migration status or error messages, joins everything into one text block, and sends that block to the snapshot checker. The output is not returned to the app; instead, the test either passes because the text matches the stored snapshot or fails because it changed.

Call relations: During the test run, this function is called by the Rust test framework. It relies on the migration message constants and helper function imported from the parent module, then hands the final combined text to assert_snapshot!, which compares it with the stored expected output.

Call graph: 1 external calls (assert_snapshot!).

tui/src/local_chatgpt_auth.rssource ↗
testtest execution

This file exists to protect a narrow but important path: using a locally saved ChatGPT login during tests. The main function, load_local_chatgpt_auth, reads Codex auth data from a given Codex home folder, rejects anything that is not a ChatGPT login, extracts the access token and workspace account ID, and optionally checks that the workspace is one of the allowed workspaces. Without these checks, tests could accidentally accept the wrong kind of credential, such as an API key, or silently use a token for the wrong ChatGPT workspace.

The file is marked test-only, so it is compiled only when running tests. Most of the rest of the file builds fake login data and verifies the important cases. The tests create temporary Codex home folders, write pretend ChatGPT auth records into them, and then ask load_local_chatgpt_auth to read them back. A small helper creates fake JWTs, which are token-shaped strings containing account and plan information. Another helper writes a complete fake ChatGPT login to disk.

The important behavior is that managed local auth wins over external ephemeral tokens, missing auth is reported clearly, API key auth is rejected, and ChatGPT plan names are preserved in the exact lowercase wire format expected by the rest of the system.

Function details8
load_local_chatgpt_auth17–59 ↗
fn load_local_chatgpt_auth(
    codex_home: &Path,
    auth_credentials_store_mode: AuthCredentialsStoreMode,
    forced_chatgpt_workspace_id: Option<&[String]>,
) -> Result<LocalChatgptAuth, String>

Purpose: This function loads a saved local ChatGPT login and turns it into a small, easy-to-use LocalChatgptAuth value. It also guards against common mistakes: no auth file, API-key auth instead of ChatGPT auth, missing token data, missing workspace ID, or a workspace that is not allowed.

Data flow: It receives a Codex home folder path, a setting that says where credentials are stored, and an optional list of allowed ChatGPT workspace IDs. It reads the saved auth data, checks that it represents a ChatGPT login, pulls out the access token, workspace account ID, and plan type, lowercases the plan type, and returns those fields together. If anything is missing or invalid, it returns a plain error message instead of auth data.

Call relations: The test cases call this function as the thing being verified. It relies on the login library’s auth-loading routine to read the saved auth file or credential store, then performs its own ChatGPT-specific checks before handing back a simplified auth object to the caller.

Call graph: calls 1 internal fn (default); called by 5 (loads_local_chatgpt_auth_from_managed_auth, prefers_managed_auth_over_external_ephemeral_tokens, preserves_usage_based_plan_type_wire_name, rejects_api_key_auth, rejects_missing_local_auth); 3 external calls (load_auth_dot_json, format!, matches!).

tests::fake_jwt77–100 ↗
fn fake_jwt(email: &str, account_id: &str, plan_type: &str) -> String

Purpose: This helper creates a fake JWT, which is a three-part token string often used to carry login claims. Here it is only used in tests, so the token is shaped like a real one but is not meant to be secure.

Data flow: It receives an email address, a ChatGPT account ID, and a plan type. It builds a small JSON header and payload, base64-encodes them, adds a fake signature, and returns one token-shaped string containing the supplied account and plan information.

Call relations: Other test helpers and tests call this when they need realistic-looking ChatGPT tokens. It feeds token strings into tests::write_chatgpt_auth and into the external token-login helper used by the managed-auth preference test.

Call graph: 3 external calls (format!, json!, to_vec).

tests::write_chatgpt_auth102–127 ↗
fn write_chatgpt_auth(codex_home: &Path, plan_type: &str)

Purpose: This helper writes a complete fake ChatGPT login into a temporary Codex home folder. Tests use it to set up the local auth state that load_local_chatgpt_auth should later read.

Data flow: It receives a Codex home folder path and a plan type. It creates fake ID and access tokens, parses the ID token into claim data, builds an auth record with workspace workspace-1, and saves that record using file-based credential storage. Its output is the changed test folder, now containing saved ChatGPT auth.

Call relations: Several tests call this before calling load_local_chatgpt_auth. It sits between tests::fake_jwt, which supplies token strings, and the auth-saving library call, which writes the finished fake login to disk.

Call graph: calls 2 internal fn (default, parse_chatgpt_jwt_claims); 3 external calls (now, save_auth, fake_jwt).

tests::loads_local_chatgpt_auth_from_managed_auth130–144 ↗
fn loads_local_chatgpt_auth_from_managed_auth()

Purpose: This test proves that a normal saved ChatGPT login can be read successfully. It checks that the workspace ID, plan type, and access token come back as expected.

Data flow: It creates a temporary Codex home folder, writes fake ChatGPT auth for workspace-1, then calls load_local_chatgpt_auth while allowing that workspace. It expects a successful result and checks that the returned account ID is workspace-1, the plan is business, and the access token is not empty.

Call relations: This is the basic happy-path caller of load_local_chatgpt_auth. It uses tests::write_chatgpt_auth to prepare the saved auth, then verifies that the main loader returns the simplified auth data.

Call graph: calls 1 internal fn (load_local_chatgpt_auth); 4 external calls (new, assert!, assert_eq!, write_chatgpt_auth).

tests::rejects_missing_local_auth147–158 ↗
fn rejects_missing_local_auth()

Purpose: This test proves that the loader gives a clear failure when there is no saved local auth. That matters because silently continuing without credentials would make later failures harder to understand.

Data flow: It creates an empty temporary Codex home folder and calls load_local_chatgpt_auth without any allowed-workspace restriction. Because no auth has been saved, it expects an error and checks that the message says no local auth available.

Call relations: This test calls load_local_chatgpt_auth directly in the missing-auth case. It verifies one of the loader’s early failure paths.

Call graph: calls 1 internal fn (load_local_chatgpt_auth); 2 external calls (new, assert_eq!).

tests::rejects_api_key_auth161–187 ↗
fn rejects_api_key_auth()

Purpose: This test proves that API-key credentials are not accepted as a ChatGPT login. The two auth styles are different, and this loader specifically needs ChatGPT token data with a workspace identity.

Data flow: It creates a temporary Codex home folder, saves an auth record marked as API-key auth, then calls load_local_chatgpt_auth. It expects the call to fail and checks that the error says the local auth is not a ChatGPT login.

Call relations: This test prepares auth data using the external save routine, then calls load_local_chatgpt_auth to confirm that the loader rejects the wrong credential type before trying to use token fields.

Call graph: calls 2 internal fn (default, load_local_chatgpt_auth); 3 external calls (new, assert_eq!, save_auth).

tests::prefers_managed_auth_over_external_ephemeral_tokens190–210 ↗
fn prefers_managed_auth_over_external_ephemeral_tokens()

Purpose: This test proves that the locally managed saved ChatGPT auth is the one used, even if separate external temporary tokens also exist. This prevents an outside token source from unexpectedly changing which workspace the test uses.

Data flow: It creates a temporary Codex home folder, writes managed ChatGPT auth for workspace-1, then saves external ephemeral token data for workspace-2. It calls load_local_chatgpt_auth while allowing both workspaces, and checks that the returned account and plan still come from workspace-1.

Call relations: This test uses tests::write_chatgpt_auth for the managed login, tests::fake_jwt plus the login helper for the external token, and then calls load_local_chatgpt_auth to verify the loader’s choice.

Call graph: calls 1 internal fn (load_local_chatgpt_auth); 5 external calls (new, assert_eq!, login_with_chatgpt_auth_tokens, fake_jwt, write_chatgpt_auth).

tests::preserves_usage_based_plan_type_wire_name213–228 ↗
fn preserves_usage_based_plan_type_wire_name()

Purpose: This test makes sure a specific ChatGPT plan name is preserved exactly as the system expects to send or compare it. In particular, the usage-based business plan string must not be renamed or simplified.

Data flow: It creates a temporary Codex home folder, writes fake ChatGPT auth whose plan type is self_serve_business_usage_based, then calls load_local_chatgpt_auth. It expects the returned plan type to match that same string.

Call relations: This test uses tests::write_chatgpt_auth to create the saved login and then calls load_local_chatgpt_auth to check the plan-type extraction and normalization behavior.

Call graph: calls 1 internal fn (load_local_chatgpt_auth); 3 external calls (new, assert_eq!, write_chatgpt_auth).

tui/src/updates_cache_tests.rssource ↗
testtest run

This is a small safety test for the app’s update-notification memory. The TUI needs a place to remember things like “we checked for updates” and “the user dismissed version 999.0.0.” Without this behavior, dismissing an update on a fresh install could fail because there is no cache file yet, or the app might keep showing the same update again.

The test creates a temporary Codex home folder, which is like giving the app a clean, empty house to work in. It then builds a configuration that points at that folder and asks the update-cache code where the version cache file should live. Next, it calls the dismiss function for a fake version number. The important part is that no cache file has been prepared beforehand.

After dismissal, the test reads the newly written version information back from disk. It confirms two things: the cache file was created successfully, and its contents say that version 999.0.0 is both the latest known version and the dismissed version. It also checks that the “last checked” time is left at the Unix epoch, a standard zero-like timestamp, meaning this action did not pretend that an update check happened.

Function details1
dismiss_version_creates_cache_file_when_missing7–29 ↗
async fn dismiss_version_creates_cache_file_when_missing()

Purpose: This test proves that dismissing an update version creates the update cache file if it is missing. It protects the fresh-install case, where the app has no saved update information yet.

Data flow: It starts with an empty temporary folder and builds a config that uses that folder as the app home. It asks for the expected version-cache path, dismisses version 999.0.0, then reads the cache file back. The expected result is a cache record whose dismissed version and latest version are both 999.0.0, while the last-checked time remains the Unix epoch.

Call relations: During the test, it uses a temporary directory helper to isolate the filesystem work, a default config builder to make a realistic configuration, and assertion helpers to compare the saved cache data with the expected values. It exercises the real update-cache functions indirectly as a user action would: dismiss first, then read the stored result.

Call graph: 3 external calls (assert_eq!, default, tempdir).

tui/src/bottom_pane/custom_prompt_view_tests.rssource ↗
testtest run

This is a test file for CustomPromptView, a text prompt shown in the terminal user interface. The important behavior under test is subtle: when someone pastes multi-line text, the terminal sends the characters very quickly, including Enter between lines. The prompt should treat that fast Enter as part of the pasted text, not as the user deliberately pressing Enter to submit. Without these tests, a pasted goal like x\nrest could be submitted too early as just x.

The tests create a prompt with a fake submit callback. That callback sends submitted text through a simple channel, which is like a small mailbox the test can check later. Each test then feeds the prompt key events at specific simulated times. Very fast key events stand in for a paste burst; a later Enter stands in for a real human confirmation.

The file checks three cases: short first lines followed by a pasted newline, a pasted newline after pressing Tab, and a normal delayed Enter after typing. Together they define the intended rule: fast Enter during a paste should keep building the text, while a delayed Enter should submit the finished prompt.

Function details5
paste_burst_newline_does_not_submit_short_first_line6–35 ↗
fn paste_burst_newline_does_not_submit_short_first_line()

Purpose: This test makes sure a very quick newline after a short first line is treated as part of pasted multi-line text, not as a submit action. It covers short first lines such as x, id, and foo because those are easy cases to accidentally submit too early.

Data flow: The test starts with a fresh prompt and a receiver that records submitted text. It sends characters from a first line, then an Enter almost immediately, then more characters for a second line. At that point, it expects nothing to have been submitted and the prompt to still be open. It then sends a later Enter, and expects the full two-line text to come out through the receiver and the prompt to be marked complete.

Call relations: This test calls custom_prompt_view to build the prompt and submission mailbox, and uses elapsed to create controlled timestamps for each fake key press. It drives CustomPromptView directly by feeding it key events, then checks the receiver to prove whether the prompt submitted or kept editing.

Call graph: calls 2 internal fn (custom_prompt_view, elapsed); 5 external calls (now, Char, from, assert!, assert_eq!).

paste_burst_newline_after_tab_does_not_submit38–61 ↗
fn paste_burst_newline_after_tab_does_not_submit()

Purpose: This test checks that a fast Enter after a Tab is also treated as paste-related input rather than a submit command. It protects a case where Tab may affect the prompt text or cursor behavior before the pasted newline arrives.

Data flow: The test creates a new prompt and sends x, then Tab, then Enter, all only milliseconds apart. It then sends the rest of the pasted text. Before the final delayed Enter, the receiver should still be empty and the view should not be complete. After the delayed Enter, the receiver should contain the intended multi-line text and the view should be complete.

Call relations: Like the other paste tests, it relies on custom_prompt_view for a controlled prompt and elapsed for precise fake timing. It exercises the same key-event path as real terminal input would, then observes the submit callback indirectly through the receiver.

Call graph: calls 2 internal fn (custom_prompt_view, elapsed); 5 external calls (now, Char, from, assert!, assert_eq!).

delayed_enter_after_typing_submits64–75 ↗
fn delayed_enter_after_typing_submits()

Purpose: This test confirms the normal behavior: when a user types text and presses Enter after a noticeable pause, the prompt submits. It makes sure the paste protection does not stop ordinary single-line submission.

Data flow: The test creates a prompt, sends the characters f, o, and o with realistic gaps, then sends Enter later. The prompt should send foo through the receiver and mark itself complete.

Call relations: This is the balancing test for the paste-burst cases. It uses custom_prompt_view and elapsed in the same way, but with slower timing so the prompt should hand the entered text to its submit callback.

Call graph: calls 2 internal fn (custom_prompt_view, elapsed); 5 external calls (now, Char, from, assert!, assert_eq!).

custom_prompt_view77–89 ↗
fn custom_prompt_view() -> (CustomPromptView, Receiver<String>)

Purpose: This helper builds a test-ready CustomPromptView and a way to observe what it submits. It keeps the tests focused on typing behavior instead of repeating setup code.

Data flow: It creates a channel, which is a simple sender-and-receiver pair for passing text inside the test. It builds a prompt with a title, instructions, empty starting text, no context label, and a callback that sends submitted text into the channel. It returns the prompt and the receiving end of the channel.

Call relations: All three tests call this helper at the start. The helper hands them a fresh prompt to drive and a receiver they can check after simulated key presses to see whether submission happened.

Call graph: calls 1 internal fn (new); called by 3 (delayed_enter_after_typing_submits, paste_burst_newline_after_tab_does_not_submit, paste_burst_newline_does_not_submit_short_first_line); 3 external calls (new, new, channel).

elapsed91–93 ↗
fn elapsed(ms: usize) -> std::time::Duration

Purpose: This helper turns a number of milliseconds into a duration value. It makes the test timelines easy to read.

Data flow: It takes a millisecond count as input, converts it to the time-duration type used by Rust, and returns that duration. The tests add this duration to a starting instant to create precise event times.

Call relations: The timing-sensitive tests call this helper whenever they need to place a fake key press on the timeline. Those times are then passed into the prompt so it can decide whether input looks like a paste burst or a deliberate Enter press.

Call graph: called by 3 (delayed_enter_after_typing_submits, paste_burst_newline_after_tab_does_not_submit, paste_burst_newline_does_not_submit_short_first_line); 1 external calls (from_millis).

Chat widget interaction flows

These tests exercise the chat widget’s user-driven flows from submission and commands through approvals, review, side threads, and app-server event handling.

tui/src/chatwidget/tests/app_server.rssource ↗
testtest run

The chat widget is the terminal user interface piece that shows a conversation and lets the user type, approve, give feedback, and watch work in progress. In this file, tests pretend to be the app server and send the widget many kinds of notifications: a turn starting, an answer arriving, a command running, a warning, an error, a thread name update, or a collaborative agent being spawned. The tests then inspect what the widget sends back through its event channels and what it renders into chat history.

This matters because the app server is the source of truth for live conversation state. If the widget misunderstood those messages, users could see duplicate prompts, stale model settings, missing warnings, misleading “Working” indicators, or the wrong thread name. Several tests also protect small but important user-facing details, such as stripping a shell wrapper from a displayed command, showing a special cybersecurity notice instead of a raw server fallback message, and avoiding duplicate error history when a failed turn reports the same error twice.

Think of this file like a checklist for a receptionist relaying messages from a back office. Each test hands the receptionist a specific note and checks that the front desk display, follow-up action, or warning sign changes correctly.

Function details25
thread_settings_for_test4–36 ↗
fn thread_settings_for_test(
    model: &str,
    thread_id: ThreadId,
) -> codex_app_server_protocol::ThreadSettingsUpdatedNotification

Purpose: Builds a realistic “thread settings updated” server notification for tests. It lets tests focus on what should happen after settings change, without repeating a large settings object each time.

Data flow: It receives a model name and a thread identifier. It fills in a complete settings update with that thread id, the model, a read-only permission profile, approval behavior, reasoning effort, service tier, collaboration mode, and personality. It returns the finished notification object for a test to feed into the chat widget.

Call relations: The thread settings tests call this helper when they need to simulate the app server saying, “This thread’s settings have changed.” It uses the shared read-only permission profile builder so the generated settings match the real permission model.

Call graph: calls 1 internal fn (read_only); called by 2 (thread_settings_updated_preserves_default_settings_for_plan_mode, thread_settings_updated_updates_visible_state_without_transcript); 1 external calls (to_string).

configured_thread_session38–61 ↗
fn configured_thread_session(thread_id: ThreadId) -> crate::session_state::ThreadSessionState

Purpose: Creates a baseline thread session state for tests. This gives the chat widget an initial, known state before a server update is applied.

Data flow: It receives a thread identifier. It builds a session state with a model, provider, approval policy, read-only permissions, working directory, workspace roots, and empty optional fields such as history and collaboration mode. It returns that session state so a test can install it into the widget.

Call relations: The thread settings tests call this before sending update notifications. It prepares the widget with a visible thread, so later checks can prove that only matching thread updates affect the screen.

Call graph: calls 1 internal fn (read_only); called by 2 (thread_settings_updated_preserves_default_settings_for_plan_mode, thread_settings_updated_updates_visible_state_without_transcript); 2 external calls (new, vec!).

invalid_url_elicitation_is_declined64–98 ↗
async fn invalid_url_elicitation_is_declined()

Purpose: Checks that the widget refuses a URL-based elicitation request when the request belongs to a different thread than the one currently visible. An elicitation request is the server asking the user for some extra action or input.

Data flow: The test creates a chat widget, gives it one visible thread id, then sends an elicitation request for a different thread id. The widget turns that into a submitted thread operation that declines the request. The test reads the outgoing event and verifies the decline goes to the request’s thread and server name.

Call relations: The async test runner invokes this test. Inside the test, the widget’s elicitation request path is exercised directly, and the result is checked through the app event receiver.

Call graph: calls 1 internal fn (new); 2 external calls (Integer, assert_matches!).

thread_settings_updated_updates_visible_state_without_transcript101–154 ↗
async fn thread_settings_updated_updates_visible_state_without_transcript()

Purpose: Verifies that a settings update for the currently visible thread changes the widget’s active model, reasoning effort, approvals, permissions, personality, and collaboration mode. It also checks that this kind of update does not add chat history.

Data flow: The test starts a widget with an initial model, installs a configured thread session, drains any setup history, then sends a matching thread settings update. It reads the widget’s current settings and confirms they changed. It then sends an update for a different thread and confirms the visible model stays unchanged.

Call relations: The test runner calls this test. It relies on configured_thread_session to create the starting state and thread_settings_for_test to create server update messages, then drives the widget through handle_server_notification.

Call graph: calls 3 internal fn (new, configured_thread_session, thread_settings_for_test); 3 external calls (ThreadSettingsUpdated, assert!, assert_eq!).

thread_settings_updated_preserves_default_settings_for_plan_mode157–190 ↗
async fn thread_settings_updated_preserves_default_settings_for_plan_mode()

Purpose: Checks that switching into plan collaboration mode uses the plan-mode settings while preserving the original default-mode settings for later. This prevents a temporary mode switch from overwriting the user’s normal model choice.

Data flow: The test gives the widget a thread whose default model and reasoning effort are known. It saves the default collaboration mode, sends a server update that activates plan mode with a different model and effort, and confirms those plan values are shown. Then it switches back to the default mask and confirms the original default model and effort return.

Call relations: The test runner invokes this test. It uses configured_thread_session for the starting session, thread_settings_for_test for the plan-mode update, and the collaboration mode default mask helper to switch back to default mode.

Call graph: calls 4 internal fn (new, configured_thread_session, thread_settings_for_test, default_mask); 2 external calls (ThreadSettingsUpdated, assert_eq!).

collab_spawn_end_shows_requested_model_and_effort193–259 ↗
async fn collab_spawn_end_shows_requested_model_and_effort()

Purpose: Checks that when a collaborative agent spawn finishes, the history line still shows the model and reasoning effort that were requested at the start. This protects useful context for the user even if the completed server item omits those fields.

Data flow: The test creates a widget, records metadata for the spawned agent, sends an in-progress spawn item containing model and effort, then sends a completed spawn item naming the new agent but leaving model and effort empty. It drains rendered history, joins it into text, and checks that the spawn line includes the agent name, role, model, and effort.

Call relations: The test runner calls this test. It drives the widget with ItemStarted and ItemCompleted notifications and then checks the rendered history emitted through the app event receiver.

Call graph: calls 1 internal fn (new); 7 external calls (from, new, ItemCompleted, ItemStarted, new, assert!, vec!).

live_app_server_user_message_item_completed_does_not_duplicate_rendered_prompt262–297 ↗
async fn live_app_server_user_message_item_completed_does_not_duplicate_rendered_prompt()

Purpose: Makes sure a user’s prompt is not shown twice when the server later confirms the same user message. The widget already renders the prompt immediately when the user presses Enter.

Data flow: The test types text into the composer, sends Enter, and confirms one user-turn operation is submitted and one prompt cell appears. It then simulates the app server completing a matching user message item. After that, it drains history again and expects nothing new.

Call relations: The async test runner invokes this test. The test exercises both local keyboard submission and later ItemCompleted server notification handling, proving the two paths cooperate instead of duplicating output.

Call graph: calls 1 internal fn (new); 7 external calls (new, ItemCompleted, new, assert!, assert_eq!, panic!, vec!).

live_app_server_turn_completed_clears_working_status_after_answer_item300–366 ↗
async fn live_app_server_turn_completed_clears_working_status_after_answer_item()

Purpose: Checks that the “Working” status remains visible while a turn is in progress and disappears only when the turn is completed. This keeps the user from seeing the task as done too early.

Data flow: The test sends a turn-started notification and confirms the bottom pane shows a running task with a “Working” header. It then sends a completed final answer item and confirms the answer appears while the task still looks active. Finally, it sends a turn-completed notification and confirms the running indicator and status widget are gone.

Call relations: The test runner calls this test. It walks through the normal server sequence of TurnStarted, ItemCompleted for the answer, and TurnCompleted, checking the widget state after each step.

Call graph: 6 external calls (ItemCompleted, TurnCompleted, TurnStarted, new, assert!, assert_eq!).

live_app_server_turn_started_sets_feedback_turn_id369–404 ↗
async fn live_app_server_turn_started_sets_feedback_turn_id()

Purpose: Verifies that feedback submitted during a turn is tagged with that turn’s id. This helps connect a bug report or feedback note to the exact server turn it came from.

Data flow: The test sends a turn-started notification with a known id. It opens a bug feedback note, submits it with Enter, and reads the outgoing feedback event. The event must include the same turn id and the chosen category.

Call relations: The test runner invokes this test. It first exercises server notification handling to set the active turn, then exercises the feedback UI path and checks the resulting app event.

Call graph: 4 external calls (new, TurnStarted, new, assert_matches!).

live_app_server_warning_notification_renders_message407–432 ↗
async fn live_app_server_warning_notification_renders_message()

Purpose: Checks that a general server warning is rendered into chat history with its message intact. This ensures users see important non-fatal problems.

Data flow: The test sends a warning notification containing a long message about a skills context budget. It drains rendered history, normalizes whitespace, and verifies both the summary and guidance text are present.

Call relations: The async test runner calls this test. It drives the widget through the Warning notification path and checks the history cell sent to the UI event stream.

Call graph: 3 external calls (Warning, assert!, assert_eq!).

live_app_server_guardian_warning_notification_renders_message435–453 ↗
async fn live_app_server_guardian_warning_notification_renders_message()

Purpose: Checks that an automatic approval review warning appears in chat history. This tells the user when a requested action was denied by the review layer.

Data flow: The test sends a guardian warning notification with a clear denial message. It drains history and confirms exactly one warning cell appears and contains that message.

Call relations: The test runner invokes this test. It exercises the GuardianWarning notification branch and verifies the rendered result.

Call graph: 3 external calls (GuardianWarning, assert!, assert_eq!).

live_app_server_config_warning_prefixes_summary456–476 ↗
async fn live_app_server_config_warning_prefixes_summary()

Purpose: Checks that configuration warnings from the server are shown to the user. A configuration warning means the app found a problem in settings and may be falling back to defaults.

Data flow: The test sends a config warning with a summary and no details. It drains history and confirms one warning cell contains the summary text.

Call relations: The test runner calls this test. It feeds a ConfigWarning notification into the widget and inspects the resulting history output.

Call graph: 3 external calls (ConfigWarning, assert!, assert_eq!).

live_app_server_file_change_item_started_preserves_changes479–507 ↗
async fn live_app_server_file_change_item_started_preserves_changes()

Purpose: Verifies that a file-change item still renders a useful patch summary as soon as it starts. This helps users see what file is being added or edited while work is underway.

Data flow: The test sends an in-progress file change for foo.txt with an add-style diff. It drains history and checks the last rendered patch cell mentions foo.txt as added or edited.

Call relations: The async test runner invokes this test. It exercises the ItemStarted path for file changes and checks that the patch renderer receives and preserves the change details.

Call graph: 3 external calls (ItemStarted, assert!, vec!).

live_app_server_command_execution_strips_shell_wrapper510–572 ↗
async fn live_app_server_command_execution_strips_shell_wrapper()

Purpose: Checks that command history shows the meaningful command instead of the surrounding shell wrapper. For example, users should see the Python command, not just the technical /bin/zsh -lc ... envelope used to run it.

Data flow: The test builds a shell-wrapped command string, sends an in-progress command execution notification, then sends a completed command execution notification with output, exit code, and duration. It drains history and compares the rendered command cell to a saved snapshot.

Call relations: The test runner calls this test. It uses the command start and completion notification paths, and the snapshot assertion records the expected user-facing rendering.

Call graph: 6 external calls (ItemCompleted, ItemStarted, assert_chatwidget_snapshot!, assert_eq!, try_join, vec!).

live_app_server_collab_wait_items_render_history575–661 ↗
async fn live_app_server_collab_wait_items_render_history()

Purpose: Checks that waiting on collaborative agents produces clear history output. This lets users see which agents were waited on and what state they ended in.

Data flow: The test creates fixed thread ids for a sender and two receivers, assigns names and roles to the receivers, sends a wait tool call start, then sends its completion with one agent completed and another still running. It drains all rendered history, joins it, and compares it to a snapshot.

Call relations: The test runner invokes this test. It exercises collaborative agent ItemStarted and ItemCompleted handling, with metadata lookup used to display human-friendly agent labels.

Call graph: calls 1 internal fn (from_string); 6 external calls (from, new, ItemCompleted, ItemStarted, assert_chatwidget_snapshot!, vec!).

live_app_server_collab_spawn_completed_renders_requested_model_and_effort664–726 ↗
async fn live_app_server_collab_spawn_completed_renders_requested_model_and_effort()

Purpose: Checks that a completed collaborative-agent spawn item renders the requested model and reasoning effort. This makes the spawned agent’s setup visible in the transcript.

Data flow: The test sends a spawn-agent start notification with a prompt, model, and effort. It then sends a completed spawn notification naming the spawned thread and repeating the model and effort. It drains the rendered history and compares it to a snapshot.

Call relations: The async test runner calls this test. It drives the widget through the collaborative spawn start and completion paths and uses a snapshot to protect the exact rendered wording.

Call graph: calls 1 internal fn (from_string); 7 external calls (from, new, ItemCompleted, ItemStarted, new, assert_chatwidget_snapshot!, vec!).

live_app_server_failed_turn_does_not_duplicate_error_history729–790 ↗
async fn live_app_server_failed_turn_does_not_duplicate_error_history()

Purpose: Makes sure the same failure is not printed twice when both an error notification and a failed turn completion report it. This avoids noisy, confusing chat history.

Data flow: The test starts a turn, sends an error notification saying “permission denied,” and confirms one history cell appears. It then sends a turn-completed notification for the same failed turn with the same error. It expects no extra history and confirms the task is no longer running.

Call relations: The test runner invokes this test. It covers the interaction between the Error notification path and the TurnCompleted failure path, checking that they share enough state to avoid duplicate rendering.

Call graph: 6 external calls (Error, TurnCompleted, TurnStarted, new, assert!, assert_eq!).

live_app_server_failed_turn_consolidates_streamed_answer793–824 ↗
async fn live_app_server_failed_turn_consolidates_streamed_answer()

Purpose: Checks that if a turn fails after partial streamed text has appeared, the partial text is first consolidated into normal history. This prevents losing streamed content when the stream controller is cleared.

Data flow: The test starts a turn, sends an agent-message delta containing a partial diff block, runs a commit tick so streaming output can be processed, then sends an error. It reads outgoing events until it finds a consolidate-agent-message event and verifies the saved source includes the streamed patch text.

Call relations: The test runner calls this test. It relies on shared test helpers for starting a turn, sending a stream delta, and sending an error, then checks that failure cleanup hands partial stream content to the consolidation path.

Call graph: 1 external calls (assert!).

live_app_server_stream_recovery_restores_previous_status_header827–882 ↗
async fn live_app_server_stream_recovery_restores_previous_status_header()

Purpose: Verifies that after a temporary retrying error, receiving new streamed content restores the normal “Working” status. This keeps a reconnect warning from sticking around after the stream has recovered.

Data flow: The test starts a turn, sends a retryable error with a “Reconnecting” message, then sends an agent-message delta. It checks the bottom status widget and confirms the header is back to “Working,” details are cleared, and retry status tracking is reset.

Call relations: The async test runner invokes this test. It exercises the sequence TurnStarted, retryable Error, then AgentMessageDelta to prove stream recovery resets the status display.

Call graph: 6 external calls (AgentMessageDelta, Error, TurnStarted, new, assert!, assert_eq!).

live_app_server_server_overloaded_error_renders_warning885–924 ↗
async fn live_app_server_server_overloaded_error_renders_warning()

Purpose: Checks that a server-overloaded error is shown as a concise warning and stops the running task indicator. This gives the user a clear reason for failure without extra clutter.

Data flow: The test starts a turn, drains any start output, then sends a non-retryable error marked as server overloaded. It expects one rendered warning cell exactly saying “ server overloaded” and confirms the bottom pane is no longer running.

Call relations: The test runner calls this test. It drives the Error notification path with a specific error code so the widget can choose the correct user-facing warning style.

Call graph: 5 external calls (Error, TurnStarted, new, assert!, assert_eq!).

live_app_server_cyber_policy_error_renders_dedicated_notice927–969 ↗
async fn live_app_server_cyber_policy_error_renders_dedicated_notice()

Purpose: Checks that a cybersecurity policy error shows a special explanatory notice instead of the raw server fallback message. This gives users a clearer and safer explanation of what happened.

Data flow: The test starts a turn, then sends a non-retryable error marked as a cybersecurity policy issue with a fallback message. It drains history and confirms the rendered notice mentions possible cybersecurity risk and Trusted Access for Cyber, does not include the fallback message, and clears the running task.

Call relations: The async test runner invokes this test. It exercises the special CyberPolicy branch in error rendering after a normal TurnStarted notification.

Call graph: 5 external calls (Error, TurnStarted, new, assert!, assert_eq!).

live_app_server_model_verification_renders_warning972–991 ↗
async fn live_app_server_model_verification_renders_warning()

Purpose: Checks that model verification warnings are rendered when extra safety checks are enabled. This informs users that the chat has been flagged for additional review conditions.

Data flow: The test sends a model verification notification containing the Trusted Access for Cyber verification. It drains history and verifies one warning cell mentions multiple cybersecurity-risk flags, extra safety checks, the verification name, and the help URL.

Call relations: The test runner calls this test. It feeds a ModelVerification notification into the widget and checks the warning text produced for the transcript.

Call graph: 4 external calls (ModelVerification, assert!, assert_eq!, vec!).

live_app_server_invalid_thread_name_update_is_ignored994–1012 ↗
async fn live_app_server_invalid_thread_name_update_is_ignored()

Purpose: Verifies that a malformed thread id in a thread-name update does not corrupt the current thread state. Bad server data should not overwrite the visible thread name.

Data flow: The test sets the widget to a known thread id and thread name. It sends a thread-name update whose thread id string is invalid. It then confirms the widget still has the original thread id and original name.

Call relations: The async test runner invokes this test. It exercises the ThreadNameUpdated notification path with invalid input and checks that validation protects existing state.

Call graph: calls 1 internal fn (new); 2 external calls (ThreadNameUpdated, assert_eq!).

live_app_server_thread_name_update_shows_resume_hint1015–1036 ↗
async fn live_app_server_thread_name_update_shows_resume_hint()

Purpose: Checks that a valid thread-name update changes the widget’s thread name and renders a resume hint. The resume hint helps users know how to return to the named thread later.

Data flow: The test sets the widget’s current thread id, sends a matching thread-name update with the name “review-fix,” and confirms the internal name changes. It then drains one rendered history cell and compares it to a snapshot.

Call relations: The test runner calls this test. It drives the valid ThreadNameUpdated path and uses a snapshot to protect the exact resume-hint rendering.

Call graph: calls 1 internal fn (from_string); 3 external calls (ThreadNameUpdated, assert_chatwidget_snapshot!, assert_eq!).

live_app_server_thread_closed_requests_immediate_exit1039–1050 ↗
async fn live_app_server_thread_closed_requests_immediate_exit()

Purpose: Checks that when the server says the thread is closed, the widget asks the app to exit immediately. This prevents the user interface from staying open on a conversation that no longer exists.

Data flow: The test sends a thread-closed notification. It reads the next app event and verifies it is an immediate exit request.

Call relations: The async test runner invokes this test. It exercises the ThreadClosed notification path and checks the widget’s outgoing event channel for the shutdown signal.

Call graph: 2 external calls (ThreadClosed, assert_matches!).

tui/src/chatwidget/tests/approval_requests.rssource ↗
testtest suite

This is a focused test file for approval requests in the chat widget, the part of the terminal interface where the assistant can ask before running a command or using extra access. The core problem is trust: before the system runs something risky, the user must see a clear request, choose yes or no, and later have a readable record of what happened. If these tests failed or disappeared, the UI could silently stop showing the right approval prompt, send the wrong approval id back to the app server, lose permission details, or write confusing history messages.

The tests build a chat widget in a controlled setup, feed it approval requests that look like real app-server events, simulate key presses such as y, n, or a, and then inspect what the widget produced. Some checks use snapshots, which are saved expected renderings of UI text; they work like a photograph used to catch accidental visual changes. Other checks compare data structures directly, such as making sure file-system permission paths survive conversion from API form into the app’s internal form.

A few tests cover network-specific approvals, where the history should say whether access to a host was allowed once, allowed for the session, or canceled. Others cover command display rules, such as splitting shell-wrapped commands and shortening long or multi-line commands in the final decision history.

Function details9
exec_approval_emits_proposed_command_and_decision_history8–48 ↗
async fn exec_approval_emits_proposed_command_and_decision_history()

Purpose: This test checks the basic command approval experience. It makes sure a proposed command is shown in the approval modal, not immediately written into chat history, and that approving it creates the expected decision record.

Data flow: It starts with a fresh chat widget and a fake command approval request for echo hello world. The request is passed into the widget, the widget is rendered into an in-memory terminal buffer, and the saved snapshot checks what the user would see. Then the test simulates pressing y, reads the emitted history item, and compares it to the expected approved-command text.

Call relations: The async test runner calls this test. Inside the story, the test creates current-directory path data, builds key events and a rendering buffer, then relies on assertions and snapshot checks to confirm that the approval modal and the later history entry stay correct.

Call graph: calls 1 internal fn (current_dir); 7 external calls (Char, new, new, assert!, assert_snapshot!, empty, vec!).

app_server_exec_approval_request_splits_shell_wrapped_command51–84 ↗
fn app_server_exec_approval_request_splits_shell_wrapped_command()

Purpose: This test checks that a command sent by the app server as one shell-quoted string is turned back into separate command arguments. That matters because the UI and approval logic need to know the actual executable, shell flag, and script text instead of treating the whole line as one blob.

Data flow: It builds a shell-wrapped command string, like /bin/zsh -lc 'python3 -c ...', using shell quoting that can safely round-trip. That string goes into the app-server approval conversion function. The resulting internal request should contain a vector of three parts: the shell path, the -lc flag, and the script itself.

Call relations: The normal test runner calls this unit test. It uses shell-joining support to create realistic input, then uses a direct equality check to verify that the conversion step produces the command shape that later approval UI code expects.

Call graph: 2 external calls (assert_eq!, try_join).

app_server_exec_approval_request_preserves_permissions_context87–148 ↗
fn app_server_exec_approval_request_preserves_permissions_context()

Purpose: This test makes sure an execution approval request does not drop extra permission information. It specifically checks both network context and requested file-system access.

Data flow: It starts with absolute read and write paths, converts them into the API’s path-string form, and puts them into a fake app-server command approval request. The conversion function turns that API request into the internal approval request. The test then checks that the network host/protocol and the additional file-system permissions are still present and unchanged.

Call relations: The test runner calls this test as part of the approval-request suite. The test uses path conversion helpers to mimic real app-server data, then hands the request through the same conversion path used before the chat widget displays or processes an approval.

Call graph: calls 2 internal fn (try_from, from_abs_path); 3 external calls (from, assert_eq!, vec!).

network_exec_approval_history_describes_session_host_allowance151–189 ↗
async fn network_exec_approval_history_describes_session_host_allowance()

Purpose: This test checks the history text for a network approval that is accepted for the whole session. It ensures the user record says that a host was allowed beyond just a single request.

Data flow: It creates a chat widget and a fake approval request for HTTPS access to example.com, with available choices including accept-for-session and cancel. The request is shown to the widget, the test simulates pressing a, then it reads the produced history entry. A snapshot verifies the final wording.

Call relations: The async test runner invokes this scenario. The test feeds a network approval request into the chat widget, simulates the user choosing the session-wide allowance shortcut, and then uses snapshot checking to protect the history message that the rest of the UI will show.

Call graph: 4 external calls (Char, new, assert_snapshot!, vec!).

network_exec_approval_history_describes_one_time_host_allowance192–230 ↗
async fn network_exec_approval_history_describes_one_time_host_allowance()

Purpose: This test checks the history text for a network approval accepted only once. It makes sure a temporary allowance is not described as a broader session permission.

Data flow: It builds a fake network approval for HTTP access to example.com, without a command string, and gives the user choices to accept or cancel. After the widget receives the request, the test simulates pressing y. It then pulls the resulting history entry and compares its text to the saved snapshot.

Call relations: The async test runner calls this test. The test follows the same path a real one-time approval would follow through the widget: request arrives, user presses the approval key, and the history output is checked for clear wording.

Call graph: 4 external calls (Char, new, assert_snapshot!, vec!).

network_exec_approval_history_describes_canceled_host_request233–271 ↗
async fn network_exec_approval_history_describes_canceled_host_request()

Purpose: This test checks the history text when the user denies a network approval request. It confirms that a canceled request is recorded clearly instead of looking like it was allowed.

Data flow: It creates a fake request for SOCKS5 TCP access to example.com, including a command-like network access string and choices to accept or cancel. The widget receives the request, the test simulates pressing n, and the emitted history entry is read. A snapshot confirms the canceled-host wording.

Call relations: The async test runner runs this case with the other network approval tests. It drives the chat widget through the denial path and then uses snapshot checking to make sure the visible record of the decision remains accurate.

Call graph: 4 external calls (Char, new, assert_snapshot!, vec!).

app_server_request_permissions_preserves_file_system_permissions274–320 ↗
fn app_server_request_permissions_preserves_file_system_permissions()

Purpose: This test checks conversion of a general permissions request from app-server format into the app’s internal format. It makes sure network permission, read roots, write roots, the current working directory, and the remote environment id are all preserved.

Data flow: It creates absolute read, write, and working-directory paths, converts the read and write paths into the API path format, and builds a fake permission request. The conversion function returns an internal request. The test compares the result against the expected internal permission profile, current directory, and environment id.

Call relations: The test runner calls this unit test directly. The test exercises the conversion step that runs before a permissions approval reaches the UI, using equality checks to prove that important permission details are not lost or reshaped incorrectly.

Call graph: calls 2 internal fn (try_from, from_abs_path); 3 external calls (from, assert_eq!, vec!).

exec_approval_uses_approval_id_when_present323–365 ↗
async fn exec_approval_uses_approval_id_when_present()

Purpose: This test makes sure the widget replies with the explicit approval id when one is provided. That matters because the approval id can identify a subcommand, while the call id may identify a larger parent operation.

Data flow: It creates a command approval request whose call_id and approval_id are different. After passing the request into the chat widget, the test simulates pressing y. It then reads outgoing app events until it finds the execution approval operation, and checks that the id is approval-subcommand and the decision is accept.

Call relations: The async test runner invokes this test. The test drives the same path used when a user approves a command, then inspects the outgoing operation that would be sent back to the rest of the application.

Call graph: calls 1 internal fn (current_dir); 6 external calls (Char, new, assert!, assert_eq!, assert_matches!, vec!).

exec_approval_decision_truncates_multiline_and_long_commands368–449 ↗
async fn exec_approval_decision_truncates_multiline_and_long_commands()

Purpose: This test checks that final approval history stays readable when commands are multi-line or very long. The approval modal may show useful detail, but the later chat history should summarize without flooding the screen.

Data flow: First it sends a multi-line shell command into the widget and confirms no history entry is written before the user decides. It renders the modal and checks that the first line of the command is visible, then simulates pressing n and snapshot-checks the aborted decision history. Next it builds a very long command, sends another approval request, confirms no early history entry appears, rejects it, and snapshot-checks the shortened history text.

Call relations: The async test runner calls this longer scenario. The test uses current-directory data, simulated key events, an in-memory render buffer, string formatting for the long command, assertions, and snapshots to cover both the display step and the post-decision history step.

Call graph: calls 1 internal fn (current_dir); 9 external calls (Char, new, new, new, assert!, assert_snapshot!, format!, empty, vec!).

tui/src/chatwidget/tests/composer_submission.rssource ↗
testtest run

The chat composer is the box where a user types before sending work to the assistant. This test file checks many edge cases around that box, especially cases where hidden bookkeeping must stay lined up with what the user sees. For example, an image may appear in the text as “[Image #1]”, but the program must also remember the real file path or remote URL behind that label. If that mapping breaks, the assistant may receive the wrong image, lose an image, or show misleading history.

The tests build a chat widget in a controlled test setup, fill in session state, type or restore messages, press keys such as Enter or Escape, and then inspect two results: the operation sent to the backend and the history cell shown in the user interface. The file also checks that queued messages behave like a tidy waiting line: they can be recalled, edited, restored after interruption, and resubmitted without changing order or content.

Several tests cover safety and context details. They verify permission profiles are included when available, inaccessible app mentions are ignored, hidden IDE context is not shown as user text, and cancel/interrupt behavior only restores drafts when no real output happened. In short, this file is a safety net for the composer’s most user-visible promises.

Function details37
submission_preserves_text_elements_and_local_images14–97 ↗
async fn submission_preserves_text_elements_and_local_images()

Purpose: Checks that sending a message with a local image keeps both the visible placeholder text and the hidden image file path. This matters because the user sees a label like “[Image #1]”, while the backend needs the real image path.

Data flow: The test starts with a fresh chat widget and a configured thread session. It puts text, a text element marking the image placeholder, and a local image path into the composer, then presses Enter. The outgoing user turn contains the local image followed by the text, and the displayed history cell stores the same text, text element, and local image path.

Call relations: The Tokio test runner calls this as an isolated async test. It drives the chat widget through session setup and key handling, then reads the outbound operation channel and app event channel to confirm submission and history display agree.

Call graph: calls 2 internal fn (read_only, new); 9 external calls (new, new, default, new, assert!, assert_eq!, format!, panic!, vec!).

submission_includes_configured_active_permission_profile100–169 ↗
async fn submission_includes_configured_active_permission_profile()

Purpose: Verifies that a submitted user turn carries the currently selected permission profile when one is present. This prevents the backend from accidentally using a default or stale sandbox setting.

Data flow: The test creates a session with a managed permission profile and an active profile named “custom”. After entering text and pressing Enter, it reads the submitted user turn. The active permission profile in that operation matches the configured one.

Call relations: The async test is run by the Tokio test harness. It prepares session state, asks ChatWidget to submit through normal key handling, and checks the operation sent toward the backend.

Call graph: calls 2 internal fn (new, new); 7 external calls (new, new, default, new, assert_eq!, panic!, vec!).

submission_omits_active_permission_profile_for_legacy_snapshot172–218 ↗
async fn submission_omits_active_permission_profile_for_legacy_snapshot()

Purpose: Checks backward-compatible behavior for old session snapshots that do not name an active permission profile. The submission should not invent one.

Data flow: The test configures a thread with a permission profile but no active profile field. It submits a simple message. The resulting user turn has no active permission profile attached.

Call relations: The test harness invokes this test directly. It exercises the same submit path as normal typing, then inspects the outbound operation to make sure legacy state is preserved as legacy state.

Call graph: calls 1 internal fn (new); 6 external calls (new, new, default, new, assert_eq!, panic!).

submission_with_remote_and_local_images_keeps_local_placeholder_numbering221–316 ↗
async fn submission_with_remote_and_local_images_keeps_local_placeholder_numbering()

Purpose: Checks that remote images and local images can be submitted together without renumbering the local image placeholder in the text. This avoids changing what the user typed just because a remote image was attached first.

Data flow: The test adds one remote image URL to the chat, then sets composer text containing “[Image #2]” for a local image. After Enter, the outgoing items contain the remote image, the local image, and the text with its original text element. The history cell also keeps the same text, local image path, and remote URL.

Call relations: The Tokio test runner runs this case. It uses ChatWidget’s remote-image state, composer state, and submission path, then compares both backend-facing data and UI history data.

Call graph: calls 2 internal fn (read_only, new); 8 external calls (new, new, default, new, assert_eq!, format!, panic!, vec!).

enter_with_only_remote_images_submits_user_turn319–383 ↗
async fn enter_with_only_remote_images_submits_user_turn()

Purpose: Verifies that pressing Enter can submit remote images even when the text composer is empty. This lets users send an image-only prompt from a URL.

Data flow: The test configures a thread, stores one remote image URL, and leaves the composer text empty. Pressing Enter produces a user turn containing just that remote image, clears the stored remote image list, and inserts a user history cell with an empty message and the URL.

Call relations: The async test is invoked by the Tokio harness. It checks the chat widget’s normal Enter handling and verifies both the outbound operation and the history event.

Call graph: calls 2 internal fn (read_only, new); 8 external calls (new, new, default, new, assert!, assert_eq!, panic!, vec!).

shift_enter_with_only_remote_images_does_not_submit_user_turn386–424 ↗
async fn shift_enter_with_only_remote_images_does_not_submit_user_turn()

Purpose: Ensures Shift+Enter does not submit an image-only message. Shift+Enter is treated differently from Enter, so it should not accidentally send work.

Data flow: The test sets a remote image URL and an empty composer. It sends a Shift+Enter key event. No user turn is emitted, and the remote image URL remains attached.

Call relations: The test harness runs this as an async UI behavior check. It drives key handling and uses the outbound operation channel only to confirm nothing was submitted.

Call graph: calls 2 internal fn (read_only, new); 6 external calls (new, new, default, new, assert_eq!, vec!).

enter_with_only_remote_images_does_not_submit_when_modal_is_active427–465 ↗
async fn enter_with_only_remote_images_does_not_submit_when_modal_is_active()

Purpose: Checks that Enter does not submit remote images while a modal popup is open. A modal is a focused dialog, so Enter should belong to that dialog rather than the composer.

Data flow: The test attaches a remote image, opens the review popup, and presses Enter. The image URL remains in chat state, and no submission operation is sent.

Call relations: The Tokio test runner calls this test. It combines modal state with normal key handling to ensure the composer does not steal keys from an active popup.

Call graph: calls 2 internal fn (read_only, new); 6 external calls (new, new, default, new, assert_eq!, vec!).

enter_with_only_remote_images_does_not_submit_when_input_disabled468–509 ↗
async fn enter_with_only_remote_images_does_not_submit_when_input_disabled()

Purpose: Verifies that image-only submission is blocked when composer input is disabled. This prevents sending new user work while the interface says input is unavailable.

Data flow: The test attaches a remote image, disables composer input with a message, and presses Enter. The remote image stays attached and no outbound user turn appears.

Call relations: The async test runs through the usual ChatWidget key path. It relies on the operation receiver to prove that disabled input truly blocks submission.

Call graph: calls 2 internal fn (read_only, new); 6 external calls (new, new, default, new, assert_eq!, vec!).

submission_prefers_selected_duplicate_skill_path512–593 ↗
async fn submission_prefers_selected_duplicate_skill_path()

Purpose: Checks that when two skills share the same display name, the selected binding path wins. This matters because “figma” could refer to a repository skill or a user skill.

Data flow: The test loads two skill records with the same name but different paths. It submits text containing a bound $figma mention pointing to the user skill path. The outgoing user turn includes a skill item for the selected user path only.

Call relations: The Tokio test harness runs this case. It sets up skill metadata, submits through the composer, and inspects the backend-facing user input items.

Call graph: calls 2 internal fn (read_only, new); 7 external calls (new, new, default, new, assert_eq!, panic!, vec!).

blocked_image_restore_preserves_mention_bindings596–648 ↗
async fn blocked_image_restore_preserves_mention_bindings()

Purpose: Checks that when an image submission is blocked and restored to the composer, mention bindings are not lost. The user should be able to fix or resubmit without reselecting mentions.

Data flow: The test gives ChatWidget text containing an image placeholder and a $file mention, plus a local image attachment and mention binding. Restore puts the same text back into the composer, rebuilds text elements for the image and mention, keeps the local image path, keeps the mention binding, and emits a warning that images are unsupported.

Call relations: The async test is driven by the test harness. It calls the blocked-image restore path directly, then checks composer state and the app-event history/warning output.

Call graph: 5 external calls (new, assert!, assert_eq!, format!, vec!).

blocked_image_restore_with_remote_images_keeps_local_placeholder_mapping651–692 ↗
async fn blocked_image_restore_with_remote_images_keeps_local_placeholder_mapping()

Purpose: Verifies that restoring a blocked image message keeps local image labels matched to the right files even when remote images are also present. This prevents the visible placeholder numbers from drifting.

Data flow: The test builds text with two local image placeholders numbered after an existing remote image, plus two local attachments and one remote URL. After restore, the composer text, text elements, local image attachment objects, and remote URLs are exactly the same as before.

Call relations: The Tokio test harness runs this focused restore test. It calls ChatWidget’s blocked-image restore method and inspects the resulting composer and remote-image state.

Call graph: 4 external calls (new, assert_eq!, format!, vec!).

queued_restore_with_remote_images_keeps_local_placeholder_mapping695–737 ↗
async fn queued_restore_with_remote_images_keeps_local_placeholder_mapping()

Purpose: Checks that restoring a queued user message also preserves local image placeholder mapping when remote images exist. Queued drafts should return to the composer exactly as the user prepared them.

Data flow: The test creates a queued-style user message with two local image placeholders, two local attachments, and a remote URL. Restoring it to the composer keeps the text, places the cursor at the end, preserves text elements and local attachments, and restores the remote URL list.

Call relations: The async test is called by the Tokio test runner. It exercises the general user-message restore path rather than the blocked-image path.

Call graph: 4 external calls (new, assert_eq!, format!, vec!).

interrupted_turn_restore_keeps_active_mode_for_resubmission740–784 ↗
async fn interrupted_turn_restore_keeps_active_mode_for_resubmission()

Purpose: Verifies that if a turn is interrupted and a queued message is restored, the active collaboration mode remains selected for resubmission. The user should not lose the mode they were working in.

Data flow: The test enables collaboration modes, selects the planning mode, starts a task, queues a message, and simulates interruption. The queued message moves into the composer, the queue is emptied, and the active mode stays selected. When Enter is pressed again, the submitted user turn carries that same mode.

Call relations: The Tokio harness runs this scenario. It combines task lifecycle helpers, collaboration mode selection, queue restoration, and final submission to check the full interrupted-resubmit flow.

Call graph: calls 2 internal fn (new, plan_mask); 5 external calls (from, new, assert!, assert_eq!, panic!).

remap_placeholders_uses_attachment_labels787–853 ↗
async fn remap_placeholders_uses_attachment_labels()

Purpose: Checks that placeholder remapping uses the labels stored on image attachments, not just their order in the text. This is important when placeholders appear in a different order than the attachment list.

Data flow: The test creates text where “[Image #2]” appears before “[Image #1]”, with attachments carrying their original labels. Remapping starts at label 3, rewrites the text to new labels, updates text element ranges and placeholder strings, updates attachment placeholder labels, and leaves remote URLs unchanged.

Call relations: The test runner calls this unit-style async test. It directly exercises remap_placeholders_for_message, a helper used when restored or combined messages need fresh image numbers.

Call graph: 4 external calls (new, assert_eq!, format!, vec!).

remap_placeholders_uses_byte_ranges_when_placeholder_missing856–915 ↗
async fn remap_placeholders_uses_byte_ranges_when_placeholder_missing()

Purpose: Checks the fallback path for remapping image placeholders when text elements do not carry placeholder strings. The byte ranges still let the code find and replace the right visible text.

Data flow: The test supplies text elements with ranges but no stored placeholder value. Remapping reads the old placeholder text from those ranges, assigns new labels, rewrites the message text, fills in placeholder values on the text elements, and updates local image attachments.

Call relations: The Tokio test harness runs this targeted helper test. It calls the placeholder-remapping function directly to verify it works with older or incomplete text-element data.

Call graph: 4 external calls (new, assert_eq!, format!, vec!).

empty_enter_during_task_does_not_queue918–929 ↗
async fn empty_enter_during_task_does_not_queue()

Purpose: Ensures pressing Enter with an empty composer during a running task does not add an empty message to the queue. This keeps the pending queue free of meaningless entries.

Data flow: The test marks the bottom pane as task-running and leaves the composer empty. It presses Enter. The queued user message list remains empty.

Call relations: The async test is invoked by the Tokio harness. It uses the normal key handling path and inspects the input queue afterward.

Call graph: 2 external calls (new, assert!).

output_free_interrupted_turn_requests_prompt_restore932–948 ↗
async fn output_free_interrupted_turn_requests_prompt_restore()

Purpose: Checks that cancelling a turn with no visible output asks to restore the original prompt. This supports an edit-and-resubmit workflow when the assistant has not really started answering.

Data flow: The test records a candidate prompt for restoration, marks a turn as started, sends an interrupt command that requests restore-if-no-output, and then simulates interruption. The outbound operation is an interrupt with that behavior, and the app event restores the cancelled prompt.

Call relations: The Tokio test runner executes this flow. It connects ChatWidget’s cancel-edit bookkeeping, command submission, and turn-interruption handling.

Call graph: calls 1 internal fn (from); 2 external calls (assert_matches!, interrupt_and_restore_prompt_if_no_output).

visible_output_prevents_cancelled_turn_prompt_restore951–963 ↗
async fn visible_output_prevents_cancelled_turn_prompt_restore()

Purpose: Verifies that once the assistant has produced visible output, cancelling does not restore the old prompt. At that point, restoring the prompt could be confusing because the turn visibly progressed.

Data flow: The test records a restore candidate, starts a turn, feeds in visible assistant text, submits the restore-if-no-output interrupt, and interrupts the turn. It drains app events and confirms none restore the cancelled prompt.

Call relations: The async test is run by the Tokio harness. It exercises the output-tracking part of interruption handling.

Call graph: calls 1 internal fn (from); 2 external calls (assert!, interrupt_and_restore_prompt_if_no_output).

thinking_status_keeps_cancelled_turn_prompt_restore_eligible966–977 ↗
async fn thinking_status_keeps_cancelled_turn_prompt_restore_eligible()

Purpose: Checks that internal reasoning or “thinking” text does not count as visible answer output for prompt restoration. A user can still get their prompt back if only thinking status appeared.

Data flow: The test records a prompt, starts a turn, adds reasoning text, submits the restore-if-no-output interrupt, and interrupts. The app event restores the original prompt.

Call relations: The Tokio test harness runs this scenario. It separates reasoning-status updates from user-visible assistant message output in the cancel-restore flow.

Call graph: calls 1 internal fn (from); 2 external calls (assert_matches!, interrupt_and_restore_prompt_if_no_output).

patch_activity_prevents_cancelled_turn_prompt_restore980–992 ↗
async fn patch_activity_prevents_cancelled_turn_prompt_restore()

Purpose: Verifies that file patch activity counts as meaningful turn output and prevents prompt restoration. If the assistant started changing files, restoring the prompt as if nothing happened would be misleading.

Data flow: The test records a restore candidate, starts a turn, reports patch-apply activity, submits an interrupt, and simulates interruption. It drains app events and confirms no restore event is emitted.

Call relations: The async test is called by the Tokio harness. It checks that patch lifecycle events feed into the same no-output decision used by cancellation.

Call graph: calls 1 internal fn (from); 3 external calls (new, assert!, interrupt_and_restore_prompt_if_no_output).

pending_steer_esc_does_not_steal_vim_insert_escape995–1021 ↗
async fn pending_steer_esc_does_not_steal_vim_insert_escape()

Purpose: Checks that Escape first exits Vim insert mode instead of interrupting a running task with pending steer messages. A steer is a follow-up instruction queued while the assistant is working.

Data flow: The test marks a task as running, adds a pending steer, enables Vim mode, enters insert mode, and presses Escape. The first Escape exits insert mode, leaves the steer queued, and sends no interrupt. A second Escape then sends an interrupt and marks pending steers for submission after interruption.

Call relations: The Tokio test runner executes this keyboard-priority scenario. It combines Vim-mode handling, pending-steer queue state, and interrupt operation emission.

Call graph: 5 external calls (Char, new, assert!, assert_eq!, panic!).

pending_steer_interrupt_uses_remapped_binding1024–1047 ↗
async fn pending_steer_interrupt_uses_remapped_binding()

Purpose: Verifies that pending-steer interruption honors a custom key binding instead of always using Escape. This lets users remap the interrupt key safely.

Data flow: The test changes the interrupt key to F12, starts a task, and adds a pending steer. Pressing Escape does nothing. Pressing F12 sends an interrupt and marks pending steers to be submitted after the interrupt completes.

Call relations: The async test is invoked by the Tokio harness. It exercises runtime keymap configuration, bottom-pane key binding setup, and ChatWidget key handling.

Call graph: calls 1 internal fn (defaults); 5 external calls (F, new, assert!, panic!, vec!).

restore_thread_input_state_syncs_sleep_inhibitor_state1050–1079 ↗
async fn restore_thread_input_state_syncs_sleep_inhibitor_state()

Purpose: Checks that restoring saved input state also restores whether the app should keep the computer awake during a running turn. The sleep inhibitor is a guard that prevents idle sleep while work is active.

Data flow: The test enables the prevent-idle-sleep feature and restores state saying a task and agent turn are running. ChatWidget marks the turn as running, the sleep inhibitor reports running, and the bottom pane shows task-running. Restoring no input state clears all three.

Call relations: The Tokio test harness runs this state-restore check. It connects saved thread input state with turn lifecycle state and visible bottom-pane task state.

Call graph: 2 external calls (new, assert!).

alt_up_edits_most_recent_queued_message1082–1115 ↗
async fn alt_up_edits_most_recent_queued_message()

Purpose: Verifies that the configured edit-queued-message shortcut pulls the newest queued message back into the composer. This lets a user fix the last pending prompt before it is sent.

Data flow: The test binds edit to Alt+Up, marks a task as running, queues two messages, and presses Alt+Up. The composer now contains the second, most recent queued message, while the queue keeps only the older first message.

Call relations: The async test is run by the Tokio harness. It checks the interaction between key binding setup, pending-input preview, queue mutation, and composer restoration.

Call graph: calls 2 internal fn (from, alt); 3 external calls (new, assert_eq!, vec!).

unbound_queued_message_edit_does_not_fall_back_to_alt_up1118–1134 ↗
async fn unbound_queued_message_edit_does_not_fall_back_to_alt_up()

Purpose: Ensures Alt+Up does not edit queued messages when the edit shortcut is deliberately unbound. This respects user or terminal configuration that removes the shortcut.

Data flow: The test clears the edit-queued-message binding, starts a running-task state, and queues one message. Pressing Alt+Up leaves the composer empty and keeps the queued message in place.

Call relations: The Tokio test harness calls this case. It verifies that ChatWidget uses the configured keymap rather than a hard-coded fallback.

Call graph: calls 1 internal fn (from); 4 external calls (new, new, assert!, assert_eq!).

shift_left_edits_most_recent_queued_message_in_apple_terminal1137–1146 ↗
async fn shift_left_edits_most_recent_queued_message_in_apple_terminal()

Purpose: Checks that Apple Terminal uses Shift+Left as the queued-message edit shortcut. Some terminals report keys differently, so the default shortcut is adapted.

Data flow: The test passes Apple Terminal information to a shared assertion helper. That helper sets up queued messages, presses the expected shortcut, and confirms the newest queued message moves into the composer.

Call relations: The Tokio harness runs this terminal-specific wrapper. It delegates the real behavior check to assert_shift_left_edits_most_recent_queued_message_for_terminal.

shift_left_edits_most_recent_queued_message_in_warp_terminal1149–1158 ↗
async fn shift_left_edits_most_recent_queued_message_in_warp_terminal()

Purpose: Checks that Warp Terminal uses Shift+Left for editing the most recent queued message. This protects the shortcut behavior on a terminal with special key handling.

Data flow: The test provides Warp Terminal metadata to the shared queued-message edit assertion. The helper verifies that the shortcut recalls the newest queued message and removes it from the queue.

Call relations: The Tokio test runner invokes this wrapper. It reuses the common terminal shortcut test helper for Warp-specific terminal detection.

shift_left_edits_most_recent_queued_message_in_vscode_terminal1161–1170 ↗
async fn shift_left_edits_most_recent_queued_message_in_vscode_terminal()

Purpose: Verifies that the integrated VS Code terminal uses Shift+Left for queued-message editing. This keeps the shortcut usable inside VS Code.

Data flow: The test supplies VS Code terminal information to the shared helper. The helper performs the queue setup and confirms Shift+Left edits the newest queued message.

Call relations: The async test is run by the Tokio harness. It delegates to the common terminal behavior helper with VS Code terminal metadata.

shift_left_edits_most_recent_queued_message_in_tmux1173–1182 ↗
async fn shift_left_edits_most_recent_queued_message_in_tmux()

Purpose: Checks that sessions running inside tmux use Shift+Left for editing queued messages. tmux can alter key sequences, so it receives special handling.

Data flow: The test describes a terminal running under tmux and calls the shared assertion helper. The helper confirms the shortcut restores the newest queued message into the composer.

Call relations: The Tokio harness invokes this wrapper. It tests the tmux branch of terminal-aware queued-message edit behavior through a common helper.

queued_message_edit_binding_mapping_covers_special_terminals_and_tmux1185–1236 ↗
fn queued_message_edit_binding_mapping_covers_special_terminals_and_tmux()

Purpose: Verifies the mapping from terminal type to queued-message edit shortcut. It makes sure known special terminals and tmux use Shift+Left, while ordinary iTerm2 keeps Alt+Up.

Data flow: The test feeds several terminal descriptions into the binding-selection function. Each result is compared with the expected key hint for that terminal environment.

Call relations: The standard Rust test runner calls this synchronous unit test. It directly checks the shortcut-mapping helper used when configuring the chat UI.

Call graph: 1 external calls (assert_eq!).

enqueueing_history_prompt_multiple_times_is_stable1242–1267 ↗
async fn enqueueing_history_prompt_multiple_times_is_stable()

Purpose: Checks that repeatedly recalling a prompt from history and queueing it produces identical queued messages each time. This prevents subtle mutation of history text across repeated use.

Data flow: The test submits “repeat me” once to seed history, marks a task as running, then three times presses Up to recall the prompt and Tab to queue it. The queue ends with three messages, all exactly “repeat me”.

Call relations: The Tokio test harness runs this workflow. It links history recall, task-running queue behavior, and repeated submission stability.

Call graph: calls 1 internal fn (new); 3 external calls (new, new, assert_eq!).

submit_user_message_ignores_inaccessible_app_mentions_from_bindings1270–1323 ↗
async fn submit_user_message_ignores_inaccessible_app_mentions_from_bindings()

Purpose: Verifies that a bound app mention is not sent as a special mention item when the app is not accessible. The raw text remains, but the backend is not told to use an app the user cannot access.

Data flow: The test enables apps, loads a connector marked enabled but inaccessible, and submits a message whose binding points at that app. The outgoing user turn contains only a plain text item with $arabica-uae, not a separate mention item.

Call relations: The async test is run by the Tokio harness. It combines connector loading, authentication/config state, and direct user-message submission.

Call graph: calls 1 internal fn (new); 4 external calls (new, assert_eq!, panic!, vec!).

user_message_display_from_inputs_matches_flattened_user_message_shape1326–1367 ↗
fn user_message_display_from_inputs_matches_flattened_user_message_shape()

Purpose: Checks that display data built from mixed user input items matches the display data built from already-flattened message parts. This keeps history rendering consistent no matter how the message was assembled.

Data flow: The test builds inputs containing text, a remote image, a local image, a skill, an app mention, and more text. The display conversion joins only the visible text, shifts text-element ranges into the joined text, collects image paths and URLs, and matches the equivalent direct display construction.

Call relations: The standard test runner calls this synchronous test. It directly exercises ChatWidget::user_message_display_from_inputs, which is used to render submitted user messages.

Call graph: 4 external calls (from, assert_eq!, user_message_display_from_inputs, vec!).

user_message_display_from_inputs_hides_prompt_context1370–1393 ↗
fn user_message_display_from_inputs_hides_prompt_context()

Purpose: Verifies that hidden IDE prompt context is removed from the message shown in chat history. The user should see their actual request, not the internal context block prepended for the assistant.

Data flow: The test creates a text input with an IDE context header and a final request containing $figma. Display conversion strips the context, keeps “Ask $figma”, and adjusts the mention text element to the new range.

Call relations: The synchronous test is run by the Rust test runner. It targets the display conversion helper for messages that include hidden context.

Call graph: 3 external calls (assert_eq!, user_message_display_from_inputs, vec!).

committed_user_message_with_hidden_prompt_context_renders_local_images1396–1430 ↗
async fn committed_user_message_with_hidden_prompt_context_renders_local_images()

Purpose: Checks that when hidden prompt context is stripped from a committed user message, local images are still shown. Removing text context must not discard image attachments.

Data flow: The test completes a user message made of hidden context text plus one local image input. The inserted user history cell has an empty visible message but still contains the local image path.

Call relations: The Tokio test harness runs this async history-rendering check. It uses the message completion helper and reads app events to inspect the resulting UserHistoryCell.

Call graph: 3 external calls (from, assert_eq!, vec!).

interrupt_restores_queued_messages_into_composer1433–1466 ↗
async fn interrupt_restores_queued_messages_into_composer()

Purpose: Verifies that interrupting a running turn moves queued messages back into the composer instead of submitting them automatically. This gives the user control after an interruption.

Data flow: The test marks a task as running, queues two messages, refreshes the pending preview, and simulates turn interruption. The composer contains both queued messages joined with newlines, the queue is empty, and no outbound user operation is sent.

Call relations: The Tokio test runner executes this interruption scenario. It checks the queue restoration path triggered by handle_turn_interrupted.

Call graph: calls 1 internal fn (from); 2 external calls (assert!, assert_eq!).

interrupt_prepends_queued_messages_before_existing_composer_text1469–1497 ↗
async fn interrupt_prepends_queued_messages_before_existing_composer_text()

Purpose: Checks that interrupted queued messages are restored before any draft already in the composer. This preserves the order in which the user intended messages to be handled.

Data flow: The test starts with “current draft” in the composer, queues two earlier messages during a running task, and simulates interruption. The composer becomes “first queued”, then “second queued”, then “current draft”, separated by newlines; the queue is cleared and nothing is submitted.

Call relations: The async test is called by the Tokio harness. It exercises the same interruption restore path as the previous test, but with pre-existing composer text included.

Call graph: calls 1 internal fn (from); 3 external calls (new, assert!, assert_eq!).

tui/src/chatwidget/tests/exec_flow.rssource ↗
testtest suite

This is a test file for the chat widget in the text user interface. The chat widget is the part of the app that shows the conversation, command activity, approval popups, and status line in a terminal. These tests act like a careful checklist for the widget’s most sensitive flows: when the assistant wants to run a command, when the user must approve or deny it, when commands start and finish, when background terminal work is still running, and when file patches or image tools appear in the history.

Most tests build a chat widget with fake channels instead of starting the real agent. They then feed it events that normally come from the backend, such as “a command started,” “a command ended,” or “approval is needed.” The tests drain the widget’s outgoing history messages, inspect submitted operations, or render the widget into a fake terminal buffer. Snapshot tests compare the rendered text against saved expected output, like taking a photograph of the terminal screen.

Without these tests, small UI changes could silently confuse users: an approval could send the wrong id, a background command could vanish, a completed command could overwrite another active command, or a dangerous patch request could show the wrong prompt.

Function details48
exec_approval_emits_proposed_command_and_decision_history5–47 ↗
async fn exec_approval_emits_proposed_command_and_decision_history()

Purpose: Checks that a command approval request appears in the approval modal, not immediately in the chat history, and that approving it later adds a short decision line.

Data flow: It creates a fake chat widget, sends in an approval request for echo hello world, renders the widget, presses y, then reads the outgoing history cells. The expected result is no history entry before the decision, a modal showing the command, and one concise approval record afterward.

Call relations: This test drives the approval flow from the outside by calling the same approval handler and key-event path a real user would trigger. It then uses rendering and history-draining helpers to verify what the rest of the app would see.

Call graph: calls 1 internal fn (current_dir); 7 external calls (Char, new, new, assert!, assert_chatwidget_snapshot!, empty, vec!).

app_server_exec_approval_request_splits_shell_wrapped_command50–83 ↗
fn app_server_exec_approval_request_splits_shell_wrapped_command()

Purpose: Verifies that a shell-wrapped command string from the app server is split back into the original command parts correctly.

Data flow: It builds a request whose command is a joined shell string, converts it into an internal approval request, and checks that the resulting command vector contains the shell, option, and script as separate pieces.

Call relations: This test focuses on the conversion helper used before approval UI is shown. It protects later approval rendering from receiving one confusing blob when it needs separate command arguments.

Call graph: 2 external calls (assert_eq!, try_join).

exec_approval_uses_approval_id_when_present86–128 ↗
async fn exec_approval_uses_approval_id_when_present()

Purpose: Checks that approving a command sends the special approval id when one is provided, instead of falling back to the parent call id.

Data flow: It sends an approval request with both a call id and a distinct approval id, presses y, and reads outgoing app events until it finds an execution approval operation. The operation must carry the approval id and an accept decision.

Call relations: This test follows the approval modal through to the operation submitted back to the app. It makes sure the UI hands off the exact id the backend expects.

Call graph: calls 1 internal fn (current_dir); 6 external calls (Char, new, assert!, assert_eq!, assert_matches!, vec!).

exec_approval_decision_truncates_multiline_and_long_commands131–215 ↗
async fn exec_approval_decision_truncates_multiline_and_long_commands()

Purpose: Ensures approval decision history stays readable when commands are multiline or very long.

Data flow: It sends one multiline command and one very long command through the approval flow, denies each, and inspects the history entries. The modal may show useful command detail, but the final history line must be shortened to a single readable snippet.

Call relations: This test uses the normal approval handler, renderer, keyboard handling, and history output. It protects the transcript from being flooded by large command text after a simple approve or deny choice.

Call graph: calls 1 internal fn (current_dir); 9 external calls (Char, new, new, new, assert!, assert_chatwidget_snapshot!, format!, empty, vec!).

preamble_keeps_working_status_snapshot218–245 ↗
async fn preamble_keeps_working_status_snapshot()

Purpose: Checks that a short assistant preamble does not make the “working” status disappear.

Data flow: It starts a task, streams a preamble line, commits it to history, completes it as commentary, then renders the widget. The snapshot must still show the expected working status area.

Call relations: This test recreates a real turn sequence before tool activity begins. It verifies that message completion and status rendering cooperate instead of one hiding the other.

Call graph: calls 1 internal fn (new); 3 external calls (assert_chatwidget_snapshot!, new, new).

unified_exec_begin_restores_status_indicator_after_preamble248–262 ↗
async fn unified_exec_begin_restores_status_indicator_after_preamble()

Purpose: Verifies that starting a unified execution command brings back the status indicator if it was hidden during an active task.

Data flow: It starts a task, manually hides the status indicator, then begins a unified execution startup command. The status indicator should become visible again.

Call relations: This test directly exercises the unified execution start path. It protects the visual feedback users rely on while background work is starting.

Call graph: 1 external calls (assert_eq!).

unified_exec_begin_restores_working_status_snapshot265–287 ↗
async fn unified_exec_begin_restores_working_status_snapshot()

Purpose: Checks the full rendered screen when unified execution starts after a preamble.

Data flow: It starts a task, records a preamble in history, begins unified execution, renders the chat widget, and compares the terminal output to a snapshot.

Call relations: This test combines message history, command startup, and terminal rendering. It confirms the pieces line up visually in the same order a user would experience.

Call graph: 4 external calls (new, assert_chatwidget_snapshot!, new, new).

exec_history_cell_shows_working_then_completed290–317 ↗
async fn exec_history_cell_shows_working_then_completed()

Purpose: Confirms that a successful command becomes a finalized history cell only after it ends.

Data flow: It begins an echo done command and sees no immediate history flush. After ending the command successfully, it expects one history cell containing the command summary.

Call relations: This test follows the begin/end command flow. It ensures command activity is not prematurely written to permanent history before the outcome is known.

Call graph: 2 external calls (assert!, assert_eq!).

exec_history_cell_shows_working_then_failed320–341 ↗
async fn exec_history_cell_shows_working_then_failed()

Purpose: Confirms that a failed command is also finalized into history, including its error output.

Data flow: It starts a false command, checks that nothing is flushed yet, then ends it with a failure code and stderr text. The resulting history cell must show the command and the failure text.

Call relations: This test uses the same command lifecycle as the successful case, but checks the failure branch. It protects users from losing important error information.

Call graph: 2 external calls (assert!, assert_eq!).

exec_end_without_begin_uses_event_command344–383 ↗
async fn exec_end_without_begin_uses_event_command()

Purpose: Checks that a command-end event can still render a useful history entry even if the widget never saw the matching command-start event.

Data flow: It builds a completed command execution item containing the command text, passes it to the end handler, and drains history. The history should show echo orphaned, not an internal call id.

Call relations: This test exercises the fallback path for out-of-order or incomplete event streams. It ensures the UI uses command data from the event instead of exposing backend identifiers to the user.

Call graph: calls 2 internal fn (parse_command, shlex_join); 3 external calls (assert!, assert_eq!, vec!).

exec_end_without_begin_does_not_flush_unrelated_running_exploring_cell386–426 ↗
async fn exec_end_without_begin_does_not_flush_unrelated_running_exploring_cell()

Purpose: Ensures an orphaned command completion does not disturb another command group that is still running.

Data flow: It starts an active exploring command, then starts and completes a separate orphan-like unified execution command. Only the orphan result should be inserted into history, while the original active exploring cell remains visible.

Call relations: This test checks that unrelated command records are kept separate. It protects against one command completion overwriting or flushing another command that is still active.

Call graph: 2 external calls (assert!, assert_eq!).

exec_end_without_begin_flushes_completed_unrelated_exploring_cell429–465 ↗
async fn exec_end_without_begin_flushes_completed_unrelated_exploring_cell()

Purpose: Checks that a completed exploring cell is flushed before a later standalone orphan command entry.

Data flow: It starts and completes an exploring command, then completes a separate unified execution command. The drained history should contain the completed exploring entry first and the later command second.

Call relations: This test covers ordering when the active cell is finished but not yet written out. It makes sure the transcript preserves the real sequence of work.

Call graph: 2 external calls (assert!, assert_eq!).

overlapping_exploring_exec_end_is_not_misclassified_as_orphan468–497 ↗
async fn overlapping_exploring_exec_end_is_not_misclassified_as_orphan()

Purpose: Verifies that overlapping exploring commands stay grouped when one finishes before the other.

Data flow: It starts two exploring commands, ends the first, and checks that no separate orphan history entry appears. The active cell should still show both commands under an exploring header.

Call relations: This test protects the grouping logic for multiple related file-inspection commands. It ensures a normal completion inside a group is not mistaken for an unknown command.

Call graph: 1 external calls (assert!).

exec_history_shows_unified_exec_startup_commands500–530 ↗
async fn exec_history_shows_unified_exec_startup_commands()

Purpose: Checks that commands launched as unified execution startup work appear in history after they finish.

Data flow: It begins a startup-sourced command, confirms nothing is flushed immediately, ends it successfully, and checks that the history shows the command.

Call relations: This test connects the unified execution source label to the ordinary command history path. It ensures startup commands are still visible to the user.

Call graph: 2 external calls (assert!, assert_eq!).

exec_history_shows_unified_exec_tool_calls533–547 ↗
async fn exec_history_shows_unified_exec_tool_calls()

Purpose: Verifies that a unified execution startup command can be summarized as an exploring tool call.

Data flow: It starts and ends an ls command from unified execution startup, then reads the active transcript text. The result should be a compact explored/list summary.

Call relations: This test checks the command classification layer that turns raw shell commands into friendlier activity summaries, such as “List ls.”

Call graph: 1 external calls (assert_eq!).

unified_exec_unknown_end_with_active_exploring_cell_snapshot550–576 ↗
async fn unified_exec_unknown_end_with_active_exploring_cell_snapshot()

Purpose: Snapshots what happens when an unknown unified execution end arrives while another exploring cell is active.

Data flow: It starts an exploring command, completes a separate unified execution command, combines flushed history and active text, and compares the result to a snapshot.

Call relations: This test documents a tricky mixed state: one item is active while another finishes. The snapshot guards the intended separation between history and active display.

Call graph: 2 external calls (assert_chatwidget_snapshot!, format!).

unified_exec_end_after_task_complete_is_suppressed579–601 ↗
async fn unified_exec_end_after_task_complete_is_suppressed()

Purpose: Ensures late unified execution completion events do not add stale history after the task has already completed.

Data flow: It starts a unified execution command, marks the task complete, then sends the command end. No new history cells should appear.

Call relations: This test protects the end-of-turn boundary. It makes sure old background events do not clutter the transcript after the app has moved on.

Call graph: 1 external calls (assert!).

unified_exec_interaction_after_task_complete_is_suppressed604–618 ↗
async fn unified_exec_interaction_after_task_complete_is_suppressed()

Purpose: Checks that terminal interaction events after task completion are ignored for transcript purposes.

Data flow: It starts and completes a task, then simulates terminal input/output. Draining history should return nothing.

Call relations: This test exercises the terminal interaction path after a turn is closed. It prevents late terminal polling from creating confusing entries.

Call graph: 1 external calls (assert!).

unified_exec_wait_after_final_agent_message_snapshot621–637 ↗
async fn unified_exec_wait_after_final_agent_message_snapshot()

Purpose: Snapshots the transcript when the system is waiting on a background terminal after the final assistant message.

Data flow: It starts a turn, begins a background command, records an empty terminal interaction, completes the assistant response, completes the turn, and snapshots the resulting history.

Call relations: This test ties together turn lifecycle, background waiting, assistant message completion, and transcript flushing. It documents what the user sees when work outlives the final text.

Call graph: 1 external calls (assert_chatwidget_snapshot!).

unified_exec_wait_before_streamed_agent_message_snapshot640–661 ↗
async fn unified_exec_wait_before_streamed_agent_message_snapshot()

Purpose: Snapshots the transcript when background terminal waiting happens before a streamed assistant message.

Data flow: It begins a background command, records an empty interaction, streams assistant text, completes the turn, and compares the combined history to a snapshot.

Call relations: This test covers the same waiting logic as a user would see during streaming output. It verifies the order of waiting status and assistant text.

Call graph: 1 external calls (assert_chatwidget_snapshot!).

final_worked_for_uses_cumulative_turn_duration_snapshot664–694 ↗
async fn final_worked_for_uses_cumulative_turn_duration_snapshot()

Purpose: Checks that the final “Worked for” separator uses the full turn duration reported by the backend.

Data flow: It starts a turn, runs a command, records a final answer, completes the turn with 125 seconds, and checks that history says Worked for 2m 05s.

Call relations: This test protects the final timing display. It ensures the UI does not calculate or show a shorter duration from only part of the turn.

Call graph: 2 external calls (assert!, assert_chatwidget_snapshot!).

unified_exec_wait_status_header_updates_on_late_command_display697–720 ↗
async fn unified_exec_wait_status_header_updates_on_late_command_display()

Purpose: Verifies that waiting status can show the command name even when the command display is learned later.

Data flow: It manually records a background process with command display sleep 5, sends an empty terminal interaction, and checks the status header and details.

Call relations: This test exercises the status widget update path for background terminals. It ensures users see what the app is waiting for, not just a generic message.

Call graph: 3 external calls (new, assert!, assert_eq!).

unified_exec_empty_poll_for_finished_process_does_not_show_waiting_status723–736 ↗
async fn unified_exec_empty_poll_for_finished_process_does_not_show_waiting_status()

Purpose: Ensures an empty terminal poll for an unknown or finished process does not falsely show a waiting status.

Data flow: It starts a task and sends an empty terminal interaction for a finished process id. The status should remain Working, and no wait streak should be recorded.

Call relations: This test protects against misleading background-terminal status. Empty polling alone is not enough to claim that a live process is waiting.

Call graph: 2 external calls (assert!, assert_eq!).

unified_exec_waiting_multiple_empty_snapshots739–765 ↗
async fn unified_exec_waiting_multiple_empty_snapshots()

Purpose: Snapshots the behavior after repeated empty terminal interactions while a background command is running.

Data flow: It starts a background command, sends two empty interactions, checks the waiting status and command details, completes the turn, and snapshots the resulting history.

Call relations: This test documents the wait-streak behavior. It makes sure repeated empty polls are shown as waiting in a stable, understandable way.

Call graph: 2 external calls (assert_chatwidget_snapshot!, assert_eq!).

unified_exec_wait_status_renders_command_in_single_details_row_snapshot768–785 ↗
async fn unified_exec_wait_status_renders_command_in_single_details_row_snapshot()

Purpose: Checks that a long background command is rendered in one details row in the bottom popup.

Data flow: It starts a background command with a long command line, records an empty interaction, renders the bottom popup at a fixed width, and snapshots the output.

Call relations: This test focuses on the visual status popup rather than history. It guards against line wrapping or layout changes that would make the status harder to read.

Call graph: 1 external calls (assert_chatwidget_snapshot!).

unified_exec_empty_then_non_empty_snapshot788–802 ↗
async fn unified_exec_empty_then_non_empty_snapshot()

Purpose: Snapshots the transition from waiting with empty terminal output to receiving real terminal output.

Data flow: It starts a background command, sends an empty interaction, then sends ls output/input text, drains history, and snapshots it.

Call relations: This test covers a common background process pattern: first no output, then activity. It ensures the transcript changes cleanly when real content arrives.

Call graph: 1 external calls (assert_chatwidget_snapshot!).

unified_exec_non_empty_then_empty_snapshots805–845 ↗
async fn unified_exec_non_empty_then_empty_snapshots()

Purpose: Snapshots the reverse transition: terminal activity followed by an empty wait poll.

Data flow: It starts a background command, sends non-empty terminal interaction, then an empty one, checks waiting status, snapshots active history before turn completion, completes the turn, and snapshots the final combined output.

Call relations: This test verifies that the waiting state can appear after visible terminal activity. It connects active transcript handling with final turn flushing.

Call graph: 2 external calls (assert_chatwidget_snapshot!, assert_eq!).

view_image_tool_call_adds_history_cell848–858 ↗
async fn view_image_tool_call_adds_history_cell()

Purpose: Checks that viewing a local image adds a visible history entry.

Data flow: It creates an image path under the current working directory, sends a view-image tool call, drains history, and snapshots the single resulting cell.

Call relations: This test exercises the image-view tool event path. It ensures image attachments are represented in the transcript instead of happening invisibly.

Call graph: 2 external calls (assert_chatwidget_snapshot!, assert_eq!).

image_generation_call_adds_history_cell861–895 ↗
async fn image_generation_call_adds_history_cell()

Purpose: Checks that image generation results, both success and failure, are recorded in history.

Data flow: It sends a completed image generation event with a prompt and saved file path, normalizes the file URL for snapshots, then sends a failed event without a file. Each should produce one history cell.

Call relations: This test covers the image-generation end handler. It ensures users can see what was generated or that generation failed.

Call graph: 3 external calls (assert_chatwidget_snapshot!, assert_eq!, from_file_path).

exec_history_extends_previous_when_consecutive898–944 ↗
async fn exec_history_extends_previous_when_consecutive()

Purpose: Verifies that consecutive exploration commands are grouped into one evolving history cell.

Data flow: It starts and finishes several commands such as ls, cat, and sed, checking the active transcript snapshot after each step. The display should grow as one exploration sequence rather than separate unrelated entries.

Call relations: This test exercises command classification and grouping over time. It protects the friendly “Exploring” summary behavior for file-browsing commands.

Call graph: 1 external calls (assert_chatwidget_snapshot!).

user_shell_command_renders_output_not_exploring947–972 ↗
async fn user_shell_command_renders_output_not_exploring()

Purpose: Ensures commands typed by the user are shown with their output, not folded into assistant-style exploration summaries.

Data flow: It starts an ls command with source UserShell, ends it with two output lines, drains history, and snapshots the rendered result.

Call relations: This test distinguishes user-run shell commands from assistant tool commands. It keeps user shell output explicit and transparent.

Call graph: 2 external calls (assert_chatwidget_snapshot!, assert_eq!).

bang_shell_enter_while_task_running_submits_run_user_shell_command975–1019 ↗
async fn bang_shell_enter_while_task_running_submits_run_user_shell_command()

Purpose: Checks that typing !command during a running task submits it as a user shell command.

Data flow: It sets up a thread session, starts a turn, puts !echo hi in the composer, presses Enter, and checks that the operation channel receives RunUserShellCommand with echo hi. It also checks that the typed line is appended to message history.

Call relations: This test goes through the real keyboard input path. It verifies the handoff from chat input to the operation channel while a task is already running.

Call graph: calls 2 internal fn (read_only, new); 7 external calls (new, new, default, new, assert_eq!, assert_matches!, panic!).

user_message_during_user_shell_command_is_queued_not_steered1022–1061 ↗
async fn user_message_during_user_shell_command_is_queued_not_steered()

Purpose: Ensures a normal user message typed while only user shell commands are running is queued for the next turn, not sent as steering input.

Data flow: It starts a turn and a long user shell command, types hi, presses Enter, and confirms no operation is sent immediately. After the shell command and assistant turn complete, the queued message is submitted as a normal user turn.

Call relations: This test protects the input queue behavior around user shell commands. It keeps ordinary messages from being misrouted while shell work is still active.

Call graph: calls 1 internal fn (new); 6 external calls (new, new, assert!, assert_eq!, assert_matches!, panic!).

disabled_slash_command_while_task_running_snapshot1064–1080 ↗
async fn disabled_slash_command_while_task_running_snapshot()

Purpose: Checks that a slash command unavailable during a running task shows a clear error in history.

Data flow: It marks the bottom pane as running, dispatches the /model command, drains history, and snapshots the emitted error cell.

Call relations: This test exercises command dispatch while busy. It ensures the user gets feedback instead of nothing happening.

Call graph: 2 external calls (assert!, assert_chatwidget_snapshot!).

approval_modal_exec_snapshot1088–1142 ↗
async fn approval_modal_exec_snapshot() -> anyhow::Result<()>

Purpose: Snapshots the full command approval modal when a reason and proposed execution-policy amendment are present.

Data flow: It configures approval-on-request, injects a command approval request, renders the widget into a fake terminal, checks that the command text appears, and snapshots the screen.

Call relations: This test drives the approval modal rendering path. It documents the exact user-facing layout for command approval.

Call graph: calls 3 internal fn (with_options, new, current_dir); 4 external calls (new, assert!, assert_chatwidget_snapshot!, vec!).

approval_modal_exec_without_reason_snapshot1147–1185 ↗
async fn approval_modal_exec_without_reason_snapshot() -> anyhow::Result<()>

Purpose: Snapshots the command approval modal when no reason text is provided.

Data flow: It creates an approval request without a reason, renders the modal, and compares the terminal contents to a snapshot.

Call relations: This test focuses on modal spacing and wording for the no-reason case. It prevents blank reason areas from leaving awkward layout gaps.

Call graph: calls 2 internal fn (new, current_dir); 4 external calls (new, assert_chatwidget_snapshot!, new, vec!).

approval_modal_exec_multiline_prefix_hides_execpolicy_option_snapshot1190–1231 ↗
async fn approval_modal_exec_multiline_prefix_hides_execpolicy_option_snapshot() -> anyhow::Result<()>

Purpose: Checks that a multiline proposed execution-policy command does not offer a “don’t ask again” style option.

Data flow: It creates a multiline shell script approval request with a proposed policy amendment, renders the modal, confirms the policy option is absent, and snapshots the output.

Call relations: This test protects a safety-related approval detail. It ensures only suitable single-line command prefixes can be added to the execution policy.

Call graph: calls 2 internal fn (new, current_dir); 5 external calls (new, assert!, assert_chatwidget_snapshot!, new, vec!).

approval_modal_patch_snapshot1235–1272 ↗
async fn approval_modal_patch_snapshot() -> anyhow::Result<()>

Purpose: Snapshots the patch approval modal for a small file change.

Data flow: It builds a patch request that adds a README file, includes a reason and grant root, renders the modal, confirms it does not show a raw $ apply_patch command, and snapshots the screen.

Call relations: This test exercises the file-edit approval UI. It makes sure users see a human-friendly edit prompt rather than internal patch mechanics.

Call graph: calls 1 internal fn (new); 6 external calls (new, from, new, assert!, assert_chatwidget_snapshot!, new).

interrupt_preserves_unified_exec_processes1275–1303 ↗
async fn interrupt_preserves_unified_exec_processes()

Purpose: Ensures interrupting a turn does not forget running background terminal processes.

Data flow: It starts two unified execution processes, interrupts the turn, confirms both process records remain, then runs the process-list output and checks both commands are listed.

Call relations: This test connects interruption handling with the /ps background-process display. It protects long-running background work from disappearing after an interrupt.

Call graph: 2 external calls (assert!, assert_eq!).

interrupt_preserves_unified_exec_wait_streak_snapshot1306–1325 ↗
async fn interrupt_preserves_unified_exec_wait_streak_snapshot()

Purpose: Snapshots behavior when a waiting background terminal survives a turn interrupt.

Data flow: It starts a turn, begins a background command, records an empty terminal interaction, interrupts the turn, ends the command, drains history, and snapshots the number and text of emitted cells.

Call relations: This test covers a subtle state handoff across interruption. It ensures wait-tracking is preserved enough to finish cleanly.

Call graph: 2 external calls (assert_chatwidget_snapshot!, format!).

turn_complete_keeps_unified_exec_processes1328–1356 ↗
async fn turn_complete_keeps_unified_exec_processes()

Purpose: Ensures completing a turn does not remove still-running background terminal processes.

Data flow: It starts two background processes, completes the turn, confirms both remain, then asks the widget to show process output and checks both commands are listed.

Call relations: This test protects background terminal continuity across turn completion. It keeps /ps useful after the assistant’s turn ends.

Call graph: 2 external calls (assert!, assert_eq!).

apply_patch_events_emit_history_cells1359–1420 ↗
async fn apply_patch_events_emit_history_cells()

Purpose: Checks the basic patch event flow: approval request, apply begin, and apply end.

Data flow: It sends a patch approval request and expects no immediate history because the modal is used. Then it sends patch-apply begin and expects a per-file history cell, while a successful apply end emits no extra success cell.

Call relations: This test follows patch events as the backend would send them. It confirms the transcript shows the actual edit application at the right moment.

Call graph: 3 external calls (new, from, assert!).

apply_patch_manual_approval_adjusts_header1423–1462 ↗
async fn apply_patch_manual_approval_adjusts_header()

Purpose: Verifies that a patch applied after manual approval gets the right file-oriented header.

Data flow: It sends a patch approval request, then a patch-apply begin event for the same file, drains history, and checks that the header says the file was added or edited.

Call relations: This test links the manual approval state to later patch rendering. It ensures approved edits are described clearly in history.

Call graph: 3 external calls (new, from, assert!).

apply_patch_manual_flow_snapshot1465–1508 ↗
async fn apply_patch_manual_flow_snapshot()

Purpose: Snapshots the history entry produced when a manually approved patch begins applying.

Data flow: It creates a patch approval request with a reason, verifies no history appears before application, then sends apply begin and snapshots the resulting approved patch cell.

Call relations: This test documents the user-visible manual patch flow. It protects the wording shown after the user has reviewed an edit.

Call graph: 4 external calls (new, from, assert!, assert_chatwidget_snapshot!).

apply_patch_approval_sends_op_with_call_id1511–1551 ↗
async fn apply_patch_approval_sends_op_with_call_id()

Purpose: Checks that approving a patch sends a patch approval operation using the backend call id.

Data flow: It sends a patch approval request, presses y, then reads outgoing app events until it finds a patch approval operation. The operation must contain call-999 and an accept decision.

Call relations: This test follows the patch modal’s keyboard approval path to the operation submitted back to the app. It ensures the backend can match the answer to the original patch request.

Call graph: 7 external calls (new, Char, new, from, assert!, assert_eq!, assert_matches!).

apply_patch_full_flow_integration_like1554–1621 ↗
async fn apply_patch_full_flow_integration_like()

Purpose: Exercises an integration-like patch approval path from backend request through user approval and forwarded operation.

Data flow: It sends a patch approval request, approves it by key press, captures the resulting app operation, submits it through the widget, verifies it reaches the operation channel, then simulates patch begin and end events.

Call relations: This test stitches together several layers that are usually separated in smaller tests: modal approval, app event submission, operation forwarding, and later patch events.

Call graph: 7 external calls (new, Char, new, from, assert_eq!, assert_matches!, panic!).

apply_patch_untrusted_shows_approval_modal1624–1672 ↗
async fn apply_patch_untrusted_shows_approval_modal() -> anyhow::Result<()>

Purpose: Verifies that in an approval-required configuration, an untrusted patch request shows the patch approval modal.

Data flow: It sets approval-on-request, sends a patch approval request, renders the widget into a buffer, and scans the buffer for the modal title asking whether to make the edits.

Call relations: This test checks the visible safety gate for file edits. It ensures patch requests are not silently accepted when approval is required.

Call graph: 6 external calls (empty, new, from, new, new, assert!).

apply_patch_request_omits_diff_summary_from_modal1675–1725 ↗
async fn apply_patch_request_omits_diff_summary_from_modal() -> anyhow::Result<()>

Purpose: Ensures the patch approval modal does not include detailed diff summary lines.

Data flow: It sends a patch request adding two lines to README, confirms no history is emitted, renders the modal, and checks that filename summary and added-line text are absent.

Call relations: This test focuses on what the approval modal deliberately leaves out. It protects the intended simplified approval prompt from accidentally becoming a noisy diff viewer.

Call graph: 6 external calls (new, from, new, new, assert!, empty).

tui/src/chatwidget/tests/goal_menu.rssource ↗
testtest run

This is a test file for the chat widget in the text-based user interface. A “goal” here is a saved task or objective attached to a chat thread, with a status such as active, paused, blocked, or complete. These tests make sure the widget shows the right text for each goal state and sends the right events when the user chooses an action.

Several tests are snapshot tests. A snapshot is like a saved photograph of the screen: the test renders the widget and compares it with a known-good version. If the menu wording, spacing, or layout changes, the test catches it.

Other tests simulate user input, such as pressing Enter, pressing Down, or pasting extra text into an edit prompt. They then check the outgoing app events. This matters because the chat widget itself does not directly change the whole application state. Instead, it sends messages such as “update this goal” or “resume this goal” to the rest of the app.

The important behavior is about status safety. Editing a paused or temporarily stopped goal keeps its status, but editing a terminal goal, such as complete or budget-limited, turns it back into active. This prevents confusing states where a newly edited goal still looks finished or unusable.

Function details14
goal_menu_active_snapshot4–15 ↗
async fn goal_menu_active_snapshot()

Purpose: Checks that an active goal is rendered in the goal summary menu exactly as expected. This protects the visible menu for the normal “currently running” state.

Data flow: The test creates a fresh chat widget, makes a new thread id, builds a sample active goal with a token budget, and shows that goal in the widget. It then collects the rendered goal summary and compares it to the saved snapshot named for the active menu.

Call relations: The async test runner calls this test. Inside it, ThreadId::new supplies a unique thread id, test_goal builds the sample data, and the snapshot assertion records whether the rendered output still matches the expected screen.

Call graph: calls 2 internal fn (new, test_goal); 1 external calls (assert_chatwidget_snapshot!).

goal_menu_paused_snapshot18–29 ↗
async fn goal_menu_paused_snapshot()

Purpose: Checks that a paused goal is shown correctly in the goal summary menu. This makes sure users see the right options and wording when work on a goal has been paused.

Data flow: The test starts with a fresh chat widget and a new thread id, then builds a sample goal marked paused and without a token budget. After the widget shows the goal summary, the rendered text is gathered and compared with the paused-goal snapshot.

Call relations: The async test runner invokes this test during the suite. It uses ThreadId::new for identity, test_goal for consistent sample goal data, and the snapshot assertion to detect unwanted changes in the paused-state display.

Call graph: calls 2 internal fn (new, test_goal); 1 external calls (assert_chatwidget_snapshot!).

goal_menu_blocked_snapshot32–43 ↗
async fn goal_menu_blocked_snapshot()

Purpose: Checks the goal summary menu for a blocked goal. A blocked goal is one that cannot continue until something changes, so the interface needs to communicate that clearly.

Data flow: The test creates a chat widget, makes a thread id, builds a sample goal with blocked status, and asks the widget to display it. It drains the rendered summary text and compares that text against the expected blocked-goal snapshot.

Call relations: The test runner calls this as part of the UI test set. ThreadId::new and test_goal provide the setup, while the snapshot assertion verifies the final rendered menu.

Call graph: calls 2 internal fn (new, test_goal); 1 external calls (assert_chatwidget_snapshot!).

goal_menu_usage_limited_snapshot46–57 ↗
async fn goal_menu_usage_limited_snapshot()

Purpose: Checks the goal summary menu for a goal stopped by usage limits. This protects the wording and layout for the case where the app cannot continue because a usage limit has been reached.

Data flow: A fresh chat widget receives a sample goal whose status is usage-limited. The test renders the goal summary, turns it into a plain string, and compares it with the stored usage-limited snapshot.

Call relations: The async test runner starts this test. It relies on ThreadId::new for a fresh id, test_goal for repeatable goal data, and the snapshot assertion to flag visual changes.

Call graph: calls 2 internal fn (new, test_goal); 1 external calls (assert_chatwidget_snapshot!).

goal_menu_budget_limited_snapshot60–71 ↗
async fn goal_menu_budget_limited_snapshot()

Purpose: Checks the goal summary menu for a goal that has hit its token budget. A token budget is a limit on how much model usage the goal may spend, so this state needs a distinct display.

Data flow: The test creates a chat widget and sample goal with budget-limited status and an 80,000-token budget. It shows the summary, collects the rendered output from the event receiver, and compares it to the budget-limited snapshot.

Call relations: The test runner calls this function with the other snapshot tests. ThreadId::new and test_goal prepare the goal, and the snapshot assertion confirms that the budget-limit screen remains stable.

Call graph: calls 2 internal fn (new, test_goal); 1 external calls (assert_chatwidget_snapshot!).

resume_paused_goal_prompt_snapshot74–87 ↗
async fn resume_paused_goal_prompt_snapshot()

Purpose: Checks the popup that asks whether to resume a paused goal. This ensures the confirmation prompt looks right before the user chooses to continue or leave the goal paused.

Data flow: The test creates a chat widget, makes a thread id, and opens the resume-paused-goal prompt with a sample objective sentence. It renders the bottom popup at a fixed width and compares the result with the saved snapshot.

Call relations: The async test runner invokes this snapshot test. It uses ThreadId::new for the goal identity and the snapshot assertion to compare the rendered popup with the expected prompt.

Call graph: calls 1 internal fn (new); 1 external calls (assert_chatwidget_snapshot!).

goal_edit_prompt_snapshot90–107 ↗
async fn goal_edit_prompt_snapshot()

Purpose: Checks the popup used to edit an existing goal. It makes sure the editing prompt, including the current goal text, appears correctly to the user.

Data flow: The test creates a chat widget, builds an active sample goal with a token budget, and opens the edit prompt for that goal. It renders the bottom popup at a fixed width and compares it with the stored edit-prompt snapshot.

Call relations: The test runner calls this function during UI snapshot testing. It gets a fresh thread id from ThreadId::new, gets sample goal contents from test_goal, and uses the snapshot assertion to catch accidental visual changes.

Call graph: calls 2 internal fn (new, test_goal); 1 external calls (assert_chatwidget_snapshot!).

goal_edit_prompt_submits_preserved_status_and_budget110–146 ↗
async fn goal_edit_prompt_submits_preserved_status_and_budget()

Purpose: Checks that editing a paused goal submits the new wording without losing its paused status or token budget. This prevents a simple text edit from accidentally resuming or changing the limits of a goal.

Data flow: The test opens the edit prompt for a paused goal with a token budget. It pastes extra words, presses Enter, reads the outgoing app event, and checks that the event contains the updated objective, the same thread id, the paused status, and the original budget. It also checks that the popup closes afterward.

Call relations: The test runner starts this scenario. It uses ThreadId::new and test_goal for setup, converts Enter into a key event with from, and then uses equality checks or a panic to confirm that the chat widget sent the expected SetThreadGoalDraft event.

Call graph: calls 2 internal fn (new, test_goal); 4 external calls (from, assert!, assert_eq!, panic!).

goal_edit_prompt_preserves_resumable_stopped_statuses149–182 ↗
async fn goal_edit_prompt_preserves_resumable_stopped_statuses()

Purpose: Checks that editing certain stopped goals keeps their stopped status. Blocked and usage-limited goals can later become resumable, so editing their text should not automatically mark them active.

Data flow: For each stopped status, the test creates a fresh chat widget and sample goal, opens the edit prompt, and presses Enter without changing the text. It reads the outgoing update event and confirms that the status and token budget are still the same as before.

Call relations: The async test runner calls this test, and the test loops through the stopped statuses. It uses ThreadId::new and test_goal for each case, from to create the Enter key event, and assertions to verify the event sent by the widget.

Call graph: calls 2 internal fn (new, test_goal); 3 external calls (from, assert_eq!, panic!).

goal_edit_prompt_resets_terminal_status_to_active185–220 ↗
async fn goal_edit_prompt_resets_terminal_status_to_active()

Purpose: Checks that editing a terminal goal turns it back into an active goal. Terminal statuses such as budget-limited or complete mean the old run is over, so a newly submitted edit should start fresh rather than stay ended.

Data flow: The test tries two terminal statuses. For each one, it opens the edit prompt, presses Enter, receives the outgoing goal-update event, and verifies that the submitted status is active while the original token budget is preserved.

Call relations: The test runner invokes this scenario with the other goal edit tests. ThreadId::new and test_goal build each case, from creates the Enter key event, and the assertions confirm that the widget converts terminal statuses to active before handing off the update.

Call graph: calls 2 internal fn (new, test_goal); 3 external calls (from, assert_eq!, panic!).

resume_paused_goal_prompt_default_resumes_goal223–241 ↗
async fn resume_paused_goal_prompt_default_resumes_goal()

Purpose: Checks the default choice in the resume prompt: pressing Enter immediately resumes the paused goal. This makes sure the quickest path in the prompt does what users would expect.

Data flow: The test opens the resume prompt for a paused goal, presses Enter, and reads the outgoing app event. It confirms that the event targets the same thread id and sets the goal status to active, then checks that the prompt is closed.

Call relations: The async test runner calls this test. It uses ThreadId::new for identity, from to turn Enter into a key event, and assertions to verify that the widget sends SetThreadGoalStatus with active status.

Call graph: calls 1 internal fn (new); 4 external calls (from, assert!, assert_eq!, panic!).

resume_paused_goal_prompt_can_leave_goal_paused244–254 ↗
async fn resume_paused_goal_prompt_can_leave_goal_paused()

Purpose: Checks that the user can choose not to resume a paused goal. This protects the alternate path where the prompt closes without changing application state.

Data flow: The test opens the resume prompt, presses Down to move to the non-resume choice, and presses Enter. It then checks that no app event was sent and that the popup is no longer active.

Call relations: The test runner invokes this interaction test. It uses ThreadId::new to set up the prompt and from to create the Down and Enter key events; the final assertion confirms that the event receiver stayed empty.

Call graph: calls 1 internal fn (new); 2 external calls (from, assert!).

test_goal256–272 ↗
fn test_goal(
    thread_id: ThreadId,
    status: AppThreadGoalStatus,
    token_budget: Option<i64>,
) -> AppThreadGoal

Purpose: Builds a repeatable sample goal for the tests in this file. It keeps the test setup short and consistent so each test can focus on one behavior.

Data flow: The function receives a thread id, a goal status, and an optional token budget. It turns the thread id into text and returns an AppThreadGoal filled with a fixed objective, usage numbers, timestamps, the supplied status, and the supplied budget.

Call relations: The snapshot and edit-behavior tests call this helper whenever they need a realistic goal object. By centralizing the sample data here, those tests can vary only the status or budget that matters for the case being checked.

Call graph: called by 9 (goal_edit_prompt_preserves_resumable_stopped_statuses, goal_edit_prompt_resets_terminal_status_to_active, goal_edit_prompt_snapshot, goal_edit_prompt_submits_preserved_status_and_budget, goal_menu_active_snapshot, goal_menu_blocked_snapshot, goal_menu_budget_limited_snapshot, goal_menu_paused_snapshot, goal_menu_usage_limited_snapshot); 1 external calls (to_string).

rendered_goal_summary274–282 ↗
fn rendered_goal_summary(
    rx: &mut tokio::sync::mpsc::UnboundedReceiver<crate::app_event::AppEvent>,
) -> String

Purpose: Turns the chat widget’s rendered goal-summary events into one plain string for snapshot comparison. This gives the snapshot tests a clean text version of what the user would see.

Data flow: The function receives the app-event receiver used by the test. It drains inserted history entries from that receiver, converts each group of rendered lines into a single string, joins the groups with newlines, and returns the final text.

Call relations: The goal summary snapshot tests use this helper after showing a goal summary. It sits between the widget’s event output and the snapshot assertion, translating structured rendered lines into comparable text.

tui/src/chatwidget/tests/goal_validation.rssource ↗
testtest run

This is a test file for the terminal chat interface. Its focus is the /goal command, which lets a user turn typed text into a draft goal for the current conversation thread. The important behavior is that this command should be routed to goal-setting code, not submitted as an ordinary message to the assistant.

The tests build a manual ChatWidget, turn on the Goals feature, attach a fresh thread id, then simulate what a user would do in the composer: type text, press keys, paste large content, or queue input while another assistant turn is still running. Think of the composer like a notepad at the bottom of the screen. These tests check that when the notepad starts with /goal, the app files that text into the “goal draft” tray rather than mailing it as a chat request.

Several edge cases matter here. A goal at the official character limit must be accepted. A goal longer than that is still emitted as a draft, so later validation or display code can decide what to do. Large pasted text may be represented by a placeholder in the visible composer, but the real pasted content must still be preserved. The queued-input test also checks that when a queued /goal is processed after a running turn ends, it consumes only that queued item and does not start a normal submit operation.

Function details11
complete_turn_with_message5–15 ↗
fn complete_turn_with_message(chat: &mut ChatWidget, turn_id: &str, message: Option<&str>)

Purpose: This helper finishes a fake assistant turn during a test. It can optionally add a final assistant message before marking the turn complete.

Data flow: It receives a mutable chat widget, a turn id, and optional message text. If message text is present, it creates a final assistant message tied to that turn. Then it marks the turn as completed, leaving the chat widget in the same state it would be after the assistant finished responding.

Call relations: The queued-goal test calls this after it has placed messages into the input queue. By ending the in-progress turn, it triggers the chat widget to process the next queued item, which is how the test checks that a queued /goal command is treated correctly.

Call graph: called by 1 (queued_goal_slash_command_emits_oversized_objective_and_stops_queue); 1 external calls (format!).

submit_composer_text17–21 ↗
fn submit_composer_text(chat: &mut ChatWidget, text: &str)

Purpose: This helper puts text into the chat composer and submits it as if the user had typed it and pressed the needed keys.

Data flow: It takes a chat widget and the text to submit. It writes that text into the bottom composer, with no pending images or pasted-content records, then hands off to submit_current_composer to simulate the key presses that submit the current composer contents.

Call relations: Several goal-command tests use this helper so they do not repeat the same setup steps. It delegates the actual keyboard simulation to submit_current_composer, keeping each test focused on the goal text being checked.

Call graph: calls 1 internal fn (submit_current_composer); called by 3 (goal_slash_command_accepts_multiline_objective_after_blank_first_line, goal_slash_command_accepts_objective_at_limit, goal_slash_command_emits_oversized_objective); 1 external calls (new).

submit_current_composer23–27 ↗
fn submit_current_composer(chat: &mut ChatWidget)

Purpose: This helper simulates the key presses needed to submit whatever is already in the composer.

Data flow: It receives a mutable chat widget. It sends an Escape key event, then two Enter key events, into the widget. The chat widget reacts to those events just as it would during real terminal use, which causes the current composer content to be submitted or confirmed.

Call relations: This is the shared submission step used directly by paste-related tests and indirectly by submit_composer_text. It hands control to the chat widget’s keyboard-event logic, so the tests exercise the real user-facing path rather than calling a lower-level command parser directly.

Call graph: called by 3 (goal_slash_command_emits_only_inserted_paste_text_element, goal_slash_command_preserves_large_pasted_objective, submit_composer_text); 2 external calls (new, handle_key_event).

queue_composer_text_with_tab29–33 ↗
fn queue_composer_text_with_tab(chat: &mut ChatWidget, text: &str)

Purpose: This helper puts text into the composer and queues it using the Tab key instead of submitting it immediately.

Data flow: It receives a chat widget and some text. It writes the text into the composer, then sends a Tab key event. The result is that the chat widget records the text in its input queue, ready to be processed later when the current assistant turn is done.

Call relations: The queued-goal test uses this twice: once for a /goal command and once for a normal follow-up message. This lets the test verify that processing the queued goal consumes only the goal item and leaves the next queued message waiting.

Call graph: called by 1 (queued_goal_slash_command_emits_oversized_objective_and_stops_queue); 3 external calls (new, new, handle_key_event).

next_goal_objective35–49 ↗
fn next_goal_objective(
    rx: &mut tokio::sync::mpsc::UnboundedReceiver<AppEvent>,
    expected_thread_id: ThreadId,
) -> String

Purpose: This helper pulls events from the app event channel until it finds a goal draft event, then returns just the goal objective text.

Data flow: It receives an event receiver and the thread id the test expects. It repeatedly tries to read the next event. When it finds a SetThreadGoalDraft event, it checks that the event belongs to the expected thread, then returns the draft’s objective string.

Call relations: Tests use this when they only care about the objective text inside the emitted goal draft. It hides the event-channel details so the test can read like: submit a goal command, then check the objective that came out.

Call graph: 2 external calls (try_recv, assert_eq!).

goal_slash_command_accepts_objective_at_limit52–74 ↗
async fn goal_slash_command_accepts_objective_at_limit()

Purpose: This test proves that a /goal command whose objective is exactly at the configured maximum length is accepted as a goal draft.

Data flow: It creates a chat widget, enables the Goals feature, assigns a thread id, and builds an objective string exactly as long as MAX_THREAD_GOAL_OBJECTIVE_CHARS. After submitting /goal <objective>, it reads the next app event and checks that the event is a goal draft for the same thread with the same objective. It also checks that no normal submit operation was started.

Call relations: The Tokio test runner runs this as an asynchronous test. It uses submit_composer_text to exercise the real composer submission path, then inspects the emitted app event to confirm the slash command went to goal drafting instead of ordinary chat submission.

Call graph: calls 2 internal fn (new, submit_composer_text); 3 external calls (assert_eq!, format!, panic!).

goal_slash_command_accepts_multiline_objective_after_blank_first_line77–98 ↗
async fn goal_slash_command_accepts_multiline_objective_after_blank_first_line()

Purpose: This test checks that /goal can accept a multiline objective even when the command is followed by blank lines before the real text starts.

Data flow: It creates a chat widget with Goals enabled and a thread id. It submits text shaped like /goal, then blank lines, then a two-line objective. The expected result is a goal draft event whose objective keeps the meaningful two-line text and belongs to the current thread, with no normal submit operation.

Call relations: The test runner invokes this case to protect a user-facing convenience: people may paste or type goal text with leading blank lines. It uses submit_composer_text to send the text through the same path as real composer input.

Call graph: calls 2 internal fn (new, submit_composer_text); 3 external calls (assert_eq!, format!, panic!).

goal_slash_command_emits_oversized_objective101–112 ↗
async fn goal_slash_command_emits_oversized_objective()

Purpose: This test checks that an objective longer than the configured maximum is still emitted as a goal draft rather than being lost or sent as a normal chat message.

Data flow: It creates a chat widget, enables Goals, sets the current thread, and builds an objective one character longer than the maximum. After submitting /goal <objective>, it reads the emitted goal objective and checks that the full oversized text is still present. It also confirms that no normal submit operation happened.

Call relations: The test runner uses this case to guard against accidental truncation or misrouting. The test relies on submit_composer_text for the user action and next_goal_objective for reading the resulting draft objective from the event stream.

Call graph: calls 2 internal fn (new, submit_composer_text); 2 external calls (assert_eq!, format!).

goal_slash_command_preserves_large_pasted_objective115–134 ↗
async fn goal_slash_command_preserves_large_pasted_objective()

Purpose: This test makes sure a large paste used as a goal objective is preserved in full, even though the composer displays it as a placeholder.

Data flow: It starts with /goal already in the composer, then simulates pasting a very large objective. The visible composer should contain a [Pasted Content ...] placeholder instead of the whole paste. After submission, the emitted goal draft should contain the real pasted text in its pending-pastes list. No normal chat submit operation should be started.

Call relations: The test runner invokes this paste-specific case. It calls submit_current_composer because the composer has already been prepared through direct text setting and paste simulation, and then it checks the resulting goal draft event.

Call graph: calls 2 internal fn (new, submit_current_composer); 3 external calls (new, assert!, assert_eq!).

queued_goal_slash_command_emits_oversized_objective_and_stops_queue137–154 ↗
async fn queued_goal_slash_command_emits_oversized_objective_and_stops_queue()

Purpose: This test checks what happens when a /goal command is queued while another assistant turn is still running. The goal should be processed as a goal draft, and the queue should stop after that item instead of immediately continuing as if it were normal chat input.

Data flow: It creates a chat widget with Goals enabled, starts a fake assistant turn, then queues two items: an oversized /goal command and a normal continue message. After the fake turn completes, the widget processes the first queued item. The test checks that the emitted goal objective is the full oversized text, that one queued message remains, and that no normal submit operation was started.

Call relations: This test ties together the queue helper and the turn-completion helper. queue_composer_text_with_tab builds the queue, and complete_turn_with_message ends the active turn so the widget naturally advances to the next queued input.

Call graph: calls 3 internal fn (new, complete_turn_with_message, queue_composer_text_with_tab); 2 external calls (assert_eq!, format!).

goal_slash_command_emits_only_inserted_paste_text_element157–184 ↗
async fn goal_slash_command_emits_only_inserted_paste_text_element()

Purpose: This test checks a subtle paste case: if the user typed text that looks like a paste placeholder, the app must not confuse that typed text with the real pasted content.

Data flow: It creates a large paste and the placeholder text that represents it. The composer starts with /goal keep literal <placeholder> and as normal typed text. Then the test performs an actual paste, which inserts another placeholder tied to real pasted content. After submission, the draft objective should include both placeholder strings as visible text, but the pending-pastes list should contain only the actually inserted paste. The composer’s pending-paste storage should then be empty, and no normal submit operation should happen.

Call relations: The test runner uses this to protect the boundary between ordinary typed text and special pasted-content records. It calls submit_current_composer after setting up both a literal placeholder and a real paste, then checks that the emitted draft keeps only the true paste as pending pasted content.

Call graph: calls 2 internal fn (new, submit_current_composer); 4 external calls (new, assert!, assert_eq!, format!).

tui/src/chatwidget/tests/guardian.rssource ↗
testtest run

These tests make sure the terminal chat widget tells the user the right story when an action is being reviewed, approved, denied, or timed out. Without this file, changes to the interface could quietly hide a safety denial, show the wrong command, forget an in-progress review, or send duplicate approval messages back to the core system.

The tests build a chat widget in a controlled test setup, feed it Guardian events, then inspect either its internal status text or the terminal output it renders. Some tests use snapshot checks, which compare the displayed screen against a saved expected version, much like comparing a printed receipt to a known-good template. Others check the events sent out of the widget, such as making sure approving a recent denial sends exactly one structured operation.

The file covers two sources of Guardian information: direct internal Guardian assessment events and app-server notification messages. It also checks several action types, including shell commands and permission requests. A few tests focus on parallel reviews, where more than one approval check is running at the same time, to ensure the remaining review stays visible after another one finishes.

Function details12
auto_review_denial_event4–22 ↗
fn auto_review_denial_event() -> GuardianAssessmentEvent

Purpose: This helper builds a realistic Guardian denial event for reuse in tests. It represents an automatic review blocking a shell command because it would send a local source file to an external website.

Data flow: It takes no input. It fills in a Guardian assessment record with fixed IDs, a denied status, high risk, low user authorization, a written reason, and a shell command action. It returns that complete event so tests can feed it into the chat widget.

Call relations: The popup test and the approval-emission test call this helper when they need the same stored denial scenario. By centralizing the event, those tests stay focused on the widget behavior instead of rebuilding the same Guardian message each time.

Call graph: called by 2 (approving_recent_denial_emits_structured_core_op_once, auto_review_denials_popup_lists_stored_auto_review_denials).

auto_review_denials_popup_lists_stored_auto_review_denials25–35 ↗
async fn auto_review_denials_popup_lists_stored_auto_review_denials()

Purpose: This test checks that the chat widget remembers recent automatic review denials and shows them in the auto-review denials popup. It protects the user-facing list that explains what was blocked.

Data flow: It creates a manual chat widget, gives it a thread ID, sends in the reusable denial event, and drains any generated history updates. Then it opens the denials popup, renders the bottom popup at a fixed width, and compares the result to a saved snapshot.

Call relations: The asynchronous test runner calls this test. Inside the test, it uses auto_review_denial_event to create the denied Guardian assessment, then relies on the snapshot assertion to verify the rendered popup.

Call graph: calls 2 internal fn (new, auto_review_denial_event); 1 external calls (assert_chatwidget_snapshot!).

approving_recent_denial_emits_structured_core_op_once38–61 ↗
async fn approving_recent_denial_emits_structured_core_op_once()

Purpose: This test makes sure that when a user approves a recent Guardian denial, the widget sends one clear operation back to the core system, and does not send it again if the same denial is approved twice. This prevents duplicate approvals for the same risky action.

Data flow: It creates a chat widget and thread ID, feeds in the reusable denial event, and clears initial history messages. It asks the widget to approve that denial, then reads the outgoing event channel to confirm it contains an ApproveGuardianDeniedAction operation with the expected thread and event ID. It tries the same approval again and confirms no second core operation is emitted, apart from normal history-cell updates.

Call relations: The test runner starts this function. It calls auto_review_denial_event to set up the denied action, then uses pattern-matching assertions to inspect what the widget sends out through its application event channel.

Call graph: calls 2 internal fn (new, auto_review_denial_event); 2 external calls (assert!, assert_matches!).

guardian_denied_exec_renders_warning_and_denied_request64–125 ↗
async fn guardian_denied_exec_renders_warning_and_denied_request()

Purpose: This test checks the terminal display for a shell command that Guardian denies. It verifies that both the warning and the denied request appear in the chat history.

Data flow: It creates a chat widget, hides the welcome banner, and builds a risky curl command action. It sends an in-progress Guardian event, then a warning message, then a completed denied Guardian event. It drains rendered history lines into a virtual terminal, draws the widget, normalizes machine-specific paths, and compares the screen to a snapshot.

Call relations: The async test harness calls this function. The test drives the chat widget through its Guardian event methods, uses terminal setup helpers to render the result, passes history through insert_history_lines, and finishes with a snapshot comparison.

Call graph: calls 3 internal fn (with_options, insert_history_lines, new); 2 external calls (new, assert_chatwidget_snapshot!).

guardian_approved_exec_renders_approved_request128–173 ↗
async fn guardian_approved_exec_renders_approved_request()

Purpose: This test checks how an approved shell command review appears in the chat history. It ensures the interface records that Guardian approved the request instead of leaving the user guessing.

Data flow: It creates a chat widget, hides the welcome banner, and sends a completed approved Guardian event for a shell command. It calculates the terminal size needed by the widget, inserts any produced history lines into a virtual terminal, draws the widget, and compares the final screen against the expected snapshot.

Call relations: The test runner invokes it. The test feeds a finished Guardian approval directly into the chat widget, then hands the resulting history to the terminal rendering helpers before the snapshot assertion checks the visible result.

Call graph: calls 3 internal fn (with_options, insert_history_lines, new); 2 external calls (new, assert_chatwidget_snapshot!).

guardian_approved_request_permissions_renders_request_summary176–251 ↗
async fn guardian_approved_request_permissions_renders_request_summary()

Purpose: This test covers Guardian review of a permission request rather than a shell command. It confirms that the status area and final history summary explain the permission request in human-readable terms.

Data flow: It creates a permission request asking for write access to a reports folder, then sends an in-progress Guardian event. It reads the bottom-pane status widget and checks that the header says a review is happening and the details include the reason for the permission request. Then it sends an approved completion event, renders the chat into a virtual terminal, and compares the result with a snapshot.

Call relations: The async test runner calls this test. It uses the permission-building helper for file-system access, checks status text with equality assertions, then uses the same virtual-terminal and snapshot path as the rendering tests.

Call graph: calls 4 internal fn (from_read_write_roots, with_options, insert_history_lines, new); 5 external calls (new, default, assert_chatwidget_snapshot!, assert_eq!, vec!).

guardian_timed_out_exec_renders_warning_and_timed_out_request254–317 ↗
async fn guardian_timed_out_exec_renders_warning_and_timed_out_request()

Purpose: This test checks the display when Guardian does not finish reviewing a shell command in time. It ensures the user sees both the timeout warning and a history entry showing that the request timed out.

Data flow: It creates a chat widget and a risky shell command action, sends an in-progress Guardian event, adds a timeout warning, and then sends a completed event with timed-out status. It drains the widget's history output into a virtual terminal, draws the chat, normalizes paths, and compares the screen against the saved timeout snapshot.

Call relations: The test harness runs this function. It exercises the chat widget's warning and Guardian assessment paths together, then passes the resulting output through terminal rendering and snapshot checking.

Call graph: calls 3 internal fn (with_options, insert_history_lines, new); 2 external calls (new, assert_chatwidget_snapshot!).

app_server_guardian_review_started_sets_review_status320–358 ↗
async fn app_server_guardian_review_started_sets_review_status()

Purpose: This test checks that a Guardian review started notification from the app server immediately updates the chat widget's visible status. The user should be able to see that the requested approval is currently under review.

Data flow: It creates a chat widget and builds an app-server notification describing an in-progress review of a shell command. It delivers that notification to the widget. Then it reads the bottom-pane status widget and verifies that the header says the approval request is being reviewed and that the details show the command being reviewed.

Call relations: The async test runner calls this function. Instead of using direct Guardian assessment events, it goes through handle_server_notification, which tests the path used when Guardian updates arrive from the app server.

Call graph: 2 external calls (ItemGuardianApprovalReviewStarted, assert_eq!).

app_server_guardian_review_denied_renders_denied_request_snapshot361–436 ↗
async fn app_server_guardian_review_denied_renders_denied_request_snapshot()

Purpose: This test verifies the full display path for an app-server Guardian review that starts and then is denied. It protects the UI shown when server-originated safety decisions block a requested command.

Data flow: It creates a chat widget, hides the welcome banner, and builds an app-server shell command action. It sends a review-started notification, followed by a review-completed notification with denied status, high risk, low authorization, and a rationale. It inserts generated history into a virtual terminal, renders the widget, normalizes paths, and compares the output with the expected denied-review snapshot.

Call relations: The test runner invokes this function. It uses app-server notification constructors to mimic real server messages, feeds them through the chat widget's server-notification entry point, and then uses the common rendering-and-snapshot flow to verify what the user would see.

Call graph: calls 3 internal fn (with_options, insert_history_lines, new); 4 external calls (new, ItemGuardianApprovalReviewCompleted, ItemGuardianApprovalReviewStarted, assert_chatwidget_snapshot!).

app_server_guardian_review_timed_out_renders_timed_out_request_snapshot439–517 ↗
async fn app_server_guardian_review_timed_out_renders_timed_out_request_snapshot()

Purpose: This test checks the terminal output for an app-server Guardian review that times out. It makes sure timeout information from the server becomes a clear visible history entry.

Data flow: It creates a chat widget, hides the welcome banner, and builds an app-server shell command action. It sends a review-started notification and then a review-completed notification whose status is timed out and whose rationale explains the timeout. It renders any history output in a virtual terminal, normalizes paths, and compares the final screen to the expected snapshot.

Call relations: The async test harness calls it. Like the denied app-server test, it exercises handle_server_notification with realistic started and completed notifications, then hands off to terminal rendering and snapshot comparison.

Call graph: calls 3 internal fn (with_options, insert_history_lines, new); 4 external calls (new, ItemGuardianApprovalReviewCompleted, ItemGuardianApprovalReviewStarted, assert_chatwidget_snapshot!).

guardian_parallel_reviews_render_aggregate_status_snapshot520–552 ↗
async fn guardian_parallel_reviews_render_aggregate_status_snapshot()

Purpose: This test checks what the bottom status area looks like when two Guardian reviews are running at once. It ensures the interface can summarize multiple pending approval checks instead of showing only one and hiding the other.

Data flow: It creates a chat widget, marks a task as started, and sends two in-progress Guardian assessment events with different IDs and commands. It renders the bottom popup at a fixed width, normalizes paths, and compares the aggregate status display to a snapshot.

Call relations: The test runner calls this function. The test feeds multiple in-progress Guardian events into the widget and then uses the popup rendering helper plus snapshot assertion to verify the combined display.

Call graph: 2 external calls (assert_chatwidget_snapshot!, format!).

guardian_parallel_reviews_keep_remaining_review_visible_after_denial555–619 ↗
async fn guardian_parallel_reviews_keep_remaining_review_visible_after_denial()

Purpose: This test makes sure that when two Guardian reviews are active and one is denied, the other still appears as the current review. This matters because a completed denial should not accidentally clear the status for a still-pending approval.

Data flow: It creates a chat widget, starts a task, and sends two in-progress Guardian events. Then it sends a denied completion for the first review. Finally, it reads the widget's current status state and checks that the header still says an approval request is being reviewed and that the details show the second command.

Call relations: The async test runner invokes this function. It directly drives the widget with Guardian assessment events and uses equality assertions on internal status state rather than rendering a terminal snapshot.

Call graph: 1 external calls (assert_eq!).

tui/src/chatwidget/tests/history_replay.rssource ↗
testtest run

When a chat thread is reopened, the app server sends old events back to the terminal user interface. The chat widget must turn those events into the same visible conversation the user saw before, without accidentally doing live-only actions such as exiting the app or showing duplicate status messages. This test file is a safety net for that replay path.

The tests create a chat widget in a controlled test setup, feed it saved thread/session events, then inspect what the widget sends to the history area and bottom input pane. In everyday terms, it checks that reopening a notebook restores the pages correctly: old user and assistant messages appear, images are remembered, command history works, and the current “working” spinner still shows if the old turn was unfinished.

It also checks less obvious behavior. Review-mode prompts should not become part of the user’s input history. Raw reasoning text is hidden or shown depending on the user setting. Retryable connection errors during replay should not create scary history entries. Forked-thread messages should use the title supplied by the app server, not stale local files. Without these tests, resuming a chat could show misleading history, lose attachments, apply wrong sandbox permissions, or leave the terminal in the wrong running state.

Function details26
resumed_initial_messages_render_history14–76 ↗
async fn resumed_initial_messages_render_history()

Purpose: Checks that messages restored during an initial resume are actually inserted into the visible history. It verifies both a replayed user message and a replayed assistant reply appear on screen.

Data flow: It starts with a fresh test chat widget, gives it a session configuration, then feeds in one saved user message and one saved assistant message. It drains the emitted history cells, turns their display lines into plain text, and confirms the expected message text is present.

Call relations: The async test harness calls this test. Inside the scenario, the test drives the chat widget through session setup and replay helper calls, then observes the app-event receiver to make sure the widget handed rendered history cells to the rest of the terminal UI.

Call graph: calls 2 internal fn (read_only, new); 4 external calls (new, default, new, assert!).

replayed_user_messages_seed_composer_history79–166 ↗
async fn replayed_user_messages_seed_composer_history()

Purpose: Checks that replayed user messages become available in the input box history, including special mention links such as plugin or app references. This lets a user press Up after resuming and recover earlier prompts correctly.

Data flow: It creates a chat widget with history metadata, replays two user messages containing mention inputs, and clears the visible history events. It then simulates Up-arrow key presses and checks that the composer text and hidden mention bindings match the replayed messages, before requesting older entries from stored history and checking those too.

Call relations: The test harness runs it as an async test. It uses replay helpers to feed saved user inputs into the widget, then uses keyboard handling and history lookup responses to follow the same path a real user would take when browsing previous prompts.

Call graph: calls 1 internal fn (new); 2 external calls (new, assert_eq!).

replayed_review_prompt_does_not_seed_composer_history169–190 ↗
async fn replayed_review_prompt_does_not_seed_composer_history()

Purpose: Makes sure an automatic review-mode prompt is not treated like a user-written prompt. Without this, pressing Up could surface boilerplate review text that the user did not intentionally type.

Data flow: It replays an event that enters review mode, then replays the review prompt message. After draining rendered history, it simulates an Up-arrow press and checks that the composer stays empty.

Call relations: The async test runner calls this test. The test feeds review-related replay events into the chat widget and then checks the bottom pane, proving the replay logic filters this special prompt out of composer history.

Call graph: 2 external calls (new, assert_eq!).

replayed_user_message_preserves_text_elements_and_local_images193–267 ↗
async fn replayed_user_message_preserves_text_elements_and_local_images()

Purpose: Checks that a replayed user message keeps both its marked text spans and local image attachments. This matters because image placeholders and their original files must still line up after resuming a thread.

Data flow: It builds a message containing an image placeholder, text element metadata describing that placeholder, and a local image path. After session setup and replay, it reads emitted events until it finds the user history cell, then compares the stored message, text elements, local image paths, and remote image list against the originals.

Call relations: The test is run by the async test harness. It drives the chat widget with a mixed text-and-local-image replay item and inspects the generated UserHistoryCell, which is the object later used to render that message in the transcript.

Call graph: calls 2 internal fn (read_only, new); 7 external calls (new, default, new, assert!, assert_eq!, format!, vec!).

replayed_user_message_preserves_remote_image_urls270–337 ↗
async fn replayed_user_message_preserves_remote_image_urls()

Purpose: Checks that remote image links survive replay as remote image attachments, not as local files or lost data. This keeps web-hosted images visible and correctly represented after reopening a thread.

Data flow: It prepares a text message plus a remote image URL, configures a session, and replays those inputs. It then finds the emitted user history cell and verifies the text is unchanged, no local image paths were added, and the remote URL list matches the original.

Call relations: The async test harness invokes it. The test uses the chat widget’s replay path for app-server user inputs and observes the history-cell output that the UI would render.

Call graph: calls 2 internal fn (read_only, new); 6 external calls (new, default, new, assert!, assert_eq!, vec!).

session_configured_syncs_widget_config_permissions_and_cwd340–433 ↗
async fn session_configured_syncs_widget_config_permissions_and_cwd()

Purpose: Verifies that a session configuration from the server replaces the chat widget’s local working directory and permission settings. This prevents the terminal from showing or enforcing stale sandbox rules after switching into a restored thread.

Data flow: It first gives the chat widget older local permission and directory settings. Then it sends a new session state containing a different current directory and a restricted permission profile, and checks that the widget’s config now reflects the server’s approval policy, sandbox projection, effective permission profile, and directory. It also checks that a later local permission change still uses the current thread’s workspace roots.

Call relations: The test runner calls this scenario. The test exercises session setup through handle_thread_session, then calls the widget’s local permission update method to confirm server-provided canonical state and later local edits work together correctly.

Call graph: calls 4 internal fn (from, legacy, workspace_write, new); 4 external calls (default, new, assert_eq!, vec!).

session_configured_preserves_profile_workspace_roots436–487 ↗
async fn session_configured_preserves_profile_workspace_roots()

Purpose: Checks that session setup keeps the distinction between visible runtime workspace roots and extra roots already baked into a permission profile. This protects users from seeing confusing workspace lists while still enforcing the intended access rules.

Data flow: It starts with a widget that has a previous current directory and an additional shared workspace root. It sends a session whose runtime root is different, but whose effective permission profile includes both the runtime root and the shared root. After setup, it checks the current directory, user-visible roots, and effective permissions.

Call relations: The async test harness runs it. The test feeds one ThreadSessionState into the chat widget and then reads the widget configuration, focusing on how session replay updates permission state.

Call graph: calls 2 internal fn (workspace_write, new); 4 external calls (default, new, assert_eq!, vec!).

session_configured_external_sandbox_keeps_external_runtime_policy490–531 ↗
async fn session_configured_external_sandbox_keeps_external_runtime_policy()

Purpose: Verifies that an externally controlled sandbox remains marked as external after session configuration. This matters because external sandboxing means another system, not the local legacy sandbox code, is responsible for enforcement.

Data flow: It creates a session state with an external permission profile and restricted network access. After sending that session to the chat widget, it compares the widget’s legacy sandbox view and effective permission profile with the expected external policy.

Call relations: The test harness calls it. The scenario goes through handle_thread_session and then checks the resulting config projection, making sure conversion into older sandbox types does not erase the external-sandbox meaning.

Call graph: calls 2 internal fn (from, new); 3 external calls (default, new, assert_eq!).

replayed_user_message_with_only_remote_images_renders_history_cell534–589 ↗
async fn replayed_user_message_with_only_remote_images_renders_history_cell()

Purpose: Checks that a user replay item containing only a remote image still creates a visible user history cell. This prevents image-only prompts from disappearing when a thread is resumed.

Data flow: It configures a session, replays a user input made only of a remote image URL, then reads emitted app events until it finds a user history cell. It verifies the message text is empty and the remote image URL is preserved.

Call relations: The async test harness runs it. The test sends a replayed image-only input through the same chat widget path as normal history restoration and inspects the generated cell.

Call graph: calls 2 internal fn (read_only, new); 6 external calls (new, default, new, assert!, assert_eq!, vec!).

replayed_user_message_with_only_local_images_renders_history_cell592–647 ↗
async fn replayed_user_message_with_only_local_images_renders_history_cell()

Purpose: Checks that a user replay item containing only a local image path still appears in history. This guards against losing prompts where the image itself was the whole message.

Data flow: It creates a session, replays a user input made only of one local image attachment, then waits for a user history cell. It checks that the text is empty and the local image path list matches the original path.

Call relations: The async test runner invokes this test. It uses the widget’s replay path for local-image inputs and observes the InsertHistoryCell event that would be rendered in the UI.

Call graph: calls 2 internal fn (read_only, new); 7 external calls (new, from, default, new, assert!, assert_eq!, vec!).

forked_thread_history_line_includes_name_and_id_snapshot650–677 ↗
async fn forked_thread_history_line_includes_name_and_id_snapshot()

Purpose: Checks the history line shown when a thread is forked from another thread and the parent has a name. The saved snapshot makes sure both the wording and formatting stay stable.

Data flow: It creates a chat widget, builds a known parent thread ID, emits a forked-thread event with a parent title, waits for the resulting history cell, turns its display lines into one string, and verifies the fork message is present before comparing it to a snapshot.

Call relations: The async test harness calls it. The test directly exercises emit_forked_thread_event and then reads the app-event channel, following the path from a fork notice to a rendered history cell.

Call graph: calls 1 internal fn (from_string); 5 external calls (assert!, assert_chatwidget_snapshot!, panic!, from_secs, timeout).

forked_thread_history_line_without_name_shows_id_once_snapshot680–706 ↗
async fn forked_thread_history_line_without_name_shows_id_once_snapshot()

Purpose: Checks the forked-thread history line when there is no parent thread name available. It ensures the parent ID is shown cleanly rather than duplicated or formatted oddly.

Data flow: It creates a chat widget, points its local home directory at a temporary folder, emits a fork event without a parent title, waits for the history cell, combines its display text, and compares that text to a snapshot.

Call relations: The test runner invokes it. The scenario drives the fork-event display code and observes only the emitted history cell, which is what the terminal transcript would show.

Call graph: calls 2 internal fn (from_string, from_absolute_path); 4 external calls (assert_chatwidget_snapshot!, panic!, from_secs, timeout).

app_server_forked_thread_history_line_uses_app_server_title_snapshot709–746 ↗
async fn app_server_forked_thread_history_line_uses_app_server_title_snapshot()

Purpose: Checks that a forked-thread notice uses the parent title supplied by the app server, even if a stale local session index contains a different name. This avoids showing the wrong parent thread title.

Data flow: It writes a fake local session index with an outdated title, then emits a fork event with a server-provided title. It waits for the fork history cell, turns it into text, checks that the server title appears and the stale local title does not, then compares the output with a snapshot.

Call relations: The async test harness runs this test. It sets up local file state, calls emit_forked_thread_event, and confirms the widget’s fork-title path trusts the app-server value instead of reading local CODEX_HOME data.

Call graph: calls 2 internal fn (from_string, from_absolute_path); 7 external calls (assert!, assert_chatwidget_snapshot!, format!, panic!, write, from_secs, timeout).

app_server_forked_thread_history_line_without_app_server_name_ignores_local_snapshot749–788 ↗
async fn app_server_forked_thread_history_line_without_app_server_name_ignores_local_snapshot()

Purpose: Checks that if the app server gives no fork parent title, the widget still does not fall back to stale local title data. This keeps app-server thread replay independent from local session-index files.

Data flow: It writes a fake local session index with a stale title, emits a fork event without a title, waits for the history cell, and verifies the stale title is absent. It then compares the rendered line with a snapshot.

Call relations: The test harness calls it. The test combines temporary file setup with the fork-event path to prove the chat widget does not consult local session metadata during app-server fork display.

Call graph: calls 2 internal fn (from_string, from_absolute_path); 7 external calls (assert!, assert_chatwidget_snapshot!, format!, panic!, write, from_secs, timeout).

thread_snapshot_replay_preserves_agent_message_during_review_mode791–807 ↗
async fn thread_snapshot_replay_preserves_agent_message_during_review_mode()

Purpose: Checks that agent messages from a thread snapshot still render while the chat is in review mode. This prevents review-mode replay from swallowing assistant progress updates.

Data flow: It enters review mode through a replay helper, drains the review-mode history output, then replays an assistant message as part of a thread snapshot. It drains new history cells and checks there is exactly one cell containing the assistant text.

Call relations: The async test runner invokes it. The test uses review-mode and agent-message replay helpers to cover the interaction between two replay features, then validates the history output.

Call graph: 2 external calls (assert!, assert_eq!).

replayed_retryable_app_server_error_keeps_turn_running810–853 ↗
async fn replayed_retryable_app_server_error_keeps_turn_running()

Purpose: Checks that a retryable app-server error seen during replay does not make the turn look finished or failed. If the server is reconnecting, the UI should still say the task is working.

Data flow: It replays a turn-started notification for an in-progress turn, then replays an error notification marked as retryable. It verifies no history cell is inserted for the error, the bottom pane still thinks a task is running, and the visible status remains “Working” without extra details.

Call relations: The async test harness runs it. The test drives handle_server_notification with replayed turn and error notifications and then checks the widget’s bottom-pane state.

Call graph: 5 external calls (Error, TurnStarted, new, assert!, assert_eq!).

replayed_thread_closed_notification_does_not_exit_tui856–867 ↗
async fn replayed_thread_closed_notification_does_not_exit_tui()

Purpose: Checks that a replayed thread-closed notification does not tell the terminal app to exit. A historical close event should be remembered, not acted on as a live shutdown command.

Data flow: It sends a thread-closed server notification with a replay marker to a fresh chat widget. It then checks the app-event receiver and expects no outgoing event.

Call relations: The async test runner calls it. The test goes through handle_server_notification and watches the event channel, proving replayed closure is ignored for live terminal control.

Call graph: 2 external calls (ThreadClosed, assert_matches!).

replayed_reasoning_item_hides_raw_reasoning_when_disabled870–915 ↗
async fn replayed_reasoning_item_hides_raw_reasoning_when_disabled()

Purpose: Checks that raw reasoning content is not shown during replay when the user setting disables it. The summary should still render, but private or verbose reasoning text should stay hidden.

Data flow: It turns off raw reasoning display, configures a session, drains setup output, then replays a reasoning item containing both a summary and raw content. It reads the inserted history cell and verifies it is not empty but does not contain the raw reasoning text.

Call relations: The test harness invokes it. The test exercises replay_thread_item for a reasoning item and inspects transcript rendering, tying the replay path to the user-facing raw-reasoning setting.

Call graph: calls 2 internal fn (read_only, new); 4 external calls (new, assert!, panic!, vec!).

replayed_reasoning_item_shows_raw_reasoning_when_enabled918–962 ↗
async fn replayed_reasoning_item_shows_raw_reasoning_when_enabled()

Purpose: Checks the opposite setting: when raw reasoning display is enabled, replayed reasoning content should include the raw text. This confirms the setting is respected in both directions.

Data flow: It turns on raw reasoning display, configures a session, drains setup output, and replays a reasoning item with summary and raw content. It reads the resulting history cell and checks that the raw reasoning text appears.

Call relations: The async test runner calls it. It uses the same replay_thread_item path as the hidden-reasoning test, but with the display flag enabled, proving rendering follows configuration.

Call graph: calls 2 internal fn (read_only, new); 4 external calls (new, assert!, panic!, vec!).

replayed_in_progress_mcp_tool_call_stays_active965–990 ↗
async fn replayed_in_progress_mcp_tool_call_stays_active()

Purpose: Checks that an unfinished MCP tool call remains active when replayed from a snapshot. MCP means “Model Context Protocol,” a way for the assistant to call external tools; an in-progress tool call should not be shown as completed without a result.

Data flow: It replays an MCP tool-call item whose status is still in progress. It expects no completed history cell, then reads the widget’s active display text and checks that it says the tool is being called and does not show a fake completion message.

Call relations: The test harness runs it. The test drives replay_thread_item with an in-progress tool call and checks the active-task area rather than the history channel, matching how live tool calls are displayed.

Call graph: 2 external calls (assert!, json!).

live_reasoning_summary_is_not_rendered_twice_when_item_completes993–1047 ↗
async fn live_reasoning_summary_is_not_rendered_twice_when_item_completes()

Purpose: Checks that a reasoning summary streamed live is not duplicated when the full reasoning item later completes. This prevents the transcript from showing the same summary twice.

Data flow: It starts a live turn, sends a reasoning-summary text delta, then sends an item-completed notification containing the same summary. It reads the resulting history cell and counts occurrences of the summary text, expecting exactly one.

Call relations: The async test runner invokes it. The test uses handle_server_notification for a live turn, a streaming delta, and completion, covering the transition from active streaming UI to saved history cell.

Call graph: 7 external calls (ItemCompleted, ReasoningSummaryTextDelta, TurnStarted, new, assert_eq!, panic!, vec!).

thread_snapshot_replayed_turn_started_marks_task_running1050–1062 ↗
async fn thread_snapshot_replayed_turn_started_marks_task_running()

Purpose: Checks that replaying a turn-started event from a thread snapshot marks the UI as busy. A restored in-progress turn should still show the user that work is underway.

Data flow: It replays a turn-started event marked as a thread snapshot, drains any history output, and checks that the bottom pane reports a running task with a “Working” status header.

Call relations: The async test harness calls it. The test uses a replay helper for turn start and then inspects the bottom pane, linking snapshot replay to the active status indicator.

Call graph: 2 external calls (assert!, assert_eq!).

replayed_in_progress_turn_marks_task_running1065–1089 ↗
async fn replayed_in_progress_turn_marks_task_running()

Purpose: Checks that replaying a saved turn whose status is already in progress also marks the task as running. This covers the batch-style replay path, not just individual turn-start notifications.

Data flow: It calls replay_thread_turns with one in-progress turn and the initial-resume replay kind. It expects no history cells, then checks that the bottom pane shows a running task and the status header says “Working.”

Call relations: The test runner invokes it. The test drives the chat widget’s turn-list replay path and verifies it updates active UI state without inserting completed transcript history.

Call graph: 3 external calls (assert!, assert_eq!, vec!).

replayed_stream_error_does_not_set_retry_status_or_status_indicator1092–1111 ↗
async fn replayed_stream_error_does_not_set_retry_status_or_status_indicator()

Purpose: Checks that a replayed stream error does not create a retry status or visible status widget. A past connection hiccup should not make the resumed UI look like it is currently reconnecting.

Data flow: It sets the current status header to “Idle,” then feeds a stream error with a replay marker. It drains history events and expects none, then checks the current status remains Idle, no retry status is stored, and no bottom-pane status widget appears.

Call relations: The async test harness runs it. The test uses the replay-aware stream-error helper and inspects both history output and status state, separating historical errors from live retry behavior.

Call graph: 2 external calls (assert!, assert_eq!).

thread_snapshot_replayed_stream_recovery_restores_previous_status_header1114–1137 ↗
async fn thread_snapshot_replayed_stream_recovery_restores_previous_status_header()

Purpose: Checks that, during thread-snapshot replay, recovery after a replayed stream error restores the previous “Working” status. This keeps the active turn display sensible after reconnect-related replay events.

Data flow: It replays a turn start, replays a stream error, then replays an assistant message delta as the recovery signal. It checks that the bottom status widget again says “Working,” has no details, and no retry status remains.

Call relations: The test harness calls it. The scenario uses replay helpers for turn start, stream error, and message delta, following the status state as replay moves from interrupted to active again.

Call graph: 2 external calls (assert!, assert_eq!).

stream_recovery_restores_previous_status_header1140–1159 ↗
async fn stream_recovery_restores_previous_status_header()

Purpose: Checks the same stream-recovery behavior for live events rather than replayed snapshot events. After a temporary live connection problem, new assistant output should restore the normal working status.

Data flow: It starts a live turn, sends a live stream error, then sends an assistant message delta. It inspects the bottom status widget and verifies the header is back to “Working,” details are cleared, and retry status is gone.

Call relations: The async test runner invokes it. The test uses live-event helper functions instead of replay-marked helpers, giving a comparison case for the replay recovery behavior tested just before it.

Call graph: 2 external calls (assert!, assert_eq!).

tui/src/chatwidget/tests/mcp_startup.rssource ↗
testtest runs for MCP startup UI behavior

This test file checks a very specific user experience: what the terminal chat widget shows while MCP servers are starting, failing, timing out, or reporting late. MCP, or Model Context Protocol, is a way for the app to talk to external tools or services. When those services boot, the user needs clear feedback, but the app must not leave a fake “still working” spinner, repeat the same warning, or overwrite a more important status like an approval review.

The tests build a ChatWidget in a controlled test setup, then send it fake server notifications such as “alpha is starting”, “beta is ready”, or “alpha failed”. They watch two main outputs. First, they inspect the bottom status area, which is like the dashboard light that says what the app is doing now. Second, they drain inserted history lines, which are messages written into the chat transcript for the user to read later.

Several tests cover awkward timing: notifications for the wrong conversation thread, duplicate failures, server startup lag, late stale updates from an old startup round, and runtime servers that were not known in advance. A few tests render snapshots of the terminal screen, so future UI changes can be compared against the expected visual result.

Function details19
notify_mcp_status4–14 ↗
fn notify_mcp_status(chat: &mut ChatWidget, name: &str, status: McpServerStartupState)

Purpose: This helper sends the chat widget a fake MCP server status update without an error message. Tests use it to say that a named server is starting or ready, without repeating the notification-building code each time.

Data flow: It takes a mutable ChatWidget, a server name, and a startup state. It wraps those into a server notification for thread "thread-1" and feeds that notification into the chat widget; it returns nothing, but the widget may change its status area or history output.

Call relations: Many tests call this helper when they need to simulate normal MCP progress. It hands the constructed McpServerStatusUpdated notification to handle_server_notification, so each test can focus on the expected UI result instead of the mechanics of building the notification.

Call graph: called by 15 (app_server_mcp_startup_after_lag_can_settle_without_starting_updates, app_server_mcp_startup_after_lag_preserves_partial_terminal_only_round, app_server_mcp_startup_failure_renders_warning_history, app_server_mcp_startup_lag_settles_startup_and_ignores_late_updates, app_server_mcp_startup_next_round_after_lag_can_settle_without_starting_updates, app_server_mcp_startup_next_round_discards_stale_terminal_updates, app_server_mcp_startup_next_round_keeps_terminal_statuses_after_starting, app_server_mcp_startup_next_round_with_empty_expected_servers_reactivates, mcp_startup_complete_does_not_clear_running_task, mcp_startup_complete_preserves_review_status (+5 more)); 2 external calls (McpServerStatusUpdated, handle_server_notification).

notify_mcp_status_error16–26 ↗
fn notify_mcp_status_error(chat: &mut ChatWidget, name: &str, error: &str)

Purpose: This helper sends the chat widget a fake MCP server failure update with a specific error message. Tests use it to check warning text, duplicate suppression, and startup completion after failures.

Data flow: It takes a mutable ChatWidget, a server name, and an error string. It creates a failed MCP status notification for thread "thread-1" with that error attached, passes it into the chat widget, and returns nothing; any visible warning or state change happens inside the widget.

Call relations: Failure-focused tests call this helper to simulate the app server reporting a broken MCP startup. Like notify_mcp_status, it delegates the real reaction to handle_server_notification, keeping the tests short and consistent.

Call graph: called by 11 (app_server_mcp_startup_after_lag_can_settle_without_starting_updates, app_server_mcp_startup_after_lag_includes_runtime_servers_with_expected_set, app_server_mcp_startup_after_lag_preserves_partial_terminal_only_round, app_server_mcp_startup_failure_renders_warning_history, app_server_mcp_startup_lag_settles_startup_and_ignores_late_updates, app_server_mcp_startup_next_round_after_lag_can_settle_without_starting_updates, app_server_mcp_startup_next_round_discards_stale_terminal_updates, app_server_mcp_startup_next_round_keeps_terminal_statuses_after_starting, app_server_mcp_startup_next_round_with_empty_expected_servers_reactivates, mcp_startup_dedupes_same_round_duplicate_failure_warning (+1 more)); 2 external calls (McpServerStatusUpdated, handle_server_notification).

mcp_startup_ignores_status_for_other_thread29–67 ↗
async fn mcp_startup_ignores_status_for_other_thread()

Purpose: This test proves that MCP startup updates from a different conversation thread are ignored. Without this, a background or child thread could accidentally change the visible status of the current chat.

Data flow: The test creates a chat widget, records its current retry status, then sends MCP starting and failed notifications tagged with a different thread id. Afterward it checks that no history was inserted, no startup state was created, the bottom pane is not running, and the previous retry status is unchanged.

Call relations: The Tokio test runner calls this async test. Instead of using the helper functions, it builds notifications directly so it can deliberately set a mismatched thread id and verify that handle_server_notification refuses to apply them.

Call graph: calls 1 internal fn (new); 4 external calls (McpServerStatusUpdated, assert!, assert_eq!, matches!).

mcp_startup_dedupes_same_round_duplicate_failure_warning70–103 ↗
async fn mcp_startup_dedupes_same_round_duplicate_failure_warning()

Purpose: This test checks that the same MCP failure warning is shown only once during a startup round. That keeps the chat transcript from being spammed by repeated identical error reports.

Data flow: It starts an expected server named alpha, sends the same failure for alpha twice, then reads the inserted history and expects one warning line. It then marks beta ready and checks that the final summary reports alpha as failed.

Call relations: The test runner invokes it as an async test. It uses notify_mcp_status and notify_mcp_status_error to drive the widget through a startup round, then compares the captured history text with the exact expected warning and summary.

Call graph: calls 2 internal fn (notify_mcp_status, notify_mcp_status_error); 1 external calls (assert_eq!).

mcp_startup_header_booting_snapshot106–122 ↗
async fn mcp_startup_header_booting_snapshot()

Purpose: This test captures what the chat widget looks like while an MCP server is booting. It protects the visible terminal layout from accidental changes.

Data flow: It creates a chat widget, sends a starting update for alpha, asks the widget how tall it wants to be, renders it into a test terminal, and compares the rendered screen with a stored snapshot.

Call relations: The test runner calls it, and it uses notify_mcp_status to create the booting state. It then hands the widget to the terminal renderer and uses a snapshot assertion to verify the visual output.

Call graph: calls 1 internal fn (notify_mcp_status); 3 external calls (assert_chatwidget_snapshot!, new, new).

mcp_startup_complete_does_not_clear_running_task125–140 ↗
async fn mcp_startup_complete_does_not_clear_running_task()

Purpose: This test makes sure finishing MCP startup does not stop an unrelated active chat turn. If the assistant is already working, the MCP completion should not turn off the working indicator.

Data flow: It starts a chat turn, confirms the bottom pane shows a running task, then starts and completes one MCP server. The final checks confirm the task indicator is still visible and the header still says "Working".

Call relations: The test runner invokes it. The test combines a turn-start event from the surrounding test helpers with MCP updates from notify_mcp_status to verify that MCP startup cleanup does not override the main chat task state.

Call graph: calls 1 internal fn (notify_mcp_status); 2 external calls (assert!, assert_eq!).

turn_start_preserves_active_mcp_startup_header143–159 ↗
async fn turn_start_preserves_active_mcp_startup_header()

Purpose: This test checks that an active MCP boot message remains visible when a chat turn starts. The user should still see that the app is booting a server if that is the most immediate startup activity.

Data flow: It tells the widget to expect one MCP server, sends a starting update, then starts a chat turn. It checks that the bottom pane is running and that the status header still names the booting MCP server; once the server becomes ready, the header changes to "Working".

Call relations: The test runner calls it. It uses notify_mcp_status before and after a turn-start helper to confirm the status priority: active MCP startup is shown first, then normal working status returns when startup completes.

Call graph: calls 1 internal fn (notify_mcp_status); 2 external calls (assert!, assert_eq!).

turn_start_replaces_idle_completed_mcp_startup_header162–179 ↗
async fn turn_start_replaces_idle_completed_mcp_startup_header()

Purpose: This test verifies that an old completed MCP startup header is replaced when real work begins. A stale boot message should not stay on screen once the user starts a new turn.

Data flow: It starts and completes one expected MCP server while no task is running, then confirms the boot header is still present but idle. After starting a chat turn, it checks that the bottom pane becomes active and the header changes to "Working".

Call relations: The test runner invokes it. It uses notify_mcp_status to create a completed startup state, then uses the turn-start helper to prove that normal chat work takes over when the MCP startup is no longer active.

Call graph: calls 1 internal fn (notify_mcp_status); 2 external calls (assert!, assert_eq!).

app_server_mcp_startup_failure_renders_warning_history182–250 ↗
async fn app_server_mcp_startup_failure_renders_warning_history()

Purpose: This test checks both the text and terminal rendering of MCP startup failure warnings. It confirms that users see a single immediate failure warning and then a final incomplete-startup summary.

Data flow: The test starts alpha, fails alpha twice, starts beta, then marks beta ready. It drains the history messages after each step, verifies the failure and summary text, inserts those history lines into a test terminal, renders the chat widget, and compares the final screen to a snapshot.

Call relations: The test runner calls it. It uses the helper notification functions to simulate server events, then hands captured history lines to insert_history_lines and renders through a terminal backend so the snapshot covers the real user-facing display.

Call graph: calls 5 internal fn (notify_mcp_status, notify_mcp_status_error, with_options, insert_history_lines, new); 4 external calls (new, assert!, assert_chatwidget_snapshot!, assert_eq!).

mcp_startup_failure_restores_running_status_header253–279 ↗
async fn mcp_startup_failure_restores_running_status_header()

Purpose: This test ensures that after MCP startup finishes with a failure, the status header returns to the active chat turn. The user should see "Working" if the assistant is still processing.

Data flow: It starts a chat turn, starts two MCP servers, fails alpha, and marks beta ready. After draining the generated warnings, it checks that the bottom pane still shows a running task and that the header is "Working".

Call relations: The async test is run by the test framework. It uses notify_mcp_status and notify_mcp_status_error to finish the MCP startup path while a chat turn is active, proving that the widget restores the previous running status afterward.

Call graph: calls 2 internal fn (notify_mcp_status, notify_mcp_status_error); 2 external calls (assert!, assert_eq!).

mcp_startup_complete_preserves_review_status282–326 ↗
async fn mcp_startup_complete_preserves_review_status()

Purpose: This test verifies that an approval review status is not overwritten when MCP startup completes. Approval review is more important to show because it may require the user's attention.

Data flow: It starts a chat turn and an MCP server, then sends a guardian assessment event, which represents a safety or approval check for a command. When the MCP server becomes ready, the test checks that the status still says "Reviewing approval request" and still shows the command details.

Call relations: The test runner invokes it. It uses notify_mcp_status for the MCP side and calls the widget's guardian assessment path to create a review state, then confirms MCP completion hands control back to that review status instead of replacing it.

Call graph: calls 1 internal fn (notify_mcp_status); 2 external calls (assert!, assert_eq!).

app_server_mcp_startup_lag_settles_startup_and_ignores_late_updates329–365 ↗
async fn app_server_mcp_startup_lag_settles_startup_and_ignores_late_updates()

Purpose: This test covers what happens when MCP startup takes too long and the app decides to settle the startup round. After that point, late updates from the same unfinished server should not restart the status indicator.

Data flow: It starts alpha, fails alpha, starts beta, then calls the widget's lag-finish method. The test expects history text about interrupted startup and alpha's failure, and expects the bottom pane to stop running. Later beta updates are sent and should produce no history and no running task.

Call relations: The test runner calls it. The helper functions simulate the app server's reports, and finish_mcp_startup_after_lag acts like the timeout decision that closes the current startup round.

Call graph: calls 2 internal fn (notify_mcp_status, notify_mcp_status_error); 1 external calls (assert!).

app_server_mcp_startup_after_lag_can_settle_without_starting_updates368–396 ↗
async fn app_server_mcp_startup_after_lag_can_settle_without_starting_updates()

Purpose: This test shows that a lag-settled startup can still process later terminal results even if no server first sent a "starting" update. It checks a forgiving path for incomplete or delayed notification streams.

Data flow: It declares alpha and beta as expected, immediately calls the lag-finish method, then sends a failure for alpha and a ready update for beta. The widget should show alpha's failure, keep running until beta is ready, then write the final incomplete summary and stop.

Call relations: The test runner invokes it. It uses notify_mcp_status_error and notify_mcp_status after the lag marker to verify that the widget can still finish the expected server set from terminal updates that arrive late.

Call graph: calls 2 internal fn (notify_mcp_status, notify_mcp_status_error); 2 external calls (assert!, assert_eq!).

app_server_mcp_startup_after_lag_preserves_partial_terminal_only_round399–437 ↗
async fn app_server_mcp_startup_after_lag_preserves_partial_terminal_only_round()

Purpose: This test checks a tricky partial-startup case after lag handling. It makes sure a previously interrupted round does not lose all information, but also does not repeat stale failure messages too early.

Data flow: It starts alpha, records alpha failed, starts beta, then settles because of lag. A repeated alpha failure after that produces no new history. After another lag finish and beta ready update, the test expects the final text to include alpha's failure and the incomplete-startup summary.

Call relations: The test runner calls it. It drives the widget with both normal helpers and finish_mcp_startup_after_lag so the test can check how the startup tracker carries partial terminal-only information across awkward timing boundaries.

Call graph: calls 2 internal fn (notify_mcp_status, notify_mcp_status_error); 1 external calls (assert!).

app_server_mcp_startup_next_round_discards_stale_terminal_updates440–481 ↗
async fn app_server_mcp_startup_next_round_discards_stale_terminal_updates()

Purpose: This test makes sure stale failure updates from an old MCP startup round do not poison the next round. It protects users from seeing old errors after a later startup has moved on.

Data flow: It creates an interrupted round where alpha failed and beta was still starting, settles it after lag, then sends an old alpha failure and beta starting update that should be ignored. When alpha and beta later become ready in the new round, the test expects no failure summary and the running indicator to stop cleanly.

Call relations: The test runner invokes it. It uses notify_mcp_status_error for the stale error and notify_mcp_status for later progress, checking that the widget distinguishes old terminal-only updates from a fresh startup round.

Call graph: calls 2 internal fn (notify_mcp_status, notify_mcp_status_error); 1 external calls (assert!).

app_server_mcp_startup_next_round_keeps_terminal_statuses_after_starting484–518 ↗
async fn app_server_mcp_startup_next_round_keeps_terminal_statuses_after_starting()

Purpose: This test confirms that once a new MCP round has clearly begun, later terminal statuses in that round are kept. In other words, stale updates are ignored, but real new-round failures are still reported.

Data flow: It first settles startup after lag, then sends alpha starting, alpha failed, beta starting, and beta ready. The test expects alpha's failure warning to appear, the bottom pane to run while beta is pending, and the final summary to name alpha as failed.

Call relations: The test runner calls it. By sending a starting update before the failure, it marks the updates as belonging to a new active round; the helper notifications then confirm the widget records and summarizes them.

Call graph: calls 2 internal fn (notify_mcp_status, notify_mcp_status_error); 2 external calls (assert!, assert_eq!).

app_server_mcp_startup_next_round_with_empty_expected_servers_reactivates521–544 ↗
async fn app_server_mcp_startup_next_round_with_empty_expected_servers_reactivates()

Purpose: This test checks that MCP startup can reactivate even when the expected server list was empty. That matters for servers discovered at runtime rather than listed beforehand.

Data flow: It sets the expected server list to empty, explicitly finishes an empty startup, then sends a runtime server starting and failing. The widget should start showing a running task again, then write both the failure and incomplete-startup summary and stop.

Call relations: The test runner invokes it. It uses notify_mcp_status and notify_mcp_status_error to simulate a runtime-discovered server, proving that the startup tracker is not permanently disabled by an empty expected set.

Call graph: calls 2 internal fn (notify_mcp_status, notify_mcp_status_error); 2 external calls (new, assert!).

app_server_mcp_startup_after_lag_includes_runtime_servers_with_expected_set547–573 ↗
async fn app_server_mcp_startup_after_lag_includes_runtime_servers_with_expected_set()

Purpose: This test verifies that runtime-discovered MCP servers are included in lag-settled startup summaries even when there is already an expected server set. Unknown-at-first servers should still count if they report a failure.

Data flow: It expects alpha but sends a failure for a different server named runtime. The widget writes the runtime failure warning and keeps startup active. After lag settlement, the summary should include runtime as failed and the bottom pane should stop running.

Call relations: The test runner calls it. It uses notify_mcp_status_error to introduce the runtime server and finish_mcp_startup_after_lag to close the round, checking that the final summary includes servers learned from notifications.

Call graph: calls 1 internal fn (notify_mcp_status_error); 1 external calls (assert!).

app_server_mcp_startup_next_round_after_lag_can_settle_without_starting_updates576–625 ↗
async fn app_server_mcp_startup_next_round_after_lag_can_settle_without_starting_updates()

Purpose: This test checks another late-update path after a lagged startup round has already ended. It ensures stale failures stay quiet until the remaining expected server result lets the widget produce the correct final summary.

Data flow: It starts a round where alpha fails and beta starts, settles it after lag, then sends a stale alpha failure that should produce no history. After another lag finish, a later alpha failure still stays quiet until beta reports ready; then the summary includes alpha's failure and says startup was incomplete.

Call relations: The test runner invokes it. It combines notify_mcp_status, notify_mcp_status_error, and repeated lag settlement to test how the widget separates stale old-round messages from the delayed completion of the next expected startup set.

Call graph: calls 2 internal fn (notify_mcp_status, notify_mcp_status_error); 1 external calls (assert!).

tui/src/chatwidget/tests/permissions.rssource ↗
testtest run

This is a test file for the chat widget’s permission controls. In this app, “permissions” decide what the assistant may do: read files, write in the workspace, use the network, run with full access, or ask a human before risky actions. These tests act like a careful user clicking through the permission menus and checking that the screen and outgoing app messages match what should happen.

The file covers several related flows. It verifies snapshot output, which means comparing the rendered popup text against a saved expected version. It tests built-in permission presets such as read-only, workspace write, auto approval, and full access. It also tests custom named profiles, where an organization or user defines their own permission profile. On Windows, it checks extra sandbox setup prompts, because Windows may need a special sandbox mode to safely run agent actions.

A key theme is safety. Disabled choices must be visible but not selectable. Full access must open a confirmation before a history message is written. Auto-review mode must only appear when the feature flag is enabled. Without these tests, a small user-interface change could silently make the app show misleading permission labels, select the wrong profile, skip a warning, or send the assistant broader access than the user intended.

Function details34
app_server_workspace_write_profile12–49 ↗
fn app_server_workspace_write_profile(extra_root: AbsolutePathBuf) -> PermissionProfile

Purpose: Builds a realistic workspace-write permission profile for tests, including one extra writable folder. Tests use it to make sure the app still recognizes a normal workspace-write setup even when the server adds extra allowed paths.

Data flow: It takes one absolute path as the extra writable root. It creates a managed permission profile with restricted network access, read access to the filesystem root, write access to project roots and temporary folders, and write access to the extra path. It returns that finished permission profile to the test.

Call relations: It is a small test helper. The preset-matching tests call it when they need a profile that looks like workspace write but has extra details, especially for checking auto-review and preset matching behavior.

Call graph: called by 2 (permissions_selection_marks_auto_review_current_with_custom_workspace_write_details, preset_matching_accepts_workspace_write_with_extra_roots); 1 external calls (vec!).

windows_sandbox_requirements_stack51–68 ↗
fn windows_sandbox_requirements_stack(
    allowed_sandbox_implementations: Vec<WindowsSandboxModeToml>,
) -> ConfigLayerStack

Purpose: Builds a fake configuration stack that says which Windows sandbox modes are allowed. Tests use this to simulate organization rules without loading a real config file.

Data flow: It takes a list of allowed Windows sandbox modes. It wraps that list in configuration requirement objects, converts those requirements into the runtime form, and returns a config layer stack that the chat widget can read. The chat widget then behaves as if those sandbox rules came from real configuration.

Call relations: This helper supports the Windows sandbox prompt tests. Those tests install the returned config stack into the chat widget before opening startup, enable, or fallback prompts.

Call graph: calls 1 internal fn (new); called by 5 (required_windows_sandbox_setup_defers_configured_initial_prompt, startup_windows_sandbox_prompt_blocks_disallowed_unelevated_fallback, windows_sandbox_required_enable_prompt_reopens_on_cancel_when_unelevated_allowed, windows_sandbox_required_enable_prompt_snapshot, windows_sandbox_required_fallback_prompt_snapshot); 4 external calls (default, new, try_from, default).

approvals_selection_popup_snapshot71–85 ↗
async fn approvals_selection_popup_snapshot()

Purpose: Checks that the approvals popup renders as expected when the older approval selection flow is used. This protects the visible wording and layout of the approval menu.

Data flow: It creates a chat widget, disables the Guardian Approval feature, clears the full-access warning suppression, opens the approvals popup, renders it at a fixed width, and compares the result to a saved snapshot. On Windows it uses a Windows-specific snapshot name.

Call relations: This test exercises the chat widget’s popup-opening and rendering path directly. It does not hand off to another helper except the shared rendering and snapshot tools supplied by the test harness.

Call graph: 2 external calls (assert_chatwidget_snapshot!, with_settings!).

profile_permissions_selection_popup_snapshot88–105 ↗
async fn profile_permissions_selection_popup_snapshot()

Purpose: Checks the rendered permission profile popup when explicit profile mode is enabled. It confirms that the current built-in workspace profile is displayed correctly.

Data flow: It creates a chat widget, turns on explicit permission profile mode, sets the active profile to the built-in workspace profile, opens the permissions popup, renders it, and compares the text to a saved snapshot.

Call relations: This test drives the same popup path a user would see after opening permissions. It prepares the widget state first, then relies on the snapshot assertion to catch display regressions.

Call graph: calls 3 internal fn (new, active, workspace_write); 1 external calls (assert_chatwidget_snapshot!).

profile_permissions_selection_popup_with_custom_profiles_snapshot108–135 ↗
async fn profile_permissions_selection_popup_with_custom_profiles_snapshot()

Purpose: Checks that the permissions popup includes custom permission profiles with their descriptions. This matters for users or organizations that define named permission profiles outside the built-in choices.

Data flow: It creates a chat widget, enables explicit profile mode, adds two custom profile summaries, marks one as active, opens the permissions popup, renders it, and compares the output with the expected snapshot.

Call relations: This test extends the basic profile popup scenario by adding custom profile data before opening the popup. The rendered result is checked through the shared snapshot mechanism.

Call graph: calls 3 internal fn (new, active, workspace_write); 2 external calls (assert_chatwidget_snapshot!, vec!).

profile_permissions_selection_emits_named_profile_event_only138–167 ↗
async fn profile_permissions_selection_emits_named_profile_event_only()

Purpose: Verifies that choosing the current built-in workspace profile emits one clear profile-selection event. It ensures the event identifies the profile by name and includes the expected approval settings.

Data flow: It sets up a chat widget in explicit profile mode with the workspace profile active, opens the permissions popup, presses Enter, collects events from the app event channel, and checks that exactly one selection event was sent with profile id ':workspace', manual approval, and the label 'Ask for approval'.

Call relations: This test simulates the user accepting the highlighted popup choice. It watches the receiver side of the event channel to confirm what the chat widget sends to the rest of the app.

Call graph: calls 3 internal fn (new, active, workspace_write); 4 external calls (from, assert!, assert_eq!, from_fn).

profile_permissions_selection_emits_active_custom_profile170–199 ↗
async fn profile_permissions_selection_emits_active_custom_profile()

Purpose: Verifies that selecting an active custom profile sends the custom profile id and does not attach built-in approval settings. Custom profiles should be treated as named bundles, not rewritten into built-in presets.

Data flow: It creates a widget, enables explicit profile mode, registers a custom profile named 'locked-down', sets it active, opens the popup, presses Enter, reads emitted events, and checks for one profile-selection event with that custom id and no separate approval policy or reviewer.

Call relations: This test follows the popup selection path and inspects the event that would be consumed by higher-level app code. It complements the built-in profile selection test.

Call graph: calls 3 internal fn (new, active, workspace_write); 5 external calls (from, assert!, assert_eq!, from_fn, vec!).

profile_permissions_selection_emits_auto_review_mode_event202–232 ↗
async fn profile_permissions_selection_emits_auto_review_mode_event()

Purpose: Checks that moving to the auto-review row and selecting it sends an event for the same workspace profile but with automatic approval review. This protects the distinction between manual approval and 'Approve for me'.

Data flow: It prepares the workspace profile in explicit profile mode, opens the popup, presses Down to move the selection, presses Enter, collects events, and checks for one profile-selection event whose reviewer is AutoReview and whose label is 'Approve for me'.

Call relations: This test drives keyboard navigation through the popup. The resulting event is the handoff from the user interface to the rest of the application.

Call graph: calls 3 internal fn (new, active, workspace_write); 4 external calls (from, assert!, assert_eq!, from_fn).

profile_permissions_full_access_opens_confirmation235–262 ↗
async fn profile_permissions_full_access_opens_confirmation()

Purpose: Confirms that selecting full access from the profile permissions popup does not immediately apply it. Instead, it must open a confirmation step because full access removes the normal sandbox protection.

Data flow: It opens the permissions popup, moves to the full-access choice, presses Enter, drains app events, and checks that the single event asks to open the full-access confirmation with the expected preset and profile-selection details.

Call relations: This test sits between the popup selection flow and the safety confirmation flow. It ensures the chat widget hands off to a confirmation event instead of directly changing permissions.

Call graph: 4 external calls (from, assert!, assert_eq!, from_fn).

approvals_selection_popup_snapshot_windows_degraded_sandbox267–289 ↗
async fn approvals_selection_popup_snapshot_windows_degraded_sandbox()

Purpose: On Windows, checks that the approvals popup clearly labels the weaker non-admin sandbox state. This helps users understand that the sandbox is degraded and how to fix it.

Data flow: It creates a chat widget, enables the Windows sandbox feature but not the elevated version, opens the approvals popup, renders it, and asserts that the popup text mentions the non-admin sandbox and the setup command.

Call relations: This Windows-only test exercises the approvals popup under a specific feature-flag combination. It verifies user-facing copy rather than comparing a full snapshot.

Call graph: 1 external calls (assert!).

preset_matching_accepts_workspace_write_with_extra_roots292–318 ↗
async fn preset_matching_accepts_workspace_write_with_extra_roots()

Purpose: Checks that the app still recognizes the 'Ask for approval' preset when the current workspace-write profile has extra writable roots. This prevents harmless server-added paths from making the current mode look unknown.

Data flow: It finds the built-in 'auto' preset, builds a workspace-write profile with an extra writable path, sets a current working directory, and asks the chat widget whether the preset matches. It expects a match for the correct approval policy and no match when the approval policy is different.

Call relations: This test calls the helper that builds the realistic profile, then exercises the chat widget’s preset-matching logic directly. It checks the decision that later affects which popup row is marked current.

Call graph: calls 1 internal fn (app_server_workspace_write_profile); 1 external calls (assert!).

preset_matching_does_not_treat_non_cwd_writable_profile_as_read_only321–357 ↗
async fn preset_matching_does_not_treat_non_cwd_writable_profile_as_read_only()

Purpose: Makes sure a profile with any writable folder is not mistaken for read-only. Even if the writable folder is outside the current project, it still grants write power and should not be labeled read-only.

Data flow: It builds a managed profile with read access to root plus write access to a separate path, chooses a different current project path, and asks whether this matches the read-only preset. The expected answer is false.

Call relations: This test directly checks preset classification logic. It protects the permission menu from showing a dangerously optimistic 'read-only' label.

Call graph: 2 external calls (assert!, vec!).

full_access_confirmation_popup_snapshot360–373 ↗
async fn full_access_confirmation_popup_snapshot()

Purpose: Checks the exact rendered text of the full-access confirmation popup. This protects the warning screen shown before the user grants unrestricted access.

Data flow: It creates a chat widget, finds the built-in full-access preset, opens the confirmation popup, renders it at a fixed width, and compares the output to a saved snapshot.

Call relations: This test exercises the confirmation dialog that is opened by other permission-selection flows. It focuses on what the user sees at that safety checkpoint.

Call graph: 1 external calls (assert_chatwidget_snapshot!).

windows_auto_mode_prompt_requests_enabling_sandbox_feature377–395 ↗
async fn windows_auto_mode_prompt_requests_enabling_sandbox_feature()

Purpose: On Windows, verifies that selecting auto mode can prompt the user to enable the stronger sandbox feature. The prompt must explain administrator permissions and offer a non-admin fallback.

Data flow: It opens the Windows sandbox enable prompt for the auto preset, renders the popup, and checks that the text mentions administrator permissions and the non-admin sandbox option.

Call relations: This Windows-only test exercises the prompt used when a desired permission mode depends on sandbox setup. It checks the user-facing guidance.

Call graph: 1 external calls (assert!).

startup_prompts_for_windows_sandbox_when_agent_requested399–424 ↗
async fn startup_prompts_for_windows_sandbox_when_agent_requested()

Purpose: On Windows, checks that startup shows a sandbox setup prompt when the agent sandbox is requested but not enabled. This prevents the app from quietly running without the expected protection.

Data flow: It disables both Windows sandbox feature flags, asks the chat widget to maybe show the startup prompt immediately, renders the popup, and checks for administrator setup, default sandbox setup, non-admin fallback, and quit options.

Call relations: This Windows-only test drives the startup prompt path. It verifies that missing sandbox support is surfaced before normal use continues.

Call graph: 1 external calls (assert!).

startup_windows_sandbox_prompt_blocks_disallowed_unelevated_fallback428–447 ↗
async fn startup_windows_sandbox_prompt_blocks_disallowed_unelevated_fallback()

Purpose: On Windows, checks that the startup prompt hides the non-admin fallback when configuration allows only the elevated sandbox. This enforces organization requirements in the user interface.

Data flow: It disables sandbox features, installs a config stack that allows only elevated mode, triggers the startup prompt, renders it, and checks that the prompt explains the required sandbox while omitting the non-admin fallback option.

Call relations: This test uses the Windows requirements helper to simulate policy, then checks the startup prompt’s response to that policy.

Call graph: calls 1 internal fn (windows_sandbox_requirements_stack); 2 external calls (assert!, vec!).

windows_sandbox_required_enable_prompt_snapshot450–466 ↗
async fn windows_sandbox_required_enable_prompt_snapshot()

Purpose: Checks the rendered prompt shown when elevated Windows sandbox setup is required. The snapshot preserves the exact message and choices for this policy-driven state.

Data flow: It installs a config stack that allows only elevated sandbox mode, opens the Windows sandbox enable prompt for the auto preset, renders the popup, and compares it to a saved snapshot.

Call relations: This test uses the Windows requirements helper and then exercises the sandbox enable prompt. It protects the required-sandbox wording.

Call graph: calls 1 internal fn (windows_sandbox_requirements_stack); 2 external calls (assert_chatwidget_snapshot!, vec!).

windows_sandbox_required_enable_prompt_reopens_on_cancel_when_unelevated_allowed469–489 ↗
async fn windows_sandbox_required_enable_prompt_reopens_on_cancel_when_unelevated_allowed()

Purpose: Checks that cancelling a required Windows sandbox prompt reopens the prompt when an unelevated fallback is still allowed. This keeps the user in the setup decision flow instead of silently continuing.

Data flow: It sets the current sandbox mode to elevated, installs requirements allowing elevated and unelevated modes, opens the enable prompt, simulates Escape, and checks that an event was sent to open the prompt again.

Call relations: This test uses the requirements helper, then follows the popup cancellation path. It verifies that the chat widget hands control back to the prompt-opening flow.

Call graph: calls 1 internal fn (windows_sandbox_requirements_stack); 3 external calls (new, assert!, vec!).

required_windows_sandbox_setup_defers_configured_initial_prompt492–549 ↗
async fn required_windows_sandbox_setup_defers_configured_initial_prompt()

Purpose: Ensures that a configured initial user message is not submitted while required Windows sandbox setup is still unresolved. The app should not start the assistant’s first task until the safety requirement is satisfied.

Data flow: It creates a chat widget with an initial prompt, configures Windows sandbox requirements, feeds in a session state, drains startup history events, and confirms no user-turn operation was sent. After setting the sandbox mode to an allowed fallback, it submits pending initial input and checks that the original prompt is finally sent.

Call relations: This test combines session setup, sandbox policy, and initial-message submission. It uses the Windows requirements helper, then verifies that the operation channel only receives the user turn after setup is no longer blocking.

Call graph: calls 3 internal fn (workspace_write, new, windows_sandbox_requirements_stack); 6 external calls (new, new, assert!, assert_eq!, panic!, vec!).

windows_sandbox_required_fallback_prompt_snapshot552–566 ↗
async fn windows_sandbox_required_fallback_prompt_snapshot()

Purpose: Checks the rendered fallback prompt shown when Windows sandbox policy requires elevated mode. The snapshot makes sure the required-fallback wording stays clear.

Data flow: It installs a config stack allowing only elevated mode, opens the Windows sandbox fallback prompt for the auto preset, renders the popup, and compares it against a saved snapshot.

Call relations: This test uses the Windows requirements helper and focuses on the fallback prompt path rather than the main enable prompt.

Call graph: calls 1 internal fn (windows_sandbox_requirements_stack); 2 external calls (assert_chatwidget_snapshot!, vec!).

startup_does_not_prompt_for_windows_sandbox_when_not_requested570–581 ↗
async fn startup_does_not_prompt_for_windows_sandbox_when_not_requested()

Purpose: On Windows, verifies that the sandbox setup prompt is not shown unless startup actually requests it. This avoids surprising users with setup screens at the wrong time.

Data flow: It disables Windows sandbox features, calls the startup prompt check with 'show now' set to false, and asserts that no modal or popup is active in the bottom pane.

Call relations: This Windows-only test covers the negative branch of the startup prompt logic. It checks that the chat widget leaves the interface untouched.

Call graph: 1 external calls (assert!).

approvals_popup_shows_disabled_presets584–619 ↗
async fn approvals_popup_shows_disabled_presets()

Purpose: Checks that permission presets blocked by configuration are still visible as disabled, with the reason shown. This helps users understand why a choice cannot be selected.

Data flow: It constrains the approval policy so only 'on request' is allowed, opens the approvals popup, renders the full terminal screen, collapses the text, and asserts that the disabled label and configured reason appear.

Call relations: This test exercises rendering with constrained configuration. It uses the terminal renderer instead of only the popup helper so it can inspect the displayed screen.

Call graph: calls 2 internal fn (new, new); 3 external calls (new, assert!, new).

approvals_popup_navigation_skips_disabled622–717 ↗
async fn approvals_popup_navigation_skips_disabled()

Purpose: Ensures that keyboard navigation and numeric shortcuts cannot select disabled permission presets. Disabled rows should be informational only, not hidden traps.

Data flow: It constrains the approval policy, opens the popup, finds the shortcut number for a disabled row from the rendered text, repeatedly presses Down and confirms the selection never lands on a disabled row. It then presses the disabled shortcut and checks that no action occurs, followed by Enter on an enabled row and confirmation that the correct update event is emitted.

Call relations: This test simulates detailed keyboard use of the approvals popup. It watches both app events and operation events to make sure disabled choices are skipped and only enabled choices are dispatched.

Call graph: calls 1 internal fn (new); 5 external calls (Char, from, new, assert!, from_digit).

permissions_selection_emits_history_cell_when_selection_changes720–744 ↗
async fn permissions_selection_emits_history_cell_when_selection_changes()

Purpose: Checks that changing permissions writes a history message into the chat. This gives the user a visible record that the permission mode changed.

Data flow: It opens the permissions popup, moves to another choice, selects it, drains inserted history cells from the event channel, and checks that exactly one cell says permissions were updated.

Call relations: This test follows the user selection path and then inspects the history-event output. It verifies the chat transcript records the change.

Call graph: 3 external calls (from, assert!, assert_eq!).

permissions_selection_history_snapshot_after_mode_switch747–769 ↗
async fn permissions_selection_history_snapshot_after_mode_switch()

Purpose: Checks the exact history message after switching permission modes. The snapshot preserves the wording and formatting of the audit-style message shown in chat.

Data flow: It opens the permissions popup, moves to another mode, selects it, drains the inserted history cell, and compares its rendered single-line text to a saved snapshot.

Call relations: This test extends the history-cell behavior check by snapshotting the full message. It uses platform-specific navigation where Windows has an extra row.

Call graph: 3 external calls (from, assert_chatwidget_snapshot!, assert_eq!).

permissions_selection_history_snapshot_full_access_to_default772–812 ↗
async fn permissions_selection_history_snapshot_full_access_to_default()

Purpose: Checks the history message when moving from full access back to a safer default mode. This confirms the transcript clearly records reducing permissions too, not only increasing them.

Data flow: It starts the widget in full-access mode, opens the permissions popup, navigates back toward the default choice, selects it, drains the history cell, and compares the rendered text to a saved snapshot, with a Windows-specific snapshot when needed.

Call relations: This test drives the permission menu from a risky starting state. It verifies the resulting history entry through the shared snapshot assertion.

Call graph: 4 external calls (from, assert_chatwidget_snapshot!, assert_eq!, with_settings!).

permissions_selection_emits_history_cell_when_current_is_selected815–846 ↗
async fn permissions_selection_emits_history_cell_when_current_is_selected()

Purpose: Checks that selecting the already-current permission mode still writes a history message. This gives the user feedback that their selection was accepted.

Data flow: It sets the current approval policy and permission profile to workspace write with approval on request, opens the popup, presses Enter without moving, drains history events, and checks that one permissions-updated message appears.

Call relations: This test uses the same popup selection flow as a normal change, but with no actual mode difference. It ensures the user still gets visible confirmation.

Call graph: calls 1 internal fn (workspace_write); 3 external calls (from, assert!, assert_eq!).

permissions_selection_hides_auto_review_when_feature_disabled849–866 ↗
async fn permissions_selection_hides_auto_review_when_feature_disabled()

Purpose: Verifies that the 'Approve for me' option is not shown when the Guardian Approval feature flag is disabled. Feature flags are switches that let the app turn behavior on or off safely.

Data flow: It disables the Guardian Approval feature, opens the permissions popup, renders it, and checks that the text does not contain 'Approve for me'.

Call relations: This test checks the rendering branch controlled by the feature flag. It protects users from seeing a mode that should not be available.

Call graph: 1 external calls (assert!).

permissions_selection_hides_auto_review_when_feature_disabled_even_if_auto_review_is_active869–897 ↗
async fn permissions_selection_hides_auto_review_when_feature_disabled_even_if_auto_review_is_active()

Purpose: Checks that 'Approve for me' stays hidden when the feature is disabled, even if the current internal reviewer value is auto-review. The visible menu should obey the feature flag.

Data flow: It disables the Guardian Approval feature, sets the current reviewer to AutoReview and the permissions to workspace write, opens the popup, renders it, and asserts that 'Approve for me' is absent.

Call relations: This test covers a mismatch between stored state and feature availability. It ensures rendering follows the feature flag rather than exposing an unavailable option.

Call graph: calls 1 internal fn (workspace_write); 1 external calls (assert!).

permissions_selection_marks_auto_review_current_after_session_configured900–943 ↗
async fn permissions_selection_marks_auto_review_current_after_session_configured()

Purpose: Checks that after session configuration says auto-review is active, the permissions popup marks 'Approve for me' as current. This keeps the UI in sync with the session state received from the backend.

Data flow: It enables Guardian Approval, feeds the chat widget a session state with approval on request, auto-review, and workspace-write permissions, opens the popup, renders it, and checks for 'Approve for me (current)'.

Call relations: This test exercises the session-state update path before opening the popup. It verifies that later rendering reflects the synchronized reviewer state.

Call graph: calls 2 internal fn (workspace_write, new); 3 external calls (new, new, assert!).

permissions_selection_marks_auto_review_current_with_custom_workspace_write_details946–993 ↗
async fn permissions_selection_marks_auto_review_current_with_custom_workspace_write_details()

Purpose: Checks that auto-review is still marked current when the workspace-write profile has extra writable paths. The UI should recognize the mode by meaning, not require an exact byte-for-byte built-in profile.

Data flow: It enables Guardian Approval, builds a workspace-write-like profile with an extra path, feeds that into session state with AutoReview, opens the popup, renders it, and checks that 'Approve for me (current)' appears.

Call relations: This test uses the custom profile helper and the session configuration path. It protects the same preset-recognition behavior that other tests check directly.

Call graph: calls 2 internal fn (new, app_server_workspace_write_profile); 3 external calls (new, new, assert!).

permissions_selection_can_disable_auto_review996–1033 ↗
async fn permissions_selection_can_disable_auto_review()

Purpose: Verifies that selecting manual approval while auto-review is available switches the reviewer back to the user. It also checks that doing this does not change feature flags.

Data flow: It enables Guardian Approval, sets workspace-write permissions, opens the popup, moves selection upward to the manual approval choice, presses Enter, gathers events, and checks for an UpdateApprovalsReviewer event with User and no feature-flag update event.

Call relations: This test follows a user turning off auto-review through the permissions menu. It confirms the chat widget sends a reviewer update rather than changing global feature availability.

Call graph: calls 1 internal fn (workspace_write); 3 external calls (from, assert!, from_fn).

permissions_selection_sends_approvals_reviewer_in_override_turn_context1036–1115 ↗
async fn permissions_selection_sends_approvals_reviewer_in_override_turn_context()

Purpose: Checks that selecting 'Approve for me' sends the reviewer choice inside the operation that updates the assistant’s turn context. The backend needs this value to know who reviews approvals.

Data flow: It enables Guardian Approval, starts in manual workspace-write mode, opens the popup, confirms the current row is selected, moves down to 'Approve for me', selects it, then searches emitted events for an OverrideTurnContext operation. It compares that operation to the expected values, including AutoReview and the active workspace profile, and also checks for an active-profile update event.

Call relations: This test ties the visible popup selection to the command sent to the rest of the app. It verifies both the operation event for the backend and the separate UI state update event.

Call graph: calls 1 internal fn (workspace_write); 4 external calls (from, assert!, assert_eq!, from_fn).

permissions_full_access_history_cell_emitted_only_after_confirmation1118–1183 ↗
async fn permissions_full_access_history_cell_emitted_only_after_confirmation()

Purpose: Ensures that selecting full access does not write the history message until the user confirms the warning. The transcript should not claim full access was enabled before the safety step is accepted.

Data flow: It opens the permissions popup, navigates to full access, selects it, collects any events before confirmation, and expects a full-access confirmation event. It opens that confirmation popup, verifies the warning appears, presses Enter to confirm, drains history cells, and checks that exactly one history message says permissions were updated to Full Access.

Call relations: This test links the permission menu, the full-access confirmation popup, and the chat history output. It verifies the safety handoff: selection opens confirmation first, and the history record appears only after confirmation.

Call graph: 5 external calls (from, new, assert!, assert_eq!, cfg!).

tui/src/chatwidget/tests/plan_mode.rssource ↗
testtest run

Plan mode is a special way to use the chat widget when the user wants the assistant to think through a plan before coding. This test file acts like a safety checklist for that feature. It checks small details, such as recognizing the word “plan” without accidentally matching “plane,” and larger flows, such as showing a popup after a plan is finished so the user can choose whether to implement it. It also tests that the interface does not interrupt the user at the wrong time: no nudges during active tasks, no duplicate popups after replayed history, and no Plan mode switch while another turn is running if that would change modes. Several tests cover “reasoning effort,” meaning how much thinking power the selected model should use, especially when Plan mode has its own override separate from the global default. Other tests confirm that notifications, slash commands, plugin mentions, personality settings, startup options, and Vim-style editing defaults still behave correctly around Plan mode. Without these tests, Plan mode could easily become confusing: hints might appear too often, implementation prompts might show at unsafe times, or submitted messages might be sent with the wrong mode or model settings.

Function details62
plan_mode_nudge_matches_only_standalone_plain_text_keyword5–12 ↗
fn plan_mode_nudge_matches_only_standalone_plain_text_keyword()

Purpose: Checks that the Plan mode hint only reacts to the standalone word “plan,” not words that merely contain those letters. This prevents annoying false hints when the user types words like “plane” or “planning.”

Data flow: The test feeds several short text examples into the keyword checker. It expects true for plain standalone uses, including punctuation before the word, and false for longer words. Nothing is changed outside the test.

Call relations: The Rust test runner calls this directly. It exercises the keyword detection helper before the larger chat-widget tests rely on that same rule.

Call graph: 1 external calls (assert!).

plan_mode_nudge_shows_only_for_eligible_default_mode_drafts15–35 ↗
async fn plan_mode_nudge_shows_only_for_eligible_default_mode_drafts()

Purpose: Verifies that the Plan mode nudge appears only when a normal draft mentions planning and the user is not already using a Plan-related command or mode.

Data flow: The test creates a chat widget, puts different text into the composer, advances the widget’s pre-draw update, and reads whether the bottom pane says the nudge is visible. It then switches to Plan mode and confirms the nudge disappears.

Call relations: The test runner calls this. It uses the Plan mode mask helper to move the widget into Plan mode and checks the user-facing nudge state after each edit.

Call graph: calls 1 internal fn (plan_mask); 2 external calls (new, assert!).

plan_mode_nudge_hides_while_task_or_modal_is_active38–60 ↗
async fn plan_mode_nudge_hides_while_task_or_modal_is_active()

Purpose: Makes sure the Plan mode nudge does not compete with active work or an open selection popup. The hint should be quiet when the interface is already busy.

Data flow: The test starts with text that should show the nudge, then marks a task as running and later opens a selection view. After each state change it asks the bottom pane whether the nudge is visible.

Call relations: The test runner invokes it. It drives the chat widget through task and modal states to confirm the nudge is suppressed by higher-priority UI.

Call graph: 4 external calls (default, new, assert!, vec!).

plan_mode_nudge_dismissal_is_scoped_to_current_thread63–87 ↗
async fn plan_mode_nudge_dismissal_is_scoped_to_current_thread()

Purpose: Checks that dismissing the Plan mode nudge only hides it for the current conversation thread. A different thread should still be allowed to show the hint.

Data flow: The test creates two thread IDs, assigns one to the chat, shows and dismisses the nudge with Escape, then switches threads and repeats. It observes whether the nudge is visible after each thread switch.

Call relations: The test runner calls it. It uses thread IDs to prove that the dismissal memory belongs to a thread, not to the whole chat widget forever.

Call graph: calls 1 internal fn (new); 3 external calls (new, new, assert!).

plan_mode_nudge_shift_tab_uses_existing_mode_cycle_path90–100 ↗
async fn plan_mode_nudge_shift_tab_uses_existing_mode_cycle_path()

Purpose: Confirms that pressing Shift+Tab while the nudge is visible switches to Plan mode through the normal mode-cycling path. This keeps the shortcut behavior consistent with the rest of the widget.

Data flow: The test types text that triggers the nudge, sends a BackTab key event, and then reads the active collaboration mode and nudge visibility. The result should be Plan mode with the nudge gone.

Call relations: The test runner invokes it. It connects the visible hint to the existing keyboard path for changing modes rather than a separate special-case path.

Call graph: 4 external calls (from, new, assert!, assert_eq!).

plan_mode_nudge_snapshot103–112 ↗
async fn plan_mode_nudge_snapshot()

Purpose: Records what the Plan mode nudge popup should look like at normal width. Snapshot tests catch unintended visual changes.

Data flow: The test creates a chat widget, adds token usage information, triggers the nudge, renders the bottom popup, and compares the rendered text to a saved snapshot.

Call relations: The test runner calls it. It relies on the same rendering path users see and hands the output to the snapshot assertion macro.

Call graph: 2 external calls (new, assert_chatwidget_snapshot!).

plan_mode_nudge_narrow_snapshot115–124 ↗
async fn plan_mode_nudge_narrow_snapshot()

Purpose: Checks the Plan mode nudge layout in a narrow terminal. This protects users on small windows from broken or unreadable popup text.

Data flow: The test triggers the nudge, renders the bottom popup with a narrow width, and compares that output to the expected snapshot.

Call relations: The test runner calls it. It follows the normal rendering path but changes the available width to exercise wrapping behavior.

Call graph: 2 external calls (new, assert_chatwidget_snapshot!).

plan_implementation_popup_snapshot127–134 ↗
async fn plan_implementation_popup_snapshot()

Purpose: Captures the expected appearance of the prompt that asks what to do after a plan is completed.

Data flow: The test records a completed plan, opens the implementation prompt, renders the bottom popup, and compares it to a stored snapshot.

Call relations: The test runner invokes it. It checks the visual result of the plan-completion flow after the widget opens the implementation prompt.

Call graph: 1 external calls (assert_chatwidget_snapshot!).

plan_implementation_popup_context_usage_snapshot137–147 ↗
async fn plan_implementation_popup_context_usage_snapshot()

Purpose: Verifies the plan implementation popup when context usage information is shown. Context usage means how much of the model’s memory window is already filled.

Data flow: The test gives the widget high token usage, records a completed plan, opens the implementation prompt, renders it, and compares it with a snapshot.

Call relations: The test runner calls it. It combines token tracking with the plan implementation prompt to protect the displayed context warning.

Call graph: 1 external calls (assert_chatwidget_snapshot!).

plan_implementation_popup_no_selected_snapshot150–158 ↗
async fn plan_implementation_popup_no_selected_snapshot()

Purpose: Checks how the implementation popup looks when no option is selected. This guards a specific keyboard-navigation state.

Data flow: The test opens the popup, sends a Down key press to move selection, renders the popup, and compares it to the saved snapshot.

Call relations: The test runner invokes it. It uses the popup’s own key handling before passing the rendered result to snapshot comparison.

Call graph: 2 external calls (from, assert_chatwidget_snapshot!).

plan_implementation_popup_yes_emits_submit_message_event161–180 ↗
async fn plan_implementation_popup_yes_emits_submit_message_event()

Purpose: Confirms that choosing the default “yes, implement” option sends a submit-message event in normal coding mode.

Data flow: The test opens the prompt, presses Enter, receives an app event from the channel, and checks that the event contains the fixed implementation message and Default collaboration mode.

Call relations: The test runner calls it. The popup hands the user’s choice to the app event channel, where the rest of the app would pick it up and submit the message.

Call graph: 3 external calls (from, assert_eq!, panic!).

plan_implementation_popup_clear_context_emits_clear_submit_event183–204 ↗
async fn plan_implementation_popup_clear_context_emits_clear_submit_event()

Purpose: Checks that the “fresh context” implementation option clears the current UI and submits a message containing the approved plan.

Data flow: The test stores completed plan markdown, opens the prompt, moves to the clear-context option, presses Enter, and reads the resulting app event. The event text should include instructions plus the plan.

Call relations: The test runner invokes it. It follows the selection popup path into an app event that later code would use to start a fresh implementation thread.

Call graph: 3 external calls (from, assert_eq!, panic!).

plan_implementation_clear_context_requires_default_mode_and_plan207–264 ↗
async fn plan_implementation_clear_context_requires_default_mode_and_plan()

Purpose: Verifies that the clear-context option is only enabled when Default mode exists and there is a non-empty approved plan.

Data flow: The test builds selection-view parameters with missing mode, missing plan, blank plan, and valid plan. It reads disabled reasons, descriptions, and actions from the resulting menu items.

Call relations: The test runner calls it. It exercises the plan implementation menu builder directly, using the default-mode mask helper as the valid-mode input.

Call graph: calls 2 internal fn (selection_view_params, default_mode_mask); 2 external calls (assert!, assert_eq!).

submit_user_message_with_mode_sets_coding_collaboration_mode267–290 ↗
async fn submit_user_message_with_mode_sets_coding_collaboration_mode()

Purpose: Makes sure a message submitted with an explicit mode is sent to the backend with that collaboration mode attached.

Data flow: The test creates a thread, enables collaboration modes, builds a Default mode mask, submits text with that mask, and reads the outgoing operation. The outgoing user turn must carry Default mode.

Call relations: The test runner invokes it. It checks the bridge from chat-widget submission code to the operation channel used by backend-facing code.

Call graph: calls 2 internal fn (new, default_mode_mask); 1 external calls (panic!).

reasoning_selection_in_plan_mode_opens_scope_prompt_event293–317 ↗
async fn reasoning_selection_in_plan_mode_opens_scope_prompt_event()

Purpose: Checks that changing reasoning effort while in Plan mode asks where the change should apply. This avoids silently changing only Plan mode or all modes without user consent.

Data flow: The test enters Plan mode, opens the reasoning popup for a model, moves to a different effort, presses Enter, and reads the app event. The expected event opens a Plan reasoning scope prompt.

Call relations: The test runner calls it. It drives the reasoning popup and expects it to hand off to a second prompt that asks about scope.

Call graph: calls 2 internal fn (new, plan_mask); 2 external calls (from, assert_matches!).

reasoning_selection_in_plan_mode_without_effort_change_does_not_open_scope_prompt_event320–350 ↗
async fn reasoning_selection_in_plan_mode_without_effort_change_does_not_open_scope_prompt_event()

Purpose: Confirms that choosing the current reasoning effort in Plan mode does not open the extra scope prompt.

Data flow: The test sets the current reasoning effort, opens the reasoning popup, presses Enter without changing selection, drains emitted events, and checks for normal model and reasoning update events.

Call relations: The test runner invokes it. It verifies the reasoning popup only opens the Plan-specific scope prompt when there is an actual Plan-mode ambiguity.

Call graph: calls 2 internal fn (new, plan_mask); 3 external calls (from, assert!, from_fn).

reasoning_selection_in_plan_mode_matching_plan_effort_but_different_global_opens_scope_prompt353–381 ↗
async fn reasoning_selection_in_plan_mode_matching_plan_effort_but_different_global_opens_scope_prompt()

Purpose: Covers a subtle case where Plan mode’s effective reasoning matches the selected option but the global default differs. The UI should still ask the user what scope they intend.

Data flow: The test sets a global reasoning effort different from Plan mode’s built-in default, opens the reasoning popup, selects the current Plan option, and checks for a scope-prompt event carrying medium effort.

Call relations: The test runner calls it. It protects the reasoning popup from silently rewriting the global default when Plan mode is active.

Call graph: calls 2 internal fn (new, plan_mask); 2 external calls (from, assert_matches!).

reasoning_shortcut_in_plan_mode_updates_plan_override_without_prompt_or_persist384–428 ↗
async fn reasoning_shortcut_in_plan_mode_updates_plan_override_without_prompt_or_persist()

Purpose: Verifies that the keyboard shortcut for reasoning effort updates only the Plan mode override while in Plan mode, without opening a prompt or saving global settings.

Data flow: The test enters Plan mode, sends Alt+Period, drains app events, and checks that there is a Plan override update but no scope prompt, no persistence event, and no global reasoning update.

Call relations: The test runner invokes it. It checks the shortcut path separately from the reasoning popup path.

Call graph: calls 2 internal fn (new, plan_mask); 4 external calls (Char, new, assert!, from_fn).

plan_mode_reasoning_override_is_marked_current_in_reasoning_popup431–451 ↗
async fn plan_mode_reasoning_override_is_marked_current_in_reasoning_popup()

Purpose: Checks that the reasoning popup labels the Plan mode override as the current choice. This keeps the menu honest when Plan mode differs from the global setting.

Data flow: The test sets global reasoning to high, Plan override to low, enters Plan mode, opens the popup, renders it, and searches the text for the correct “current” label.

Call relations: The test runner calls it. It connects stored Plan override state to the user-visible reasoning menu.

Call graph: calls 1 internal fn (plan_mask); 1 external calls (assert!).

reasoning_selection_in_plan_mode_model_switch_does_not_open_scope_prompt_event454–482 ↗
async fn reasoning_selection_in_plan_mode_model_switch_does_not_open_scope_prompt_event()

Purpose: Confirms that switching models in Plan mode follows the normal update path instead of opening the Plan reasoning scope prompt.

Data flow: The test enters Plan mode, opens the reasoning popup for a different model, presses Enter, drains events, and checks for model and reasoning updates.

Call relations: The test runner invokes it. It distinguishes a model switch from a Plan reasoning-scope decision.

Call graph: calls 2 internal fn (new, plan_mask); 3 external calls (from, assert!, from_fn).

plan_reasoning_scope_popup_all_modes_persists_global_and_plan_override485–515 ↗
async fn plan_reasoning_scope_popup_all_modes_persists_global_and_plan_override()

Purpose: Checks that choosing the “all modes” option in the Plan reasoning scope popup saves both the global model reasoning choice and the Plan override.

Data flow: The test opens the scope prompt, moves to the all-modes option, presses Enter, drains app events, and looks for Plan override update, Plan override persistence, and global model-selection persistence.

Call relations: The test runner calls it. It exercises the scope prompt’s event output, which later app code would use to update in-memory state and saved preferences.

Call graph: 3 external calls (from, assert!, from_fn).

plan_mode_prompt_notification_uses_dedicated_type_name518–533 ↗
fn plan_mode_prompt_notification_uses_dedicated_type_name()

Purpose: Verifies that Plan mode prompts have their own notification type name and display text.

Data flow: The test creates a PlanModePrompt notification, checks which notification filters allow it, and checks the human-readable display string.

Call relations: The test runner invokes it. It tests the notification type directly before other tests check when the chat widget sets that notification.

Call graph: 2 external calls (assert!, assert_eq!).

open_plan_implementation_prompt_sets_pending_notification536–547 ↗
async fn open_plan_implementation_prompt_sets_pending_notification()

Purpose: Checks that opening the plan implementation prompt sets a pending desktop or terminal notification when that notification type is enabled.

Data flow: The test enables only plan-mode prompt notifications, opens the implementation prompt, and inspects the widget’s pending notification field.

Call relations: The test runner calls it. It follows the prompt-opening path and confirms it prepares a notification for the app’s notification system.

Call graph: 3 external calls (assert_matches!, Custom, vec!).

open_plan_reasoning_scope_prompt_sets_pending_notification550–561 ↗
async fn open_plan_reasoning_scope_prompt_sets_pending_notification()

Purpose: Checks that opening the Plan reasoning scope prompt also sets a Plan mode prompt notification.

Data flow: The test enables plan-mode prompt notifications, opens the reasoning scope prompt, and reads the pending notification title.

Call relations: The test runner invokes it. It ensures the reasoning-scope prompt participates in the same notification path as the implementation prompt.

Call graph: 3 external calls (assert_matches!, Custom, vec!).

agent_turn_complete_does_not_override_pending_plan_mode_prompt_notification564–576 ↗
async fn agent_turn_complete_does_not_override_pending_plan_mode_prompt_notification()

Purpose: Makes sure a normal “agent turn complete” notification does not replace an already pending Plan mode prompt notification.

Data flow: The test opens the plan implementation prompt, then sends an agent-complete notification, and checks that the pending notification is still the Plan prompt.

Call relations: The test runner calls it. It tests notification priority: a prompt needing user attention stays ahead of a routine completion notice.

Call graph: 1 external calls (assert_matches!).

request_user_input_notification_overrides_pending_agent_turn_complete_notification579–607 ↗
async fn request_user_input_notification_overrides_pending_agent_turn_complete_notification()

Purpose: Confirms that a new request for user input can replace a pending agent-complete notification. User decisions should be more urgent than completion messages.

Data flow: The test first sets an agent-complete notification, then simulates a tool asking the user a reasoning-scope question. The pending notification should become a Plan mode prompt titled from the question header.

Call relations: The test runner invokes it. It drives the request-user-input path and checks notification priority.

Call graph: 2 external calls (assert_matches!, vec!).

handle_request_user_input_sets_pending_notification610–637 ↗
async fn handle_request_user_input_sets_pending_notification()

Purpose: Checks that when the backend asks the user a question, the chat widget sets a Plan mode prompt notification if that notification type is enabled.

Data flow: The test enables plan-mode prompt notifications, passes a user-input request with one question, and inspects the pending notification title.

Call relations: The test runner calls it. It links backend user-input requests to the notification mechanism.

Call graph: 3 external calls (assert_matches!, Custom, vec!).

plan_reasoning_scope_popup_mentions_selected_reasoning640–654 ↗
async fn plan_reasoning_scope_popup_mentions_selected_reasoning()

Purpose: Verifies that the Plan reasoning scope popup clearly names the selected reasoning level and explains both scope choices.

Data flow: The test sets an existing Plan override, opens the scope prompt for medium reasoning, renders the popup, and checks for key explanatory phrases.

Call relations: The test runner invokes it. It checks the text produced by the scope prompt renderer for a case with an existing user-chosen Plan override.

Call graph: 1 external calls (assert!).

plan_reasoning_scope_popup_mentions_built_in_plan_default_when_no_override657–666 ↗
async fn plan_reasoning_scope_popup_mentions_built_in_plan_default_when_no_override()

Purpose: Checks that the scope popup explains the built-in Plan default when the user has not set a Plan override.

Data flow: The test opens the scope prompt without setting a Plan override, renders it, and searches for text describing the built-in default.

Call relations: The test runner calls it. It covers the no-override branch of the same prompt tested by the previous function.

Call graph: 1 external calls (assert!).

plan_reasoning_scope_popup_plan_only_does_not_update_all_modes_reasoning669–689 ↗
async fn plan_reasoning_scope_popup_plan_only_does_not_update_all_modes_reasoning()

Purpose: Confirms that choosing the Plan-only option updates Plan mode reasoning but leaves the global reasoning setting untouched.

Data flow: The test opens the scope prompt, accepts the default Plan-only option, drains events, and checks for a Plan update while ensuring no global reasoning update appears.

Call relations: The test runner invokes it. It tests the event output of the Plan-only branch of the reasoning scope prompt.

Call graph: 3 external calls (from, assert!, from_fn).

submit_user_message_with_mode_errors_when_mode_changes_during_running_turn692–717 ↗
async fn submit_user_message_with_mode_errors_when_mode_changes_during_running_turn()

Purpose: Checks that the widget refuses to switch collaboration modes while a turn is already running.

Data flow: The test starts in Plan mode, marks a task as running, tries to submit a Default-mode message, then checks that no backend operation is sent and an error appears in history.

Call relations: The test runner calls it. It protects the submit path from changing modes mid-turn, which could confuse the active backend conversation.

Call graph: calls 3 internal fn (new, default_mask, mask_for_kind); 3 external calls (assert!, assert_eq!, assert_matches!).

submit_user_message_blocks_when_thread_model_is_unavailable720–739 ↗
async fn submit_user_message_blocks_when_thread_model_is_unavailable()

Purpose: Verifies that a message cannot be submitted when the thread has no usable model.

Data flow: The test clears the model, types a message, presses Enter, and checks that no submit operation is produced. It then reads history output for an unavailable-model error.

Call relations: The test runner invokes it. It exercises the normal Enter-to-submit path and confirms validation blocks the backend operation.

Call graph: calls 1 internal fn (new); 3 external calls (from, new, assert!).

submit_user_message_with_mode_allows_same_mode_during_running_turn742–769 ↗
async fn submit_user_message_with_mode_allows_same_mode_during_running_turn()

Purpose: Confirms that submitting another message in the same collaboration mode is allowed during a running turn.

Data flow: The test starts a Plan-mode turn, submits more Plan-mode text, and reads the outgoing operation. The operation should be a user turn still marked as Plan mode.

Call relations: The test runner calls it. It distinguishes a safe same-mode steer from the unsafe mode-switch case tested nearby.

Call graph: calls 2 internal fn (new, mask_for_kind); 3 external calls (assert!, assert_eq!, panic!).

submit_user_message_with_mode_submits_when_plan_stream_is_not_active772–799 ↗
async fn submit_user_message_with_mode_submits_when_plan_stream_is_not_active()

Purpose: Checks that switching from Plan mode to Default mode is allowed when no Plan stream is actively running.

Data flow: The test enters Plan mode without starting a task, submits a Default-mode implementation message, and verifies that the active mode and outgoing user turn use the expected Default mode.

Call relations: The test runner invokes it. It tests the allowed handoff from planning to implementation when the widget is idle.

Call graph: calls 3 internal fn (new, default_mask, mask_for_kind); 3 external calls (assert!, assert_eq!, panic!).

plan_implementation_popup_skips_replayed_turn_complete802–833 ↗
async fn plan_implementation_popup_skips_replayed_turn_complete()

Purpose: Makes sure old replayed conversation history does not trigger a fresh plan implementation popup.

Data flow: The test enters Plan mode and replays a completed server turn containing an agent message. It renders the bottom popup and checks that the implementation title is absent.

Call relations: The test runner calls it. It exercises the replay path so restored history does not behave like new live output.

Call graph: calls 1 internal fn (mask_for_kind); 2 external calls (assert!, vec!).

plan_implementation_popup_shows_once_when_replay_precedes_live_turn_complete836–904 ↗
async fn plan_implementation_popup_shows_once_when_replay_precedes_live_turn_complete()

Purpose: Verifies that replayed history does not show the implementation prompt, but the first later live completed plan does, and only once.

Data flow: The test records plan output, replays an old turn, confirms no popup, completes a live agent message and turn, confirms the popup appears, dismisses it, then completes another live turn and confirms no duplicate popup.

Call relations: The test runner invokes it. It combines replay handling, live completion handling, Escape dismissal, and duplicate prevention.

Call graph: calls 1 internal fn (mask_for_kind); 3 external calls (new, assert!, vec!).

plan_implementation_popup_skips_when_messages_queued907–927 ↗
async fn plan_implementation_popup_skips_when_messages_queued()

Purpose: Checks that the plan implementation popup does not appear if user messages are already queued. The queue should continue without an extra prompt interrupting it.

Data flow: The test enters Plan mode, marks a task running, queues a user message, completes the task with plan details, and renders the popup area. The implementation prompt should be absent.

Call relations: The test runner calls it. It verifies that the task-complete path respects the input queue before opening Plan prompts.

Call graph: calls 1 internal fn (mask_for_kind); 1 external calls (assert!).

plan_implementation_popup_skips_without_proposed_plan930–954 ↗
async fn plan_implementation_popup_skips_without_proposed_plan()

Purpose: Makes sure the implementation prompt is not shown merely because an internal plan status update happened. It requires actual proposed plan output.

Data flow: The test sends a structured plan update with a pending item, completes the task, renders the popup, and checks that the implementation title is not present.

Call relations: The test runner invokes it. It separates internal progress updates from final plan text that can be offered for implementation.

Call graph: calls 1 internal fn (mask_for_kind); 2 external calls (assert!, vec!).

plan_implementation_popup_shows_after_proposed_plan_output957–976 ↗
async fn plan_implementation_popup_shows_after_proposed_plan_output()

Purpose: Checks the positive case: after real plan text has been produced and the task completes, the implementation prompt appears.

Data flow: The test starts a Plan-mode task, sends plan text as both a streaming delta and completed item, completes the task, renders the popup, and searches for the prompt title.

Call relations: The test runner calls it. It validates the normal live Plan-mode completion flow.

Call graph: calls 1 internal fn (mask_for_kind); 1 external calls (assert!).

plan_implementation_popup_skips_when_steer_follows_proposed_plan979–1019 ↗
async fn plan_implementation_popup_skips_when_steer_follows_proposed_plan()

Purpose: Confirms that if the user sends a follow-up instruction after a plan, the old plan does not immediately trigger an implementation popup.

Data flow: The test records an initial plan, submits a user follow-up, completes that user message, finishes the task, and checks that no implementation popup appears.

Call relations: The test runner invokes it. It protects the task-complete logic from treating an older plan as newly actionable after a user steer.

Call graph: calls 2 internal fn (new, mask_for_kind); 5 external calls (new, new, assert!, assert_eq!, panic!).

plan_implementation_popup_shows_after_new_plan_follows_steer1022–1066 ↗
async fn plan_implementation_popup_shows_after_new_plan_follows_steer()

Purpose: Checks that if a new plan is produced after the user’s follow-up instruction, the implementation prompt does appear.

Data flow: The test records an initial plan, submits a revision request, completes the user message, records a revised plan, completes the task, and checks that the popup contains the implementation title.

Call relations: The test runner calls it. It complements the previous test by proving new plan output after a steer is still actionable.

Call graph: calls 2 internal fn (new, mask_for_kind); 5 external calls (new, new, assert!, assert_eq!, panic!).

plan_implementation_popup_skips_when_rate_limit_prompt_pending1069–1099 ↗
async fn plan_implementation_popup_skips_when_rate_limit_prompt_pending()

Purpose: Verifies that a rate-limit warning takes priority over the plan implementation prompt.

Data flow: The test enters Plan mode with a ChatGPT account, creates a plan update, sends a high rate-limit snapshot, completes the task, and renders the popup. It expects the rate-limit popup and not the plan implementation prompt.

Call relations: The test runner invokes it. It checks popup priority when two possible prompts could be shown.

Call graph: calls 1 internal fn (mask_for_kind); 2 external calls (assert!, vec!).

plan_completion_restores_status_indicator_after_streaming_plan_output1102–1123 ↗
async fn plan_completion_restores_status_indicator_after_streaming_plan_output()

Purpose: Checks that the task status indicator returns after streaming plan output finishes.

Data flow: The test starts a task, observes the status indicator, streams plan text and commits it to history, observes that the indicator hides during streaming output, then completes the plan item and confirms the indicator returns while the task is still running.

Call relations: The test runner calls it. It exercises the visual transition between streaming plan content and normal running-task status.

Call graph: calls 1 internal fn (mask_for_kind); 1 external calls (assert_eq!).

submit_user_message_queues_while_compaction_turn_is_running1126–1202 ↗
async fn submit_user_message_queues_while_compaction_turn_is_running()

Purpose: Tests a recovery path for messages sent while a compaction turn is running. A compaction turn is maintenance work that cannot accept live user steering.

Data flow: The test simulates a running compaction turn, submits a user message, observes an attempted operation, then simulates a backend error saying the turn cannot be steered. The message is moved back into the queue and submitted again after the turn completes.

Call relations: The test runner invokes it. It links server turn notifications, submit behavior, error handling, and queued follow-up submission.

Call graph: calls 2 internal fn (new, from); 6 external calls (TurnCompleted, TurnStarted, new, assert!, assert_eq!, panic!).

submit_user_message_emits_structured_plugin_mentions_from_bindings1205–1271 ↗
async fn submit_user_message_emits_structured_plugin_mentions_from_bindings()

Purpose: Checks that typed plugin mentions are sent as structured mention items, not just plain text.

Data flow: The test sets up a thread session, enables plugins, registers a visible plugin mention, submits text with a mention binding, and reads the outgoing user turn. The output contains both the original text and a separate plugin mention item.

Call relations: The test runner calls it. It exercises the submit path that converts composer mention bindings into backend-readable user input.

Call graph: calls 2 internal fn (read_only, new); 6 external calls (new, default, new, assert_eq!, panic!, vec!).

enter_submits_when_plan_stream_is_not_active1274–1295 ↗
async fn enter_submits_when_plan_stream_is_not_active()

Purpose: Verifies that pressing Enter submits immediately when a task is running but no Plan output stream is active.

Data flow: The test enters Plan mode, starts a task, types text, presses Enter, and checks that no message is queued and a user turn is sent with the expected personality.

Call relations: The test runner invokes it. It distinguishes ordinary running-turn submission from special handling while Plan output is actively streaming.

Call graph: calls 2 internal fn (new, mask_for_kind); 4 external calls (new, new, assert!, panic!).

collab_mode_shift_tab_cycles_only_when_idle1298–1314 ↗
async fn collab_mode_shift_tab_cycles_only_when_idle()

Purpose: Checks that Shift+Tab cycles the displayed collaboration mode only while the chat is idle.

Data flow: The test presses Shift+Tab twice while idle and observes Plan then Default active modes, while the saved current mode stays unchanged. It then starts a task and confirms Shift+Tab no longer changes the active mode.

Call relations: The test runner calls it. It exercises keyboard mode cycling and the guard that blocks cycling during active work.

Call graph: 2 external calls (from, assert_eq!).

mode_switch_surfaces_model_change_notification_when_effective_model_changes1317–1353 ↗
async fn mode_switch_surfaces_model_change_notification_when_effective_model_changes()

Purpose: Verifies that switching collaboration modes shows a history notice when the effective model changes.

Data flow: The test customizes Plan mode to use a different model, switches into Plan mode and reads history output for the Plan notice, then switches back to Default mode and checks for the Default-mode model notice.

Call relations: The test runner invokes it. It uses collaboration mask helpers and then observes the history messages produced by mode switching.

Call graph: calls 2 internal fn (default_mask, mask_for_kind); 2 external calls (assert!, format!).

mode_switch_surfaces_reasoning_change_notification_when_model_stays_same1356–1374 ↗
async fn mode_switch_surfaces_reasoning_change_notification_when_model_stays_same()

Purpose: Checks that a mode switch also notifies the user when only reasoning effort changes, even if the model name stays the same.

Data flow: The test starts with high global reasoning, switches to Plan mode with medium reasoning for the same model, drains history output, and looks for the expected model-and-reasoning notice.

Call relations: The test runner calls it. It covers the notification path for effective setting changes that are not model-name changes.

Call graph: calls 1 internal fn (plan_mask); 1 external calls (assert!).

plan_slash_command_switches_to_plan_mode1377–1392 ↗
async fn plan_slash_command_switches_to_plan_mode()

Purpose: Confirms that the /plan command switches the chat into Plan mode without emitting unrelated app events.

Data flow: The test dispatches the Plan slash command, drains app events to ensure only history insertions occurred, and checks that the active mode is Plan while the stored current mode remains unchanged.

Call relations: The test runner invokes it. It tests the slash-command dispatch path into collaboration-mode switching.

Call graph: 2 external calls (assert!, assert_eq!).

plan_slash_command_with_args_submits_prompt_in_plan_mode1395–1440 ↗
async fn plan_slash_command_with_args_submits_prompt_in_plan_mode()

Purpose: Checks that typing /plan followed by text submits that text as a Plan-mode prompt.

Data flow: The test sets up a thread session, types “/plan build the plan,” presses Enter, reads the outgoing user turn, and confirms only “build the plan” is sent while Plan mode becomes active.

Call relations: The test runner calls it. It links composer command parsing, mode switching, and message submission.

Call graph: calls 2 internal fn (read_only, new); 5 external calls (from, default, new, assert_eq!, panic!).

collaboration_modes_defaults_to_code_on_startup1443–1454 ↗
async fn collaboration_modes_defaults_to_code_on_startup()

Purpose: Verifies that when collaboration modes are enabled at startup, the chat still begins in Default coding mode.

Data flow: The test starts a chat widget with a CLI override enabling collaboration modes, then reads the active mode and current model.

Call relations: The test runner invokes it. It uses the startup helper to build a realistic widget with configuration overrides.

Call graph: calls 1 internal fn (make_startup_chat_with_cli_overrides); 2 external calls (assert_eq!, vec!).

vim_mode_default_disabled_starts_composer_in_insert_mode1457–1460 ↗
async fn vim_mode_default_disabled_starts_composer_in_insert_mode()

Purpose: Checks that Vim-style editing is off by default. Insert mode means typed characters go directly into the composer.

Data flow: The test starts a chat widget with no overrides and reads whether the composer has Vim mode enabled.

Call relations: The test runner calls it. It uses the shared startup helper to test the default configuration path.

Call graph: calls 1 internal fn (make_startup_chat_with_cli_overrides); 2 external calls (new, assert!).

vim_mode_default_enabled_starts_composer_in_normal_mode1463–1475 ↗
async fn vim_mode_default_enabled_starts_composer_in_normal_mode()

Purpose: Verifies that enabling the Vim-mode startup option starts the composer in Vim normal mode, where regular letter keys are commands instead of inserted text.

Data flow: The test starts a chat widget with the Vim default override, checks that Vim mode is enabled and the composer is empty, presses x, and confirms no text was inserted.

Call relations: The test runner invokes it. It uses the startup helper and then sends a key event to prove the initial editor mode.

Call graph: calls 1 internal fn (make_startup_chat_with_cli_overrides); 5 external calls (Char, new, assert!, assert_eq!, vec!).

make_startup_chat_with_cli_overrides1477–1512 ↗
async fn make_startup_chat_with_cli_overrides(
    cli_overrides: Vec<(String, TomlValue)>,
) -> ChatWidget

Purpose: Builds a real ChatWidget for startup-style tests using temporary configuration and chosen command-line overrides.

Data flow: It receives a list of configuration override key-value pairs, creates a temporary Codex home, builds a config, resolves a test model, prepares telemetry and widget initialization data, and returns a new ChatWidget.

Call relations: The startup-related tests call this helper when they need a widget that has gone through configuration loading instead of the lighter manual test setup.

Call graph: calls 3 internal fn (new, new, test_dummy); called by 3 (collaboration_modes_defaults_to_code_on_startup, vim_mode_default_disabled_starts_composer_in_insert_mode, vim_mode_default_enabled_starts_composer_in_normal_mode); 4 external calls (new, new, default, new_with_app_event).

set_model_updates_active_collaboration_mask1515–1526 ↗
async fn set_model_updates_active_collaboration_mask()

Purpose: Checks that changing the model while in Plan mode keeps the active collaboration mode as Plan and updates its effective model.

Data flow: The test enters Plan mode, calls set_model with a new model name, then reads the current model and active mode.

Call relations: The test runner calls it. It exercises the model-setting path while a collaboration mask is active.

Call graph: calls 1 internal fn (mask_for_kind); 1 external calls (assert_eq!).

set_reasoning_effort_updates_active_collaboration_mask1529–1543 ↗
async fn set_reasoning_effort_updates_active_collaboration_mask()

Purpose: Verifies that changing global reasoning effort while in Plan mode refreshes the active Plan mask to its correct effective reasoning.

Data flow: The test enters Plan mode, clears the global reasoning effort, then reads the current reasoning effort and active mode. Plan mode should still report its medium reasoning.

Call relations: The test runner invokes it. It checks how the reasoning-setting path interacts with Plan mode defaults.

Call graph: calls 1 internal fn (mask_for_kind); 1 external calls (assert_eq!).

set_reasoning_effort_does_not_override_active_plan_override1546–1561 ↗
async fn set_reasoning_effort_does_not_override_active_plan_override()

Purpose: Makes sure a user-chosen Plan mode reasoning override is not overwritten by later global reasoning changes.

Data flow: The test sets a Plan override to high, enters Plan mode, changes global reasoning to low, and reads the current reasoning effort. The active effort should remain high.

Call relations: The test runner calls it. It protects the precedence rule: Plan override wins over global reasoning while Plan mode is active.

Call graph: calls 1 internal fn (mask_for_kind); 1 external calls (assert_eq!).

collab_mode_is_sent_after_enabling1564–1586 ↗
async fn collab_mode_is_sent_after_enabling()

Purpose: Checks that after collaboration modes are enabled, normal submitted messages include the Default collaboration mode.

Data flow: The test enables the feature, types a message, presses Enter, and reads the outgoing user turn. It expects Default mode and the pragmatic personality preset.

Call relations: The test runner invokes it. It tests the standard composer submit path after turning on the collaboration-modes feature flag.

Call graph: calls 1 internal fn (new); 3 external calls (from, new, panic!).

collab_mode_applies_default_preset1589–1613 ↗
async fn collab_mode_applies_default_preset()

Purpose: Verifies that even without explicitly enabling the feature in this test, the default collaboration preset is applied to submitted turns.

Data flow: The test types and submits a message, reads the outgoing operation for Default mode and pragmatic personality, then checks the widget’s active and current collaboration mode.

Call relations: The test runner calls it. It confirms the default submit path carries collaboration metadata expected by the backend.

Call graph: calls 1 internal fn (new); 4 external calls (from, new, assert_eq!, panic!).

user_turn_includes_personality_from_config1616–1633 ↗
async fn user_turn_includes_personality_from_config()

Purpose: Checks that a user-selected personality is included in submitted user turns when the personality feature is enabled.

Data flow: The test enables personality, sets a thread and model, chooses the Friendly personality, submits text, and checks the outgoing operation for that personality.

Call relations: The test runner invokes it. It links chat configuration state to the backend-facing user turn.

Call graph: calls 1 internal fn (new); 3 external calls (from, new, panic!).

plan_update_renders_history_cell1636–1666 ↗
async fn plan_update_renders_history_cell()

Purpose: Verifies that structured plan updates are rendered into the chat history so the user can see the current plan.

Data flow: The test creates a plan update with completed, in-progress, and pending steps, sends it to the widget, drains inserted history cells, and checks that the rendered text contains the header and each step.

Call relations: The test runner calls it. It exercises the plan-update display path and inspects the history cell sent through the app event channel.

Call graph: 2 external calls (assert!, vec!).

tui/src/chatwidget/tests/popups_and_settings.rssource ↗
testtest run

This test file protects many of the small popups that appear at the bottom of the chat terminal. These popups are where users browse plugins, add or remove plugin marketplaces, install or disable apps, change experimental features, choose models, adjust reasoning level, enable memories, and send feedback. Without these tests, small changes could quietly break important flows: a button might disappear, a keyboard shortcut might fire the wrong action, a loading screen might never update, or a disabled admin-controlled plugin might still look installable.

Most tests build a fake ChatWidget, feed it pretend server responses, press keys as if a user were navigating with the keyboard, and then render the bottom popup as plain text. Some tests compare that text to saved snapshots, which are like reference photos of the UI. Others inspect events sent out of the widget, such as “fetch plugin details” or “save these feature flags.”

The file covers both happy paths and edge cases: loading states, backend errors, partial app refreshes, duplicate marketplace names, remote plugins, admin-disabled plugins, missing uninstall identities, and shortcuts that should be ignored while another popup is open. In plain terms, it is a safety net for the chat UI’s interactive settings and marketplace experience.

Function details70
experimental_mode_plan_is_ignored_on_startup14–58 ↗
async fn experimental_mode_plan_is_ignored_on_startup()

Purpose: Checks that an old or experimental startup setting for “plan” mode does not force the chat into that mode. This keeps startup behavior predictable even if the config file contains that experimental value.

Data flow: It builds a temporary config with collaboration modes enabled and experimental mode set to plan, creates a ChatWidget from that config, then checks the widget starts in the default collaboration mode and keeps the expected model.

Call relations: The async test runner calls this test. The test creates the widget through the normal startup constructor and verifies the resulting state directly, so it catches regressions in initialization.

Call graph: calls 3 internal fn (new, new, test_dummy); 6 external calls (new, new, assert_eq!, default, new_with_app_event, vec!).

plugins_popup_loading_state_snapshot61–73 ↗
async fn plugins_popup_loading_state_snapshot()

Purpose: Verifies that opening the plugins popup shows a clear loading message before marketplace data has arrived.

Data flow: It creates a test chat widget, turns on the plugins feature, opens the plugins output, renders the popup, and compares the text against the expected loading view.

Call relations: The test runner calls it. It exercises the same popup-opening path a user triggers with the plugins command, then hands the rendered popup to snapshot checking.

Call graph: 2 external calls (assert!, assert_chatwidget_snapshot!).

marketplace_upgrade_loading_popup_snapshot76–93 ↗
async fn marketplace_upgrade_loading_popup_snapshot()

Purpose: Checks the visual text shown while a plugin marketplace upgrade is in progress.

Data flow: It opens the upgrade-loading popup for a marketplace named debug, extracts the lines mentioning the upgrade, and compares them to the expected wording.

Call relations: The test runner calls it. It focuses on the loading popup opened by the marketplace upgrade flow before any backend result is received.

Call graph: 1 external calls (assert_snapshot!).

marketplace_upgrade_failure_includes_backend_messages_snapshot96–128 ↗
async fn marketplace_upgrade_failure_includes_backend_messages_snapshot()

Purpose: Makes sure marketplace upgrade failures include the detailed error messages returned by the backend. This matters because users need the real reason, such as authentication failure or invalid marketplace files.

Data flow: It sends a fake failed upgrade result with two marketplace errors into the chat widget, drains the history messages that the widget emits, and checks the final error text.

Call relations: The test runner calls it. It exercises the widget’s response handler for marketplace upgrade results and observes the history entry that would be shown to the user.

Call graph: 3 external calls (new, assert_snapshot!, vec!).

hooks_popup_shows_list_diagnostics131–152 ↗
async fn hooks_popup_shows_list_diagnostics()

Purpose: Checks that the hooks popup displays warnings and errors found while reading hook configuration. Hooks are user-configured actions that run around tool use, so configuration problems must be visible.

Data flow: It feeds a fake hooks list response containing one warning and one parse error into the widget, renders the popup, normalizes paths, and checks the snapshot.

Call relations: The test runner calls it. It uses the same hook-list result path used after the app asks the backend to list hooks.

Call graph: 2 external calls (assert_chatwidget_snapshot!, vec!).

plugins_popup_snapshot_shows_all_marketplaces_and_sorts_installed_then_name155–214 ↗
async fn plugins_popup_snapshot_shows_all_marketplaces_and_sorts_installed_then_name()

Purpose: Verifies that the plugins list includes plugins from all marketplaces and sorts them sensibly: installed plugins first, then by name.

Data flow: It creates fake curated and repository marketplaces, opens the loaded plugins popup, checks that all expected rows are present, and compares their row positions.

Call relations: The test runner calls it. It exercises the plugin marketplace display logic after a successful plugin list response.

Call graph: 3 external calls (assert!, assert_chatwidget_snapshot!, vec!).

plugins_popup_truncates_long_descriptions_in_list_rows217–260 ↗
async fn plugins_popup_truncates_long_descriptions_in_list_rows()

Purpose: Checks that long plugin descriptions are shortened instead of wrapping and making the list hard to read.

Data flow: It loads two fake plugins, one with a long description, renders the popup at a narrow width, and checks that the long row ends with a shortened description.

Call relations: The test runner calls it. It verifies the rendering layer for plugin rows after plugin data has been loaded.

Call graph: 3 external calls (assert!, assert_snapshot!, vec!).

plugins_popup_add_marketplace_tab_opens_prompt_and_submits_source263–316 ↗
async fn plugins_popup_add_marketplace_tab_opens_prompt_and_submits_source()

Purpose: Tests the keyboard flow for adding a marketplace from the plugins popup.

Data flow: It opens the plugins popup, moves to the Add Marketplace tab, presses Enter, verifies the prompt event, types a source value, submits it, and checks that loading and fetch events carry the typed source and current folder.

Call relations: The test runner calls it. It follows the user path from tab navigation to prompt submission, then inspects the app events sent to the rest of the system.

Call graph: 5 external calls (from, assert!, assert_eq!, panic!, vec!).

plugins_popup_upgrades_user_configured_git_marketplace_from_marketplace_tab319–388 ↗
async fn plugins_popup_upgrades_user_configured_git_marketplace_from_marketplace_tab()

Purpose: Checks that a user-configured Git marketplace can be upgraded from its marketplace tab and that repeated shortcut presses do not send duplicate requests.

Data flow: It sets up a fake user config with a Git marketplace, opens the marketplace tab, presses the upgrade shortcut twice, and checks that only one loading event and one fetch event are emitted.

Call relations: The test runner calls it. It exercises marketplace tab rendering, shortcut handling, and the event handoff that asks the backend to upgrade the marketplace.

Call graph: 8 external calls (Char, from, new, assert!, assert_eq!, default, panic!, vec!).

marketplace_add_success_refreshes_to_new_marketplace_tab391–472 ↗
async fn marketplace_add_success_refreshes_to_new_marketplace_tab()

Purpose: Verifies that after successfully adding a marketplace, the plugins popup refreshes and switches to the new marketplace’s tab with a success message.

Data flow: It starts from a curated marketplace only, opens the add-loading state, feeds a successful add response, then feeds a refreshed plugin list containing the new marketplace and checks the displayed result.

Call relations: The test runner calls it. It follows the flow from marketplace add completion into a plugin list refresh, then checks what the user sees immediately and after reopening.

Call graph: 5 external calls (from, assert!, assert_chatwidget_snapshot!, default, vec!).

plugins_popup_removes_user_configured_marketplace_flow475–584 ↗
async fn plugins_popup_removes_user_configured_marketplace_flow()

Purpose: Tests the full removal flow for a user-configured marketplace, including confirmation, loading, backend request, and refreshed list.

Data flow: It opens a removable marketplace tab, presses the remove shortcut, confirms removal, checks the emitted loading and fetch events, feeds a successful remove response, refreshes plugins, and verifies the removed marketplace is gone.

Call relations: The test runner calls it. It walks through the same multi-step UI path a user follows, with the widget handing removal requests to the app event system.

Call graph: 9 external calls (Char, from, new, assert!, assert_chatwidget_snapshot!, assert_eq!, default, panic!, vec!).

plugin_detail_popup_snapshot_shows_install_actions_and_capability_summaries587–628 ↗
async fn plugin_detail_popup_snapshot_shows_install_actions_and_capability_summaries()

Purpose: Checks that an installable plugin’s detail popup shows install actions and summaries of its abilities.

Data flow: It loads a fake plugin list, feeds detailed plugin information with skills, hooks, apps, and servers, renders the detail popup, and compares the snapshot.

Call relations: The test runner calls it. It verifies the detail view that appears after the plugin list asks for more information about a selected plugin.

Call graph: 2 external calls (assert_chatwidget_snapshot!, vec!).

plugin_detail_popup_hides_disclosure_for_installed_plugins631–676 ↗
async fn plugin_detail_popup_hides_disclosure_for_installed_plugins()

Purpose: Makes sure already installed plugins do not show the installation disclosure text meant for new installs.

Data flow: It loads an installed plugin, feeds detailed information, renders the detail popup, checks that the disclosure line is absent, and snapshots the result.

Call relations: The test runner calls it. It exercises plugin detail rendering for installed plugins, a separate state from installable plugins.

Call graph: 3 external calls (assert!, assert_chatwidget_snapshot!, vec!).

plugins_popup_remote_row_opens_remote_detail679–732 ↗
async fn plugins_popup_remote_row_opens_remote_detail()

Purpose: Verifies that selecting a remote plugin row opens a detail request using the remote marketplace identity rather than a local file path.

Data flow: It loads a remote marketplace with one plugin, presses Enter on the row, and checks that the widget emits a loading event and a detail fetch event with the remote marketplace name and plugin name.

Call relations: The test runner calls it. It connects list-row keyboard handling to the app event that asks the backend for remote plugin details.

Call graph: 5 external calls (from, assert!, assert_eq!, panic!, vec!).

plugin_detail_remote_install_uses_remote_location735–807 ↗
async fn plugin_detail_remote_install_uses_remote_location()

Purpose: Checks that installing a remote plugin sends a remote location to the backend.

Data flow: It loads a remote plugin detail view, moves to the install action, presses Enter, and verifies that the install event contains the remote marketplace name, plugin identifier, and display name.

Call relations: The test runner calls it. It exercises the detail popup action that hands a remote plugin install request to the rest of the app.

Call graph: 6 external calls (from, new, assert!, assert_eq!, panic!, vec!).

plugin_detail_remote_uninstall_uses_remote_plugin_id810–875 ↗
async fn plugin_detail_remote_uninstall_uses_remote_plugin_id()

Purpose: Checks that uninstalling a remote plugin uses the plugin’s remote identifier, not just its short display name.

Data flow: It loads an installed remote plugin detail view, chooses the uninstall action, and verifies the uninstall event includes the remote plugin id and display name.

Call relations: The test runner calls it. It protects the handoff between the plugin detail popup and the backend uninstall command.

Call graph: 5 external calls (from, new, assert_eq!, panic!, vec!).

plugin_detail_remote_without_remote_id_disables_uninstall_action878–937 ↗
async fn plugin_detail_remote_without_remote_id_disables_uninstall_action()

Purpose: Ensures an installed remote plugin cannot be uninstalled from the UI if it does not provide the identity needed to uninstall it safely.

Data flow: It loads a remote installed plugin whose id is not a valid remote uninstall identity, renders the popup, and checks that the UI explains the problem and does not offer the remove action.

Call relations: The test runner calls it. It verifies that detail rendering blocks unsafe actions before any event can be emitted.

Call graph: 3 external calls (new, assert!, vec!).

plugin_detail_admin_disabled_plugin_blocks_install940–982 ↗
async fn plugin_detail_admin_disabled_plugin_blocks_install()

Purpose: Checks that a plugin disabled by an administrator cannot be installed and clearly says why.

Data flow: It loads a plugin marked disabled by admin, opens its detail view, renders the popup, and checks for the disabled message and absence of install text.

Call relations: The test runner calls it. It exercises policy-aware plugin detail rendering, ensuring the UI respects administrative restrictions.

Call graph: 2 external calls (assert!, vec!).

plugins_popup_admin_disabled_installed_plugin_has_no_toggle_hint985–1023 ↗
async fn plugins_popup_admin_disabled_installed_plugin_has_no_toggle_hint()

Purpose: Verifies that an installed plugin disabled by admin does not show or respond to the usual enable/disable shortcut.

Data flow: It renders a plugins list containing an admin-disabled installed plugin, checks that the toggle hint is absent, presses Space, and confirms no event or visual change occurs.

Call relations: The test runner calls it. It tests list-row keyboard handling and policy-based blocking together.

Call graph: 5 external calls (Char, new, assert!, assert_eq!, vec!).

plugin_detail_error_popup_skips_disabled_row_numbering1026–1051 ↗
async fn plugin_detail_error_popup_skips_disabled_row_numbering()

Purpose: Checks the error version of the plugin detail popup, especially that disabled rows are not counted like selectable actions.

Data flow: It opens plugin details but feeds an error instead of data, renders the popup, and compares it to the expected snapshot.

Call relations: The test runner calls it. It covers the failure path after a plugin detail fetch fails.

Call graph: 2 external calls (assert_chatwidget_snapshot!, vec!).

plugins_popup_refresh_preserves_selected_row_position1054–1132 ↗
async fn plugins_popup_refresh_preserves_selected_row_position()

Purpose: Ensures the plugins popup keeps the selected row position when a refreshed list arrives.

Data flow: It opens a list, moves selection down, refreshes with a new plugin inserted above, and checks that the same row position remains selected even though the plugin at that position changed.

Call relations: The test runner calls it. It exercises the refresh handler for plugin data while the popup is already open.

Call graph: 3 external calls (from, assert!, vec!).

plugins_popup_refreshes_installed_counts_after_install1135–1201 ↗
async fn plugins_popup_refreshes_installed_counts_after_install()

Purpose: Checks that the plugins popup updates installed counts and row wording after a plugin becomes installed.

Data flow: It renders a list with one installed plugin, refreshes it so both plugins are installed, then checks the header count and selected row instructions.

Call relations: The test runner calls it. It simulates the plugin list refresh that follows an install operation.

Call graph: 2 external calls (assert!, vec!).

plugins_popup_space_toggles_installed_plugin_from_list1204–1262 ↗
async fn plugins_popup_space_toggles_installed_plugin_from_list()

Purpose: Verifies that pressing Space on an installed plugin toggles its enabled state from the list.

Data flow: It selects an installed plugin, presses Space, checks that a SetPluginEnabled event asks to disable it, then feeds a successful result and confirms the row stays selected.

Call relations: The test runner calls it. It tests list keyboard input, event emission, and the update path after the backend confirms the toggle.

Call graph: 7 external calls (Char, from, new, assert!, assert_eq!, panic!, vec!).

plugins_popup_space_with_active_search_does_not_toggle_installed_plugin1306–1343 ↗
async fn plugins_popup_space_with_active_search_does_not_toggle_installed_plugin()

Purpose: Makes sure Space is treated as part of search input behavior, not as a toggle shortcut, when plugin search is active.

Data flow: It selects an installed plugin, types a search query, presses Space, and verifies no enable or disable event is emitted.

Call relations: The test runner calls it. It covers the interaction between the plugin search mode and normal list shortcuts.

Call graph: 5 external calls (Char, from, new, assert!, vec!).

plugins_popup_search_filters_visible_rows_snapshot1346–1391 ↗
async fn plugins_popup_search_filters_visible_rows_snapshot()

Purpose: Checks that typing in the plugins popup search field filters the list to matching plugin rows.

Data flow: It loads three plugins, types a search query matching Slack, renders the popup, snapshots it, and confirms unrelated rows are gone.

Call relations: The test runner calls it. It exercises the search input path and filtered rendering for plugin rows.

Call graph: 3 external calls (assert!, assert_chatwidget_snapshot!, vec!).

plugins_popup_openai_curated_tab_omits_marketplace_in_rows1441–1485 ↗
async fn plugins_popup_openai_curated_tab_omits_marketplace_in_rows()

Purpose: Checks that the OpenAI Curated marketplace tab only shows official curated plugins and omits redundant marketplace labels in those rows.

Data flow: It loads curated and repository plugins, navigates to the curated tab, renders the popup, and checks which plugin names and labels appear.

Call relations: The test runner calls it. It exercises marketplace-specific tab rendering after plugin data is loaded.

Call graph: 3 external calls (from, assert!, vec!).

plugins_popup_refresh_preserves_duplicate_marketplace_tab_by_path1488–1549 ↗
async fn plugins_popup_refresh_preserves_duplicate_marketplace_tab_by_path()

Purpose: Ensures that when two marketplaces have the same name, the selected marketplace tab is preserved by its path during refresh.

Data flow: It loads two marketplaces with the same display name but different paths, navigates to the second one, refreshes with the same response, and checks that the second tab remains selected.

Call relations: The test runner calls it. It protects tab identity logic in the plugin popup when names alone are not unique.

Call graph: 3 external calls (from, assert!, vec!).

plugins_popup_search_no_matches_and_backspace_restores_results1552–1605 ↗
async fn plugins_popup_search_no_matches_and_backspace_restores_results()

Purpose: Checks the no-results search state and confirms Backspace restores the full plugin list.

Data flow: It types a query with no matches, verifies the no-matches message, deletes the query with Backspace, and checks that the original rows return.

Call relations: The test runner calls it. It exercises search editing and dynamic list restoration in the plugins popup.

Call graph: 3 external calls (from, assert!, vec!).

apps_popup_stays_loading_until_final_snapshot_updates1608–1699 ↗
async fn apps_popup_stays_loading_until_final_snapshot_updates()

Purpose: Verifies that the apps popup stays in a loading state while only a partial apps snapshot is available, then updates when the final list arrives.

Data flow: It feeds a partial connector list, opens the apps popup, checks the loading message, then feeds a final list with more apps and checks the installed count and new row.

Call relations: The test runner calls it. It tests the connector refresh flow used by the apps popup, including partial and final updates.

Call graph: 3 external calls (assert!, assert_chatwidget_snapshot!, vec!).

apps_notification_update_excludes_inaccessible_apps_from_mentions1702–1770 ↗
async fn apps_notification_update_excludes_inaccessible_apps_from_mentions()

Purpose: Checks that inaccessible directory apps are stored in the partial snapshot but not shown in the mention popup.

Data flow: It sets the composer text to app-mention mode, feeds one accessible and one inaccessible app, confirms the inaccessible app exists in internal data, then checks only the accessible app is displayed.

Call relations: The test runner calls it. It covers the connector update path that feeds mention suggestions in the chat composer.

Call graph: 4 external calls (new, assert!, assert_matches!, vec!).

apps_refresh_failure_keeps_existing_full_snapshot1773–1859 ↗
async fn apps_refresh_failure_keeps_existing_full_snapshot()

Purpose: Ensures a failed apps refresh does not throw away the last complete apps list.

Data flow: It loads a full connector snapshot, starts a partial refresh, then feeds a final error and checks that the cached full snapshot is still used in the popup.

Call relations: The test runner calls it. It tests the error path of connector loading after a good cache already exists.

Call graph: 3 external calls (assert!, assert_matches!, vec!).

apps_popup_preserves_selected_app_across_refresh1862–1979 ↗
async fn apps_popup_preserves_selected_app_across_refresh()

Purpose: Checks that the selected app remains selected after the apps list refreshes and new rows are inserted.

Data flow: It loads Notion and Slack, selects Slack, refreshes with Airtable added before them, and checks that Slack is still selected.

Call relations: The test runner calls it. It exercises selection preservation in the apps popup during connector refresh.

Call graph: 3 external calls (from, assert!, vec!).

apps_refresh_failure_with_cached_snapshot_triggers_pending_force_refetch1982–2023 ↗
async fn apps_refresh_failure_with_cached_snapshot_triggers_pending_force_refetch()

Purpose: Verifies that if a refresh fails while another forced refresh was pending, the widget starts that pending refetch and keeps the existing cache.

Data flow: It sets connector state to show an in-flight refresh and a pending forced refresh, provides a cached snapshot, feeds a final error, and checks the flags and cache afterward.

Call relations: The test runner calls it. It tests internal connector refresh state rather than visible popup text.

Call graph: 4 external calls (assert!, assert_matches!, Ready, vec!).

apps_popup_keeps_existing_full_snapshot_while_partial_refresh_loads2026–2127 ↗
async fn apps_popup_keeps_existing_full_snapshot_while_partial_refresh_loads()

Purpose: Checks that the apps popup keeps showing the last full list while a partial refresh is still loading.

Data flow: It loads a full snapshot, opens the apps popup, feeds a partial snapshot with different rows, and verifies the cache and visible popup still reflect the old full snapshot.

Call relations: The test runner calls it. It protects the user experience during background connector refreshes.

Call graph: 3 external calls (assert!, assert_matches!, vec!).

apps_refresh_failure_without_full_snapshot_falls_back_to_installed_apps2130–2186 ↗
async fn apps_refresh_failure_without_full_snapshot_falls_back_to_installed_apps()

Purpose: Ensures that if final app loading fails and there is no previous full list, the popup falls back to the partial installed-app snapshot.

Data flow: It feeds a partial connector snapshot, opens the apps popup in loading state, then feeds a final error and checks that the partial app becomes the ready list.

Call relations: The test runner calls it. It covers the no-cache failure path for apps loading.

Call graph: 3 external calls (assert!, assert_matches!, vec!).

apps_popup_shows_disabled_status_for_installed_but_disabled_apps2189–2229 ↗
async fn apps_popup_shows_disabled_status_for_installed_but_disabled_apps()

Purpose: Checks that an installed app that is currently disabled is labeled as disabled and offers enable or disable guidance.

Data flow: It loads one accessible but disabled app, opens the apps popup, and verifies the selected row description includes disabled status and enable/disable wording.

Call relations: The test runner calls it. It exercises row text generation for installed apps with disabled state.

Call graph: 2 external calls (assert!, vec!).

apps_refresh_preserves_toggled_enabled_state2232–2300 ↗
async fn apps_refresh_preserves_toggled_enabled_state()

Purpose: Verifies that a locally toggled app enabled state is not overwritten by a later refresh that still says the app is enabled.

Data flow: It loads an enabled app, locally marks it disabled, refreshes with server data saying enabled, and checks the cache and popup still show disabled.

Call relations: The test runner calls it. It tests the connector cache merge behavior after a user changes app state.

Call graph: 3 external calls (assert!, assert_matches!, vec!).

apps_popup_for_not_installed_app_uses_install_only_selected_description2303–2343 ↗
async fn apps_popup_for_not_installed_app_uses_install_only_selected_description()

Purpose: Checks that an app that is not installed tells the user how to install it, without mentioning enable or disable actions.

Data flow: It loads one inaccessible app, opens the apps popup, and checks the selected row text for install-only wording.

Call relations: The test runner calls it. It verifies app row descriptions for available-but-not-installed connectors.

Call graph: 2 external calls (assert!, vec!).

experimental_features_popup_snapshot2346–2372 ↗
async fn experimental_features_popup_snapshot()

Purpose: Checks the visual layout of the experimental features popup with enabled and disabled feature rows.

Data flow: It builds a view with two fake experimental feature items, shows it in the bottom pane, renders the popup, and compares the snapshot.

Call relations: The test runner calls it. It exercises the standalone ExperimentalFeaturesView rendered inside the chat widget’s bottom pane.

Call graph: calls 2 internal fn (new, defaults); 3 external calls (new, assert_chatwidget_snapshot!, vec!).

experimental_features_toggle_saves_on_exit2375–2413 ↗
async fn experimental_features_toggle_saves_on_exit()

Purpose: Verifies that toggling an experimental feature does not immediately save, but pressing Enter emits a save event.

Data flow: It opens a feature view, presses Space to change the local checkbox, confirms no event yet, presses Enter, then reads the UpdateFeatureFlags event with the expected change.

Call relations: The test runner calls it. It tests the feature settings popup’s delayed-save behavior through chat key handling.

Call graph: calls 2 internal fn (new, defaults); 6 external calls (new, Char, new, assert!, assert_eq!, vec!).

experimental_popup_omits_stable_guardian_approval2416–2433 ↗
async fn experimental_popup_omits_stable_guardian_approval()

Purpose: Checks that stable features are not shown in the experimental features popup.

Data flow: It confirms the GuardianApproval feature is marked stable, opens the experimental popup, renders it, and checks that the stable feature label is absent.

Call relations: The test runner calls it. It exercises the ChatWidget method that builds the experimental feature list from feature metadata.

Call graph: 2 external calls (assert!, assert_eq!).

multi_agent_enable_prompt_snapshot2436–2443 ↗
async fn multi_agent_enable_prompt_snapshot()

Purpose: Checks the visual text of the prompt that asks the user to enable multi-agent or subagent support.

Data flow: It opens the multi-agent enable prompt, renders the bottom popup, and compares it to the saved snapshot.

Call relations: The test runner calls it. It covers the prompt-opening method on ChatWidget.

Call graph: 1 external calls (assert_chatwidget_snapshot!).

multi_agent_enable_prompt_updates_feature_and_emits_notice2446–2462 ↗
async fn multi_agent_enable_prompt_updates_feature_and_emits_notice()

Purpose: Verifies that confirming the multi-agent prompt requests the feature flag update and shows a notice that it applies next session.

Data flow: It opens the prompt, presses Enter, checks for an UpdateFeatureFlags event enabling collaboration, then checks the inserted history notice text.

Call relations: The test runner calls it. It follows the prompt confirmation path into app events and visible chat history.

Call graph: 4 external calls (from, assert!, assert_matches!, panic!).

memories_enable_prompt_snapshot2465–2473 ↗
async fn memories_enable_prompt_snapshot()

Purpose: Checks the enable prompt shown when the memories feature is off.

Data flow: It disables the memory feature, opens the memories popup, renders the bottom pane, and compares the snapshot.

Call relations: The test runner calls it. It tests the memory popup’s first branch: asking to enable the feature.

Call graph: 1 external calls (assert_chatwidget_snapshot!).

memories_enable_prompt_updates_feature_without_notice2476–2491 ↗
async fn memories_enable_prompt_updates_feature_without_notice()

Purpose: Verifies that confirming the memories enable prompt sends only a feature update event and does not show a success notice too early.

Data flow: It disables memories, opens the prompt, presses Enter, checks for the MemoryTool feature update, and confirms no extra event follows.

Call relations: The test runner calls it. It covers the event emitted by the memory enable prompt before persistence succeeds.

Call graph: 3 external calls (from, assert!, assert_matches!).

memories_settings_popup_snapshot2494–2504 ↗
async fn memories_settings_popup_snapshot()

Purpose: Checks the visual layout of the memories settings popup when the memory feature is already enabled.

Data flow: It enables memory support, sets use and generate settings, opens the popup, strips terminal link markup, and snapshots the result.

Call relations: The test runner calls it. It exercises the normal settings view for memories.

Call graph: 1 external calls (assert_chatwidget_snapshot!).

memories_reset_confirmation_snapshot2507–2520 ↗
async fn memories_reset_confirmation_snapshot()

Purpose: Checks the confirmation screen shown before resetting memories.

Data flow: It opens memory settings, moves selection to the reset action, presses Enter, renders the confirmation popup, and snapshots it.

Call relations: The test runner calls it. It follows keyboard navigation from settings into the reset confirmation view.

Call graph: 2 external calls (from, assert_chatwidget_snapshot!).

memories_settings_toggle_saves_on_enter2523–2541 ↗
async fn memories_settings_toggle_saves_on_enter()

Purpose: Verifies that changing a memory setting and pressing Enter sends the updated settings.

Data flow: It opens memory settings, toggles the generate-memories option, presses Enter, and checks for an UpdateMemorySettings event with the new values.

Call relations: The test runner calls it. It tests the save path for editable memory settings.

Call graph: 3 external calls (Char, from, assert_matches!).

memories_reset_confirmation_sends_event_on_confirm2544–2557 ↗
async fn memories_reset_confirmation_sends_event_on_confirm()

Purpose: Checks that confirming the reset memories dialog emits the reset event.

Data flow: It navigates to the reset confirmation and presses Enter again, then verifies a ResetMemories event is sent.

Call relations: The test runner calls it. It completes the reset confirmation path from the memory popup into the app event system.

Call graph: 2 external calls (from, assert_matches!).

model_selection_popup_snapshot2560–2567 ↗
async fn model_selection_popup_snapshot()

Purpose: Checks the model picker popup for a chat session using a specific starting model.

Data flow: It creates a widget with a chosen model, marks a thread as active, opens the model popup, renders it, and snapshots the result.

Call relations: The test runner calls it. It exercises the ChatWidget model picker opening path.

Call graph: calls 1 internal fn (new); 1 external calls (assert_chatwidget_snapshot!).

personality_selection_popup_snapshot2570–2577 ↗
async fn personality_selection_popup_snapshot()

Purpose: Checks the personality picker popup for a model that supports personality choices.

Data flow: It creates a widget with a compatible model, marks a thread as active, opens the personality popup, renders it, and snapshots the result.

Call relations: The test runner calls it. It verifies the personality selection view created from ChatWidget state.

Call graph: calls 1 internal fn (new); 1 external calls (assert_chatwidget_snapshot!).

skills_menu_default_mentions_shortcut_snapshot2580–2586 ↗
async fn skills_menu_default_mentions_shortcut_snapshot()

Purpose: Checks the skills menu and its default mention shortcut hint.

Data flow: It opens the skills menu, renders the bottom popup, and compares it to the saved snapshot.

Call relations: The test runner calls it. It exercises the ChatWidget method that opens the skills menu.

Call graph: 1 external calls (assert_chatwidget_snapshot!).

model_picker_hides_show_in_picker_false_models_from_cache2589–2628 ↗
async fn model_picker_hides_show_in_picker_false_models_from_cache()

Purpose: Verifies that models marked as hidden from the picker do not appear in the model selection popup.

Data flow: It builds one visible and one hidden model preset, opens the picker with both, renders the popup, and checks only the visible model appears.

Call relations: The test runner calls it. It tests filtering inside the model picker before users see the list.

Call graph: calls 1 internal fn (new); 3 external calls (assert!, assert_chatwidget_snapshot!, vec!).

server_overloaded_error_does_not_switch_models2631–2660 ↗
async fn server_overloaded_error_does_not_switch_models()

Purpose: Checks that a server overloaded error does not trigger an automatic model switch.

Data flow: It sets the current model, clears pending events, feeds a server-overloaded error, then scans chat and operation events to ensure no model override happened.

Call relations: The test runner calls it. It exercises the shared error-handling path used when backend requests fail.

Call graph: 2 external calls (assert!, assert_eq!).

model_reasoning_selection_popup_snapshot2663–2681 ↗
async fn model_reasoning_selection_popup_snapshot()

Purpose: Checks the reasoning-level picker popup, including a custom reasoning option.

Data flow: It authenticates the test chat, sets current reasoning effort, adds a custom reasoning preset to a model, opens the reasoning popup, and snapshots the result.

Call relations: The test runner calls it. It verifies the popup built by the model reasoning selection flow.

Call graph: 2 external calls (Custom, assert_chatwidget_snapshot!).

model_reasoning_selection_popup_applies_custom_effort2684–2716 ↗
async fn model_reasoning_selection_popup_applies_custom_effort()

Purpose: Verifies that selecting a custom reasoning effort updates both current reasoning and persisted model selection.

Data flow: It opens a reasoning popup containing a custom effort, moves to that option, presses Enter, collects update events, and checks they contain the custom value.

Call relations: The test runner calls it. It follows the reasoning popup confirmation path into app events.

Call graph: 4 external calls (from, Custom, assert_eq!, from_fn).

model_reasoning_selection_popup_extra_high_warning_snapshot2719–2730 ↗
async fn model_reasoning_selection_popup_extra_high_warning_snapshot()

Purpose: Checks the warning text shown when the Extra High reasoning level is selected.

Data flow: It sets the current reasoning effort to Extra High, opens the reasoning popup for a model, renders it, and snapshots the warning state.

Call relations: The test runner calls it. It exercises special-case rendering in the reasoning picker.

Call graph: 1 external calls (assert_chatwidget_snapshot!).

assert_reasoning_shortcuts_update_effort2732–2767 ↗
async fn assert_reasoning_shortcuts_update_effort(
    key_events: [KeyEvent; 2],
    expected_effort: ReasoningEffortConfig,
    expect_model_update: bool,
)

Purpose: Provides a shared test helper for checking keyboard shortcuts that raise or lower reasoning effort.

Data flow: For each supplied key event, it creates a chat widget, sets a starting reasoning effort, sends the key, collects emitted events, and verifies the expected reasoning update and optional model update occurred without persistence.

Call relations: It is called by the two reasoning shortcut tests. Those tests supply the shortcut keys and expected direction, while this helper performs the repeated setup and event checks.

Call graph: calls 1 internal fn (new); called by 2 (reasoning_down_shortcuts_lower_reasoning_effort, reasoning_up_shortcuts_raise_reasoning_effort); 2 external calls (assert!, from_fn).

reasoning_up_shortcuts_raise_reasoning_effort2770–2780 ↗
async fn reasoning_up_shortcuts_raise_reasoning_effort()

Purpose: Checks that the configured “reasoning up” shortcuts increase reasoning effort.

Data flow: It passes the Alt-period and Shift-Up key events to the shared helper with the expected High effort and asks it to expect a model update.

Call relations: The test runner calls it, and it delegates the actual widget setup and assertions to assert_reasoning_shortcuts_update_effort.

Call graph: calls 1 internal fn (assert_reasoning_shortcuts_update_effort); 2 external calls (Char, new).

reasoning_down_shortcuts_lower_reasoning_effort2783–2793 ↗
async fn reasoning_down_shortcuts_lower_reasoning_effort()

Purpose: Checks that the configured “reasoning down” shortcuts lower reasoning effort.

Data flow: It passes the Alt-comma and Shift-Down key events to the shared helper with the expected Low effort and no model update requirement.

Call relations: The test runner calls it, and it uses assert_reasoning_shortcuts_update_effort to run the repeated checks.

Call graph: calls 1 internal fn (assert_reasoning_shortcuts_update_effort); 2 external calls (Char, new).

reasoning_shortcut_clears_armed_quit_shortcut2796–2814 ↗
async fn reasoning_shortcut_clears_armed_quit_shortcut()

Purpose: Verifies that using a reasoning shortcut cancels a previously armed quit shortcut instead of accidentally quitting.

Data flow: It arms the quit shortcut, sends a reasoning-up key event, checks the quit hint and stored quit key are cleared, and confirms no exit event was emitted.

Call relations: The test runner calls it. It exercises interaction between global shortcut handling and the quit confirmation mechanism.

Call graph: calls 2 internal fn (new, ctrl); 4 external calls (Char, new, assert!, from_fn).

reasoning_shortcut_is_ignored_with_model_popup_open2817–2838 ↗
async fn reasoning_shortcut_is_ignored_with_model_popup_open()

Purpose: Checks that reasoning shortcuts do not change settings while the model popup is open.

Data flow: It opens the model popup, sends a reasoning shortcut, collects events, and verifies no reasoning update or model persistence event appears.

Call relations: The test runner calls it. It protects popup focus behavior: when a modal view is active, global reasoning shortcuts should not take over.

Call graph: calls 1 internal fn (new); 4 external calls (Char, new, assert!, from_fn).

reasoning_popup_shows_extra_high_with_space2841–2858 ↗
async fn reasoning_popup_shows_extra_high_with_space()

Purpose: Checks that the reasoning popup displays “Extra high” with a space, not as a single mashed-together word.

Data flow: It opens the reasoning popup and inspects the rendered text for the correct and incorrect spellings.

Call relations: The test runner calls it. It is a focused display-quality test for reasoning level labels.

Call graph: 1 external calls (assert!).

single_reasoning_option_skips_selection2861–2905 ↗
async fn single_reasoning_option_skips_selection()

Purpose: Verifies that if a model has only one reasoning option, the UI skips the selection popup and applies it automatically.

Data flow: It creates a model preset with one supported reasoning effort, asks the chat to open the reasoning popup, checks no selection title is rendered, then verifies an update event applied the single effort.

Call relations: The test runner calls it. It exercises the shortcut path inside reasoning selection when there is nothing for the user to choose.

Call graph: 3 external calls (new, assert!, vec!).

feedback_selection_popup_snapshot2908–2916 ↗
async fn feedback_selection_popup_snapshot()

Purpose: Checks the feedback category selection popup opened by the feedback slash command.

Data flow: It dispatches the feedback command, renders the bottom popup, and compares it to the saved snapshot.

Call relations: The test runner calls it. It uses the command dispatch path instead of opening the view directly.

Call graph: 1 external calls (assert_chatwidget_snapshot!).

reasoning_popup_escape_returns_to_model_popup2961–2977 ↗
async fn reasoning_popup_escape_returns_to_model_popup()

Purpose: Verifies that pressing Escape from the reasoning popup returns to the model picker instead of closing back to chat.

Data flow: It opens the model popup, then the reasoning popup, checks the reasoning title is visible, sends Escape, and checks that the model picker is visible again.

Call relations: The test runner calls it. It covers the navigation relationship between the model picker and the reasoning picker.

Call graph: calls 1 internal fn (new); 2 external calls (new, assert!).

tui/src/chatwidget/tests/review_mode.rssource ↗
testtest run

This is a test file, not production code. It acts like a careful checklist for the chat widget when the user is in or around code review mode. Review mode is a special running state where the assistant is reviewing code changes, and the user may still type follow-up instructions. The tests check that those follow-ups are stored in the right place, shown at the right time, and not lost when a turn is interrupted.

A lot of the file focuses on two kinds of waiting input. Queued messages are normal drafts waiting for the current turn to finish. Pending steers are follow-up instructions sent while a turn is already running. The distinction matters because review turns may reject steering, and the widget must then put the user's words back into the normal queue instead of silently dropping them.

The file also tests the visible interface: review banners, warning messages, snapshot text, commit picker rendering, custom review prompts, Escape-key navigation, Ctrl-C behavior, image placeholders, mention bindings, and context-window indicators. In everyday terms, these tests make sure the chat box behaves like a reliable notepad: if the assistant is busy, interrupted, or reviewing, the user's draft and attachments still end up exactly where the user expects.

Function details39
interrupted_turn_restores_queued_messages_with_images_and_elements6–100 ↗
async fn interrupted_turn_restores_queued_messages_with_images_and_elements()

Purpose: Checks that when a running turn is interrupted, queued messages with image attachments are put back into the composer correctly. It especially verifies that image labels such as "[Image #1]" are renumbered after messages are merged.

Data flow: The test starts with a chat widget, two queued messages with images, and an existing composer draft with another image. It simulates an interrupted turn, then checks that the composer contains all three messages in order, that the text-element ranges point at the right image labels, and that the image path list matches the visible numbering.

Call relations: The async test runner calls this directly. Inside the test, helper setup creates the widget, then the interruption helper exercises the same path used when a real turn is stopped.

Call graph: 5 external calls (from, new, assert_eq!, format!, vec!).

entered_review_mode_uses_request_hint104–113 ↗
async fn entered_review_mode_uses_request_hint()

Purpose: Verifies that entering review mode displays the specific review hint supplied by the request. This protects the banner text the user sees at the start of a review.

Data flow: The test creates a chat widget, enters review mode with the hint "feature branch", drains the rendered history output, and confirms the final banner uses that exact phrase. It also confirms the internal review-mode flag is turned on.

Call relations: The test runner invokes it. It uses the review-mode entry helper and then inspects the app-event history that the widget emits for display.

Call graph: 2 external calls (assert!, assert_eq!).

entered_review_mode_defaults_to_current_changes_banner117–126 ↗
async fn entered_review_mode_defaults_to_current_changes_banner()

Purpose: Checks the review-start banner for the common case where the review target is "current changes". It ensures the user gets a clear visible confirmation.

Data flow: A fresh widget enters review mode with the text "current changes". The test reads the inserted history cell and verifies both the banner text and the internal review-mode state.

Call relations: The test runner calls it, and the test drives the same review-entry helper used by notification handling.

Call graph: 2 external calls (assert!, assert_eq!).

live_review_prompt_item_is_not_rendered129–144 ↗
async fn live_review_prompt_item_is_not_rendered()

Purpose: Ensures the hidden prompt used to start a review is not shown as a normal user message. Without this, users would see implementation text instead of only the review banner.

Data flow: The test enters review mode, confirms only the review banner appeared, then completes a user-message item containing the review prompt. It drains the display events again and expects nothing new.

Call relations: The test runner calls it. It combines the review-entry helper with the user-message completion helper to model what happens as live thread items arrive.

Call graph: 2 external calls (assert!, assert_eq!).

live_app_server_review_prompt_item_is_not_rendered147–196 ↗
async fn live_app_server_review_prompt_item_is_not_rendered()

Purpose: Checks the same hidden-review-prompt behavior through app-server notifications. This covers the network-style event path rather than only local helper calls.

Data flow: The test sends an item-started notification for entering review mode, confirms the banner appears, then sends completed notifications for the review-mode item and the hidden prompt message. It expects no extra visible history for either completion.

Call relations: The test runner invokes it. It feeds server notifications into the chat widget, which is the route used when the widget is driven by app-server events.

Call graph: 5 external calls (ItemCompleted, ItemStarted, assert!, assert_eq!, vec!).

steer_rejection_queues_review_follow_up_before_existing_queued_messages199–286 ↗
async fn steer_rejection_queues_review_follow_up_before_existing_queued_messages()

Purpose: Verifies that follow-up messages rejected during a review turn are not lost and are placed before older queued drafts. This preserves the order in which the user intended things to happen.

Data flow: The test starts a review turn, adds an older queued message, submits two review follow-ups as pending steers, and then simulates server errors saying review turns cannot be steered. The pending steers move into the queued-message area ahead of the older draft. After review exits and the turn completes, the rejected follow-ups submit first as one merged message, followed by the older draft.

Call relations: The test runner calls it. It exercises submission, error handling, review exit, and turn completion together, checking the outgoing operations sent by the widget.

Call graph: calls 2 internal fn (new, from); 3 external calls (assert!, assert_eq!, panic!).

esc_with_review_queued_steers_shows_warning_and_does_not_interrupt289–309 ↗
async fn esc_with_review_queued_steers_shows_warning_and_does_not_interrupt()

Purpose: Checks that pressing Escape while review follow-ups are pending shows a warning instead of interrupting the review. This prevents a confusing or unsupported review interruption path.

Data flow: The test starts review mode with one pending steer, presses Escape, and then checks that no interrupt operation was sent. The pending steer remains in place, and the displayed output contains the expected warning snapshot.

Call relations: The test runner invokes it. It drives the keyboard event path and then inspects both outgoing operations and rendered history.

Call graph: calls 1 internal fn (new); 4 external calls (new, assert!, assert_chatwidget_snapshot!, assert_eq!).

live_agent_message_renders_during_review_mode312–328 ↗
async fn live_agent_message_renders_during_review_mode()

Purpose: Confirms that normal assistant messages still appear while review mode is active. Review mode should not hide progress updates from the assistant.

Data flow: The test enters review mode, clears the banner from the event queue, completes an assistant message, and checks that the rendered history contains that message.

Call relations: The test runner calls it. It uses the review-entry helper, then the assistant-message completion helper, matching how live review updates arrive.

Call graph: 2 external calls (assert!, assert_eq!).

review_restores_context_window_indicator332–358 ↗
async fn review_restores_context_window_indicator()

Purpose: Ensures the token/context indicator returns to its pre-review value after review mode ends. The context window is the model's available working memory, and the UI should not keep showing review-specific numbers afterward.

Data flow: The test feeds one token count before review, another during review, and then exits review mode. It checks the bottom pane's displayed percentage before, during, and after review, confirming the old value is restored.

Call relations: The test runner invokes it. It ties together token-count updates, review entry, review exit, and bottom-pane display state.

Call graph: 2 external calls (assert!, assert_eq!).

restore_thread_input_state_restores_pending_steers_without_downgrading_them361–410 ↗
async fn restore_thread_input_state_restores_pending_steers_without_downgrading_them()

Purpose: Checks that restoring saved thread input keeps pending steers as pending steers, rather than turning them into ordinary queued messages. This matters when returning to an existing thread.

Data flow: The test builds a saved input state containing one pending steer, one rejected steer, and one queued draft. After restoring it into the widget, it checks that rejected and queued messages are in the normal queue while the pending steer remains pending with its comparison key intact.

Call relations: The test runner calls it. It directly exercises the widget's state-restore method, which is used when thread state is reloaded.

Call graph: calls 1 internal fn (from); 2 external calls (new, assert_eq!).

steer_enter_queues_while_plan_stream_is_active413–437 ↗
async fn steer_enter_queues_while_plan_stream_is_active()

Purpose: Verifies that pressing Enter during an active plan stream queues the message instead of sending it as a steer. A plan stream is a visible planning output, and this test protects the special input behavior for that mode.

Data flow: The test enables collaboration modes, switches to plan mode, starts a task, emits a plan delta, types a draft, and presses Enter. The draft becomes one queued user message, no pending steer is created, and no outgoing submit operation is sent.

Call relations: The test runner invokes it. It combines collaboration-mode setup, plan streaming, keyboard input, and operation-channel inspection.

Call graph: calls 2 internal fn (new, mask_for_kind); 4 external calls (new, new, assert!, assert_eq!).

steer_enter_uses_pending_steers_while_turn_is_running_without_streaming440–472 ↗
async fn steer_enter_uses_pending_steers_while_turn_is_running_without_streaming()

Purpose: Checks that pressing Enter during a running turn sends the draft as a pending steer when there is no active stream. This lets the user give follow-up instructions without waiting for the current task to finish.

Data flow: The test starts a task, types a draft, presses Enter, and confirms the text is stored as a pending steer and submitted as a user turn operation. When the matching user message completes, the pending steer is removed and rendered in history.

Call relations: The test runner calls it. It exercises the normal running-turn steering path and the cleanup that happens when the server confirms the message.

Call graph: calls 1 internal fn (new); 5 external calls (new, new, assert!, assert_eq!, panic!).

steer_enter_uses_pending_steers_while_final_answer_stream_is_active475–513 ↗
async fn steer_enter_uses_pending_steers_while_final_answer_stream_is_active()

Purpose: Checks that pressing Enter while the assistant's final answer is still streaming also creates a pending steer. This protects a timing-sensitive case where users submit follow-ups before the final output has fully settled.

Data flow: The test starts a task, opens a final-answer stream, types a follow-up, and presses Enter. It verifies the message becomes a pending steer, is submitted immediately, and is later removed when the matching user message is completed and displayed.

Call relations: The test runner invokes it. It drives the final-answer streaming path, keyboard submission path, outgoing operation path, and item-completion path together.

Call graph: calls 1 internal fn (new); 5 external calls (new, new, assert!, assert_eq!, panic!).

failed_pending_steer_submit_does_not_add_pending_preview516–532 ↗
async fn failed_pending_steer_submit_does_not_add_pending_preview()

Purpose: Ensures a failed attempt to submit a pending steer does not leave a fake pending message in the UI. This avoids showing the user a message that was never actually sent.

Data flow: The test starts a task, drops the operation receiver to make submission fail, types a draft, and presses Enter. It then checks that neither pending steers nor queued messages were added, and no history output appeared.

Call relations: The test runner calls it. It deliberately breaks the outgoing operation channel, then exercises the Enter-key submit path.

Call graph: calls 1 internal fn (new); 3 external calls (new, new, assert!).

item_completed_only_pops_front_pending_steer535–576 ↗
async fn item_completed_only_pops_front_pending_steer()

Purpose: Checks that completing an unrelated user item does not remove pending steers, and completing the matching first steer removes only that one. This preserves queue order.

Data flow: The test seeds two pending steers and completes a different user message first. Both steers remain. It then completes a message matching the first steer, and only that front steer is removed while the second stays pending.

Call relations: The test runner invokes it. It uses message-completion helpers to test the pending-steer matching and removal rules.

Call graph: 2 external calls (assert!, assert_eq!).

item_completed_pops_pending_steer_with_local_image_and_text_elements579–660 ↗
async fn item_completed_pops_pending_steer_with_local_image_and_text_elements()

Purpose: Verifies that pending steers with images and text metadata are matched and rendered correctly when completed. This protects rich user messages, not just plain text.

Data flow: The test writes a tiny temporary PNG file, submits a message containing that image and a text element, and checks the pending steer records the message and image count. It then completes the user item using image and text inputs, confirms the pending steer is removed, and inspects the rendered user history cell to make sure the original text element and local image path are preserved.

Call relations: The test runner calls it. It exercises file-backed image attachment setup, user submission, operation sending, completion matching, and history-cell rendering.

Call graph: calls 1 internal fn (new); 6 external calls (new, assert!, assert_eq!, panic!, write, vec!).

steer_enter_during_final_stream_preserves_follow_up_prompts_in_order663–745 ↗
async fn steer_enter_during_final_stream_preserves_follow_up_prompts_in_order()

Purpose: Checks that multiple follow-up prompts submitted during a streaming final answer stay in the user's original order. This prevents later prompts from jumping ahead of earlier ones.

Data flow: The test starts a final-answer stream, submits two follow-ups with Enter, and confirms there are two pending steers in first-then-second order. It checks both outgoing submit operations, then completes each user message and verifies each one is removed and rendered in sequence.

Call relations: The test runner invokes it. It covers the repeated use of the running-turn steering path while a stream is active.

Call graph: calls 1 internal fn (new); 5 external calls (new, new, assert!, assert_eq!, panic!).

manual_interrupt_restores_pending_steers_to_composer748–790 ↗
async fn manual_interrupt_restores_pending_steers_to_composer()

Purpose: Ensures that if a turn is manually interrupted, an unsatisfied pending steer is put back into the text composer. This lets the user edit or resubmit it instead of losing it.

Data flow: The test creates a pending steer by submitting during a final-answer stream, then simulates an interrupted turn. The pending-steer queue becomes empty, the composer contains the original text, no extra submit operation appears, and the message is not falsely shown as completed history.

Call relations: The test runner calls it. It drives submission through the keyboard path and then calls the interruption path used when a turn is aborted.

Call graph: calls 1 internal fn (new); 5 external calls (new, new, assert!, assert_eq!, panic!).

esc_interrupt_sends_all_pending_steers_immediately_and_keeps_existing_draft793–870 ↗
async fn esc_interrupt_sends_all_pending_steers_immediately_and_keeps_existing_draft()

Purpose: Checks the special Escape behavior where pending steers are submitted after interruption, while the user's current draft remains untouched. This is a careful recovery flow for active turns.

Data flow: The test submits two pending steers, adds an existing queued draft, types another draft in the composer, and presses Escape. After the interruption finishes, the two pending steers are sent together, the current composer draft remains, and the older queued draft is still queued.

Call relations: The test runner invokes it. It links keyboard input, interrupt operation sending, interruption cleanup, merged follow-up submission, and rendered history.

Call graph: calls 2 internal fn (new, from); 5 external calls (new, new, assert!, assert_eq!, panic!).

esc_with_pending_steers_overrides_agent_command_interrupt_behavior873–892 ↗
async fn esc_with_pending_steers_overrides_agent_command_interrupt_behavior()

Purpose: Verifies that when pending steers exist, Escape interrupts the running task even if the composer currently looks like an agent command. This protects the higher-priority recovery behavior for pending steers.

Data flow: The test creates a pending steer, changes the composer text to an agent-command prefix, presses Escape, and confirms an interrupt operation is sent. The command text remains in the composer.

Call relations: The test runner calls it. It exercises a conflict between agent-command editing behavior and pending-steer interruption behavior.

Call graph: calls 1 internal fn (new); 4 external calls (new, new, assert_eq!, panic!).

manual_interrupt_restores_pending_steer_mention_bindings_to_composer895–935 ↗
async fn manual_interrupt_restores_pending_steer_mention_bindings_to_composer()

Purpose: Checks that restoring a pending steer after interruption also restores mention bindings. Mention bindings connect visible text like "$figma" to a real referenced skill or file, so losing them would change the meaning of the prompt.

Data flow: The test types a message with a mention binding, submits it as a pending steer, verifies the outgoing text input, then interrupts the turn. The composer text and the stored mention binding are both restored, and no extra submit operation is sent.

Call relations: The test runner invokes it. It covers the rich composer path, pending-steer submission, and interruption restoration.

Call graph: calls 1 internal fn (new); 5 external calls (new, new, assert_eq!, panic!, vec!).

manual_interrupt_restores_pending_steers_before_queued_messages938–978 ↗
async fn manual_interrupt_restores_pending_steers_before_queued_messages()

Purpose: Ensures that when interruption restores both pending steers and queued drafts, pending steers appear first in the composer. This keeps the user's most immediate follow-up before older waiting drafts.

Data flow: The test submits one pending steer during a final stream, manually adds a queued draft, and interrupts the turn. Both queues are emptied, and the composer becomes a two-line draft with the pending steer above the queued draft.

Call relations: The test runner calls it. It combines pending-steer restoration and queued-message restoration through the interruption path.

Call graph: calls 2 internal fn (new, from); 5 external calls (new, new, assert!, assert_eq!, panic!).

ctrl_c_shutdown_works_with_caps_lock981–987 ↗
async fn ctrl_c_shutdown_works_with_caps_lock()

Purpose: Checks that Ctrl-C works even when the character is uppercase, as can happen with Caps Lock. The user should still be able to request shutdown.

Data flow: The test sends a Ctrl-uppercase-C key event to a fresh widget and reads the app event channel. It expects a shutdown-first exit event.

Call relations: The test runner invokes it. It exercises the keyboard handler and the app-event channel used to request application exit.

Call graph: 3 external calls (Char, new, assert_matches!).

ctrl_c_interrupts_without_arming_quit_when_double_press_disabled990–1005 ↗
async fn ctrl_c_interrupts_without_arming_quit_when_double_press_disabled()

Purpose: Verifies that Ctrl-C interrupts a running task without showing or arming a double-press-to-quit hint. This protects the configured Ctrl-C behavior for running tasks.

Data flow: The test marks the bottom pane as running, presses Ctrl-C, and checks that an interrupt operation is sent, no exit event appears, and the quit hint is hidden. It presses Ctrl-C again and confirms the same behavior repeats.

Call relations: The test runner calls it. It drives key handling while task-running state is active and inspects both operation and UI-event outputs.

Call graph: 4 external calls (Char, new, assert!, assert_matches!).

ctrl_c_cleared_prompt_is_recoverable_via_history1008–1036 ↗
async fn ctrl_c_cleared_prompt_is_recoverable_via_history()

Purpose: Checks that Ctrl-C clearing a draft does not permanently lose it; the user can recover it with history recall. It also verifies attached image information survives that recovery.

Data flow: The test types draft text, attaches an image, presses Ctrl-C, and confirms the composer is cleared without sending an operation. It then presses Up to recall history and verifies the text and image placeholder return, along with the original image path.

Call relations: The test runner invokes it. It exercises composer editing, image attachment, Ctrl-C clearing, history recall, and image recovery.

Call graph: 6 external calls (Char, new, from, assert!, assert_eq!, assert_matches!).

review_popup_custom_prompt_action_sends_event1041–1063 ↗
async fn review_popup_custom_prompt_action_sends_event()

Purpose: Checks that choosing "Custom review instructions" from the review popup asks the app to open the custom prompt view. This confirms the popup selection is wired to the right event.

Data flow: The test opens the review popup, moves the selection down to the custom prompt option, presses Enter, and drains events until it finds the custom-prompt request.

Call relations: The test runner calls it. It uses the widget's popup-opening and key-handling paths, then observes the app-event channel.

Call graph: 2 external calls (new, assert!).

review_commit_picker_shows_subjects_without_timestamps1067–1124 ↗
async fn review_commit_picker_shows_subjects_without_timestamps()

Purpose: Verifies that the review commit picker displays only commit subjects, not relative timestamps. This keeps the picker focused and avoids noisy time text.

Data flow: The test opens the review popup, injects two synthetic commit entries, renders the widget into a terminal buffer, and scans the text. It expects both subjects to appear and checks that words like "ago", "minute", or "hour" are absent.

Call relations: The test runner invokes it. It drives the popup and commit-picker display code, then inspects the rendered terminal buffer directly.

Call graph: 6 external calls (new, assert!, empty, new, show_review_commit_picker_with_entries, vec!).

custom_prompt_submit_sends_review_op1129–1150 ↗
async fn custom_prompt_submit_sends_review_op()

Purpose: Checks that submitting the custom review prompt sends a review operation with trimmed instructions. This ensures extra spaces typed by the user do not become part of the review request.

Data flow: The test opens the custom prompt view, pastes text with leading and trailing spaces, presses Enter, and reads the outgoing app event. It expects an operation requesting a custom review target with the cleaned-up prompt text.

Call relations: The test runner calls it. It exercises the custom prompt view, paste handling, Enter submission, and app-event output.

Call graph: 3 external calls (new, assert_eq!, panic!).

custom_prompt_enter_empty_does_not_send1154–1163 ↗
async fn custom_prompt_enter_empty_does_not_send()

Purpose: Verifies that pressing Enter on an empty custom review prompt does nothing. This prevents sending a meaningless review request.

Data flow: The test opens the custom prompt view, presses Enter without typing anything, and checks that no app event was produced.

Call relations: The test runner invokes it. It covers the empty-input guard inside the custom prompt submission path.

Call graph: 2 external calls (new, assert!).

interrupt_exec_marks_failed_snapshot1168–1187 ↗
async fn interrupt_exec_marks_failed_snapshot()

Purpose: Checks the visual result of interrupting a running command execution cell. The active spinner should become a failed marker and be placed into history.

Data flow: The test starts a fake long-running command, simulates an interrupted turn, drains inserted history cells, and snapshots the finalized command cell text.

Call relations: The test runner calls it. It uses execution-start and turn-interruption helpers, then verifies the user-visible rendering through a snapshot.

Call graph: 2 external calls (assert!, assert_chatwidget_snapshot!).

interrupted_turn_error_message_snapshot1192–1208 ↗
async fn interrupted_turn_error_message_snapshot()

Purpose: Verifies the friendly error message shown after a normal interrupted turn. The message should guide the user rather than expose low-level failure details.

Data flow: The test starts a turn, interrupts it, drains the inserted history cells, and snapshots the last inserted message.

Call relations: The test runner invokes it. It exercises the turn-start and turn-interruption path and records the visible message.

Call graph: 2 external calls (assert!, assert_chatwidget_snapshot!).

interrupted_turn_after_goal_budget_limited_uses_budget_message_snapshot1211–1274 ↗
async fn interrupted_turn_after_goal_budget_limited_uses_budget_message_snapshot()

Purpose: Checks that when a goal becomes budget-limited and the turn is then interrupted, the UI shows the budget-specific message. A budget-limited goal means the task stopped because it used more tokens than allowed.

Data flow: The test enables goals, sends server notifications for turn start, goal update with budget-limited status, and interrupted turn completion. It drains history and snapshots the final displayed message.

Call relations: The test runner calls it. It drives the server-notification path for goals and turn completion, rather than using only local helper functions.

Call graph: 5 external calls (new, assert_chatwidget_snapshot!, ThreadGoalUpdated, TurnCompleted, TurnStarted).

direct_budget_limited_turn_uses_budget_message_snapshot1277–1286 ↗
async fn direct_budget_limited_turn_uses_budget_message_snapshot()

Purpose: Verifies the message shown when a turn directly ends because of a token-budget limit. This protects the wording for a clear stop condition.

Data flow: The test starts a turn, simulates a budget-limited ending, drains history, and snapshots the last message.

Call relations: The test runner invokes it. It uses turn-start and budget-limit helpers to exercise the direct budget-stop path.

Call graph: 1 external calls (assert_chatwidget_snapshot!).

budget_limited_turn_restores_queued_input_without_submitting1289–1305 ↗
async fn budget_limited_turn_restores_queued_input_without_submitting()

Purpose: Checks that if a turn stops due to budget limits, queued user input is restored to the composer instead of being submitted automatically. This lets the user decide what to do next.

Data flow: The test seeds one queued message, starts a turn, and simulates a budget-limited stop. The queue is emptied, the composer contains the queued text, and no outgoing submit operation is sent.

Call relations: The test runner calls it. It covers the budget-limit turn-ending path and the queued-input restoration logic.

Call graph: calls 1 internal fn (from); 2 external calls (assert!, assert_eq!).

interrupted_turn_pending_steers_message_snapshot1311–1330 ↗
async fn interrupted_turn_pending_steers_message_snapshot()

Purpose: Checks that interrupting specifically to submit pending steers shows an informational message, not the generic interruption error. This makes the UI explain the intentional interruption correctly.

Data flow: The test creates a pending steer, marks that pending steers should be submitted after interruption, starts a turn, and interrupts it. It finds the inserted informational message and snapshots it.

Call relations: The test runner invokes it. It exercises the interruption path with the pending-steer-submission flag set.

Call graph: calls 1 internal fn (new); 1 external calls (assert_chatwidget_snapshot!).

review_custom_prompt_escape_navigates_back_then_dismisses1335–1365 ↗
async fn review_custom_prompt_escape_navigates_back_then_dismisses()

Purpose: Verifies Escape-key navigation from the custom review prompt. One Escape should return to the parent review popup; a second Escape should close the popup stack.

Data flow: The test opens the review popup, opens the custom prompt view, renders the first row to confirm the child view is visible, presses Escape and confirms the parent popup is visible, then presses Escape again and confirms normal composer mode is restored.

Call relations: The test runner calls it. It drives popup stack navigation through the widget's key handler and checks the rendered bottom-pane header.

Call graph: 2 external calls (new, assert!).

review_branch_picker_escape_navigates_back_then_dismisses1370–1401 ↗
async fn review_branch_picker_escape_navigates_back_then_dismisses()

Purpose: Verifies Escape-key navigation from the review base-branch picker. It should behave like the custom prompt: back to the parent popup first, then close.

Data flow: The test opens the review popup, opens the branch picker using a temporary directory, checks the branch-picker header, presses Escape to return to the review preset popup, then presses Escape again to return to normal composer mode.

Call relations: The test runner invokes it. It exercises the asynchronous branch-picker opening path and the shared popup back-navigation behavior.

Call graph: 3 external calls (new, assert!, temp_dir).

enter_submits_steer_while_review_is_running1404–1441 ↗
async fn enter_submits_steer_while_review_is_running()

Purpose: Checks that pressing Enter during a running review submits the text as a pending steer. This is the intended first attempt at giving review follow-up instructions.

Data flow: The test starts a turn, enters review mode, types a follow-up, and presses Enter. It verifies no normal queued message was added, one pending steer exists, and the outgoing user-turn operation contains the follow-up text.

Call relations: The test runner calls it. It combines review-mode state, keyboard submission, pending-steer storage, and outgoing operation inspection.

Call graph: calls 1 internal fn (new); 5 external calls (new, new, assert!, assert_eq!, panic!).

review_queues_user_messages_snapshot1444–1477 ↗
async fn review_queues_user_messages_snapshot()

Purpose: Checks the visual state after a review follow-up is rejected and queued. The snapshot protects how queued review messages are shown to the user.

Data flow: The test starts a review turn, submits a follow-up, simulates the server error that review turns cannot be steered, renders the widget into a terminal screen, normalizes paths, and snapshots the result.

Call relations: The test runner invokes it. It drives review submission, rejection handling, terminal rendering, and snapshot comparison together.

Call graph: calls 4 internal fn (new, from, with_options, new); 2 external calls (new, assert_chatwidget_snapshot!).

tui/src/chatwidget/tests/side.rssource ↗
testtest run

Side conversations are like stepping into a quick side room while the main chat keeps its place. This test file checks the rules around that side room. It verifies that starting a side conversation sends a clear app event instead of submitting a normal message to the main thread, and that optional text after /side or /btw becomes the first question in the side conversation. It also checks the guardrails: side conversations cannot be renamed, commands such as /review are blocked while inside a side conversation, and /side or /btw are blocked when code review is already running or when there is no active session to fork from. Several tests read events from in-memory channels, which are like mailboxes used by the widget to tell the rest of the app what happened. Others render the widget into a fake terminal screen and compare it to a stored snapshot, so visual details such as footer labels do not accidentally change. One test also makes sure that text beginning with !, which might normally look like a shell command, is sent as plain user text in a side conversation. Without these tests, small command-handling changes could quietly break side chats, confuse users, or send messages to the wrong thread.

Function details17
forked_thread_history_line_without_name_shows_id_once_snapshot7–28 ↗
async fn forked_thread_history_line_without_name_shows_id_once_snapshot()

Purpose: This test checks the history line shown when a thread is forked but has no friendly title. It makes sure the thread ID is displayed in a stable, non-duplicated way.

Data flow: It creates a test chat widget and a receiver for app events, builds a known thread ID from text, and tells the widget that a forked thread event happened. It waits until the widget emits a history cell, turns that cell into plain text, and compares the result with a saved snapshot. The output is not returned to callers; the test passes or fails based on the snapshot comparison.

Call relations: During the test, the widget under test emits an InsertHistoryCell event into the test receiver. The test uses the thread ID parser and a timeout so it can fail clearly if the expected history event never arrives, then hands the rendered text to the snapshot assertion.

Call graph: calls 1 internal fn (from_string); 4 external calls (assert_chatwidget_snapshot!, panic!, from_secs, timeout).

suppressed_interrupted_turn_notice_skips_history_warning31–49 ↗
async fn suppressed_interrupted_turn_notice_skips_history_warning()

Purpose: This test confirms that a side conversation can suppress the usual warning shown when a model turn is interrupted. That matters because side conversations may have different interruption behavior and should not show misleading main-thread guidance.

Data flow: It creates a widget, gives it a thread ID, switches the interrupted-turn notice mode to suppress, starts a task, and feeds in partial model output. Then it simulates an interrupted turn and drains any inserted history cells. The test checks that none of the rendered history text contains the standard interruption warning messages.

Call relations: The test drives the widget through the same callbacks it would receive during a real model response. It then inspects the history events emitted by the widget, using assertions to confirm the warning path stayed silent.

Call graph: calls 1 internal fn (new); 1 external calls (assert!).

assert_side_rename_rejected51–70 ↗
fn assert_side_rename_rejected(
    rx: &mut tokio::sync::mpsc::UnboundedReceiver<AppEvent>,
    op_rx: &mut tokio::sync::mpsc::UnboundedReceiver<Op>,
)

Purpose: This helper checks the common expected result when a rename command is blocked in a side conversation. It keeps the two rename tests focused on setup while sharing the exact checks for the error message and lack of follow-up actions.

Data flow: It receives two test mailboxes: one for app events and one for operations sent to the backend. It expects exactly one app event containing a history cell with the side-conversation rename error, then verifies there are no more app events and no rename operation was sent. It does not return a value; it fails the test if anything is wrong.

Call relations: The two rename tests call this helper after dispatching /rename in different forms. The helper reads from the widget's event channel and operation channel to prove the command was rejected locally instead of being passed onward.

Call graph: called by 2 (slash_rename_is_rejected_for_side_threads, slash_rename_with_args_is_rejected_for_side_threads); 3 external calls (try_recv, assert!, panic!).

slash_rename_is_rejected_for_side_threads73–81 ↗
async fn slash_rename_is_rejected_for_side_threads()

Purpose: This test checks that the plain /rename command is rejected for side conversations. Side conversations are temporary, so giving them permanent names would be misleading.

Data flow: It creates a test widget, installs the message that should be shown when renaming is blocked, and dispatches the rename command. The emitted event and operation mailbox are then passed to the shared helper, which verifies the visible error and confirms no backend rename operation was created.

Call relations: This test sets up the blocked-rename condition and then delegates the detailed checking to assert_side_rename_rejected. The bigger flow is: command enters the widget, the widget refuses it, and the test confirms the refusal stayed inside the user interface.

Call graph: calls 1 internal fn (assert_side_rename_rejected).

slash_rename_with_args_is_rejected_for_side_threads84–92 ↗
async fn slash_rename_with_args_is_rejected_for_side_threads()

Purpose: This test checks that /rename is still rejected when the user supplies a proposed name. Arguments should not bypass the rule that side conversations cannot be renamed.

Data flow: It creates a widget, sets the side-thread rename block message, and dispatches /rename investigate. The helper then reads the widget's app-event mailbox and backend-operation mailbox to make sure the user sees the error and no rename request is sent.

Call relations: Like the no-argument rename test, this test calls assert_side_rename_rejected for the final checks. It covers the alternate command path where command text includes extra input.

Call graph: calls 1 internal fn (assert_side_rename_rejected); 1 external calls (new).

slash_commands_without_side_flag_are_rejected_for_side_threads95–118 ↗
async fn slash_commands_without_side_flag_are_rejected_for_side_threads()

Purpose: This test makes sure commands that are not allowed inside a side conversation are blocked with a helpful message. It uses /review as the example.

Data flow: It creates a widget, marks side conversation mode as active, and dispatches the review command. It reads the next app event and checks that it is a history message saying /review is unavailable in side conversations and tells the user to press Ctrl+C to return to the main thread. It also confirms there are no extra events and no backend operation.

Call relations: The test exercises the widget's command gate while side mode is active. Instead of allowing the command to reach the operation channel, the widget emits only a user-facing error, which the test verifies.

Call graph: 2 external calls (assert!, panic!).

slash_side_is_rejected_for_side_threads121–147 ↗
async fn slash_side_is_rejected_for_side_threads()

Purpose: This test checks that a user cannot start another side conversation from inside an existing side conversation. That avoids nested side rooms, which would be confusing to track and return from.

Data flow: It marks the widget as already being in a side conversation, dispatches /side, and reads the resulting app event. The expected output is a history cell explaining that /side is unavailable in side conversations and that Ctrl+C returns to the main thread. The test also checks that no extra events or side-conversation operations were sent.

Call relations: The widget's command dispatcher receives /side while side mode is active. The test confirms the dispatcher stops there and reports an error instead of emitting a new side-conversation request.

Call graph: 2 external calls (assert!, panic!).

slash_side_is_rejected_during_review_mode150–174 ↗
async fn slash_side_is_rejected_during_review_mode()

Purpose: This test confirms that /side is blocked while code review is running. Starting a side conversation during review could mix two different workflows in a way the interface does not support.

Data flow: It creates a widget, sets its review state to active, and dispatches /side. It then reads the event mailbox and expects a history cell saying /side is unavailable while code review is running. Finally, it verifies no further events and no operation were produced.

Call relations: The command dispatcher sees that review mode is active before it starts any side-conversation flow. The test checks that the dispatcher turns the command into a local error message and does not hand anything to the backend.

Call graph: 2 external calls (assert!, panic!).

slash_btw_is_rejected_during_review_mode177–201 ↗
async fn slash_btw_is_rejected_during_review_mode()

Purpose: This test confirms that /btw, another way to start a side conversation, is also blocked during code review. Both aliases need the same safety rule.

Data flow: It turns on review mode in a test widget and dispatches /btw. The test expects one history-cell event with a message that /btw is unavailable while code review is running, and then confirms that both the app-event and backend-operation mailboxes are otherwise empty.

Call relations: This follows the same review-mode guard as the /side review test, but through the /btw command path. It proves the alias cannot slip past the review-mode block.

Call graph: 2 external calls (assert!, panic!).

slash_btw_is_rejected_before_the_session_starts204–227 ↗
async fn slash_btw_is_rejected_before_the_session_starts()

Purpose: This test checks that /btw cannot be used before there is an active session. A side conversation needs a parent thread to fork from, so there is nothing meaningful to start yet.

Data flow: It creates a fresh widget without assigning a thread ID or starting a session, then dispatches /btw. It expects a single history-cell error saying the command is unavailable before the session starts, and verifies that no backend operation or extra app event appears.

Call relations: The command dispatcher receives /btw before the widget has a parent conversation. The test confirms the dispatcher stops the flow early and reports the problem to the user.

Call graph: 2 external calls (assert!, panic!).

submit_user_message_as_plain_user_turn_does_not_run_shell_commands230–248 ↗
async fn submit_user_message_as_plain_user_turn_does_not_run_shell_commands()

Purpose: This test makes sure side-conversation text that looks like a shell command is still submitted as ordinary user text. This prevents a message such as !echo hello from being treated as something to run on the user's machine.

Data flow: It creates a widget, gives it a thread ID, and submits !echo hello through the plain-user-turn path. It then reads the next submitted operation and checks that it is a normal user turn containing exactly that text, with no text elements attached. The test fails if any other kind of operation appears.

Call relations: The test drives the special submission method used for plain side-conversation messages. It then inspects the operation sent onward, proving the message bypassed any shell-command interpretation and became a normal model input.

Call graph: calls 1 internal fn (new); 2 external calls (assert_eq!, panic!).

slash_side_without_args_starts_empty_side_conversation251–273 ↗
async fn slash_side_without_args_starts_empty_side_conversation()

Purpose: This test checks that typing /side by itself starts a side conversation without an initial question. It also ensures the main thread does not receive a normal message.

Data flow: It creates a widget with a parent thread ID, marks a task as running, puts /side into the composer, and simulates pressing Enter. The expected result is a StartSide app event containing the parent thread ID and no user message. It then confirms no backend operation was submitted and the queued-message list is empty.

Call relations: The simulated Enter key sends composer text into the widget's command handling path. The widget emits a side-start event to the app layer, and the test confirms the parent-thread operation channel stays untouched.

Call graph: calls 1 internal fn (new); 4 external calls (new, new, assert!, assert_matches!).

slash_btw_without_args_starts_empty_side_conversation276–298 ↗
async fn slash_btw_without_args_starts_empty_side_conversation()

Purpose: This test checks that /btw by itself behaves like /side: it starts an empty side conversation. The alias should not accidentally submit anything to the parent chat.

Data flow: It creates a widget with an active parent thread, starts a task, sets the composer text to /btw, and simulates Enter. It expects a StartSide event with the same parent thread ID and no initial user message, then checks that no backend operation or queued user message was created.

Call relations: This follows the same flow as the bare /side test, but through the /btw alias. The widget turns the command into an app-level side-start request rather than a parent-thread submission.

Call graph: calls 1 internal fn (new); 4 external calls (new, new, assert!, assert_matches!).

slash_side_requests_forked_side_question_while_task_running301–347 ↗
async fn slash_side_requests_forked_side_question_while_task_running()

Purpose: This test checks the full /side question path while the main task is running. The text after /side should become the first message in the side conversation, and the parent thread should not receive it.

Data flow: It creates a widget with a parent thread ID, sets a status-line model name, starts a task, hides the welcome banner, and places /side explore the codebase in the composer. After simulating Enter, it expects a StartSide event containing the parent thread ID and a user message with the text explore the codebase and empty image, text-element, and mention lists. It also confirms no parent operation was sent, renders the widget into a fake terminal, and compares the screen to a snapshot.

Call relations: The command handling path strips the /side command from the composer text and packages the remaining words as a side-conversation starting message. The test then checks both the emitted app event and the rendered footer, using the snapshot to catch visual regressions.

Call graph: calls 1 internal fn (new); 8 external calls (new, new, new, assert!, assert_chatwidget_snapshot!, assert_matches!, new, vec!).

slash_btw_requests_forked_side_question_while_task_running350–382 ↗
async fn slash_btw_requests_forked_side_question_while_task_running()

Purpose: This test checks that /btw question starts a side conversation with the question as its first message. It proves the /btw alias matches the important behavior of /side.

Data flow: It creates a widget with a parent thread, starts a task, puts /btw explore the codebase in the composer, and simulates Enter. The expected output is a StartSide app event with the parent thread ID and a user message containing explore the codebase. The test also verifies that no operation was submitted on the parent thread.

Call relations: The widget processes /btw through the side-conversation command path. The test inspects the app event to confirm the side conversation request was formed correctly and checks the operation mailbox to ensure the parent conversation was left alone.

Call graph: calls 1 internal fn (new); 4 external calls (new, new, assert!, assert_matches!).

side_context_label_preserves_status_line_snapshot385–405 ↗
async fn side_context_label_preserves_status_line_snapshot()

Purpose: This visual test checks that the side-conversation context label can appear without wiping out the configured status line. The footer should show both the side-context information and the model/status information correctly.

Data flow: It creates a widget, hides the welcome banner, sets a custom status line, refreshes it, marks side conversation mode active, and sets a context label saying the side came from the main thread. It renders the widget into a fake terminal and compares the resulting screen with a snapshot. The test output is the pass or fail result of that comparison.

Call relations: This test exercises the rendering path rather than command dispatch. The widget combines status-line state and side-context state into its terminal output, and the snapshot assertion catches unwanted layout or text changes.

Call graph: 4 external calls (new, assert_chatwidget_snapshot!, new, vec!).

side_context_label_shows_parent_status_snapshot408–423 ↗
async fn side_context_label_shows_parent_status_snapshot()

Purpose: This visual test checks that a side conversation can show context about the parent thread, such as that the main thread needs input. This helps users understand what is happening outside the temporary side chat.

Data flow: It creates a widget, hides the welcome banner, turns on side conversation mode, and sets a context label mentioning the main thread's status and Ctrl+C return instruction. It renders the widget into a fake terminal and compares the screen to a saved snapshot.

Call relations: Like the other footer snapshot test, this one drives the widget's render path. The side-context label is fed into the widget state, then the rendered terminal buffer is handed to the snapshot assertion to verify the visible result.

Call graph: 3 external calls (new, assert_chatwidget_snapshot!, new).

tui/src/chatwidget/tests/slash_commands.rssource ↗
testtest suite

This file checks that the chat screen behaves correctly when a user enters special commands instead of ordinary chat text. In this app, slash commands are like shortcut buttons typed into the prompt: /usage asks for token activity, /goal edits a session goal, /model opens a picker, and /copy copies the latest agent reply. The tests also cover commands that are queued while the agent is busy, so a follow-up message or command waits its turn instead of interrupting work incorrectly.

The file uses helper functions to set up common situations: making pet images supported or unsupported, submitting composer text, queuing text with Tab, completing a fake agent turn, and reading expected events from test channels. Those channels are like a mailbox: the chat widget sends AppEvent messages to the surrounding app, and core operations such as user turns or shell commands to another receiver.

Without these tests, small changes to command parsing or UI state could silently break important user workflows: history recall, confirmations, modal popups, clipboard copying, token usage cards, goal drafts with images or pasted text, and fast-mode model selection. Many tests also make sure invalid commands give helpful messages and do not accidentally send work to the backend.

Function details132
force_pet_image_support6–10 ↗
fn force_pet_image_support(chat: &mut ChatWidget)

Purpose: Sets a test chat widget to pretend the terminal can display pet images. Tests use it when they need the /pets picker or pet selection to work.

Data flow: It takes a mutable chat widget, writes a supported pet-image status into it, and returns nothing; after this, pet-related commands see Kitty image support.

Call relations: Pet tests call this before opening the pets picker or selecting a named pet, so the command path being tested is the normal supported-terminal path.

Call graph: called by 2 (slash_pets_opens_picker, slash_pets_with_arg_selects_named_pet); 2 external calls (set_pet_image_support_for_tests, Supported).

force_tmux_pet_image_unsupported12–16 ↗
fn force_tmux_pet_image_unsupported(chat: &mut ChatWidget)

Purpose: Sets a test chat widget to pretend pet images are unavailable because the app is running inside tmux. This lets tests check the tmux-specific warning and the special case that disabling pets still works.

Data flow: It takes a mutable chat widget, records an unsupported pet-image state with the tmux reason, and returns nothing.

Call relations: Unsupported-pets tests call this before dispatching /pets, /pets disable, or /pet hide, so the chat widget must either warn or disable pets without opening the picker.

Call graph: called by 4 (slash_pet_hide_disables_pets_even_on_unsupported_terminal, slash_pets_disable_disables_pets_even_on_unsupported_terminal, slash_pets_on_unsupported_terminal_warns_without_picker, slash_pets_with_arg_on_unsupported_terminal_warns_without_selection); 2 external calls (set_pet_image_support_for_tests, Unsupported).

force_terminal_pet_image_unsupported18–22 ↗
fn force_terminal_pet_image_unsupported(chat: &mut ChatWidget)

Purpose: Sets a test chat widget to pretend the terminal itself cannot show pet images. Tests use this to check the generic unsupported-terminal message.

Data flow: It takes a mutable chat widget, stores an unsupported pet-image state with the terminal reason, and returns nothing.

Call relations: The terminal-warning pet test calls this before /pets, so the command should produce guidance instead of opening the pet picker.

Call graph: called by 1 (slash_pets_on_unsupported_terminal_shows_terminal_warning); 2 external calls (set_pet_image_support_for_tests, Unsupported).

force_old_iterm2_pet_image_unsupported24–28 ↗
fn force_old_iterm2_pet_image_unsupported(chat: &mut ChatWidget)

Purpose: Sets a test chat widget to pretend iTerm2 is too old for pet images. This checks that users get the right upgrade message.

Data flow: It takes a mutable chat widget, stores an unsupported pet-image state with the old-iTerm2 reason, and returns nothing.

Call relations: The old-iTerm2 pet test calls this before /pets, so the command path should show an upgrade warning.

Call graph: called by 1 (slash_pets_on_old_iterm2_shows_upgrade_warning); 2 external calls (set_pet_image_support_for_tests, Unsupported).

fast_tier_command30–36 ↗
fn fast_tier_command() -> ServiceTierCommand

Purpose: Builds the test version of the service-tier command for Fast mode. It gives several tests the same command object without repeating the setup.

Data flow: It reads the Fast service tier’s request value, combines it with a display name and description, and returns a ServiceTierCommand.

Call relations: Fast-mode tests pass this returned command into chat-widget service-tier dispatch, then check that events and later user turns use the expected tier.

Call graph: called by 3 (fast_slash_command_updates_and_persists_local_service_tier, user_turn_carries_service_tier_after_fast_toggle, user_turn_sends_standard_override_after_fast_is_turned_off).

complete_turn_with_message38–48 ↗
fn complete_turn_with_message(chat: &mut ChatWidget, turn_id: &str, message: Option<&str>)

Purpose: Finishes a fake assistant turn, optionally adding a final assistant message first. Tests use it to move the chat widget from “agent is busy” to “agent is done.”

Data flow: It receives a chat widget, a turn id, and optional text; if text is present it inserts a final assistant message, then marks the turn complete.

Call relations: Many queueing and notification tests call this after starting a turn, because queued commands and messages are supposed to run only after the active turn completes.

Call graph: called by 19 (active_goal_without_follow_up_suppresses_agent_turn_complete_notification, agent_turn_complete_notification_does_not_reuse_stale_copy_source, assert_cancelled_queued_menu_drains_next_input, queued_bang_shell_dispatches_after_active_turn, queued_bang_shell_waits_for_user_shell_completion_before_next_input, queued_bare_rename_drains_next_input_after_name_update, queued_empty_bang_shell_reports_help_when_dequeued_and_drains_next_input, queued_fast_slash_applies_before_next_queued_message, queued_follow_up_suppresses_agent_turn_complete_notification, queued_goal_slash_command_preserves_large_paste (+9 more)); 1 external calls (format!).

submit_composer_text50–54 ↗
fn submit_composer_text(chat: &mut ChatWidget, text: &str)

Purpose: Puts text into the composer and submits it as if the user typed it and pressed the right keys. It keeps command-submission tests short.

Data flow: It takes a chat widget and text, writes that text into the bottom composer, then calls the helper that simulates submission; the resulting effects appear in the widget and event receivers.

Call relations: Most tests for direct slash-command entry call this, and it delegates the key sequence to submit_current_composer.

Call graph: calls 1 internal fn (submit_current_composer); called by 21 (bare_slash_command_is_available_from_local_recall_after_dispatch, goal_control_slash_command_without_thread_shows_full_usage, goal_control_slash_commands_emit_goal_events, goal_edit_slash_command_opens_goal_editor, goal_slash_command_with_extra_os_emits_set_goal_event, inline_slash_command_is_available_from_local_recall_after_dispatch, no_op_stub_slash_command_is_available_from_local_recall, queued_goal_slash_command_emits_set_goal_event_after_thread_starts, queued_goal_slash_command_preserves_current_draft_metadata, restored_queued_goal_slash_command_emits_set_goal_event (+11 more)); 1 external calls (new).

submit_current_composer56–60 ↗
fn submit_current_composer(chat: &mut ChatWidget)

Purpose: Simulates the keystrokes needed to submit whatever is already in the composer. It is useful when a test has prepared composer state with images, mentions, or pasted text.

Data flow: It sends Escape and Enter key events to the chat widget; the widget then decides whether to submit text, dispatch a command, or interact with a popup.

Call relations: It is called by submit_composer_text and by a large-paste goal test that edits existing composer state before submission.

Call graph: called by 2 (queued_goal_slash_command_restores_large_paste_for_edit, submit_composer_text); 2 external calls (new, handle_key_event).

queue_composer_text_with_tab62–66 ↗
fn queue_composer_text_with_tab(chat: &mut ChatWidget, text: &str)

Purpose: Places text in the composer and queues it with Tab while another turn is active. Tests use it to verify that commands and messages wait in line correctly.

Data flow: It writes text into the composer, sends a Tab key event, and leaves the result in the chat widget’s input queue instead of immediately submitting it.

Call relations: Queueing tests call this before completing the active turn, then check whether the queued slash command, shell command, menu, or user message runs afterward.

Call graph: called by 13 (assert_cancelled_queued_menu_drains_next_input, queued_bang_shell_dispatches_after_active_turn, queued_bang_shell_waits_for_user_shell_completion_before_next_input, queued_bare_rename_drains_next_input_after_name_update, queued_empty_bang_shell_reports_help_when_dequeued_and_drains_next_input, queued_fast_slash_applies_before_next_queued_message, queued_inline_rename_does_not_drain_again_before_turn_started, queued_menu_slash_keeps_agent_turn_complete_notification, queued_slash_compact_dispatches_after_active_turn, queued_slash_menu_selection_drains_next_input (+3 more)); 3 external calls (new, new, handle_key_event).

queue_goal_with_large_paste68–73 ↗
fn queue_goal_with_large_paste(chat: &mut ChatWidget, paste: String)

Purpose: Queues a /goal command whose objective includes a paste too large to fit inline. It tests that large pasted content is preserved safely.

Data flow: It starts the composer with /goal , feeds in a large paste, sends Tab to queue it, and leaves the paste metadata attached to the queued input.

Call relations: Goal paste tests call this while a turn is active, then later inspect either the emitted goal draft or the restored composer state.

Call graph: called by 3 (interrupt_disambiguates_same_sized_goal_pastes, queued_goal_slash_command_preserves_large_paste, queued_goal_slash_command_restores_large_paste_for_edit); 4 external calls (new, new, handle_key_event, handle_paste).

recall_latest_after_clearing75–80 ↗
fn recall_latest_after_clearing(chat: &mut ChatWidget) -> String

Purpose: Clears the composer, presses Up, and returns whatever history recall restores. Tests use it to check whether commands were saved for later recall.

Data flow: It empties the composer, sends an Up key event, reads the composer text, and returns that text.

Call relations: Many command-history tests use this after dispatching a command to confirm whether the command was remembered or deliberately excluded.

Call graph: 4 external calls (new, new, new, handle_key_event).

dispatch_usage_and_expect_refresh82–88 ↗
fn dispatch_usage_and_expect_refresh(
    chat: &mut ChatWidget,
    rx: &mut tokio::sync::mpsc::UnboundedReceiver<AppEvent>,
) -> u64

Purpose: Runs /usage daily and immediately checks that the widget asked the app to refresh token activity. It avoids repeating that setup in usage-card tests.

Data flow: It dispatches the usage command with the daily argument, reads the event receiver, and returns the request id for the refresh request.

Call relations: Usage refresh tests call this before simulating late, completed, stale, or blocked token-activity results; it delegates the receiver check to expect_token_activity_refresh.

Call graph: calls 1 internal fn (expect_token_activity_refresh); called by 11 (account_state_change_discards_pending_token_activity_refresh, clearing_pending_token_activity_refreshes_discards_late_result, completed_token_activity_refresh_retries_after_plan_item_completion, completed_token_activity_refresh_returns_one_history_cell, completed_token_activity_refresh_waits_for_active_history_cell, completed_token_activity_refresh_waits_for_active_hook, completed_token_activity_refresh_waits_for_active_stream, completed_token_activity_refresh_waits_for_queued_stream_consolidation, pending_token_activity_refresh_keeps_composer_visible_in_short_viewport, pending_token_activity_refresh_renders_above_composer_snapshot (+1 more)); 2 external calls (new, dispatch_command_with_args).

expect_token_activity_refresh90–95 ↗
fn expect_token_activity_refresh(rx: &mut tokio::sync::mpsc::UnboundedReceiver<AppEvent>) -> u64

Purpose: Reads the next app event and verifies it is a token-activity refresh request. It gives tests a clear failure if the expected event was not sent.

Data flow: It tries to receive one event; if it is RefreshTokenActivity, it returns the request id, otherwise it panics with the unexpected value.

Call relations: It is used by the usage helper and by the repeated-refresh test to capture the request id that later results must match.

Call graph: called by 2 (dispatch_usage_and_expect_refresh, repeated_token_activity_refreshes_keep_only_latest_card); 2 external calls (try_recv, panic!).

next_add_to_history_event97–110 ↗
fn next_add_to_history_event(rx: &mut tokio::sync::mpsc::UnboundedReceiver<AppEvent>) -> String

Purpose: Finds the next history-entry event in the app event receiver. Tests use it when other unrelated events may appear first.

Data flow: It repeatedly reads events until it sees AppendMessageHistoryEntry, then returns its text; if the queue is empty or closed first, it panics.

Call relations: Shell, copy, clear, and interrupted-message tests use this to confirm exactly what text the widget added to local history.

Call graph: 2 external calls (try_recv, panic!).

service_tier_commands_lowercase_catalog_names113–139 ↗
async fn service_tier_commands_lowercase_catalog_names()

Purpose: Checks that service-tier command names from the model catalog are normalized to lowercase. This prevents a catalog value like Fast from becoming an inconsistent command label.

Data flow: The test edits a model preset so the Fast tier name is capitalized, installs that catalog in the chat widget, and expects the generated command list to contain fast.

Call relations: It exercises the chat widget’s current-model service-tier command builder without sending backend operations.

Call graph: calls 1 internal fn (new); 3 external calls (assert_eq!, new, vec!).

slash_compact_eagerly_queues_follow_up_before_turn_start142–167 ↗
async fn slash_compact_eagerly_queues_follow_up_before_turn_start()

Purpose: Verifies that /compact immediately starts a task state, and a user message typed before the compact turn officially starts is queued instead of submitted too soon.

Data flow: The test dispatches /compact, checks for a compact operation, enters follow-up text, presses Enter, and expects one queued user message and no submitted operation.

Call relations: It covers the early gap between command dispatch and turn-start notification, where queueing mistakes are easy.

Call graph: 6 external calls (new, new, assert!, assert_eq!, assert_matches!, panic!).

queued_slash_compact_dispatches_after_active_turn170–197 ↗
async fn queued_slash_compact_dispatches_after_active_turn()

Purpose: Checks that a queued /compact command waits for the current turn to finish, then sends the compact operation.

Data flow: The test starts a turn, queues /compact, confirms no event is sent yet, completes the turn, then searches emitted events for the compact operation.

Call relations: It uses the queue helper and turn-completion helper to test the delayed slash-command path.

Call graph: calls 3 internal fn (new, complete_turn_with_message, queue_composer_text_with_tab); 4 external calls (assert!, assert_eq!, assert_matches!, from_fn).

queued_slash_review_with_args_dispatches_after_active_turn200–218 ↗
async fn queued_slash_review_with_args_dispatches_after_active_turn()

Purpose: Checks that a queued /review command keeps its custom instructions and dispatches them after the active turn.

Data flow: The test queues /review check regressions, completes the active turn, and expects a review operation with those instructions.

Call relations: It proves queued slash commands preserve arguments, not just the command name.

Call graph: calls 3 internal fn (new, complete_turn_with_message, queue_composer_text_with_tab); 2 external calls (assert_eq!, panic!).

queued_slash_review_with_args_restores_for_edit221–233 ↗
async fn queued_slash_review_with_args_restores_for_edit()

Purpose: Checks that a queued /review command can be pulled back into the composer for editing. This protects the user’s typed arguments.

Data flow: The test queues the command, sends Alt-Up, then reads the composer and expects the full command text.

Call relations: It uses the same queue helper as dispatch tests but focuses on edit recall rather than backend operation submission.

Call graph: calls 2 internal fn (new, queue_composer_text_with_tab); 2 external calls (new, assert_eq!).

queued_bang_shell_dispatches_after_active_turn236–262 ↗
async fn queued_bang_shell_dispatches_after_active_turn()

Purpose: Checks that a queued ! shell command waits for the agent turn to finish, then runs as a user shell command.

Data flow: The test queues !echo hi, completes the turn, expects a shell operation with echo hi, records history, and confirms the queue is empty.

Call relations: It exercises the queued shell-command path, which is separate from normal slash-command parsing.

Call graph: calls 3 internal fn (new, complete_turn_with_message, queue_composer_text_with_tab); 4 external calls (assert!, assert_eq!, assert_matches!, panic!).

queued_empty_bang_shell_reports_help_when_dequeued_and_drains_next_input265–299 ↗
async fn queued_empty_bang_shell_reports_help_when_dequeued_and_drains_next_input()

Purpose: Checks that a queued bare ! shows shell help when it is eventually processed, then continues to the next queued message.

Data flow: The test queues ! and a normal message, completes the active turn, expects help text in history, then expects the next user message operation.

Call relations: It proves an invalid queued shell command does not block the rest of the input queue forever.

Call graph: calls 3 internal fn (new, complete_turn_with_message, queue_composer_text_with_tab); 3 external calls (assert!, assert_eq!, panic!).

queued_bang_shell_waits_for_user_shell_completion_before_next_input302–338 ↗
async fn queued_bang_shell_waits_for_user_shell_completion_before_next_input()

Purpose: Checks that the next queued message does not run until a queued user shell command has finished. This prevents overlapping shell output and agent turns.

Data flow: The test queues a shell command and a message, completes the active turn, starts and ends the shell execution, then expects the queued message to submit.

Call relations: It links the queued-input system to execution notifications, using fake begin/end execution calls to unblock the queue.

Call graph: calls 3 internal fn (new, complete_turn_with_message, queue_composer_text_with_tab); 3 external calls (assert!, assert_eq!, panic!).

assert_cancelled_queued_menu_drains_next_input340–371 ↗
async fn assert_cancelled_queued_menu_drains_next_input(command: &str, expected_popup_text: &str)

Purpose: Shared test helper that verifies canceling a queued menu command lets the next queued message run. It is used for menu-style slash commands such as model and permissions.

Data flow: It queues a menu command and a follow-up message, completes the active turn, confirms the popup appears, sends Escape, and expects the follow-up user turn.

Call relations: The menu-cancel test calls this helper twice, once for /model and once for /permissions.

Call graph: calls 3 internal fn (new, complete_turn_with_message, queue_composer_text_with_tab); called by 1 (queued_slash_menu_cancel_drains_next_input); 5 external calls (new, assert!, assert_eq!, assert_matches!, panic!).

queued_slash_menu_cancel_drains_next_input374–378 ↗
async fn queued_slash_menu_cancel_drains_next_input()

Purpose: Checks that queued slash commands which open menus do not trap the input queue if the user cancels the menu.

Data flow: It runs the shared helper for /model and /permissions, each time expecting the next queued message to submit after Escape.

Call relations: It delegates the actual scenario to assert_cancelled_queued_menu_drains_next_input.

Call graph: calls 1 internal fn (assert_cancelled_queued_menu_drains_next_input).

queued_slash_menu_selection_drains_next_input381–410 ↗
async fn queued_slash_menu_selection_drains_next_input()

Purpose: Checks that choosing an item from a queued menu also lets the next queued message run.

Data flow: The test queues /permissions and a follow-up message, completes the active turn, presses Enter in the menu, and expects the follow-up user turn.

Call relations: It complements the cancel test by covering the selection path through the same queued-menu machinery.

Call graph: calls 3 internal fn (new, complete_turn_with_message, queue_composer_text_with_tab); 4 external calls (new, assert!, assert_eq!, panic!).

queued_bare_rename_drains_next_input_after_name_update413–461 ↗
async fn queued_bare_rename_drains_next_input_after_name_update()

Purpose: Checks that a queued bare /rename opens a prompt, submits the chosen name, and only then drains the next queued message after the server confirms the rename.

Data flow: The test queues /rename and a message, completes the turn, fills the rename prompt, checks for a set-name event, simulates a server name update, and expects the next user turn.

Call relations: It covers a queued command that pauses for both user input and server confirmation before continuing.

Call graph: calls 3 internal fn (new, complete_turn_with_message, queue_composer_text_with_tab); 7 external calls (new, ThreadNameUpdated, assert!, assert_eq!, assert_matches!, panic!, from_fn).

queued_inline_rename_does_not_drain_again_before_turn_started464–544 ↗
async fn queued_inline_rename_does_not_drain_again_before_turn_started()

Purpose: Checks that an inline queued rename followed by multiple messages only drains one follow-up until the next user turn has actually started and completed.

Data flow: The test queues /rename Queued rename plus two messages, completes the first turn, expects the first follow-up to submit, saves and restores input state, simulates rename confirmation, then verifies the second waits until another turn completes.

Call relations: It protects the queue’s user_turn_pending_start state across capture and restore, preventing double-submission.

Call graph: calls 3 internal fn (new, complete_turn_with_message, queue_composer_text_with_tab); 6 external calls (ThreadNameUpdated, assert!, assert_eq!, assert_matches!, panic!, from_fn).

queued_unknown_slash_reports_error_when_dequeued547–569 ↗
async fn queued_unknown_slash_reports_error_when_dequeued()

Purpose: Checks that an unknown queued slash command reports its error only when it is processed after the active turn.

Data flow: The test queues /does-not-exist, confirms no immediate history message, completes the turn, then expects an unrecognized-command message and an empty queue.

Call relations: It verifies delayed error reporting for queued command parsing.

Call graph: calls 3 internal fn (new, complete_turn_with_message, queue_composer_text_with_tab); 1 external calls (assert!).

ctrl_d_quits_without_prompt572–577 ↗
async fn ctrl_d_quits_without_prompt()

Purpose: Checks that Ctrl-D exits the app when no modal dialog is open.

Data flow: The test sends a Ctrl-D key event and expects an app exit event.

Call relations: It covers a global keyboard shortcut handled by the chat widget.

Call graph: 3 external calls (Char, new, assert_matches!).

ctrl_d_with_modal_open_does_not_quit580–587 ↗
async fn ctrl_d_with_modal_open_does_not_quit()

Purpose: Checks that Ctrl-D does not quit while a modal popup is open. This prevents accidental app exits during focused dialogs.

Data flow: The test opens an approvals popup, sends Ctrl-D, and expects no exit event.

Call relations: It pairs with the no-modal Ctrl-D test to prove modal focus changes shortcut behavior.

Call graph: 3 external calls (Char, new, assert_matches!).

slash_init_does_not_depend_on_loaded_instruction_sources590–599 ↗
async fn slash_init_does_not_depend_on_loaded_instruction_sources()

Purpose: Checks that /init can be submitted even when instruction source paths are present but not loaded. This prevents project-instruction state from blocking init.

Data flow: The test sets an instruction path, submits /init, expects one queued user message, no history output, and successful command recall.

Call relations: It uses the common submission and recall helpers to test command dispatch and local history.

Call graph: calls 1 internal fn (submit_composer_text); 3 external calls (assert!, assert_eq!, vec!).

bare_slash_command_is_available_from_local_recall_after_dispatch602–610 ↗
async fn bare_slash_command_is_available_from_local_recall_after_dispatch()

Purpose: Checks that a bare slash command such as /diff is saved in local recall after dispatch.

Data flow: The test submits /diff, drains any output, presses Up, and expects /diff back in the composer.

Call relations: It verifies successful slash commands participate in composer history.

Call graph: calls 1 internal fn (submit_composer_text); 2 external calls (new, assert_eq!).

inline_slash_command_is_available_from_local_recall_after_dispatch613–621 ↗
async fn inline_slash_command_is_available_from_local_recall_after_dispatch()

Purpose: Checks that a slash command with inline arguments is saved in local recall exactly as typed.

Data flow: The test submits /rename Better title, drains output, presses Up, and expects the same text.

Call relations: It complements the bare-command recall test with an argument-bearing command.

Call graph: calls 1 internal fn (submit_composer_text); 2 external calls (new, assert_eq!).

goal_slash_command_with_extra_os_emits_set_goal_event624–647 ↗
async fn goal_slash_command_with_extra_os_emits_set_goal_event()

Purpose: Checks that /goal parsing accepts an exaggerated command spelling and treats the rest as the goal objective. This guards permissive command matching.

Data flow: With goals enabled and a thread id set, the test submits the command and expects a goal-draft event with the objective text and no backend operation.

Call relations: It exercises the goal event path and confirms the command is recallable.

Call graph: calls 2 internal fn (new, submit_composer_text); 2 external calls (assert_eq!, panic!).

goal_slash_command_uses_plain_text_for_mentions650–673 ↗
async fn goal_slash_command_uses_plain_text_for_mentions()

Purpose: Checks that mentions inside a goal objective are kept as the plain text the user typed, not converted into link markup.

Data flow: The test prepares composer text with a $figma mention binding, submits /goal, and expects the goal draft objective to contain use $figma for the mockup.

Call relations: It focuses on the boundary between rich composer metadata and goal-draft text.

Call graph: calls 1 internal fn (new); 4 external calls (new, new, assert_eq!, vec!).

goal_slash_command_emits_attached_images676–711 ↗
async fn goal_slash_command_emits_attached_images()

Purpose: Checks that images attached while setting a goal are included in the goal draft. It covers both remote image URLs and local image files.

Data flow: The test creates a local image, sets a remote URL and text element placeholder, submits /goal, then expects the draft to contain the objective, remote URL, local image metadata, and cleared composer attachments.

Call relations: It verifies goal submission drains image attachment state instead of leaving stale attachments behind.

Call graph: calls 1 internal fn (new); 6 external calls (new, assert!, assert_eq!, format!, write, vec!).

bare_goal_slash_command_drains_pending_submission_state714–733 ↗
async fn bare_goal_slash_command_drains_pending_submission_state()

Purpose: Checks that bare /goal opens the goal menu and clears pending image submission state. This avoids accidentally attaching old images later.

Data flow: The test sets remote and local images, submits /goal, expects an open-goal-menu event, and confirms the attachment state is empty.

Call relations: It covers the no-objective goal command path.

Call graph: calls 1 internal fn (new); 6 external calls (new, from, new, assert!, assert_matches!, vec!).

goal_control_slash_commands_emit_goal_events736–776 ↗
async fn goal_control_slash_commands_emit_goal_events()

Purpose: Checks that /goal clear, /goal pause, and /goal resume emit the correct goal-control events.

Data flow: For each command, the test enables goals, sets a thread id, submits the command, and expects either a clear event or a status update event.

Call relations: It groups the simple goal-control commands into one table-driven test.

Call graph: calls 2 internal fn (new, submit_composer_text); 2 external calls (assert_eq!, panic!).

goal_control_slash_command_without_thread_shows_full_usage779–791 ↗
async fn goal_control_slash_command_without_thread_shows_full_usage()

Purpose: Checks that goal-control commands explain the problem when there is no current thread. Users cannot pause or resume a goal before a session exists.

Data flow: The test submits /goal pause without a thread id and expects a usage message saying the session must start first.

Call relations: It tests the error path for the goal-control command group.

Call graph: calls 1 internal fn (submit_composer_text); 2 external calls (assert_eq!, assert_snapshot!).

goal_edit_slash_command_opens_goal_editor794–812 ↗
async fn goal_edit_slash_command_opens_goal_editor()

Purpose: Checks that /goal edit opens the goal editor whether or not a thread id exists yet.

Data flow: For both a present and missing thread id, the test submits /goal edit and expects an open-editor event carrying that optional id.

Call relations: It confirms this command is UI-only and sends no backend operation.

Call graph: calls 2 internal fn (new, submit_composer_text); 2 external calls (assert_eq!, panic!).

queued_goal_slash_command_emits_set_goal_event_after_thread_starts815–831 ↗
async fn queued_goal_slash_command_emits_set_goal_event_after_thread_starts()

Purpose: Checks that a /goal command submitted before a thread exists is queued and emitted once the thread id becomes available.

Data flow: The test submits a goal command, sees it queued, later sets a thread id and asks the widget to send queued input, then expects a goal draft event.

Call relations: It covers startup timing where user input arrives before the session is ready.

Call graph: calls 2 internal fn (new, submit_composer_text); 2 external calls (assert_eq!, assert_matches!).

queued_goal_slash_command_preserves_large_paste834–852 ↗
async fn queued_goal_slash_command_preserves_large_paste()

Purpose: Checks that a queued goal command with a very large paste keeps the paste content and placeholder intact.

Data flow: The test queues a /goal with oversized pasted text during an active turn, completes the turn, and expects the emitted draft to include one pending paste with the original content.

Call relations: It uses queue_goal_with_large_paste and the turn-completion helper to test deferred goal submission.

Call graph: calls 3 internal fn (new, complete_turn_with_message, queue_goal_with_large_paste); 2 external calls (assert!, assert_eq!).

queued_goal_slash_command_restores_large_paste_for_edit855–874 ↗
async fn queued_goal_slash_command_restores_large_paste_for_edit()

Purpose: Checks that a queued goal with a large paste can be restored to the composer and resubmitted without losing the paste data.

Data flow: The test queues the goal, uses Alt-Up to restore it for editing, verifies the paste metadata, completes the turn, submits the composer, and expects the draft to contain the paste.

Call relations: It connects queued-input edit recall with the goal submission path.

Call graph: calls 4 internal fn (new, complete_turn_with_message, queue_goal_with_large_paste, submit_current_composer); 2 external calls (new, assert_eq!).

interrupt_disambiguates_same_sized_goal_pastes877–897 ↗
async fn interrupt_disambiguates_same_sized_goal_pastes()

Purpose: Checks that two large goal pastes of the same length are still tracked separately when a turn is interrupted.

Data flow: The test queues one large paste, types another same-sized paste, interrupts the turn, edits recalled text, and confirms the remaining paste is the second one.

Call relations: It protects paste bookkeeping from using size alone as an identity.

Call graph: calls 1 internal fn (queue_goal_with_large_paste); 4 external calls (new, new, assert!, assert_eq!).

queued_goal_slash_command_preserves_current_draft_metadata900–935 ↗
async fn queued_goal_slash_command_preserves_current_draft_metadata()

Purpose: Checks that sending a queued goal does not erase the user’s current composer draft and its attachments.

Data flow: The test queues a goal, then sets a different current draft with image metadata, starts the thread, sends the queued goal, and confirms the current draft text and image state are still present.

Call relations: It protects the separation between queued command data and live composer state.

Call graph: calls 2 internal fn (new, submit_composer_text); 5 external calls (from, assert_eq!, assert_matches!, format!, vec!).

restored_queued_goal_slash_command_emits_set_goal_event938–958 ↗
async fn restored_queued_goal_slash_command_emits_set_goal_event()

Purpose: Checks that a queued goal command survives saving and restoring thread input state.

Data flow: The test queues a goal, captures input state, creates a new chat widget, restores that state, sets a thread id, and expects the goal draft event when queued input is sent.

Call relations: It covers session restore behavior for queued slash commands.

Call graph: calls 2 internal fn (new, submit_composer_text).

merged_history_record_preserves_raw_text_and_rebased_elements961–999 ↗
fn merged_history_record_preserves_raw_text_and_rebased_elements()

Purpose: Checks that merging user messages for history preserves the text the user should see and correctly shifts rich-text element positions.

Data flow: The test builds two messages, one with a mention and one with a history override, merges them, and expects the combined history record to contain rebased element ranges.

Call relations: It directly tests the message/history merging helper used when input is combined after interruptions or internal prompts.

Call graph: calls 1 internal fn (from); 3 external calls (new, assert_eq!, vec!).

merged_history_record_remaps_override_image_placeholders1002–1072 ↗
fn merged_history_record_remaps_override_image_placeholders()

Purpose: Checks that image placeholders are renumbered correctly when merged messages both start with [Image #1].

Data flow: The test builds two image-bearing messages, merges them with a history override, and expects the second image to become [Image #2] in both submitted text and history text.

Call relations: It protects history display from duplicate image labels after message merging.

Call graph: 4 external calls (new, assert_eq!, format!, vec!).

interrupted_merged_message_history_encodes_mentions_once1075–1130 ↗
async fn interrupted_merged_message_history_encodes_mentions_once()

Purpose: Checks that a mention is encoded once in history when a user message is submitted, interrupted, and resubmitted.

Data flow: The test submits text with a $figma mention, expects plain text in the backend operation and encoded markdown in history, interrupts, then expects the same behavior on resubmission.

Call relations: It covers the interaction between interruption recovery, message merging, and mention history encoding.

Call graph: calls 1 internal fn (new); 5 external calls (new, new, assert_eq!, panic!, vec!).

slash_rename_prefills_existing_thread_name1133–1148 ↗
async fn slash_rename_prefills_existing_thread_name()

Purpose: Checks that /rename opens a prompt prefilled with the current thread name. This makes renaming easier and prevents accidental blank replacement.

Data flow: The test sets an existing thread name, dispatches /rename, snapshots the popup, presses Enter, and expects a set-name event with the existing name.

Call relations: It exercises the rename prompt command path.

Call graph: 3 external calls (new, assert_chatwidget_snapshot!, assert_matches!).

slash_rename_without_existing_thread_name_starts_empty1151–1163 ↗
async fn slash_rename_without_existing_thread_name_starts_empty()

Purpose: Checks that /rename starts with an empty prompt when there is no current thread name.

Data flow: The test dispatches /rename, verifies the popup instructions, presses Enter without typing, and expects no event.

Call relations: It complements the prefilled rename test with the empty-state behavior.

Call graph: 3 external calls (new, assert!, assert_matches!).

usage_error_slash_command_is_available_from_local_recall1166–1184 ↗
async fn usage_error_slash_command_is_available_from_local_recall()

Purpose: Checks that a slash command with invalid usage is still saved in recall. This lets users edit and fix their mistake.

Data flow: The test submits /raw maybe, expects a usage message, and then recalls the exact command.

Call relations: It covers command-history behavior for recognized commands with bad arguments.

Call graph: calls 1 internal fn (submit_composer_text); 2 external calls (assert!, assert_eq!).

signed_out_usage_command_reports_chatgpt_login_requirement1187–1203 ↗
async fn signed_out_usage_command_reports_chatgpt_login_requirement()

Purpose: Checks that /usage tells signed-out users they need ChatGPT sign-in.

Data flow: The test submits /usage, snapshots the rendered history message, and confirms the command can be recalled.

Call relations: It tests the usage command’s authentication guard.

Call graph: calls 1 internal fn (submit_composer_text); 2 external calls (assert_chatwidget_snapshot!, assert_eq!).

signed_out_usage_command_with_args_reports_chatgpt_login_requirement1206–1222 ↗
async fn signed_out_usage_command_with_args_reports_chatgpt_login_requirement()

Purpose: Checks that /usage weekly gives the same sign-in requirement when the user is signed out.

Data flow: The test submits the command with an argument, renders history output, checks the sign-in text, and verifies recall.

Call relations: It complements the bare signed-out usage test.

Call graph: calls 1 internal fn (submit_composer_text); 2 external calls (assert!, assert_eq!).

usage_command_with_invalid_view_reports_usage_snapshot1225–1238 ↗
async fn usage_command_with_invalid_view_reports_usage_snapshot()

Purpose: Checks that /usage monthly shows a usage message because monthly is not a valid view.

Data flow: The test signs in the widget, submits the invalid command, snapshots the usage output, and verifies recall.

Call relations: It tests argument validation after authentication succeeds.

Call graph: calls 1 internal fn (submit_composer_text); 2 external calls (assert_chatwidget_snapshot!, assert_eq!).

usage_command_runs_with_backend_auth_without_chatgpt_account_flag1241–1252 ↗
async fn usage_command_runs_with_backend_auth_without_chatgpt_account_flag()

Purpose: Checks that backend authentication is enough to run /usage, even if the ChatGPT-account flag is false.

Data flow: The test updates account state to backend-authenticated, dispatches /usage daily, and expects a token activity refresh event while the ChatGPT flag remains false.

Call relations: It covers account-state logic used by usage command dispatch.

Call graph: 3 external calls (new, assert!, assert_matches!).

usage_command_runs_with_backend_auth_from_widget_init1255–1267 ↗
async fn usage_command_runs_with_backend_auth_from_widget_init()

Purpose: Checks that backend authentication passed during widget creation also enables /usage.

Data flow: The test creates a widget with backend auth but no ChatGPT-account flag, dispatches /usage daily, and expects a refresh event.

Call relations: It complements the account-update usage test by covering initialization state.

Call graph: 3 external calls (new, assert!, assert_matches!).

clearing_pending_token_activity_refreshes_discards_late_result1270–1294 ↗
async fn clearing_pending_token_activity_refreshes_discards_late_result()

Purpose: Checks that clearing pending token-activity refreshes causes an old result to be ignored.

Data flow: The test starts a usage refresh, verifies the loading card, clears pending refreshes, then submits an error result with the old request id and expects it to be rejected.

Call relations: It uses the usage dispatch helper and then exercises stale-result protection.

Call graph: calls 1 internal fn (dispatch_usage_and_expect_refresh); 2 external calls (assert!, assert_eq!).

account_state_change_discards_pending_token_activity_refresh1297–1321 ↗
async fn account_state_change_discards_pending_token_activity_refresh()

Purpose: Checks that changing accounts removes an in-flight token-activity card and rejects its later result.

Data flow: The test starts a usage refresh, updates account state to a different display account, confirms no pending output remains, and expects the old result to be ignored.

Call relations: It protects against showing usage data from the wrong account.

Call graph: calls 1 internal fn (dispatch_usage_and_expect_refresh); 1 external calls (assert!).

pending_token_activity_refresh_renders_above_composer_snapshot1324–1343 ↗
async fn pending_token_activity_refresh_renders_above_composer_snapshot()

Purpose: Checks how the /usage loading card is drawn above the composer while a token-activity refresh is pending.

Data flow: The test starts a usage refresh, renders the chat widget into a virtual terminal, and snapshots the screen contents.

Call relations: It connects usage state to terminal rendering.

Call graph: calls 3 internal fn (dispatch_usage_and_expect_refresh, with_options, new); 2 external calls (new, assert_chatwidget_snapshot!).

completed_token_activity_refresh_returns_one_history_cell1346–1369 ↗
async fn completed_token_activity_refresh_returns_one_history_cell()

Purpose: Checks that a completed token-activity refresh can be taken as one history cell with the final message.

Data flow: The test starts a refresh, finishes it with an error, takes the completed output cell, and compares its rendered text.

Call relations: It verifies the handoff from pending usage card to history insertion.

Call graph: calls 1 internal fn (dispatch_usage_and_expect_refresh); 2 external calls (assert!, assert_eq!).

completed_token_activity_refresh_waits_for_active_stream1372–1399 ↗
async fn completed_token_activity_refresh_waits_for_active_stream()

Purpose: Checks that completed usage output waits until an active assistant stream is finalized before entering history.

Data flow: The test starts a refresh, simulates partial assistant output, finishes the refresh, confirms insertion is blocked, finalizes the turn, and expects a commit event.

Call relations: It protects transcript ordering between streaming replies and usage cards.

Call graph: calls 1 internal fn (dispatch_usage_and_expect_refresh); 2 external calls (assert!, assert_eq!).

completed_token_activity_refresh_waits_for_queued_stream_consolidation1402–1422 ↗
async fn completed_token_activity_refresh_waits_for_queued_stream_consolidation()

Purpose: Checks that usage output also waits for queued stream-consolidation work to finish.

Data flow: The test creates pending stream consolidation, finishes usage refresh, confirms blocking, then marks consolidation complete and expects blocking to end.

Call relations: It covers another condition that can delay safe history insertion.

Call graph: calls 1 internal fn (dispatch_usage_and_expect_refresh); 1 external calls (assert!).

completed_token_activity_refresh_waits_for_active_history_cell1425–1445 ↗
async fn completed_token_activity_refresh_waits_for_active_history_cell()

Purpose: Checks that usage output waits behind an active history cell and commits only after that cell is flushed.

Data flow: The test sets an active history cell, finishes the usage refresh, sees blocking, flushes the active cell, and expects insert-history followed by commit-usage events.

Call relations: It protects transcript order when tool or other active cells are being written.

Call graph: calls 2 internal fn (dispatch_usage_and_expect_refresh, new); 4 external calls (new, assert!, assert_matches!, vec!).

completed_token_activity_refresh_waits_for_active_hook1448–1487 ↗
async fn completed_token_activity_refresh_waits_for_active_hook()

Purpose: Checks that usage output waits while a hook is running. A hook is a configured action that runs around tool use.

Data flow: The test starts a fake hook, starts and finishes a usage refresh, confirms blocking, completes the hook, and expects history insertion plus usage commit events.

Call relations: It ensures hook output is not interleaved incorrectly with usage output.

Call graph: calls 1 internal fn (dispatch_usage_and_expect_refresh); 4 external calls (new, assert!, assert_matches!, vec!).

completed_token_activity_refresh_retries_after_plan_item_completion1490–1515 ↗
async fn completed_token_activity_refresh_retries_after_plan_item_completion()

Purpose: Checks that pending usage output gets another chance to commit after a plan item finishes.

Data flow: The test starts a usage refresh, creates a plan stream controller, finishes the refresh, completes the plan item, and expects a commit-after-stream-shutdown event.

Call relations: It covers plan rendering as another source of delayed transcript updates.

Call graph: calls 2 internal fn (dispatch_usage_and_expect_refresh, new); 1 external calls (assert!).

pending_token_activity_refresh_keeps_composer_visible_in_short_viewport1518–1544 ↗
async fn pending_token_activity_refresh_keeps_composer_visible_in_short_viewport()

Purpose: Checks that a usage loading card does not push the composer off-screen in a very short terminal.

Data flow: The test creates tall active output, starts usage refresh, renders into an eight-line virtual terminal, and expects the composer prompt to still be visible.

Call relations: It protects usability of the rendering layout under tight space.

Call graph: calls 4 internal fn (dispatch_usage_and_expect_refresh, with_options, new, new); 5 external calls (new, from, new, assert!, repeat_n).

repeated_token_activity_refreshes_keep_only_latest_card1547–1569 ↗
async fn repeated_token_activity_refreshes_keep_only_latest_card()

Purpose: Checks that if /usage is run again, only the newest pending card matters.

Data flow: The test starts a daily refresh, then a weekly refresh, expects the visible card to be weekly, rejects the first result as stale, and accepts the second.

Call relations: It uses both usage-refresh helpers to verify request-id based freshness.

Call graph: calls 2 internal fn (dispatch_usage_and_expect_refresh, expect_token_activity_refresh); 3 external calls (new, assert!, assert_eq!).

unrecognized_slash_command_is_not_added_to_local_recall1572–1589 ↗
async fn unrecognized_slash_command_is_not_added_to_local_recall()

Purpose: Checks that a completely unknown slash command is not saved in local recall.

Data flow: The test submits /does-not-exist, expects an error while the text remains in the composer, clears and recalls, and expects no recalled command.

Call relations: It contrasts unknown commands with recognized-but-invalid commands that are recallable.

Call graph: calls 1 internal fn (submit_composer_text); 2 external calls (assert!, assert_eq!).

unavailable_slash_command_is_available_from_local_recall1592–1609 ↗
async fn unavailable_slash_command_is_available_from_local_recall()

Purpose: Checks that a recognized command disabled during a running task is still saved for recall.

Data flow: The test marks a task as running, submits /model, expects a disabled-command message, and confirms /model can be recalled.

Call relations: It tests command-history behavior for unavailable but known commands.

Call graph: calls 1 internal fn (submit_composer_text); 2 external calls (assert!, assert_eq!).

no_op_stub_slash_command_is_available_from_local_recall1612–1628 ↗
async fn no_op_stub_slash_command_is_available_from_local_recall()

Purpose: Checks that a stubbed command still appears in recall. A stub is a placeholder command that reports it is not implemented yet.

Data flow: The test submits /debug-m-drop, expects the memory-maintenance message, and confirms the command can be recalled.

Call relations: It covers recall behavior for known commands that intentionally do not perform work.

Call graph: calls 1 internal fn (submit_composer_text); 2 external calls (assert!, assert_eq!).

slash_quit_requests_exit1631–1637 ↗
async fn slash_quit_requests_exit()

Purpose: Checks that /quit requests app shutdown.

Data flow: The test dispatches the quit command and expects an exit event.

Call relations: It tests the slash-command path for quitting, separate from keyboard shortcuts.

Call graph: 1 external calls (assert_matches!).

slash_logout_requests_app_server_logout1640–1646 ↗
async fn slash_logout_requests_app_server_logout()

Purpose: Checks that /logout asks the surrounding app to log out.

Data flow: The test dispatches the logout command and expects a logout event.

Call relations: It verifies the command is routed to the app layer, not the core operation channel.

Call graph: 1 external calls (assert_matches!).

slash_copy_state_tracks_turn_complete_final_reply1649–1658 ↗
async fn slash_copy_state_tracks_turn_complete_final_reply()

Purpose: Checks that the copy source is updated to the final assistant reply when a turn completes.

Data flow: The test completes a fake turn with final markdown and expects last_agent_markdown_text to return it.

Call relations: It uses the turn-completion helper to test /copy state without actually copying.

Call graph: calls 1 internal fn (complete_turn_with_message); 1 external calls (assert_eq!).

slash_copy_state_tracks_plan_item_completion1661–1684 ↗
async fn slash_copy_state_tracks_plan_item_completion()

Purpose: Checks that a completed plan item can become the latest copyable agent text.

Data flow: The test sends a plan item-completed notification, completes the turn, and expects the plan text in copy state and notification state.

Call relations: It covers agent output that arrives as a plan item rather than a final answer message.

Call graph: 4 external calls (ItemCompleted, new, assert_eq!, assert_matches!).

slash_copy_reports_when_no_agent_response_exists1687–1700 ↗
async fn slash_copy_reports_when_no_agent_response_exists()

Purpose: Checks that /copy gives a helpful message when there is no agent response to copy.

Data flow: The test dispatches /copy, drains one history cell, snapshots it, and checks for the no-output text.

Call relations: It tests the command path for copy failure due to missing content.

Call graph: 3 external calls (assert!, assert_chatwidget_snapshot!, assert_eq!).

ctrl_o_copy_reports_when_no_agent_response_exists1703–1715 ↗
async fn ctrl_o_copy_reports_when_no_agent_response_exists()

Purpose: Checks that the default copy shortcut Ctrl-O reports the same no-response message as /copy.

Data flow: The test sends Ctrl-O, drains history, and checks the no-output text.

Call relations: It ties keyboard shortcut handling to the same copy behavior as the slash command.

Call graph: 4 external calls (Char, new, assert!, assert_eq!).

keymap_capture_can_capture_current_copy_shortcut1718–1747 ↗
async fn keymap_capture_can_capture_current_copy_shortcut()

Purpose: Checks that keymap-capture mode records Ctrl-O instead of running the copy shortcut.

Data flow: The test opens key capture for a composer action, sends Ctrl-O, and expects a KeymapCaptured event with ctrl-o and no history output.

Call relations: It proves key-capture mode takes priority over normal shortcut behavior.

Call graph: calls 1 internal fn (defaults); 5 external calls (Char, new, assert!, assert_eq!, panic!).

slash_keymap_capture_can_capture_app_shortcuts1750–1778 ↗
async fn slash_keymap_capture_can_capture_app_shortcuts()

Purpose: Checks that keymap-capture mode can record global app shortcuts such as Ctrl-T, Ctrl-L, and Ctrl-G.

Data flow: For each key, the test opens capture, sends the key, and expects a captured-key event with the right string.

Call relations: It extends the key-capture priority check beyond the copy shortcut.

Call graph: calls 1 internal fn (defaults); 4 external calls (Char, new, assert_eq!, panic!).

slash_keymap_debug_opens_keypress_inspector1781–1797 ↗
async fn slash_keymap_debug_opens_keypress_inspector()

Purpose: Checks that /keymap debug opens a keypress inspector popup and shows what action a pressed key maps to.

Data flow: The test dispatches the debug command, checks the popup, sends Ctrl-O, checks the popup includes the copy action, and confirms no history or core operation is sent.

Call relations: It tests the command’s UI-only inspection mode.

Call graph: 4 external calls (Char, new, new, assert!).

slash_keymap_debug_can_inspect_app_shortcuts1800–1824 ↗
async fn slash_keymap_debug_can_inspect_app_shortcuts()

Purpose: Checks that the keymap debug inspector can identify several global shortcuts without running their side effects.

Data flow: The test opens debug mode, presses Ctrl-T, Ctrl-L, and Ctrl-G, and expects the popup to name each action while no history or core operation appears.

Call relations: It complements the Ctrl-O debug test with app-level shortcuts.

Call graph: 4 external calls (Char, new, new, assert!).

slash_keymap_invalid_args_show_usage1827–1844 ↗
async fn slash_keymap_invalid_args_show_usage()

Purpose: Checks that invalid /keymap arguments show usage help and do not send a backend operation.

Data flow: The test submits /keymap nope, reads the history message, confirms it contains usage text, verifies recall, and checks the operation channel is empty.

Call relations: It tests argument validation for the keymap command.

Call graph: calls 1 internal fn (submit_composer_text); 2 external calls (assert!, assert_eq!).

copy_shortcut_can_be_remapped1847–1871 ↗
async fn copy_shortcut_can_be_remapped()

Purpose: Checks that the copy shortcut follows runtime keymap configuration changes.

Data flow: The test changes global copy to Ctrl-X, applies the keymap, sends old Ctrl-O and sees no effect, then sends Ctrl-X and expects the copy no-response message.

Call relations: It connects keymap configuration updates to chat-widget key handling.

Call graph: calls 1 internal fn (from_config); 6 external calls (Char, new, assert!, assert_eq!, KeybindingSpec, One).

slash_copy_stores_clipboard_lease_and_preserves_it_on_failure1874–1905 ↗
async fn slash_copy_stores_clipboard_lease_and_preserves_it_on_failure()

Purpose: Checks that a successful copy stores a clipboard lease and a later failed copy does not drop that lease. A lease is a small object that keeps clipboard ownership alive.

Data flow: The test sets copyable markdown, runs copy with a success closure returning a test lease, checks success output and stored lease, then runs copy with an error closure and confirms the lease remains.

Call relations: It directly tests the copy helper with injected clipboard behavior instead of touching the real clipboard.

Call graph: 2 external calls (assert!, assert_eq!).

slash_copy_state_is_preserved_during_running_task1908–1918 ↗
async fn slash_copy_state_is_preserved_during_running_task()

Purpose: Checks that starting a new task does not erase the last completed reply used by /copy.

Data flow: The test completes one turn with a reply, starts another task, and expects the old reply to remain copyable.

Call relations: It protects copy state across task transitions.

Call graph: calls 1 internal fn (complete_turn_with_message); 1 external calls (assert_eq!).

slash_copy_uses_agent_message_item_when_turn_complete_omits_final_text1921–1943 ↗
async fn slash_copy_uses_agent_message_item_when_turn_complete_omits_final_text()

Purpose: Checks that copy state can fall back to a completed assistant message item when the turn-complete notification lacks final text.

Data flow: The test starts a turn, completes an assistant message without a final phase, completes the turn, and expects that message to become the latest copy source and notification response.

Call relations: It covers compatibility with older or alternate server message formats.

Call graph: 2 external calls (assert_eq!, assert_matches!).

agent_turn_complete_notification_does_not_reuse_stale_copy_source1946–1958 ↗
async fn agent_turn_complete_notification_does_not_reuse_stale_copy_source()

Purpose: Checks that a turn-complete notification without a new response does not reuse an old copied response.

Data flow: The test completes one turn with text, clears the pending notification, completes a second turn without text, and expects the notification response to be empty.

Call relations: It prevents stale agent text from appearing as if it belonged to a later turn.

Call graph: calls 1 internal fn (complete_turn_with_message); 1 external calls (assert_matches!).

active_goal_without_follow_up_suppresses_agent_turn_complete_notification1961–1987 ↗
async fn active_goal_without_follow_up_suppresses_agent_turn_complete_notification()

Purpose: Checks that an active session goal suppresses the normal agent-turn-complete notification when there is no follow-up.

Data flow: The test enables goals, sends a goal-updated notification marking the goal active, completes a turn with text, and expects no pending notification.

Call relations: It verifies goal mode changes notification behavior.

Call graph: calls 1 internal fn (complete_turn_with_message); 2 external calls (ThreadGoalUpdated, assert_matches!).

queued_follow_up_suppresses_agent_turn_complete_notification1990–2001 ↗
async fn queued_follow_up_suppresses_agent_turn_complete_notification()

Purpose: Checks that if a follow-up message is queued, the app does not show a turn-complete notification for the just-finished turn.

Data flow: The test starts a turn, queues a user message, completes the turn, expects no notification, and confirms the queued message is submitted.

Call relations: It protects the smooth chained-turn flow from extra notifications.

Call graph: calls 2 internal fn (new, complete_turn_with_message); 2 external calls (assert!, assert_matches!).

queued_menu_slash_keeps_agent_turn_complete_notification2004–2018 ↗
async fn queued_menu_slash_keeps_agent_turn_complete_notification()

Purpose: Checks that a queued menu command does not suppress the completed-turn notification, because it does not immediately start another user turn.

Data flow: The test queues /model, completes the active turn, expects the notification with the response text, sees the model popup, and confirms no core operation was sent.

Call relations: It contrasts menu commands with queued follow-up messages.

Call graph: calls 3 internal fn (new, complete_turn_with_message, queue_composer_text_with_tab); 2 external calls (assert!, assert_matches!).

slash_copy_uses_latest_surviving_response_after_rollback2021–2048 ↗
async fn slash_copy_uses_latest_surviving_response_after_rollback()

Purpose: Checks that after rewinding conversation history, /copy uses the latest agent response that still survives the rewind.

Data flow: The test replays two user/agent pairs, confirms the second response is copyable, truncates copy history to one user turn, then expects the first response to be copied.

Call relations: It tests copy-history rollback behavior used when conversation state is rewound.

Call graph: 1 external calls (assert_eq!).

slash_copy_reports_when_rewind_exceeds_retained_copy_history2051–2074 ↗
async fn slash_copy_reports_when_rewind_exceeds_retained_copy_history()

Purpose: Checks that /copy gives a clear message if a rewind goes beyond retained copy history.

Data flow: The test replays one response, truncates copy history to zero user turns, dispatches /copy, and expects an evicted-history warning.

Call relations: It covers the limit of retained copyable responses.

Call graph: 1 external calls (assert!).

slash_exit_requests_exit2077–2083 ↗
async fn slash_exit_requests_exit()

Purpose: Checks that /exit requests app shutdown.

Data flow: The test dispatches the exit command and expects a shutdown exit event.

Call relations: It mirrors the /quit command test.

Call graph: 1 external calls (assert_matches!).

slash_stop_submits_background_terminal_cleanup2086–2099 ↗
async fn slash_stop_submits_background_terminal_cleanup()

Purpose: Checks that /stop asks the core to clean up background terminals and tells the user it is doing so.

Data flow: The test dispatches /stop, expects a cleanup operation, drains one history cell, and checks it contains the stopping message.

Call relations: It tests a command that both sends a core operation and writes user-facing feedback.

Call graph: 3 external calls (assert!, assert_eq!, assert_matches!).

slash_clear_requests_ui_clear_when_idle2102–2108 ↗
async fn slash_clear_requests_ui_clear_when_idle()

Purpose: Checks that /clear clears the UI when no task is running.

Data flow: The test dispatches /clear and expects a ClearUi app event.

Call relations: It covers the normal clear command path.

Call graph: 1 external calls (assert_matches!).

slash_clear_after_ctrl_c_keeps_stashed_draft_recallable2111–2139 ↗
async fn slash_clear_after_ctrl_c_keeps_stashed_draft_recallable()

Purpose: Checks that text stashed by Ctrl-C remains recallable even after /clear is run.

Data flow: The test submits ok, stashes a draft with Ctrl-C, runs /clear, then uses Up history recall to get the stashed draft and then the earlier message.

Call relations: It connects interrupt/stash behavior, history entries, and clear command behavior.

Call graph: calls 2 internal fn (new, submit_composer_text); 5 external calls (Char, new, new, assert_eq!, assert_matches!).

slash_clear_is_disabled_while_task_running2142–2160 ↗
async fn slash_clear_is_disabled_while_task_running()

Purpose: Checks that /clear refuses to run while a task is in progress.

Data flow: The test marks the bottom pane as running, dispatches /clear, expects one history error cell, and confirms no extra events.

Call relations: It tests the disabled-command guard for clear.

Call graph: 2 external calls (assert!, panic!).

slash_archive_is_disabled_while_task_running2163–2181 ↗
async fn slash_archive_is_disabled_while_task_running()

Purpose: Checks that /archive refuses to run while a task is in progress.

Data flow: The test marks a task as running, dispatches /archive, expects a disabled-command history message, and no follow-up events.

Call relations: It applies the same task-running guard to an irreversible thread action.

Call graph: 2 external calls (assert!, panic!).

slash_memory_drop_reports_stubbed_feature2184–2201 ↗
async fn slash_memory_drop_reports_stubbed_feature()

Purpose: Checks that the memory-drop command reports that memory maintenance is not available in the TUI yet.

Data flow: The test dispatches the command, expects a history cell with the stub message, and confirms no memory operation is sent.

Call relations: It tests a known but currently unsupported command.

Call graph: 2 external calls (assert!, panic!).

slash_mcp_requests_inventory_via_app_server2204–2220 ↗
async fn slash_mcp_requests_inventory_via_app_server()

Purpose: Checks that /mcp asks the app server for a concise MCP inventory. MCP means Model Context Protocol, a way external tools expose capabilities.

Data flow: The test sets a thread id, dispatches /mcp, expects a loading message and a fetch-inventory app event with tools/auth detail, and no core operation.

Call relations: It covers the default MCP inventory command path.

Call graph: calls 1 internal fn (new); 2 external calls (assert!, assert_matches!).

slash_mcp_verbose_requests_full_inventory_via_app_server2223–2239 ↗
async fn slash_mcp_verbose_requests_full_inventory_via_app_server()

Purpose: Checks that /mcp verbose requests the full MCP inventory.

Data flow: The test submits /mcp verbose, expects loading text and a fetch event with full detail for the current thread, and no core operation.

Call relations: It complements the default MCP inventory test with the verbose argument.

Call graph: calls 2 internal fn (new, submit_composer_text); 2 external calls (assert!, assert_matches!).

slash_mcp_invalid_args_show_usage2242–2259 ↗
async fn slash_mcp_invalid_args_show_usage()

Purpose: Checks that invalid /mcp arguments show usage help.

Data flow: The test submits /mcp full, expects a usage message, verifies recall, and confirms no operation is sent.

Call relations: It tests argument validation for the MCP command.

Call graph: calls 1 internal fn (submit_composer_text); 2 external calls (assert!, assert_eq!).

slash_memories_opens_memory_menu2262–2271 ↗
async fn slash_memories_opens_memory_menu()

Purpose: Checks that /memories opens the memory menu when the memory feature is enabled.

Data flow: The test enables the memory feature, dispatches the command, expects a popup titled for memory use, and no app or core events.

Call relations: It tests the UI-only memory menu command.

Call graph: 2 external calls (assert!, assert_matches!).

slash_memory_update_reports_stubbed_feature2274–2291 ↗
async fn slash_memory_update_reports_stubbed_feature()

Purpose: Checks that the memory-update command reports that memory maintenance is not available in the TUI yet.

Data flow: The test dispatches the command, expects the stub history message, and confirms no memory operation is sent.

Call relations: It pairs with the memory-drop stub test.

Call graph: 2 external calls (assert!, panic!).

slash_resume_opens_picker2294–2300 ↗
async fn slash_resume_opens_picker()

Purpose: Checks that /resume opens the saved-session picker.

Data flow: The test dispatches /resume and expects an open-resume-picker app event.

Call relations: It tests the no-argument resume command path.

Call graph: 1 external calls (assert_matches!).

slash_import_opens_claude_code_import_picker2303–2312 ↗
async fn slash_import_opens_claude_code_import_picker()

Purpose: Checks that /import opens the external agent configuration migration flow.

Data flow: The test dispatches /import and expects an open-migration app event.

Call relations: It verifies this slash command is routed to the surrounding app UI.

Call graph: 1 external calls (assert_matches!).

slash_archive_confirmation_requests_current_thread_archive2315–2330 ↗
async fn slash_archive_confirmation_requests_current_thread_archive()

Purpose: Checks that /archive opens a confirmation popup and only archives after the user confirms.

Data flow: The test dispatches /archive, snapshots the popup, navigates to the confirming option, presses Enter, and expects an archive-current-thread event.

Call relations: It covers the safe confirmation flow for archiving.

Call graph: 4 external calls (from, assert!, assert_chatwidget_snapshot!, assert_matches!).

slash_delete_confirmation_requests_current_thread_delete2333–2348 ↗
async fn slash_delete_confirmation_requests_current_thread_delete()

Purpose: Checks that /delete opens a confirmation popup and only deletes after the user confirms.

Data flow: The test dispatches /delete, snapshots the popup, selects the confirming option, presses Enter, and expects a delete-current-thread event.

Call relations: It mirrors the archive confirmation test for the delete action.

Call graph: 4 external calls (from, assert!, assert_chatwidget_snapshot!, assert_matches!).

slash_resume_with_arg_requests_named_session2351–2366 ↗
async fn slash_resume_with_arg_requests_named_session()

Purpose: Checks that /resume with an argument asks to resume a specific session by id or name.

Data flow: The test enters /resume my-saved-thread, submits it, expects a resume-by-id-or-name app event, and confirms no core operation.

Call relations: It complements the picker-opening resume test.

Call graph: 3 external calls (from, new, assert_matches!).

slash_pets_opens_picker2370–2381 ↗
async fn slash_pets_opens_picker()

Purpose: Checks that /pets opens the pet picker when image support is available.

Data flow: The test forces pet image support, dispatches /pets, confirms a popup is active, expects no app event, and snapshots the picker.

Call relations: It uses the pet-support helper to test the happy path.

Call graph: calls 1 internal fn (force_pet_image_support); 3 external calls (assert!, assert_chatwidget_snapshot!, assert_matches!).

slash_pets_with_arg_selects_named_pet2385–2398 ↗
async fn slash_pets_with_arg_selects_named_pet()

Purpose: Checks that /pets chefito selects a named pet directly when pets are supported.

Data flow: The test forces support, submits the command, expects a PetSelected event with chefito, and no core operation.

Call relations: It covers the direct-selection path instead of the picker path.

Call graph: calls 1 internal fn (force_pet_image_support); 3 external calls (from, new, assert_matches!).

slash_pets_disable_disables_pets_even_on_unsupported_terminal2402–2413 ↗
async fn slash_pets_disable_disables_pets_even_on_unsupported_terminal()

Purpose: Checks that /pets disable works even when the terminal cannot show pets.

Data flow: The test forces tmux unsupported state, submits the disable command, expects a PetDisabled event and no extra events.

Call relations: It verifies disabling does not require image support.

Call graph: calls 1 internal fn (force_tmux_pet_image_unsupported); 3 external calls (from, new, assert_matches!).

slash_pet_hide_disables_pets_even_on_unsupported_terminal2417–2428 ↗
async fn slash_pet_hide_disables_pets_even_on_unsupported_terminal()

Purpose: Checks that /pet hide also disables pets on an unsupported terminal.

Data flow: The test forces tmux unsupported state, submits /pet hide, expects a PetDisabled event, and no core operation.

Call relations: It tests an alias-style command path for disabling pets.

Call graph: calls 1 internal fn (force_tmux_pet_image_unsupported); 3 external calls (from, new, assert_matches!).

slash_pets_on_unsupported_terminal_warns_without_picker2432–2447 ↗
async fn slash_pets_on_unsupported_terminal_warns_without_picker()

Purpose: Checks that /pets in tmux shows a warning instead of opening the picker.

Data flow: The test forces tmux unsupported state, dispatches /pets, confirms no popup is active, and checks the history warning mentions tmux and running outside tmux.

Call relations: It tests the tmux unsupported-pets path.

Call graph: calls 1 internal fn (force_tmux_pet_image_unsupported); 1 external calls (assert!).

slash_pets_with_arg_on_unsupported_terminal_warns_without_selection2451–2468 ↗
async fn slash_pets_with_arg_on_unsupported_terminal_warns_without_selection()

Purpose: Checks that selecting a pet by name is blocked on an unsupported terminal and shows a warning.

Data flow: The test forces tmux unsupported state, submits /pets chefito, checks the warning, and confirms no selection or operation event occurs.

Call relations: It complements the unsupported picker test with the direct-selection path.

Call graph: calls 1 internal fn (force_tmux_pet_image_unsupported); 4 external calls (from, new, assert!, assert_matches!).

slash_pets_on_unsupported_terminal_shows_terminal_warning2472–2487 ↗
async fn slash_pets_on_unsupported_terminal_shows_terminal_warning()

Purpose: Checks that unsupported terminals get a general graphics-support warning for /pets.

Data flow: The test forces terminal unsupported state, dispatches /pets, and checks the message mentions unavailable pets and Kitty graphics or Sixel support.

Call relations: It uses the terminal-unsupported helper to test a different warning reason.

Call graph: calls 1 internal fn (force_terminal_pet_image_unsupported); 1 external calls (assert!).

slash_pets_on_old_iterm2_shows_upgrade_warning2491–2506 ↗
async fn slash_pets_on_old_iterm2_shows_upgrade_warning()

Purpose: Checks that old iTerm2 users are told to upgrade before using pets.

Data flow: The test forces old-iTerm2 unsupported state, dispatches /pets, and checks the warning text mentions iTerm2 3.6 or newer.

Call relations: It uses the old-iTerm2 helper to test the version-specific warning.

Call graph: calls 1 internal fn (force_old_iterm2_pet_image_unsupported); 1 external calls (assert!).

slash_fork_requests_current_fork2509–2515 ↗
async fn slash_fork_requests_current_fork()

Purpose: Checks that /fork asks the app to fork the current session.

Data flow: The test dispatches /fork and expects a fork-current-session event.

Call relations: It verifies simple routing from slash command to app event.

Call graph: 1 external calls (assert_matches!).

slash_app_requests_desktop_handoff2518–2531 ↗
async fn slash_app_requests_desktop_handoff()

Purpose: Checks that /app opens the current thread in the desktop app when a thread id exists.

Data flow: The test sets a thread id, dispatches /app, and expects an open-desktop-thread event with that id.

Call relations: It tests desktop handoff for an active thread.

Call graph: calls 1 internal fn (new); 1 external calls (assert_matches!).

slash_app_without_thread_id_shows_starting_error2534–2545 ↗
async fn slash_app_without_thread_id_shows_starting_error()

Purpose: Checks that /app explains the session is not ready when there is no thread id yet.

Data flow: The test dispatches /app without a thread id, drains one history cell, and snapshots the error message.

Call relations: It complements the successful desktop handoff test.

Call graph: 2 external calls (assert_chatwidget_snapshot!, assert_eq!).

slash_rollout_displays_current_path2548–2562 ↗
async fn slash_rollout_displays_current_path()

Purpose: Checks that /rollout shows the path to the current rollout log when one is known.

Data flow: The test sets a rollout path, dispatches /rollout, drains one history cell, and checks that the path is displayed.

Call relations: It tests the informational command path with available data.

Call graph: 3 external calls (from, assert!, assert_eq!).

slash_rollout_handles_missing_path2565–2581 ↗
async fn slash_rollout_handles_missing_path()

Purpose: Checks that /rollout gives a helpful message when no rollout path is available.

Data flow: The test dispatches /rollout without setting a path and expects one history message saying it is not available.

Call relations: It covers the missing-data path for the rollout command.

Call graph: 2 external calls (assert!, assert_eq!).

fast_slash_command_updates_and_persists_local_service_tier2584–2614 ↗
async fn fast_slash_command_updates_and_persists_local_service_tier()

Purpose: Checks that the Fast service-tier command updates the active turn context and asks the app to persist the choice.

Data flow: The test enables fast mode, dispatches the Fast tier command, collects app events, and expects both an override event and a persistence event, with no core operation.

Call relations: It uses fast_tier_command to exercise the same service-tier dispatch path that /fast would use.

Call graph: calls 1 internal fn (fast_tier_command); 3 external calls (assert!, assert_matches!, from_fn).

fast_keybinding_toggle_uses_same_events_as_fast_slash_command2617–2647 ↗
async fn fast_keybinding_toggle_uses_same_events_as_fast_slash_command()

Purpose: Checks that toggling fast mode from the UI keybinding emits the same kinds of events as the slash command.

Data flow: The test enables fast mode, calls the UI toggle, collects events, and expects the fast service-tier override and persistence events.

Call relations: It compares keybinding behavior with slash-command behavior.

Call graph: 3 external calls (assert!, assert_matches!, from_fn).

fast_keybinding_toggle_requires_feature_and_idle_surface2650–2662 ↗
async fn fast_keybinding_toggle_requires_feature_and_idle_surface()

Purpose: Checks that the fast-mode keybinding is only available when the feature is enabled and the chat surface is idle.

Data flow: The test starts with the feature disabled, then enables it, then marks a task running, checking the keybinding availability at each step.

Call relations: It tests the guard used before the UI lets a fast-mode keypress act.

Call graph: 1 external calls (assert!).

user_turn_carries_service_tier_after_fast_toggle2665–2687 ↗
async fn user_turn_carries_service_tier_after_fast_toggle()

Purpose: Checks that after Fast mode is selected, the next user turn carries the Fast service-tier override.

Data flow: The test enables fast mode and auth, dispatches the Fast command, sends hello, and expects the submitted user-turn operation to include the Fast tier.

Call relations: It verifies service-tier selection affects actual backend-bound user turns.

Call graph: calls 2 internal fn (new, fast_tier_command); 4 external calls (from, new, panic!, from_fn).

model_switch_recomputes_catalog_default_service_tier2690–2728 ↗
async fn model_switch_recomputes_catalog_default_service_tier()

Purpose: Checks that switching models recomputes the effective default service tier from the model catalog.

Data flow: The test edits the catalog so one model defaults to Fast, switches models, checks current tier values, sends a message, and expects the default service-tier override in the user turn.

Call relations: It tests the interaction between model selection, catalog defaults, and submitted turn context.

Call graph: calls 2 internal fn (new, new); 5 external calls (from, new, assert_eq!, panic!, new).

queued_fast_slash_applies_before_next_queued_message2731–2770 ↗
async fn queued_fast_slash_applies_before_next_queued_message()

Purpose: Checks that a queued /fast command changes service tier before the following queued message is submitted.

Data flow: The test queues /fast and then a message during an active turn, completes the turn, confirms the fast override event, and expects the message operation to carry the Fast tier.

Call relations: It verifies queued command ordering matters and is preserved.

Call graph: calls 3 internal fn (new, complete_turn_with_message, queue_composer_text_with_tab); 4 external calls (assert!, assert_eq!, panic!, from_fn).

user_turn_sends_standard_override_after_fast_is_turned_off2773–2816 ↗
async fn user_turn_sends_standard_override_after_fast_is_turned_off()

Purpose: Checks that toggling Fast mode off sends the standard service-tier override and uses it on the next user turn.

Data flow: The test turns Fast on, drains events, dispatches the same Fast command again to turn it off, expects default-tier override and persistence events, then submits a message and checks its tier.

Call relations: It covers the off-toggle side of the same service-tier command path.

Call graph: calls 2 internal fn (new, fast_tier_command); 5 external calls (from, new, assert!, panic!, from_fn).

raw_slash_command_toggles_and_accepts_on_off_args2819–2848 ↗
async fn raw_slash_command_toggles_and_accepts_on_off_args()

Purpose: Checks that /raw toggles raw output mode and that /raw off and /raw on explicitly set it.

Data flow: The test dispatches the raw command three ways, checking the internal raw-output flag and emitted mode-changed events each time.

Call relations: It tests both toggle and explicit-argument behavior for raw mode.

Call graph: 3 external calls (new, assert!, from_fn).

raw_slash_command_reports_usage_for_invalid_arg2851–2867 ↗
async fn raw_slash_command_reports_usage_for_invalid_arg()

Purpose: Checks that /raw with an invalid argument shows usage help and does not change raw mode.

Data flow: The test dispatches /raw status, confirms raw mode remains off, and checks the history output contains Usage: /raw [on|off].

Call relations: It complements the successful raw-command argument test.

Call graph: 2 external calls (new, assert!).

compact_queues_user_messages_snapshot2870–2900 ↗
async fn compact_queues_user_messages_snapshot()

Purpose: Checks the rendered UI when a user message is queued because a compact turn cannot be steered. This protects the visual feedback for a subtle queueing case.

Data flow: The test starts a turn, submits a user message, simulates an error saying compact turns are not steerable, renders the widget in a virtual terminal, and snapshots the screen.

Call relations: It ties compact-turn queueing behavior to the final terminal display.

Call graph: calls 4 internal fn (new, from, with_options, new); 2 external calls (new, assert_chatwidget_snapshot!).

tui/src/chatwidget/tests/status_command_tests.rssource ↗
testtest run

The /status command is meant to give the user a quick snapshot of the current chat setup: model choice, reasoning settings, instruction files, and, for ChatGPT-authenticated sessions, rate-limit information. This test file protects that user experience. Without these tests, the terminal could show stale details, delay status output while waiting for a network refresh, or update the wrong status message when more than one refresh is happening.

Each test builds a manual chat widget, sends it the Status slash command, and then watches the app events the widget emits. These events are like messages dropped into an inbox: one event inserts visible text into chat history, while another may ask the wider app to refresh rate-limit data. The tests make sure the visible status cell is inserted immediately, before any refresh work completes.

The file pays special attention to ChatGPT authentication because that is when rate-limit refreshes are requested. It also checks that refreshed limits are cached for later /status runs, that non-ChatGPT sessions do not ask for limit refreshes, that default model reasoning settings are shown correctly, and that instruction source paths from the current thread/session appear instead of stale placeholder text. The final test covers overlapping refreshes, making sure each refresh request only affects the matching status output.

Function details6
status_command_renders_immediately_and_refreshes_rate_limits_for_chatgpt_auth5–28 ↗
async fn status_command_renders_immediately_and_refreshes_rate_limits_for_chatgpt_auth()

Purpose: This test checks the first and most important behavior for ChatGPT-authenticated users: /status should show something immediately, then ask for rate-limit data afterward. It also makes sure the displayed history does not contain a temporary phrase like “refreshing limits,” which would be confusing once saved in the terminal output.

Data flow: The test starts with a fresh chat widget and marks it as using ChatGPT authentication. It sends the /status command, reads the next app event, and turns the inserted status cell into plain text for checking. Then it reads the following app event and verifies that it is a rate-limit refresh request with the first request id, 0. If the events arrive in the wrong order or contain the wrong text, the test fails.

Call relations: This test drives the chat widget as a user would by dispatching SlashCommand::Status. It expects the widget to hand back an InsertHistoryCell event first, then a RefreshRateLimits event. The assertions and panic paths are only there to clearly fail the test if the chat widget breaks that sequence.

Call graph: 3 external calls (assert!, panic!, assert_eq!).

status_command_refresh_updates_cached_limits_for_future_status_outputs31–63 ↗
async fn status_command_refresh_updates_cached_limits_for_future_status_outputs()

Purpose: This test checks that refreshed rate-limit information is remembered and used the next time the user runs /status. It protects against a bug where the app fetches fresh data but keeps showing old or empty limit information afterward.

Data flow: The test creates a ChatGPT-authenticated chat widget and runs /status, consuming the immediate status output and capturing the refresh request id. It then feeds the widget a fake rate-limit snapshot showing 92% used, finishes the matching refresh, and clears any extra history updates. When it runs /status again, the new rendered text should say 8% left, proving the cached limit data was updated and reused.

Call relations: This test follows the full refresh story: /status asks for a refresh, the widget receives a rate-limit snapshot through on_rate_limit_snapshot, and finish_status_rate_limit_refresh marks the request as complete. A later /status call should then render from that stored data instead of starting from nothing.

Call graph: 2 external calls (assert!, panic!).

status_command_renders_immediately_without_rate_limit_refresh66–77 ↗
async fn status_command_renders_immediately_without_rate_limit_refresh()

Purpose: This test confirms that ordinary, non-ChatGPT sessions still get immediate /status output but do not ask for ChatGPT rate-limit refreshes. That matters because unnecessary refresh requests would waste work or call services that are not relevant to the current session.

Data flow: The test creates a chat widget without enabling ChatGPT authentication. After dispatching /status, it checks that the first event inserts a history cell. It then drains any remaining available events and confirms none of them are RefreshRateLimits events.

Call relations: This is the counterpart to the ChatGPT-authenticated tests. It sends the same SlashCommand::Status, but because no ChatGPT auth is configured, the widget should stop after producing visible status text and should not hand off any rate-limit refresh request.

Call graph: 2 external calls (assert!, assert_matches!).

status_command_uses_catalog_default_reasoning_when_config_empty80–96 ↗
async fn status_command_uses_catalog_default_reasoning_when_config_empty()

Purpose: This test checks that /status can still describe the model's reasoning setting when the user's config does not explicitly set one. It ensures the app falls back to the model catalog default instead of showing a blank or misleading value.

Data flow: The test creates a chat widget with a specific model override, gpt-5.4, then clears the configured reasoning effort. It runs /status, reads the inserted status cell, and converts it to text. The expected output includes the model name plus its catalog default reasoning and summary settings.

Call relations: The test exercises the status rendering path for model configuration. It does not need a rate-limit refresh; it only verifies that when dispatch_command builds the status output, it consults the model catalog default if the config field is empty.

Call graph: 2 external calls (assert!, panic!).

status_command_renders_instruction_sources_from_thread_session99–119 ↗
async fn status_command_renders_instruction_sources_from_thread_session()

Purpose: This test checks that /status displays instruction files supplied by the current thread/session. These instruction files, such as AGENTS.md, tell the assistant how to behave, so users need /status to show where those instructions came from.

Data flow: The test creates a chat widget and sets its instruction source paths to include an AGENTS.md file under the current working directory. After dispatching /status, it reads the inserted history cell as text. The text must mention Agents.md and must not show the stale placeholder form Agents.md <none>.

Call relations: This test feeds session-level instruction source data directly into the chat widget before running the status command. The status renderer should use that fresh session data when producing the InsertHistoryCell event, rather than falling back to an older “none found” display.

Call graph: 3 external calls (assert!, panic!, vec!).

status_command_overlapping_refreshes_update_matching_cells_only122–164 ↗
async fn status_command_overlapping_refreshes_update_matching_cells_only()

Purpose: This test checks a timing-sensitive case: the user runs /status twice before the first rate-limit refresh finishes. It makes sure each refresh request has its own identity, so finishing one refresh does not accidentally update or clear the other status output.

Data flow: The test creates a ChatGPT-authenticated chat widget, runs /status, consumes the first visible output, and records the first refresh request id. It then runs /status again, checks the second visible output, and records a second request id. The ids must be different. When the first refresh is finished, one pending status output should remain. After a fake snapshot is delivered and the second refresh is finished, no pending status outputs should remain.

Call relations: This test stresses the coordination between dispatch_command, rate-limit refresh requests, cached snapshots, and finish_status_rate_limit_refresh. It shows that the widget tracks multiple in-flight status refreshes separately, like numbered claim tickets, and only completes the matching ticket when a refresh finishes.

Call graph: 4 external calls (assert!, assert_ne!, panic!, assert_eq!).

tui/src/chatwidget/tests/usage.rssource ↗
testtest run

This is a test file for the text-based chat user interface. It checks what happens when a user opens the /usage command and when the app offers “rate-limit reset credits,” which are credits that can reset usage limits. Without these tests, small changes could easily break important behavior: the wrong menu item might open, a reset might be offered to the wrong kind of account, a popup might disappear while work is still running, or the screen might show stale credit counts.

The tests build a fake ChatWidget, set up account and plan information, then drive it like a person would: opening /usage, pressing arrow keys, pressing Enter, pressing Escape, or pressing Ctrl-C. They also simulate server replies, such as “2 reset credits are available,” “no credits are available,” or “the reset succeeded.” Some tests use snapshots, meaning they compare the rendered popup text against a saved expected version so visual wording and layout changes are caught.

A recurring idea is request identity. The widget starts a request and later receives a result with a request id. These tests make sure old or invalid requests do not update the screen after account changes or after a newer flow begins. The helper functions at the bottom keep the tests readable by wrapping common actions like dismissing a popup or building a fake reset response.

Function details30
usage_command_opens_menu_when_reset_is_available_snapshot10–27 ↗
async fn usage_command_opens_menu_when_reset_is_available_snapshot()

Purpose: Checks that /usage opens a menu showing reset credits when the account has available credits. It also verifies that pressing Enter on the default menu choice opens token activity.

Data flow: The test creates a chat widget, marks it as a ChatGPT-authenticated account, and feeds it a startup reset check result saying 2 credits are available. It opens the /usage menu, compares the rendered popup to a saved snapshot, then sends an Enter key. The expected output is an app event asking to open token activity.

Call relations: The async test runner calls this test. Inside the test, the chat widget’s startup check and command dispatch logic are exercised, and the assertion helpers confirm both the displayed menu and the event sent through the test receiver.

Call graph: 4 external calls (new, assert!, assert_chatwidget_snapshot!, assert_matches!).

usage_command_can_recheck_reset_availability_after_cached_zero_snapshot30–48 ↗
async fn usage_command_can_recheck_reset_availability_after_cached_zero_snapshot()

Purpose: Checks that a previous “zero reset credits” result does not permanently hide the option to check again. This matters because credit availability can change later.

Data flow: The test starts with an authenticated chat widget and records a startup check result of 0 available credits. It opens /usage, snapshots the menu, moves down to the reset-related option, and presses Enter. The expected result is an event that opens the rate-limit reset credit flow so the app can check again.

Call relations: The async test runner invokes this case. It drives the widget through command dispatch and keyboard input, then observes the outgoing app event through the receiver.

Call graph: 4 external calls (new, assert!, assert_chatwidget_snapshot!, assert_matches!).

usage_command_can_check_reset_availability_before_startup_refresh_finishes_snapshot51–65 ↗
async fn usage_command_can_check_reset_availability_before_startup_refresh_finishes_snapshot()

Purpose: Checks that the user can open the reset-credit check even while the automatic startup availability check is still unfinished. The UI should not get stuck waiting.

Data flow: The test creates an authenticated chat widget and starts, but does not finish, the startup reset check. It opens /usage, snapshots the menu, selects the reset availability option, and presses Enter. The output is an event to open the rate-limit reset credits flow.

Call relations: The async test runner runs this scenario. The test uses the same keyboard path a user would use and confirms that unfinished background work does not block the manual reset flow.

Call graph: 3 external calls (new, assert_chatwidget_snapshot!, assert_matches!).

usage_command_disables_reset_for_workspace_accounts68–78 ↗
async fn usage_command_disables_reset_for_workspace_accounts()

Purpose: Checks that workspace or business accounts do not get the reset-credit action in the /usage menu. This prevents showing a feature that should only apply to eligible personal accounts.

Data flow: The test builds an authenticated chat widget, marks its plan type as Business, opens /usage, then presses Down and Enter. Instead of opening reset credits, the resulting event is token activity, showing the reset entry is not available as a selectable action.

Call relations: The async test runner calls this test. It relies on the widget’s account-plan logic and reads the emitted app event to confirm the menu behaves differently for workspace accounts.

Call graph: 2 external calls (new, assert_matches!).

usage_menu_rate_limit_reset_entry_opens_reset_flow81–95 ↗
async fn usage_menu_rate_limit_reset_entry_opens_reset_flow()

Purpose: Checks the happy path where the /usage menu contains a reset-credit entry and selecting it opens the reset flow.

Data flow: The test creates an authenticated chat widget, completes a reset availability check with 2 credits, opens /usage, moves to the reset entry, and presses Enter. The receiver should get an event requesting the rate-limit reset credits screen.

Call relations: The async test runner runs this case. It connects the menu rendering state to the event layer by verifying that a user selection turns into the correct app event.

Call graph: 3 external calls (new, assert!, assert_matches!).

rate_limit_reset_popup_states_snapshot98–173 ↗
async fn rate_limit_reset_popup_states_snapshot()

Purpose: Captures the main visual states of the rate-limit reset popup in one snapshot. It protects the wording and transitions for loading, success, empty, error, retry, and completed states.

Data flow: The test walks a chat widget through many simulated server outcomes: loading credits, finding credits, finding none, load failure, consuming a credit, consume failure, nothing to reset, no credit, success, and post-success refresh. After each important step, it records the popup text into a list. The final output is a combined snapshot of all recorded states.

Call relations: The async test runner calls this broad snapshot test. It uses record_popup to collect rendered screens and dismiss_popup to move between popup states, while the widget methods under test update the bottom pane.

Call graph: calls 2 internal fn (dismiss_popup, record_popup); 3 external calls (new, assert!, assert_chatwidget_snapshot!).

rate_limit_reset_confirmation_selects_cancel_by_default176–188 ↗
async fn rate_limit_reset_confirmation_selects_cancel_by_default()

Purpose: Checks that the confirmation popup defaults to Cancel rather than immediately using a reset credit. This is a safety feature because spending a reset should require a deliberate choice.

Data flow: The test opens a loading popup, finishes it with 1 available credit, then presses Enter without moving the selection. The popup closes and no app event is emitted, meaning Cancel was selected.

Call relations: The async test runner invokes this test. It exercises the popup’s default selection behavior and checks both the visible state and the absence of outgoing events.

Call graph: 2 external calls (new, assert!).

rate_limit_reset_confirmation_can_use_reset191–207 ↗
async fn rate_limit_reset_confirmation_can_use_reset()

Purpose: Checks that a user can intentionally choose to use a reset credit from the confirmation popup. It also verifies that the request includes a valid unique id for safe retries.

Data flow: The test shows the reset confirmation with 1 available credit, sends an Up key to move from Cancel to the reset action, then presses Enter. The output is a ConsumeRateLimitResetCredit event containing an idempotency key, which is a unique value used so retrying the same action is not counted twice. The test confirms that key is a valid UUID string.

Call relations: The async test runner calls this scenario. The widget turns keyboard navigation into an app event, and the assertion checks the event payload.

Call graph: 3 external calls (new, assert!, assert_matches!).

rate_limit_reset_retry_reuses_idempotency_key210–226 ↗
async fn rate_limit_reset_retry_reuses_idempotency_key()

Purpose: Checks that retrying a failed reset redemption uses the same idempotency key. This prevents the app from accidentally spending more than one credit for one intended action.

Data flow: The test starts a consuming popup and finishes the consume request with an error using the key stable-redeem-id. It then presses Enter to retry. The output event asks to consume a reset credit again, and the idempotency key is the same one.

Call relations: The async test runner invokes this test. It drives the widget through an error state and verifies the retry event preserves the original safety key.

Call graph: 3 external calls (new, assert!, assert_matches!).

no_credit_outcome_allows_reset_availability_recheck229–251 ↗
async fn no_credit_outcome_allows_reset_availability_recheck()

Purpose: Checks that after a consume attempt reports “NoCredit,” the user can still reopen /usage and ask the app to check reset availability again. This avoids trapping the UI in an outdated state.

Data flow: The test begins with a startup hint saying 1 credit is available, then simulates a consume result of NoCredit. It dismisses the popup, opens /usage, selects the reset option, and presses Enter. The expected output is an event to open the reset credits flow.

Call relations: The async test runner runs this case. It uses dismiss_popup to close the error state and then verifies the normal /usage menu path still reaches the reset check.

Call graph: calls 1 internal fn (dismiss_popup); 3 external calls (new, assert!, assert_matches!).

rate_limit_reset_redemption_cannot_be_dismissed_while_in_flight254–277 ↗
async fn rate_limit_reset_redemption_cannot_be_dismissed_while_in_flight()

Purpose: Checks that a reset redemption popup cannot be dismissed while important work is in progress. This prevents the user from losing sight of an active operation.

Data flow: The test starts a consuming popup, tries to dismiss it, and confirms the popup still says the reset is being used. After a successful consume result, it tries to dismiss again and confirms the popup still shows refreshing. Only after the post-consume refresh finishes can the popup be dismissed completely.

Call relations: The async test runner calls this test. It uses dismiss_popup at different stages to prove that the widget protects in-flight consume and refresh states from accidental Escape-key dismissal.

Call graph: calls 1 internal fn (dismiss_popup); 1 external calls (assert!).

rate_limit_reset_redemption_allows_ctrl_c_to_quit_while_in_flight280–288 ↗
async fn rate_limit_reset_redemption_allows_ctrl_c_to_quit_while_in_flight()

Purpose: Checks that Ctrl-C can still quit the app even while a reset redemption is running. The popup stays visible, but the quit event must still be sent.

Data flow: The test shows the consuming popup, sends a Ctrl-C key event, and reads the receiver. The output is an Exit event with shutdown-first behavior, while the rendered popup still says the reset is being used.

Call relations: The async test runner invokes this test. It verifies that the popup blocks normal dismissal but does not block the global quit shortcut.

Call graph: 4 external calls (Char, new, assert!, assert_matches!).

already_redeemed_is_an_idempotent_success291–309 ↗
async fn already_redeemed_is_an_idempotent_success()

Purpose: Checks that an “AlreadyRedeemed” server outcome is treated as success. This is important for retries: if the first response was lost but the server did use the credit, the app should not show failure.

Data flow: The test starts a consuming popup, finishes the consume request with AlreadyRedeemed, then finishes the follow-up credit refresh with 0 credits left. The rendered popup says usage was reset and shows 0 resets remaining.

Call relations: The async test runner runs this case. It exercises the widget’s idempotent success path, where a repeated request is accepted as completing the same original action.

Call graph: 1 external calls (assert!).

failed_post_consume_refresh_does_not_keep_stale_reset_count312–338 ↗
async fn failed_post_consume_refresh_does_not_keep_stale_reset_count()

Purpose: Checks that if the reset succeeds but the follow-up credit-count refresh fails, the UI does not keep showing an old count. Stale counts could mislead the user.

Data flow: The test first records a startup availability count of 2. It then simulates a successful reset redemption, but the refresh that should update the remaining count fails. After dismissing the popup and reopening /usage, the menu asks the user to check availability instead of claiming 2 credits are still available.

Call relations: The async test runner invokes this scenario. It uses dismiss_popup to leave the failure popup and then checks the next /usage render for safe, non-stale wording.

Call graph: calls 1 internal fn (dismiss_popup); 1 external calls (assert!).

account_change_invalidates_pending_reset_requests341–356 ↗
async fn account_change_invalidates_pending_reset_requests()

Purpose: Checks that changing account state cancels pending reset-credit requests. This prevents results from an old account from appearing after the user signs out or switches accounts.

Data flow: The test shows a loading popup and stores its request id. It then updates the account state to no ChatGPT account and no backend authentication. When the old credit refresh result arrives, the widget rejects it and the bottom pane has no active popup.

Call relations: The async test runner calls this test. It verifies that account updates invalidate earlier request ids before their results can change the UI.

Call graph: 1 external calls (assert!).

clearing_pending_reset_hint_preserves_in_flight_redemption359–378 ↗
async fn clearing_pending_reset_hint_preserves_in_flight_redemption()

Purpose: Checks that clearing a startup hint does not cancel a separate reset redemption already in progress. These are related features, but their request state must stay separate.

Data flow: The test starts a consuming popup, then starts and completes a startup hint request with available credits. It clears the pending hint and confirms the hint is gone. It then finishes the original consume request successfully, proving the redemption was preserved.

Call relations: The async test runner runs this case. It separates hint cleanup from the consume flow and uses the consume finishing path to prove the in-flight redemption still belongs to the widget.

Call graph: 1 external calls (assert!).

rate_limit_reset_load_result_updates_popup_beneath_overlay381–400 ↗
async fn rate_limit_reset_load_result_updates_popup_beneath_overlay()

Purpose: Checks that a reset-credit load result updates its popup even if another overlay is currently covering it. When the overlay closes, the user should see the latest state, not the old loading state.

Data flow: The test starts a loading popup, then shows a test overlay on top of it. It finishes the credit refresh with 2 available credits and confirms the active view is still the overlay. After pressing Escape to close the overlay, the rendered popup underneath shows the updated available-credit message.

Call relations: The async test runner invokes this test. It calls show_usage_test_overlay to cover the popup, then verifies the widget can update a hidden underlying view without stealing focus.

Call graph: calls 1 internal fn (show_usage_test_overlay); 3 external calls (new, assert!, assert_eq!).

rate_limit_reset_success_updates_popup_beneath_overlay403–428 ↗
async fn rate_limit_reset_success_updates_popup_beneath_overlay()

Purpose: Checks that a successful reset result and its follow-up refresh update a covered popup. This keeps the hidden popup accurate until the user closes the overlay.

Data flow: The test starts a consuming popup, places a test overlay above it, completes a successful reset, and refreshes the remaining credits to 1. The active view remains the overlay. After Escape closes the overlay, the popup underneath says the usage reset succeeded and 1 reset remains.

Call relations: The async test runner calls this case. It uses show_usage_test_overlay to simulate another UI layer and then checks that background popup state still advances correctly.

Call graph: calls 1 internal fn (show_usage_test_overlay); 3 external calls (new, assert!, assert_eq!).

account_change_dismisses_reset_popup_beneath_overlay431–448 ↗
async fn account_change_dismisses_reset_popup_beneath_overlay()

Purpose: Checks that an account change removes a reset popup even when it is hidden under another overlay. This prevents account-specific information from reappearing after the account is no longer valid.

Data flow: The test shows a reset loading popup, covers it with a test overlay, then updates the account state to signed out or unauthenticated. The overlay remains active. When Escape closes the overlay, there is no reset popup underneath.

Call relations: The async test runner invokes this test. It uses show_usage_test_overlay to cover the bottom pane and confirms account-state cleanup reaches hidden popup layers too.

Call graph: calls 1 internal fn (show_usage_test_overlay); 3 external calls (new, assert!, assert_eq!).

startup_check_shows_available_reset_hint_snapshot451–467 ↗
async fn startup_check_shows_available_reset_hint_snapshot()

Purpose: Checks that the startup availability check creates a visible hint when reset credits are available. The snapshot protects the hint’s wording and formatting.

Data flow: The test creates an authenticated chat widget, starts the startup reset check, and finishes it with 2 available credits. It reads the pending hint’s display lines, turns them into one string, and compares that string to a saved snapshot.

Call relations: The async test runner runs this case. It exercises the startup hint path and the snapshot assertion checks what the user would see.

Call graph: 2 external calls (assert!, assert_chatwidget_snapshot!).

startup_reset_hint_waits_for_active_output_snapshot470–498 ↗
async fn startup_reset_hint_waits_for_active_output_snapshot()

Purpose: Checks that a startup reset hint waits if the transcript is currently showing active output, such as a running tool message. This prevents the hint from interrupting ongoing output.

Data flow: The test starts a reset availability check, then creates an active transcript cell containing active tool. When the check finishes with 2 credits, the hint is attached to the active output instead of immediately inserting history. The test snapshots the active output, then flushes the active cell and confirms history insertion and pending usage commit events are sent.

Call relations: The async test runner calls this test. It combines transcript state, pending usage output, and the app event receiver to ensure the hint is deferred until the active cell is flushed.

Call graph: calls 1 internal fn (new); 5 external calls (new, assert!, assert_chatwidget_snapshot!, assert_matches!, vec!).

opening_rate_limit_reset_flow_invalidates_in_flight_startup_hint501–513 ↗
async fn opening_rate_limit_reset_flow_invalidates_in_flight_startup_hint()

Purpose: Checks that manually opening the reset flow cancels a startup hint request that is still in flight. The manual flow should take priority over an older background check.

Data flow: The test starts a startup hint request, then opens the reset loading popup. When the old startup hint result arrives with 2 credits, the widget rejects it and no pending hint remains.

Call relations: The async test runner invokes this scenario. It verifies that starting the full reset flow invalidates older startup-check request ids.

Call graph: 1 external calls (assert!).

starting_rate_limit_reset_redemption_clears_deferred_startup_hint516–529 ↗
async fn starting_rate_limit_reset_redemption_clears_deferred_startup_hint()

Purpose: Checks that beginning an actual reset redemption clears any deferred startup hint. Once the user is using a reset, the old reminder should disappear.

Data flow: The test completes a startup check with 2 credits and confirms a pending hint exists. It then shows the consuming popup for a reset redemption. The pending hint becomes empty.

Call relations: The async test runner runs this case. It connects the hint system to the redemption flow and confirms the redemption flow cleans up obsolete hint state.

Call graph: 1 external calls (assert!).

startup_check_omits_reset_hint_when_none_are_available532–542 ↗
async fn startup_check_omits_reset_hint_when_none_are_available()

Purpose: Checks that startup does not show a reset hint when the account has no reset credits. This avoids distracting the user with an unusable suggestion.

Data flow: The test starts a startup reset check and finishes it with 0 available credits. The widget accepts the result, but there is no pending reset hint afterward.

Call relations: The async test runner calls this test. It exercises the startup hint filter that suppresses hints when the available count is zero.

Call graph: 1 external calls (assert!).

startup_check_omits_reset_hint_for_workspace_accounts545–557 ↗
async fn startup_check_omits_reset_hint_for_workspace_accounts()

Purpose: Checks that workspace or business accounts do not receive startup reset hints, even if the server says credits are available. This keeps account-type rules consistent across startup and the /usage menu.

Data flow: The test authenticates the chat widget, marks the plan as Business, starts the startup reset check, and finishes it with 2 available credits. No pending hint is created, and the cached available reset-credit count remains empty.

Call relations: The async test runner invokes this scenario. It verifies that the same eligibility rule used by the menu also applies to background startup hints.

Call graph: 2 external calls (assert!, assert_eq!).

consume_response559–563 ↗
fn consume_response(
    outcome: ConsumeAccountRateLimitResetCreditOutcome,
) -> ConsumeAccountRateLimitResetCreditResponse

Purpose: Builds a small fake server response for a reset-credit consume attempt. Tests use it so they can focus on the outcome they want to simulate.

Data flow: The input is a consume outcome, such as Reset, NoCredit, NothingToReset, or AlreadyRedeemed. The function wraps that outcome in a ConsumeAccountRateLimitResetCreditResponse object and returns it. It does not change any shared state.

Call relations: finish_reset_consume_outcome calls this helper whenever a test needs to feed a consume result into the chat widget.

Call graph: called by 1 (finish_reset_consume_outcome).

finish_reset_consume_outcome565–576 ↗
fn finish_reset_consume_outcome(
    chat: &mut ChatWidget,
    request_id: u64,
    idempotency_key: &str,
    outcome: ConsumeAccountRateLimitResetCreditOutcome,
) -> bool

Purpose: Finishes a reset-credit consume request with a chosen successful server outcome. It keeps tests shorter by hiding the response-wrapping details.

Data flow: The inputs are the chat widget, the request id, the idempotency key, and the desired outcome. The function converts the key to an owned string, wraps the outcome with consume_response, and passes the successful result into the widget’s finish_rate_limit_reset_consume method. It returns the boolean result from the widget, which says whether the finish was accepted as active and relevant.

Call relations: Several reset-related tests use this helper when they need to simulate a specific consume outcome. It delegates response construction to consume_response and then hands the result to the widget’s consume-finishing logic.

Call graph: calls 1 internal fn (consume_response); 1 external calls (finish_rate_limit_reset_consume).

record_popup578–580 ↗
fn record_popup(chat: &ChatWidget, states: &mut Vec<String>)

Purpose: Adds the current bottom popup rendering to a list of recorded states. It is used to build one combined snapshot of many popup screens.

Data flow: The inputs are a chat widget and a mutable list of strings. The function renders the bottom popup at a fixed width of 80 columns and pushes that text into the list. The list gains one new screen capture.

Call relations: rate_limit_reset_popup_states_snapshot calls this helper after each important popup transition so the final snapshot can show the whole sequence.

Call graph: called by 1 (rate_limit_reset_popup_states_snapshot).

dismiss_popup582–584 ↗
fn dismiss_popup(chat: &mut ChatWidget)

Purpose: Simulates the user pressing Escape to dismiss the current popup or modal. It gives tests one readable way to close UI layers.

Data flow: The input is a mutable chat widget. The function creates an Escape key event with no modifiers and sends it to the widget’s key handler. The widget may close the popup, ignore the key if dismissal is blocked, or update focus depending on its current state.

Call relations: Tests call this helper when they need to leave a popup state, including the popup-state snapshot test, the no-credit recheck test, the in-flight redemption dismissal test, and the stale-count test.

Call graph: called by 4 (failed_post_consume_refresh_does_not_keep_stale_reset_count, no_credit_outcome_allows_reset_availability_recheck, rate_limit_reset_popup_states_snapshot, rate_limit_reset_redemption_cannot_be_dismissed_while_in_flight); 2 external calls (new, handle_key_event).

show_usage_test_overlay586–597 ↗
fn show_usage_test_overlay(chat: &mut ChatWidget)

Purpose: Places a simple test overlay above the current bottom pane content. Tests use it to prove that hidden reset popups still update correctly underneath another view.

Data flow: The input is a mutable chat widget. The function asks the bottom pane to show a selection view with a fixed test id, a title, and one Close item that dismisses the overlay when selected. The visible active view becomes this covering overlay.

Call relations: Overlay-related tests call this helper before completing reset-load, reset-success, or account-change actions. It creates the cover layer so those tests can check what happens to the reset popup underneath.

Call graph: called by 3 (account_change_dismisses_reset_popup_beneath_overlay, rate_limit_reset_load_result_updates_popup_beneath_overlay, rate_limit_reset_success_updates_popup_beneath_overlay); 2 external calls (default, vec!).

Chat widget rendering and status surfaces

This set focuses on how chat-widget state is presented through transcript cells, status lines, layout, terminal title, and configuration-error rendering.

tui/src/chatwidget/tests/config_errors_tests.rssource ↗
testtest run

This test protects a small but important user-facing detail: when something goes wrong while saving configuration, the terminal user interface should show a readable error instead of cutting it off or laying it out badly. The test creates a chat widget in a controlled test setup, injects a realistic chained error message about an invalid setting, and then renders the resulting chat history into a fake terminal screen. A fake terminal is used so the test can inspect exactly what a user would have seen, without needing a real terminal window. The screen is deliberately narrow and short, which forces the long message to wrap across lines. Finally, the rendered screen is compared against a saved snapshot. A snapshot is like a reference photo: if the output changes later, the test will show that the visible behavior changed. This matters because error messages are often the only clue a user has when configuration fails, so wrapping, spacing, and wording need to remain understandable.

Function details1
chained_config_error_wraps_in_history_snapshot4–25 ↗
async fn chained_config_error_wraps_in_history_snapshot()

Purpose: This test checks that a long, nested configuration error is shown correctly in the chat history. It is used to catch accidental changes in how the terminal interface wraps and displays this kind of error.

Data flow: The test starts by creating a test chat widget and a receiver for history updates. It adds a long configuration error message to the chat, creates a fake terminal with a fixed width and height, drains the generated history lines, and inserts those lines into the terminal. The final terminal contents are normalized and compared to a stored expected snapshot, so the test either passes with matching output or fails if the displayed text changed.

Call relations: During the test, it builds the fake terminal through new and with_options, then feeds each batch of chat history lines into insert_history_lines so the terminal screen looks like the real interface would. At the end it hands the rendered screen to assert_chatwidget_snapshot!, which performs the snapshot comparison.

Call graph: calls 3 internal fn (with_options, insert_history_lines, new); 2 external calls (assert_chatwidget_snapshot!, new).

tui/src/chatwidget/tests/status_and_layout.rssource ↗
testtest run

The chat widget is the part of the terminal app that shows the conversation, the input box, progress messages, warnings, approvals, limits, and optional visual extras like the ambient pet. This file tests many edge cases around that surface. It checks that token and context usage are shown correctly, rate-limit warnings appear only when useful, status-line items update when model or Git state changes, streaming answers finish cleanly, and very small terminal sizes still render safely. It also tests user-facing prompts, such as asking a workspace owner for credits or a usage-limit increase.

Many tests work by building a ChatWidget in a controlled test setup, sending it fake server events or key presses, then reading the app events and rendered terminal output it produces. Snapshot tests compare full terminal pictures against stored expected output, like taking a photo of the screen and making sure the next run still looks the same. Helper functions near the bottom build fake hook runs, fake goals, or drain specific events so the tests can focus on behavior instead of setup.

Without this file, changes to the chat widget could silently break important details: warnings might repeat forever, prompts might send the wrong request, live hook rows might overwrite command output, or the footer could show stale model, context, or goal information.

Function details131
enable_test_ambient_pet10–15 ↗
fn enable_test_ambient_pet(chat: &mut ChatWidget)

Purpose: Sets up a test-only ambient pet so layout tests can check how the chat widget behaves when a pet image is present. It avoids needing a real terminal image setup.

Data flow: It receives a mutable ChatWidget → marks pet images as supported using the Kitty image protocol and installs a non-animated test pet → the widget now behaves as if a pet is visible.

Call relations: Several ambient-pet tests call this helper before measuring wrap width, drawing position, stream width, or notification behavior.

Call graph: called by 5 (ambient_pet_draw_uses_terminal_screen_area_not_short_inline_viewport, ambient_pet_hides_notification_text_overlay, ambient_pet_reduces_stream_width_and_composer_text_width, ambient_pet_reserves_history_wrap_width, ambient_pet_screen_bottom_anchor_uses_terminal_bottom); 3 external calls (install_test_ambient_pet_for_tests, set_pet_image_support_for_tests, Supported).

token_count_none_resets_context_indicator19–33 ↗
async fn token_count_none_resets_context_indicator()

Purpose: Checks that a token update with no data clears the context usage indicator. This matters because stale context usage would mislead users after usage information disappears.

Data flow: It creates a chat widget → applies a real token count and sees a percentage → applies a missing token count → expects the bottom pane to show no context percentage.

Call relations: The test runner calls this test; it exercises the token-count handling path and verifies the bottom pane state.

Call graph: 1 external calls (assert_eq!).

app_server_cyber_policy_error_renders_dedicated_notice36–51 ↗
async fn app_server_cyber_policy_error_renders_dedicated_notice()

Purpose: Verifies that cybersecurity policy errors show the special, user-friendly notice instead of a generic server message.

Data flow: It feeds a CyberPolicy error into the widget → drains the inserted history cell → checks that the dedicated cybersecurity text is present and the fallback text is absent.

Call relations: The test runner calls this test; it covers the error-rendering path used when the app server classifies a message as cybersecurity-sensitive.

Call graph: 2 external calls (assert!, assert_eq!).

app_server_model_verification_renders_warning54–69 ↗
async fn app_server_model_verification_renders_warning()

Purpose: Checks that model verification warnings are shown with clear safety-check messaging and a helpful link.

Data flow: It sends a Trusted Access for Cyber verification notice → reads the rendered history output → confirms the warning, safety text, product name, and URL appear.

Call relations: The test runner calls this test; it validates how model-verification notifications become transcript notices.

Call graph: 3 external calls (assert!, assert_eq!, vec!).

context_indicator_shows_used_tokens_when_window_unknown72–98 ↗
async fn context_indicator_shows_used_tokens_when_window_unknown()

Purpose: Confirms that when the model's context window size is unknown, the UI falls back to showing raw tokens used instead of a fake percentage.

Data flow: It removes the configured context window → sends token usage with no model window → expects no percent but does expect the used-token count.

Call relations: The test runner calls this test; it exercises token usage display logic in the bottom pane.

Call graph: 2 external calls (assert_eq!, default).

token_usage_update_uses_runtime_context_window101–145 ↗
async fn token_usage_update_uses_runtime_context_window()

Purpose: Ensures runtime token metadata can override the configured context window shown in status output. This prevents the /status display from showing stale configuration values.

Data flow: It sets a config window of 1M but sends runtime info saying 950K → checks the status-line item and /status output → expects 950K, not 1M.

Call relations: The test runner calls this test; it connects token-count handling, status-line values, and status transcript output.

Call graph: 2 external calls (assert!, assert_eq!).

status_line_git_summary_items_render_values148–169 ↗
async fn status_line_git_summary_items_render_values()

Purpose: Checks that pull request and branch-change summaries are formatted correctly in the status line.

Data flow: It installs a fake Git summary with a PR number and diff stats → asks for the relevant status-line values → expects readable text like a PR number and added/deleted lines.

Call relations: The test runner calls this test; it validates the status-line formatting used after Git summary lookup.

Call graph: 1 external calls (assert_eq!).

raw_output_status_line_value_only_shows_when_enabled172–186 ↗
async fn raw_output_status_line_value_only_shows_when_enabled()

Purpose: Verifies that the status line only advertises raw output mode when that mode is actually on.

Data flow: It reads the raw-output status item while disabled → turns raw mode on → reads it again → expects no value before and a label after.

Call relations: The test runner calls this test; it covers the raw-output mode flag and its status-line representation.

Call graph: 1 external calls (assert_eq!).

status_line_branch_changes_render_no_changes189–203 ↗
async fn status_line_branch_changes_render_no_changes()

Purpose: Checks that a Git branch with zero additions and deletions says “No changes” rather than showing awkward numeric output.

Data flow: It provides Git diff stats of zero additions and zero deletions → asks for the branch-changes status text → expects the friendly no-changes label.

Call relations: The test runner calls this test; it validates the status-line branch summary formatter.

Call graph: 1 external calls (assert_eq!).

stale_status_line_git_summary_update_is_ignored206–227 ↗
async fn stale_status_line_git_summary_update_is_ignored()

Purpose: Ensures Git summary results for an old working directory are ignored. This prevents the footer from showing information for the wrong project.

Data flow: It marks one directory as expected → sends a summary for another directory → checks that no summary is stored and pending state is cleared.

Call relations: The test runner calls this test; it exercises the guard inside status-line Git summary updates.

Call graph: 2 external calls (from, assert!).

raw_output_mode_can_change_without_inserting_notice230–250 ↗
async fn raw_output_mode_can_change_without_inserting_notice()

Purpose: Confirms that raw output mode can be changed silently, while the notifying version still adds a transcript notice.

Data flow: It turns raw mode on using the quiet method → sees no history cells → turns it off with notification → sees a message explaining rich rendering is restored.

Call relations: The test runner calls this test; it distinguishes the silent setter from the user-notifying setter.

Call graph: 1 external calls (assert!).

flush_answer_stream_keeps_default_reflow_for_plain_text_tail253–298 ↗
async fn flush_answer_stream_keeps_default_reflow_for_plain_text_tail()

Purpose: Checks that finishing a plain-text streamed answer inserts history normally and does not force a full scrollback reflow.

Data flow: It creates a stream controller with a plain line → flushes the stream → reads app events → expects both a history insertion and a normal consolidation request.

Call relations: The test runner calls this test; it exercises stream finalization for ordinary text.

Call graph: calls 1 internal fn (new); 2 external calls (assert!, assert_eq!).

flush_answer_stream_requests_scrollback_reflow_for_live_table_tail301–355 ↗
async fn flush_answer_stream_requests_scrollback_reflow_for_live_table_tail()

Purpose: Ensures streamed Markdown tables are finalized carefully so the final table layout is canonical. A live table tail should not be inserted too early.

Data flow: It streams a table that is held back as a live tail → flushes → checks events → expects required scrollback reflow and deferred history, with no provisional insert.

Call relations: The test runner calls this test; it protects the streaming table rendering path.

Call graph: calls 1 internal fn (new); 2 external calls (assert!, assert_eq!).

completed_plan_table_tail_skips_provisional_history_insert358–404 ↗
async fn completed_plan_table_tail_skips_provisional_history_insert()

Purpose: Checks that completed plan tables render from the final source, not from a temporary streaming tail.

Data flow: It streams a plan table, marks a plan item complete, and drains history → expects a final ProposedPlanCell with table separators and no temporary stream-plan cell.

Call relations: The test runner calls this test; it covers plan stream finalization and final plan rendering.

Call graph: calls 1 internal fn (new); 2 external calls (new, assert!).

configured_pet_load_is_deferred_until_after_construction408–452 ↗
async fn configured_pet_load_is_deferred_until_after_construction()

Purpose: Verifies that a configured pet is loaded asynchronously after ChatWidget construction, not during construction. This keeps setup from doing blocking or image-dependent work too early.

Data flow: It builds a config with a test pet → constructs the widget → confirms the pet is not immediately enabled → waits for a ConfiguredPetLoaded event with a successful result.

Call relations: The test runner calls this test; it observes the construction path and the later app event emitted by pet loading.

Call graph: calls 3 internal fn (new, new, test_dummy); 8 external calls (new, new, assert!, assert_matches!, write_test_pack, from_secs, timeout, new_with_app_event).

prefetch_rate_limits_is_gated_on_chatgpt_auth_provider455–468 ↗
async fn prefetch_rate_limits_is_gated_on_chatgpt_auth_provider()

Purpose: Checks that rate-limit prefetching only happens when ChatGPT authentication and an OpenAI-auth-requiring provider are both present.

Data flow: It toggles authentication and provider requirements → asks whether prefetching should happen → then calls prefetch and verifies the gate closes.

Call relations: The test runner calls this test; it protects startup/request prefetch behavior from running under the wrong account setup.

Call graph: 1 external calls (assert!).

rate_limit_warnings_emit_thresholds471–500 ↗
async fn rate_limit_warnings_emit_thresholds()

Purpose: Ensures rate-limit warnings are emitted once per limit when crossing important thresholds, such as below 25% or 5% remaining.

Data flow: It feeds changing usage percentages into warning state → collects warning strings → expects one warning for each relevant limit and threshold.

Call relations: The test runner calls this test; it exercises RateLimitWarningState directly.

Call graph: 3 external calls (new, assert_eq!, default).

test_rate_limit_warnings_monthly503–520 ↗
async fn test_rate_limit_warnings_monthly()

Purpose: Checks that a monthly limit window is labeled as monthly in warning text.

Data flow: It sends a 75% used secondary limit with a monthly window → collects warnings → expects a message saying less than 25% of the monthly limit remains.

Call relations: The test runner calls this test; it covers duration labeling inside the warning generator.

Call graph: 3 external calls (new, assert_eq!, default).

rate_limit_duration_labels_only_render_supported_windows523–530 ↗
fn rate_limit_duration_labels_only_render_supported_windows()

Purpose: Verifies which rate-limit window lengths get friendly names like daily or annual. Unsupported lengths should not get misleading labels.

Data flow: It asks for labels for several durations → expects no label for an unsupported two-hour window and labels for supported daily and annual windows.

Call relations: The test runner calls this test; it covers the get_limits_duration helper from the rate-limit module.

Call graph: 1 external calls (assert_eq!).

test_rate_limit_warnings_use_generic_fallback_labels533–552 ↗
async fn test_rate_limit_warnings_use_generic_fallback_labels()

Purpose: Checks that warnings still make sense when the server does not say how long the limit window is.

Data flow: It sends primary and secondary usage without durations → collects warnings → expects generic “usage limit” and “secondary usage limit” labels.

Call relations: The test runner calls this test; it validates fallback wording in RateLimitWarningState.

Call graph: 2 external calls (assert_eq!, default).

test_rate_limit_warnings_use_secondary_fallback_for_unsupported_window555–569 ↗
async fn test_rate_limit_warnings_use_secondary_fallback_for_unsupported_window()

Purpose: Ensures unsupported secondary windows use a safe generic label instead of pretending to be a known duration.

Data flow: It sends a secondary usage window with an unsupported duration → collects warnings → expects “secondary usage limit” wording.

Call relations: The test runner calls this test; it covers fallback behavior for unknown rate-limit durations.

Call graph: 2 external calls (assert_eq!, default).

status_line_uses_secondary_fallback_for_unsupported_window572–594 ↗
async fn status_line_uses_secondary_fallback_for_unsupported_window()

Purpose: Checks status-line text when only an unsupported secondary limit exists.

Data flow: It stores a snapshot with a secondary two-hour window → asks for the weekly-limit status item → expects a generic secondary usage label with percent left.

Call relations: The test runner calls this test; it validates status-line rate-limit fallback text.

Call graph: 1 external calls (assert_eq!).

status_line_legacy_limit_items_prefer_matching_windows597–627 ↗
async fn status_line_legacy_limit_items_prefer_matching_windows()

Purpose: Ensures older status-line items still choose the matching five-hour and weekly windows when both are available.

Data flow: It provides primary weekly and secondary five-hour snapshots → reads both legacy status items → expects each to show the matching limit.

Call relations: The test runner calls this test; it protects backward-compatible status-line behavior.

Call graph: 1 external calls (assert_eq!).

status_line_shows_secondary_non_weekly_when_primary_is_weekly630–660 ↗
async fn status_line_shows_secondary_non_weekly_when_primary_is_weekly()

Purpose: Checks that when the primary limit is weekly, a non-weekly secondary limit can still appear in the other status-line slot.

Data flow: It supplies a weekly primary and monthly secondary limit → reads five-hour and weekly items → expects monthly in one slot and weekly in the other.

Call relations: The test runner calls this test; it covers status-line selection among multiple rate-limit windows.

Call graph: 1 external calls (assert_eq!).

status_line_five_hour_item_omits_weekly_only_limit663–689 ↗
async fn status_line_five_hour_item_omits_weekly_only_limit()

Purpose: Verifies that a five-hour status item does not show a weekly-only limit when no non-weekly limit exists.

Data flow: It stores only a weekly primary limit → reads the five-hour and weekly status items → expects the five-hour item to be absent and weekly to render.

Call relations: The test runner calls this test; it protects legacy status item semantics.

Call graph: 1 external calls (assert_eq!).

status_line_single_monthly_primary_omits_weekly_limit_item692–718 ↗
async fn status_line_single_monthly_primary_omits_weekly_limit_item()

Purpose: Checks that a single monthly primary limit appears in the non-weekly slot and does not masquerade as weekly.

Data flow: It stores a monthly primary limit only → reads both status items → expects monthly text for the first and no weekly text.

Call relations: The test runner calls this test; it covers rate-limit status selection for monthly plans.

Call graph: 1 external calls (assert_eq!).

status_line_secondary_only_non_weekly_limit_omits_primary_limit_item721–747 ↗
async fn status_line_secondary_only_non_weekly_limit_omits_primary_limit_item()

Purpose: Verifies that a secondary-only non-weekly limit appears in the secondary/weekly slot and does not fill the primary slot.

Data flow: It stores only a monthly secondary limit → reads both status items → expects no five-hour item and monthly text in the weekly item slot.

Call relations: The test runner calls this test; it guards the status-line fallback rules for secondary-only data.

Call graph: 1 external calls (assert_eq!).

rate_limit_snapshot_keeps_prior_credits_when_missing_from_headers750–804 ↗
async fn rate_limit_snapshot_keeps_prior_credits_when_missing_from_headers()

Purpose: Ensures credit balance information is not lost when later rate-limit headers omit it.

Data flow: It first stores credits with a balance → then stores a rate-limit update without credits → checks the cached display → expects the old credits plus the new primary usage.

Call relations: The test runner calls this test; it exercises snapshot merging in ChatWidget.

Call graph: 2 external calls (assert!, assert_eq!).

rolling_rate_limit_snapshot_preserves_prior_individual_limit807–838 ↗
async fn rolling_rate_limit_snapshot_preserves_prior_individual_limit()

Purpose: Checks that rolling rate-limit updates preserve existing individual monthly limit data, but full snapshots can clear it.

Data flow: It stores an individual limit → applies a rolling update → expects the individual limit to remain formatted → applies a normal snapshot → expects it to be gone.

Call relations: The test runner calls this test; it validates the difference between rolling and full rate-limit updates.

Call graph: 2 external calls (assert!, assert_eq!).

rate_limit_snapshot_updates_and_retains_plan_type841–903 ↗
async fn rate_limit_snapshot_updates_and_retains_plan_type()

Purpose: Verifies that plan type updates when supplied and remains unchanged when later snapshots omit it.

Data flow: It applies snapshots with Plus, then Pro, then no plan type → checks the widget plan type after each → expects the last known value to stay Pro.

Call relations: The test runner calls this test; it protects account-plan display state.

Call graph: 1 external calls (assert_eq!).

rate_limit_snapshots_keep_separate_entries_per_limit_id906–962 ↗
async fn rate_limit_snapshots_keep_separate_entries_per_limit_id()

Purpose: Ensures rate-limit data for different limit IDs is cached separately.

Data flow: It sends one snapshot for codex and another for codex_other → reads both cache entries → expects each to keep its own usage and credits.

Call relations: The test runner calls this test; it covers multi-limit snapshot storage.

Call graph: 2 external calls (assert!, assert_eq!).

rate_limit_switch_prompt_skips_when_on_lower_cost_model965–975 ↗
async fn rate_limit_switch_prompt_skips_when_on_lower_cost_model()

Purpose: Checks that the model-switch nudge is not shown when the user is already on the lower-cost nudge model.

Data flow: It creates a chat widget using the nudge model → sends high usage → expects the prompt state to remain idle.

Call relations: The test runner calls this test; it validates one guard in the rate-limit model-switch prompt.

Call graph: 1 external calls (assert!).

rate_limit_switch_prompt_skips_non_codex_limit978–1001 ↗
async fn rate_limit_switch_prompt_skips_non_codex_limit()

Purpose: Ensures the model-switch prompt is only triggered for the Codex limit, not unrelated limits.

Data flow: It sends a high-usage snapshot for a different limit ID → checks prompt state → expects no prompt.

Call relations: The test runner calls this test; it covers limit-ID filtering for the rate-limit nudge.

Call graph: 1 external calls (assert!).

rate_limit_switch_prompt_shows_once_per_session1004–1024 ↗
async fn rate_limit_switch_prompt_shows_once_per_session()

Purpose: Verifies that the rate-limit model-switch prompt appears at most once in a session.

Data flow: It sends high usage, shows the pending prompt, then sends more high usage → expects the state to remain shown rather than showing again.

Call relations: The test runner calls this test; it exercises warning emission and prompt state transitions.

Call graph: 1 external calls (assert!).

rate_limit_switch_prompt_respects_hidden_notice1027–1038 ↗
async fn rate_limit_switch_prompt_respects_hidden_notice()

Purpose: Checks that user configuration can hide the rate-limit model-switch notice.

Data flow: It enables the hide flag → sends high usage → expects the prompt to stay idle.

Call relations: The test runner calls this test; it validates the notice opt-out setting.

Call graph: 1 external calls (assert!).

rate_limit_switch_prompt_defers_until_task_complete1041–1058 ↗
async fn rate_limit_switch_prompt_defers_until_task_complete()

Purpose: Ensures the model-switch prompt waits until an active task finishes before appearing.

Data flow: It marks a task as running → sends high usage → sees a pending prompt → marks the task stopped and asks to show pending prompts → expects it shown.

Call relations: The test runner calls this test; it protects prompt timing so it does not interrupt work.

Call graph: 1 external calls (assert!).

rate_limit_switch_prompt_popup_snapshot1061–1070 ↗
async fn rate_limit_switch_prompt_popup_snapshot()

Purpose: Captures the visual appearance of the rate-limit model-switch popup.

Data flow: It triggers the prompt → renders the bottom popup at a fixed width → compares the text picture against a snapshot.

Call relations: The test runner calls this snapshot test; it checks the popup rendering path.

Call graph: 1 external calls (assert_chatwidget_snapshot!).

workspace_member_credits_depleted_prompts_and_sends_credits1073–1089 ↗
async fn workspace_member_credits_depleted_prompts_and_sends_credits()

Purpose: Checks that a workspace member with depleted credits gets the right prompt and sends the right owner-nudge request when they accept.

Data flow: It sends a credits-depleted snapshot and rate-limit error → snapshots the popup → presses y → expects an app event requesting a Credits nudge email.

Call relations: The test runner calls this test; it uses next_send_add_credits_nudge_email_event to read the emitted request.

Call graph: calls 1 internal fn (next_send_add_credits_nudge_email_event); 4 external calls (Char, new, assert_chatwidget_snapshot!, assert_eq!).

workspace_member_usage_limit_prompts_and_sends_usage_limit1092–1108 ↗
async fn workspace_member_usage_limit_prompts_and_sends_usage_limit()

Purpose: Checks that a workspace member who hit a usage limit gets a limit-increase prompt and sends the matching request when accepted.

Data flow: It sends a usage-limit snapshot and error → snapshots the popup → presses y → expects a UsageLimit nudge email event.

Call relations: The test runner calls this test; it uses the event-draining helper to verify the outgoing app event.

Call graph: calls 1 internal fn (next_send_add_credits_nudge_email_event); 4 external calls (Char, new, assert_chatwidget_snapshot!, assert_eq!).

header_rate_limit_snapshot_preserves_member_limit_type_for_error_prompt1111–1137 ↗
async fn header_rate_limit_snapshot_preserves_member_limit_type_for_error_prompt()

Purpose: Ensures a later header-only snapshot does not erase the backend-classified member limit type before the error prompt is shown.

Data flow: It stores a member usage-limit type → applies a later snapshot without that type → handles the error → expects the usage-limit prompt and matching nudge event.

Call relations: The test runner calls this test; it validates snapshot merging before rate-limit error handling.

Call graph: calls 1 internal fn (next_send_add_credits_nudge_email_event); 4 external calls (Char, new, assert!, assert_eq!).

usage_limit_error_remaps_stale_member_credits_state_to_usage_limit_prompt1140–1159 ↗
async fn usage_limit_error_remaps_stale_member_credits_state_to_usage_limit_prompt()

Purpose: Checks that a UsageLimit error overrides stale credits-depleted state so the user sees the right request wording.

Data flow: It stores a credits-depleted state → handles a UsageLimit error → expects a limit-increase prompt and UsageLimit nudge event.

Call relations: The test runner calls this test; it covers error-kind correction logic.

Call graph: calls 1 internal fn (next_send_add_credits_nudge_email_event); 4 external calls (Char, new, assert!, assert_eq!).

workspace_owner_limit_states_do_not_prompt_for_owner_nudge1162–1187 ↗
async fn workspace_owner_limit_states_do_not_prompt_for_owner_nudge()

Purpose: Verifies that owner-side limit states do not ask the user to notify a workspace owner.

Data flow: For several owner or generic limit states, it handles an error → checks the popup and event stream → expects no owner-nudge or refresh request.

Call relations: The test runner calls this test; it uses assert_no_owner_nudge_or_rate_limit_refresh to ensure nothing inappropriate is emitted.

Call graph: calls 1 internal fn (assert_no_owner_nudge_or_rate_limit_refresh); 1 external calls (assert!).

workspace_owner_limit_states_render_state_specific_messages1190–1224 ↗
async fn workspace_owner_limit_states_render_state_specific_messages()

Purpose: Checks that owner-side credit and usage-limit failures render distinct, helpful messages in history.

Data flow: It runs two cases → handles each rate-limit error → drains rendered history → expects the state-specific message and snapshots all cases.

Call relations: The test runner calls this test; it validates user-facing copy for workspace owners.

Call graph: 3 external calls (new, assert!, assert_chatwidget_snapshot!).

missing_rate_limit_reached_type_does_not_prompt_or_refresh1227–1238 ↗
async fn missing_rate_limit_reached_type_does_not_prompt_or_refresh()

Purpose: Ensures missing backend classification does not trigger an owner-nudge prompt or a rate-limit refresh.

Data flow: It sends a generic full-usage snapshot with no reached type → handles a usage-limit error → expects no workspace-owner prompt and no related app events.

Call relations: The test runner calls this test; it uses the no-event helper to guard conservative behavior.

Call graph: calls 1 internal fn (assert_no_owner_nudge_or_rate_limit_refresh); 1 external calls (assert!).

workspace_owner_nudge_default_no_dismisses_without_sending1241–1254 ↗
async fn workspace_owner_nudge_default_no_dismisses_without_sending()

Purpose: Checks that the owner-nudge popup defaults to “no,” so pressing Enter dismisses without sending email.

Data flow: It shows a member credits-depleted prompt → presses Enter → confirms no nudge or rate-limit refresh events are emitted.

Call relations: The test runner calls this test; it protects safe default dialog behavior.

Call graph: calls 1 internal fn (assert_no_owner_nudge_or_rate_limit_refresh); 1 external calls (new).

workspace_owner_nudge_reappears_after_dismissing_no1257–1279 ↗
async fn workspace_owner_nudge_reappears_after_dismissing_no()

Purpose: Verifies that saying no only dismisses the current prompt and does not permanently suppress future prompts.

Data flow: It shows a usage-limit prompt → dismisses it with Enter → triggers the error again → expects the prompt to reappear.

Call relations: The test runner calls this test; it validates prompt lifecycle after dismissal.

Call graph: calls 1 internal fn (assert_no_owner_nudge_or_rate_limit_refresh); 2 external calls (new, assert!).

workspace_owner_credits_nudge_completion_renders_feedback1282–1315 ↗
async fn workspace_owner_credits_nudge_completion_renders_feedback()

Purpose: Checks the feedback messages after trying to notify a workspace owner about credits.

Data flow: It simulates sent, cooldown, and failure results → drains history for each → expects the correct user-facing completion text and snapshots all cases.

Call relations: The test runner calls this test; it exercises request completion rendering for credit nudges.

Call graph: 3 external calls (new, assert!, assert_chatwidget_snapshot!).

workspace_owner_usage_limit_nudge_completion_renders_feedback1318–1351 ↗
async fn workspace_owner_usage_limit_nudge_completion_renders_feedback()

Purpose: Checks the feedback messages after requesting a usage-limit increase from a workspace owner.

Data flow: It simulates sent, cooldown, and failure results → drains history → expects the matching limit-increase completion text and snapshots all cases.

Call relations: The test runner calls this test; it exercises request completion rendering for usage-limit nudges.

Call graph: 3 external calls (new, assert!, assert_chatwidget_snapshot!).

next_send_add_credits_nudge_email_event1353–1362 ↗
fn next_send_add_credits_nudge_email_event(
    rx: &mut tokio::sync::mpsc::UnboundedReceiver<AppEvent>,
) -> AddCreditsNudgeCreditType

Purpose: Finds the next app event that asks to send an add-credits or limit-increase nudge email.

Data flow: It receives an app-event receiver → repeatedly drains available events → returns the credit type from the first SendAddCreditsNudgeEmail event or panics if none appears.

Call relations: Workspace-member and stale-state tests call this helper after simulating a yes key press.

Call graph: called by 4 (header_rate_limit_snapshot_preserves_member_limit_type_for_error_prompt, usage_limit_error_remaps_stale_member_credits_state_to_usage_limit_prompt, workspace_member_credits_depleted_prompts_and_sends_credits, workspace_member_usage_limit_prompts_and_sends_usage_limit); 2 external calls (try_recv, panic!).

assert_no_owner_nudge_or_rate_limit_refresh1364–1376 ↗
fn assert_no_owner_nudge_or_rate_limit_refresh(
    rx: &mut tokio::sync::mpsc::UnboundedReceiver<AppEvent>,
)

Purpose: Asserts that no owner-nudge email request or rate-limit refresh event was emitted.

Data flow: It drains all pending app events → fails if any forbidden event is found → otherwise leaves the test passing.

Call relations: Several rate-limit prompt tests call this helper when a prompt or refresh should not happen.

Call graph: called by 4 (missing_rate_limit_reached_type_does_not_prompt_or_refresh, workspace_owner_limit_states_do_not_prompt_for_owner_nudge, workspace_owner_nudge_default_no_dismisses_without_sending, workspace_owner_nudge_reappears_after_dismissing_no); 2 external calls (try_recv, assert!).

streaming_final_answer_keeps_task_running_state1379–1408 ↗
async fn streaming_final_answer_keeps_task_running_state()

Purpose: Checks that streaming a final answer hides the status row but keeps the task marked as running until the turn really ends.

Data flow: It starts a task, streams answer text, queues a new user message with Tab, then presses Ctrl-C → expects queued input, no premature submit, and an interrupt operation.

Call relations: The test runner calls this test; it covers streaming state, input queueing, and interruption behavior.

Call graph: calls 1 internal fn (new); 7 external calls (Char, new, new, assert!, assert_eq!, assert_matches!, panic!).

ctrl_c_interrupt_pauses_active_goal_turn1411–1447 ↗
async fn ctrl_c_interrupt_pauses_active_goal_turn()

Purpose: Ensures Ctrl-C during an active goal turn both interrupts the task and marks the goal as paused.

Data flow: It enables goals, installs an active goal for the current thread, starts a task, and presses Ctrl-C → expects an interrupt operation and a SetThreadGoalStatus Paused event.

Call relations: The test runner calls this test; it uses test_thread_goal to build the fake goal update.

Call graph: calls 2 internal fn (new, test_thread_goal); 5 external calls (Char, new, ThreadGoalUpdated, assert_matches!, panic!).

idle_commit_ticks_do_not_restore_status_without_commentary_completion1450–1466 ↗
async fn idle_commit_ticks_do_not_restore_status_without_commentary_completion()

Purpose: Verifies that idle stream ticks do not make the hidden status row flicker back on after final-answer text.

Data flow: It starts a task, streams answer text, commits once, then commits again with no new commentary completion → expects the status indicator to stay hidden.

Call relations: The test runner calls this test; it protects status-row stability during streaming.

Call graph: 1 external calls (assert_eq!).

final_answer_completion_restores_status_indicator_for_pending_steer1469–1525 ↗
async fn final_answer_completion_restores_status_indicator_for_pending_steer()

Purpose: Checks that if the user sends a steering message while an answer is streaming, completing the final answer restores the status indicator for the still-running turn.

Data flow: It streams two answer lines, submits a steer, completes the assistant message, then completes the user steer → expects the task still running and status visible.

Call relations: The test runner calls this test; it exercises pending steer state and final-answer completion.

Call graph: calls 1 internal fn (new); 5 external calls (new, new, assert!, assert_eq!, panic!).

commentary_completion_restores_status_indicator_before_exec_begin1528–1552 ↗
async fn commentary_completion_restores_status_indicator_before_exec_begin()

Purpose: Ensures commentary completion restores the status row before a command execution begins.

Data flow: It streams commentary text, hides the indicator, completes the commentary message, then begins an exec → expects the indicator visible throughout the exec start.

Call relations: The test runner calls this test; it covers the transition from assistant commentary to tool execution.

Call graph: 1 external calls (assert_eq!).

fast_status_indicator_requires_chatgpt_auth1555–1568 ↗
async fn fast_status_indicator_requires_chatgpt_auth()

Purpose: Checks that the fast-mode status indicator only appears for authenticated ChatGPT users.

Data flow: It enables a fast-capable model and fast service tier → checks without auth, then with auth → expects hidden before auth and visible after.

Call relations: The test runner calls this test; it validates one gate for fast-mode UI.

Call graph: 1 external calls (assert!).

fast_status_indicator_is_hidden_for_models_without_fast_support1571–1581 ↗
async fn fast_status_indicator_is_hidden_for_models_without_fast_support()

Purpose: Ensures fast-mode status is not shown for models that do not support fast mode.

Data flow: It selects a model marked as not fast-capable, enables fast tier and auth → asks whether fast status should show → expects false.

Call relations: The test runner calls this test; it validates model-capability gating.

Call graph: 1 external calls (assert!).

fast_status_indicator_is_hidden_when_fast_mode_is_off1584–1593 ↗
async fn fast_status_indicator_is_hidden_when_fast_mode_is_off()

Purpose: Checks that fast status stays hidden when the service tier is not set to fast.

Data flow: It selects a fast-capable model and authenticates → leaves fast tier off → expects the fast status indicator to be hidden.

Call relations: The test runner calls this test; it protects the service-tier gate.

Call graph: 1 external calls (assert!).

ui_snapshots_small_heights_idle1598–1610 ↗
async fn ui_snapshots_small_heights_idle()

Purpose: Captures how the idle chat widget renders in extremely short terminal heights.

Data flow: It renders the widget at heights 1, 2, and 3 → normalizes each test backend buffer → compares each picture to a snapshot.

Call relations: The test runner calls this snapshot test; it guards cramped-layout rendering.

Call graph: 4 external calls (new, assert_chatwidget_snapshot!, format!, new).

ui_snapshots_small_heights_task_running1615–1630 ↗
async fn ui_snapshots_small_heights_task_running()

Purpose: Captures how the chat widget renders at tiny heights while a task is running.

Data flow: It starts a fake turn with reasoning text → renders at heights 1, 2, and 3 → snapshots each result.

Call relations: The test runner calls this snapshot test; it protects layout when status and composer compete for little space.

Call graph: 4 external calls (new, assert_chatwidget_snapshot!, format!, new).

ambient_pet_stays_hidden_until_a_pet_is_selected1634–1671 ↗
async fn ambient_pet_stays_hidden_until_a_pet_is_selected()

Purpose: Checks that pet image support alone does not display a pet; a specific pet must be selected.

Data flow: It enables image support, confirms no pet, writes a test pack, selects a pet, and measures draw coordinates → expects the pet to appear in the correct spot.

Call relations: The test runner calls this test; it covers pet selection and placement.

Call graph: 5 external calls (new, assert!, assert_eq!, write_test_pack, Supported).

ambient_pet_screen_bottom_anchor_uses_terminal_bottom1675–1696 ↗
async fn ambient_pet_screen_bottom_anchor_uses_terminal_bottom()

Purpose: Verifies that the screen-bottom pet anchor uses the terminal bottom rather than the composer bottom.

Data flow: It enables a test pet → measures default y position → switches anchor mode → measures again → expects the pet lower on the screen.

Call relations: The test runner calls this test; it calls enable_test_ambient_pet for setup.

Call graph: calls 1 internal fn (enable_test_ambient_pet); 2 external calls (new, assert_eq!).

ambient_pet_can_be_disabled1700–1706 ↗
async fn ambient_pet_can_be_disabled()

Purpose: Checks that selecting the disabled pet ID removes the ambient pet.

Data flow: It sets the pet selection to the disabled ID → checks that the widget has no ambient pet.

Call relations: The test runner calls this test; it protects the user-facing off switch.

Call graph: 1 external calls (assert!).

ambient_pet_reserves_history_wrap_width1710–1719 ↗
async fn ambient_pet_reserves_history_wrap_width()

Purpose: Ensures history text wraps narrower when a pet occupies screen space, and returns to full width when the pet is disabled.

Data flow: It enables a test pet and asks for wrap width at 80 columns → disables the pet and asks again → expects 69 columns with the pet and 80 without.

Call relations: The test runner calls this test; it uses enable_test_ambient_pet to create the occupied side area.

Call graph: calls 1 internal fn (enable_test_ambient_pet); 1 external calls (assert_eq!).

ambient_pet_reduces_stream_width_and_composer_text_width1723–1776 ↗
async fn ambient_pet_reduces_stream_width_and_composer_text_width()

Purpose: Checks that the ambient pet reduces both streaming text width and composer text width so text does not draw under the pet.

Data flow: It compares widgets with and without a pet → measures stream widths → renders composer drafts → checks that the pet-side tail is blank only when the pet is present.

Call relations: The test runner calls this test; it uses enable_test_ambient_pet, buffer_row_containing, and row_tail_is_blank.

Call graph: calls 2 internal fn (buffer_row_containing, enable_test_ambient_pet); 5 external calls (new, new, assert!, assert_eq!, new).

buffer_row_containing1778–1786 ↗
fn buffer_row_containing(buffer: &ratatui::buffer::Buffer, text: &str) -> Option<String>

Purpose: Finds the first rendered terminal row that contains a given piece of text.

Data flow: It reads every cell in a test buffer row by row → turns each row into a string → returns the first row containing the requested text, or none.

Call relations: The ambient pet width test calls this helper to locate the composer draft row.

Call graph: called by 1 (ambient_pet_reduces_stream_width_and_composer_text_width).

row_tail_is_blank1788–1790 ↗
fn row_tail_is_blank(row: &str, start_col: usize) -> bool

Purpose: Checks whether a rendered row is blank from a given column onward.

Data flow: It receives a string row and start column → skips characters before that column → returns true if all remaining characters are whitespace.

Call relations: This helper is defined for layout assertions; the ambient pet width test uses the same idea to confirm text does not enter the pet area.

ambient_pet_draw_uses_terminal_screen_area_not_short_inline_viewport1794–1821 ↗
async fn ambient_pet_draw_uses_terminal_screen_area_not_short_inline_viewport()

Purpose: Ensures pet drawing is based on the full terminal area, not a short inline viewport that cannot fit the pet.

Data flow: It asks for a pet draw in a short viewport and expects none → asks in a full terminal area and expects specific coordinates.

Call relations: The test runner calls this test; it uses enable_test_ambient_pet.

Call graph: calls 1 internal fn (enable_test_ambient_pet); 3 external calls (new, assert!, assert_eq!).

ambient_pet_hides_notification_text_overlay1825–1847 ↗
async fn ambient_pet_hides_notification_text_overlay()

Purpose: Checks that pet notification labels are not rendered as text overlays when the ambient pet is visible.

Data flow: It cycles through notification kinds → renders the terminal → confirms labels like Running or Ready do not appear in the snapshot text.

Call relations: The test runner calls this test; it uses enable_test_ambient_pet and normal terminal rendering.

Call graph: calls 1 internal fn (enable_test_ambient_pet); 3 external calls (new, assert!, new).

status_widget_and_approval_modal_snapshot1853–1895 ↗
async fn status_widget_and_approval_modal_snapshot()

Purpose: Captures the layout when a running status widget and an approval modal are both active.

Data flow: It starts a task, sets deterministic status text, shows an exec approval request, renders at desired height, and snapshots the result.

Call relations: The test runner calls this snapshot test; it protects visual precedence between status and modal UI.

Call graph: 5 external calls (new, assert_chatwidget_snapshot!, new, new, vec!).

status_widget_active_snapshot1900–1917 ↗
async fn status_widget_active_snapshot()

Purpose: Captures the normal active status widget rendering.

Data flow: It starts a fake turn, feeds reasoning text, renders the widget, and compares the terminal buffer to a snapshot.

Call relations: The test runner calls this snapshot test; it guards the status indicator's stable appearance.

Call graph: 3 external calls (assert_chatwidget_snapshot!, new, new).

stream_error_updates_status_indicator1920–1938 ↗
async fn stream_error_updates_status_indicator()

Purpose: Checks that stream errors update the status indicator instead of adding transcript history.

Data flow: It marks a task as running, sends a stream error with details, drains history, and reads the status widget → expects no history cell and matching header/details.

Call relations: The test runner calls this test; it covers transient stream-error UI.

Call graph: 2 external calls (assert!, assert_eq!).

stream_error_restores_hidden_status_indicator1941–1959 ↗
async fn stream_error_restores_hidden_status_indicator()

Purpose: Ensures a stream error makes the status indicator visible even if answer streaming had hidden it.

Data flow: It starts a task, streams text to hide the indicator, sends a stream error → expects the indicator restored with the error message.

Call relations: The test runner calls this test; it protects reconnect/error feedback visibility.

Call graph: 2 external calls (assert!, assert_eq!).

warning_event_adds_warning_history_cell1962–1973 ↗
async fn warning_event_adds_warning_history_cell()

Purpose: Checks that a warning event becomes a visible warning cell in history.

Data flow: It sends a warning string → drains inserted history → expects one cell containing the warning text.

Call relations: The test runner calls this test; it covers generic warning rendering.

Call graph: 2 external calls (assert!, assert_eq!).

repeated_model_metadata_warning_is_hidden_for_same_slug1976–1990 ↗
async fn repeated_model_metadata_warning_is_hidden_for_same_slug()

Purpose: Ensures duplicate model-metadata warnings for the same model slug are suppressed.

Data flow: It sends the same model metadata warning twice → drains history → expects only one warning cell containing the model slug.

Call relations: The test runner calls this test; it protects users from repeated noisy warnings.

Call graph: 2 external calls (assert!, assert_eq!).

repeated_generic_warning_is_not_hidden1993–2001 ↗
async fn repeated_generic_warning_is_not_hidden()

Purpose: Checks that ordinary duplicate warnings are not suppressed by the model-metadata warning filter.

Data flow: It sends the same generic warning twice → drains history → expects two warning cells.

Call relations: The test runner calls this test; it ensures suppression is narrowly targeted.

Call graph: 1 external calls (assert_eq!).

status_line_invalid_items_warn_once2004–2029 ↗
async fn status_line_invalid_items_warn_once()

Purpose: Verifies that invalid status-line configuration items produce a warning only once.

Data flow: It configures a status line with repeated bogus items → refreshes twice → expects one warning after the first refresh and none after the second.

Call relations: The test runner calls this test; it guards warning deduplication for bad config.

Call graph: calls 1 internal fn (new); 3 external calls (assert!, assert_eq!, vec!).

status_line_context_used_renders_labeled_percent2032–2044 ↗
async fn status_line_context_used_renders_labeled_percent()

Purpose: Checks that the context-used status-line item renders a labeled percentage.

Data flow: It configures context-used, refreshes the status line, and reads it → expects “Context 0% used” with no warning.

Call relations: The test runner calls this test; it confirms the item remains valid.

Call graph: calls 1 internal fn (new); 3 external calls (assert!, assert_eq!, vec!).

status_line_context_remaining_renders_labeled_percent2047–2062 ↗
async fn status_line_context_remaining_renders_labeled_percent()

Purpose: Checks that the context-remaining status-line item renders a labeled remaining percentage.

Data flow: It configures context-remaining, refreshes, and reads the status line → expects “Context 100% left” with no warning.

Call relations: The test runner calls this test; it validates context remaining display.

Call graph: calls 1 internal fn (new); 3 external calls (assert!, assert_eq!, vec!).

status_line_legacy_context_usage_renders_context_used_percent2065–2077 ↗
async fn status_line_legacy_context_usage_renders_context_used_percent()

Purpose: Ensures the old context-usage status-line item still works as an alias for context used.

Data flow: It configures context-usage, refreshes, and reads the status line → expects “Context 0% used” and no warning.

Call relations: The test runner calls this test; it protects backward-compatible configuration.

Call graph: calls 1 internal fn (new); 3 external calls (assert!, assert_eq!, vec!).

status_line_branch_state_resets_when_git_branch_disabled2080–2092 ↗
async fn status_line_branch_state_resets_when_git_branch_disabled()

Purpose: Checks that Git branch lookup state is cleared when the status line no longer asks for Git branch info.

Data flow: It seeds branch state, configures a status line without Git branch, refreshes → expects branch value and pending flags to reset.

Call relations: The test runner calls this test; it covers cleanup when config changes.

Call graph: 3 external calls (assert!, assert_eq!, vec!).

status_line_branch_refreshes_after_turn_complete2095–2105 ↗
async fn status_line_branch_refreshes_after_turn_complete()

Purpose: Ensures the Git branch status item refreshes after a turn completes.

Data flow: It installs a no-op workspace command runner, enables git-branch status, marks lookup complete, then completes a turn → expects a new branch lookup pending.

Call relations: The test runner calls this test; it uses install_noop_workspace_command_runner for safe command execution.

Call graph: calls 1 internal fn (install_noop_workspace_command_runner); 2 external calls (assert!, vec!).

status_line_branch_refreshes_after_interrupt2108–2118 ↗
async fn status_line_branch_refreshes_after_interrupt()

Purpose: Ensures the Git branch status item refreshes after a turn is interrupted.

Data flow: It sets up git-branch status and a no-op command runner → simulates interruption → expects branch lookup to become pending.

Call relations: The test runner calls this test; it shares setup with the turn-complete branch refresh test.

Call graph: calls 1 internal fn (install_noop_workspace_command_runner); 2 external calls (assert!, vec!).

install_noop_workspace_command_runner2120–2122 ↗
fn install_noop_workspace_command_runner(chat: &mut ChatWidget)

Purpose: Installs a fake workspace command runner that does not run real commands.

Data flow: It receives a mutable ChatWidget → stores a NoopWorkspaceCommandRunner inside it → later Git status refresh code can call it safely.

Call relations: Branch refresh tests call this helper before triggering status-line Git lookups.

Call graph: called by 2 (status_line_branch_refreshes_after_interrupt, status_line_branch_refreshes_after_turn_complete); 1 external calls (new).

NoopWorkspaceCommandRunner::run2127–2148 ↗
fn run(
        &self,
        _command: crate::workspace_command::WorkspaceCommand,
    ) -> std::pin::Pin<
        Box<
            dyn std::future::Future<
                    Output = Result<

Purpose: Implements a fake command execution method for tests.

Data flow: It ignores the requested workspace command → returns an async result with exit code 1 and empty output → no shell command is actually run.

Call relations: ChatWidget uses this through the WorkspaceCommandExecutor trait when tests trigger branch refresh behavior.

Call graph: 2 external calls (pin, new).

interrupted_turn_clears_visible_running_hook2152–2175 ↗
async fn interrupted_turn_clears_visible_running_hook()

Purpose: Checks that interrupting a turn clears any visible running hook row.

Data flow: It starts a hook, reveals it, records the live hook text, interrupts the turn, and snapshots before/after output.

Call relations: The test runner calls this test; it uses hook_started_run to build the fake hook.

Call graph: calls 1 internal fn (hook_started_run); 1 external calls (assert_chatwidget_snapshot!).

completed_turn_clears_visible_running_hook2178–2201 ↗
async fn completed_turn_clears_visible_running_hook()

Purpose: Checks that completing a turn clears any visible running hook row.

Data flow: It starts and reveals a hook, records its display, completes the turn, and snapshots before/after state.

Call relations: The test runner calls this test; it uses hook_started_run for setup.

Call graph: calls 1 internal fn (hook_started_run); 1 external calls (assert_chatwidget_snapshot!).

status_line_fast_mode_renders_on_and_off2204–2214 ↗
async fn status_line_fast_mode_renders_on_and_off()

Purpose: Verifies that the fast-mode status-line item reflects whether fast service tier is active.

Data flow: It configures fast-mode in the status line → refreshes with fast off and on → expects “Fast off” then “Fast on.”

Call relations: The test runner calls this test; it covers status-line text for service tier.

Call graph: 2 external calls (assert_eq!, vec!).

status_line_model_with_reasoning_includes_fast_for_fast_capable_models2240–2272 ↗
async fn status_line_model_with_reasoning_includes_fast_for_fast_capable_models()

Purpose: Checks that model-with-reasoning includes “fast” only for fast-capable models when fast mode is active.

Data flow: It configures model, reasoning, context, and directory items → enables fast and auth → expects fast in the text for one model, then absent after switching to a non-fast model.

Call relations: The test runner calls this test; it combines model catalog, service tier, and status-line formatting.

Call graph: 3 external calls (assert!, assert_eq!, vec!).

terminal_title_model_updates_on_model_change_without_manual_refresh2275–2285 ↗
async fn terminal_title_model_updates_on_model_change_without_manual_refresh()

Purpose: Ensures the terminal title updates automatically when the model changes.

Data flow: It configures the terminal title to show the model → refreshes once → changes model → expects last_terminal_title to update immediately.

Call relations: The test runner calls this test; it covers model-change side effects.

Call graph: 2 external calls (assert_eq!, vec!).

status_line_and_terminal_title_reasoning_render_only_effort2288–2300 ↗
async fn status_line_and_terminal_title_reasoning_render_only_effort()

Purpose: Checks that the reasoning item shows only reasoning effort, not fast mode.

Data flow: It configures status line and terminal title to show reasoning → sets reasoning and fast tier → refreshes both → expects just “xhigh.”

Call relations: The test runner calls this test; it validates separation between reasoning and fast-mode labels.

Call graph: 2 external calls (assert_eq!, vec!).

status_line_reasoning_updates_on_mode_switch_without_manual_refresh2303–2316 ↗
async fn status_line_reasoning_updates_on_mode_switch_without_manual_refresh()

Purpose: Ensures switching collaboration mode updates the reasoning status item automatically.

Data flow: It enables collaboration modes, sets high effort, then switches to plan mode → expects status text to change from high to medium.

Call relations: The test runner calls this test; it uses collaboration_modes::plan_mask to simulate the mode change.

Call graph: calls 1 internal fn (plan_mask); 2 external calls (assert_eq!, vec!).

status_line_model_with_reasoning_updates_on_mode_switch_without_manual_refresh2319–2347 ↗
async fn status_line_model_with_reasoning_updates_on_mode_switch_without_manual_refresh()

Purpose: Checks that model-with-reasoning updates automatically when collaboration mode changes reasoning effort.

Data flow: It sets high effort → switches to plan mode and then default mode → expects the status line to show medium, then high again.

Call relations: The test runner calls this test; it uses plan and default collaboration masks.

Call graph: calls 2 internal fn (default_mask, plan_mask); 2 external calls (assert_eq!, vec!).

thread_goal_update_for_other_thread_is_ignored2615–2641 ↗
async fn thread_goal_update_for_other_thread_is_ignored()

Purpose: Checks that goal updates for another thread do not affect the current chat.

Data flow: It sets the widget to one thread ID → sends a goal update for a different thread → expects no current goal state or budget markers.

Call relations: The test runner calls this test; it protects cross-thread isolation.

Call graph: calls 2 internal fn (new, test_thread_goal); 3 external calls (ThreadGoalUpdated, assert!, assert_eq!).

goal_status_indicator_formats_statuses_and_budgets2644–2709 ↗
fn goal_status_indicator_formats_statuses_and_budgets()

Purpose: Verifies conversion from app-server goal status data into compact footer indicator values.

Data flow: It builds goals with different statuses, budgets, and usage → converts each to an indicator → expects the right enum value and usage label.

Call relations: The test runner calls this unit test; it exercises goal_status_indicator_from_app_goal using test_thread_goal.

Call graph: 1 external calls (assert_eq!).

goal_status_indicator_line_formats_goal_text2712–2758 ↗
fn goal_status_indicator_line_formats_goal_text()

Purpose: Checks the exact readable text shown for each goal status indicator.

Data flow: It loops over indicator cases → renders each into a status line → joins the text spans → compares with expected phrases.

Call relations: The test runner calls this unit test; it covers goal_status_indicator_line from the bottom pane.

Call graph: 2 external calls (assert_eq!, goal_status_indicator_line).

test_thread_goal2760–2775 ↗
fn test_thread_goal(
    status: codex_app_server_protocol::ThreadGoalStatus,
    token_budget: Option<i64>,
    tokens_used: i64,
) -> codex_app_server_protocol::ThreadGoal

Purpose: Builds a reusable fake ThreadGoal for tests.

Data flow: It receives a goal status, optional token budget, and tokens used → fills in a ThreadGoal with stable IDs, objective, and timestamps → returns it.

Call relations: Goal-related tests call this helper to avoid repeating boilerplate goal construction.

Call graph: called by 5 (ctrl_c_interrupt_pauses_active_goal_turn, session_configured_clears_goal_status_footer, status_line_goal_active_token_budget_footer_snapshot, status_line_goal_complete_elapsed_footer_snapshot, thread_goal_update_for_other_thread_is_ignored).

runtime_metrics_websocket_timing_logs_and_final_separator_sums_totals2778–2821 ↗
async fn runtime_metrics_websocket_timing_logs_and_final_separator_sums_totals()

Purpose: Checks that runtime metrics are logged during a task and summarized in the final separator.

Data flow: It enables runtime metrics, applies timing deltas, drains timing logs, completes the task, and reads the final separator → expects the latest TTFT and accumulated TBT values.

Call relations: The test runner calls this test; it covers runtime metrics logging and final-turn summary rendering.

Call graph: 2 external calls (assert!, default).

multiple_agent_messages_in_single_turn_emit_multiple_headers2824–2860 ↗
async fn multiple_agent_messages_in_single_turn_emit_multiple_headers()

Purpose: Ensures multiple finalized assistant messages in one turn all appear, in order.

Data flow: It starts a turn, completes two assistant messages, completes the turn, and drains history → expects both messages with the first before the second.

Call relations: The test runner calls this test; it protects transcript ordering for multi-message turns.

Call graph: 1 external calls (assert!).

final_reasoning_then_message_without_deltas_are_rendered2863–2885 ↗
async fn final_reasoning_then_message_without_deltas_are_rendered()

Purpose: Checks that final reasoning and final assistant message still render when no streaming deltas were received.

Data flow: It finalizes reasoning, completes an assistant message, drains history, and snapshots the combined text.

Call relations: The test runner calls this snapshot test; it covers non-streaming final-message rendering.

Call graph: 1 external calls (assert_chatwidget_snapshot!).

deltas_then_same_final_message_are_rendered_snapshot2888–2919 ↗
async fn deltas_then_same_final_message_are_rendered_snapshot()

Purpose: Checks rendering when streamed deltas are followed by the same final message text.

Data flow: It streams reasoning deltas, finalizes reasoning, streams answer deltas, then completes the same final message → drains history and snapshots it.

Call relations: The test runner calls this snapshot test; it guards duplicate/finalization handling in streaming.

Call graph: 1 external calls (assert_chatwidget_snapshot!).

user_prompt_submit_app_server_hook_notifications_render_snapshot2922–2991 ↗
async fn user_prompt_submit_app_server_hook_notifications_render_snapshot()

Purpose: Captures rendering for app-server hook notifications tied to user prompt submission.

Data flow: It sends a hook-started notification and a stopped hook-completed notification with warning and stop entries → drains history and snapshots the result.

Call relations: The test runner calls this snapshot test; it covers server hook notification rendering.

Call graph: calls 1 internal fn (new); 7 external calls (from, HookCompleted, HookStarted, new, assert!, assert_chatwidget_snapshot!, vec!).

pre_tool_use_hook_events_render_snapshot2994–3002 ↗
async fn pre_tool_use_hook_events_render_snapshot()

Purpose: Runs the shared hook-event snapshot scenario for PreToolUse hooks.

Data flow: It passes the PreToolUse event kind, hook ID, status message, and snapshot name into the shared hook snapshot helper → the helper performs the rendering checks.

Call relations: The test runner calls this test; it delegates to assert_hook_events_snapshot from the surrounding test module.

post_tool_use_hook_events_render_snapshot3005–3013 ↗
async fn post_tool_use_hook_events_render_snapshot()

Purpose: Runs the shared hook-event snapshot scenario for PostToolUse hooks.

Data flow: It passes PostToolUse hook details into the shared snapshot helper → the helper drives the widget and compares output.

Call relations: The test runner calls this test; it delegates to assert_hook_events_snapshot.

completed_hook_with_no_entries_stays_out_of_history3016–3050 ↗
async fn completed_hook_with_no_entries_stays_out_of_history()

Purpose: Checks that a quiet hook with no output does not add transcript history, while its live row lingers briefly if it was visible.

Data flow: It starts a hook, reveals it, completes it with no entries, drains history, expires linger, and snapshots live/history states.

Call relations: The test runner calls this test; it uses hook_started_run, hook_completed_run, and hook_live_and_history_snapshot.

Call graph: calls 3 internal fn (hook_completed_run, hook_live_and_history_snapshot, hook_started_run); 3 external calls (new, assert!, assert_chatwidget_snapshot!).

quiet_hook_linger_starts_when_delayed_redraw_reveals_hook3053–3084 ↗
async fn quiet_hook_linger_starts_when_delayed_redraw_reveals_hook()

Purpose: Ensures a quiet hook still lingers if it became visible through a delayed redraw before completing.

Data flow: It starts a hook, reveals it after delayed redraw, completes it quietly, checks it still appears, expires linger, and expects it gone.

Call relations: The test runner calls this test; it uses hook_started_run and hook_completed_run.

Call graph: calls 2 internal fn (hook_completed_run, hook_started_run); 3 external calls (new, assert!, assert_eq!).

blocked_and_failed_hooks_render_feedback_and_errors3087–3130 ↗
async fn blocked_and_failed_hooks_render_feedback_and_errors()

Purpose: Checks that blocked and failed hooks write their feedback or error entries into history.

Data flow: It completes one blocked PreToolUse hook with feedback and one failed PostToolUse hook with an error → drains history → snapshots and checks both messages.

Call relations: The test runner calls this test; it uses hook_completed_run to build final hook summaries.

Call graph: calls 1 internal fn (hook_completed_run); 3 external calls (assert!, assert_chatwidget_snapshot!, vec!).

completed_hook_with_output_flushes_immediately3133–3169 ↗
async fn completed_hook_with_output_flushes_immediately()

Purpose: Ensures a hook with output is flushed to history immediately when it completes.

Data flow: It starts and reveals a hook → completes it as blocked with feedback → drains history → snapshots live and history output.

Call relations: The test runner calls this test; it uses hook helper constructors and hook_live_and_history_snapshot.

Call graph: calls 3 internal fn (hook_completed_run, hook_live_and_history_snapshot, hook_started_run); 2 external calls (assert_chatwidget_snapshot!, vec!).

completed_hook_output_precedes_following_assistant_message3172–3226 ↗
async fn completed_hook_output_precedes_following_assistant_message()

Purpose: Checks that completed hook output appears before any assistant message that follows it.

Data flow: It starts and completes a hook with feedback, then completes an assistant message → drains history → verifies the hook text comes before the assistant text.

Call relations: The test runner calls this test; it protects transcript ordering around hooks.

Call graph: calls 2 internal fn (hook_completed_run, hook_started_run); 3 external calls (assert!, assert_chatwidget_snapshot!, vec!).

completed_same_id_hook_output_survives_restart3229–3279 ↗
async fn completed_same_id_hook_output_survives_restart()

Purpose: Ensures output from a completed hook is not overwritten if another hook with the same ID starts later.

Data flow: It starts and completes a hook with stop output, then starts another hook with the same ID → drains history → expects the first output still present.

Call relations: The test runner calls this test; it covers hook identity reuse.

Call graph: calls 2 internal fn (hook_completed_run, hook_started_run); 3 external calls (assert!, assert_chatwidget_snapshot!, vec!).

identical_parallel_running_hooks_collapse_to_count3282–3301 ↗
async fn identical_parallel_running_hooks_collapse_to_count()

Purpose: Checks that identical parallel running hooks are collapsed into one live row with a count.

Data flow: It starts three similar hooks with different tool-call IDs → reveals hooks → snapshots the compact live-hook display.

Call relations: The test runner calls this test; it repeatedly uses hook_started_run.

Call graph: calls 1 internal fn (hook_started_run); 2 external calls (assert_chatwidget_snapshot!, format!).

overlapping_hook_live_cell_tracks_parallel_quiet_hooks3304–3372 ↗
async fn overlapping_hook_live_cell_tracks_parallel_quiet_hooks()

Purpose: Tests live-hook display when multiple quiet hooks overlap and complete at different times.

Data flow: It starts two hooks, reveals them, completes each quietly, expires linger in stages, and snapshots every phase while ensuring the main status header remains unchanged.

Call relations: The test runner calls this test; it uses hook helper constructors and hook_live_and_history_snapshot.

Call graph: calls 3 internal fn (hook_completed_run, hook_live_and_history_snapshot, hook_started_run); 4 external calls (new, assert!, assert_chatwidget_snapshot!, assert_eq!).

running_hook_does_not_displace_active_exec_cell3375–3423 ↗
async fn running_hook_does_not_displace_active_exec_cell()

Purpose: Ensures a running hook does not replace or hide an active command-execution cell.

Data flow: It begins an exec, starts a hook, ends the exec, completes the hook, and snapshots active exec, active hooks, and history at each stage.

Call relations: The test runner calls this test; it combines exec rendering with hook rendering.

Call graph: calls 2 internal fn (hook_completed_run, hook_started_run); 4 external calls (new, assert!, assert_chatwidget_snapshot!, format!).

hidden_active_hook_does_not_add_transcript_separator3426–3467 ↗
async fn hidden_active_hook_does_not_add_transcript_separator()

Purpose: Checks that a hidden active hook does not add an extra separator to active transcript lines.

Data flow: It starts an exec and counts transcript lines → starts a hook while hidden and confirms count unchanged → reveals the hook and expects exactly one separator plus hook lines.

Call relations: The test runner calls this test; it uses hook_started_run to create the hidden hook.

Call graph: calls 1 internal fn (hook_started_run); 1 external calls (assert_eq!).

hook_completed_before_reveal_renders_completed_without_running_flash3470–3504 ↗
async fn hook_completed_before_reveal_renders_completed_without_running_flash()

Purpose: Ensures a hook that completes before it is ever revealed renders as completed output, not as a brief running row.

Data flow: It starts a hidden hook, completes it with context output, drains history, and snapshots hidden/live plus history output.

Call relations: The test runner calls this test; it uses hook_started_run and hook_completed_run.

Call graph: calls 2 internal fn (hook_completed_run, hook_started_run); 2 external calls (assert_chatwidget_snapshot!, vec!).

session_start_hook_events_render_snapshot3507–3515 ↗
async fn session_start_hook_events_render_snapshot()

Purpose: Runs the shared hook-event snapshot scenario for SessionStart hooks.

Data flow: It passes SessionStart hook details into the shared snapshot helper → the helper drives rendering and checks the snapshot.

Call relations: The test runner calls this test; it delegates to assert_hook_events_snapshot.

hook_started_run3517–3529 ↗
fn hook_started_run(
    id: &str,
    event_name: codex_app_server_protocol::HookEventName,
    status_message: Option<&str>,
) -> codex_app_server_protocol::HookRunSummary

Purpose: Builds a fake running hook summary for tests.

Data flow: It receives a hook ID, event kind, and optional status message → calls hook_run_summary with Running status and no entries → returns the summary.

Call relations: Many hook tests call this helper before feeding a started hook into the ChatWidget.

Call graph: calls 1 internal fn (hook_run_summary); called by 12 (completed_hook_output_precedes_following_assistant_message, completed_hook_with_no_entries_stays_out_of_history, completed_hook_with_output_flushes_immediately, completed_same_id_hook_output_survives_restart, completed_turn_clears_visible_running_hook, hidden_active_hook_does_not_add_transcript_separator, hook_completed_before_reveal_renders_completed_without_running_flash, identical_parallel_running_hooks_collapse_to_count, interrupted_turn_clears_visible_running_hook, overlapping_hook_live_cell_tracks_parallel_quiet_hooks (+2 more)); 1 external calls (new).

hook_completed_run3531–3540 ↗
fn hook_completed_run(
    id: &str,
    event_name: codex_app_server_protocol::HookEventName,
    status: codex_app_server_protocol::HookRunStatus,
    entries: Vec<codex_app_server_protocol::HookOut

Purpose: Builds a fake completed, blocked, failed, or stopped hook summary for tests.

Data flow: It receives hook identity, event kind, final status, and output entries → calls hook_run_summary with completion data → returns the summary.

Call relations: Hook completion tests call this helper to simulate app-server hook results.

Call graph: calls 1 internal fn (hook_run_summary); called by 9 (blocked_and_failed_hooks_render_feedback_and_errors, completed_hook_output_precedes_following_assistant_message, completed_hook_with_no_entries_stays_out_of_history, completed_hook_with_output_flushes_immediately, completed_same_id_hook_output_survives_restart, hook_completed_before_reveal_renders_completed_without_running_flash, overlapping_hook_live_cell_tracks_parallel_quiet_hooks, quiet_hook_linger_starts_when_delayed_redraw_reveals_hook, running_hook_does_not_displace_active_exec_cell).

hook_run_summary3542–3565 ↗
fn hook_run_summary(
    id: &str,
    event_name: codex_app_server_protocol::HookEventName,
    status: codex_app_server_protocol::HookRunStatus,
    status_message: Option<&str>,
    entries: Vec<co

Purpose: Creates the full hook summary object shared by started and completed hook helpers.

Data flow: It receives hook fields → fills in stable handler, scope, path, timing, status, and entries → returns a HookRunSummary suitable for fake server events.

Call relations: hook_started_run and hook_completed_run both delegate to this constructor.

Call graph: called by 2 (hook_completed_run, hook_started_run); 1 external calls (from).

hook_live_and_history_snapshot3567–3577 ↗
fn hook_live_and_history_snapshot(chat: &ChatWidget, phase: &str, history: &str) -> String

Purpose: Formats a readable snapshot string that combines live hook display and history text.

Data flow: It receives a ChatWidget, phase label, and history string → substitutes “<empty>” for missing history → returns a labeled block of text.

Call relations: Several hook snapshot tests call this helper to compare live and transcript states together.

Call graph: called by 3 (completed_hook_with_no_entries_stays_out_of_history, completed_hook_with_output_flushes_immediately, overlapping_hook_live_cell_tracks_parallel_quiet_hooks); 1 external calls (format!).

chatwidget_exec_and_status_layout_vt100_snapshot3583–3672 ↗
async fn chatwidget_exec_and_status_layout_vt100_snapshot()

Purpose: Creates an end-to-end terminal snapshot showing history, an exec block, status line, and composer together.

Data flow: It simulates an assistant message, command execution, running status, and composer text → inserts history into a VT100-style terminal buffer → renders the live UI overlay → snapshots the full screen.

Call relations: The test runner calls this snapshot test; it combines history insertion, command rendering, status rendering, and terminal viewport behavior.

Call graph: calls 4 internal fn (shlex_join, with_options, insert_history_lines, new); 4 external calls (new, new, assert_chatwidget_snapshot!, vec!).

chatwidget_markdown_code_blocks_vt100_snapshot3676–3754 ↗
async fn chatwidget_markdown_code_blocks_vt100_snapshot()

Purpose: Checks terminal rendering for streamed Markdown with indented and nested fenced code blocks.

Data flow: It streams a complex Markdown source in small chunks → commits streaming output into a VT100 buffer → completes the turn and snapshots the final screen.

Call relations: The test runner calls this snapshot test; it protects Markdown streaming and history insertion behavior.

Call graph: calls 3 internal fn (with_options, insert_history_lines, new); 3 external calls (new, new, assert_chatwidget_snapshot!).

chatwidget_tall3757–3778 ↗
async fn chatwidget_tall()

Purpose: Captures chat widget rendering when many queued messages make the bottom UI tall.

Data flow: It starts a turn, queues many user messages, renders into a fixed terminal viewport, and snapshots the resulting screen.

Call relations: The test runner calls this snapshot test; it guards tall composer/input-queue layout.

Call graph: calls 3 internal fn (new, with_options, new); 3 external calls (new, assert_chatwidget_snapshot!, format!).

tui/src/chatwidget/tests/status_surface_previews.rssource ↗
testtest run

The chat interface can show useful context in two places: a status line inside the text UI and the terminal window title. Users can choose which pieces appear there, such as the project name, Git branch, thread title, task progress, or rate-limit usage. This test file makes sure those previews stay understandable and stable.

Most tests build a fresh ChatWidget, fill in just the pieces of state needed for the scenario, then ask the widget for its preview text or render the setup popup. The result is compared with a saved snapshot, which is like a reference photo: if the output changes later, the test will catch it.

The file also checks important edge cases. For example, if a thread has no name, the preview should fall back to the thread ID. If rate-limit data is missing for a five-hour window, that item should be skipped instead of showing misleading text. Terminal titles are also tested for shorter, title-friendly truncation, so very long thread or branch names do not make the terminal title unwieldy.

Without these tests, small UI regressions could slip in unnoticed: setup popups might show stale placeholder text, unavailable rate limits might appear, or long titles might stop being shortened.

Function details25
line_text6–11 ↗
fn line_text(line: Line<'static>) -> String

Purpose: Turns a styled terminal line into plain text so tests can compare only what a user would read. This removes formatting concerns from preview checks.

Data flow: It receives a ratatui Line, which is made of spans of text that may carry styling. It takes each span's text, joins the pieces in order, and returns one plain String.

Call relations: This is a helper for preview tests. title_preview_line uses it after building a terminal title preview, so later assertions can compare a simple string instead of styled UI objects.

Call graph: called by 1 (title_preview_line).

status_preview_line_option13–18 ↗
fn status_preview_line_option(chat: &mut ChatWidget, items: &[StatusLineItem]) -> Option<String>

Purpose: Asks a ChatWidget to produce a status-line preview for a chosen list of status items. It returns nothing when none of the requested items can currently be shown.

Data flow: It receives a mutable chat widget and a list of status-line items. It gathers the widget's preview data, asks that data to build a themed status line, and converts the result to plain text if a line exists. The output is an Option<String>: either the preview text or no preview.

Call relations: This is the lower-level status preview helper. status_preview_line calls it when a test expects a preview to exist, while tests that need to verify missing items can use this optional result directly.

Call graph: called by 1 (status_preview_line); 2 external calls (iter, status_surface_preview_data).

status_preview_line20–22 ↗
fn status_preview_line(chat: &mut ChatWidget, items: &[StatusLineItem]) -> String

Purpose: Gets a status-line preview and treats its absence as a test failure. It is useful in tests where the preview is expected to exist.

Data flow: It receives a chat widget and requested status items. It calls status_preview_line_option, then unwraps the returned value with an error message if no line was produced. The output is the preview text as a String.

Call relations: This helper sits between individual tests and status_preview_line_option. The missing-project-root test uses it to check the exact status-line fallback text.

Call graph: calls 1 internal fn (status_preview_line_option); called by 1 (missing_project_root_uses_different_status_and_title_preview_sources).

title_preview_line24–29 ↗
fn title_preview_line(chat: &mut ChatWidget, items: &[TerminalTitleItem]) -> String

Purpose: Builds the terminal-title preview for a selected list of title items and returns it as plain text. Tests use it to check what would appear in the terminal title bar.

Data flow: It receives a mutable chat widget and title item choices. It asks the widget for terminal-title preview data, passes that data to the title preview builder, then flattens the styled line into a String. If no preview is produced, the test fails.

Call relations: This helper is called by tests that directly compare terminal title text. It relies on the shared preview builder from the bottom pane and on line_text to make the result easy to assert.

Call graph: calls 1 internal fn (line_text); called by 2 (missing_project_root_uses_different_status_and_title_preview_sources, terminal_title_preview_uses_title_truncation_for_live_values); 2 external calls (preview_line_for_title_items, terminal_title_preview_data).

combined_preview_snapshot31–41 ↗
fn combined_preview_snapshot(
    chat: &mut ChatWidget,
    status_items: &[StatusLineItem],
    title_items: &[TerminalTitleItem],
) -> String

Purpose: Creates one snapshot string containing both the status-line preview and the terminal-title preview. This lets related UI behavior be checked together in one saved reference output.

Data flow: It receives a chat widget plus two item lists: one for the status line and one for the terminal title. It builds both preview strings, formats them under clear labels, normalizes paths so machine-specific folders do not affect the test, and returns the final snapshot text.

Call relations: Several snapshot tests call this when they want to compare the two preview surfaces side by side. It combines the work of status_preview_line and title_preview_line into one stable test artifact.

Call graph: called by 4 (status_surface_preview_lines_hardcoded_only_snapshot, status_surface_preview_lines_live_only_snapshot, status_surface_preview_lines_mixed_snapshot, status_surface_preview_lines_rate_limits_snapshot); 1 external calls (format!).

status_line_popup_snapshot43–48 ↗
fn status_line_popup_snapshot(chat: &mut ChatWidget) -> String

Purpose: Opens the status-line setup popup and captures what it looks like as snapshot text. This checks the user-facing configuration screen, not just the raw preview string.

Data flow: It receives a mutable chat widget. It tells the widget to open the status-line setup screen, renders the bottom popup at a fixed width, removes terminal hyperlink escape codes that would make snapshots noisy, normalizes paths, and returns the rendered text.

Call relations: Status-line popup tests use this helper after setting up chat state and configuration. It hands the widget through the real popup-opening and rendering path, so the snapshot covers the visible setup UI.

Call graph: 1 external calls (open_status_line_setup).

terminal_title_popup_snapshot50–55 ↗
fn terminal_title_popup_snapshot(chat: &mut ChatWidget) -> String

Purpose: Opens the terminal-title setup popup and captures its rendered text for snapshot testing. It checks the setup screen users see when choosing terminal title parts.

Data flow: It receives a mutable chat widget. It opens the terminal-title setup screen, renders the bottom popup at a fixed width, removes terminal hyperlink escape codes, normalizes paths, and returns the snapshot-ready text.

Call relations: Terminal-title popup tests call this after preparing live values or configuration choices. It uses the same rendering path as the UI, which makes the saved snapshot a close stand-in for what a user would see.

Call graph: 1 external calls (open_terminal_title_setup).

cache_project_root57–62 ↗
fn cache_project_root(chat: &mut ChatWidget, root_name: &str)

Purpose: Seeds the chat widget with a known project-root name so preview tests do not depend on the real folder on the test machine. This makes the output predictable.

Data flow: It receives a mutable chat widget and a root name string. It stores a cached project-root record using the widget's current working directory and the supplied display name. The chat widget is changed in place.

Call relations: Tests for live preview data call this before building status-line or terminal-title snapshots. By doing so, they can check project-name behavior without relying on outside filesystem details.

Call graph: called by 3 (status_line_setup_popup_live_only_snapshot, status_surface_preview_lines_live_only_snapshot, terminal_title_setup_popup_live_only_snapshot).

cache_rate_limit_snapshot64–83 ↗
fn cache_rate_limit_snapshot(chat: &mut ChatWidget)

Purpose: Seeds the chat widget with fixed rate-limit usage data. This lets tests verify how five-hour and weekly limits are displayed.

Data flow: It receives a mutable chat widget. It creates a rate-limit snapshot with a primary window at 35 percent used and a secondary window at 50 percent used, then feeds that snapshot into the widget. The widget's stored rate-limit preview data is updated.

Call relations: Rate-limit preview and popup tests call this before taking snapshots. It uses the widget's normal rate-limit update method, so the tests exercise the same path used when real rate-limit data arrives.

Call graph: called by 3 (status_line_setup_popup_rate_limits_snapshot, status_surface_preview_lines_rate_limits_snapshot, terminal_title_setup_popup_rate_limits_snapshot); 1 external calls (on_rate_limit_snapshot).

status_surface_preview_lines_live_only_snapshot86–109 ↗
async fn status_surface_preview_lines_live_only_snapshot()

Purpose: Verifies previews when all requested fields have live values, such as a real project name, branch name, thread title, and task progress. This protects the happy path users expect during an active chat.

Data flow: The test creates a fresh chat widget, fills in live-looking project, branch, thread, and progress data, then builds a combined status-line and terminal-title snapshot. It compares that text with the saved expected snapshot.

Call relations: It calls cache_project_root to stabilize the project name and combined_preview_snapshot to produce the final text. The snapshot assertion then checks that the preview surfaces still match the intended output.

Call graph: calls 2 internal fn (cache_project_root, combined_preview_snapshot); 1 external calls (assert_chatwidget_snapshot!).

status_line_setup_popup_live_only_snapshot112–127 ↗
async fn status_line_setup_popup_live_only_snapshot()

Purpose: Checks the status-line setup popup when its configured items all have live data available. It makes sure the setup screen previews real values instead of placeholders in this case.

Data flow: The test builds a chat widget, seeds project, branch, and thread values, and sets the status-line configuration to those three items. It renders the setup popup and compares it with the saved snapshot.

Call relations: It uses cache_project_root for stable project text, then status_line_popup_snapshot through the snapshot macro to exercise the popup UI exactly as a user would open it.

Call graph: calls 1 internal fn (cache_project_root); 2 external calls (assert_chatwidget_snapshot!, vec!).

status_surface_preview_lines_hardcoded_only_snapshot130–150 ↗
async fn status_surface_preview_lines_hardcoded_only_snapshot()

Purpose: Verifies preview output when the chat widget lacks live values and must use fallback or example text. This keeps empty-state previews useful instead of blank or confusing.

Data flow: The test creates a fresh chat widget without seeding branch, thread, project, permission, or progress state. It requests several status and title items, builds the combined preview snapshot, and compares it with the stored expected output.

Call relations: It calls combined_preview_snapshot to gather both preview surfaces. The snapshot assertion records how the system should behave when only built-in fallback values are available.

Call graph: calls 1 internal fn (combined_preview_snapshot); 1 external calls (assert_chatwidget_snapshot!).

thread_title_falls_back_to_thread_id_when_unnamed153–166 ↗
async fn thread_title_falls_back_to_thread_id_when_unnamed()

Purpose: Checks that an unnamed thread still has something identifiable in previews. If no thread title exists, the thread ID is used instead.

Data flow: The test creates a chat widget, generates a new thread ID, and stores it on the widget without setting a thread name. It then asks for both status-line and terminal-title thread previews and asserts that both equal the thread ID string.

Call relations: This test uses the preview helpers indirectly to confirm fallback behavior shared by both preview surfaces. It protects users from seeing an empty thread field when the thread has not been named.

Call graph: calls 1 internal fn (new); 1 external calls (assert_eq!).

status_line_setup_popup_hardcoded_only_snapshot169–181 ↗
async fn status_line_setup_popup_hardcoded_only_snapshot()

Purpose: Checks the status-line setup popup when configured items do not have live values. It verifies that the popup still shows sensible fallback preview text.

Data flow: The test creates a chat widget, configures the status line to show project name, Git branch, and thread title, but does not seed live values. It renders the setup popup and compares the result with the expected snapshot.

Call relations: It feeds the chosen configuration into the widget, then relies on status_line_popup_snapshot through the snapshot assertion to capture the rendered popup.

Call graph: 2 external calls (assert_chatwidget_snapshot!, vec!).

status_surface_preview_lines_mixed_snapshot184–204 ↗
async fn status_surface_preview_lines_mixed_snapshot()

Purpose: Verifies previews when some fields have live data and others must fall back to defaults. This mirrors common real use, where not every piece of context is known at once.

Data flow: The test creates a chat widget, sets a live branch and thread title, leaves other data absent, then builds a combined preview snapshot for selected status and title items. The resulting text is compared with the saved snapshot.

Call relations: It uses combined_preview_snapshot to check both preview surfaces together. The snapshot assertion locks in how live and fallback values should blend.

Call graph: calls 1 internal fn (combined_preview_snapshot); 1 external calls (assert_chatwidget_snapshot!).

status_surface_preview_lines_rate_limits_snapshot207–221 ↗
async fn status_surface_preview_lines_rate_limits_snapshot()

Purpose: Checks that rate-limit information appears correctly in both status-line and terminal-title previews. This helps users see remaining usage at a glance.

Data flow: The test creates a chat widget, seeds fixed rate-limit data, requests five-hour and weekly limit items for both preview surfaces, and snapshots the combined result.

Call relations: It calls cache_rate_limit_snapshot to provide predictable usage data, then combined_preview_snapshot to format both preview outputs. The snapshot assertion catches changes in wording or ordering.

Call graph: calls 2 internal fn (cache_rate_limit_snapshot, combined_preview_snapshot); 1 external calls (assert_chatwidget_snapshot!).

status_surface_preview_omits_unavailable_rate_limit_items224–263 ↗
async fn status_surface_preview_omits_unavailable_rate_limit_items()

Purpose: Verifies that unavailable rate-limit windows are skipped rather than shown incorrectly. This matters because showing a missing five-hour limit as if it were real would mislead users.

Data flow: The test creates a rate-limit snapshot containing only a weekly-style window and no secondary window. It then checks that a five-hour-only status preview returns nothing, while a combined five-hour-plus-weekly request shows only the weekly remaining text. It also checks the terminal title uses the same visible weekly text.

Call relations: This test talks directly to the widget's rate-limit update path, then uses the preview helpers and equality assertions. It focuses on the special case where requested items are not all available.

Call graph: 1 external calls (assert_eq!).

status_line_setup_popup_rate_limits_snapshot266–278 ↗
async fn status_line_setup_popup_rate_limits_snapshot()

Purpose: Checks the status-line setup popup when it is configured to show rate-limit items. It confirms that the setup screen presents rate-limit preview text consistently.

Data flow: The test creates a chat widget, seeds fixed rate-limit data, and configures the status line for five-hour and weekly limits. It renders the setup popup and compares it with the saved snapshot.

Call relations: It calls cache_rate_limit_snapshot before opening the popup. The snapshot assertion then uses the rendered setup UI to catch changes in rate-limit display behavior.

Call graph: calls 1 internal fn (cache_rate_limit_snapshot); 2 external calls (assert_chatwidget_snapshot!, vec!).

status_line_setup_popup_mixed_snapshot281–295 ↗
async fn status_line_setup_popup_mixed_snapshot()

Purpose: Checks the status-line setup popup when some configured items have live values and others rely on fallback text. This protects the mixed preview experience in the setup screen.

Data flow: The test creates a chat widget, sets a live branch and thread title, configures project, branch, and thread status items, then snapshots the rendered popup.

Call relations: It prepares the widget state directly, then uses the popup snapshot path through the snapshot assertion. This ties the mixed-value preview behavior to the actual setup UI.

Call graph: 2 external calls (assert_chatwidget_snapshot!, vec!).

terminal_title_setup_popup_live_only_snapshot298–315 ↗
async fn terminal_title_setup_popup_live_only_snapshot()

Purpose: Checks the terminal-title setup popup when every selected item has live data. It ensures users see realistic terminal-title previews while configuring the feature.

Data flow: The test creates a chat widget, seeds project, branch, thread, and task-progress values, and configures the terminal title to use those items. It renders the terminal-title setup popup and compares it with the saved snapshot.

Call relations: It uses cache_project_root for stable project text and the terminal title popup snapshot path through the snapshot assertion. This tests the visible popup rather than only the preview-building helper.

Call graph: calls 1 internal fn (cache_project_root); 2 external calls (assert_chatwidget_snapshot!, vec!).

terminal_title_setup_popup_hardcoded_only_snapshot318–330 ↗
async fn terminal_title_setup_popup_hardcoded_only_snapshot()

Purpose: Checks the terminal-title setup popup when no live values are present for the configured items. It verifies that fallback examples remain clear and stable.

Data flow: The test creates a fresh chat widget, configures the terminal title to include thread title, Git branch, and task progress, then renders and snapshots the setup popup.

Call relations: It sets configuration directly and then relies on the terminal title popup rendering helper through the snapshot assertion. This protects the empty-state version of the setup screen.

Call graph: 2 external calls (assert_chatwidget_snapshot!, vec!).

terminal_title_setup_popup_mixed_snapshot333–346 ↗
async fn terminal_title_setup_popup_mixed_snapshot()

Purpose: Checks the terminal-title setup popup when it has a mix of live thread data and fallback data for other items. This reflects a partial-information state users can hit in practice.

Data flow: The test creates a chat widget, sets a live thread name, configures the terminal title for project, thread, and task progress, then renders and snapshots the popup.

Call relations: It prepares just enough widget state to create a mixed preview. The snapshot assertion then captures the terminal-title setup UI so later changes are easy to spot.

Call graph: 2 external calls (assert_chatwidget_snapshot!, vec!).

terminal_title_setup_popup_rate_limits_snapshot349–361 ↗
async fn terminal_title_setup_popup_rate_limits_snapshot()

Purpose: Checks the terminal-title setup popup when rate-limit items are selected. It confirms that usage information is previewed properly for the terminal title.

Data flow: The test creates a chat widget, seeds fixed rate-limit data, configures the terminal title to show five-hour and weekly limits, then renders and snapshots the popup.

Call relations: It calls cache_rate_limit_snapshot, then uses the terminal-title popup rendering path through the snapshot assertion. This ties rate-limit formatting to the actual setup screen.

Call graph: calls 1 internal fn (cache_rate_limit_snapshot); 2 external calls (assert_chatwidget_snapshot!, vec!).

missing_project_root_uses_different_status_and_title_preview_sources364–372 ↗
async fn missing_project_root_uses_different_status_and_title_preview_sources()

Purpose: Checks that missing project-root data falls back differently for the status line and terminal title. This preserves the intended wording for each surface.

Data flow: The test creates a fresh chat widget without caching a project root. It asks for the project item in the status-line preview and the terminal-title preview, then asserts that the status line says "my-project" while the terminal title says "project".

Call relations: It calls status_preview_line and title_preview_line to compare the two preview paths side by side. The test documents that these two surfaces intentionally use different fallback sources.

Call graph: calls 2 internal fn (status_preview_line, title_preview_line); 1 external calls (assert_eq!).

terminal_title_preview_uses_title_truncation_for_live_values375–392 ↗
async fn terminal_title_preview_uses_title_truncation_for_live_values()

Purpose: Verifies that live thread and branch names are shortened using terminal-title-specific limits. This prevents very long names from making the terminal title hard to read.

Data flow: The test creates a chat widget, stores deliberately long thread and branch names, and builds a terminal-title preview for those two items. It separately applies the widget's title-part truncation helper with the expected limits, then asserts that the preview matches the shortened thread and branch joined with a separator.

Call relations: It uses title_preview_line to exercise the real title preview path and truncate_terminal_title_part to compute the expected result. The final equality assertion ensures the preview builder follows the same truncation rules.

Call graph: calls 1 internal fn (title_preview_line); 2 external calls (assert_eq!, truncate_terminal_title_part).

tui/src/chatwidget/tests/terminal_title.rssource ↗
testtest run

These tests check the terminal title as a status surface, meaning the title bar of the terminal is used like a small signpost for what the app needs from the user. The file focuses on one situation: the chat widget is busy running a task, then an execution approval request arrives. An execution approval request is the app asking the user, “May I run this command?”

Each test builds a chat widget in a controlled test setup, marks a task as running, creates a fake approval request, and then asks the widget to update just before drawing. The tests then inspect the last terminal title that the widget wanted to set.

The important behavior is subtle. While approval is pending, the title should show “Action Required” so the user can notice it even if they are looking at the terminal title instead of the main screen. If animations are enabled, the indicator may blink or spin. If the user’s settings disable title animation, the title should stay plain. If all animations are disabled, no activity indicator should animate, though the warning text can still appear.

Without these tests, a future change could accidentally hide an approval prompt, animate when the user asked it not to, or leave the title stuck in the urgent state after approval.

Function details4
terminal_title_shows_action_required_while_exec_approval_is_pending7–45 ↗
async fn terminal_title_shows_action_required_while_exec_approval_is_pending()

Purpose: This test checks the basic urgent-title behavior. When a command approval is waiting, the terminal title should say “Action Required”; after the user approves it, that urgent wording should go away and the normal running-task spinner can animate again.

Data flow: The test starts with a fresh chat widget, marks it as running a task, and refreshes the title. It then builds a fake command approval request using the current working directory, feeds that request into the chat widget, and triggers a pre-draw update. The expected result is a title like “[ ! ] Action Required | project” and no normal spinner animation. Then the test sends a simulated y key press, meaning the user approved the command, runs another pre-draw update, and checks that the title still names the project but no longer says “Action Required”.

Call relations: This function is run by the Tokio asynchronous test runner. Inside the story it relies on helpers to create the chat widget and submit the approval request, uses current_dir to give the fake command a real folder, uses a constructed key event to imitate the user pressing y, and finishes by using assertions to lock in the expected title and animation state.

Call graph: calls 1 internal fn (current_dir); 5 external calls (Char, new, assert!, assert_eq!, vec!).

terminal_title_action_required_respects_spinner_setting48–73 ↗
async fn terminal_title_action_required_respects_spinner_setting()

Purpose: This test checks that a user setting can keep the terminal title simple, even while approval is needed. The app should not force an animated or decorated title when the configured title format is just the project name.

Data flow: The test creates a chat widget, changes its terminal-title configuration to only include “project”, and marks a task as running. It then creates a fake command approval request in the current directory and gives it to the widget. After the pre-draw update, the output should be exactly “project”, and the action-required animation flag should be off.

Call relations: This function is also called by the Tokio test runner. It follows the same approval-request path as the other tests, but changes the title configuration before the request arrives. It uses current_dir for the fake command location and assertion calls to confirm that the configuration wins over the animated warning display.

Call graph: calls 1 internal fn (current_dir); 3 external calls (assert!, assert_eq!, vec!).

terminal_title_activity_indicators_do_not_animate_when_animations_are_disabled107–139 ↗
async fn terminal_title_activity_indicators_do_not_animate_when_animations_are_disabled()

Purpose: This test makes sure the global “animations off” setting is respected. Even if a task is running and an approval request appears, the title should not animate when animations are disabled.

Data flow: The test creates a chat widget and turns off animations in its configuration. It marks a task as running and sets the animation clock forward, but after refreshing the title the result should still be the plain project title and the spinner should not animate. Then it submits a fake approval request. After the pre-draw update, the title may show the fixed urgent text “[ ! ] Action Required | project”, but the action-required animation flag must remain off.

Call relations: This test is run by the Tokio test runner and exercises both running-task and approval-needed title states under the same disabled-animation setting. It uses now and from_millis to prove that elapsed animation time does not matter when animations are off, current_dir to build the fake request, and assertions to confirm the title text and animation decisions.

Call graph: calls 1 internal fn (current_dir); 5 external calls (now, assert!, assert_eq!, from_millis, vec!).

Rendering primitives and transcript formatting

These lower-level rendering tests validate markdown, history-cell formatting, layout allocation, status output, and token-activity visualizations used by the TUI.

tui/src/chatwidget/tokens/chart/palette_tests.rssource ↗
testtest run

The token activity chart is a small visual display in the terminal UI. To look right, it needs a palette: colors for empty cells, low activity, high activity, and chart bars. This test file checks that the palette-building code makes sensible choices depending on what the terminal can show and what colors the current theme provides.

The tests cover both rich color terminals and simpler terminals. A “truecolor” terminal can show exact red-green-blue colors, so the palette can blend the theme’s accent color with the terminal background to create smooth intensity levels. A simpler “ANSI 16” terminal only has a small fixed color set, so the code should avoid pretending it can create subtle shades.

The file also checks fallback behavior. If the theme’s accent color is not an exact RGB color, or if the terminal does not report enough default colors, the palette should use the active theme style directly instead of inventing colors. Think of it like painting a heat map: when you have a full paint set, you mix shades; when you only have a few markers, you use the marker the theme gave you.

Function details5
truecolor_palette_blends_theme_accent_against_dark_background7–35 ↗
fn truecolor_palette_blends_theme_accent_against_dark_background()

Purpose: This test checks that, on a truecolor terminal with a dark background, the token chart creates a smooth palette by blending the theme accent color against that dark background. It also confirms that the palette records that it is using custom color blending.

Data flow: The test starts with a light default foreground, a black default background, and a green RGB accent style. It builds a TokenActivityPalette from those pieces, then asks for styles at several activity levels. The expected result is that empty and low levels are dark blended shades, the highest level matches the accent color, the bar color is a slightly dimmer accent shade, and the palette says color blending is active.

Call relations: During the test, this function calls the palette builder, TokenActivityPalette::from_parts, after creating RGB colors with rgb_color. It then uses assertions to compare the palette’s answers with the exact colors expected for a dark-background truecolor setup.

Call graph: calls 2 internal fn (from_parts, rgb_color); 3 external calls (default, assert!, assert_eq!).

truecolor_palette_blends_empty_cell_for_light_background38–58 ↗
fn truecolor_palette_blends_empty_cell_for_light_background()

Purpose: This test checks that the palette also works on a truecolor terminal with a light background. In particular, it makes sure an empty chart cell is blended toward a light gray instead of becoming too dark or visually heavy.

Data flow: The test provides a black default foreground, a white default background, and a blue RGB accent style. It builds the palette and checks the style for an empty level and the strongest activity level. The output should be a light gray for empty cells, the original accent color for maximum activity, and a flag showing that custom color blending is being used.

Call relations: This test exercises the same palette-building path as the dark-background test, but with opposite terminal colors. It calls rgb_color to make exact RGB values, passes them into TokenActivityPalette::from_parts, and then verifies the resulting styles with assertions.

Call graph: calls 2 internal fn (from_parts, rgb_color); 3 external calls (default, assert!, assert_eq!).

ansi16_palette_uses_theme_accent_without_green_fallback61–76 ↗
fn ansi16_palette_uses_theme_accent_without_green_fallback()

Purpose: This test checks behavior on a limited 16-color terminal. It ensures the chart uses the theme’s accent style directly for active cells instead of falling back to an unrelated default color such as green.

Data flow: The test gives the palette a dark terminal background, a magenta active style, and a terminal color level that only supports 16 basic colors. After building the palette, it checks that level 0 is just a dim default style, while active levels and bar levels use the magenta active style. The palette should report that it is not doing custom truecolor blending.

Call relations: This function calls TokenActivityPalette::from_parts with an ANSI 16 color setting to force the fallback path. The assertions then confirm that the palette hands back the theme-provided active style rather than trying to calculate blended RGB shades.

Call graph: calls 1 internal fn (from_parts); 3 external calls (default, assert!, assert_eq!).

non_rgb_theme_accent_remains_active_fallback79–98 ↗
fn non_rgb_theme_accent_remains_active_fallback()

Purpose: This test checks what happens when the terminal supports truecolor but the theme accent is not written as an exact RGB value. The palette should keep using the active style as-is, including bold text, instead of trying to blend a color it cannot precisely read.

Data flow: The test supplies normal terminal colors and an active style using a named color, cyan, rather than numeric RGB values. It builds the palette and asks for an active level. The result should be exactly the active style, still bold, and the palette should say it is not using custom blended colors.

Call relations: This test reaches the palette builder with truecolor support enabled, but with a non-RGB accent. That combination should send the palette down its safe fallback route. The test then checks both the returned style and its bold modifier to make sure no styling was lost.

Call graph: calls 1 internal fn (from_parts); 3 external calls (default, assert!, assert_eq!).

missing_terminal_colors_use_theme_accent_fallback101–115 ↗
fn missing_terminal_colors_use_theme_accent_fallback()

Purpose: This test checks that the palette behaves safely when the terminal does not provide all the color information needed for blending. If a default foreground or background is missing, the chart should fall back to simple theme styles.

Data flow: The test leaves the default foreground color unknown, provides a black background, and uses a blue bold active style. It builds the palette and checks that empty cells get a dim default style while strong activity gets the blue active style. The palette should report that custom color blending is not in use.

Call relations: This function calls TokenActivityPalette::from_parts with incomplete terminal color data. That setup should prevent the color-mixing path from running, and the assertions confirm that the palette falls back to predictable default and active styles.

Call graph: calls 1 internal fn (from_parts); 3 external calls (default, assert!, assert_eq!).

tui/src/chatwidget/tokens/chart_tests.rssource ↗
testtest run

This is a test file for the token-usage chart in the text user interface. The chart is the small terminal drawing that lets a user see daily, weekly, or cumulative token activity, plus a short summary such as lifetime tokens and streaks. These tests protect the user-facing output: if spacing, symbols, totals, or captions change by accident, the tests catch it.

The file builds small fake usage histories, using dates and token counts, then asks the chart code to turn them into display lines. Some tests check simple facts, such as whether duplicate dates are added together or whether a typed view name like “week” is understood. Other tests use snapshot testing, which means the expected terminal output is stored directly in the test. It is like comparing a printed receipt against a known-good receipt.

The important behavior here is visual as much as mathematical. Empty days and active days must use different symbols. Wide terminals should not stretch the graph awkwardly. Weekly and cumulative views should draw bars with the right height and caption. The summary line should stay readable and split across lines only when space is tight.

Function details8
duplicate_dates_sum_and_negative_values_clamp8–29 ↗
fn duplicate_dates_sum_and_negative_values_clamp()

Purpose: This test makes sure daily token totals are cleaned up before being drawn. If the input has two records for the same date, they should be added together, and negative token counts should not reduce the visible total.

Data flow: It starts with a fixed “today” date and three fake daily records: two for the same day with positive token counts, and one previous day with a negative count. It passes those records into the daily value calculation. The result is checked by summing all returned values; the final total must be 15, meaning the two positive entries were combined and the negative value did not subtract from the total.

Call relations: During the test run, the Rust test harness calls this function. The test then calls the date constructor to create a stable date, builds sample records, hands them to the chart calculation code, and uses an equality assertion to confirm the cleanup rule.

Call graph: 3 external calls (from_ymd_opt, assert_eq!, vec!).

bar_levels_fill_from_bottom32–37 ↗
fn bar_levels_fill_from_bottom()

Purpose: This test checks how numeric values become bar heights for a terminal bar chart. It confirms that an empty value produces no filled cells, while the maximum value fills the bar to the top.

Data flow: It gives the bar-level calculation two values: 0 and 10. The returned level list is then split into the cells for each value. The first value’s cells must all be empty levels, and the second value’s cells must all be full levels.

Call relations: The test harness calls this test when the suite runs. The test exercises the bar-level helper and then uses equality checks to make sure the visual bars will be built from the bottom upward rather than appearing inverted or partly filled in the wrong place.

Call graph: 1 external calls (assert_eq!).

token_activity_view_aliases_parse40–55 ↗
fn token_activity_view_aliases_parse()

Purpose: This test checks that user-entered names for chart views are interpreted correctly. It protects the small command-language around the chart, such as treating “day” as the daily view and rejecting unknown words.

Data flow: It feeds several strings into the view parser: an empty string, “day”, “week”, “cumulative”, and “year”. The parser should return the matching chart view for the accepted words and return nothing for “year”, because that is not a supported view.

Call relations: The test harness calls this function. The function calls the view parser repeatedly and uses equality assertions to verify that the parser’s public behavior matches the names a user is expected to type.

Call graph: 1 external calls (assert_eq!).

daily_graph_snapshot_uses_distinct_empty_and_active_cells58–91 ↗
fn daily_graph_snapshot_uses_distinct_empty_and_active_cells()

Purpose: This test verifies the exact daily chart shown to the user when only a couple of days have activity. It especially checks that inactive days and active days use visibly different symbols.

Data flow: It creates a fixed date and two fake usage records, one earlier in the week and one on today. It asks the chart code to render the daily view at a narrow width, trims trailing spaces from each line, joins the lines into one text block, and compares that block to the expected snapshot.

Call relations: The test harness runs this as part of the chart test suite. The test prepares sample input, hands it to the chart renderer, and then passes the rendered text to the snapshot assertion so any accidental change in symbols, month labels, weekday rows, legend, or spacing is noticed.

Call graph: 3 external calls (from_ymd_opt, assert_snapshot!, vec!).

daily_graph_snapshot_stays_left_aligned_in_wide_terminal94–112 ↗
fn daily_graph_snapshot_stays_left_aligned_in_wide_terminal()

Purpose: This test makes sure the daily graph remains readable on very wide terminals. It protects against the chart being stretched or centered in a way that would make it harder to scan.

Data flow: It first checks the graph width chosen for a normal wide terminal and for the largest possible terminal width. Then it renders an empty daily chart at width 160, keeps a few representative lines, trims trailing spaces, joins them, and compares the result to a stored snapshot.

Call relations: The test harness calls this test. The test checks the width-limiting helper first, then calls the chart renderer with no usage data, and finally uses a snapshot assertion to confirm that the month labels, first weekday row, and view selector stay left-aligned.

Call graph: 3 external calls (from_ymd_opt, assert_eq!, assert_snapshot!).

weekly_graph_snapshot_renders_bar_chart_and_caption115–157 ↗
fn weekly_graph_snapshot_renders_bar_chart_and_caption()

Purpose: This test checks the weekly token-usage view. It confirms that daily records are grouped into week-sized columns, drawn as a bar chart, and explained with the right caption.

Data flow: It creates three weekly-spaced usage records with increasing token counts. It renders the weekly chart at a narrow width, turns the rendered lines into a single text block, and compares that text to the expected snapshot. The expected output includes bars, month labels, a maximum marker, a zero marker, and a caption saying each column represents one week.

Call relations: The test harness invokes this test during the suite. The test supplies controlled input to the chart renderer and uses snapshot comparison to guard the complete visible output of the weekly mode.

Call graph: 3 external calls (from_ymd_opt, assert_snapshot!, vec!).

cumulative_graph_snapshot_renders_running_total_bar_chart_and_caption160–202 ↗
fn cumulative_graph_snapshot_renders_running_total_bar_chart_and_caption()

Purpose: This test checks the cumulative token-usage view, where each bar shows the running total so far instead of that week’s separate amount. It protects the difference between “weekly amount” and “total over time.”

Data flow: It builds the same three dated usage records used by the weekly test. It renders the cumulative view, trims and joins the output lines, and compares them with the stored snapshot. The expected bars rise according to the running total, and the caption reports the top cumulative value.

Call relations: The test harness calls this function. The test feeds sample data into the chart renderer in cumulative mode and hands the resulting text to the snapshot assertion, making sure this view keeps its own bar heights and explanatory caption.

Call graph: 3 external calls (from_ymd_opt, assert_snapshot!, vec!).

summary_snapshot_left_aligns_and_splits_when_needed205–243 ↗
fn summary_snapshot_left_aligns_and_splits_when_needed()

Purpose: This test checks the short token-usage summary line shown near the chart. It makes sure large numbers and long durations are formatted clearly, and that the line splits only when the available width is too small.

Data flow: It creates a fake usage response containing lifetime tokens, peak daily tokens, a longest task duration, and streak counts. A small helper inside the test renders the summary for different terminal widths. The test combines the wide, narrow, and tight versions into one text block and compares it to a snapshot.

Call relations: The test harness runs this test with the others. The test calls the summary-rendering code through its local rendering helper and uses snapshot comparison to confirm both formatting and wrapping behavior across several terminal widths.

Call graph: 1 external calls (assert_snapshot!).

tui/src/chatwidget/tokens_tests.rssource ↗
testtest run

The token activity widget shows account token usage over time. To draw a chart, it needs an anchor date: the date treated as “today.” This test checks that the anchor date is frozen at the moment loading finishes, instead of being recalculated later.

The test starts with token activity in a Loading state, wrapped in shared thread-safe storage. That storage uses an Arc, which lets multiple parts of the program share ownership, and an RwLock, which is a lock that allows safe reading or writing from different places. It then creates a TokenActivityHandle, which is the small object used to update that shared state.

Next, the test chooses a fixed date, May 29, 2026, and calls finish_with_today with a successful but mostly empty usage response. The usage numbers themselves are not the focus here. The important part is that finish_with_today receives the chosen date.

Finally, the test reads the state back. If the state became Loaded, it checks that the stored today value exactly matches the date passed in. If the state is anything else, the test fails. In plain terms, this is like checking that a receipt keeps the checkout date printed on it, rather than changing whenever someone looks at it later.

Function details1
loaded_state_freezes_chart_anchor_date_at_completion6–38 ↗
fn loaded_state_freezes_chart_anchor_date_at_completion()

Purpose: This test proves that completing token-usage loading stores the supplied date as the chart’s fixed “today” date. Someone would rely on this to make sure the token chart remains stable and predictable after data has loaded.

Data flow: It starts with shared token activity state set to Loading, then builds a handle that can update that state. It creates a fixed calendar date and passes it, along with a successful empty usage response, into finish_with_today. After that, it reads the shared state and expects to find a Loaded state whose stored today date is exactly the same fixed date; otherwise the test fails.

Call relations: During the test run, the test framework calls this function. Inside it, the function uses shared-state setup helpers, creates a date, asks the token activity handle to finish loading, and then uses an equality assertion to confirm the result. If finish_with_today ever stops preserving the supplied date, this test catches that regression.

Call graph: 6 external calls (clone, new, from_ymd_opt, new, assert_eq!, panic!).

tui/src/history_cell/tests.rssource ↗
testtest suite

The terminal UI is built from “history cells,” which are small blocks of past conversation or activity. This test file checks that those blocks look right when rendered to terminal lines. It covers rich display mode, raw copy-friendly mode, transcript output, word wrapping, links, blank lines, image summaries, background terminal interactions, MCP tool output, session information, and command execution summaries.

Many tests create a cell, ask it for display lines at a chosen terminal width, turn those styled terminal lines into plain strings, and compare the result with an expected value or a saved snapshot. This is like taking screenshots of receipts printed by many different receipt printers: the tests make sure the spacing, indentation, labels, and wrapping stay readable.

The helper functions build small fake configs, fake server settings, fake tool results, and simplified render output so the tests can focus on behavior instead of setup. The important thing this file guards is trust in the transcript. If these tests were missing, changes could silently break copying raw text, hide links, leak sensitive config values, leave stale terminal characters behind, or make long commands and URLs unreadable.

Function details111
test_config33–40 ↗
async fn test_config() -> Config

Purpose: Builds a minimal test configuration using the system temporary directory as the Codex home. Tests use it when they need realistic configuration without touching a real user setup.

Data flow: It reads the temporary directory path, feeds it into a config builder, waits for the builder to finish, and returns the finished config. If building fails, the test stops immediately.

Call relations: Session-info and MCP-tools tests call this first so they can pass a believable config into the history-cell constructors they are exercising.

Call graph: called by 7 (mcp_tools_output_lists_tools_for_hyphenated_server_names, mcp_tools_output_masks_sensitive_values, reasoning_summary_block_respects_config_overrides, session_info_availability_nux_tooltip_snapshot, session_info_first_event_suppresses_tooltips_and_nux, session_info_hides_tooltips_when_disabled, session_info_uses_availability_nux_tooltip_override); 2 external calls (default, temp_dir).

test_cwd42–46 ↗
fn test_cwd() -> PathBuf

Purpose: Returns a stable absolute working directory for tests. It avoids relying on Unix or Windows root path rules.

Data flow: It asks the operating system for the temporary directory and returns that path. Nothing else is changed.

Call relations: Markdown, plan, reasoning, and consolidation tests use this path when creating cells that need a current directory for link or path formatting.

Call graph: called by 17 (agent_markdown_cell_does_not_split_words_after_inline_markdown, agent_markdown_cell_narrow_width_shows_prefix_only, agent_markdown_cell_renders_source_at_different_widths, agent_markdown_cell_survives_insert_history_rewrap, consolidation_walker_replaces_agent_message_cells, proposed_plan_cell_preserves_wrapped_table_web_links, proposed_plan_cell_renders_markdown_table, proposed_plan_cell_unwraps_markdown_fenced_table, reasoning_summary_block, reasoning_summary_block_falls_back_when_header_is_missing (+7 more)); 1 external calls (temp_dir).

streaming_agent_tail_blank_line_uses_one_viewport_row49–64 ↗
fn streaming_agent_tail_blank_line_uses_one_viewport_row()

Purpose: Checks that a blank line in streamed assistant text occupies exactly one visible row. This prevents the UI from over-counting empty lines and leaving odd gaps.

Data flow: It creates a streaming assistant-tail cell with text, a blank line, and more text, renders it, and compares both the visible output and desired height.

Call relations: This directly exercises the streaming tail cell’s line rendering and height calculation.

Call graph: calls 1 internal fn (new); 3 external calls (assert_eq!, assert_snapshot!, vec!).

stdio_server_config66–105 ↗
fn stdio_server_config(
    command: &str,
    args: Vec<&str>,
    env: Option<HashMap<String, String>>,
    env_vars: Vec<&str>,
) -> McpServerConfig

Purpose: Creates a fake MCP server configuration for a server launched through standard input/output. MCP means Model Context Protocol, a way for Codex to talk to external tools.

Data flow: It receives a command, optional arguments, fixed environment values, and environment-variable names, builds a TOML table from them, and converts that table into an MCP server config.

Call relations: MCP tools-output tests use this helper to set up local tool servers, especially when checking display and secret masking.

Call graph: calls 1 internal fn (string_map_to_toml_value); called by 2 (mcp_tools_output_lists_tools_for_hyphenated_server_names, mcp_tools_output_masks_sensitive_values); 4 external calls (new, Array, String, Table).

streamable_http_server_config107–137 ↗
fn streamable_http_server_config(
    url: &str,
    bearer_token_env_var: Option<&str>,
    http_headers: Option<HashMap<String, String>>,
    env_http_headers: Option<HashMap<String, String>>,
) ->

Purpose: Creates a fake MCP server configuration for a server reached over HTTP. It lets tests describe URLs, bearer-token environment variables, and headers without writing full config files.

Data flow: It receives HTTP settings, builds a TOML table, converts any header maps into TOML values, and returns a deserialized MCP server config.

Call relations: The sensitive-value masking test uses this alongside the stdio config helper to verify both server styles are displayed safely.

Call graph: calls 1 internal fn (string_map_to_toml_value); called by 1 (mcp_tools_output_masks_sensitive_values); 3 external calls (new, String, Table).

string_map_to_toml_value139–146 ↗
fn string_map_to_toml_value(entries: HashMap<String, String>) -> toml::Value

Purpose: Turns a plain string-to-string map into a TOML table value. TOML is the configuration format used by these test configs.

Data flow: It takes each key and value from the map, wraps the value as a TOML string, collects them into a table, and returns that table as a TOML value.

Call relations: Both MCP config helpers call this when they need to include environment variables or HTTP headers.

Call graph: called by 2 (stdio_server_config, streamable_http_server_config); 1 external calls (Table).

render_lines148–158 ↗
fn render_lines(lines: &[Line<'static>]) -> Vec<String>

Purpose: Converts styled terminal lines into plain strings so tests can compare what a person would read. It ignores color and formatting.

Data flow: It receives a list of terminal lines, joins the text content of each line’s spans, and returns a vector of plain strings.

Call relations: Most rendering tests call this after asking a cell for display lines, because it gives a simple comparison target.

Call graph: called by 68 (active_mcp_tool_call_snapshot, agent_markdown_cell_does_not_split_words_after_inline_markdown, agent_markdown_cell_narrow_width_shows_prefix_only, agent_markdown_cell_renders_source_at_different_widths, agent_markdown_cell_survives_insert_history_rewrap, coalesced_reads_dedupe_names, coalesces_reads_across_multiple_calls, coalesces_sequential_reads_within_one_call, completed_mcp_tool_call_accepts_data_url_image_blocks, completed_mcp_tool_call_error_snapshot (+15 more)); 1 external calls (iter).

render_transcript160–162 ↗
fn render_transcript(cell: &dyn HistoryCell) -> Vec<String>

Purpose: Gets the transcript version of a history cell as plain strings. The transcript is the copy/log form of the UI history.

Data flow: It asks the cell for transcript lines using a very wide width, then passes those lines through the plain-string renderer.

Call relations: Transcript-focused tests call this to check that cells produce stable, readable log output separate from rich on-screen rendering.

Call graph: calls 2 internal fn (transcript_lines, render_lines); called by 11 (reasoning_summary_block, reasoning_summary_block_falls_back_when_header_is_missing, reasoning_summary_block_falls_back_when_summary_is_missing, reasoning_summary_block_returns_reasoning_cell_when_feature_disabled, reasoning_summary_block_splits_header_and_summary_when_present, session_info_availability_nux_tooltip_snapshot, session_info_first_event_suppresses_tooltips_and_nux, session_info_hides_tooltips_when_disabled, session_info_uses_availability_nux_tooltip_override, unified_exec_interaction_cell_renders_input (+1 more)).

assert_unstyled_lines164–171 ↗
fn assert_unstyled_lines(lines: &[Line<'static>])

Purpose: Verifies that lines contain no terminal styling. This matters for raw mode, where copied text should not carry display decoration.

Data flow: It walks through every line and span and asserts that each style equals the default empty style.

Call relations: Raw-source and raw-tool-output tests call this after rendering to make sure raw output is plain text only.

Call graph: called by 3 (raw_lines_from_source_preserves_explicit_blank_lines, source_backed_cells_render_raw_source_without_prefix_or_style, structured_tool_cell_renders_raw_plain_text_without_prefix_or_style); 1 external calls (assert_eq!).

image_block173–176 ↗
fn image_block(data: &str) -> serde_json::Value

Purpose: Builds a serialized MCP image content block for tests. It lets tool-call tests simulate tools returning image data.

Data flow: It receives image data, wraps it as PNG content, serializes it to JSON, and returns the JSON value.

Call relations: Completed MCP tool-call tests use this to check that image results produce separate image cells and skip invalid image blocks.

Call graph: 2 external calls (image, to_value).

text_block178–180 ↗
fn text_block(text: &str) -> serde_json::Value

Purpose: Builds a serialized MCP text content block for tests. It is a small shortcut for fake tool results.

Data flow: It receives text, wraps it as MCP text content, serializes it to JSON, and returns the JSON value.

Call relations: Many MCP tool-call tests use this helper when constructing successful tool responses.

Call graph: 2 external calls (text, to_value).

raw_lines_from_source_preserves_explicit_blank_lines202–210 ↗
fn raw_lines_from_source_preserves_explicit_blank_lines()

Purpose: Checks that raw source rendering keeps intentional blank lines. This protects copy-paste behavior.

Data flow: It passes source text with an empty line into the raw-line parser, converts the result to strings, and checks both content and lack of styling.

Call relations: This tests the shared raw-line conversion used by source-backed cells such as user prompts and assistant markdown.

Call graph: calls 1 internal fn (assert_unstyled_lines); 1 external calls (assert_eq!).

raw_lines_from_source_preserves_trailing_blank_but_not_trailing_newline213–219 ↗
fn raw_lines_from_source_preserves_trailing_blank_but_not_trailing_newline()

Purpose: Checks the fine distinction between a meaningful trailing blank line and a final newline character. This avoids adding or losing copyable lines.

Data flow: It parses source strings with trailing newlines and compares the resulting raw lines to the expected list.

Call relations: This directly validates the raw source parser that other cells rely on for raw mode.

Call graph: 1 external calls (assert_eq!).

source_backed_cells_render_raw_source_without_prefix_or_style222–287 ↗
fn source_backed_cells_render_raw_source_without_prefix_or_style()

Purpose: Verifies that user, assistant, reasoning, and proposed-plan cells expose their original source in raw mode. Raw mode should not include bullets, gutters, or colors.

Data flow: It creates several source-backed cells, asks each for raw lines, converts them to strings, and checks that blank lines and text are preserved without styles.

Call relations: It uses the shared current-directory helper and unstyled assertion to check several cell types together.

Call graph: calls 4 internal fn (new, new, assert_unstyled_lines, test_cwd); 2 external calls (new, assert_eq!).

proposed_plan_cell_renders_markdown_table290–314 ↗
fn proposed_plan_cell_renders_markdown_table()

Purpose: Checks that a proposed plan containing a Markdown table is shown as a rich table on screen. It also confirms raw mode still preserves the original table text.

Data flow: It creates a proposed-plan cell, renders rich display lines, looks for table separator characters, then renders raw lines and checks the Markdown header remains.

Call relations: This connects the plan cell to the Markdown renderer and raw-source path.

Call graph: calls 2 internal fn (render_lines, test_cwd); 1 external calls (assert!).

proposed_plan_cell_unwraps_markdown_fenced_table358–375 ↗
fn proposed_plan_cell_unwraps_markdown_fenced_table()

Purpose: Verifies that a table wrapped inside a Markdown code fence marked as Markdown is still rendered as a table. This avoids showing the fence itself as code.

Data flow: It creates a proposed plan with a fenced Markdown table, renders it, and checks that table decoration appears while the fence marker does not.

Call relations: This protects special preprocessing in proposed-plan rendering before it reaches the Markdown renderer.

Call graph: calls 2 internal fn (render_lines, test_cwd); 1 external calls (assert!).

structured_tool_cell_renders_raw_plain_text_without_prefix_or_style378–405 ↗
fn structured_tool_cell_renders_raw_plain_text_without_prefix_or_style()

Purpose: Checks that a completed MCP tool call has a clean raw version: the call summary plus the tool’s plain text output. This supports copying tool results.

Data flow: It creates an active tool-call cell, completes it with text output, asks for raw lines, and checks the lines and styles.

Call relations: This uses the MCP tool-call completion path and then validates the raw-mode output path.

Call graph: calls 2 internal fn (assert_unstyled_lines, render_lines); 4 external calls (assert!, assert_eq!, json!, vec!).

raw_mode_toggle_transcript_snapshot408–466 ↗
fn raw_mode_toggle_transcript_snapshot()

Purpose: Records how a small transcript looks when switching between rich mode and raw mode, then back to rich. This catches accidental state changes during toggling.

Data flow: It creates user, assistant, and tool cells, renders all of them in rich, raw, and rich modes, joins the text, and compares it to a snapshot.

Call relations: This test exercises the common display-lines-for-mode path across multiple cell types.

Call graph: 5 external calls (assert!, format!, assert_snapshot!, json!, vec!).

image_generation_call_renders_saved_path469–490 ↗
fn image_generation_call_renders_saved_path()

Purpose: Checks that an image-generation history cell shows both the prompt/description and the saved file path. The path is shown as a file URL.

Data flow: It creates an image-generation cell with a saved path, renders it, and compares the three expected output lines.

Call relations: This directly tests the image-generation cell constructor and display rendering.

Call graph: 2 external calls (assert_eq!, format!).

session_configured_event492–515 ↗
fn session_configured_event(model: &str) -> ThreadSessionState

Purpose: Builds a fake session state for session-header tests. It supplies realistic model, permission, directory, and thread information.

Data flow: It receives a model name, fills a thread session state with fixed test values, and returns it.

Call relations: Session-info tests pass this fake state into the session-info cell so they can focus on the rendered text.

Call graph: calls 2 internal fn (read_only, new); called by 4 (session_info_availability_nux_tooltip_snapshot, session_info_first_event_suppresses_tooltips_and_nux, session_info_hides_tooltips_when_disabled, session_info_uses_availability_nux_tooltip_override); 2 external calls (new, new).

unified_exec_interaction_cell_renders_input518–529 ↗
fn unified_exec_interaction_cell_renders_input()

Purpose: Checks how the UI records text sent to a background terminal. It should show the related command and the entered lines.

Data flow: It creates an interaction cell with a command label and multi-line input, renders the transcript, and compares the expected lines.

Call relations: This tests transcript output for background terminal interaction cells.

Call graph: calls 1 internal fn (render_transcript); 1 external calls (assert_eq!).

unified_exec_interaction_cell_renders_wait532–536 ↗
fn unified_exec_interaction_cell_renders_wait()

Purpose: Checks the simpler background-terminal case where the user only waited. The UI should say that clearly.

Data flow: It creates an interaction cell with no command label and no input, renders the transcript, and checks for the wait message.

Call relations: This covers the alternate branch of the same background terminal interaction cell.

Call graph: calls 1 internal fn (render_transcript); 2 external calls (new, assert_eq!).

final_message_separator_hides_short_worked_label_and_includes_runtime_metrics539–584 ↗
fn final_message_separator_hides_short_worked_label_and_includes_runtime_metrics()

Purpose: Verifies that short tasks do not show a “Worked for” label, but still show runtime metrics. This keeps the final separator useful without clutter.

Data flow: It builds runtime metrics, creates a final-message separator, renders it, and checks for metric text and absence of the short worked label.

Call relations: This tests the final separator’s summary formatting with performance data.

Call graph: calls 2 internal fn (new, render_lines); 2 external calls (assert!, assert_eq!).

final_message_separator_includes_worked_label_after_one_minute587–593 ↗
fn final_message_separator_includes_worked_label_after_one_minute()

Purpose: Checks that the final separator mentions work duration once the duration is long enough. This gives users useful context for longer runs.

Data flow: It creates a separator with a duration over one minute, renders it, and checks that the worked label appears.

Call relations: This complements the short-duration separator test.

Call graph: calls 2 internal fn (new, render_lines); 2 external calls (assert!, assert_eq!).

ps_output_empty_snapshot596–600 ↗
fn ps_output_empty_snapshot()

Purpose: Records how the background-process output looks when there are no processes. This prevents regressions in the empty state.

Data flow: It creates a process-output cell with an empty list, renders it at a fixed width, and snapshots the text.

Call relations: This exercises the unified exec process list display path.

Call graph: calls 1 internal fn (render_lines); 2 external calls (new, assert_snapshot!).

session_info_uses_availability_nux_tooltip_override603–617 ↗
async fn session_info_uses_availability_nux_tooltip_override()

Purpose: Checks that a model-availability tooltip override appears in session info when allowed. NUX means “new user experience,” a helpful onboarding hint.

Data flow: It builds config and session state, creates a session-info cell with tooltip text, renders the transcript, and checks that the text appears.

Call relations: This uses the test config and fake session state helpers to exercise session-info rendering.

Call graph: calls 3 internal fn (render_transcript, session_configured_event, test_config); 1 external calls (assert!).

session_info_availability_nux_tooltip_snapshot624–639 ↗
async fn session_info_availability_nux_tooltip_snapshot()

Purpose: Snapshots the full session-info text when a model-availability tooltip is shown. This captures path and onboarding formatting.

Data flow: It builds config, sets the working directory, creates the session-info cell, renders the transcript, and snapshots it.

Call relations: This is a broader snapshot version of the tooltip override test.

Call graph: calls 3 internal fn (render_transcript, session_configured_event, test_config); 1 external calls (assert_snapshot!).

session_info_first_event_suppresses_tooltips_and_nux642–657 ↗
async fn session_info_first_event_suppresses_tooltips_and_nux()

Purpose: Checks that the first session event shows the normal getting-started text instead of availability tooltips. This avoids overwhelming startup output.

Data flow: It creates first-event session info with tooltip text, renders the transcript, and verifies the tooltip is absent while startup guidance is present.

Call relations: This tests the first-event branch of session-info rendering.

Call graph: calls 3 internal fn (render_transcript, session_configured_event, test_config); 1 external calls (assert!).

session_info_hides_tooltips_when_disabled660–675 ↗
async fn session_info_hides_tooltips_when_disabled()

Purpose: Ensures user configuration can disable tooltips. If tooltips are off, the availability message should not appear.

Data flow: It builds config, turns off tooltip display, renders session info, and checks that the tooltip text is missing.

Call relations: This connects configuration settings to session-info output.

Call graph: calls 3 internal fn (render_transcript, session_configured_event, test_config); 1 external calls (assert!).

ps_output_multiline_snapshot678–691 ↗
fn ps_output_multiline_snapshot()

Purpose: Snapshots background-process output when commands and recent output chunks span multiple lines. This protects indentation and grouping.

Data flow: It creates process details with multi-line command text and chunks, renders the process-output cell, and snapshots the result.

Call relations: This exercises the process list renderer with realistic multi-line content.

Call graph: calls 1 internal fn (render_lines); 2 external calls (assert_snapshot!, vec!).

cyber_policy_error_event_snapshot694–698 ↗
fn cyber_policy_error_event_snapshot()

Purpose: Records the normal-width rendering of a cyber-policy error message. This keeps policy-block messages readable.

Data flow: It creates the policy-error cell, renders it at a wider width, and snapshots the output.

Call relations: This directly tests the cyber-policy error cell display.

Call graph: calls 1 internal fn (render_lines); 1 external calls (assert_snapshot!).

cyber_policy_error_event_narrow_snapshot701–705 ↗
fn cyber_policy_error_event_narrow_snapshot()

Purpose: Records the narrow-width rendering of a cyber-policy error message. This protects wrapping on small terminals.

Data flow: It creates the same error cell, renders it at a narrow width, and snapshots the output.

Call relations: This complements the normal-width policy-error snapshot.

Call graph: calls 1 internal fn (render_lines); 1 external calls (assert_snapshot!).

ps_output_long_command_snapshot708–717 ↗
fn ps_output_long_command_snapshot()

Purpose: Checks how a very long background command is shown. Long commands need careful wrapping so they remain understandable.

Data flow: It creates one process with a long command and a recent chunk, renders at a narrow width, and snapshots the result.

Call relations: This covers the long-command branch of process-output rendering.

Call graph: calls 1 internal fn (render_lines); 2 external calls (assert_snapshot!, vec!).

ps_output_many_sessions_snapshot720–731 ↗
fn ps_output_many_sessions_snapshot()

Purpose: Snapshots the process-output view when many background sessions exist. This guards the layout used for long process lists.

Data flow: It builds twenty fake process entries, renders the output cell, and snapshots the text.

Call relations: This tests scaling behavior of the unified exec process list display.

Call graph: calls 1 internal fn (render_lines); 1 external calls (assert_snapshot!).

ps_output_chunk_leading_whitespace_snapshot734–744 ↗
fn ps_output_chunk_leading_whitespace_snapshot()

Purpose: Checks that recent output chunks with leading spaces keep that spacing. Leading spaces can be meaningful in command output.

Data flow: It creates one process with indented chunks, renders it, and snapshots the result.

Call relations: This protects whitespace handling in process-output rendering.

Call graph: calls 1 internal fn (render_lines); 2 external calls (assert_snapshot!, vec!).

error_event_oversized_input_snapshot747–753 ↗
fn error_event_oversized_input_snapshot()

Purpose: Snapshots how an oversized-input error is displayed. This ensures a common user-facing error stays clear.

Data flow: It creates an error-event cell with a length-limit message, renders it, and snapshots the text.

Call relations: This tests generic error-event rendering.

Call graph: calls 1 internal fn (render_lines); 1 external calls (assert_snapshot!).

mcp_tools_output_masks_sensitive_values756–819 ↗
async fn mcp_tools_output_masks_sensitive_values()

Purpose: Checks that MCP tools output does not reveal secrets from environment values, bearer tokens, or headers. This is a safety test.

Data flow: It builds fake stdio and HTTP server configs containing secret-looking values, creates fake tools, renders the tools output, and snapshots it.

Call relations: This combines the test config helpers and MCP tools-output cell to verify secret masking across server types.

Call graph: calls 4 internal fn (render_lines, stdio_server_config, streamable_http_server_config, test_config); 4 external calls (new, assert_snapshot!, json!, vec!).

mcp_tools_output_lists_tools_for_hyphenated_server_names822–859 ↗
async fn mcp_tools_output_lists_tools_for_hyphenated_server_names()

Purpose: Checks that tools are listed correctly for MCP servers whose names contain hyphens. Internally, names may appear with underscores, so this avoids mismatches.

Data flow: It adds a hyphenated server config, creates a matching tool name with underscores, renders the tools output, and snapshots it.

Call relations: This tests name matching between configuration and reported MCP tools.

Call graph: calls 3 internal fn (render_lines, stdio_server_config, test_config); 5 external calls (from, new, assert_snapshot!, json!, vec!).

mcp_tools_output_from_statuses_renders_status_only_servers862–889 ↗
fn mcp_tools_output_from_statuses_renders_status_only_servers()

Purpose: Checks that MCP output can render servers described only by status data. This matters when no full config is available.

Data flow: It builds a server-status object with one tool, asks for a tools-and-auth-only cell, renders it, and snapshots the result.

Call relations: This tests the status-based MCP inventory display path.

Call graph: calls 1 internal fn (render_lines); 2 external calls (assert_snapshot!, vec!).

mcp_tools_output_from_statuses_renders_verbose_inventory892–935 ↗
fn mcp_tools_output_from_statuses_renders_verbose_inventory()

Purpose: Checks the full MCP inventory display, including tools, resources, and resource templates. Resources are named things a server can expose, like files or records.

Data flow: It builds a server-status object with a tool, resource, and template, renders the full inventory cell, and snapshots it.

Call relations: This exercises the verbose status-based MCP inventory renderer.

Call graph: calls 1 internal fn (render_lines); 2 external calls (assert_snapshot!, vec!).

empty_agent_message_cell_transcript938–942 ↗
fn empty_agent_message_cell_transcript()

Purpose: Ensures an empty streamed assistant message still produces a one-line transcript placeholder with the right prefix spacing.

Data flow: It creates an agent message cell containing a default empty line, asks for transcript lines and height, and compares both.

Call relations: This tests a small edge case in streamed assistant transcript rendering.

Call graph: calls 1 internal fn (new); 2 external calls (assert_eq!, vec!).

prefixed_wrapped_history_cell_indents_wrapped_lines945–965 ↗
fn prefixed_wrapped_history_cell_indents_wrapped_lines()

Purpose: Checks that a generic prefixed cell wraps long text with continuation lines aligned under the text, not under the prefix.

Data flow: It creates a line with mixed styling, wraps it at a narrow width, converts to strings, and compares the expected indentation.

Call relations: This tests shared wrapping behavior used by several prefixed history cells.

Call graph: calls 2 internal fn (new, render_lines); 3 external calls (from, assert_eq!, vec!).

prefixed_wrapped_history_cell_does_not_split_url_like_token968–981 ↗
fn prefixed_wrapped_history_cell_does_not_split_url_like_token()

Purpose: Ensures URL-like tokens are not split by the logical line renderer. Keeping such tokens whole preserves readability and link copying.

Data flow: It renders a long URL-like string in a prefixed cell and checks the complete token appears in one rendered line.

Call relations: This protects the wrapping helper used by prefixed cells.

Call graph: calls 2 internal fn (new, render_lines); 2 external calls (from, assert_eq!).

unified_exec_interaction_cell_does_not_split_url_like_stdin_token984–997 ↗
fn unified_exec_interaction_cell_does_not_split_url_like_stdin_token()

Purpose: Checks that long URL-like input sent to a background terminal is not split in the logical display lines.

Data flow: It creates a background interaction cell with a long input token, renders it narrowly, and checks the full token appears together.

Call relations: This applies the URL-like wrapping rule to background terminal interactions.

Call graph: calls 2 internal fn (new, render_lines); 1 external calls (assert_eq!).

prefixed_wrapped_history_cell_height_matches_wrapped_rendering1000–1034 ↗
fn prefixed_wrapped_history_cell_height_matches_wrapped_rendering()

Purpose: Verifies that a prefixed cell’s reported height matches the actual terminal wrapping, especially for long URL-like text. Wrong height would cause overlapping or clipped UI.

Data flow: It compares logical line count with desired wrapped height, renders into a terminal buffer, and checks the prefix remains visible.

Call relations: This connects the cell’s height calculation to Ratatui’s actual paragraph rendering.

Call graph: calls 1 internal fn (new); 5 external calls (new, from, new, assert!, empty).

unified_exec_interaction_cell_height_matches_wrapped_rendering1037–1070 ↗
fn unified_exec_interaction_cell_height_matches_wrapped_rendering()

Purpose: Verifies that background terminal interaction cells report enough height for long wrapped input. This prevents the header or input from being cut off.

Data flow: It creates a narrow interaction cell, checks desired height exceeds simple line count, renders into a buffer, and confirms the header is visible.

Call relations: This mirrors the prefixed-cell height test for the exec-interaction cell.

Call graph: calls 1 internal fn (new); 4 external calls (new, new, assert!, empty).

web_search_history_cell_snapshot1073–1086 ↗
fn web_search_history_cell_snapshot()

Purpose: Snapshots how a web search call with a detailed query is shown. This protects the label and wrapping for web search history.

Data flow: It creates a web-search cell, renders it at a fixed width, and snapshots the output.

Call relations: This exercises the web-search call rendering path.

Call graph: calls 1 internal fn (render_lines); 1 external calls (assert_snapshot!).

standalone_unix_update_available_history_cell_snapshot1089–1095 ↗
fn standalone_unix_update_available_history_cell_snapshot()

Purpose: Snapshots the update-available notice for standalone Unix installs. The instructions differ by platform.

Data flow: It creates an update cell with the Unix action, renders it, and snapshots the text.

Call relations: This tests platform-specific update notice wording.

Call graph: calls 2 internal fn (new, render_lines); 1 external calls (assert_snapshot!).

standalone_windows_update_available_history_cell_snapshot1098–1104 ↗
fn standalone_windows_update_available_history_cell_snapshot()

Purpose: Snapshots the update-available notice for standalone Windows installs. The instructions differ from Unix.

Data flow: It creates an update cell with the Windows action, renders it, and snapshots the text.

Call relations: This complements the Unix update notice snapshot.

Call graph: calls 2 internal fn (new, render_lines); 1 external calls (assert_snapshot!).

web_search_history_cell_without_detail_snapshot1107–1112 ↗
fn web_search_history_cell_without_detail_snapshot()

Purpose: Checks the web-search history display when there is no specific search detail. The fallback should still be readable.

Data flow: It creates a web-search cell with an “other” action, renders it, and snapshots the output.

Call relations: This tests the generic branch of web-search rendering.

Call graph: calls 1 internal fn (render_lines); 2 external calls (new, assert_snapshot!).

web_search_history_cell_wraps_with_indented_continuation1115–1134 ↗
fn web_search_history_cell_wraps_with_indented_continuation()

Purpose: Verifies that long web-search queries wrap with a clean indented second line. This keeps the bullet label readable.

Data flow: It renders a long search query and compares the two expected lines.

Call relations: This is a precise assertion for the web-search wrapping behavior.

Call graph: calls 1 internal fn (render_lines); 1 external calls (assert_eq!).

web_search_history_cell_short_query_does_not_wrap1137–1153 ↗
fn web_search_history_cell_short_query_does_not_wrap()

Purpose: Checks that a short web-search query stays on one line. This avoids unnecessary visual clutter.

Data flow: It renders a short search query and compares it to a single expected line.

Call relations: This complements the long-query wrapping test.

Call graph: calls 1 internal fn (render_lines); 1 external calls (assert_eq!).

web_search_history_cell_transcript_snapshot1156–1169 ↗
fn web_search_history_cell_transcript_snapshot()

Purpose: Snapshots the transcript form of a web search call. Transcript output may differ from rich display output.

Data flow: It creates a web-search cell, asks for transcript lines, converts them to text, and snapshots them.

Call relations: This tests web-search transcript rendering.

Call graph: calls 1 internal fn (render_lines); 1 external calls (assert_snapshot!).

active_mcp_tool_call_snapshot1172–1190 ↗
fn active_mcp_tool_call_snapshot()

Purpose: Snapshots how an MCP tool call looks while it is still running. This includes the server, tool name, and arguments.

Data flow: It creates an active tool-call cell with JSON arguments, renders it, and snapshots the output.

Call relations: This exercises the active state of MCP tool-call rendering.

Call graph: calls 1 internal fn (render_lines); 2 external calls (assert_snapshot!, json!).

mcp_inventory_loading_snapshot1193–1198 ↗
fn mcp_inventory_loading_snapshot()

Purpose: Snapshots the animated loading message for MCP inventory. Inventory means the list of available MCP tools and resources.

Data flow: It creates a loading cell with animations enabled, renders it, and snapshots the output.

Call relations: This tests the animated loading display for MCP inventory.

Call graph: calls 1 internal fn (render_lines); 1 external calls (assert_snapshot!).

mcp_inventory_loading_without_animations_is_stable1201–1208 ↗
fn mcp_inventory_loading_without_animations_is_stable()

Purpose: Ensures the MCP loading message is stable when animations are disabled. This is important for deterministic tests and non-animated terminals.

Data flow: It renders the same loading cell twice and checks both outputs are identical and match the expected text.

Call relations: This tests the non-animated branch of the MCP inventory loading cell.

Call graph: calls 1 internal fn (render_lines); 1 external calls (assert_eq!).

completed_mcp_tool_call_success_snapshot1211–1241 ↗
fn completed_mcp_tool_call_success_snapshot()

Purpose: Snapshots a successful completed MCP tool call with text output. This protects duration, status, and output formatting.

Data flow: It creates an active call, completes it with a successful text result and duration, renders it, and snapshots the display.

Call relations: This follows the normal MCP tool-call lifecycle from active to completed.

Call graph: calls 1 internal fn (render_lines); 4 external calls (assert!, assert_snapshot!, json!, vec!).

completed_mcp_tool_call_image_after_text_returns_extra_cell1244–1274 ↗
fn completed_mcp_tool_call_image_after_text_returns_extra_cell()

Purpose: Checks that a tool result containing text followed by an image returns an extra image cell. The UI needs a separate block for image output.

Data flow: It completes a tool call with text and image content, receives the extra cell, renders it, and checks the image-output label.

Call relations: This tests the MCP completion path that creates follow-up cells for image content.

Call graph: calls 1 internal fn (render_lines); 4 external calls (from_millis, assert_eq!, json!, vec!).

completed_mcp_tool_call_accepts_data_url_image_blocks1277–1305 ↗
fn completed_mcp_tool_call_accepts_data_url_image_blocks()

Purpose: Ensures image blocks encoded as data URLs are accepted. A data URL is a string that includes both the media type and base64 image data.

Data flow: It creates a data-url PNG block, completes a tool call with it, renders the extra image cell, and checks the label.

Call relations: This covers a variant of MCP image result parsing.

Call graph: calls 1 internal fn (render_lines); 5 external calls (from_millis, assert_eq!, format!, json!, vec!).

completed_mcp_tool_call_skips_invalid_image_blocks1308–1335 ↗
fn completed_mcp_tool_call_skips_invalid_image_blocks()

Purpose: Checks that invalid image blocks are skipped while valid later images are still used. One bad image should not prevent showing a good one.

Data flow: It completes a tool call with one invalid image and one valid image, receives an extra image cell, and checks its rendered label.

Call relations: This tests robust MCP image-result handling.

Call graph: calls 1 internal fn (render_lines); 4 external calls (from_millis, assert_eq!, json!, vec!).

completed_mcp_tool_call_error_snapshot1338–1361 ↗
fn completed_mcp_tool_call_error_snapshot()

Purpose: Snapshots a failed MCP tool call. Error output should clearly show what went wrong.

Data flow: It creates an active call, completes it with an error string and duration, renders it, and snapshots the output.

Call relations: This tests the error branch of MCP tool-call completion.

Call graph: calls 1 internal fn (render_lines); 3 external calls (assert!, assert_snapshot!, json!).

completed_mcp_tool_call_multiple_outputs_snapshot1364–1404 ↗
fn completed_mcp_tool_call_multiple_outputs_snapshot()

Purpose: Snapshots a completed MCP call with multiple output types, including text and a resource link. Mixed outputs need clear grouping.

Data flow: It completes a tool call with text plus a resource-link block, renders it at a narrower width, and snapshots the result.

Call relations: This exercises MCP output formatting for heterogeneous content.

Call graph: calls 1 internal fn (render_lines); 4 external calls (assert!, assert_snapshot!, json!, vec!).

completed_mcp_tool_call_wrapped_outputs_snapshot1407–1439 ↗
fn completed_mcp_tool_call_wrapped_outputs_snapshot()

Purpose: Checks how long MCP arguments and multi-line output wrap in a narrow terminal. This protects readability of detailed tool results.

Data flow: It completes a tool call with long JSON arguments and long text output, renders narrowly, and snapshots the text.

Call relations: This tests wrapping in the completed MCP tool-call renderer.

Call graph: calls 1 internal fn (render_lines); 4 external calls (assert!, assert_snapshot!, json!, vec!).

completed_mcp_tool_call_multiple_outputs_inline_snapshot1442–1475 ↗
fn completed_mcp_tool_call_multiple_outputs_inline_snapshot()

Purpose: Snapshots a completed MCP call with multiple short text outputs that can fit inline. This guards compact display formatting.

Data flow: It completes a tool call with two text blocks, renders at a wide width, and snapshots the output.

Call relations: This complements the narrow and mixed-output MCP tests.

Call graph: calls 1 internal fn (render_lines); 4 external calls (assert!, assert_snapshot!, json!, vec!).

session_header_includes_reasoning_level_when_present1478–1495 ↗
fn session_header_includes_reasoning_level_when_present()

Purpose: Checks that the session header shows the model’s reasoning level when it exists, along with fast-status text when enabled.

Data flow: It creates a session header with a model and high reasoning setting, renders it, finds the model line, and checks for the expected labels.

Call relations: This directly tests session-header formatting for model details.

Call graph: calls 2 internal fn (new, render_lines); 2 external calls (assert!, temp_dir).

session_header_hides_fast_status_when_disabled1498–1515 ↗
fn session_header_hides_fast_status_when_disabled()

Purpose: Ensures the session header omits the “fast” label when that status display is turned off.

Data flow: It creates a header with fast status disabled, renders it, and checks the model line includes reasoning but not fast status.

Call relations: This covers the fast-status option in session-header rendering.

Call graph: calls 2 internal fn (new, render_lines); 2 external calls (assert!, temp_dir).

session_header_indicates_yolo_mode1522–1534 ↗
fn session_header_indicates_yolo_mode()

Purpose: Snapshots the session header when YOLO mode is enabled. Here YOLO mode means broad permissions with little or no approval prompting.

Data flow: It creates a header, marks it as YOLO mode, renders it, and snapshots the output.

Call relations: This tests the session-header display of high-permission mode.

Call graph: calls 2 internal fn (new, render_lines); 1 external calls (assert_snapshot!).

yolo_mode_includes_managed_full_access_profiles1537–1547 ↗
fn yolo_mode_includes_managed_full_access_profiles()

Purpose: Checks that managed full file-system access with never-ask approval counts as YOLO permissions.

Data flow: It builds a managed permission profile with unrestricted file-system access and asserts the YOLO-permission detector returns true.

Call relations: This directly tests the helper that decides whether the session header should show YOLO mode.

Call graph: 1 external calls (assert!).

yolo_mode_excludes_external_sandbox_profiles1550–1559 ↗
fn yolo_mode_excludes_external_sandbox_profiles()

Purpose: Checks that externally sandboxed profiles are not treated as YOLO mode. External sandboxing still limits what the process can do.

Data flow: It builds an external sandbox profile and asserts the YOLO-permission detector returns false.

Call relations: This complements the managed-full-access YOLO permission test.

Call graph: 1 external calls (assert!).

session_header_directory_center_truncates1562–1572 ↗
fn session_header_directory_center_truncates()

Purpose: Checks that long directories are shortened in the middle, keeping useful beginning and ending path parts.

Data flow: It builds a path under the home directory, formats it with a length limit, and compares the expected abbreviated path.

Call relations: This directly tests the directory-formatting helper used in session headers.

Call graph: calls 1 internal fn (format_directory_inner); 3 external calls (assert_eq!, home_dir, format!).

session_header_directory_front_truncates_long_segment1575–1583 ↗
fn session_header_directory_front_truncates_long_segment()

Purpose: Checks that a single very long path segment is shortened from the front when needed. This keeps the visible end of the name.

Data flow: It builds a home-directory path with one long segment, formats it with a tight limit, and compares the expected result.

Call relations: This covers another edge case in session-header directory formatting.

Call graph: calls 1 internal fn (format_directory_inner); 3 external calls (assert_eq!, home_dir, format!).

coalesces_sequential_reads_within_one_call1586–1624 ↗
fn coalesces_sequential_reads_within_one_call()

Purpose: Checks that multiple file reads after a search inside one command are grouped in the UI. Grouping avoids noisy repeated entries.

Data flow: It builds an exec cell with a search and two read commands, marks it complete, renders it, and snapshots the output.

Call relations: This tests command-summary coalescing inside a single execution cell.

Call graph: calls 2 internal fn (new, render_lines); 5 external calls (from_millis, now, assert_snapshot!, default, vec!).

coalesces_reads_across_multiple_calls1627–1681 ↗
fn coalesces_reads_across_multiple_calls()

Purpose: Checks that related read commands can be grouped even when they arrive as separate command calls. This keeps the history compact.

Data flow: It creates an exec cell, completes a search call, adds and completes two read calls, renders the cell, and snapshots the result.

Call relations: This tests coalescing across the exec cell’s multi-call update path.

Call graph: calls 2 internal fn (new, render_lines); 5 external calls (from_millis, now, assert_snapshot!, default, vec!).

coalesced_reads_dedupe_names1684–1718 ↗
fn coalesced_reads_dedupe_names()

Purpose: Ensures grouped read summaries do not repeat the same file name twice. Duplicate names would make the UI look noisy.

Data flow: It creates an exec call with duplicate read commands, completes it, renders it, and snapshots the deduplicated output.

Call relations: This tests the read-coalescing logic’s duplicate filtering.

Call graph: calls 2 internal fn (new, render_lines); 5 external calls (from_millis, now, assert_snapshot!, default, vec!).

multiline_command_wraps_with_extra_indent_on_subsequent_lines1721–1746 ↗
fn multiline_command_wraps_with_extra_indent_on_subsequent_lines()

Purpose: Checks wrapping for a multi-line shell command when the terminal is narrow. Continuation lines should be indented enough to show they belong to the command.

Data flow: It creates a completed exec cell with a multi-line command, renders at a narrow width, and snapshots the result.

Call relations: This exercises command display formatting inside completed exec cells.

Call graph: calls 2 internal fn (new, render_lines); 6 external calls (from_millis, now, new, assert_snapshot!, default, vec!).

single_line_command_compact_when_fits1749–1769 ↗
fn single_line_command_compact_when_fits()

Purpose: Checks that a short one-line command stays compact when it fits. The UI should not waste vertical space.

Data flow: It creates and completes a simple exec cell, renders at a wide width, and snapshots the output.

Call relations: This covers the compact branch of exec command rendering.

Call graph: calls 2 internal fn (new, render_lines); 6 external calls (from_millis, now, new, assert_snapshot!, default, vec!).

single_line_command_wraps_with_four_space_continuation1772–1792 ↗
fn single_line_command_wraps_with_four_space_continuation()

Purpose: Checks how a long one-line command wraps when it cannot fit. The continuation should use the expected four-space indent.

Data flow: It creates a completed exec cell with a long token, renders narrowly, and snapshots the result.

Call relations: This covers the wrapping branch for one-line exec commands.

Call graph: calls 2 internal fn (new, render_lines); 6 external calls (from_millis, now, new, assert_snapshot!, default, vec!).

multiline_command_without_wrap_uses_branch_then_eight_spaces1795–1815 ↗
fn multiline_command_without_wrap_uses_branch_then_eight_spaces()

Purpose: Checks formatting for a multi-line command whose individual lines fit. Later lines should use the branch-style prefix and indentation.

Data flow: It creates a completed exec cell with two command lines, renders widely, and snapshots the output.

Call relations: This tests multi-line command formatting without additional wrapping.

Call graph: calls 2 internal fn (new, render_lines); 6 external calls (from_millis, now, new, assert_snapshot!, default, vec!).

multiline_command_both_lines_wrap_with_correct_prefixes1818–1839 ↗
fn multiline_command_both_lines_wrap_with_correct_prefixes()

Purpose: Checks that both lines of a multi-line command wrap correctly and keep their proper prefixes. This avoids confusing command structure.

Data flow: It creates a completed exec cell with two long command lines, renders narrowly, and snapshots the output.

Call relations: This combines multi-line command formatting with wrapping behavior.

Call graph: calls 2 internal fn (new, render_lines); 6 external calls (from_millis, now, new, assert_snapshot!, default, vec!).

stderr_tail_more_than_five_lines_snapshot1842–1885 ↗
fn stderr_tail_more_than_five_lines_snapshot()

Purpose: Snapshots how failed command output is shortened when stderr has many lines. Stderr is the error-output stream from a command.

Data flow: It creates a failed exec cell with ten stderr lines, completes it with a nonzero exit code, renders it, and snapshots the output.

Call relations: This tests the exec cell’s error-output head/tail display.

Call graph: calls 1 internal fn (new); 6 external calls (from_millis, now, new, new, assert_snapshot!, vec!).

ran_cell_multiline_with_stderr_snapshot1888–1935 ↗
fn ran_cell_multiline_with_stderr_snapshot()

Purpose: Checks a completed command with a long command line and stderr output. The command and output blocks both need correct wrapping and prefixes.

Data flow: It creates a completed exec cell with a long command and two stderr lines, renders narrowly, and snapshots the display.

Call relations: This exercises the completed “Ran” exec rendering with error output.

Call graph: calls 1 internal fn (new); 6 external calls (from_millis, now, new, new, assert_snapshot!, vec!).

user_history_cell_wraps_and_prefixes_each_line_snapshot1937–1952 ↗
fn user_history_cell_wraps_and_prefixes_each_line_snapshot()

Purpose: Snapshots how a user message wraps with the user prefix. This protects the visual gutter used for user text.

Data flow: It creates a user-history cell with a sentence, renders it at a narrow width, and snapshots the lines.

Call relations: This directly tests user-message wrapping.

Call graph: calls 1 internal fn (render_lines); 2 external calls (new, assert_snapshot!).

user_history_cell_renders_remote_image_urls1955–1968 ↗
fn user_history_cell_renders_remote_image_urls()

Purpose: Checks that user messages with remote image URLs include image markers and the text prompt. This lets users see that images were attached.

Data flow: It creates a user cell with one remote image URL, renders it, asserts the marker and prompt are present, and snapshots it.

Call relations: This tests remote-image attachment display in user history.

Call graph: calls 1 internal fn (render_lines); 4 external calls (new, assert!, assert_snapshot!, vec!).

user_history_cell_summarizes_inline_data_urls1971–1983 ↗
fn user_history_cell_summarizes_inline_data_urls()

Purpose: Ensures inline data URL images are summarized instead of dumping the long encoded string. This keeps history readable.

Data flow: It creates a user cell with a data URL image, renders it, and checks for the image marker and prompt text.

Call relations: This covers a special remote-image case in user-history rendering.

Call graph: calls 1 internal fn (render_lines); 3 external calls (new, assert!, vec!).

user_history_cell_numbers_multiple_remote_images1986–2002 ↗
fn user_history_cell_numbers_multiple_remote_images()

Purpose: Checks that multiple remote images are numbered separately. Clear numbering helps match prompts to attachments.

Data flow: It creates a user cell with two image URLs, renders it, checks for both image labels, and snapshots the output.

Call relations: This extends the remote-image display test to multiple images.

Call graph: calls 1 internal fn (render_lines); 4 external calls (new, assert!, assert_snapshot!, vec!).

user_history_cell_height_matches_rendered_lines_with_remote_images2005–2024 ↗
fn user_history_cell_height_matches_rendered_lines_with_remote_images()

Purpose: Verifies that a user cell’s reported height matches the number of rendered lines when images are attached. Wrong height could clip images or leave gaps.

Data flow: It renders a user cell with two images, counts the display lines, and compares that count to both display and transcript height methods.

Call relations: This tests height calculation for user-history cells with attachments.

Call graph: 3 external calls (new, assert_eq!, vec!).

user_history_cell_trims_trailing_blank_message_lines2027–2043 ↗
fn user_history_cell_trims_trailing_blank_message_lines()

Purpose: Checks that extra blank lines at the end of a user message are trimmed, while a needed separator before image attachments remains.

Data flow: It renders a message ending in several blank or whitespace-only lines plus an image, counts trailing blank rendered lines, and checks the main text remains.

Call relations: This tests cleanup of user-message text before attachment rendering.

Call graph: calls 1 internal fn (render_lines); 4 external calls (new, assert!, assert_eq!, vec!).

user_history_cell_trims_trailing_blank_message_lines_with_text_elements2046–2066 ↗
fn user_history_cell_trims_trailing_blank_message_lines_with_text_elements()

Purpose: Checks the same trailing-blank trimming behavior when the user message uses text elements. Text elements represent tokenized spans of the original message.

Data flow: It creates a tokenized user cell with trailing blank source text and an image, renders it, counts trailing blank lines, and checks text remains.

Call relations: This covers the text-element path of user-history rendering.

Call graph: calls 1 internal fn (render_lines); 4 external calls (new, assert!, assert_eq!, vec!).

render_uses_wrapping_for_long_url_like_line2069–2115 ↗
fn render_uses_wrapping_for_long_url_like_line()

Purpose: Verifies that rendering a very long URL-like user message actually wraps across visible terminal rows. This prevents the tail of the URL from disappearing.

Data flow: It creates a user-history cell with a very long URL, asks for height, renders into a buffer, and checks that later URL text is visible across multiple rows.

Call relations: This connects user-cell height calculation to real Ratatui buffer rendering.

Call graph: 5 external calls (new, new, new, assert!, empty).

plan_update_with_note_and_wrapping_snapshot2118–2146 ↗
fn plan_update_with_note_and_wrapping_snapshot()

Purpose: Snapshots a plan update that has an explanatory note and long steps. This protects wrapping and alignment of plan status rows.

Data flow: It builds a plan update with completed, in-progress, and pending steps, renders narrowly, and snapshots the result.

Call relations: This tests the plan-update history cell with both note and step content.

Call graph: calls 1 internal fn (render_lines); 2 external calls (assert_snapshot!, vec!).

plan_update_without_note_snapshot2149–2168 ↗
fn plan_update_without_note_snapshot()

Purpose: Snapshots a plan update that has steps but no explanatory note. The cell should still be clear and compact.

Data flow: It builds a two-step plan update without a note, renders it, and snapshots the output.

Call relations: This covers the no-note branch of plan-update rendering.

Call graph: calls 1 internal fn (render_lines); 2 external calls (assert_snapshot!, vec!).

plan_update_does_not_split_url_like_tokens_in_note_or_step2171–2203 ↗
fn plan_update_does_not_split_url_like_tokens_in_note_or_step()

Purpose: Ensures URL-like tokens in plan notes and steps stay whole in logical display lines. This preserves copyability and readability.

Data flow: It creates a plan update containing long URL-like strings, renders narrowly, and checks each full token appears in one line.

Call relations: This applies the URL-like wrapping rule to plan-update cells.

Call graph: calls 1 internal fn (render_lines); 3 external calls (assert_eq!, format!, vec!).

reasoning_summary_block2206–2217 ↗
fn reasoning_summary_block()

Purpose: Checks that a reasoning summary block displays only the useful summary text when a bold header is present. Reasoning summaries are short explanations of what the assistant considered.

Data flow: It creates a reasoning-summary block from header-plus-body text, renders display and transcript lines, and compares both to the expected summary line.

Call relations: This tests parsing and rendering for reasoning-summary blocks.

Call graph: calls 3 internal fn (render_lines, render_transcript, test_cwd); 1 external calls (assert_eq!).

reasoning_summary_height_matches_wrapped_rendering_for_url_like_content2220–2262 ↗
fn reasoning_summary_height_matches_wrapped_rendering_for_url_like_content()

Purpose: Verifies that reasoning-summary height matches actual wrapped rendering for long URL-like content. This avoids clipping in narrow terminals.

Data flow: It creates a reasoning cell with long text, compares desired height to Ratatui paragraph line count, checks transcript height, renders into a buffer, and confirms the bullet remains visible.

Call relations: This connects reasoning-summary display lines, height calculation, and real rendering.

Call graph: calls 2 internal fn (new, test_cwd); 7 external calls (new, new, new, from, assert!, assert_eq!, empty).

reasoning_summary_block_returns_reasoning_cell_when_feature_disabled2265–2271 ↗
fn reasoning_summary_block_returns_reasoning_cell_when_feature_disabled()

Purpose: Checks the fallback reasoning-summary behavior when the richer feature path is not used. The summary should still render as a reasoning cell.

Data flow: It creates a reasoning-summary block from plain text, renders the transcript, and compares it to the expected bullet line.

Call relations: This exercises the fallback constructor path for reasoning summaries.

Call graph: calls 2 internal fn (render_transcript, test_cwd); 1 external calls (assert_eq!).

reasoning_summary_block_respects_config_overrides2274–2285 ↗
async fn reasoning_summary_block_respects_config_overrides()

Purpose: Checks that reasoning-summary rendering still works when config values override model support. This keeps behavior stable across model settings.

Data flow: It builds config with a model override, creates a reasoning-summary block, renders it, and compares the display line.

Call relations: This uses the config helper while testing reasoning-summary display.

Call graph: calls 3 internal fn (render_lines, test_config, test_cwd); 1 external calls (assert_eq!).

reasoning_summary_block_falls_back_when_header_is_missing2288–2296 ↗
fn reasoning_summary_block_falls_back_when_header_is_missing()

Purpose: Ensures malformed reasoning text without a proper bold header still appears instead of being dropped.

Data flow: It creates a reasoning-summary block from incomplete header markup, renders the transcript, and checks the original text is preserved with a bullet.

Call relations: This tests the parser’s safe fallback path.

Call graph: calls 2 internal fn (render_transcript, test_cwd); 1 external calls (assert_eq!).

reasoning_summary_block_falls_back_when_summary_is_missing2299–2315 ↗
fn reasoning_summary_block_falls_back_when_summary_is_missing()

Purpose: Checks behavior when a reasoning header exists but no separate summary body follows. The header text should become the visible summary.

Data flow: It creates two header-only reasoning blocks, renders their transcripts, and compares both to the expected header-derived line.

Call relations: This covers missing-body fallback logic in reasoning-summary parsing.

Call graph: calls 2 internal fn (render_transcript, test_cwd); 1 external calls (assert_eq!).

reasoning_summary_block_splits_header_and_summary_when_present2318–2329 ↗
fn reasoning_summary_block_splits_header_and_summary_when_present()

Purpose: Checks that a valid bold header and following summary are split correctly, with only the summary shown.

Data flow: It creates a reasoning block from header-plus-summary text, renders display and transcript lines, and compares both.

Call relations: This is the normal parsing path for reasoning summary blocks.

Call graph: calls 3 internal fn (render_lines, render_transcript, test_cwd); 1 external calls (assert_eq!).

deprecation_notice_renders_summary_with_details2332–2346 ↗
fn deprecation_notice_renders_summary_with_details()

Purpose: Checks that a deprecation notice shows both the warning summary and optional detail text. Deprecation means a feature is being phased out.

Data flow: It creates a deprecation notice with summary and detail, renders it, and compares the two expected lines.

Call relations: This directly tests deprecation notice rendering.

Call graph: calls 1 internal fn (render_lines); 1 external calls (assert_eq!).

agent_markdown_cell_renders_source_at_different_widths2349–2366 ↗
fn agent_markdown_cell_renders_source_at_different_widths()

Purpose: Verifies that assistant Markdown text wraps differently when terminal width changes. Narrower terminals should produce more lines.

Data flow: It creates an assistant Markdown cell, renders it at wide and narrow widths, checks the bullet prefix, and confirms the narrow output has more lines.

Call relations: This tests width-sensitive Markdown rendering.

Call graph: calls 3 internal fn (new, render_lines, test_cwd); 1 external calls (assert!).

agent_markdown_cell_does_not_split_words_after_inline_markdown2369–2382 ↗
fn agent_markdown_cell_does_not_split_words_after_inline_markdown()

Purpose: Checks that inline Markdown formatting does not cause bad word splitting during wrapping. Formatting should not break natural text flow.

Data flow: It creates a long Markdown paragraph with bold, italic, code, strikethrough, and links, renders it, and checks where wrapping occurs.

Call relations: This protects the Markdown-to-terminal wrapping logic.

Call graph: calls 3 internal fn (new, render_lines, test_cwd); 1 external calls (assert!).

streamed_agent_list_paragraph_preserves_item_indent_when_wrapped2385–2406 ↗
fn streamed_agent_list_paragraph_preserves_item_indent_when_wrapped()

Purpose: Ensures streamed assistant list paragraphs keep their list indentation after wrapping. This keeps numbered-list explanations readable.

Data flow: It creates streamed assistant lines with a numbered item and indented paragraph, renders narrowly, checks wrapped rows keep indentation, and snapshots the output.

Call relations: This tests streamed agent message rendering rather than finalized Markdown rendering.

Call graph: calls 2 internal fn (new, render_lines); 3 external calls (assert!, assert_snapshot!, vec!).

agent_markdown_cell_narrow_width_shows_prefix_only2409–2415 ↗
fn agent_markdown_cell_narrow_width_shows_prefix_only()

Purpose: Checks that an assistant Markdown cell still renders safely at an extremely narrow width. It should at least show the prefix and not crash.

Data flow: It creates a Markdown cell, renders at width two, and compares the prefix-only output.

Call relations: This covers a tiny-terminal edge case in assistant Markdown rendering.

Call graph: calls 3 internal fn (new, render_lines, test_cwd); 1 external calls (assert_eq!).

wrapped_and_prefixed_cells_handle_tiny_widths2418–2456 ↗
fn wrapped_and_prefixed_cells_handle_tiny_widths()

Purpose: Ensures several wrapped or prefixed cell types return some output even at widths from one to four columns. Tiny widths should not cause panics or empty displays.

Data flow: It creates user, streamed assistant, reasoning, and Markdown cells, renders each at very small widths, and asserts none are empty.

Call relations: This is a cross-cell safety test for narrow terminal handling.

Call graph: calls 4 internal fn (new, new, new, test_cwd); 3 external calls (new, assert!, vec!).

render_clears_area_when_cell_content_shrinks2459–2493 ↗
fn render_clears_area_when_cell_content_shrinks()

Purpose: Checks that rendering a shorter cell over a previous taller cell clears stale text. Without this, old terminal characters could remain visible.

Data flow: It renders a multi-line plain cell into a buffer, then renders a one-line cell in the same area, reads the buffer, and checks stale text is gone and fresh text remains.

Call relations: This tests the shared render behavior for history cells.

Call graph: calls 1 internal fn (new); 7 external calls (new, empty, new, new, new, assert!, vec!).

agent_markdown_cell_survives_insert_history_rewrap2496–2516 ↗
fn agent_markdown_cell_survives_insert_history_rewrap()

Purpose: Ensures Markdown-rendered assistant lines are not changed by a later generic wrapping pass when they already fit. This prevents double-wrapping artifacts.

Data flow: It renders an assistant Markdown cell, runs the generic word wrapper on those lines, converts both before and after to strings, and compares them.

Call relations: This simulates the history insertion path used elsewhere in the app.

Call graph: calls 4 internal fn (new, render_lines, test_cwd, word_wrap_lines); 1 external calls (assert_eq!).

consolidation_walker_replaces_agent_message_cells2521–2590 ↗
fn consolidation_walker_replaces_agent_message_cells()

Purpose: Simulates the app logic that replaces a run of streamed assistant message cells with one final Markdown cell. This keeps history tidy after streaming completes.

Data flow: It builds a transcript with one user cell and three streamed assistant cells, walks backward to find the assistant run, splices in a consolidated Markdown cell, and checks the resulting cell types.

Call relations: This mirrors consolidation logic from the app event handler while using history-cell types from this module.

Call graph: calls 3 internal fn (new, new, test_cwd); 6 external calls (new, new, assert!, assert_eq!, once, vec!).

tui/src/markdown_render_tests.rssource ↗
testtest run

The terminal UI cannot show Markdown exactly like a web browser. It must convert Markdown into Ratatui text, which is styled text for a terminal screen. This test file acts like a large checklist for that conversion. It feeds many small Markdown examples into the renderer and compares the result with the exact lines, colors, and emphasis the UI should show. Without these tests, small changes could quietly break common messages: file links might show noisy absolute paths, lists might lose indentation, blockquotes might merge with normal text, tables might become unreadable, or code blocks might lose blank lines. The file also tests narrower edge cases, such as URLs containing tildes, percent-encoded file names, line-number anchors, escaped table pipes, and tables that are too wide for the available terminal width. Some tests use snapshots, which are saved expected outputs, useful when the rendered text is too large to write inline. In short, this file is the renderer’s quality gate. It describes, through examples, what “readable Markdown in a terminal” means for this project.

Function details107
render_markdown_text_for_cwd18–20 ↗
fn render_markdown_text_for_cwd(input: &str, cwd: &Path) -> Text<'static>

Purpose: This helper renders Markdown while pretending the app is running in a specific current folder. Tests use it to check that local file links are shortened in a user-friendly way.

Data flow: It takes Markdown text and a folder path as input. It passes them to the main renderer with no fixed width and with that folder as context, then returns the rendered terminal text.

Call relations: File-link tests call this helper when they need current-folder behavior. It hands the work to render_markdown_text_with_width_and_cwd so each test does not repeat the same setup.

Call graph: calls 1 internal fn (render_markdown_text_with_width_and_cwd); called by 12 (file_link_appends_hash_anchor_when_label_lacks_it, file_link_appends_hash_range_when_label_lacks_it, file_link_appends_line_number_when_label_lacks_it, file_link_appends_range_when_label_lacks_it, file_link_decodes_percent_encoded_bare_path_destination, file_link_hides_destination, file_link_keeps_absolute_paths_outside_cwd, file_link_uses_target_path_for_hash_anchor, file_link_uses_target_path_for_hash_range, file_link_uses_target_path_for_range (+2 more)).

plain_lines22–32 ↗
fn plain_lines(text: &Text<'_>) -> Vec<String>

Purpose: This helper removes styling and returns only the visible text from rendered output. Tests use it when they care about line breaks and words, not colors or bold text.

Data flow: It receives rendered Ratatui text. It joins the spans on each line into plain strings and returns a list of those strings.

Call relations: Tests about list spacing and table fallback call this helper after rendering. It lets those tests compare simple text lines instead of full styled objects.

Call graph: called by 3 (list_item_after_code_block_keeps_blank_separator, outer_list_item_after_nested_code_block_keeps_blank_separator, table_key_value_fallback_preserves_rich_values_and_themed_labels).

merged_text_events_preserve_entity_decoding85–118 ↗
fn merged_text_events_preserve_entity_decoding()

Purpose: This test ensures HTML-style entities, such as ampersand written as &amp;, are decoded correctly even when text events are merged. It prevents visible text and hyperlink targets from disagreeing.

Data flow: It renders a URL containing an encoded ampersand, gathers the displayed text and hyperlink destination, and checks that both use the decoded ampersand.

Call relations: The test runner calls it. It asks render_markdown_lines_with_width_and_cwd for both displayed spans and hyperlink ranges.

Call graph: calls 1 internal fn (render_markdown_lines_with_width_and_cwd); 1 external calls (assert_eq!).

empty121–123 ↗
fn empty()

Purpose: This test checks that empty Markdown produces empty rendered text. It confirms the renderer does not invent a blank line or stray content.

Data flow: It passes an empty string to the renderer and compares the result with Ratatui’s default empty text value.

Call relations: The test runner calls it as a basic baseline before more complex Markdown cases.

Call graph: 1 external calls (assert_eq!).

paragraph_single126–131 ↗
fn paragraph_single()

Purpose: This test checks the simplest paragraph case. Plain text should remain plain text.

Data flow: It renders one sentence and expects exactly one line containing that sentence.

Call relations: The test runner calls it. It exercises the default render_markdown_text path indirectly through the assertion.

Call graph: 1 external calls (assert_eq!).

paragraph_soft_break134–139 ↗
fn paragraph_soft_break()

Purpose: This test checks how a single newline inside a paragraph is shown. In this renderer, it becomes a new terminal line.

Data flow: It renders text with one newline and expects two output lines, one for each side of the newline.

Call relations: The test runner calls it to guard the renderer’s paragraph line-break behavior.

Call graph: 1 external calls (assert_eq!).

paragraph_multiple142–147 ↗
fn paragraph_multiple()

Purpose: This test checks that separate paragraphs stay separated. A blank line in Markdown should remain a blank line in the terminal output.

Data flow: It renders two paragraphs separated by an empty line and expects three lines: first paragraph, blank line, second paragraph.

Call relations: The test runner calls it as a basic paragraph spacing check.

Call graph: 1 external calls (assert_eq!).

headings150–167 ↗
fn headings()

Purpose: This test verifies that Markdown headings are displayed with heading markers and distinct styles. It confirms the renderer gives headings visual weight in the terminal.

Data flow: It renders headings from level 1 through 6 and compares them with expected styled lines using bold, underline, and italic combinations.

Call relations: The test runner calls it. It calls render_markdown_text and compares the result with hand-built Ratatui lines.

Call graph: calls 1 internal fn (render_markdown_text); 4 external calls (default, from_iter, from_iter, assert_eq!).

blockquote_single170–174 ↗
fn blockquote_single()

Purpose: This test checks a one-line blockquote. The quote should keep its visible “>” marker and quote styling.

Data flow: It renders one blockquote and expects a green line containing the quote prefix and text.

Call relations: The test runner calls it to verify basic blockquote rendering.

Call graph: calls 1 internal fn (render_markdown_text); 3 external calls (from_iter, from, assert_eq!).

blockquote_soft_break177–197 ↗
fn blockquote_soft_break()

Purpose: This test checks that a soft line break inside a blockquote keeps the quote prefix on each line. It prevents the second line from looking like normal text.

Data flow: It renders a blockquote with a continuation line, strips styling to plain strings, and expects both lines to start with “>”.

Call relations: The test runner calls it. It uses render_markdown_text, then inspects the rendered lines directly.

Call graph: calls 1 internal fn (render_markdown_text); 1 external calls (assert_eq!).

blockquote_multiple_with_break200–208 ↗
fn blockquote_multiple_with_break()

Purpose: This test checks two separate blockquotes with a blank line between them. It protects paragraph spacing inside quoted text.

Data flow: It renders two quote blocks and expects quote line, blank line, quote line.

Call relations: The test runner calls it to cover blockquote separation behavior.

Call graph: calls 1 internal fn (render_markdown_text); 4 external calls (default, from_iter, from_iter, assert_eq!).

blockquote_three_paragraphs_short_lines211–222 ↗
fn blockquote_three_paragraphs_short_lines()

Purpose: This test checks a blockquote containing three short paragraphs. It ensures empty quoted lines are shown with the quote prefix.

Data flow: It renders quote text with blank quoted lines and compares against five expected green lines.

Call relations: The test runner calls it. It focuses on how render_markdown_text keeps quote structure visible.

Call graph: calls 1 internal fn (render_markdown_text); 3 external calls (from_iter, from_iter, assert_eq!).

blockquote_nested_two_levels225–234 ↗
fn blockquote_nested_two_levels()

Purpose: This test checks nested blockquotes. It ensures the renderer shows both quote levels clearly.

Data flow: It renders a quote inside a quote and expects lines with one and then two “>” prefixes, including the separator line.

Call relations: The test runner calls it as part of the blockquote nesting coverage.

Call graph: calls 1 internal fn (render_markdown_text); 3 external calls (from_iter, from_iter, assert_eq!).

blockquote_with_list_items237–245 ↗
fn blockquote_with_list_items()

Purpose: This test checks bullet lists inside a blockquote. It ensures quote markers and list markers work together instead of one hiding the other.

Data flow: It renders two quoted bullet items and expects each line to contain “> -” before the item text.

Call relations: The test runner calls it. It exercises the renderer’s combined quote and list logic.

Call graph: calls 1 internal fn (render_markdown_text); 3 external calls (from_iter, from_iter, assert_eq!).

blockquote_with_ordered_list248–266 ↗
fn blockquote_with_ordered_list()

Purpose: This test checks numbered lists inside a blockquote. It also confirms the numbered markers keep their list styling.

Data flow: It renders two quoted numbered items and compares the styled output with expected quote text, blue number markers, and item text.

Call relations: The test runner calls it to cover the intersection of blockquotes and ordered lists.

Call graph: calls 1 internal fn (render_markdown_text); 4 external calls (from_iter, from_iter, assert_eq!, vec!).

blockquote_list_then_nested_blockquote269–277 ↗
fn blockquote_list_then_nested_blockquote()

Purpose: This test checks a quoted list item followed by a nested quote. It ensures indentation and quote markers remain readable.

Data flow: It renders a parent bullet and a child blockquote inside the same quote, then compares exact visible pieces.

Call relations: The test runner calls it to verify nested structures inside blockquotes.

Call graph: calls 1 internal fn (render_markdown_text); 3 external calls (from_iter, from_iter, assert_eq!).

list_item_with_inline_blockquote_on_same_line280–288 ↗
fn list_item_with_inline_blockquote_on_same_line()

Purpose: This test checks a numbered list item whose content starts with a blockquote marker on the same line. It ensures the text is not split or lost.

Data flow: It renders the Markdown, joins the spans of the first line, and expects the visible string “1. > quoted”.

Call relations: The test runner calls it. It directly inspects the renderer’s first output line.

Call graph: calls 1 internal fn (render_markdown_text); 1 external calls (assert_eq!).

blockquote_surrounded_by_blank_lines291–314 ↗
fn blockquote_surrounded_by_blank_lines()

Purpose: This test checks a blockquote between normal paragraphs. It ensures blank lines around the quote are preserved.

Data flow: It renders normal text, a quoted line, and more normal text, then compares the plain output line by line.

Call relations: The test runner calls it to protect paragraph-to-blockquote boundaries.

Call graph: calls 1 internal fn (render_markdown_text); 1 external calls (assert_eq!).

blockquote_in_ordered_list_on_next_line317–333 ↗
fn blockquote_in_ordered_list_on_next_line()

Purpose: This test checks a blockquote that begins on the next line inside an ordered list item. It should appear on the same rendered marker line when the item has no other text.

Data flow: It renders a numbered item followed by an indented quote and expects one visible line: “1. > quoted”.

Call relations: The test runner calls it to cover list-item blockquote compaction.

Call graph: calls 1 internal fn (render_markdown_text); 1 external calls (assert_eq!).

blockquote_in_unordered_list_on_next_line336–352 ↗
fn blockquote_in_unordered_list_on_next_line()

Purpose: This test checks the same behavior for an unordered bullet item. It ensures an empty bullet followed by a quote becomes readable on one line.

Data flow: It renders a bullet item with an indented quote and expects “- > quoted”.

Call relations: The test runner calls it alongside the ordered-list version.

Call graph: calls 1 internal fn (render_markdown_text); 1 external calls (assert_eq!).

blockquote_two_paragraphs_inside_ordered_list_has_blank_line355–378 ↗
fn blockquote_two_paragraphs_inside_ordered_list_has_blank_line()

Purpose: This test checks two quoted paragraphs inside one numbered item. It ensures the blank quoted line stays aligned after the list marker.

Data flow: It renders an ordered item containing a two-paragraph quote and compares the plain output lines, including the quoted blank line.

Call relations: The test runner calls it to guard a subtle list-and-quote spacing rule.

Call graph: calls 1 internal fn (render_markdown_text); 1 external calls (assert_eq!).

blockquote_inside_nested_list381–395 ↗
fn blockquote_inside_nested_list()

Purpose: This test checks a blockquote inside a nested list. It ensures the quote is indented to the correct depth.

Data flow: It renders an ordered item, a nested bullet, and a quote under that bullet, then compares plain lines.

Call relations: The test runner calls it to cover deeper nesting with quotes.

Call graph: calls 1 internal fn (render_markdown_text); 1 external calls (assert_eq!).

list_item_text_then_blockquote398–412 ↗
fn list_item_text_then_blockquote()

Purpose: This test checks a list item with normal text followed by a blockquote. The quote should stay on its own indented line.

Data flow: It renders the list item and compares two plain lines: the item text and the indented quote.

Call relations: The test runner calls it as one ordering case for list text and quotes.

Call graph: calls 1 internal fn (render_markdown_text); 1 external calls (assert_eq!).

list_item_blockquote_then_text415–429 ↗
fn list_item_blockquote_then_text()

Purpose: This test checks a list item that starts with a quote and then continues with text. It ensures continuation text stays within the quote context.

Data flow: It renders the Markdown and expects the first line to combine the marker and quote, with the next line quoted and indented.

Call relations: The test runner calls it as the reverse ordering case from list_item_text_then_blockquote.

Call graph: calls 1 internal fn (render_markdown_text); 1 external calls (assert_eq!).

list_item_text_blockquote_text432–446 ↗
fn list_item_text_blockquote_text()

Purpose: This test checks normal list text, then a quote, then more text. It ensures the renderer keeps later continuation text aligned with the quoted section.

Data flow: It renders the mixed list item and compares three plain output lines.

Call relations: The test runner calls it to cover a more complex list-and-blockquote sequence.

Call graph: calls 1 internal fn (render_markdown_text); 1 external calls (assert_eq!).

blockquote_with_heading_and_paragraph449–471 ↗
fn blockquote_with_heading_and_paragraph()

Purpose: This test checks a heading inside a blockquote followed by paragraph text. It focuses on the visible line shape.

Data flow: It renders the quote, strips style, and expects a quoted heading line, a quoted blank line, and a quoted paragraph line.

Call relations: The test runner calls it to verify blockquote structure around headings.

Call graph: calls 1 internal fn (render_markdown_text); 1 external calls (assert_eq!).

blockquote_heading_inherits_heading_style474–489 ↗
fn blockquote_heading_inherits_heading_style()

Purpose: This test checks that a heading inside a blockquote still looks like a heading. It protects both quote styling and heading styling at once.

Data flow: It renders a quoted level-one heading and a quoted paragraph, then compares styled Ratatui lines.

Call relations: The test runner calls it after the shape-only heading test to check style details.

Call graph: calls 1 internal fn (render_markdown_text); 1 external calls (assert_eq!).

blockquote_with_code_block492–506 ↗
fn blockquote_with_code_block()

Purpose: This test checks a fenced code block inside a blockquote. It ensures only the code content is shown, still marked as quoted.

Data flow: It renders a quoted code fence and expects one visible line: “> code”.

Call relations: The test runner calls it to cover code blocks inside quoted text.

Call graph: calls 1 internal fn (render_markdown_text); 1 external calls (assert_eq!).

blockquote_with_multiline_code_block509–523 ↗
fn blockquote_with_multiline_code_block()

Purpose: This test checks a multi-line fenced code block inside a blockquote. It ensures each code line keeps the quote prefix.

Data flow: It renders two quoted code lines and compares the two visible output strings.

Call relations: The test runner calls it as the multi-line companion to blockquote_with_code_block.

Call graph: calls 1 internal fn (render_markdown_text); 1 external calls (assert_eq!).

nested_blockquote_with_inline_and_fenced_code526–566 ↗
fn nested_blockquote_with_inline_and_fenced_code()

Purpose: This test checks nested blockquotes containing both inline code and a fenced code block. It protects a complicated but realistic Markdown shape.

Data flow: It renders nested quoted text and code, strips styles, and compares the exact visible quote prefixes and code lines.

Call relations: The test runner calls it to exercise several renderer features at the same time.

Call graph: calls 1 internal fn (render_markdown_text); 1 external calls (assert_eq!).

list_unordered_single569–573 ↗
fn list_unordered_single()

Purpose: This test checks a single bullet list item. It ensures the bullet marker and text render on one line.

Data flow: It renders one unordered item and compares it with an expected Ratatui line.

Call relations: The test runner calls it as the simplest unordered-list case.

Call graph: calls 1 internal fn (render_markdown_text); 3 external calls (from_iter, from_iter, assert_eq!).

list_unordered_multiple576–583 ↗
fn list_unordered_multiple()

Purpose: This test checks multiple bullet list items. It ensures each item becomes its own rendered line.

Data flow: It renders two bullets and compares two expected lines.

Call relations: The test runner calls it to verify repeated unordered list items.

Call graph: calls 1 internal fn (render_markdown_text); 3 external calls (from_iter, from_iter, assert_eq!).

list_ordered586–593 ↗
fn list_ordered()

Purpose: This test checks a basic numbered list. It ensures number markers are shown and styled distinctly.

Data flow: It renders two numbered items and compares expected lines with blue number markers.

Call relations: The test runner calls it as the simplest ordered-list case.

Call graph: calls 1 internal fn (render_markdown_text); 3 external calls (from_iter, from_iter, assert_eq!).

list_nested596–603 ↗
fn list_nested()

Purpose: This test checks a nested bullet list. It ensures the nested item is indented enough to show hierarchy.

Data flow: It renders a parent bullet and child bullet, then compares the expected indentation.

Call relations: The test runner calls it to guard list nesting layout.

Call graph: calls 1 internal fn (render_markdown_text); 3 external calls (from_iter, from_iter, assert_eq!).

list_ordered_custom_start606–613 ↗
fn list_ordered_custom_start()

Purpose: This test checks a numbered list that starts at 3 instead of 1. It ensures the renderer respects the numbers written in Markdown.

Data flow: It renders items numbered 3 and 4 and expects those same markers in the output.

Call relations: The test runner calls it to cover custom ordered-list starts.

Call graph: calls 1 internal fn (render_markdown_text); 3 external calls (from_iter, from_iter, assert_eq!).

nested_unordered_in_ordered616–627 ↗
fn nested_unordered_in_ordered()

Purpose: This test checks bullet items nested inside a numbered list. It ensures nested bullets are indented and the next numbered item is separated correctly.

Data flow: It renders an ordered item with two nested bullets and another ordered item, then compares styled lines including a blank separator.

Call relations: The test runner calls it to cover mixed list types.

Call graph: calls 1 internal fn (render_markdown_text); 4 external calls (default, from_iter, from_iter, assert_eq!).

nested_ordered_in_unordered630–641 ↗
fn nested_ordered_in_unordered()

Purpose: This test checks numbered items nested inside a bullet list. It ensures nested numbers are styled and aligned under the parent bullet.

Data flow: It renders a bullet with two nested numbered items and another bullet, then compares expected lines.

Call relations: The test runner calls it as the opposite mixed-list case from nested_unordered_in_ordered.

Call graph: calls 1 internal fn (render_markdown_text); 4 external calls (default, from_iter, from_iter, assert_eq!).

loose_list_item_multiple_paragraphs644–655 ↗
fn loose_list_item_multiple_paragraphs()

Purpose: This test checks a list item with more than one paragraph. It ensures the second paragraph stays indented under the same item.

Data flow: It renders a numbered item, a blank line, a continuation paragraph, another blank line, and the next item, then compares output.

Call relations: The test runner calls it to protect loose-list paragraph behavior.

Call graph: calls 1 internal fn (render_markdown_text); 4 external calls (default, from_iter, from_iter, assert_eq!).

tight_item_with_soft_break658–666 ↗
fn tight_item_with_soft_break()

Purpose: This test checks a list item with a soft line break but no blank paragraph gap. It ensures the continuation line is indented without extra spacing.

Data flow: It renders a bullet item split across two source lines and expects two compact rendered lines.

Call relations: The test runner calls it to verify tight-list continuation layout.

Call graph: calls 1 internal fn (render_markdown_text); 3 external calls (from_iter, from_iter, assert_eq!).

deeply_nested_mixed_three_levels669–680 ↗
fn deeply_nested_mixed_three_levels()

Purpose: This test checks three levels of mixed ordered and unordered lists. It ensures indentation remains consistent as nesting gets deeper.

Data flow: It renders numbered, bullet, and nested numbered items, then compares expected styled lines and separator spacing.

Call relations: The test runner calls it to cover deeper mixed-list nesting.

Call graph: calls 1 internal fn (render_markdown_text); 4 external calls (default, from_iter, from_iter, assert_eq!).

loose_items_due_to_blank_line_between_items683–691 ↗
fn loose_items_due_to_blank_line_between_items()

Purpose: This test checks two numbered items separated by a blank source line. It ensures the renderer does not add an unwanted blank rendered line between simple items.

Data flow: It renders two simple items with a blank line between them and expects two compact output lines.

Call relations: The test runner calls it to pin down a subtle Markdown list spacing choice.

Call graph: calls 1 internal fn (render_markdown_text); 3 external calls (from_iter, from_iter, assert_eq!).

mixed_tight_then_loose_in_one_list694–702 ↗
fn mixed_tight_then_loose_in_one_list()

Purpose: This test checks a list containing both tight and loose-looking item syntax. It ensures simple content stays compact.

Data flow: It renders two numbered items where the second item’s text starts on the next line, and expects two compact lines.

Call relations: The test runner calls it to prevent unnecessary blank lines in mixed list forms.

Call graph: calls 1 internal fn (render_markdown_text); 3 external calls (from_iter, from_iter, assert_eq!).

ordered_item_with_indented_continuation_is_tight705–713 ↗
fn ordered_item_with_indented_continuation_is_tight()

Purpose: This test checks an ordered item with an indented continuation line. It ensures the continuation is shown under the item without a blank gap.

Data flow: It renders a numbered item with a following indented line and compares the two expected lines.

Call relations: The test runner calls it to cover ordered-list continuation indentation.

Call graph: calls 1 internal fn (render_markdown_text); 3 external calls (from_iter, from_iter, assert_eq!).

inline_code716–720 ↗
fn inline_code()

Purpose: This test checks inline code formatting. Text inside backticks should appear as code-styled text, not include the backticks.

Data flow: It renders a sentence with inline code and expects normal text followed by cyan code text.

Call relations: The test runner calls it as the basic inline-code style check.

Call graph: calls 1 internal fn (render_markdown_text); 2 external calls (from_iter, assert_eq!).

strong723–728 ↗
fn strong()

Purpose: This test checks bold Markdown. It ensures double-asterisk text becomes bold terminal text.

Data flow: It renders bold Markdown and compares the result with one bold line.

Call relations: The test runner calls it to cover strong emphasis.

Call graph: 1 external calls (assert_eq!).

emphasis731–736 ↗
fn emphasis()

Purpose: This test checks italic Markdown. It ensures single-asterisk text becomes italic terminal text.

Data flow: It renders italic Markdown and compares the result with one italic line.

Call relations: The test runner calls it to cover emphasis.

Call graph: 1 external calls (assert_eq!).

strikethrough739–744 ↗
fn strikethrough()

Purpose: This test checks strikethrough Markdown. It ensures text wrapped in double tildes is shown crossed out.

Data flow: It renders strikethrough Markdown and compares the result with one crossed-out line.

Call relations: The test runner calls it to cover strikethrough styling.

Call graph: 1 external calls (assert_eq!).

strong_emphasis747–754 ↗
fn strong_emphasis()

Purpose: This test checks nested bold and italic formatting. It ensures inner emphasized text keeps both styles.

Data flow: It renders bold text containing italic text and expects the first span bold and the second span bold plus italic.

Call relations: The test runner calls it to verify style stacking.

Call graph: calls 1 internal fn (render_markdown_text); 3 external calls (from_iter, from, assert_eq!).

load_location_suffix_regexes769–772 ↗
fn load_location_suffix_regexes()

Purpose: This test forces the file-location regular expressions to initialize. A regular expression is a pattern matcher; this catches invalid patterns early.

Data flow: It reads the two shared location-suffix regex values. If either pattern cannot be built, the test fails during initialization.

Call relations: The test runner calls it directly. It does not render Markdown; it validates support data used by file-link rendering.

code_block_known_lang_has_syntax_colors1021–1048 ↗
fn code_block_known_lang_has_syntax_colors()

Purpose: This test checks that a fenced code block with a known language gets syntax highlighting. Syntax highlighting means coloring parts of code to make it easier to read.

Data flow: It renders a Rust code block, checks the code text is present, and verifies at least one span has a foreground color.

Call relations: The test runner calls it. It exercises render_markdown_text plus the syntax coloring path.

Call graph: calls 1 internal fn (render_markdown_text); 2 external calls (assert!, assert_eq!).

code_block_unknown_lang_plain1051–1077 ↗
fn code_block_unknown_lang_plain()

Purpose: This test checks that an unknown code language is still shown, but without syntax colors. It prevents bad language names from producing odd styling.

Data flow: It renders a fenced block marked with an unknown language, confirms the content appears, and checks that no span has a color.

Call relations: The test runner calls it as the fallback case for code highlighting.

Call graph: calls 1 internal fn (render_markdown_text); 2 external calls (assert!, assert_eq!).

code_block_no_lang_plain1080–1098 ↗
fn code_block_no_lang_plain()

Purpose: This test checks a code block with no language name. It should render as plain code text.

Data flow: It renders an unlabeled fenced code block and checks the visible code line is preserved.

Call relations: The test runner calls it to cover the no-language code path.

Call graph: calls 1 internal fn (render_markdown_text); 1 external calls (assert_eq!).

code_block_multiple_lines_root1101–1109 ↗
fn code_block_multiple_lines_root()

Purpose: This test checks a multi-line fenced code block at the document root. It ensures each code line becomes its own rendered line.

Data flow: It renders two code lines and compares them with expected Ratatui lines.

Call relations: The test runner calls it to verify basic multi-line code output.

Call graph: calls 1 internal fn (render_markdown_text); 3 external calls (from_iter, from_iter, assert_eq!).

code_block_indented1112–1121 ↗
fn code_block_indented()

Purpose: This test checks indented code blocks, the older Markdown form where four leading spaces mean code. It ensures indentation and content are preserved.

Data flow: It renders an indented JavaScript-like block and expects each output line to keep the code indentation prefix.

Call relations: The test runner calls it to cover non-fenced code blocks.

Call graph: calls 1 internal fn (render_markdown_text); 3 external calls (from_iter, from_iter, assert_eq!).

horizontal_rule_renders_em_dashes1124–1138 ↗
fn horizontal_rule_renders_em_dashes()

Purpose: This test checks horizontal rules. A Markdown rule should become a clear divider line in the terminal.

Data flow: It renders text before and after a rule and expects the middle line to be em dashes with blank lines around it.

Call relations: The test runner calls it to verify divider rendering.

Call graph: calls 1 internal fn (render_markdown_text); 1 external calls (assert_eq!).

code_block_with_inner_triple_backticks_outer_four1141–1184 ↗
fn code_block_with_inner_triple_backticks_outer_four()

Purpose: This test checks a code block fenced with four backticks that contains triple backticks inside. It ensures inner fences are treated as content, not as the end of the block.

Data flow: It renders the block, trims unstable trailing empty lines, and compares the preserved code content.

Call relations: The test runner calls it to guard nested-fence code examples.

Call graph: calls 1 internal fn (render_markdown_text); 1 external calls (assert_eq!).

code_block_inside_unordered_list_item_is_indented1187–1201 ↗
fn code_block_inside_unordered_list_item_is_indented()

Purpose: This test checks a code block inside a bullet item. It ensures the code is indented under the list item.

Data flow: It renders a bullet followed by a fenced code block and expects the code line to keep two leading spaces.

Call relations: The test runner calls it to cover code blocks within list items.

Call graph: calls 1 internal fn (render_markdown_text); 1 external calls (assert_eq!).

code_block_multiple_lines_inside_unordered_list1204–1218 ↗
fn code_block_multiple_lines_inside_unordered_list()

Purpose: This test checks a multi-line code block inside a bullet list item. It ensures every code line keeps the same list indentation.

Data flow: It renders two code lines under a bullet and compares the plain output.

Call relations: The test runner calls it as a multi-line version of the list-code case.

Call graph: calls 1 internal fn (render_markdown_text); 1 external calls (assert_eq!).

code_block_inside_unordered_list_item_multiple_lines1221–1235 ↗
fn code_block_inside_unordered_list_item_multiple_lines()

Purpose: This test repeats the multi-line unordered-list code case. It reinforces the expected indentation for this common structure.

Data flow: It renders a bullet with two fenced code lines and expects the same indented output lines.

Call relations: The test runner calls it. It overlaps with code_block_multiple_lines_inside_unordered_list to catch regressions in the same area.

Call graph: calls 1 internal fn (render_markdown_text); 1 external calls (assert_eq!).

list_item_after_code_block_keeps_blank_separator1238–1250 ↗
fn list_item_after_code_block_keeps_blank_separator()

Purpose: This test checks that a numbered item after a code block is separated by a blank line. It prevents code blocks and following list items from visually running together.

Data flow: It renders a numbered list with a fenced code block, converts output to plain lines, checks exact lines, and records a snapshot.

Call relations: The test runner calls it. It uses plain_lines to ignore styling and focus on spacing.

Call graph: calls 2 internal fn (render_markdown_text, plain_lines); 2 external calls (assert_eq!, assert_snapshot!).

outer_list_item_after_nested_code_block_keeps_blank_separator1253–1268 ↗
fn outer_list_item_after_nested_code_block_keeps_blank_separator()

Purpose: This test checks a numbered item after a nested list item containing code. It ensures the outer next item still gets a blank separator.

Data flow: It renders nested list content with a code block, turns it into plain lines, and compares the expected spacing.

Call relations: The test runner calls it. It uses plain_lines because indentation and blank lines are the important result.

Call graph: calls 2 internal fn (render_markdown_text, plain_lines); 1 external calls (assert_eq!).

list_item_after_simple_item_stays_compact1271–1275 ↗
fn list_item_after_simple_item_stays_compact()

Purpose: This test checks that simple list items stay compact even when the source has a blank line. It prevents over-spacing ordinary lists.

Data flow: It renders two simple numbered items and expects two plain lines with no blank line between them.

Call relations: The test runner calls it to balance the code-block separator tests.

Call graph: calls 1 internal fn (render_markdown_text); 1 external calls (assert_eq!).

multiline_finding_items_are_separated_snapshot1278–1295 ↗
fn multiline_finding_items_are_separated_snapshot()

Purpose: This snapshot test checks a realistic findings list with bold titles and multi-line explanations. It protects readable spacing between long list items.

Data flow: It renders a multi-item Markdown report and compares its plain output with a saved snapshot.

Call relations: The test runner calls it. It uses render_markdown_text and snapshot testing for a larger example.

Call graph: calls 1 internal fn (render_markdown_text); 1 external calls (assert_snapshot!).

wrapped_list_item_is_separated_from_next_sibling1298–1311 ↗
fn wrapped_list_item_is_separated_from_next_sibling()

Purpose: This test checks that a wrapped list item is separated from the next sibling item. It prevents wrapped text from looking like it belongs to the next item.

Data flow: It renders a numbered list at a narrow width and expects the first item to wrap with indentation, then a blank line, then the next item.

Call relations: The test runner calls it. It uses render_markdown_text_with_width to force wrapping.

Call graph: calls 1 internal fn (render_markdown_text_with_width); 1 external calls (assert_eq!).

mixed_url_markdown_wraps_prose_without_splitting_words_snapshot1314–1318 ↗
fn mixed_url_markdown_wraps_prose_without_splitting_words_snapshot()

Purpose: This snapshot test checks word wrapping around styled text and a link. It ensures wrapping keeps prose readable and does not split words unnecessarily.

Data flow: It renders a sentence with strikethrough and a link at a fixed width, then snapshots the plain lines.

Call relations: The test runner calls it to cover wrapping mixed inline Markdown.

Call graph: calls 1 internal fn (render_markdown_text_with_width); 1 external calls (assert_snapshot!).

markdown_render_complex_snapshot1321–1389 ↗
fn markdown_render_complex_snapshot()

Purpose: This large snapshot test checks many Markdown features together. It acts like a broad smoke test for realistic assistant messages.

Data flow: It renders a long Markdown sample containing headings, links, images, quotes, lists, tasks, tables, HTML, escapes, code blocks, footnotes, and entities, then snapshots the plain text.

Call relations: The test runner calls it. It uses render_markdown_text to exercise the full renderer in one pass.

Call graph: calls 1 internal fn (render_markdown_text); 1 external calls (assert_snapshot!).

ordered_item_with_code_block_and_nested_bullet1392–1415 ↗
fn ordered_item_with_code_block_and_nested_bullet()

Purpose: This test checks a numbered list item that contains a code block and a nested bullet. It ensures the code and nested bullet line up under the correct item.

Data flow: It renders two numbered items, a fenced code block, and a nested bullet with inline code, then compares visible output lines.

Call relations: The test runner calls it to cover mixed list, code, and inline-code rendering.

Call graph: calls 1 internal fn (render_markdown_text); 1 external calls (assert_eq!).

nested_five_levels_mixed_lists1418–1432 ↗
fn nested_five_levels_mixed_lists()

Purpose: This test checks five levels of mixed list nesting. It ensures deep indentation remains predictable.

Data flow: It renders nested ordered and unordered items and compares exact styled lines at each depth.

Call relations: The test runner calls it as a stress test for list indentation.

Call graph: calls 1 internal fn (render_markdown_text); 3 external calls (from_iter, from_iter, assert_eq!).

html_inline_is_verbatim1435–1440 ↗
fn html_inline_is_verbatim()

Purpose: This test checks inline HTML. The renderer should show HTML tags as written rather than trying to interpret them like a browser.

Data flow: It renders text with span tags and expects the tags and word content to appear verbatim.

Call relations: The test runner calls it to guard inline HTML handling.

Call graph: calls 1 internal fn (render_markdown_text); 2 external calls (from_iter, assert_eq!).

html_block_is_verbatim_multiline1443–1452 ↗
fn html_block_is_verbatim_multiline()

Purpose: This test checks multi-line HTML blocks. It ensures HTML block lines are preserved as visible text.

Data flow: It renders a div block with an indented span and compares the three output lines.

Call relations: The test runner calls it as the block-level HTML case.

Call graph: calls 1 internal fn (render_markdown_text); 3 external calls (from_iter, from_iter, assert_eq!).

html_in_tight_ordered_item_soft_breaks_with_space1455–1463 ↗
fn html_in_tight_ordered_item_soft_breaks_with_space()

Purpose: This test checks inline HTML on a continuation line inside a numbered item. It ensures the continuation stays indented under the item.

Data flow: It renders an ordered item followed by an indented HTML line and compares the expected two lines.

Call relations: The test runner calls it to cover HTML inside tight list items.

Call graph: calls 1 internal fn (render_markdown_text); 3 external calls (from_iter, from_iter, assert_eq!).

html_continuation_paragraph_in_unordered_item_indented1466–1475 ↗
fn html_continuation_paragraph_in_unordered_item_indented()

Purpose: This test checks an HTML continuation paragraph inside a bullet item. It ensures the continuation paragraph keeps list indentation.

Data flow: It renders a bullet, a blank line, and indented HTML, then compares the expected rendered lines.

Call relations: The test runner calls it to cover loose-list HTML continuation.

Call graph: calls 1 internal fn (render_markdown_text); 4 external calls (default, from_iter, from_iter, assert_eq!).

unordered_item_continuation_paragraph_is_indented1478–1500 ↗
fn unordered_item_continuation_paragraph_is_indented()

Purpose: This test checks a normal continuation paragraph inside a bullet item. It ensures the paragraph remains visibly part of the bullet.

Data flow: It renders a bullet with a later two-line continuation paragraph and compares plain lines.

Call relations: The test runner calls it for unordered-list paragraph continuation behavior.

Call graph: calls 1 internal fn (render_markdown_text); 1 external calls (assert_eq!).

ordered_item_continuation_paragraph_is_indented1503–1512 ↗
fn ordered_item_continuation_paragraph_is_indented()

Purpose: This test checks a continuation paragraph inside a numbered item. It ensures the paragraph is indented under the number marker.

Data flow: It renders a numbered item, blank line, and continuation paragraph, then compares expected styled lines.

Call relations: The test runner calls it as the ordered-list counterpart to the bullet continuation test.

Call graph: calls 1 internal fn (render_markdown_text); 4 external calls (default, from_iter, from_iter, assert_eq!).

nested_item_continuation_paragraph_is_indented1515–1527 ↗
fn nested_item_continuation_paragraph_is_indented()

Purpose: This test checks a continuation paragraph inside a nested list item. It protects indentation when both nesting and paragraph breaks are involved.

Data flow: It renders an ordered item, nested bullet, continuation paragraph, and next ordered item, then compares the expected spacing.

Call relations: The test runner calls it to cover nested continuation paragraphs.

Call graph: calls 1 internal fn (render_markdown_text); 4 external calls (default, from_iter, from_iter, assert_eq!).

code_block_preserves_trailing_blank_lines1530–1560 ↗
fn code_block_preserves_trailing_blank_lines()

Purpose: This test checks that blank lines inside a fenced code block are not dropped. In code examples, blank lines can be meaningful for readability.

Data flow: It renders a Rust code block with an intentional blank line before the closing fence, finds the code line, and checks the following rendered line is blank.

Call relations: The test runner calls it to protect code-block whitespace preservation.

Call graph: calls 1 internal fn (render_markdown_text); 2 external calls (assert!, assert_eq!).

table_renders_app_style_rows_with_themed_bold_header1563–1602 ↗
fn table_renders_app_style_rows_with_themed_bold_header()

Purpose: This test checks the normal table style. It ensures headers are bold and colored, separators are dim, and body rows are not bold.

Data flow: It renders a small table, compares the visible table rows, and inspects style flags on the header, separator, and body.

Call relations: The test runner calls it to verify both table layout and table styling.

Call graph: calls 1 internal fn (render_markdown_text); 2 external calls (assert!, assert_eq!).

table_alignment_respects_markers1605–1616 ↗
fn table_alignment_respects_markers()

Purpose: This test checks Markdown table alignment markers. Left, center, and right columns should place their text differently.

Data flow: It renders an aligned table and compares the header and body spacing for the aligned columns.

Call relations: The test runner calls it to guard table alignment behavior.

Call graph: calls 1 internal fn (render_markdown_text); 1 external calls (assert_eq!).

table_separates_logical_rows_after_wrapped_content1619–1655 ↗
fn table_separates_logical_rows_after_wrapped_content()

Purpose: This test checks a table row whose content wraps onto multiple terminal lines. It ensures a separator appears after the whole logical row, not in the middle.

Data flow: It renders a table at a narrow width, confirms wrapped text appears, finds separator lines, and checks the second separator comes after the wrapped row.

Call relations: The test runner calls it. It uses render_markdown_text_with_width to force table wrapping.

Call graph: calls 1 internal fn (render_markdown_text_with_width); 2 external calls (assert!, assert_eq!).

table_wraps_file_paths_before_collapsing_narrative_columns_snapshot1658–1671 ↗
fn table_wraps_file_paths_before_collapsing_narrative_columns_snapshot()

Purpose: This snapshot test checks wide tables containing local file links and long prose. It ensures paths wrap sensibly before the table gives up on grid layout.

Data flow: It renders a wide table with current-folder context and a fixed width, converts to plain lines, and compares a snapshot.

Call relations: The test runner calls it. It uses render_markdown_text_with_width_and_cwd because both width and local file shortening matter.

Call graph: calls 1 internal fn (render_markdown_text_with_width_and_cwd); 2 external calls (new, assert_snapshot!).

table_renders_stacked_key_value_records_when_path_column_becomes_too_narrow_snapshot1674–1684 ↗
fn table_renders_stacked_key_value_records_when_path_column_becomes_too_narrow_snapshot()

Purpose: This snapshot test checks that very narrow tables can become stacked key-value records. That fallback is easier to read than a broken grid.

Data flow: It renders a table with long session paths at a narrow width and snapshots the plain output.

Call relations: The test runner calls it to cover table fallback layout.

Call graph: calls 1 internal fn (render_markdown_text_with_width); 1 external calls (assert_snapshot!).

table_renders_records_when_multiple_prose_columns_are_starved_snapshot1687–1699 ↗
fn table_renders_records_when_multiple_prose_columns_are_starved_snapshot()

Purpose: This snapshot test checks table fallback when several prose columns are too narrow. It ensures the renderer chooses a readable record layout.

Data flow: It renders an issue-ranking table at a fixed width and snapshots the plain lines.

Call relations: The test runner calls it as another table fallback scenario.

Call graph: calls 1 internal fn (render_markdown_text_with_width); 1 external calls (assert_snapshot!).

table_keeps_grid_when_only_one_compact_record_fragments_snapshot1702–1712 ↗
fn table_keeps_grid_when_only_one_compact_record_fragments_snapshot()

Purpose: This snapshot test checks that the renderer does not abandon grid layout too eagerly. If only one compact value is awkward, the table can still remain a table.

Data flow: It renders a small table with one long identifier at a limited width and snapshots the result.

Call relations: The test runner calls it to balance the table fallback tests.

Call graph: calls 1 internal fn (render_markdown_text_with_width); 1 external calls (assert_snapshot!).

table_renders_key_value_records_when_compact_fragmentation_is_systemic_snapshot1715–1725 ↗
fn table_renders_key_value_records_when_compact_fragmentation_is_systemic_snapshot()

Purpose: This snapshot test checks that a table falls back to key-value records when compact values fragment throughout the table. It protects readability on very narrow screens.

Data flow: It renders a two-column table at a very narrow width and snapshots the plain output.

Call relations: The test runner calls it to verify the systemic-fragmentation fallback decision.

Call graph: calls 1 internal fn (render_markdown_text_with_width); 1 external calls (assert_snapshot!).

table_inside_blockquote_has_quote_prefix1728–1739 ↗
fn table_inside_blockquote_has_quote_prefix()

Purpose: This test checks a table inside a blockquote. It ensures every table line still shows the quote prefix.

Data flow: It renders a quoted table, collects visible lines, checks all lines start with “> ”, and checks the table separator appears.

Call relations: The test runner calls it to cover table rendering inside quoted text.

Call graph: calls 1 internal fn (render_markdown_text); 1 external calls (assert!).

escaped_pipes_render_in_table_cells1742–1752 ↗
fn escaped_pipes_render_in_table_cells()

Purpose: This test checks escaped pipe characters inside table cells. A pipe written as \| should appear as a character, not split the cell.

Data flow: It renders a one-column table containing an escaped pipe and checks that “a | b” appears in the output.

Call relations: The test runner calls it to guard table parsing around escaped separators.

Call graph: calls 1 internal fn (render_markdown_text); 1 external calls (assert!).

table_falls_back_to_key_value_records_if_grid_cannot_fit1755–1771 ↗
fn table_falls_back_to_key_value_records_if_grid_cannot_fit()

Purpose: This test checks that a table with too many columns does not render as a broken grid. It should fall back to readable key-value records.

Data flow: It renders a ten-column table at a very narrow width, checks that first and last column values appear, and checks no grid separator characters remain.

Call relations: The test runner calls it. It uses render_markdown_text_with_width to force the fallback.

Call graph: calls 1 internal fn (render_markdown_text_with_width); 1 external calls (assert!).

table_key_value_fallback_preserves_rich_values_and_themed_labels1774–1797 ↗
fn table_key_value_fallback_preserves_rich_values_and_themed_labels()

Purpose: This test checks that table fallback keeps rich cell content and label styling. Links, bold text, and inline code should survive the layout change.

Data flow: It renders a table at a narrow width, extracts plain lines to confirm all content appears, and inspects styled spans for bold labels and underlined links.

Call relations: The test runner calls it. It uses plain_lines for content checks and direct style inspection for formatting checks.

Call graph: calls 2 internal fn (render_markdown_text_with_width, plain_lines); 1 external calls (assert!).

tui/src/render/renderable_tests.rssource ↗
testtest run

This is a small test file for the terminal user interface layout code. The real problem it checks is simple: when several things need to be drawn in a terminal window, the program must decide how many rows each thing gets. If that decision is wrong, panels can overlap, leave blank space, or crowd out more important content.

To make the tests easy to reason about, the file defines a tiny fake renderable called HeightRenderable. It does not actually draw anything. It only reports a desired height, like a cardboard placeholder that says “I would like 2 rows” or “I would like 20 rows.” That lets the tests focus only on space allocation.

The tests build a FlexRenderable, which is a layout container that stacks child items and divides available height between them. Each child has a flex value. A flex value is like a claim on leftover space: higher or nonzero values can share flexible space, while a zero value behaves more like a fixed reservation.

One test checks that if a child only wants a small height, unused room is given to another flexible child instead of being wasted. The other checks that non-flexible space is reserved first, then the remaining height is split between flexible children. Together, these tests protect the layout behavior that keeps the text interface visually balanced.

Function details5
HeightRenderable::with_height7–9 ↗
fn with_height(height: u16) -> Self

Purpose: This helper creates a fake renderable item with a chosen desired height. The tests use it so they can say exactly how tall each pretend child wants to be.

Data flow: A height number goes in. The function wraps that number inside a HeightRenderable value. The resulting object comes out ready to be put into the layout being tested.

Call relations: Both layout tests call this helper while setting up their examples. It supplies the simple test objects that FlexRenderable later asks about their preferred height.

Call graph: called by 2 (flex_redistributes_space_unused_by_short_children, flex_reserves_non_flex_space_before_flexible_children).

HeightRenderable::render13–13 ↗
fn render(&self, _area: Rect, _buf: &mut Buffer)

Purpose: This is the required drawing method for the fake renderable, but in these tests it intentionally does nothing. The tests care about height calculation, not about drawing pixels or text into a terminal buffer.

Data flow: A screen area and drawing buffer are passed in, but the function ignores them. Nothing is written, and no value is returned.

Call relations: It exists so HeightRenderable satisfies the Renderable interface used by FlexRenderable. The tests do not call it directly because they only exercise layout allocation.

HeightRenderable::desired_height15–17 ↗
fn desired_height(&self, _width: u16) -> u16

Purpose: This reports how many terminal rows the fake renderable says it wants. It is the key behavior that lets the tests simulate children with different height needs.

Data flow: The layout may provide an available width, but this fake object ignores it. It reads the height stored inside itself and returns that number unchanged.

Call relations: FlexRenderable relies on this method when deciding how much vertical space to give each child. The test functions create HeightRenderable values with known heights so the final allocations can be checked exactly.

flex_redistributes_space_unused_by_short_children21–43 ↗
fn flex_redistributes_space_unused_by_short_children()

Purpose: This test proves that flexible layout space is not wasted when one child wants less height than its initial share. In the example, a short child gets only the two rows it needs, and the extra rows are given to the taller child.

Data flow: The test starts with an empty FlexRenderable, adds two equally flexible fake children, and gives the container a 10-row area. It asks the container to allocate space, extracts only the resulting heights, and checks that they are 8 and 2.

Call relations: The test calls the layout constructor, uses HeightRenderable::with_height to create predictable child items, wraps them as owned renderable objects, and then calls the allocation behavior under test. The final assertion is the guard: if future layout changes stop redistributing unused space, this test fails.

Call graph: calls 2 internal fn (new, with_height); 4 external calls (new, new, assert_eq!, Owned).

flex_reserves_non_flex_space_before_flexible_children46–72 ↗
fn flex_reserves_non_flex_space_before_flexible_children()

Purpose: This test proves that a non-flexible child gets its requested space before flexible children split the remainder. It protects the rule that fixed-size content should not be squeezed by flexible neighbors unless there is not enough room overall.

Data flow: The test creates a FlexRenderable with three fake children: flexible, non-flexible, flexible. It gives the container 10 rows total, asks for allocation, collects the assigned heights, and checks that the result is 4, 2, and 4.

Call relations: Like the other test, it builds a controlled layout using HeightRenderable::with_height and owned renderable items. It then exercises FlexRenderable allocation and uses the assertion to confirm the fixed-height middle child is reserved first, with the leftover space shared by the two flexible children.

Call graph: calls 2 internal fn (new, with_height); 4 external calls (new, new, assert_eq!, Owned).

tui/src/status/tests.rssource ↗
testtest run

The status screen is a quick dashboard for a Codex terminal session. If it says the wrong thing, a user might misunderstand whether the tool can write files, use the network, how much model context is left, or whether rate limits are current. This test file builds many small fake sessions and checks the exact text that would appear in the terminal.

Most tests follow the same pattern. They create a temporary home directory, build a test configuration, set details such as the model, workspace folder, approval policy, permission profile, token usage, or rate-limit snapshot, then ask the real status-rendering code to draw the card. The rendered terminal lines are turned into plain strings, machine-specific paths are cleaned up, and the result is compared with saved snapshots or direct assertions.

The file also contains helpers that act like stage props: a standard test config, a workspace-write permission profile, fake token information, fixed reset times, and path sanitizing. Together, these tests cover important edge cases: custom permission labels, built-in profile names, auto-review wording, Bedrock provider URLs, hidden or visible usage links, credits display, stale limits, narrow terminal wrapping, and context-window math.

Function details45
stale_monthly_limit_marks_fresh_rolling_snapshot_stale55–80 ↗
fn stale_monthly_limit_marks_fresh_rolling_snapshot_stale()

Purpose: Checks that rate-limit data is treated as stale when the monthly spend-control part is old, even if the rolling window limit looks fresh. This prevents the status screen from showing mixed fresh and outdated billing information as if it were fully current.

Data flow: It starts with the current local time, builds a fake rate-limit display where the rolling limit is current but the monthly limit was captured 20 minutes earlier, and feeds that into the rate-limit combiner. The expected result is a stale rate-limit state.

Call relations: This is a direct unit test of the rate-limit composition logic. It calls the production combiner and stops there, using an assertion to verify that stale data is detected.

Call graph: 3 external calls (minutes, now, assert!).

app_server_workspace_write_profile82–119 ↗
fn app_server_workspace_write_profile(network_enabled: bool) -> PermissionProfile

Purpose: Builds a test permission profile that allows writing in workspace-related places while limiting the rest of the file system. Tests use it to mimic the profile produced by the app server.

Data flow: It receives a yes-or-no choice for network access. It returns a permission profile with either enabled or restricted network access, read access to the root, and write access to project roots and temporary directories.

Call relations: The shared test configuration uses this helper as its default permission setup. A permission-label test also calls it directly to check how a non-default but workspace-like profile is described.

Call graph: called by 2 (status_permissions_non_default_workspace_write_uses_workspace_label, test_config); 1 external calls (vec!).

test_config121–136 ↗
async fn test_config(temp_home: &TempDir) -> Config

Purpose: Creates a clean configuration object for status-screen tests. It gives every test a predictable starting point without reading real user configuration.

Data flow: It receives a temporary home directory. It builds a config using test-only loader overrides, sets approval review to the user, installs the workspace-write permission profile, and returns the finished config.

Call relations: Nearly every async test starts here before changing only the fields it cares about. It calls the workspace-write helper so permission-related tests begin from the same baseline.

Call graph: calls 2 internal fn (without_managed_config_for_tests, app_server_workspace_write_profile); called by 35 (status_card_token_usage_excludes_cached_tokens, status_context_window_uses_last_usage, status_model_provider_uses_bedrock_runtime_base_url_and_gates_usage_link, status_permissions_broadened_workspace_profile_shows_builtin_label, status_permissions_full_disk_managed_with_network_is_danger_full_access, status_permissions_full_disk_managed_without_network_is_external_sandbox, status_permissions_named_profile_shows_additional_writable_roots, status_permissions_named_read_only_profile_shows_builtin_label, status_permissions_named_workspace_profile_shows_builtin_label, status_permissions_non_default_workspace_write_uses_workspace_label (+15 more)); 2 external calls (path, default).

set_workspace_cwd138–144 ↗
fn set_workspace_cwd(config: &mut Config, cwd: AbsolutePathBuf)

Purpose: Sets the configuration’s current working directory and workspace roots together. This keeps the test config internally consistent when a test wants a specific project folder.

Data flow: It receives a mutable config and an absolute path. It writes that path into the current directory field, sets it as the only workspace root, and tells the permissions system about the same roots.

Call relations: Snapshot tests call this before rendering the status card so the Directory and Workspace permission lines are based on a known test path.

Call graph: called by 20 (status_card_token_usage_excludes_cached_tokens, status_permissions_non_default_workspace_write_uses_workspace_label, status_permissions_workspace_roots_include_profile_defined_directories, status_permissions_workspace_roots_show_additional_directories, status_snapshot_cached_limits_hide_credits_without_flag, status_snapshot_includes_credits_and_limits, status_snapshot_includes_enterprise_monthly_credit_limit, status_snapshot_includes_forked_from, status_snapshot_includes_monthly_limit, status_snapshot_includes_reasoning_details (+10 more)); 2 external calls (clone, vec!).

test_status_account_display146–148 ↗
fn test_status_account_display() -> Option<StatusAccountDisplay>

Purpose: Provides the account-display value used by these tests. It currently returns no account information, so tests focus on status details other than signed-in account text.

Data flow: It takes no input and returns None, meaning there is no account block to show.

Call relations: Many status-rendering tests pass its result into the production status builder. This keeps account display out of the expected snapshots unless a future test chooses to add it.

Call graph: called by 22 (permissions_text_for, status_card_token_usage_excludes_cached_tokens, status_context_window_uses_last_usage, status_model_provider_uses_bedrock_runtime_base_url_and_gates_usage_link, status_snapshot_cached_limits_hide_credits_without_flag, status_snapshot_hides_when_has_no_credits_flag, status_snapshot_hides_zero_credits, status_snapshot_includes_credits_and_limits, status_snapshot_includes_enterprise_monthly_credit_limit, status_snapshot_includes_forked_from (+12 more)).

token_info_for150–159 ↗
fn token_info_for(model_slug: &str, config: &Config, usage: &TokenUsage) -> TokenUsageInfo

Purpose: Builds token-usage information for a chosen model. This lets tests check context-window and token display using realistic model metadata without going online.

Data flow: It receives a model name, config, and token usage totals. It looks up offline model information, copies the usage into both total and last-usage fields, and returns a TokenUsageInfo value with the model’s context-window size.

Call relations: Status snapshot tests call this before rendering whenever they want token usage or context-window text to appear. It hands the resulting data to the production status-output functions.

Call graph: calls 1 internal fn (construct_model_info_offline_for_tests); called by 21 (status_card_token_usage_excludes_cached_tokens, status_snapshot_cached_limits_hide_credits_without_flag, status_snapshot_hides_when_has_no_credits_flag, status_snapshot_hides_zero_credits, status_snapshot_includes_credits_and_limits, status_snapshot_includes_enterprise_monthly_credit_limit, status_snapshot_includes_forked_from, status_snapshot_includes_monthly_limit, status_snapshot_includes_reasoning_details, status_snapshot_shows_active_user_defined_profile (+11 more)); 2 external calls (to_models_manager_config, clone).

render_lines161–171 ↗
fn render_lines(lines: &[Line<'static>]) -> Vec<String>

Purpose: Turns styled terminal lines into ordinary strings. This makes rendered status output easy to compare in tests.

Data flow: It receives a list of Ratatui Line values, each made of styled spans. It joins the text content of each line’s spans and returns a vector of plain strings.

Call relations: Almost every test uses this after asking the status card to draw itself. The plain strings are then checked with snapshots or simple text assertions.

Call graph: called by 24 (permissions_text_for, status_card_token_usage_excludes_cached_tokens, status_context_window_uses_last_usage, status_model_provider_uses_bedrock_runtime_base_url_and_gates_usage_link, status_snapshot_cached_limits_hide_credits_without_flag, status_snapshot_hides_when_has_no_credits_flag, status_snapshot_hides_zero_credits, status_snapshot_includes_credits_and_limits, status_snapshot_includes_enterprise_monthly_credit_limit, status_snapshot_includes_forked_from (+14 more)); 1 external calls (iter).

sanitize_directory173–203 ↗
fn sanitize_directory(lines: Vec<String>) -> Vec<String>

Purpose: Replaces the real rendered workspace directory with a stable placeholder. This keeps snapshot tests from changing just because a machine or operating system formats paths differently.

Data flow: It receives rendered text lines. If it finds a framed line containing Directory:, it replaces the directory value with [[workspace]] and pads the line so the box width stays unchanged; all other lines pass through unchanged.

Call relations: Snapshot tests call this after rendering and before comparing output. It makes the snapshots focus on status behavior rather than local path details.

Call graph: called by 16 (status_snapshot_cached_limits_hide_credits_without_flag, status_snapshot_includes_credits_and_limits, status_snapshot_includes_enterprise_monthly_credit_limit, status_snapshot_includes_forked_from, status_snapshot_includes_monthly_limit, status_snapshot_includes_reasoning_details, status_snapshot_shows_active_user_defined_profile, status_snapshot_shows_auto_review_permissions, status_snapshot_shows_missing_limits_message, status_snapshot_shows_refreshing_limits_notice (+6 more)).

reset_at_from205–209 ↗
fn reset_at_from(captured_at: &chrono::DateTime<chrono::Local>, seconds: i64) -> i64

Purpose: Creates a fake rate-limit reset timestamp a fixed number of seconds after a captured time. Tests use it to make reset messages predictable.

Data flow: It receives a local timestamp and a number of seconds. It adds that duration, converts the result to UTC, and returns a Unix timestamp.

Call relations: Rate-limit tests call this while building fake snapshots. The produced timestamp is then fed into the production formatter through rate_limit_snapshot_display.

Call graph: called by 9 (status_snapshot_cached_limits_hide_credits_without_flag, status_snapshot_includes_credits_and_limits, status_snapshot_includes_enterprise_monthly_credit_limit, status_snapshot_includes_monthly_limit, status_snapshot_includes_reasoning_details, status_snapshot_shows_refreshing_limits_notice, status_snapshot_shows_stale_limits_message, status_snapshot_truncates_in_narrow_terminal, status_snapshot_uses_generic_limit_labels_for_unsupported_windows); 1 external calls (seconds).

permissions_text_for211–244 ↗
fn permissions_text_for(config: &Config) -> Option<String>

Purpose: Extracts just the Permissions text from a rendered status card. This lets permission-label tests make short, focused assertions instead of comparing a whole screen snapshot.

Data flow: It receives a config, builds a minimal status card with fixed time and default token usage, renders it, finds the line containing Permissions:, trims the frame characters and spacing, and returns the text after that label.

Call relations: Several permission tests call this after changing the config’s permission profile or approval policy. It calls the real status-output builder, so the assertion checks user-visible behavior.

Call graph: calls 3 internal fn (get_model_offline_for_tests, render_lines, test_status_account_display); 2 external calls (default, new_status_output).

status_snapshot_includes_reasoning_details247–319 ↗
async fn status_snapshot_includes_reasoning_details()

Purpose: Checks that the status card includes model reasoning details, token usage, rate limits, and permission information in a normal-width terminal. This guards the full user-facing layout for a reasoning-capable model.

Data flow: It builds a config for an OpenAI model with detailed reasoning enabled, sets workspace permissions, creates token usage and rate-limit data, renders the status card, normalizes paths, and compares the result to a saved snapshot.

Call relations: This test uses the shared config, workspace, token, reset-time, rendering, and sanitizing helpers. It exercises the main new_status_output path with a reasoning-effort override.

Call graph: calls 9 internal fn (get_model_offline_for_tests, workspace_write, render_lines, reset_at_from, sanitize_directory, set_workspace_cwd, test_config, test_status_account_display, token_info_for); 6 external calls (new, assert_snapshot!, cfg!, test_path_buf, new_status_output, rate_limit_snapshot_display).

status_permissions_non_default_workspace_write_uses_workspace_label322–344 ↗
async fn status_permissions_non_default_workspace_write_uses_workspace_label()

Purpose: Verifies that a custom profile matching workspace-write behavior is described with a clear workspace label instead of a vague custom label alone.

Data flow: It creates a config, enables on-request approvals, sets a workspace path, installs the app-server-style workspace-write profile, renders only the permission text, and expects a workspace-with-network-access description.

Call relations: It uses the app-server profile helper and the permission-text extractor. The result checks how production status text names this kind of permission setup.

Call graph: calls 3 internal fn (app_server_workspace_write_profile, set_workspace_cwd, test_config); 3 external calls (new, assert_eq!, test_path_buf).

status_permissions_named_read_only_profile_shows_builtin_label347–367 ↗
async fn status_permissions_named_read_only_profile_shows_builtin_label()

Purpose: Checks that the built-in read-only permission profile is shown as Read Only. This matters because users need to quickly understand that file writes are blocked.

Data flow: It creates a config, sets approval to on-request, applies a read-only profile snapshot marked as the active built-in read-only profile, and reads the rendered permission text.

Call relations: It relies on test_config for setup and permissions_text_for indirectly through the assertion. The production permission display is expected to recognize the built-in profile name.

Call graph: calls 4 internal fn (read_only, active, read_only, test_config); 2 external calls (new, assert_eq!).

status_permissions_read_only_profile_shows_additional_writable_roots370–397 ↗
async fn status_permissions_read_only_profile_shows_additional_writable_roots()

Purpose: Makes sure a read-only active profile still displays as Read Only even when runtime permissions include extra writable roots. This prevents noisy internal details from changing the main label.

Data flow: It creates a read-only file-system policy with an extra writable directory, stores it as the active read-only profile snapshot, renders the permission text, and expects the built-in read-only wording.

Call relations: The test builds on the shared config and production permission snapshot path. It confirms that extra writable roots do not override the active profile label.

Call graph: calls 5 internal fn (read_only, active, from_runtime_permissions, read_only, test_config); 4 external calls (new, assert_eq!, test_path_buf, from_ref).

status_permissions_named_workspace_profile_shows_builtin_label400–420 ↗
async fn status_permissions_named_workspace_profile_shows_builtin_label()

Purpose: Checks that the built-in workspace profile appears as Workspace. This gives users a familiar label for the common mode where the project can be edited.

Data flow: It creates a config, turns on request-based approval, applies the workspace-write profile with the built-in workspace active name, renders the permission text, and compares it to the expected label.

Call relations: It uses the same permission-text rendering path as other label tests. The production code must recognize the built-in workspace profile identifier.

Call graph: calls 4 internal fn (new, active, workspace_write, test_config); 2 external calls (new, assert_eq!).

status_permissions_workspace_auto_review_shows_reviewer_label423–444 ↗
async fn status_permissions_workspace_auto_review_shows_reviewer_label()

Purpose: Verifies that when auto-review is responsible for approvals, the permission line says Approve for me instead of Ask for approval. This wording tells the user who is making approval decisions.

Data flow: It creates a workspace profile config, changes the approvals reviewer to auto-review, renders the permission text, and checks the reviewer phrase.

Call relations: The test starts from the shared config and uses the production permission display. It focuses on the interaction between approval policy and approval reviewer.

Call graph: calls 4 internal fn (new, active, workspace_write, test_config); 2 external calls (new, assert_eq!).

status_permissions_named_profile_shows_additional_writable_roots447–473 ↗
async fn status_permissions_named_profile_shows_additional_writable_roots()

Purpose: Checks that a workspace profile with additional writable roots still uses the built-in workspace label. The display should not become confusing just because the profile contains extra directories.

Data flow: It creates an extra root, builds a workspace-write profile that includes it, marks the built-in workspace profile as active, renders permission text, and expects the normal workspace wording.

Call relations: This test feeds a broadened profile into the same status-rendering path used by normal permission tests. It confirms that the active built-in profile name remains the main label.

Call graph: calls 4 internal fn (new, active, workspace_write_with, test_config); 4 external calls (new, assert_eq!, test_path_buf, from_ref).

status_permissions_workspace_roots_show_additional_directories476–505 ↗
async fn status_permissions_workspace_roots_show_additional_directories()

Purpose: Checks that extra workspace roots are shown in the permission label when they come from the session’s workspace roots. This helps users see that more than the current directory may be writable.

Data flow: It sets a known current workspace, adds another workspace root, applies the workspace profile, renders permission text, and expects the extra directory to appear in brackets.

Call relations: It uses set_workspace_cwd to keep the config consistent, then relies on production permission formatting to include the extra workspace root.

Call graph: calls 5 internal fn (new, active, workspace_write, set_workspace_cwd, test_config); 4 external calls (new, assert_eq!, test_path_buf, vec!).

status_permissions_workspace_roots_include_profile_defined_directories508–541 ↗
async fn status_permissions_workspace_roots_include_profile_defined_directories()

Purpose: Checks that directories supplied by the active permission profile are included in the workspace permission label. This makes profile-defined writable areas visible to the user.

Data flow: It sets a workspace, creates a profile with an additional shared directory, records that directory as a profile workspace root, renders permission text, and expects the shared path in the label.

Call relations: The test combines workspace setup with the permission snapshot constructor for profile workspace roots. It checks that status rendering uses that snapshot information.

Call graph: calls 5 internal fn (new, active_with_profile_workspace_roots, workspace_write_with, set_workspace_cwd, test_config); 5 external calls (new, assert_eq!, test_path_buf, from_ref, vec!).

status_permissions_broadened_workspace_profile_shows_builtin_label544–569 ↗
async fn status_permissions_broadened_workspace_profile_shows_builtin_label()

Purpose: Verifies that the workspace profile with network access is labeled as workspace with network access. This makes the extra network permission visible without losing the built-in profile identity.

Data flow: It creates a config with on-request approvals, installs a workspace profile whose network policy is enabled, renders permission text, and checks the expected wording.

Call relations: It uses the production permission display through the helper. The test focuses on how a built-in workspace profile is described when broadened with network access.

Call graph: calls 4 internal fn (new, active, workspace_write_with, test_config); 2 external calls (new, assert_eq!).

status_permissions_user_defined_profile_shows_name572–587 ↗
async fn status_permissions_user_defined_profile_shows_name()

Purpose: Checks that a user-defined active profile name is shown in the status line. This helps users confirm that their named profile, not just a generic mode, is active.

Data flow: It creates a config, applies a read-only profile snapshot with the active name locked, renders permission text, and expects text beginning with Profile locked.

Call relations: The shared config supplies defaults, while the production status text decides how to combine the user profile name, underlying permission shape, and approval wording.

Call graph: calls 4 internal fn (new, active, read_only, test_config); 2 external calls (new, assert_eq!).

status_snapshot_shows_active_user_defined_profile590–634 ↗
async fn status_snapshot_shows_active_user_defined_profile()

Purpose: Checks the full status-card snapshot when a user-defined profile is active. It ensures the named profile appears correctly in the overall panel, not only in an isolated permission line.

Data flow: It builds a config with a known workspace and model, installs a read-only profile named locked, prepares token info, renders the card, cleans the directory path, and compares with a snapshot.

Call relations: This test uses the shared config, workspace, token, render, and sanitize helpers. It exercises the main status-output builder with a user-defined profile.

Call graph: calls 10 internal fn (new, active, get_model_offline_for_tests, read_only, render_lines, sanitize_directory, set_workspace_cwd, test_config, test_status_account_display, token_info_for); 6 external calls (new, assert_snapshot!, cfg!, test_path_buf, default, new_status_output).

status_snapshot_shows_auto_review_permissions744–789 ↗
async fn status_snapshot_shows_auto_review_permissions()

Purpose: Checks the full status-card snapshot when auto-review approvals are enabled. This ensures the complete panel uses the right approval wording.

Data flow: It creates a workspace model config, switches approval review to auto-review, applies the workspace profile, prepares token info, renders the status card, sanitizes the directory, and compares with a snapshot.

Call relations: It uses the standard setup helpers and the main status builder. It complements the smaller permission-text test by checking the full rendered card.

Call graph: calls 10 internal fn (new, active, get_model_offline_for_tests, workspace_write, render_lines, sanitize_directory, set_workspace_cwd, test_config, test_status_account_display, token_info_for); 6 external calls (new, assert_snapshot!, cfg!, test_path_buf, default, new_status_output).

status_permissions_full_disk_managed_with_network_is_danger_full_access792–812 ↗
async fn status_permissions_full_disk_managed_with_network_is_danger_full_access()

Purpose: Verifies that unrestricted file access plus network access is labeled danger-full-access. This wording warns users that the tool has broad power.

Data flow: It creates a config, enables on-request approvals, sets a managed profile with unrestricted file system access and enabled network, renders permission text, and checks the warning-style label.

Call relations: The test uses the shared config and the permission-text helper. It checks the production label for the most permissive managed sandbox setup.

Call graph: calls 1 internal fn (test_config); 2 external calls (new, assert_eq!).

status_permissions_full_disk_managed_without_network_is_external_sandbox815–835 ↗
async fn status_permissions_full_disk_managed_without_network_is_external_sandbox()

Purpose: Verifies that unrestricted disk access without network is labeled as an external sandbox. This distinguishes it from full network-enabled access.

Data flow: It creates a config, enables on-request approvals, sets unrestricted file-system access but restricted network access, renders permission text, and checks the external-sandbox label.

Call relations: Like the full-access test, it goes through production permission rendering. The only changed input is the network policy, proving that network access affects the label.

Call graph: calls 1 internal fn (test_config); 2 external calls (new, assert_eq!).

status_snapshot_includes_forked_from838–889 ↗
async fn status_snapshot_includes_forked_from()

Purpose: Checks that the status card shows when the current session was forked from another session. This helps users understand session history.

Data flow: It creates a config and token usage, builds fixed current and parent thread IDs, renders the status card with both IDs, sanitizes the output, and compares it to a snapshot.

Call relations: The test uses helpers for config, workspace, account display, token info, rendering, and sanitizing. It exercises the main status builder’s session lineage inputs.

Call graph: calls 8 internal fn (get_model_offline_for_tests, from_string, render_lines, sanitize_directory, set_workspace_cwd, test_config, test_status_account_display, token_info_for); 5 external calls (new, assert_snapshot!, cfg!, test_path_buf, new_status_output).

status_snapshot_includes_monthly_limit892–953 ↗
async fn status_snapshot_includes_monthly_limit()

Purpose: Checks that a monthly rate limit appears correctly in the status card. This tells users when a longer-term usage limit is active.

Data flow: It builds a fake rate-limit snapshot with a monthly-sized window, formats it for display, renders the full status card with token info, sanitizes the directory, and compares with a snapshot.

Call relations: It uses reset_at_from to make the reset time stable and rate_limit_snapshot_display to pass realistic display data into the production status builder.

Call graph: calls 8 internal fn (get_model_offline_for_tests, render_lines, reset_at_from, sanitize_directory, set_workspace_cwd, test_config, test_status_account_display, token_info_for); 6 external calls (new, assert_snapshot!, cfg!, test_path_buf, new_status_output, rate_limit_snapshot_display).

status_snapshot_includes_enterprise_monthly_credit_limit956–1029 ↗
async fn status_snapshot_includes_enterprise_monthly_credit_limit()

Purpose: Checks display of an enterprise monthly spend-control limit, including wrapping in a narrow terminal. This protects both the content and layout of billing-limit information.

Data flow: It creates a snapshot with an individual monthly limit showing used amount, total limit, remaining percent, and reset time. It renders the status card at a wider width and a narrow width, sanitizes both, and compares both outputs to snapshots.

Call relations: The test uses the shared rendering path twice with different widths. It verifies that production layout code can wrap long monthly credit details cleanly.

Call graph: calls 8 internal fn (get_model_offline_for_tests, render_lines, reset_at_from, sanitize_directory, set_workspace_cwd, test_config, test_status_account_display, token_info_for); 6 external calls (new, assert_snapshot!, cfg!, test_path_buf, new_status_output, rate_limit_snapshot_display).

status_snapshot_uses_generic_limit_labels_for_unsupported_windows1032–1097 ↗
async fn status_snapshot_uses_generic_limit_labels_for_unsupported_windows()

Purpose: Checks that unfamiliar rate-limit window lengths get generic labels instead of misleading names. This avoids pretending an unsupported two-hour or three-hour window is a known daily or weekly limit.

Data flow: It builds primary and secondary rate-limit windows with unusual durations, renders the status card, sanitizes the output, and compares with a snapshot.

Call relations: It feeds unusual window values through the normal rate-limit formatter and status builder. The snapshot captures how production code labels unsupported windows.

Call graph: calls 8 internal fn (get_model_offline_for_tests, render_lines, reset_at_from, sanitize_directory, set_workspace_cwd, test_config, test_status_account_display, token_info_for); 6 external calls (new, assert_snapshot!, cfg!, test_path_buf, new_status_output, rate_limit_snapshot_display).

status_snapshot_shows_unlimited_credits1100–1148 ↗
async fn status_snapshot_shows_unlimited_credits()

Purpose: Verifies that unlimited credits are shown as Unlimited. Users should see clearly when their credit balance is not a finite number.

Data flow: It builds a rate-limit snapshot with credits enabled and marked unlimited, renders the card, converts lines to strings, and checks for a Credits line containing Unlimited.

Call relations: This test uses the real rate-limit display conversion and status builder. It makes a focused text assertion rather than a full snapshot.

Call graph: calls 5 internal fn (get_model_offline_for_tests, render_lines, test_config, test_status_account_display, token_info_for); 5 external calls (new, assert!, default, new_status_output, rate_limit_snapshot_display).

status_snapshot_shows_positive_credits1151–1199 ↗
async fn status_snapshot_shows_positive_credits()

Purpose: Checks that a positive credit balance is displayed and rounded for the user. This protects the simple credit summary shown in status.

Data flow: It creates a credits snapshot with a balance of 12.5, renders the status card, and checks that the Credits line contains 13 credits.

Call relations: It passes fake credit data through the production formatter and renderer. The assertion verifies the rounded user-facing value.

Call graph: calls 5 internal fn (get_model_offline_for_tests, render_lines, test_config, test_status_account_display, token_info_for); 5 external calls (new, assert!, default, new_status_output, rate_limit_snapshot_display).

status_snapshot_hides_zero_credits1202–1248 ↗
async fn status_snapshot_hides_zero_credits()

Purpose: Checks that a zero credit balance is not shown as a Credits line. This avoids cluttering the status card with unhelpful credit information.

Data flow: It creates a credits snapshot with balance 0, renders the status card, and asserts that no rendered line contains Credits:.

Call relations: The test uses the standard status-rendering path. It verifies the production rule that zero credits are hidden.

Call graph: calls 5 internal fn (get_model_offline_for_tests, render_lines, test_config, test_status_account_display, token_info_for); 5 external calls (new, assert!, default, new_status_output, rate_limit_snapshot_display).

status_snapshot_hides_when_has_no_credits_flag1251–1297 ↗
async fn status_snapshot_hides_when_has_no_credits_flag()

Purpose: Checks that credits are hidden when the snapshot says the user does not have credits, even if other fields suggest unlimited credits. The explicit flag wins.

Data flow: It builds a snapshot with has_credits false, renders the status card, and asserts that no Credits line appears.

Call relations: This test passes contradictory-looking credit data through the real formatter. It confirms that the display trusts the has_credits flag.

Call graph: calls 5 internal fn (get_model_offline_for_tests, render_lines, test_config, test_status_account_display, token_info_for); 5 external calls (new, assert!, default, new_status_output, rate_limit_snapshot_display).

status_card_token_usage_excludes_cached_tokens1300–1343 ↗
async fn status_card_token_usage_excludes_cached_tokens()

Purpose: Verifies that cached input tokens are not separately displayed in the status card. This keeps token usage text focused on the values the UI intends to show.

Data flow: It creates token usage with cached input tokens, renders the status card, and asserts that no line contains the word cached.

Call relations: The test uses the shared config, workspace, account, token, and rendering helpers. It checks the production token display behavior.

Call graph: calls 6 internal fn (get_model_offline_for_tests, render_lines, set_workspace_cwd, test_config, test_status_account_display, token_info_for); 4 external calls (new, assert!, test_path_buf, new_status_output).

status_snapshot_truncates_in_narrow_terminal1346–1410 ↗
async fn status_snapshot_truncates_in_narrow_terminal()

Purpose: Checks that the status card remains acceptable in a narrow terminal. This protects users from broken or overflowing layout when the window is small.

Data flow: It builds a rich status card with reasoning details, token usage, and rate limits, renders it at width 70, normalizes paths, and compares to a snapshot.

Call relations: It uses the same setup as the reasoning-details snapshot but changes the width. This specifically exercises the production truncation and wrapping rules.

Call graph: calls 8 internal fn (get_model_offline_for_tests, render_lines, reset_at_from, sanitize_directory, set_workspace_cwd, test_config, test_status_account_display, token_info_for); 6 external calls (new, assert_snapshot!, cfg!, test_path_buf, new_status_output, rate_limit_snapshot_display).

status_snapshot_shows_missing_limits_message1413–1458 ↗
async fn status_snapshot_shows_missing_limits_message()

Purpose: Checks what the status card says when no rate-limit data is available at all. Users should get a clear missing-limits message rather than a blank or misleading section.

Data flow: It builds a normal config and token usage but passes no rate-limit display data, renders the card, sanitizes the output, and compares with a snapshot.

Call relations: The test goes through the main new_status_output path with rate_limits set to none. It verifies the fallback message for absent limit data.

Call graph: calls 7 internal fn (get_model_offline_for_tests, render_lines, sanitize_directory, set_workspace_cwd, test_config, test_status_account_display, token_info_for); 5 external calls (new, assert_snapshot!, cfg!, test_path_buf, new_status_output).

status_snapshot_uses_default_reasoning_when_config_empty1461–1514 ↗
async fn status_snapshot_uses_default_reasoning_when_config_empty()

Purpose: Checks that the status card can show a default reasoning effort when the config has no explicit reasoning setting. It also includes remote connection details.

Data flow: It creates a model config without a reasoning summary, adds a fake remote app-server connection, passes a medium reasoning-effort override, renders the card, sanitizes it, and compares to a snapshot.

Call relations: This test uses the status builder variant that accepts remote connection and rate-limit-handle inputs. It verifies how production output fills in reasoning information from runtime data.

Call graph: calls 7 internal fn (get_model_offline_for_tests, render_lines, sanitize_directory, set_workspace_cwd, test_config, test_status_account_display, token_info_for); 5 external calls (new, assert_snapshot!, cfg!, test_path_buf, new_status_output_with_rate_limits_handle).

status_snapshot_shows_refreshing_limits_notice1517–1580 ↗
async fn status_snapshot_shows_refreshing_limits_notice()

Purpose: Checks that the status card tells the user when rate limits are currently being refreshed. This prevents cached data from looking like the final answer.

Data flow: It creates current rate-limit data, calls the status builder that accepts many rate-limit displays with the refreshing flag set, renders and sanitizes the result, and compares with a snapshot.

Call relations: The test uses new_status_output_with_rate_limits, passing the refresh state into production rendering. It verifies the notice shown alongside existing limit data.

Call graph: calls 7 internal fn (get_model_offline_for_tests, render_lines, reset_at_from, sanitize_directory, set_workspace_cwd, test_config, token_info_for); 7 external calls (new, assert_snapshot!, cfg!, test_path_buf, from_ref, new_status_output_with_rate_limits, rate_limit_snapshot_display).

status_snapshot_includes_credits_and_limits1583–1651 ↗
async fn status_snapshot_includes_credits_and_limits()

Purpose: Checks that credits and rolling rate limits can appear together in the same status card. This protects the combined billing-and-limit view.

Data flow: It builds token usage plus a rate-limit snapshot containing primary and secondary windows and a positive credit balance, renders the card, sanitizes it, and compares with a snapshot.

Call relations: It uses reset-time and token-info helpers before calling the main status builder. The snapshot verifies how production code combines multiple limit-related signals.

Call graph: calls 8 internal fn (get_model_offline_for_tests, render_lines, reset_at_from, sanitize_directory, set_workspace_cwd, test_config, test_status_account_display, token_info_for); 6 external calls (new, assert_snapshot!, cfg!, test_path_buf, new_status_output, rate_limit_snapshot_display).

status_snapshot_shows_unavailable_limits_message1654–1710 ↗
async fn status_snapshot_shows_unavailable_limits_message()

Purpose: Checks the message shown when a rate-limit snapshot exists but contains no usable limits or credits. This is different from having no snapshot at all.

Data flow: It creates an empty rate-limit snapshot, converts it to display data, renders the status card, sanitizes output, and compares with a snapshot.

Call relations: The test feeds an empty snapshot through the normal formatter into the main status builder. It verifies the unavailable-limits fallback path.

Call graph: calls 7 internal fn (get_model_offline_for_tests, render_lines, sanitize_directory, set_workspace_cwd, test_config, test_status_account_display, token_info_for); 6 external calls (new, assert_snapshot!, cfg!, test_path_buf, new_status_output, rate_limit_snapshot_display).

status_snapshot_treats_refreshing_empty_limits_as_unavailable1713–1769 ↗
async fn status_snapshot_treats_refreshing_empty_limits_as_unavailable()

Purpose: Checks that an empty limit snapshot is still shown as unavailable even while refreshing. This avoids implying that useful current data is present.

Data flow: It creates an empty rate-limit snapshot, renders through the rate-limits builder with the refreshing flag set, sanitizes the output, and compares with a snapshot.

Call relations: This test uses new_status_output_with_rate_limits instead of the simpler builder. It verifies the interaction between empty limit data and the refresh state.

Call graph: calls 6 internal fn (get_model_offline_for_tests, render_lines, sanitize_directory, set_workspace_cwd, test_config, token_info_for); 7 external calls (new, assert_snapshot!, cfg!, test_path_buf, from_ref, new_status_output_with_rate_limits, rate_limit_snapshot_display).

status_snapshot_shows_stale_limits_message1772–1837 ↗
async fn status_snapshot_shows_stale_limits_message()

Purpose: Checks that old rate-limit data is labeled as stale. This warns users that the displayed limits may no longer be accurate.

Data flow: It creates rate-limit data captured at a fixed time, advances the current time by 20 minutes, renders the status card, sanitizes it, and compares with a snapshot.

Call relations: The test relies on the production stale-detection path inside status rendering. It uses fixed reset times and token info to make the snapshot stable.

Call graph: calls 8 internal fn (get_model_offline_for_tests, render_lines, reset_at_from, sanitize_directory, set_workspace_cwd, test_config, test_status_account_display, token_info_for); 7 external calls (minutes, new, assert_snapshot!, cfg!, test_path_buf, new_status_output, rate_limit_snapshot_display).

status_snapshot_cached_limits_hide_credits_without_flag1840–1909 ↗
async fn status_snapshot_cached_limits_hide_credits_without_flag()

Purpose: Checks that cached rate-limit data does not show credits unless the credits flag says credits are available. This avoids displaying stale or irrelevant credit balances.

Data flow: It creates cached-looking rate-limit data with a credit balance but has_credits set to false, renders at a later time, sanitizes output, and compares with a snapshot.

Call relations: It passes the snapshot through the normal rate-limit display and status builder. The test confirms that the production renderer hides credits according to the flag even when other limit data is present.

Call graph: calls 8 internal fn (get_model_offline_for_tests, render_lines, reset_at_from, sanitize_directory, set_workspace_cwd, test_config, test_status_account_display, token_info_for); 7 external calls (minutes, new, assert_snapshot!, cfg!, test_path_buf, new_status_output, rate_limit_snapshot_display).

status_context_window_uses_last_usage1912–1973 ↗
async fn status_context_window_uses_last_usage()

Purpose: Verifies that the context-window line uses the most recent message’s token usage, not the total tokens accumulated across the whole session. This matters because the model’s context window limits what fits in the current request.

Data flow: It creates separate total and last token usage values, sets a known context-window size, renders the status card, finds the Context window line, and checks that it contains the last-usage number and not the total session number.

Call relations: This test constructs TokenUsageInfo directly instead of using token_info_for, because it needs different total and last usage values. It then calls the main status builder and inspects the rendered line.

Call graph: calls 4 internal fn (get_model_offline_for_tests, render_lines, test_config, test_status_account_display); 3 external calls (new, assert!, new_status_output).

Integration and VT100 smoke tests

These integration suites verify terminal-backed behavior, architectural boundaries, resize/reflow behavior, and VT100 history/live rendering in end-to-end or smoke-test form.

tui/tests/manager_dependency_regression.rssource ↗
testtest run

This file is a regression test, meaning it exists to stop an old architectural problem from coming back. The text user interface runtime code should not reach directly for certain “manager” escape hatches, such as AuthManager or ThreadManager. Those managers may be important elsewhere, but using them directly from this layer would blur responsibilities and make the interface code harder to reason about, test, and change.

The test works by finding the real source directory that contains chatwidget.rs, then walking through every Rust source file under that directory. For each file, it reads the text and searches for a short list of forbidden words and function-call patterns. If any are found, it reports exactly which file contains which forbidden string.

An everyday analogy is a building inspection checklist. The test does not prove the whole building is perfect, but it checks that certain blocked-off doors have not been reopened. Without this file, a developer could accidentally add a direct dependency on these manager escape hatches, and the codebase might only feel the damage later as tighter coupling and harder maintenance.

Function details2
rust_sources_under6–20 ↗
fn rust_sources_under(dir: &Path) -> Vec<PathBuf>

Purpose: This helper finds all Rust source files under a given folder, including files in nested subfolders. The test uses it so it can check the whole runtime source area instead of only one file.

Data flow: It receives a folder path. It reads that folder, looks at each entry, recursively enters subfolders, and keeps paths whose file extension is .rs. It sorts the collected paths and returns them as a list of Rust source files.

Call relations: The regression test calls this helper after it has located the source directory. This helper does the file-tree walking work, then hands back the complete list of Rust files that the test will inspect for forbidden dependency names.

Call graph: called by 1 (tui_runtime_source_does_not_depend_on_manager_escape_hatches); 2 external calls (new, read_dir).

tui_runtime_source_does_not_depend_on_manager_escape_hatches23–54 ↗
fn tui_runtime_source_does_not_depend_on_manager_escape_hatches()

Purpose: This is the actual test. It verifies that the TUI runtime source does not mention specific manager types or accessor calls that are considered forbidden in this layer.

Data flow: It starts by locating src/chatwidget.rs as a known anchor file, then uses that file’s parent directory as the source root to scan. It asks rust_sources_under for all Rust files there, reads each file as text, searches for forbidden strings, collects any matches into human-readable messages, and finally asserts that the list of violations is empty.

Call relations: During the test run, the test framework calls this function. It uses find_resource! to locate the source file, delegates directory scanning to rust_sources_under, and then uses an assertion to fail the test if any forbidden manager dependency appears.

Call graph: calls 1 internal fn (rust_sources_under); 2 external calls (assert!, find_resource!).

tui/tests/suite/resize_reflow.rssource ↗
testmanual integration testing

These tests act like a careful human tester using Codex in a terminal multiplexer called tmux, which lets one terminal window be split and resized. The file starts a real Codex binary in a temporary, isolated home directory, points it at a fake local OpenAI-style server, and feeds it a predictable response. That fake response includes a unique phrase, “resize reflow sentinel,” so the test can find the same piece of output again after the terminal changes shape.

The main idea is simple: take a snapshot of the pane, resize it by splitting tmux, wait for Codex to redraw, then take another snapshot. The tests compare row numbers. They look for the composer row, which is the prompt line where the user types, and for a known line in the conversation history. If either row drifts after the pane is restored, the test fails.

The file also includes small helpers for finding the Codex binary, writing temporary config and auth files, capturing tmux pane text, waiting until expected text appears, and cleaning up tmux sessions. Because these tests need tmux, a built binary, and network-related test setup, they are ignored by default and are meant to be run manually as resize smoke tests.

Function details17
tmux_split_preserves_fresh_session_composer_row_after_resize_reflow18–164 ↗
async fn tmux_split_preserves_fresh_session_composer_row_after_resize_reflow() -> Result<()>

Purpose: This test checks that a fresh Codex session keeps its input prompt in the right vertical position after the tmux pane is split and then restored. It is meant to catch a resize bug where the composer row slowly moves down or the visible history shifts after reflow.

Data flow: It starts by skipping environments that cannot run the test, then creates a temporary Codex home, a fake model server, config files, and a tmux session running Codex. It waits until the fake response and model label are visible, types a draft message, records where the composer and sentinel text appear, creates a vertical split, captures the pane again, and compares row positions before and after. If the rows do not stay anchored within the expected bounds, it returns an error; otherwise it finishes successfully and the tmux session is cleaned up.

Call relations: This is one of the top-level ignored tests. It calls the setup helpers to find the binary, write config and auth, build the fake server response, and run tmux commands. During the check phase it relies on capture_pane, wait_for_capture_contains, last_composer_row, and first_row_containing to turn the visible terminal screen into row numbers that can be compared.

Call graph: calls 12 internal fn (mount_sse_once, capture_pane, check, checked_output, codex_binary, first_row_containing, last_composer_row, resize_reflow_sse, stdout_text, wait_for_capture_contains (+2 more)); 12 external calls (from_millis, from_secs, start, ensure!, cfg!, new, repo_root, eprintln!, format!, skip_if_no_network! (+2 more)).

tmux_repeated_resizes_do_not_push_composer_down168–181 ↗
async fn tmux_repeated_resizes_do_not_push_composer_down() -> Result<()>

Purpose: This test checks the repeated-resize version of the same problem: the composer should not creep downward after several split-and-restore cycles. It is a wrapper around the longer repeated resize scenario.

Data flow: It first exits harmlessly on Windows, when network-dependent test support is unavailable, or when tmux is missing. If the environment is suitable, it delegates the real setup and checking work to run_repeated_resize_smoke and returns that result.

Call relations: This is a top-level ignored test that keeps the environment checks close to the test declaration. Once those checks pass, it hands the story off to run_repeated_resize_smoke, which performs the actual tmux session setup, resizing loop, and row comparisons.

Call graph: calls 1 internal fn (run_repeated_resize_smoke); 4 external calls (cfg!, new, eprintln!, skip_if_no_network!).

tmux_width_resize_restore_keeps_visible_content_anchored185–312 ↗
async fn tmux_width_resize_restore_keeps_visible_content_anchored() -> Result<()>

Purpose: This test checks horizontal resizing, not just height changes. It makes sure that narrowing the Codex pane with a side split and then restoring the width does not move the visible composer or known history line.

Data flow: It prepares a temporary Codex environment and fake response, starts Codex in a tmux pane, waits for known output, types a draft, and records baseline row positions. It then creates a horizontal tmux split that reduces the pane width, waits, closes the split, captures the restored pane, and compares the restored composer and history rows against the baseline. A mismatch becomes a test failure with the before-and-after pane text included for diagnosis.

Call relations: This top-level ignored test follows the same pattern as the vertical resize test, but uses a side-by-side tmux split. It calls the shared helpers for binary discovery, config writing, fake server response creation, command checking, pane capture, and row finding so that only the resize scenario itself differs.

Call graph: calls 12 internal fn (mount_sse_once, capture_pane, check, checked_output, codex_binary, first_row_containing, last_composer_row, resize_reflow_sse, stdout_text, wait_for_capture_contains (+2 more)); 12 external calls (from_millis, from_secs, start, ensure!, cfg!, new, repo_root, eprintln!, format!, skip_if_no_network! (+2 more)).

run_repeated_resize_smoke314–435 ↗
async fn run_repeated_resize_smoke() -> Result<()>

Purpose: This helper runs the full repeated-resize smoke test after the outer test has decided the environment is suitable. It verifies that several vertical split-and-restore cycles leave both the composer and visible history exactly where they started.

Data flow: It creates a temporary Codex home, fake model server, tmux session, and baseline pane capture. It finds the composer row and sentinel history row, then loops through three resize cycles: split the pane, wait briefly, kill the split pane, wait for redraw, capture the pane, and compare the restored rows to the original rows. It returns success only if every cycle restores the same visible layout.

Call relations: tmux_repeated_resizes_do_not_push_composer_down calls this after doing skip checks. Inside the scenario, this function uses the same helper chain as the other smoke tests: codex_binary, write_config, write_auth, resize_reflow_sse, checked_output, check, stdout_text, wait_for_capture_contains, capture_pane, last_composer_row, and first_row_containing.

Call graph: calls 12 internal fn (mount_sse_once, capture_pane, check, checked_output, codex_binary, first_row_containing, last_composer_row, resize_reflow_sse, stdout_text, wait_for_capture_contains (+2 more)); called by 1 (tmux_repeated_resizes_do_not_push_composer_down); 9 external calls (from_millis, from_secs, start, ensure!, new, repo_root, format!, sleep, tempdir).

TmuxSession::drop442–448 ↗
fn drop(&mut self)

Purpose: This cleanup hook kills the tmux session when the TmuxSession guard goes out of scope. It prevents failed or interrupted tests from leaving stray tmux sessions behind.

Data flow: It reads the stored tmux session name, runs tmux kill-session -t <name>, and ignores the result. Nothing is returned; the important effect is best-effort cleanup of an external process.

Call relations: The tests create a TmuxSession value after choosing a unique session name. They do not call this method directly; Rust calls it automatically when the guard is dropped, including during error returns, much like a hotel keycard that closes the room when you leave.

Call graph: 1 external calls (new).

codex_binary451–462 ↗
fn codex_binary(repo_root: &Path) -> Result<PathBuf>

Purpose: This helper finds the Codex executable that the tmux tests should run. It lets the test use the normal cargo-built test binary path when available, with a clear fallback to the debug build location.

Data flow: It receives the repository root path. It first asks the cargo helper for the codex binary; if that works, it returns that path. If not, it checks for codex-rs/target/debug/codex under the repo root and returns it only if the file exists; otherwise it returns an error telling the user to build the CLI first.

Call relations: All three smoke scenarios call this during setup before starting tmux. The returned path is passed into the tmux new-session command so the test launches the local Codex binary rather than some unrelated program.

Call graph: called by 3 (run_repeated_resize_smoke, tmux_split_preserves_fresh_session_composer_row_after_resize_reflow, tmux_width_resize_restore_keeps_visible_content_anchored); 3 external calls (join, ensure!, cargo_bin).

write_config464–477 ↗
fn write_config(codex_home: &Path, repo_root: &Path) -> Result<()>

Purpose: This helper writes a minimal Codex configuration file into the temporary test home directory. It tells Codex which model/provider to use and marks the repository as trusted so the smoke test can run without interactive setup.

Data flow: It receives the temporary Codex home path and repository root path. It builds a TOML configuration string containing the fake model name, OpenAI provider choice, warning suppression, and trusted project entry, then writes that text to config.toml. On success it returns nothing; on file write failure it returns an error.

Call relations: Each smoke scenario calls this before launching Codex in tmux. It works together with write_auth and the command-line base URL override so the Codex process starts in a fully prepared, isolated test environment.

Call graph: called by 3 (run_repeated_resize_smoke, tmux_split_preserves_fresh_session_composer_row_after_resize_reflow, tmux_width_resize_restore_keeps_visible_content_anchored); 4 external calls (display, join, format!, write).

write_auth479–485 ↗
fn write_auth(codex_home: &Path) -> Result<()>

Purpose: This helper writes fake authentication data into the temporary Codex home directory. It gives Codex a dummy API key so the program can start normally while requests are actually served by the local mock server.

Data flow: It receives the temporary Codex home path, writes a small auth.json file containing OPENAI_API_KEY set to dummy, and returns success or a file write error. It does not contact any real authentication service.

Call relations: Each smoke scenario calls this during setup, right after writing config. Together with the environment variable OPENAI_API_KEY=dummy, it keeps the launched Codex process satisfied without using real credentials.

Call graph: called by 3 (run_repeated_resize_smoke, tmux_split_preserves_fresh_session_composer_row_after_resize_reflow, tmux_width_resize_restore_keeps_visible_content_anchored); 2 external calls (join, write).

resize_reflow_sse487–494 ↗
fn resize_reflow_sse() -> String

Purpose: This helper builds the fake streaming model response used by the resize tests. The response includes long, wrapping text and a unique sentinel phrase so the tests can check whether visible history stays anchored.

Data flow: It starts with a fixed paragraph of text, wraps it in a sequence of server-sent events, and returns the final event stream as a string. Server-sent events are a simple web format where the server sends chunks of data over time, similar to a live transcript.

Call relations: The smoke scenarios pass this string to the mock response setup through mount_sse_once. That fake server response is what Codex displays in tmux, and later the row-finding helpers search for its sentinel phrase.

Call graph: calls 1 internal fn (sse); called by 3 (run_repeated_resize_smoke, tmux_split_preserves_fresh_session_composer_row_after_resize_reflow, tmux_width_resize_restore_keeps_visible_content_anchored); 1 external calls (vec!).

wait_for_capture_contains496–508 ↗
fn wait_for_capture_contains(pane: &str, needle: &str, timeout: Duration) -> Result<String>

Purpose: This helper repeatedly captures a tmux pane until expected text appears or a timeout expires. It gives Codex time to start, render, and receive the fake model response before the test measures row positions.

Data flow: It receives a pane id, the text to search for, and a timeout. Until the deadline, it calls capture_pane, checks whether the captured text contains the target string, and sleeps briefly between attempts. If the text appears, it returns the capture that contained it; if not, it returns an error showing the last captured screen.

Call relations: The smoke scenarios use this before making assertions, for example to wait for the sentinel text, the model label, or the typed draft. It depends on capture_pane for the actual tmux snapshot and shields the tests from racing ahead before the terminal has redrawn.

Call graph: calls 1 internal fn (capture_pane); called by 3 (run_repeated_resize_smoke, tmux_split_preserves_fresh_session_composer_row_after_resize_reflow, tmux_width_resize_restore_keeps_visible_content_anchored); 5 external calls (from_millis, now, new, bail!, sleep).

capture_pane510–519 ↗
fn capture_pane(pane: &str) -> Result<String>

Purpose: This helper reads the visible text from a tmux pane. It turns the terminal screen into a plain string that the tests can search and measure.

Data flow: It receives a tmux pane id, runs tmux capture-pane -p -t <pane>, and converts the command’s standard output bytes into text. The result is the current pane contents as a string, or an error if the tmux command could not run.

Call relations: wait_for_capture_contains calls this while polling, and the smoke scenarios call it directly after resize operations. It uses output to run the command, then hands the captured text to row-finding helpers such as last_composer_row and first_row_containing.

Call graph: calls 1 internal fn (output); called by 4 (run_repeated_resize_smoke, tmux_split_preserves_fresh_session_composer_row_after_resize_reflow, tmux_width_resize_restore_keeps_visible_content_anchored, wait_for_capture_contains); 2 external calls (from_utf8_lossy, new).

last_composer_row521–533 ↗
fn last_composer_row(capture: &str) -> Option<usize>

Purpose: This helper finds the row number of the last visible Codex composer prompt in a captured pane. The composer prompt is identified by the leading symbol, which marks where the user types.

Data flow: It receives the full captured pane text, splits it into lines, and checks each line after ignoring leading spaces. For every line that starts with , it records the line index, then returns the last such index if one exists. If no composer prompt is visible, it returns nothing.

Call relations: The smoke scenarios call this on baseline and post-resize captures. Its row number is the main measurement used to detect whether the input area drifted after tmux changed the pane size.

Call graph: called by 3 (run_repeated_resize_smoke, tmux_split_preserves_fresh_session_composer_row_after_resize_reflow, tmux_width_resize_restore_keeps_visible_content_anchored).

first_row_containing535–540 ↗
fn first_row_containing(capture: &str, needle: &str) -> Option<usize>

Purpose: This helper finds the first row where a chosen piece of text appears. In these tests it is used to locate the sentinel phrase in the conversation history.

Data flow: It receives captured pane text and a search string. It scans the lines from top to bottom and returns the first line index whose text contains the search string. If the string is not visible, it returns nothing.

Call relations: The smoke scenarios use this alongside last_composer_row. Together they check both ends of the visible screen: the prompt where the user types and a known piece of output above it.

Call graph: called by 3 (run_repeated_resize_smoke, tmux_split_preserves_fresh_session_composer_row_after_resize_reflow, tmux_width_resize_restore_keeps_visible_content_anchored).

check542–545 ↗
fn check(command: &mut Command) -> Result<()>

Purpose: This small helper runs a command and only cares whether it succeeded. It is used for tmux commands where the output is not needed, such as sending keystrokes or killing a pane.

Data flow: It receives a prepared command, passes it to checked_output, discards the returned command output if the command succeeded, and returns success. If the command failed, it returns the detailed error produced by checked_output.

Call relations: The smoke scenarios call this for side-effect-only tmux operations. It is a thin convenience layer over checked_output, keeping the test steps easier to read.

Call graph: calls 1 internal fn (checked_output); called by 3 (run_repeated_resize_smoke, tmux_split_preserves_fresh_session_composer_row_after_resize_reflow, tmux_width_resize_restore_keeps_visible_content_anchored).

checked_output547–557 ↗
fn checked_output(command: &mut Command) -> Result<Output>

Purpose: This helper runs an external command and turns a non-zero exit status into a useful test error. It keeps failures readable by including the command’s exit code, standard output, and standard error.

Data flow: It receives a prepared command, runs it through output, then checks whether the process reported success. If it did, it returns the full Output object. If it failed, it returns an error containing the status and captured text streams.

Call relations: The smoke scenarios use this when they need command output, such as reading tmux’s reported pane id. The check helper also uses it when only success matters.

Call graph: calls 1 internal fn (output); called by 4 (check, run_repeated_resize_smoke, tmux_split_preserves_fresh_session_composer_row_after_resize_reflow, tmux_width_resize_restore_keeps_visible_content_anchored); 1 external calls (ensure!).

output559–563 ↗
fn output(command: &mut Command) -> Result<Output>

Purpose: This helper is the lowest-level command runner in the file. It runs an external process and adds context if the process could not even be started.

Data flow: It receives a mutable command, calls the operating system to run it, and returns the captured process Output. If launching fails, for example because the executable is missing, it returns an error that includes the command being attempted.

Call relations: capture_pane and checked_output call this instead of invoking commands directly. It centralizes the basic “run this command and explain launch failures” behavior used throughout the tmux tests.

Call graph: called by 2 (capture_pane, checked_output); 1 external calls (output).

stdout_text565–567 ↗
fn stdout_text(output: &Output) -> String

Purpose: This helper converts a command’s standard output into normal Rust text. It is used when tmux prints a pane id and the test needs that id as a string.

Data flow: It receives an Output object from a completed command, reads its stdout bytes, converts them to text in a forgiving way, and returns the resulting string. It does not check whether the command succeeded; callers use checked_output for that first.

Call relations: The smoke scenarios call this after tmux commands that create sessions or split panes. The returned text is trimmed and then used as the pane id for later capture, resize, and cleanup commands.

Call graph: called by 3 (run_repeated_resize_smoke, tmux_split_preserves_fresh_session_composer_row_after_resize_reflow, tmux_width_resize_restore_keeps_visible_content_anchored); 1 external calls (from_utf8_lossy).

tui/tests/suite/status_indicator.rssource ↗
testtest run

Terminal text can include ANSI escape sequences: hidden control codes such as \x1b[31m that tell a terminal to show text in red. Those codes are useful when writing directly to a terminal, but they are dangerous inside a structured terminal UI buffer because they are not real printable characters. If they leak through, the UI may render incorrectly, count text widths wrongly, or leave raw control bytes in places that expect clean text.

This test focuses on the public helper ansi_escape_line(), which the status indicator widget relies on. It feeds the helper a small string that says RED, wrapped in ANSI codes for “make this red” and “reset formatting.” The expected result is not colored terminal control text, but a clean line whose visible content is simply RED.

The test then joins together the text stored in the returned line’s spans. A span is a small piece of styled text. By combining the span contents, the test checks the human-visible output rather than the internal layout details. Finally, it asserts that the combined text equals RED. This makes sure the escape sequences were stripped and no raw \x1b control bytes survived.

Function details1
ansi_escape_line_strips_escape_sequences10–24 ↗
fn ansi_escape_line_strips_escape_sequences()

Purpose: This test proves that ansi_escape_line() removes ANSI escape sequences and keeps only the printable text. It exists to prevent a past or likely bug from returning: raw terminal control codes leaking into the status indicator’s backing buffer.

Data flow: It starts with an input string containing hidden ANSI control codes around the word RED. It passes that string into ansi_escape_line(), then reads the returned line’s spans and joins their visible text together. The final output should be exactly RED; if any escape sequence remains or the visible text is damaged, the equality check fails.

Call relations: During the test run, the Rust test framework calls this function. The function delegates the real cleanup work to the external ansi_escape_line() helper, then uses assert_eq! to compare the cleaned visible text with the expected plain word.

Call graph: 2 external calls (assert_eq!, ansi_escape_line).

tui/tests/suite/vt100_history.rssource ↗
testtest run

This is a test file for the terminal user interface. It uses a VT100-style test backend, which is a fake terminal that behaves like an old text terminal, so the tests can inspect what would appear on screen without opening a real terminal window. The main feature under test is insert_history_lines: it takes lines of past output and places them above or around the current viewport, like adding previous chat messages into a scrolling terminal view.

The file builds a small reusable TestScenario so each test can start with a clean simulated terminal of a chosen size. Then each test inserts one or more lines and reads the fake screen back to confirm the visible result. The tests cover simple insertion, long unbroken text that must wrap, emoji and Chinese/Japanese/Korean-width characters, styled spans such as red text, and whether the cursor is put back where the application expects it.

Two tests focus on word wrapping. They make sure normal prose does not split words awkwardly across lines when there is a better break point nearby. This matters because history output is what users read; if wrapping loses characters, splits words badly, or leaves the cursor in the wrong place, the interface can look broken or become hard to use.

Function details9
TestScenario::new27–33 ↗
fn new(width: u16, height: u16, viewport: Rect) -> Self

Purpose: Creates a fresh simulated terminal for a test. A test uses it to choose the terminal size and the viewport area, so the screen behaves like the situation being checked.

Data flow: It receives a width, a height, and a viewport rectangle. It creates a VT100Backend, wraps it in the project’s terminal type using with_options, sets the viewport area, and returns a TestScenario containing that prepared terminal.

Call relations: The individual tests call this first to set up their fake screen. It relies on the backend constructor and the terminal constructor to produce the test terminal before any history text is inserted.

Call graph: calls 2 internal fn (with_options, new); called by 7 (basic_insertion_no_wrap, cursor_restoration, em_dash_and_space_word_wrap, emoji_and_cjk, long_token_wraps, mixed_ansi_spans, word_wrap_no_mid_word_split).

TestScenario::run_insert35–38 ↗
fn run_insert(&mut self, lines: Vec<Line<'static>>)

Purpose: Runs the history insertion operation that the tests are really checking. It gives the tests a short, readable way to insert lines into the simulated terminal.

Data flow: It receives a list of styled text lines. It passes those lines and the scenario’s terminal into insert_history_lines; if insertion fails, the test stops with a clear failure message. The terminal’s fake screen is changed as a result.

Call relations: After a test creates a TestScenario, it uses this helper to exercise the real history-insertion code. This helper is the bridge between the test setup and the project function being tested.

Call graph: 1 external calls (insert_history_lines).

basic_insertion_no_wrap42–54 ↗
fn basic_insertion_no_wrap()

Purpose: Checks the simplest case: short lines should be inserted exactly as visible rows without needing to wrap.

Data flow: It creates a 20-by-6 fake terminal with a one-row viewport at the bottom, inserts the lines first and second, then reads the simulated screen contents. The expected outcome is that both words appear somewhere in the screen text.

Call relations: This test starts by calling TestScenario::new, then inserts lines through the scenario helper. It uses the custom containment assertion to make failures easier to understand if either inserted line is missing.

Call graph: calls 1 internal fn (new); 3 external calls (new, assert_contains!, vec!).

long_token_wraps57–86 ↗
fn long_token_wraps()

Purpose: Checks that a very long unbroken string wraps across rows without losing characters. This protects against text being cut off when there are no spaces to wrap at.

Data flow: It creates a small fake terminal, builds a string of 45 A characters, inserts it, then scans every cell on the 20-by-6 screen. It counts how many A characters are present and expects the count to match the original string length.

Call relations: The test uses TestScenario::new for setup and then runs the insertion path. Instead of checking whole rows, it inspects individual fake terminal cells because wrapping spreads the text across multiple rows.

Call graph: calls 1 internal fn (new); 3 external calls (new, assert_eq!, vec!).

emoji_and_cjk89–105 ↗
fn emoji_and_cjk()

Purpose: Checks that wide and non-ASCII characters, such as emoji and Chinese characters, survive insertion. These characters often occupy more visual space than ordinary English letters, so they are easy to mishandle in terminal layouts.

Data flow: It creates a fake terminal, inserts a line containing emoji and Chinese text, then reconstructs the visible screen contents. For every non-space character in the original text, it checks that the character appears on the screen.

Call relations: This test follows the same setup-and-insert pattern as the others through TestScenario::new and the scenario helper. Its assertions focus on character preservation rather than exact row layout.

Call graph: calls 1 internal fn (new); 4 external calls (new, from, assert!, vec!).

mixed_ansi_spans108–118 ↗
fn mixed_ansi_spans()

Purpose: Checks that styled and unstyled text in the same line still produces the right plain visible text. For example, red text should affect color, not add or remove letters.

Data flow: It creates a fake terminal, builds a line made from a red red span followed by plain +plain, inserts that line, and reads the screen contents. The expected visible text is red+plain.

Call relations: The test uses TestScenario::new to create the fake terminal and then sends a styled line through the insertion path. It checks the final screen text with the helper assertion.

Call graph: calls 1 internal fn (new); 3 external calls (new, assert_contains!, vec!).

cursor_restoration121–130 ↗
fn cursor_restoration()

Purpose: Checks that inserting history does not leave the terminal cursor in an unexpected place. This matters because later drawing code depends on knowing where the cursor is.

Data flow: It creates a fake terminal, inserts a single x, and then reads last_known_cursor_pos from the terminal. The expected result is that the remembered cursor position is back at (0, 0).

Call relations: The test uses the same scenario setup as the content tests, but its final check is about terminal state rather than visible text. It verifies that the insertion routine cleans up after itself.

Call graph: calls 1 internal fn (new); 3 external calls (new, assert_eq!, vec!).

word_wrap_no_mid_word_split133–147 ↗
fn word_wrap_no_mid_word_split()

Purpose: Checks that prose wraps at sensible word boundaries instead of splitting a normal word when a space break is available.

Data flow: It creates a wider fake terminal, inserts a long story-like sentence, and joins the simulated screen contents into one string. It specifically verifies that the word both was not broken as bo on one line and th on the next.

Call relations: This test sets up a terminal with TestScenario::new, runs the real insertion logic, and then searches the screen text for an unwanted line break pattern. It guards the word-wrapping behavior used for readable history output.

Call graph: calls 1 internal fn (new); 3 external calls (new, assert!, vec!).

em_dash_and_space_word_wrap150–164 ↗
fn em_dash_and_space_word_wrap()

Purpose: Checks a reported wrapping edge case involving an em dash and a following word. It ensures the word inside is not split in the middle when wrapping the sentence.

Data flow: It creates a fake terminal, inserts a sentence containing sand—and inside, and reads the screen contents. It then verifies that the screen does not contain insi followed by a line break and then de.

Call relations: Like the other wrapping test, it uses TestScenario::new and then the history insertion path. It focuses on a specific punctuation-and-space case that could otherwise make wrapped text look broken.

Call graph: calls 1 internal fn (new); 3 external calls (new, assert!, vec!).

tui/tests/suite/vt100_live_commit.rssource ↗
testtest run

This test protects a small but important behavior in the text user interface: when streamed or newly built output grows beyond the space reserved for the “live” area, the oldest rows should be committed into terminal history instead of disappearing. Think of the live area like a small notepad that only keeps the latest few lines; when it fills up, older lines are copied into a permanent log above it.

The test creates a fake VT100 terminal backend. VT100 is a family of terminal control rules, and here it means the test can inspect what would have appeared on a real terminal screen without launching one. It then sets the terminal viewport to a one-line area at the bottom of a six-line screen. Next, it uses a row builder to create five separate rows of text: “one” through “five”. The row builder is asked to keep only the last three rows live, so the first two rows should be drained out as ready to commit.

Those committed rows are inserted into the terminal history. Finally, the test reads the simulated screen contents and verifies that “one” and “two” are present. The last three rows are intentionally not checked here because they remain in the live ring rather than being committed by this step.

Function details1
live_001_commit_on_overflow6–43 ↗
fn live_001_commit_on_overflow()

Purpose: This test confirms that when five built rows are reduced to a live set of three, the two oldest rows are committed into terminal history. It exists to catch regressions where overflowing live text would be lost or fail to appear in the scrollback area.

Data flow: The test starts with a simulated terminal that is 20 columns wide and 6 rows high, then narrows the active viewport to a single bottom row. It builds five text rows, asks the row builder to keep only the newest three, converts the older two rows into terminal lines, and inserts them into history. It then reads the fake terminal screen and expects to find the words “one” and “two” in the visible contents.

Call relations: The test sets up its fake terminal through the terminal construction helpers, creates geometry for the viewport, builds rows with the row builder, and then hands the committed rows to insert_history_lines so the terminal can display them as history. The final assertions act as the outside observer: they inspect the VT100 backend after the insert and verify that the committed text reached the screen.

Call graph: calls 3 internal fn (with_options, new, new); 3 external calls (new, assert!, insert_history_lines).