mirror of
https://github.com/larksuite/cli.git
synced 2026-07-07 09:11:44 +08:00
262 lines
8.3 KiB
Go
262 lines
8.3 KiB
Go
// Copyright (c) 2026 Lark Technologies Pte. Ltd.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package vc
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/spf13/cobra"
|
|
|
|
"github.com/larksuite/cli/internal/cmdutil"
|
|
"github.com/larksuite/cli/internal/core"
|
|
"github.com/larksuite/cli/shortcuts/common"
|
|
)
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Unit tests for pure functions
|
|
// ---------------------------------------------------------------------------
|
|
|
|
func TestUniqueIDs(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input []string
|
|
want []string
|
|
}{
|
|
{"nil", nil, nil},
|
|
{"empty", []string{}, nil},
|
|
{"no dups", []string{"a", "b", "c"}, []string{"a", "b", "c"}},
|
|
{"with dups", []string{"a", "b", "a", "c", "b"}, []string{"a", "b", "c"}},
|
|
{"single", []string{"x"}, []string{"x"}},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := uniqueIDs(tt.input)
|
|
if len(got) != len(tt.want) {
|
|
t.Fatalf("uniqueIDs(%v) = %v, want %v", tt.input, got, tt.want)
|
|
}
|
|
for i := range got {
|
|
if got[i] != tt.want[i] {
|
|
t.Errorf("uniqueIDs(%v)[%d] = %q, want %q", tt.input, i, got[i], tt.want[i])
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestParseTimeRange(t *testing.T) {
|
|
cfg := &core.CliConfig{AppID: "test", AppSecret: "s", Brand: core.BrandFeishu}
|
|
tests := []struct {
|
|
name string
|
|
start string
|
|
end string
|
|
wantErr bool
|
|
}{
|
|
{"both empty", "", "", false},
|
|
{"valid start", "2026-03-24T00:00+08:00", "", false},
|
|
{"valid end", "", "2026-03-24T23:59+08:00", false},
|
|
{"both valid", "2026-03-24T00:00+08:00", "2026-03-24T23:59+08:00", false},
|
|
{"invalid start", "not-a-date", "", true},
|
|
{"invalid end", "", "not-a-date", true},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
cmd := &cobra.Command{Use: "test"}
|
|
cmd.Flags().String("start", "", "")
|
|
cmd.Flags().String("end", "", "")
|
|
if tt.start != "" {
|
|
cmd.Flags().Set("start", tt.start)
|
|
}
|
|
if tt.end != "" {
|
|
cmd.Flags().Set("end", tt.end)
|
|
}
|
|
runtime := common.TestNewRuntimeContext(cmd, cfg)
|
|
_, _, err := parseTimeRange(runtime)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("parseTimeRange() error = %v, wantErr %v", err, tt.wantErr)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestBuildSearchBody(t *testing.T) {
|
|
cfg := &core.CliConfig{AppID: "test", AppSecret: "s", Brand: core.BrandFeishu}
|
|
cmd := &cobra.Command{Use: "test"}
|
|
cmd.Flags().String("query", "", "")
|
|
cmd.Flags().String("start", "", "")
|
|
cmd.Flags().String("end", "", "")
|
|
cmd.Flags().String("organizer-ids", "", "")
|
|
cmd.Flags().String("participant-ids", "", "")
|
|
cmd.Flags().String("room-ids", "", "")
|
|
cmd.Flags().Set("query", "weekly")
|
|
cmd.Flags().Set("organizer-ids", "ou_a,ou_b")
|
|
cmd.Flags().Set("room-ids", "room1")
|
|
|
|
runtime := common.TestNewRuntimeContext(cmd, cfg)
|
|
body := buildSearchBody(runtime, "2026-03-20T00:00:00Z", "2026-03-24T00:00:00Z")
|
|
|
|
if body["query"] != "weekly" {
|
|
t.Errorf("query = %v, want 'weekly'", body["query"])
|
|
}
|
|
filter, ok := body["meeting_filter"].(map[string]interface{})
|
|
if !ok {
|
|
t.Fatal("meeting_filter should be present")
|
|
}
|
|
if filter["organizer_ids"] == nil {
|
|
t.Error("organizer_ids should be present")
|
|
}
|
|
if filter["open_room_ids"] == nil {
|
|
t.Error("open_room_ids should be present")
|
|
}
|
|
if filter["start_time"] == nil {
|
|
t.Error("start_time should be present")
|
|
}
|
|
}
|
|
|
|
func TestBuildSearchBody_Empty(t *testing.T) {
|
|
cfg := &core.CliConfig{AppID: "test", AppSecret: "s", Brand: core.BrandFeishu}
|
|
cmd := &cobra.Command{Use: "test"}
|
|
cmd.Flags().String("query", "", "")
|
|
cmd.Flags().String("start", "", "")
|
|
cmd.Flags().String("end", "", "")
|
|
cmd.Flags().String("organizer-ids", "", "")
|
|
cmd.Flags().String("participant-ids", "", "")
|
|
cmd.Flags().String("room-ids", "", "")
|
|
|
|
runtime := common.TestNewRuntimeContext(cmd, cfg)
|
|
body := buildSearchBody(runtime, "", "")
|
|
|
|
if len(body) != 0 {
|
|
t.Errorf("expected empty body, got %v", body)
|
|
}
|
|
}
|
|
|
|
func TestBuildTimeFilter(t *testing.T) {
|
|
if got := buildTimeFilter("", ""); got != nil {
|
|
t.Errorf("expected nil for empty times, got %v", got)
|
|
}
|
|
got := buildTimeFilter("2026-03-24T00:00Z", "2026-03-25T00:00Z")
|
|
if got["start_time"] != "2026-03-24T00:00Z" || got["end_time"] != "2026-03-25T00:00Z" {
|
|
t.Errorf("unexpected time filter: %v", got)
|
|
}
|
|
got = buildTimeFilter("2026-03-24T00:00Z", "")
|
|
if got["start_time"] != "2026-03-24T00:00Z" || got["end_time"] != nil {
|
|
t.Errorf("expected only start_time: %v", got)
|
|
}
|
|
}
|
|
|
|
func TestBuildMeetingFilter_Empty(t *testing.T) {
|
|
if got := buildMeetingFilter(nil, nil, nil, nil); got != nil {
|
|
t.Errorf("expected nil for all empty, got %v", got)
|
|
}
|
|
}
|
|
|
|
func TestBuildMeetingFilter_WithData(t *testing.T) {
|
|
got := buildMeetingFilter([]string{"ou_a"}, nil, []string{"r1"}, nil)
|
|
if got["participant_ids"] == nil {
|
|
t.Error("participant_ids should be present")
|
|
}
|
|
if got["open_room_ids"] == nil {
|
|
t.Error("open_room_ids should be present")
|
|
}
|
|
if got["organizer_ids"] != nil {
|
|
t.Error("organizer_ids should not be present")
|
|
}
|
|
}
|
|
|
|
func TestMeetingSearchDisplayInfo(t *testing.T) {
|
|
if got := meetingSearchDisplayInfo(map[string]interface{}{"display_info": "Weekly Sync"}); got != "Weekly Sync" {
|
|
t.Fatalf("meetingSearchDisplayInfo() = %q, want %q", got, "Weekly Sync")
|
|
}
|
|
if got := meetingSearchDisplayInfo(map[string]interface{}{}); got != "" {
|
|
t.Fatalf("meetingSearchDisplayInfo() = %q, want empty string", got)
|
|
}
|
|
}
|
|
|
|
func TestMeetingSearchDescription(t *testing.T) {
|
|
if got := meetingSearchDescription(map[string]interface{}{
|
|
"meta_data": map[string]interface{}{"description": "2026-03-24 15:00"},
|
|
}); got != "2026-03-24 15:00" {
|
|
t.Fatalf("meetingSearchDescription() = %q, want %q", got, "2026-03-24 15:00")
|
|
}
|
|
if got := meetingSearchDescription(map[string]interface{}{}); got != "" {
|
|
t.Fatalf("meetingSearchDescription() = %q, want empty string", got)
|
|
}
|
|
}
|
|
|
|
func TestSearch_Validation_NoFilter(t *testing.T) {
|
|
f, _, _, _ := cmdutil.TestFactory(t, defaultConfig())
|
|
err := mountAndRun(t, VCSearch, []string{"+search", "--as", "user"}, f, nil)
|
|
if err == nil {
|
|
t.Fatal("expected validation error for no filter")
|
|
}
|
|
if !strings.Contains(err.Error(), "specify at least one") {
|
|
t.Errorf("unexpected error message: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestSearch_Validation_QueryTooLong(t *testing.T) {
|
|
cmd := &cobra.Command{Use: "test"}
|
|
cmd.Flags().String("query", "", "")
|
|
cmd.Flags().String("start", "", "")
|
|
cmd.Flags().String("end", "", "")
|
|
cmd.Flags().String("organizer-ids", "", "")
|
|
cmd.Flags().String("participant-ids", "", "")
|
|
cmd.Flags().String("room-ids", "", "")
|
|
cmd.Flags().String("page-size", "", "")
|
|
longQuery := strings.Repeat("a", 51)
|
|
_ = cmd.Flags().Set("query", longQuery)
|
|
|
|
runtime := common.TestNewRuntimeContext(cmd, defaultConfig())
|
|
err := VCSearch.Validate(context.Background(), runtime)
|
|
if err == nil {
|
|
t.Fatal("expected validation error for overlong query")
|
|
}
|
|
if !strings.Contains(err.Error(), "length must be between 1 and 50 characters") {
|
|
t.Fatalf("unexpected error message: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestSearch_Validation_InvalidPageSize(t *testing.T) {
|
|
cmd := &cobra.Command{Use: "test"}
|
|
cmd.Flags().String("query", "", "")
|
|
cmd.Flags().String("start", "", "")
|
|
cmd.Flags().String("end", "", "")
|
|
cmd.Flags().String("organizer-ids", "", "")
|
|
cmd.Flags().String("participant-ids", "", "")
|
|
cmd.Flags().String("room-ids", "", "")
|
|
cmd.Flags().String("page-size", "", "")
|
|
_ = cmd.Flags().Set("query", "weekly")
|
|
_ = cmd.Flags().Set("page-size", "31")
|
|
|
|
runtime := common.TestNewRuntimeContext(cmd, defaultConfig())
|
|
err := VCSearch.Validate(context.Background(), runtime)
|
|
if err == nil {
|
|
t.Fatal("expected validation error for invalid page-size")
|
|
}
|
|
if !strings.Contains(err.Error(), "must be between 1 and 30") {
|
|
t.Fatalf("unexpected error message: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestSearch_DryRun(t *testing.T) {
|
|
f, stdout, _, _ := cmdutil.TestFactory(t, defaultConfig())
|
|
err := mountAndRun(t, VCSearch, []string{"+search", "--query", "test", "--dry-run", "--as", "user"}, f, stdout)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if !strings.Contains(stdout.String(), "/open-apis/vc/v1/meetings/search") {
|
|
t.Errorf("dry-run should show API path, got: %s", stdout.String())
|
|
}
|
|
}
|
|
|
|
func TestSearch_InvalidTimeRange(t *testing.T) {
|
|
f, _, _, _ := cmdutil.TestFactory(t, defaultConfig())
|
|
err := mountAndRun(t, VCSearch, []string{"+search", "--start", "bad-time", "--as", "user"}, f, nil)
|
|
if err == nil {
|
|
t.Fatal("expected error for invalid time")
|
|
}
|
|
}
|