Skip to content
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: added test for build-rss.js #3101

Merged
merged 83 commits into from
Nov 9, 2024
Merged

Conversation

vishvamsinh28
Copy link
Contributor

@vishvamsinh28 vishvamsinh28 commented Jul 21, 2024

This PR adds test for build-rss.js script

Summary by CodeRabbit

  • New Features

    • Enhanced error handling for RSS feed generation, ensuring more robust performance.
    • Added comprehensive unit tests for the RSS feed functionality, covering various scenarios and edge cases.
    • Introduced mock data structures for testing RSS feed generation.
    • Asynchronous processing of RSS feed generation to improve performance and reliability.
    • Prioritized featured posts in the generated RSS feed.
    • Implemented filtering for posts without dates before sorting.
    • Added a new dependency for XML parsing to enhance functionality.
  • Bug Fixes

    • Improved handling of missing fields and date attributes in posts, preventing errors during RSS feed generation.
    • Ensured that posts without dates are filtered out before sorting.

Copy link

netlify bot commented Jul 21, 2024

Deploy Preview for asyncapi-website ready!

Name Link
🔨 Latest commit 08c88ae
🔍 Latest deploy log https://app.netlify.com/sites/asyncapi-website/deploys/672f06f6edbe58000863f592
😎 Deploy Preview https://deploy-preview-3101--asyncapi-website.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

@asyncapi-bot
Copy link
Contributor

asyncapi-bot commented Jul 21, 2024

⚡️ Lighthouse report for the changes in this PR:

Category Score
🔴 Performance 44
🟢 Accessibility 98
🟢 Best practices 92
🟢 SEO 100
🔴 PWA 33

Lighthouse ran on https://deploy-preview-3101--asyncapi-website.netlify.app/

@sambhavgupta0705 sambhavgupta0705 added the gsoc This label should be used for issues or discussions related to ideas for Google Summer of Code label Jul 23, 2024
@anshgoyalevil
Copy link
Member

@vishvamsinh28 Statement and branch coverage aren't 100% for this file.

image

@vishvamsinh28
Copy link
Contributor Author

vishvamsinh28 commented Aug 16, 2024

@anshgoyalevil updated the test, now it has 98.33% coverage. I will push another change to make it 100%

scripts/build-rss.js Show resolved Hide resolved
tests/build-rss.test.js Outdated Show resolved Hide resolved
tests/fixtures/rssData.js Show resolved Hide resolved
@anshgoyalevil
Copy link
Member

There's still room for improvement, @vishvamsinh28
image

Copy link

@coderabbitai coderabbitai bot left a 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 (4)
tests/fixtures/rssData.js (2)

45-61: Enhance date validation test cases.

The current test data covers basic date validation, but consider adding more edge cases:

  • Invalid date formats
  • Malformed dates
  • Different timezone formats

Consider adding these test cases:

 const missingDateMockData = {
   blog: [
     // ... existing entries
+    {
+      title: 'Post with Invalid Date',
+      slug: '/blog/invalid-date',
+      excerpt: 'This post has an invalid date',
+      date: 'not-a-date',
+      featured: false,
+    },
+    {
+      title: 'Post with Malformed Date',
+      slug: '/blog/malformed-date',
+      excerpt: 'This post has a malformed date',
+      date: '2023-13-45',
+      featured: false,
+    },
   ],
 };

63-72: Expand incomplete post test scenarios.

Consider adding more test cases for other missing required fields:

  • Missing excerpt
  • Missing slug
  • Empty string values

Consider expanding the test cases:

 const incompletePostMockData = {
   blog: [
     // ... existing entry
+    {
+      title: 'Post with Empty Excerpt',
+      slug: '/blog/empty-excerpt',
+      excerpt: '',
+      date: '2023-07-05',
+      featured: false,
+    },
+    {
+      title: 'Post with Missing Slug',
+      excerpt: 'This post is missing a slug',
+      date: '2023-07-05',
+      featured: false,
+    },
   ],
 };
scripts/build-rss.js (1)

83-83: Consider calculating the actual image size for enclosure

Using a dummy value for enclosure["@length"] may lead to inaccurate metadata in the RSS feed. If feasible, calculate the actual file size of the image to provide precise information.

tests/build-rss.test.js (1)

92-94: Use path.join to construct file paths for consistency

Instead of hardcoding "invalid/path", use path.join to create file paths. This ensures cross-platform compatibility and consistency throughout your code.

Suggested change:

-const invalidOutputPath = "invalid/path";
+const invalidOutputPath = path.join('invalid', 'path');
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 551c47a and bc76d4b.

📒 Files selected for processing (3)
  • scripts/build-rss.js (2 hunks)
  • tests/build-rss.test.js (1 hunks)
  • tests/fixtures/rssData.js (1 hunks)
🧰 Additional context used
📓 Learnings (2)
scripts/build-rss.js (1)
Learnt from: akshatnema
PR: asyncapi/website#3101
File: scripts/build-rss.js:4-6
Timestamp: 2024-11-01T09:35:23.912Z
Learning: Converting `getAllPosts()` to asynchronous in `scripts/build-rss.js` causes the existing build system to fail.
tests/build-rss.test.js (1)
Learnt from: akshatnema
PR: asyncapi/website#3101
File: tests/build-rss.test.js:25-27
Timestamp: 2024-11-01T09:55:20.531Z
Learning: In `tests/build-rss.test.js`, replacing `jest.resetModules()` with `jest.resetAllMocks()` in the `afterEach()` block causes errors. It is necessary to use `jest.resetModules()` to reset the module registry between tests in this file.
🔇 Additional comments (12)
tests/fixtures/rssData.js (1)

74-79: Verify output path compatibility.

The hardcoded output path 'test-output/blog.xml' might need validation to ensure:

  1. The directory exists or can be created
  2. The path is compatible across different operating systems

Let's verify the output directory existence and path compatibility:

scripts/build-rss.js (3)

1-1: Good use of fs.promises for asynchronous operations

Importing fs.promises enables the use of async/await with file system operations, improving code readability and avoiding callback complexities.


5-5: Consistency maintained in getAllPosts() function

Retaining the synchronous nature of getAllPosts() aligns with the existing build system requirements, preventing potential build failures.


18-34: Efficient filtering and sorting of posts

Filtering out posts without dates and sorting them prior to processing ensures that only valid and relevant posts are included, enhancing reliability.

tests/build-rss.test.js (8)

25-27: jest.resetModules() is appropriately used

Using jest.resetModules() in the afterEach hook ensures that the module registry is reset between tests. This is necessary in your test setup to properly mock modules without caching issues.


29-38: Test case for RSS feed generation is well-implemented

The test effectively validates that the RSS feed is generated and written to the correct file path. It correctly mocks posts.json and asserts the existence and basic content of the generated RSS file.


40-71: Tests for post prioritization and sorting are comprehensive

The tests verify that featured posts are prioritized and that posts are sorted by date in descending order. The use of regular expressions to extract titles serves the purpose, but consider the potential fragility of regex parsing with XML content.


127-133: Error handling tests are thorough and validate expected failures

The test correctly checks that the rssFeed function throws an error when encountering a post missing the date field during sorting. This ensures that error handling is functioning as expected.


108-117: Test for handling an empty posts array is effective

The test verifies that the rssFeed function can handle an empty posts array without errors, and that the generated RSS feed does not contain any <item> elements.


119-125: Properly testing for missing required fields

The test ensures that an error is thrown when a post is missing required fields, confirming that the function validates input data correctly.


99-105: Malformed posts.json error handling is appropriately tested

This test case validates that the function throws a meaningful error when posts.json is malformed, which is crucial for debugging and maintaining data integrity.


89-97: Effective testing of write operation failures

By providing an invalid output path, the test confirms that the function properly rejects and throws an error when the write operation fails, ensuring robust error handling.

Comment on lines 1 to 43
const mockRssData = {
blog: [
{
title: 'Non-Featured Post 1',
slug: '/blog/non-featured-post-1',
excerpt: 'This is a non-featured post',
date: '2024-07-05',
featured: false,
},
{
title: 'Test Post 1',
slug: '/blog/test-post-1',
excerpt: 'This is a featured test post',
date: '2024-07-07',
featured: true,
cover: '/img/test-cover.jpg',
},
{
title: 'Another Featured Post',
slug: '/blog/another-featured-post',
excerpt: 'This is another featured post',
date: '2024-07-06',
featured: true,
cover: '/img/test-cover.svg',
},
{
title: 'Non-Featured Post 2',
slug: '/blog/non-featured-post-2',
excerpt: 'This is another non-featured post',
date: '2024-07-03',
featured: false,
cover: '/img/test-cover.webp',
},
{
title: 'Non-Featured Post 3',
slug: '/blog/non-featured-post-3',
excerpt: 'This is yet another non-featured post',
date: '2024-07-04',
featured: false,
cover: '/img/test-cover.png',
},
],
};
Copy link

@coderabbitai coderabbitai bot Nov 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider enhancing test coverage with additional edge cases.

The mock data could be improved by:

  1. Using past dates instead of future dates to prevent test failures over time
  2. Including test cases with special characters in titles and excerpts
  3. Adding test cases with different date formats (ISO 8601, UTC, etc.)

Consider applying these changes:

 const mockRssData = {
   blog: [
     {
       title: 'Non-Featured Post 1',
       slug: '/blog/non-featured-post-1',
       excerpt: 'This is a non-featured post',
-      date: '2024-07-05',
+      date: '2023-07-05',
       featured: false,
     },
+    {
+      title: 'Post with Special Characters: & < > "',
+      slug: '/blog/special-chars',
+      excerpt: 'Testing HTML entities & encoding',
+      date: '2023-07-06T12:00:00Z',
+      featured: false,
+    },
     // ... rest of the entries with updated past dates
   ],
 };

Committable suggestion skipped: line range outside the PR's diff.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vishvamsinh28 Kindly apply this suggestion

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Comment on lines 62 to 64
if (invalidPosts.length > 0) {
throw new Error('Missing required fields in post data');
}
Copy link

@coderabbitai coderabbitai bot Nov 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Enhance error message to include missing post details

Including the titles or slugs of posts missing required fields in the error message aids in debugging and identifying problematic entries.

Apply this diff to improve the error message:

if (invalidPosts.length > 0) {
-   throw new Error('Missing required fields in post data');
+   throw new Error(`Missing required fields in posts: ${invalidPosts.map(p => p.title || p.slug).join(', ')}`);
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (invalidPosts.length > 0) {
throw new Error('Missing required fields in post data');
}
if (invalidPosts.length > 0) {
throw new Error(`Missing required fields in posts: ${invalidPosts.map(p => p.title || p.slug).join(', ')}`);
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vishvamsinh28 Kindly apply this suggestion

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment on lines +73 to +87
it('should set correct enclosure type based on image extension', async () => {
jest.doMock('../config/posts.json', () => mockRssData, { virtual: true });

await expect(rssFeed(type, title, desc, outputPath)).resolves.toBeUndefined()

const filePath = path.join(__dirname, '..', 'public', outputPath);
const fileContent = fs.readFileSync(filePath, 'utf8');

expect(fileContent).toContain('<enclosure url="https://www.asyncapi.com/img/test-cover.png"');
expect(fileContent).toContain('type="image/png"');
expect(fileContent).toContain('<enclosure url="https://www.asyncapi.com/img/test-cover.svg"');
expect(fileContent).toContain('type="image/svg+xml"');
expect(fileContent).toContain('<enclosure url="https://www.asyncapi.com/img/test-cover.webp"');
expect(fileContent).toContain('type="image/webp"');
});
Copy link

@coderabbitai coderabbitai bot Nov 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider using an XML parser instead of regex for parsing RSS feed

Parsing XML with regex can be brittle and may fail with valid XML that doesn't match the regex pattern. To improve robustness and maintainability, use an XML parser like fast-xml-parser or xml2js.

Example refactoring using fast-xml-parser:

+const { XMLParser } = require('fast-xml-parser');
+const parser = new XMLParser({ ignoreAttributes: false });

 // ...

 const fileContent = fs.readFileSync(filePath, 'utf8');
-const itemTitles = fileContent.match(/<title>(.*?)<\/title>/g);

+const parsedContent = parser.parse(fileContent);
+const items = parsedContent.rss.channel.item;

 expect(items[0].enclosure.url).toBe('https://www.asyncapi.com/img/test-cover.png');
 expect(items[0].enclosure.type).toBe('image/png');
 // Continue with other assertions

This approach enhances reliability and readability of your tests.

Committable suggestion skipped: line range outside the PR's diff.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vishvamsinh28 Kindly apply this suggestion

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vishvamsinh28 Have you made changes for this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

Comment on lines 7 to 24
const testOutputDir = path.join(__dirname, '..', 'public', 'test-output');
const outputPath = 'test-output/rss.xml';

beforeAll(() => {
if (!fs.existsSync(testOutputDir)) {
fs.mkdirSync(testOutputDir, { recursive: true });
}
});

afterAll(() => {
if (fs.existsSync(testOutputDir)) {
fs.readdirSync(testOutputDir).forEach(file => {
fs.unlinkSync(path.join(testOutputDir, file));
});
fs.rmdirSync(testOutputDir);
}
});

Copy link

@coderabbitai coderabbitai bot Nov 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider using asynchronous file operations in setup and teardown

In the beforeAll and afterAll hooks, synchronous file operations like fs.mkdirSync, fs.readdirSync, fs.unlinkSync, and fs.rmdirSync are used. While this is acceptable for small tests, using asynchronous versions can improve performance and prevent blocking the event loop.

You can refactor the setup and teardown to use asynchronous methods:

-beforeAll(() => {
-  if (!fs.existsSync(testOutputDir)) {
-    fs.mkdirSync(testOutputDir, { recursive: true });
-  }
-});
+beforeAll(async () => {
+  try {
+    await fs.promises.mkdir(testOutputDir, { recursive: true });
+  } catch (err) {
+    // Handle error if necessary
+  }
+});

-afterAll(() => {
-  if (fs.existsSync(testOutputDir)) {
-    fs.readdirSync(testOutputDir).forEach(file => {
-      fs.unlinkSync(path.join(testOutputDir, file));
-    });
-    fs.rmdirSync(testOutputDir);
-  }
-});
+afterAll(async () => {
+  try {
+    const files = await fs.promises.readdir(testOutputDir);
+    await Promise.all(files.map(file => fs.promises.unlink(path.join(testOutputDir, file))));
+    await fs.promises.rmdir(testOutputDir);
+  } catch (err) {
+    // Handle error if necessary
+  }
+});
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const testOutputDir = path.join(__dirname, '..', 'public', 'test-output');
const outputPath = 'test-output/rss.xml';
beforeAll(() => {
if (!fs.existsSync(testOutputDir)) {
fs.mkdirSync(testOutputDir, { recursive: true });
}
});
afterAll(() => {
if (fs.existsSync(testOutputDir)) {
fs.readdirSync(testOutputDir).forEach(file => {
fs.unlinkSync(path.join(testOutputDir, file));
});
fs.rmdirSync(testOutputDir);
}
});
const testOutputDir = path.join(__dirname, '..', 'public', 'test-output');
const outputPath = 'test-output/rss.xml';
beforeAll(async () => {
try {
await fs.promises.mkdir(testOutputDir, { recursive: true });
} catch (err) {
// Handle error if necessary
}
});
afterAll(async () => {
try {
const files = await fs.promises.readdir(testOutputDir);
await Promise.all(files.map(file => fs.promises.unlink(path.join(testOutputDir, file))));
await fs.promises.rmdir(testOutputDir);
} catch (err) {
// Handle error if necessary
}
});

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vishvamsinh28 Apply this suggestion if it doesn't breaks.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Outside diff range and nitpick comments (1)
package.json (1)

73-73: Consider upgrading fast-xml-parser to latest patch version.

While version 4.5.0 works, consider upgrading to the latest patch version (4.5.5) for potential bug fixes and security updates.

Apply this diff:

-    "fast-xml-parser": "^4.5.0",
+    "fast-xml-parser": "^4.5.5",
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 5407af0 and 1d13e0b.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (4)
  • package.json (1 hunks)
  • scripts/build-rss.js (2 hunks)
  • tests/build-rss.test.js (1 hunks)
  • tests/fixtures/rssData.js (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • scripts/build-rss.js
  • tests/build-rss.test.js
🔇 Additional comments (2)
tests/fixtures/rssData.js (1)

88-93: LGTM!

The configuration constants and exports are well-structured and include all necessary components.

package.json (1)

73-73: Verify the fast-xml-parser usage in the codebase.

The addition of fast-xml-parser as a dependency is appropriate for XML parsing needs in the RSS feed generation.

Let's verify its usage:

✅ Verification successful

Based on the search results, I can see that fast-xml-parser is used in tests/build-rss.test.js for parsing XML content in RSS feed tests. Let me verify if there are any other usages in the codebase:


Let me check the implementation of build-rss.js to fully understand how fast-xml-parser is used:


The fast-xml-parser dependency is only used in tests for validation purposes

The fast-xml-parser package is only used in tests/build-rss.test.js to parse and validate the XML output generated by build-rss.js. The actual RSS feed generation uses jgexml/json2xml package. The addition of fast-xml-parser as a dependency is appropriate and correctly scoped for testing purposes.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of fast-xml-parser in the codebase
# Expected: Usage in build-rss.js and related test files

# Test: Search for imports/requires of fast-xml-parser
rg -l "require.*fast-xml-parser|from.*fast-xml-parser"

# Test: Search for XMLParser usage (common class from this library)
rg "XMLParser|parse[^d]|validate|build"

Length of output: 219586


Script:

#!/bin/bash
# Search for the actual build-rss.js file to see its implementation
rg -l "build-rss"

# Get content of build-rss.js and test file
cat tests/build-rss.test.js

Length of output: 5997


Script:

#!/bin/bash
# Get content of build-rss.js implementation
cat scripts/build-rss.js

Length of output: 3431

Comment on lines +77 to +86
const incompletePostMockData = {
blog: [
{
slug: '/blog/incomplete-post',
excerpt: 'This post is incomplete',
date: '2024-07-05',
featured: false,
},
],
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Enhance incomplete post test cases and fix future date.

Two suggestions for improvement:

  1. Replace the future date with a past date
  2. Add more incomplete data scenarios
 const incompletePostMockData = {
   blog: [
     {
       slug: '/blog/incomplete-post',
       excerpt: 'This post is incomplete',
-      date: '2024-07-05',
+      date: '2023-07-05',
       featured: false,
     },
+    {
+      title: 'Missing Excerpt Post',
+      slug: '/blog/no-excerpt',
+      date: '2023-07-06',
+      featured: false,
+    },
+    {
+      title: 'Missing Slug Post',
+      excerpt: 'This post has no slug',
+      date: '2023-07-07',
+      featured: false,
+    },
   ],
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const incompletePostMockData = {
blog: [
{
slug: '/blog/incomplete-post',
excerpt: 'This post is incomplete',
date: '2024-07-05',
featured: false,
},
],
};
const incompletePostMockData = {
blog: [
{
slug: '/blog/incomplete-post',
excerpt: 'This post is incomplete',
date: '2023-07-05',
featured: false,
},
{
title: 'Missing Excerpt Post',
slug: '/blog/no-excerpt',
date: '2023-07-06',
featured: false,
},
{
title: 'Missing Slug Post',
excerpt: 'This post has no slug',
date: '2023-07-07',
featured: false,
},
],
};

Comment on lines +59 to +75
const missingDateMockData = {
blog: [
{
title: 'Post without Date',
slug: '/blog/no-date-post',
excerpt: 'This post is missing a date',
featured: false,
},
{
title: 'Valid Post',
slug: '/blog/valid-post',
excerpt: 'This post has a valid date',
date: '2024-07-05',
featured: true,
},
],
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Replace future dates with past dates to prevent test failures.

Using future dates in tests can cause failures when the date passes. Consider using past dates consistently.

     {
       title: 'Valid Post',
       slug: '/blog/valid-post',
       excerpt: 'This post has a valid date',
-      date: '2024-07-05',
+      date: '2023-07-05',
       featured: true,
     },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const missingDateMockData = {
blog: [
{
title: 'Post without Date',
slug: '/blog/no-date-post',
excerpt: 'This post is missing a date',
featured: false,
},
{
title: 'Valid Post',
slug: '/blog/valid-post',
excerpt: 'This post has a valid date',
date: '2024-07-05',
featured: true,
},
],
};
const missingDateMockData = {
blog: [
{
title: 'Post without Date',
slug: '/blog/no-date-post',
excerpt: 'This post is missing a date',
featured: false,
},
{
title: 'Valid Post',
slug: '/blog/valid-post',
excerpt: 'This post has a valid date',
date: '2023-07-05',
featured: true,
},
],
};

Comment on lines +1 to +57
const mockRssData = {
blog: [
{
title: 'Non-Featured Post 1',
slug: '/blog/non-featured-post-1',
excerpt: 'This is a non-featured post',
date: '2023-07-05',
featured: false,
},
{
title: 'Test Post 1',
slug: '/blog/test-post-1',
excerpt: 'This is a featured test post',
date: '2023-07-07',
featured: true,
cover: '/img/test-cover.jpg',
},
{
title: 'Another Featured Post',
slug: '/blog/another-featured-post',
excerpt: 'This is another featured post',
date: '2023-07-06',
featured: true,
cover: '/img/test-cover.svg',
},
{
title: 'Non-Featured Post 2',
slug: '/blog/non-featured-post-2',
excerpt: 'This is another non-featured post',
date: '2023-07-03',
featured: false,
cover: '/img/test-cover.webp',
},
{
title: 'Non-Featured Post 3',
slug: '/blog/non-featured-post-3',
excerpt: 'This is yet another non-featured post',
date: '2023-07-04',
featured: false,
cover: '/img/test-cover.png',
},
{
title: 'Post with Special Characters: & < > "',
slug: '/blog/special-chars',
excerpt: 'Testing HTML entities & encoding',
date: '2023-07-06T12:00:00Z',
featured: false,
},
{
title: 'Post with UTC Date Format',
slug: '/blog/utc-date-format',
excerpt: 'This post uses a UTC date format',
date: 'Wed, 05 Jul 2023 12:00:00 GMT',
featured: false,
},
],
};
Copy link

@coderabbitai coderabbitai bot Nov 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider adding more edge cases to strengthen test coverage.

The mock data has good variety including special characters, different date formats, and image types. Consider enhancing it with these additional edge cases:

  • Empty strings for title/excerpt
  • Very long text content
  • International characters (UTF-8)
  • Malformed URLs in slug/cover
 const mockRssData = {
   blog: [
+    {
+      title: '',  // Empty title edge case
+      slug: '/blog/empty-title',
+      excerpt: 'Testing empty title handling',
+      date: '2023-07-01',
+      featured: false,
+    },
+    {
+      title: '国际化标题 - インターナショナル',  // International characters
+      slug: '/blog/international',
+      excerpt: '测试国际化内容 - テスト',
+      date: '2023-07-02',
+      featured: false,
+    },
+    {
+      title: 'Malformed URL Test',
+      slug: '/blog/bad url#$%^',  // Invalid URL characters
+      excerpt: 'Testing URL handling',
+      date: '2023-07-03',
+      featured: false,
+      cover: 'invalid://cover.jpg',
+    },
     // ... existing entries
   ],
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const mockRssData = {
blog: [
{
title: 'Non-Featured Post 1',
slug: '/blog/non-featured-post-1',
excerpt: 'This is a non-featured post',
date: '2023-07-05',
featured: false,
},
{
title: 'Test Post 1',
slug: '/blog/test-post-1',
excerpt: 'This is a featured test post',
date: '2023-07-07',
featured: true,
cover: '/img/test-cover.jpg',
},
{
title: 'Another Featured Post',
slug: '/blog/another-featured-post',
excerpt: 'This is another featured post',
date: '2023-07-06',
featured: true,
cover: '/img/test-cover.svg',
},
{
title: 'Non-Featured Post 2',
slug: '/blog/non-featured-post-2',
excerpt: 'This is another non-featured post',
date: '2023-07-03',
featured: false,
cover: '/img/test-cover.webp',
},
{
title: 'Non-Featured Post 3',
slug: '/blog/non-featured-post-3',
excerpt: 'This is yet another non-featured post',
date: '2023-07-04',
featured: false,
cover: '/img/test-cover.png',
},
{
title: 'Post with Special Characters: & < > "',
slug: '/blog/special-chars',
excerpt: 'Testing HTML entities & encoding',
date: '2023-07-06T12:00:00Z',
featured: false,
},
{
title: 'Post with UTC Date Format',
slug: '/blog/utc-date-format',
excerpt: 'This post uses a UTC date format',
date: 'Wed, 05 Jul 2023 12:00:00 GMT',
featured: false,
},
],
};
const mockRssData = {
blog: [
{
title: '', // Empty title edge case
slug: '/blog/empty-title',
excerpt: 'Testing empty title handling',
date: '2023-07-01',
featured: false,
},
{
title: '国际化标题 - インターナショナル', // International characters
slug: '/blog/international',
excerpt: '测试国际化内容 - テスト',
date: '2023-07-02',
featured: false,
},
{
title: 'Malformed URL Test',
slug: '/blog/bad url#$%^', // Invalid URL characters
excerpt: 'Testing URL handling',
date: '2023-07-03',
featured: false,
cover: 'invalid://cover.jpg',
},
{
title: 'Non-Featured Post 1',
slug: '/blog/non-featured-post-1',
excerpt: 'This is a non-featured post',
date: '2023-07-05',
featured: false,
},
{
title: 'Test Post 1',
slug: '/blog/test-post-1',
excerpt: 'This is a featured test post',
date: '2023-07-07',
featured: true,
cover: '/img/test-cover.jpg',
},
{
title: 'Another Featured Post',
slug: '/blog/another-featured-post',
excerpt: 'This is another featured post',
date: '2023-07-06',
featured: true,
cover: '/img/test-cover.svg',
},
{
title: 'Non-Featured Post 2',
slug: '/blog/non-featured-post-2',
excerpt: 'This is another non-featured post',
date: '2023-07-03',
featured: false,
cover: '/img/test-cover.webp',
},
{
title: 'Non-Featured Post 3',
slug: '/blog/non-featured-post-3',
excerpt: 'This is yet another non-featured post',
date: '2023-07-04',
featured: false,
cover: '/img/test-cover.png',
},
{
title: 'Post with Special Characters: & < > "',
slug: '/blog/special-chars',
excerpt: 'Testing HTML entities & encoding',
date: '2023-07-06T12:00:00Z',
featured: false,
},
{
title: 'Post with UTC Date Format',
slug: '/blog/utc-date-format',
excerpt: 'This post uses a UTC date format',
date: 'Wed, 05 Jul 2023 12:00:00 GMT',
featured: false,
},
],
};

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These cases will not occur.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@akshatnema, understood. Thank you for the clarification.


✏️ Learnings added
Learnt from: akshatnema
PR: asyncapi/website#3101
File: tests/fixtures/rssData.js:1-57
Timestamp: 2024-11-01T13:32:15.167Z
Learning: In the `tests/fixtures/rssData.js` file of the `@asyncapi/website` project, tests for edge cases such as empty strings for title or excerpt, very long text content, international characters (UTF-8), or malformed URLs in `slug` or `cover` are not necessary because these cases will not occur.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Copy link

@coderabbitai coderabbitai bot left a 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 (4)
tests/fixtures/rssData.js (2)

1-27: Consider refactoring for better maintainability.

The function could be more concise and maintainable:

  1. Handle cover consistently with other properties
  2. Use object spread for cleaner code
 function createMockPost({
   title,
   slug,
   excerpt,
   date,
   featured,
   cover,
 } = {}, useDefaults = true) {
-  const post = {};
+  if (useDefaults) {
+    return {
+      title: title ?? 'Default Post Title',
+      slug: slug ?? '/blog/default-post',
+      excerpt: excerpt ?? 'This is a default excerpt',
+      date: date ?? '2023-07-01',
+      featured: featured ?? false,
+      ...(cover !== undefined && { cover }),
+    };
+  }
 
-  if (useDefaults) {
-    post.title = title ?? 'Default Post Title';
-    post.slug = slug ?? '/blog/default-post';
-    post.excerpt = excerpt ?? 'This is a default excerpt';
-    post.date = date ?? new Date().toISOString();
-    post.featured = featured ?? false;
-  } else {
-    if (title !== undefined) post.title = title;
-    if (slug !== undefined) post.slug = slug;
-    if (excerpt !== undefined) post.excerpt = excerpt;
-    if (date !== undefined) post.date = date;
-    if (featured !== undefined) post.featured = featured;
-  }
-
-  if (cover !== undefined) post.cover = cover;
-  return post;
+  return {
+    ...(title !== undefined && { title }),
+    ...(slug !== undefined && { slug }),
+    ...(excerpt !== undefined && { excerpt }),
+    ...(date !== undefined && { date }),
+    ...(featured !== undefined && { featured }),
+    ...(cover !== undefined && { cover }),
+  };
 }

37-40: Fix trailing comma style.

Remove the trailing comma to comply with the project's style guidelines.

 module.exports = {
   createMockPost,
-  createMockData,
+  createMockData
 };
🧰 Tools
🪛 eslint

[error] 39-39: Delete ,

(prettier/prettier)

tests/build-rss.test.js (2)

26-108: Test coverage looks good, consider adding a few more edge cases.

The current test suite is well-structured with good coverage of main scenarios. Consider adding these additional test cases:

  1. Malformed XML validation
  2. Invalid file path handling
  3. Network-related issues with cover images

Example test case for malformed XML validation:

it('should generate valid XML output', async () => {
  const mockData = createMockData({
    blogPosts: [
      { title: 'Post with Special Characters & <>', slug: '/blog/special', date: '2023-07-05', featured: true },
    ],
  });

  jest.doMock('../config/posts.json', () => mockData, { virtual: true });

  await expect(rssFeed('blog', 'Test Blog RSS', 'Test blog RSS feed', outputPath)).resolves.toBeUndefined();

  const filePath = path.join(__dirname, '..', 'public', outputPath);
  const fileContent = fs.readFileSync(filePath, 'utf8');
  
  // This will throw if XML is malformed
  expect(() => parser.parse(fileContent)).not.toThrow();
});
🧰 Tools
🪛 eslint

[error] 106-106: Replace 'Missing·required·fields' with ⏎······'Missing·required·fields'⏎····

(prettier/prettier)


106-106: Minor formatting improvement needed.

Update the line to match the project's formatting rules:

-    await expect(rssFeed('blog', 'Test Blog RSS', 'Test blog RSS feed', outputPath)).rejects.toThrow('Missing required fields');
+    await expect(rssFeed('blog', 'Test Blog RSS', 'Test blog RSS feed', outputPath)).rejects.toThrow(
+      'Missing required fields'
+    );
🧰 Tools
🪛 eslint

[error] 106-106: Replace 'Missing·required·fields' with ⏎······'Missing·required·fields'⏎····

(prettier/prettier)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 1d13e0b and db84460.

📒 Files selected for processing (2)
  • tests/build-rss.test.js (1 hunks)
  • tests/fixtures/rssData.js (1 hunks)
🧰 Additional context used
📓 Learnings (1)
tests/build-rss.test.js (1)
Learnt from: akshatnema
PR: asyncapi/website#3101
File: tests/build-rss.test.js:25-27
Timestamp: 2024-11-01T09:55:20.531Z
Learning: In `tests/build-rss.test.js`, replacing `jest.resetModules()` with `jest.resetAllMocks()` in the `afterEach()` block causes errors. It is necessary to use `jest.resetModules()` to reset the module registry between tests in this file.
🪛 eslint
tests/build-rss.test.js

[error] 106-106: Replace 'Missing·required·fields' with ⏎······'Missing·required·fields'⏎····

(prettier/prettier)

tests/fixtures/rssData.js

[error] 39-39: Delete ,

(prettier/prettier)

🔇 Additional comments (3)
tests/fixtures/rssData.js (1)

29-35: LGTM!

The function is well-structured and correctly implements the mock data generation logic.

tests/build-rss.test.js (2)

1-7: LGTM! Well-structured imports and parser configuration.

The imports are complete and the XMLParser is properly configured to handle RSS feed attributes.


8-24: LGTM! Well-implemented test suite setup and teardown.

  • Proper use of async/await for file operations
  • Correct cleanup of test files
  • Appropriate use of jest.resetModules() as required for this test suite

post.title = title ?? 'Default Post Title';
post.slug = slug ?? '/blog/default-post';
post.excerpt = excerpt ?? 'This is a default excerpt';
post.date = date ?? new Date().toISOString();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Replace dynamic default date with a static one.

Using new Date().toISOString() as a default value makes tests non-deterministic and could cause failures over time. Consider using a static past date instead.

-    post.date = date ?? new Date().toISOString();
+    post.date = date ?? '2023-07-01';
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
post.date = date ?? new Date().toISOString();
post.date = date ?? '2023-07-01';

package.json Outdated
@@ -70,6 +70,7 @@
"clsx": "^2.1.0",
"cssnano": "^6.0.3",
"dotenv": "^16.4.4",
"fast-xml-parser": "^4.5.0",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be pushed to devDependencies?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@akshatnema
Copy link
Member

@coderabbitai review

Copy link

coderabbitai bot commented Nov 4, 2024

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a 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-rss.test.js (3)

1-6: Reorder imports for better organization.

Consider reordering the imports following the convention: built-in modules, then external modules, then local modules.

 const fs = require('fs');
 const path = require('path');
+const { XMLParser } = require('fast-xml-parser');
 const rssFeed = require('../scripts/build-rss');
-const { XMLParser } = require('fast-xml-parser');
 const parser = new XMLParser({ ignoreAttributes: false });
 const { mockRssData, title, type, desc, missingDateMockData, incompletePostMockData } = require('./fixtures/rssData');
🧰 Tools
🪛 eslint

[error] 4-4: Expected 1 empty line after require statement not followed by another require.

(import/newline-after-import)


[error] 4-4: fast-xml-parser import should occur before import of ../scripts/build-rss

(import/order)


85-99: Use XML parser for enclosure assertions.

For consistency with other tests and more reliable XML parsing, consider using the XML parser instead of string matching.

 const fileContent = fs.readFileSync(filePath, 'utf8');
+const parsedContent = parser.parse(fileContent);
+const items = parsedContent.rss.channel.item;
 
-expect(fileContent).toContain('<enclosure url="https://www.asyncapi.com/img/test-cover.png"');
-expect(fileContent).toContain('type="image/png"');
+expect(items[0].enclosure.url).toBe('https://www.asyncapi.com/img/test-cover.png');
+expect(items[0].enclosure.type).toBe('image/png');
 // Apply similar changes for other assertions
🧰 Tools
🪛 eslint

[error] 85-85: 'it' is not defined.

(no-undef)


[error] 86-86: 'jest' is not defined.

(no-undef)


[error] 88-88: Insert ;

(prettier/prettier)


34-145: Address formatting inconsistencies.

There are several formatting issues that should be addressed:

  • Missing semicolons (lines 38, 78, 88, 123)
  • Inconsistent string quotes (line 104)
  • Extra whitespace and newlines

Consider running Prettier to automatically fix these formatting issues.

🧰 Tools
🪛 eslint

[error] 34-34: 'it' is not defined.

(no-undef)


[error] 35-36: Delete ⏎····

(prettier/prettier)


[error] 36-36: 'jest' is not defined.

(no-undef)


[error] 38-38: Insert ;

(prettier/prettier)


[error] 46-46: 'it' is not defined.

(no-undef)


[error] 47-47: 'jest' is not defined.

(no-undef)


[error] 48-48: Delete ··

(prettier/prettier)


[error] 50-50: Delete ··

(prettier/prettier)


[error] 53-53: Delete ··

(prettier/prettier)


[error] 55-55: Replace item with (item)

(prettier/prettier)


[error] 56-56: Delete ··

(prettier/prettier)


[error] 59-59: Delete ··

(prettier/prettier)


[error] 65-65: Delete ··

(prettier/prettier)


[error] 66-66: 'it' is not defined.

(no-undef)


[error] 67-67: 'jest' is not defined.

(no-undef)


[error] 68-68: Delete ··

(prettier/prettier)


[error] 70-70: Delete ··

(prettier/prettier)


[error] 73-73: Delete ··

(prettier/prettier)


[error] 75-75: Replace item with (item)

(prettier/prettier)


[error] 76-76: Delete ··

(prettier/prettier)


[error] 78-78: Insert ;

(prettier/prettier)


[error] 85-85: 'it' is not defined.

(no-undef)


[error] 86-86: 'jest' is not defined.

(no-undef)


[error] 88-88: Insert ;

(prettier/prettier)


[error] 101-101: 'it' is not defined.

(no-undef)


[error] 102-102: 'jest' is not defined.

(no-undef)


[error] 104-104: Replace "invalid/path" with 'invalid/path'

(prettier/prettier)


[error] 106-107: Delete

(prettier/prettier)


[error] 110-110: 'it' is not defined.

(no-undef)


[error] 111-111: 'jest' is not defined.

(no-undef)


[error] 111-111: Replace '../config/posts.json', with ⏎······'../config/posts.json',⏎·····

(prettier/prettier)


[error] 112-112: Insert ··

(prettier/prettier)


[error] 113-113: Replace },·{·virtual:·true·} with ··},⏎······{·virtual:·true·}⏎····

(prettier/prettier)


[error] 116-117: Delete

(prettier/prettier)


[error] 119-119: 'it' is not defined.

(no-undef)


[error] 121-121: 'jest' is not defined.

(no-undef)


[error] 123-123: Insert ;

(prettier/prettier)


[error] 131-131: 'it' is not defined.

(no-undef)


[error] 131-132: Delete

(prettier/prettier)


[error] 133-133: 'jest' is not defined.

(no-undef)


[error] 136-137: Delete

(prettier/prettier)


[error] 139-139: 'it' is not defined.

(no-undef)


[error] 139-140: Delete

(prettier/prettier)


[error] 141-141: 'jest' is not defined.

(no-undef)


[error] 143-144: Replace 'Failed·to·generate·RSS·feed:·Missing·date·in·posts:·Post·without·Date');⏎ with ⏎······'Failed·to·generate·RSS·feed:·Missing·date·in·posts:·Post·without·Date'⏎····);

(prettier/prettier)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between db84460 and 02d5c07.

📒 Files selected for processing (2)
  • package.json (1 hunks)
  • tests/build-rss.test.js (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • package.json
🧰 Additional context used
📓 Learnings (1)
tests/build-rss.test.js (1)
Learnt from: akshatnema
PR: asyncapi/website#3101
File: tests/build-rss.test.js:25-27
Timestamp: 2024-11-01T09:55:20.531Z
Learning: In `tests/build-rss.test.js`, replacing `jest.resetModules()` with `jest.resetAllMocks()` in the `afterEach()` block causes errors. It is necessary to use `jest.resetModules()` to reset the module registry between tests in this file.
🪛 eslint
tests/build-rss.test.js

[error] 4-4: Expected 1 empty line after require statement not followed by another require.

(import/newline-after-import)


[error] 4-4: fast-xml-parser import should occur before import of ../scripts/build-rss

(import/order)


[error] 8-8: 'describe' is not defined.

(no-undef)


[error] 12-12: 'beforeAll' is not defined.

(no-undef)


[error] 20-20: 'afterAll' is not defined.

(no-undef)


[error] 23-23: Replace file with (file)

(prettier/prettier)


[error] 30-30: 'afterEach' is not defined.

(no-undef)


[error] 31-31: 'jest' is not defined.

(no-undef)


[error] 34-34: 'it' is not defined.

(no-undef)


[error] 35-36: Delete ⏎····

(prettier/prettier)


[error] 36-36: 'jest' is not defined.

(no-undef)


[error] 38-38: Insert ;

(prettier/prettier)


[error] 46-46: 'it' is not defined.

(no-undef)


[error] 47-47: 'jest' is not defined.

(no-undef)


[error] 48-48: Delete ··

(prettier/prettier)


[error] 50-50: Delete ··

(prettier/prettier)


[error] 53-53: Delete ··

(prettier/prettier)


[error] 55-55: Replace item with (item)

(prettier/prettier)


[error] 56-56: Delete ··

(prettier/prettier)


[error] 59-59: Delete ··

(prettier/prettier)


[error] 65-65: Delete ··

(prettier/prettier)


[error] 66-66: 'it' is not defined.

(no-undef)


[error] 67-67: 'jest' is not defined.

(no-undef)


[error] 68-68: Delete ··

(prettier/prettier)


[error] 70-70: Delete ··

(prettier/prettier)


[error] 73-73: Delete ··

(prettier/prettier)


[error] 75-75: Replace item with (item)

(prettier/prettier)


[error] 76-76: Delete ··

(prettier/prettier)


[error] 78-78: Insert ;

(prettier/prettier)


[error] 85-85: 'it' is not defined.

(no-undef)


[error] 86-86: 'jest' is not defined.

(no-undef)


[error] 88-88: Insert ;

(prettier/prettier)


[error] 101-101: 'it' is not defined.

(no-undef)


[error] 102-102: 'jest' is not defined.

(no-undef)


[error] 104-104: Replace "invalid/path" with 'invalid/path'

(prettier/prettier)


[error] 106-107: Delete

(prettier/prettier)


[error] 110-110: 'it' is not defined.

(no-undef)


[error] 111-111: 'jest' is not defined.

(no-undef)


[error] 111-111: Replace '../config/posts.json', with ⏎······'../config/posts.json',⏎·····

(prettier/prettier)


[error] 112-112: Insert ··

(prettier/prettier)


[error] 113-113: Replace },·{·virtual:·true·} with ··},⏎······{·virtual:·true·}⏎····

(prettier/prettier)


[error] 116-117: Delete

(prettier/prettier)


[error] 119-119: 'it' is not defined.

(no-undef)


[error] 121-121: 'jest' is not defined.

(no-undef)


[error] 123-123: Insert ;

(prettier/prettier)


[error] 131-131: 'it' is not defined.

(no-undef)


[error] 131-132: Delete

(prettier/prettier)


[error] 133-133: 'jest' is not defined.

(no-undef)


[error] 136-137: Delete

(prettier/prettier)


[error] 139-139: 'it' is not defined.

(no-undef)


[error] 139-140: Delete

(prettier/prettier)


[error] 141-141: 'jest' is not defined.

(no-undef)


[error] 143-144: Replace 'Failed·to·generate·RSS·feed:·Missing·date·in·posts:·Post·without·Date');⏎ with ⏎······'Failed·to·generate·RSS·feed:·Missing·date·in·posts:·Post·without·Date'⏎····);

