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
112 lines
3.4 KiB
Go
112 lines
3.4 KiB
Go
// Copyright (c) 2026 Lark Technologies Pte. Ltd.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package slides
|
|
|
|
import (
|
|
"errors"
|
|
"testing"
|
|
|
|
"github.com/larksuite/cli/errs"
|
|
"github.com/larksuite/cli/extension/fileio"
|
|
)
|
|
|
|
// TestSlidesInputStatError verifies the shared stat-error helper tags the
|
|
// offending flag via the typed Param — so callers route on the structured
|
|
// field rather than parsing the message — and always classifies as a
|
|
// validation error while preserving the underlying cause.
|
|
func TestSlidesInputStatError(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
if err := slidesInputStatError(nil, "--slides", "ctx"); err != nil {
|
|
t.Fatalf("nil input should return nil, got %v", err)
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
in error
|
|
}{
|
|
{"path validation", fileio.ErrPathValidation},
|
|
{"generic stat error", errors.New("permission denied")},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
err := slidesInputStatError(tt.in, "--file", "file not found")
|
|
|
|
var ve *errs.ValidationError
|
|
if !errors.As(err, &ve) {
|
|
t.Fatalf("err = %v, want *errs.ValidationError", err)
|
|
}
|
|
if ve.Param != "--file" {
|
|
t.Fatalf("Param = %q, want --file", ve.Param)
|
|
}
|
|
if !errors.Is(err, tt.in) {
|
|
t.Fatalf("err must wrap the underlying cause %v", tt.in)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestAppendSlidesProgressHint covers both branches of the orchestration-hint
|
|
// helper: a typed error keeps its classification and gains (or extends) the
|
|
// progress hint, while an unclassified error surfaced from a shared-helper
|
|
// boundary falls back to a typed internal error that still carries the hint
|
|
// and the original cause.
|
|
func TestAppendSlidesProgressHint(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
if err := appendSlidesProgressHint(nil, "hint"); err != nil {
|
|
t.Fatalf("nil input should return nil, got %v", err)
|
|
}
|
|
|
|
t.Run("typed error preserves classification and sets hint", func(t *testing.T) {
|
|
t.Parallel()
|
|
base := errs.NewValidationError(errs.SubtypeInvalidArgument, "bad input")
|
|
err := appendSlidesProgressHint(base, "2 image(s) uploaded before failure")
|
|
|
|
var ve *errs.ValidationError
|
|
if !errors.As(err, &ve) {
|
|
t.Fatalf("err = %v, want classification preserved as *errs.ValidationError", err)
|
|
}
|
|
p, _ := errs.ProblemOf(err)
|
|
if p.Hint != "2 image(s) uploaded before failure" {
|
|
t.Fatalf("Hint = %q, want the progress hint", p.Hint)
|
|
}
|
|
})
|
|
|
|
t.Run("typed error appends to an existing hint", func(t *testing.T) {
|
|
t.Parallel()
|
|
base := errs.NewValidationError(errs.SubtypeInvalidArgument, "bad input").WithHint("first")
|
|
err := appendSlidesProgressHint(base, "second")
|
|
|
|
p, _ := errs.ProblemOf(err)
|
|
if p.Hint != "first\nsecond" {
|
|
t.Fatalf("Hint = %q, want %q", p.Hint, "first\nsecond")
|
|
}
|
|
})
|
|
|
|
t.Run("unclassified error falls back to typed internal error", func(t *testing.T) {
|
|
t.Parallel()
|
|
cause := errors.New("raw boundary error")
|
|
err := appendSlidesProgressHint(cause, "presentation was created")
|
|
|
|
p, ok := errs.ProblemOf(err)
|
|
if !ok {
|
|
t.Fatalf("err = %v, want a typed errs.* error", err)
|
|
}
|
|
if p.Category != errs.CategoryInternal {
|
|
t.Fatalf("Category = %v, want CategoryInternal", p.Category)
|
|
}
|
|
if p.Subtype != errs.SubtypeUnknown {
|
|
t.Fatalf("Subtype = %v, want SubtypeUnknown", p.Subtype)
|
|
}
|
|
if p.Hint != "presentation was created" {
|
|
t.Fatalf("Hint = %q, want the progress hint", p.Hint)
|
|
}
|
|
if !errors.Is(err, cause) {
|
|
t.Fatalf("fallback must preserve the original cause via WithCause")
|
|
}
|
|
})
|
|
}
|