Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion shortcuts/doc/docs_update_check_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ func TestCheckDocsUpdateReplaceMultilineMarkdown(t *testing.T) {
t.Fatalf("checkDocsUpdateReplaceMultilineMarkdown(%q, %q) = %q, wantHint=%v",
tt.mode, tt.markdown, got, tt.wantHint)
}
if tt.wantHint && !strings.Contains(got, "delete_range") {
if tt.wantHint && (!strings.Contains(got, "delete_range") || !strings.Contains(got, "insert_before")) {
t.Errorf("hint should suggest delete_range/insert_before remediation, got: %s", got)
}
})
Expand Down
70 changes: 70 additions & 0 deletions tests/cli_e2e/docs/docs_update_dryrun_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright (c) 2026 Lark Technologies Pte. Ltd.
// SPDX-License-Identifier: MIT

package docs

import (
"context"
"strings"
"testing"
"time"

clie2e "github.com/larksuite/cli/tests/cli_e2e"
"github.com/stretchr/testify/require"
)

// TestDocs_UpdateDryRunSuppressesSemanticWarnings asserts the contract that
// docsUpdateWarnings is NOT invoked on the --dry-run path. The unit tests in
// shortcuts/doc/docs_update_check_test.go prove the helper emits warnings for
// replace_range + blank-line and for combined-emphasis markers; this E2E
// locks in that they never reach the user during dry-run planning, so a
// future refactor that moves warning emission into a shared code path can't
// silently regress.
//
// Input is intentionally crafted to trigger BOTH warnings the helper emits:
// - mode=replace_range + markdown containing "\n\n" (blank-line warning)
// - markdown containing `***combined***` (combined bold+italic warning)
//
// Neither string may appear in dry-run output.
func TestDocs_UpdateDryRunSuppressesSemanticWarnings(t *testing.T) {
// Fake creds are enough — dry-run short-circuits before any real API call.
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)

// "***combined***" is a triple-asterisk combined-emphasis shape; "\n\n"
// is a paragraph break. Both would normally produce warnings when
// Execute runs under --mode=replace_range; both must be absent here.
markdown := "***combined***\n\nsecond paragraph"

result, err := clie2e.RunCmd(ctx, clie2e.Request{
Args: []string{
"docs", "+update",
"--doc", "doxcnDryRunE2E",
"--mode", "replace_range",
"--selection-with-ellipsis", "placeholder",
"--markdown", markdown,
"--dry-run",
},
DefaultAs: "bot",
})
require.NoError(t, err)
result.AssertExitCode(t, 0)

// Neither warning prefix ("warning:") nor either specific warning body
// may appear in dry-run output (stdout OR stderr).
combined := result.Stdout + "\n" + result.Stderr
for _, needle := range []string{
"warning:",
"does not split a block into multiple paragraphs",
"combined bold+italic markers",
} {
if strings.Contains(combined, needle) {
t.Errorf("dry-run output must not surface pre-write warning %q\nstdout:\n%s\nstderr:\n%s",
needle, result.Stdout, result.Stderr)
}
}
}
Loading