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
Show file tree
Hide file tree
Changes from 72 commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
63e8bf5
added test for build-rss.js
vishvamsinh28 Jul 21, 2024
c2570b9
Merge branch 'master' into rssTest
asyncapi-bot Aug 11, 2024
30f1c7f
Merge branch 'master' into rssTest
vishvamsinh28 Aug 16, 2024
aad7bf2
test updated
vishvamsinh28 Aug 16, 2024
312d4c5
Merge branch 'master' into rssTest
anshgoyalevil Aug 18, 2024
8d7269a
Merge branch 'master' into rssTest
vishvamsinh28 Aug 22, 2024
cfd547f
fewe
vishvamsinh28 Aug 22, 2024
5859c79
fedge
vishvamsinh28 Aug 22, 2024
44c3b63
fsfa
vishvamsinh28 Aug 22, 2024
de5edec
test for write operation error
vishvamsinh28 Aug 22, 2024
bf10b10
test updated
vishvamsinh28 Aug 22, 2024
1bacff6
egrwsdb
vishvamsinh28 Aug 22, 2024
3ce90ca
Merge branch 'master' into rssTest
vishvamsinh28 Aug 26, 2024
5d8fb67
use pretteir for rssData
vishvamsinh28 Aug 31, 2024
198c2a4
Merge branch 'master' into rssTest
anshgoyalevil Sep 5, 2024
5f4d05b
Merge branch 'master' into rssTest
asyncapi-bot Sep 5, 2024
5ab37aa
Merge branch 'master' into rssTest
vishvamsinh28 Sep 7, 2024
81b9845
Merge branch 'master' into rssTest
vishvamsinh28 Sep 11, 2024
92e86a3
Merge branch 'rssTest' of https://github.com/vishvamsinh28/website in…
vishvamsinh28 Sep 11, 2024
0d0cb30
updated rss mock data
vishvamsinh28 Sep 11, 2024
d7e0ac1
updated rss test
vishvamsinh28 Sep 11, 2024
fc57c2a
udadw
vishvamsinh28 Sep 11, 2024
1a8aa47
updated imports
vishvamsinh28 Sep 11, 2024
5ddb184
test updated
vishvamsinh28 Sep 11, 2024
5e8c0c7
Merge branch 'master' into rssTest
anshgoyalevil Sep 13, 2024
1eb6790
added try catch block for tests
vishvamsinh28 Sep 13, 2024
b03191d
Merge branch 'master' into rssTest
vishvamsinh28 Sep 15, 2024
239e65b
Merge branch 'master' into rssTest
vishvamsinh28 Sep 16, 2024
5e98d50
removed try catch block
vishvamsinh28 Sep 16, 2024
45f6ef6
Merge branch 'rssTest' of https://github.com/vishvamsinh28/website in…
vishvamsinh28 Sep 16, 2024
e6258c5
replaced trown with console.error
vishvamsinh28 Sep 16, 2024
7c9730f
using promise for throwign errors
vishvamsinh28 Sep 16, 2024
6e9f039
add error variable
vishvamsinh28 Sep 16, 2024
aac6e13
updated the test for rss
vishvamsinh28 Sep 16, 2024
0f61abe
Merge branch 'master' into rssTest
vishvamsinh28 Sep 20, 2024
e06fa47
updated test
vishvamsinh28 Sep 20, 2024
bc67c28
Merge branch 'master' into rssTest
anshgoyalevil Sep 23, 2024
8c93997
fwwfwf
vishvamsinh28 Sep 23, 2024
6e0b4ce
revert getAllPosts func changes
anshgoyalevil Sep 23, 2024
2631dc6
Merge branch 'master' into rssTest
vishvamsinh28 Sep 26, 2024
a66f2a2
Merge branch 'master' into rssTest
vishvamsinh28 Sep 28, 2024
a51c362
wsff
vishvamsinh28 Sep 28, 2024
4eb10e3
fefe
vishvamsinh28 Sep 28, 2024
4e75b0a
added test cases for errors
vishvamsinh28 Sep 28, 2024
5892f1e
Merge branch 'master' into rssTest
vishvamsinh28 Sep 30, 2024
e04cfba
Merge branch 'master' into rssTest
vishvamsinh28 Oct 4, 2024
07b2344
Merge branch 'master' into rssTest
vishvamsinh28 Oct 7, 2024
d55f553
suggested changes applied
vishvamsinh28 Oct 7, 2024
d9585fe
Merge branch 'master' into rssTest
vishvamsinh28 Oct 12, 2024
d41b851
Merge branch 'master' into rssTest
vishvamsinh28 Oct 13, 2024
d5b6882
empty line at end
vishvamsinh28 Oct 13, 2024
7980458
Merge branch 'rssTest' of https://github.com/vishvamsinh28/website in…
vishvamsinh28 Oct 13, 2024
6a93919
Merge branch 'master' into rssTest
vishvamsinh28 Oct 14, 2024
a5c083b
Merge branch 'master' into rssTest
vishvamsinh28 Oct 15, 2024
49f308a
replaced throw with promise.reject
vishvamsinh28 Oct 17, 2024
a4903ef
Merge branch 'master' into rssTest
vishvamsinh28 Oct 17, 2024
1ab85ee
Merge branch 'master' into rssTest
vishvamsinh28 Oct 20, 2024
36e7511
Merge branch 'master' into rssTest
anshgoyalevil Oct 23, 2024
1d39693
Merge branch 'master' into rssTest
vishvamsinh28 Oct 23, 2024
8a55fa2
test updated
vishvamsinh28 Oct 23, 2024
2ee9f6f
test updted
vishvamsinh28 Oct 23, 2024
6804d6e
rwwq
vishvamsinh28 Oct 23, 2024
fd0bb07
removed try/catch
vishvamsinh28 Oct 23, 2024
17fd825
Merge branch 'master' into rssTest
vishvamsinh28 Oct 27, 2024
8f77c30
Merge branch 'master' into rssTest
vishvamsinh28 Oct 27, 2024
a3dfa93
fef
vishvamsinh28 Oct 27, 2024
968d071
Merge branch 'master' into rssTest
anshgoyalevil Oct 31, 2024
7b1f401
Merge branch 'master' into rssTest
vishvamsinh28 Nov 1, 2024
87eb06b
Merge branch 'master' into rssTest
vishvamsinh28 Nov 1, 2024
2312a57
replaced promise.reject with throw
vishvamsinh28 Nov 1, 2024
d77cf7a
fewgge
vishvamsinh28 Nov 1, 2024
bc76d4b
fegewg
vishvamsinh28 Nov 1, 2024
5407af0
updated before and after block
vishvamsinh28 Nov 1, 2024
fb49686
fewgfew
vishvamsinh28 Nov 1, 2024
1d13e0b
fixtures updated
vishvamsinh28 Nov 1, 2024
3837d4b
Merge branch 'master' into rssTest
vishvamsinh28 Nov 4, 2024
51fc2a3
move package to dev dep
vishvamsinh28 Nov 4, 2024
9e166ae
fqefq
vishvamsinh28 Nov 4, 2024
02d5c07
Merge branch 'master' into rssTest
anshgoyalevil Nov 6, 2024
fed5650
Merge branch 'master' into rssTest
vishvamsinh28 Nov 8, 2024
8d0ff17
eqfe
vishvamsinh28 Nov 8, 2024
d9ce3ab
Merge branch 'rssTest' of https://github.com/vishvamsinh28/website in…
vishvamsinh28 Nov 8, 2024
08c88ae
Merge branch 'master' into rssTest
akshatnema Nov 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 78 additions & 50 deletions scripts/build-rss.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
const fs = require('fs')
const fs = require('fs').promises
const json2xml = require('jgexml/json2xml')

