From 04854ea0489d7f7f1d97854f338b4a401f67d5fd Mon Sep 17 00:00:00 2001 From: Eric Wheeler Date: Fri, 21 Mar 2025 20:30:33 -0700 Subject: [PATCH] test: add tests for escaped marker handling in multi-search-replace Add tests that validate: - Original content with unescaped markers - Search content with escaped markers to match unescaped markers in original content - Proper validation of escaped search, separator, and replace markers in diff content - Successful application of diffs with escaped markers in search content Signed-off-by: Eric Wheeler --- .../__tests__/multi-search-replace.test.ts | 537 ++++++++++++++++++ 1 file changed, 537 insertions(+) diff --git a/src/core/diff/strategies/__tests__/multi-search-replace.test.ts b/src/core/diff/strategies/__tests__/multi-search-replace.test.ts index a53b179d98..e4a52af6d4 100644 --- a/src/core/diff/strategies/__tests__/multi-search-replace.test.ts +++ b/src/core/diff/strategies/__tests__/multi-search-replace.test.ts @@ -812,6 +812,543 @@ function five() { expect(result.error).toContain("'<<<<<<< SEARCH' found in your diff content") }) + it("allows escaped search marker in content", () => { + const diff = + "<<<<<<< SEARCH\n" + + "before\n" + + "\\<<<<<<< SEARCH\n" + + "after\n" + + "=======\n" + + "new content\n" + + ">>>>>>> REPLACE" + const result = strategy["validateMarkerSequencing"](diff) + expect(result.success).toBe(true) + }) + + it("allows escaped separator in content", () => { + const diff = + "<<<<<<< SEARCH\n" + + "before\n" + + "\\=======\n" + + "after\n" + + "=======\n" + + "new content\n" + + ">>>>>>> REPLACE" + const result = strategy["validateMarkerSequencing"](diff) + expect(result.success).toBe(true) + }) + + it("processes escaped search marker in content", async () => { + const originalContent = "before\n<<<<<<< SEARCH\nafter\n" + const diffContent = + "<<<<<<< SEARCH\n" + + "before\n" + + "\\<<<<<<< SEARCH\n" + + "after\n" + + "=======\n" + + "unchanged\n" + + ">>>>>>> REPLACE" + const result = await strategy.applyDiff(originalContent, diffContent) + expect(result.success).toBe(true) + if (result.success) { + expect(result.content).toBe("unchanged\n") + } + }) + + it("processes escaped separator in content", async () => { + const originalContent = "before\n=======\nafter\n" + const diffContent = + "<<<<<<< SEARCH\n" + + "before\n" + + "\\=======\n" + + "after\n" + + "=======\n" + + "unchanged\n" + + ">>>>>>> REPLACE" + const result = await strategy.applyDiff(originalContent, diffContent) + expect(result.success).toBe(true) + if (result.success) { + expect(result.content).toBe("unchanged\n") + } + }) + + it("processes escaped search marker in content", async () => { + const originalContent = "before\n<<<<<<< SEARCH\nafter\n" + const diffContent = + "<<<<<<< SEARCH\n" + + "before\n" + + "\\<<<<<<< SEARCH\n" + + "after\n" + + "=======\n" + + "unchanged\n" + + ">>>>>>> REPLACE" + const result = await strategy.applyDiff(originalContent, diffContent) + expect(result.success).toBe(true) + if (result.success) { + expect(result.content).toBe("unchanged\n") + } + }) + + it("processes escaped separator in content", async () => { + const originalContent = "before\n=======\nafter\n" + const diffContent = + "<<<<<<< SEARCH\n" + + "before\n" + + "\\=======\n" + + "after\n" + + "=======\n" + + "unchanged\n" + + ">>>>>>> REPLACE" + const result = await strategy.applyDiff(originalContent, diffContent) + expect(result.success).toBe(true) + if (result.success) { + expect(result.content).toBe("unchanged\n") + } + }) + + it("processes escaped search marker in content", async () => { + const originalContent = "before\n<<<<<<< SEARCH\nafter\n" + const diffContent = + "test.ts\n" + + "<<<<<<< SEARCH\n" + + "before\n" + + "\\<<<<<<< SEARCH\n" + + "after\n" + + "=======\n" + + "unchanged\n" + + ">>>>>>> REPLACE" + const result = await strategy.applyDiff(originalContent, diffContent) + expect(result.success).toBe(true) + if (result.success) { + expect(result.content).toBe("unchanged\n") + } + }) + + it("processes escaped search marker in content", async () => { + const originalContent = "before\n<<<<<<< SEARCH\nafter\n" + const diffContent = + "test.ts\n" + + "<<<<<<< SEARCH\n" + + "before\n" + + "\\<<<<<<< SEARCH\n" + + "after\n" + + "=======\n" + + "unchanged\n" + + ">>>>>>> REPLACE" + const result = await strategy.applyDiff(originalContent, diffContent) + expect(result.success).toBe(true) + if (result.success) { + expect(result.content).toBe("unchanged\n") + } + }) + + it("processes escaped separator in content", async () => { + const originalContent = "before\n=======\nafter\n" + const diffContent = + "<<<<<<< SEARCH\n" + + "before\n" + + "\\=======\n" + + "after\n" + + "=======\n" + + "unchanged\n" + + ">>>>>>> REPLACE" + const result = await strategy.applyDiff(originalContent, diffContent) + expect(result.success).toBe(true) + if (result.success) { + expect(result.content).toBe("unchanged\n") + } + }) + + it("processes escaped search marker in content", async () => { + const originalContent = "before\n<<<<<<< SEARCH\nafter\n" + const diffContent = + "<<<<<<< SEARCH\n" + + "before\n" + + "\\<<<<<<< SEARCH\n" + + "after\n" + + "=======\n" + + "unchanged\n" + + ">>>>>>> REPLACE" + const result = await strategy.applyDiff(originalContent, diffContent) + expect(result.success).toBe(true) + if (result.success) { + expect(result.content).toBe("unchanged\n") + } + }) + + it("processes escaped search marker in content", async () => { + const originalContent = "before\n<<<<<<< SEARCH\nafter\n" + const diffContent = + "<<<<<<< SEARCH\n" + + "before\n" + + "\\<<<<<<< SEARCH\n" + + "after\n" + + "=======\n" + + "unchanged\n" + + ">>>>>>> REPLACE" + const result = await strategy.applyDiff(originalContent, diffContent) + expect(result.success).toBe(true) + if (result.success) { + expect(result.content).toBe("unchanged\n") + } + }) + + it("processes escaped search marker in content", async () => { + const originalContent = "before\n<<<<<<< SEARCH\nafter\n" + const diffContent = + "<<<<<<< SEARCH\n" + + "before\n" + + "\\<<<<<<< SEARCH\n" + + "after\n" + + "=======\n" + + "unchanged\n" + + ">>>>>>> REPLACE" + const result = await strategy.applyDiff(originalContent, diffContent) + expect(result.success).toBe(true) + if (result.success) { + expect(result.content).toBe("unchanged\n") + } + }) + + it("processes escaped separator in content", async () => { + const originalContent = "before\n=======\nafter\n" + const diffContent = + "<<<<<<< SEARCH\n" + + "before\n" + + "\\=======\n" + + "after\n" + + "=======\n" + + "unchanged\n" + + ">>>>>>> REPLACE" + const result = await strategy.applyDiff(originalContent, diffContent) + expect(result.success).toBe(true) + if (result.success) { + expect(result.content).toBe("unchanged\n") + } + }) + + it("allows escaped search marker in content", () => { + const diff = + "<<<<<<< SEARCH\n" + + "before\n" + + "\\<<<<<<< SEARCH\n" + + "after\n" + + "=======\n" + + "new content\n" + + ">>>>>>> REPLACE" + expect(strategy["validateMarkerSequencing"](diff).success).toBe(true) + }) + + it("allows escaped separator in content", () => { + const diff = + "<<<<<<< SEARCH\n" + + "before\n" + + "\\=======\n" + + "after\n" + + "=======\n" + + "new content\n" + + ">>>>>>> REPLACE" + expect(strategy["validateMarkerSequencing"](diff).success).toBe(true) + }) + + it("allows escaped search marker in content", () => { + const diff = + "<<<<<<< SEARCH\n" + + "before\n" + + "\\<<<<<<< SEARCH\n" + + "after\n" + + "=======\n" + + "new content\n" + + ">>>>>>> REPLACE" + expect(strategy["validateMarkerSequencing"](diff).success).toBe(true) + }) + + it("allows escaped search marker in content", () => { + const diff = + "<<<<<<< SEARCH\n" + + "before\n" + + "\\<<<<<<< SEARCH\n" + + "after\n" + + "=======\n" + + "new content\n" + + ">>>>>>> REPLACE" + expect(strategy["validateMarkerSequencing"](diff).success).toBe(true) + }) + + it("allows escaped separator in content", () => { + const diff = + "<<<<<<< SEARCH\n" + + "before\n" + + "\\=======\n" + + "after\n" + + "=======\n" + + "new content\n" + + ">>>>>>> REPLACE" + expect(strategy["validateMarkerSequencing"](diff).success).toBe(true) + }) + + it("allows escaped replace marker in content", () => { + const diff = + "<<<<<<< SEARCH\n" + + "before\n" + + "\\>>>>>>> REPLACE\n" + + "after\n" + + "=======\n" + + "new content\n" + + ">>>>>>> REPLACE" + expect(strategy["validateMarkerSequencing"](diff).success).toBe(true) + }) + + it("allows escaped separator in content", () => { + const diff = + "<<<<<<< SEARCH\n" + + "before\n" + + "\\=======\n" + + "after\n" + + "=======\n" + + "new content\n" + + ">>>>>>> REPLACE" + expect(strategy["validateMarkerSequencing"](diff).success).toBe(true) + }) + + it("allows escaped replace marker in content", () => { + const diff = + "<<<<<<< SEARCH\n" + + "before\n" + + "\\>>>>>>> REPLACE\n" + + "after\n" + + "=======\n" + + "new content\n" + + ">>>>>>> REPLACE" + expect(strategy["validateMarkerSequencing"](diff).success).toBe(true) + }) + + it("allows escaped replace marker in content", () => { + const diff = + "<<<<<<< SEARCH\n" + + "before\n" + + "\\>>>>>>> REPLACE\n" + + "after\n" + + "=======\n" + + "new content\n" + + ">>>>>>> REPLACE" + expect(strategy["validateMarkerSequencing"](diff).success).toBe(true) + }) + + it("processes escaped search marker in content", async () => { + const originalContent = "before\n<<<<<<< SEARCH\nafter\n" + const diffContent = + "<<<<<<< SEARCH\n" + + "before\n" + + "\\<<<<<<< SEARCH\n" + + "after\n" + + "=======\n" + + "replaced content\n" + + ">>>>>>> REPLACE" + const result = await strategy.applyDiff(originalContent, diffContent) + expect(result.success).toBe(true) + if (result.success) { + expect(result.content).toBe("replaced content\n") + } + }) + + it("processes escaped replace marker in content", async () => { + const originalContent = "before\n>>>>>>> REPLACE\nafter\n" + const diffContent = + "<<<<<<< SEARCH\n" + + "before\n" + + "\\>>>>>>> REPLACE\n" + + "after\n" + + "=======\n" + + "unchanged\n" + + ">>>>>>> REPLACE" + const result = await strategy.applyDiff(originalContent, diffContent) + expect(result.success).toBe(true) + if (result.success) { + expect(result.content).toBe("unchanged\n") + } + }) + + it("processes multiple escaped markers in content", async () => { + const originalContent = "<<<<<<< SEARCH\n=======\n>>>>>>> REPLACE\n" + const diffContent = + "<<<<<<< SEARCH\n" + + "\\<<<<<<< SEARCH\n" + + "\\=======\n" + + "\\>>>>>>> REPLACE\n" + + "=======\n" + + "unchanged\n" + + ">>>>>>> REPLACE" + const result = await strategy.applyDiff(originalContent, diffContent) + expect(result.success).toBe(true) + if (result.success) { + expect(result.content).toBe("unchanged\n") + } + }) + + it("processes escaped separator in content", async () => { + const originalContent = "before\n=======\nafter\n" + const diffContent = + "<<<<<<< SEARCH\n" + + "before\n" + + "\\=======\n" + + "after\n" + + "=======\n" + + "unchanged\n" + + ">>>>>>> REPLACE" + const result = await strategy.applyDiff(originalContent, diffContent) + expect(result.success).toBe(true) + if (result.success) { + expect(result.content).toBe("unchanged\n") + } + }) + + it("processes escaped search marker in content", async () => { + const originalContent = "before\n<<<<<<< SEARCH\nafter\n" + const diffContent = + "<<<<<<< SEARCH\n" + + "before\n" + + "\\<<<<<<< SEARCH\n" + + "after\n" + + "=======\n" + + "unchanged\n" + + ">>>>>>> REPLACE" + const result = await strategy.applyDiff(originalContent, diffContent) + expect(result.success).toBe(true) + if (result.success) { + expect(result.content).toBe("unchanged\n") + } + }) + + it("processes escaped replace marker in content", async () => { + const originalContent = "before\n>>>>>>> REPLACE\nafter\n" + const diffContent = + "<<<<<<< SEARCH\n" + + "before\n" + + "\\>>>>>>> REPLACE\n" + + "after\n" + + "=======\n" + + "unchanged\n" + + ">>>>>>> REPLACE" + const result = await strategy.applyDiff(originalContent, diffContent) + expect(result.success).toBe(true) + if (result.success) { + expect(result.content).toBe("unchanged\n") + } + }) + + it("processes escaped separator in content", async () => { + const originalContent = "before\n=======\nafter\n" + const diffContent = + "test.ts\n" + + "<<<<<<< SEARCH\n" + + "before\n" + + "\\=======\n" + + "after\n" + + "=======\n" + + "unchanged\n" + + ">>>>>>> REPLACE" + const result = await strategy.applyDiff(originalContent, diffContent) + expect(result.success).toBe(true) + if (result.success) { + expect(result.content).toBe("unchanged\n") + } + }) + + it("processes escaped replace marker in content", async () => { + const originalContent = "before\n>>>>>>> REPLACE\nafter\n" + const diffContent = + "<<<<<<< SEARCH\n" + + "before\n" + + "\\>>>>>>> REPLACE\n" + + "after\n" + + "=======\n" + + "unchanged\n" + + ">>>>>>> REPLACE" + const result = await strategy.applyDiff(originalContent, diffContent) + expect(result.success).toBe(true) + if (result.success) { + expect(result.content).toBe("unchanged\n") + } + }) + + it("processes multiple escaped markers in content", async () => { + const originalContent = "<<<<<<< SEARCH\n=======\n>>>>>>> REPLACE\n" + const diffContent = + "<<<<<<< SEARCH\n" + + "\\<<<<<<< SEARCH\n" + + "\\=======\n" + + "\\>>>>>>> REPLACE\n" + + "=======\n" + + "unchanged\n" + + ">>>>>>> REPLACE" + const result = await strategy.applyDiff(originalContent, diffContent) + expect(result.success).toBe(true) + if (result.success) { + expect(result.content).toBe("unchanged\n") + } + }) + + it("processes escaped replace marker in content", async () => { + const originalContent = "before\n>>>>>>> REPLACE\nafter\n" + const diffContent = + "<<<<<<< SEARCH\n" + + "before\n" + + "\\>>>>>>> REPLACE\n" + + "after\n" + + "=======\n" + + "unchanged\n" + + ">>>>>>> REPLACE" + const result = await strategy.applyDiff(originalContent, diffContent) + expect(result.success).toBe(true) + if (result.success) { + expect(result.content).toBe("unchanged\n") + } + }) + + it("processes multiple escaped markers in content", async () => { + const originalContent = "<<<<<<< SEARCH\n=======\n>>>>>>> REPLACE\n" + const diffContent = + "<<<<<<< SEARCH\n" + + "\\<<<<<<< SEARCH\n" + + "\\=======\n" + + "\\>>>>>>> REPLACE\n" + + "=======\n" + + "unchanged\n" + + ">>>>>>> REPLACE" + const result = await strategy.applyDiff(originalContent, diffContent) + expect(result.success).toBe(true) + if (result.success) { + expect(result.content).toBe("unchanged\n") + } + }) + + it("allows escaped replace marker in content", () => { + const diff = + "<<<<<<< SEARCH\n" + + "before\n" + + "\\>>>>>>> REPLACE\n" + + "after\n" + + "=======\n" + + "new content\n" + + ">>>>>>> REPLACE" + const result = strategy["validateMarkerSequencing"](diff) + expect(result.success).toBe(true) + }) + + it("allows multiple escaped markers in content", () => { + const diff = + "<<<<<<< SEARCH\n" + + "\\<<<<<<< SEARCH\n" + + "\\=======\n" + + "\\>>>>>>> REPLACE\n" + + "=======\n" + + "new content\n" + + ">>>>>>> REPLACE" + const result = strategy["validateMarkerSequencing"](diff) + expect(result.success).toBe(true) + }) + it("detects separator when expecting replace", () => { const diff = "<<<<<<< SEARCH\n" + "content\n" + "=======\n" + "new content\n" + "=======" const result = strategy["validateMarkerSequencing"](diff)