mirror of
https://github.com/larksuite/cli.git
synced 2026-09-14 18:42:53 +08:00
b20f374c18
XML written into a field name this shortcut does not accept — most often "content", because <shape> nests a <content> child — was silently dropped, so the part failed the required-field check and reported "requires non-empty replacement". That reads as "the value is empty", which sends callers rewriting the value instead of the key. Reject fields outside the action's own set and name the field the caller most likely meant, with a correct one-liner attached as a hint. Matching folds case and separators so "Content", "newXml" and "block-id" resolve too, while the whitelist itself stays exact: the API accepts only snake_case, so "Replacement" must be rejected rather than slip through. Only block_replace and block_insert parts are checked, so missing / str_replace / unknown actions keep their existing errors, and an actually-empty payload still reports the non-empty wording. The alias list covers only names that plausibly carry a fragment. A shape attribute like "fill" is deliberately absent: whoever writes it means "recolor this block", not "here is my XML", so answering did-you-mean "replacement" would be guessing. The unknown-field error already names the valid set, which is true under either reading. Docs carry the same constraint at the three points a caller can hit first: SKILL.md, the +replace-slide reference (warning + counter-examples + error table), and the read-modify-write workflow. The --parts flag description now spells the field names out instead of eliding them behind "...". Note: this tightens parsing. Extra keys inside a part used to be ignored; they are now rejected.
5.6 KiB
5.6 KiB
Slides CLI E2E Coverage
Metrics
- Denominator: 6 leaf commands
- Covered: 5
- Coverage: 83.3%
Summary
- TestSlides_CreateWorkflowAsUser: proves the user slides workflow through
create presentation with slide as userandget created presentation xml as user; creates a fresh presentation, asserts returned IDs, then reads back the XML content to prove the title and slide body persisted. - TestSlidesAddSlideDryRunE2E / TestSlidesDeleteSlideDryRunE2E: pin the request shapes the unit tests cover, but through the real binary, which is the only layer that proves a full
<slide>XML document survives flag parsing with its quotes and angle brackets intact. Delete additionally proves the shortcut runs without--yes, unlike the high-risk-write raw command. - TestSlides_SlideAddDeleteWorkflowAsUser: live add/delete round trip on a throwaway presentation created and torn down per run. Asserts against a readback rather than the write's own response, so it proves what the request shape cannot: the returned
slide_idaddresses a real page,--before-slide-idpositions the page between its neighbours instead of merely being forwarded, and the deleted page is gone while both neighbours survive. - TestSlidesUpdateSlideDryRunE2E / TestSlidesUpdateAliasDryRunE2E / TestSlidesUpdateSlideRefuses*DryRunE2E: dry-run coverage for
+update-slidethrough the built binary — one request carrying oneblock_replacepart whoseblock_idis the PAGE id (the whole design; an element id there would replace one element and leave the rest of the page), theslideservice alias /+updatecommand alias /--xmlspelling, and the two refusals that must not produce a request (a bare element root, and a root id naming a different page). - TestSlides_HistoryWorkflow: opt-in live round-trip coverage for
+update-slide; creates a presentation, updates its page in place, asserts the returnedslide_id, the persisted marker, and that an element written back with its original id keeps that id, then reverts through slide history and self-cleans. It runs only whenLARK_SLIDES_HISTORY_E2E=1and therefore does not yet exercise the default live lane. - TestSlidesReplaceSlideUnknownFieldDryRunE2E / TestSlidesReplaceSlideEmptyReplacementDryRunE2E / TestSlidesReplaceSlideDryRunE2E: dry-run coverage for
+replace-slidethrough the built binary. The package tests receive the Go error directly and never run the dispatcher, so only these pin the user-visible contract: exit code 2, an empty stdout, and a stderr envelope carryingvalidation/invalid_argument,param: "--parts"and the actionablehint— which is what an agent parses to repair its own command. The three cases split the two failures that must stay distinguishable (a wrong field name names the field and suggests the right one; an actually-empty payload keeps therequires non-emptywording) and prove the field whitelist still admits a legitimate mixedblock_replace+block_insertbatch with the block id injected. - Known gap: the default live lane cannot exercise
+update-slideuntil it carries a backend that accepts the page's own id asblock_id; until then, dry-run is the default-CI proof and the opt-in history workflow is the real-API proof when explicitly enabled. Once rollout completes, add a dedicated live workflow covering restyle / no-op / insert / delete / background and asserting the control page and deck order did not move. - Blocked area:
slides +media-uploadis still uncovered because it needs a deterministic local image fixture plus XML follow-up proof that is separate from the base create/read workflow.
Command Table
| Status | Cmd | Type | Testcase | Key parameter shapes | Notes / uncovered reason |
|---|---|---|---|---|---|
| ✓ | slides +create | shortcut | slides_create_workflow_test.go::TestSlides_CreateWorkflowAsUser/create presentation with slide as user | --title; --slides ["<slide ...>"] |
read back through raw slides API to prove persisted XML |
| ✓ | slides +add-slide | shortcut | slides_slide_add_delete_dryrun_test.go::TestSlidesAddSlideDryRunE2E; slides_slide_add_delete_workflow_test.go::TestSlides_SlideAddDeleteWorkflowAsUser | --slide "<slide ...>"; --before-slide-id; --revision-id |
live append and insert both verified by reading the deck back |
| ✓ | slides +delete-slide | shortcut | slides_slide_add_delete_dryrun_test.go::TestSlidesDeleteSlideDryRunE2E, TestSlidesDeleteSlideWikiDryRunE2E; slides_slide_add_delete_workflow_test.go::TestSlides_SlideAddDeleteWorkflowAsUser | --slide-id; --revision-id; wiki URL |
live delete runs on a throwaway deck; readback proves the neighbours survive |
| ◐ | slides +update-slide | shortcut | slides_update_slide_dryrun_test.go::TestSlidesUpdateSlideDryRunE2E (+ alias / refusal cases); slides_history_workflow_test.go::TestSlides_HistoryWorkflow (opt-in live) | --presentation; --slide-id; --content "<slide ...>"; --revision-id |
default CI is dry-run only; opt-in history workflow proves a live in-place update and persisted content |
| ◐ | slides +replace-slide | shortcut | slides_replace_slide_dryrun_test.go::TestSlidesReplaceSlideUnknownFieldDryRunE2E, TestSlidesReplaceSlideEmptyReplacementDryRunE2E, TestSlidesReplaceSlideDryRunE2E | --presentation; --slide-id; --parts '[{action,block_id,replacement}]' / '[{action,insertion,insert_before_block_id}]' |
dry-run only; covers the rejected-field envelope, the empty-payload split and an accepted mixed batch. No live lane yet: a real round trip needs a throwaway deck plus a readback proving only the named block moved |
| ✕ | slides +media-upload | shortcut | none | needs a stable local image fixture plus follow-up slide XML proof |