Skip to content

test: insta snapshot#1103

Merged
ryoppippi merged 1 commit into
ryoppippi:mainfrom
ubugeeei-forks:insta
May 20, 2026
Merged

test: insta snapshot#1103
ryoppippi merged 1 commit into
ryoppippi:mainfrom
ubugeeei-forks:insta

Conversation

@ubugeeei
Copy link
Copy Markdown
Collaborator

@ubugeeei ubugeeei commented May 20, 2026

Screen.Recording.2026-05-20.at.21.53.16.mov

Summary by cubic

Adds comprehensive insta snapshot tests across ccusage and ccusage-terminal to lock down CLI help, JSON report shapes, and terminal table rendering. Introduces render_lines() in the terminal crate for deterministic output; runtime behavior is unchanged.

  • Refactors

    • Added render_lines() to ccusage-terminal::SimpleTable and made print() delegate to it for stable, testable output.
  • Dependencies

    • Added dev-dependency insta to ccusage-terminal.
    • Added dev-dependency insta (with json feature) to ccusage.

Written for commit 45e5543. Summary will update on new commits. Review in cubic

Summary by CodeRabbit

  • Tests

    • Added comprehensive snapshot-based tests validating table rendering with multiline and narrow display cases, JSON serialization for reports and summaries, CLI command parsing with agent-specific options, configuration schema output, and usage aggregation by time period and session
  • Refactor

    • Refactored table output generation to modularize rendering of headers, rows, separators, and borders

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 20, 2026

📝 Walkthrough

Walkthrough

This PR introduces comprehensive snapshot-based test coverage using the insta library across the ccusage ecosystem. It adds insta as a dev-dependency, refactors terminal table rendering to support testing, and instruments data serialization, CLI parsing, configuration schema, output formatting, and core summarization logic with snapshot assertions.

Changes

Snapshot Test Coverage

Layer / File(s) Summary
Snapshot testing dependencies
rust/crates/ccusage-terminal/Cargo.toml, rust/crates/ccusage/Cargo.toml
Add insta = "1.47.2" and insta with json feature to dev-dependencies respectively.
Terminal rendering refactor and snapshots
rust/crates/ccusage-terminal/src/lib.rs
Refactor SimpleTable::print to delegate to render_lines() helper that constructs all table lines as strings; add insta snapshots validating multiline box title output, full table rendering with multiline cells and separators, narrow table wrapping/truncation with compact dates, and ANSI truncation boundary handling.
Summary aggregation logic and test fixtures
rust/crates/ccusage/src/summary.rs
Add snapshot tests for summarize_by_key, SessionAccumulator metadata tracking, summarize_summaries_by_bucket weekly/monthly aggregation with invalid-date handling, and filter_and_sort_summaries inclusive filtering and sorting; introduce LoadedEntryFixture and SummaryFixture helpers to construct test data with token/cost fields, model breakdowns, and timezone-aware timestamps.
Output formatting snapshots
rust/crates/ccusage/src/output.rs
Add snapshot tests for summary_json, session_summary_json, totals_json, group_project_output, and format_models_multiline; introduce snapshot_summary() helper to build UsageSummary instances with configurable periods, projects, and credits while populating nested ModelBreakdown entries.
Data model serialization and adapter tests
rust/crates/ccusage/src/adapter/opencode/parser.rs, rust/crates/ccusage/src/adapter/opencode/mod.rs, rust/crates/ccusage/src/adapter/codex.rs
Add entry_snapshot() helper for LoadedEntry JSON serialization; test message_value_to_entry() output for calculated and display-cost modes with model-candidate assertions; test CodexTokenUsageEvent report generation across Daily/Weekly/Monthly/Session report kinds and pricing scenarios; test agent_summary_json() across report kinds with conditional session metadata and period-key selection.
CLI parsing and help text snapshots
rust/crates/ccusage/src/cli.rs
Add serde_json import and CLI snapshot helpers (to_json_value) that serialize SharedArgs, Cli, and command variants (including agent-specific options like codex speed and paths) into JSON; add insta snapshot tests for root and contextual agent help text variants, representative CLI parse shapes with shared flags and nested command options, and parse-error guidance messages.
Config schema snapshot tests
rust/crates/ccusage/src/config_schema.rs
Add snapshot test targeting schema "agent specific option edges" (root refs/properties, defaults, and agent-specific option sets like Claude statusline, Codex defaults, Opencode weekly, Pi, and Openclaw defaults); introduce running_in_schema_generator_test_binary() helper to detect and skip execution when running under schema-generator binary.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • ryoppippi/ccusage#1061: Codex pricing and --speed fast regression tests directly related to the new Codex adapter snapshot coverage.
  • ryoppippi/ccusage#1023: Summary/output serialization tests align with Copilot adapter's extra_total_tokens and total_tokens() computation changes.
  • ryoppippi/ccusage#1058: Config schema snapshot test's generate-config-schema binary detection introduced by the schema-generator binary addition.

