fix: accept UUID strings for WorkItemDetail labels and assignees (Plane v1.3.0+)#29
Conversation
Plane v1.3.0 changed the API to return labels and assignees as UUID strings instead of expanded objects. WorkItemDetail typed these as list[Label] and list[UserLite] respectively, causing a Pydantic ValidationError on any retrieve_work_item call against a v1.3.0+ instance. Change both fields to list[str] | list[T] = [] so they accept either representation, and default to [] for sparse responses (consistent with WorkItemExpand and the fix in makeplane#28). Adds 8 unit tests covering: UUID strings, expanded objects, empty lists, omitted fields, and that name remains required.
📝 WalkthroughWalkthroughThe Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
tests/unit/test_work_item_detail_types.py (1)
58-92: Strengthen object-form tests with type assertions.These two tests currently validate count only. Adding element-type checks will catch parser regressions where dict/object coercion changes unexpectedly.
Suggested test hardening
import pytest from pydantic import ValidationError +from plane.models.labels import Label +from plane.models.users import UserLite from plane.models.work_items import WorkItemDetail @@ def test_labels_as_objects(self) -> None: @@ item = WorkItemDetail(**data) assert len(item.labels) == 1 + assert isinstance(item.labels[0], Label) @@ def test_assignees_as_objects(self) -> None: @@ item = WorkItemDetail(**data) assert len(item.assignees) == 1 + assert isinstance(item.assignees[0], UserLite)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/unit/test_work_item_detail_types.py` around lines 58 - 92, Tests test_labels_as_objects and test_assignees_as_objects only assert lengths; strengthen them by asserting the parsed elements are proper model instances (not raw dicts) and expose expected attributes: for WorkItemDetail -> item.labels[0], assert it's not a dict (e.g., not isinstance(..., dict)) and has attributes like id and name/color; for item.assignees[0], assert it's not a dict and has id and display_name (and optional avatar/is_bot) to catch regressions where dicts are returned instead of parsed objects.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@tests/unit/test_work_item_detail_types.py`:
- Around line 58-92: Tests test_labels_as_objects and test_assignees_as_objects
only assert lengths; strengthen them by asserting the parsed elements are proper
model instances (not raw dicts) and expose expected attributes: for
WorkItemDetail -> item.labels[0], assert it's not a dict (e.g., not
isinstance(..., dict)) and has attributes like id and name/color; for
item.assignees[0], assert it's not a dict and has id and display_name (and
optional avatar/is_bot) to catch regressions where dicts are returned instead of
parsed objects.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 0402f7cb-fa2f-4ed2-b315-c75be3cd46e3
📒 Files selected for processing (2)
plane/models/work_items.pytests/unit/test_work_item_detail_types.py
Problem
Plane v1.3.0 changed the API to return
labelsandassigneesas UUID strings instead of expanded objects, even on full (non-sparse) responses.WorkItemDetailtyped both as required non-optional lists of objects:This causes a
ValidationErroron everyretrieve_work_item/retrieve_work_item_by_identifiercall against a Plane v1.3.0+ instance:Fix
Change both fields to accept either UUID strings or expanded objects, and default to
[]for sparse responses (consistent withWorkItemExpandand the approach in #28):Relation to #28
PR #28 fixes
ValidationErrorwhenlabels/assigneesare absent from a sparse response. This PR fixesValidationErrorwhen they are present as strings — a different code path, same field. The two fixes are complementary; combining them (union type + default[]) handles all cases.Tests
8 new unit tests in
tests/unit/test_work_item_detail_types.py:[]nameremains required (no over-relaxation)All 8 pass.
🤖 Generated with Claude Code
Summary by CodeRabbit
Release Notes
New Features
Tests