Files
larksuite--cli/shortcuts/base/base_form_execute_test.go
wehub-resource-sync bf9395e022
CI / license-header (push) Has been skipped
CI / e2e-dry-run (push) Has been skipped
CI / fast-gate (push) Failing after 0s
Test PR Label Logic / test-pr-labels (push) Failing after 1s
Skill Format Check / check-format (push) Failing after 2s
CI / security (push) Failing after 5s
CI / unit-test (push) Has been skipped
CI / lint (push) Has been skipped
CI / script-test (push) Has been skipped
CI / deterministic-gate (push) Has been skipped
CI / coverage (push) Has been skipped
CI / results (push) Has been cancelled
CI / deadcode (push) Has been cancelled
CI / e2e-live (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:22:54 +08:00

352 lines
12 KiB
Go

// Copyright (c) 2026 Lark Technologies Pte. Ltd.
// SPDX-License-Identifier: MIT
package base
import (
"strings"
"testing"
"github.com/larksuite/cli/internal/httpmock"
)
func TestBaseFormExecuteList(t *testing.T) {
t.Run("single page", func(t *testing.T) {
factory, stdout, reg := newExecuteFactory(t)
reg.Register(&httpmock.Stub{
Method: "GET",
URL: "/open-apis/base/v3/bases/app_x/tables/tbl_x/forms",
Body: map[string]interface{}{
"code": 0,
"data": map[string]interface{}{
"has_more": false,
"total": 2,
"forms": []interface{}{
map[string]interface{}{"id": "vew_form1", "name": "用户调研问卷", "description": "2024年调研"},
map[string]interface{}{"id": "vew_form2", "name": "产品反馈表", "description": ""},
},
},
},
})
if err := runShortcut(t, BaseFormsList, []string{"+form-list", "--base-token", "app_x", "--table-id", "tbl_x"}, factory, stdout); err != nil {
t.Fatalf("err=%v", err)
}
if got := stdout.String(); !strings.Contains(got, `"vew_form1"`) || !strings.Contains(got, `"total": 2`) {
t.Fatalf("stdout=%s", got)
}
})
t.Run("auto pagination", func(t *testing.T) {
factory, stdout, reg := newExecuteFactory(t)
// First page: has_more=true
reg.Register(&httpmock.Stub{
Method: "GET",
URL: "/open-apis/base/v3/bases/app_x/tables/tbl_x/forms",
Body: map[string]interface{}{
"code": 0,
"data": map[string]interface{}{
"has_more": true,
"page_token": "tok_p2",
"total": 2,
"forms": []interface{}{
map[string]interface{}{"id": "vew_form1", "name": "Page1 Form", "description": ""},
},
},
},
})
// Second page: has_more=false
reg.Register(&httpmock.Stub{
Method: "GET",
URL: "page_token=tok_p2",
Body: map[string]interface{}{
"code": 0,
"data": map[string]interface{}{
"has_more": false,
"total": 2,
"forms": []interface{}{
map[string]interface{}{"id": "vew_form2", "name": "Page2 Form", "description": ""},
},
},
},
})
if err := runShortcut(t, BaseFormsList, []string{"+form-list", "--base-token", "app_x", "--table-id", "tbl_x"}, factory, stdout); err != nil {
t.Fatalf("err=%v", err)
}
got := stdout.String()
if !strings.Contains(got, `"vew_form1"`) || !strings.Contains(got, `"vew_form2"`) {
t.Fatalf("stdout=%s", got)
}
if !strings.Contains(got, `"total": 2`) {
t.Fatalf("expected total=2 in stdout=%s", got)
}
})
}
func TestBaseFormExecuteGet(t *testing.T) {
factory, stdout, reg := newExecuteFactory(t)
reg.Register(&httpmock.Stub{
Method: "GET",
URL: "/open-apis/base/v3/bases/app_x/tables/tbl_x/forms/vew_form1",
Body: map[string]interface{}{
"code": 0,
"data": map[string]interface{}{
"id": "vew_form1",
"name": "用户调研问卷",
"description": "2024年度用户满意度调研",
},
},
})
if err := runShortcut(t, BaseFormGet, []string{"+form-get", "--base-token", "app_x", "--table-id", "tbl_x", "--form-id", "vew_form1"}, factory, stdout); err != nil {
t.Fatalf("err=%v", err)
}
if got := stdout.String(); !strings.Contains(got, `"vew_form1"`) || !strings.Contains(got, `"用户调研问卷"`) {
t.Fatalf("stdout=%s", got)
}
}
func TestBaseFormExecuteCreate(t *testing.T) {
t.Run("name only", func(t *testing.T) {
factory, stdout, reg := newExecuteFactory(t)
reg.Register(&httpmock.Stub{
Method: "POST",
URL: "/open-apis/base/v3/bases/app_x/tables/tbl_x/forms",
Body: map[string]interface{}{
"code": 0,
"data": map[string]interface{}{
"id": "vew_form_new",
"name": "新建表单",
"description": "",
},
},
})
if err := runShortcut(t, BaseFormCreate, []string{"+form-create", "--base-token", "app_x", "--table-id", "tbl_x", "--name", "新建表单"}, factory, stdout); err != nil {
t.Fatalf("err=%v", err)
}
if got := stdout.String(); !strings.Contains(got, `"vew_form_new"`) || !strings.Contains(got, `"新建表单"`) {
t.Fatalf("stdout=%s", got)
}
})
t.Run("with description", func(t *testing.T) {
factory, stdout, reg := newExecuteFactory(t)
reg.Register(&httpmock.Stub{
Method: "POST",
URL: "/open-apis/base/v3/bases/app_x/tables/tbl_x/forms",
Body: map[string]interface{}{
"code": 0,
"data": map[string]interface{}{
"id": "vew_form_desc",
"name": "含描述表单",
"description": "这是表单说明",
},
},
})
args := []string{"+form-create", "--base-token", "app_x", "--table-id", "tbl_x", "--name", "含描述表单",
"--description", "这是表单说明"}
if err := runShortcut(t, BaseFormCreate, args, factory, stdout); err != nil {
t.Fatalf("err=%v", err)
}
if got := stdout.String(); !strings.Contains(got, `"vew_form_desc"`) {
t.Fatalf("stdout=%s", got)
}
})
t.Run("with description link", func(t *testing.T) {
factory, stdout, reg := newExecuteFactory(t)
reg.Register(&httpmock.Stub{
Method: "POST",
URL: "/open-apis/base/v3/bases/app_x/tables/tbl_x/forms",
Body: map[string]interface{}{
"code": 0,
"data": map[string]interface{}{
"id": "vew_form_link",
"name": "含链接表单",
"description": "更多信息请查看[这里](https://example.com)",
},
},
})
args := []string{"+form-create", "--base-token", "app_x", "--table-id", "tbl_x", "--name", "含链接表单",
"--description", "更多信息请查看[这里](https://example.com)"}
if err := runShortcut(t, BaseFormCreate, args, factory, stdout); err != nil {
t.Fatalf("err=%v", err)
}
if got := stdout.String(); !strings.Contains(got, `"vew_form_link"`) {
t.Fatalf("stdout=%s", got)
}
})
}
func TestBaseFormExecuteUpdate(t *testing.T) {
t.Run("update name", func(t *testing.T) {
factory, stdout, reg := newExecuteFactory(t)
reg.Register(&httpmock.Stub{
Method: "PATCH",
URL: "/open-apis/base/v3/bases/app_x/tables/tbl_x/forms/vew_form1",
Body: map[string]interface{}{
"code": 0,
"data": map[string]interface{}{
"id": "vew_form1",
"name": "更新后的表单",
"description": "",
},
},
})
if err := runShortcut(t, BaseFormUpdate, []string{"+form-update", "--base-token", "app_x", "--table-id", "tbl_x", "--form-id", "vew_form1", "--name", "更新后的表单"}, factory, stdout); err != nil {
t.Fatalf("err=%v", err)
}
if got := stdout.String(); !strings.Contains(got, `"vew_form1"`) || !strings.Contains(got, `"更新后的表单"`) {
t.Fatalf("stdout=%s", got)
}
})
t.Run("update with description", func(t *testing.T) {
factory, stdout, reg := newExecuteFactory(t)
reg.Register(&httpmock.Stub{
Method: "PATCH",
URL: "/open-apis/base/v3/bases/app_x/tables/tbl_x/forms/vew_form1",
Body: map[string]interface{}{
"code": 0,
"data": map[string]interface{}{
"id": "vew_form1",
"name": "Form",
"description": "更新的描述内容",
},
},
})
args := []string{"+form-update", "--base-token", "app_x", "--table-id", "tbl_x", "--form-id", "vew_form1",
"--description", "更新的描述内容"}
if err := runShortcut(t, BaseFormUpdate, args, factory, stdout); err != nil {
t.Fatalf("err=%v", err)
}
if got := stdout.String(); !strings.Contains(got, `"vew_form1"`) {
t.Fatalf("stdout=%s", got)
}
})
}
func TestBaseFormExecuteDelete(t *testing.T) {
factory, stdout, reg := newExecuteFactory(t)
reg.Register(&httpmock.Stub{
Method: "DELETE",
URL: "/open-apis/base/v3/bases/app_x/tables/tbl_x/forms/vew_form1",
Body: map[string]interface{}{"code": 0, "data": map[string]interface{}{}},
})
if err := runShortcut(t, BaseFormDelete, []string{"+form-delete", "--base-token", "app_x", "--table-id", "tbl_x", "--form-id", "vew_form1", "--yes"}, factory, stdout); err != nil {
t.Fatalf("err=%v", err)
}
if got := stdout.String(); !strings.Contains(got, `"deleted": true`) || !strings.Contains(got, `"form_id": "vew_form1"`) {
t.Fatalf("stdout=%s", got)
}
}
func TestBaseFormQuestionsExecuteList(t *testing.T) {
factory, stdout, reg := newExecuteFactory(t)
reg.Register(&httpmock.Stub{
Method: "GET",
URL: "/open-apis/base/v3/bases/app_x/tables/tbl_x/forms/vew_form1/questions",
Body: map[string]interface{}{
"code": 0,
"data": map[string]interface{}{
"total": 2,
"questions": []interface{}{
map[string]interface{}{"id": "q_001", "title": "您的姓名", "required": true, "description": nil},
map[string]interface{}{"id": "q_002", "title": "您的年龄", "required": false, "description": nil},
},
},
},
})
if err := runShortcut(t, BaseFormQuestionsList, []string{"+form-questions-list", "--base-token", "app_x", "--table-id", "tbl_x", "--form-id", "vew_form1"}, factory, stdout); err != nil {
t.Fatalf("err=%v", err)
}
if got := stdout.String(); !strings.Contains(got, `"q_001"`) || !strings.Contains(got, `"total": 2`) {
t.Fatalf("stdout=%s", got)
}
}
func TestBaseFormQuestionsExecuteCreate(t *testing.T) {
t.Run("create questions", func(t *testing.T) {
factory, stdout, reg := newExecuteFactory(t)
reg.Register(&httpmock.Stub{
Method: "POST",
URL: "/open-apis/base/v3/bases/app_x/tables/tbl_x/forms/vew_form1/questions",
Body: map[string]interface{}{
"code": 0,
"data": map[string]interface{}{
"questions": []interface{}{
map[string]interface{}{"id": "q_new1", "title": "您的姓名", "required": true},
},
},
},
})
args := []string{"+form-questions-create", "--base-token", "app_x", "--table-id", "tbl_x", "--form-id", "vew_form1",
"--questions", `[{"type":"text","title":"您的姓名","required":true}]`}
if err := runShortcut(t, BaseFormQuestionsCreate, args, factory, stdout); err != nil {
t.Fatalf("err=%v", err)
}
if got := stdout.String(); !strings.Contains(got, `"questions"`) || !strings.Contains(got, `"q_new1"`) {
t.Fatalf("stdout=%s", got)
}
})
t.Run("invalid questions json", func(t *testing.T) {
factory, stdout, _ := newExecuteFactory(t)
args := []string{"+form-questions-create", "--base-token", "app_x", "--table-id", "tbl_x", "--form-id", "vew_form1",
"--questions", `not-an-array`}
if err := runShortcut(t, BaseFormQuestionsCreate, args, factory, stdout); err == nil {
t.Fatalf("expected error for invalid questions JSON")
}
})
}
func TestBaseFormQuestionsExecuteUpdate(t *testing.T) {
factory, stdout, reg := newExecuteFactory(t)
reg.Register(&httpmock.Stub{
Method: "PATCH",
URL: "/open-apis/base/v3/bases/app_x/tables/tbl_x/forms/vew_form1/questions",
Body: map[string]interface{}{
"code": 0,
"data": map[string]interface{}{
"questions": []interface{}{
map[string]interface{}{"id": "q_001", "title": "更新后的问题", "required": true},
},
},
},
})
args := []string{"+form-questions-update", "--base-token", "app_x", "--table-id", "tbl_x", "--form-id", "vew_form1",
"--questions", `[{"id":"q_001","title":"更新后的问题","required":true}]`}
if err := runShortcut(t, BaseFormQuestionsUpdate, args, factory, stdout); err != nil {
t.Fatalf("err=%v", err)
}
if got := stdout.String(); !strings.Contains(got, `"questions"`) || !strings.Contains(got, `"q_001"`) {
t.Fatalf("stdout=%s", got)
}
}
func TestBaseFormQuestionsExecuteDelete(t *testing.T) {
t.Run("delete questions", func(t *testing.T) {
factory, stdout, reg := newExecuteFactory(t)
reg.Register(&httpmock.Stub{
Method: "DELETE",
URL: "/open-apis/base/v3/bases/app_x/tables/tbl_x/forms/vew_form1/questions",
Body: map[string]interface{}{"code": 0, "data": map[string]interface{}{}},
})
args := []string{"+form-questions-delete", "--base-token", "app_x", "--table-id", "tbl_x", "--form-id", "vew_form1",
"--question-ids", `["q_001","q_002"]`, "--yes"}
if err := runShortcut(t, BaseFormQuestionsDelete, args, factory, stdout); err != nil {
t.Fatalf("err=%v", err)
}
if got := stdout.String(); !strings.Contains(got, `"deleted": true`) || !strings.Contains(got, `"q_001"`) {
t.Fatalf("stdout=%s", got)
}
})
t.Run("invalid question-ids json", func(t *testing.T) {
factory, stdout, _ := newExecuteFactory(t)
args := []string{"+form-questions-delete", "--base-token", "app_x", "--table-id", "tbl_x", "--form-id", "vew_form1",
"--question-ids", `not-json`}
if err := runShortcut(t, BaseFormQuestionsDelete, args, factory, stdout); err == nil {
t.Fatalf("expected error for invalid question-ids JSON")
}
})
}