Files
larksuite-cli/tests/cli_e2e/im/flag_workflow_test.go

306 lines
8.3 KiB
Go

// Copyright (c) 2026 Lark Technologies Pte. Ltd.
// SPDX-License-Identifier: MIT
package im
import (
"context"
"testing"
"time"
clie2e "github.com/larksuite/cli/tests/cli_e2e"
"github.com/stretchr/testify/require"
"github.com/tidwall/gjson"
)
func TestIM_FlagWorkflowAsUser(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
t.Cleanup(cancel)
clie2e.SkipWithoutUserToken(t)
parentT := t
suffix := clie2e.GenerateSuffix()
chatName := "im-flag-" + suffix
messageText := "flag-test-msg-" + suffix
var chatID string
var messageID string
t.Run("create chat as user", func(t *testing.T) {
chatID = createChatAs(t, parentT, ctx, chatName, "user")
})
t.Run("send message as user", func(t *testing.T) {
messageID = sendMessageAs(t, ctx, chatID, messageText, "user")
})
t.Run("create flag as user", func(t *testing.T) {
result, err := clie2e.RunCmd(ctx, clie2e.Request{
Args: []string{
"im", "+flag-create",
"--message-id", messageID,
},
DefaultAs: "user",
})
require.NoError(t, err)
result.AssertExitCode(t, 0)
result.AssertStdoutStatus(t, true)
})
t.Run("list flags as user", func(t *testing.T) {
result, err := clie2e.RunCmdWithRetry(ctx, clie2e.Request{
Args: []string{
"im", "+flag-list",
"--page-size", "10",
"--page-all",
},
DefaultAs: "user",
}, clie2e.RetryOptions{
ShouldRetry: func(result *clie2e.Result) bool {
if result == nil || result.ExitCode != 0 {
return true
}
// Check if our message is in the list
for _, item := range gjson.Get(result.Stdout, "data.flag_items").Array() {
if item.Get("item_id").String() == messageID {
return false
}
}
return true
},
})
require.NoError(t, err)
result.AssertExitCode(t, 0)
result.AssertStdoutStatus(t, true)
// Verify our flagged message is in the list
var found bool
for _, item := range gjson.Get(result.Stdout, "data.flag_items").Array() {
if item.Get("item_id").String() == messageID {
found = true
// Verify it's a message-type flag (flag_type=2)
require.Equal(t, "2", item.Get("flag_type").String(), "expected flag_type=2 (message)")
break
}
}
require.True(t, found, "expected message %s in flag list", messageID)
})
t.Run("cancel flag as user", func(t *testing.T) {
result, err := clie2e.RunCmd(ctx, clie2e.Request{
Args: []string{
"im", "+flag-cancel",
"--message-id", messageID,
},
DefaultAs: "user",
})
require.NoError(t, err)
result.AssertExitCode(t, 0)
result.AssertStdoutStatus(t, true)
})
t.Run("verify flag removed", func(t *testing.T) {
result, err := clie2e.RunCmdWithRetry(ctx, clie2e.Request{
Args: []string{
"im", "+flag-list",
"--page-size", "10",
"--page-all",
},
DefaultAs: "user",
}, clie2e.RetryOptions{
ShouldRetry: func(result *clie2e.Result) bool {
if result == nil || result.ExitCode != 0 {
return true
}
// Check if our message is still in the list
for _, item := range gjson.Get(result.Stdout, "data.flag_items").Array() {
if item.Get("item_id").String() == messageID {
return true // Still there, retry
}
}
return false // Not found, success
},
})
require.NoError(t, err)
result.AssertExitCode(t, 0)
result.AssertStdoutStatus(t, true)
// Verify our message is NOT in the list
for _, item := range gjson.Get(result.Stdout, "data.flag_items").Array() {
require.NotEqual(t, messageID, item.Get("item_id").String(), "message should not be in flag list after cancel")
}
})
}
func TestIM_FlagCreateWithExplicitTypeAsUser(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
t.Cleanup(cancel)
clie2e.SkipWithoutUserToken(t)
parentT := t
suffix := clie2e.GenerateSuffix()
chatName := "im-flag-explicit-" + suffix
messageText := "flag-explicit-msg-" + suffix
var chatID string
var messageID string
t.Run("create chat as user", func(t *testing.T) {
chatID = createChatAs(t, parentT, ctx, chatName, "user")
})
t.Run("send message as user", func(t *testing.T) {
messageID = sendMessageAs(t, ctx, chatID, messageText, "user")
})
t.Run("create flag with explicit types as user", func(t *testing.T) {
result, err := clie2e.RunCmd(ctx, clie2e.Request{
Args: []string{
"im", "+flag-create",
"--message-id", messageID,
"--item-type", "default",
"--flag-type", "message",
},
DefaultAs: "user",
})
require.NoError(t, err)
result.AssertExitCode(t, 0)
result.AssertStdoutStatus(t, true)
})
t.Run("list flags to verify explicit types as user", func(t *testing.T) {
result, err := clie2e.RunCmdWithRetry(ctx, clie2e.Request{
Args: []string{
"im", "+flag-list",
"--page-size", "10",
"--page-all",
},
DefaultAs: "user",
}, clie2e.RetryOptions{
ShouldRetry: func(result *clie2e.Result) bool {
if result == nil || result.ExitCode != 0 {
return true
}
for _, item := range gjson.Get(result.Stdout, "data.flag_items").Array() {
if item.Get("item_id").String() == messageID {
return false
}
}
return true
},
})
require.NoError(t, err)
result.AssertExitCode(t, 0)
result.AssertStdoutStatus(t, true)
// Verify explicit types were applied
var found bool
for _, item := range gjson.Get(result.Stdout, "data.flag_items").Array() {
if item.Get("item_id").String() == messageID {
found = true
require.Equal(t, "0", item.Get("item_type").String(), "expected item_type=0 (default)")
require.Equal(t, "2", item.Get("flag_type").String(), "expected flag_type=2 (message)")
break
}
}
require.True(t, found, "expected message %s in flag list", messageID)
})
t.Run("cancel flag with explicit types as user", func(t *testing.T) {
result, err := clie2e.RunCmd(ctx, clie2e.Request{
Args: []string{
"im", "+flag-cancel",
"--message-id", messageID,
"--flag-type", "message",
},
DefaultAs: "user",
})
require.NoError(t, err)
result.AssertExitCode(t, 0)
result.AssertStdoutStatus(t, true)
})
}
func TestIM_FlagListPaginationAsUser(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
t.Cleanup(cancel)
clie2e.SkipWithoutUserToken(t)
t.Run("list flags with page-all as user", func(t *testing.T) {
result, err := clie2e.RunCmd(ctx, clie2e.Request{
Args: []string{
"im", "+flag-list",
"--page-size", "5",
"--page-all",
"--page-limit", "3",
},
DefaultAs: "user",
})
require.NoError(t, err)
result.AssertExitCode(t, 0)
result.AssertStdoutStatus(t, true)
})
}
func TestIM_FlagDryRun(t *testing.T) {
t.Setenv("LARKSUITE_CLI_CONFIG_DIR", t.TempDir())
t.Setenv("LARKSUITE_CLI_APP_ID", "app")
t.Setenv("LARKSUITE_CLI_APP_SECRET", "secret")
t.Setenv("LARKSUITE_CLI_BRAND", "feishu")
t.Setenv("LARKSUITE_CLI_STRICT_MODE", "user")
t.Setenv("LARKSUITE_CLI_DEFAULT_AS", "user")
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
t.Cleanup(cancel)
t.Run("create flag dry-run", func(t *testing.T) {
result, err := clie2e.RunCmd(ctx, clie2e.Request{
Args: []string{
"im", "+flag-create",
"--message-id", "om_test_dry_run",
"--dry-run",
},
DefaultAs: "user",
})
require.NoError(t, err)
result.AssertExitCode(t, 0)
require.Contains(t, result.Stdout, "POST")
require.Contains(t, result.Stdout, "/open-apis/im/v1/flags")
require.Contains(t, result.Stdout, "flag_items")
require.Contains(t, result.Stdout, "om_test_dry_run")
})
t.Run("cancel flag dry-run with om", func(t *testing.T) {
result, err := clie2e.RunCmd(ctx, clie2e.Request{
Args: []string{
"im", "+flag-cancel",
"--message-id", "om_test_dry_run",
"--dry-run",
},
DefaultAs: "user",
})
require.NoError(t, err)
result.AssertExitCode(t, 0)
require.Contains(t, result.Stdout, "POST")
require.Contains(t, result.Stdout, "/open-apis/im/v1/flags/cancel")
require.Contains(t, result.Stdout, "flag_items")
require.Contains(t, result.Stdout, "om_test_dry_run")
})
t.Run("list flag dry-run", func(t *testing.T) {
result, err := clie2e.RunCmd(ctx, clie2e.Request{
Args: []string{
"im", "+flag-list",
"--dry-run",
},
DefaultAs: "user",
})
require.NoError(t, err)
result.AssertExitCode(t, 0)
require.Contains(t, result.Stdout, "GET")
require.Contains(t, result.Stdout, "/open-apis/im/v1/flags")
require.Contains(t, result.Stdout, "page_size")
})
}