webviewMessageHandler.checkpoint.spec.ts 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. import { describe, it, expect, vi, beforeEach } from "vitest"
  2. import { webviewMessageHandler } from "../webviewMessageHandler"
  3. import { saveTaskMessages } from "../../task-persistence"
  4. import { handleCheckpointRestoreOperation } from "../checkpointRestoreHandler"
  5. import { MessageManager } from "../../message-manager"
  6. // Mock dependencies
  7. vi.mock("../../task-persistence")
  8. vi.mock("../checkpointRestoreHandler")
  9. vi.mock("vscode", () => ({
  10. window: {
  11. showErrorMessage: vi.fn(),
  12. },
  13. workspace: {
  14. workspaceFolders: undefined,
  15. },
  16. }))
  17. describe("webviewMessageHandler - checkpoint operations", () => {
  18. let mockProvider: any
  19. let mockCline: any
  20. beforeEach(() => {
  21. vi.clearAllMocks()
  22. // Setup mock Cline instance
  23. mockCline = {
  24. taskId: "test-task-123",
  25. clineMessages: [
  26. { ts: 1, type: "user", say: "user", text: "First message" },
  27. { ts: 2, type: "assistant", say: "checkpoint_saved", text: "abc123" },
  28. { ts: 3, type: "user", say: "user", text: "Message to delete" },
  29. { ts: 4, type: "assistant", say: "assistant", text: "After message" },
  30. ],
  31. apiConversationHistory: [
  32. { ts: 1, role: "user", content: [{ type: "text", text: "First message" }] },
  33. { ts: 3, role: "user", content: [{ type: "text", text: "Message to delete" }] },
  34. { ts: 4, role: "assistant", content: [{ type: "text", text: "After message" }] },
  35. ],
  36. checkpointRestore: vi.fn(),
  37. overwriteClineMessages: vi.fn(),
  38. overwriteApiConversationHistory: vi.fn(),
  39. }
  40. mockCline.messageManager = new MessageManager(mockCline)
  41. // Setup mock provider
  42. mockProvider = {
  43. getCurrentTask: vi.fn(() => mockCline),
  44. postMessageToWebview: vi.fn(),
  45. getTaskWithId: vi.fn(() => ({
  46. historyItem: { id: "test-task-123", messages: mockCline.clineMessages },
  47. })),
  48. createTaskWithHistoryItem: vi.fn(),
  49. setPendingEditOperation: vi.fn(),
  50. contextProxy: {
  51. globalStorageUri: { fsPath: "/test/storage" },
  52. },
  53. getState: vi.fn().mockResolvedValue({
  54. maxImageFileSize: 5,
  55. maxTotalImageSize: 20,
  56. }),
  57. }
  58. })
  59. describe("delete operations with checkpoint restoration", () => {
  60. it("should call handleCheckpointRestoreOperation for checkpoint deletes", async () => {
  61. // Mock handleCheckpointRestoreOperation
  62. ;(handleCheckpointRestoreOperation as any).mockResolvedValue(undefined)
  63. // Call the handler with delete confirmation
  64. await webviewMessageHandler(mockProvider, {
  65. type: "deleteMessageConfirm",
  66. messageTs: 1,
  67. restoreCheckpoint: true,
  68. })
  69. // Verify handleCheckpointRestoreOperation was called with correct parameters
  70. expect(handleCheckpointRestoreOperation).toHaveBeenCalledWith({
  71. provider: mockProvider,
  72. currentCline: mockCline,
  73. messageTs: 1,
  74. messageIndex: 0,
  75. checkpoint: { hash: "abc123" },
  76. operation: "delete",
  77. })
  78. })
  79. it("should save messages for non-checkpoint deletes", async () => {
  80. // Call the handler with delete confirmation (no checkpoint restoration)
  81. await webviewMessageHandler(mockProvider, {
  82. type: "deleteMessageConfirm",
  83. messageTs: 2,
  84. restoreCheckpoint: false,
  85. })
  86. // Verify saveTaskMessages was called
  87. expect(saveTaskMessages).toHaveBeenCalledWith({
  88. messages: expect.any(Array),
  89. taskId: "test-task-123",
  90. globalStoragePath: "/test/storage",
  91. })
  92. // Verify checkpoint restore was NOT called
  93. expect(mockCline.checkpointRestore).not.toHaveBeenCalled()
  94. })
  95. })
  96. describe("edit operations with checkpoint restoration", () => {
  97. it("should call handleCheckpointRestoreOperation for checkpoint edits", async () => {
  98. // Mock handleCheckpointRestoreOperation
  99. ;(handleCheckpointRestoreOperation as any).mockResolvedValue(undefined)
  100. // Call the handler with edit confirmation
  101. await webviewMessageHandler(mockProvider, {
  102. type: "editMessageConfirm",
  103. messageTs: 1,
  104. text: "Edited checkpoint message",
  105. restoreCheckpoint: true,
  106. })
  107. // Verify handleCheckpointRestoreOperation was called with correct parameters
  108. expect(handleCheckpointRestoreOperation).toHaveBeenCalledWith({
  109. provider: mockProvider,
  110. currentCline: mockCline,
  111. messageTs: 1,
  112. messageIndex: 0,
  113. checkpoint: { hash: "abc123" },
  114. operation: "edit",
  115. editData: {
  116. editedContent: "Edited checkpoint message",
  117. images: [],
  118. apiConversationHistoryIndex: 0,
  119. },
  120. })
  121. })
  122. })
  123. })