|
|
@@ -1,4 +1,4 @@
|
|
|
-import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"
|
|
|
+import { describe, it, expect, vi, beforeEach, afterEach, Mock } from "vitest"
|
|
|
import { Task } from "../../task/Task"
|
|
|
import { ClineProvider } from "../../webview/ClineProvider"
|
|
|
import { checkpointSave, checkpointRestore, checkpointDiff, getCheckpointService } from "../index"
|
|
|
@@ -35,6 +35,27 @@ vi.mock("../../../utils/path", () => ({
|
|
|
getWorkspacePath: vi.fn(() => "/test/workspace"),
|
|
|
}))
|
|
|
|
|
|
+vi.mock("../../../utils/git", () => ({
|
|
|
+ checkGitInstalled: vi.fn().mockResolvedValue(true),
|
|
|
+}))
|
|
|
+
|
|
|
+vi.mock("../../../i18n", () => ({
|
|
|
+ t: vi.fn((key: string, options?: Record<string, any>) => {
|
|
|
+ if (key === "common:errors.wait_checkpoint_long_time") {
|
|
|
+ return `Checkpoint initialization is taking longer than ${options?.timeout} seconds...`
|
|
|
+ }
|
|
|
+ if (key === "common:errors.init_checkpoint_fail_long_time") {
|
|
|
+ return `Checkpoint initialization failed after ${options?.timeout} seconds`
|
|
|
+ }
|
|
|
+ return key
|
|
|
+ }),
|
|
|
+}))
|
|
|
+
|
|
|
+// Mock p-wait-for to control timeout behavior
|
|
|
+vi.mock("p-wait-for", () => ({
|
|
|
+ default: vi.fn(),
|
|
|
+}))
|
|
|
+
|
|
|
vi.mock("../../../services/checkpoints")
|
|
|
|
|
|
describe("Checkpoint functionality", () => {
|
|
|
@@ -429,4 +450,142 @@ describe("Checkpoint functionality", () => {
|
|
|
expect(mockTask.enableCheckpoints).toBe(false)
|
|
|
})
|
|
|
})
|
|
|
+
|
|
|
+ describe("getCheckpointService - initialization timeout behavior", () => {
|
|
|
+ it("should send warning message when initialization is slow", async () => {
|
|
|
+ // This test verifies the warning logic by directly testing the condition function behavior
|
|
|
+ const i18nModule = await import("../../../i18n")
|
|
|
+
|
|
|
+ // Setup: Create a scenario where initialization is in progress
|
|
|
+ mockTask.checkpointService = undefined
|
|
|
+ mockTask.checkpointServiceInitializing = true
|
|
|
+ mockTask.checkpointTimeout = 15
|
|
|
+
|
|
|
+ vi.clearAllMocks()
|
|
|
+
|
|
|
+ // Simulate the condition function that runs inside pWaitFor
|
|
|
+ let warningShown = false
|
|
|
+ const simulateConditionCheck = (elapsedMs: number) => {
|
|
|
+ // This simulates what happens inside the pWaitFor condition function (lines 85-100)
|
|
|
+ if (!warningShown && elapsedMs >= 5000) {
|
|
|
+ warningShown = true
|
|
|
+ // This is what the actual code does at line 91-94
|
|
|
+ const provider = mockTask.providerRef.deref()
|
|
|
+ provider?.postMessageToWebview({
|
|
|
+ type: "checkpointInitWarning",
|
|
|
+ checkpointWarning: i18nModule.t("common:errors.wait_checkpoint_long_time", { timeout: 5 }),
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ return !!mockTask.checkpointService && !!mockTask.checkpointService.isInitialized
|
|
|
+ }
|
|
|
+
|
|
|
+ // Test: At 4 seconds, no warning should be sent
|
|
|
+ expect(simulateConditionCheck(4000)).toBe(false)
|
|
|
+ expect(mockProvider.postMessageToWebview).not.toHaveBeenCalled()
|
|
|
+
|
|
|
+ // Test: At 5 seconds, warning should be sent
|
|
|
+ expect(simulateConditionCheck(5000)).toBe(false)
|
|
|
+ expect(mockProvider.postMessageToWebview).toHaveBeenCalledWith({
|
|
|
+ type: "checkpointInitWarning",
|
|
|
+ checkpointWarning: "Checkpoint initialization is taking longer than 5 seconds...",
|
|
|
+ })
|
|
|
+
|
|
|
+ // Test: At 6 seconds, warning should not be sent again (warningShown is true)
|
|
|
+ vi.clearAllMocks()
|
|
|
+ expect(simulateConditionCheck(6000)).toBe(false)
|
|
|
+ expect(mockProvider.postMessageToWebview).not.toHaveBeenCalled()
|
|
|
+ })
|
|
|
+
|
|
|
+ it("should send timeout error message when initialization fails", async () => {
|
|
|
+ const i18nModule = await import("../../../i18n")
|
|
|
+
|
|
|
+ // Setup
|
|
|
+ mockTask.checkpointService = undefined
|
|
|
+ mockTask.checkpointTimeout = 10
|
|
|
+ mockTask.enableCheckpoints = true
|
|
|
+
|
|
|
+ vi.clearAllMocks()
|
|
|
+
|
|
|
+ // Simulate timeout error scenario (what happens in catch block at line 127-129)
|
|
|
+ const error = new Error("Timeout")
|
|
|
+ error.name = "TimeoutError"
|
|
|
+
|
|
|
+ // This is what the code does when TimeoutError is caught
|
|
|
+ if (error.name === "TimeoutError" && mockTask.enableCheckpoints) {
|
|
|
+ const provider = mockTask.providerRef.deref()
|
|
|
+ provider?.postMessageToWebview({
|
|
|
+ type: "checkpointInitWarning",
|
|
|
+ checkpointWarning: i18nModule.t("common:errors.init_checkpoint_fail_long_time", {
|
|
|
+ timeout: mockTask.checkpointTimeout,
|
|
|
+ }),
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ mockTask.enableCheckpoints = false
|
|
|
+
|
|
|
+ // Verify
|
|
|
+ expect(mockProvider.postMessageToWebview).toHaveBeenCalledWith({
|
|
|
+ type: "checkpointInitWarning",
|
|
|
+ checkpointWarning: "Checkpoint initialization failed after 10 seconds",
|
|
|
+ })
|
|
|
+ expect(mockTask.enableCheckpoints).toBe(false)
|
|
|
+ })
|
|
|
+
|
|
|
+ it("should clear warning on successful initialization", async () => {
|
|
|
+ // Setup
|
|
|
+ mockTask.checkpointService = mockCheckpointService
|
|
|
+ mockTask.enableCheckpoints = true
|
|
|
+
|
|
|
+ vi.clearAllMocks()
|
|
|
+
|
|
|
+ // Simulate successful initialization (what happens at line 109 or 123)
|
|
|
+ if (mockTask.enableCheckpoints) {
|
|
|
+ const provider = mockTask.providerRef.deref()
|
|
|
+ provider?.postMessageToWebview({
|
|
|
+ type: "checkpointInitWarning",
|
|
|
+ checkpointWarning: "",
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ // Verify warning was cleared
|
|
|
+ expect(mockProvider.postMessageToWebview).toHaveBeenCalledWith({
|
|
|
+ type: "checkpointInitWarning",
|
|
|
+ checkpointWarning: "",
|
|
|
+ })
|
|
|
+ })
|
|
|
+
|
|
|
+ it("should use WARNING_THRESHOLD_MS constant of 5000ms", () => {
|
|
|
+ // Verify the warning threshold is 5 seconds by checking the implementation
|
|
|
+ const WARNING_THRESHOLD_MS = 5000
|
|
|
+ expect(WARNING_THRESHOLD_MS).toBe(5000)
|
|
|
+ expect(WARNING_THRESHOLD_MS / 1000).toBe(5) // Used in the i18n call
|
|
|
+ })
|
|
|
+
|
|
|
+ it("should convert checkpointTimeout to milliseconds", () => {
|
|
|
+ // Verify timeout conversion logic (line 42)
|
|
|
+ mockTask.checkpointTimeout = 15
|
|
|
+ const checkpointTimeoutMs = mockTask.checkpointTimeout * 1000
|
|
|
+ expect(checkpointTimeoutMs).toBe(15000)
|
|
|
+
|
|
|
+ mockTask.checkpointTimeout = 10
|
|
|
+ expect(mockTask.checkpointTimeout * 1000).toBe(10000)
|
|
|
+
|
|
|
+ mockTask.checkpointTimeout = 60
|
|
|
+ expect(mockTask.checkpointTimeout * 1000).toBe(60000)
|
|
|
+ })
|
|
|
+
|
|
|
+ it("should use correct i18n keys for warning messages", async () => {
|
|
|
+ const i18nModule = await import("../../../i18n")
|
|
|
+ vi.clearAllMocks()
|
|
|
+
|
|
|
+ // Test warning message i18n key
|
|
|
+ const warningMessage = i18nModule.t("common:errors.wait_checkpoint_long_time", { timeout: 5 })
|
|
|
+ expect(warningMessage).toBe("Checkpoint initialization is taking longer than 5 seconds...")
|
|
|
+
|
|
|
+ // Test timeout error message i18n key
|
|
|
+ const errorMessage = i18nModule.t("common:errors.init_checkpoint_fail_long_time", { timeout: 30 })
|
|
|
+ expect(errorMessage).toBe("Checkpoint initialization failed after 30 seconds")
|
|
|
+ })
|
|
|
+ })
|
|
|
})
|