function getAllPosts() {
return require('../config/posts.json')
return require('../config/posts.json');
}

akshatnema marked this conversation as resolved.
Show resolved Hide resolved
function clean(s) {
Expand All @@ -15,61 +15,89 @@ function clean(s) {
return s
}

module.exports = function rssFeed(type, title, desc, outputPath) {
module.exports = async function rssFeed(type, title, desc, outputPath) {
try {

const posts = getAllPosts()[`${type}`]
.sort((i1, i2) => {
const i1Date = new Date(i1.date)
const i2Date = new Date(i2.date)
let posts = getAllPosts()[`${type}`]
const missingDatePosts = posts.filter(post => !post.date);
posts = posts.filter(post => post.date);
posts.sort((i1, i2) => {
const i1Date = new Date(i1.date);
const i2Date = new Date(i2.date);
if (i1.featured && !i2.featured) return -1;
if (!i1.featured && i2.featured) return 1;
return i2Date - i1Date;
});

if (i1.featured && !i2.featured) return -1
if (!i1.featured && i2.featured) return 1
return i2Date - i1Date
})
if (missingDatePosts.length > 0) {
throw new Error(`Missing date in posts: ${missingDatePosts.map(p => p.title || p.slug).join(', ')}`);
}

const base = 'https://www.asyncapi.com'
const tracking = '?utm_source=rss';

const feed = {}
const rss = {}
rss['@version'] = '2.0'
rss["@xmlns:atom"] = 'http://www.w3.org/2005/Atom'
rss.channel = {}
rss.channel.title = title
rss.channel.link = `${base}/${outputPath}`
rss.channel["atom:link"] = {}
rss.channel["atom:link"]["@rel"] = 'self'
rss.channel["atom:link"]["@href"] = rss.channel.link
rss.channel["atom:link"]["@type"] = 'application/rss+xml'
rss.channel.description = desc
rss.channel.language = 'en-gb';
rss.channel.copyright = 'Made with :love: by the AsyncAPI Initiative.';
rss.channel.webMaster = '[email protected] (AsyncAPI Initiative)'
rss.channel.pubDate = new Date().toUTCString()
rss.channel.generator = 'next.js'
rss.channel.item = []

const base = 'https://www.asyncapi.com'
const tracking = '?utm_source=rss';
const invalidPosts = posts.filter(post =>
!post.title || !post.slug || !post.excerpt || !post.date
);

const feed = {}
const rss = {}
rss['@version'] = '2.0'
rss["@xmlns:atom"] = 'http://www.w3.org/2005/Atom'
rss.channel = {}
rss.channel.title = title
rss.channel.link = `${base}/${outputPath}`
rss.channel["atom:link"] = {}
rss.channel["atom:link"]["@rel"] = 'self'
rss.channel["atom:link"]["@href"] = rss.channel.link
rss.channel["atom:link"]["@type"] = 'application/rss+xml'
rss.channel.description = desc
rss.channel.language = 'en-gb';
rss.channel.copyright = 'Made with :love: by the AsyncAPI Initiative.';
rss.channel.webMaster = '[email protected] (AsyncAPI Initiative)'
rss.channel.pubDate = new Date().toUTCString()
rss.channel.generator = 'next.js'
rss.channel.item = []
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

for (let post of posts) {
const link = `${base}${post.slug}${tracking}`;
const item = { title: post.title, description: clean(post.excerpt), link, category: type, guid: { '@isPermaLink': true, '': link }, pubDate: new Date(post.date).toUTCString() }
if (post.cover) {
const enclosure = {};
enclosure["@url"] = base+post.cover;
enclosure["@length"] = 15026; // dummy value, anything works
enclosure["@type"] = 'image/jpeg';
if (typeof enclosure["@url"] === 'string') {
let tmp = enclosure["@url"].toLowerCase();
if (tmp.indexOf('.png')>=0) enclosure["@type"] = 'image/png';
if (tmp.indexOf('.svg')>=0) enclosure["@type"] = 'image/svg+xml';
if (tmp.indexOf('.webp')>=0) enclosure["@type"] = 'image/webp';
for (let post of posts) {
const link = `${base}${post.slug}${tracking}`;
const { title, excerpt, date } = post;
const pubDate = new Date(date).toUTCString();
const description = clean(excerpt);
const guid = { '@isPermaLink': true, '': link };
const item = {
title,
description,
link,
category: type,
guid,
pubDate
};
if (post.cover) {
const enclosure = {};
enclosure["@url"] = base + post.cover;
enclosure["@length"] = 15026; // dummy value, anything works
enclosure["@type"] = 'image/jpeg';
if (typeof enclosure["@url"] === 'string') {
let tmp = enclosure["@url"].toLowerCase();
if (tmp.indexOf('.png') >= 0) enclosure["@type"] = 'image/png';
if (tmp.indexOf('.svg') >= 0) enclosure["@type"] = 'image/svg+xml';
if (tmp.indexOf('.webp') >= 0) enclosure["@type"] = 'image/webp';
}
item.enclosure = enclosure;
}
akshatnema marked this conversation as resolved.
Show resolved Hide resolved
akshatnema marked this conversation as resolved.
Show resolved Hide resolved
item.enclosure = enclosure;
rss.channel.item.push(item)
}
rss.channel.item.push(item)
}

feed.rss = rss
feed.rss = rss

const xml = json2xml.getXml(feed,'@','',2)
fs.writeFileSync(`./public/${outputPath}`, xml, 'utf8')
const xml = json2xml.getXml(feed, '@', '', 2);
await fs.writeFile(`./public/${outputPath}`, xml, 'utf8');
} catch (err) {
throw new Error(`Failed to generate RSS feed: ${err.message}`);
}
akshatnema marked this conversation as resolved.
Show resolved Hide resolved
};
134 changes: 134 additions & 0 deletions tests/build-rss.test.js
akshatnema marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
const fs = require('fs');
const path = require('path');
const rssFeed = require('../scripts/build-rss');
const { mockRssData, title, type, desc, missingDateMockData, incompletePostMockData } = require('./fixtures/rssData');

describe('rssFeed', () => {
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.

afterEach(() => {
jest.resetModules();
akshatnema marked this conversation as resolved.
Show resolved Hide resolved
});
akshatnema marked this conversation as resolved.
Show resolved Hide resolved

it('should generate RSS feed and write to file', 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);
expect(fs.existsSync(filePath)).toBe(true);
const fileContent = fs.readFileSync(filePath, 'utf8');
expect(fileContent).toContain('<rss version="2.0"');
});

it('should prioritize featured posts over non-featured ones', 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 itemTitles = fileContent.match(/<title>(.*?)<\/title>/g);

expect(itemTitles[1]).toContain('Test Post 1');
expect(itemTitles[2]).toContain('Another Featured Post');
expect(itemTitles[3]).toContain('Non-Featured Post 1');
});

it('should sort posts by date in descending order', 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 itemTitles = fileContent.match(/<title>(.*?)<\/title>/g);

expect(itemTitles[1]).toContain('Test Post 1');
expect(itemTitles[2]).toContain('Another Featured Post');
expect(itemTitles[3]).toContain('Non-Featured Post 1');
expect(itemTitles[4]).toContain('Non-Featured Post 3');
expect(itemTitles[5]).toContain('Non-Featured Post 2');
});

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"');
});
Comment on lines +85 to +99
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


