edit.test.ts 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. import { describe, expect, test } from "bun:test"
  2. import { replace } from "../../src/tool/edit"
  3. interface TestCase {
  4. content: string
  5. find: string
  6. replace: string
  7. all?: boolean
  8. fail?: boolean
  9. }
  10. const testCases: TestCase[] = [
  11. // SimpleReplacer cases
  12. {
  13. content: ["function hello() {", ' console.log("world");', "}"].join("\n"),
  14. find: 'console.log("world");',
  15. replace: 'console.log("universe");',
  16. },
  17. {
  18. content: [
  19. "if (condition) {",
  20. " doSomething();",
  21. " doSomethingElse();",
  22. "}",
  23. ].join("\n"),
  24. find: [" doSomething();", " doSomethingElse();"].join("\n"),
  25. replace: [" doNewThing();", " doAnotherThing();"].join("\n"),
  26. },
  27. // LineTrimmedReplacer cases
  28. {
  29. content: ["function test() {", ' console.log("hello");', "}"].join("\n"),
  30. find: 'console.log("hello");',
  31. replace: 'console.log("goodbye");',
  32. },
  33. {
  34. content: ["const x = 5; ", "const y = 10;"].join("\n"),
  35. find: "const x = 5;",
  36. replace: "const x = 15;",
  37. },
  38. {
  39. content: [" if (true) {", " return false;", " }"].join("\n"),
  40. find: ["if (true) {", "return false;", "}"].join("\n"),
  41. replace: ["if (false) {", "return true;", "}"].join("\n"),
  42. },
  43. // BlockAnchorReplacer cases
  44. {
  45. content: [
  46. "function calculate(a, b) {",
  47. " const temp = a + b;",
  48. " const result = temp * 2;",
  49. " return result;",
  50. "}",
  51. ].join("\n"),
  52. find: [
  53. "function calculate(a, b) {",
  54. " // different middle content",
  55. " return result;",
  56. "}",
  57. ].join("\n"),
  58. replace: ["function calculate(a, b) {", " return a * b * 2;", "}"].join(
  59. "\n",
  60. ),
  61. },
  62. {
  63. content: [
  64. "class MyClass {",
  65. " constructor() {",
  66. " this.value = 0;",
  67. " }",
  68. " ",
  69. " getValue() {",
  70. " return this.value;",
  71. " }",
  72. "}",
  73. ].join("\n"),
  74. find: ["class MyClass {", " // different implementation", "}"].join("\n"),
  75. replace: [
  76. "class MyClass {",
  77. " constructor() {",
  78. " this.value = 42;",
  79. " }",
  80. "}",
  81. ].join("\n"),
  82. },
  83. // WhitespaceNormalizedReplacer cases
  84. {
  85. content: ["function test() {", '\tconsole.log("hello");', "}"].join("\n"),
  86. find: ' console.log("hello");',
  87. replace: ' console.log("world");',
  88. },
  89. {
  90. content: "const x = 5;",
  91. find: "const x = 5;",
  92. replace: "const x = 10;",
  93. },
  94. {
  95. content: "if\t( condition\t) {",
  96. find: "if ( condition ) {",
  97. replace: "if (newCondition) {",
  98. },
  99. // IndentationFlexibleReplacer cases
  100. {
  101. content: [
  102. " function nested() {",
  103. ' console.log("deeply nested");',
  104. " return true;",
  105. " }",
  106. ].join("\n"),
  107. find: [
  108. "function nested() {",
  109. ' console.log("deeply nested");',
  110. " return true;",
  111. "}",
  112. ].join("\n"),
  113. replace: [
  114. "function nested() {",
  115. ' console.log("updated");',
  116. " return false;",
  117. "}",
  118. ].join("\n"),
  119. },
  120. {
  121. content: [
  122. " if (true) {",
  123. ' console.log("level 1");',
  124. ' console.log("level 2");',
  125. " }",
  126. ].join("\n"),
  127. find: [
  128. "if (true) {",
  129. 'console.log("level 1");',
  130. ' console.log("level 2");',
  131. "}",
  132. ].join("\n"),
  133. replace: ["if (true) {", 'console.log("updated");', "}"].join("\n"),
  134. },
  135. // replaceAll option cases
  136. {
  137. content: [
  138. 'console.log("test");',
  139. 'console.log("test");',
  140. 'console.log("test");',
  141. ].join("\n"),
  142. find: 'console.log("test");',
  143. replace: 'console.log("updated");',
  144. all: true,
  145. },
  146. {
  147. content: ['console.log("test");', 'console.log("test");'].join("\n"),
  148. find: 'console.log("test");',
  149. replace: 'console.log("updated");',
  150. all: false,
  151. },
  152. // Error cases
  153. {
  154. content: 'console.log("hello");',
  155. find: "nonexistent string",
  156. replace: "updated",
  157. fail: true,
  158. },
  159. {
  160. content: ["test", "test", "different content", "test"].join("\n"),
  161. find: "test",
  162. replace: "updated",
  163. all: false,
  164. fail: true,
  165. },
  166. // Edge cases
  167. {
  168. content: "",
  169. find: "",
  170. replace: "new content",
  171. },
  172. {
  173. content: "const regex = /[.*+?^${}()|[\\\\]\\\\\\\\]/g;",
  174. find: "/[.*+?^${}()|[\\\\]\\\\\\\\]/g",
  175. replace: "/\\\\w+/g",
  176. },
  177. {
  178. content: 'const message = "Hello 世界! 🌍";',
  179. find: "Hello 世界! 🌍",
  180. replace: "Hello World! 🌎",
  181. },
  182. ]
  183. describe("EditTool Replacers", () => {
  184. test.each(testCases)("case %#", (testCase) => {
  185. if (testCase.fail) {
  186. expect(() => {
  187. replace(testCase.content, testCase.find, testCase.replace, testCase.all)
  188. }).toThrow()
  189. } else {
  190. const result = replace(
  191. testCase.content,
  192. testCase.find,
  193. testCase.replace,
  194. testCase.all,
  195. )
  196. expect(result).toContain(testCase.replace)
  197. }
  198. })
  199. })