(prettier/prettier)

🔇 Additional comments (2)
tests/build-rss.test.js (2)

8-32: LGTM! Well-structured test setup and teardown.

The implementation follows best practices:

  • Uses async file operations with proper error handling
  • Ensures proper cleanup of test files
  • Correctly uses jest.resetModules() to reset the module registry between tests
🧰 Tools
🪛 eslint

[error] 8-8: 'describe' is not defined.

(no-undef)


[error] 12-12: 'beforeAll' is not defined.

(no-undef)


[error] 20-20: 'afterAll' is not defined.

(no-undef)


[error] 23-23: Replace file with (file)

(prettier/prettier)


[error] 30-30: 'afterEach' is not defined.

(no-undef)


[error] 31-31: 'jest' is not defined.

(no-undef)


34-145: LGTM! Comprehensive test coverage.

The test suite provides excellent coverage of both happy paths and error cases:

  • Validates RSS feed generation and file writing
  • Tests post prioritization and sorting
  • Handles various error scenarios
  • Verifies enclosure types
  • Tests empty posts and missing fields
🧰 Tools
🪛 eslint

[error] 34-34: 'it' is not defined.

(no-undef)


[error] 35-36: Delete ⏎····

(prettier/prettier)


[error] 36-36: 'jest' is not defined.