it('should catch and handle errors when write operation fails', async () => {
jest.doMock('../config/posts.json', () => mockRssData, { virtual: true });

const invalidOutputPath = "invalid/path";

await expect(rssFeed(type, title, desc, invalidOutputPath)).rejects.toThrow(/ENOENT|EACCES/);

});

it('should throw an error when posts.json is malformed', async () => {
jest.doMock('../config/posts.json', () => {
return { invalidKey: [] };
}, { virtual: true });

await expect(rssFeed(type, title, desc, outputPath)).rejects.toThrow('Failed to generate RSS feed');

});

it('should handle empty posts array', async () => {
const emptyMockData = { blog: [] };
jest.doMock('../config/posts.json', () => emptyMockData, { 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('<rss version="2.0"');
expect(fileContent).not.toContain('<item>');
});

it('should throw an error when post is missing required fields', async () => {

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

await expect(rssFeed(type, title, desc, outputPath)).rejects.toThrow('Missing required fields');

});

it('should throw an error when a post is missing a date field during sorting', async () => {

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

await expect(rssFeed(type, title, desc, outputPath)).rejects.toThrow('Failed to generate RSS feed: Missing date in posts: Post without Date');

});
});
79 changes: 79 additions & 0 deletions tests/fixtures/rssData.js
akshatnema marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
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!


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,
},
],
};
Comment on lines +59 to +75
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,
},
],
};


const incompletePostMockData = {
blog: [
{
slug: '/blog/incomplete-post',
excerpt: 'This post is incomplete',
date: '2024-07-05',
featured: false,
},
],
};
Comment on lines +77 to +86
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,
},
],
};


const type = 'blog';
const title = 'Test Blog RSS';
const desc = 'Test blog RSS feed';
const outputPath = 'test-output/blog.xml';

module.exports = { mockRssData, title, type, desc, outputPath, missingDateMockData, incompletePostMockData };
Loading