|
1 | 1 | import { describe, expect, test } from "bun:test"; |
2 | | -import { replace } from "../../../src/lib/init/replacers.js"; |
| 2 | +import { |
| 3 | + ContextAwareReplacer, |
| 4 | + replace, |
| 5 | +} from "../../../src/lib/init/replacers.js"; |
3 | 6 |
|
4 | 7 | describe("replace", () => { |
5 | 8 | test("exact match", () => { |
@@ -164,3 +167,79 @@ describe("replace", () => { |
164 | 167 | }); |
165 | 168 | }); |
166 | 169 | }); |
| 170 | + |
| 171 | +// --------------------------------------------------------------------------- |
| 172 | +// ContextAwareReplacer |
| 173 | +// --------------------------------------------------------------------------- |
| 174 | + |
| 175 | +describe("ContextAwareReplacer", () => { |
| 176 | + function* collect(content: string, find: string): Generator<string> { |
| 177 | + yield* ContextAwareReplacer(content, find); |
| 178 | + } |
| 179 | + |
| 180 | + function collectAll(content: string, find: string): string[] { |
| 181 | + return [...collect(content, find)]; |
| 182 | + } |
| 183 | + |
| 184 | + test("returns nothing when find has < 3 lines", () => { |
| 185 | + const content = "line1\nline2\nline3\n"; |
| 186 | + expect(collectAll(content, "line1\nline2")).toEqual([]); |
| 187 | + expect(collectAll(content, "line1")).toEqual([]); |
| 188 | + }); |
| 189 | + |
| 190 | + test("finds exact multi-line block", () => { |
| 191 | + const content = "function foo() {\n doSomething();\n}\n\nother code\n"; |
| 192 | + const find = "function foo() {\n doSomething();\n}"; |
| 193 | + const results = collectAll(content, find); |
| 194 | + expect(results).toHaveLength(1); |
| 195 | + expect(results[0]).toContain("function foo()"); |
| 196 | + expect(results[0]).toContain("doSomething"); |
| 197 | + }); |
| 198 | + |
| 199 | + test("handles trailing newline in find by trimming it", () => { |
| 200 | + const content = "start\n middle line\nend\nother"; |
| 201 | + const find = "start\n middle line\nend\n"; // trailing newline |
| 202 | + const results = collectAll(content, find); |
| 203 | + expect(results).toHaveLength(1); |
| 204 | + }); |
| 205 | + |
| 206 | + test("matches block where middle lines have >= 50% similarity", () => { |
| 207 | + // Same first/last line, middle differs slightly |
| 208 | + const content = "START\n line a\n line b\nEND\nextra"; |
| 209 | + const find = "START\n line a\n line X\nEND"; // "line X" differs from "line b" |
| 210 | + // line a matches (1/2 = 50%) → should yield the block |
| 211 | + const results = collectAll(content, find); |
| 212 | + expect(results).toHaveLength(1); |
| 213 | + }); |
| 214 | + |
| 215 | + test("does not match when middle lines have < 50% similarity", () => { |
| 216 | + // Same first/last, but too many middle lines differ |
| 217 | + const content = [ |
| 218 | + "START", |
| 219 | + " line1", |
| 220 | + " line2", |
| 221 | + " line3", |
| 222 | + " line4", |
| 223 | + "END", |
| 224 | + ].join("\n"); |
| 225 | + const find = [ |
| 226 | + "START", |
| 227 | + " lineX", |
| 228 | + " lineY", |
| 229 | + " lineZ", |
| 230 | + " lineW", |
| 231 | + "END", |
| 232 | + ].join("\n"); |
| 233 | + // 0/4 = 0% match < 50% threshold → no yield |
| 234 | + const results = collectAll(content, find); |
| 235 | + expect(results).toHaveLength(0); |
| 236 | + }); |
| 237 | + |
| 238 | + test("handles block where all middle lines are empty", () => { |
| 239 | + const content = "OPEN\n\n\nCLOSE\nother"; |
| 240 | + const find = "OPEN\n\n\nCLOSE"; |
| 241 | + const results = collectAll(content, find); |
| 242 | + // totalNonEmptyLines === 0 → still yields (always match when all empty) |
| 243 | + expect(results).toHaveLength(1); |
| 244 | + }); |
| 245 | +}); |
0 commit comments