From bf61566852533e8fd0ac9de91e954fcf82c808b6 Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela <90895835+vishvamsinh28@users.noreply.github.com> Date: Sun, 25 Aug 2024 11:32:45 +0530 Subject: [PATCH] feat: added tests for build-newsroom-videos.js (#3075) Co-authored-by: Ansh Goyal %0ACo-authored-by: asyncapi-bot --- package-lock.json | 8 +-- package.json | 2 +- scripts/build-newsroom-videos.js | 59 +++++++++------- tests/build-newsroom-videos.test.js | 101 ++++++++++++++++++++++++++++ tests/fixtures/newsroomData.js | 49 ++++++++++++++ 5 files changed, 188 insertions(+), 31 deletions(-) create mode 100644 tests/build-newsroom-videos.test.js create mode 100644 tests/fixtures/newsroomData.js diff --git a/package-lock.json b/package-lock.json index c271fd28258d..879c389d24d7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -52,7 +52,7 @@ "node-fetch": "^3.3.2", "node-fetch-2": "npm:node-fetch@^2.7.0", "postcss": "^8.4.35", - "prettier": "^3.3.0", + "prettier": "^3.3.3", "react": "^18", "react-dom": "^18", "react-ga": "^3.3.1", @@ -24202,9 +24202,9 @@ } }, "node_modules/prettier": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz", - "integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", "bin": { "prettier": "bin/prettier.cjs" }, diff --git a/package.json b/package.json index 01fa27ea3f4b..fde5349b991c 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ "node-fetch": "^3.3.2", "node-fetch-2": "npm:node-fetch@^2.7.0", "postcss": "^8.4.35", - "prettier": "^3.3.0", + "prettier": "^3.3.3", "react": "^18", "react-dom": "^18", "react-ga": "^3.3.1", diff --git a/scripts/build-newsroom-videos.js b/scripts/build-newsroom-videos.js index 5de122247104..b67ee0378cf2 100644 --- a/scripts/build-newsroom-videos.js +++ b/scripts/build-newsroom-videos.js @@ -1,10 +1,9 @@ const { writeFileSync } = require('fs'); const { resolve } = require('path'); -const fetch = require('node-fetch-2') -async function buildNewsroomVideos() { +const fetch = require('node-fetch-2'); +async function buildNewsroomVideos(writePath) { try { - let data; const response = await fetch('https://youtube.googleapis.com/youtube/v3/search?' + new URLSearchParams({ key: process.env.YOUTUBE_TOKEN, part: 'snippet', @@ -13,32 +12,40 @@ async function buildNewsroomVideos() { type: 'video', order: 'Date', maxResults: 5, - })) - data = await response.json() - const videoDataItems = data.items.map((video) => { - return { - image_url: video.snippet.thumbnails.high.url, - title: video.snippet.title, - description: video.snippet.description, - videoId: video.id.videoId, - } - }) - const videoData = JSON.stringify(videoDataItems, null, ' '); - console.log('The following are the Newsroom Youtube videos: ', videoData) - - try { - writeFileSync( - resolve(__dirname, '../config', 'newsroom_videos.json'), - videoData - ); - } catch (err) { - console.error(err); + })); + + if (!response.ok) { + throw new Error(`HTTP error! with status code: ${response.status}`); + } + + const data = await response.json(); + console.log(data) + + if (!data.items || !Array.isArray(data.items)) { + throw new Error('Invalid data structure received from YouTube API'); } + + const videoDataItems = data.items.map((video) => ({ + image_url: video.snippet.thumbnails.high.url, + title: video.snippet.title, + description: video.snippet.description, + videoId: video.id.videoId, + })); + + const videoData = JSON.stringify(videoDataItems, null, ' '); + console.log('The following are the Newsroom Youtube videos: ', videoData); + + writeFileSync(writePath, videoData); + return videoData; } catch (err) { - console.log(err) + throw new Error(`Failed to build newsroom videos: ${err.message}`); } } -buildNewsroomVideos() -module.exports={buildNewsroomVideos} \ No newline at end of file +/* istanbul ignore next */ +if (require.main === module) { + buildNewsroomVideos(resolve(__dirname, '../config', 'newsroom_videos.json')) +} + +module.exports = { buildNewsroomVideos }; diff --git a/tests/build-newsroom-videos.test.js b/tests/build-newsroom-videos.test.js new file mode 100644 index 000000000000..63f571466944 --- /dev/null +++ b/tests/build-newsroom-videos.test.js @@ -0,0 +1,101 @@ +const { readFileSync, rmSync, mkdirSync } = require('fs'); +const { resolve } = require('path'); +const { buildNewsroomVideos } = require('../scripts/build-newsroom-videos'); +const { mockApiResponse, expectedResult } = require('./fixtures/newsroomData'); +const fetch = require('node-fetch-2'); + +jest.mock('node-fetch-2', () => jest.fn()); + +describe('buildNewsroomVideos', () => { + const testDir = resolve(__dirname, 'test_config'); + const testFilePath = resolve(testDir, 'newsroom_videos.json'); + + beforeAll(() => { + mkdirSync(testDir, { recursive: true }); + process.env.YOUTUBE_TOKEN = 'testkey'; + }); + + afterAll(() => { + rmSync(testDir, { recursive: true, force: true }); + }); + + beforeEach(() => { + fetch.mockClear(); + }); + + it('should fetch video data and write to file', async () => { + fetch.mockResolvedValue({ + ok: true, + json: jest.fn().mockResolvedValue(mockApiResponse), + }); + + const result = await buildNewsroomVideos(testFilePath); + + const expectedUrl = new URL('https://youtube.googleapis.com/youtube/v3/search'); + expectedUrl.searchParams.set('key', 'testkey'); + expectedUrl.searchParams.set('part', 'snippet'); + expectedUrl.searchParams.set('channelId', 'UCIz9zGwDLbrYQcDKVXdOstQ'); + expectedUrl.searchParams.set('eventType', 'completed'); + expectedUrl.searchParams.set('type', 'video'); + expectedUrl.searchParams.set('order', 'Date'); + expectedUrl.searchParams.set('maxResults', '5'); + + expect(fetch).toHaveBeenCalledWith(expectedUrl.toString()); + const response = readFileSync(testFilePath, 'utf8'); + expect(response).toEqual(expectedResult); + expect(result).toEqual(expectedResult); + }); + + it('should handle fetch errors', async () => { + fetch.mockRejectedValue(new Error('Fetch error')); + + try { + await buildNewsroomVideos(testFilePath); + } catch (err) { + expect(err.message).toContain('Fetch error'); + } + }); + + it('should handle invalid API response', async () => { + fetch.mockResolvedValue({ + ok: true, + json: jest.fn().mockResolvedValue({}), + }); + + try { + await buildNewsroomVideos(testFilePath); + } catch (err) { + expect(err.message).toContain('Invalid data structure received from YouTube API'); + } + }); + + it('should handle HTTP status code', async () => { + fetch.mockResolvedValue({ + ok: false, + status: 404, + json: jest.fn().mockResolvedValue({}), + }); + + try { + await buildNewsroomVideos(testFilePath); + } catch (err) { + expect(err.message).toContain('HTTP error! with status code: 404'); + } + }); + + it('should handle file write errors', async () => { + fetch.mockResolvedValue({ + ok: true, + json: jest.fn().mockResolvedValue(mockApiResponse), + }); + + const invalidPath = '/invalid_dir/newsroom_videos.json'; + + try { + await buildNewsroomVideos(invalidPath); + } catch (err) { + expect(err.message).toMatch(/ENOENT|EACCES/); + } + }); + +}); diff --git a/tests/fixtures/newsroomData.js b/tests/fixtures/newsroomData.js new file mode 100644 index 000000000000..a42f93636492 --- /dev/null +++ b/tests/fixtures/newsroomData.js @@ -0,0 +1,49 @@ +const mockApiResponse = { + items: [ + { + snippet: { + thumbnails: { + high: { + url: 'https://i.ytimg.com/vi/K7fvKbOfqOg/hqdefault.jpg', + }, + }, + title: 'Developer Experience Working Group, 14:00 UTC Thursday May 23rd 2024', + description: 'Define our vision and plans https://github.com/asyncapi/community/issues/1220.', + }, + id: { + videoId: 'K7fvKbOfqOg', + }, + }, + { + snippet: { + thumbnails: { + high: { + url: 'https://i.ytimg.com/vi/94SSXX78VCU/hqdefault.jpg', + }, + }, + title: 'Essential Building Blocks Working Group, 18:00 UTC Tuesday May 14th 2024', + description: 'https://github.com/asyncapi/community/issues/1200.', + }, + id: { + videoId: '94SSXX78VCU', + }, + }, + ], +}; + +const expectedResult = JSON.stringify([ + { + "image_url": "https://i.ytimg.com/vi/K7fvKbOfqOg/hqdefault.jpg", + "title": "Developer Experience Working Group, 14:00 UTC Thursday May 23rd 2024", + "description": "Define our vision and plans https://github.com/asyncapi/community/issues/1220.", + "videoId": "K7fvKbOfqOg" + }, + { + "image_url": "https://i.ytimg.com/vi/94SSXX78VCU/hqdefault.jpg", + "title": "Essential Building Blocks Working Group, 18:00 UTC Tuesday May 14th 2024", + "description": "https://github.com/asyncapi/community/issues/1200.", + "videoId": "94SSXX78VCU" + }, +], null, ' '); + +module.exports = { mockApiResponse, expectedResult }