@checkdigit/eslint-plugin 7.6.0-PR.75-4751 → 7.6.0-PR.75-a611

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.
@@ -1,332 +0,0 @@
1
- // src/agent/no-supertest.ts
2
- import { strict as assert } from "node:assert";
3
- import { AST_NODE_TYPES, ESLintUtils } from "@typescript-eslint/utils";
4
- import {
5
- getEnclosingFunction,
6
- getEnclosingScopeNode,
7
- getEnclosingStatement,
8
- getParent,
9
- isUsedInArrayOrAsArgument
10
- } from "../library/ts-tree.mjs";
11
- import getDocumentationUrl from "../get-documentation-url.mjs";
12
- import { getIndentation } from "../library/format.mjs";
13
- import { analyzeResponseReferences } from "./response-reference.mjs";
14
- import { getResponseBodyRetrievalText, getResponseHeadersRetrievalText, getResponseStatusRetrievalText } from "./fetch.mjs";
15
- var ruleId = "no-supertest";
16
- function analyzeFixtureCall(call, results, sourceCode) {
17
- const parent = getParent(call);
18
- assert.ok(parent, "parent should exist for fixture/supertest call node");
19
- let nextCall;
20
- if (parent.type === AST_NODE_TYPES.ReturnStatement) {
21
- results.fixtureNode = call;
22
- results.rootNode = parent;
23
- } else if (parent.type === AST_NODE_TYPES.ArrayExpression || parent.type === AST_NODE_TYPES.CallExpression || parent.type === AST_NODE_TYPES.ArrowFunctionExpression) {
24
- results.fixtureNode = call;
25
- results.rootNode = call;
26
- } else if (parent.type === AST_NODE_TYPES.AwaitExpression) {
27
- results.fixtureNode = call;
28
- const enclosingStatement = getEnclosingStatement(parent);
29
- assert.ok(enclosingStatement);
30
- const awaitParent = getParent(parent);
31
- if (awaitParent?.type === AST_NODE_TYPES.MemberExpression) {
32
- results.rootNode = parent;
33
- results.inlineStatementNode = enclosingStatement;
34
- if (awaitParent.property.type === AST_NODE_TYPES.Identifier && awaitParent.property.name === "body") {
35
- results.inlineBodyReference = awaitParent;
36
- }
37
- if (awaitParent.property.type === AST_NODE_TYPES.Identifier && (awaitParent.property.name === "status" || awaitParent.property.name === "statusCode")) {
38
- results.inlineStatusReference = awaitParent;
39
- }
40
- if (awaitParent.property.type === AST_NODE_TYPES.Identifier && (awaitParent.property.name === "header" || awaitParent.property.name === "headers")) {
41
- results.inlineHeadersReference = awaitParent;
42
- }
43
- } else if (enclosingStatement.type === AST_NODE_TYPES.VariableDeclaration) {
44
- results.variableDeclaration = enclosingStatement;
45
- results.rootNode = enclosingStatement;
46
- } else if (enclosingStatement.type === AST_NODE_TYPES.ExpressionStatement && enclosingStatement.expression.type === AST_NODE_TYPES.AssignmentExpression) {
47
- results.variableAssignment = enclosingStatement;
48
- results.rootNode = enclosingStatement;
49
- } else {
50
- results.rootNode = parent;
51
- }
52
- } else if (parent.type === AST_NODE_TYPES.MemberExpression && parent.property.type === AST_NODE_TYPES.Identifier) {
53
- if (parent.property.name === "expect") {
54
- const assertionCall = getParent(parent);
55
- assert.ok(assertionCall && assertionCall.type === AST_NODE_TYPES.CallExpression);
56
- results.assertions = [...results.assertions ?? [], assertionCall.arguments];
57
- nextCall = assertionCall;
58
- }
59
- } else {
60
- throw new Error(`Unexpected expression in fixture/supertest call ${sourceCode.getText(parent)}.`);
61
- }
62
- if (nextCall) {
63
- analyzeFixtureCall(nextCall, results, sourceCode);
64
- }
65
- }
66
- function createResponseAssertions(fixtureCallInformation, sourceCode, responseVariableName, destructuringResponseHeadersVariable) {
67
- let statusAssertion;
68
- const nonStatusAssertions = [];
69
- for (const expectArguments of fixtureCallInformation.assertions ?? []) {
70
- if (expectArguments.length === 1) {
71
- const [assertionArgument] = expectArguments;
72
- assert.ok(assertionArgument);
73
- if (assertionArgument.type === AST_NODE_TYPES.MemberExpression && assertionArgument.object.type === AST_NODE_TYPES.Identifier && assertionArgument.object.name === "StatusCodes" || assertionArgument.type === AST_NODE_TYPES.Literal || sourceCode.getText(assertionArgument).includes("StatusCodes.")) {
74
- statusAssertion = `assert.equal(${responseVariableName}.status, ${sourceCode.getText(assertionArgument)})`;
75
- } else if (assertionArgument.type === AST_NODE_TYPES.ArrowFunctionExpression) {
76
- let functionBody = sourceCode.getText(assertionArgument.body);
77
- const [originalResponseArgument] = assertionArgument.params;
78
- assert.ok(originalResponseArgument?.type === AST_NODE_TYPES.Identifier);
79
- const originalResponseArgumentName = originalResponseArgument.name;
80
- if (originalResponseArgumentName !== responseVariableName) {
81
- functionBody = functionBody.replace(
82
- new RegExp(`\\b${originalResponseArgumentName}\\b`, "ug"),
83
- responseVariableName
84
- );
85
- }
86
- nonStatusAssertions.push(`assert.doesNotThrow(()=>${functionBody})`);
87
- } else if (assertionArgument.type === AST_NODE_TYPES.Identifier) {
88
- nonStatusAssertions.push(
89
- `assert.doesNotThrow(()=>${sourceCode.getText(assertionArgument)}(${responseVariableName}))`
90
- );
91
- } else if (assertionArgument.type === AST_NODE_TYPES.ObjectExpression || assertionArgument.type === AST_NODE_TYPES.CallExpression) {
92
- nonStatusAssertions.push(
93
- `assert.deepEqual(await ${responseVariableName}.json(), ${sourceCode.getText(assertionArgument)})`
94
- );
95
- } else {
96
- throw new Error(`Unexpected Supertest assertion argument: ".expect(${sourceCode.getText(assertionArgument)})`);
97
- }
98
- } else if (expectArguments.length === 2) {
99
- const [headerName, headerValue] = expectArguments;
100
- assert.ok(headerName && headerValue);
101
- const headersReference = destructuringResponseHeadersVariable !== void 0 ? destructuringResponseHeadersVariable.name : `${responseVariableName}.headers`;
102
- if (headerValue.type === AST_NODE_TYPES.Literal && headerValue.value instanceof RegExp) {
103
- nonStatusAssertions.push(
104
- `assert.ok(${headersReference}.get(${sourceCode.getText(headerName)}).match(${sourceCode.getText(headerValue)}))`
105
- );
106
- } else {
107
- nonStatusAssertions.push(
108
- `assert.equal(${headersReference}.get(${sourceCode.getText(headerName)}), ${sourceCode.getText(headerValue)})`
109
- );
110
- }
111
- }
112
- }
113
- return {
114
- statusAssertion,
115
- nonStatusAssertions
116
- };
117
- }
118
- function getResponseVariableNameToUse(supertestFunctionName, scopeManager, fixtureCallInformation, scopeVariablesMap) {
119
- if (fixtureCallInformation.variableAssignment) {
120
- assert.ok(
121
- fixtureCallInformation.variableAssignment.expression.type === AST_NODE_TYPES.AssignmentExpression && fixtureCallInformation.variableAssignment.expression.left.type === AST_NODE_TYPES.Identifier
122
- );
123
- return fixtureCallInformation.variableAssignment.expression.left.name;
124
- }
125
- if (fixtureCallInformation.variableDeclaration) {
126
- const firstDeclaration = fixtureCallInformation.variableDeclaration.declarations[0];
127
- if (firstDeclaration !== void 0 && firstDeclaration.id.type === AST_NODE_TYPES.Identifier) {
128
- return firstDeclaration.id.name;
129
- }
130
- }
131
- const enclosingScopeNode = getEnclosingScopeNode(fixtureCallInformation.rootNode);
132
- scopeManager.getDeclaredVariables(fixtureCallInformation.rootNode);
133
- assert.ok(enclosingScopeNode);
134
- const scope = scopeManager.acquire(enclosingScopeNode);
135
- assert.ok(scope !== null);
136
- let scopeVariables = scopeVariablesMap.get(scope);
137
- if (!scopeVariables) {
138
- scopeVariables = [...scope.set.keys()];
139
- scopeVariablesMap.set(scope, scopeVariables);
140
- }
141
- let responseVariableCounter = 0;
142
- let responseVariableNameToUse;
143
- while (responseVariableNameToUse === void 0) {
144
- responseVariableNameToUse = `${supertestFunctionName}Response${responseVariableCounter === 0 ? "" : responseVariableCounter.toString()}`;
145
- if (scopeVariables.includes(responseVariableNameToUse)) {
146
- responseVariableNameToUse = void 0;
147
- }
148
- responseVariableCounter++;
149
- }
150
- scopeVariables.push(responseVariableNameToUse);
151
- return responseVariableNameToUse;
152
- }
153
- function isResponseBodyRedefinition(responseBodyReference) {
154
- const parent = getParent(responseBodyReference);
155
- return parent?.type === AST_NODE_TYPES.VariableDeclarator && parent.id.type === AST_NODE_TYPES.Identifier;
156
- }
157
- var createRule = ESLintUtils.RuleCreator((name) => getDocumentationUrl(name));
158
- var rule = createRule({
159
- name: ruleId,
160
- meta: {
161
- type: "suggestion",
162
- docs: {
163
- description: "Transform supertest assersions to regular node assertions.",
164
- url: getDocumentationUrl(ruleId)
165
- },
166
- messages: {
167
- preferNativeFetch: "Transform supertest assersions to regular node assertions.",
168
- unknownError: 'Unknown error occurred in file "{{fileName}}": {{ error }}.'
169
- },
170
- fixable: "code",
171
- schema: []
172
- },
173
- defaultOptions: [],
174
- // eslint-disable-next-line max-lines-per-function
175
- create(context) {
176
- const sourceCode = context.sourceCode;
177
- const scopeManager = sourceCode.scopeManager;
178
- assert.ok(scopeManager !== null);
179
- const scopeVariablesMap = /* @__PURE__ */ new Map();
180
- return {
181
- // eslint-disable-next-line max-lines-per-function
182
- 'CallExpression[callee.property.name="expect"]': (supertestCall) => {
183
- try {
184
- assert.ok(supertestCall.callee.type === AST_NODE_TYPES.MemberExpression);
185
- if (supertestCall.callee.object.type !== AST_NODE_TYPES.CallExpression || supertestCall.callee.object.callee.type === AST_NODE_TYPES.MemberExpression && supertestCall.callee.object.callee.property.type === AST_NODE_TYPES.Identifier && supertestCall.callee.object.callee.property.name === "expect") {
186
- return;
187
- }
188
- if (supertestCall.callee.object.callee.type === AST_NODE_TYPES.MemberExpression && supertestCall.callee.object.callee.object.type === AST_NODE_TYPES.MemberExpression && supertestCall.callee.object.callee.object.object.type === AST_NODE_TYPES.Identifier && supertestCall.callee.object.callee.object.object.name === "fixture" && supertestCall.callee.object.callee.object.property.type === AST_NODE_TYPES.Identifier && supertestCall.callee.object.callee.object.property.name === "api") {
189
- return;
190
- }
191
- const fullSupertestFunctionName = sourceCode.getText(supertestCall.callee.object.callee);
192
- const supertestFunctionName = fullSupertestFunctionName.split(".").pop();
193
- assert.ok(supertestFunctionName !== void 0);
194
- if (isUsedInArrayOrAsArgument(supertestCall) || getEnclosingFunction(supertestCall)?.async === false) {
195
- return;
196
- }
197
- const indentation = getIndentation(supertestCall, sourceCode);
198
- const fixtureCallInformation = {};
199
- const fixtureFunction = supertestCall.callee.object;
200
- analyzeFixtureCall(fixtureFunction, fixtureCallInformation, sourceCode);
201
- fixtureCallInformation.assertions?.flat().map((ass) => sourceCode.getText(ass));
202
- const {
203
- variable: responseVariable,
204
- bodyReferences: responseBodyReferences,
205
- // headersReferences: responseHeadersReferences,
206
- statusReferences: responseStatusReferences,
207
- destructuringBodyVariable: destructuringResponseBodyVariable,
208
- destructuringHeadersVariable: destructuringResponseHeadersVariable,
209
- destructuringStatusVariable: destructuringResponseStatusVariable
210
- } = analyzeResponseReferences(fixtureCallInformation.variableDeclaration, scopeManager);
211
- const responseVariableNameToUse = getResponseVariableNameToUse(
212
- supertestFunctionName,
213
- scopeManager,
214
- fixtureCallInformation,
215
- scopeVariablesMap
216
- );
217
- const isResponseBodyVariableRedefinitionNeeded = destructuringResponseBodyVariable !== void 0 || fixtureCallInformation.inlineBodyReference !== void 0 || responseBodyReferences.length > 0 && !responseBodyReferences.some(isResponseBodyRedefinition);
218
- const redefineResponseBodyVariableName = `${responseVariableNameToUse}Body`;
219
- const isResponseStatusVariableRedefinitionNeeded = destructuringResponseStatusVariable !== void 0 || fixtureCallInformation.inlineStatusReference !== void 0;
220
- const redefineResponseStatusVariableName = `${responseVariableNameToUse}Status`;
221
- const isResponseHeadersVariableRedefinitionNeeded = destructuringResponseHeadersVariable !== void 0 && // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
222
- destructuringResponseHeadersVariable.type === AST_NODE_TYPES.ObjectPattern || fixtureCallInformation.inlineHeadersReference !== void 0;
223
- const redefineResponseHeadersVariableName = `${responseVariableNameToUse}Headers`;
224
- const isResponseVariableRedefinitionNeeded = fixtureCallInformation.variableAssignment === void 0 && responseVariable === void 0 && fixtureCallInformation.assertions !== void 0 || isResponseBodyVariableRedefinitionNeeded || isResponseStatusVariableRedefinitionNeeded || isResponseHeadersVariableRedefinitionNeeded;
225
- const responseBodyHeadersVariableRedefineLines = isResponseVariableRedefinitionNeeded ? [
226
- // eslint-disable-next-line no-nested-ternary
227
- ...destructuringResponseBodyVariable ? [
228
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
229
- `${fixtureCallInformation.variableDeclaration?.kind ?? "const"} ${destructuringResponseBodyVariable.type === AST_NODE_TYPES.ObjectPattern ? sourceCode.getText(destructuringResponseBodyVariable) : destructuringResponseBodyVariable.name} = ${getResponseBodyRetrievalText(responseVariableNameToUse)}`
230
- ] : isResponseBodyVariableRedefinitionNeeded ? [
231
- `const ${redefineResponseBodyVariableName} = ${getResponseBodyRetrievalText(responseVariableNameToUse)}`
232
- ] : [],
233
- // eslint-disable-next-line no-nested-ternary
234
- ...destructuringResponseStatusVariable ? [
235
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
236
- `${fixtureCallInformation.variableDeclaration?.kind ?? "const"} ${destructuringResponseStatusVariable.type === AST_NODE_TYPES.ObjectPattern ? sourceCode.getText(destructuringResponseStatusVariable) : destructuringResponseStatusVariable.name} = ${getResponseStatusRetrievalText(responseVariableNameToUse)}`
237
- ] : isResponseStatusVariableRedefinitionNeeded ? [
238
- `const ${redefineResponseStatusVariableName} = ${getResponseStatusRetrievalText(responseVariableNameToUse)}`
239
- ] : [],
240
- // eslint-disable-next-line no-nested-ternary
241
- ...destructuringResponseHeadersVariable ? (
242
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
243
- destructuringResponseHeadersVariable.type === AST_NODE_TYPES.ObjectPattern ? destructuringResponseHeadersVariable.properties.map((property) => {
244
- assert.ok(property.type === AST_NODE_TYPES.Property);
245
- assert.ok(property.value.type === AST_NODE_TYPES.Identifier);
246
- return `${fixtureCallInformation.variableDeclaration?.kind ?? "const"} ${property.value.name} = ${getResponseHeadersRetrievalText(responseVariableNameToUse)}.get(${property.key.type === AST_NODE_TYPES.Literal ? sourceCode.getText(property.key) : `'${sourceCode.getText(property.key)}'`})`;
247
- }) : [
248
- `${fixtureCallInformation.variableDeclaration?.kind ?? "const"} ${destructuringResponseHeadersVariable.name} = ${getResponseHeadersRetrievalText(responseVariableNameToUse)}`
249
- ]
250
- ) : isResponseHeadersVariableRedefinitionNeeded ? [
251
- `const ${redefineResponseHeadersVariableName} = ${getResponseHeadersRetrievalText(responseVariableNameToUse)}`
252
- ] : []
253
- ] : [];
254
- const { statusAssertion, nonStatusAssertions } = createResponseAssertions(
255
- fixtureCallInformation,
256
- sourceCode,
257
- responseVariableNameToUse,
258
- destructuringResponseHeadersVariable
259
- );
260
- const fetchCallText = sourceCode.getText(fixtureFunction);
261
- const fetchStatementText = !isResponseVariableRedefinitionNeeded ? fetchCallText : `${fixtureCallInformation.variableDeclaration?.kind ?? "const"} ${responseVariableNameToUse} = await ${fetchCallText}`;
262
- const nodeToReplace = isResponseVariableRedefinitionNeeded ? fixtureCallInformation.rootNode : fixtureCallInformation.fixtureNode;
263
- const appendingAssignmentAndAssertionText = [
264
- "",
265
- ...statusAssertion !== void 0 ? [statusAssertion] : [],
266
- ...responseBodyHeadersVariableRedefineLines,
267
- ...nonStatusAssertions
268
- ].join(`;
269
- ${indentation}`);
270
- context.report({
271
- node: supertestCall,
272
- messageId: "preferNativeFetch",
273
- *fix(fixer) {
274
- if (fixtureCallInformation.inlineStatementNode) {
275
- const preInlineDeclaration = [
276
- fetchStatementText,
277
- `${appendingAssignmentAndAssertionText};
278
- ${indentation}`
279
- ].join(``);
280
- yield fixer.insertTextBefore(fixtureCallInformation.inlineStatementNode, preInlineDeclaration);
281
- } else {
282
- yield fixer.replaceText(nodeToReplace, fetchStatementText);
283
- const needEndingSemiColon = sourceCode.getText(nodeToReplace).endsWith(";");
284
- yield fixer.insertTextAfter(
285
- nodeToReplace,
286
- needEndingSemiColon ? `${appendingAssignmentAndAssertionText};` : appendingAssignmentAndAssertionText
287
- );
288
- }
289
- for (const responseBodyReference of responseBodyReferences) {
290
- yield fixer.replaceText(
291
- responseBodyReference,
292
- isResponseBodyVariableRedefinitionNeeded || !isResponseBodyRedefinition(responseBodyReference) ? redefineResponseBodyVariableName : getResponseBodyRetrievalText(responseVariableNameToUse)
293
- );
294
- }
295
- if (fixtureCallInformation.inlineBodyReference) {
296
- yield fixer.replaceText(fixtureCallInformation.inlineBodyReference, redefineResponseBodyVariableName);
297
- }
298
- for (const responseStatusReference of responseStatusReferences) {
299
- if (responseStatusReference.property.type === AST_NODE_TYPES.Identifier && responseStatusReference.property.name === "statusCode") {
300
- yield fixer.replaceText(responseStatusReference.property, `status`);
301
- }
302
- }
303
- if (fixtureCallInformation.rootNode.type === AST_NODE_TYPES.ReturnStatement && fixtureCallInformation.assertions !== void 0) {
304
- yield fixer.insertTextAfter(
305
- fixtureCallInformation.rootNode,
306
- `
307
- ${indentation}return ${responseVariableNameToUse};`
308
- );
309
- }
310
- }
311
- });
312
- } catch (error) {
313
- console.error(`Failed to apply ${ruleId} rule for file "${context.filename}":`, error);
314
- context.report({
315
- node: supertestCall,
316
- messageId: "unknownError",
317
- data: {
318
- fileName: context.filename,
319
- error: error instanceof Error ? error.toString() : JSON.stringify(error)
320
- }
321
- });
322
- }
323
- }
324
- };
325
- }
326
- });
327
- var no_supertest_default = rule;
328
- export {
329
- no_supertest_default as default,
330
- ruleId
331
- };
332
- //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL2FnZW50L25vLXN1cGVydGVzdC50cyJdLAogICJtYXBwaW5ncyI6ICI7QUFRQSxTQUFTLFVBQVUsY0FBYztBQUVqQyxTQUFTLGdCQUFnQixtQkFBNkI7QUFJdEQ7QUFBQSxFQUNFO0FBQUEsRUFDQTtBQUFBLEVBQ0E7QUFBQSxFQUNBO0FBQUEsRUFDQTtBQUFBLE9BQ0s7QUFDUCxPQUFPLHlCQUF5QjtBQUNoQyxTQUFTLHNCQUFzQjtBQUMvQixTQUFTLGlDQUFpQztBQUMxQyxTQUFTLDhCQUE4QixpQ0FBaUMsc0NBQXNDO0FBRXZHLElBQU0sU0FBUztBQXFCdEIsU0FBUyxtQkFBbUIsTUFBK0IsU0FBaUMsWUFBd0I7QUFDbEgsUUFBTSxTQUFTLFVBQVUsSUFBSTtBQUM3QixTQUFPLEdBQUcsUUFBUSxxREFBcUQ7QUFFdkUsTUFBSTtBQUNKLE1BQUksT0FBTyxTQUFTLGVBQWUsaUJBQWlCO0FBRWxELFlBQVEsY0FBYztBQUN0QixZQUFRLFdBQVc7QUFBQSxFQUNyQixXQUNFLE9BQU8sU0FBUyxlQUFlLG1CQUMvQixPQUFPLFNBQVMsZUFBZSxrQkFDL0IsT0FBTyxTQUFTLGVBQWUseUJBQy9CO0FBRUEsWUFBUSxjQUFjO0FBQ3RCLFlBQVEsV0FBVztBQUFBLEVBQ3JCLFdBQVcsT0FBTyxTQUFTLGVBQWUsaUJBQWlCO0FBQ3pELFlBQVEsY0FBYztBQUN0QixVQUFNLHFCQUFxQixzQkFBc0IsTUFBTTtBQUN2RCxXQUFPLEdBQUcsa0JBQWtCO0FBQzVCLFVBQU0sY0FBYyxVQUFVLE1BQU07QUFDcEMsUUFBSSxhQUFhLFNBQVMsZUFBZSxrQkFBa0I7QUFDekQsY0FBUSxXQUFXO0FBQ25CLGNBQVEsc0JBQXNCO0FBQzlCLFVBQUksWUFBWSxTQUFTLFNBQVMsZUFBZSxjQUFjLFlBQVksU0FBUyxTQUFTLFFBQVE7QUFDbkcsZ0JBQVEsc0JBQXNCO0FBQUEsTUFDaEM7QUFDQSxVQUNFLFlBQVksU0FBUyxTQUFTLGVBQWUsZUFDNUMsWUFB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