@checkdigit/eslint-plugin 6.6.0-PR.75-24d6 → 6.6.0-PR.75-3e31
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/dist-cjs/index.cjs +179 -130
- package/dist-cjs/metafile.json +40 -3
- package/dist-mjs/ast/format.mjs +13 -0
- package/dist-mjs/ast/tree.mjs +18 -0
- package/dist-mjs/no-fixture.mjs +145 -118
- package/dist-types/ast/format.d.ts +3 -0
- package/dist-types/ast/tree.d.ts +3 -0
- package/package.json +1 -1
- package/src/ast/format.ts +19 -0
- package/src/ast/tree.ts +29 -0
- package/src/no-fixture.ts +237 -179
package/dist-cjs/metafile.json
CHANGED
|
@@ -33,9 +33,30 @@
|
|
|
33
33
|
],
|
|
34
34
|
"format": "esm"
|
|
35
35
|
},
|
|
36
|
+
"src/ast/tree.ts": {
|
|
37
|
+
"bytes": 719,
|
|
38
|
+
"imports": [],
|
|
39
|
+
"format": "esm"
|
|
40
|
+
},
|
|
41
|
+
"src/ast/format.ts": {
|
|
42
|
+
"bytes": 532,
|
|
43
|
+
"imports": [
|
|
44
|
+
{
|
|
45
|
+
"path": "node:assert",
|
|
46
|
+
"kind": "import-statement",
|
|
47
|
+
"external": true
|
|
48
|
+
}
|
|
49
|
+
],
|
|
50
|
+
"format": "esm"
|
|
51
|
+
},
|
|
36
52
|
"src/no-fixture.ts": {
|
|
37
|
-
"bytes":
|
|
53
|
+
"bytes": 17779,
|
|
38
54
|
"imports": [
|
|
55
|
+
{
|
|
56
|
+
"path": "src/ast/tree.ts",
|
|
57
|
+
"kind": "import-statement",
|
|
58
|
+
"original": "./ast/tree"
|
|
59
|
+
},
|
|
39
60
|
{
|
|
40
61
|
"path": "node:assert",
|
|
41
62
|
"kind": "import-statement",
|
|
@@ -45,6 +66,11 @@
|
|
|
45
66
|
"path": "src/get-documentation-url.ts",
|
|
46
67
|
"kind": "import-statement",
|
|
47
68
|
"original": "./get-documentation-url"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"path": "src/ast/format.ts",
|
|
72
|
+
"kind": "import-statement",
|
|
73
|
+
"original": "./ast/format"
|
|
48
74
|
}
|
|
49
75
|
],
|
|
50
76
|
"format": "esm"
|
|
@@ -175,6 +201,11 @@
|
|
|
175
201
|
"outputs": {
|
|
176
202
|
"dist-cjs/index.cjs": {
|
|
177
203
|
"imports": [
|
|
204
|
+
{
|
|
205
|
+
"path": "node:assert",
|
|
206
|
+
"kind": "require-call",
|
|
207
|
+
"external": true
|
|
208
|
+
},
|
|
178
209
|
{
|
|
179
210
|
"path": "node:assert",
|
|
180
211
|
"kind": "require-call",
|
|
@@ -196,8 +227,14 @@
|
|
|
196
227
|
"src/invalid-json-stringify.ts": {
|
|
197
228
|
"bytesInOutput": 2471
|
|
198
229
|
},
|
|
230
|
+
"src/ast/tree.ts": {
|
|
231
|
+
"bytesInOutput": 329
|
|
232
|
+
},
|
|
233
|
+
"src/ast/format.ts": {
|
|
234
|
+
"bytesInOutput": 320
|
|
235
|
+
},
|
|
199
236
|
"src/no-fixture.ts": {
|
|
200
|
-
"bytesInOutput":
|
|
237
|
+
"bytesInOutput": 14327
|
|
201
238
|
},
|
|
202
239
|
"src/no-promise-instance-method.ts": {
|
|
203
240
|
"bytesInOutput": 1275
|
|
@@ -230,7 +267,7 @@
|
|
|
230
267
|
"bytesInOutput": 3362
|
|
231
268
|
}
|
|
232
269
|
},
|
|
233
|
-
"bytes":
|
|
270
|
+
"bytes": 81956
|
|
234
271
|
}
|
|
235
272
|
}
|
|
236
273
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// src/ast/format.ts
|
|
2
|
+
import { strict as assert } from "node:assert";
|
|
3
|
+
function getIndentation(node, sourceCode) {
|
|
4
|
+
assert.ok(node.loc);
|
|
5
|
+
const line = sourceCode.lines[node.loc.start.line - 1];
|
|
6
|
+
assert.ok(line);
|
|
7
|
+
const indentMatch = line.match(/^\s*/u);
|
|
8
|
+
return indentMatch ? indentMatch[0] : "";
|
|
9
|
+
}
|
|
10
|
+
export {
|
|
11
|
+
getIndentation
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL2FzdC9mb3JtYXQudHMiXSwKICAibWFwcGluZ3MiOiAiO0FBVUEsU0FBUyxVQUFVLGNBQWM7QUFFMUIsU0FBUyxlQUFlLE1BQVksWUFBd0I7QUFDakUsU0FBTyxHQUFHLEtBQUssR0FBRztBQUNsQixRQUFNLE9BQU8sV0FBVyxNQUFNLEtBQUssSUFBSSxNQUFNLE9BQU8sQ0FBQztBQUNyRCxTQUFPLEdBQUcsSUFBSTtBQUNkLFFBQU0sY0FBYyxLQUFLLE1BQU0sT0FBTztBQUN0QyxTQUFPLGNBQWMsWUFBWSxDQUFDLElBQUk7QUFDeEM7IiwKICAibmFtZXMiOiBbXQp9Cg==
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// src/ast/tree.ts
|
|
2
|
+
function getParent(node) {
|
|
3
|
+
return node.parent;
|
|
4
|
+
}
|
|
5
|
+
function getAncestor(node, typeToMatch, typeToExit) {
|
|
6
|
+
const parent = getParent(node);
|
|
7
|
+
if (!parent || parent.type === typeToExit) {
|
|
8
|
+
return void 0;
|
|
9
|
+
} else if (parent.type === typeToMatch) {
|
|
10
|
+
return parent;
|
|
11
|
+
}
|
|
12
|
+
return getAncestor(parent, typeToMatch, typeToExit);
|
|
13
|
+
}
|
|
14
|
+
export {
|
|
15
|
+
getAncestor,
|
|
16
|
+
getParent
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL2FzdC90cmVlLnRzIl0sCiAgIm1hcHBpbmdzIjogIjtBQWdCTyxTQUFTLFVBQVUsTUFBcUM7QUFDN0QsU0FBUSxLQUF3QztBQUNsRDtBQUVPLFNBQVMsWUFBWSxNQUFZLGFBQXFCLFlBQW9CO0FBQy9FLFFBQU0sU0FBUyxVQUFVLElBQUk7QUFDN0IsTUFBSSxDQUFDLFVBQVUsT0FBTyxTQUFTLFlBQVk7QUFDekMsV0FBTztBQUFBLEVBQ1QsV0FBVyxPQUFPLFNBQVMsYUFBYTtBQUN0QyxXQUFPO0FBQUEsRUFDVDtBQUNBLFNBQU8sWUFBWSxRQUFRLGFBQWEsVUFBVTtBQUNwRDsiLAogICJuYW1lcyI6IFtdCn0K
|
package/dist-mjs/no-fixture.mjs
CHANGED
|
@@ -1,16 +1,25 @@
|
|
|
1
1
|
// src/no-fixture.ts
|
|
2
|
+
import { getAncestor, getParent } from "./ast/tree.mjs";
|
|
2
3
|
import { strict as assert } from "node:assert";
|
|
3
4
|
import getDocumentationUrl from "./get-documentation-url.mjs";
|
|
5
|
+
import { getIndentation } from "./ast/format.mjs";
|
|
4
6
|
var ruleId = "no-fixture";
|
|
5
|
-
function
|
|
6
|
-
return node.parent;
|
|
7
|
-
}
|
|
8
|
-
function analyze(call, results) {
|
|
7
|
+
function analyzeFixtureCall(call, results) {
|
|
9
8
|
const parent = getParent(call);
|
|
10
9
|
assert.ok(parent, "parent should exist for fixture/supertest call node");
|
|
11
10
|
let nextCall;
|
|
12
|
-
if (parent.type === "
|
|
13
|
-
results.
|
|
11
|
+
if (parent.type === "ReturnStatement") {
|
|
12
|
+
results.fixtureNode = call;
|
|
13
|
+
results.rootNode = parent;
|
|
14
|
+
} else if (parent.type === "AwaitExpression") {
|
|
15
|
+
results.fixtureNode = call;
|
|
16
|
+
const variableDeclaration = getAncestor(parent, "VariableDeclaration", "FunctionDeclaration");
|
|
17
|
+
if (variableDeclaration?.type === "VariableDeclaration") {
|
|
18
|
+
results.variableDeclaration = variableDeclaration;
|
|
19
|
+
results.rootNode = variableDeclaration;
|
|
20
|
+
} else {
|
|
21
|
+
results.rootNode = parent;
|
|
22
|
+
}
|
|
14
23
|
} else if (parent.type === "MemberExpression" && parent.property.type === "Identifier") {
|
|
15
24
|
if (parent.property.name === "expect") {
|
|
16
25
|
const assertionCall = getParent(parent);
|
|
@@ -33,29 +42,73 @@ function analyze(call, results) {
|
|
|
33
42
|
throw new Error(`Unexpected expression in fixture/supertest call ${String(parent)}`);
|
|
34
43
|
}
|
|
35
44
|
if (nextCall) {
|
|
36
|
-
|
|
45
|
+
analyzeFixtureCall(nextCall, results);
|
|
37
46
|
}
|
|
38
47
|
}
|
|
48
|
+
function analyzeResponseReferences(fixtureInformation, scopeManager) {
|
|
49
|
+
const results = {
|
|
50
|
+
bodyReferences: [],
|
|
51
|
+
headersReferences: [],
|
|
52
|
+
statusReferences: []
|
|
53
|
+
};
|
|
54
|
+
if (fixtureInformation.variableDeclaration) {
|
|
55
|
+
const responseVariables = scopeManager.getDeclaredVariables(fixtureInformation.variableDeclaration);
|
|
56
|
+
for (const responseVariable of responseVariables) {
|
|
57
|
+
const identifier = responseVariable.identifiers[0];
|
|
58
|
+
assert.ok(identifier);
|
|
59
|
+
const identifierParent = getParent(identifier);
|
|
60
|
+
assert.ok(identifierParent);
|
|
61
|
+
if (identifierParent.type === "VariableDeclarator") {
|
|
62
|
+
results.variable = responseVariable;
|
|
63
|
+
results.bodyReferences = responseVariable.references.map((responseBodyReference) => getParent(responseBodyReference.identifier)).filter(
|
|
64
|
+
(node) => node !== null && node !== void 0 && node.type === "MemberExpression" && node.property.type === "Identifier" && node.property.name === "body"
|
|
65
|
+
);
|
|
66
|
+
results.headersReferences = responseVariable.references.map((responseHeadersReference) => getParent(responseHeadersReference.identifier)).filter(
|
|
67
|
+
(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")
|
|
68
|
+
);
|
|
69
|
+
results.statusReferences = responseVariable.references.map((responseHeadersReference) => getParent(responseHeadersReference.identifier)).filter(
|
|
70
|
+
(node) => node !== null && node !== void 0 && node.type === "MemberExpression" && node.property.type === "Identifier" && (node.property.name === "status" || node.property.name === "statusCode")
|
|
71
|
+
);
|
|
72
|
+
} else if (
|
|
73
|
+
// body reference through destruction/renaming, e.g. "const { body } = ..."
|
|
74
|
+
identifierParent.type === "Property" && identifierParent.key.type === "Identifier" && identifierParent.key.name === "body"
|
|
75
|
+
) {
|
|
76
|
+
results.spreadBodyVariable = responseVariable;
|
|
77
|
+
} else if (
|
|
78
|
+
// header reference through destruction/renaming, e.g. "const { headers } = ..."
|
|
79
|
+
identifierParent.type === "Property" && identifierParent.key.type === "Identifier" && identifierParent.key.name === "headers"
|
|
80
|
+
) {
|
|
81
|
+
results.spreadHeadersVariable = responseVariable;
|
|
82
|
+
} else {
|
|
83
|
+
throw new Error(`Unknown response variable reference: ${responseVariable.name}`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return results;
|
|
88
|
+
}
|
|
39
89
|
function replaceEndpointUrlPrefixWithBasePath(url) {
|
|
40
90
|
return url.replace(/`\/\w+(?<parts>-\w+)*\/v\d+\//u, "`${BASE_PATH}/");
|
|
41
91
|
}
|
|
42
92
|
function isValidPropertyName(name) {
|
|
43
93
|
return typeof name === "string" && /^[a-zA-Z_$][a-zA-Z_$0-9]*$/u.test(name);
|
|
44
94
|
}
|
|
45
|
-
function
|
|
46
|
-
|
|
47
|
-
|
|
95
|
+
function createResponseAssertions(fixtureCallInformation, sourceCode, variableName) {
|
|
96
|
+
let statusAssertion;
|
|
97
|
+
const nonStatusAssertions = [];
|
|
98
|
+
for (const expectArguments of fixtureCallInformation.assertions ?? []) {
|
|
48
99
|
if (expectArguments.length === 1) {
|
|
49
100
|
const [assertionArgument] = expectArguments;
|
|
50
101
|
assert.ok(assertionArgument);
|
|
51
102
|
if (assertionArgument.type === "MemberExpression" && assertionArgument.object.type === "Identifier" && assertionArgument.object.name === "StatusCodes" || assertionArgument.type === "Literal") {
|
|
52
|
-
|
|
103
|
+
statusAssertion = `assert.equal(${variableName}.status, ${sourceCode.getText(assertionArgument)})`;
|
|
53
104
|
} else if (assertionArgument.type === "ArrowFunctionExpression") {
|
|
54
|
-
|
|
105
|
+
nonStatusAssertions.push(`assert.ok(${sourceCode.getText(assertionArgument)})`);
|
|
55
106
|
} else if (assertionArgument.type === "Identifier") {
|
|
56
|
-
|
|
107
|
+
nonStatusAssertions.push(`assert.ok(${sourceCode.getText(assertionArgument)}(${variableName}))`);
|
|
57
108
|
} else if (assertionArgument.type === "ObjectExpression" || assertionArgument.type === "CallExpression") {
|
|
58
|
-
|
|
109
|
+
nonStatusAssertions.push(
|
|
110
|
+
`assert.deepEqual(await ${variableName}.json(), ${sourceCode.getText(assertionArgument)})`
|
|
111
|
+
);
|
|
59
112
|
} else {
|
|
60
113
|
throw new Error(`Unexpected Supertest assertion argument: ".expect(${sourceCode.getText(assertionArgument)})`);
|
|
61
114
|
}
|
|
@@ -63,52 +116,20 @@ function appendAssertions(expects, sourceCode, variableName) {
|
|
|
63
116
|
const [headerName, headerValue] = expectArguments;
|
|
64
117
|
assert.ok(headerName && headerValue);
|
|
65
118
|
if (headerValue.type === "Literal" && headerValue.value instanceof RegExp) {
|
|
66
|
-
|
|
119
|
+
nonStatusAssertions.push(
|
|
67
120
|
`assert.ok(${variableName}.headers.get(${sourceCode.getText(headerName)}).match(${sourceCode.getText(headerValue)}))`
|
|
68
121
|
);
|
|
69
122
|
} else {
|
|
70
|
-
|
|
123
|
+
nonStatusAssertions.push(
|
|
71
124
|
`assert.equal(${variableName}.headers.get(${sourceCode.getText(headerName)}), ${sourceCode.getText(headerValue)})`
|
|
72
125
|
);
|
|
73
126
|
}
|
|
74
127
|
}
|
|
75
128
|
}
|
|
76
|
-
return
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
const parent = getParent(node);
|
|
80
|
-
if (!parent || parent.type === quitType) {
|
|
81
|
-
return void 0;
|
|
82
|
-
} else if (parent.type === matchType) {
|
|
83
|
-
return parent;
|
|
84
|
-
}
|
|
85
|
-
return getAncestor(parent, matchType, quitType);
|
|
86
|
-
}
|
|
87
|
-
function analyzeReferences(fixtureCallAwait, scopeManager) {
|
|
88
|
-
const results = {
|
|
89
|
-
responseBodyReferences: [],
|
|
90
|
-
responseHeadersReferences: []
|
|
129
|
+
return {
|
|
130
|
+
statusAssertion,
|
|
131
|
+
nonStatusAssertions
|
|
91
132
|
};
|
|
92
|
-
const variableDeclaration = getAncestor(fixtureCallAwait, "VariableDeclaration", "FunctionDeclaration");
|
|
93
|
-
if (variableDeclaration && variableDeclaration.type === "VariableDeclaration") {
|
|
94
|
-
const [responseVariable] = scopeManager.getDeclaredVariables(variableDeclaration);
|
|
95
|
-
assert.ok(responseVariable);
|
|
96
|
-
results.responseVariable = responseVariable;
|
|
97
|
-
results.responseBodyReferences = responseVariable.references.map((responseBodyReference) => getParent(responseBodyReference.identifier)).filter(
|
|
98
|
-
(node) => node !== null && node !== void 0 && node.type === "MemberExpression" && node.property.type === "Identifier" && node.property.name === "body"
|
|
99
|
-
);
|
|
100
|
-
results.responseHeadersReferences = responseVariable.references.map((responseHeadersReference) => getParent(responseHeadersReference.identifier)).filter(
|
|
101
|
-
(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")
|
|
102
|
-
);
|
|
103
|
-
}
|
|
104
|
-
return results;
|
|
105
|
-
}
|
|
106
|
-
function getIndentation(node, sourceCode) {
|
|
107
|
-
assert.ok(node.loc);
|
|
108
|
-
const line = sourceCode.lines[node.loc.start.line - 1];
|
|
109
|
-
assert.ok(line);
|
|
110
|
-
const indentMatch = line.match(/^\s*/u);
|
|
111
|
-
return indentMatch ? indentMatch[0] : "";
|
|
112
133
|
}
|
|
113
134
|
var rule = {
|
|
114
135
|
meta: {
|
|
@@ -127,76 +148,86 @@ var rule = {
|
|
|
127
148
|
create(context) {
|
|
128
149
|
const sourceCode = context.sourceCode;
|
|
129
150
|
const scopeManager = sourceCode.scopeManager;
|
|
130
|
-
let
|
|
151
|
+
let responseVariableCounter = 0;
|
|
131
152
|
return {
|
|
132
153
|
'CallExpression[callee.object.object.name="fixture"][callee.object.property.name="api"]': (fixtureCall) => {
|
|
133
154
|
try {
|
|
134
155
|
assert.ok(fixtureCall.type === "CallExpression");
|
|
135
156
|
const fixtureFunction = fixtureCall.callee;
|
|
136
157
|
assert.ok(fixtureFunction.type === "MemberExpression");
|
|
137
|
-
const methodNode = fixtureFunction.property;
|
|
138
|
-
assert.ok(methodNode.type === "Identifier");
|
|
139
158
|
const indentation = getIndentation(fixtureCall, sourceCode);
|
|
140
159
|
const [urlArgumentNode] = fixtureCall.arguments;
|
|
141
160
|
assert.ok(urlArgumentNode !== void 0);
|
|
142
161
|
const fixtureCallInformation = {};
|
|
143
|
-
|
|
144
|
-
const {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
162
|
+
analyzeFixtureCall(fixtureCall, fixtureCallInformation);
|
|
163
|
+
const {
|
|
164
|
+
variable: responseVariable,
|
|
165
|
+
bodyReferences: responseBodyReferences,
|
|
166
|
+
headersReferences: responseHeadersReferences,
|
|
167
|
+
statusReferences: responseStatusReferences,
|
|
168
|
+
spreadBodyVariable: spreadResponseBodyVariable,
|
|
169
|
+
spreadHeadersVariable: spreadResponseHeadersVariable
|
|
170
|
+
} = analyzeResponseReferences(fixtureCallInformation, scopeManager);
|
|
171
|
+
const originalUrlArgumentText = sourceCode.getText(urlArgumentNode);
|
|
172
|
+
const fetchUrlArgumentText = replaceEndpointUrlPrefixWithBasePath(originalUrlArgumentText);
|
|
173
|
+
const methodNode = fixtureFunction.property;
|
|
174
|
+
assert.ok(methodNode.type === "Identifier");
|
|
175
|
+
const fetchRequestArgumentLines = [
|
|
176
|
+
"{",
|
|
177
|
+
` method: '${methodNode.name.toUpperCase()}',`,
|
|
178
|
+
...fixtureCallInformation.requestBody ? [` body: JSON.stringify(${sourceCode.getText(fixtureCallInformation.requestBody)}),`] : [],
|
|
179
|
+
...fixtureCallInformation.requestHeaders ? [
|
|
180
|
+
` headers: {`,
|
|
181
|
+
...fixtureCallInformation.requestHeaders.map(
|
|
182
|
+
({ name, value }) => (
|
|
183
|
+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions, no-nested-ternary, sonarjs/no-nested-template-literals
|
|
184
|
+
` ${name.type === "Literal" ? isValidPropertyName(name.value) ? name.value : `'${name.value}'` : `[${sourceCode.getText(name)}]`}: ${sourceCode.getText(value)},`
|
|
185
|
+
)
|
|
186
|
+
),
|
|
187
|
+
` },`
|
|
188
|
+
] : [],
|
|
189
|
+
"}"
|
|
190
|
+
].join(`
|
|
191
|
+
${indentation}`);
|
|
192
|
+
let responseVariableNameToUse;
|
|
150
193
|
if (responseVariable === void 0) {
|
|
151
|
-
|
|
152
|
-
|
|
194
|
+
responseVariableNameToUse = `response${responseVariableCounter === 0 ? "" : responseVariableCounter.toString()}`;
|
|
195
|
+
responseVariableCounter++;
|
|
153
196
|
} else {
|
|
154
|
-
|
|
155
|
-
variableNameToUse = responseVariable.name;
|
|
156
|
-
}
|
|
157
|
-
const fixtureApiCallText = sourceCode.getText(fixtureCall);
|
|
158
|
-
const fixtureMethodText = sourceCode.getText(fixtureFunction);
|
|
159
|
-
const fetchStatementStart = fixtureCallInformation.root.type === "ReturnStatement" && fixtureCallInformation.assertions === void 0 ? "return" : "await";
|
|
160
|
-
let replacedText = fixtureApiCallText.replace(fixtureMethodText, `${fetchStatementStart} fetch`);
|
|
161
|
-
const fixtureArgumentText = sourceCode.getText(urlArgumentNode);
|
|
162
|
-
let fetchArgumentText = replaceEndpointUrlPrefixWithBasePath(fixtureArgumentText);
|
|
163
|
-
if (methodNode.name !== "get" || fixtureCallInformation.requestBody !== void 0 || fixtureCallInformation.requestHeaders !== void 0) {
|
|
164
|
-
fetchArgumentText += [
|
|
165
|
-
", {",
|
|
166
|
-
` method: '${methodNode.name.toUpperCase()}',`,
|
|
167
|
-
...fixtureCallInformation.requestBody ? [` body: JSON.stringify(${sourceCode.getText(fixtureCallInformation.requestBody)}),`] : [],
|
|
168
|
-
...fixtureCallInformation.requestHeaders ? [
|
|
169
|
-
` headers: {`,
|
|
170
|
-
...fixtureCallInformation.requestHeaders.map(
|
|
171
|
-
({ name, value }) => (
|
|
172
|
-
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions, no-nested-ternary, sonarjs/no-nested-template-literals
|
|
173
|
-
` ${name.type === "Literal" ? isValidPropertyName(name.value) ? name.value : `'${name.value}'` : `[${sourceCode.getText(name)}]`}: ${sourceCode.getText(value)},`
|
|
174
|
-
)
|
|
175
|
-
),
|
|
176
|
-
` },`
|
|
177
|
-
] : [],
|
|
178
|
-
"}"
|
|
179
|
-
].join(`
|
|
180
|
-
${indentation}`);
|
|
197
|
+
responseVariableNameToUse = responseVariable.name;
|
|
181
198
|
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
199
|
+
const needResponseVariableRedefine = spreadResponseBodyVariable !== void 0 || responseVariable === void 0 && fixtureCallInformation.assertions !== void 0;
|
|
200
|
+
const responseBodyHeadersVariableRedefineLines = needResponseVariableRedefine ? [
|
|
201
|
+
...spreadResponseBodyVariable ? [`const ${spreadResponseBodyVariable.name} = await ${responseVariableNameToUse}.json()`] : [],
|
|
202
|
+
...spreadResponseHeadersVariable ? [`const ${spreadResponseHeadersVariable.name} = ${responseVariableNameToUse}.headers`] : []
|
|
203
|
+
] : [];
|
|
204
|
+
const { statusAssertion, nonStatusAssertions } = createResponseAssertions(
|
|
205
|
+
fixtureCallInformation,
|
|
206
|
+
sourceCode,
|
|
207
|
+
responseVariableNameToUse
|
|
208
|
+
);
|
|
209
|
+
const fetchCallText = `fetch(${fetchUrlArgumentText}, ${fetchRequestArgumentLines})`;
|
|
210
|
+
const fetchStatementText = !needResponseVariableRedefine ? fetchCallText : `const ${responseVariableNameToUse} = await ${fetchCallText}`;
|
|
211
|
+
const nodeToReplace = needResponseVariableRedefine ? fixtureCallInformation.rootNode : fixtureCallInformation.fixtureNode;
|
|
212
|
+
const appendingAssignmentAndAssertionText = [
|
|
213
|
+
"",
|
|
214
|
+
...statusAssertion !== void 0 ? [statusAssertion] : [],
|
|
215
|
+
...responseBodyHeadersVariableRedefineLines,
|
|
216
|
+
...nonStatusAssertions
|
|
217
|
+
].join(`;
|
|
191
218
|
${indentation}`);
|
|
192
|
-
}
|
|
193
219
|
context.report({
|
|
194
220
|
node: fixtureCall,
|
|
195
221
|
messageId: "preferNativeFetch",
|
|
196
222
|
*fix(fixer) {
|
|
197
|
-
yield fixer.replaceText(
|
|
223
|
+
yield fixer.replaceText(nodeToReplace, fetchStatementText);
|
|
224
|
+
const needEndingSemiColon = sourceCode.getText(nodeToReplace).endsWith(";");
|
|
225
|
+
yield fixer.insertTextAfter(
|
|
226
|
+
nodeToReplace,
|
|
227
|
+
needEndingSemiColon ? `${appendingAssignmentAndAssertionText};` : appendingAssignmentAndAssertionText
|
|
228
|
+
);
|
|
198
229
|
for (const responseBodyReference of responseBodyReferences) {
|
|
199
|
-
yield fixer.replaceText(responseBodyReference, `await ${
|
|
230
|
+
yield fixer.replaceText(responseBodyReference, `await ${responseVariableNameToUse}.json()`);
|
|
200
231
|
}
|
|
201
232
|
for (const responseHeadersReference of responseHeadersReferences) {
|
|
202
233
|
const parent = getParent(responseHeadersReference);
|
|
@@ -211,28 +242,24 @@ ${indentation}`);
|
|
|
211
242
|
headerName = sourceCode.getText(headerNameNode);
|
|
212
243
|
}
|
|
213
244
|
assert.ok(headerName);
|
|
214
|
-
yield fixer.replaceText(parent, `${
|
|
245
|
+
yield fixer.replaceText(parent, `${responseVariableNameToUse}.headers.get(${headerName})`);
|
|
215
246
|
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
`;
|
|
220
|
-
${indentation}return ${variableNameToUse};`
|
|
221
|
-
);
|
|
222
|
-
}
|
|
223
|
-
function* statusCodeReplacer(reference) {
|
|
224
|
-
const parent = getParent(reference.identifier);
|
|
225
|
-
if (parent?.type === "MemberExpression" && parent.property.type === "Identifier" && parent.property.name === "statusCode") {
|
|
226
|
-
yield fixer.replaceText(parent.property, "status");
|
|
247
|
+
for (const responseStatusReference of responseStatusReferences) {
|
|
248
|
+
if (responseStatusReference.property.type === "Identifier" && responseStatusReference.property.name === "statusCode") {
|
|
249
|
+
yield fixer.replaceText(responseStatusReference.property, `status`);
|
|
227
250
|
}
|
|
228
251
|
}
|
|
229
|
-
|
|
230
|
-
yield
|
|
252
|
+
if (fixtureCallInformation.rootNode.type === "ReturnStatement" && fixtureCallInformation.assertions !== void 0) {
|
|
253
|
+
yield fixer.insertTextAfter(
|
|
254
|
+
fixtureCallInformation.rootNode,
|
|
255
|
+
`
|
|
256
|
+
${indentation}return ${responseVariableNameToUse};`
|
|
257
|
+
);
|
|
231
258
|
}
|
|
232
259
|
}
|
|
233
260
|
});
|
|
234
261
|
} catch (error) {
|
|
235
|
-
console.
|
|
262
|
+
console.error(`Failed to apply ${ruleId} rule. Error:`, error);
|
|
236
263
|
context.report({
|
|
237
264
|
node: fixtureCall,
|
|
238
265
|
messageId: "unknownError",
|
|
@@ -250,4 +277,4 @@ export {
|
|
|
250
277
|
no_fixture_default as default,
|
|
251
278
|
ruleId
|
|
252
279
|
};
|
|
253
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
280
|
+
//# sourceMappingURL=data:application/json;base64,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
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { Node } from 'estree';
|
|
2
|
+
export declare function getParent(node: Node): Node | undefined | null;
|
|
3
|
+
export declare function getAncestor(node: Node, typeToMatch: string, typeToExit: string): import("estree").Property | import("estree").CatchClause | import("estree").ClassDeclaration | import("estree").ClassExpression | import("estree").ClassBody | import("estree").Identifier | import("estree").SimpleLiteral | import("estree").RegExpLiteral | import("estree").BigIntLiteral | import("estree").ArrayExpression | import("estree").ArrowFunctionExpression | import("estree").AssignmentExpression | import("estree").AwaitExpression | import("estree").BinaryExpression | import("estree").SimpleCallExpression | import("estree").NewExpression | import("estree").ChainExpression | import("estree").ConditionalExpression | import("estree").FunctionExpression | import("estree").ImportExpression | import("estree").LogicalExpression | import("estree").MemberExpression | import("estree").MetaProperty | import("estree").ObjectExpression | import("estree").SequenceExpression | import("estree").TaggedTemplateExpression | import("estree").TemplateLiteral | import("estree").ThisExpression | import("estree").UnaryExpression | import("estree").UpdateExpression | import("estree").YieldExpression | import("estree").FunctionDeclaration | import("estree").MethodDefinition | import("estree").ImportDeclaration | import("estree").ExportNamedDeclaration | import("estree").ExportDefaultDeclaration | import("estree").ExportAllDeclaration | import("estree").ImportSpecifier | import("estree").ImportDefaultSpecifier | import("estree").ImportNamespaceSpecifier | import("estree").ExportSpecifier | import("estree").ObjectPattern | import("estree").ArrayPattern | import("estree").RestElement | import("estree").AssignmentPattern | import("estree").PrivateIdentifier | import("estree").Program | import("estree").PropertyDefinition | import("estree").SpreadElement | import("estree").ExpressionStatement | import("estree").BlockStatement | import("estree").StaticBlock | import("estree").EmptyStatement | import("estree").DebuggerStatement | import("estree").WithStatement | import("estree").ReturnStatement | import("estree").LabeledStatement | import("estree").BreakStatement | import("estree").ContinueStatement | import("estree").IfStatement | import("estree").SwitchStatement | import("estree").ThrowStatement | import("estree").TryStatement | import("estree").WhileStatement | import("estree").DoWhileStatement | import("estree").ForStatement | import("estree").ForInStatement | import("estree").ForOfStatement | import("estree").VariableDeclaration | import("estree").Super | import("estree").SwitchCase | import("estree").TemplateElement | import("estree").VariableDeclarator | undefined;
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@checkdigit/eslint-plugin","version":"6.6.0-PR.75-
|
|
1
|
+
{"name":"@checkdigit/eslint-plugin","version":"6.6.0-PR.75-3e31","description":"Check Digit eslint plugins","keywords":["eslint","eslintplugin"],"homepage":"https://github.com/checkdigit/eslint-plugin#readme","bugs":{"url":"https://github.com/checkdigit/eslint-plugin/issues"},"repository":{"type":"git","url":"https://github.com/checkdigit/eslint-plugin"},"license":"MIT","author":"Check Digit, LLC","sideEffects":false,"type":"module","exports":{".":{"types":"./dist-types/index.d.ts","require":"./dist-cjs/index.cjs","import":"./dist-mjs/index.mjs","default":"./dist-mjs/index.mjs"}},"files":["src","dist-types","dist-cjs","dist-mjs","!src/**/*.test.ts","!src/**/*.spec.ts","!dist-types/**/*.test.d.ts","!dist-types/**/*.spec.d.ts","!dist-cjs/**/*.test.cjs","!dist-cjs/**/*.spec.cjs","!dist-mjs/**/*.test.mjs","!dist-mjs/**/*.spec.mjs","SECURITY.md"],"scripts":{"build:dist-cjs":"rimraf dist-cjs && npx builder --type=commonjs --sourceMap --entryPoint=index.ts --outDir=dist-cjs --outFile=index.cjs && echo \"module.exports = module.exports.default;\" >> dist-cjs/index.cjs && node dist-cjs/index.cjs","build:dist-mjs":"rimraf dist-mjs && npx builder --type=module --sourceMap --outDir=dist-mjs && node dist-mjs/index.mjs","build:dist-types":"rimraf dist-types && npx builder --type=types --outDir=dist-types","ci:compile":"tsc --noEmit","ci:coverage":"NODE_OPTIONS=\"--disable-warning ExperimentalWarning --experimental-vm-modules\" jest --coverage=true","ci:lint":"npm run lint","ci:style":"npm run prettier","ci:test":"NODE_OPTIONS=\"--disable-warning ExperimentalWarning --experimental-vm-modules\" jest --coverage=false","lint":"eslint --max-warnings 0 --ignore-path .gitignore .","lint:fix":"eslint --ignore-path .gitignore . --fix","prepublishOnly":"npm run build:dist-types && npm run build:dist-cjs && npm run build:dist-mjs","prettier":"prettier --ignore-path .gitignore --list-different .","prettier:fix":"prettier --ignore-path .gitignore --write .","test":"npm run ci:compile && npm run ci:test && npm run ci:lint && npm run ci:style"},"prettier":"@checkdigit/prettier-config","jest":{"preset":"@checkdigit/jest-config"},"devDependencies":{"@checkdigit/jest-config":"^6.0.2","@checkdigit/prettier-config":"^5.5.0","@checkdigit/typescript-config":"6.0.0","@types/eslint":"^8.56.10","@typescript-eslint/eslint-plugin":"^7.16.1","@typescript-eslint/parser":"^7.16.1","eslint-config-prettier":"^9.1.0","eslint-plugin-eslint-plugin":"^6.2.0","eslint-plugin-import":"^2.29.1","eslint-plugin-no-only-tests":"^3.1.0","eslint-plugin-no-secrets":"^1.0.2","eslint-plugin-node":"^11.1.0","eslint-plugin-sonarjs":"0.24.0"},"peerDependencies":{"eslint":">=8 <9"},"engines":{"node":">=20.14"}}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// format.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 { Node } from 'estree';
|
|
10
|
+
import type { SourceCode } from 'eslint';
|
|
11
|
+
import { strict as assert } from 'node:assert';
|
|
12
|
+
|
|
13
|
+
export function getIndentation(node: Node, sourceCode: SourceCode) {
|
|
14
|
+
assert.ok(node.loc);
|
|
15
|
+
const line = sourceCode.lines[node.loc.start.line - 1];
|
|
16
|
+
assert.ok(line);
|
|
17
|
+
const indentMatch = line.match(/^\s*/u);
|
|
18
|
+
return indentMatch ? indentMatch[0] : '';
|
|
19
|
+
}
|
package/src/ast/tree.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// tree.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 { Node } from 'estree';
|
|
10
|
+
|
|
11
|
+
type NodeParent = Node | undefined | null;
|
|
12
|
+
|
|
13
|
+
interface NodeParentExtension {
|
|
14
|
+
parent: NodeParent;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function getParent(node: Node): Node | undefined | null {
|
|
18
|
+
return (node as unknown as NodeParentExtension).parent;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function getAncestor(node: Node, typeToMatch: string, typeToExit: string) {
|
|
22
|
+
const parent = getParent(node);
|
|
23
|
+
if (!parent || parent.type === typeToExit) {
|
|
24
|
+
return undefined;
|
|
25
|
+
} else if (parent.type === typeToMatch) {
|
|
26
|
+
return parent;
|
|
27
|
+
}
|
|
28
|
+
return getAncestor(parent, typeToMatch, typeToExit);
|
|
29
|
+
}
|