(no-undef)


[error] 38-38: Insert ;

(prettier/prettier)


[error] 46-46: 'it' is not defined.

(no-undef)


[error] 47-47: 'jest' is not defined.

(no-undef)


[error] 48-48: Delete ··

(prettier/prettier)


[error] 50-50: Delete ··

(prettier/prettier)


[error] 53-53: Delete ··

(prettier/prettier)


[error] 55-55: Replace item with (item)

(prettier/prettier)


[error] 56-56: Delete ··

(prettier/prettier)


[error] 59-59: Delete ··

(prettier/prettier)


[error] 65-65: Delete ··

(prettier/prettier)


[error] 66-66: 'it' is not defined.

(no-undef)


[error] 67-67: 'jest' is not defined.

(no-undef)


[error] 68-68: Delete ··

(prettier/prettier)


[error] 70-70: Delete ··

(prettier/prettier)


[error] 73-73: Delete ··

(prettier/prettier)


[error] 75-75: Replace item with (item)

(prettier/prettier)


[error] 76-76: Delete ··

(prettier/prettier)


[error] 78-78: Insert ;

(prettier/prettier)


[error] 85-85: 'it' is not defined.

(no-undef)


[error] 86-86: 'jest' is not defined.

(no-undef)


[error] 88-88: Insert ;

(prettier/prettier)


[error] 101-101: 'it' is not defined.

(no-undef)


[error] 102-102: 'jest' is not defined.

(no-undef)


[error] 104-104: Replace "invalid/path" with 'invalid/path'

(prettier/prettier)


[error] 106-107: Delete

(prettier/prettier)


[error] 110-110: 'it' is not defined.

(no-undef)


[error] 111-111: 'jest' is not defined.

(no-undef)


[error] 111-111: Replace '../config/posts.json', with ⏎······'../config/posts.json',⏎·····

(prettier/prettier)


[error] 112-112: Insert ··

(prettier/prettier)


[error] 113-113: Replace },·{·virtual:·true·} with ··},⏎······{·virtual:·true·}⏎····

(prettier/prettier)


[error] 116-117: Delete

(prettier/prettier)


[error] 119-119: 'it' is not defined.

(no-undef)


[error] 121-121: 'jest' is not defined.

(no-undef)


[error] 123-123: Insert ;

(prettier/prettier)


[error] 131-131: 'it' is not defined.

(no-undef)


[error] 131-132: Delete

(prettier/prettier)


[error] 133-133: 'jest' is not defined.

(no-undef)


[error] 136-137: Delete

(prettier/prettier)


[error] 139-139: 'it' is not defined.

(no-undef)


[error] 139-140: Delete

(prettier/prettier)


[error] 141-141: 'jest' is not defined.

(no-undef)


[error] 143-144: Replace 'Failed·to·generate·RSS·feed:·Missing·date·in·posts:·Post·without·Date');⏎ with ⏎······'Failed·to·generate·RSS·feed:·Missing·date·in·posts:·Post·without·Date'⏎····);

(prettier/prettier)

Copy link

@coderabbitai coderabbitai bot left a 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-rss.test.js (3)

1-6: Reorder imports following convention.

The imports should be ordered as: built-in modules, external dependencies, and then local modules.

 const fs = require('fs');
 const path = require('path');
+const { XMLParser } = require('fast-xml-parser');
 const rssFeed = require('../scripts/build-rss');
-const { XMLParser } = require('fast-xml-parser');
 const parser = new XMLParser({ ignoreAttributes: false });
 const { mockRssData, title, type, desc, missingDateMockData, incompletePostMockData } = require('./fixtures/rssData');
🧰 Tools
🪛 eslint

[error] 4-4: Expected 1 empty line after require statement not followed by another require.

(import/newline-after-import)


[error] 4-4: fast-xml-parser import should occur before import of ../scripts/build-rss

(import/order)


34-146: Comprehensive test coverage with room for improvement.

The test suite covers essential scenarios including:

  • Basic RSS feed generation
  • Featured posts prioritization
  • Date-based sorting
  • Error handling
  • Edge cases

However, there's inconsistency in XML content validation.

Consider using the XML parser consistently across all tests, particularly in the enclosure type test:

 it('should set correct enclosure type based on image extension', async () => {
   jest.doMock('../config/posts.json', () => mockRssData, { virtual: true });

   await expect(rssFeed(type, title, desc, outputPath)).resolves.toBeUndefined();

   const filePath = path.join(__dirname, '..', 'public', outputPath);
   const fileContent = fs.readFileSync(filePath, 'utf8');
+  const parsedContent = parser.parse(fileContent);
+  const items = parsedContent.rss.channel.item;

-  expect(fileContent).toContain('<enclosure url="https://www.asyncapi.com/img/test-cover.png"');
-  expect(fileContent).toContain('type="image/png"');
+  expect(items[0].enclosure.url).toBe('https://www.asyncapi.com/img/test-cover.png');
+  expect(items[0].enclosure.type).toBe('image/png');
   // Apply similar changes for other enclosure assertions
 });
🧰 Tools
🪛 eslint

[error] 34-34: 'it' is not defined.

(no-undef)


[error] 35-36: Delete ⏎····

(prettier/prettier)


[error] 36-36: 'jest' is not defined.

(no-undef)


[error] 38-38: Insert ;

(prettier/prettier)


[error] 46-46: 'it' is not defined.

(no-undef)


[error] 47-47: 'jest' is not defined.

(no-undef)


[error] 48-48: Delete ··

(prettier/prettier)


[error] 50-50: Delete ··

(prettier/prettier)


[error] 53-53: Delete ··

(prettier/prettier)


[error] 55-55: Replace item with (item)

(prettier/prettier)


[error] 56-56: Delete ··

(prettier/prettier)


[error] 59-59: Delete ··

(prettier/prettier)


[error] 65-65: Delete ··

(prettier/prettier)


[error] 66-66: 'it' is not defined.

(no-undef)


[error] 67-67: 'jest' is not defined.

(no-undef)


[error] 68-68: Delete ··

(prettier/prettier)


[error] 70-70: Delete ··

(prettier/prettier)


[error] 73-73: Delete ··

(prettier/prettier)


[error] 75-75: Replace item with (item)

(prettier/prettier)


[error] 76-76: Delete ··

(prettier/prettier)


[error] 78-78: Insert ;

(prettier/prettier)


[error] 85-85: 'it' is not defined.

(no-undef)


[error] 86-86: 'jest' is not defined.

(no-undef)


[error] 88-88: Insert ;

(prettier/prettier)


[error] 101-101: 'it' is not defined.

(no-undef)


[error] 102-102: 'jest' is not defined.

(no-undef)


[error] 104-104: Replace "invalid/path" with 'invalid/path'

(prettier/prettier)


[error] 106-107: Delete

(prettier/prettier)


[error] 110-110: 'it' is not defined.

(no-undef)


[error] 111-111: 'jest' is not defined.

(no-undef)


[error] 111-111: Replace '../config/posts.json', with ⏎······'../config/posts.json',⏎·····

(prettier/prettier)


[error] 112-112: Insert ··

(prettier/prettier)


[error] 113-113: Replace ····},·{·virtual:·true·} with ······},⏎······{·virtual:·true·}⏎····

(prettier/prettier)


[error] 115-116: Delete

(prettier/prettier)


[error] 119-119: 'it' is not defined.

(no-undef)


[error] 121-121: 'jest' is not defined.

(no-undef)


[error] 123-123: Insert ;

(prettier/prettier)


[error] 131-131: 'it' is not defined.

(no-undef)


[error] 132-133: Delete

(prettier/prettier)


[error] 133-133: 'jest' is not defined.

(no-undef)


[error] 136-137: Delete

(prettier/prettier)


[error] 139-139: 'it' is not defined.

(no-undef)


[error] 139-140: Delete

(prettier/prettier)


[error] 141-141: 'jest' is not defined.

(no-undef)


[error] 143-143: Replace 'Failed·to·generate·RSS·feed:·Missing·date·in·posts:·Post·without·Date' with ⏎······'Failed·to·generate·RSS·feed:·Missing·date·in·posts:·Post·without·Date'⏎····

(prettier/prettier)


[error] 144-146: Replace ⏎··});⏎·· with ··});

(prettier/prettier)


1-146: Run prettier to fix formatting issues.

There are several formatting inconsistencies flagged by the linter:

  • Missing semicolons
  • Inconsistent quote usage
  • Extra whitespace

Run the project's formatter to fix these issues:

npm run format
# or
yarn format
🧰 Tools
🪛 eslint

[error] 4-4: Expected 1 empty line after require statement not followed by another require.

(import/newline-after-import)


[error] 4-4: fast-xml-parser import should occur before import of ../scripts/build-rss

(import/order)


[error] 8-8: 'describe' is not defined.

(no-undef)


[error] 12-12: 'beforeAll' is not defined.

(no-undef)


[error] 20-20: 'afterAll' is not defined.

(no-undef)


[error] 23-23: Replace file with (file)

(prettier/prettier)


[error] 30-30: 'afterEach' is not defined.

(no-undef)


[error] 31-31: 'jest' is not defined.

(no-undef)


[error] 34-34: 'it' is not defined.

(no-undef)


[error] 35-36: Delete ⏎····

(prettier/prettier)


[error] 36-36: 'jest' is not defined.

(no-undef)


[error] 38-38: Insert ;

(prettier/prettier)


[error] 46-46: 'it' is not defined.

(no-undef)


[error] 47-47: 'jest' is not defined.

(no-undef)


[error] 48-48: Delete ··

(prettier/prettier)


[error] 50-50: Delete ··

(prettier/prettier)


[error] 53-53: Delete ··

(prettier/prettier)


[error] 55-55: Replace item with (item)

(prettier/prettier)


[error] 56-56: Delete ··

(prettier/prettier)


[error] 59-59: Delete ··

(prettier/prettier)


[error] 65-65: Delete ··

