Skip to content

fix(tasks): handle the canonical TasksStateUpdate wrapper from GET /tasks#85

Merged
joshrotenberg merged 1 commit into
mainfrom
fix/tasks-get-all-deserialize-wrapper
May 15, 2026
Merged

fix(tasks): handle the canonical TasksStateUpdate wrapper from GET /tasks#85
joshrotenberg merged 1 commit into
mainfrom
fix/tasks-get-all-deserialize-wrapper

Conversation

@joshrotenberg
Copy link
Copy Markdown
Contributor

Summary

  • get_all_tasks now correctly handles the OpenAPI-defined response shape TasksStateUpdate { tasks: [TaskStateUpdate] }. Previously the handler only matched on a bare JSON array, so every real-API response fell through to a silent Vec::new().
  • Tolerates the legitimate empty replies the API also returns ({}, null) and the legacy bare-array shape (backward compatibility).
  • Any other shape surfaces as CloudError::JsonError instead of silently returning empty — so a future schema change is loud, not invisible.
  • mock_tasks_list in src/testing/server.rs now wraps its payload in the canonical shape so consumers of the test-support feature exercise the same code path as real callers.
  • Replaces the previously dead-letter test_get_all_tasks (which mounted a wiremock expectation but never called the handler) with four focused tests covering wrapper, empty-object, bare-array, and unknown-shape cases.

Why

Issue #74 documents the bug. Static analysis against cloud_openapi.json and the existing test fixture both confirm the wire shape; the previous handler couldn't decode it.

This PR is scoped to get_all_tasks only. The broader TaskStateUpdate deduplication across the crate is tracked in #64.

Test plan

  • cargo fmt --all -- --check
  • cargo clippy --workspace --all-targets -- -D warnings
  • cargo test --workspace — all pass (full suite)
  • 4 new tests, all green
  • mock_tasks_list change verified against the existing test_mock_tasks_list_with_handler inside src/testing/server.rs

Closes #74
Refs #64 (task type dedup)

…asks

The OpenAPI spec defines the response as
`TasksStateUpdate { tasks: [TaskStateUpdate] }`, but `get_all_tasks`
only matched on a bare JSON array and silently returned `Vec::new()`
for any other shape — including the wrapper the API actually returns.
The result: every call returned no tasks, with no error surfaced.

This commit:

- Introduces a private `TasksStateUpdate` matching the spec.
- Rewrites `get_all_tasks` to accept the wrapper, the empty `{}` /
  `null` responses (legitimate "no tasks" replies), and a bare array
  (legacy compatibility), erroring loudly on anything else via
  `CloudError::JsonError`. No more silent fallback to empty.
- Updates the `mock_tasks_list` test-support helper to wrap its
  payload in the canonical shape so test consumers exercise the same
  path real callers will.
- Replaces the previously dead-letter test
  `tests/tasks_tests.rs::test_get_all_tasks` (which mounted a mock
  but never invoked the handler) with four focused tests covering
  the wrapper, empty-object, bare-array, and unknown-shape cases.

Refs #74 #64 (canonical task models — `TaskStateUpdate` dedup is the
follow-on)
Closes #74
@joshrotenberg joshrotenberg merged commit 2c6b393 into main May 15, 2026
8 checks passed
@joshrotenberg joshrotenberg deleted the fix/tasks-get-all-deserialize-wrapper branch May 15, 2026 18:46
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.

fix(tasks): GET /tasks deserialization is inverted; returns empty Vec on real responses

1 participant