Added new rule to detect assertions where statusCode is in the parameter#97
Added new rule to detect assertions where statusCode is in the parameter#97
Conversation
le-cong
left a comment
There was a problem hiding this comment.
just a few things, also does it make sense to check number literal values such as 200/409/etc. because they are also frequently used in status code assertion? ideally they should be replaced by StatusCodes.OK/etc. from http-status-codes package.
maybe it should be a separated rules? i'm not sure ...
src/no-status-code-assert.ts
Outdated
|
|
||
| export const ruleId = 'no-status-code-assert'; | ||
| const NO_STATUS_CODE_ASSERT = 'NO_STATUS_CODE_ASSERT'; | ||
| const keywords = ['status', 'code', 'StatusCodes', 'statusCode']; |
There was a problem hiding this comment.
status/code are widely used in none response status code related assertions, e.g. things like account.status/message.code can be incorrectly labelled.
There was a problem hiding this comment.
@le-cong refactored to just check for StatusCodes for all assertions in parameters else if it is BinaryExpression check on either side.
src/no-status-code-assert.ts
Outdated
| */ | ||
| const hasStatusCodeOrValue = (arg: TSESTree.Node): boolean => { | ||
| const checkName = (name?: string): boolean => | ||
| name !== undefined && keywords.some((keyword) => name.toLowerCase().includes(keyword)); |
There was a problem hiding this comment.
the usage of name.toLowerCase() seems contradict with the keyword const values which contains upper case values.
src/no-status-code-assert.ts
Outdated
| node.object.name === 'assert' && | ||
| node.property.type === AST_NODE_TYPES.Identifier; | ||
|
|
||
| //Checks if a given AST node is an identifier with the name 'assert'. |
src/no-status-code-assert.ts
Outdated
|
|
||
| const isAssertCallWithStatusCode = (callee: TSESTree.Node, args: TSESTree.Node[]): boolean => | ||
| (isAssertIdentifier(callee) || isAssertMemberExpression(callee)) && | ||
| args.some((arg) => hasStatusCodeOrValue(arg) && arg.type !== AST_NODE_TYPES.Identifier); |
There was a problem hiding this comment.
the arg.type check seems unnecessary given the fact that hasStatusCodeOrValue function is already testing some specific conditions in its switch statements.
src/no-status-code-assert.ts
Outdated
| switch (arg.type) { | ||
| case AST_NODE_TYPES.Literal: | ||
| if (typeof arg.value === 'number') { | ||
| return isStatusCodeLiteral(arg.value); |
There was a problem hiding this comment.
this branch doesn't have test coverage, either add test case or remove this logic and leave it for a separated rule to detect the direct usage of numeric value instead of http-status-codes for response status code?
There was a problem hiding this comment.
oh we are just focusing on statusCodes, we can remove this
docs/rules/no-status-code-assert.md
Outdated
| ## Fail | ||
|
|
||
| ```js | ||
| assert(statusCode === 200); |
There was a problem hiding this comment.
update to reflect the latest implementation?
There was a problem hiding this comment.
@carlansley should we have rule to auto fix the prod code with statusCode if we have numbers?
There was a problem hiding this comment.
Not sure I can answer that, can we add a little more description to the issue/PR about what this entire rule is needed for? I'm sure this was discussed at some point but tbh I don't recall what the original problem was.
There was a problem hiding this comment.
We need to monitor for assertion failures in production and also improve how assertions are used in production code. Currently, assertions are being used for status checks, which isn’t ideal. A good first step is to implement an ESLint rule that will detect when assertions are made using a statusCode as one of the parameters. This will help identify and clean up improper use of assertions in the code. notify service could look for assertion errors, but we need to clean up usage of assertions for status checks.
As we are checking for statusCode, should we have another rule to auto fix the prod code with statusCode if we have numbers some thing like
assert(statusCode === 200);
would be assert(statusCode === StatusCodes.OK);
There was a problem hiding this comment.
is there a mistake in the documentation wrt what is "pass" and what is "fail"? That was what confused me initially.
There was a problem hiding this comment.
But initially it was like
Fail
assert(statusCode === 200);
assert.equal(statusCode, 200);Pass
assert(response.status === 200);
assert.equal(response.status, 200);Updated the rule to handle just statusCodes.
Fail
assert(statusCode === StatusCodes.OK);
assert.equal(statusCode, StatusCodes.OK);Pass
assert(response.status === 200);
assert.equal(response.status, 200);Pass wouldn't report as StatusCodes aren't used. This was the reason if we need to have another rule to auto fix all the numbers to statusCodes?
docs/rules/no-status-code-assert.md
Outdated
| assert(response.status === 200); | ||
| assert.equal(response.status, 200); |
There was a problem hiding this comment.
shouldn't these be failures as well? In a nutshell, we want to disallow the usage of assert to check for the desired response status, whether by using status or statusCode, in production code.
There was a problem hiding this comment.
status/code are widely used in none response status code related assertions, e.g. things like account.status/message.code can be incorrectly labelled. Should we check .status, .code in the params of assert instead
There was a problem hiding this comment.
not sure I understand, but all I'm saying is, just like how you're disallowing assert.ok(response.statusCode === StatusCodes.OK), we should also disallow assert.ok(response.status === StatusCodes.OK)
There was a problem hiding this comment.
assert.ok(response.status === StatusCodes.OK) is disallowed and would be reported as error but assert.equal(response.status, 200); is allowed since the rule check is going by StatusCodes. We can add that to disallow
There was a problem hiding this comment.
created #109 to address the usage of magic number instead of StatusCodes.xxx
There was a problem hiding this comment.
@le-cong, why do we need a separate rule? if 200/201/400/500 etc., are used, it will fail with a no-magic-numbers correct?
There was a problem hiding this comment.
good point, the only thing is that no-magic-number rule is turned off for test codes, thought we might want to be consistent with status code handling all across targeting a specific subset of numbers. thoughts?
There was a problem hiding this comment.
no-magic-number is turned off for https://github.com/checkdigit/eslint-config/blob/main/index.mjs#L208. So, the only HTTP response status codes that will be allowed would be 256 and 512, which are uncommon and I can't think of any services that use these.
There was a problem hiding this comment.
L208 is for default setting including production code, but it's overridden by the next section in https://github.com/checkdigit/eslint-config/blob/5eea1c576703f1ba1663bd6bb73542d19ccbce5d/index.mjs#L438, which disables this rule completely for test codes.
There was a problem hiding this comment.
got it. the new GitHub issue you created makes sense to me then
carlansley
left a comment
There was a problem hiding this comment.
lftm, but main needs to be merged in
|
Beta Published - Install Command: |
|
✅ PR review status - All reviews completed and approved! |
Closes #96
Tested with internal services