diff --git a/report-app/report-server.ts b/report-app/report-server.ts index 113a4a9..f2aeb3b 100644 --- a/report-app/report-server.ts +++ b/report-app/report-server.ts @@ -13,7 +13,7 @@ import { } from '../runner/reporting/report-local-disk'; const app = express(); -const reportsLoaderPromise = getReportLoader(); +const reportsLoader = await getReportLoader(); const options = getOptions(); const serverDistFolder = dirname(fileURLToPath(import.meta.url)); const browserDistFolder = resolve(serverDistFolder, '../browser'); @@ -23,7 +23,7 @@ let localDataPromise: Promise | null = null; // Endpoint for fetching all available report groups. app.get('/api/reports', async (_, res) => { const [remoteGroups, localData] = await Promise.all([ - reportsLoaderPromise.then((loader) => loader.getGroupsList()), + reportsLoader.getGroupsList(), resolveLocalData(options.reportsRoot), ]); const results = remoteGroups.slice(); @@ -44,8 +44,7 @@ app.get('/api/reports/:id', async (req, res) => { if (localData.has(id)) { result = [localData.get(id)!.run]; } else { - const loader = await reportsLoaderPromise; - result = await loader.getGroupedReports(id); + result = await reportsLoader.getGroupedReports(id); } res.json(result); @@ -68,8 +67,13 @@ app.use('/**', (req, res, next) => { .catch(next); }); +// Support custom endpoints by advanced users. +await reportsLoader.configureEndpoints?.(app); + if (isMainModule(import.meta.url)) { - app.listen(options.port); + app.listen(options.port, () => { + console.log(`Server listening on port: ${options.port}`); + }); } export const reqHandler = createNodeRequestHandler(app); @@ -77,6 +81,7 @@ export const reqHandler = createNodeRequestHandler(app); interface ReportLoader { getGroupedReports: (groupId: string) => Promise<{ group: string }[]>; getGroupsList: () => Promise<{ id: string }[]>; + configureEndpoints?: (expressApp: typeof app) => Promise; } /** Gets the server options from the command line. */ diff --git a/report-app/src/app/pages/report-viewer/report-viewer.ts b/report-app/src/app/pages/report-viewer/report-viewer.ts index 70ff5e8..16d8ce2 100644 --- a/report-app/src/app/pages/report-viewer/report-viewer.ts +++ b/report-app/src/app/pages/report-viewer/report-viewer.ts @@ -235,14 +235,7 @@ export class ReportViewer { }); protected getScreenshotUrl(result: AssessmentResult): string | null { - for (let i = result.attemptDetails.length - 1; i > -1; i--) { - const screenshotUrl = - result.attemptDetails[i].buildResult.screenshotPngUrl; - if (screenshotUrl) { - return screenshotUrl; - } - } - return null; + return result.build.screenshotPngUrl ?? null; } protected isLoading = this.reportsFetcher.isLoadingSingleReport; diff --git a/runner/report-cli.ts b/runner/report-cli.ts index bd777d2..ed51fdd 100644 --- a/runner/report-cli.ts +++ b/runner/report-cli.ts @@ -59,19 +59,26 @@ async function handler(cliArgs: Arguments): Promise { ); } - console.log( - formatTitleCard( - [ - `View your reports at http://localhost:${cliArgs.port}`, - `Reports are served from ${relative(process.cwd(), reportsDir)}`, - ].join('\n') - ) - ); - await executeCommand( 'node report-app/server/server.mjs', join(import.meta.dirname, '..'), environmentVariables, - { forwardStderrToParent: true, forwardStdoutToParent: true } + { + forwardStderrToParent: true, + forwardStdoutToParent: true, + notifyWhenMatchingStdout: { + pattern: /Server listening on port:/, + notifyFn: () => { + console.log( + formatTitleCard( + [ + `View your reports at http://localhost:${cliArgs.port}`, + `Reports are served from ${relative(process.cwd(), reportsDir)}`, + ].join('\n') + ) + ); + }, + }, + } ); } diff --git a/runner/utils/exec.ts b/runner/utils/exec.ts index 83de7f3..e774529 100644 --- a/runner/utils/exec.ts +++ b/runner/utils/exec.ts @@ -13,6 +13,7 @@ export function executeCommand( opts: { forwardStderrToParent?: boolean; forwardStdoutToParent?: boolean; + notifyWhenMatchingStdout?: { notifyFn: () => void; pattern: RegExp }; abortSignal?: AbortSignal; } = {} ): Promise { @@ -28,6 +29,7 @@ export function executeCommand( let stdout = ''; let stderr = ''; + let notifyWhenMatchingStdout = opts.notifyWhenMatchingStdout; proc.on('error', (err) => { reject(err); @@ -38,6 +40,13 @@ export function executeCommand( if (opts.forwardStdoutToParent) { process.stdout.write(c); } + if ( + notifyWhenMatchingStdout && + notifyWhenMatchingStdout.pattern.test(stdout) + ) { + notifyWhenMatchingStdout.notifyFn(); + notifyWhenMatchingStdout = undefined; + } }); proc.stderr!.on('data', (c) => { stderr += c;