@checkdigit/eslint-plugin 6.6.0-PR.75-f33d → 6.6.0-PR.75-9891

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,98 +0,0 @@
1
- // src/no-fixture-headers.ts
2
- import { getEnclosingScopeNode, getParent } from "./ast/tree.mjs";
3
- import "eslint";
4
- import { strict as assert } from "node:assert";
5
- import getDocumentationUrl from "./get-documentation-url.mjs";
6
- var ruleId = "no-fixture-headers";
7
- var rule = {
8
- meta: {
9
- type: "suggestion",
10
- docs: {
11
- description: "Prefer native fetch API over customized fixture API.",
12
- url: getDocumentationUrl(ruleId)
13
- },
14
- messages: {
15
- preferNativeFetch: "Prefer native fetch API over customized fixture API.",
16
- unknownError: 'Unknown error occurred in file "{{fileName}}": {{ error }}. Please manually convert the fixture API call to fetch API call.'
17
- },
18
- fixable: "code",
19
- schema: []
20
- },
21
- // eslint-disable-next-line max-lines-per-function
22
- create(context) {
23
- const sourceCode = context.sourceCode;
24
- const scopeManager = sourceCode.scopeManager;
25
- return {
26
- // eslint-disable-next-line max-lines-per-function
27
- 'VariableDeclarator[init.argument.callee.name="fetch"]': (fetchCall) => {
28
- try {
29
- const enclosingScopeNode = getEnclosingScopeNode(fetchCall);
30
- assert.ok(fetchCall.id.type === "Identifier");
31
- const fetchVariableName = fetchCall.id.name;
32
- assert.ok(enclosingScopeNode !== void 0, "enclosing scope node should exist");
33
- const scope = scopeManager.acquire(enclosingScopeNode);
34
- const responseVariable = scope?.variables.find((variable) => {
35
- const identifier = variable.identifiers[0];
36
- return identifier?.type === "Identifier" && identifier.name === fetchVariableName;
37
- });
38
- if (responseVariable === void 0) {
39
- return;
40
- }
41
- const headersReferences = responseVariable.references.map((reference) => getParent(reference.identifier)).filter(
42
- (parent) => parent?.type === "MemberExpression" && parent.property.type === "Identifier" && parent.property.name === "headers"
43
- );
44
- const directHeadersReferences = headersReferences.map(getParent).filter(
45
- (parent) => parent?.type === "MemberExpression" && !(parent.property.type === "Identifier" && parent.property.name === "get")
46
- );
47
- directHeadersReferences.map((reference) => sourceCode.getText(reference));
48
- const reDeclaredHeadersVariableNames = headersReferences.map((reference) => getParent(reference)).filter((parent) => parent?.type === "VariableDeclarator").map((declarator) => declarator.id.name);
49
- const indirectHeadersReferences = reDeclaredHeadersVariableNames.map((variableName) => {
50
- const headersVariable = scope?.variables.find((variable) => {
51
- const identifier = variable.identifiers[0];
52
- return identifier?.type === "Identifier" && identifier.name === variableName;
53
- });
54
- return headersVariable?.references.map((reference) => getParent(reference.identifier)).filter(
55
- (parent) => parent?.type === "MemberExpression" && !(parent.property.type === "Identifier" && parent.property.name === "get")
56
- ) ?? [];
57
- }).flat();
58
- indirectHeadersReferences.map((reference) => sourceCode.getText(reference));
59
- const invalidHeadersReferences = [...directHeadersReferences, ...indirectHeadersReferences].map((reference) => {
60
- sourceCode.getText(reference);
61
- const headerNameNode = reference.property;
62
- const headerName = (
63
- // eslint-disable-next-line no-nested-ternary, @typescript-eslint/restrict-template-expressions
64
- reference.computed ? sourceCode.getText(headerNameNode) : `'${sourceCode.getText(headerNameNode)}'`
65
- );
66
- const replacementText = `${sourceCode.getText(reference.object)}.get(${headerName})`;
67
- return [reference, replacementText];
68
- });
69
- context.report({
70
- node: fetchCall,
71
- messageId: "preferNativeFetch",
72
- *fix(fixer) {
73
- for (const [node, replacementText] of invalidHeadersReferences) {
74
- yield fixer.replaceText(node, replacementText);
75
- }
76
- }
77
- });
78
- } catch (error) {
79
- console.error(`Failed to apply ${ruleId} rule for file "${context.filename}":`, error);
80
- context.report({
81
- node: fetchCall,
82
- messageId: "unknownError",
83
- data: {
84
- fileName: context.filename,
85
- error: error instanceof Error ? error.toString() : JSON.stringify(error)
86
- }
87
- });
88
- }
89
- }
90
- };
91
- }
92
- };
93
- var no_fixture_headers_default = rule;
94
- export {
95
- no_fixture_headers_default as default,
96
- ruleId
97
- };
98
- //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL25vLWZpeHR1cmUtaGVhZGVycy50cyJdLAogICJtYXBwaW5ncyI6ICI7QUFTQSxTQUFTLHVCQUF1QixpQkFBaUI7QUFDakQsT0FBMEI7QUFDMUIsU0FBUyxVQUFVLGNBQWM7QUFDakMsT0FBTyx5QkFBeUI7QUFFekIsSUFBTSxTQUFTO0FBRXRCLElBQU0sT0FBd0I7QUFBQSxFQUM1QixNQUFNO0FBQUEsSUFDSixNQUFNO0FBQUEsSUFDTixNQUFNO0FBQUEsTUFDSixhQUFhO0FBQUEsTUFDYixLQUFLLG9CQUFvQixNQUFNO0FBQUEsSUFDakM7QUFBQSxJQUNBLFVBQVU7QUFBQSxNQUNSLG1CQUFtQjtBQUFBLE1BQ25CLGNBQ0U7QUFBQSxJQUNKO0FBQUEsSUFDQSxTQUFTO0FBQUEsSUFDVCxRQUFRLENBQUM7QUFBQSxFQUNYO0FBQUE7QUFBQSxFQUVBLE9BQU8sU0FBUztBQUNkLFVBQU0sYUFBYSxRQUFRO0FBQzNCLFVBQU0sZUFBZSxXQUFXO0FBRWhDLFdBQU87QUFBQTtBQUFBLE1BRUwseURBQXlELENBQUMsY0FBa0M7QUFDMUYsWUFBSTtBQUNGLGdCQUFNLHFCQUFxQixzQkFBc0IsU0FBUztBQUMxRCxpQkFBTyxHQUFHLFVBQVUsR0FBRyxTQUFTLFlBQVk7QUFDNUMsZ0JBQU0sb0JBQW9CLFVBQVUsR0FBRztBQUN2QyxpQkFBTyxHQUFHLHVCQUF1QixRQUFXLG1DQUFtQztBQUMvRSxnQkFBTSxRQUFRLGFBQWEsUUFBUSxrQkFBa0I7QUFDckQsZ0JBQU0sbUJBQW1CLE9BQU8sVUFBVSxLQUFLLENBQUMsYUFBYTtBQUMzRCxrQkFBTSxhQUFhLFNBQVMsWUFBWSxDQUFDO0FBQ3pDLG1CQUFPLFlBQVksU0FBUyxnQkFBZ0IsV0FBVyxTQUFTO0FBQUEsVUFDbEUsQ0FBQztBQUNELGNBQUkscUJBQXFCLFFBQVc7QUFDbEM7QUFBQSxVQUNGO0FBRUEsZ0JBQU0sb0JBQW9CLGlCQUFpQixXQUN4QyxJQUFJLENBQUMsY0FBYyxVQUFVLFVB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
@@ -1,369 +0,0 @@
1
- // src/no-fixture.ts
2
- import "eslint";
3
- import { getEnclosingScopeNode, getEnclosingStatement, getParent } from "./ast/tree.mjs";
4
- import { strict as assert } from "node:assert";
5
- import getDocumentationUrl from "./get-documentation-url.mjs";
6
- import { getIndentation } from "./ast/format.mjs";
7
- var ruleId = "no-fixture";
8
- function analyzeFixtureCall(call, results, sourceCode) {
9
- const parent = getParent(call);
10
- assert.ok(parent, "parent should exist for fixture/supertest call node");
11
- let nextCall;
12
- if (parent.type === "ReturnStatement") {
13
- results.fixtureNode = call;
14
- results.rootNode = parent;
15
- } else if (parent.type === "AwaitExpression") {
16
- results.fixtureNode = call;
17
- const enclosingStatement = getEnclosingStatement(parent);
18
- assert.ok(enclosingStatement);
19
- const awaitParent = getParent(parent);
20
- if (awaitParent?.type === "MemberExpression") {
21
- results.rootNode = parent;
22
- results.inlineStatementNode = enclosingStatement;
23
- if (awaitParent.property.type === "Identifier" && awaitParent.property.name === "body") {
24
- results.inlineBodyReference = awaitParent;
25
- }
26
- } else if (enclosingStatement.type === "VariableDeclaration") {
27
- results.variableDeclaration = enclosingStatement;
28
- results.rootNode = enclosingStatement;
29
- } else {
30
- results.rootNode = parent;
31
- }
32
- } else if (parent.type === "MemberExpression" && parent.property.type === "Identifier") {
33
- if (parent.property.name === "expect") {
34
- const assertionCall = getParent(parent);
35
- assert.ok(assertionCall && assertionCall.type === "CallExpression");
36
- results.assertions = [...results.assertions ?? [], assertionCall.arguments];
37
- nextCall = assertionCall;
38
- } else if (parent.property.name === "send") {
39
- const sendRequestBodyCall = getParent(parent);
40
- assert.ok(sendRequestBodyCall && sendRequestBodyCall.type === "CallExpression");
41
- results.requestBody = sendRequestBodyCall.arguments[0];
42
- nextCall = sendRequestBodyCall;
43
- } else if (parent.property.name === "set") {
44
- const setRequestHeaderCall = getParent(parent);
45
- assert.ok(setRequestHeaderCall && setRequestHeaderCall.type === "CallExpression");
46
- const [name, value] = setRequestHeaderCall.arguments;
47
- results.requestHeaders = [...results.requestHeaders ?? [], { name, value }];
48
- nextCall = setRequestHeaderCall;
49
- }
50
- } else {
51
- throw new Error(`Unexpected expression in fixture/supertest call ${sourceCode.getText(parent)}`);
52
- }
53
- if (nextCall) {
54
- analyzeFixtureCall(nextCall, results, sourceCode);
55
- }
56
- }
57
- function analyzeResponseReferences(fixtureInformation, scopeManager) {
58
- const results = {
59
- bodyReferences: [],
60
- headersReferences: [],
61
- statusReferences: []
62
- };
63
- if (fixtureInformation.variableDeclaration) {
64
- const responseVariables = scopeManager.getDeclaredVariables(fixtureInformation.variableDeclaration);
65
- for (const responseVariable of responseVariables) {
66
- const scope = responseVariable.scope;
67
- const identifier = responseVariable.identifiers[0];
68
- assert.ok(identifier);
69
- const identifierParent = getParent(identifier);
70
- assert.ok(identifierParent);
71
- if (identifierParent.type === "VariableDeclarator") {
72
- results.variable = responseVariable;
73
- const responseReferences = responseVariable.references.map(
74
- (responseReference) => getParent(responseReference.identifier)
75
- );
76
- results.bodyReferences = responseReferences.filter(
77
- (node) => node !== null && node !== void 0 && node.type === "MemberExpression" && node.property.type === "Identifier" && node.property.name === "body"
78
- );
79
- results.headersReferences = responseReferences.filter(
80
- (node) => node !== null && node !== void 0 && node.type === "MemberExpression" && node.property.type === "Identifier" && (node.property.name === "header" || node.property.name === "headers" || node.property.name === "get")
81
- );
82
- results.statusReferences = responseReferences.filter(
83
- (node) => node !== null && node !== void 0 && node.type === "MemberExpression" && node.property.type === "Identifier" && (node.property.name === "status" || node.property.name === "statusCode")
84
- );
85
- } else if (
86
- // body reference through destruction/renaming, e.g. "const { body } = ..."
87
- identifierParent.type === "Property" && identifierParent.key.type === "Identifier" && identifierParent.key.name === "body"
88
- ) {
89
- results.destructuringBodyVariable = responseVariable;
90
- } else if (
91
- // header reference through destruction/renaming, e.g. "const { headers } = ..."
92
- identifierParent.type === "Property" && identifierParent.key.type === "Identifier" && identifierParent.key.name === "headers"
93
- ) {
94
- results.destructuringHeadersVariable = responseVariable;
95
- results.destructuringHeadersReferences = scope.set.get(responseVariable.name)?.references.map((reference) => reference.identifier).map(getParent).filter(
96
- (parent) => parent?.type === "MemberExpression" && parent.property.type === "Identifier" && parent.property.name !== "get" && getParent(parent)?.type !== "CallExpression"
97
- );
98
- } else {
99
- throw new Error(`Unknown response variable reference: ${responseVariable.name}`);
100
- }
101
- }
102
- }
103
- return results;
104
- }
105
- function replaceEndpointUrlPrefixWithBasePath(url) {
106
- return url.replace(/`\/\w+(?<parts>-\w+)*\/v\d+\//u, "`${BASE_PATH}/");
107
- }
108
- function isValidPropertyName(name) {
109
- return typeof name === "string" && /^[a-zA-Z_$][a-zA-Z_$0-9]*$/u.test(name);
110
- }
111
- function createResponseAssertions(fixtureCallInformation, sourceCode, responseVariableName, destructuringResponseHeadersVariable) {
112
- let statusAssertion;
113
- const nonStatusAssertions = [];
114
- for (const expectArguments of fixtureCallInformation.assertions ?? []) {
115
- if (expectArguments.length === 1) {
116
- const [assertionArgument] = expectArguments;
117
- assert.ok(assertionArgument);
118
- if (assertionArgument.type === "MemberExpression" && assertionArgument.object.type === "Identifier" && assertionArgument.object.name === "StatusCodes" || assertionArgument.type === "Literal" || sourceCode.getText(assertionArgument).includes("StatusCodes.")) {
119
- statusAssertion = `assert.equal(${responseVariableName}.status, ${sourceCode.getText(assertionArgument)})`;
120
- } else if (assertionArgument.type === "ArrowFunctionExpression") {
121
- let functionBody = sourceCode.getText(assertionArgument.body);
122
- const [originalResponseArgument] = assertionArgument.params;
123
- assert.ok(originalResponseArgument?.type === "Identifier");
124
- const originalResponseArgumentName = originalResponseArgument.name;
125
- if (originalResponseArgumentName !== responseVariableName) {
126
- functionBody = functionBody.replace(
127
- new RegExp(`\\b${originalResponseArgumentName}\\b`, "ug"),
128
- responseVariableName
129
- );
130
- }
131
- nonStatusAssertions.push(`assert.ok(${functionBody})`);
132
- } else if (assertionArgument.type === "Identifier") {
133
- nonStatusAssertions.push(`assert.ok(${sourceCode.getText(assertionArgument)}(${responseVariableName}))`);
134
- } else if (assertionArgument.type === "ObjectExpression" || assertionArgument.type === "CallExpression") {
135
- nonStatusAssertions.push(
136
- `assert.deepEqual(await ${responseVariableName}.json(), ${sourceCode.getText(assertionArgument)})`
137
- );
138
- } else {
139
- throw new Error(`Unexpected Supertest assertion argument: ".expect(${sourceCode.getText(assertionArgument)})`);
140
- }
141
- } else if (expectArguments.length === 2) {
142
- const [headerName, headerValue] = expectArguments;
143
- assert.ok(headerName && headerValue);
144
- const headersReference = destructuringResponseHeadersVariable !== void 0 ? destructuringResponseHeadersVariable.name : `${responseVariableName}.headers`;
145
- if (headerValue.type === "Literal" && headerValue.value instanceof RegExp) {
146
- nonStatusAssertions.push(
147
- `assert.ok(${headersReference}.get(${sourceCode.getText(headerName)}).match(${sourceCode.getText(headerValue)}))`
148
- );
149
- } else {
150
- nonStatusAssertions.push(
151
- `assert.equal(${headersReference}.get(${sourceCode.getText(headerName)}), ${sourceCode.getText(headerValue)})`
152
- );
153
- }
154
- }
155
- }
156
- return {
157
- statusAssertion,
158
- nonStatusAssertions
159
- };
160
- }
161
- function getResponseVariableNameToUse(scopeManager, fixtureCallInformation, scopeVariablesMap) {
162
- if (fixtureCallInformation.variableDeclaration) {
163
- const firstDeclaration = fixtureCallInformation.variableDeclaration.declarations[0];
164
- if (firstDeclaration && firstDeclaration.id.type === "Identifier") {
165
- return firstDeclaration.id.name;
166
- }
167
- }
168
- const enclosingScopeNode = getEnclosingScopeNode(fixtureCallInformation.rootNode);
169
- scopeManager.getDeclaredVariables(fixtureCallInformation.rootNode);
170
- assert.ok(enclosingScopeNode);
171
- const scope = scopeManager.acquire(enclosingScopeNode);
172
- assert.ok(scope !== null);
173
- let scopeVariables = scopeVariablesMap.get(scope);
174
- if (!scopeVariables) {
175
- scopeVariables = [...scope.set.keys()];
176
- scopeVariablesMap.set(scope, scopeVariables);
177
- }
178
- let responseVariableCounter = 0;
179
- let responseVariableNameToUse;
180
- while (responseVariableNameToUse === void 0) {
181
- responseVariableCounter++;
182
- responseVariableNameToUse = `response${responseVariableCounter === 1 ? "" : responseVariableCounter.toString()}`;
183
- if (scopeVariables.includes(responseVariableNameToUse)) {
184
- responseVariableNameToUse = void 0;
185
- }
186
- }
187
- scopeVariables.push(responseVariableNameToUse);
188
- return responseVariableNameToUse;
189
- }
190
- function isResponseBodyRedefinition(responseBodyReference) {
191
- const parent = getParent(responseBodyReference);
192
- return parent?.type === "VariableDeclarator" && parent.id.type === "Identifier";
193
- }
194
- function getResponseBodyRetrievalText(responseVariableName) {
195
- return `await ${responseVariableName}.json()`;
196
- }
197
- var rule = {
198
- meta: {
199
- type: "suggestion",
200
- docs: {
201
- description: "Prefer native fetch API over customized fixture API.",
202
- url: getDocumentationUrl(ruleId)
203
- },
204
- messages: {
205
- preferNativeFetch: "Prefer native fetch API over customized fixture API.",
206
- unknownError: 'Unknown error occurred in file "{{fileName}}": {{ error }}. Please manually convert the fixture API call to fetch API call.'
207
- },
208
- fixable: "code",
209
- schema: []
210
- },
211
- // eslint-disable-next-line max-lines-per-function
212
- create(context) {
213
- const sourceCode = context.sourceCode;
214
- const scopeManager = sourceCode.scopeManager;
215
- const scopeVariablesMap = /* @__PURE__ */ new Map();
216
- return {
217
- // eslint-disable-next-line max-lines-per-function
218
- 'CallExpression[callee.object.object.name="fixture"][callee.object.property.name="api"]': (fixtureCall) => {
219
- try {
220
- assert.ok(fixtureCall.type === "CallExpression");
221
- const fixtureFunction = fixtureCall.callee;
222
- assert.ok(fixtureFunction.type === "MemberExpression");
223
- const indentation = getIndentation(fixtureCall, sourceCode);
224
- const [urlArgumentNode] = fixtureCall.arguments;
225
- assert.ok(urlArgumentNode !== void 0);
226
- const fixtureCallInformation = {};
227
- analyzeFixtureCall(fixtureCall, fixtureCallInformation, sourceCode);
228
- const {
229
- variable: responseVariable,
230
- bodyReferences: responseBodyReferences,
231
- headersReferences: responseHeadersReferences,
232
- statusReferences: responseStatusReferences,
233
- destructuringBodyVariable: destructuringResponseBodyVariable,
234
- destructuringHeadersVariable: destructuringResponseHeadersVariable
235
- // destructuringHeadersReferences: destructuringResponseHeadersReferences,
236
- } = analyzeResponseReferences(fixtureCallInformation, scopeManager);
237
- const originalUrlArgumentText = sourceCode.getText(urlArgumentNode);
238
- const fetchUrlArgumentText = replaceEndpointUrlPrefixWithBasePath(originalUrlArgumentText);
239
- const methodNode = fixtureFunction.property;
240
- assert.ok(methodNode.type === "Identifier");
241
- const fetchRequestArgumentLines = [
242
- "{",
243
- ` method: '${methodNode.name.toUpperCase()}',`,
244
- ...fixtureCallInformation.requestBody ? [` body: JSON.stringify(${sourceCode.getText(fixtureCallInformation.requestBody)}),`] : [],
245
- ...fixtureCallInformation.requestHeaders ? [
246
- ` headers: {`,
247
- ...fixtureCallInformation.requestHeaders.map(
248
- ({ name, value }) => (
249
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions, no-nested-ternary, sonarjs/no-nested-template-literals
250
- ` ${name.type === "Literal" ? isValidPropertyName(name.value) ? name.value : `'${name.value}'` : `[${sourceCode.getText(name)}]`}: ${sourceCode.getText(value)},`
251
- )
252
- ),
253
- ` },`
254
- ] : [],
255
- "}"
256
- ].join(`
257
- ${indentation}`);
258
- const responseVariableNameToUse = getResponseVariableNameToUse(
259
- scopeManager,
260
- fixtureCallInformation,
261
- scopeVariablesMap
262
- );
263
- const isResponseBodyVariableRedefinitionNeeded = destructuringResponseBodyVariable !== void 0 || fixtureCallInformation.inlineBodyReference !== void 0 || responseBodyReferences.length > 0 && !responseBodyReferences.some(isResponseBodyRedefinition);
264
- const redefineResponseBodyVariableName = `${responseVariableNameToUse}Body`;
265
- const isResponseVariableRedefinitionNeeded = responseVariable === void 0 && fixtureCallInformation.assertions !== void 0 || isResponseBodyVariableRedefinitionNeeded;
266
- const responseBodyHeadersVariableRedefineLines = isResponseVariableRedefinitionNeeded ? [
267
- // eslint-disable-next-line no-nested-ternary
268
- ...destructuringResponseBodyVariable ? [
269
- `const ${destructuringResponseBodyVariable.name} = ${getResponseBodyRetrievalText(responseVariableNameToUse)}`
270
- ] : isResponseBodyVariableRedefinitionNeeded ? [
271
- `const ${redefineResponseBodyVariableName} = ${getResponseBodyRetrievalText(responseVariableNameToUse)}`
272
- ] : [],
273
- ...destructuringResponseHeadersVariable ? [`const ${destructuringResponseHeadersVariable.name} = ${responseVariableNameToUse}.headers`] : []
274
- ] : [];
275
- const { statusAssertion, nonStatusAssertions } = createResponseAssertions(
276
- fixtureCallInformation,
277
- sourceCode,
278
- responseVariableNameToUse,
279
- destructuringResponseHeadersVariable
280
- );
281
- const fetchCallText = `fetch(${fetchUrlArgumentText}, ${fetchRequestArgumentLines})`;
282
- const fetchStatementText = !isResponseVariableRedefinitionNeeded ? fetchCallText : `const ${responseVariableNameToUse} = await ${fetchCallText}`;
283
- const nodeToReplace = isResponseVariableRedefinitionNeeded ? fixtureCallInformation.rootNode : fixtureCallInformation.fixtureNode;
284
- const appendingAssignmentAndAssertionText = [
285
- "",
286
- ...statusAssertion !== void 0 ? [statusAssertion] : [],
287
- ...responseBodyHeadersVariableRedefineLines,
288
- ...nonStatusAssertions
289
- ].join(`;
290
- ${indentation}`);
291
- context.report({
292
- node: fixtureCall,
293
- messageId: "preferNativeFetch",
294
- // eslint-disable-next-line sonarjs/cognitive-complexity
295
- *fix(fixer) {
296
- if (fixtureCallInformation.inlineStatementNode) {
297
- const preInlineDeclaration = [
298
- fetchStatementText,
299
- `${appendingAssignmentAndAssertionText};
300
- ${indentation}`
301
- ].join(``);
302
- yield fixer.insertTextBefore(fixtureCallInformation.inlineStatementNode, preInlineDeclaration);
303
- } else {
304
- yield fixer.replaceText(nodeToReplace, fetchStatementText);
305
- const needEndingSemiColon = sourceCode.getText(nodeToReplace).endsWith(";");
306
- yield fixer.insertTextAfter(
307
- nodeToReplace,
308
- needEndingSemiColon ? `${appendingAssignmentAndAssertionText};` : appendingAssignmentAndAssertionText
309
- );
310
- }
311
- for (const responseBodyReference of responseBodyReferences) {
312
- yield fixer.replaceText(
313
- responseBodyReference,
314
- isResponseBodyVariableRedefinitionNeeded || !isResponseBodyRedefinition(responseBodyReference) ? redefineResponseBodyVariableName : getResponseBodyRetrievalText(responseVariableNameToUse)
315
- );
316
- }
317
- if (fixtureCallInformation.inlineBodyReference) {
318
- yield fixer.replaceText(fixtureCallInformation.inlineBodyReference, redefineResponseBodyVariableName);
319
- }
320
- for (const responseHeadersReference of responseHeadersReferences) {
321
- const parent = getParent(responseHeadersReference);
322
- assert.ok(parent);
323
- let headerName;
324
- if (parent.type === "MemberExpression") {
325
- const headerNameNode = parent.property;
326
- headerName = // eslint-disable-next-line no-nested-ternary, @typescript-eslint/restrict-template-expressions
327
- parent.computed ? sourceCode.getText(headerNameNode) : `'${sourceCode.getText(headerNameNode)}'`;
328
- } else if (parent.type === "CallExpression") {
329
- const headerNameNode = parent.arguments[0];
330
- headerName = sourceCode.getText(headerNameNode);
331
- }
332
- assert.ok(headerName !== void 0);
333
- yield fixer.replaceText(parent, `${responseVariableNameToUse}.headers.get(${headerName})`);
334
- }
335
- for (const responseStatusReference of responseStatusReferences) {
336
- if (responseStatusReference.property.type === "Identifier" && responseStatusReference.property.name === "statusCode") {
337
- yield fixer.replaceText(responseStatusReference.property, `status`);
338
- }
339
- }
340
- if (fixtureCallInformation.rootNode.type === "ReturnStatement" && fixtureCallInformation.assertions !== void 0) {
341
- yield fixer.insertTextAfter(
342
- fixtureCallInformation.rootNode,
343
- `
344
- ${indentation}return ${responseVariableNameToUse};`
345
- );
346
- }
347
- }
348
- });
349
- } catch (error) {
350
- console.error(`Failed to apply ${ruleId} rule for file "${context.filename}":`, error);
351
- context.report({
352
- node: fixtureCall,
353
- messageId: "unknownError",
354
- data: {
355
- fileName: context.filename,
356
- error: error instanceof Error ? error.toString() : JSON.stringify(error)
357
- }
358
- });
359
- }
360
- }
361
- };
362
- }
363
- };
364
- var no_fixture_default = rule;
365
- export {
366
- no_fixture_default as default,
367
- ruleId
368
- };
369
- //# sourceMappingURL=data:application/json;base64,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
@@ -1,134 +0,0 @@
1
- // no-fixture.ts
2
-
3
- /*
4
- * Copyright (c) 2021-2024 Check Digit, LLC
5
- *
6
- * This code is licensed under the MIT license (see LICENSE.txt for details).
7
- */
8
-
9
- import type { Identifier, MemberExpression, VariableDeclarator } from 'estree';
10
- import { getEnclosingScopeNode, getParent } from './ast/tree';
11
- import { type Rule } from 'eslint';
12
- import { strict as assert } from 'node:assert';
13
- import getDocumentationUrl from './get-documentation-url';
14
-
15
- export const ruleId = 'no-fixture-headers';
16
-
17
- const rule: Rule.RuleModule = {
18
- meta: {
19
- type: 'suggestion',
20
- docs: {
21
- description: 'Prefer native fetch API over customized fixture API.',
22
- url: getDocumentationUrl(ruleId),
23
- },
24
- messages: {
25
- preferNativeFetch: 'Prefer native fetch API over customized fixture API.',
26
- unknownError:
27
- 'Unknown error occurred in file "{{fileName}}": {{ error }}. Please manually convert the fixture API call to fetch API call.',
28
- },
29
- fixable: 'code',
30
- schema: [],
31
- },
32
- // eslint-disable-next-line max-lines-per-function
33
- create(context) {
34
- const sourceCode = context.sourceCode;
35
- const scopeManager = sourceCode.scopeManager;
36
-
37
- return {
38
- // eslint-disable-next-line max-lines-per-function
39
- 'VariableDeclarator[init.argument.callee.name="fetch"]': (fetchCall: VariableDeclarator) => {
40
- try {
41
- const enclosingScopeNode = getEnclosingScopeNode(fetchCall);
42
- assert.ok(fetchCall.id.type === 'Identifier');
43
- const fetchVariableName = fetchCall.id.name; /*?*/
44
- assert.ok(enclosingScopeNode !== undefined, 'enclosing scope node should exist');
45
- const scope = scopeManager.acquire(enclosingScopeNode);
46
- const responseVariable = scope?.variables.find((variable) => {
47
- const identifier = variable.identifiers[0];
48
- return identifier?.type === 'Identifier' && identifier.name === fetchVariableName;
49
- });
50
- if (responseVariable === undefined) {
51
- return;
52
- }
53
-
54
- const headersReferences = responseVariable.references
55
- .map((reference) => getParent(reference.identifier))
56
- .filter(
57
- (parent): parent is MemberExpression =>
58
- parent?.type === 'MemberExpression' &&
59
- parent.property.type === 'Identifier' &&
60
- parent.property.name === 'headers',
61
- );
62
- const directHeadersReferences = headersReferences
63
- .map(getParent)
64
- .filter(
65
- (parent): parent is MemberExpression =>
66
- parent?.type === 'MemberExpression' &&
67
- !(parent.property.type === 'Identifier' && parent.property.name === 'get'),
68
- );
69
- directHeadersReferences.map((reference) => sourceCode.getText(reference)); /*?*/
70
-
71
- const reDeclaredHeadersVariableNames = headersReferences
72
- .map((reference) => getParent(reference))
73
- .filter((parent): parent is VariableDeclarator => parent?.type === 'VariableDeclarator')
74
- .map((declarator) => (declarator.id as Identifier).name);
75
-
76
- const indirectHeadersReferences = reDeclaredHeadersVariableNames
77
- .map((variableName) => {
78
- const headersVariable = scope?.variables.find((variable) => {
79
- const identifier = variable.identifiers[0];
80
- return identifier?.type === 'Identifier' && identifier.name === variableName;
81
- });
82
- return (
83
- headersVariable?.references
84
- .map((reference) => getParent(reference.identifier))
85
- .filter(
86
- (parent): parent is MemberExpression =>
87
- parent?.type === 'MemberExpression' &&
88
- !(parent.property.type === 'Identifier' && parent.property.name === 'get'),
89
- ) ?? []
90
- );
91
- })
92
- .flat();
93
- indirectHeadersReferences.map((reference) => sourceCode.getText(reference)); /*?*/
94
-
95
- const invalidHeadersReferences = [...directHeadersReferences, ...indirectHeadersReferences].map<
96
- [MemberExpression, string]
97
- >((reference) => {
98
- sourceCode.getText(reference); /*?*/
99
- const headerNameNode = reference.property; /*?*/
100
- const headerName =
101
- // eslint-disable-next-line no-nested-ternary, @typescript-eslint/restrict-template-expressions
102
- reference.computed ? sourceCode.getText(headerNameNode) : `'${sourceCode.getText(headerNameNode)}'`; /*?*/
103
- const replacementText = `${sourceCode.getText(reference.object)}.get(${headerName})`;
104
- return [reference, replacementText];
105
- });
106
-
107
- context.report({
108
- node: fetchCall,
109
- messageId: 'preferNativeFetch',
110
- *fix(fixer) {
111
- // handle response headers references
112
- for (const [node, replacementText] of invalidHeadersReferences) {
113
- yield fixer.replaceText(node, replacementText);
114
- }
115
- },
116
- });
117
- } catch (error) {
118
- // eslint-disable-next-line no-console
119
- console.error(`Failed to apply ${ruleId} rule for file "${context.filename}":`, error);
120
- context.report({
121
- node: fetchCall,
122
- messageId: 'unknownError',
123
- data: {
124
- fileName: context.filename,
125
- error: error instanceof Error ? error.toString() : JSON.stringify(error),
126
- },
127
- });
128
- }
129
- },
130
- };
131
- },
132
- };
133
-
134
- export default rule;