mirror of
https://github.com/larksuite/cli.git
synced 2026-09-14 18:42:53 +08:00
d66b1cac2e
- guide record-search callers to the correct flag or command path without reporting recovery-only flags as invalid input - reject blank form question IDs before destructive deletion and preserve keep-field request semantics - cover typed validation and dry-run request contracts, then refresh Base E2E coverage Co-authored-by: BASE Infra Harness <ai@base-infra-harness.noreply.local>
21 KiB
21 KiB
Base CLI E2E Coverage
Metrics
- Denominator: 99 leaf commands
- Covered: 49
- Coverage: 49.5%
Summary
- TestBase_BasicWorkflow: proves
+base-create,+base-get,+table-create,+table-get, and+table-list; keyt.Run(...)proof points areget base as bot,get table as bot, andlist tables and find created table as bot. - TestBaseBlockDryRun: proves the five
+base-block-*shortcuts request shapes without touching live data. - TestBaseAppWorkflow: live user workflow in an isolated fixture Workspace covering Workspace entity listing, BaseApp create/get, Page create/list/get/update/delete, text Block create/list/get/update, and App cleanup through Drive delete (
type=bitable). SetLARK_CLI_E2E_BASEAPP_WORKSPACE_TOKENto enable it. - TestBaseDashboardBlockCreateDryRun_PositionAndNumberFormat / TestBaseDashboardBlockUpdateDryRun_Position: prove
+dashboard-block-create/+dashboard-block-updatedry-run request shape carries the optional top-levelpositionsibling and statisticsdata_config.number_format; TestBaseDashboardBlockCreateDryRun_InvalidNumberFormat proves the number_format enum validation rejects a bad formatName before any request. - TestBaseFieldCreateDryRunArrayCompat: proves
+field-createdry-run request shape for the internal JSON-array compatibility path. - TestBaseFieldExtensionDryRun: proves
+field-extension-get,+field-extension-update, and+field-extension-update-cellsrequest shapes, including row-vs-column update bodies; TestBaseFieldExtensionUpdateCellsDryRunRejectsRowWithoutRecordID proves row updates require an explicit record. - TestBaseFormQuestionsCreateDryRun: proves
+form-questions-createpreserves its POST body and renders the existing-question guard in command help. - TestBaseFormDetailDryRun / TestBaseFormSubmitDryRun: prove shared-form detail and submission request shapes.
- TestBaseDashboardBlockGetDataDryRun: proves dashboard block data request shapes and identifier handling.
- TestBaseDashboardBlockLayoutPrecisionWorkflow: creates a temporary Base/table/dashboard, creates a statistics block with
positionand omittednumber_format, asserts the server default, updates to a custom format, then verifies a precision-only update preservesformatName, and cleans up the block/dashboard/base.+dashboard-create,+dashboard-delete,+dashboard-block-getand+dashboard-block-deletehave no dry-run coverage and rest on this test alone. This workflow was executed successfully against a live tenant on 2026-08-20 while validating PR #2118. - TestBaseDashboardBlockRankingCreateDryRun / TestBaseDashboardBlockRankingUpdateDryRunPreservesPatch / TestBaseDashboardBlockRankingDryRunRejectsInvalidConfig: prove ranking create defaults, top-level patch preservation, and typed validation failures for unsupported fields and malformed filters.
- TestBaseShareDryRun: proves dashboard/form share GET and PATCH routes, one-field update requests, explicit false preservation, and nested form settings without touching live data.
- TestBaseShareWorkflow: deployment-gated by
LARK_CLI_E2E_BASE_SHARE_READY=1; creates a Base, table, form, and dashboard, updates each share field in a separate request, verifies get round trips for both resources, disables sharing, and cleans up the Base. - TestBaseRecordBatchUpdatePerRecordDryRun: proves
+record-batch-updatepreserves the per-recordupdate_recordsrequest shape. - TestBaseRecordBatchUpdatePerRecordWorkflow: creates two records, generates their share links using mixed
--record-id/--record-idsinput, updates different field types in one request, asserts the minimal response contract, reads both records back, verifies a missing record ID is not prevalidated, and cleans up the temporary Base. - TestBaseRecordShareLinkCreateDryRunAcceptsSingularAndPluralRecordIDFlags: proves singular and plural record ID flags compose into one deduplicated share-link request.
- TestBaseRecordHistoryListDryRunUsesExplicitRecordID / TestBaseRecordHistoryListDryRunRejectsNonPositiveMaxVersion: prove the history request keeps the explicit record ID and rejects explicitly non-positive cursors with a typed validation error.
- TestBase_RoleWorkflow: proves
+advperm-enable,+role-create,+role-list,+role-get, and+role-update; keyt.Run(...)proof points arelist as bot,get as bot, andupdate as bot. - TestBaseFormListDryRun_UsesBaseAndTableIdentifiers: proves
+form-listdry-run request shape uses Base and table identifiers in the endpoint. - TestBaseFormQuestionsCreateVisibleRuleDryRun / TestBaseFormQuestionsUpdateVisibleRuleDryRun: prove
+form-questions-create/+form-questions-updatedry-run request shape and that the optionalvisible_ruledisplay condition is transcribed verbatim into the request body. - TestBaseTableCopyDryRun: proves
+table-copyand+table-copy-statusrequest shapes, including the schema-safe default, table-name path escaping, explicit all+wait orchestration, Cobra duration parsing, and the opaque task ID body. - TestBaseTableCopyWorkflow: feature-gated by
LARK_CLI_E2E_BASE_TABLE_COPY_READY=1until the OpenAPI is deployed; creates a source table and record, proves schema-only copy, all no-wait plus status, all wait, record inclusion, and cleanup. - TestBaseTemplateCenterDryRun: proves
+template-categories,+template-list, and+template-searchrequest shapes; the list case covers category, limit, and offset parameters. - Cleanup note:
+table-deleteand+role-deleteonly run in cleanup and are intentionally left uncovered. - Blocked area: table-copy live integration remains deployment-gated; remaining dashboard, field, most record operations, most form operations, view, and workflow operations still lack deterministic create/read/update workflows in this suite.
Command Table
| Status | Cmd | Type | Testcase | Key parameter shapes | Notes / uncovered reason |
|---|---|---|---|---|---|
| ✕ | base +advperm-disable | shortcut | none | no disable workflow yet | |
| ✓ | base +advperm-enable | shortcut | base_role_workflow_test.go::TestBase_RoleWorkflow | --base-token |
|
| ✕ | base +base-copy | shortcut | none | no copy workflow yet | |
| ✓ | base +base-create | shortcut | base/helpers_test.go::createBaseWithRetry | --name; --time-zone |
helper asserts created base token |
| ✓ | base +base-get | shortcut | base_basic_workflow_test.go::TestBase_BasicWorkflow/get base as bot | --base-token |
|
| ✓ | base +base-block-create | shortcut | base_block_dryrun_test.go::TestBaseBlockDryRun/create | --base-token; --type; --name; --parent-id; dry-run only |
request shape only |
| ✓ | base +base-block-delete | shortcut | base_block_dryrun_test.go::TestBaseBlockDryRun/delete | --base-token; --block-id; dry-run only |
request shape only |
| ✓ | base +base-block-list | shortcut | base_block_dryrun_test.go::TestBaseBlockDryRun/list all,list folder | --base-token; optional --parent-id; optional --type; dry-run only |
request shape only |
| ✓ | base +base-block-move | shortcut | base_block_dryrun_test.go::TestBaseBlockDryRun/move root,move after | --base-token; --block-id; optional --parent-id; --after-id; dry-run only |
request shape only |
| ✓ | base +base-block-rename | shortcut | base_block_dryrun_test.go::TestBaseBlockDryRun/rename | --base-token; --block-id; --name; dry-run only |
request shape only |
| ✓ | base +template-categories | shortcut | base_template_center_dryrun_test.go::TestBaseTemplateCenterDryRun/categories | dry-run only | request shape only |
| ✓ | base +template-list | shortcut | base_template_center_dryrun_test.go::TestBaseTemplateCenterDryRun/list | --category-key; --limit/--page-size; --offset; dry-run only |
request shape only |
| ✓ | base +template-search | shortcut | base_template_center_dryrun_test.go::TestBaseTemplateCenterDryRun/search | --keyword; --limit; dry-run only |
request shape only; blank keyword validation covered |
| ✕ | base +dashboard-arrange | shortcut | none | dashboard workflows not covered | |
| ✓ | base +dashboard-block-create | shortcut | base_dashboard_block_layout_precision_dryrun_test.go::TestBaseDashboardBlockCreateDryRun_PositionAndNumberFormat; base_dashboard_block_layout_precision_workflow_test.go::TestBaseDashboardBlockLayoutPrecisionWorkflow; base_dashboard_block_ranking_dryrun_test.go::TestBaseDashboardBlockRankingCreateDryRun; TestBaseDashboardBlockRankingDryRunRejectsInvalidConfig | --position top-level; --data-config.number_format; ranking defaults and invalid child/top-level/filter fields; dry-run + live |
request shape, typed validation envelope, plus live statistics block creation |
| ✓ | base +dashboard-block-delete | shortcut | base_dashboard_block_layout_precision_workflow_test.go::TestBaseDashboardBlockLayoutPrecisionWorkflow (cleanup) | --base-token; --dashboard-id; --block-id; --yes; live cleanup |
deletes the temporary block |
| ✓ | base +dashboard-block-get | shortcut | base_dashboard_block_layout_precision_workflow_test.go::TestBaseDashboardBlockLayoutPrecisionWorkflow | --base-token; --dashboard-id; --block-id; live |
reads back number_format; coordinates are not asserted (get is not contracted to echo position this iteration) |
| ✓ | base +dashboard-block-get-data | shortcut | base_dashboard_block_get_data_dryrun_test.go | --base-token; --dashboard-id; --block-id; dry-run only |
request shape and identifier handling |
| ✕ | base +dashboard-block-list | shortcut | none | dashboard workflows not covered | |
| ✓ | base +dashboard-block-update | shortcut | base_dashboard_block_layout_precision_dryrun_test.go::TestBaseDashboardBlockUpdateDryRun_Position; base_dashboard_block_layout_precision_workflow_test.go::TestBaseDashboardBlockLayoutPrecisionWorkflow; base_dashboard_block_ranking_dryrun_test.go::TestBaseDashboardBlockRankingUpdateDryRunPreservesPatch | --position top-level dry-run; --data-config.number_format live; ranking limit_size patch dry-run |
request shape for position and ranking patch; live workflow verifies number_format update and read-back, while position read-back remains unverified |
| ✓ | base +dashboard-create | shortcut | base_dashboard_block_layout_precision_workflow_test.go::TestBaseDashboardBlockLayoutPrecisionWorkflow | --base-token; --name; live |
creates the temporary dashboard |
| ✓ | base +dashboard-delete | shortcut | base_dashboard_block_layout_precision_workflow_test.go::TestBaseDashboardBlockLayoutPrecisionWorkflow (cleanup) | --base-token; --dashboard-id; --yes; live cleanup |
deletes the temporary dashboard |
| ✕ | base +dashboard-get | shortcut | none | dashboard workflows not covered | |
| ✕ | base +dashboard-list | shortcut | none | dashboard workflows not covered | |
| ✓ | base +dashboard-share-get | shortcut | base_share_dryrun_test.go::TestBaseShareDryRun/dashboard get; base_share_workflow_test.go::TestBaseShareWorkflow/dashboard share update and get | --base-token; --dashboard-id; dry-run + deployment-gated live |
live requires LARK_CLI_E2E_BASE_SHARE_READY=1 |
| ✓ | base +dashboard-share-update | shortcut | base_share_dryrun_test.go::TestBaseShareDryRun/dashboard partial update, dashboard auto analysis is not exposed; base_share_workflow_test.go::TestBaseShareWorkflow/dashboard share update and get | one of --enabled; --access-scope=invite; --show-source per request; unsupported auto-analysis flag |
single-field updates, explicit false, invite-only scope, live read-back, and backend-gated setting exclusion covered |
| ✕ | base +dashboard-update | shortcut | none | dashboard workflows not covered | |
| ✕ | base +data-query | shortcut | none | no data-query assertions yet | |
| ✓ | base +field-create | shortcut | base_field_dryrun_test.go::TestBaseFieldCreateDryRunArrayCompat | --base-token; --table-id; --json; dry-run only |
request shape only |
| ✕ | base +field-delete | shortcut | none | field workflows not covered | |
| ✓ | base +field-extension-get | shortcut | base_field_extension_dryrun_test.go::TestBaseFieldExtensionDryRun/get | --base-token; --table-id; --field-id; dry-run only |
request shape only |
| ✓ | base +field-extension-update | shortcut | base_field_extension_dryrun_test.go::TestBaseFieldExtensionDryRun/update | --json.extension_id; --json.inputs.prompt; --yes; dry-run only |
request shape only |
| ✓ | base +field-extension-update-cells | shortcut | base_field_extension_dryrun_test.go::TestBaseFieldExtensionDryRun/update cells row,update cells column; TestBaseFieldExtensionUpdateCellsDryRunRejectsRowWithoutRecordID | --type=row + repeated --record-id; --type=column + optional --view-id; --yes; dry-run only |
request shape and row validation |
| ✕ | base +field-get | shortcut | none | field workflows not covered | |
| ✕ | base +field-list | shortcut | none | field workflows not covered | |
| ✕ | base +field-search-options | shortcut | none | field workflows not covered | |
| ✕ | base +field-update | shortcut | none | field workflows not covered | |
| ✕ | base +form-create | shortcut | none | form workflows not covered | |
| ✕ | base +form-delete | shortcut | none | form workflows not covered | |
| ✓ | base +form-detail | shortcut | base_form_detail_dryrun_test.go::TestBaseFormDetailDryRun | --share-token; dry-run only |
shared-form request shape |
| ✕ | base +form-get | shortcut | none | form workflows not covered | |
| ✓ | base +form-list | shortcut | base_form_detail_dryrun_test.go::TestBaseFormListDryRun_UsesBaseAndTableIdentifiers | --base-token; --table-id; dry-run only |
request shape only |
| ✓ | base +form-share-get | shortcut | base_share_dryrun_test.go::TestBaseShareDryRun/form get; base_share_workflow_test.go::TestBaseShareWorkflow/form share update and get | --base-token; --table-id; --form-id; dry-run + deployment-gated live |
live requires LARK_CLI_E2E_BASE_SHARE_READY=1 |
| ✓ | base +form-share-update | shortcut | base_share_dryrun_test.go::TestBaseShareDryRun/form settings update; base_share_workflow_test.go::TestBaseShareWorkflow/form share update and get | one of share enablement; access-scope=invite; anonymous/login settings per request |
single-field updates, login-plus-anonymous across separate requests, explicit false, and live read-back covered |
| ✓ | base +form-questions-create | shortcut | TestBaseFormQuestionsCreateVisibleRuleDryRun; base_form_questions_create_dryrun_test.go | questions[].visible_rule; dry-run | request body, visible_rule passthrough, and help guard covered |
| ✓ | base +form-questions-delete | shortcut | base_form_questions_dryrun_test.go::TestBaseFormQuestionsDeleteDefaultDryRun; TestBaseFormQuestionsDeleteKeepFieldDryRun | question_ids; optional keep_field=true |
default destructive body and opt-in field-preserving body covered |
| ✕ | base +form-questions-list | shortcut | none | form workflows not covered | |
| ✓ | base +form-questions-update | shortcut | TestBaseFormQuestionsUpdateVisibleRuleDryRun | questions[].visible_rule | dry-run: request shape + visible_rule body passthrough |
| ✓ | base +form-submit | shortcut | base_form_submit_dryrun_test.go::TestBaseFormSubmitDryRun | --share-token; --json; dry-run only |
submission request shape |
| ✕ | base +form-update | shortcut | none | form workflows not covered | |
| ✓ | base +record-batch-create | shortcut | base_record_batch_update_workflow_test.go::TestBaseRecordBatchUpdatePerRecordWorkflow | --base-token; --table-id; --json.create_records |
seeds heterogeneous live workflow records |
| ✓ | base +record-batch-update | shortcut | base_record_batch_update_dryrun_test.go::TestBaseRecordBatchUpdatePerRecordDryRun; base_record_batch_update_workflow_test.go::TestBaseRecordBatchUpdatePerRecordWorkflow | --base-token; --table-id; --json.update_records; dry-run + live |
heterogeneous select/number update with write-back verification |
| ✕ | base +record-delete | shortcut | none | record workflows not covered | |
| ✓ | base +record-get | shortcut | base_record_batch_update_workflow_test.go::TestBaseRecordBatchUpdatePerRecordWorkflow | --record-id; repeated --field-id; --format json |
reads back select and number values after batch update |
| ✓ | base +record-history-list | shortcut | base_record_history_dryrun_test.go::TestBaseRecordHistoryListDryRunUsesExplicitRecordID; TestBaseRecordHistoryListDryRunRejectsNonPositiveMaxVersion | --base-token; --table-id; --record-id; --page-size; --max-version; dry-run |
request shape and typed cursor validation |
| ✕ | base +record-list | shortcut | none | record workflows not covered | |
| ✕ | base +record-search | shortcut | none | record workflows not covered | |
| ✓ | base +record-share-link-create | shortcut | base_record_share_link_dryrun_test.go::TestBaseRecordShareLinkCreateDryRunAcceptsSingularAndPluralRecordIDFlags; base_record_batch_update_workflow_test.go::TestBaseRecordBatchUpdatePerRecordWorkflow | canonical --record-id; hidden compatibility alias --record-ids; dry-run + live |
singular and plural flags compose into one request |
| ✓ | base +record-upload-attachment | shortcut | base_attachment_dryrun_test.go::TestBase_AttachmentDryRun/upload | dry-run only | request shape only |
| ✓ | base +record-download-attachment | shortcut | base_attachment_dryrun_test.go::TestBase_AttachmentDryRun/download | dry-run only | request shape only |
| ✓ | base +record-remove-attachment | shortcut | base_attachment_dryrun_test.go::TestBase_AttachmentDryRun/remove | dry-run only | request shape only |
| ✕ | base +record-upsert | shortcut | none | record workflows not covered | |
| ✓ | base +role-create | shortcut | base/helpers_test.go::createRole | --base-token; --json |
helper asserts created role id |
| ✕ | base +role-delete | shortcut | none | cleanup only | |
| ✓ | base +role-get | shortcut | base_role_workflow_test.go::TestBase_RoleWorkflow/get as bot | --base-token; --role-id |
|
| ✓ | base +role-list | shortcut | base_role_workflow_test.go::TestBase_RoleWorkflow/list as bot | --base-token |
|
| ✓ | base +role-update | shortcut | base_role_workflow_test.go::TestBase_RoleWorkflow/update as bot | --base-token; --role-id; --json |
|
| ✓ | base +table-create | shortcut | base/helpers_test.go::createTableWithRetry | --base-token; --name; --fields; optional --view |
helper asserts table id |
| ✓ | base +table-copy | shortcut | base_table_copy_dryrun_test.go::TestBaseTableCopyDryRun; base_table_copy_workflow_test.go::TestBaseTableCopyWorkflow | --table-id ID/name; default --range schema; explicit --range all --wait --timeout |
dry-run covered; live workflow is deployment-gated and not yet verified |
| ✓ | base +table-copy-status | shortcut | base_table_copy_dryrun_test.go::TestBaseTableCopyDryRun/status; base_table_copy_workflow_test.go::TestBaseTableCopyWorkflow/all no-wait and status | opaque --task-id |
dry-run covered; live polling is deployment-gated and not yet verified |
| ✕ | base +table-delete | shortcut | none | cleanup only | |
| ✓ | base +table-get | shortcut | base_basic_workflow_test.go::TestBase_BasicWorkflow/get table as bot | --base-token; --table-id |
|
| ✓ | base +table-list | shortcut | base_basic_workflow_test.go::TestBase_BasicWorkflow/list tables and find created table as bot | --base-token |
|
| ✕ | base +table-update | shortcut | none | no rename workflow yet | |
| ✕ | base +title-resolve | shortcut | none | resolver workflow not covered | |
| ✕ | base +url-resolve | shortcut | none | resolver workflow not covered | |
| ✕ | base +view-create | shortcut | none | view workflows not covered | |
| ✕ | base +view-delete | shortcut | none | view workflows not covered | |
| ✕ | base +view-get | shortcut | none | view workflows not covered | |
| ✕ | base +view-get-card | shortcut | none | view workflows not covered | |
| ✕ | base +view-get-filter | shortcut | none | view workflows not covered | |
| ✕ | base +view-get-group | shortcut | none | view workflows not covered | |
| ✕ | base +view-get-sort | shortcut | none | view workflows not covered | |
| ✕ | base +view-get-timebar | shortcut | none | view workflows not covered | |
| ✕ | base +view-get-visible-fields | shortcut | none | view workflows not covered | |
| ✕ | base +view-list | shortcut | none | view workflows not covered | |
| ✕ | base +view-rename | shortcut | none | view workflows not covered | |
| ✕ | base +view-set-card | shortcut | none | view workflows not covered | |
| ✕ | base +view-set-filter | shortcut | none | view workflows not covered | |
| ✕ | base +view-set-group | shortcut | none | view workflows not covered | |
| ✕ | base +view-set-sort | shortcut | none | view workflows not covered | |
| ✕ | base +view-set-timebar | shortcut | none | view workflows not covered | |
| ✕ | base +view-set-visible-fields | shortcut | none | view workflows not covered | |
| ✕ | base +workflow-create | shortcut | none | workflow CRUD not covered | |
| ✕ | base +workflow-disable | shortcut | none | workflow CRUD not covered | |
| ✕ | base +workflow-enable | shortcut | none | workflow CRUD not covered | |
| ✕ | base +workflow-get | shortcut | none | workflow CRUD not covered | |
| ✕ | base +workflow-list | shortcut | none | workflow CRUD not covered | |
| ✕ | base +workflow-update | shortcut | none | workflow CRUD not covered |