Skip to content

CLI↔library contract test coverage #214

@sdairs

Description

@sdairs

Summary

The CLI now delegates migrated Cloud commands through clickhouse-cloud-api. The library tests already prove the wire contract: HTTP method, path, auth, and struct → JSON serialization. The remaining useful CLI-specific gap is narrower:

  1. Do clap-parsed flags still have the intended names, types, defaults, and repeatability?
  2. Do CLI request builders populate the intended clickhouse-cloud-api request structs?

This issue adds that coverage without adding another CLI-layer wiremock or JSON snapshot suite.

Current State

crates/clickhousectl/src/cloud/commands.rs already has partial unit coverage for all 8 existing build_*_request helpers. The gap is not first-time coverage; it is systematic coverage: minimal + maximal inputs with direct assertions on every relevant library struct field.

crates/clickhousectl/src/cloud/cli.rs already has some Cli::try_parse_from tests, but they are selective and mostly prove clap parsing only.

service scale does not currently use a helper — it constructs ServiceReplicaScalingPatchRequest inline in service_scale (commands.rs:2050-2059). Three Option<u32> fields all using .map(f64::from) make this the most accident-prone construction in the file. This issue extracts it into a build_service_scale_request helper for parity and testability.

Three other body-building handlers also construct request structs inline and have no unit coverage:

  • member_update (commands.rs:2492) builds MemberPatchRequest. Maps the repeatable --role-id Vec to assigned_role_ids, collapses an empty Vec to None, and hardcodes role: None.
  • invitation_create (commands.rs:2582) builds InvitationPostRequest. Maps --emailemail, repeatable --role-idassigned_role_ids, uses InvitationPostRequestRole::default().
  • private_endpoint_create (commands.rs:2284) builds ServicPrivateEndpointePostRequest. Maps --endpoint-idid, and applies description.map(String::from).unwrap_or_default() so a missing --description becomes an empty string.

All three sit in the same fault class as service scale (wrong target field, dropped flag, flipped repeatability, wrong default coercion) and are extracted into build_member_update_request, build_invitation_create_request, and build_private_endpoint_create_request helpers under this issue.

crates/clickhousectl/tests/cli_request_shape_test.rs already exists for ClickPipes. That file uses subprocess + wiremock because ClickPipe handlers include runtime behavior that pure struct tests cannot catch, such as reading credential/certificate files and base64 encoding them. This issue deliberately uses a lighter pattern for migrated Cloud commands where the CLI mostly builds typed library request structs.

Fault Classes In Scope

  • Request builder miswiring, e.g. assigning min_replica_memory_gb to max_replica_memory_gb, dropping a flag, flipping a boolean, or choosing the wrong enum variant.
  • Clap drift, e.g. a renamed option field silently changing a public --flag.

Approach

Use plain Rust assertions against library request structs.

No JSON snapshots and no new CLI-layer wiremock tests for these commands. JSON shape and method/path are already covered at the clickhouse-cloud-api boundary.

Concretely:

  • Add one minimal and one maximal test per build_*_request helper in crates/clickhousectl/src/cloud/commands.rs.
  • Assert directly on the resulting library struct fields, not serialized JSON.
  • Keep existing validation/rejection tests.
  • Extract the inline ServiceReplicaScalingPatchRequest construction in service_scale into a build_service_scale_request helper, and cover it with the same minimal + maximal pattern.
  • Cover clap parsing with Cli::try_parse_from for each body-building command, asserting parsed enum fields.

Commands In Scope

  • cloud service create
  • cloud service update
  • cloud service scale (requires extracting build_service_scale_request)
  • cloud service reset-password
  • cloud service query-endpoint create
  • cloud org update
  • cloud key create
  • cloud key update
  • cloud service backup-config update
  • cloud member update (requires extracting build_member_update_request)
  • cloud invitation create (requires extracting build_invitation_create_request)
  • cloud private-endpoint create (requires extracting build_private_endpoint_create_request)

Out Of Scope

  • GET, DELETE, and list commands whose contract is path/query passthrough.
  • Full serialized JSON snapshots.
  • New CLI-layer wiremock tests for these migrated Cloud commands.
  • Broad human-readable output testing, unless a specific non-trivial formatting helper is extracted.

Definition Of Done

  • Every in-scope request builder has minimal and maximal struct-field tests.
  • service scale, member update, invitation create, and private-endpoint create each have a build_*_request helper extracted from inline construction and covered in the same style. These helper extractions are the only production-code changes in this issue.
  • Each in-scope command has clap parsing coverage for its body-related flags.
  • No new dev-dependencies are introduced by this issue.
  • cargo test -p clickhousectl passes.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or requesttest-coverageLive API integration test coverage work

Type

No type
No fields configured for issues without a type.

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions