-
-
Notifications
You must be signed in to change notification settings - Fork 678
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
feat: add tests for build post list script #3284
base: master
Are you sure you want to change the base?
Conversation
✅ Deploy Preview for asyncapi-website ready!Built without sensitive environment variables
To edit notification comments on pull requests, go to your Netlify site configuration. |
WalkthroughThe pull request introduces significant modifications to the Changes
Possibly related PRs
Suggested labels
Suggested reviewers
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 using PR comments)
Other keywords and placeholders
Documentation and Community
|
⚡️ Lighthouse report for the changes in this PR:
Lighthouse ran on https://deploy-preview-3284--asyncapi-website.netlify.app/ |
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #3284 +/- ##
===========================================
+ Coverage 77.22% 89.45% +12.22%
===========================================
Files 21 21
Lines 663 673 +10
===========================================
+ Hits 512 602 +90
+ Misses 151 71 -80 ☔ View full report in Codecov by Sentry. |
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.
Actionable comments posted: 4
🧹 Outside diff range and nitpick comments (9)
scripts/index.js (3)
11-15
: LGTM! Consider extractingpostDirectories
for improved maintainability.The new
postDirectories
array provides a clear and flexible way to define the directories to be processed bybuildPostList
. This change enhances the configurability of the script.For improved maintainability, consider extracting this array to a separate configuration file. This would allow easier updates to the directory list without modifying the main script. For example:
const { postDirectories } = require('../config/build-config.js');
16-17
: LGTM! Consider usingresolve
forbasePath
as well.The introduction of
basePath
andwriteFilePath
variables improves the flexibility of the script by allowing easy configuration of input and output paths.For consistency, consider using
resolve
forbasePath
as well:const basePath = resolve(__dirname, '..', 'pages');This ensures that the path is always resolved correctly, regardless of the current working directory.
19-19
: LGTM! Consider adding error handling.The updated
buildPostList
function call correctly uses the new parameters, providing more flexibility in the post list building process.Consider adding error handling to manage potential failures in the
buildPostList
function:try { await buildPostList(postDirectories, basePath, writeFilePath); } catch (error) { console.error('Error building post list:', error); // Optionally, you might want to throw the error or handle it in a way that's appropriate for your application }This will help in identifying and debugging any issues that may occur during the post list building process.
tests/build-post-list.test.js (5)
37-53
: LGTM with suggestion: Consider enhancing assertion specificityThe test case effectively verifies the basic functionality of buildPostList. It checks for the existence of the output file and the presence of expected properties in the output.
To further improve the test, consider adding more specific assertions about the content of the output. For example, you could check for the exact number of entries in each category or verify specific fields of the blog entry beyond just the title.
55-82
: LGTM with suggestion: Enhance negative test casesThese test cases effectively cover important scenarios: handling directories with only section files and processing multiple release notes. The assertions verify the presence of expected entries in the output.
To make these tests more robust, consider adding negative assertions. For example, in the "handles multiple release notes correctly" test, you could also verify that no unexpected release notes are present in the output.
84-101
: LGTM with suggestions: Enhance error handling test and expand slugifyToC testsThe error handling test and slugifyToC tests are good additions to the test suite. However, there are opportunities for improvement:
For the error handling test, consider asserting on the specific type of error thrown, not just that an error is thrown.
The slugifyToC tests cover various input scenarios well. Consider adding a test case for a regular heading without an ID to ensure the function behaves correctly in this common scenario.
Example:
it('handles regular headings without ids', () => { const input = '## My Regular Heading'; expect(slugifyToC(input)).toBe('my-regular-heading'); });
148-189
: LGTM with suggestion: Enhance error message assertionsThese additional error handling tests are valuable additions to the test suite, covering important scenarios such as unreadable directories, unparseable front matter, and the case where no post directories are provided.
To further improve these tests, consider making the error message assertions more specific. Instead of just checking for a partial match with "Error while building post list", you could assert on more detailed error messages that provide information about the specific error condition. This would ensure that the function is not only throwing errors but also providing helpful error messages for debugging.
Example:
expect(error.message).toMatch(/Error while building post list: Unable to read directory/);
1-191
: Great job on the comprehensive test suite!This test suite for the buildPostList and slugifyToC functions is well-structured and covers a wide range of scenarios, including both happy paths and error cases. The use of beforeEach and afterEach hooks for setup and teardown is commendable.
To further enhance the test suite, consider adding the following:
- Performance test: Add a test case with a large number of files to ensure the function performs well under load.
- Edge case: Test with very long file names or paths to ensure there are no issues with path length limits.
- Internationalization: If relevant, add tests with non-ASCII characters in file names and content to ensure proper handling of international content.
These additions would make an already strong test suite even more robust.
scripts/build-post-list.js (1)
39-40
: Remove commented out codeThere is a commented-out
console.log
statement at line 39. If it's no longer needed, consider removing it to keep the code clean.Apply this diff to remove the commented code:
- // console.log(inspect(result, { depth: null, colors: true }))
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (4)
- scripts/build-post-list.js (6 hunks)
- scripts/index.js (1 hunks)
- tests/build-post-list.test.js (1 hunks)
- tests/index.test.js (1 hunks)
🧰 Additional context used
🔇 Additional comments (8)
tests/index.test.js (2)
Line range hint
1-35
: LGTM! The changes are consistent throughout the file.The updated import statement for
buildPostList
is the only change in this file, and it's correctly reflected in the rest of the code. The test cases and mocks usebuildPostList
directly, which is consistent with the new named import. The overall structure and functionality of the tests remain intact.
2-2
: LGTM! Verify the corresponding export in the source file.The change from default import to named import is a good practice and improves code clarity. This change suggests that
buildPostList
is now exported as a named export in thebuild-post-list.js
file.To ensure consistency, please verify that the export in
scripts/build-post-list.js
matches this import style. You can run the following script to check:✅ Verification successful
Export Style Verified
The
scripts/build-post-list.js
file correctly exportsbuildPostList
as a named export:module.exports = {slugifyToC, buildPostList}🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify the export style of buildPostList in the source file # Test: Search for the export of buildPostList. Expect: Named export rg --type javascript 'exports?.buildPostList|module\.exports.*buildPostList' scripts/build-post-list.jsLength of output: 140
Script:
#!/bin/bash # Description: Verify the export style of buildPostList in the source file without specifying file type # Test: Search for the export of buildPostList. Expect: Named export rg 'exports?.buildPostList|module\.exports.*buildPostList' scripts/build-post-list.jsLength of output: 132
scripts/index.js (2)
4-19
: Summary: Good refactoring, ensure consistency across the codebase.The changes to
scripts/index.js
significantly improve the flexibility and configurability of the post list building process. The introduction ofpostDirectories
,basePath
, andwriteFilePath
variables, along with the updatedbuildPostList
function call, allow for easier maintenance and future extensions.To ensure consistency across the codebase:
- Verify that all files importing
buildPostList
have been updated to use the new named import syntax.- Check if there are any other scripts or components that might be affected by these changes and update them accordingly.
- Update any documentation or comments related to the post list building process to reflect these new configurations.
Run the following script to identify potential areas that might need updates:
#!/bin/bash # Description: Identify potential areas affected by the changes # Test 1: Find all files that import from build-post-list.js echo "Files importing from build-post-list.js:" rg --type js "from ['\"].*build-post-list['\"]" # Test 2: Find all files that mention buildPostList echo "Files mentioning buildPostList:" rg --type js "buildPostList" # Test 3: Check for any hardcoded paths related to blog, docs, or about pages echo "Files with hardcoded paths:" rg --type js "pages/(blog|docs|about)"Review the output of this script to ensure all affected areas are properly updated.
4-4
: Verify the export change inbuild-post-list.js
and update other imports.The import statement for
buildPostList
has been changed from a default import to a named import. This suggests a corresponding change in thebuild-post-list.js
file.Please run the following script to verify the export in
build-post-list.js
and check for any other import statements in the codebase that might need updating:Ensure that all occurrences are updated to use the new named import syntax.
✅ Verification successful
Export and Imports Verified Successfully.
The
build-post-list.js
file correctly exportsbuildPostList
as a named export, and all import statements in the codebase, includingscripts/index.js
, have been appropriately updated. No further issues were detected.🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify the export in build-post-list.js and check for other imports # Test 1: Check the export in build-post-list.js echo "Checking export in build-post-list.js:" rg --type js "export.*buildPostList" scripts/build-post-list.js # Test 2: Check for other import statements in the codebase echo "Checking for other import statements:" rg --type js "import.*buildPostList.*from ['\"]./build-post-list['\"]" --glob '!scripts/index.js'Length of output: 2201
tests/build-post-list.test.js (2)
1-35
: LGTM: Well-structured test setupThe import statements and describe block setup are well-organized. The use of beforeEach and afterEach hooks to create and clean up a temporary directory structure ensures isolated and repeatable tests. This approach follows testing best practices.
103-146
: LGTM: Comprehensive coverage of specification file handlingThese tests effectively verify that the buildPostList function correctly handles various types of specification files that should not be processed. The tests cover files without a title, files with "next-spec" in the filename, and files with "explorer" in the filename. The consistent approach across these tests and the verification of the absence of these entries in the output demonstrate thorough testing of this functionality.
scripts/build-post-list.js (2)
163-163
: Ensure imports are updated after exportingbuildPostList
Now that
buildPostList
is exported, make sure all modules that import it are updated accordingly.Run the following script to find all import statements of
build-post-list
:#!/bin/bash # Description: Find all import statements of `build-post-list`. # Expectation: Imports should destructure `buildPostList` from the module. rg --type js "require\(.+build-post-list.+\)" -A 2
29-43
: Ensure all calls tobuildPostList
are updatedThe
buildPostList
function now acceptspostDirectories
,basePath
, andwriteFilePath
as parameters. Ensure that all places wherebuildPostList
is called have been updated to use the new signature.Run the following script to find all calls to
buildPostList
and verify their parameters:✅ Verification successful
All calls to
buildPostList
have been updated to use the new signature with three arguments.
tests/build-post-list.test.js
scripts/index.js
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Find all calls to `buildPostList` in the codebase. # Expectation: Calls should use the new signature with three arguments. rg --type js "buildPostList\(" -A 2Length of output: 714
Script:
#!/bin/bash # Description: Find all direct calls to `buildPostList` in the JavaScript codebase. # Improved search pattern to capture function calls with varying whitespace and argument structures. rg --type js "\bbuildPostList\s*\(" -A 2Length of output: 2505
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.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (3)
tests/build-post-list.test.js (3)
37-53
: Consider adding more specific assertionsWhile this test case covers the basic functionality of
buildPostList
, it could be enhanced by adding more specific assertions about the content of the output. For example, you could check for the exact number of entries in each category (docs, blog, about) and verify the structure of individual entries.Here's an example of how you could add more specific assertions:
expect(output.docs).toHaveLength(1); expect(output.blog).toHaveLength(1); expect(output.about).toHaveLength(1); const docEntry = output.docs[0]; expect(docEntry).toHaveProperty('title', 'Docs Home'); expect(docEntry).toHaveProperty('slug', '/docs'); expect(docEntry).toHaveProperty('excerpt');
84-101
: Enhance error handling test and add a case for slugifyToCThe error handling test is good, but it could be more specific:
For the error handling test, consider asserting the specific type of error thrown:
await expect(buildPostList([invalidDir], tempDir, writeFilePath)).rejects.toThrow(Error);Add a test case for slugifyToC with a regular heading without an ID:
it('handles regular headings without ids', () => { const input = '## My Regular Heading'; expect(slugifyToC(input)).toBe('my-regular-heading'); });These additions will improve the test coverage and make the error handling more robust.
148-187
: Enhance error handling testsWhile these additional error handling tests cover important scenarios, they could be improved for more precise error checking:
Instead of catching the error and checking its message, use
expect().rejects.toThrow()
for asynchronous functions:it('throws an error if the directory cannot be read', async () => { const invalidDir = [join(tempDir, 'non-existent-dir'), '/invalid']; await expect(buildPostList([invalidDir], tempDir, writeFilePath)) .rejects.toThrow(/Error while building post list/); });Apply the same pattern to the other two error tests.
Consider adding more specific error message checks if the
buildPostList
function throws different error messages for different scenarios.These changes will make the tests more robust and easier to maintain.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (1)
- tests/build-post-list.test.js (1 hunks)
🧰 Additional context used
🔇 Additional comments (4)
tests/build-post-list.test.js (4)
1-35
: LGTM: Well-structured test setupThe import statements and describe block setup are well-organized. The use of beforeEach and afterEach hooks ensures a clean test environment for each test case, which is a good practice for maintaining test isolation.
55-82
: LGTM: Good coverage of edge casesThese test cases effectively cover important scenarios:
- Handling directories with only section files.
- Processing multiple release notes correctly.
The tests are well-structured and include specific assertions to verify the correct behavior of the
buildPostList
function in these scenarios.
103-146
: LGTM: Comprehensive tests for specification file filteringThese test cases effectively cover the filtering of specification files:
- Files without a title
- Files with "next-spec" in the filename
- Files with "explorer" in the filename
The tests are well-structured and include appropriate assertions to verify that these files are not processed by the
buildPostList
function. This ensures that only the intended files are included in the final output.
1-189
: Overall: Well-structured and comprehensive test suiteThis test file provides a thorough and well-organized suite of tests for the
buildPostList
andslugifyToC
functions. Key strengths include:
- Comprehensive coverage of happy paths, edge cases, and error scenarios.
- Consistent structure throughout the file.
- Good use of beforeEach and afterEach hooks for test isolation.
- Effective testing of file filtering logic.
While there are some minor suggestions for improvements (as noted in previous comments), the overall quality of the test suite is high. It should provide robust validation of the functions' behavior and help catch potential regressions in future development.
Tests are passing on Ubuntu but failing on Windows. I will keep it as a draft until I find a solution for it. |
98f835b
to
ecf927e
Compare
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.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (2)
scripts/build-post-list.js (2)
29-43
: Improved flexibility and error handling inbuildPostList
The changes to the
buildPostList
function are well-implemented:
- The function now accepts parameters, enhancing its configurability and reusability.
- Error handling for empty
postDirectories
has been added, which is a good practice.- The use of a
writeFilePath
parameter allows for more flexible output options.These changes align well with the PR objectives of adding tests, as they make the function more testable.
However, the error handling in the catch block could be improved to preserve the original error stack trace.
Consider updating the error handling to preserve the original stack trace:
} catch (error) { - throw new Error(`Error while building post list: ${error.message}`); + throw new Error('Error while building post list', { cause: error }); }This change will provide more context for debugging while preserving the original error information.
125-128
: Improve variable naming consistency in release notes handlingWhile the logic for extracting version information from release notes file names has been updated, the variable naming could be improved for consistency and clarity.
Consider updating the variable names to follow the camelCase convention used elsewhere in the code:
- const fileName_without_extension = file.slice(0, -4) + const fileNameWithoutExtension = file.slice(0, -4)This change will improve code consistency and readability.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (2)
- scripts/build-post-list.js (7 hunks)
- tests/build-post-list.test.js (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- tests/build-post-list.test.js
🧰 Additional context used
🔇 Additional comments (6)
scripts/build-post-list.js (6)
2-2
: Improved cross-platform compatibilityThe addition of
join
andsep
from thepath
module enhances the code's ability to handle file paths consistently across different operating systems. This is a positive change that aligns with best practices for cross-platform Node.js applications.
47-47
: Improved consistency inwalkDirectories
functionThe addition of
basePath
to thewalkDirectories
function signature and its recursive call ensures consistent handling of the base path throughout the directory traversal process. This change enhances the function's flexibility and aligns well with the modifications made tobuildPostList
.Also applies to: 83-83
55-57
: Enhanced cross-platform compatibility in file path handlingThe updates to file path handling using
join
andsep
, as well as the platform-independent index file check, significantly improve the code's cross-platform compatibility. These changes ensure consistent behavior across different operating systems and align with Node.js best practices for file system operations.Also applies to: 98-98
57-57
: Improved slug generation for cross-platform consistencyThe update to slug generation now uses the
basePath
parameter and normalizes separators to forward slashes. This change ensures consistent slug generation across different platforms, further enhancing the code's cross-platform compatibility.
162-163
: Improved module API with updated exportsThe module exports have been updated to include both
slugifyToC
andbuildPostList
functions. This change enhances the module's API by making both functions available for external use, which aligns well with the PR objectives of adding tests for thebuild-post-list.js
script. This modification will facilitate easier testing and potential reuse of these functions in other parts of the project.
Line range hint
1-163
: Overall assessment of changes tobuild-post-list.js
The modifications to this file are well-implemented and align closely with the PR objectives of adding tests for the
build-post-list.js
script. Key improvements include:
- Enhanced cross-platform compatibility through better file path handling.
- Improved function flexibility with parameterized inputs.
- Better error handling, particularly in the
buildPostList
function.- Updated module exports for easier testing and potential reuse.
These changes contribute positively to the codebase by improving testability, maintainability, and cross-platform consistency. The script is now better equipped to handle various input scenarios, which should facilitate more comprehensive testing.
There are a few minor suggestions for improvement, such as preserving the original error stack trace and maintaining consistent variable naming conventions. Addressing these points will further enhance the overall quality of the code.
da6c058
to
fe9c3da
Compare
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.
Actionable comments posted: 2
🧹 Outside diff range and nitpick comments (1)
tests/build-post-list.test.js (1)
62-64
: Remove unnecessaryconsole.log
statements in testsThe
console.log
statements at lines 62, 64, and 72 are unnecessary and can clutter the test output. Consider removing them to keep the test output clean.Apply this diff to remove the
console.log
statements:- console.log("output before ", output); - console.log("output after ", output); - console.log("blog entry ", blogEntry);Also applies to: 72-72
0b9b50e
to
7ae14bd
Compare
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.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (4)
tests/index.test.js (1)
Line range hint
16-33
: Consider updating the test forbuildPostList
.The test suite currently only checks if
buildPostList
is called, but doesn't verify its parameters. SincebuildPostList
now accepts three parameters (postDirectories
,basePath
, andwriteFilePath
), consider updating the test to ensure it's called with the correct arguments.Here's a suggested update to the test:
test('should call all functions in the correct order', async () => { await start(); expect(buildPostList).toHaveBeenCalledWith( expect.any(Array), // postDirectories expect.any(String), // basePath expect.any(String) // writeFilePath ); // ... rest of the test remains the same });This change will provide more robust verification of the
buildPostList
function usage.scripts/index.js (2)
11-17
: LGTM: New variables improve configurability.The introduction of
postDirectories
,basePath
, andwriteFilePath
variables enhances the flexibility of the post list building process. This is a good improvement.Consider adding a brief comment explaining the structure of the
postDirectories
array for improved readability:// Each item in postDirectories is a pair of [directoryPath, urlPath] const postDirectories = [ ['pages/blog', '/blog'], ['pages/docs', '/docs'], ['pages/about', '/about'] ];
Line range hint
1-70
: Overall assessment: Changes improve flexibility and maintainability.The modifications to
scripts/index.js
align well with the PR objectives. They support the new functionality being tested in thebuild-post-list.js
script by updating the import statement and function call. These changes enhance the flexibility and configurability of the post list building process.Consider documenting the new parameter structure for
buildPostList
in a README or inline documentation to help future developers understand the configuration options quickly.scripts/build-post-list.js (1)
71-72
: LGTM: Improved handling of nested sectionsThe changes in how
parent
andsectionId
are set, along with the updated recursive call towalkDirectories
, improve the handling of nested sections. This makes the code more robust when dealing with different directory structures.For added clarity, consider adding a comment explaining the logic behind using
slugElements.length - 2
andslugElements.length - 1
forparent
andsectionId
respectively.Also applies to: 82-82
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (4)
- scripts/build-post-list.js (7 hunks)
- scripts/index.js (1 hunks)
- tests/build-post-list.test.js (1 hunks)
- tests/index.test.js (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- tests/build-post-list.test.js
🧰 Additional context used
🔇 Additional comments (10)
tests/index.test.js (2)
Line range hint
1-33
: Overall, the changes look good with room for improvement.The import statement has been correctly updated to reflect the changes in the
buildPostList
function. However, the test suite could be enhanced to verify the new function signature. Consider implementing the suggested changes to improve test coverage and ensure consistency with the updatedbuildPostList
function.
2-2
: LGTM! Import statement updated correctly.The change from default import to named import is correct and consistent with the changes in the
buildPostList
function.To ensure consistency, let's verify if the
start
function has been updated to use the newbuildPostList
parameters:✅ Verification successful
Verified! The
start
function correctly usesbuildPostList
with the updated parameters.🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Check if the start function uses the new buildPostList parameters # Test: Search for buildPostList usage in the start function rg -A 5 'function start' scripts/index.js | rg 'buildPostList'Length of output: 62
Script:
#!/bin/bash # Description: Verify that buildPostList is called with three parameters in scripts/index.js # Search for buildPostList function calls with exactly three arguments ast-grep --pattern 'buildPostList($_, $_, $_)' scripts/index.jsLength of output: 150
scripts/index.js (2)
4-4
: LGTM: Import statement updated correctly.The change to use destructuring for importing
buildPostList
is consistent with modern JavaScript practices and improves code readability.
19-19
: LGTM: Function call updated correctly.The
buildPostList
function call has been correctly updated to include the new parameters, which is consistent with the changes in the function's signature.To ensure that the
buildPostList
function in thebuild-post-list.js
file correctly handles these new parameters, please run the following verification script:This script will help verify that the function signature has been updated correctly and that there are no remaining calls to
buildPostList
without parameters.scripts/build-post-list.js (6)
2-2
: LGTM: Cleaned up importsGood job on cleaning up the imports by only importing the
basename
function from thepath
module. This is a best practice that helps keep the code clean and potentially improves performance.
20-26
: Improved readability, but consider removing empty else blockThe changes to the
addItem
function improve readability with better whitespace. However, the emptyelse { }
block at line 26 is still present and serves no purpose. Consider removing it as suggested in the previous review.
29-43
: Improved function signature and error handling, but consider preserving error stack traceThe changes to the
buildPostList
function are good improvements:
- The updated function signature allows for more flexibility.
- The new error handling for empty
postDirectories
is a good addition.- Writing to a specified
writeFilePath
enhances the function's configurability.However, as mentioned in a previous review, consider preserving the original error stack trace when rethrowing errors. You can do this by either using
throw error
or using thecause
property to retain the error's context.
47-47
: LGTM: Updated walkDirectories function signatureThe addition of the
basePath
parameter to thewalkDirectories
function signature is a good change. It aligns with the updates in thebuildPostList
function and allows for more flexible handling of directory paths.
99-105
: Consider renaming variables and improving consistencyThe changes in this section make minor adjustments to the logic for handling specification references. However, as mentioned in a previous review, the variable
fileName
is still being reused, which could lead to confusion. Consider renaming the innerfileName
to something likeversionName
for clarity.Also, for consistency, consider using template literals for string concatenation in line 105:
details.title = `${capitalize(fileName.slice(1))}`Also applies to: 110-110
125-128
: Improved exports, but consider refining file name handlingThe export of
slugifyToC
andbuildPostList
functions is a good practice for modularity. However, there are a couple of points to consider:
As mentioned in a previous review, instead of manually slicing the file name to remove the extension, consider using
path.basename
andpath.extname
for safer and more reliable handling of file names and extensions.The logic for extracting the version from the file name could be simplified and made more robust. Consider using a regular expression to extract the version number directly:
const versionMatch = file.match(/release-notes-(.+)\.md$/); if (versionMatch) { const version = versionMatch[1]; releaseNotes.push(version); }This approach would be more resilient to changes in file naming conventions.
Also applies to: 162-163
@vishvamsinh28 Kindly apply nitpick comment suggestions as well. |
@akshatnema I have applied your suggestions, and there are no new CodeRabbit suggestions. I have already applied the older suggestions in which you tagged me. |
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.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (7)
tests/fixtures/buildPostListData.js (2)
1-27
: Consider enhancing test fixtures with edge casesThe test fixtures cover basic cases well, but could be enhanced to include:
- Invalid frontmatter cases
- Special characters in titles
- Nested directory structures
- Files with different extensions
🧰 Tools
🪛 eslint
[error] 2-2: Delete
··
(prettier/prettier)
[error] 3-3: Delete
····
(prettier/prettier)
[error] 4-4: Replace
········
with····
(prettier/prettier)
[error] 5-5: Delete
····
(prettier/prettier)
[error] 8-8: Delete
,
(prettier/prettier)
[error] 9-9: Delete
··
(prettier/prettier)
[error] 10-10: Delete
··
(prettier/prettier)
[error] 11-11: Replace
········
with····
(prettier/prettier)
[error] 12-12: Delete
····
(prettier/prettier)
[error] 13-13: Replace
········
with····
(prettier/prettier)
[error] 17-17: Replace
····subDir:·'reference/specification',
withsubDir:·'reference/specification'
(prettier/prettier)
[error] 18-18: Delete
··
(prettier/prettier)
[error] 19-19: Replace
····
with··
(prettier/prettier)
[error] 20-20: Replace
········
with····
(prettier/prettier)
[error] 21-21: Delete
····
(prettier/prettier)
[error] 22-22: Replace
········
with····
(prettier/prettier)
[error] 25-25: Delete
,
(prettier/prettier)
[error] 26-26: Replace
····},
with··}
(prettier/prettier)
17-17
: Use path.join for directory pathsFor better cross-platform compatibility, consider using
path.join
for the subdirectory path.- subDir: 'reference/specification', + subDir: path.join('reference', 'specification'),🧰 Tools
🪛 eslint
[error] 17-17: Replace
····subDir:·'reference/specification',
withsubDir:·'reference/specification'
(prettier/prettier)
tests/build-post-list.test.js (5)
3-3
: Simplify relative import pathThe import path can be simplified as both files are in the tests directory.
-const { TEST_CONTENT } = require("../tests/fixtures/buildPostListData"); +const { TEST_CONTENT } = require("./fixtures/buildPostListData");🧰 Tools
🪛 eslint
[error] 3-3: Replace
"../tests/fixtures/buildPostListData"
with'../tests/fixtures/buildPostListData'
(prettier/prettier)
[error] 3-3: Useless path segments for "../tests/fixtures/buildPostListData", should be "./fixtures/buildPostListData"
(import/no-useless-path-segments)
11-39
: Add error handling to beforeEach setupThe setup creates directories and files but doesn't handle potential filesystem errors. Consider wrapping the operations in a try-catch block.
beforeEach(async () => { + try { tempDir = resolve(__dirname, `test-config-${Date.now()}-${Math.random().toString(36).slice(2)}`); // ... rest of the setup ... + } catch (error) { + console.error('Test setup failed:', error); + throw error; + } });🧰 Tools
🪛 eslint
[error] 17-17: Delete
,
(prettier/prettier)
[error] 21-24: Replace
⏎······join(tempDir,·TEST_CONTENT.blog.dir,·TEST_CONTENT.blog.file),⏎······TEST_CONTENT.blog.content⏎····
withjoin(tempDir,·TEST_CONTENT.blog.dir,·TEST_CONTENT.blog.file),·TEST_CONTENT.blog.content
(prettier/prettier)
[error] 27-30: Replace
⏎······join(tempDir,·TEST_CONTENT.docs.dir,·TEST_CONTENT.docs.file),⏎······TEST_CONTENT.docs.content⏎····
withjoin(tempDir,·TEST_CONTENT.docs.dir,·TEST_CONTENT.docs.file),·TEST_CONTENT.docs.content
(prettier/prettier)
[error] 35-38: Replace
⏎······join(tempDir,·TEST_CONTENT.about.dir,·TEST_CONTENT.about.file),⏎······TEST_CONTENT.about.content⏎····
withjoin(tempDir,·TEST_CONTENT.about.dir,·TEST_CONTENT.about.file),·TEST_CONTENT.about.content
(prettier/prettier)
135-169
: Group related specification file testsThe three specification file tests (no title, next-spec, explorer) are related and should be grouped in a nested describe block.
+ describe('specification file handling', () => { it('does not process specification files without a title', async () => { // ... test implementation ... }); it('does not process specification files with "next-spec" in the filename', async () => { // ... test implementation ... }); it('does not process specification files with "explorer" in the filename', async () => { // ... test implementation ... }); + });🧰 Tools
🪛 eslint
[error] 142-142: Replace
item
with(item)
(prettier/prettier)
[error] 149-149: Replace
join(specDir,·'v2.1.0-next-spec.1.mdx'),·'---\n---\nContent·of·pre-release·specification·v2.1.0-next-spec.1.'
with⏎······join(specDir,·'v2.1.0-next-spec.1.mdx'),⏎······'---\n---\nContent·of·pre-release·specification·v2.1.0-next-spec.1.'⏎····
(prettier/prettier)
[error] 154-154: Replace
item
with(item)
(prettier/prettier)
[error] 166-166: Replace
item
with(item)
(prettier/prettier)
171-187
: Enhance error handling tests with specific error typesThe error handling tests could be more specific about the types of errors they expect. Consider testing for specific error instances or properties.
it('throws "Error while building post list" when front matter is invalid', async () => { await fs.writeFile(join(tempDir, 'docs', 'invalid.mdx'), '---\ninvalid front matter\n---\nContent'); - await expect(buildPostList(postDirectories, tempDir, writeFilePath)).rejects.toThrow(/Error while building post list/); + await expect(buildPostList(postDirectories, tempDir, writeFilePath)).rejects.toMatchObject({ + name: 'Error', + message: expect.stringMatching(/Error while building post list/), + }); });🧰 Tools
🪛 eslint
[error] 174-174: This line has a length of 123. Maximum allowed is 120.
(max-len)
[error] 174-174: Replace
/Error·while·building·post·list/
with⏎······/Error·while·building·post·list/⏎····
(prettier/prettier)
[error] 182-182: This line has a length of 166. Maximum allowed is 120.
(max-len)
[error] 182-182: Replace
/Error·while·building·post·list:·basePath·and·writeFilePath·are·required/
with⏎······/Error·while·building·post·list:·basePath·and·writeFilePath·are·required/⏎····
(prettier/prettier)
[error] 186-186: This line has a length of 160. Maximum allowed is 120.
(max-len)
[error] 186-186: Replace
/Error·while·building·post·list:·basePath·and·writeFilePath·are·required/
with⏎······/Error·while·building·post·list:·basePath·and·writeFilePath·are·required/⏎····
(prettier/prettier)
6-6
: Consider adding concurrent operation testsThe test suite would benefit from tests that verify the behavior when multiple instances of
buildPostList
are running concurrently.Example test:
it('handles concurrent operations correctly', async () => { const operations = Array(3).fill().map(() => buildPostList(postDirectories, tempDir, writeFilePath) ); await expect(Promise.all(operations)).resolves.not.toThrow(); });
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
📒 Files selected for processing (2)
tests/build-post-list.test.js
(1 hunks)tests/fixtures/buildPostListData.js
(1 hunks)
🧰 Additional context used
🪛 eslint
tests/build-post-list.test.js
[error] 3-3: Replace "../tests/fixtures/buildPostListData"
with '../tests/fixtures/buildPostListData'
(prettier/prettier)
[error] 3-3: Useless path segments for "../tests/fixtures/buildPostListData", should be "./fixtures/buildPostListData"
(import/no-useless-path-segments)
[error] 17-17: Delete ,
(prettier/prettier)
[error] 21-24: Replace ⏎······join(tempDir,·TEST_CONTENT.blog.dir,·TEST_CONTENT.blog.file),⏎······TEST_CONTENT.blog.content⏎····
with join(tempDir,·TEST_CONTENT.blog.dir,·TEST_CONTENT.blog.file),·TEST_CONTENT.blog.content
(prettier/prettier)
[error] 27-30: Replace ⏎······join(tempDir,·TEST_CONTENT.docs.dir,·TEST_CONTENT.docs.file),⏎······TEST_CONTENT.docs.content⏎····
with join(tempDir,·TEST_CONTENT.docs.dir,·TEST_CONTENT.docs.file),·TEST_CONTENT.docs.content
(prettier/prettier)
[error] 35-38: Replace ⏎······join(tempDir,·TEST_CONTENT.about.dir,·TEST_CONTENT.about.file),⏎······TEST_CONTENT.about.content⏎····
with join(tempDir,·TEST_CONTENT.about.dir,·TEST_CONTENT.about.file),·TEST_CONTENT.about.content
(prettier/prettier)
[error] 57-57: Delete ,
(prettier/prettier)
[error] 62-62: Delete ,
(prettier/prettier)
[error] 67-67: Delete ,
(prettier/prettier)
[error] 68-68: Delete ,
(prettier/prettier)
[error] 76-76: Delete ,
(prettier/prettier)
[error] 77-77: Delete ,
(prettier/prettier)
[error] 85-85: Delete ,
(prettier/prettier)
[error] 86-86: Delete ,
(prettier/prettier)
[error] 92-92: Replace item
with (item)
(prettier/prettier)
[error] 99-99: Replace join(tempDir,·'docs',·'section1',·'_section.mdx'),·'---\ntitle:·Section·1\n---\nThis·is·section·1.'
with ⏎······join(tempDir,·'docs',·'section1',·'_section.mdx'),⏎······'---\ntitle:·Section·1\n---\nThis·is·section·1.'⏎····
(prettier/prettier)
[error] 105-105: Replace item
with (item)
(prettier/prettier)
[error] 114-114: Replace join(tempDir,·'blog',·'release-notes-2.1.1.mdx'),·'---\ntitle:·Release·Notes·2.1.1\n---\nThis·is·a·release·note.'
with ⏎······join(tempDir,·'blog',·'release-notes-2.1.1.mdx'),⏎······'---\ntitle:·Release·Notes·2.1.1\n---\nThis·is·a·release·note.'⏎····
(prettier/prettier)
[error] 120-120: Replace (item
with ((item)
(prettier/prettier)
[error] 121-121: Replace item
with (item)
(prettier/prettier)
[error] 142-142: Replace item
with (item)
(prettier/prettier)
[error] 149-149: Replace join(specDir,·'v2.1.0-next-spec.1.mdx'),·'---\n---\nContent·of·pre-release·specification·v2.1.0-next-spec.1.'
with ⏎······join(specDir,·'v2.1.0-next-spec.1.mdx'),⏎······'---\n---\nContent·of·pre-release·specification·v2.1.0-next-spec.1.'⏎····
(prettier/prettier)
[error] 154-154: Replace item
with (item)
(prettier/prettier)
[error] 166-166: Replace item
with (item)
(prettier/prettier)
[error] 174-174: This line has a length of 123. Maximum allowed is 120.
(max-len)
[error] 174-174: Replace /Error·while·building·post·list/
with ⏎······/Error·while·building·post·list/⏎····
(prettier/prettier)
[error] 182-182: This line has a length of 166. Maximum allowed is 120.
(max-len)
[error] 182-182: Replace /Error·while·building·post·list:·basePath·and·writeFilePath·are·required/
with ⏎······/Error·while·building·post·list:·basePath·and·writeFilePath·are·required/⏎····
(prettier/prettier)
[error] 186-186: This line has a length of 160. Maximum allowed is 120.
(max-len)
[error] 186-186: Replace /Error·while·building·post·list:·basePath·and·writeFilePath·are·required/
with ⏎······/Error·while·building·post·list:·basePath·and·writeFilePath·are·required/⏎····
(prettier/prettier)
[error] 189-190: Delete ⏎
(prettier/prettier)
tests/fixtures/buildPostListData.js
[error] 2-2: Delete ··
(prettier/prettier)
[error] 3-3: Delete ····
(prettier/prettier)
[error] 4-4: Replace ········
with ····
(prettier/prettier)
[error] 5-5: Delete ····
(prettier/prettier)
[error] 8-8: Delete ,
(prettier/prettier)
[error] 9-9: Delete ··
(prettier/prettier)
[error] 10-10: Delete ··
(prettier/prettier)
[error] 11-11: Replace ········
with ····
(prettier/prettier)
[error] 12-12: Delete ····
(prettier/prettier)
[error] 13-13: Replace ········
with ····
(prettier/prettier)
[error] 17-17: Replace ····subDir:·'reference/specification',
with subDir:·'reference/specification'
(prettier/prettier)
[error] 18-18: Delete ··
(prettier/prettier)
[error] 19-19: Replace ····
with ··
(prettier/prettier)
[error] 20-20: Replace ········
with ····
(prettier/prettier)
[error] 21-21: Delete ····
(prettier/prettier)
[error] 22-22: Replace ········
with ····
(prettier/prettier)
[error] 25-25: Delete ,
(prettier/prettier)
[error] 26-26: Replace ····},
with ··}
(prettier/prettier)
[error] 29-29: Insert ⏎
(prettier/prettier)
tests/build-post-list.test.js
Outdated
}); | ||
|
||
it('throws specific error message when basePath parameter is undefined', async () => { | ||
await expect(buildPostList(postDirectories, undefined, writeFilePath)).rejects.toThrow(/Error while building post list: basePath and writeFilePath are required/); |
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.
Fix these long lines using eslint errors.
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.
Done
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.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (5)
tests/build-post-list.test.js (5)
1-4
: Fix import path.The import path for
buildPostListData
can be simplified.-const { TEST_CONTENT } = require('../tests/fixtures/buildPostListData'); +const { TEST_CONTENT } = require('./fixtures/buildPostListData');🧰 Tools
🪛 eslint
[error] 3-3: Useless path segments for "../tests/fixtures/buildPostListData", should be "./fixtures/buildPostListData"
(import/no-useless-path-segments)
11-44
: Consider extracting test setup helper.The
beforeEach
setup is quite lengthy and could be moved to a separate helper function for better maintainability.+async function setupTestDirectories(tempDir) { + const dirs = ['blog', 'docs', 'about']; + for (const dir of dirs) { + await fs.ensureDir(join(tempDir, TEST_CONTENT[dir].dir)); + await fs.writeFile( + join(tempDir, TEST_CONTENT[dir].dir, TEST_CONTENT[dir].file), + TEST_CONTENT[dir].content + ); + } + await fs.ensureDir(join(tempDir, TEST_CONTENT.docs.dir, TEST_CONTENT.docs.subDir)); +} + beforeEach(async () => { tempDir = resolve( __dirname, `test-config-${Date.now()}-${Math.random().toString(36).slice(2)}` ); writeFilePath = resolve(tempDir, 'posts.json'); postDirectories = [ [join(tempDir, 'blog'), '/blog'], [join(tempDir, 'docs'), '/docs'], [join(tempDir, 'about'), '/about'] ]; - await fs.ensureDir(join(tempDir, TEST_CONTENT.blog.dir)); - // ... rest of the setup + await setupTestDirectories(tempDir); });🧰 Tools
🪛 eslint
[error] 12-15: Replace
⏎······__dirname,⏎······
test-config-${Date.now()}-${Math.random().toString(36).slice(2)},⏎····
with__dirname,·
test-config-${Date.now()}-${Math.random().toString(36).slice(2)}``(prettier/prettier)
[error] 20-20: Delete
,
(prettier/prettier)
[error] 24-27: Replace
⏎······join(tempDir,·TEST_CONTENT.blog.dir,·TEST_CONTENT.blog.file),⏎······TEST_CONTENT.blog.content,⏎····
withjoin(tempDir,·TEST_CONTENT.blog.dir,·TEST_CONTENT.blog.file),·TEST_CONTENT.blog.content
(prettier/prettier)
[error] 30-33: Replace
⏎······join(tempDir,·TEST_CONTENT.docs.dir,·TEST_CONTENT.docs.file),⏎······TEST_CONTENT.docs.content,⏎····
withjoin(tempDir,·TEST_CONTENT.docs.dir,·TEST_CONTENT.docs.file),·TEST_CONTENT.docs.content
(prettier/prettier)
[error] 35-37: Replace
⏎······join(tempDir,·TEST_CONTENT.docs.dir,·TEST_CONTENT.docs.subDir),⏎····
withjoin(tempDir,·TEST_CONTENT.docs.dir,·TEST_CONTENT.docs.subDir)
(prettier/prettier)
[error] 40-43: Replace
⏎······join(tempDir,·TEST_CONTENT.about.dir,·TEST_CONTENT.about.file),⏎······TEST_CONTENT.about.content,⏎····
withjoin(tempDir,·TEST_CONTENT.about.dir,·TEST_CONTENT.about.file),·TEST_CONTENT.about.content
(prettier/prettier)
50-102
: Enhance test assertions for better coverage.The main functionality test could be improved by:
- Testing the structure of
docsTree
- Verifying the order of items in arrays
expect(output.docsTree).toBeDefined(); +expect(output.docsTree).toMatchObject({ + children: expect.arrayContaining([ + expect.objectContaining({ + title: 'Reference', + children: expect.any(Array) + }) + ]) +});🧰 Tools
🪛 eslint
[error] 62-62: Delete
,
(prettier/prettier)
[error] 67-67: Delete
,
(prettier/prettier)
[error] 72-72: Delete
,
(prettier/prettier)
[error] 73-73: Delete
,
(prettier/prettier)
[error] 74-74: Delete
,
(prettier/prettier)
[error] 81-81: Delete
,
(prettier/prettier)
[error] 82-82: Delete
,
(prettier/prettier)
[error] 83-83: Delete
,
(prettier/prettier)
[error] 90-90: Delete
,
(prettier/prettier)
[error] 91-91: Delete
,
(prettier/prettier)
[error] 92-92: Delete
,
(prettier/prettier)
[error] 97-99: Replace
⏎······(item)·=>·item.slug·===·'/blog/release-notes-2.1.0',⏎····
with(item)·=>·item.slug·===·'/blog/release-notes-2.1.0'
(prettier/prettier)
205-214
: Consider testing specific front matter error cases.The front matter error test could be more specific by testing different types of invalid front matter.
- it('throws "Error while building post list" when front matter is invalid', async () => { + it.each([ + ['missing closing delimiter', '---\ntitle: Test'], + ['invalid YAML', '---\n@invalid: -\n---'], + ['empty front matter', '---\n---'] + ])('throws error for %s', async (_, content) => { await fs.writeFile( join(tempDir, 'docs', 'invalid.mdx'), - '---\ninvalid front matter\n---\nContent', + content ); await expect( buildPostList(postDirectories, tempDir, writeFilePath) ).rejects.toThrow(/Error while building post list/); });🧰 Tools
🪛 eslint
[error] 206-209: Replace
⏎······join(tempDir,·'docs',·'invalid.mdx'),⏎······'---\ninvalid·front·matter\n---\nContent',⏎····
withjoin(tempDir,·'docs',·'invalid.mdx'),·'---\ninvalid·front·matter\n---\nContent'
(prettier/prettier)
[error] 211-213: Replace
⏎······buildPostList(postDirectories,·tempDir,·writeFilePath),⏎····).rejects.toThrow(/Error·while·building·post·list/
withbuildPostList(postDirectories,·tempDir,·writeFilePath)).rejects.toThrow(⏎······/Error·while·building·post·list/⏎····
(prettier/prettier)
238-252
: Add test case for slugifyToC with multiple IDs.The slugifyToC tests should cover the case where multiple IDs are present in the heading.
describe('slugifyToC', () => { + it('returns first ID when multiple IDs are present', () => { + const input = '## My Heading {#first-id} {#second-id}'; + expect(slugifyToC(input)).toBe('first-id'); + }); });
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
📒 Files selected for processing (1)
tests/build-post-list.test.js
(1 hunks)
🧰 Additional context used
🪛 eslint
tests/build-post-list.test.js
[error] 3-3: Useless path segments for "../tests/fixtures/buildPostListData", should be "./fixtures/buildPostListData"
(import/no-useless-path-segments)
[error] 12-15: Replace ⏎······__dirname,⏎······
test-config-${Date.now()}-${Math.random().toString(36).slice(2)},⏎····
with __dirname,·
test-config-${Date.now()}-${Math.random().toString(36).slice(2)}``
(prettier/prettier)
[error] 20-20: Delete ,
(prettier/prettier)
[error] 24-27: Replace ⏎······join(tempDir,·TEST_CONTENT.blog.dir,·TEST_CONTENT.blog.file),⏎······TEST_CONTENT.blog.content,⏎····
with join(tempDir,·TEST_CONTENT.blog.dir,·TEST_CONTENT.blog.file),·TEST_CONTENT.blog.content
(prettier/prettier)
[error] 30-33: Replace ⏎······join(tempDir,·TEST_CONTENT.docs.dir,·TEST_CONTENT.docs.file),⏎······TEST_CONTENT.docs.content,⏎····
with join(tempDir,·TEST_CONTENT.docs.dir,·TEST_CONTENT.docs.file),·TEST_CONTENT.docs.content
(prettier/prettier)
[error] 35-37: Replace ⏎······join(tempDir,·TEST_CONTENT.docs.dir,·TEST_CONTENT.docs.subDir),⏎····
with join(tempDir,·TEST_CONTENT.docs.dir,·TEST_CONTENT.docs.subDir)
(prettier/prettier)
[error] 40-43: Replace ⏎······join(tempDir,·TEST_CONTENT.about.dir,·TEST_CONTENT.about.file),⏎······TEST_CONTENT.about.content,⏎····
with join(tempDir,·TEST_CONTENT.about.dir,·TEST_CONTENT.about.file),·TEST_CONTENT.about.content
(prettier/prettier)
[error] 62-62: Delete ,
(prettier/prettier)
[error] 67-67: Delete ,
(prettier/prettier)
[error] 72-72: Delete ,
(prettier/prettier)
[error] 73-73: Delete ,
(prettier/prettier)
[error] 74-74: Delete ,
(prettier/prettier)
[error] 81-81: Delete ,
(prettier/prettier)
[error] 82-82: Delete ,
(prettier/prettier)
[error] 83-83: Delete ,
(prettier/prettier)
[error] 90-90: Delete ,
(prettier/prettier)
[error] 91-91: Delete ,
(prettier/prettier)
[error] 92-92: Delete ,
(prettier/prettier)
[error] 97-99: Replace ⏎······(item)·=>·item.slug·===·'/blog/release-notes-2.1.0',⏎····
with (item)·=>·item.slug·===·'/blog/release-notes-2.1.0'
(prettier/prettier)
[error] 108-108: Delete ,
(prettier/prettier)
[error] 119-119: Delete ,
(prettier/prettier)
[error] 126-126: Delete ,
(prettier/prettier)
[error] 133-135: Replace ⏎······(item)·=>·item.slug·===·'/blog/release-notes-2.1.0',⏎····
with (item)·=>·item.slug·===·'/blog/release-notes-2.1.0'
(prettier/prettier)
[error] 136-138: Replace ⏎······(item)·=>·item.slug·===·'/blog/release-notes-2.1.1',⏎····
with (item)·=>·item.slug·===·'/blog/release-notes-2.1.1'
(prettier/prettier)
[error] 149-151: Replace ⏎······buildPostList([invalidDir],·tempDir,·writeFilePath),⏎····
with buildPostList([invalidDir],·tempDir,·writeFilePath)
(prettier/prettier)
[error] 156-159: Replace ⏎······join(specDir,·'v2.1.0-no-title.mdx'),⏎······'---\n---\nContent·of·specification·without·a·title.',⏎····
with join(specDir,·'v2.1.0-no-title.mdx'),·'---\n---\nContent·of·specification·without·a·title.'
(prettier/prettier)
[error] 164-166: Replace ⏎······item.slug.includes('/reference/specification/v2.1.0-no-title'),⏎····
with ·item.slug.includes('/reference/specification/v2.1.0-no-title')
(prettier/prettier)
[error] 175-175: Delete ,
(prettier/prettier)
[error] 181-183: Replace ⏎······item.slug.includes('/reference/specification/v2.1.0-next-spec.1'),⏎····
with ·item.slug.includes('/reference/specification/v2.1.0-next-spec.1')
(prettier/prettier)
[error] 190-193: Replace ⏎······join(specDir,·'explorer.mdx'),⏎······'---\n---\nContent·of·explorer·specification.',⏎····
with join(specDir,·'explorer.mdx'),·'---\n---\nContent·of·explorer·specification.'
(prettier/prettier)
[error] 198-200: Replace ⏎······item.slug.includes('/reference/specification/explorer'),⏎····
with ·item.slug.includes('/reference/specification/explorer')
(prettier/prettier)
[error] 206-209: Replace ⏎······join(tempDir,·'docs',·'invalid.mdx'),⏎······'---\ninvalid·front·matter\n---\nContent',⏎····
with join(tempDir,·'docs',·'invalid.mdx'),·'---\ninvalid·front·matter\n---\nContent'
(prettier/prettier)
[error] 211-213: Replace ⏎······buildPostList(postDirectories,·tempDir,·writeFilePath),⏎····).rejects.toThrow(/Error·while·building·post·list/
with buildPostList(postDirectories,·tempDir,·writeFilePath)).rejects.toThrow(⏎······/Error·while·building·post·list/⏎····
(prettier/prettier)
[error] 217-219: Replace ⏎······/Error·while·building·post·list/,⏎····
with /Error·while·building·post·list/
(prettier/prettier)
[error] 223-225: Replace ⏎······buildPostList(postDirectories,·undefined,·writeFilePath),⏎····
with buildPostList(postDirectories,·undefined,·writeFilePath)
(prettier/prettier)
[error] 226-226: Delete ,
(prettier/prettier)
[error] 231-233: Replace ⏎······buildPostList(postDirectories,·tempDir,·undefined),⏎····
with buildPostList(postDirectories,·tempDir,·undefined)
(prettier/prettier)
[error] 234-234: Delete ,
(prettier/prettier)
🔇 Additional comments (1)
tests/build-post-list.test.js (1)
1-253
: LGTM! Comprehensive test coverage.
The test suite provides thorough coverage of the buildPostList
and slugifyToC
functions, including:
- Basic functionality
- Edge cases
- Error handling
- File filtering
- Parameter validation
The tests are well-structured and follow good testing practices.
🧰 Tools
🪛 eslint
[error] 3-3: Useless path segments for "../tests/fixtures/buildPostListData", should be "./fixtures/buildPostListData"
(import/no-useless-path-segments)
[error] 12-15: Replace ⏎······__dirname,⏎······
test-config-${Date.now()}-${Math.random().toString(36).slice(2)},⏎····
with __dirname,·
test-config-${Date.now()}-${Math.random().toString(36).slice(2)}``
(prettier/prettier)
[error] 20-20: Delete ,
(prettier/prettier)
[error] 24-27: Replace ⏎······join(tempDir,·TEST_CONTENT.blog.dir,·TEST_CONTENT.blog.file),⏎······TEST_CONTENT.blog.content,⏎····
with join(tempDir,·TEST_CONTENT.blog.dir,·TEST_CONTENT.blog.file),·TEST_CONTENT.blog.content
(prettier/prettier)
[error] 30-33: Replace ⏎······join(tempDir,·TEST_CONTENT.docs.dir,·TEST_CONTENT.docs.file),⏎······TEST_CONTENT.docs.content,⏎····
with join(tempDir,·TEST_CONTENT.docs.dir,·TEST_CONTENT.docs.file),·TEST_CONTENT.docs.content
(prettier/prettier)
[error] 35-37: Replace ⏎······join(tempDir,·TEST_CONTENT.docs.dir,·TEST_CONTENT.docs.subDir),⏎····
with join(tempDir,·TEST_CONTENT.docs.dir,·TEST_CONTENT.docs.subDir)
(prettier/prettier)
[error] 40-43: Replace ⏎······join(tempDir,·TEST_CONTENT.about.dir,·TEST_CONTENT.about.file),⏎······TEST_CONTENT.about.content,⏎····
with join(tempDir,·TEST_CONTENT.about.dir,·TEST_CONTENT.about.file),·TEST_CONTENT.about.content
(prettier/prettier)
[error] 62-62: Delete ,
(prettier/prettier)
[error] 67-67: Delete ,
(prettier/prettier)
[error] 72-72: Delete ,
(prettier/prettier)
[error] 73-73: Delete ,
(prettier/prettier)
[error] 74-74: Delete ,
(prettier/prettier)
[error] 81-81: Delete ,
(prettier/prettier)
[error] 82-82: Delete ,
(prettier/prettier)
[error] 83-83: Delete ,
(prettier/prettier)
[error] 90-90: Delete ,
(prettier/prettier)
[error] 91-91: Delete ,
(prettier/prettier)
[error] 92-92: Delete ,
(prettier/prettier)
[error] 97-99: Replace ⏎······(item)·=>·item.slug·===·'/blog/release-notes-2.1.0',⏎····
with (item)·=>·item.slug·===·'/blog/release-notes-2.1.0'
(prettier/prettier)
[error] 108-108: Delete ,
(prettier/prettier)
[error] 119-119: Delete ,
(prettier/prettier)
[error] 126-126: Delete ,
(prettier/prettier)
[error] 133-135: Replace ⏎······(item)·=>·item.slug·===·'/blog/release-notes-2.1.0',⏎····
with (item)·=>·item.slug·===·'/blog/release-notes-2.1.0'
(prettier/prettier)
[error] 136-138: Replace ⏎······(item)·=>·item.slug·===·'/blog/release-notes-2.1.1',⏎····
with (item)·=>·item.slug·===·'/blog/release-notes-2.1.1'
(prettier/prettier)
[error] 149-151: Replace ⏎······buildPostList([invalidDir],·tempDir,·writeFilePath),⏎····
with buildPostList([invalidDir],·tempDir,·writeFilePath)
(prettier/prettier)
[error] 156-159: Replace ⏎······join(specDir,·'v2.1.0-no-title.mdx'),⏎······'---\n---\nContent·of·specification·without·a·title.',⏎····
with join(specDir,·'v2.1.0-no-title.mdx'),·'---\n---\nContent·of·specification·without·a·title.'
(prettier/prettier)
[error] 164-166: Replace ⏎······item.slug.includes('/reference/specification/v2.1.0-no-title'),⏎····
with ·item.slug.includes('/reference/specification/v2.1.0-no-title')
(prettier/prettier)
[error] 175-175: Delete ,
(prettier/prettier)
[error] 181-183: Replace ⏎······item.slug.includes('/reference/specification/v2.1.0-next-spec.1'),⏎····
with ·item.slug.includes('/reference/specification/v2.1.0-next-spec.1')
(prettier/prettier)
[error] 190-193: Replace ⏎······join(specDir,·'explorer.mdx'),⏎······'---\n---\nContent·of·explorer·specification.',⏎····
with join(specDir,·'explorer.mdx'),·'---\n---\nContent·of·explorer·specification.'
(prettier/prettier)
[error] 198-200: Replace ⏎······item.slug.includes('/reference/specification/explorer'),⏎····
with ·item.slug.includes('/reference/specification/explorer')
(prettier/prettier)
[error] 206-209: Replace ⏎······join(tempDir,·'docs',·'invalid.mdx'),⏎······'---\ninvalid·front·matter\n---\nContent',⏎····
with join(tempDir,·'docs',·'invalid.mdx'),·'---\ninvalid·front·matter\n---\nContent'
(prettier/prettier)
[error] 211-213: Replace ⏎······buildPostList(postDirectories,·tempDir,·writeFilePath),⏎····).rejects.toThrow(/Error·while·building·post·list/
with buildPostList(postDirectories,·tempDir,·writeFilePath)).rejects.toThrow(⏎······/Error·while·building·post·list/⏎····
(prettier/prettier)
[error] 217-219: Replace ⏎······/Error·while·building·post·list/,⏎····
with /Error·while·building·post·list/
(prettier/prettier)
[error] 223-225: Replace ⏎······buildPostList(postDirectories,·undefined,·writeFilePath),⏎····
with buildPostList(postDirectories,·undefined,·writeFilePath)
(prettier/prettier)
[error] 226-226: Delete ,
(prettier/prettier)
[error] 231-233: Replace ⏎······buildPostList(postDirectories,·tempDir,·undefined),⏎····
with buildPostList(postDirectories,·tempDir,·undefined)
(prettier/prettier)
[error] 234-234: Delete ,
(prettier/prettier)
tests/build-post-list.test.js
Outdated
@@ -0,0 +1,253 @@ | |||
const fs = require('fs-extra'); | |||
const { resolve, join } = require('path'); | |||
const { TEST_CONTENT } = require('../tests/fixtures/buildPostListData'); |
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.
const { TEST_CONTENT } = require('../tests/fixtures/buildPostListData'); | |
const { TEST_CONTENT } = require('./fixtures/buildPostListData'); |
tests/build-post-list.test.js
Outdated
tempDir = resolve( | ||
__dirname, | ||
`test-config-${Date.now()}-${Math.random().toString(36).slice(2)}`, | ||
); | ||
writeFilePath = resolve(tempDir, 'posts.json'); | ||
postDirectories = [ | ||
[join(tempDir, 'blog'), '/blog'], | ||
[join(tempDir, 'docs'), '/docs'], | ||
[join(tempDir, 'about'), '/about'], | ||
]; | ||
|
||
await fs.ensureDir(join(tempDir, TEST_CONTENT.blog.dir)); | ||
await fs.writeFile( | ||
join(tempDir, TEST_CONTENT.blog.dir, TEST_CONTENT.blog.file), | ||
TEST_CONTENT.blog.content, | ||
); | ||
|
||
await fs.ensureDir(join(tempDir, TEST_CONTENT.docs.dir)); | ||
await fs.writeFile( | ||
join(tempDir, TEST_CONTENT.docs.dir, TEST_CONTENT.docs.file), | ||
TEST_CONTENT.docs.content, | ||
); | ||
|
||
await fs.ensureDir( | ||
join(tempDir, TEST_CONTENT.docs.dir, TEST_CONTENT.docs.subDir), | ||
); | ||
|
||
await fs.ensureDir(join(tempDir, TEST_CONTENT.about.dir)); | ||
await fs.writeFile( | ||
join(tempDir, TEST_CONTENT.about.dir, TEST_CONTENT.about.file), | ||
TEST_CONTENT.about.content, | ||
); |
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.
Move this implementation to a separate function, beforeEach setup is quite lengthy and could be moved to a separate helper function for better maintainability. Use this:
async function setupTestDirectories(tempDir) {
const dirs = ['blog', 'docs', 'about'];
for (const dir of dirs) {
await fs.ensureDir(join(tempDir, TEST_CONTENT[dir].dir));
await fs.writeFile(
join(tempDir, TEST_CONTENT[dir].dir, TEST_CONTENT[dir].file),
TEST_CONTENT[dir].content
);
}
await fs.ensureDir(join(tempDir, TEST_CONTENT.docs.dir, TEST_CONTENT.docs.subDir));
}
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.
Done
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.
Actionable comments posted: 2
🧹 Outside diff range and nitpick comments (2)
tests/helper/buildPostListSetup.js (1)
5-15
: Consider using Promise.all for parallel operationsThe directory creation and file writing operations are independent and could be executed in parallel for better performance.
async function setupTestDirectories(tempDir) { const dirs = ['blog', 'docs', 'about']; - for (const dir of dirs) { - await fs.ensureDir(join(tempDir, TEST_CONTENT[dir].dir)); - await fs.writeFile( - join(tempDir, TEST_CONTENT[dir].dir, TEST_CONTENT[dir].file), - TEST_CONTENT[dir].content - ); - } - await fs.ensureDir(join(tempDir, TEST_CONTENT.docs.dir, TEST_CONTENT.docs.subDir)); + await Promise.all([ + ...dirs.map(dir => Promise.all([ + fs.ensureDir(join(tempDir, TEST_CONTENT[dir].dir)), + fs.writeFile( + join(tempDir, TEST_CONTENT[dir].dir, TEST_CONTENT[dir].file), + TEST_CONTENT[dir].content + ) + ])), + fs.ensureDir(join(tempDir, TEST_CONTENT.docs.dir, TEST_CONTENT.docs.subDir)) + ]); }🧰 Tools
🪛 eslint
[error] 6-6: Delete
··
(prettier/prettier)
[error] 7-7: Replace
····
with··
(prettier/prettier)
[error] 7-13: iterators/generators require regenerator-runtime, which is too heavyweight for this guide to allow them. Separately, loops should be avoided in favor of array iterations.
(no-restricted-syntax)
[error] 8-8: Replace
········
with····
(prettier/prettier)
[error] 8-8: Unexpected
await
inside a loop.(no-await-in-loop)
[error] 9-12: Replace
····await·fs.writeFile(⏎············join(tempDir,·TEST_CONTENT[dir].dir,·TEST_CONTENT[dir].file),⏎············TEST_CONTENT[dir].content⏎········
withawait·fs.writeFile(join(tempDir,·TEST_CONTENT[dir].dir,·TEST_CONTENT[dir].file),·TEST_CONTENT[dir].content
(prettier/prettier)
[error] 9-12: Unexpected
await
inside a loop.(no-await-in-loop)
[error] 13-13: Replace
····
with··
(prettier/prettier)
[error] 14-14: Delete
··
(prettier/prettier)
tests/build-post-list.test.js (1)
11-25
: Consider extracting temporary directory path generationThe temporary directory path generation logic could be moved to a helper function for better reusability and maintainability.
+function generateTempDirPath(baseDir) { + return resolve( + baseDir, + `test-config-${Date.now()}-${Math.random().toString(36).slice(2)}` + ); +} beforeEach(async () => { - tempDir = resolve( - __dirname, - `test-config-${Date.now()}-${Math.random().toString(36).slice(2)}`, - ); + tempDir = generateTempDirPath(__dirname); writeFilePath = resolve(tempDir, 'posts.json'); postDirectories = [ [join(tempDir, 'blog'), '/blog'], [join(tempDir, 'docs'), '/docs'], [join(tempDir, 'about'), '/about'], ]; await setupTestDirectories(tempDir); });🧰 Tools
🪛 eslint
[error] 12-15: Replace
⏎······__dirname,⏎······
test-config-${Date.now()}-${Math.random().toString(36).slice(2)},⏎····
with__dirname,·
test-config-${Date.now()}-${Math.random().toString(36).slice(2)}``(prettier/prettier)
[error] 20-20: Delete
,
(prettier/prettier)
[error] 23-24: Delete
⏎
(prettier/prettier)
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
📒 Files selected for processing (2)
tests/build-post-list.test.js
(1 hunks)tests/helper/buildPostListSetup.js
(1 hunks)
🧰 Additional context used
🪛 eslint
tests/helper/buildPostListSetup.js
[error] 1-1: ../fixtures/buildPostListData
import should occur after import of path
(import/order)
[error] 1-1: Replace "../fixtures/buildPostListData"
with '../fixtures/buildPostListData'
(prettier/prettier)
[error] 3-3: Replace "path")
with 'path');
(prettier/prettier)
[error] 6-6: Delete ··
(prettier/prettier)
[error] 7-7: Replace ····
with ··
(prettier/prettier)
[error] 7-13: iterators/generators require regenerator-runtime, which is too heavyweight for this guide to allow them. Separately, loops should be avoided in favor of array iterations.
(no-restricted-syntax)
[error] 8-8: Replace ········
with ····
(prettier/prettier)
[error] 8-8: Unexpected await
inside a loop.
(no-await-in-loop)
[error] 9-12: Replace ····await·fs.writeFile(⏎············join(tempDir,·TEST_CONTENT[dir].dir,·TEST_CONTENT[dir].file),⏎············TEST_CONTENT[dir].content⏎········
with await·fs.writeFile(join(tempDir,·TEST_CONTENT[dir].dir,·TEST_CONTENT[dir].file),·TEST_CONTENT[dir].content
(prettier/prettier)
[error] 9-12: Unexpected await
inside a loop.
(no-await-in-loop)
[error] 13-13: Replace ····
with ··
(prettier/prettier)
[error] 14-14: Delete ··
(prettier/prettier)
[error] 17-17: Insert ⏎
(prettier/prettier)
tests/build-post-list.test.js
[error] 3-3: Insert ;
(prettier/prettier)
[error] 12-15: Replace ⏎······__dirname,⏎······
test-config-${Date.now()}-${Math.random().toString(36).slice(2)},⏎····
with __dirname,·
test-config-${Date.now()}-${Math.random().toString(36).slice(2)}``
(prettier/prettier)
[error] 20-20: Delete ,
(prettier/prettier)
[error] 23-24: Delete ⏎
(prettier/prettier)
[error] 43-43: Delete ,
(prettier/prettier)
[error] 48-48: Delete ,
(prettier/prettier)
[error] 53-53: Delete ,
(prettier/prettier)
[error] 54-54: Delete ,
(prettier/prettier)
[error] 55-55: Delete ,
(prettier/prettier)
[error] 62-62: Delete ,
(prettier/prettier)
[error] 63-63: Delete ,
(prettier/prettier)
[error] 64-64: Delete ,
(prettier/prettier)
[error] 71-71: Delete ,
(prettier/prettier)
[error] 72-72: Delete ,
(prettier/prettier)
[error] 73-73: Delete ,
(prettier/prettier)
[error] 78-80: Replace ⏎······(item)·=>·item.slug·===·'/blog/release-notes-2.1.0',⏎····
with (item)·=>·item.slug·===·'/blog/release-notes-2.1.0'
(prettier/prettier)
[error] 89-89: Delete ,
(prettier/prettier)
[error] 100-100: Delete ,
(prettier/prettier)
[error] 107-107: Delete ,
(prettier/prettier)
[error] 114-116: Replace ⏎······(item)·=>·item.slug·===·'/blog/release-notes-2.1.0',⏎····
with (item)·=>·item.slug·===·'/blog/release-notes-2.1.0'
(prettier/prettier)
[error] 117-119: Replace ⏎······(item)·=>·item.slug·===·'/blog/release-notes-2.1.1',⏎····
with (item)·=>·item.slug·===·'/blog/release-notes-2.1.1'
(prettier/prettier)
[error] 130-132: Replace ⏎······buildPostList([invalidDir],·tempDir,·writeFilePath),⏎····
with buildPostList([invalidDir],·tempDir,·writeFilePath)
(prettier/prettier)
[error] 137-140: Replace ⏎······join(specDir,·'v2.1.0-no-title.mdx'),⏎······'---\n---\nContent·of·specification·without·a·title.',⏎····
with join(specDir,·'v2.1.0-no-title.mdx'),·'---\n---\nContent·of·specification·without·a·title.'
(prettier/prettier)
[error] 145-147: Replace ⏎······item.slug.includes('/reference/specification/v2.1.0-no-title'),⏎····
with ·item.slug.includes('/reference/specification/v2.1.0-no-title')
(prettier/prettier)
[error] 156-156: Delete ,
(prettier/prettier)
[error] 162-164: Replace ⏎······item.slug.includes('/reference/specification/v2.1.0-next-spec.1'),⏎····
with ·item.slug.includes('/reference/specification/v2.1.0-next-spec.1')
(prettier/prettier)
[error] 171-174: Replace ⏎······join(specDir,·'explorer.mdx'),⏎······'---\n---\nContent·of·explorer·specification.',⏎····
with join(specDir,·'explorer.mdx'),·'---\n---\nContent·of·explorer·specification.'
(prettier/prettier)
[error] 179-181: Replace ⏎······item.slug.includes('/reference/specification/explorer'),⏎····
with ·item.slug.includes('/reference/specification/explorer')
(prettier/prettier)
[error] 187-190: Replace ⏎······join(tempDir,·'docs',·'invalid.mdx'),⏎······'---\ninvalid·front·matter\n---\nContent',⏎····
with join(tempDir,·'docs',·'invalid.mdx'),·'---\ninvalid·front·matter\n---\nContent'
(prettier/prettier)
[error] 192-194: Replace ⏎······buildPostList(postDirectories,·tempDir,·writeFilePath),⏎····).rejects.toThrow(/Error·while·building·post·list/
with buildPostList(postDirectories,·tempDir,·writeFilePath)).rejects.toThrow(⏎······/Error·while·building·post·list/⏎····
(prettier/prettier)
[error] 198-200: Replace ⏎······/Error·while·building·post·list/,⏎····
with /Error·while·building·post·list/
(prettier/prettier)
[error] 204-206: Replace ⏎······buildPostList(postDirectories,·undefined,·writeFilePath),⏎····
with buildPostList(postDirectories,·undefined,·writeFilePath)
(prettier/prettier)
[error] 207-207: Delete ,
(prettier/prettier)
[error] 212-214: Replace ⏎······buildPostList(postDirectories,·tempDir,·undefined),⏎····
with buildPostList(postDirectories,·tempDir,·undefined)
(prettier/prettier)
[error] 215-215: Delete ,
(prettier/prettier)
🔇 Additional comments (2)
tests/helper/buildPostListSetup.js (1)
1-17
: Well-structured helper function!
The function has a clear single responsibility and good separation of concerns.
🧰 Tools
🪛 eslint
[error] 1-1: ../fixtures/buildPostListData
import should occur after import of path
(import/order)
[error] 1-1: Replace "../fixtures/buildPostListData"
with '../fixtures/buildPostListData'
(prettier/prettier)
[error] 3-3: Replace "path")
with 'path');
(prettier/prettier)
[error] 6-6: Delete ··
(prettier/prettier)
[error] 7-7: Replace ····
with ··
(prettier/prettier)
[error] 7-13: iterators/generators require regenerator-runtime, which is too heavyweight for this guide to allow them. Separately, loops should be avoided in favor of array iterations.
(no-restricted-syntax)
[error] 8-8: Replace ········
with ····
(prettier/prettier)
[error] 8-8: Unexpected await
inside a loop.
(no-await-in-loop)
[error] 9-12: Replace ····await·fs.writeFile(⏎············join(tempDir,·TEST_CONTENT[dir].dir,·TEST_CONTENT[dir].file),⏎············TEST_CONTENT[dir].content⏎········
with await·fs.writeFile(join(tempDir,·TEST_CONTENT[dir].dir,·TEST_CONTENT[dir].file),·TEST_CONTENT[dir].content
(prettier/prettier)
[error] 9-12: Unexpected await
inside a loop.
(no-await-in-loop)
[error] 13-13: Replace ····
with ··
(prettier/prettier)
[error] 14-14: Delete ··
(prettier/prettier)
[error] 17-17: Insert ⏎
(prettier/prettier)
tests/build-post-list.test.js (1)
1-234
: Well-structured and comprehensive test suite!
The test suite provides excellent coverage of various scenarios and edge cases. The use of beforeEach/afterEach hooks for setup/cleanup is particularly good practice.
🧰 Tools
🪛 eslint
[error] 3-3: Insert ;
(prettier/prettier)
[error] 12-15: Replace ⏎······__dirname,⏎······
test-config-${Date.now()}-${Math.random().toString(36).slice(2)},⏎····
with __dirname,·
test-config-${Date.now()}-${Math.random().toString(36).slice(2)}``
(prettier/prettier)
[error] 20-20: Delete ,
(prettier/prettier)
[error] 23-24: Delete ⏎
(prettier/prettier)
[error] 43-43: Delete ,
(prettier/prettier)
[error] 48-48: Delete ,
(prettier/prettier)
[error] 53-53: Delete ,
(prettier/prettier)
[error] 54-54: Delete ,
(prettier/prettier)
[error] 55-55: Delete ,
(prettier/prettier)
[error] 62-62: Delete ,
(prettier/prettier)
[error] 63-63: Delete ,
(prettier/prettier)
[error] 64-64: Delete ,
(prettier/prettier)
[error] 71-71: Delete ,
(prettier/prettier)
[error] 72-72: Delete ,
(prettier/prettier)
[error] 73-73: Delete ,
(prettier/prettier)
[error] 78-80: Replace ⏎······(item)·=>·item.slug·===·'/blog/release-notes-2.1.0',⏎····
with (item)·=>·item.slug·===·'/blog/release-notes-2.1.0'
(prettier/prettier)
[error] 89-89: Delete ,
(prettier/prettier)
[error] 100-100: Delete ,
(prettier/prettier)
[error] 107-107: Delete ,
(prettier/prettier)
[error] 114-116: Replace ⏎······(item)·=>·item.slug·===·'/blog/release-notes-2.1.0',⏎····
with (item)·=>·item.slug·===·'/blog/release-notes-2.1.0'
(prettier/prettier)
[error] 117-119: Replace ⏎······(item)·=>·item.slug·===·'/blog/release-notes-2.1.1',⏎····
with (item)·=>·item.slug·===·'/blog/release-notes-2.1.1'
(prettier/prettier)
[error] 130-132: Replace ⏎······buildPostList([invalidDir],·tempDir,·writeFilePath),⏎····
with buildPostList([invalidDir],·tempDir,·writeFilePath)
(prettier/prettier)
[error] 137-140: Replace ⏎······join(specDir,·'v2.1.0-no-title.mdx'),⏎······'---\n---\nContent·of·specification·without·a·title.',⏎····
with join(specDir,·'v2.1.0-no-title.mdx'),·'---\n---\nContent·of·specification·without·a·title.'
(prettier/prettier)
[error] 145-147: Replace ⏎······item.slug.includes('/reference/specification/v2.1.0-no-title'),⏎····
with ·item.slug.includes('/reference/specification/v2.1.0-no-title')
(prettier/prettier)
[error] 156-156: Delete ,
(prettier/prettier)
[error] 162-164: Replace ⏎······item.slug.includes('/reference/specification/v2.1.0-next-spec.1'),⏎····
with ·item.slug.includes('/reference/specification/v2.1.0-next-spec.1')
(prettier/prettier)
[error] 171-174: Replace ⏎······join(specDir,·'explorer.mdx'),⏎······'---\n---\nContent·of·explorer·specification.',⏎····
with join(specDir,·'explorer.mdx'),·'---\n---\nContent·of·explorer·specification.'
(prettier/prettier)
[error] 179-181: Replace ⏎······item.slug.includes('/reference/specification/explorer'),⏎····
with ·item.slug.includes('/reference/specification/explorer')
(prettier/prettier)
[error] 187-190: Replace ⏎······join(tempDir,·'docs',·'invalid.mdx'),⏎······'---\ninvalid·front·matter\n---\nContent',⏎····
with join(tempDir,·'docs',·'invalid.mdx'),·'---\ninvalid·front·matter\n---\nContent'
(prettier/prettier)
[error] 192-194: Replace ⏎······buildPostList(postDirectories,·tempDir,·writeFilePath),⏎····).rejects.toThrow(/Error·while·building·post·list/
with buildPostList(postDirectories,·tempDir,·writeFilePath)).rejects.toThrow(⏎······/Error·while·building·post·list/⏎····
(prettier/prettier)
[error] 198-200: Replace ⏎······/Error·while·building·post·list/,⏎····
with /Error·while·building·post·list/
(prettier/prettier)
[error] 204-206: Replace ⏎······buildPostList(postDirectories,·undefined,·writeFilePath),⏎····
with buildPostList(postDirectories,·undefined,·writeFilePath)
(prettier/prettier)
[error] 207-207: Delete ,
(prettier/prettier)
[error] 212-214: Replace ⏎······buildPostList(postDirectories,·tempDir,·undefined),⏎····
with buildPostList(postDirectories,·tempDir,·undefined)
(prettier/prettier)
[error] 215-215: Delete ,
(prettier/prettier)
tests/build-post-list.test.js
Outdated
it('builds a post list and writes the result to a file', async () => { | ||
await buildPostList(postDirectories, tempDir, writeFilePath); | ||
|
||
const outputExists = await fs.pathExists(writeFilePath); | ||
expect(outputExists).toBe(true); | ||
|
||
const output = JSON.parse(await fs.readFile(writeFilePath, 'utf-8')); | ||
|
||
expect(output.docs).toEqual( | ||
expect.arrayContaining([ | ||
expect.objectContaining({ | ||
title: 'Docs Home', | ||
slug: '/docs', | ||
}), | ||
expect.objectContaining({ | ||
title: 'Reference', | ||
slug: '/docs/reference', | ||
isRootSection: true, | ||
}), | ||
expect.objectContaining({ | ||
title: 'Specification', | ||
slug: '/docs/reference/specification', | ||
isSection: true, | ||
}), | ||
]), | ||
); | ||
|
||
expect(output.blog).toEqual( | ||
expect.arrayContaining([ | ||
expect.objectContaining({ | ||
title: 'Release Notes 2.1.0', | ||
slug: '/blog/release-notes-2.1.0', | ||
}), | ||
]), | ||
); | ||
|
||
expect(output.about).toEqual( | ||
expect.arrayContaining([ | ||
expect.objectContaining({ | ||
title: 'About Us', | ||
slug: '/about', | ||
}), | ||
]), | ||
); | ||
|
||
expect(output.docsTree).toBeDefined(); | ||
|
||
const blogEntry = output.blog.find( | ||
(item) => item.slug === '/blog/release-notes-2.1.0', | ||
); | ||
expect(blogEntry).toBeDefined(); | ||
expect(blogEntry.title).toBe('Release Notes 2.1.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.
🛠️ Refactor suggestion
Consider breaking down the large test case
The "builds a post list and writes the result to a file" test case is testing multiple aspects. Consider breaking it down into smaller, focused test cases for better maintainability and easier debugging.
- it('builds a post list and writes the result to a file', async () => {
+ it('writes the result to a file', async () => {
await buildPostList(postDirectories, tempDir, writeFilePath);
const outputExists = await fs.pathExists(writeFilePath);
expect(outputExists).toBe(true);
+ });
+
+ it('correctly structures docs entries', async () => {
+ await buildPostList(postDirectories, tempDir, writeFilePath);
+ const output = JSON.parse(await fs.readFile(writeFilePath, 'utf-8'));
expect(output.docs).toEqual(
expect.arrayContaining([
expect.objectContaining({
title: 'Docs Home',
slug: '/docs',
}),
// ... other docs expectations
]),
);
+ });
+
+ it('correctly structures blog entries', async () => {
+ await buildPostList(postDirectories, tempDir, writeFilePath);
+ const output = JSON.parse(await fs.readFile(writeFilePath, 'utf-8'));
expect(output.blog).toEqual(
// ... blog expectations
);
// ... other blog-related assertions
+ });
Committable suggestion skipped: line range outside the PR's diff.
🧰 Tools
🪛 eslint
[error] 43-43: Delete ,
(prettier/prettier)
[error] 48-48: Delete ,
(prettier/prettier)
[error] 53-53: Delete ,
(prettier/prettier)
[error] 54-54: Delete ,
(prettier/prettier)
[error] 55-55: Delete ,
(prettier/prettier)
[error] 62-62: Delete ,
(prettier/prettier)
[error] 63-63: Delete ,
(prettier/prettier)
[error] 64-64: Delete ,
(prettier/prettier)
[error] 71-71: Delete ,
(prettier/prettier)
[error] 72-72: Delete ,
(prettier/prettier)
[error] 73-73: Delete ,
(prettier/prettier)
[error] 78-80: Replace ⏎······(item)·=>·item.slug·===·'/blog/release-notes-2.1.0',⏎····
with (item)·=>·item.slug·===·'/blog/release-notes-2.1.0'
(prettier/prettier)
@vishvamsinh28 Kindly look into the suggestions made by CodeRabbitAI and nitpick comments as well. |
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.
Actionable comments posted: 1
🧹 Outside diff range and nitpick comments (5)
tests/helper/buildPostListSetup.js (2)
7-13
: Consider using Promise.all for parallel directory creationThe current implementation uses a sequential for...of loop with await, which could be slower for multiple directories. Consider using Promise.all for parallel execution.
- for (const dir of dirs) { - await fs.ensureDir(join(tempDir, TEST_CONTENT[dir].dir)); - await fs.writeFile( - join(tempDir, TEST_CONTENT[dir].dir, TEST_CONTENT[dir].file), - TEST_CONTENT[dir].content - ); - } + await Promise.all( + dirs.map(async (dir) => { + await fs.ensureDir(join(tempDir, TEST_CONTENT[dir].dir)); + await fs.writeFile( + join(tempDir, TEST_CONTENT[dir].dir, TEST_CONTENT[dir].file), + TEST_CONTENT[dir].content + ); + }) + );🧰 Tools
🪛 eslint
[error] 7-7: Delete
··
(prettier/prettier)
[error] 7-13: iterators/generators require regenerator-runtime, which is too heavyweight for this guide to allow them. Separately, loops should be avoided in favor of array iterations.
(no-restricted-syntax)
[error] 8-8: Delete
····
(prettier/prettier)
[error] 8-8: Unexpected
await
inside a loop.(no-await-in-loop)
[error] 9-12: Replace
········await·fs.writeFile(⏎············join(tempDir,·TEST_CONTENT[dir].dir,·TEST_CONTENT[dir].file),⏎············TEST_CONTENT[dir].content⏎········
with····await·fs.writeFile(join(tempDir,·TEST_CONTENT[dir].dir,·TEST_CONTENT[dir].file),·TEST_CONTENT[dir].content
(prettier/prettier)
[error] 9-12: Unexpected
await
inside a loop.(no-await-in-loop)
[error] 13-13: Replace
····
with··
(prettier/prettier)
17-22
: Consider adding input validation for baseDirThe generateTempDirPath function should validate the baseDir parameter to ensure it's a valid directory path.
function generateTempDirPath(baseDir) { + if (!baseDir || typeof baseDir !== 'string') { + throw new Error('baseDir must be a valid string'); + } return resolve( baseDir, `test-config-${Date.now()}-${Math.random().toString(36).slice(2)}` ); }🧰 Tools
🪛 eslint
[error] 18-21: Replace
··return·resolve(⏎········baseDir,⏎········
test-config-${Date.now()}-${Math.random().toString(36).slice(2)}⏎····
withreturn·resolve(baseDir,·
test-config-${Date.now()}-${Math.random().toString(36).slice(2)}``(prettier/prettier)
tests/build-post-list.test.js (3)
11-22
: Consider extracting test configurationThe test setup configuration could be moved to a separate fixture file for better maintainability.
Create a new file
tests/fixtures/buildPostListConfig.js
:module.exports = { getTestConfig: (tempDir) => ({ writeFilePath: resolve(tempDir, 'posts.json'), postDirectories: [ [join(tempDir, 'blog'), '/blog'], [join(tempDir, 'docs'), '/docs'], [join(tempDir, 'about'), '/about'], ] }) };🧰 Tools
🪛 eslint
[error] 17-17: Delete
,
(prettier/prettier)
[error] 20-21: Delete
⏎
(prettier/prettier)
90-107
: Consider adding negative test cases for section handlingThe section handling tests could be more comprehensive by including negative test cases.
Add a test case for invalid section files:
it('ignores invalid section files', async () => { await fs.writeFile( join(tempDir, 'docs', 'invalid_section.mdx'), '---\ntitle: Invalid Section\nisSection: true\n---\nInvalid section.', ); await buildPostList(postDirectories, tempDir, writeFilePath); const output = JSON.parse(await fs.readFile(writeFilePath, 'utf-8')); const invalidSection = output.docs.find( item => item.slug.includes('invalid_section') ); expect(invalidSection).toBeUndefined(); });🧰 Tools
🪛 eslint
[error] 94-94: Delete
,
(prettier/prettier)
[error] 105-105: Delete
,
(prettier/prettier)
133-138
: Enhance error test with specific error messageThe error test for non-existent directory should verify the specific error message.
it('throws an error when accessing non-existent directory', async () => { const invalidDir = [join(tempDir, 'non-existent-dir'), '/invalid']; await expect( buildPostList([invalidDir], tempDir, writeFilePath), - ).rejects.toThrow(); + ).rejects.toThrow(/Error while building post list/); });🧰 Tools
🪛 eslint
[error] 135-137: Replace
⏎······buildPostList([invalidDir],·tempDir,·writeFilePath),⏎····
withbuildPostList([invalidDir],·tempDir,·writeFilePath)
(prettier/prettier)
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
📒 Files selected for processing (2)
tests/build-post-list.test.js
(1 hunks)tests/helper/buildPostListSetup.js
(1 hunks)
🧰 Additional context used
🪛 eslint
tests/helper/buildPostListSetup.js
[error] 1-1: ../fixtures/buildPostListData
import should occur after import of path
(import/order)
[error] 1-1: Replace "../fixtures/buildPostListData"
with '../fixtures/buildPostListData'
(prettier/prettier)
[error] 3-3: Replace "path")
with 'path');
(prettier/prettier)
[error] 6-6: Delete ··
(prettier/prettier)
[error] 7-7: Delete ··
(prettier/prettier)
[error] 7-13: iterators/generators require regenerator-runtime, which is too heavyweight for this guide to allow them. Separately, loops should be avoided in favor of array iterations.
(no-restricted-syntax)
[error] 8-8: Delete ····
(prettier/prettier)
[error] 8-8: Unexpected await
inside a loop.
(no-await-in-loop)
[error] 9-12: Replace ········await·fs.writeFile(⏎············join(tempDir,·TEST_CONTENT[dir].dir,·TEST_CONTENT[dir].file),⏎············TEST_CONTENT[dir].content⏎········
with ····await·fs.writeFile(join(tempDir,·TEST_CONTENT[dir].dir,·TEST_CONTENT[dir].file),·TEST_CONTENT[dir].content
(prettier/prettier)
[error] 9-12: Unexpected await
inside a loop.
(no-await-in-loop)
[error] 13-13: Replace ····
with ··
(prettier/prettier)
[error] 14-14: Delete ··
(prettier/prettier)
[error] 18-21: Replace ··return·resolve(⏎········baseDir,⏎········
test-config-${Date.now()}-${Math.random().toString(36).slice(2)}⏎····
with return·resolve(baseDir,·
test-config-${Date.now()}-${Math.random().toString(36).slice(2)}``
(prettier/prettier)
[error] 24-24: Insert ⏎
(prettier/prettier)
tests/build-post-list.test.js
[error] 3-3: Insert ;
(prettier/prettier)
[error] 17-17: Delete ,
(prettier/prettier)
[error] 20-21: Delete ⏎
(prettier/prettier)
[error] 43-43: Delete ,
(prettier/prettier)
[error] 48-48: Delete ,
(prettier/prettier)
[error] 53-53: Delete ,
(prettier/prettier)
[error] 54-54: Delete ,
(prettier/prettier)
[error] 55-55: Delete ,
(prettier/prettier)
[error] 67-67: Delete ,
(prettier/prettier)
[error] 68-68: Delete ,
(prettier/prettier)
[error] 69-69: Delete ,
(prettier/prettier)
[error] 76-76: Delete ,
(prettier/prettier)
[error] 77-77: Delete ,
(prettier/prettier)
[error] 78-78: Delete ,
(prettier/prettier)
[error] 83-85: Replace ⏎······(item)·=>·item.slug·===·'/blog/release-notes-2.1.0',⏎····
with (item)·=>·item.slug·===·'/blog/release-notes-2.1.0'
(prettier/prettier)
[error] 94-94: Delete ,
(prettier/prettier)
[error] 105-105: Delete ,
(prettier/prettier)
[error] 112-112: Delete ,
(prettier/prettier)
[error] 119-121: Replace ⏎······(item)·=>·item.slug·===·'/blog/release-notes-2.1.0',⏎····
with (item)·=>·item.slug·===·'/blog/release-notes-2.1.0'
(prettier/prettier)
[error] 122-124: Replace ⏎······(item)·=>·item.slug·===·'/blog/release-notes-2.1.1',⏎····
with (item)·=>·item.slug·===·'/blog/release-notes-2.1.1'
(prettier/prettier)
[error] 135-137: Replace ⏎······buildPostList([invalidDir],·tempDir,·writeFilePath),⏎····
with buildPostList([invalidDir],·tempDir,·writeFilePath)
(prettier/prettier)
[error] 142-145: Replace ⏎······join(specDir,·'v2.1.0-no-title.mdx'),⏎······'---\n---\nContent·of·specification·without·a·title.',⏎····
with join(specDir,·'v2.1.0-no-title.mdx'),·'---\n---\nContent·of·specification·without·a·title.'
(prettier/prettier)
[error] 150-152: Replace ⏎······item.slug.includes('/reference/specification/v2.1.0-no-title'),⏎····
with ·item.slug.includes('/reference/specification/v2.1.0-no-title')
(prettier/prettier)
[error] 161-161: Delete ,
(prettier/prettier)
[error] 167-169: Replace ⏎······item.slug.includes('/reference/specification/v2.1.0-next-spec.1'),⏎····
with ·item.slug.includes('/reference/specification/v2.1.0-next-spec.1')
(prettier/prettier)
[error] 176-179: Replace ⏎······join(specDir,·'explorer.mdx'),⏎······'---\n---\nContent·of·explorer·specification.',⏎····
with join(specDir,·'explorer.mdx'),·'---\n---\nContent·of·explorer·specification.'
(prettier/prettier)
[error] 184-186: Replace ⏎······item.slug.includes('/reference/specification/explorer'),⏎····
with ·item.slug.includes('/reference/specification/explorer')
(prettier/prettier)
[error] 192-195: Replace ⏎······join(tempDir,·'docs',·'invalid.mdx'),⏎······'---\ninvalid·front·matter\n---\nContent',⏎····
with join(tempDir,·'docs',·'invalid.mdx'),·'---\ninvalid·front·matter\n---\nContent'
(prettier/prettier)
[error] 197-199: Replace ⏎······buildPostList(postDirectories,·tempDir,·writeFilePath),⏎····).rejects.toThrow(/Error·while·building·post·list/
with buildPostList(postDirectories,·tempDir,·writeFilePath)).rejects.toThrow(⏎······/Error·while·building·post·list/⏎····
(prettier/prettier)
[error] 203-205: Replace ⏎······/Error·while·building·post·list/,⏎····
with /Error·while·building·post·list/
(prettier/prettier)
[error] 209-211: Replace ⏎······buildPostList(postDirectories,·undefined,·writeFilePath),⏎····
with buildPostList(postDirectories,·undefined,·writeFilePath)
(prettier/prettier)
[error] 212-212: Delete ,
(prettier/prettier)
[error] 217-219: Replace ⏎······buildPostList(postDirectories,·tempDir,·undefined),⏎····
with buildPostList(postDirectories,·tempDir,·undefined)
(prettier/prettier)
[error] 220-220: Delete ,
(prettier/prettier)
tests/build-post-list.test.js
Outdated
describe('slugifyToC', () => { | ||
it('handles heading ids like {# myHeadingId}', () => { | ||
const input = '## My Heading {#custom-id}'; | ||
expect(slugifyToC(input)).toBe('custom-id'); | ||
}); | ||
|
||
it('handles heading ids like {<a name="myHeadingId"/>}', () => { | ||
const input = '## My Heading {<a name="custom-anchor-id"/>}'; | ||
expect(slugifyToC(input)).toBe('custom-anchor-id'); | ||
}); | ||
|
||
it('handles empty strings', () => { | ||
expect(slugifyToC('')).toBe(''); | ||
}); | ||
}); |
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.
🛠️ Refactor suggestion
Add test cases for malformed heading IDs
The slugifyToC tests should include cases for malformed heading IDs and mixed formats.
Add these test cases:
it('returns empty string for malformed heading IDs', () => {
expect(slugifyToC('## Heading {#}')).toBe('');
expect(slugifyToC('## Heading {# }')).toBe('');
expect(slugifyToC('## Heading {<a name=""/>}')).toBe('');
});
it('handles mixed format heading IDs', () => {
expect(slugifyToC('## Heading {#id} {<a name="name"/>}')).toBe('id');
});
@akshatnema I have applied the suggestions provided by Coderabbit. However, I have ignored a few suggestions because they caused the script/test to not work as expected. |
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.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (7)
scripts/build-post-list.js (4)
31-33
: Consider more specific error messagesThe error message could be more descriptive by specifying which parameter is missing.
- throw new Error('Error while building post list: basePath and writeFilePath are required'); + const missing = []; + if (!basePath) missing.push('basePath'); + if (!writeFilePath) missing.push('writeFilePath'); + throw new Error(`Error while building post list: ${missing.join(' and ')} ${missing.length > 1 ? 'are' : 'is'} required`);
49-53
: Consider breaking down the walkDirectories functionThe function has grown complex and handles multiple responsibilities. Consider extracting the file processing logic into separate functions for better maintainability.
+async function processFile(fileName, directory, sectionSlug, basePath) { + const fileNameWithSection = posix.join(fileName, '_section.mdx'); + const normalizedSlug = posix.join('/', relative(basePath, fileName)); + const slug = normalizedSlug.replace(/\\/g,'/'); + + if (await isDirectory(fileName)) { + return processDirectory(fileName, directory, slug, basePath); + } + return processMarkdownFile(fileName, directory, slug, sectionSlug); +} async function walkDirectories(directories, resultObj, basePath, sectionTitle, sectionId, rootSectionId, sectionWeight = 0) { for (let dir of directories) { const directory = posix.normalize(dir[0]); const sectionSlug = dir[1] || ''; const files = await readdir(directory); + for (const file of files) { + const fileName = posix.join(directory, file); + const details = await processFile(fileName, directory, sectionSlug, basePath); + if (details) addItem(details); + } } }🧰 Tools
🪛 eslint
[error] 49-49: This line has a length of 125. Maximum allowed is 120.
(max-len)
[error] 49-49: Replace
directories,·resultObj,·basePath,·sectionTitle,·sectionId,·rootSectionId,·sectionWeight·=·0
with⏎··directories,⏎··resultObj,⏎··basePath,⏎··sectionTitle,⏎··sectionId,⏎··rootSectionId,⏎··sectionWeight·=·0⏎
(prettier/prettier)
[error] 50-50: 'dir' is never reassigned. Use 'const' instead.
(prefer-const)
[error] 51-51: 'directory' is never reassigned. Use 'const' instead.
(prefer-const)
[error] 52-52: 'sectionSlug' is never reassigned. Use 'const' instead.
(prefer-const)
[error] 53-53: 'files' is never reassigned. Use 'const' instead.
(prefer-const)
[error] 53-53: Unexpected
await
inside a loop.(no-await-in-loop)
[error] 53-53: Insert
;
(prettier/prettier)
148-161
: Enhance regex patterns and error handling in slugifyToCThe regex patterns could be more robust, and the function could benefit from better error handling.
function slugifyToC(str) { + if (typeof str !== 'string') return ''; let slug = ''; // Match heading IDs like {# myHeadingId} - const headingIdMatch = str.match(/[\s]?\{\#([\w\d\-_]+)\}/); + const headingIdMatch = str.match(/[\s]*\{#([a-zA-Z0-9\-_]+)\}/); if (headingIdMatch && headingIdMatch[1].trim()) { slug = headingIdMatch[1]; } else { // Match heading IDs like {<a name="myHeadingId"/>} - const anchorTagMatch = str.match(/[\s]*<a[\s]+name="([\w\d\-_]+)"/); + const anchorTagMatch = str.match(/[\s]*<a[\s]+name="([a-zA-Z0-9\-_]+)"/); if (anchorTagMatch && anchorTagMatch[1].trim()) { slug = anchorTagMatch[1]; } } return slug; }🧰 Tools
🪛 Biome (1.9.4)
[error] 150-150: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 155-155: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
🪛 eslint
[error] 149-149: Unnecessary escape character: #.
(no-useless-escape)
[error] 151-151: Use array destructuring.
(prefer-destructuring)
[error] 156-156: Use array destructuring.
(prefer-destructuring)
164-172
: Optimize the capitalize functionThe capitalize function could be more efficient by avoiding multiple string operations.
function capitalize(text) { - return text.split(/[\s\-]/g).map(word => `${word[0].toUpperCase()}${word.substr(1)}`).join(' ') + return text.replace(/(?:^|\s|-)([a-z])/g, (_, char) => char.toUpperCase()) }🧰 Tools
🪛 eslint
[error] 165-165: Insert
;
(prettier/prettier)
[error] 169-169: Replace
.split(/[\s\-]/g).map(word·=>·
${word[0].toUpperCase()}${word.substr(1)}).join('·')
with⏎····.split(/[\s\-]/g)⏎····.map((word)·=>·
${word[0].toUpperCase()}${word.substr(1)})⏎····.join('·');
(prettier/prettier)
[error] 169-169: Unnecessary escape character: -.
(no-useless-escape)
[error] 172-172: Insert
;
(prettier/prettier)
tests/build-post-list.test.js (3)
28-33
: Enhance test description and assertionsThe test description "writes the result to a file" could be more specific, and additional assertions could be added.
- it('writes the result to a file', async () => { + it('writes a valid JSON file with the expected structure', async () => { await buildPostList(postDirectories, tempDir, writeFilePath); const outputExists = await fs.pathExists(writeFilePath); expect(outputExists).toBe(true); + + const content = await fs.readFile(writeFilePath, 'utf-8'); + expect(() => JSON.parse(content)).not.toThrow(); });
133-138
: Improve error test assertionsThe error test could be more specific about the expected error message.
it('throws an error when accessing non-existent directory', async () => { const invalidDir = [join(tempDir, 'non-existent-dir'), '/invalid']; await expect( buildPostList([invalidDir], tempDir, writeFilePath), - ).rejects.toThrow(); + ).rejects.toThrow(/Error while building post list: ENOENT/); });🧰 Tools
🪛 eslint
[error] 135-137: Replace
⏎······buildPostList([invalidDir],·tempDir,·writeFilePath),⏎····
withbuildPostList([invalidDir],·tempDir,·writeFilePath)
(prettier/prettier)
224-248
: Add edge cases to slugifyToC testsThe test suite for slugifyToC could include more edge cases.
Add these test cases:
it('handles invalid input types gracefully', () => { expect(slugifyToC(null)).toBe(''); expect(slugifyToC(undefined)).toBe(''); expect(slugifyToC(123)).toBe(''); }); it('ignores invalid characters in heading IDs', () => { expect(slugifyToC('## Heading {#invalid@id}')).toBe(''); expect(slugifyToC('## Heading {#invalid spaces}')).toBe(''); });🧰 Tools
🪛 eslint
[error] 238-238: Delete
····
(prettier/prettier)
[error] 244-244: Delete
····
(prettier/prettier)
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
-
scripts/build-post-list.js
(7 hunks) -
tests/build-post-list.test.js
(1 hunks)
🧰 Additional context used
📓 Learnings (1)
scripts/build-post-list.js (2)
Learnt from: vishvamsinh28
PR: asyncapi/website#3284
File: scripts/build-post-list.js:28-46
Timestamp: 2024-11-12T06:59:33.852Z
Learning: In the `scripts/build-post-list.js` JavaScript file, tests rely on the `result` object being a global variable. Moving it inside the `buildPostList` function causes tests to fail; therefore, keep `result` as a global variable.
Learnt from: vishvamsinh28
PR: asyncapi/website#3284
File: scripts/build-post-list.js:49-53
Timestamp: 2024-11-12T06:59:33.851Z
Learning: In `scripts/build-post-list.js`, the `walkDirectories` function depends on sequential execution because it mutates `resultObj`. Parallelizing the loop with `Promise.all` causes tests to fail.
🪛 eslint
scripts/build-post-list.js
[error] 1-1: Insert ;
(prettier/prettier)
[error] 2-2: Insert ;
(prettier/prettier)
[error] 20-21: Replace ⏎····result["docs"].push(details)
with ·result['docs'].push(details);
(prettier/prettier)
[error] 21-21: ["docs"] is better written in dot notation.
(dot-notation)
[error] 22-23: Replace ⏎····result["blog"].push(details)
with ·result['blog'].push(details);
(prettier/prettier)
[error] 23-23: ["blog"] is better written in dot notation.
(dot-notation)
[error] 24-25: Replace ⏎····result["about"].push(details)
with ·result['about'].push(details);
(prettier/prettier)
[error] 25-25: ["about"] is better written in dot notation.
(dot-notation)
[error] 29-30: Delete ⏎
(prettier/prettier)
[error] 38-38: Insert ;
(prettier/prettier)
[error] 39-39: 'walkDirectories' was used before it was defined.
(no-use-before-define)
[error] 39-39: Insert ;
(prettier/prettier)
[error] 40-40: Replace "docs"].filter((p)·=>·p.slug.startsWith('/docs/')))
with 'docs'].filter((p)·=>·p.slug.startsWith('/docs/')));
(prettier/prettier)
[error] 40-40: ["docs"] is better written in dot notation.
(dot-notation)
[error] 41-41: Replace "docsTree"]·=·treePosts
with 'docsTree']·=·treePosts;
(prettier/prettier)
[error] 41-41: ["docsTree"] is better written in dot notation.
(dot-notation)
[error] 42-42: Replace "docs"]·=·addDocButtons(result["docs"],·treePosts)
with 'docs']·=·addDocButtons(result['docs'],·treePosts);
(prettier/prettier)
[error] 42-42: ["docs"] is better written in dot notation.
(dot-notation)
[error] 42-42: ["docs"] is better written in dot notation.
(dot-notation)
[error] 43-43: Insert ;
(prettier/prettier)
[error] 49-49: This line has a length of 125. Maximum allowed is 120.
(max-len)
[error] 49-49: Replace directories,·resultObj,·basePath,·sectionTitle,·sectionId,·rootSectionId,·sectionWeight·=·0
with ⏎··directories,⏎··resultObj,⏎··basePath,⏎··sectionTitle,⏎··sectionId,⏎··rootSectionId,⏎··sectionWeight·=·0⏎
(prettier/prettier)
[error] 50-50: 'dir' is never reassigned. Use 'const' instead.
(prefer-const)
[error] 51-51: 'directory' is never reassigned. Use 'const' instead.
(prefer-const)
[error] 52-52: 'sectionSlug' is never reassigned. Use 'const' instead.
(prefer-const)
[error] 53-53: 'files' is never reassigned. Use 'const' instead.
(prefer-const)
[error] 53-53: Unexpected await
inside a loop.
(no-await-in-loop)
[error] 53-53: Insert ;
(prettier/prettier)
[error] 55-55: 'file' is never reassigned. Use 'const' instead.
(prefer-const)
[error] 58-58: Insert ;
(prettier/prettier)
[error] 59-59: Insert ;
(prettier/prettier)
[error] 60-60: Replace '/')
with ·'/');
(prettier/prettier)
[error] 61-61: Insert ;
(prettier/prettier)
[error] 63-63: Unexpected await
inside a loop.
(no-await-in-loop)
[error] 63-63: 'isDirectory' was used before it was defined.
(no-use-before-define)
[error] 64-64: Unexpected await
inside a loop.
(no-await-in-loop)
[error] 66-66: Unexpected await
inside a loop.
(no-await-in-loop)
[error] 66-66: Insert ;
(prettier/prettier)
[error] 75-75: Insert ;
(prettier/prettier)
[error] 76-76: Insert ;
(prettier/prettier)
[error] 86-86: This line has a length of 135. Maximum allowed is 120.
(max-len)
[error] 86-86: Unexpected await
inside a loop.
(no-await-in-loop)
[error] 86-86: Replace [[fileName,·slug]],·resultObj,·basePath,·details.title,·details.sectionId,·rootId,·details.sectionWeight)
with ⏎··········[[fileName,·slug]],⏎··········resultObj,⏎··········basePath,⏎··········details.title,⏎··········details.sectionId,⏎··········rootId,⏎··········details.sectionWeight⏎········);
(prettier/prettier)
[error] 87-87: Unexpected string concatenation.
(prefer-template)
[error] 88-88: Unexpected await
inside a loop.
(no-await-in-loop)
[error] 88-88: Insert ;
(prettier/prettier)
[error] 100-100: Insert ;
(prettier/prettier)
[error] 101-101: Insert ;
(prettier/prettier)
[error] 102-102: Insert ;
(prettier/prettier)
[error] 104-104: Replace ·
with ;
(prettier/prettier)
[error] 105-105: Insert ;
(prettier/prettier)
[error] 106-106: Unary operator '--' used.
(no-plusplus)
[error] 106-106: Insert ;
(prettier/prettier)
[error] 109-109: 'capitalize' was used before it was defined.
(no-use-before-define)
[error] 109-109: Insert ;
(prettier/prettier)
[error] 111-111: 'capitalize' was used before it was defined.
(no-use-before-define)
[error] 111-111: Insert ;
(prettier/prettier)
[error] 129-129: Replace "release-notes")·&&·dir[1]·===·"/blog"
with 'release-notes')·&&·dir[1]·===·'/blog'
(prettier/prettier)
[error] 130-130: Insert ;
(prettier/prettier)
[error] 132-132: Replace "-")·+·1)
with '-')·+·1);
(prettier/prettier)
[error] 134-134: This line has a length of 164. Maximum allowed is 120.
(max-len)
[error] 149-149: Unnecessary escape character: #.
(no-useless-escape)
[error] 151-151: Use array destructuring.
(prefer-destructuring)
[error] 156-156: Use array destructuring.
(prefer-destructuring)
[error] 165-165: Insert ;
(prettier/prettier)
[error] 169-169: Replace .split(/[\s\-]/g).map(word·=>·
${word[0].toUpperCase()}${word.substr(1)}).join('·')
with ⏎····.split(/[\s\-]/g)⏎····.map((word)·=>·
${word[0].toUpperCase()}${word.substr(1)})⏎····.join('·');
(prettier/prettier)
[error] 169-169: Unnecessary escape character: -.
(no-useless-escape)
[error] 172-172: Insert ;
(prettier/prettier)
tests/build-post-list.test.js
[error] 3-3: Insert ;
(prettier/prettier)
[error] 17-17: Delete ,
(prettier/prettier)
[error] 20-21: Delete ⏎
(prettier/prettier)
[error] 43-43: Delete ,
(prettier/prettier)
[error] 48-48: Delete ,
(prettier/prettier)
[error] 53-53: Delete ,
(prettier/prettier)
[error] 54-54: Delete ,
(prettier/prettier)
[error] 55-55: Delete ,
(prettier/prettier)
[error] 67-67: Delete ,
(prettier/prettier)
[error] 68-68: Delete ,
(prettier/prettier)
[error] 69-69: Delete ,
(prettier/prettier)
[error] 76-76: Delete ,
(prettier/prettier)
[error] 77-77: Delete ,
(prettier/prettier)
[error] 78-78: Delete ,
(prettier/prettier)
[error] 83-85: Replace ⏎······(item)·=>·item.slug·===·'/blog/release-notes-2.1.0',⏎····
with (item)·=>·item.slug·===·'/blog/release-notes-2.1.0'
(prettier/prettier)
[error] 94-94: Delete ,
(prettier/prettier)
[error] 105-105: Delete ,
(prettier/prettier)
[error] 112-112: Delete ,
(prettier/prettier)
[error] 119-121: Replace ⏎······(item)·=>·item.slug·===·'/blog/release-notes-2.1.0',⏎····
with (item)·=>·item.slug·===·'/blog/release-notes-2.1.0'
(prettier/prettier)
[error] 122-124: Replace ⏎······(item)·=>·item.slug·===·'/blog/release-notes-2.1.1',⏎····
with (item)·=>·item.slug·===·'/blog/release-notes-2.1.1'
(prettier/prettier)
[error] 135-137: Replace ⏎······buildPostList([invalidDir],·tempDir,·writeFilePath),⏎····
with buildPostList([invalidDir],·tempDir,·writeFilePath)
(prettier/prettier)
[error] 142-145: Replace ⏎······join(specDir,·'v2.1.0-no-title.mdx'),⏎······'---\n---\nContent·of·specification·without·a·title.',⏎····
with join(specDir,·'v2.1.0-no-title.mdx'),·'---\n---\nContent·of·specification·without·a·title.'
(prettier/prettier)
[error] 150-152: Replace ⏎······item.slug.includes('/reference/specification/v2.1.0-no-title'),⏎····
with ·item.slug.includes('/reference/specification/v2.1.0-no-title')
(prettier/prettier)
[error] 161-161: Delete ,
(prettier/prettier)
[error] 167-169: Replace ⏎······item.slug.includes('/reference/specification/v2.1.0-next-spec.1'),⏎····
with ·item.slug.includes('/reference/specification/v2.1.0-next-spec.1')
(prettier/prettier)
[error] 176-179: Replace ⏎······join(specDir,·'explorer.mdx'),⏎······'---\n---\nContent·of·explorer·specification.',⏎····
with join(specDir,·'explorer.mdx'),·'---\n---\nContent·of·explorer·specification.'
(prettier/prettier)
[error] 184-186: Replace ⏎······item.slug.includes('/reference/specification/explorer'),⏎····
with ·item.slug.includes('/reference/specification/explorer')
(prettier/prettier)
[error] 192-195: Replace ⏎······join(tempDir,·'docs',·'invalid.mdx'),⏎······'---\ninvalid·front·matter\n---\nContent',⏎····
with join(tempDir,·'docs',·'invalid.mdx'),·'---\ninvalid·front·matter\n---\nContent'
(prettier/prettier)
[error] 197-199: Replace ⏎······buildPostList(postDirectories,·tempDir,·writeFilePath),⏎····).rejects.toThrow(/Error·while·building·post·list/
with buildPostList(postDirectories,·tempDir,·writeFilePath)).rejects.toThrow(⏎······/Error·while·building·post·list/⏎····
(prettier/prettier)
[error] 203-205: Replace ⏎······/Error·while·building·post·list/,⏎····
with /Error·while·building·post·list/
(prettier/prettier)
[error] 209-211: Replace ⏎······buildPostList(postDirectories,·undefined,·writeFilePath),⏎····
with buildPostList(postDirectories,·undefined,·writeFilePath)
(prettier/prettier)
[error] 212-212: Delete ,
(prettier/prettier)
[error] 217-219: Replace ⏎······buildPostList(postDirectories,·tempDir,·undefined),⏎····
with buildPostList(postDirectories,·tempDir,·undefined)
(prettier/prettier)
[error] 220-220: Delete ,
(prettier/prettier)
[error] 238-238: Delete ····
(prettier/prettier)
[error] 244-244: Delete ····
(prettier/prettier)
🪛 Biome (1.9.4)
scripts/build-post-list.js
[error] 150-150: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
[error] 155-155: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
🔇 Additional comments (1)
scripts/build-post-list.js (1)
1-1
: Good choice using fs-extra!
The switch to fs-extra
is a good improvement as it provides more robust file operations and better error handling. It also ensures directory existence automatically during write operations.
🧰 Tools
🪛 eslint
[error] 1-1: Insert ;
(prettier/prettier)
This script adds tests for build-post-list.js script
Summary by CodeRabbit
New Features
buildPostList
andslugifyToC
functions.TEST_CONTENT
for structured test data across different sections.Bug Fixes
Documentation