esupgrade 2025.3.0 → 2025.3.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "esupgrade",
3
- "version": "2025.3.0",
3
+ "version": "2025.3.1",
4
4
  "description": "Auto-upgrade your JavaScript syntax",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -68,17 +68,32 @@ export function concatToTemplateLiteral(j, root) {
68
68
  return false
69
69
  }
70
70
 
71
- const addStringPart = (value) => {
71
+ // Helper to get the raw value of a string literal (preserving escape sequences)
72
+ const getRawStringValue = (node) => {
73
+ // In string literals, backslashes are used for escape sequences
74
+ // In template literals, backslashes in the raw value also need escaping
75
+ // So we need to double the backslashes: \\ -> \\\\
76
+ // Note: node.extra.rawValue is always defined for string literals with the current parser
77
+ return node.extra.rawValue.replace(/\\/g, "\\\\")
78
+ }
79
+
80
+ const addStringPart = (stringNode) => {
81
+ // Store both the raw and cooked values
82
+ const rawValue = getRawStringValue(stringNode)
83
+ const cookedValue = stringNode.value
84
+
72
85
  if (parts.length === 0 || expressions.length >= parts.length) {
73
- parts.push(value)
86
+ parts.push({ raw: rawValue, cooked: cookedValue })
74
87
  } else {
75
- parts[parts.length - 1] += value
88
+ const lastPart = parts[parts.length - 1]
89
+ lastPart.raw += rawValue
90
+ lastPart.cooked += cookedValue
76
91
  }
77
92
  }
78
93
 
79
94
  const addExpression = (expr) => {
80
95
  if (parts.length === 0) {
81
- parts.push("")
96
+ parts.push({ raw: "", cooked: "" })
82
97
  }
83
98
  expressions.push(expr)
84
99
  }
@@ -103,8 +118,8 @@ export function concatToTemplateLiteral(j, root) {
103
118
  // Left is also a + expression - recurse
104
119
  flatten(node.left, stringContext)
105
120
  } else if (isStringLiteral(node.left)) {
106
- // Left is a string literal
107
- addStringPart(node.left.value)
121
+ // Left is a string literal - use raw value to preserve escape sequences
122
+ addStringPart(node.left)
108
123
  } else {
109
124
  // Left is some other expression
110
125
  addExpression(node.left)
@@ -121,8 +136,8 @@ export function concatToTemplateLiteral(j, root) {
121
136
  flatten(node.right, rightInStringContext)
122
137
  }
123
138
  } else if (isStringLiteral(node.right)) {
124
- // Right is a string literal
125
- addStringPart(node.right.value)
139
+ // Right is a string literal - use raw value to preserve escape sequences
140
+ addStringPart(node.right)
126
141
  } else {
127
142
  // Right is some other expression
128
143
  addExpression(node.right)
@@ -135,12 +150,15 @@ export function concatToTemplateLiteral(j, root) {
135
150
 
136
151
  // Ensure we have the right number of quasis (one more than expressions)
137
152
  while (parts.length <= expressions.length) {
138
- parts.push("")
153
+ parts.push({ raw: "", cooked: "" })
139
154
  }
140
155
 
141
156
  // Create template literal
142
157
  const quasis = parts.map((part, i) =>
143
- j.templateElement({ raw: part, cooked: part }, i === parts.length - 1),
158
+ j.templateElement(
159
+ { raw: part.raw, cooked: part.cooked },
160
+ i === parts.length - 1,
161
+ ),
144
162
  )
145
163
 
146
164
  const templateLiteral = j.templateLiteral(quasis, expressions)
@@ -913,62 +931,6 @@ export function anonymousFunctionToArrow(j, root) {
913
931
  return found
914
932
  }
915
933
 
916
- // Helper to check if a node or its descendants use 'super'
917
- const usesSuper = (node) => {
918
- let found = false
919
-
920
- const visit = (n) => {
921
- if (!n || typeof n !== "object" || found) return
922
-
923
- // If we encounter a nested function, don't traverse into it
924
- // as it has its own 'super' binding context
925
- if (n.type === "FunctionExpression" || n.type === "FunctionDeclaration") {
926
- return
927
- }
928
-
929
- // Check if this is a 'super' node
930
- if (n.type === "Super") {
931
- found = true
932
- return
933
- }
934
-
935
- // Traverse all child nodes
936
- for (const key in n) {
937
- if (
938
- key === "loc" ||
939
- key === "start" ||
940
- key === "end" ||
941
- key === "tokens" ||
942
- key === "comments" ||
943
- key === "type"
944
- ) {
945
- continue
946
- }
947
- const value = n[key]
948
- if (Array.isArray(value)) {
949
- for (const item of value) {
950
- visit(item)
951
- if (found) return
952
- }
953
- } else if (value && typeof value === "object") {
954
- visit(value)
955
- }
956
- }
957
- }
958
-
959
- // Start visiting from the function body's child nodes
960
- // Don't check the body node itself, check its contents
961
- // Note: FunctionExpression.body is always a BlockStatement
962
- if (node.type === "BlockStatement" && node.body) {
963
- for (const statement of node.body) {
964
- visit(statement)
965
- if (found) break
966
- }
967
- }
968
-
969
- return found
970
- }
971
-
972
934
  root
973
935
  .find(j.FunctionExpression)
974
936
  .filter((path) => {
@@ -996,10 +958,8 @@ export function anonymousFunctionToArrow(j, root) {
996
958
  return false
997
959
  }
998
960
 
999
- // Skip if it uses 'super'
1000
- if (usesSuper(node.body)) {
1001
- return false
1002
- }
961
+ // Note: We don't need to check for 'super' because using super in a
962
+ // function expression is a syntax error and will never parse successfully
1003
963
 
1004
964
  return true
1005
965
  })
package/tests/cli.test.js CHANGED
@@ -1,6 +1,6 @@
1
- import { describe, test, beforeEach, afterEach } from "node:test"
2
- import assert from "node:assert"
3
- import { execSync, spawnSync } from "node:child_process"
1
+ import { afterEach, beforeEach, describe, test } from "node:test"
2
+ import assert from "node:assert/strict"
3
+ import { spawnSync } from "node:child_process"
4
4
  import fs from "node:fs"
5
5
  import path from "node:path"
6
6
  import os from "node:os"
@@ -20,50 +20,63 @@ describe("CLI", () => {
20
20
  }
21
21
  })
22
22
 
23
- test("should display help when no files specified", () => {
23
+ test("display help when no files specified", () => {
24
24
  const result = spawnSync(process.execPath, [CLI_PATH], {
25
25
  encoding: "utf8",
26
26
  })
27
27
 
28
- assert.match(result.stderr, /Error: No files specified/)
29
- // Commander shows help and exits with 0
30
- assert.strictEqual(result.status, 0)
28
+ assert.match(
29
+ result.stderr,
30
+ /Error: No files specified/,
31
+ "displays error for no files",
32
+ )
33
+ assert.equal(result.status, 0, "exits with 0 when showing help")
31
34
  })
32
35
 
33
- test("should transform a single file with --write", () => {
36
+ test("transform a single file with --write", () => {
34
37
  const testFile = path.join(tempDir, "test.js")
35
- const originalCode = `var x = 1;`
36
- fs.writeFileSync(testFile, originalCode)
38
+ fs.writeFileSync(testFile, `var x = 1;`)
37
39
 
38
40
  const result = spawnSync(process.execPath, [CLI_PATH, testFile, "--write"], {
39
41
  encoding: "utf8",
40
42
  })
41
43
 
42
- const transformedCode = fs.readFileSync(testFile, "utf8")
43
- assert.match(transformedCode, /const x = 1/)
44
- assert.match(result.stdout, /✓ 1 file\(s\) upgraded/)
45
- assert.strictEqual(result.status, 0)
44
+ assert.match(
45
+ fs.readFileSync(testFile, "utf8"),
46
+ /const x = 1/,
47
+ "transforms var to const",
48
+ )
49
+ assert.match(result.stdout, /✓ 1 file\(s\) upgraded/, "reports 1 file upgraded")
50
+ assert.equal(result.status, 0, "exits successfully")
46
51
  })
47
52
 
48
- test("should transform files with widely-available baseline by default", () => {
53
+ test("transform files with widely-available baseline by default", () => {
49
54
  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)
55
+ fs.writeFileSync(
56
+ testFile,
57
+ `var x = 1;\nconst p = new Promise((resolve) => resolve(getData()));`,
58
+ )
52
59
 
53
60
  const result = spawnSync(process.execPath, [CLI_PATH, testFile, "--write"], {
54
61
  encoding: "utf8",
55
62
  })
56
63
 
57
64
  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.strictEqual(result.status, 0)
65
+ assert.match(transformedCode, /const x = 1/, "transforms var to const")
66
+ assert.doesNotMatch(
67
+ transformedCode,
68
+ /Promise\.try/,
69
+ "excludes Promise.try for widely-available baseline",
70
+ )
71
+ assert.equal(result.status, 0, "exits successfully")
61
72
  })
62
73
 
63
- test("should transform files with newly-available baseline", () => {
74
+ test("transform files with newly-available baseline", () => {
64
75
  const testFile = path.join(tempDir, "test.js")
65
- const originalCode = `var x = 1;\nconst p = new Promise((resolve) => resolve(getData()));`
66
- fs.writeFileSync(testFile, originalCode)
76
+ fs.writeFileSync(
77
+ testFile,
78
+ `var x = 1;\nconst p = new Promise((resolve) => resolve(getData()));`,
79
+ )
67
80
 
68
81
  const result = spawnSync(
69
82
  process.execPath,
@@ -74,12 +87,16 @@ describe("CLI", () => {
74
87
  )
75
88
 
76
89
  const transformedCode = fs.readFileSync(testFile, "utf8")
77
- assert.match(transformedCode, /const x = 1/)
78
- assert.match(transformedCode, /Promise\.try/) // Promise.try in newly-available
79
- assert.strictEqual(result.status, 0)
90
+ assert.match(transformedCode, /const x = 1/, "transforms var to const")
91
+ assert.match(
92
+ transformedCode,
93
+ /Promise\.try/,
94
+ "includes Promise.try for newly-available baseline",
95
+ )
96
+ assert.equal(result.status, 0, "exits successfully")
80
97
  })
81
98
 
82
- test("should check files without writing with --check", () => {
99
+ test("check files without writing with --check", () => {
83
100
  const testFile = path.join(tempDir, "test.js")
84
101
  const originalCode = `var x = 1;`
85
102
  fs.writeFileSync(testFile, originalCode)
@@ -88,14 +105,21 @@ describe("CLI", () => {
88
105
  encoding: "utf8",
89
106
  })
90
107
 
91
- const fileContent = fs.readFileSync(testFile, "utf8")
92
- assert.strictEqual(fileContent, originalCode) // File unchanged
93
- assert.match(result.stdout, /✗/)
94
- assert.match(result.stdout, /1 file\(s\) need upgrading/)
95
- assert.strictEqual(result.status, 1) // Exit with code 1 when changes needed
108
+ assert.equal(
109
+ fs.readFileSync(testFile, "utf8"),
110
+ originalCode,
111
+ "leaves file unchanged",
112
+ )
113
+ assert.match(result.stdout, /✗/, "indicates changes needed")
114
+ assert.match(
115
+ result.stdout,
116
+ /1 file\(s\) need upgrading/,
117
+ "reports 1 file needs upgrading",
118
+ )
119
+ assert.equal(result.status, 1, "exits with 1 when changes needed")
96
120
  })
97
121
 
98
- test("should exit with 0 when --check and no changes needed", () => {
122
+ test("exit with 0 when --check and no changes needed", () => {
99
123
  const testFile = path.join(tempDir, "test.js")
100
124
  const originalCode = `const x = 1;`
101
125
  fs.writeFileSync(testFile, originalCode)
@@ -104,16 +128,22 @@ describe("CLI", () => {
104
128
  encoding: "utf8",
105
129
  })
106
130
 
107
- const fileContent = fs.readFileSync(testFile, "utf8")
108
- assert.strictEqual(fileContent, originalCode) // File unchanged
109
- assert.match(result.stdout, /All files are up to date/)
110
- assert.strictEqual(result.status, 0)
131
+ assert.equal(
132
+ fs.readFileSync(testFile, "utf8"),
133
+ originalCode,
134
+ "leaves file unchanged",
135
+ )
136
+ assert.match(
137
+ result.stdout,
138
+ /All files are up to date/,
139
+ "reports all files up to date",
140
+ )
141
+ assert.equal(result.status, 0, "exits with 0")
111
142
  })
112
143
 
113
- test("should support both --check and --write together", () => {
144
+ test("support both --check and --write together", () => {
114
145
  const testFile = path.join(tempDir, "test.js")
115
- const originalCode = `var x = 1;`
116
- fs.writeFileSync(testFile, originalCode)
146
+ fs.writeFileSync(testFile, `var x = 1;`)
117
147
 
118
148
  const result = spawnSync(
119
149
  process.execPath,
@@ -123,14 +153,17 @@ describe("CLI", () => {
123
153
  },
124
154
  )
125
155
 
126
- const transformedCode = fs.readFileSync(testFile, "utf8")
127
- assert.match(transformedCode, /const x = 1/)
128
- assert.match(result.stdout, /✗/)
129
- assert.match(result.stdout, /Changes have been written/)
130
- assert.strictEqual(result.status, 1) // Still exit 1 with --check
156
+ assert.match(
157
+ fs.readFileSync(testFile, "utf8"),
158
+ /const x = 1/,
159
+ "transforms var to const",
160
+ )
161
+ assert.match(result.stdout, /✗/, "indicates changes needed")
162
+ assert.match(result.stdout, /Changes have been written/, "reports changes written")
163
+ assert.equal(result.status, 1, "exits with 1 with --check")
131
164
  })
132
165
 
133
- test("should process directory recursively", () => {
166
+ test("process directory recursively", () => {
134
167
  const subDir = path.join(tempDir, "src")
135
168
  fs.mkdirSync(subDir)
136
169
 
@@ -143,36 +176,31 @@ describe("CLI", () => {
143
176
  encoding: "utf8",
144
177
  })
145
178
 
146
- const transformed1 = fs.readFileSync(file1, "utf8")
147
- const transformed2 = fs.readFileSync(file2, "utf8")
148
- assert.match(transformed1, /const x = 1/)
149
- assert.match(transformed2, /const y = 2/)
150
- assert.match(result.stdout, /2 file\(s\) upgraded/)
151
- assert.strictEqual(result.status, 0)
179
+ assert.match(fs.readFileSync(file1, "utf8"), /const x = 1/, "transforms file1")
180
+ assert.match(fs.readFileSync(file2, "utf8"), /const y = 2/, "transforms file2")
181
+ assert.match(result.stdout, /2 file\(s\) upgraded/, "reports 2 files upgraded")
182
+ assert.equal(result.status, 0, "exits successfully")
152
183
  })
153
184
 
154
- test("should skip node_modules and .git directories", () => {
185
+ test("skip node_modules and .git directories", () => {
155
186
  const nodeModules = path.join(tempDir, "node_modules")
156
187
  const gitDir = path.join(tempDir, ".git")
157
188
  fs.mkdirSync(nodeModules)
158
189
  fs.mkdirSync(gitDir)
159
190
 
160
191
  const file1 = path.join(tempDir, "test.js")
161
- const file2 = path.join(nodeModules, "test.js")
162
- const file3 = path.join(gitDir, "test.js")
163
192
  fs.writeFileSync(file1, `var x = 1;`)
164
- fs.writeFileSync(file2, `var y = 2;`)
165
- fs.writeFileSync(file3, `var z = 3;`)
193
+ fs.writeFileSync(path.join(nodeModules, "test.js"), `var y = 2;`)
194
+ fs.writeFileSync(path.join(gitDir, "test.js"), `var z = 3;`)
166
195
 
167
196
  const result = spawnSync(process.execPath, [CLI_PATH, tempDir, "--write"], {
168
197
  encoding: "utf8",
169
198
  })
170
199
 
171
- // Should only process file1 in tempDir, not in node_modules or .git
172
- assert.strictEqual(result.status, 0)
200
+ assert.equal(result.status, 0, "exits successfully skipping ignored dirs")
173
201
  })
174
202
 
175
- test("should process multiple file extensions", () => {
203
+ test("process multiple file extensions", () => {
176
204
  const jsFile = path.join(tempDir, "test.js")
177
205
  const mjsFile = path.join(tempDir, "test.mjs")
178
206
  const cjsFile = path.join(tempDir, "test.cjs")
@@ -187,11 +215,11 @@ describe("CLI", () => {
187
215
  encoding: "utf8",
188
216
  })
189
217
 
190
- assert.match(result.stdout, /4 file\(s\) upgraded/)
191
- assert.strictEqual(result.status, 0)
218
+ assert.match(result.stdout, /4 file\(s\) upgraded/, "reports 4 files upgraded")
219
+ assert.equal(result.status, 0, "exits successfully")
192
220
  })
193
221
 
194
- test("should handle TypeScript file extensions", () => {
222
+ test("handle TypeScript file extensions", () => {
195
223
  const tsFile = path.join(tempDir, "test.ts")
196
224
  const tsxFile = path.join(tempDir, "test.tsx")
197
225
 
@@ -202,10 +230,10 @@ describe("CLI", () => {
202
230
  encoding: "utf8",
203
231
  })
204
232
 
205
- assert.strictEqual(result.status, 0)
233
+ assert.equal(result.status, 0, "exits successfully for TS files")
206
234
  })
207
235
 
208
- test("should error on invalid baseline", () => {
236
+ test("error on invalid baseline", () => {
209
237
  const testFile = path.join(tempDir, "test.js")
210
238
  fs.writeFileSync(testFile, `var x = 1;`)
211
239
 
@@ -217,11 +245,11 @@ describe("CLI", () => {
217
245
  },
218
246
  )
219
247
 
220
- assert.match(result.stderr, /error/)
221
- assert.strictEqual(result.status, 1)
248
+ assert.match(result.stderr, /error/, "displays error for invalid baseline")
249
+ assert.equal(result.status, 1, "exits with 1")
222
250
  })
223
251
 
224
- test("should error on non-existent file", () => {
252
+ test("error on non-existent file", () => {
225
253
  const result = spawnSync(
226
254
  process.execPath,
227
255
  [CLI_PATH, path.join(tempDir, "nonexistent.js")],
@@ -230,24 +258,27 @@ describe("CLI", () => {
230
258
  },
231
259
  )
232
260
 
233
- assert.match(result.stderr, /Error: Cannot access/)
234
- assert.strictEqual(result.status, 1)
261
+ assert.match(
262
+ result.stderr,
263
+ /Error: Cannot access/,
264
+ "displays error for non-existent file",
265
+ )
266
+ assert.equal(result.status, 1, "exits with 1")
235
267
  })
236
268
 
237
- test("should show detailed changes with --check", () => {
269
+ test("show detailed changes with --check", () => {
238
270
  const testFile = path.join(tempDir, "test.js")
239
- const originalCode = `var x = 1;\nvar y = 2;`
240
- fs.writeFileSync(testFile, originalCode)
271
+ fs.writeFileSync(testFile, `var x = 1;\nvar y = 2;`)
241
272
 
242
273
  const result = spawnSync(process.execPath, [CLI_PATH, testFile, "--check"], {
243
274
  encoding: "utf8",
244
275
  })
245
276
 
246
- assert.match(result.stdout, /var to const/)
247
- assert.strictEqual(result.status, 1)
277
+ assert.match(result.stdout, /var to const/, "shows var to const changes")
278
+ assert.equal(result.status, 1, "exits with 1")
248
279
  })
249
280
 
250
- test("should process multiple files specified as arguments", () => {
281
+ test("process multiple files specified as arguments", () => {
251
282
  const file1 = path.join(tempDir, "test1.js")
252
283
  const file2 = path.join(tempDir, "test2.js")
253
284
  fs.writeFileSync(file1, `var x = 1;`)
@@ -257,15 +288,13 @@ describe("CLI", () => {
257
288
  encoding: "utf8",
258
289
  })
259
290
 
260
- const transformed1 = fs.readFileSync(file1, "utf8")
261
- const transformed2 = fs.readFileSync(file2, "utf8")
262
- assert.match(transformed1, /const x = 1/)
263
- assert.match(transformed2, /const y = 2/)
264
- assert.match(result.stdout, /2 file\(s\) upgraded/)
265
- assert.strictEqual(result.status, 0)
291
+ assert.match(fs.readFileSync(file1, "utf8"), /const x = 1/, "transforms file1")
292
+ assert.match(fs.readFileSync(file2, "utf8"), /const y = 2/, "transforms file2")
293
+ assert.match(result.stdout, /2 file\(s\) upgraded/, "reports 2 files upgraded")
294
+ assert.equal(result.status, 0, "exits successfully")
266
295
  })
267
296
 
268
- test("should handle files with no changes needed", () => {
297
+ test("handle files with no changes needed", () => {
269
298
  const testFile = path.join(tempDir, "test.js")
270
299
  const originalCode = `const x = 1;`
271
300
  fs.writeFileSync(testFile, originalCode)
@@ -274,13 +303,20 @@ describe("CLI", () => {
274
303
  encoding: "utf8",
275
304
  })
276
305
 
277
- const fileContent = fs.readFileSync(testFile, "utf8")
278
- assert.strictEqual(fileContent, originalCode)
279
- assert.match(result.stdout, /All files are up to date/)
280
- assert.strictEqual(result.status, 0)
306
+ assert.equal(
307
+ fs.readFileSync(testFile, "utf8"),
308
+ originalCode,
309
+ "leaves file unchanged",
310
+ )
311
+ assert.match(
312
+ result.stdout,
313
+ /All files are up to date/,
314
+ "reports all files up to date",
315
+ )
316
+ assert.equal(result.status, 0, "exits successfully")
281
317
  })
282
318
 
283
- test("should show no changes message for individual files", () => {
319
+ test("show no changes message for individual files", () => {
284
320
  const testFile = path.join(tempDir, "test.js")
285
321
  const originalCode = `const x = 1;`
286
322
  fs.writeFileSync(testFile, originalCode)
@@ -289,11 +325,15 @@ describe("CLI", () => {
289
325
  encoding: "utf8",
290
326
  })
291
327
 
292
- assert.match(result.stdout, /All files are up to date/)
293
- assert.strictEqual(result.status, 0)
328
+ assert.match(
329
+ result.stdout,
330
+ /All files are up to date/,
331
+ "reports all files up to date",
332
+ )
333
+ assert.equal(result.status, 0, "exits successfully")
294
334
  })
295
335
 
296
- test("should handle empty directory", () => {
336
+ test("handle empty directory", () => {
297
337
  const emptyDir = path.join(tempDir, "empty")
298
338
  fs.mkdirSync(emptyDir)
299
339
 
@@ -301,37 +341,39 @@ describe("CLI", () => {
301
341
  encoding: "utf8",
302
342
  })
303
343
 
304
- assert.match(result.stdout, /No JavaScript files found/)
305
- assert.strictEqual(result.status, 0)
344
+ assert.match(
345
+ result.stdout,
346
+ /No JavaScript files found/,
347
+ "reports no JS files found",
348
+ )
349
+ assert.equal(result.status, 0, "exits successfully")
306
350
  })
307
351
 
308
- test("should group changes by type in --check output", () => {
352
+ test("group changes by type in --check output", () => {
309
353
  const testFile = path.join(tempDir, "test.js")
310
- const originalCode = `var x = 1;\nvar y = 2;\nvar z = 3;`
311
- fs.writeFileSync(testFile, originalCode)
354
+ fs.writeFileSync(testFile, `var x = 1;\nvar y = 2;\nvar z = 3;`)
312
355
 
313
356
  const result = spawnSync(process.execPath, [CLI_PATH, testFile, "--check"], {
314
357
  encoding: "utf8",
315
358
  })
316
359
 
317
- assert.match(result.stdout, /var to const/)
318
- assert.strictEqual(result.status, 1)
360
+ assert.match(result.stdout, /var to const/, "shows var to const changes")
361
+ assert.equal(result.status, 1, "exits with 1")
319
362
  })
320
363
 
321
- test("should handle syntax errors gracefully", () => {
364
+ test("handle syntax errors gracefully", () => {
322
365
  const testFile = path.join(tempDir, "test.js")
323
- const invalidCode = `var x = {{{;`
324
- fs.writeFileSync(testFile, invalidCode)
366
+ fs.writeFileSync(testFile, `var x = {{{;`)
325
367
 
326
368
  const result = spawnSync(process.execPath, [CLI_PATH, testFile, "--write"], {
327
369
  encoding: "utf8",
328
370
  })
329
371
 
330
- assert.match(result.stderr, /✗ Error:/)
331
- assert.strictEqual(result.status, 0) // CLI continues despite errors
372
+ assert.match(result.stderr, /✗ Error:/, "displays error for syntax issues")
373
+ assert.equal(result.status, 0, "continues despite errors")
332
374
  })
333
375
 
334
- test("should handle mixed directory and file arguments", () => {
376
+ test("handle mixed directory and file arguments", () => {
335
377
  const subDir = path.join(tempDir, "src")
336
378
  fs.mkdirSync(subDir)
337
379
 
@@ -344,11 +386,9 @@ describe("CLI", () => {
344
386
  encoding: "utf8",
345
387
  })
346
388
 
347
- const file1Content = fs.readFileSync(file1, "utf8")
348
- const file2Content = fs.readFileSync(file2, "utf8")
349
- assert.match(file1Content, /const x = 1/)
350
- assert.match(file2Content, /const y = 2/)
351
- assert.match(result.stdout, /2 file\(s\) upgraded/)
352
- assert.strictEqual(result.status, 0)
389
+ assert.match(fs.readFileSync(file1, "utf8"), /const x = 1/, "transforms file1")
390
+ assert.match(fs.readFileSync(file2, "utf8"), /const y = 2/, "transforms file2")
391
+ assert.match(result.stdout, /2 file\(s\) upgraded/, "reports 2 files upgraded")
392
+ assert.equal(result.status, 0, "exits successfully")
353
393
  })
354
394
  })