Suggested labels

enhancement

Poem

🐰 Snapshots frozen in time, test by test,
Rendering tables and JSON blessed,
From CLI to schema, we capture the scene,
With insta's keen eye, each output's pristine!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 64.71% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The PR title 'test: insta snapshot' is vague and generic, using non-descriptive terms that don't clearly convey the scope or purpose of the changes beyond mentioning insta snapshots. Provide a more specific title that clearly indicates the main objective, such as 'test: add insta snapshot tests for CLI, JSON reports, and terminal output' or 'test: add comprehensive insta snapshot test suite across ccusage crates'.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@ubugeeei ubugeeei marked this pull request as ready for review May 20, 2026 12:54
@ubugeeei ubugeeei requested a review from ryoppippi May 20, 2026 12:58
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
rust/crates/ccusage/src/config_schema.rs (1)

1249-1251: ⚡ Quick win

Add a comment explaining why snapshot testing is skipped in the schema-generator context.

The early return based on binary name is a pragmatic solution for snapshot testing across different execution contexts—it prevents snapshot assertions from running when the generate_config_schema binary is regenerating schema definitions. This pattern is intentional and appropriate.

To improve maintainability, add a doc comment above the helper function explaining why the skip is necessary:

/// Detects if running in the `generate_config_schema` binary context.
/// Returns true to skip snapshot tests, which would conflict with snapshot
/// regeneration during schema generation.
fn running_in_schema_generator_test_binary() -> bool {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@rust/crates/ccusage/src/config_schema.rs` around lines 1249 - 1251, Add a
short doc comment above the helper function
running_in_schema_generator_test_binary explaining that it detects when tests
are running inside the generate_config_schema binary and returns true to skip
snapshot assertions because snapshot tests would conflict with snapshot
regeneration during schema generation; then keep the existing early return that
uses this helper (the if running_in_schema_generator_test_binary() { return; }
block) so snapshot tests are skipped in that execution context.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@rust/crates/ccusage/src/config_schema.rs`:
- Around line 1249-1251: Add a short doc comment above the helper function
running_in_schema_generator_test_binary explaining that it detects when tests
are running inside the generate_config_schema binary and returns true to skip
snapshot assertions because snapshot tests would conflict with snapshot
regeneration during schema generation; then keep the existing early return that
uses this helper (the if running_in_schema_generator_test_binary() { return; }
block) so snapshot tests are skipped in that execution context.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: badcc1bd-f958-4500-b1c2-76c3da16daea

📥 Commits

Reviewing files that changed from the base of the PR and between 2ccaab3 and 45e5543.

⛔ Files ignored due to path filters (24)
  • rust/Cargo.lock is excluded by !**/*.lock
  • rust/crates/ccusage-terminal/src/snapshots/ccusage_terminal__tests__snapshots_ansi_truncation_boundary.snap is excluded by !**/*.snap
  • rust/crates/ccusage-terminal/src/snapshots/ccusage_terminal__tests__snapshots_full_table_with_multiline_cells_and_separators.snap is excluded by !**/*.snap
  • rust/crates/ccusage-terminal/src/snapshots/ccusage_terminal__tests__snapshots_multiline_box_title_layout.snap is excluded by !**/*.snap
  • rust/crates/ccusage-terminal/src/snapshots/ccusage_terminal__tests__snapshots_narrow_table_with_wrapping_truncation_and_compact_dates.snap is excluded by !**/*.snap
  • rust/crates/ccusage/src/adapter/opencode/snapshots/ccusage__adapter__opencode__parser__tests__snapshots_message_to_entry_variants_and_model_candidates.snap is excluded by !**/*.snap
  • rust/crates/ccusage/src/adapter/opencode/snapshots/ccusage__adapter__opencode__tests__snapshots_agent_summary_json_period_keys_and_session_metadata.snap is excluded by !**/*.snap
  • rust/crates/ccusage/src/adapter/snapshots/ccusage__adapter__codex__tests__snapshots_codex_reports_for_periods_sessions_costs_and_fallback_models.snap is excluded by !**/*.snap
  • rust/crates/ccusage/src/snapshots/ccusage__cli__tests__claude_agent_help.snap is excluded by !**/*.snap
  • rust/crates/ccusage/src/snapshots/ccusage__cli__tests__codex_daily_help.snap is excluded by !**/*.snap
  • rust/crates/ccusage/src/snapshots/ccusage__cli__tests__root_help.snap is excluded by !**/*.snap
  • rust/crates/ccusage/src/snapshots/ccusage__cli__tests__snapshots_cli_parse_error_guidance.snap is excluded by !**/*.snap
  • rust/crates/ccusage/src/snapshots/ccusage__cli__tests__snapshots_representative_cli_parse_shapes.snap is excluded by !**/*.snap
  • rust/crates/ccusage/src/snapshots/ccusage__cli__tests__statusline_help.snap is excluded by !**/*.snap
  • rust/crates/ccusage/src/snapshots/ccusage__config_schema__tests__snapshots_schema_agent_specific_option_edges.snap is excluded by !**/*.snap
  • rust/crates/ccusage/src/snapshots/ccusage__output__tests__snapshots_group_project_output_orders_named_projects_and_unknown_bucket.snap is excluded by !**/*.snap
  • rust/crates/ccusage/src/snapshots/ccusage__output__tests__snapshots_model_multiline_formatting_sorts_dedupes_and_shortens_names.snap is excluded by !**/*.snap
  • rust/crates/ccusage/src/snapshots/ccusage__output__tests__snapshots_session_summary_json_with_present_and_missing_options.snap is excluded by !**/*.snap
  • rust/crates/ccusage/src/snapshots/ccusage__output__tests__snapshots_summary_json_with_optional_fields_and_model_breakdowns.snap is excluded by !**/*.snap
  • rust/crates/ccusage/src/snapshots/ccusage__output__tests__snapshots_totals_json_with_extra_tokens_credits_and_zero_credit_omission.snap is excluded by !**/*.snap
  • rust/crates/ccusage/src/snapshots/ccusage__summary__tests__snapshots_bucket_aggregation_for_week_boundaries_invalid_dates_and_model_merging.snap is excluded by !**/*.snap
  • rust/crates/ccusage/src/snapshots/ccusage__summary__tests__snapshots_filter_and_sort_summaries_since_until_inclusive.snap is excluded by !**/*.snap
  • rust/crates/ccusage/src/snapshots/ccusage__summary__tests__snapshots_session_accumulator_latest_metadata_versions_and_timezone.snap is excluded by !**/*.snap
  • rust/crates/ccusage/src/snapshots/ccusage__summary__tests__snapshots_summarize_by_key_aggregates_counts_costs_and_breakdowns.snap is excluded by !**/*.snap
📒 Files selected for processing (10)
  • rust/crates/ccusage-terminal/Cargo.toml
  • rust/crates/ccusage-terminal/src/lib.rs
  • rust/crates/ccusage/Cargo.toml
  • rust/crates/ccusage/src/adapter/codex.rs
  • rust/crates/ccusage/src/adapter/opencode/mod.rs
  • rust/crates/ccusage/src/adapter/opencode/parser.rs
  • rust/crates/ccusage/src/cli.rs
  • rust/crates/ccusage/src/config_schema.rs
  • rust/crates/ccusage/src/output.rs
  • rust/crates/ccusage/src/summary.rs

@ryoppippi
Copy link
Copy Markdown
Owner

@coderabbitai review this

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 20, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Get the full diff for the PR
gh pr diff 1103 --repo ryoppippi/ccusage

Length of output: 135024


@ryoppippi This is a well-structured PR that adds meaningful snapshot coverage across the codebase. The render_lines() refactor is clean and the print() delegation is behavior-preserving. A few observations below:


render_lines() visibility

render_lines is declared private (fn render_lines), which is fine for the in-module tests here. However, if integration tests in a sibling crate ever need to assert rendered table output, they won't be able to call it. Consider pub(crate) if that use case is anticipated.


Exact version pinning for insta

# rust/crates/ccusage-terminal/Cargo.toml
insta = "1.47.2"

# rust/crates/ccusage/Cargo.toml
insta = { version = "1.47.2", features = ["json"] }

Pinning to an exact patch version in [dev-dependencies] means patch-level bug fixes and security updates in insta won't be picked up automatically. A semver-compatible range like "1" or "1.47" is the typical convention for dev-only dependencies.


entry_snapshot manual serialization (opencode/parser.rs)

fn entry_snapshot(entry: &LoadedEntry) -> serde_json::Value {
    json!({
        "date": entry.date,
        "timestamp": entry.timestamp.as_millis(),
        // ... many fields manually mapped
    })
}

This helper manually cherry-picks fields from LoadedEntry. If new fields are added to the struct, this helper silently misses them and the snapshot won't catch regressions on those fields. If LoadedEntry implements (or could implement) Serialize, passing serde_json::to_value(entry) directly to assert_json_snapshot! would be more robust. If the manual projection is intentional (e.g. excluding internal/noise fields), a comment explaining that would help future maintainers.


running_in_schema_generator_test_binary() needs documentation

fn running_in_schema_generator_test_binary() -> bool {
    std::env::current_exe()
        .ok()
        .and_then(|path| {
            path.file_name()
                .map(|name| name.to_string_lossy().into_owned())
        })
        .is_some_and(|name| {
            name.starts_with("generate_config_schema")
                || name.starts_with("generate-config-schema")
        })
}

This function guards the snapshots_schema_agent_specific_option_edges test with an early return when the test binary has a specific name. Without a comment, it's not obvious why this guard is needed or what would fail without it. A short // Skip when running under the schema-generator binary to avoid circular invocation comment would make this much clearer for reviewers.


Snapshot for sessionReportlastActivity/projectPath absent

In the ccusage__adapter__opencode__tests__snapshots_agent_summary_json_period_keys_and_session_metadata.snap, the top-level "session" object includes lastActivity and projectPath, but the "sessionReport".sessions[0] entry does not:

"sessionReport": {
  "sessions": [
    {
      "sessionId": "session-a",
      "totalCost": 0.25,
      // no lastActivity, no projectPath here
    }
  ]
}

This is worth confirming it's the intended behavior of report_from_rows (i.e. those fields are intentionally excluded from the sessions array). If it's a discrepancy, the snapshot would silently lock in the bug.


Minor: extra_total_tokens excluded from ModelBreakdown snapshot output

The ModelBreakdown struct has an extra_total_tokens field (set to non-zero values in several test fixtures), but it doesn't appear in any of the JSON snapshots for modelBreakdowns. Confirming this is expected (i.e. the field is intentionally omitted from serialization) is worth a quick check.


Overall the PR is in good shape — comprehensive coverage, all snapshots committed, and the terminal rendering refactor is clean. 🐇

Copy link
Copy Markdown
Owner

@ryoppippi ryoppippi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@ryoppippi ryoppippi merged commit 0d937fa into ryoppippi:main May 20, 2026
19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants