From 7bbc0a8c98644f777eb433e6f6bc55883195b994 Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Sun, 28 Jul 2024 23:08:40 +0530 Subject: [PATCH 1/4] tools test added --- scripts/build-tools.js | 2 +- scripts/tools/combine-tools.js | 13 +- tests/fixtures/tools/automated-tools.json | 17 +++ tests/fixtures/tools/manual-tools.json | 12 ++ tests/tools/combine-tools.test.js | 149 ++++++++++++++++++++++ 5 files changed, 182 insertions(+), 11 deletions(-) create mode 100644 tests/fixtures/tools/automated-tools.json create mode 100644 tests/fixtures/tools/manual-tools.json create mode 100644 tests/tools/combine-tools.test.js diff --git a/scripts/build-tools.js b/scripts/build-tools.js index 363e3418816..f3997b06d1d 100644 --- a/scripts/build-tools.js +++ b/scripts/build-tools.js @@ -14,7 +14,7 @@ const buildTools = async () => { resolve(__dirname, '../config', 'tools-automated.json'), JSON.stringify(automatedTools, null, ' ') ); - await combineTools(automatedTools, manualTools); + await combineTools(automatedTools, manualTools, resolve(__dirname, '../../config', 'tools.json'), resolve(__dirname, '../../config', 'all-tags.json')); } catch (err) { console.log(err); throw err diff --git a/scripts/tools/combine-tools.js b/scripts/tools/combine-tools.js index f929f00095b..602262428fa 100644 --- a/scripts/tools/combine-tools.js +++ b/scripts/tools/combine-tools.js @@ -5,7 +5,6 @@ const fs = require('fs') const schema = require("./tools-schema.json"); const Ajv = require("ajv") const addFormats = require("ajv-formats") -const { resolve } = require('path'); const Fuse = require("fuse.js"); const ajv = new Ajv() addFormats(ajv, ["uri"]) @@ -106,7 +105,7 @@ const getFinalTool = async (toolObject) => { // Combine the automated tools and manual tools list into single JSON object file, and // lists down all the language and technology tags in one JSON file. -const combineTools = async (automatedTools, manualTools) => { +const combineTools = async (automatedTools, manualTools, toolsPath, tagsPath) => { for (const key in automatedTools) { let finalToolsList = []; if (automatedTools[key].toolsList.length) { @@ -136,14 +135,8 @@ const combineTools = async (automatedTools, manualTools) => { finalToolsList.sort((tool, anotherTool) => tool.title.localeCompare(anotherTool.title)); finalTools[key].toolsList = finalToolsList } - fs.writeFileSync( - resolve(__dirname, '../../config', 'tools.json'), - JSON.stringify(finalTools) - ); - fs.writeFileSync( - resolve(__dirname, '../../config', 'all-tags.json'), - JSON.stringify({ languages: languageList, technologies: technologyList }), - ) + fs.writeFileSync(toolsPath,JSON.stringify(finalTools)); + fs.writeFileSync(tagsPath,JSON.stringify({ languages: languageList, technologies: technologyList }),) } module.exports = { combineTools } \ No newline at end of file diff --git a/tests/fixtures/tools/automated-tools.json b/tests/fixtures/tools/automated-tools.json new file mode 100644 index 00000000000..1184da03e71 --- /dev/null +++ b/tests/fixtures/tools/automated-tools.json @@ -0,0 +1,17 @@ +{ + "category1": { + "description": "Sample Category", + "toolsList": [ + { + "title": "Tool B", + "filters": { + "language": "Python", + "technology": ["Flask"] + }, + "links": { + "repoUrl": "https://github.com/asyncapi/tool-b" + } + } + ] + } +} diff --git a/tests/fixtures/tools/manual-tools.json b/tests/fixtures/tools/manual-tools.json new file mode 100644 index 00000000000..47469bc1a7e --- /dev/null +++ b/tests/fixtures/tools/manual-tools.json @@ -0,0 +1,12 @@ +[ + { + "title": "Tool A", + "filters": { + "language": "JavaScript", + "technology": ["Node.js"] + }, + "links": { + "repoUrl": "https://github.com/asyncapi/tool-a" + } + } +] diff --git a/tests/tools/combine-tools.test.js b/tests/tools/combine-tools.test.js new file mode 100644 index 00000000000..352f8e16f32 --- /dev/null +++ b/tests/tools/combine-tools.test.js @@ -0,0 +1,149 @@ +const fs = require('fs'); +const path = require('path'); +const { combineTools } = require('../../scripts/tools/combine-tools'); +const Ajv = require("ajv"); +const addFormats = require("ajv-formats"); + +// Mock dependencies +jest.mock('../../scripts/tools/tags-color', () => ({ + languagesColor: [ + { name: 'JavaScript', color: 'bg-[#57f281]', borderColor: 'border-[#37f069]' }, + { name: 'Python', color: 'bg-[#3572A5]', borderColor: 'border-[#3572A5]' } + ], + technologiesColor: [ + { name: 'Node.js', color: 'bg-[#61d0f2]', borderColor: 'border-[#40ccf7]' }, + { name: 'Flask', color: 'bg-[#000000]', borderColor: 'border-[#FFFFFF]' } + ] +})); + +jest.mock('../../scripts/tools/categorylist', () => ({ + categoryList: [ + { name: 'category1', description: 'Sample Category 1' }, + { name: 'category2', description: 'Sample Category 2' } + ] +})); + +jest.mock('../../scripts/tools/tools-object', () => ({ + createToolObject: jest.fn((tool, _, __, isAsyncAPIrepo) => { + return { ...tool, isAsyncAPIrepo }; + }) +})); + +const ajv = new Ajv(); +addFormats(ajv, ["uri"]); + +const readJSON = (filePath) => JSON.parse(fs.readFileSync(filePath, 'utf-8')); + +describe('combineTools function', () => { + const toolsPath = path.join(__dirname, '../', 'fixtures', 'tools', 'tools.json'); + const tagsPath = path.join(__dirname, '../', 'fixtures', 'tools', 'tags.json'); + const manualToolsPath = path.join(__dirname, '../', 'fixtures', 'tools', 'manual-tools.json'); + const automatedToolsPath = path.join(__dirname, '../', 'fixtures', 'tools', 'automated-tools.json'); + + let manualTools; + let automatedTools; + + beforeAll(() => { + manualTools = readJSON(manualToolsPath); + automatedTools = readJSON(automatedToolsPath); + }); + + afterAll(() => { + // Clean up by removing the created files + if (fs.existsSync(toolsPath)) fs.unlinkSync(toolsPath); + if (fs.existsSync(tagsPath)) fs.unlinkSync(tagsPath); + }); + + test('should combine tools and create correct JSON files', async () => { + await combineTools(automatedTools, manualTools, toolsPath, tagsPath); + + // Verify toolsPath file exists and has correct content + const combinedTools = readJSON(toolsPath); + expect(combinedTools).toHaveProperty('category1'); + + // Verify tagsPath file exists and has correct content + const tagsData = readJSON(tagsPath); + expect(tagsData).toHaveProperty('languages'); + expect(tagsData).toHaveProperty('technologies'); + expect(tagsData.languages).toContainEqual({ + name: 'JavaScript', + color: 'bg-[#57f281]', + borderColor: 'border-[#37f069]' + }); + expect(tagsData.languages).toContainEqual({ + name: 'Python', + color: 'bg-[#3572A5]', + borderColor: 'border-[#3572A5]' + }); + expect(tagsData.technologies).toContainEqual({ + name: 'Node.js', + color: 'bg-[#61d0f2]', + borderColor: 'border-[#40ccf7]' + }); + expect(tagsData.technologies).toContainEqual({ + name: 'Flask', + color: 'bg-[#000000]', + borderColor: 'border-[#FFFFFF]' + }); + }); + + test('should handle tools with missing language or technology', async () => { + const manualToolsWithMissingData = [ + { + title: 'Tool C', + filters: {}, + links: { repoUrl: 'https://github.com/asyncapi/tool-c' } + } + ]; + + await combineTools({}, manualToolsWithMissingData, toolsPath, tagsPath); + + const combinedTools = readJSON(toolsPath); + expect(combinedTools).toHaveProperty('category1'); + }); + + test('should validate manual tools and skip invalid ones', async () => { + const invalidManualTools = [ + { + title: 'Invalid Tool', + filters: { + language: 'Invalid Language' + }, + links: {} + } + ]; + + await combineTools({}, invalidManualTools, toolsPath, tagsPath); + + const combinedTools = readJSON(toolsPath); + expect(combinedTools).toHaveProperty('category1'); + }); + + + test('should sort tools alphabetically by title', async () => { + const manualToolsToSort = { + category1: { + description: 'Sample Category', + toolsList: [ + { + title: 'Tool Z', + filters: { language: 'JavaScript' }, + links: { repoUrl: 'https://github.com/asyncapi/tool-z' } + }, + { + title: 'Tool A', + filters: { language: 'Python' }, + links: { repoUrl: 'https://github.com/asyncapi/tool-a' } + } + ] + } + }; + + await combineTools(manualToolsToSort, {}, toolsPath, tagsPath); + + const combinedTools = readJSON(toolsPath); + const toolTitles = combinedTools.category1.toolsList.map(tool => tool.title); + expect(toolTitles).toEqual(['Tool A', 'Tool Z']); + }); + +}); From 527cf9f4bfafbc37f38ae7e5b1b9090add38bf1a Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Mon, 29 Jul 2024 11:40:11 +0530 Subject: [PATCH 2/4] tools test updated for errors --- tests/tools/combine-tools.test.js | 70 +++++++++++++++++-------------- 1 file changed, 39 insertions(+), 31 deletions(-) diff --git a/tests/tools/combine-tools.test.js b/tests/tools/combine-tools.test.js index 352f8e16f32..0e8cdff8fb6 100644 --- a/tests/tools/combine-tools.test.js +++ b/tests/tools/combine-tools.test.js @@ -1,10 +1,8 @@ const fs = require('fs'); const path = require('path'); const { combineTools } = require('../../scripts/tools/combine-tools'); -const Ajv = require("ajv"); -const addFormats = require("ajv-formats"); +const { createToolObject } = require('../../scripts/tools/tools-object'); -// Mock dependencies jest.mock('../../scripts/tools/tags-color', () => ({ languagesColor: [ { name: 'JavaScript', color: 'bg-[#57f281]', borderColor: 'border-[#37f069]' }, @@ -29,9 +27,6 @@ jest.mock('../../scripts/tools/tools-object', () => ({ }) })); -const ajv = new Ajv(); -addFormats(ajv, ["uri"]); - const readJSON = (filePath) => JSON.parse(fs.readFileSync(filePath, 'utf-8')); describe('combineTools function', () => { @@ -43,25 +38,26 @@ describe('combineTools function', () => { let manualTools; let automatedTools; + let consoleErrorMock; + beforeAll(() => { manualTools = readJSON(manualToolsPath); automatedTools = readJSON(automatedToolsPath); + + consoleErrorMock = jest.spyOn(console, 'error').mockImplementation(() => {}); }); afterAll(() => { - // Clean up by removing the created files if (fs.existsSync(toolsPath)) fs.unlinkSync(toolsPath); if (fs.existsSync(tagsPath)) fs.unlinkSync(tagsPath); }); - test('should combine tools and create correct JSON files', async () => { + it('should combine tools and create correct JSON files', async () => { await combineTools(automatedTools, manualTools, toolsPath, tagsPath); - // Verify toolsPath file exists and has correct content const combinedTools = readJSON(toolsPath); expect(combinedTools).toHaveProperty('category1'); - // Verify tagsPath file exists and has correct content const tagsData = readJSON(tagsPath); expect(tagsData).toHaveProperty('languages'); expect(tagsData).toHaveProperty('technologies'); @@ -87,7 +83,7 @@ describe('combineTools function', () => { }); }); - test('should handle tools with missing language or technology', async () => { + it('should handle tools with missing language or technology', async () => { const manualToolsWithMissingData = [ { title: 'Tool C', @@ -102,25 +98,7 @@ describe('combineTools function', () => { expect(combinedTools).toHaveProperty('category1'); }); - test('should validate manual tools and skip invalid ones', async () => { - const invalidManualTools = [ - { - title: 'Invalid Tool', - filters: { - language: 'Invalid Language' - }, - links: {} - } - ]; - - await combineTools({}, invalidManualTools, toolsPath, tagsPath); - - const combinedTools = readJSON(toolsPath); - expect(combinedTools).toHaveProperty('category1'); - }); - - - test('should sort tools alphabetically by title', async () => { + it('should sort tools alphabetically by title', async () => { const manualToolsToSort = { category1: { description: 'Sample Category', @@ -146,4 +124,34 @@ describe('combineTools function', () => { expect(toolTitles).toEqual(['Tool A', 'Tool Z']); }); -}); + + it('should log validation errors to console.error', async () => { + const invalidTool = { title: 'Invalid Tool' }; + const automatedTools = { + 'category1': { + description: 'Category 1 Description', + toolsList: [] + } + }; + const manualTools = { + 'category1': { + toolsList: [invalidTool] + } + }; + + createToolObject.mockImplementation((tool) => Promise.resolve(tool)); + + await combineTools(automatedTools, manualTools, toolsPath, tagsPath); + + const errorCalls = console.error.mock.calls; + + expect(errorCalls[0][0]).toBe('Script is not failing, it is just dropping errors for further investigation'); + expect(errorCalls[1][0]).toBe('Invalid Invalid Tool .asyncapi-tool file.'); + expect(errorCalls[2][0]).toBe('Located in manual-tools.json file'); + expect(errorCalls[3][0]).toEqual(expect.stringContaining('Validation errors:')); + + expect(fs.existsSync(toolsPath)).toBe(true); + expect(fs.existsSync(tagsPath)).toBe(true); + }); + +}); \ No newline at end of file From 878023a0f87b33fdfb51c675b35c24de6467984a Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Wed, 31 Jul 2024 18:43:24 +0530 Subject: [PATCH 3/4] tools test upadted --- tests/tools/combine-tools.test.js | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/tests/tools/combine-tools.test.js b/tests/tools/combine-tools.test.js index 0e8cdff8fb6..5f717796909 100644 --- a/tests/tools/combine-tools.test.js +++ b/tests/tools/combine-tools.test.js @@ -154,4 +154,34 @@ describe('combineTools function', () => { expect(fs.existsSync(tagsPath)).toBe(true); }); + it('should handle tools with multiple languages, including new ones', async () => { + const toolWithMultipleLanguages = { + title: 'Multi-Language Tool', + filters: { + language: ['JavaScript', 'Python', 'NewLanguage'], + technology: ['Node.js'] + }, + links: { repoUrl: 'https://github.com/example/multi-language-tool' } + }; + + const automatedTools = { + 'category1': { + description: 'Category 1 Description', + toolsList: [toolWithMultipleLanguages] + } + }; + + await combineTools(automatedTools, {}, toolsPath, tagsPath); + + const combinedTools = readJSON(toolsPath); + const tool = combinedTools.category1.toolsList[0]; + + expect(tool.filters.language).toHaveLength(3); + expect(tool.filters.language).toContainEqual(expect.objectContaining({ name: 'JavaScript' })); + expect(tool.filters.language).toContainEqual(expect.objectContaining({ name: 'Python' })); + expect(tool.filters.language).toContainEqual(expect.objectContaining({ name: 'NewLanguage' })); + + const tagsData = readJSON(tagsPath); + expect(tagsData.languages).toContainEqual(expect.objectContaining({ name: 'NewLanguage' })); + }); }); \ No newline at end of file From be808852f2b4fdb113d088fd0af81993e4a0597c Mon Sep 17 00:00:00 2001 From: Vishvamsinh Vaghela Date: Sat, 31 Aug 2024 22:46:40 +0530 Subject: [PATCH 4/4] refactor build-tools --- 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 f3997b06d1d..e8c380a6298 100644 --- a/scripts/build-tools.js +++ b/scripts/build-tools.js @@ -6,15 +6,19 @@ const manualTools = require('../config/tools-manual.json') const fs = require('fs'); const { resolve } = require('path'); +let toolsPath = resolve(__dirname, '../../config', 'tools.json') +let tagsPath = resolve(__dirname, '../../config', 'all-tags.json') +let automatedToolsPath = resolve(__dirname, '../config', 'tools-automated.json') + const buildTools = async () => { try { let githubExtractData = await getData(); let automatedTools = await convertTools(githubExtractData); fs.writeFileSync( - resolve(__dirname, '../config', 'tools-automated.json'), + automatedToolsPath, JSON.stringify(automatedTools, null, ' ') ); - await combineTools(automatedTools, manualTools, resolve(__dirname, '../../config', 'tools.json'), resolve(__dirname, '../../config', 'all-tags.json')); + await combineTools(automatedTools, manualTools, toolsPath, tagsPath); } catch (err) { console.log(err); throw err