-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
refactor: enable safe index access by setting noUncheckedIndexedAccess
#78
base: dev
Are you sure you want to change the base?
Conversation
@@ -110,7 +110,7 @@ export class PageHelper { | |||
prevStart: number, | |||
idGetter: (item: TData) => number, | |||
): [TData[], PageRespondDto] { | |||
if (data.length == 0 || pageSize < 0) { | |||
if (data[0] == null || pageSize < 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TData maybe T | undefined
@coderabbitai review |
WalkthroughThe recent updates focus on enhancing code readability, maintainability, and error handling across various components of the project. Key improvements include the introduction of new private methods for cleaner logic abstraction, refinements in variable naming and function return types for consistency, and the adoption of optional chaining for more robust error handling. These changes contribute to a more organized and efficient codebase, facilitating easier future development and debugging. Changes
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (invoked as PR comments)
Additionally, you can add CodeRabbit Configration File (
|
@coderabbitai review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Review Status
Actionable comments generated: 7
Configuration used: CodeRabbit UI
Files ignored due to path filters (1)
tsconfig.json
is excluded by:!**/*.json
Files selected for processing (11)
- src/auth/session.service.ts (3 hunks)
- src/common/helper/page.helper.ts (1 hunks)
- src/users/users.controller.ts (3 hunks)
- test/answer.e2e-spec.ts (3 hunks)
- test/comment.e2e-spec.ts (23 hunks)
- test/groups.e2e-spec.ts (26 hunks)
- test/question.e2e-spec.ts (4 hunks)
- test/topic.e2e-spec.ts (2 hunks)
- test/user.e2e-spec.ts (18 hunks)
- test/user.follow.e2e-spec.ts (4 hunks)
- test/user.profile.e2e-spec.ts (2 hunks)
Check Runs (16)
test (12, 8.0.0, 18.x, 8) completed (1)
test (12, 8.0.0, 18.x, 6) completed (1)
test (12, 8.0.0, 16.x, 8) completed (1)
test (12, 8.0.0, 16.x, 6) completed (1)
test (12, 8.12.2, 18.x, 8) completed (1)
test (12, 8.12.2, 18.x, 6) completed (1)
test (12, 8.12.2, 16.x, 8) completed (1)
test (12, 8.12.2, 16.x, 6) completed (1)
test (latest, 8.0.0, 18.x, 8) completed (1)
test (latest, 8.0.0, 18.x, 6) completed (1)
test (latest, 8.0.0, 16.x, 8) completed (1)
test (latest, 8.0.0, 16.x, 6) completed (1)
test (latest, 8.12.2, 18.x, 8) completed (1)
test (latest, 8.12.2, 18.x, 6) completed (1)
test (latest, 8.12.2, 16.x, 8) completed (1)
test (latest, 8.12.2, 16.x, 6) completed (1)
Additional comments: 34
src/common/helper/page.helper.ts (1)
- 113-113: The change from checking the length to checking if the first element is
null
enhances safety by explicitly handling potentiallynull
orundefined
values. This is a good practice. Consider adding a comment explaining why this check is necessary for future maintainability.src/auth/session.service.ts (3)
- 77-90: The addition of
getSessionIdByRefreshToken
improves code readability and reusability by encapsulating the logic for extracting the session ID from a refresh token. Ensure that theauthService.verify
method called within handles potential errors robustly.- 101-101: Refactoring
refreshSession
to usegetSessionIdByRefreshToken
simplifies its logic and improves maintainability without compromising functionality.- 167-167: Refactoring
revokeSession
to usegetSessionIdByRefreshToken
enhances code consistency and maintainability.test/user.profile.e2e-spec.ts (2)
- 36-42: Refactoring the way mocked email service methods are accessed and reset in the
beforeEach
block improves readability and maintainability. Ensure that optional chaining is used appropriately and doesn't mask potential issues with the mock setup.- 60-68: Using optional chaining for accessing
MockedEmailService
methods in tests makes the assertions cleaner. Ensure that the tests still accurately capture the intended behavior and that optional chaining doesn't lead to false positives.test/user.follow.e2e-spec.ts (4)
- 37-37: Using optional chaining (
?.
) here improves the safety of accessingsendRegisterCode
on potentially undefined instances ofMockedEmailService
. This is a good practice, especially in tests where the setup might not always guarantee the presence of mocked instances.- 64-73: The use of optional chaining (
?.
) in these lines is consistent with the approach to safely access methods on potentially undefined objects. This change enhances the robustness of the test setup phase by preventing possible runtime errors.- 91-97: The application of optional chaining (
?.
) in these assertions is appropriate and aligns with the goal of making the code safer and more resilient to potential null or undefined values. This practice should help maintain the reliability of the tests.- 139-141: Adding a check for
tempUserIds[0]
being null or undefined before proceeding with the test is a crucial safety measure. This prevents the test from failing in an unclear manner if the setup did not populatetempUserIds
as expected. Throwing an explicit error provides clearer feedback for debugging.test/answer.e2e-spec.ts (3)
- 37-37: The use of optional chaining (
?.
) when accessingsendRegisterCode
onMockedEmailService.mock.instances[0]
is a prudent choice. It ensures that the test does not fail due to an undefined object, which aligns with the goal of making the codebase more robust.- 63-69: The introduction of a local variable
mockedEmailService
to holdMockedEmailService.mock.instances[0]
and the subsequent use of optional chaining (?.
) is a significant improvement. It not only makes the code cleaner but also safer by handling potential undefined instances gracefully.- 87-93: Applying optional chaining (
?.
) in these assertions is consistent with the overall goal of enhancing code safety and reliability. This approach minimizes the risk of encountering runtime errors due to undefined or null values in the test setup.test/comment.e2e-spec.ts (9)
- 30-33: Renaming
CommentIds
tocommentIds
,TopicIds
totopicIds
, andTestCommentPrefix
totestCommentPrefix
improves readability and adheres to the camelCase naming convention typically used in TypeScript for variables. This change aligns with best practices for naming conventions in TypeScript.- 56-56: The adjustment in the return value of the
createAuxiliaryUser
function to return both the user ID and access token as a tuple is a good practice. It makes the function more versatile by providing both pieces of information needed in subsequent tests without requiring additional calls or global variables.- 69-75: Refactoring the
beforeEach
function to reset themockedEmailService
calls and results for each test ensures that the mock state is clean before each test runs. This is crucial for avoiding test interference and ensuring that each test runs in a predictable environment.- 202-208: The modification in the
createComment
function to explicitly check forundefined
commentableId
and throw an error if it is undefined is a good practice for error handling. This ensures that the function fails fast with a clear error message if required arguments are not provided, which can help in debugging and maintaining the code.- 220-226: Appending created comment IDs to the
commentIds
array for future reference in tests is a practical approach to managing resources created during tests. This allows for easy access to these resources in subsequent tests, such as deleting or querying comments, which can help in cleaning up or further testing.- 234-234: The use of
testCommentPrefix
in the content of a comment being tested ensures that test-generated content is easily identifiable. This can be useful for filtering or cleaning up test data from the application if needed.- 297-297: Retrieving a comment by its ID and verifying the response structure and content is a good practice for testing read operations in the API. This test ensures that the comment retrieval functionality works as expected and returns the correct data.
- 344-344: Testing the functionality to express an attitude towards a comment is important for ensuring that the application's interaction features work as intended. This test verifies that users can successfully agree to a comment and that the system records this action correctly.
- 483-483: The test for deleting a comment verifies that the delete operation works as expected and that the system correctly responds with a status indicating the comment has been deleted. This is crucial for ensuring that the application can manage content dynamically.
test/question.e2e-spec.ts (3)
- 42-42: The use of optional chaining here (
MockedEmailService.mock.instances[0]?.sendRegisterCode
) is a good practice as it enhances the safety of the code by preventing potential runtime errors whenmock.instances[0]
isundefined
. This change aligns with the PR's objective to improve code safety and reliability.- 68-74: Initializing the
mockedEmailService
variable and resetting the mock calls and results at the beginning of each test is a good practice. It ensures that the state is clean for every test, which is crucial for avoiding test interferences and ensuring test reliability.- 92-98: The verification of the
sendRegisterCode
method being called with the expected arguments and the correct number of times demonstrates attention to detail in testing the email verification functionality. This ensures that the email service behaves as expected, which is critical for user registration flows.test/groups.e2e-spec.ts (8)
- 34-35: Consider using a more deterministic approach for generating unique test group prefixes to avoid potential collisions in parallel test executions.
- 38-47: The creation of auxiliary users involves direct interaction with the email service mock. Ensure that this approach is consistent with the overall testing strategy and consider abstracting it for reuse.
- 97-100: The assertions on the mock email service's behavior are good for ensuring the expected interactions. However, consider also verifying the content of the email sent to ensure it meets the application's requirements.
Also applies to: 103-103
- 126-132: > 📝 NOTE
This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [129-147]
Creating groups in tests without cleaning them up can lead to state pollution between tests. Ensure that there is a teardown step that cleans up created groups to maintain test isolation.
- 355-361: > 📝 NOTE
This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [358-382]
The tests for fetching a group's details are well-structured. However, consider adding assertions for additional fields in the
groupDto
to ensure all expected properties are correctly returned and populated.
- 418-421: The explicit check for
groupId == null
is good for error handling. Consider also logging an error message or throwing a more descriptive error to aid in debugging when this condition is met.- 544-549: The test for permission control is crucial. Ensure that the application has implemented and enforced permission checks correctly, and consider adding more tests to cover various permission scenarios.
- 656-662: > 📝 NOTE
This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [659-678]
The pagination logic in the
get group members
tests is well-tested. Consider adding tests for edge cases, such as when thepage_start
is beyond the last member, to ensure the pagination logic handles these scenarios gracefully.Also applies to: 697-715
test/user.e2e-spec.ts (1)
- 114-120: Using optional chaining (
?.
) when accessingMockedEmailService.mock.instances[0]?.sendRegisterCode
and similar patterns throughout the tests is a good practice to avoid potential runtime errors when the instance might be undefined. This change aligns with the PR's objective to enhance safety and reliability through stricter type checks.This approach correctly handles potential null values, improving the robustness of the test suite.
Also applies to: 156-162, 214-220, 283-289, 323-329, 361-367, 399-405, 442-448, 467-471, 522-526, 553-559, 580-584, 615-621, 640-644, 789-795, 853-859, 892-899
async function unfollow(questionId: number | undefined) { | ||
if (questionId == undefined) { | ||
throw new Error('questionId is undefined'); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The addition of a guard clause to throw an error if questionId
is undefined
is a proactive approach to error handling. This change ensures that the function fails fast if called with incorrect arguments, preventing potential runtime errors further down the execution path. However, consider adding a more descriptive error message to aid in debugging.
- throw new Error('questionId is undefined');
+ throw new Error('unfollow function was called with an undefined questionId. Ensure questionId is provided.');
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.
async function unfollow(questionId: number | undefined) { | |
if (questionId == undefined) { | |
throw new Error('questionId is undefined'); | |
} | |
async function unfollow(questionId: number | undefined) { | |
if (questionId == undefined) { | |
throw new Error('unfollow function was called with an undefined questionId. Ensure questionId is provided.'); | |
} |
const mockedEmailService = MockedEmailService.mock.instances[0]!; | ||
(mockedEmailService.sendRegisterCode as jest.Mock).mock.calls.length = 0; | ||
(mockedEmailService.sendRegisterCode as jest.Mock).mock.results.length = 0; | ||
(mockedEmailService.sendPasswordResetEmail as jest.Mock).mock.calls.length = | ||
0; | ||
( | ||
MockedEmailService.mock.instances[0].sendRegisterCode as jest.Mock | ||
).mock.calls.length = 0; | ||
( | ||
MockedEmailService.mock.instances[0].sendRegisterCode as jest.Mock | ||
).mock.results.length = 0; | ||
( | ||
MockedEmailService.mock.instances[0].sendPasswordResetEmail as jest.Mock | ||
).mock.calls.length = 0; | ||
( | ||
MockedEmailService.mock.instances[0].sendPasswordResetEmail as jest.Mock | ||
mockedEmailService.sendPasswordResetEmail as jest.Mock |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Resetting mock calls and results manually in beforeEach
can be error-prone. Consider using Jest's built-in reset functions like jest.clearAllMocks()
for clarity and reliability.
- (mockedEmailService.sendRegisterCode as jest.Mock).mock.calls.length = 0;
- (mockedEmailService.sendRegisterCode as jest.Mock).mock.results.length = 0;
- (mockedEmailService.sendPasswordResetEmail as jest.Mock).mock.calls.length = 0;
- (mockedEmailService.sendPasswordResetEmail as jest.Mock).mock.results.length = 0;
+ jest.clearAllMocks();
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.
const mockedEmailService = MockedEmailService.mock.instances[0]!; | |
(mockedEmailService.sendRegisterCode as jest.Mock).mock.calls.length = 0; | |
(mockedEmailService.sendRegisterCode as jest.Mock).mock.results.length = 0; | |
(mockedEmailService.sendPasswordResetEmail as jest.Mock).mock.calls.length = | |
0; | |
( | |
MockedEmailService.mock.instances[0].sendRegisterCode as jest.Mock | |
).mock.calls.length = 0; | |
( | |
MockedEmailService.mock.instances[0].sendRegisterCode as jest.Mock | |
).mock.results.length = 0; | |
( | |
MockedEmailService.mock.instances[0].sendPasswordResetEmail as jest.Mock | |
).mock.calls.length = 0; | |
( | |
MockedEmailService.mock.instances[0].sendPasswordResetEmail as jest.Mock | |
mockedEmailService.sendPasswordResetEmail as jest.Mock | |
const mockedEmailService = MockedEmailService.mock.instances[0]!; | |
jest.clearAllMocks(); |
const TestGroupId = groupIds[0]; | ||
const respond = await request(app.getHttpServer()) | ||
.put(`/groups/${TestGroupId}`) | ||
.set('Authorization', `Bearer ${TestToken}`) | ||
.send({ | ||
name: TestGroupPrefix + '关注幻城谢谢喵', | ||
name: testGroupPrefix + '关注幻城谢谢喵', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When updating a group, ensure that the test verifies not just the success response but also that the group's details have been updated as expected by fetching the group again and checking the updated fields.
const TestGroupId = groupIds[0]; | ||
const respond = await request(app.getHttpServer()) | ||
.put(`/groups/${TestGroupId}`) | ||
.set('Authorization', `Bearer ${TestToken}`) | ||
.send({ | ||
name: TestGroupPrefix + 'ICS膜膜膜', | ||
name: testGroupPrefix + 'ICS膜膜膜', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The test for the GroupNameAlreadyUsedError
is important for ensuring unique group names. Consider adding a setup step that explicitly creates a group with the conflicting name to make the test more robust and self-contained.
@@ -740,7 +740,7 @@ | |||
expect(respond.body.code).toBe(404); | |||
}); | |||
it('should return empty list when page_size is not positive', async () => { | |||
const TestGroupId = GroupIds[1]; | |||
const TestGroupId = groupIds[1]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Testing for invalid page_size
input is good for ensuring robustness. Consider also testing other invalid inputs and edge cases to ensure the API handles them gracefully.
const mockedEmailService = MockedEmailService.mock.instances[0]!; | ||
(mockedEmailService.sendRegisterCode as jest.Mock).mock.calls.length = 0; | ||
(mockedEmailService.sendRegisterCode as jest.Mock).mock.results.length = 0; | ||
(mockedEmailService.sendPasswordResetEmail as jest.Mock).mock.calls.length = | ||
0; | ||
( | ||
MockedEmailService.mock.instances[0].sendRegisterCode as jest.Mock | ||
).mock.calls.length = 0; | ||
( | ||
MockedEmailService.mock.instances[0].sendRegisterCode as jest.Mock | ||
).mock.results.length = 0; | ||
( | ||
MockedEmailService.mock.instances[0].sendPasswordResetEmail as jest.Mock | ||
).mock.calls.length = 0; | ||
( | ||
MockedEmailService.mock.instances[0].sendPasswordResetEmail as jest.Mock | ||
mockedEmailService.sendPasswordResetEmail as jest.Mock |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Refactoring the mock setup for EmailService
improves readability and maintainability by resetting mock calls and results directly. However, directly manipulating mock.calls.length
and mock.results.length
is unconventional and might lead to unexpected behavior or maintenance issues in the future.
Consider using jest.clearAllMocks()
or jest.resetAllMocks()
at the beginning of the beforeEach
block to achieve the same effect in a more conventional and reliable manner.
expect(respond.header['set-cookie']?.[0]).toMatch( | ||
/^REFRESH_TOKEN=.+; Path=\/users\/auth; Expires=.+; HttpOnly; SameSite=Strict$/, | ||
); | ||
TestRefreshToken = respond.header['set-cookie'][0] | ||
.split(';')[0] | ||
.split('=')[1]; | ||
const TestRefreshToken2 = respond?.header?.['set-cookie']?.[0] | ||
?.split(';')?.[0] | ||
?.split('=')?.[1]; | ||
expect(TestRefreshToken2).toBeDefined(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The handling of set-cookie
headers to extract the REFRESH_TOKEN
value demonstrates a detailed understanding of HTTP headers and cookie manipulation. However, this pattern is repeated multiple times throughout the file, which could be refactored into a helper function to improve code reusability and maintainability.
Consider creating a utility function, such as extractRefreshTokenFromHeader
, to encapsulate the logic for extracting the REFRESH_TOKEN
value from the set-cookie
header. This function can then be reused across all test cases that require this operation.
Also applies to: 467-471, 522-526, 553-559, 580-584, 615-621, 640-644
d08274a
to
d840758
Compare
Summary by CodeRabbit
PageHelper
to correctly handle empty data scenarios.