-
Notifications
You must be signed in to change notification settings - Fork 585
Add cli e2e tests coverage #400
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
dccdb71
3ab45fb
819d09e
22efa4f
c7b71f8
59c23ca
02769f7
a2d3dd0
2f17ac1
39703df
e94ba11
42df0dd
8447621
7bcc7b2
7813d74
8477a8c
5231aa9
b97e307
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -34,3 +34,4 @@ tests/mail/reports/ | |
| # Generated / test artifacts | ||
| internal/registry/meta_data.json | ||
| cmd/api/download.bin | ||
| app.log | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,86 @@ | ||
| // Copyright (c) 2026 Lark Technologies Pte. Ltd. | ||
| // SPDX-License-Identifier: MIT | ||
|
|
||
| package base | ||
|
|
||
| import ( | ||
| "context" | ||
| "testing" | ||
| "time" | ||
|
|
||
| clie2e "github.com/larksuite/cli/tests/cli_e2e" | ||
| "github.com/stretchr/testify/assert" | ||
| "github.com/stretchr/testify/require" | ||
| "github.com/tidwall/gjson" | ||
| ) | ||
|
|
||
| func TestBase_BasicWorkflow(t *testing.T) { | ||
| parentT := t | ||
| ctx, cancel := context.WithTimeout(context.Background(), 4*time.Minute) | ||
| t.Cleanup(cancel) | ||
|
|
||
| baseName := "lark-cli-e2e-base-basic-" + testSuffix() | ||
| baseToken := createBase(t, ctx, baseName) | ||
|
|
||
| t.Run("get base", func(t *testing.T) { | ||
| result, err := clie2e.RunCmd(ctx, clie2e.Request{ | ||
| Args: []string{"base", "+base-get", "--base-token", baseToken}, | ||
| DefaultAs: "bot", | ||
| }) | ||
| require.NoError(t, err) | ||
| if result.ExitCode != 0 { | ||
| skipIfBaseUnavailable(t, result, "requires bot base get capability") | ||
| } | ||
| result.AssertExitCode(t, 0) | ||
| result.AssertStdoutStatus(t, true) | ||
| returnedBaseToken := gjson.Get(result.Stdout, "data.base.app_token").String() | ||
| if returnedBaseToken == "" { | ||
| returnedBaseToken = gjson.Get(result.Stdout, "data.base.base_token").String() | ||
| } | ||
| assert.Equal(t, baseToken, returnedBaseToken, "stdout:\n%s", result.Stdout) | ||
| assert.NotEmpty(t, gjson.Get(result.Stdout, "data.base.name").String(), "stdout:\n%s", result.Stdout) | ||
| }) | ||
|
|
||
| tableName := "lark-cli-e2e-table-basic-" + testSuffix() | ||
| tableID, primaryFieldID, primaryViewID := createTable( | ||
| t, | ||
| parentT, | ||
| ctx, | ||
| baseToken, | ||
| tableName, | ||
| `[{"name":"Name","type":"text"}]`, | ||
| `{"name":"Main","type":"grid"}`, | ||
| ) | ||
|
|
||
| t.Run("get table", func(t *testing.T) { | ||
| result, err := clie2e.RunCmd(ctx, clie2e.Request{ | ||
| Args: []string{"base", "+table-get", "--base-token", baseToken, "--table-id", tableID}, | ||
| DefaultAs: "bot", | ||
| }) | ||
| require.NoError(t, err) | ||
| if result.ExitCode != 0 { | ||
| skipIfBaseUnavailable(t, result, "requires bot table get capability") | ||
| } | ||
| result.AssertExitCode(t, 0) | ||
| result.AssertStdoutStatus(t, true) | ||
| assert.Equal(t, tableID, gjson.Get(result.Stdout, "data.table.id").String()) | ||
| assert.Equal(t, tableName, gjson.Get(result.Stdout, "data.table.name").String()) | ||
| }) | ||
|
|
||
| t.Run("list tables and find created table", func(t *testing.T) { | ||
| result, err := clie2e.RunCmd(ctx, clie2e.Request{ | ||
| Args: []string{"base", "+table-list", "--base-token", baseToken}, | ||
| DefaultAs: "bot", | ||
| }) | ||
| require.NoError(t, err) | ||
| if result.ExitCode != 0 { | ||
| skipIfBaseUnavailable(t, result, "requires bot table list capability") | ||
| } | ||
| result.AssertExitCode(t, 0) | ||
| result.AssertStdoutStatus(t, true) | ||
| assert.True(t, gjson.Get(result.Stdout, `data.items.#(table_id=="`+tableID+`")`).Exists(), "stdout:\n%s", result.Stdout) | ||
| }) | ||
|
|
||
| require.NotEmpty(t, primaryFieldID) | ||
| require.NotEmpty(t, primaryViewID) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,130 @@ | ||
| // Copyright (c) 2026 Lark Technologies Pte. Ltd. | ||
| // SPDX-License-Identifier: MIT | ||
|
|
||
| package base | ||
|
|
||
| import ( | ||
| "context" | ||
| "testing" | ||
| "time" | ||
|
|
||
| clie2e "github.com/larksuite/cli/tests/cli_e2e" | ||
| "github.com/stretchr/testify/assert" | ||
| "github.com/stretchr/testify/require" | ||
| "github.com/tidwall/gjson" | ||
| ) | ||
|
|
||
| func TestBase_RoleWorkflow(t *testing.T) { | ||
| parentT := t | ||
| ctx, cancel := context.WithTimeout(context.Background(), 4*time.Minute) | ||
| t.Cleanup(cancel) | ||
|
Comment on lines
+17
to
+20
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isolate CLI config per test run. This test does not isolate As per coding guidelines 🤖 Prompt for AI Agents |
||
|
|
||
| baseToken := createBase(t, ctx, "lark-cli-e2e-base-role-"+testSuffix()) | ||
| result, err := clie2e.RunCmd(ctx, clie2e.Request{ | ||
| Args: []string{"base", "+advperm-enable", "--base-token", baseToken}, | ||
| DefaultAs: "bot", | ||
| }) | ||
| require.NoError(t, err) | ||
| if result.ExitCode != 0 { | ||
| skipIfBaseUnavailable(t, result, "requires bot advanced permission enable capability") | ||
| } | ||
| result.AssertExitCode(t, 0) | ||
| result.AssertStdoutStatus(t, true) | ||
|
|
||
| roleName := "Reviewer-" + testSuffix() | ||
| roleID := createRole(t, parentT, ctx, baseToken, `{"role_name":"`+roleName+`","role_type":"custom_role"}`) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoid deleting the same role twice (workflow delete + helper cleanup).
Consider either:
Also applies to: 118-129 🤖 Prompt for AI Agents |
||
|
|
||
| t.Run("list", func(t *testing.T) { | ||
| result, err := clie2e.RunCmd(ctx, clie2e.Request{ | ||
| Args: []string{"base", "+role-list", "--base-token", baseToken}, | ||
| DefaultAs: "bot", | ||
| }) | ||
| require.NoError(t, err) | ||
| if result.ExitCode != 0 { | ||
| skipIfBaseUnavailable(t, result, "requires bot role list capability") | ||
| } | ||
| result.AssertExitCode(t, 0) | ||
| result.AssertStdoutStatus(t, true) | ||
|
|
||
| roleListPayload := gjson.Get(result.Stdout, "data.data").String() | ||
| require.NotEmpty(t, roleListPayload, "stdout:\n%s", result.Stdout) | ||
| assert.True(t, gjson.Valid(roleListPayload), "role list payload should be valid JSON: %s", roleListPayload) | ||
|
|
||
| roleItems := gjson.Get(roleListPayload, "base_roles").Array() | ||
| assert.NotEmpty(t, roleItems, "role list should contain at least one role: %s", roleListPayload) | ||
|
|
||
| found := false | ||
| for _, item := range roleItems { | ||
| rolePayload := item.String() | ||
| if !gjson.Valid(rolePayload) { | ||
| continue | ||
| } | ||
| if gjson.Get(rolePayload, "role_id").String() == roleID { | ||
| found = true | ||
| break | ||
| } | ||
| } | ||
| assert.True(t, found, "stdout:\n%s", result.Stdout) | ||
| }) | ||
|
|
||
| t.Run("get", func(t *testing.T) { | ||
| result, err := clie2e.RunCmd(ctx, clie2e.Request{ | ||
| Args: []string{"base", "+role-get", "--base-token", baseToken, "--role-id", roleID}, | ||
| DefaultAs: "bot", | ||
| }) | ||
| require.NoError(t, err) | ||
| if result.ExitCode != 0 { | ||
| skipIfBaseUnavailable(t, result, "requires bot role get capability") | ||
| } | ||
| result.AssertExitCode(t, 0) | ||
| result.AssertStdoutStatus(t, true) | ||
|
|
||
| rolePayload := gjson.Get(result.Stdout, "data.data").String() | ||
| require.NotEmpty(t, rolePayload, "stdout:\n%s", result.Stdout) | ||
| require.True(t, gjson.Valid(rolePayload), "stdout:\n%s", result.Stdout) | ||
| assert.Equal(t, roleID, gjson.Get(rolePayload, "role_id").String()) | ||
| }) | ||
|
|
||
| t.Run("update", func(t *testing.T) { | ||
| updatedRoleName := roleName + " Updated" | ||
| result, err := clie2e.RunCmd(ctx, clie2e.Request{ | ||
| Args: []string{"base", "+role-update", "--base-token", baseToken, "--role-id", roleID, "--json", `{"role_name":"` + updatedRoleName + `","role_type":"custom_role"}`, "--yes"}, | ||
| DefaultAs: "bot", | ||
| }) | ||
| require.NoError(t, err) | ||
| if result.ExitCode != 0 { | ||
| skipIfBaseUnavailable(t, result, "requires bot role update capability") | ||
| } | ||
| result.AssertExitCode(t, 0) | ||
| result.AssertStdoutStatus(t, true) | ||
|
|
||
| getResult, err := clie2e.RunCmd(ctx, clie2e.Request{ | ||
| Args: []string{"base", "+role-get", "--base-token", baseToken, "--role-id", roleID}, | ||
| DefaultAs: "bot", | ||
| }) | ||
| require.NoError(t, err) | ||
| if getResult.ExitCode != 0 { | ||
| skipIfBaseUnavailable(t, getResult, "requires bot role get capability") | ||
| } | ||
| getResult.AssertExitCode(t, 0) | ||
| getResult.AssertStdoutStatus(t, true) | ||
|
|
||
| rolePayload := gjson.Get(getResult.Stdout, "data.data").String() | ||
| require.NotEmpty(t, rolePayload, "stdout:\n%s", getResult.Stdout) | ||
| require.True(t, gjson.Valid(rolePayload), "stdout:\n%s", getResult.Stdout) | ||
| assert.Equal(t, updatedRoleName, gjson.Get(rolePayload, "role_name").String()) | ||
| }) | ||
|
|
||
| t.Run("delete", func(t *testing.T) { | ||
| result, err := clie2e.RunCmd(ctx, clie2e.Request{ | ||
| Args: []string{"base", "+role-delete", "--base-token", baseToken, "--role-id", roleID, "--yes"}, | ||
| DefaultAs: "bot", | ||
| }) | ||
| require.NoError(t, err) | ||
| if result.ExitCode != 0 { | ||
| skipIfBaseUnavailable(t, result, "requires bot role delete capability") | ||
| } | ||
| result.AssertExitCode(t, 0) | ||
| result.AssertStdoutStatus(t, true) | ||
| }) | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replace hardcoded absolute path with a relative or placeholder path.
The path
/Users/bytedance/cli/tests/cli_e2e/browser/.auth/state.jsonis user-specific and won't work for other contributors. Consider using a relative path or a placeholder.📝 Suggested fix
Or use a placeholder:
📝 Committable suggestion
🤖 Prompt for AI Agents