esupgrade 2025.0.0 → 2025.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,358 @@
1
+ import { describe, test, beforeEach, afterEach } from "node:test"
2
+ import assert from "node:assert"
3
+ import { execSync, spawnSync } from "node:child_process"
4
+ import fs from "node:fs"
5
+ import path from "node:path"
6
+ import os from "node:os"
7
+
8
+ const CLI_PATH = path.join(process.cwd(), "bin", "esupgrade.js")
9
+
10
+ describe("CLI", () => {
11
+ let tempDir
12
+
13
+ beforeEach(() => {
14
+ tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "esupgrade-test-"))
15
+ })
16
+
17
+ afterEach(() => {
18
+ if (tempDir && fs.existsSync(tempDir)) {
19
+ fs.rmSync(tempDir, { recursive: true, force: true })
20
+ }
21
+ })
22
+
23
+ test("should display help when no files specified", () => {
24
+ const result = spawnSync(process.execPath, [CLI_PATH], {
25
+ encoding: "utf8",
26
+ })
27
+
28
+ assert.match(result.stderr, /Error: No files specified/)
29
+ // Commander shows help and exits with 0
30
+ assert.strictEqual(result.status, 0)
31
+ })
32
+
33
+ test("should transform a single file with --write", () => {
34
+ const testFile = path.join(tempDir, "test.js")
35
+ const originalCode = `var x = 1;`
36
+ fs.writeFileSync(testFile, originalCode)
37
+
38
+ const result = spawnSync(process.execPath, [CLI_PATH, testFile, "--write"], {
39
+ encoding: "utf8",
40
+ })
41
+
42
+ const transformedCode = fs.readFileSync(testFile, "utf8")
43
+ assert.match(transformedCode, /const x = 1/)
44
+ assert.match(result.stdout, /Summary: 1 file\(s\) upgraded/)
45
+ assert.strictEqual(result.status, 0)
46
+ })
47
+
48
+ test("should transform files with widely-available baseline by default", () => {
49
+ const testFile = path.join(tempDir, "test.js")
50
+ const originalCode = `var x = 1;\nconst p = new Promise((resolve) => resolve(getData()));`
51
+ fs.writeFileSync(testFile, originalCode)
52
+
53
+ const result = spawnSync(process.execPath, [CLI_PATH, testFile, "--write"], {
54
+ encoding: "utf8",
55
+ })
56
+
57
+ const transformedCode = fs.readFileSync(testFile, "utf8")
58
+ assert.match(transformedCode, /const x = 1/)
59
+ assert.doesNotMatch(transformedCode, /Promise\.try/) // Promise.try not in widely-available
60
+ assert.match(result.stdout, /widely-available/)
61
+ assert.strictEqual(result.status, 0)
62
+ })
63
+
64
+ test("should transform files with newly-available baseline", () => {
65
+ const testFile = path.join(tempDir, "test.js")
66
+ const originalCode = `var x = 1;\nconst p = new Promise((resolve) => resolve(getData()));`
67
+ fs.writeFileSync(testFile, originalCode)
68
+
69
+ const result = spawnSync(
70
+ process.execPath,
71
+ [CLI_PATH, testFile, "--baseline", "newly-available", "--write"],
72
+ {
73
+ encoding: "utf8",
74
+ },
75
+ )
76
+
77
+ const transformedCode = fs.readFileSync(testFile, "utf8")
78
+ assert.match(transformedCode, /const x = 1/)
79
+ assert.match(transformedCode, /Promise\.try/) // Promise.try in newly-available
80
+ assert.match(result.stdout, /newly-available/)
81
+ assert.strictEqual(result.status, 0)
82
+ })
83
+
84
+ test("should check files without writing with --check", () => {
85
+ const testFile = path.join(tempDir, "test.js")
86
+ const originalCode = `var x = 1;`
87
+ fs.writeFileSync(testFile, originalCode)
88
+
89
+ const result = spawnSync(process.execPath, [CLI_PATH, testFile, "--check"], {
90
+ encoding: "utf8",
91
+ })
92
+
93
+ const fileContent = fs.readFileSync(testFile, "utf8")
94
+ assert.strictEqual(fileContent, originalCode) // File unchanged
95
+ assert.match(result.stdout, /✗/)
96
+ assert.match(result.stdout, /1 file\(s\) need upgrading/)
97
+ assert.strictEqual(result.status, 1) // Exit with code 1 when changes needed
98
+ })
99
+
100
+ test("should exit with 0 when --check and no changes needed", () => {
101
+ const testFile = path.join(tempDir, "test.js")
102
+ const originalCode = `const x = 1;`
103
+ fs.writeFileSync(testFile, originalCode)
104
+
105
+ const result = spawnSync(process.execPath, [CLI_PATH, testFile, "--check"], {
106
+ encoding: "utf8",
107
+ })
108
+
109
+ const fileContent = fs.readFileSync(testFile, "utf8")
110
+ assert.strictEqual(fileContent, originalCode) // File unchanged
111
+ assert.match(result.stdout, /All files are already modern/)
112
+ assert.strictEqual(result.status, 0)
113
+ })
114
+
115
+ test("should support both --check and --write together", () => {
116
+ const testFile = path.join(tempDir, "test.js")
117
+ const originalCode = `var x = 1;`
118
+ fs.writeFileSync(testFile, originalCode)
119
+
120
+ const result = spawnSync(
121
+ process.execPath,
122
+ [CLI_PATH, testFile, "--check", "--write"],
123
+ {
124
+ encoding: "utf8",
125
+ },
126
+ )
127
+
128
+ const transformedCode = fs.readFileSync(testFile, "utf8")
129
+ assert.match(transformedCode, /const x = 1/)
130
+ assert.match(result.stdout, /✗/)
131
+ assert.match(result.stdout, /Changes written to file/)
132
+ assert.match(result.stdout, /1 file\(s\) upgraded/)
133
+ assert.strictEqual(result.status, 1) // Still exit 1 with --check
134
+ })
135
+
136
+ test("should process directory recursively", () => {
137
+ const subDir = path.join(tempDir, "src")
138
+ fs.mkdirSync(subDir)
139
+
140
+ const file1 = path.join(tempDir, "test1.js")
141
+ const file2 = path.join(subDir, "test2.js")
142
+ fs.writeFileSync(file1, `var x = 1;`)
143
+ fs.writeFileSync(file2, `var y = 2;`)
144
+
145
+ const result = spawnSync(process.execPath, [CLI_PATH, tempDir, "--write"], {
146
+ encoding: "utf8",
147
+ })
148
+
149
+ const transformed1 = fs.readFileSync(file1, "utf8")
150
+ const transformed2 = fs.readFileSync(file2, "utf8")
151
+ assert.match(transformed1, /const x = 1/)
152
+ assert.match(transformed2, /const y = 2/)
153
+ assert.match(result.stdout, /Processing 2 file/)
154
+ assert.match(result.stdout, /2 file\(s\) upgraded/)
155
+ assert.strictEqual(result.status, 0)
156
+ })
157
+
158
+ test("should skip node_modules and .git directories", () => {
159
+ const nodeModules = path.join(tempDir, "node_modules")
160
+ const gitDir = path.join(tempDir, ".git")
161
+ fs.mkdirSync(nodeModules)
162
+ fs.mkdirSync(gitDir)
163
+
164
+ const file1 = path.join(tempDir, "test.js")
165
+ const file2 = path.join(nodeModules, "test.js")
166
+ const file3 = path.join(gitDir, "test.js")
167
+ fs.writeFileSync(file1, `var x = 1;`)
168
+ fs.writeFileSync(file2, `var y = 2;`)
169
+ fs.writeFileSync(file3, `var z = 3;`)
170
+
171
+ const result = spawnSync(process.execPath, [CLI_PATH, tempDir, "--write"], {
172
+ encoding: "utf8",
173
+ })
174
+
175
+ assert.match(result.stdout, /Processing 1 file/)
176
+ assert.strictEqual(result.status, 0)
177
+ })
178
+
179
+ test("should process multiple file extensions", () => {
180
+ const jsFile = path.join(tempDir, "test.js")
181
+ const mjsFile = path.join(tempDir, "test.mjs")
182
+ const cjsFile = path.join(tempDir, "test.cjs")
183
+ const jsxFile = path.join(tempDir, "test.jsx")
184
+
185
+ fs.writeFileSync(jsFile, `var a = 1;`)
186
+ fs.writeFileSync(mjsFile, `var b = 2;`)
187
+ fs.writeFileSync(cjsFile, `var c = 3;`)
188
+ fs.writeFileSync(jsxFile, `var d = 4;`)
189
+
190
+ const result = spawnSync(process.execPath, [CLI_PATH, tempDir, "--write"], {
191
+ encoding: "utf8",
192
+ })
193
+
194
+ assert.match(result.stdout, /Processing 4 file/)
195
+ assert.match(result.stdout, /4 file\(s\) upgraded/)
196
+ assert.strictEqual(result.status, 0)
197
+ })
198
+
199
+ test("should handle TypeScript file extensions", () => {
200
+ const tsFile = path.join(tempDir, "test.ts")
201
+ const tsxFile = path.join(tempDir, "test.tsx")
202
+
203
+ fs.writeFileSync(tsFile, `var a = 1;`)
204
+ fs.writeFileSync(tsxFile, `var b = 2;`)
205
+
206
+ const result = spawnSync(process.execPath, [CLI_PATH, tempDir, "--write"], {
207
+ encoding: "utf8",
208
+ })
209
+
210
+ assert.match(result.stdout, /Processing 2 file/)
211
+ assert.strictEqual(result.status, 0)
212
+ })
213
+
214
+ test("should error on invalid baseline", () => {
215
+ const testFile = path.join(tempDir, "test.js")
216
+ fs.writeFileSync(testFile, `var x = 1;`)
217
+
218
+ const result = spawnSync(
219
+ process.execPath,
220
+ [CLI_PATH, testFile, "--baseline", "invalid"],
221
+ {
222
+ encoding: "utf8",
223
+ },
224
+ )
225
+
226
+ assert.match(result.stderr, /error/)
227
+ assert.strictEqual(result.status, 1)
228
+ })
229
+
230
+ test("should error on non-existent file", () => {
231
+ const result = spawnSync(
232
+ process.execPath,
233
+ [CLI_PATH, path.join(tempDir, "nonexistent.js")],
234
+ {
235
+ encoding: "utf8",
236
+ },
237
+ )
238
+
239
+ assert.match(result.stderr, /Error: Cannot access/)
240
+ assert.strictEqual(result.status, 1)
241
+ })
242
+
243
+ test("should show detailed changes with --check", () => {
244
+ const testFile = path.join(tempDir, "test.js")
245
+ const originalCode = `var x = 1;\nvar y = 2;`
246
+ fs.writeFileSync(testFile, originalCode)
247
+
248
+ const result = spawnSync(process.execPath, [CLI_PATH, testFile, "--check"], {
249
+ encoding: "utf8",
250
+ })
251
+
252
+ assert.match(result.stdout, /var to const/)
253
+ assert.match(result.stdout, /line/)
254
+ assert.strictEqual(result.status, 1)
255
+ })
256
+
257
+ test("should process multiple files specified as arguments", () => {
258
+ const file1 = path.join(tempDir, "test1.js")
259
+ const file2 = path.join(tempDir, "test2.js")
260
+ fs.writeFileSync(file1, `var x = 1;`)
261
+ fs.writeFileSync(file2, `var y = 2;`)
262
+
263
+ const result = spawnSync(process.execPath, [CLI_PATH, file1, file2, "--write"], {
264
+ encoding: "utf8",
265
+ })
266
+
267
+ const transformed1 = fs.readFileSync(file1, "utf8")
268
+ const transformed2 = fs.readFileSync(file2, "utf8")
269
+ assert.match(transformed1, /const x = 1/)
270
+ assert.match(transformed2, /const y = 2/)
271
+ assert.match(result.stdout, /Processing 2 file/)
272
+ assert.strictEqual(result.status, 0)
273
+ })
274
+
275
+ test("should handle files with no changes needed", () => {
276
+ const testFile = path.join(tempDir, "test.js")
277
+ const originalCode = `const x = 1;`
278
+ fs.writeFileSync(testFile, originalCode)
279
+
280
+ const result = spawnSync(process.execPath, [CLI_PATH, testFile, "--write"], {
281
+ encoding: "utf8",
282
+ })
283
+
284
+ const fileContent = fs.readFileSync(testFile, "utf8")
285
+ assert.strictEqual(fileContent, originalCode)
286
+ assert.match(result.stdout, /All files are already modern/)
287
+ assert.strictEqual(result.status, 0)
288
+ })
289
+
290
+ test("should show no changes message for individual files", () => {
291
+ const testFile = path.join(tempDir, "test.js")
292
+ const originalCode = `const x = 1;`
293
+ fs.writeFileSync(testFile, originalCode)
294
+
295
+ const result = spawnSync(process.execPath, [CLI_PATH, testFile, "--write"], {
296
+ encoding: "utf8",
297
+ })
298
+
299
+ assert.match(result.stdout, /No changes:/)
300
+ assert.strictEqual(result.status, 0)
301
+ })
302
+
303
+ test("should handle empty directory", () => {
304
+ const emptyDir = path.join(tempDir, "empty")
305
+ fs.mkdirSync(emptyDir)
306
+
307
+ const result = spawnSync(process.execPath, [CLI_PATH, emptyDir, "--write"], {
308
+ encoding: "utf8",
309
+ })
310
+
311
+ assert.match(result.stdout, /No JavaScript files found/)
312
+ assert.strictEqual(result.status, 0)
313
+ })
314
+
315
+ test("should group changes by type in --check output", () => {
316
+ const testFile = path.join(tempDir, "test.js")
317
+ const originalCode = `var x = 1;\nvar y = 2;\nvar z = 3;`
318
+ fs.writeFileSync(testFile, originalCode)
319
+
320
+ const result = spawnSync(process.execPath, [CLI_PATH, testFile, "--check"], {
321
+ encoding: "utf8",
322
+ })
323
+
324
+ assert.match(result.stdout, /var to const/)
325
+ assert.match(result.stdout, /lines:/)
326
+ assert.strictEqual(result.status, 1)
327
+ })
328
+
329
+ test("should handle syntax errors gracefully", () => {
330
+ const testFile = path.join(tempDir, "test.js")
331
+ const invalidCode = `var x = {{{;`
332
+ fs.writeFileSync(testFile, invalidCode)
333
+
334
+ const result = spawnSync(process.execPath, [CLI_PATH, testFile, "--write"], {
335
+ encoding: "utf8",
336
+ })
337
+
338
+ assert.match(result.stderr, /Error processing/)
339
+ assert.strictEqual(result.status, 0) // CLI continues despite errors
340
+ })
341
+
342
+ test("should handle mixed directory and file arguments", () => {
343
+ const subDir = path.join(tempDir, "src")
344
+ fs.mkdirSync(subDir)
345
+
346
+ const file1 = path.join(tempDir, "test1.js")
347
+ const file2 = path.join(subDir, "test2.js")
348
+ fs.writeFileSync(file1, `var x = 1;`)
349
+ fs.writeFileSync(file2, `var y = 2;`)
350
+
351
+ const result = spawnSync(process.execPath, [CLI_PATH, file1, subDir, "--write"], {
352
+ encoding: "utf8",
353
+ })
354
+
355
+ assert.match(result.stdout, /Processing 2 file/)
356
+ assert.strictEqual(result.status, 0)
357
+ })
358
+ })
@@ -0,0 +1,274 @@
1
+ import { describe, test } from "node:test"
2
+ import assert from "node:assert"
3
+ import { transform } from "../src/index.js"
4
+
5
+ describe("index", () => {
6
+ describe("transform function", () => {
7
+ test("should return TransformResult with correct structure", () => {
8
+ const input = `var x = 1;`
9
+ const result = transform(input)
10
+
11
+ assert.ok(result.hasOwnProperty("code"))
12
+ assert.ok(result.hasOwnProperty("modified"))
13
+ assert.ok(result.hasOwnProperty("changes"))
14
+ assert.strictEqual(typeof result.code, "string")
15
+ assert.strictEqual(typeof result.modified, "boolean")
16
+ assert.ok(Array.isArray(result.changes))
17
+ })
18
+
19
+ test("should handle empty string", () => {
20
+ const input = ``
21
+ const result = transform(input)
22
+
23
+ assert.strictEqual(result.modified, false)
24
+ assert.strictEqual(result.changes.length, 0)
25
+ assert.strictEqual(result.code, "")
26
+ })
27
+
28
+ test("should handle whitespace-only string", () => {
29
+ const input = ` \n\n `
30
+ const result = transform(input)
31
+
32
+ assert.strictEqual(result.modified, false)
33
+ assert.strictEqual(result.changes.length, 0)
34
+ })
35
+
36
+ test("should handle comments only", () => {
37
+ const input = `// This is a comment\n/* Another comment */`
38
+ const result = transform(input)
39
+
40
+ assert.strictEqual(result.modified, false)
41
+ assert.strictEqual(result.changes.length, 0)
42
+ })
43
+
44
+ test("should apply multiple transformations and track all changes", () => {
45
+ const input = `
46
+ var x = 1;
47
+ var y = 'Hello ' + name;
48
+ var obj = Object.assign({}, data);
49
+ `
50
+ const result = transform(input)
51
+
52
+ assert.strictEqual(result.modified, true)
53
+ assert.ok(result.changes.length > 0)
54
+
55
+ // Should have changes from varToConst (which does track line numbers)
56
+ const changeTypes = result.changes.map((c) => c.type)
57
+ assert.ok(changeTypes.includes("varToConst"))
58
+
59
+ // Verify the transformations happened even if not all are tracked
60
+ assert.match(result.code, /const/)
61
+ assert.match(result.code, /`Hello/)
62
+ assert.match(result.code, /\.\.\.data/)
63
+ })
64
+
65
+ test("should aggregate changes from multiple transformers", () => {
66
+ const input = `
67
+ var a = 1;
68
+ var b = 'Hello ' + world;
69
+ Array.from(items).forEach(item => console.log(item));
70
+ `
71
+ const result = transform(input, "widely-available")
72
+
73
+ assert.strictEqual(result.modified, true)
74
+
75
+ // Should track line numbers for all changes
76
+ assert.ok(result.changes.every((c) => c.hasOwnProperty("line")))
77
+ assert.ok(result.changes.every((c) => c.hasOwnProperty("type")))
78
+ })
79
+
80
+ test("should use widely-available transformers by default", () => {
81
+ const input = `var x = 1;`
82
+ const result = transform(input)
83
+
84
+ assert.strictEqual(result.modified, true)
85
+ assert.strictEqual(result.changes[0].type, "varToConst")
86
+ })
87
+
88
+ test("should include newly-available transformers when specified", () => {
89
+ const input = `
90
+ var x = 1;
91
+ const p = new Promise((resolve) => resolve(getData()));
92
+ `
93
+ const result = transform(input, "newly-available")
94
+
95
+ assert.strictEqual(result.modified, true)
96
+
97
+ const changeTypes = result.changes.map((c) => c.type)
98
+ assert.ok(changeTypes.includes("varToConst"))
99
+ assert.ok(changeTypes.includes("promiseTry"))
100
+ })
101
+
102
+ test("should handle complex nested structures", () => {
103
+ const input = `
104
+ function test() {
105
+ var result = Object.assign({}, {
106
+ message: 'Hello ' + name
107
+ });
108
+ return result;
109
+ }
110
+ `
111
+ const result = transform(input)
112
+
113
+ assert.strictEqual(result.modified, true)
114
+ assert.match(result.code, /const result/)
115
+ assert.match(result.code, /\.\.\./)
116
+ assert.match(result.code, /`Hello/)
117
+ })
118
+
119
+ test("should handle JSX syntax", () => {
120
+ const input = `
121
+ var Component = () => {
122
+ var title = 'Hello ' + name;
123
+ return <div>{title}</div>;
124
+ };
125
+ `
126
+ const result = transform(input)
127
+
128
+ assert.strictEqual(result.modified, true)
129
+ assert.match(result.code, /const/)
130
+ assert.match(result.code, /<div>/)
131
+ })
132
+
133
+ test("should handle TypeScript syntax", () => {
134
+ const input = `
135
+ var x: number = 1;
136
+ const greeting: string = 'Hello ' + name;
137
+ `
138
+ const result = transform(input)
139
+
140
+ assert.strictEqual(result.modified, true)
141
+ assert.match(result.code, /const x: number/)
142
+ assert.match(result.code, /`Hello/)
143
+ })
144
+
145
+ test("should preserve code formatting structure", () => {
146
+ const input = `var x = 1;
147
+ var y = 2;`
148
+ const result = transform(input)
149
+
150
+ // Should maintain separation between statements
151
+ assert.match(result.code, /const x = 1/)
152
+ assert.match(result.code, /const y = 2/)
153
+ })
154
+
155
+ test("should handle very large code", () => {
156
+ // Generate a large input with many var declarations
157
+ const lines = []
158
+ for (let i = 0; i < 100; i++) {
159
+ lines.push(`var x${i} = ${i};`)
160
+ }
161
+ const input = lines.join("\n")
162
+
163
+ const result = transform(input)
164
+
165
+ assert.strictEqual(result.modified, true)
166
+ assert.strictEqual(result.changes.length, 100)
167
+ assert.match(result.code, /const x0 = 0/)
168
+ assert.match(result.code, /const x99 = 99/)
169
+ })
170
+
171
+ test("should handle code with special characters", () => {
172
+ const input = `var msg = 'Hello \\n' + 'World\\t!';`
173
+ const result = transform(input)
174
+
175
+ assert.strictEqual(result.modified, true)
176
+ assert.match(result.code, /const msg/)
177
+ // Template literals preserve the escape sequences
178
+ assert.match(result.code, /`Hello/)
179
+ })
180
+
181
+ test("should handle code with unicode characters", () => {
182
+ const input = `var msg = 'Hello ' + '世界' + '!';`
183
+ const result = transform(input)
184
+
185
+ assert.strictEqual(result.modified, true)
186
+ assert.match(result.code, /const msg/)
187
+ })
188
+
189
+ test("should handle all transformers returning no changes", () => {
190
+ const input = `const x = 1; const y = 2;`
191
+ const result = transform(input)
192
+
193
+ assert.strictEqual(result.modified, false)
194
+ assert.strictEqual(result.changes.length, 0)
195
+ })
196
+
197
+ test("should handle baseline parameter case sensitivity", () => {
198
+ const input = `var x = 1;`
199
+
200
+ // Should accept exact strings
201
+ const result1 = transform(input, "widely-available")
202
+ assert.strictEqual(result1.modified, true)
203
+
204
+ const result2 = transform(input, "newly-available")
205
+ assert.strictEqual(result2.modified, true)
206
+ })
207
+
208
+ test("should merge transformers correctly for newly-available", () => {
209
+ const input = `
210
+ var x = 1;
211
+ var obj = Object.assign({}, data);
212
+ const p = new Promise((resolve) => resolve(getData()));
213
+ `
214
+ const result = transform(input, "newly-available")
215
+
216
+ assert.strictEqual(result.modified, true)
217
+
218
+ // Should have changes from transformers that track line numbers
219
+ const changeTypes = result.changes.map((c) => c.type)
220
+ assert.ok(changeTypes.includes("varToConst")) // from widely-available
221
+ assert.ok(changeTypes.includes("promiseTry")) // from newly-available
222
+
223
+ // Verify all transformations happened
224
+ assert.match(result.code, /const/)
225
+ assert.match(result.code, /\.\.\.data/)
226
+ assert.match(result.code, /Promise\.try/)
227
+ })
228
+
229
+ test("should handle code without location info gracefully", () => {
230
+ // Even if some transformations don't have location info, should still work
231
+ const input = `var x = 1;`
232
+ const result = transform(input)
233
+
234
+ assert.strictEqual(result.modified, true)
235
+ // Should handle missing loc info gracefully
236
+ })
237
+
238
+ test("should generate valid JavaScript output", () => {
239
+ const input = `
240
+ var x = 1;
241
+ var greeting = 'Hello ' + name;
242
+ Array.from(items).forEach(item => console.log(item));
243
+ `
244
+ const result = transform(input)
245
+
246
+ // Try to parse the output to ensure it's valid JS
247
+ assert.doesNotThrow(() => {
248
+ new Function(result.code)
249
+ })
250
+ })
251
+
252
+ test("should handle single-line code", () => {
253
+ const input = `var x = 1; var y = 2; var z = 3;`
254
+ const result = transform(input)
255
+
256
+ assert.strictEqual(result.modified, true)
257
+ assert.match(result.code, /const x = 1/)
258
+ assert.match(result.code, /const y = 2/)
259
+ assert.match(result.code, /const z = 3/)
260
+ })
261
+
262
+ test("should handle code with existing template literals", () => {
263
+ const input = `
264
+ var msg = \`Hello \${name}\`;
265
+ var other = 'Test ' + value;
266
+ `
267
+ const result = transform(input)
268
+
269
+ assert.strictEqual(result.modified, true)
270
+ assert.match(result.code, /const msg/)
271
+ assert.match(result.code, /const other/)
272
+ })
273
+ })
274
+ })