Files
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

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")
}
})
}