Files
larksuite--cli/shortcuts/common/runner_partial_failure_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

64 lines
2.1 KiB
Go

// Copyright (c) 2026 Lark Technologies Pte. Ltd.
// SPDX-License-Identifier: MIT
package common
import (
"context"
"encoding/json"
"errors"
"testing"
"github.com/spf13/cobra"
"github.com/larksuite/cli/internal/cmdutil"
"github.com/larksuite/cli/internal/core"
"github.com/larksuite/cli/internal/output"
)
// TestOutPartialFailure pins the batch / multi-status contract: the result
// rides on stdout as an ok:false envelope (carrying the full payload), and the
// returned error is the typed partial-failure exit signal (ExitAPI), distinct
// from ErrBare (the silent-exit signal).
func TestOutPartialFailure(t *testing.T) {
cfg := &core.CliConfig{Brand: core.BrandFeishu, AppID: "cli_x"}
f, stdout, _, _ := cmdutil.TestFactory(t, cfg)
rt := TestNewRuntimeContextForAPI(context.Background(), &cobra.Command{Use: "+push"}, cfg, f, core.AsUser)
payload := map[string]interface{}{
"summary": map[string]interface{}{"uploaded": 1, "failed": 1},
"items": []map[string]interface{}{
{"rel_path": "a.txt", "action": "uploaded"},
{"rel_path": "b.txt", "action": "failed", "error": "boom"},
},
}
err := rt.OutPartialFailure(payload, nil)
// 1) typed partial-failure exit signal
var pfErr *output.PartialFailureError
if !errors.As(err, &pfErr) {
t.Fatalf("expected *output.PartialFailureError, got %T: %v", err, err)
}
if pfErr.Code != output.ExitAPI {
t.Errorf("exit code = %d, want %d (ExitAPI)", pfErr.Code, output.ExitAPI)
}
// 2) stdout envelope reports ok:false but still carries the full payload
// (both the succeeded and failed items) — consistent with a success Out().
var env struct {
OK bool `json:"ok"`
Data map[string]interface{} `json:"data"`
}
if err := json.Unmarshal(stdout.Bytes(), &env); err != nil {
t.Fatalf("unmarshal stdout envelope: %v\nstdout: %s", err, stdout.String())
}
if env.OK {
t.Errorf("ok must be false on partial failure, got ok:true\nstdout: %s", stdout.String())
}
items, _ := env.Data["items"].([]interface{})
if len(items) != 2 {
t.Fatalf("both succeeded and failed items must ride on stdout, got %d items\nstdout: %s", len(items), stdout.String())
}
}