From 7d9150fe1c5c27b3fe7d6a6956a9b0504a9a9ed2 Mon Sep 17 00:00:00 2001 From: Roman Kuznetsov Date: Thu, 31 Aug 2023 23:47:48 +0300 Subject: [PATCH] perf: resolve json databases while merging report --- lib/merge-reports/index.js | 45 +++++++++++++++++++++++++++- lib/server-utils.ts | 12 ++++++-- test/unit/lib/merge-reports/index.js | 37 +++++++++++++++++++++-- 3 files changed, 88 insertions(+), 6 deletions(-) diff --git a/lib/merge-reports/index.js b/lib/merge-reports/index.js index d18d685a4..eea44cb6b 100644 --- a/lib/merge-reports/index.js +++ b/lib/merge-reports/index.js @@ -1,13 +1,17 @@ 'use strict'; +const axios = require('axios'); +const _ = require('lodash'); const serverUtils = require('../server-utils'); module.exports = async (pluginConfig, hermione, srcPaths, {destination: destPath}) => { validateOpts(srcPaths, destPath); + const resolvedUrls = await tryResolveUrls(srcPaths); + await Promise.all([ serverUtils.saveStaticFilesToReportDir(hermione.htmlReporter, pluginConfig, destPath), - serverUtils.writeDatabaseUrlsFile(destPath, srcPaths) + serverUtils.writeDatabaseUrlsFile(destPath, resolvedUrls) ]); await hermione.htmlReporter.emitAsync(hermione.htmlReporter.events.REPORT_SAVED, {reportPath: destPath}); @@ -22,3 +26,42 @@ function validateOpts(srcPaths, destPath) { throw new Error(`Destination report path: ${destPath}, exists in source report paths`); } } + +async function tryResolveUrls(urls) { + const resolvedUrls = []; + const results = await Promise.all(urls.map(tryResolveUrl)); + + results.forEach(({jsonUrls, dbUrls}) => { + resolvedUrls.push(...jsonUrls.concat(dbUrls)); + }); + + return resolvedUrls; +} + +async function tryResolveUrl(url) { + const jsonUrls = []; + const dbUrls = []; + + if (serverUtils.isDbUrl(url)) { + dbUrls.push(url); + } else if (serverUtils.isJsonUrl(url)) { + try { + const {data} = await axios.get(url); + const currentDbUrls = _.get(data, 'dbUrls', []); + const currentJsonUrls = _.get(data, 'jsonUrls', []); + + const responses = await Promise.all(currentJsonUrls.map(tryResolveUrl)); + + dbUrls.push(...currentDbUrls); + + responses.forEach(response => { + dbUrls.push(...response.dbUrls); + jsonUrls.push(...response.jsonUrls); + }); + } catch (e) { + jsonUrls.push(url); + } + } + + return {jsonUrls, dbUrls}; +} diff --git a/lib/server-utils.ts b/lib/server-utils.ts index a20fedb92..94f3b09f2 100644 --- a/lib/server-utils.ts +++ b/lib/server-utils.ts @@ -171,9 +171,17 @@ export function urlPathNameEndsWith(currentUrl: string, searchString: string): b } } +export function isJsonUrl(url: string): boolean { + return urlPathNameEndsWith(url, '.json'); +} + +export function isDbUrl(url: string): boolean { + return urlPathNameEndsWith(url, '.db'); +} + export async function writeDatabaseUrlsFile(destPath: string, srcPaths: string[]): Promise { - const jsonUrls = srcPaths.filter(p => urlPathNameEndsWith(p, '.json')); - const dbUrls = srcPaths.filter(p => urlPathNameEndsWith(p, '.db')); + const jsonUrls = srcPaths.filter(isJsonUrl); + const dbUrls = srcPaths.filter(isDbUrl); const data = { dbUrls, jsonUrls diff --git a/test/unit/lib/merge-reports/index.js b/test/unit/lib/merge-reports/index.js index e83f9a2c5..d35c2ff4c 100644 --- a/test/unit/lib/merge-reports/index.js +++ b/test/unit/lib/merge-reports/index.js @@ -7,7 +7,7 @@ const originalServerUtils = require('lib/server-utils'); describe('lib/merge-reports', () => { const sandbox = sinon.sandbox.create(); - let htmlReporter, serverUtils, mergeReports; + let htmlReporter, serverUtils, mergeReports, axiosStub; const execMergeReports_ = async ({pluginConfig = stubConfig(), hermione = stubTool(stubConfig()), paths = [], opts = {}}) => { opts = _.defaults(opts, {destination: 'default-dest-report/path'}); @@ -17,6 +17,7 @@ describe('lib/merge-reports', () => { beforeEach(() => { serverUtils = _.clone(originalServerUtils); + axiosStub = {get: sandbox.stub().rejects()}; sandbox.stub(serverUtils, 'saveStaticFilesToReportDir').resolves(); sandbox.stub(serverUtils, 'writeDatabaseUrlsFile').resolves(); @@ -26,7 +27,8 @@ describe('lib/merge-reports', () => { htmlReporter.emitAsync = sinon.stub(); mergeReports = proxyquire('lib/merge-reports', { - '../server-utils': serverUtils + '../server-utils': serverUtils, + 'axios': axiosStub }); }); @@ -51,7 +53,7 @@ describe('lib/merge-reports', () => { it('should merge reports', async () => { const pluginConfig = stubConfig(); const hermione = stubTool(pluginConfig, {}, {}, htmlReporter); - const paths = ['src-report/path-1', 'src-report/path-2']; + const paths = ['src-report/path-1.json', 'src-report/path-2.db']; const destination = 'dest-report/path'; await execMergeReports_({pluginConfig, hermione, paths, opts: {destination}}); @@ -60,6 +62,35 @@ describe('lib/merge-reports', () => { assert.calledOnceWith(serverUtils.writeDatabaseUrlsFile, destination, paths); }); + it('should resolve json urls while merging reports', async () => { + const pluginConfig = stubConfig(); + const hermione = stubTool(pluginConfig, {}, {}, htmlReporter); + const paths = ['src-report/path-1.json']; + const destination = 'dest-report/path'; + + axiosStub.get.withArgs('src-report/path-1.json').resolves({data: {jsonUrls: ['src-report/path-2.json', 'src-report/path-3.json'], dbUrls: ['path-1.db']}}); + axiosStub.get.withArgs('src-report/path-2.json').resolves({data: {jsonUrls: [], dbUrls: ['path-2.db']}}); + axiosStub.get.withArgs('src-report/path-3.json').resolves({data: {jsonUrls: ['src-report/path-4.json'], dbUrls: ['path-3.db']}}); + axiosStub.get.withArgs('src-report/path-4.json').resolves({data: {jsonUrls: [], dbUrls: ['path-4.db']}}); + + await execMergeReports_({pluginConfig, hermione, paths, opts: {destination}}); + + assert.calledOnceWith(serverUtils.writeDatabaseUrlsFile, destination, ['path-1.db', 'path-2.db', 'path-3.db', 'path-4.db']); + }); + + it('should fallback to json url while merging reports', async () => { + const pluginConfig = stubConfig(); + const hermione = stubTool(pluginConfig, {}, {}, htmlReporter); + const paths = ['src-report/path-1.json']; + const destination = 'dest-report/path'; + + axiosStub.get.rejects(); + + await execMergeReports_({pluginConfig, hermione, paths, opts: {destination}}); + + assert.calledOnceWith(serverUtils.writeDatabaseUrlsFile, destination, ['src-report/path-1.json']); + }); + it('should emit REPORT_SAVED event', async () => { const hermione = stubTool({}, {}, {}, htmlReporter); const destination = 'dest-report/path';