Skip to content

refactor(test): table-drive Copilot quota mapping and validation fixtures #180

Description

@Nanako0129

Summary

crates/tb_core_ffi/src/agent_copilot.rs implements a relatively small provider adapter with two quota rows—Premium and Chat—but its embedded test module is already roughly the same size as the production mapping code.

The current tests repeatedly construct complete provider JSON payloads and then restate the same row semantics across:

  • premium/chat mapping and zero-entitlement placeholders;
  • lossy quota_reset_date values;
  • missing, malformed, negative, contradictory, and rounded quota fields;
  • malformed-sibling isolation;
  • calendar-month duration inference and observed fallback;
  • complete UsageWindow wire fields and privacy sentinels;
  • a historical stage4 end-to-end fixture.

The contracts are useful, but several cases verify the same decision at three layers: raw JSON decoding, CopilotRow classification, and the shared UsageWindow serializer. This makes a two-row adapter carry hundreds of lines of bespoke fixture text and duplicates wire guarantees already owned by the shared quota enrichment/serialization tests.

Goal

Keep Copilot's fail-closed row validation, sibling isolation, exact calendar-month duration, and privacy behavior while replacing copied provider payloads and repeated full-wire assertions with compact typed cases.

Contracts to retain

  1. Credential-independent provider decoding

    • Premium and Chat use stable canonical identities;
    • a valid non-zero entitlement produces the expected remaining percentage;
    • a zero-entitlement row is a placeholder rather than a usable quota window;
    • an absent row remains distinct from a malformed row.
  2. Row validation

    • entitlement and remaining values must be finite, non-negative, and coherent;
    • provider percentages must be finite, in range, and agree with the absolute quota within the documented rounding tolerance;
    • malformed fields fail closed.
  3. Sibling isolation

    • one malformed row does not remove a valid sibling;
    • placeholder-only input remains accepted as the documented empty state;
    • invalid-only input remains terminal.
  4. Reset handling

    • a valid first-of-month UTC reset uses the exact preceding 28–31 day calendar duration;
    • malformed or non-string reset fields are ignored without poisoning otherwise valid rows;
    • a non-calendar reset remains eligible for observed-duration learning rather than becoming a guessed 30-day window.
  5. Privacy and integration

    • malformed reset objects or arrays cannot leak their contents into public output;
    • one representative end-to-end payload proves plan normalization, both canonical cards, reset serialization, and shared pace metadata.

Consolidate or remove

  • Introduce a small typed QuotaRowCase table over entitlement, remaining, optional provider percentage, and expected CopilotRow classification.
  • Build provider payloads through one fixture builder instead of copying complete JSON documents for each field mutation.
  • Put malformed reset values in one table and assert the adapter-level result once; do not reassert every shared UsageWindow field for every malformed value.
  • Keep one sibling-isolation table with Premium/Chat outcomes rather than separate full-payload scenarios for each malformed field class.
  • Retain one end-to-end wire fixture. Detailed pace-state and serializer invariants remain owned by the shared enrichment/wire issue.
  • Replace historical stage4 naming with the current observable Copilot contract.
  • Remove assertions that merely repeat a lower-level row classification at the serializer layer.
  • Do not merely move the inline JSON into another file; total fixture and test LOC must decrease.

Acceptance criteria

  • Copilot Premium/Chat behavior, exact calendar duration, malformed-row isolation, and privacy remain unchanged.
  • The Copilot test slice is reduced by at least 35% from the current baseline.
  • Row validation and malformed-reset behavior are visibly table-driven.
  • Only one complete provider-to-wire fixture remains.
  • Shared quota pace and serializer fields are not exhaustively re-tested inside the provider adapter.
  • cargo test, the cross-language quota fixture checks, and relevant CI gates pass.

Boundaries

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions