chore: import upstream snapshot with attribution
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
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
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
// Copyright (c) 2026 Lark Technologies Pte. Ltd.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package calendar
|
||||
|
||||
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"
|
||||
)
|
||||
|
||||
// TestCalendar_CreateEvent tests the workflow of creating a calendar event.
|
||||
func TestCalendar_CreateEvent(t *testing.T) {
|
||||
parentT := t
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
|
||||
t.Cleanup(cancel)
|
||||
|
||||
suffix := clie2e.GenerateSuffix()
|
||||
eventSummary := "lark-cli-e2e-event-" + suffix
|
||||
eventDescription := "test event description"
|
||||
|
||||
startAt := time.Now().UTC().Add(1 * time.Hour).Truncate(time.Minute)
|
||||
endAt := startAt.Add(1 * time.Hour)
|
||||
startTime := startAt.Format(time.RFC3339)
|
||||
endTime := endAt.Format(time.RFC3339)
|
||||
|
||||
var eventID string
|
||||
var deletedEvent bool
|
||||
calendarID := getPrimaryCalendarID(t, ctx)
|
||||
|
||||
t.Run("create event with shortcut as bot", func(t *testing.T) {
|
||||
result, err := clie2e.RunCmd(ctx, clie2e.Request{
|
||||
Args: []string{"calendar", "+create",
|
||||
"--summary", eventSummary,
|
||||
"--start", startTime,
|
||||
"--end", endTime,
|
||||
"--calendar-id", calendarID,
|
||||
"--description", eventDescription,
|
||||
},
|
||||
DefaultAs: "bot",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
result.AssertExitCode(t, 0)
|
||||
result.AssertStdoutStatus(t, true)
|
||||
|
||||
eventID = gjson.Get(result.Stdout, "data.event_id").String()
|
||||
require.NotEmpty(t, eventID)
|
||||
|
||||
parentT.Cleanup(func() {
|
||||
if eventID == "" || deletedEvent {
|
||||
return
|
||||
}
|
||||
|
||||
cleanupCtx, cancel := clie2e.CleanupContext()
|
||||
defer cancel()
|
||||
|
||||
deleteResult, deleteErr := clie2e.RunCmd(cleanupCtx, clie2e.Request{
|
||||
Args: []string{"calendar", "events", "delete"},
|
||||
DefaultAs: "bot",
|
||||
Params: map[string]any{
|
||||
"calendar_id": calendarID,
|
||||
"event_id": eventID,
|
||||
},
|
||||
})
|
||||
clie2e.ReportCleanupFailure(parentT, "delete event "+eventID, deleteResult, deleteErr)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("verify event created as bot", func(t *testing.T) {
|
||||
require.NotEmpty(t, eventID)
|
||||
result, err := clie2e.RunCmd(ctx, clie2e.Request{
|
||||
Args: []string{"calendar", "events", "get"},
|
||||
DefaultAs: "bot",
|
||||
Params: map[string]any{
|
||||
"calendar_id": calendarID,
|
||||
"event_id": eventID,
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
result.AssertExitCode(t, 0)
|
||||
result.AssertStdoutStatus(t, true)
|
||||
assert.Equal(t, eventSummary, gjson.Get(result.Stdout, "data.event.summary").String())
|
||||
assert.Equal(t, eventDescription, gjson.Get(result.Stdout, "data.event.description").String())
|
||||
assert.Equal(t, unixSecondsRFC3339(startAt), gjson.Get(result.Stdout, "data.event.start_time.timestamp").String())
|
||||
assert.Equal(t, unixSecondsRFC3339(endAt), gjson.Get(result.Stdout, "data.event.end_time.timestamp").String())
|
||||
})
|
||||
|
||||
t.Run("delete event as bot", func(t *testing.T) {
|
||||
require.NotEmpty(t, eventID)
|
||||
result, err := clie2e.RunCmd(ctx, clie2e.Request{
|
||||
Args: []string{"calendar", "events", "delete"},
|
||||
DefaultAs: "bot",
|
||||
Params: map[string]any{
|
||||
"calendar_id": calendarID,
|
||||
"event_id": eventID,
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
result.AssertExitCode(t, 0)
|
||||
result.AssertStdoutStatus(t, true)
|
||||
deletedEvent = true
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
// Copyright (c) 2026 Lark Technologies Pte. Ltd.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package calendar
|
||||
|
||||
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"
|
||||
)
|
||||
|
||||
// TestCalendar_ManageCalendar tests the workflow of managing calendars.
|
||||
func TestCalendar_ManageCalendar(t *testing.T) {
|
||||
parentT := t
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
|
||||
t.Cleanup(cancel)
|
||||
|
||||
suffix := clie2e.GenerateSuffix()
|
||||
calendarSummary := "lark-cli-e2e-cal-" + suffix
|
||||
updatedCalendarSummary := calendarSummary + "-updated"
|
||||
calendarDescription := "test calendar created by e2e"
|
||||
|
||||
var createdCalendarID string
|
||||
var deletedCalendar bool
|
||||
|
||||
t.Run("get primary calendar as bot", func(t *testing.T) {
|
||||
primaryCalendarID := getPrimaryCalendarID(t, ctx)
|
||||
require.NotEmpty(t, primaryCalendarID)
|
||||
})
|
||||
|
||||
t.Run("create calendar as bot", func(t *testing.T) {
|
||||
result, err := clie2e.RunCmd(ctx, clie2e.Request{
|
||||
Args: []string{"calendar", "calendars", "create"},
|
||||
DefaultAs: "bot",
|
||||
Data: map[string]any{
|
||||
"summary": calendarSummary,
|
||||
"description": calendarDescription,
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
result.AssertExitCode(t, 0)
|
||||
result.AssertStdoutStatus(t, true)
|
||||
|
||||
createdCalendarID = gjson.Get(result.Stdout, "data.calendar.calendar_id").String()
|
||||
require.NotEmpty(t, createdCalendarID)
|
||||
|
||||
parentT.Cleanup(func() {
|
||||
if createdCalendarID == "" || deletedCalendar {
|
||||
return
|
||||
}
|
||||
|
||||
cleanupCtx, cancel := clie2e.CleanupContext()
|
||||
defer cancel()
|
||||
|
||||
deleteResult, deleteErr := clie2e.RunCmd(cleanupCtx, clie2e.Request{
|
||||
Args: []string{"calendar", "calendars", "delete"},
|
||||
DefaultAs: "bot",
|
||||
Params: map[string]any{
|
||||
"calendar_id": createdCalendarID,
|
||||
},
|
||||
Yes: true,
|
||||
})
|
||||
clie2e.ReportCleanupFailure(parentT, "delete calendar "+createdCalendarID, deleteResult, deleteErr)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("get created calendar as bot", func(t *testing.T) {
|
||||
require.NotEmpty(t, createdCalendarID)
|
||||
result, err := clie2e.RunCmd(ctx, clie2e.Request{
|
||||
Args: []string{"calendar", "calendars", "get"},
|
||||
DefaultAs: "bot",
|
||||
Params: map[string]any{
|
||||
"calendar_id": createdCalendarID,
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
result.AssertExitCode(t, 0)
|
||||
result.AssertStdoutStatus(t, true)
|
||||
assert.Equal(t, createdCalendarID, gjson.Get(result.Stdout, "data.calendar_id").String())
|
||||
assert.Equal(t, calendarSummary, gjson.Get(result.Stdout, "data.summary").String())
|
||||
assert.Equal(t, calendarDescription, gjson.Get(result.Stdout, "data.description").String())
|
||||
})
|
||||
|
||||
t.Run("update calendar as bot", func(t *testing.T) {
|
||||
require.NotEmpty(t, createdCalendarID)
|
||||
result, err := clie2e.RunCmd(ctx, clie2e.Request{
|
||||
Args: []string{"calendar", "calendars", "patch"},
|
||||
DefaultAs: "bot",
|
||||
Params: map[string]any{
|
||||
"calendar_id": createdCalendarID,
|
||||
},
|
||||
Data: map[string]any{
|
||||
"summary": updatedCalendarSummary,
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
result.AssertExitCode(t, 0)
|
||||
result.AssertStdoutStatus(t, true)
|
||||
})
|
||||
|
||||
t.Run("verify updated calendar as bot", func(t *testing.T) {
|
||||
require.NotEmpty(t, createdCalendarID)
|
||||
result, err := clie2e.RunCmd(ctx, clie2e.Request{
|
||||
Args: []string{"calendar", "calendars", "get"},
|
||||
DefaultAs: "bot",
|
||||
Params: map[string]any{
|
||||
"calendar_id": createdCalendarID,
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
result.AssertExitCode(t, 0)
|
||||
result.AssertStdoutStatus(t, true)
|
||||
assert.Equal(t, updatedCalendarSummary, gjson.Get(result.Stdout, "data.summary").String())
|
||||
})
|
||||
|
||||
t.Run("delete calendar as bot", func(t *testing.T) {
|
||||
require.NotEmpty(t, createdCalendarID)
|
||||
result, err := clie2e.RunCmd(ctx, clie2e.Request{
|
||||
Args: []string{"calendar", "calendars", "delete"},
|
||||
DefaultAs: "bot",
|
||||
Params: map[string]any{
|
||||
"calendar_id": createdCalendarID,
|
||||
},
|
||||
Yes: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
result.AssertExitCode(t, 0)
|
||||
result.AssertStdoutStatus(t, true)
|
||||
deletedCalendar = true
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
// Copyright (c) 2026 Lark Technologies Pte. Ltd.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package calendar
|
||||
|
||||
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 TestCalendar_PersonalEventWorkflowAsUser(t *testing.T) {
|
||||
parentT := t
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
|
||||
t.Cleanup(cancel)
|
||||
|
||||
clie2e.SkipWithoutUserToken(t)
|
||||
|
||||
suffix := clie2e.GenerateSuffix()
|
||||
eventSummary := "lark-cli-e2e-personal-event-" + suffix
|
||||
eventDescription := "created by calendar personal event workflow"
|
||||
startAt := time.Now().UTC().Add(24 * time.Hour).Truncate(time.Minute)
|
||||
endAt := startAt.Add(30 * time.Minute)
|
||||
startTime := startAt.Format(time.RFC3339)
|
||||
endTime := endAt.Format(time.RFC3339)
|
||||
|
||||
var calendarID string
|
||||
var eventID string
|
||||
|
||||
t.Run("get primary calendar as user", func(t *testing.T) {
|
||||
result, err := clie2e.RunCmd(ctx, clie2e.Request{
|
||||
Args: []string{"calendar", "calendars", "primary"},
|
||||
DefaultAs: "user",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
result.AssertExitCode(t, 0)
|
||||
result.AssertStdoutStatus(t, true)
|
||||
|
||||
calendarID = gjson.Get(result.Stdout, "data.calendars.0.calendar.calendar_id").String()
|
||||
require.NotEmpty(t, calendarID, "stdout:\n%s", result.Stdout)
|
||||
})
|
||||
|
||||
t.Run("create personal event with shortcut as user", func(t *testing.T) {
|
||||
require.NotEmpty(t, calendarID, "calendar should be loaded before creating an event")
|
||||
|
||||
result, err := clie2e.RunCmd(ctx, clie2e.Request{
|
||||
Args: []string{
|
||||
"calendar", "+create",
|
||||
"--summary", eventSummary,
|
||||
"--start", startTime,
|
||||
"--end", endTime,
|
||||
"--calendar-id", calendarID,
|
||||
"--description", eventDescription,
|
||||
},
|
||||
DefaultAs: "user",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
result.AssertExitCode(t, 0)
|
||||
result.AssertStdoutStatus(t, true)
|
||||
|
||||
eventID = gjson.Get(result.Stdout, "data.event_id").String()
|
||||
require.NotEmpty(t, eventID, "stdout:\n%s", result.Stdout)
|
||||
|
||||
parentT.Cleanup(func() {
|
||||
cleanupCtx, cancel := clie2e.CleanupContext()
|
||||
defer cancel()
|
||||
|
||||
deleteResult, deleteErr := clie2e.RunCmd(cleanupCtx, clie2e.Request{
|
||||
Args: []string{"calendar", "events", "delete"},
|
||||
DefaultAs: "user",
|
||||
Params: map[string]any{
|
||||
"calendar_id": calendarID,
|
||||
"event_id": eventID,
|
||||
},
|
||||
})
|
||||
clie2e.ReportCleanupFailure(parentT, "delete event "+eventID, deleteResult, deleteErr)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("get created event as user", func(t *testing.T) {
|
||||
require.NotEmpty(t, calendarID, "calendar should be loaded before getting an event")
|
||||
require.NotEmpty(t, eventID, "event should be created before reading it back")
|
||||
|
||||
result, err := clie2e.RunCmd(ctx, clie2e.Request{
|
||||
Args: []string{"calendar", "events", "get"},
|
||||
DefaultAs: "user",
|
||||
Params: map[string]any{
|
||||
"calendar_id": calendarID,
|
||||
"event_id": eventID,
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
result.AssertExitCode(t, 0)
|
||||
result.AssertStdoutStatus(t, true)
|
||||
|
||||
assert.Equal(t, eventID, gjson.Get(result.Stdout, "data.event.event_id").String())
|
||||
assert.Equal(t, eventSummary, gjson.Get(result.Stdout, "data.event.summary").String())
|
||||
assert.Equal(t, eventDescription, gjson.Get(result.Stdout, "data.event.description").String())
|
||||
assert.Equal(t, unixSecondsRFC3339(startAt), gjson.Get(result.Stdout, "data.event.start_time.timestamp").String())
|
||||
assert.Equal(t, unixSecondsRFC3339(endAt), gjson.Get(result.Stdout, "data.event.end_time.timestamp").String())
|
||||
})
|
||||
|
||||
t.Run("find created event in agenda as user", func(t *testing.T) {
|
||||
require.NotEmpty(t, eventID, "event should be created before checking agenda")
|
||||
|
||||
result, err := clie2e.RunCmd(ctx, clie2e.Request{
|
||||
Args: []string{
|
||||
"calendar", "+agenda",
|
||||
"--start", startTime,
|
||||
"--end", endTime,
|
||||
},
|
||||
DefaultAs: "user",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
result.AssertExitCode(t, 0)
|
||||
result.AssertStdoutStatus(t, true)
|
||||
|
||||
matchedEvent := gjson.Get(result.Stdout, `data.#(event_id=="`+eventID+`")`)
|
||||
require.True(t, matchedEvent.Exists(), "stdout:\n%s", result.Stdout)
|
||||
assert.Equal(t, eventSummary, matchedEvent.Get("summary").String())
|
||||
|
||||
agendaStart, parseErr := time.Parse(time.RFC3339, matchedEvent.Get("start_time.datetime").String())
|
||||
require.NoError(t, parseErr, "stdout:\n%s", result.Stdout)
|
||||
agendaEnd, parseErr := time.Parse(time.RFC3339, matchedEvent.Get("end_time.datetime").String())
|
||||
require.NoError(t, parseErr, "stdout:\n%s", result.Stdout)
|
||||
assert.True(t, agendaStart.Equal(startAt), "stdout:\n%s", result.Stdout)
|
||||
assert.True(t, agendaEnd.Equal(endAt), "stdout:\n%s", result.Stdout)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
// Copyright (c) 2026 Lark Technologies Pte. Ltd.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package calendar
|
||||
|
||||
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 requireFreebusyEntry(t *testing.T, stdout string, startAt time.Time, endAt time.Time, expectedRSVP string) {
|
||||
t.Helper()
|
||||
|
||||
var matched gjson.Result
|
||||
for _, item := range gjson.Parse(stdout).Get("data").Array() {
|
||||
itemStart, err := time.Parse(time.RFC3339, item.Get("start_time").String())
|
||||
require.NoError(t, err, "stdout:\n%s", stdout)
|
||||
itemEnd, err := time.Parse(time.RFC3339, item.Get("end_time").String())
|
||||
require.NoError(t, err, "stdout:\n%s", stdout)
|
||||
|
||||
if !itemStart.Equal(startAt) || !itemEnd.Equal(endAt) {
|
||||
continue
|
||||
}
|
||||
if item.Get("rsvp_status").String() != expectedRSVP {
|
||||
continue
|
||||
}
|
||||
matched = item
|
||||
break
|
||||
}
|
||||
|
||||
require.True(t, matched.Exists(), "expected freebusy entry start=%s end=%s rsvp=%s in stdout:\n%s", startAt.Format(time.RFC3339), endAt.Format(time.RFC3339), expectedRSVP, stdout)
|
||||
assert.Equal(t, expectedRSVP, matched.Get("rsvp_status").String(), "stdout:\n%s", stdout)
|
||||
}
|
||||
|
||||
func TestCalendar_RSVPWorkflowAsUser(t *testing.T) {
|
||||
parentT := t
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
|
||||
t.Cleanup(cancel)
|
||||
|
||||
clie2e.SkipWithoutUserToken(t)
|
||||
|
||||
userOpenID := getCurrentUserOpenIDForCalendar(t, ctx)
|
||||
calendarID := getPrimaryCalendarID(t, ctx)
|
||||
startAt := time.Now().UTC().Add(2 * time.Hour).Truncate(time.Minute)
|
||||
endAt := startAt.Add(30 * time.Minute)
|
||||
startTime := startAt.Format(time.RFC3339)
|
||||
endTime := endAt.Format(time.RFC3339)
|
||||
var eventID string
|
||||
|
||||
t.Run("query freebusy as user", func(t *testing.T) {
|
||||
result, err := clie2e.RunCmd(ctx, clie2e.Request{
|
||||
Args: []string{
|
||||
"calendar", "+freebusy",
|
||||
"--start", startTime,
|
||||
"--end", endTime,
|
||||
},
|
||||
DefaultAs: "user",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
result.AssertExitCode(t, 0)
|
||||
result.AssertStdoutStatus(t, true)
|
||||
data := gjson.Get(result.Stdout, "data")
|
||||
require.True(t, data.IsArray() || data.Type == gjson.Null, "stdout:\n%s", result.Stdout)
|
||||
})
|
||||
|
||||
t.Run("create invite-only event as bot", func(t *testing.T) {
|
||||
result, err := clie2e.RunCmd(ctx, clie2e.Request{
|
||||
Args: []string{
|
||||
"calendar", "+create",
|
||||
"--summary", "lark-cli-e2e-calendar-rsvp-" + clie2e.GenerateSuffix(),
|
||||
"--start", startTime,
|
||||
"--end", endTime,
|
||||
"--calendar-id", calendarID,
|
||||
"--attendee-ids", userOpenID,
|
||||
},
|
||||
DefaultAs: "bot",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
result.AssertExitCode(t, 0)
|
||||
result.AssertStdoutStatus(t, true)
|
||||
|
||||
eventID = gjson.Get(result.Stdout, "data.event_id").String()
|
||||
require.NotEmpty(t, eventID, "stdout:\n%s", result.Stdout)
|
||||
|
||||
parentT.Cleanup(func() {
|
||||
cleanupCtx, cancel := clie2e.CleanupContext()
|
||||
defer cancel()
|
||||
|
||||
deleteResult, deleteErr := clie2e.RunCmd(cleanupCtx, clie2e.Request{
|
||||
Args: []string{"calendar", "events", "delete"},
|
||||
DefaultAs: "bot",
|
||||
Params: map[string]any{
|
||||
"calendar_id": calendarID,
|
||||
"event_id": eventID,
|
||||
},
|
||||
})
|
||||
clie2e.ReportCleanupFailure(parentT, "delete event "+eventID, deleteResult, deleteErr)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("reply tentative as user", func(t *testing.T) {
|
||||
require.NotEmpty(t, eventID, "event should be created before RSVP")
|
||||
|
||||
result, err := clie2e.RunCmd(ctx, clie2e.Request{
|
||||
Args: []string{
|
||||
"calendar", "+rsvp",
|
||||
"--calendar-id", calendarID,
|
||||
"--event-id", eventID,
|
||||
"--rsvp-status", "tentative",
|
||||
},
|
||||
DefaultAs: "user",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
result.AssertExitCode(t, 0)
|
||||
result.AssertStdoutStatus(t, true)
|
||||
require.Equal(t, calendarID, gjson.Get(result.Stdout, "data.calendar_id").String(), "stdout:\n%s", result.Stdout)
|
||||
require.Equal(t, eventID, gjson.Get(result.Stdout, "data.event_id").String(), "stdout:\n%s", result.Stdout)
|
||||
require.Equal(t, "tentative", gjson.Get(result.Stdout, "data.rsvp_status").String())
|
||||
})
|
||||
|
||||
t.Run("verify tentative freebusy as user", func(t *testing.T) {
|
||||
result, err := clie2e.RunCmdWithRetry(ctx, clie2e.Request{
|
||||
Args: []string{
|
||||
"calendar", "+freebusy",
|
||||
"--start", startTime,
|
||||
"--end", endTime,
|
||||
},
|
||||
DefaultAs: "user",
|
||||
}, clie2e.RetryOptions{
|
||||
ShouldRetry: func(result *clie2e.Result) bool {
|
||||
if result == nil || result.ExitCode != 0 || !gjson.Get(result.Stdout, "status").Bool() {
|
||||
return true
|
||||
}
|
||||
for _, item := range gjson.Parse(result.Stdout).Get("data").Array() {
|
||||
itemStart, err := time.Parse(time.RFC3339, item.Get("start_time").String())
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
itemEnd, err := time.Parse(time.RFC3339, item.Get("end_time").String())
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
if itemStart.Equal(startAt) && itemEnd.Equal(endAt) && item.Get("rsvp_status").String() == "tentative" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
result.AssertExitCode(t, 0)
|
||||
result.AssertStdoutStatus(t, true)
|
||||
requireFreebusyEntry(t, result.Stdout, startAt, endAt, "tentative")
|
||||
})
|
||||
|
||||
t.Run("reply accept as user", func(t *testing.T) {
|
||||
result, err := clie2e.RunCmd(ctx, clie2e.Request{
|
||||
Args: []string{
|
||||
"calendar", "+rsvp",
|
||||
"--calendar-id", calendarID,
|
||||
"--event-id", eventID,
|
||||
"--rsvp-status", "accept",
|
||||
},
|
||||
DefaultAs: "user",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
result.AssertExitCode(t, 0)
|
||||
result.AssertStdoutStatus(t, true)
|
||||
require.Equal(t, calendarID, gjson.Get(result.Stdout, "data.calendar_id").String(), "stdout:\n%s", result.Stdout)
|
||||
require.Equal(t, eventID, gjson.Get(result.Stdout, "data.event_id").String(), "stdout:\n%s", result.Stdout)
|
||||
require.Equal(t, "accept", gjson.Get(result.Stdout, "data.rsvp_status").String())
|
||||
})
|
||||
|
||||
t.Run("verify accepted freebusy as user", func(t *testing.T) {
|
||||
result, err := clie2e.RunCmdWithRetry(ctx, clie2e.Request{
|
||||
Args: []string{
|
||||
"calendar", "+freebusy",
|
||||
"--start", startTime,
|
||||
"--end", endTime,
|
||||
},
|
||||
DefaultAs: "user",
|
||||
}, clie2e.RetryOptions{
|
||||
ShouldRetry: func(result *clie2e.Result) bool {
|
||||
if result == nil || result.ExitCode != 0 || !gjson.Get(result.Stdout, "status").Bool() {
|
||||
return true
|
||||
}
|
||||
for _, item := range gjson.Parse(result.Stdout).Get("data").Array() {
|
||||
itemStart, err := time.Parse(time.RFC3339, item.Get("start_time").String())
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
itemEnd, err := time.Parse(time.RFC3339, item.Get("end_time").String())
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
if itemStart.Equal(startAt) && itemEnd.Equal(endAt) && item.Get("rsvp_status").String() == "accept" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
result.AssertExitCode(t, 0)
|
||||
result.AssertStdoutStatus(t, true)
|
||||
requireFreebusyEntry(t, result.Stdout, startAt, endAt, "accept")
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
// Copyright (c) 2026 Lark Technologies Pte. Ltd.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package calendar
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
clie2e "github.com/larksuite/cli/tests/cli_e2e"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
func TestCalendar_UpdateDryRun(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")
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
t.Cleanup(cancel)
|
||||
|
||||
result, err := clie2e.RunCmd(ctx, clie2e.Request{
|
||||
Args: []string{
|
||||
"calendar", "+update",
|
||||
"--calendar-id", "cal_dry",
|
||||
"--event-id", "evt_dry",
|
||||
"--summary", "updated dry-run",
|
||||
"--start", "2026-04-25T10:00:00+08:00",
|
||||
"--end", "2026-04-25T11:00:00+08:00",
|
||||
"--remove-attendee-ids", "ou_old,omm_oldroom",
|
||||
"--add-attendee-ids", "ou_new,oc_group,omm_newroom",
|
||||
"--notify=false",
|
||||
"--dry-run",
|
||||
},
|
||||
DefaultAs: "bot",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
result.AssertExitCode(t, 0)
|
||||
|
||||
out := result.Stdout
|
||||
require.Equal(t, "PATCH", gjson.Get(out, "api.0.method").String(), "stdout:\n%s", out)
|
||||
require.Equal(t, "/open-apis/calendar/v4/calendars/cal_dry/events/evt_dry", gjson.Get(out, "api.0.url").String(), "stdout:\n%s", out)
|
||||
require.Equal(t, "updated dry-run", gjson.Get(out, "api.0.body.summary").String(), "stdout:\n%s", out)
|
||||
require.False(t, gjson.Get(out, "api.0.body.need_notification").Bool(), "stdout:\n%s", out)
|
||||
|
||||
require.Equal(t, "POST", gjson.Get(out, "api.1.method").String(), "stdout:\n%s", out)
|
||||
require.Equal(t, "/open-apis/calendar/v4/calendars/cal_dry/events/evt_dry/attendees/batch_delete", gjson.Get(out, "api.1.url").String(), "stdout:\n%s", out)
|
||||
require.Equal(t, "ou_old", gjson.Get(out, `api.1.body.delete_ids.#(type=="user").user_id`).String(), "stdout:\n%s", out)
|
||||
require.Equal(t, "omm_oldroom", gjson.Get(out, `api.1.body.delete_ids.#(type=="resource").room_id`).String(), "stdout:\n%s", out)
|
||||
|
||||
require.Equal(t, "POST", gjson.Get(out, "api.2.method").String(), "stdout:\n%s", out)
|
||||
require.Equal(t, "/open-apis/calendar/v4/calendars/cal_dry/events/evt_dry/attendees", gjson.Get(out, "api.2.url").String(), "stdout:\n%s", out)
|
||||
require.Equal(t, "ou_new", gjson.Get(out, `api.2.body.attendees.#(type=="user").user_id`).String(), "stdout:\n%s", out)
|
||||
require.Equal(t, "oc_group", gjson.Get(out, `api.2.body.attendees.#(type=="chat").chat_id`).String(), "stdout:\n%s", out)
|
||||
require.Equal(t, "omm_newroom", gjson.Get(out, `api.2.body.attendees.#(type=="resource").room_id`).String(), "stdout:\n%s", out)
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
// Copyright (c) 2026 Lark Technologies Pte. Ltd.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package calendar
|
||||
|
||||
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 TestCalendar_UpdateEventWorkflow(t *testing.T) {
|
||||
parentT := t
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
|
||||
t.Cleanup(cancel)
|
||||
|
||||
clie2e.SkipWithoutUserToken(t)
|
||||
|
||||
suffix := clie2e.GenerateSuffix()
|
||||
calendarID := getPrimaryCalendarID(t, ctx)
|
||||
userOpenID := getCurrentUserOpenIDForCalendar(t, ctx)
|
||||
|
||||
startAt := time.Now().UTC().Add(2 * time.Hour).Truncate(time.Minute)
|
||||
endAt := startAt.Add(30 * time.Minute)
|
||||
updatedStartAt := startAt.Add(30 * time.Minute)
|
||||
updatedEndAt := updatedStartAt.Add(45 * time.Minute)
|
||||
|
||||
createdSummary := "lark-cli-e2e-update-before-" + suffix
|
||||
updatedSummary := "lark-cli-e2e-update-after-" + suffix
|
||||
updatedDescription := "updated by calendar update workflow"
|
||||
|
||||
var eventID string
|
||||
var deletedEvent bool
|
||||
|
||||
t.Run("create event as bot", func(t *testing.T) {
|
||||
result, err := clie2e.RunCmd(ctx, clie2e.Request{
|
||||
Args: []string{"calendar", "+create",
|
||||
"--summary", createdSummary,
|
||||
"--start", startAt.Format(time.RFC3339),
|
||||
"--end", endAt.Format(time.RFC3339),
|
||||
"--calendar-id", calendarID,
|
||||
},
|
||||
DefaultAs: "bot",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
result.AssertExitCode(t, 0)
|
||||
result.AssertStdoutStatus(t, true)
|
||||
|
||||
eventID = gjson.Get(result.Stdout, "data.event_id").String()
|
||||
require.NotEmpty(t, eventID, "stdout:\n%s", result.Stdout)
|
||||
|
||||
parentT.Cleanup(func() {
|
||||
if eventID == "" || deletedEvent {
|
||||
return
|
||||
}
|
||||
cleanupCtx, cleanupCancel := clie2e.CleanupContext()
|
||||
defer cleanupCancel()
|
||||
|
||||
deleteResult, deleteErr := clie2e.RunCmd(cleanupCtx, clie2e.Request{
|
||||
Args: []string{"calendar", "events", "delete"},
|
||||
DefaultAs: "bot",
|
||||
Params: map[string]any{
|
||||
"calendar_id": calendarID,
|
||||
"event_id": eventID,
|
||||
},
|
||||
})
|
||||
clie2e.ReportCleanupFailure(parentT, "delete event "+eventID, deleteResult, deleteErr)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("update event and add attendee as bot", func(t *testing.T) {
|
||||
require.NotEmpty(t, eventID)
|
||||
require.NotEmpty(t, userOpenID)
|
||||
|
||||
result, err := clie2e.RunCmd(ctx, clie2e.Request{
|
||||
Args: []string{"calendar", "+update",
|
||||
"--event-id", eventID,
|
||||
"--calendar-id", calendarID,
|
||||
"--summary", updatedSummary,
|
||||
"--description", updatedDescription,
|
||||
"--start", updatedStartAt.Format(time.RFC3339),
|
||||
"--end", updatedEndAt.Format(time.RFC3339),
|
||||
"--add-attendee-ids", userOpenID,
|
||||
"--notify=false",
|
||||
},
|
||||
DefaultAs: "bot",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
result.AssertExitCode(t, 0)
|
||||
result.AssertStdoutStatus(t, true)
|
||||
assert.Equal(t, eventID, gjson.Get(result.Stdout, "data.event_id").String())
|
||||
})
|
||||
|
||||
t.Run("verify updated event as bot", func(t *testing.T) {
|
||||
require.NotEmpty(t, eventID)
|
||||
|
||||
result, err := clie2e.RunCmd(ctx, clie2e.Request{
|
||||
Args: []string{"calendar", "events", "get"},
|
||||
DefaultAs: "bot",
|
||||
Params: map[string]any{
|
||||
"calendar_id": calendarID,
|
||||
"event_id": eventID,
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
result.AssertExitCode(t, 0)
|
||||
result.AssertStdoutStatus(t, true)
|
||||
assert.Equal(t, updatedSummary, gjson.Get(result.Stdout, "data.event.summary").String())
|
||||
assert.Equal(t, updatedDescription, gjson.Get(result.Stdout, "data.event.description").String())
|
||||
assert.Equal(t, unixSecondsRFC3339(updatedStartAt), gjson.Get(result.Stdout, "data.event.start_time.timestamp").String())
|
||||
assert.Equal(t, unixSecondsRFC3339(updatedEndAt), gjson.Get(result.Stdout, "data.event.end_time.timestamp").String())
|
||||
})
|
||||
|
||||
t.Run("delete event as bot", func(t *testing.T) {
|
||||
require.NotEmpty(t, eventID)
|
||||
result, err := clie2e.RunCmd(ctx, clie2e.Request{
|
||||
Args: []string{"calendar", "events", "delete"},
|
||||
DefaultAs: "bot",
|
||||
Params: map[string]any{
|
||||
"calendar_id": calendarID,
|
||||
"event_id": eventID,
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
result.AssertExitCode(t, 0)
|
||||
result.AssertStdoutStatus(t, true)
|
||||
deletedEvent = true
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
// Copyright (c) 2026 Lark Technologies Pte. Ltd.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package calendar
|
||||
|
||||
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 TestCalendar_ViewAgenda(t *testing.T) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
|
||||
t.Cleanup(cancel)
|
||||
|
||||
clie2e.SkipWithoutUserToken(t)
|
||||
calendarID := getCurrentUserPrimaryCalendarID(t, ctx)
|
||||
|
||||
t.Run("view today agenda as user", func(t *testing.T) {
|
||||
result, err := clie2e.RunCmd(ctx, clie2e.Request{
|
||||
Args: []string{"calendar", "+agenda", "--calendar-id", calendarID},
|
||||
DefaultAs: "user",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
result.AssertExitCode(t, 0)
|
||||
result.AssertStdoutStatus(t, true)
|
||||
assert.True(t, gjson.Get(result.Stdout, "data").IsArray(), "stdout:\n%s", result.Stdout)
|
||||
})
|
||||
|
||||
t.Run("view agenda with date range as user", func(t *testing.T) {
|
||||
startDate := time.Now().UTC().Format("2006-01-02")
|
||||
endDate := time.Now().UTC().AddDate(0, 0, 7).Format("2006-01-02")
|
||||
result, err := clie2e.RunCmd(ctx, clie2e.Request{
|
||||
Args: []string{"calendar", "+agenda", "--calendar-id", calendarID, "--start", startDate, "--end", endDate},
|
||||
DefaultAs: "user",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
result.AssertExitCode(t, 0)
|
||||
result.AssertStdoutStatus(t, true)
|
||||
assert.True(t, gjson.Get(result.Stdout, "data").IsArray(), "stdout:\n%s", result.Stdout)
|
||||
})
|
||||
|
||||
t.Run("view agenda with pretty format as user", func(t *testing.T) {
|
||||
result, err := clie2e.RunCmd(ctx, clie2e.Request{
|
||||
Args: []string{"calendar", "+agenda"},
|
||||
DefaultAs: "user",
|
||||
Format: "pretty",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
result.AssertExitCode(t, 0)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
# Calendar CLI E2E Coverage
|
||||
|
||||
## Metrics
|
||||
- Denominator: 23 leaf commands
|
||||
- Covered: 11
|
||||
- Coverage: 47.8%
|
||||
|
||||
## Summary
|
||||
- TestCalendar_ViewAgenda: proves the user shortcut `calendar +agenda`; key `t.Run(...)` proof points are `view today agenda as user`, `view agenda with date range as user`, and `view agenda with pretty format as user`.
|
||||
- TestCalendar_PersonalEventWorkflowAsUser: proves a self-contained user event workflow across `calendar calendars primary`, `calendar +create`, `calendar events get`, and `calendar +agenda`; key `t.Run(...)` proof points are `get primary calendar as user`, `create personal event with shortcut as user`, `get created event as user`, and `find created event in agenda as user`.
|
||||
- TestCalendar_RSVPWorkflowAsUser: proves the user shortcuts `calendar +freebusy` and `calendar +rsvp`; key `t.Run(...)` proof points are `query freebusy as user`, `reply tentative as user`, `verify tentative freebusy as user`, `reply accept as user`, and `verify accepted freebusy as user`.
|
||||
- TestCalendar_CreateEvent: proves `calendar +create`, `calendar events get`, and `calendar events delete`; key `t.Run(...)` proof points are `create event with shortcut as bot`, `verify event created as bot`, and `delete event as bot`.
|
||||
- TestCalendar_ManageCalendar: proves `calendar calendars primary`, `calendar calendars create`, `calendar calendars get`, and `calendar calendars patch`; key `t.Run(...)` proof points are `get primary calendar as bot`, `create calendar as bot`, `get created calendar as bot`, and `update calendar as bot`.
|
||||
- Cleanup note: `calendar calendars delete` is part of the calendar lifecycle workflow and is counted as covered because the workflow proves the full shared-calendar lifecycle.
|
||||
- Blocked area: direct `event.attendees *` APIs, `calendar calendars search`, `calendar events create|instance_view|patch|search`, `calendar freebusys list`, and planning shortcuts `calendar +room-find` / `calendar +suggestion` still need deterministic workflows; the planning shortcuts currently depend on live tenant availability and room inventory, so they remain uncovered.
|
||||
|
||||
## Command Table
|
||||
|
||||
| Status | Cmd | Type | Testcase | Key parameter shapes | Notes / uncovered reason |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| ✓ | calendar +agenda | shortcut | calendar_view_agenda_test.go::TestCalendar_ViewAgenda; calendar_personal_event_workflow_test.go::TestCalendar_PersonalEventWorkflowAsUser/find created event in agenda as user | default today; `--start`; `--end`; `--format pretty` | user identity readback plus general agenda view |
|
||||
| ✓ | calendar +create | shortcut | calendar_create_event_test.go::TestCalendar_CreateEvent/create event with shortcut as bot; calendar_personal_event_workflow_test.go::TestCalendar_PersonalEventWorkflowAsUser/create personal event with shortcut as user | `--summary`; `--start`; `--end`; `--calendar-id`; `--description` | bot and user workflow coverage |
|
||||
| ✓ | calendar +freebusy | shortcut | calendar_rsvp_workflow_test.go::TestCalendar_RSVPWorkflowAsUser/query freebusy as user; calendar_rsvp_workflow_test.go::TestCalendar_RSVPWorkflowAsUser/verify tentative freebusy as user; calendar_rsvp_workflow_test.go::TestCalendar_RSVPWorkflowAsUser/verify accepted freebusy as user | default current user; `--start`; `--end` | user identity flow |
|
||||
| ✕ | calendar +room-find | shortcut | | none | no deterministic self-contained workflow yet; output depends on live room inventory |
|
||||
| ✓ | calendar +rsvp | shortcut | calendar_rsvp_workflow_test.go::TestCalendar_RSVPWorkflowAsUser/reply tentative as user; calendar_rsvp_workflow_test.go::TestCalendar_RSVPWorkflowAsUser/reply accept as user | `--calendar-id`; `--event-id`; `--rsvp-status` | user reply flow |
|
||||
| ✕ | calendar +suggestion | shortcut | | none | no deterministic self-contained workflow yet; output depends on live availability suggestions |
|
||||
| ✓ | calendar calendars create | api | calendar_manage_calendar_test.go::TestCalendar_ManageCalendar/create calendar as bot | `summary`; `description` in `--data` | |
|
||||
| ✓ | calendar calendars delete | api | calendar_manage_calendar_test.go::TestCalendar_ManageCalendar/delete calendar as bot | `calendar_id` in `--params` | |
|
||||
| ✓ | calendar calendars get | api | calendar_manage_calendar_test.go::TestCalendar_ManageCalendar/get created calendar as bot; calendar_manage_calendar_test.go::TestCalendar_ManageCalendar/verify updated calendar as bot | `calendar_id` in `--params` | |
|
||||
| ✕ | calendar calendars list | api | | none | removed from the live workflow because tenant history made list latency non-deterministic |
|
||||
| ✓ | calendar calendars patch | api | calendar_manage_calendar_test.go::TestCalendar_ManageCalendar/update calendar as bot | `calendar_id` in `--params`; `summary` in `--data` | |
|
||||
| ✓ | calendar calendars primary | api | calendar_manage_calendar_test.go::TestCalendar_ManageCalendar/get primary calendar as bot; calendar_personal_event_workflow_test.go::TestCalendar_PersonalEventWorkflowAsUser/get primary calendar as user | none | bot and user primary calendar lookup |
|
||||
| ✕ | calendar calendars search | api | | none | no search workflow yet |
|
||||
| ✕ | calendar events create | api | | none | only covered indirectly through `calendar +create` |
|
||||
| ✓ | calendar events delete | api | calendar_create_event_test.go::TestCalendar_CreateEvent/delete event as bot | `calendar_id`; `event_id` in `--params` | |
|
||||
| ✓ | calendar events get | api | calendar_create_event_test.go::TestCalendar_CreateEvent/verify event created as bot; calendar_personal_event_workflow_test.go::TestCalendar_PersonalEventWorkflowAsUser/get created event as user | `calendar_id`; `event_id` in `--params` | bot and user read-after-write coverage |
|
||||
| ✕ | calendar events instance_view | api | | none | `+agenda` is indirect orchestration, not direct API coverage |
|
||||
| ✕ | calendar events patch | api | | none | no direct event-update workflow yet |
|
||||
| ✕ | calendar events search | api | | none | no search workflow yet |
|
||||
| ✕ | calendar freebusys list | api | | none | no direct freebusy API workflow yet |
|
||||
| ✕ | calendar event.attendees batch_delete | api | | none | requires an isolated attendee lifecycle workflow |
|
||||
| ✕ | calendar event.attendees create | api | | none | requires an isolated attendee lifecycle workflow |
|
||||
| ✕ | calendar event.attendees list | api | | none | requires an isolated attendee lifecycle workflow |
|
||||
@@ -0,0 +1,67 @@
|
||||
// Copyright (c) 2026 Lark Technologies Pte. Ltd.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package calendar
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
clie2e "github.com/larksuite/cli/tests/cli_e2e"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
func getPrimaryCalendarID(t *testing.T, ctx context.Context) string {
|
||||
t.Helper()
|
||||
|
||||
result, err := clie2e.RunCmd(ctx, clie2e.Request{
|
||||
Args: []string{"calendar", "calendars", "primary"},
|
||||
DefaultAs: "bot",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
result.AssertExitCode(t, 0)
|
||||
result.AssertStdoutStatus(t, true)
|
||||
|
||||
calendarID := gjson.Get(result.Stdout, "data.calendars.0.calendar.calendar_id").String()
|
||||
require.NotEmpty(t, calendarID, "stdout:\n%s", result.Stdout)
|
||||
return calendarID
|
||||
}
|
||||
|
||||
func getCurrentUserPrimaryCalendarID(t *testing.T, ctx context.Context) string {
|
||||
t.Helper()
|
||||
|
||||
result, err := clie2e.RunCmd(ctx, clie2e.Request{
|
||||
Args: []string{"calendar", "calendars", "primary"},
|
||||
DefaultAs: "user",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
result.AssertExitCode(t, 0)
|
||||
result.AssertStdoutStatus(t, true)
|
||||
|
||||
calendarID := gjson.Get(result.Stdout, "data.calendars.0.calendar.calendar_id").String()
|
||||
require.NotEmpty(t, calendarID, "stdout:\n%s", result.Stdout)
|
||||
return calendarID
|
||||
}
|
||||
|
||||
func getCurrentUserOpenIDForCalendar(t *testing.T, ctx context.Context) string {
|
||||
t.Helper()
|
||||
|
||||
result, err := clie2e.RunCmd(ctx, clie2e.Request{
|
||||
Args: []string{"contact", "+get-user"},
|
||||
DefaultAs: "user",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
result.AssertExitCode(t, 0)
|
||||
result.AssertStdoutStatus(t, true)
|
||||
|
||||
openID := gjson.Get(result.Stdout, "data.user.open_id").String()
|
||||
require.NotEmpty(t, openID, "stdout:\n%s", result.Stdout)
|
||||
return openID
|
||||
}
|
||||
|
||||
func unixSecondsRFC3339(t time.Time) string {
|
||||
return strconv.FormatInt(t.Unix(), 10)
|
||||
}
|
||||
Reference in New Issue
Block a user