From d1fc6c4d2225603e67b5d7fd9cac338544fd8bf1 Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Sat, 28 Sep 2024 18:44:10 +0530 Subject: [PATCH 01/43] tests added --- tests/tools/tools-object.test.js | 203 +++++++++++++++++++++++++++++++ 1 file changed, 203 insertions(+) create mode 100644 tests/tools/tools-object.test.js diff --git a/tests/tools/tools-object.test.js b/tests/tools/tools-object.test.js new file mode 100644 index 000000000000..3c17e24c36d7 --- /dev/null +++ b/tests/tools/tools-object.test.js @@ -0,0 +1,203 @@ +const { convertTools, createToolObject } = require('../../scripts/tools/tools-object'); +const axios = require('axios'); +const Ajv = require('ajv'); +const addFormats = require('ajv-formats'); +const schema = require('../../scripts/tools/tools-schema.json'); + +// Mock axios +jest.mock('axios'); + +// Mock categoryList to include 'Category1' and 'Others' +jest.mock('../../scripts/tools/categorylist', () => ({ + categoryList: [ + { name: 'Category1', tag: 'Category1', description: 'Description for Category1' }, + { name: 'Others', tag: 'Others', description: 'Other tools category' }, + ] +})); + +const { categoryList } = require('../../scripts/tools/categorylist'); + +// Setup AJV +const ajv = new Ajv(); +addFormats(ajv, ["uri"]); +const validate = ajv.compile(schema); + +// Sample data +const mockData = { + items: [ + { + name: '.asyncapi-tool-example', + url: 'https://api.github.com/repositories/351453552/contents/.asyncapi-tool?ref=61855e7365a881e98c2fe667a658a0005753d873', + repository: { + full_name: 'asyncapi/example-repo', + html_url: 'https://github.com/asyncapi/example-repo', + description: 'Example repository', + owner: { + login: 'asyncapi' + } + }, + path: '.asyncapi-tool' + } + ] +}; + +const mockToolFileContent = ` +title: Example Tool +description: This is an example tool. +links: + repoUrl: https://github.com/asyncapi/example-repo +filters: + categories: + - Category1 + hasCommercial: true +`; + +describe('createToolObject', () => { + it('should create a tool object with provided parameters', async () => { + const toolFile = { + title: 'Example Tool', + description: 'This is an example tool.', + links: { + repoUrl: 'https://github.com/asyncapi/example-repo' + }, + filters: { + categories: ['Category1'], + hasCommercial: true + } + }; + const repositoryUrl = 'https://github.com/asyncapi/example-repo'; + const repoDescription = 'Example repository'; + const isAsyncAPIrepo = true; + + const expectedObject = { + title: 'Example Tool', + description: 'This is an example tool.', + links: { + repoUrl: 'https://github.com/asyncapi/example-repo' + }, + filters: { + categories: ['Category1'], + hasCommercial: true, + isAsyncAPIOwner: true + } + }; + + const result = await createToolObject(toolFile, repositoryUrl, repoDescription, isAsyncAPIrepo); + expect(result).toEqual(expectedObject); + }); + + it('should use repoDescription when toolFile.description is not provided', async () => { + const toolFile = { + title: 'Example Tool', + links: { + repoUrl: 'https://github.com/asyncapi/example-repo' + }, + filters: { + categories: ['Category1'] + } + }; + const repositoryUrl = 'https://github.com/asyncapi/example-repo'; + const repoDescription = 'Example repository'; + const isAsyncAPIrepo = true; + + const expectedObject = { + title: 'Example Tool', + description: 'Example repository', + links: { + repoUrl: 'https://github.com/asyncapi/example-repo' + }, + filters: { + categories: ['Category1'], + hasCommercial: false, + isAsyncAPIOwner: true + } + }; + + const result = await createToolObject(toolFile, repositoryUrl, repoDescription, isAsyncAPIrepo); + expect(result).toEqual(expectedObject); + }); +}); + +describe('convertTools', () => { + beforeEach(() => { + axios.get.mockClear(); + console.error = jest.fn(); + }); + + it('should convert tools data correctly', async () => { + axios.get.mockResolvedValue({ data: mockToolFileContent }); + + const result = await convertTools(mockData); + + const expectedObject = { + Category1: { + description: 'Description for Category1', + toolsList: [ + { + title: 'Example Tool', + description: 'This is an example tool.', + links: { + repoUrl: 'https://github.com/asyncapi/example-repo' + }, + filters: { + categories: ['Category1'], + hasCommercial: true, + isAsyncAPIOwner: true + } + } + ] + }, + Others: { + description: 'Other tools category', + toolsList: [] + } + }; + + expect(result).toEqual(expect.objectContaining(expectedObject)); + expect(axios.get).toHaveBeenCalledTimes(1); + }); + + it('should assign tool to Others category if no matching category is found', async () => { + const dataWithUnknownCategory = { + items: [ + { + name: '.asyncapi-tool-unknown', + url: 'https://api.github.com/repositories/351453552/contents/.asyncapi-tool?ref=61855e7365a881e98c2fe667a658a0005753d873', + repository: { + full_name: 'asyncapi/unknown-repo', + html_url: 'https://github.com/asyncapi/unknown-repo', + description: 'Unknown repository', + owner: { + login: 'asyncapi' + } + }, + path: '.asyncapi-tool' + } + ] + }; + + const toolFileContent = ` +title: Unknown Tool +description: This tool has an unknown category. +links: + repoUrl: https://github.com/asyncapi/unknown-repo +filters: + categories: + - UnknownCategory +`; + + axios.get.mockResolvedValue({ data: toolFileContent }); + + const result = await convertTools(dataWithUnknownCategory); + + expect(result.Others.toolsList).toHaveLength(1); + expect(result.Others.toolsList[0].title).toBe('Unknown Tool'); + }); + + it('should throw an error if axios.get fails', async () => { + axios.get.mockRejectedValue(new Error('Network Error')); + + await expect(convertTools(mockData)).rejects.toThrow('Network Error'); + }); +}); + From 9b22bc1450d105c950ee17e8f3e4365ff194f19b Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Sat, 28 Sep 2024 19:34:05 +0530 Subject: [PATCH 02/43] fwqfwq --- tests/tools/tools-object.test.js | 179 +++++++++++++++++++++++++++---- 1 file changed, 158 insertions(+), 21 deletions(-) diff --git a/tests/tools/tools-object.test.js b/tests/tools/tools-object.test.js index 3c17e24c36d7..763393587ab1 100644 --- a/tests/tools/tools-object.test.js +++ b/tests/tools/tools-object.test.js @@ -1,13 +1,8 @@ const { convertTools, createToolObject } = require('../../scripts/tools/tools-object'); const axios = require('axios'); -const Ajv = require('ajv'); -const addFormats = require('ajv-formats'); -const schema = require('../../scripts/tools/tools-schema.json'); -// Mock axios jest.mock('axios'); -// Mock categoryList to include 'Category1' and 'Others' jest.mock('../../scripts/tools/categorylist', () => ({ categoryList: [ { name: 'Category1', tag: 'Category1', description: 'Description for Category1' }, @@ -15,14 +10,6 @@ jest.mock('../../scripts/tools/categorylist', () => ({ ] })); -const { categoryList } = require('../../scripts/tools/categorylist'); - -// Setup AJV -const ajv = new Ajv(); -addFormats(ajv, ["uri"]); -const validate = ajv.compile(schema); - -// Sample data const mockData = { items: [ { @@ -52,7 +39,11 @@ filters: hasCommercial: true `; -describe('createToolObject', () => { +describe('Tools Object', () => { + beforeEach(() => { + axios.get.mockClear(); + console.error = jest.fn(); + }); it('should create a tool object with provided parameters', async () => { const toolFile = { title: 'Example Tool', @@ -116,13 +107,6 @@ describe('createToolObject', () => { const result = await createToolObject(toolFile, repositoryUrl, repoDescription, isAsyncAPIrepo); expect(result).toEqual(expectedObject); }); -}); - -describe('convertTools', () => { - beforeEach(() => { - axios.get.mockClear(); - console.error = jest.fn(); - }); it('should convert tools data correctly', async () => { axios.get.mockResolvedValue({ data: mockToolFileContent }); @@ -199,5 +183,158 @@ filters: await expect(convertTools(mockData)).rejects.toThrow('Network Error'); }); + + it('should log errors for invalid .asyncapi-tool file', async () => { + const invalidToolFileContent = ` + title: Invalid Tool + description: This tool has invalid schema. + links: + repoUrl: https://github.com/asyncapi/invalid-repo + filters: + categories: + - Category1 + invalidField: true + `; + + const invalidToolData = { + items: [ + { + name: '.asyncapi-tool-invalid', + url: 'https://api.github.com/repositories/351453552/contents/.asyncapi-tool?ref=invalidref', + repository: { + full_name: 'asyncapi/invalid-repo', + html_url: 'https://github.com/asyncapi/invalid-repo', + description: 'Invalid repository', + owner: { + login: 'asyncapi' + } + }, + path: '.asyncapi-tool' + } + ] + }; + + axios.get.mockResolvedValue({ data: invalidToolFileContent }); + + await convertTools(invalidToolData); + + console.log('All console.error calls:', console.error.mock.calls); + + const allErrorMessages = console.error.mock.calls.flat(); + expect(allErrorMessages).toEqual( + expect.arrayContaining([ + expect.stringContaining('Script is not failing, it is just dropping errors for further investigation'), + expect.stringContaining('Invalid .asyncapi-tool file'), + expect.stringContaining('Located in:'), + expect.stringContaining('Validation errors:') + ]) + ); + + }); + + it('should add duplicate tool objects to the same category', async () => { + const duplicateToolData = { + items: [ + { + name: '.asyncapi-tool-duplicate', + url: 'https://api.github.com/repositories/351453552/contents/.asyncapi-tool?ref=duplicate1', + repository: { + full_name: 'asyncapi/duplicate-repo', + html_url: 'https://github.com/asyncapi/duplicate-repo', + description: 'Duplicate repository', + owner: { + login: 'asyncapi' + } + }, + path: '.asyncapi-tool' + }, + { + name: '.asyncapi-tool-duplicate', + url: 'https://api.github.com/repositories/351453552/contents/.asyncapi-tool?ref=duplicate2', + repository: { + full_name: 'asyncapi/duplicate-repo', + html_url: 'https://github.com/asyncapi/duplicate-repo', + description: 'Duplicate repository', + owner: { + login: 'asyncapi' + } + }, + path: '.asyncapi-tool' + } + ] + }; + + const duplicateToolFileContent = ` + title: Duplicate Tool + description: This is a duplicate tool. + links: + repoUrl: https://github.com/asyncapi/duplicate-repo + filters: + categories: + - Category1 + `; + + axios.get.mockResolvedValue({ data: duplicateToolFileContent }); + + const result = await convertTools(duplicateToolData); + + expect(result.Category1.toolsList).toHaveLength(2); + expect(result.Category1.toolsList[0].title).toBe('Duplicate Tool'); + expect(result.Category1.toolsList[1].title).toBe('Duplicate Tool'); + }); + + it('should add tool to Others category only once', async () => { + const dataWithUnknownCategory = { + items: [ + { + name: '.asyncapi-tool-unknown', + url: 'https://api.github.com/repositories/351453552/contents/.asyncapi-tool?ref=unknown1', + repository: { + full_name: 'asyncapi/unknown-repo', + html_url: 'https://github.com/asyncapi/unknown-repo', + description: 'Unknown repository', + owner: { + login: 'asyncapi' + } + }, + path: '.asyncapi-tool' + }, + { + name: '.asyncapi-tool-unknown', + url: 'https://api.github.com/repositories/351453552/contents/.asyncapi-tool?ref=unknown2', + repository: { + full_name: 'asyncapi/unknown-repo', + html_url: 'https://github.com/asyncapi/unknown-repo', + description: 'Unknown repository', + owner: { + login: 'asyncapi' + } + }, + path: '.asyncapi-tool' + } + ] + }; + + const unknownToolFileContent = ` + title: Unknown Tool + description: This tool has an unknown category. + links: + repoUrl: https://github.com/asyncapi/unknown-repo + filters: + categories: + - UnknownCategory + `; + + axios.get.mockResolvedValue({ data: unknownToolFileContent }); + + const result = await convertTools(dataWithUnknownCategory); + + const uniqueTools = result.Others.toolsList.filter((tool, index, self) => + index === self.findIndex((t) => t.title === tool.title) + ); + + expect(uniqueTools).toHaveLength(1); + expect(uniqueTools[0].title).toBe('Unknown Tool'); + }); }); From 3629568c5dc74b27967f8a2848e0ef49a3c8e96a Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Sat, 28 Sep 2024 19:34:30 +0530 Subject: [PATCH 03/43] fefeq --- tests/tools/tools-object.test.js | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/tests/tools/tools-object.test.js b/tests/tools/tools-object.test.js index 763393587ab1..86a445695748 100644 --- a/tests/tools/tools-object.test.js +++ b/tests/tools/tools-object.test.js @@ -40,10 +40,12 @@ filters: `; describe('Tools Object', () => { + beforeEach(() => { axios.get.mockClear(); console.error = jest.fn(); }); + it('should create a tool object with provided parameters', async () => { const toolFile = { title: 'Example Tool', @@ -195,7 +197,7 @@ filters: - Category1 invalidField: true `; - + const invalidToolData = { items: [ { @@ -213,13 +215,13 @@ filters: } ] }; - + axios.get.mockResolvedValue({ data: invalidToolFileContent }); - + await convertTools(invalidToolData); - + console.log('All console.error calls:', console.error.mock.calls); - + const allErrorMessages = console.error.mock.calls.flat(); expect(allErrorMessages).toEqual( expect.arrayContaining([ @@ -314,7 +316,7 @@ filters: } ] }; - + const unknownToolFileContent = ` title: Unknown Tool description: This tool has an unknown category. @@ -324,15 +326,15 @@ filters: categories: - UnknownCategory `; - + axios.get.mockResolvedValue({ data: unknownToolFileContent }); - + const result = await convertTools(dataWithUnknownCategory); - + const uniqueTools = result.Others.toolsList.filter((tool, index, self) => index === self.findIndex((t) => t.title === tool.title) ); - + expect(uniqueTools).toHaveLength(1); expect(uniqueTools[0].title).toBe('Unknown Tool'); }); From cabfbae3e17cff0ad37e0c4d45a63dbd4b9c2660 Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Sat, 28 Sep 2024 22:19:42 +0530 Subject: [PATCH 04/43] errors added --- scripts/tools/tools-object.js | 106 ++++++++++++++++--------------- tests/tools/tools-object.test.js | 91 ++++++++++++++++++++++++-- 2 files changed, 139 insertions(+), 58 deletions(-) diff --git a/scripts/tools/tools-object.js b/scripts/tools/tools-object.js index e5a30334f7d3..b89d72b3f560 100644 --- a/scripts/tools/tools-object.js +++ b/scripts/tools/tools-object.js @@ -25,7 +25,7 @@ const fuse = new Fuse(categoryList, options) // isAsyncAPIrepo boolean variable to define whether the tool repository is under // AsyncAPI organization or not, to create a JSON tool object as required in the frontend // side to show ToolCard. -const createToolObject = async (toolFile, repositoryUrl='', repoDescription='', isAsyncAPIrepo='') => { +const createToolObject = async (toolFile, repositoryUrl = '', repoDescription = '', isAsyncAPIrepo = '') => { let resultantObject = { title: toolFile.title, description: toolFile?.description ? toolFile.description : repoDescription, @@ -47,67 +47,71 @@ const createToolObject = async (toolFile, repositoryUrl='', repoDescription='', // and creating a JSON tool object in which all the tools are listed in defined // categories order, which is then updated in `automated-tools.json` file. async function convertTools(data) { - let finalToolsObject = {}; - const dataArray = data.items; + try { + let finalToolsObject = {}; + const dataArray = data.items; - // initialising finalToolsObject with all categories inside it with proper elements in each category - for (var index in categoryList) { - finalToolsObject[categoryList[index].name] = { - description: categoryList[index].description, - toolsList: [] - }; - } + // initialising finalToolsObject with all categories inside it with proper elements in each category + for (var index in categoryList) { + finalToolsObject[categoryList[index].name] = { + description: categoryList[index].description, + toolsList: [] + }; + } - for (let tool of dataArray) { - try { - if (tool.name.startsWith('.asyncapi-tool')) { - // extracting the reference id of the repository which will be used to extract the path of the .asyncapi-tool file in the Tools repository - // ex: for a url = "https://api.github.com/repositories/351453552/contents/.asyncapi-tool?ref=61855e7365a881e98c2fe667a658a0005753d873" - // the text (id) present after '=' gives us a reference id for the repo - let reference_id = tool.url.split("=")[1]; - let download_url = `https://raw.githubusercontent.com/${tool.repository.full_name}/${reference_id}/${tool.path}`; + for (let tool of dataArray) { + try { + if (tool.name.startsWith('.asyncapi-tool')) { + // extracting the reference id of the repository which will be used to extract the path of the .asyncapi-tool file in the Tools repository + // ex: for a url = "https://api.github.com/repositories/351453552/contents/.asyncapi-tool?ref=61855e7365a881e98c2fe667a658a0005753d873" + // the text (id) present after '=' gives us a reference id for the repo + let reference_id = tool.url.split("=")[1]; + let download_url = `https://raw.githubusercontent.com/${tool.repository.full_name}/${reference_id}/${tool.path}`; - const { data: toolFileContent } = await axios.get(download_url); + const { data: toolFileContent } = await axios.get(download_url); - //some stuff can be YAML - const jsonToolFileContent = await convertToJson(toolFileContent) + //some stuff can be YAML + const jsonToolFileContent = await convertToJson(toolFileContent) - //validating against JSON Schema for tools file - const isValid = await validate(jsonToolFileContent) + //validating against JSON Schema for tools file + const isValid = await validate(jsonToolFileContent) - if (isValid) { - let repositoryUrl = tool.repository.html_url; - let repoDescription = tool.repository.description; - let isAsyncAPIrepo = tool.repository.owner.login === "asyncapi"; - let toolObject = await createToolObject(jsonToolFileContent, repositoryUrl, repoDescription, isAsyncAPIrepo); + if (isValid) { + let repositoryUrl = tool.repository.html_url; + let repoDescription = tool.repository.description; + let isAsyncAPIrepo = tool.repository.owner.login === "asyncapi"; + let toolObject = await createToolObject(jsonToolFileContent, repositoryUrl, repoDescription, isAsyncAPIrepo); - // Tool Object is appended to each category array according to Fuse search for categories inside Tool Object - jsonToolFileContent.filters.categories.forEach(async (category) => { - const categorySearch = await fuse.search(category); + // Tool Object is appended to each category array according to Fuse search for categories inside Tool Object + jsonToolFileContent.filters.categories.forEach(async (category) => { + const categorySearch = await fuse.search(category); - if (categorySearch.length) { - let searchedCategoryName = categorySearch[0].item.name - if (!finalToolsObject[searchedCategoryName].toolsList.find((element => element === toolObject))) - finalToolsObject[searchedCategoryName].toolsList.push(toolObject); - } else { - // if Tool object has a category, not defined in our categorylist, then this provides a `other` category to the tool. - if (!finalToolsObject['Others'].toolsList.find((element => element === toolObject))) - finalToolsObject['Others'].toolsList.push(toolObject); - } - }); - } else { - console.error('Script is not failing, it is just dropping errors for further investigation'); - console.error('Invalid .asyncapi-tool file.'); - console.error(`Located in: ${tool.html_url}`); - console.error('Validation errors:', JSON.stringify(validate.errors, null, 2)); + if (categorySearch.length) { + let searchedCategoryName = categorySearch[0].item.name + if (!finalToolsObject[searchedCategoryName].toolsList.find((element => element === toolObject))) + finalToolsObject[searchedCategoryName].toolsList.push(toolObject); + } else { + // if Tool object has a category, not defined in our categorylist, then this provides a `other` category to the tool. + if (!finalToolsObject['Others'].toolsList.find((element => element === toolObject))) + finalToolsObject['Others'].toolsList.push(toolObject); + } + }); + } else { + console.error('Script is not failing, it is just dropping errors for further investigation'); + console.error('Invalid .asyncapi-tool file.'); + console.error(`Located in: ${tool.html_url}`); + console.error('Validation errors:', JSON.stringify(validate.errors, null, 2)); + } } + } catch (err) { + console.error(err) + throw err; } - } catch (err) { - console.error(err) - throw err; } + return finalToolsObject; + } catch (err) { + throw new Error(`Error processing tool: ${err.message}`) } - return finalToolsObject; } -module.exports = {convertTools, createToolObject} \ No newline at end of file +module.exports = { convertTools, createToolObject } \ No newline at end of file diff --git a/tests/tools/tools-object.test.js b/tests/tools/tools-object.test.js index 86a445695748..639dbc3830d3 100644 --- a/tests/tools/tools-object.test.js +++ b/tests/tools/tools-object.test.js @@ -40,7 +40,7 @@ filters: `; describe('Tools Object', () => { - + beforeEach(() => { axios.get.mockClear(); console.error = jest.fn(); @@ -180,12 +180,6 @@ filters: expect(result.Others.toolsList[0].title).toBe('Unknown Tool'); }); - it('should throw an error if axios.get fails', async () => { - axios.get.mockRejectedValue(new Error('Network Error')); - - await expect(convertTools(mockData)).rejects.toThrow('Network Error'); - }); - it('should log errors for invalid .asyncapi-tool file', async () => { const invalidToolFileContent = ` title: Invalid Tool @@ -338,5 +332,88 @@ filters: expect(uniqueTools).toHaveLength(1); expect(uniqueTools[0].title).toBe('Unknown Tool'); }); + + it('should throw an error if axios.get fails', async () => { + axios.get.mockRejectedValue(new Error('Network Error')); + + try { + await convertTools(mockData) + } catch (err) { + expect(err.message).toContain("Network Error") + } + }); + + it('should throw an error if JSON schema validation fails', async () => { + const invalidToolFileContent = ` + title: Invalid Tool + description: This tool has invalid schema. + links: + repoUrl: https://github.com/asyncapi/invalid-repo + filters: + categories: + - Category1 + invalidField: true + `; + + axios.get.mockResolvedValue({ data: invalidToolFileContent }); + + try { + await convertTools(mockData); + } catch (err) { + expect(err).toBeInstanceOf(Error); + expect(err.message).toContain('Invalid .asyncapi-tool file'); + } + }); + + it('should throw an error if toolFile cannot be converted to JSON', async () => { + const invalidJsonContent = ` + title: Invalid Tool + description: This is an invalid JSON + links: + repoUrl: https://github.com/asyncapi/invalid-repo + `; + + axios.get.mockResolvedValue({ data: invalidJsonContent }); + + jest.doMock('../../scripts/utils', () => ({ + convertToJson: jest.fn(() => { + throw new Error('Invalid JSON format'); + }) + })); + + try { + await convertTools(mockData); + } catch (err) { + expect(err).toBeInstanceOf(Error); + expect(err.message).toBe('Error processing tool: Invalid JSON format'); + } + }); + + it('should throw an error if a required tool property is missing', async () => { + const missingToolPropertyContent = ` + title: Missing Property Tool + description: This tool is missing required properties + links: + repoUrl: https://github.com/asyncapi/missing-property + `; + + axios.get.mockResolvedValue({ data: missingToolPropertyContent }); + + jest.doMock('../../scripts/utils', () => ({ + convertToJson: jest.fn(() => { + return { + title: 'Missing Property Tool', + }; + }) + })); + + try { + await convertTools(mockData); + } catch (err) { + expect(err).toBeInstanceOf(Error); + expect(err.message).toContain('Missing required tool properties'); + } + }); + }); From 340c1f76a7ef3ea223c2b37972b1f06db369abc8 Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Sat, 28 Sep 2024 23:02:08 +0530 Subject: [PATCH 05/43] fixture update --- tests/fixtures/toolsObjectData.js | 292 ++++++++++++++++++++++++++++ tests/tools/tools-object.test.js | 303 ++++-------------------------- 2 files changed, 324 insertions(+), 271 deletions(-) create mode 100644 tests/fixtures/toolsObjectData.js diff --git a/tests/fixtures/toolsObjectData.js b/tests/fixtures/toolsObjectData.js new file mode 100644 index 000000000000..96b425f523e8 --- /dev/null +++ b/tests/fixtures/toolsObjectData.js @@ -0,0 +1,292 @@ +const mockData = { + items: [ + { + name: '.asyncapi-tool-example', + url: 'https://api.github.com/repositories/351453552/contents/.asyncapi-tool?ref=61855e7365a881e98c2fe667a658a0005753d873', + repository: { + full_name: 'asyncapi/example-repo', + html_url: 'https://github.com/asyncapi/example-repo', + description: 'Example repository', + owner: { + login: 'asyncapi' + } + }, + path: '.asyncapi-tool' + } + ] +}; + +const mockToolFileContent = ` + title: Example Tool + description: This is an example tool. + links: + repoUrl: https://github.com/asyncapi/example-repo + filters: + categories: + - Category1 + hasCommercial: true + `; + +const toolFileT1 = { + title: 'Example Tool', + description: 'This is an example tool.', + links: { + repoUrl: 'https://github.com/asyncapi/example-repo' + }, + filters: { + categories: ['Category1'], + hasCommercial: true + } +}; + +const expectedObjectT1 = { + title: 'Example Tool', + description: 'This is an example tool.', + links: { + repoUrl: 'https://github.com/asyncapi/example-repo' + }, + filters: { + categories: ['Category1'], + hasCommercial: true, + isAsyncAPIOwner: true + } +}; + +const repositoryUrl = 'https://github.com/asyncapi/example-repo'; +const repoDescription = 'Example repository'; +const isAsyncAPIrepo = true; + +const toolFileT2 = { + title: 'Example Tool', + links: { + repoUrl: 'https://github.com/asyncapi/example-repo' + }, + filters: { + categories: ['Category1'] + } +}; + +const expectedObjectT2 = { + title: 'Example Tool', + description: 'Example repository', + links: { + repoUrl: 'https://github.com/asyncapi/example-repo' + }, + filters: { + categories: ['Category1'], + hasCommercial: false, + isAsyncAPIOwner: true + } +}; + +const expectedObjectT3 = { + Category1: { + description: 'Description for Category1', + toolsList: [ + { + title: 'Example Tool', + description: 'This is an example tool.', + links: { + repoUrl: 'https://github.com/asyncapi/example-repo' + }, + filters: { + categories: ['Category1'], + hasCommercial: true, + isAsyncAPIOwner: true + } + } + ] + }, + Others: { + description: 'Other tools category', + toolsList: [] + } +}; + +const dataWithUnknownCategory = { + items: [ + { + name: '.asyncapi-tool-unknown', + url: 'https://api.github.com/repositories/351453552/contents/.asyncapi-tool?ref=61855e7365a881e98c2fe667a658a0005753d873', + repository: { + full_name: 'asyncapi/unknown-repo', + html_url: 'https://github.com/asyncapi/unknown-repo', + description: 'Unknown repository', + owner: { + login: 'asyncapi' + } + }, + path: '.asyncapi-tool' + } + ] +}; + +const toolFileContent = ` + title: Unknown Tool + description: This tool has an unknown category. + links: + repoUrl: https://github.com/asyncapi/unknown-repo + filters: + categories: + - UnknownCategory + `; + +const invalidToolFileContent = ` + title: Invalid Tool + description: This tool has invalid schema. + links: + repoUrl: https://github.com/asyncapi/invalid-repo + filters: + categories: + - Category1 + invalidField: true + `; + +const invalidToolData = { + items: [ + { + name: '.asyncapi-tool-invalid', + url: 'https://api.github.com/repositories/351453552/contents/.asyncapi-tool?ref=invalidref', + repository: { + full_name: 'asyncapi/invalid-repo', + html_url: 'https://github.com/asyncapi/invalid-repo', + description: 'Invalid repository', + owner: { + login: 'asyncapi' + } + }, + path: '.asyncapi-tool' + } + ] +}; + +const duplicateToolData = { + items: [ + { + name: '.asyncapi-tool-duplicate', + url: 'https://api.github.com/repositories/351453552/contents/.asyncapi-tool?ref=duplicate1', + repository: { + full_name: 'asyncapi/duplicate-repo', + html_url: 'https://github.com/asyncapi/duplicate-repo', + description: 'Duplicate repository', + owner: { + login: 'asyncapi' + } + }, + path: '.asyncapi-tool' + }, + { + name: '.asyncapi-tool-duplicate', + url: 'https://api.github.com/repositories/351453552/contents/.asyncapi-tool?ref=duplicate2', + repository: { + full_name: 'asyncapi/duplicate-repo', + html_url: 'https://github.com/asyncapi/duplicate-repo', + description: 'Duplicate repository', + owner: { + login: 'asyncapi' + } + }, + path: '.asyncapi-tool' + } + ] +}; + +const duplicateToolFileContent = ` + title: Duplicate Tool + description: This is a duplicate tool. + links: + repoUrl: https://github.com/asyncapi/duplicate-repo + filters: + categories: + - Category1 + `; + +const dataWithUnknownCategoryOnce = { + items: [ + { + name: '.asyncapi-tool-unknown', + url: 'https://api.github.com/repositories/351453552/contents/.asyncapi-tool?ref=unknown1', + repository: { + full_name: 'asyncapi/unknown-repo', + html_url: 'https://github.com/asyncapi/unknown-repo', + description: 'Unknown repository', + owner: { + login: 'asyncapi' + } + }, + path: '.asyncapi-tool' + }, + { + name: '.asyncapi-tool-unknown', + url: 'https://api.github.com/repositories/351453552/contents/.asyncapi-tool?ref=unknown2', + repository: { + full_name: 'asyncapi/unknown-repo', + html_url: 'https://github.com/asyncapi/unknown-repo', + description: 'Unknown repository', + owner: { + login: 'asyncapi' + } + }, + path: '.asyncapi-tool' + } + ] +}; + +const unknownToolFileContent = ` + title: Unknown Tool + description: This tool has an unknown category. + links: + repoUrl: https://github.com/asyncapi/unknown-repo + filters: + categories: + - UnknownCategory + `; + +const invalidToolFileContentJSON = ` + title: Invalid Tool + description: This tool has invalid schema. + links: + repoUrl: https://github.com/asyncapi/invalid-repo + filters: + categories: + - Category1 + invalidField: true + `; + +const invalidJsonContent = ` + title: Invalid Tool + description: This is an invalid JSON + links: + repoUrl: https://github.com/asyncapi/invalid-repo +`; + +const missingToolPropertyContent = ` +title: Missing Property Tool +description: This tool is missing required properties +links: + repoUrl: https://github.com/asyncapi/missing-property +`; + +module.exports = { + mockData, + mockToolFileContent, + toolFileT1, + expectedObjectT1, + repoDescription, + repositoryUrl, + isAsyncAPIrepo, + toolFileT2, + expectedObjectT2, + expectedObjectT3, + dataWithUnknownCategory, + toolFileContent, + invalidToolFileContent, + invalidToolData, + duplicateToolData, + duplicateToolFileContent, + dataWithUnknownCategoryOnce, + unknownToolFileContent, + invalidToolFileContentJSON, + invalidJsonContent, + missingToolPropertyContent +} \ No newline at end of file diff --git a/tests/tools/tools-object.test.js b/tests/tools/tools-object.test.js index 639dbc3830d3..2f2450ffeaef 100644 --- a/tests/tools/tools-object.test.js +++ b/tests/tools/tools-object.test.js @@ -1,6 +1,29 @@ const { convertTools, createToolObject } = require('../../scripts/tools/tools-object'); const axios = require('axios'); +const { mockData, + mockToolFileContent, + toolFileT1, + expectedObjectT1, + repoDescription, + repositoryUrl, + isAsyncAPIrepo, + toolFileT2, + expectedObjectT2, + expectedObjectT3, + dataWithUnknownCategory, + toolFileContent, + invalidToolFileContent, + invalidToolData, + duplicateToolData, + duplicateToolFileContent, + dataWithUnknownCategoryOnce, + unknownToolFileContent, + invalidToolFileContentJSON, + invalidJsonContent, + missingToolPropertyContent +} = require("../fixtures/toolsObjectData") + jest.mock('axios'); jest.mock('../../scripts/tools/categorylist', () => ({ @@ -10,35 +33,6 @@ jest.mock('../../scripts/tools/categorylist', () => ({ ] })); -const mockData = { - items: [ - { - name: '.asyncapi-tool-example', - url: 'https://api.github.com/repositories/351453552/contents/.asyncapi-tool?ref=61855e7365a881e98c2fe667a658a0005753d873', - repository: { - full_name: 'asyncapi/example-repo', - html_url: 'https://github.com/asyncapi/example-repo', - description: 'Example repository', - owner: { - login: 'asyncapi' - } - }, - path: '.asyncapi-tool' - } - ] -}; - -const mockToolFileContent = ` -title: Example Tool -description: This is an example tool. -links: - repoUrl: https://github.com/asyncapi/example-repo -filters: - categories: - - Category1 - hasCommercial: true -`; - describe('Tools Object', () => { beforeEach(() => { @@ -47,67 +41,15 @@ describe('Tools Object', () => { }); it('should create a tool object with provided parameters', async () => { - const toolFile = { - title: 'Example Tool', - description: 'This is an example tool.', - links: { - repoUrl: 'https://github.com/asyncapi/example-repo' - }, - filters: { - categories: ['Category1'], - hasCommercial: true - } - }; - const repositoryUrl = 'https://github.com/asyncapi/example-repo'; - const repoDescription = 'Example repository'; - const isAsyncAPIrepo = true; - - const expectedObject = { - title: 'Example Tool', - description: 'This is an example tool.', - links: { - repoUrl: 'https://github.com/asyncapi/example-repo' - }, - filters: { - categories: ['Category1'], - hasCommercial: true, - isAsyncAPIOwner: true - } - }; - - const result = await createToolObject(toolFile, repositoryUrl, repoDescription, isAsyncAPIrepo); - expect(result).toEqual(expectedObject); + + const result = await createToolObject(toolFileT1, repositoryUrl, repoDescription, isAsyncAPIrepo); + expect(result).toEqual(expectedObjectT1); }); it('should use repoDescription when toolFile.description is not provided', async () => { - const toolFile = { - title: 'Example Tool', - links: { - repoUrl: 'https://github.com/asyncapi/example-repo' - }, - filters: { - categories: ['Category1'] - } - }; - const repositoryUrl = 'https://github.com/asyncapi/example-repo'; - const repoDescription = 'Example repository'; - const isAsyncAPIrepo = true; - - const expectedObject = { - title: 'Example Tool', - description: 'Example repository', - links: { - repoUrl: 'https://github.com/asyncapi/example-repo' - }, - filters: { - categories: ['Category1'], - hasCommercial: false, - isAsyncAPIOwner: true - } - }; - - const result = await createToolObject(toolFile, repositoryUrl, repoDescription, isAsyncAPIrepo); - expect(result).toEqual(expectedObject); + + const result = await createToolObject(toolFileT2, repositoryUrl, repoDescription, isAsyncAPIrepo); + expect(result).toEqual(expectedObjectT2); }); it('should convert tools data correctly', async () => { @@ -115,62 +57,11 @@ describe('Tools Object', () => { const result = await convertTools(mockData); - const expectedObject = { - Category1: { - description: 'Description for Category1', - toolsList: [ - { - title: 'Example Tool', - description: 'This is an example tool.', - links: { - repoUrl: 'https://github.com/asyncapi/example-repo' - }, - filters: { - categories: ['Category1'], - hasCommercial: true, - isAsyncAPIOwner: true - } - } - ] - }, - Others: { - description: 'Other tools category', - toolsList: [] - } - }; - - expect(result).toEqual(expect.objectContaining(expectedObject)); + expect(result).toEqual(expect.objectContaining(expectedObjectT3)); expect(axios.get).toHaveBeenCalledTimes(1); }); it('should assign tool to Others category if no matching category is found', async () => { - const dataWithUnknownCategory = { - items: [ - { - name: '.asyncapi-tool-unknown', - url: 'https://api.github.com/repositories/351453552/contents/.asyncapi-tool?ref=61855e7365a881e98c2fe667a658a0005753d873', - repository: { - full_name: 'asyncapi/unknown-repo', - html_url: 'https://github.com/asyncapi/unknown-repo', - description: 'Unknown repository', - owner: { - login: 'asyncapi' - } - }, - path: '.asyncapi-tool' - } - ] - }; - - const toolFileContent = ` -title: Unknown Tool -description: This tool has an unknown category. -links: - repoUrl: https://github.com/asyncapi/unknown-repo -filters: - categories: - - UnknownCategory -`; axios.get.mockResolvedValue({ data: toolFileContent }); @@ -181,34 +72,6 @@ filters: }); it('should log errors for invalid .asyncapi-tool file', async () => { - const invalidToolFileContent = ` - title: Invalid Tool - description: This tool has invalid schema. - links: - repoUrl: https://github.com/asyncapi/invalid-repo - filters: - categories: - - Category1 - invalidField: true - `; - - const invalidToolData = { - items: [ - { - name: '.asyncapi-tool-invalid', - url: 'https://api.github.com/repositories/351453552/contents/.asyncapi-tool?ref=invalidref', - repository: { - full_name: 'asyncapi/invalid-repo', - html_url: 'https://github.com/asyncapi/invalid-repo', - description: 'Invalid repository', - owner: { - login: 'asyncapi' - } - }, - path: '.asyncapi-tool' - } - ] - }; axios.get.mockResolvedValue({ data: invalidToolFileContent }); @@ -229,46 +92,6 @@ filters: }); it('should add duplicate tool objects to the same category', async () => { - const duplicateToolData = { - items: [ - { - name: '.asyncapi-tool-duplicate', - url: 'https://api.github.com/repositories/351453552/contents/.asyncapi-tool?ref=duplicate1', - repository: { - full_name: 'asyncapi/duplicate-repo', - html_url: 'https://github.com/asyncapi/duplicate-repo', - description: 'Duplicate repository', - owner: { - login: 'asyncapi' - } - }, - path: '.asyncapi-tool' - }, - { - name: '.asyncapi-tool-duplicate', - url: 'https://api.github.com/repositories/351453552/contents/.asyncapi-tool?ref=duplicate2', - repository: { - full_name: 'asyncapi/duplicate-repo', - html_url: 'https://github.com/asyncapi/duplicate-repo', - description: 'Duplicate repository', - owner: { - login: 'asyncapi' - } - }, - path: '.asyncapi-tool' - } - ] - }; - - const duplicateToolFileContent = ` - title: Duplicate Tool - description: This is a duplicate tool. - links: - repoUrl: https://github.com/asyncapi/duplicate-repo - filters: - categories: - - Category1 - `; axios.get.mockResolvedValue({ data: duplicateToolFileContent }); @@ -280,50 +103,10 @@ filters: }); it('should add tool to Others category only once', async () => { - const dataWithUnknownCategory = { - items: [ - { - name: '.asyncapi-tool-unknown', - url: 'https://api.github.com/repositories/351453552/contents/.asyncapi-tool?ref=unknown1', - repository: { - full_name: 'asyncapi/unknown-repo', - html_url: 'https://github.com/asyncapi/unknown-repo', - description: 'Unknown repository', - owner: { - login: 'asyncapi' - } - }, - path: '.asyncapi-tool' - }, - { - name: '.asyncapi-tool-unknown', - url: 'https://api.github.com/repositories/351453552/contents/.asyncapi-tool?ref=unknown2', - repository: { - full_name: 'asyncapi/unknown-repo', - html_url: 'https://github.com/asyncapi/unknown-repo', - description: 'Unknown repository', - owner: { - login: 'asyncapi' - } - }, - path: '.asyncapi-tool' - } - ] - }; - - const unknownToolFileContent = ` - title: Unknown Tool - description: This tool has an unknown category. - links: - repoUrl: https://github.com/asyncapi/unknown-repo - filters: - categories: - - UnknownCategory - `; axios.get.mockResolvedValue({ data: unknownToolFileContent }); - const result = await convertTools(dataWithUnknownCategory); + const result = await convertTools(dataWithUnknownCategoryOnce); const uniqueTools = result.Others.toolsList.filter((tool, index, self) => index === self.findIndex((t) => t.title === tool.title) @@ -344,18 +127,8 @@ filters: }); it('should throw an error if JSON schema validation fails', async () => { - const invalidToolFileContent = ` - title: Invalid Tool - description: This tool has invalid schema. - links: - repoUrl: https://github.com/asyncapi/invalid-repo - filters: - categories: - - Category1 - invalidField: true - `; - axios.get.mockResolvedValue({ data: invalidToolFileContent }); + axios.get.mockResolvedValue({ data: invalidToolFileContentJSON }); try { await convertTools(mockData); @@ -366,12 +139,6 @@ filters: }); it('should throw an error if toolFile cannot be converted to JSON', async () => { - const invalidJsonContent = ` - title: Invalid Tool - description: This is an invalid JSON - links: - repoUrl: https://github.com/asyncapi/invalid-repo - `; axios.get.mockResolvedValue({ data: invalidJsonContent }); @@ -390,12 +157,6 @@ filters: }); it('should throw an error if a required tool property is missing', async () => { - const missingToolPropertyContent = ` - title: Missing Property Tool - description: This tool is missing required properties - links: - repoUrl: https://github.com/asyncapi/missing-property - `; axios.get.mockResolvedValue({ data: missingToolPropertyContent }); From 5d4771bd30d46aaf0645cc5ec946cc9dcdac41d6 Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Mon, 30 Sep 2024 13:46:51 +0530 Subject: [PATCH 06/43] fwqf --- tests/tools/tools-object.test.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/tools/tools-object.test.js b/tests/tools/tools-object.test.js index 2f2450ffeaef..3b9c5383b5b5 100644 --- a/tests/tools/tools-object.test.js +++ b/tests/tools/tools-object.test.js @@ -77,8 +77,6 @@ describe('Tools Object', () => { await convertTools(invalidToolData); - console.log('All console.error calls:', console.error.mock.calls); - const allErrorMessages = console.error.mock.calls.flat(); expect(allErrorMessages).toEqual( expect.arrayContaining([ From 403bb4e42ce59b2c9ead36ddab60fdc11c3d9601 Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Fri, 4 Oct 2024 11:13:22 +0530 Subject: [PATCH 07/43] wfwqf --- tests/build-tools.test.js | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/build-tools.test.js b/tests/build-tools.test.js index 2bc4592e8e11..e86dd50d77fb 100644 --- a/tests/build-tools.test.js +++ b/tests/build-tools.test.js @@ -86,4 +86,5 @@ describe('buildTools', () => { expect(err.message).toMatch(/ENOENT|EACCES/); } }); + }); From 9d7415287dc7691ad7b0b0d4f67b5ad984b0bd10 Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Fri, 4 Oct 2024 11:19:55 +0530 Subject: [PATCH 08/43] fwgff --- tests/tools/tools-object.test.js | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/tools/tools-object.test.js b/tests/tools/tools-object.test.js index 3b9c5383b5b5..81bcf56fdb13 100644 --- a/tests/tools/tools-object.test.js +++ b/tests/tools/tools-object.test.js @@ -175,4 +175,3 @@ describe('Tools Object', () => { }); }); - From 3e2059358500496b4b3353be6e001e64243757d6 Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Fri, 4 Oct 2024 12:12:12 +0530 Subject: [PATCH 09/43] updated test for errors --- tests/fixtures/toolsObjectData.js | 30 ++++---------- tests/tools/tools-object.test.js | 66 +++++++++---------------------- 2 files changed, 26 insertions(+), 70 deletions(-) diff --git a/tests/fixtures/toolsObjectData.js b/tests/fixtures/toolsObjectData.js index 96b425f523e8..3d478712d79e 100644 --- a/tests/fixtures/toolsObjectData.js +++ b/tests/fixtures/toolsObjectData.js @@ -242,31 +242,17 @@ const unknownToolFileContent = ` - UnknownCategory `; -const invalidToolFileContentJSON = ` - title: Invalid Tool - description: This tool has invalid schema. +// New Fixtures for Error Handling Tests +const toolFileMalformedJSON = ` + title: Malformed Tool + description: This tool has malformed JSON. links: - repoUrl: https://github.com/asyncapi/invalid-repo - filters: + repoUrl: https://github.com/asyncapi/malformed-repo + filters categories: - Category1 - invalidField: true `; -const invalidJsonContent = ` - title: Invalid Tool - description: This is an invalid JSON - links: - repoUrl: https://github.com/asyncapi/invalid-repo -`; - -const missingToolPropertyContent = ` -title: Missing Property Tool -description: This tool is missing required properties -links: - repoUrl: https://github.com/asyncapi/missing-property -`; - module.exports = { mockData, mockToolFileContent, @@ -286,7 +272,5 @@ module.exports = { duplicateToolFileContent, dataWithUnknownCategoryOnce, unknownToolFileContent, - invalidToolFileContentJSON, - invalidJsonContent, - missingToolPropertyContent + toolFileMalformedJSON, } \ No newline at end of file diff --git a/tests/tools/tools-object.test.js b/tests/tools/tools-object.test.js index 81bcf56fdb13..d88ba4092d10 100644 --- a/tests/tools/tools-object.test.js +++ b/tests/tools/tools-object.test.js @@ -19,9 +19,7 @@ const { mockData, duplicateToolFileContent, dataWithUnknownCategoryOnce, unknownToolFileContent, - invalidToolFileContentJSON, - invalidJsonContent, - missingToolPropertyContent + toolFileMalformedJSON, } = require("../fixtures/toolsObjectData") jest.mock('axios'); @@ -75,7 +73,14 @@ describe('Tools Object', () => { axios.get.mockResolvedValue({ data: invalidToolFileContent }); - await convertTools(invalidToolData); + let error; + try { + await convertTools(invalidToolData); + } catch (err) { + error = err; + } + + expect(error).toBeUndefined(); const allErrorMessages = console.error.mock.calls.flat(); expect(allErrorMessages).toEqual( @@ -115,63 +120,30 @@ describe('Tools Object', () => { }); it('should throw an error if axios.get fails', async () => { + let error; axios.get.mockRejectedValue(new Error('Network Error')); try { await convertTools(mockData) } catch (err) { + error = err; expect(err.message).toContain("Network Error") } + expect(error).toBeDefined(); }); - it('should throw an error if JSON schema validation fails', async () => { - - axios.get.mockResolvedValue({ data: invalidToolFileContentJSON }); - - try { - await convertTools(mockData); - } catch (err) { - expect(err).toBeInstanceOf(Error); - expect(err.message).toContain('Invalid .asyncapi-tool file'); - } - }); - - it('should throw an error if toolFile cannot be converted to JSON', async () => { - - axios.get.mockResolvedValue({ data: invalidJsonContent }); - - jest.doMock('../../scripts/utils', () => ({ - convertToJson: jest.fn(() => { - throw new Error('Invalid JSON format'); - }) - })); + it('should handle malformed JSON in tool file', async () => { + axios.get.mockResolvedValue({ data: toolFileMalformedJSON }); + let error; try { await convertTools(mockData); } catch (err) { - expect(err).toBeInstanceOf(Error); - expect(err.message).toBe('Error processing tool: Invalid JSON format'); + error = err; + expect(err.message).toContain('Unexpected token'); } - }); - - it('should throw an error if a required tool property is missing', async () => { - - axios.get.mockResolvedValue({ data: missingToolPropertyContent }); - jest.doMock('../../scripts/utils', () => ({ - convertToJson: jest.fn(() => { - return { - title: 'Missing Property Tool', - }; - }) - })); - - try { - await convertTools(mockData); - } catch (err) { - expect(err).toBeInstanceOf(Error); - expect(err.message).toContain('Missing required tool properties'); - } + expect(error).toBeDefined(); }); -}); +}); \ No newline at end of file From 5000a47666c8f8fccf8a0ad26dd3160100809c9f Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Fri, 4 Oct 2024 12:14:30 +0530 Subject: [PATCH 10/43] updated test for errors --- tests/fixtures/toolsObjectData.js | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/fixtures/toolsObjectData.js b/tests/fixtures/toolsObjectData.js index 3d478712d79e..4c5fbb9bf436 100644 --- a/tests/fixtures/toolsObjectData.js +++ b/tests/fixtures/toolsObjectData.js @@ -242,7 +242,6 @@ const unknownToolFileContent = ` - UnknownCategory `; -// New Fixtures for Error Handling Tests const toolFileMalformedJSON = ` title: Malformed Tool description: This tool has malformed JSON. From 56b0fddecbaa2ba080572a12fb6c22104be529e7 Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Mon, 7 Oct 2024 16:16:28 +0530 Subject: [PATCH 11/43] renamed a variabel --- tests/fixtures/toolsObjectData.js | 4 ++-- tests/tools/tools-object.test.js | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/fixtures/toolsObjectData.js b/tests/fixtures/toolsObjectData.js index 4c5fbb9bf436..305013059862 100644 --- a/tests/fixtures/toolsObjectData.js +++ b/tests/fixtures/toolsObjectData.js @@ -54,7 +54,7 @@ const expectedObjectT1 = { const repositoryUrl = 'https://github.com/asyncapi/example-repo'; const repoDescription = 'Example repository'; -const isAsyncAPIrepo = true; +const isAsyncAPIOwner = true; const toolFileT2 = { title: 'Example Tool', @@ -259,7 +259,7 @@ module.exports = { expectedObjectT1, repoDescription, repositoryUrl, - isAsyncAPIrepo, + isAsyncAPIOwner, toolFileT2, expectedObjectT2, expectedObjectT3, diff --git a/tests/tools/tools-object.test.js b/tests/tools/tools-object.test.js index d88ba4092d10..aa57008b835f 100644 --- a/tests/tools/tools-object.test.js +++ b/tests/tools/tools-object.test.js @@ -7,7 +7,7 @@ const { mockData, expectedObjectT1, repoDescription, repositoryUrl, - isAsyncAPIrepo, + isAsyncAPIOwner, toolFileT2, expectedObjectT2, expectedObjectT3, @@ -40,13 +40,13 @@ describe('Tools Object', () => { it('should create a tool object with provided parameters', async () => { - const result = await createToolObject(toolFileT1, repositoryUrl, repoDescription, isAsyncAPIrepo); + const result = await createToolObject(toolFileT1, repositoryUrl, repoDescription, isAsyncAPIOwner); expect(result).toEqual(expectedObjectT1); }); it('should use repoDescription when toolFile.description is not provided', async () => { - const result = await createToolObject(toolFileT2, repositoryUrl, repoDescription, isAsyncAPIrepo); + const result = await createToolObject(toolFileT2, repositoryUrl, repoDescription, isAsyncAPIOwner); expect(result).toEqual(expectedObjectT2); }); From f51feb335a8a9e3a13e231e7afd96621a5deead4 Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Sun, 13 Oct 2024 23:01:26 +0530 Subject: [PATCH 12/43] test updated --- tests/build-tools.test.js | 1 - tests/fixtures/toolsObjectData.js | 97 ++++++++++++++++--------------- tests/tools/tools-object.test.js | 3 +- 3 files changed, 52 insertions(+), 49 deletions(-) diff --git a/tests/build-tools.test.js b/tests/build-tools.test.js index e86dd50d77fb..2bc4592e8e11 100644 --- a/tests/build-tools.test.js +++ b/tests/build-tools.test.js @@ -86,5 +86,4 @@ describe('buildTools', () => { expect(err.message).toMatch(/ENOENT|EACCES/); } }); - }); diff --git a/tests/fixtures/toolsObjectData.js b/tests/fixtures/toolsObjectData.js index 305013059862..24865e0065d8 100644 --- a/tests/fixtures/toolsObjectData.js +++ b/tests/fixtures/toolsObjectData.js @@ -16,16 +16,17 @@ const mockData = { ] }; -const mockToolFileContent = ` - title: Example Tool - description: This is an example tool. - links: - repoUrl: https://github.com/asyncapi/example-repo - filters: - categories: - - Category1 +const mockToolFileContent = { + title: "Example Tool", + description: "This is an example tool.", + links: { + repoUrl: "https://github.com/asyncapi/example-repo" + }, + filters: { + categories: ["Category1"], hasCommercial: true - `; + } +}; const toolFileT1 = { title: 'Example Tool', @@ -121,26 +122,28 @@ const dataWithUnknownCategory = { ] }; -const toolFileContent = ` - title: Unknown Tool - description: This tool has an unknown category. - links: - repoUrl: https://github.com/asyncapi/unknown-repo - filters: - categories: - - UnknownCategory - `; +const toolFileContent = { + title: "Unknown Tool", + description: "This tool has an unknown category.", + links: { + repoUrl: "https://github.com/asyncapi/unknown-repo" + }, + filters: { + categories: ["UnknownCategory"] + } +}; -const invalidToolFileContent = ` - title: Invalid Tool - description: This tool has invalid schema. - links: - repoUrl: https://github.com/asyncapi/invalid-repo - filters: - categories: - - Category1 +const invalidToolFileContent = { + title: "Invalid Tool", + description: "This tool has invalid schema.", + links: { + repoUrl: "https://github.com/asyncapi/invalid-repo" + }, + filters: { + categories: ["Category1"], invalidField: true - `; + } +}; const invalidToolData = { items: [ @@ -191,15 +194,16 @@ const duplicateToolData = { ] }; -const duplicateToolFileContent = ` - title: Duplicate Tool - description: This is a duplicate tool. - links: - repoUrl: https://github.com/asyncapi/duplicate-repo - filters: - categories: - - Category1 - `; +const duplicateToolFileContent = { + title: "Duplicate Tool", + description: "This is a duplicate tool.", + links: { + repoUrl: "https://github.com/asyncapi/duplicate-repo" + }, + filters: { + categories: ["Category1"] + } +}; const dataWithUnknownCategoryOnce = { items: [ @@ -232,15 +236,16 @@ const dataWithUnknownCategoryOnce = { ] }; -const unknownToolFileContent = ` - title: Unknown Tool - description: This tool has an unknown category. - links: - repoUrl: https://github.com/asyncapi/unknown-repo - filters: - categories: - - UnknownCategory - `; +const unknownToolFileContent = { + title: "Unknown Tool", + description: "This tool has an unknown category.", + links: { + repoUrl: "https://github.com/asyncapi/unknown-repo" + }, + filters: { + categories: ["UnknownCategory"] + } +}; const toolFileMalformedJSON = ` title: Malformed Tool @@ -272,4 +277,4 @@ module.exports = { dataWithUnknownCategoryOnce, unknownToolFileContent, toolFileMalformedJSON, -} \ No newline at end of file +}; diff --git a/tests/tools/tools-object.test.js b/tests/tools/tools-object.test.js index aa57008b835f..7706e24572fd 100644 --- a/tests/tools/tools-object.test.js +++ b/tests/tools/tools-object.test.js @@ -140,10 +140,9 @@ describe('Tools Object', () => { await convertTools(mockData); } catch (err) { error = err; - expect(err.message).toContain('Unexpected token'); } - expect(error).toBeDefined(); + expect(error.message).toContain('Unexpected token'); }); }); \ No newline at end of file From 3e73220c34a191ffa9ed6561e2e9919c92dbe77d Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Wed, 16 Oct 2024 19:04:55 +0530 Subject: [PATCH 13/43] path update --- scripts/build-tools.js | 10 +++++----- tests/build-tools.test.js | 14 +++++++------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/scripts/build-tools.js b/scripts/build-tools.js index 84965815dcc4..05c9e85bcb94 100644 --- a/scripts/build-tools.js +++ b/scripts/build-tools.js @@ -2,7 +2,7 @@ const { getData } = require('./tools/extract-tools-github'); const { convertTools } = require('./tools/tools-object'); const { combineTools } = require('./tools/combine-tools'); const fs = require('fs'); -const { resolve } = require('path'); +const path = require('path'); const buildTools = async (automatedToolsPath, manualToolsPath, toolsPath, tagsPath) => { try { @@ -22,10 +22,10 @@ const buildTools = async (automatedToolsPath, manualToolsPath, toolsPath, tagsPa /* istanbul ignore next */ if (require.main === module) { - const automatedToolsPath = resolve(__dirname, '../config', 'tools-automated.json'); - const manualToolsPath = resolve(__dirname, '../config', 'tools-manual.json'); - const toolsPath = resolve(__dirname, '../config', 'tools.json'); - const tagsPath = resolve(__dirname, '../config', 'all-tags.json'); + const automatedToolsPath = path.join(__dirname, '../config', 'tools-automated.json'); + const manualToolsPath = path.join(__dirname, '../config', 'tools-manual.json'); + const toolsPath = path.join(__dirname, '../config', 'tools.json'); + const tagsPath = path.join(__dirname, '../config', 'all-tags.json'); buildTools(automatedToolsPath, manualToolsPath, toolsPath, tagsPath); } diff --git a/tests/build-tools.test.js b/tests/build-tools.test.js index 2bc4592e8e11..c8d0a029079e 100644 --- a/tests/build-tools.test.js +++ b/tests/build-tools.test.js @@ -1,5 +1,5 @@ const axios = require('axios'); -const { resolve } = require('path'); +const path = require('path'); const { buildTools } = require('../scripts/build-tools'); const { tagsData, manualTools, mockConvertedData, mockExtractData } = require('../tests/fixtures/buildToolsData'); const fs = require('fs'); @@ -24,11 +24,11 @@ jest.mock('../scripts/tools/tags-color', () => ({ })); describe('buildTools', () => { - const testDir = resolve(__dirname, 'test_config'); - const toolsPath = resolve(testDir, 'tools.json'); - const tagsPath = resolve(testDir, 'all-tags.json'); - const automatedToolsPath = resolve(testDir, 'tools-automated.json'); - const manualToolsPath = resolve(testDir, 'tools-manual.json'); + const testDir = path.join(__dirname, 'test_config'); + const toolsPath = path.join(testDir, 'tools.json'); + const tagsPath = path.join(testDir, 'all-tags.json'); + const automatedToolsPath = path.join(testDir, 'tools-automated.json'); + const manualToolsPath = path.join(testDir, 'tools-manual.json'); beforeAll(() => { fs.mkdirSync(testDir, { recursive: true }); @@ -78,7 +78,7 @@ describe('buildTools', () => { it('should handle file write errors', async () => { axios.get.mockResolvedValue({ data: mockExtractData }); - const invalidPath = '/invalid_dir/tools.json'; + const invalidPath = path.join('/invalid_dir', 'tools.json'); try { await buildTools(invalidPath, manualToolsPath, toolsPath, tagsPath); From d31a06fb9e2092d9f9280cf431986aff98bad24d Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Wed, 16 Oct 2024 19:11:27 +0530 Subject: [PATCH 14/43] commit to rerun workflow --- scripts/build-tools.js | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/build-tools.js b/scripts/build-tools.js index 05c9e85bcb94..6af262eee69a 100644 --- a/scripts/build-tools.js +++ b/scripts/build-tools.js @@ -22,6 +22,7 @@ const buildTools = async (automatedToolsPath, manualToolsPath, toolsPath, tagsPa /* istanbul ignore next */ if (require.main === module) { + const automatedToolsPath = path.join(__dirname, '../config', 'tools-automated.json'); const manualToolsPath = path.join(__dirname, '../config', 'tools-manual.json'); const toolsPath = path.join(__dirname, '../config', 'tools.json'); From 03f9dc17be307abdbef4aab1e099d4865523f13c Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Wed, 16 Oct 2024 19:11:46 +0530 Subject: [PATCH 15/43] commit to rerun workflow --- scripts/build-tools.js | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/build-tools.js b/scripts/build-tools.js index 6af262eee69a..05c9e85bcb94 100644 --- a/scripts/build-tools.js +++ b/scripts/build-tools.js @@ -22,7 +22,6 @@ const buildTools = async (automatedToolsPath, manualToolsPath, toolsPath, tagsPa /* istanbul ignore next */ if (require.main === module) { - const automatedToolsPath = path.join(__dirname, '../config', 'tools-automated.json'); const manualToolsPath = path.join(__dirname, '../config', 'tools-manual.json'); const toolsPath = path.join(__dirname, '../config', 'tools.json'); From bfc9e6e1dc700cf4cac0ecfb8f648c2d75475697 Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Fri, 18 Oct 2024 10:55:11 +0530 Subject: [PATCH 16/43] fefewg --- scripts/build-tools.js | 10 +++++----- tests/build-tools.test.js | 14 +++++++------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/scripts/build-tools.js b/scripts/build-tools.js index 05c9e85bcb94..84965815dcc4 100644 --- a/scripts/build-tools.js +++ b/scripts/build-tools.js @@ -2,7 +2,7 @@ const { getData } = require('./tools/extract-tools-github'); const { convertTools } = require('./tools/tools-object'); const { combineTools } = require('./tools/combine-tools'); const fs = require('fs'); -const path = require('path'); +const { resolve } = require('path'); const buildTools = async (automatedToolsPath, manualToolsPath, toolsPath, tagsPath) => { try { @@ -22,10 +22,10 @@ const buildTools = async (automatedToolsPath, manualToolsPath, toolsPath, tagsPa /* istanbul ignore next */ if (require.main === module) { - const automatedToolsPath = path.join(__dirname, '../config', 'tools-automated.json'); - const manualToolsPath = path.join(__dirname, '../config', 'tools-manual.json'); - const toolsPath = path.join(__dirname, '../config', 'tools.json'); - const tagsPath = path.join(__dirname, '../config', 'all-tags.json'); + const automatedToolsPath = resolve(__dirname, '../config', 'tools-automated.json'); + const manualToolsPath = resolve(__dirname, '../config', 'tools-manual.json'); + const toolsPath = resolve(__dirname, '../config', 'tools.json'); + const tagsPath = resolve(__dirname, '../config', 'all-tags.json'); buildTools(automatedToolsPath, manualToolsPath, toolsPath, tagsPath); } diff --git a/tests/build-tools.test.js b/tests/build-tools.test.js index c8d0a029079e..2bc4592e8e11 100644 --- a/tests/build-tools.test.js +++ b/tests/build-tools.test.js @@ -1,5 +1,5 @@ const axios = require('axios'); -const path = require('path'); +const { resolve } = require('path'); const { buildTools } = require('../scripts/build-tools'); const { tagsData, manualTools, mockConvertedData, mockExtractData } = require('../tests/fixtures/buildToolsData'); const fs = require('fs'); @@ -24,11 +24,11 @@ jest.mock('../scripts/tools/tags-color', () => ({ })); describe('buildTools', () => { - const testDir = path.join(__dirname, 'test_config'); - const toolsPath = path.join(testDir, 'tools.json'); - const tagsPath = path.join(testDir, 'all-tags.json'); - const automatedToolsPath = path.join(testDir, 'tools-automated.json'); - const manualToolsPath = path.join(testDir, 'tools-manual.json'); + const testDir = resolve(__dirname, 'test_config'); + const toolsPath = resolve(testDir, 'tools.json'); + const tagsPath = resolve(testDir, 'all-tags.json'); + const automatedToolsPath = resolve(testDir, 'tools-automated.json'); + const manualToolsPath = resolve(testDir, 'tools-manual.json'); beforeAll(() => { fs.mkdirSync(testDir, { recursive: true }); @@ -78,7 +78,7 @@ describe('buildTools', () => { it('should handle file write errors', async () => { axios.get.mockResolvedValue({ data: mockExtractData }); - const invalidPath = path.join('/invalid_dir', 'tools.json'); + const invalidPath = '/invalid_dir/tools.json'; try { await buildTools(invalidPath, manualToolsPath, toolsPath, tagsPath); From 9c1ef9e36387c9af59d5e3652ad0715a1301345c Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Fri, 18 Oct 2024 21:31:32 +0530 Subject: [PATCH 17/43] supress logs --- tests/build-tools.test.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/build-tools.test.js b/tests/build-tools.test.js index 2bc4592e8e11..d1de02f54352 100644 --- a/tests/build-tools.test.js +++ b/tests/build-tools.test.js @@ -29,14 +29,17 @@ describe('buildTools', () => { const tagsPath = resolve(testDir, 'all-tags.json'); const automatedToolsPath = resolve(testDir, 'tools-automated.json'); const manualToolsPath = resolve(testDir, 'tools-manual.json'); + let consoleErrorMock; beforeAll(() => { fs.mkdirSync(testDir, { recursive: true }); fs.writeFileSync(manualToolsPath, JSON.stringify(manualTools)); + consoleErrorMock = jest.spyOn(console, 'error').mockImplementation(() => {}); }); afterAll(() => { fs.rmSync(testDir, { recursive: true, force: true }); + consoleErrorMock.mockRestore(); }); beforeEach(() => { From a1af4f70b96ddbd50b87d4d448faaf9ccf95c626 Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Fri, 18 Oct 2024 21:36:37 +0530 Subject: [PATCH 18/43] newsroom test update --- tests/build-newsroom-videos.test.js | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/tests/build-newsroom-videos.test.js b/tests/build-newsroom-videos.test.js index 63f571466944..c6ef40c838c2 100644 --- a/tests/build-newsroom-videos.test.js +++ b/tests/build-newsroom-videos.test.js @@ -1,4 +1,4 @@ -const { readFileSync, rmSync, mkdirSync } = require('fs'); +const { readFileSync, rmSync, mkdirSync, existsSync } = require('fs'); const { resolve } = require('path'); const { buildNewsroomVideos } = require('../scripts/build-newsroom-videos'); const { mockApiResponse, expectedResult } = require('./fixtures/newsroomData'); @@ -11,12 +11,16 @@ describe('buildNewsroomVideos', () => { const testFilePath = resolve(testDir, 'newsroom_videos.json'); beforeAll(() => { - mkdirSync(testDir, { recursive: true }); + if (!existsSync(testDir)) { + mkdirSync(testDir, { recursive: true }); + } process.env.YOUTUBE_TOKEN = 'testkey'; }); afterAll(() => { - rmSync(testDir, { recursive: true, force: true }); + if (existsSync(testDir)) { + rmSync(testDir, { recursive: true, force: true }); + } }); beforeEach(() => { @@ -29,6 +33,10 @@ describe('buildNewsroomVideos', () => { json: jest.fn().mockResolvedValue(mockApiResponse), }); + if (!existsSync(testDir)) { + mkdirSync(testDir, { recursive: true }); + } + const result = await buildNewsroomVideos(testFilePath); const expectedUrl = new URL('https://youtube.googleapis.com/youtube/v3/search'); @@ -41,6 +49,7 @@ describe('buildNewsroomVideos', () => { expectedUrl.searchParams.set('maxResults', '5'); expect(fetch).toHaveBeenCalledWith(expectedUrl.toString()); + const response = readFileSync(testFilePath, 'utf8'); expect(response).toEqual(expectedResult); expect(result).toEqual(expectedResult); @@ -97,5 +106,4 @@ describe('buildNewsroomVideos', () => { expect(err.message).toMatch(/ENOENT|EACCES/); } }); - }); From 9d38d419972b9618daeedcd10cc68e2a10a3ac63 Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Fri, 18 Oct 2024 21:40:44 +0530 Subject: [PATCH 19/43] build-tools test update --- tests/build-tools.test.js | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/tests/build-tools.test.js b/tests/build-tools.test.js index d1de02f54352..7be2e5148e85 100644 --- a/tests/build-tools.test.js +++ b/tests/build-tools.test.js @@ -32,13 +32,19 @@ describe('buildTools', () => { let consoleErrorMock; beforeAll(() => { - fs.mkdirSync(testDir, { recursive: true }); - fs.writeFileSync(manualToolsPath, JSON.stringify(manualTools)); + if (!fs.existsSync(testDir)) { + fs.mkdirSync(testDir, { recursive: true }); + } + if (!fs.existsSync(manualToolsPath)) { + fs.writeFileSync(manualToolsPath, JSON.stringify(manualTools)); + } consoleErrorMock = jest.spyOn(console, 'error').mockImplementation(() => {}); }); afterAll(() => { - fs.rmSync(testDir, { recursive: true, force: true }); + if (fs.existsSync(testDir)) { + fs.rmSync(testDir, { recursive: true, force: true }); + } consoleErrorMock.mockRestore(); }); @@ -49,6 +55,10 @@ describe('buildTools', () => { it('should extract, convert, combine tools, and write to file', async () => { axios.get.mockResolvedValue({ data: mockExtractData }); + if (!fs.existsSync(testDir)) { + fs.mkdirSync(testDir, { recursive: true }); + } + await buildTools(automatedToolsPath, manualToolsPath, toolsPath, tagsPath); const automatedToolsContent = JSON.parse(fs.readFileSync(automatedToolsPath, 'utf8')); @@ -65,7 +75,6 @@ describe('buildTools', () => { expect(combinedToolsContent["Category2"].description).toEqual(mockConvertedData["Category2"].description); expect(tagsContent).toEqual(tagsData); - }); it('should handle getData error', async () => { From 08a89709c375149457d20952bf8932fc099b9435 Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Fri, 18 Oct 2024 21:54:54 +0530 Subject: [PATCH 20/43] uupdate newsroom function --- scripts/build-newsroom-videos.js | 8 ++++++-- tests/build-newsroom-videos.test.js | 6 +++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/scripts/build-newsroom-videos.js b/scripts/build-newsroom-videos.js index b67ee0378cf2..f8a06787bdf5 100644 --- a/scripts/build-newsroom-videos.js +++ b/scripts/build-newsroom-videos.js @@ -1,9 +1,13 @@ -const { writeFileSync } = require('fs'); -const { resolve } = require('path'); +const { writeFileSync, mkdirSync, existsSync } = require('fs'); +const { resolve, dirname } = require('path'); const fetch = require('node-fetch-2'); async function buildNewsroomVideos(writePath) { try { + const dir = dirname(writePath); + if (!existsSync(dir)) { + mkdirSync(dir, { recursive: true }); + } const response = await fetch('https://youtube.googleapis.com/youtube/v3/search?' + new URLSearchParams({ key: process.env.YOUTUBE_TOKEN, part: 'snippet', diff --git a/tests/build-newsroom-videos.test.js b/tests/build-newsroom-videos.test.js index c6ef40c838c2..704b479fa0e3 100644 --- a/tests/build-newsroom-videos.test.js +++ b/tests/build-newsroom-videos.test.js @@ -11,9 +11,6 @@ describe('buildNewsroomVideos', () => { const testFilePath = resolve(testDir, 'newsroom_videos.json'); beforeAll(() => { - if (!existsSync(testDir)) { - mkdirSync(testDir, { recursive: true }); - } process.env.YOUTUBE_TOKEN = 'testkey'; }); @@ -24,6 +21,9 @@ describe('buildNewsroomVideos', () => { }); beforeEach(() => { + if (!existsSync(testDir)) { + mkdirSync(testDir, { recursive: true }); + } fetch.mockClear(); }); From cb902549199cb58e2c87b226069a680220a605f9 Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Fri, 18 Oct 2024 21:57:01 +0530 Subject: [PATCH 21/43] update build-tools function --- scripts/build-tools.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/scripts/build-tools.js b/scripts/build-tools.js index 84965815dcc4..3ba810cc245f 100644 --- a/scripts/build-tools.js +++ b/scripts/build-tools.js @@ -2,13 +2,17 @@ const { getData } = require('./tools/extract-tools-github'); const { convertTools } = require('./tools/tools-object'); const { combineTools } = require('./tools/combine-tools'); const fs = require('fs'); -const { resolve } = require('path'); +const { resolve, dirname } = require('path'); const buildTools = async (automatedToolsPath, manualToolsPath, toolsPath, tagsPath) => { try { let githubExtractData = await getData(); let automatedTools = await convertTools(githubExtractData); - + + const automatedDir = dirname(automatedToolsPath); + if (!fs.existsSync(automatedDir)) { + fs.mkdirSync(automatedDir, { recursive: true }); + } fs.writeFileSync( automatedToolsPath, JSON.stringify(automatedTools, null, ' ') From d16f9a11051d4d638df7b92ff493ffe7490ed2bc Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Fri, 18 Oct 2024 22:00:49 +0530 Subject: [PATCH 22/43] commit to re run the workflow --- scripts/build-tools.js | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/build-tools.js b/scripts/build-tools.js index 3ba810cc245f..d3e4d6c10897 100644 --- a/scripts/build-tools.js +++ b/scripts/build-tools.js @@ -10,6 +10,7 @@ const buildTools = async (automatedToolsPath, manualToolsPath, toolsPath, tagsPa let automatedTools = await convertTools(githubExtractData); const automatedDir = dirname(automatedToolsPath); + if (!fs.existsSync(automatedDir)) { fs.mkdirSync(automatedDir, { recursive: true }); } From 4540530a037894b5c9bc1164c68e1d7d34d57c57 Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Sat, 19 Oct 2024 11:05:32 +0530 Subject: [PATCH 23/43] added retry mechanicasm for enoent errors --- scripts/build-newsroom-videos.js | 24 +++++++++++++++++++++--- scripts/build-tools.js | 23 +++++++++++++++++++---- 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/scripts/build-newsroom-videos.js b/scripts/build-newsroom-videos.js index f8a06787bdf5..f4cf83066925 100644 --- a/scripts/build-newsroom-videos.js +++ b/scripts/build-newsroom-videos.js @@ -5,9 +5,11 @@ const fetch = require('node-fetch-2'); async function buildNewsroomVideos(writePath) { try { const dir = dirname(writePath); + if (!existsSync(dir)) { mkdirSync(dir, { recursive: true }); } + const response = await fetch('https://youtube.googleapis.com/youtube/v3/search?' + new URLSearchParams({ key: process.env.YOUTUBE_TOKEN, part: 'snippet', @@ -23,7 +25,6 @@ async function buildNewsroomVideos(writePath) { } 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'); @@ -39,7 +40,7 @@ async function buildNewsroomVideos(writePath) { const videoData = JSON.stringify(videoDataItems, null, ' '); console.log('The following are the Newsroom Youtube videos: ', videoData); - writeFileSync(writePath, videoData); + await retryWriteFile(writePath, videoData); return videoData; } catch (err) { @@ -47,9 +48,26 @@ async function buildNewsroomVideos(writePath) { } } +async function retryWriteFile(filePath, data, retries = 3, delay = 1000) { + for (let attempt = 0; attempt < retries; attempt++) { + try { + writeFileSync(filePath, data); + console.log(`File written successfully to ${filePath}`); + break; + } catch (err) { + if (err.code === 'ENOENT') { + console.error(`ENOENT error on attempt ${attempt + 1}. Retrying in ${delay}ms...`); + await new Promise((resolve) => setTimeout(resolve, delay)); + } else { + throw err; + } + } + } +} + /* istanbul ignore next */ if (require.main === module) { - buildNewsroomVideos(resolve(__dirname, '../config', 'newsroom_videos.json')) + buildNewsroomVideos(resolve(__dirname, '../config', 'newsroom_videos.json')); } module.exports = { buildNewsroomVideos }; diff --git a/scripts/build-tools.js b/scripts/build-tools.js index d3e4d6c10897..2b7c47768f78 100644 --- a/scripts/build-tools.js +++ b/scripts/build-tools.js @@ -14,10 +14,8 @@ const buildTools = async (automatedToolsPath, manualToolsPath, toolsPath, tagsPa if (!fs.existsSync(automatedDir)) { fs.mkdirSync(automatedDir, { recursive: true }); } - fs.writeFileSync( - automatedToolsPath, - JSON.stringify(automatedTools, null, ' ') - ); + + await retryWriteFile(automatedToolsPath, JSON.stringify(automatedTools, null, ' ')); await combineTools(automatedTools, require(manualToolsPath), toolsPath, tagsPath); } catch (err) { @@ -25,6 +23,23 @@ const buildTools = async (automatedToolsPath, manualToolsPath, toolsPath, tagsPa } }; +async function retryWriteFile(filePath, data, retries = 3, delay = 1000) { + for (let attempt = 0; attempt < retries; attempt++) { + try { + fs.writeFileSync(filePath, data); + console.log(`File written successfully to ${filePath}`); + break; + } catch (err) { + if (err.code === 'ENOENT') { + console.error(`ENOENT error on attempt ${attempt + 1}. Retrying in ${delay}ms...`); + await new Promise((resolve) => setTimeout(resolve, delay)); + } else { + throw err; + } + } + } +} + /* istanbul ignore next */ if (require.main === module) { const automatedToolsPath = resolve(__dirname, '../config', 'tools-automated.json'); From 0a83f543b5960a932e8711a3fe5085ef2b43b55c Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Sat, 19 Oct 2024 17:28:16 +0530 Subject: [PATCH 24/43] fegwg --- tests/build-tools.test.js | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/tests/build-tools.test.js b/tests/build-tools.test.js index 7be2e5148e85..c4feff26227c 100644 --- a/tests/build-tools.test.js +++ b/tests/build-tools.test.js @@ -3,6 +3,7 @@ const { resolve } = require('path'); const { buildTools } = require('../scripts/build-tools'); const { tagsData, manualTools, mockConvertedData, mockExtractData } = require('../tests/fixtures/buildToolsData'); const fs = require('fs'); +const { beforeEach, afterEach } = require('node:test'); jest.mock('axios'); jest.mock('../scripts/tools/categorylist', () => ({ @@ -29,15 +30,17 @@ describe('buildTools', () => { const tagsPath = resolve(testDir, 'all-tags.json'); const automatedToolsPath = resolve(testDir, 'tools-automated.json'); const manualToolsPath = resolve(testDir, 'tools-manual.json'); + + if (!fs.existsSync(testDir)) { + fs.mkdirSync(testDir, { recursive: true }); + } + if (!fs.existsSync(manualToolsPath)) { + fs.writeFileSync(manualToolsPath, JSON.stringify(manualTools)); + } + let consoleErrorMock; beforeAll(() => { - if (!fs.existsSync(testDir)) { - fs.mkdirSync(testDir, { recursive: true }); - } - if (!fs.existsSync(manualToolsPath)) { - fs.writeFileSync(manualToolsPath, JSON.stringify(manualTools)); - } consoleErrorMock = jest.spyOn(console, 'error').mockImplementation(() => {}); }); @@ -50,6 +53,10 @@ describe('buildTools', () => { beforeEach(() => { jest.clearAllMocks(); + + if (!fs.existsSync(manualToolsPath)) { + fs.writeFileSync(manualToolsPath, JSON.stringify(manualTools)); + } }); it('should extract, convert, combine tools, and write to file', async () => { From 740d4d6e05f2673dbec0566c1a0e4c860a7d1584 Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Sat, 19 Oct 2024 17:48:57 +0530 Subject: [PATCH 25/43] fwqfqf --- scripts/build-tools.js | 4 +++- tests/build-tools.test.js | 10 +++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/scripts/build-tools.js b/scripts/build-tools.js index 2b7c47768f78..fc689095d996 100644 --- a/scripts/build-tools.js +++ b/scripts/build-tools.js @@ -17,7 +17,9 @@ const buildTools = async (automatedToolsPath, manualToolsPath, toolsPath, tagsPa await retryWriteFile(automatedToolsPath, JSON.stringify(automatedTools, null, ' ')); - await combineTools(automatedTools, require(manualToolsPath), toolsPath, tagsPath); + const manualTools = JSON.parse(fs.readFileSync(manualToolsPath, 'utf-8')); + + await combineTools(automatedTools, manualTools, toolsPath, tagsPath); } catch (err) { throw new Error(`An error occurred while building tools: ${err.message}`); } diff --git a/tests/build-tools.test.js b/tests/build-tools.test.js index c4feff26227c..a9af2a66ab21 100644 --- a/tests/build-tools.test.js +++ b/tests/build-tools.test.js @@ -3,7 +3,6 @@ const { resolve } = require('path'); const { buildTools } = require('../scripts/build-tools'); const { tagsData, manualTools, mockConvertedData, mockExtractData } = require('../tests/fixtures/buildToolsData'); const fs = require('fs'); -const { beforeEach, afterEach } = require('node:test'); jest.mock('axios'); jest.mock('../scripts/tools/categorylist', () => ({ @@ -54,10 +53,15 @@ describe('buildTools', () => { beforeEach(() => { jest.clearAllMocks(); + if (!fs.existsSync(testDir)) { + fs.mkdirSync(testDir, { recursive: true }); + } + if (!fs.existsSync(manualToolsPath)) { - fs.writeFileSync(manualToolsPath, JSON.stringify(manualTools)); + fs.writeFileSync(manualToolsPath, JSON.stringify(manualTools)); } - }); + }); + it('should extract, convert, combine tools, and write to file', async () => { axios.get.mockResolvedValue({ data: mockExtractData }); From 8f2162d925294570f0b23bbad18e10eccceacd7d Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Sat, 19 Oct 2024 18:02:46 +0530 Subject: [PATCH 26/43] feeqg --- scripts/build-newsroom-videos.js | 32 +++++---------------------- scripts/build-tools.js | 34 +++++------------------------ tests/build-newsroom-videos.test.js | 15 +++---------- tests/build-tools.test.js | 31 +++++--------------------- 4 files changed, 20 insertions(+), 92 deletions(-) diff --git a/scripts/build-newsroom-videos.js b/scripts/build-newsroom-videos.js index f4cf83066925..b67ee0378cf2 100644 --- a/scripts/build-newsroom-videos.js +++ b/scripts/build-newsroom-videos.js @@ -1,15 +1,9 @@ -const { writeFileSync, mkdirSync, existsSync } = require('fs'); -const { resolve, dirname } = require('path'); +const { writeFileSync } = require('fs'); +const { resolve } = require('path'); const fetch = require('node-fetch-2'); async function buildNewsroomVideos(writePath) { try { - const dir = dirname(writePath); - - if (!existsSync(dir)) { - mkdirSync(dir, { recursive: true }); - } - const response = await fetch('https://youtube.googleapis.com/youtube/v3/search?' + new URLSearchParams({ key: process.env.YOUTUBE_TOKEN, part: 'snippet', @@ -25,6 +19,7 @@ async function buildNewsroomVideos(writePath) { } 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'); @@ -40,7 +35,7 @@ async function buildNewsroomVideos(writePath) { const videoData = JSON.stringify(videoDataItems, null, ' '); console.log('The following are the Newsroom Youtube videos: ', videoData); - await retryWriteFile(writePath, videoData); + writeFileSync(writePath, videoData); return videoData; } catch (err) { @@ -48,26 +43,9 @@ async function buildNewsroomVideos(writePath) { } } -async function retryWriteFile(filePath, data, retries = 3, delay = 1000) { - for (let attempt = 0; attempt < retries; attempt++) { - try { - writeFileSync(filePath, data); - console.log(`File written successfully to ${filePath}`); - break; - } catch (err) { - if (err.code === 'ENOENT') { - console.error(`ENOENT error on attempt ${attempt + 1}. Retrying in ${delay}ms...`); - await new Promise((resolve) => setTimeout(resolve, delay)); - } else { - throw err; - } - } - } -} - /* istanbul ignore next */ if (require.main === module) { - buildNewsroomVideos(resolve(__dirname, '../config', 'newsroom_videos.json')); + buildNewsroomVideos(resolve(__dirname, '../config', 'newsroom_videos.json')) } module.exports = { buildNewsroomVideos }; diff --git a/scripts/build-tools.js b/scripts/build-tools.js index fc689095d996..84965815dcc4 100644 --- a/scripts/build-tools.js +++ b/scripts/build-tools.js @@ -2,46 +2,24 @@ const { getData } = require('./tools/extract-tools-github'); const { convertTools } = require('./tools/tools-object'); const { combineTools } = require('./tools/combine-tools'); const fs = require('fs'); -const { resolve, dirname } = require('path'); +const { resolve } = require('path'); const buildTools = async (automatedToolsPath, manualToolsPath, toolsPath, tagsPath) => { try { let githubExtractData = await getData(); let automatedTools = await convertTools(githubExtractData); - - const automatedDir = dirname(automatedToolsPath); - if (!fs.existsSync(automatedDir)) { - fs.mkdirSync(automatedDir, { recursive: true }); - } + fs.writeFileSync( + automatedToolsPath, + JSON.stringify(automatedTools, null, ' ') + ); - await retryWriteFile(automatedToolsPath, JSON.stringify(automatedTools, null, ' ')); - - const manualTools = JSON.parse(fs.readFileSync(manualToolsPath, 'utf-8')); - - await combineTools(automatedTools, manualTools, toolsPath, tagsPath); + await combineTools(automatedTools, require(manualToolsPath), toolsPath, tagsPath); } catch (err) { throw new Error(`An error occurred while building tools: ${err.message}`); } }; -async function retryWriteFile(filePath, data, retries = 3, delay = 1000) { - for (let attempt = 0; attempt < retries; attempt++) { - try { - fs.writeFileSync(filePath, data); - console.log(`File written successfully to ${filePath}`); - break; - } catch (err) { - if (err.code === 'ENOENT') { - console.error(`ENOENT error on attempt ${attempt + 1}. Retrying in ${delay}ms...`); - await new Promise((resolve) => setTimeout(resolve, delay)); - } else { - throw err; - } - } - } -} - /* istanbul ignore next */ if (require.main === module) { const automatedToolsPath = resolve(__dirname, '../config', 'tools-automated.json'); diff --git a/tests/build-newsroom-videos.test.js b/tests/build-newsroom-videos.test.js index 704b479fa0e3..3ffaba79a756 100644 --- a/tests/build-newsroom-videos.test.js +++ b/tests/build-newsroom-videos.test.js @@ -1,4 +1,4 @@ -const { readFileSync, rmSync, mkdirSync, existsSync } = require('fs'); +const { readFileSync, rmSync, mkdirSync } = require('fs'); const { resolve } = require('path'); const { buildNewsroomVideos } = require('../scripts/build-newsroom-videos'); const { mockApiResponse, expectedResult } = require('./fixtures/newsroomData'); @@ -11,19 +11,15 @@ describe('buildNewsroomVideos', () => { const testFilePath = resolve(testDir, 'newsroom_videos.json'); beforeAll(() => { + mkdirSync(testDir, { recursive: true }); process.env.YOUTUBE_TOKEN = 'testkey'; }); afterAll(() => { - if (existsSync(testDir)) { - rmSync(testDir, { recursive: true, force: true }); - } + rmSync(testDir, { recursive: true, force: true }); }); beforeEach(() => { - if (!existsSync(testDir)) { - mkdirSync(testDir, { recursive: true }); - } fetch.mockClear(); }); @@ -33,10 +29,6 @@ describe('buildNewsroomVideos', () => { json: jest.fn().mockResolvedValue(mockApiResponse), }); - if (!existsSync(testDir)) { - mkdirSync(testDir, { recursive: true }); - } - const result = await buildNewsroomVideos(testFilePath); const expectedUrl = new URL('https://youtube.googleapis.com/youtube/v3/search'); @@ -49,7 +41,6 @@ describe('buildNewsroomVideos', () => { expectedUrl.searchParams.set('maxResults', '5'); expect(fetch).toHaveBeenCalledWith(expectedUrl.toString()); - const response = readFileSync(testFilePath, 'utf8'); expect(response).toEqual(expectedResult); expect(result).toEqual(expectedResult); diff --git a/tests/build-tools.test.js b/tests/build-tools.test.js index a9af2a66ab21..fc0231c86c6c 100644 --- a/tests/build-tools.test.js +++ b/tests/build-tools.test.js @@ -29,47 +29,27 @@ describe('buildTools', () => { const tagsPath = resolve(testDir, 'all-tags.json'); const automatedToolsPath = resolve(testDir, 'tools-automated.json'); const manualToolsPath = resolve(testDir, 'tools-manual.json'); - - if (!fs.existsSync(testDir)) { - fs.mkdirSync(testDir, { recursive: true }); - } - if (!fs.existsSync(manualToolsPath)) { - fs.writeFileSync(manualToolsPath, JSON.stringify(manualTools)); - } - let consoleErrorMock; beforeAll(() => { consoleErrorMock = jest.spyOn(console, 'error').mockImplementation(() => {}); + + fs.mkdirSync(testDir, { recursive: true }); + fs.writeFileSync(manualToolsPath, JSON.stringify(manualTools)); }); afterAll(() => { - if (fs.existsSync(testDir)) { - fs.rmSync(testDir, { recursive: true, force: true }); - } + fs.rmSync(testDir, { recursive: true, force: true }); consoleErrorMock.mockRestore(); }); beforeEach(() => { jest.clearAllMocks(); - - if (!fs.existsSync(testDir)) { - fs.mkdirSync(testDir, { recursive: true }); - } - - if (!fs.existsSync(manualToolsPath)) { - fs.writeFileSync(manualToolsPath, JSON.stringify(manualTools)); - } - }); - + }); it('should extract, convert, combine tools, and write to file', async () => { axios.get.mockResolvedValue({ data: mockExtractData }); - if (!fs.existsSync(testDir)) { - fs.mkdirSync(testDir, { recursive: true }); - } - await buildTools(automatedToolsPath, manualToolsPath, toolsPath, tagsPath); const automatedToolsContent = JSON.parse(fs.readFileSync(automatedToolsPath, 'utf8')); @@ -86,6 +66,7 @@ describe('buildTools', () => { expect(combinedToolsContent["Category2"].description).toEqual(mockConvertedData["Category2"].description); expect(tagsContent).toEqual(tagsData); + }); it('should handle getData error', async () => { From c2ee924bf566c83806165f84f1b4d0aee10f266b Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Sat, 19 Oct 2024 18:11:33 +0530 Subject: [PATCH 27/43] use fs-extra --- package-lock.json | 124 ++++++++-------------------- package.json | 1 + scripts/build-newsroom-videos.js | 4 +- scripts/build-tools.js | 7 +- tests/build-newsroom-videos.test.js | 6 +- tests/build-tools.test.js | 9 +- 6 files changed, 48 insertions(+), 103 deletions(-) diff --git a/package-lock.json b/package-lock.json index bea2b1cc43e4..3e06c5cffdb9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -34,6 +34,7 @@ "clsx": "^2.1.0", "cssnano": "^6.0.3", "dotenv": "^16.4.4", + "fs-extra": "^11.2.0", "fuse.js": "^7.0.0", "googleapis": "^133.0.0", "gray-matter": "^4.0.3", @@ -4697,20 +4698,6 @@ "unstorage": "1.9.0" } }, - "node_modules/@netlify/ipx/node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, "node_modules/@netlify/ipx/node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -4787,6 +4774,21 @@ "node": ">=14.0.0" } }, + "node_modules/@netlify/plugin-nextjs/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/@netlify/plugin-nextjs/node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -6253,20 +6255,6 @@ "storybook": "^8.2.9" } }, - "node_modules/@storybook/addon-docs/node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, "node_modules/@storybook/addon-essentials": { "version": "8.2.9", "resolved": "https://registry.npmjs.org/@storybook/addon-essentials/-/addon-essentials-8.2.9.tgz", @@ -6526,20 +6514,6 @@ "undici-types": "~5.26.4" } }, - "node_modules/@storybook/builder-webpack5/node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, "node_modules/@storybook/codemod": { "version": "8.2.9", "resolved": "https://registry.npmjs.org/@storybook/codemod/-/codemod-8.2.9.tgz", @@ -6829,20 +6803,6 @@ "undici-types": "~5.26.4" } }, - "node_modules/@storybook/nextjs/node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, "node_modules/@storybook/preset-react-webpack": { "version": "8.2.9", "resolved": "https://registry.npmjs.org/@storybook/preset-react-webpack/-/preset-react-webpack-8.2.9.tgz", @@ -6890,20 +6850,6 @@ "undici-types": "~5.26.4" } }, - "node_modules/@storybook/preset-react-webpack/node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, "node_modules/@storybook/preview-api": { "version": "8.2.9", "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-8.2.9.tgz", @@ -14227,6 +14173,21 @@ "concat-map": "0.0.1" } }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/fork-ts-checker-webpack-plugin/node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -14339,17 +14300,17 @@ "dev": true }, "node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" }, "engines": { - "node": ">=12" + "node": ">=14.14" } }, "node_modules/fs-minipass": { @@ -27097,19 +27058,6 @@ "node": ">= 6" } }, - "node_modules/storybook/node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, "node_modules/storybook/node_modules/globby": { "version": "14.0.2", "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.2.tgz", diff --git a/package.json b/package.json index 04ba37b586eb..aab6109d1349 100644 --- a/package.json +++ b/package.json @@ -69,6 +69,7 @@ "clsx": "^2.1.0", "cssnano": "^6.0.3", "dotenv": "^16.4.4", + "fs-extra": "^11.2.0", "fuse.js": "^7.0.0", "googleapis": "^133.0.0", "gray-matter": "^4.0.3", diff --git a/scripts/build-newsroom-videos.js b/scripts/build-newsroom-videos.js index b67ee0378cf2..383927765d36 100644 --- a/scripts/build-newsroom-videos.js +++ b/scripts/build-newsroom-videos.js @@ -1,4 +1,4 @@ -const { writeFileSync } = require('fs'); +const { writeFileSync } = require('fs-extra'); const { resolve } = require('path'); const fetch = require('node-fetch-2'); @@ -19,7 +19,7 @@ async function buildNewsroomVideos(writePath) { } const data = await response.json(); - console.log(data) + console.log(data); if (!data.items || !Array.isArray(data.items)) { throw new Error('Invalid data structure received from YouTube API'); diff --git a/scripts/build-tools.js b/scripts/build-tools.js index 84965815dcc4..c5cce74a7cb1 100644 --- a/scripts/build-tools.js +++ b/scripts/build-tools.js @@ -1,7 +1,7 @@ const { getData } = require('./tools/extract-tools-github'); const { convertTools } = require('./tools/tools-object'); const { combineTools } = require('./tools/combine-tools'); -const fs = require('fs'); +const fs = require('fs-extra'); const { resolve } = require('path'); const buildTools = async (automatedToolsPath, manualToolsPath, toolsPath, tagsPath) => { @@ -9,10 +9,7 @@ const buildTools = async (automatedToolsPath, manualToolsPath, toolsPath, tagsPa let githubExtractData = await getData(); let automatedTools = await convertTools(githubExtractData); - fs.writeFileSync( - automatedToolsPath, - JSON.stringify(automatedTools, null, ' ') - ); + await fs.writeFile(automatedToolsPath, JSON.stringify(automatedTools, null, ' ')); await combineTools(automatedTools, require(manualToolsPath), toolsPath, tagsPath); } catch (err) { diff --git a/tests/build-newsroom-videos.test.js b/tests/build-newsroom-videos.test.js index 3ffaba79a756..a43c55ea9cd0 100644 --- a/tests/build-newsroom-videos.test.js +++ b/tests/build-newsroom-videos.test.js @@ -1,4 +1,4 @@ -const { readFileSync, rmSync, mkdirSync } = require('fs'); +const { readFileSync, removeSync, mkdirpSync } = require('fs-extra'); const { resolve } = require('path'); const { buildNewsroomVideos } = require('../scripts/build-newsroom-videos'); const { mockApiResponse, expectedResult } = require('./fixtures/newsroomData'); @@ -11,12 +11,12 @@ describe('buildNewsroomVideos', () => { const testFilePath = resolve(testDir, 'newsroom_videos.json'); beforeAll(() => { - mkdirSync(testDir, { recursive: true }); + mkdirpSync(testDir); process.env.YOUTUBE_TOKEN = 'testkey'; }); afterAll(() => { - rmSync(testDir, { recursive: true, force: true }); + removeSync(testDir); }); beforeEach(() => { diff --git a/tests/build-tools.test.js b/tests/build-tools.test.js index fc0231c86c6c..4377e1f298ff 100644 --- a/tests/build-tools.test.js +++ b/tests/build-tools.test.js @@ -2,7 +2,7 @@ const axios = require('axios'); const { resolve } = require('path'); const { buildTools } = require('../scripts/build-tools'); const { tagsData, manualTools, mockConvertedData, mockExtractData } = require('../tests/fixtures/buildToolsData'); -const fs = require('fs'); +const fs = require('fs-extra'); jest.mock('axios'); jest.mock('../scripts/tools/categorylist', () => ({ @@ -34,12 +34,12 @@ describe('buildTools', () => { beforeAll(() => { consoleErrorMock = jest.spyOn(console, 'error').mockImplementation(() => {}); - fs.mkdirSync(testDir, { recursive: true }); - fs.writeFileSync(manualToolsPath, JSON.stringify(manualTools)); + fs.ensureDirSync(testDir); + fs.outputFileSync(manualToolsPath, JSON.stringify(manualTools)); }); afterAll(() => { - fs.rmSync(testDir, { recursive: true, force: true }); + fs.removeSync(testDir); consoleErrorMock.mockRestore(); }); @@ -66,7 +66,6 @@ describe('buildTools', () => { expect(combinedToolsContent["Category2"].description).toEqual(mockConvertedData["Category2"].description); expect(tagsContent).toEqual(tagsData); - }); it('should handle getData error', async () => { From 267023e75c06e73c479854a60120726efd7963d3 Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Sat, 19 Oct 2024 20:04:26 +0530 Subject: [PATCH 28/43] commit to re run the workflow --- tests/tools/tools-object.test.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/tools/tools-object.test.js b/tests/tools/tools-object.test.js index 7706e24572fd..a5ac5032d366 100644 --- a/tests/tools/tools-object.test.js +++ b/tests/tools/tools-object.test.js @@ -144,5 +144,4 @@ describe('Tools Object', () => { expect(error).toBeDefined(); expect(error.message).toContain('Unexpected token'); }); - -}); \ No newline at end of file +}); From e4be92f68472a51c77e755560b80a7e55d6a1778 Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Sat, 19 Oct 2024 20:08:57 +0530 Subject: [PATCH 29/43] fqefeqf --- tests/tools/tools-object.test.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/tools/tools-object.test.js b/tests/tools/tools-object.test.js index a5ac5032d366..7706e24572fd 100644 --- a/tests/tools/tools-object.test.js +++ b/tests/tools/tools-object.test.js @@ -144,4 +144,5 @@ describe('Tools Object', () => { expect(error).toBeDefined(); expect(error.message).toContain('Unexpected token'); }); -}); + +}); \ No newline at end of file From dcb955b48d960762524441210feae9b50280e6a1 Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Mon, 21 Oct 2024 09:32:21 +0530 Subject: [PATCH 30/43] test updated --- tests/build-newsroom-videos.test.js | 7 ++++--- tests/build-tools.test.js | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/tests/build-newsroom-videos.test.js b/tests/build-newsroom-videos.test.js index a43c55ea9cd0..494f91f27341 100644 --- a/tests/build-newsroom-videos.test.js +++ b/tests/build-newsroom-videos.test.js @@ -1,13 +1,14 @@ const { readFileSync, removeSync, mkdirpSync } = require('fs-extra'); -const { resolve } = require('path'); +const { resolve, join } = require('path'); const { buildNewsroomVideos } = require('../scripts/build-newsroom-videos'); const { mockApiResponse, expectedResult } = require('./fixtures/newsroomData'); const fetch = require('node-fetch-2'); +const os = require('os'); jest.mock('node-fetch-2', () => jest.fn()); describe('buildNewsroomVideos', () => { - const testDir = resolve(__dirname, 'test_config'); + const testDir = join(os.tmpdir(), 'test_config'); const testFilePath = resolve(testDir, 'newsroom_videos.json'); beforeAll(() => { @@ -89,7 +90,7 @@ describe('buildNewsroomVideos', () => { json: jest.fn().mockResolvedValue(mockApiResponse), }); - const invalidPath = '/invalid_dir/newsroom_videos.json'; + const invalidPath = resolve(os.tmpdir(), 'invalid_dir', 'newsroom_videos.json'); try { await buildNewsroomVideos(invalidPath); diff --git a/tests/build-tools.test.js b/tests/build-tools.test.js index 4377e1f298ff..74524ddb9775 100644 --- a/tests/build-tools.test.js +++ b/tests/build-tools.test.js @@ -3,6 +3,8 @@ const { resolve } = require('path'); const { buildTools } = require('../scripts/build-tools'); const { tagsData, manualTools, mockConvertedData, mockExtractData } = require('../tests/fixtures/buildToolsData'); const fs = require('fs-extra'); +const os = require('os'); +const path = require('path'); jest.mock('axios'); jest.mock('../scripts/tools/categorylist', () => ({ @@ -24,7 +26,7 @@ jest.mock('../scripts/tools/tags-color', () => ({ })); describe('buildTools', () => { - const testDir = resolve(__dirname, 'test_config'); + const testDir = path.join(os.tmpdir(), 'test_config'); const toolsPath = resolve(testDir, 'tools.json'); const tagsPath = resolve(testDir, 'all-tags.json'); const automatedToolsPath = resolve(testDir, 'tools-automated.json'); @@ -33,7 +35,6 @@ describe('buildTools', () => { beforeAll(() => { consoleErrorMock = jest.spyOn(console, 'error').mockImplementation(() => {}); - fs.ensureDirSync(testDir); fs.outputFileSync(manualToolsPath, JSON.stringify(manualTools)); }); @@ -81,7 +82,7 @@ describe('buildTools', () => { it('should handle file write errors', async () => { axios.get.mockResolvedValue({ data: mockExtractData }); - const invalidPath = '/invalid_dir/tools.json'; + const invalidPath = path.resolve(os.tmpdir(), 'invalid_dir', 'tools.json'); try { await buildTools(invalidPath, manualToolsPath, toolsPath, tagsPath); From 72f1e630870d9aa788af7c1c17f6a76d974e8af6 Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Sun, 27 Oct 2024 08:01:33 +0530 Subject: [PATCH 31/43] fef --- scripts/tools/tools-object.js | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/tools/tools-object.js b/scripts/tools/tools-object.js index b89d72b3f560..e75ae1093997 100644 --- a/scripts/tools/tools-object.js +++ b/scripts/tools/tools-object.js @@ -9,7 +9,6 @@ addFormats(ajv, ["uri"]) const validate = ajv.compile(schema) const { convertToJson } = require('../utils'); - // Config options set for the Fuse object const options = { includeScore: true, From 7554976ad15642a4d848bdd3c128fe3c96709eed Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Sun, 27 Oct 2024 22:53:01 +0530 Subject: [PATCH 32/43] add empty line at end --- scripts/tools/tools-object.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/tools/tools-object.js b/scripts/tools/tools-object.js index e75ae1093997..30dc173224c4 100644 --- a/scripts/tools/tools-object.js +++ b/scripts/tools/tools-object.js @@ -113,4 +113,4 @@ async function convertTools(data) { } } -module.exports = { convertTools, createToolObject } \ No newline at end of file +module.exports = { convertTools, createToolObject } From 2be6d4241e1751aedeb9679022a47979a37cc5b5 Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Tue, 5 Nov 2024 14:04:22 +0530 Subject: [PATCH 33/43] fef --- scripts/tools/tools-object.js | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/scripts/tools/tools-object.js b/scripts/tools/tools-object.js index 30dc173224c4..a7d5e0308f92 100644 --- a/scripts/tools/tools-object.js +++ b/scripts/tools/tools-object.js @@ -82,19 +82,14 @@ async function convertTools(data) { let toolObject = await createToolObject(jsonToolFileContent, repositoryUrl, repoDescription, isAsyncAPIrepo); // Tool Object is appended to each category array according to Fuse search for categories inside Tool Object - jsonToolFileContent.filters.categories.forEach(async (category) => { + await Promise.all(jsonToolFileContent.filters.categories.map(async (category) => { const categorySearch = await fuse.search(category); - - if (categorySearch.length) { - let searchedCategoryName = categorySearch[0].item.name - if (!finalToolsObject[searchedCategoryName].toolsList.find((element => element === toolObject))) - finalToolsObject[searchedCategoryName].toolsList.push(toolObject); - } else { - // if Tool object has a category, not defined in our categorylist, then this provides a `other` category to the tool. - if (!finalToolsObject['Others'].toolsList.find((element => element === toolObject))) - finalToolsObject['Others'].toolsList.push(toolObject); + const targetCategory = categorySearch.length ? categorySearch[0].item.name : 'Others'; + const toolsList = finalToolsObject[targetCategory].toolsList; + if (!toolsList.includes(toolObject)) { + toolsList.push(toolObject); } - }); + })); } else { console.error('Script is not failing, it is just dropping errors for further investigation'); console.error('Invalid .asyncapi-tool file.'); From 159f1509aff4a8267f66af4e8b26cb524bfff14a Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Sun, 10 Nov 2024 23:55:08 +0530 Subject: [PATCH 34/43] loop update --- scripts/tools/tools-object.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/tools/tools-object.js b/scripts/tools/tools-object.js index a7d5e0308f92..d18be330581d 100644 --- a/scripts/tools/tools-object.js +++ b/scripts/tools/tools-object.js @@ -51,9 +51,9 @@ async function convertTools(data) { const dataArray = data.items; // initialising finalToolsObject with all categories inside it with proper elements in each category - for (var index in categoryList) { - finalToolsObject[categoryList[index].name] = { - description: categoryList[index].description, + for (const category of categoryList) { + finalToolsObject[category.name] = { + description: category.description, toolsList: [] }; } From c71e125af2b4dcc1d94f0a2318f73ecd25de7979 Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Mon, 11 Nov 2024 00:58:49 +0530 Subject: [PATCH 35/43] added helper function --- tests/fixtures/toolsObjectData.js | 344 ++++++------------------------ tests/tools/tools-object.test.js | 165 +++++++------- 2 files changed, 146 insertions(+), 363 deletions(-) diff --git a/tests/fixtures/toolsObjectData.js b/tests/fixtures/toolsObjectData.js index 24865e0065d8..bdc8ba59a622 100644 --- a/tests/fixtures/toolsObjectData.js +++ b/tests/fixtures/toolsObjectData.js @@ -1,280 +1,74 @@ -const mockData = { - items: [ - { - name: '.asyncapi-tool-example', - url: 'https://api.github.com/repositories/351453552/contents/.asyncapi-tool?ref=61855e7365a881e98c2fe667a658a0005753d873', - repository: { - full_name: 'asyncapi/example-repo', - html_url: 'https://github.com/asyncapi/example-repo', - description: 'Example repository', - owner: { - login: 'asyncapi' - } - }, - path: '.asyncapi-tool' - } - ] -}; - -const mockToolFileContent = { - title: "Example Tool", - description: "This is an example tool.", - links: { - repoUrl: "https://github.com/asyncapi/example-repo" - }, - filters: { - categories: ["Category1"], - hasCommercial: true - } -}; - -const toolFileT1 = { - title: 'Example Tool', - description: 'This is an example tool.', - links: { - repoUrl: 'https://github.com/asyncapi/example-repo' +const createToolRepositoryData = ({ + name = '.asyncapi-tool', + refId = '61855e7365a881e98c2fe667a658a0005753d873', + owner = 'asyncapi', + repoName = 'example-repo', + description = 'Example repository', + path = '.asyncapi-tool' +} = {}) => ({ + name, + url: `https://api.github.com/repositories/351453552/contents/${path}?ref=${refId}`, + repository: { + full_name: `${owner}/${repoName}`, + html_url: `https://github.com/${owner}/${repoName}`, + description, + owner: { login: owner } }, - filters: { - categories: ['Category1'], - hasCommercial: true - } -}; - -const expectedObjectT1 = { - title: 'Example Tool', - description: 'This is an example tool.', - links: { - repoUrl: 'https://github.com/asyncapi/example-repo' - }, - filters: { - categories: ['Category1'], - hasCommercial: true, - isAsyncAPIOwner: true - } -}; - -const repositoryUrl = 'https://github.com/asyncapi/example-repo'; -const repoDescription = 'Example repository'; -const isAsyncAPIOwner = true; - -const toolFileT2 = { - title: 'Example Tool', - links: { - repoUrl: 'https://github.com/asyncapi/example-repo' - }, - filters: { - categories: ['Category1'] - } -}; - -const expectedObjectT2 = { - title: 'Example Tool', - description: 'Example repository', - links: { - repoUrl: 'https://github.com/asyncapi/example-repo' - }, - filters: { - categories: ['Category1'], - hasCommercial: false, - isAsyncAPIOwner: true - } -}; - -const expectedObjectT3 = { - Category1: { - description: 'Description for Category1', - toolsList: [ - { - title: 'Example Tool', - description: 'This is an example tool.', - links: { - repoUrl: 'https://github.com/asyncapi/example-repo' - }, - filters: { - categories: ['Category1'], - hasCommercial: true, - isAsyncAPIOwner: true - } - } - ] - }, - Others: { - description: 'Other tools category', - toolsList: [] - } -}; - -const dataWithUnknownCategory = { - items: [ - { - name: '.asyncapi-tool-unknown', - url: 'https://api.github.com/repositories/351453552/contents/.asyncapi-tool?ref=61855e7365a881e98c2fe667a658a0005753d873', - repository: { - full_name: 'asyncapi/unknown-repo', - html_url: 'https://github.com/asyncapi/unknown-repo', - description: 'Unknown repository', - owner: { - login: 'asyncapi' - } - }, - path: '.asyncapi-tool' - } - ] -}; - -const toolFileContent = { - title: "Unknown Tool", - description: "This tool has an unknown category.", - links: { - repoUrl: "https://github.com/asyncapi/unknown-repo" - }, - filters: { - categories: ["UnknownCategory"] - } -}; - -const invalidToolFileContent = { - title: "Invalid Tool", - description: "This tool has invalid schema.", - links: { - repoUrl: "https://github.com/asyncapi/invalid-repo" - }, - filters: { - categories: ["Category1"], - invalidField: true - } -}; - -const invalidToolData = { - items: [ - { - name: '.asyncapi-tool-invalid', - url: 'https://api.github.com/repositories/351453552/contents/.asyncapi-tool?ref=invalidref', - repository: { - full_name: 'asyncapi/invalid-repo', - html_url: 'https://github.com/asyncapi/invalid-repo', - description: 'Invalid repository', - owner: { - login: 'asyncapi' - } - }, - path: '.asyncapi-tool' - } - ] -}; - -const duplicateToolData = { - items: [ - { - name: '.asyncapi-tool-duplicate', - url: 'https://api.github.com/repositories/351453552/contents/.asyncapi-tool?ref=duplicate1', - repository: { - full_name: 'asyncapi/duplicate-repo', - html_url: 'https://github.com/asyncapi/duplicate-repo', - description: 'Duplicate repository', - owner: { - login: 'asyncapi' - } - }, - path: '.asyncapi-tool' - }, - { - name: '.asyncapi-tool-duplicate', - url: 'https://api.github.com/repositories/351453552/contents/.asyncapi-tool?ref=duplicate2', - repository: { - full_name: 'asyncapi/duplicate-repo', - html_url: 'https://github.com/asyncapi/duplicate-repo', - description: 'Duplicate repository', - owner: { - login: 'asyncapi' - } - }, - path: '.asyncapi-tool' - } - ] -}; - -const duplicateToolFileContent = { - title: "Duplicate Tool", - description: "This is a duplicate tool.", - links: { - repoUrl: "https://github.com/asyncapi/duplicate-repo" - }, - filters: { - categories: ["Category1"] - } -}; - -const dataWithUnknownCategoryOnce = { - items: [ - { - name: '.asyncapi-tool-unknown', - url: 'https://api.github.com/repositories/351453552/contents/.asyncapi-tool?ref=unknown1', - repository: { - full_name: 'asyncapi/unknown-repo', - html_url: 'https://github.com/asyncapi/unknown-repo', - description: 'Unknown repository', - owner: { - login: 'asyncapi' - } - }, - path: '.asyncapi-tool' - }, - { - name: '.asyncapi-tool-unknown', - url: 'https://api.github.com/repositories/351453552/contents/.asyncapi-tool?ref=unknown2', - repository: { - full_name: 'asyncapi/unknown-repo', - html_url: 'https://github.com/asyncapi/unknown-repo', - description: 'Unknown repository', - owner: { - login: 'asyncapi' - } - }, - path: '.asyncapi-tool' - } - ] -}; - -const unknownToolFileContent = { - title: "Unknown Tool", - description: "This tool has an unknown category.", - links: { - repoUrl: "https://github.com/asyncapi/unknown-repo" - }, - filters: { - categories: ["UnknownCategory"] - } -}; - -const toolFileMalformedJSON = ` - title: Malformed Tool - description: This tool has malformed JSON. + path +}); + +const createToolFileContent = ({ + title = 'Example Tool', + description = 'This is an example tool.', + repoUrl = null, + categories = ['Category1'], + hasCommercial = false, + additionalLinks = {}, + additionalFilters = {} +} = {}) => ({ + title, + description, + links: { repoUrl: repoUrl || `https://github.com/asyncapi/${title.toLowerCase().replace(/\s+/g, '-')}`, ...additionalLinks }, + filters: { categories, hasCommercial, ...additionalFilters } +}); + +const createExpectedToolObject = ({ + title = 'Example Tool', + description = 'This is an example tool.', + repoUrl = null, + categories = ['Category1'], + hasCommercial = false, + isAsyncAPIOwner = true, + additionalLinks = {}, + additionalFilters = {} +} = {}) => createToolFileContent({ + title, + description, + repoUrl, + categories, + hasCommercial, + additionalLinks, + additionalFilters: { isAsyncAPIOwner, ...additionalFilters } +}); + +const createMockData = (tools = []) => ({ + items: tools.map(tool => + typeof tool === 'string' + ? createToolRepositoryData({ name: `.asyncapi-tool-${tool}`, repoName: tool }) + : createToolRepositoryData(tool) + ) +}); + +const createMalformedYAML = ({ title = 'Malformed Tool', + description = 'This tool has malformed YAML.', + repoUrl = 'https://github.com/asyncapi/malformed-repo' } = {}) => ` + title: ${title} + description: ${description} links: - repoUrl: https://github.com/asyncapi/malformed-repo - filters + repoUrl: ${repoUrl} + filters: categories: - Category1 - `; +`; -module.exports = { - mockData, - mockToolFileContent, - toolFileT1, - expectedObjectT1, - repoDescription, - repositoryUrl, - isAsyncAPIOwner, - toolFileT2, - expectedObjectT2, - expectedObjectT3, - dataWithUnknownCategory, - toolFileContent, - invalidToolFileContent, - invalidToolData, - duplicateToolData, - duplicateToolFileContent, - dataWithUnknownCategoryOnce, - unknownToolFileContent, - toolFileMalformedJSON, -}; +module.exports = { createToolFileContent, createExpectedToolObject, createMockData, createMalformedYAML }; diff --git a/tests/tools/tools-object.test.js b/tests/tools/tools-object.test.js index 7706e24572fd..e23a6b5eb923 100644 --- a/tests/tools/tools-object.test.js +++ b/tests/tools/tools-object.test.js @@ -1,29 +1,13 @@ const { convertTools, createToolObject } = require('../../scripts/tools/tools-object'); const axios = require('axios'); - -const { mockData, - mockToolFileContent, - toolFileT1, - expectedObjectT1, - repoDescription, - repositoryUrl, - isAsyncAPIOwner, - toolFileT2, - expectedObjectT2, - expectedObjectT3, - dataWithUnknownCategory, - toolFileContent, - invalidToolFileContent, - invalidToolData, - duplicateToolData, - duplicateToolFileContent, - dataWithUnknownCategoryOnce, - unknownToolFileContent, - toolFileMalformedJSON, -} = require("../fixtures/toolsObjectData") +const { + createToolFileContent, + createExpectedToolObject, + createMockData, + createMalformedYAML +} = require('../fixtures/toolsObjectData'); jest.mock('axios'); - jest.mock('../../scripts/tools/categorylist', () => ({ categoryList: [ { name: 'Category1', tag: 'Category1', description: 'Description for Category1' }, @@ -32,73 +16,89 @@ jest.mock('../../scripts/tools/categorylist', () => ({ })); describe('Tools Object', () => { - beforeEach(() => { axios.get.mockClear(); console.error = jest.fn(); }); - it('should create a tool object with provided parameters', async () => { - - const result = await createToolObject(toolFileT1, repositoryUrl, repoDescription, isAsyncAPIOwner); - expect(result).toEqual(expectedObjectT1); - }); + const mockToolData = (toolContent, toolNames = ['valid-tool']) => { + const mockData = createMockData(toolNames.map(name => ({ name: `.asyncapi-tool-${name}`, repoName: name }))); + axios.get.mockResolvedValue({ data: toolContent }); + return mockData; + }; - it('should use repoDescription when toolFile.description is not provided', async () => { + it('should create a tool object with provided parameters', async () => { + const toolFile = createToolFileContent({ + title: 'Test Tool', + description: 'Test Description', + hasCommercial: true, + additionalLinks: { docsUrl: 'https://docs.example.com' } + }); + + const expected = createExpectedToolObject({ + title: 'Test Tool', + description: 'Test Description', + hasCommercial: true, + additionalLinks: { docsUrl: 'https://docs.example.com' } + }); + + const result = await createToolObject( + toolFile, + expected.links.repoUrl, + 'Repository Description', + true + ); - const result = await createToolObject(toolFileT2, repositoryUrl, repoDescription, isAsyncAPIOwner); - expect(result).toEqual(expectedObjectT2); + expect(result).toEqual(expected); }); it('should convert tools data correctly', async () => { - axios.get.mockResolvedValue({ data: mockToolFileContent }); + const toolContent = createToolFileContent({ title: 'Valid Tool', categories: ['Category1'] }); + const mockData = mockToolData(toolContent); const result = await convertTools(mockData); - expect(result).toEqual(expect.objectContaining(expectedObjectT3)); - expect(axios.get).toHaveBeenCalledTimes(1); + expect(result.Category1.toolsList).toHaveLength(1); + expect(result.Category1.toolsList[0].title).toBe('Valid Tool'); }); it('should assign tool to Others category if no matching category is found', async () => { + const toolContent = createToolFileContent({ title: 'Unknown Category Tool', categories: ['UnknownCategory'] }); + const mockData = mockToolData(toolContent); - axios.get.mockResolvedValue({ data: toolFileContent }); - - const result = await convertTools(dataWithUnknownCategory); + const result = await convertTools(mockData); expect(result.Others.toolsList).toHaveLength(1); - expect(result.Others.toolsList[0].title).toBe('Unknown Tool'); + expect(result.Others.toolsList[0].title).toBe('Unknown Category Tool'); }); it('should log errors for invalid .asyncapi-tool file', async () => { + const invalidContent = createToolFileContent({ + title: 'Invalid Tool', + additionalFilters: { invalidField: true } + }); + const mockData = mockToolData(invalidContent); - axios.get.mockResolvedValue({ data: invalidToolFileContent }); - - let error; - try { - await convertTools(invalidToolData); - } catch (err) { - error = err; - } - - expect(error).toBeUndefined(); - - const allErrorMessages = console.error.mock.calls.flat(); - expect(allErrorMessages).toEqual( - expect.arrayContaining([ - expect.stringContaining('Script is not failing, it is just dropping errors for further investigation'), - expect.stringContaining('Invalid .asyncapi-tool file'), - expect.stringContaining('Located in:'), - expect.stringContaining('Validation errors:') - ]) - ); + await convertTools(mockData); + expect(console.error).toHaveBeenCalledWith(expect.stringContaining('Script is not failing')); + expect(console.error).toHaveBeenCalledWith(expect.stringContaining('Invalid .asyncapi-tool file')); }); it('should add duplicate tool objects to the same category', async () => { + const toolContent = createToolFileContent({ + title: 'Duplicate Tool', + categories: ['Category1'] + }); + + const mockData = createMockData([ + { name: '.asyncapi-tool-dup1', repoName: 'dup1' }, + { name: '.asyncapi-tool-dup2', repoName: 'dup2' } + ]); - axios.get.mockResolvedValue({ data: duplicateToolFileContent }); + axios.get.mockResolvedValue({ data: toolContent }); - const result = await convertTools(duplicateToolData); + const result = await convertTools(mockData); expect(result.Category1.toolsList).toHaveLength(2); expect(result.Category1.toolsList[0].title).toBe('Duplicate Tool'); @@ -106,43 +106,32 @@ describe('Tools Object', () => { }); it('should add tool to Others category only once', async () => { + const toolContent = createToolFileContent({ + title: 'Duplicate Tool in Others', + categories: ['UnknownCategory'] + }); - axios.get.mockResolvedValue({ data: unknownToolFileContent }); + const mockData = mockToolData(toolContent); - const result = await convertTools(dataWithUnknownCategoryOnce); - - const uniqueTools = result.Others.toolsList.filter((tool, index, self) => - index === self.findIndex((t) => t.title === tool.title) - ); + const result = await convertTools(mockData); - expect(uniqueTools).toHaveLength(1); - expect(uniqueTools[0].title).toBe('Unknown Tool'); + expect(result.Others.toolsList).toHaveLength(1); + expect(result.Others.toolsList[0].title).toBe('Duplicate Tool in Others'); }); it('should throw an error if axios.get fails', async () => { - let error; + const mockData = createMockData([{ + name: '.asyncapi-tool-error', + repoName: 'error-tool' + }]); + axios.get.mockRejectedValue(new Error('Network Error')); - try { - await convertTools(mockData) - } catch (err) { - error = err; - expect(err.message).toContain("Network Error") - } - expect(error).toBeDefined(); + await expect(convertTools(mockData)).rejects.toThrow('Network Error'); }); it('should handle malformed JSON in tool file', async () => { - axios.get.mockResolvedValue({ data: toolFileMalformedJSON }); - - let error; - try { - await convertTools(mockData); - } catch (err) { - error = err; - } - expect(error).toBeDefined(); - expect(error.message).toContain('Unexpected token'); + const malformedContent = createMalformedYAML(); + await expect(convertTools(malformedContent)).rejects.toThrow(); }); - -}); \ No newline at end of file +}); From 99dcd7caf36d8f0ab6ba10af16d83fa89dd80da5 Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Wed, 13 Nov 2024 17:31:07 +0530 Subject: [PATCH 36/43] helper function --- tests/{fixtures => helper}/toolsObjectData.js | 0 tests/tools/tools-object.test.js | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename tests/{fixtures => helper}/toolsObjectData.js (100%) diff --git a/tests/fixtures/toolsObjectData.js b/tests/helper/toolsObjectData.js similarity index 100% rename from tests/fixtures/toolsObjectData.js rename to tests/helper/toolsObjectData.js diff --git a/tests/tools/tools-object.test.js b/tests/tools/tools-object.test.js index e23a6b5eb923..c8e2f8a7eab1 100644 --- a/tests/tools/tools-object.test.js +++ b/tests/tools/tools-object.test.js @@ -5,7 +5,7 @@ const { createExpectedToolObject, createMockData, createMalformedYAML -} = require('../fixtures/toolsObjectData'); +} = require('../helper/toolsObjectData'); jest.mock('axios'); jest.mock('../../scripts/tools/categorylist', () => ({ From c6ffd22dd776913f36cb2a6eb5c4e3852e747efe Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Sat, 23 Nov 2024 10:37:13 +0530 Subject: [PATCH 37/43] script updated --- scripts/tools/tools-object.js | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/scripts/tools/tools-object.js b/scripts/tools/tools-object.js index d18be330581d..dc8e9e1a601e 100644 --- a/scripts/tools/tools-object.js +++ b/scripts/tools/tools-object.js @@ -58,16 +58,13 @@ async function convertTools(data) { }; } - for (let tool of dataArray) { + await Promise.all(dataArray.map(async (tool) => { try { if (tool.name.startsWith('.asyncapi-tool')) { - // extracting the reference id of the repository which will be used to extract the path of the .asyncapi-tool file in the Tools repository - // ex: for a url = "https://api.github.com/repositories/351453552/contents/.asyncapi-tool?ref=61855e7365a881e98c2fe667a658a0005753d873" - // the text (id) present after '=' gives us a reference id for the repo - let reference_id = tool.url.split("=")[1]; - let download_url = `https://raw.githubusercontent.com/${tool.repository.full_name}/${reference_id}/${tool.path}`; + const referenceId = tool.url.split('=')[1]; + const downloadUrl = `https://raw.githubusercontent.com/${tool.repository.full_name}/${referenceId}/${tool.path}`; - const { data: toolFileContent } = await axios.get(download_url); + const { data: toolFileContent } = await axios.get(referenceId); //some stuff can be YAML const jsonToolFileContent = await convertToJson(toolFileContent) @@ -101,7 +98,7 @@ async function convertTools(data) { console.error(err) throw err; } - } + })) return finalToolsObject; } catch (err) { throw new Error(`Error processing tool: ${err.message}`) From d2235496d48d6489aaf362b4440f7bb116cdbdb0 Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Thu, 28 Nov 2024 21:56:18 +0530 Subject: [PATCH 38/43] tests updated --- tests/tools/tools-object.test.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/tools/tools-object.test.js b/tests/tools/tools-object.test.js index c8e2f8a7eab1..d71545c732d8 100644 --- a/tests/tools/tools-object.test.js +++ b/tests/tools/tools-object.test.js @@ -134,4 +134,28 @@ describe('Tools Object', () => { const malformedContent = createMalformedYAML(); await expect(convertTools(malformedContent)).rejects.toThrow(); }); + + it('should use repository description when tool description is missing', async () => { + const toolFile = createToolFileContent({ + title: 'No Description Tool', + description: '', + }); + + const repositoryDescription = 'Fallback Repository Description'; + const mockData = createMockData([{ + name: '.asyncapi-tool-no-description', + repoName: 'no-description', + description: repositoryDescription + }]); + + axios.get.mockResolvedValue({ data: toolFile }); + + const result = await convertTools(mockData); + + const toolObject = result.Category1.toolsList[0]; + + expect(toolObject.description).toBe(repositoryDescription); + expect(toolObject.title).toBe('No Description Tool'); + }); + }); From bff29b808d3e7f44c749bacb904955613b59dd19 Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Fri, 29 Nov 2024 12:08:43 +0530 Subject: [PATCH 39/43] test updated --- scripts/tools/tools-object.js | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/scripts/tools/tools-object.js b/scripts/tools/tools-object.js index dc8e9e1a601e..5ac305ae8530 100644 --- a/scripts/tools/tools-object.js +++ b/scripts/tools/tools-object.js @@ -51,12 +51,13 @@ async function convertTools(data) { const dataArray = data.items; // initialising finalToolsObject with all categories inside it with proper elements in each category - for (const category of categoryList) { - finalToolsObject[category.name] = { + finalToolsObject = categoryList.reduce((acc, category) => ({ + ...acc, + [category.name]: { description: category.description, toolsList: [] - }; - } + } + }), {}); await Promise.all(dataArray.map(async (tool) => { try { @@ -73,10 +74,10 @@ async function convertTools(data) { const isValid = await validate(jsonToolFileContent) if (isValid) { - let repositoryUrl = tool.repository.html_url; - let repoDescription = tool.repository.description; - let isAsyncAPIrepo = tool.repository.owner.login === "asyncapi"; - let toolObject = await createToolObject(jsonToolFileContent, repositoryUrl, repoDescription, isAsyncAPIrepo); + const repositoryUrl = tool.repository.html_url; + const repoDescription = tool.repository.description; + const isAsyncAPIrepo = tool.repository.owner.login === "asyncapi"; + const toolObject = await createToolObject(jsonToolFileContent, repositoryUrl, repoDescription, isAsyncAPIrepo); // Tool Object is appended to each category array according to Fuse search for categories inside Tool Object await Promise.all(jsonToolFileContent.filters.categories.map(async (category) => { From 7f7ce0d73e95a66e2455141f19bd4a270f23f466 Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Fri, 29 Nov 2024 23:17:32 +0530 Subject: [PATCH 40/43] Optimize loop --- scripts/tools/tools-object.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/scripts/tools/tools-object.js b/scripts/tools/tools-object.js index 5ac305ae8530..95d7d9434139 100644 --- a/scripts/tools/tools-object.js +++ b/scripts/tools/tools-object.js @@ -51,13 +51,15 @@ async function convertTools(data) { const dataArray = data.items; // initialising finalToolsObject with all categories inside it with proper elements in each category - finalToolsObject = categoryList.reduce((acc, category) => ({ - ...acc, - [category.name]: { - description: category.description, - toolsList: [] - } - }), {}); + finalToolsObject = Object.fromEntries( + categoryList.map(category => [ + category.name, + { + description: category.description, + toolsList: [] + } + ]) + ); await Promise.all(dataArray.map(async (tool) => { try { From dd54d8c6e75a545037ec3a062337987a6d9af333 Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Sat, 30 Nov 2024 11:07:09 +0530 Subject: [PATCH 41/43] suggested changes applied --- scripts/tools/tools-object.js | 10 +++++----- tests/helper/toolsObjectData.js | 22 ++++++++++++---------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/scripts/tools/tools-object.js b/scripts/tools/tools-object.js index 95d7d9434139..fc146758c26b 100644 --- a/scripts/tools/tools-object.js +++ b/scripts/tools/tools-object.js @@ -25,7 +25,7 @@ const fuse = new Fuse(categoryList, options) // AsyncAPI organization or not, to create a JSON tool object as required in the frontend // side to show ToolCard. const createToolObject = async (toolFile, repositoryUrl = '', repoDescription = '', isAsyncAPIrepo = '') => { - let resultantObject = { + const resultantObject = { title: toolFile.title, description: toolFile?.description ? toolFile.description : repoDescription, links: { @@ -52,7 +52,7 @@ async function convertTools(data) { // initialising finalToolsObject with all categories inside it with proper elements in each category finalToolsObject = Object.fromEntries( - categoryList.map(category => [ + categoryList.map((category) => [ category.name, { description: category.description, @@ -67,7 +67,7 @@ async function convertTools(data) { const referenceId = tool.url.split('=')[1]; const downloadUrl = `https://raw.githubusercontent.com/${tool.repository.full_name}/${referenceId}/${tool.path}`; - const { data: toolFileContent } = await axios.get(referenceId); + const { data: toolFileContent } = await axios.get(downloadUrl); //some stuff can be YAML const jsonToolFileContent = await convertToJson(toolFileContent) @@ -78,14 +78,14 @@ async function convertTools(data) { if (isValid) { const repositoryUrl = tool.repository.html_url; const repoDescription = tool.repository.description; - const isAsyncAPIrepo = tool.repository.owner.login === "asyncapi"; + const isAsyncAPIrepo = tool.repository.owner.login === 'asyncapi'; const toolObject = await createToolObject(jsonToolFileContent, repositoryUrl, repoDescription, isAsyncAPIrepo); // Tool Object is appended to each category array according to Fuse search for categories inside Tool Object await Promise.all(jsonToolFileContent.filters.categories.map(async (category) => { const categorySearch = await fuse.search(category); const targetCategory = categorySearch.length ? categorySearch[0].item.name : 'Others'; - const toolsList = finalToolsObject[targetCategory].toolsList; + const { toolsList } = finalToolsObject[targetCategory]; if (!toolsList.includes(toolObject)) { toolsList.push(toolObject); } diff --git a/tests/helper/toolsObjectData.js b/tests/helper/toolsObjectData.js index bdc8ba59a622..84b87fc3d58b 100644 --- a/tests/helper/toolsObjectData.js +++ b/tests/helper/toolsObjectData.js @@ -41,25 +41,27 @@ const createExpectedToolObject = ({ isAsyncAPIOwner = true, additionalLinks = {}, additionalFilters = {} -} = {}) => createToolFileContent({ - title, - description, - repoUrl, - categories, - hasCommercial, - additionalLinks, - additionalFilters: { isAsyncAPIOwner, ...additionalFilters } +} = {}) => + createToolFileContent({ + title, + description, + repoUrl, + categories, + hasCommercial, + additionalLinks, + additionalFilters: { isAsyncAPIOwner, ...additionalFilters } }); const createMockData = (tools = []) => ({ - items: tools.map(tool => + items: tools.map((tool) => typeof tool === 'string' ? createToolRepositoryData({ name: `.asyncapi-tool-${tool}`, repoName: tool }) : createToolRepositoryData(tool) ) }); -const createMalformedYAML = ({ title = 'Malformed Tool', +const createMalformedYAML = ({ + title = 'Malformed Tool', description = 'This tool has malformed YAML.', repoUrl = 'https://github.com/asyncapi/malformed-repo' } = {}) => ` title: ${title} From 840d13acef20938dd1136b906f5a7b49832bab91 Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Mon, 2 Dec 2024 09:26:10 +0530 Subject: [PATCH 42/43] test updated --- tests/helper/toolsObjectData.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tests/helper/toolsObjectData.js b/tests/helper/toolsObjectData.js index 84b87fc3d58b..929d985f9773 100644 --- a/tests/helper/toolsObjectData.js +++ b/tests/helper/toolsObjectData.js @@ -28,7 +28,10 @@ const createToolFileContent = ({ } = {}) => ({ title, description, - links: { repoUrl: repoUrl || `https://github.com/asyncapi/${title.toLowerCase().replace(/\s+/g, '-')}`, ...additionalLinks }, + links: { + repoUrl: repoUrl || `https://github.com/asyncapi/${encodeURIComponent(title.toLowerCase().replace(/\s+/g, '-'))}`, + ...additionalLinks + }, filters: { categories, hasCommercial, ...additionalFilters } }); @@ -41,7 +44,7 @@ const createExpectedToolObject = ({ isAsyncAPIOwner = true, additionalLinks = {}, additionalFilters = {} -} = {}) => +} = {}) => createToolFileContent({ title, description, @@ -50,7 +53,7 @@ const createExpectedToolObject = ({ hasCommercial, additionalLinks, additionalFilters: { isAsyncAPIOwner, ...additionalFilters } -}); + }); const createMockData = (tools = []) => ({ items: tools.map((tool) => @@ -60,7 +63,7 @@ const createMockData = (tools = []) => ({ ) }); -const createMalformedYAML = ({ +const createMalformedYAML = ({ title = 'Malformed Tool', description = 'This tool has malformed YAML.', repoUrl = 'https://github.com/asyncapi/malformed-repo' } = {}) => ` From 2b56cb3613c7ddd9576521604def1ff52631c35d Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Mon, 2 Dec 2024 11:41:14 +0530 Subject: [PATCH 43/43] applied coderabbit suggestions --- scripts/tools/tools-object.js | 7 ++++++- tests/tools/tools-object.test.js | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/scripts/tools/tools-object.js b/scripts/tools/tools-object.js index fc146758c26b..1d8c73f8074b 100644 --- a/scripts/tools/tools-object.js +++ b/scripts/tools/tools-object.js @@ -79,7 +79,12 @@ async function convertTools(data) { const repositoryUrl = tool.repository.html_url; const repoDescription = tool.repository.description; const isAsyncAPIrepo = tool.repository.owner.login === 'asyncapi'; - const toolObject = await createToolObject(jsonToolFileContent, repositoryUrl, repoDescription, isAsyncAPIrepo); + const toolObject = await createToolObject( + jsonToolFileContent, + repositoryUrl, + repoDescription, + isAsyncAPIrepo + ); // Tool Object is appended to each category array according to Fuse search for categories inside Tool Object await Promise.all(jsonToolFileContent.filters.categories.map(async (category) => { diff --git a/tests/tools/tools-object.test.js b/tests/tools/tools-object.test.js index d71545c732d8..2577a2a27d94 100644 --- a/tests/tools/tools-object.test.js +++ b/tests/tools/tools-object.test.js @@ -1,5 +1,5 @@ -const { convertTools, createToolObject } = require('../../scripts/tools/tools-object'); const axios = require('axios'); +const { convertTools, createToolObject } = require('../../scripts/tools/tools-object'); const { createToolFileContent, createExpectedToolObject, @@ -22,7 +22,7 @@ describe('Tools Object', () => { }); const mockToolData = (toolContent, toolNames = ['valid-tool']) => { - const mockData = createMockData(toolNames.map(name => ({ name: `.asyncapi-tool-${name}`, repoName: name }))); + const mockData = createMockData(toolNames.map((name) => ({ name: `.asyncapi-tool-${name}`, repoName: name }))); axios.get.mockResolvedValue({ data: toolContent }); return mockData; };