readme-assert 7.2.1 → 7.3.0
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 +1 -1
- package/readme.md +6 -0
- package/src/comment-to-assert.js +46 -9
- package/src/generate.js +3 -1
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -103,6 +103,12 @@ Assert that a promise rejects with `// rejects`:
|
|
|
103
103
|
Promise.reject(new Error("no")) // rejects /no/
|
|
104
104
|
```
|
|
105
105
|
|
|
106
|
+
Or match the error name and message with `//=> rejects`:
|
|
107
|
+
|
|
108
|
+
```javascript test
|
|
109
|
+
Promise.reject(new TypeError("no")) //=> rejects TypeError: no
|
|
110
|
+
```
|
|
111
|
+
|
|
106
112
|
### TypeScript
|
|
107
113
|
|
|
108
114
|
TypeScript code blocks are supported natively:
|
package/src/comment-to-assert.js
CHANGED
|
@@ -11,6 +11,10 @@ import MagicString from "magic-string";
|
|
|
11
11
|
* console.log(x) //=> v → console.log(x); assert.deepEqual(x, v)
|
|
12
12
|
* expr //=> resolves to v → assert.deepEqual(await expr, v)
|
|
13
13
|
* expr // rejects /pat/ → assert.rejects(() => expr, /pat/)
|
|
14
|
+
* expr //=> rejects Error: msg → assert.rejects(() => expr, { message: "msg" })
|
|
15
|
+
*
|
|
16
|
+
* When the expression is an AwaitExpression, throws/Error assertions are
|
|
17
|
+
* promoted to async rejects (await converts rejection → throw).
|
|
14
18
|
*
|
|
15
19
|
* Uses oxc-parser for AST + comment extraction. Handles both JS and TS.
|
|
16
20
|
*
|
|
@@ -33,6 +37,8 @@ export function commentToAssert(code, { typescript = false } = {}) {
|
|
|
33
37
|
const comment = findTrailingComment(comments, node, code);
|
|
34
38
|
if (!comment) continue;
|
|
35
39
|
|
|
40
|
+
const isAwait = node.expression.type === "AwaitExpression";
|
|
41
|
+
|
|
36
42
|
const match = comment.value.match(/^\s*(=>|→|->)\s*([\s\S]*)$/);
|
|
37
43
|
const throwsMatch = comment.value.match(/^\s*throws\s+([\s\S]*)$/);
|
|
38
44
|
const rejectsMatch = comment.value.match(/^\s*rejects\s+([\s\S]*)$/);
|
|
@@ -40,6 +46,9 @@ export function commentToAssert(code, { typescript = false } = {}) {
|
|
|
40
46
|
if (match) {
|
|
41
47
|
const rest = match[2].trim();
|
|
42
48
|
const resolvesMatch = rest.match(/^resolves\s+(?:to\s+)?([\s\S]*)$/);
|
|
49
|
+
const rejectsErrorMatch = rest.match(
|
|
50
|
+
/^rejects\s+((?:[A-Z]\w+)?Error)(?::\s*(.*))?$/,
|
|
51
|
+
);
|
|
43
52
|
changed = true;
|
|
44
53
|
|
|
45
54
|
const errorMatch = rest.match(/^((?:[A-Z]\w+)?Error)(?::\s*(.*))?$/);
|
|
@@ -56,8 +65,28 @@ export function commentToAssert(code, { typescript = false } = {}) {
|
|
|
56
65
|
comment.end,
|
|
57
66
|
`assert.deepEqual(await ${exprSource}, ${expected});`,
|
|
58
67
|
);
|
|
68
|
+
} else if (rejectsErrorMatch) {
|
|
69
|
+
// expr //=> rejects TypeError: msg → assert.rejects(() => expr, { name, message })
|
|
70
|
+
const errorName = rejectsErrorMatch[1];
|
|
71
|
+
const errorMessage = rejectsErrorMatch[2]?.trim();
|
|
72
|
+
const exprSource = code.slice(
|
|
73
|
+
node.expression.start,
|
|
74
|
+
node.expression.end,
|
|
75
|
+
);
|
|
76
|
+
const props = [`name: "${errorName}"`];
|
|
77
|
+
if (errorMessage) {
|
|
78
|
+
props.push(formatMessageProp(errorMessage));
|
|
79
|
+
}
|
|
80
|
+
s.overwrite(
|
|
81
|
+
node.start,
|
|
82
|
+
comment.end,
|
|
83
|
+
isAwait
|
|
84
|
+
? `await assert.rejects(async () => { ${exprSource}; }, { ${props.join(", ")} });`
|
|
85
|
+
: `await assert.rejects(() => ${exprSource}, { ${props.join(", ")} });`,
|
|
86
|
+
);
|
|
59
87
|
} else if (errorMatch) {
|
|
60
88
|
// expr //=> TypeError: msg → assert.throws(() => { expr }, { name, message })
|
|
89
|
+
// await expr //=> Error: msg → assert.rejects(async () => { expr }, { name, message })
|
|
61
90
|
const errorName = errorMatch[1];
|
|
62
91
|
const errorMessage = errorMatch[2]?.trim();
|
|
63
92
|
const exprSource = code.slice(
|
|
@@ -66,17 +95,14 @@ export function commentToAssert(code, { typescript = false } = {}) {
|
|
|
66
95
|
);
|
|
67
96
|
const props = [`name: "${errorName}"`];
|
|
68
97
|
if (errorMessage) {
|
|
69
|
-
|
|
70
|
-
props.push(
|
|
71
|
-
reMatch
|
|
72
|
-
? `message: /${reMatch[1]}/${reMatch[2]}`
|
|
73
|
-
: `message: "${errorMessage}"`,
|
|
74
|
-
);
|
|
98
|
+
props.push(formatMessageProp(errorMessage));
|
|
75
99
|
}
|
|
76
100
|
s.overwrite(
|
|
77
101
|
node.start,
|
|
78
102
|
comment.end,
|
|
79
|
-
|
|
103
|
+
isAwait
|
|
104
|
+
? `await assert.rejects(async () => { ${exprSource}; }, { ${props.join(", ")} });`
|
|
105
|
+
: `assert.throws(() => { ${exprSource}; }, { ${props.join(", ")} });`,
|
|
80
106
|
);
|
|
81
107
|
} else if (isConsoleCall(node.expression)) {
|
|
82
108
|
// console.log(expr) //=> value → keep log, add assertion after.
|
|
@@ -112,7 +138,9 @@ export function commentToAssert(code, { typescript = false } = {}) {
|
|
|
112
138
|
s.overwrite(
|
|
113
139
|
node.start,
|
|
114
140
|
comment.end,
|
|
115
|
-
|
|
141
|
+
isAwait
|
|
142
|
+
? `await assert.rejects(async () => { ${exprSource}; }, ${pattern});`
|
|
143
|
+
: `assert.throws(() => { ${exprSource}; }, ${pattern});`,
|
|
116
144
|
);
|
|
117
145
|
changed = true;
|
|
118
146
|
} else if (rejectsMatch) {
|
|
@@ -124,7 +152,9 @@ export function commentToAssert(code, { typescript = false } = {}) {
|
|
|
124
152
|
s.overwrite(
|
|
125
153
|
node.start,
|
|
126
154
|
comment.end,
|
|
127
|
-
|
|
155
|
+
isAwait
|
|
156
|
+
? `await assert.rejects(async () => { ${exprSource}; }, ${pattern});`
|
|
157
|
+
: `await assert.rejects(() => ${exprSource}, ${pattern});`,
|
|
128
158
|
);
|
|
129
159
|
changed = true;
|
|
130
160
|
}
|
|
@@ -153,6 +183,13 @@ function findTrailingComment(comments, node, code) {
|
|
|
153
183
|
return null;
|
|
154
184
|
}
|
|
155
185
|
|
|
186
|
+
function formatMessageProp(msg) {
|
|
187
|
+
const reMatch = msg.match(/^\/(.+)\/([gimsuy]*)$/);
|
|
188
|
+
return reMatch
|
|
189
|
+
? `message: /${reMatch[1]}/${reMatch[2]}`
|
|
190
|
+
: `message: "${msg}"`;
|
|
191
|
+
}
|
|
192
|
+
|
|
156
193
|
function isConsoleCall(expr) {
|
|
157
194
|
return (
|
|
158
195
|
expr.type === "CallExpression" &&
|
package/src/generate.js
CHANGED
|
@@ -66,7 +66,9 @@ function assembleUnit(blocks) {
|
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
const hasESM = imports.length > 0;
|
|
69
|
-
const
|
|
69
|
+
const body = bodyLines.join("\n");
|
|
70
|
+
const hasAwait = /\bawait\s/.test(body);
|
|
71
|
+
const hasCJS = !hasAwait && /\brequire\s*\(/.test(body);
|
|
70
72
|
|
|
71
73
|
// Place assert import on line 0 (before markdown line 1) so line numbers
|
|
72
74
|
// in the generated code match the original markdown positions exactly.
|