(prettier/prettier)


[error] 66-66: 'it' is not defined.

(no-undef)


[error] 67-67: 'jest' is not defined.

(no-undef)


[error] 68-68: Delete ··

(prettier/prettier)


[error] 70-70: Delete ··

(prettier/prettier)


[error] 73-73: Delete ··

(prettier/prettier)


[error] 75-75: Replace item with (item)

(prettier/prettier)


[error] 76-76: Delete ··

(prettier/prettier)


[error] 78-78: Insert ;

(prettier/prettier)


[error] 85-85: 'it' is not defined.

(no-undef)


[error] 86-86: 'jest' is not defined.

(no-undef)


[error] 88-88: Insert ;

(prettier/prettier)


[error] 101-101: 'it' is not defined.

(no-undef)


[error] 102-102: 'jest' is not defined.

(no-undef)


[error] 104-104: Replace "invalid/path" with 'invalid/path'

(prettier/prettier)


[error] 106-107: Delete

(prettier/prettier)


[error] 110-110: 'it' is not defined.

(no-undef)


[error] 111-111: 'jest' is not defined.

(no-undef)


[error] 111-111: Replace '../config/posts.json', with ⏎······'../config/posts.json',⏎·····

(prettier/prettier)


[error] 112-112: Insert ··

(prettier/prettier)


[error] 113-113: Replace ····},·{·virtual:·true·} with ······},⏎······{·virtual:·true·}⏎····

(prettier/prettier)


[error] 115-116: Delete

(prettier/prettier)


[error] 119-119: 'it' is not defined.

(no-undef)


[error] 121-121: 'jest' is not defined.

(no-undef)


[error] 123-123: Insert ;

(prettier/prettier)


[error] 131-131: 'it' is not defined.

(no-undef)


[error] 132-133: Delete

(prettier/prettier)


[error] 133-133: 'jest' is not defined.

(no-undef)


[error] 136-137: Delete

(prettier/prettier)


[error] 139-139: 'it' is not defined.

(no-undef)


[error] 139-140: Delete

(prettier/prettier)


[error] 141-141: 'jest' is not defined.

(no-undef)


[error] 143-143: Replace 'Failed·to·generate·RSS·feed:·Missing·date·in·posts:·Post·without·Date' with ⏎······'Failed·to·generate·RSS·feed:·Missing·date·in·posts:·Post·without·Date'⏎····

(prettier/prettier)


[error] 144-146: Replace ⏎··});⏎·· with ··});

(prettier/prettier)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 02d5c07 and d9ce3ab.

📒 Files selected for processing (1)
  • tests/build-rss.test.js (1 hunks)
🧰 Additional context used
📓 Learnings (1)
tests/build-rss.test.js (1)
Learnt from: akshatnema
PR: asyncapi/website#3101
File: tests/build-rss.test.js:25-27
Timestamp: 2024-11-01T09:55:20.531Z
Learning: In `tests/build-rss.test.js`, replacing `jest.resetModules()` with `jest.resetAllMocks()` in the `afterEach()` block causes errors. It is necessary to use `jest.resetModules()` to reset the module registry between tests in this file.
🪛 eslint
tests/build-rss.test.js

[error] 4-4: Expected 1 empty line after require statement not followed by another require.

(import/newline-after-import)


[error] 4-4: fast-xml-parser import should occur before import of ../scripts/build-rss

(import/order)


[error] 8-8: 'describe' is not defined.

(no-undef)


[error] 12-12: 'beforeAll' is not defined.

(no-undef)


[error] 20-20: 'afterAll' is not defined.

(no-undef)


[error] 23-23: Replace file with (file)

(prettier/prettier)


[error] 30-30: 'afterEach' is not defined.

(no-undef)


[error] 31-31: 'jest' is not defined.

(no-undef)


[error] 34-34: 'it' is not defined.

(no-undef)


[error] 35-36: Delete ⏎····

(prettier/prettier)


[error] 36-36: 'jest' is not defined.

(no-undef)


[error] 38-38: Insert ;

(prettier/prettier)


[error] 46-46: 'it' is not defined.

(no-undef)


[error] 47-47: 'jest' is not defined.

(no-undef)


[error] 48-48: Delete ··

(prettier/prettier)


[error] 50-50: Delete ··

(prettier/prettier)


[error] 53-53: Delete ··

(prettier/prettier)


[error] 55-55: Replace item with (item)

(prettier/prettier)


[error] 56-56: Delete ··

(prettier/prettier)


[error] 59-59: Delete ··

(prettier/prettier)


[error] 65-65: Delete ··

(prettier/prettier)


[error] 66-66: 'it' is not defined.

(no-undef)


[error] 67-67: 'jest' is not defined.

(no-undef)


[error] 68-68: Delete ··

(prettier/prettier)


[error] 70-70: Delete ··

(prettier/prettier)


[error] 73-73: Delete ··

(prettier/prettier)


[error] 75-75: Replace item with (item)

(prettier/prettier)


[error] 76-76: Delete ··

(prettier/prettier)


[error] 78-78: Insert ;

(prettier/prettier)


[error] 85-85: 'it' is not defined.

(no-undef)


[error] 86-86: 'jest' is not defined.

(no-undef)


[error] 88-88: Insert ;

(prettier/prettier)


[error] 101-101: 'it' is not defined.

(no-undef)


[error] 102-102: 'jest' is not defined.

(no-undef)


[error] 104-104: Replace "invalid/path" with 'invalid/path'

(prettier/prettier)


[error] 106-107: Delete

(prettier/prettier)


[error] 110-110: 'it' is not defined.

(no-undef)


[error] 111-111: 'jest' is not defined.

(no-undef)


[error] 111-111: Replace '../config/posts.json', with ⏎······'../config/posts.json',⏎·····

(prettier/prettier)


[error] 112-112: Insert ··

(prettier/prettier)


[error] 113-113: Replace ····},·{·virtual:·true·} with ······},⏎······{·virtual:·true·}⏎····

(prettier/prettier)


[error] 115-116: Delete

(prettier/prettier)


[error] 119-119: 'it' is not defined.

(no-undef)


[error] 121-121: 'jest' is not defined.

(no-undef)


[error] 123-123: Insert ;

(prettier/prettier)


[error] 131-131: 'it' is not defined.

(no-undef)


[error] 132-133: Delete

(prettier/prettier)


[error] 133-133: 'jest' is not defined.

(no-undef)


[error] 136-137: Delete

(prettier/prettier)


[error] 139-139: 'it' is not defined.

(no-undef)


[error] 139-140: Delete

(prettier/prettier)


[error] 141-141: 'jest' is not defined.

(no-undef)


[error] 143-143: Replace 'Failed·to·generate·RSS·feed:·Missing·date·in·posts:·Post·without·Date' with ⏎······'Failed·to·generate·RSS·feed:·Missing·date·in·posts:·Post·without·Date'⏎····

(prettier/prettier)


[error] 144-146: Replace ⏎··});⏎·· with ··});

(prettier/prettier)

🔇 Additional comments (1)
tests/build-rss.test.js (1)

12-32: Well-structured test setup and teardown!

The implementation shows good practices:

  • Uses async/await for file operations
  • Includes proper error handling
  • Ensures cleanup after tests
  • Correctly uses jest.resetModules() to reset the module registry between tests
🧰 Tools
🪛 eslint

[error] 12-12: 'beforeAll' is not defined.

(no-undef)


[error] 20-20: 'afterAll' is not defined.

(no-undef)


[error] 23-23: Replace file with (file)

(prettier/prettier)


[error] 30-30: 'afterEach' is not defined.

(no-undef)


[error] 31-31: 'jest' is not defined.

(no-undef)

@akshatnema
Copy link
Member

/rtm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
gsoc This label should be used for issues or discussions related to ideas for Google Summer of Code ready-to-merge
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants