Skip to content

Commit 8748be0

Browse files
committed
feat: support configuring custom endpoints in loader scripts
This is useful for advanced users who might upload images to e.g. Firebase Storage and then want to proxy image URLs to augment with an `Authorization` header.
1 parent 4ce8bbf commit 8748be0

File tree

4 files changed

+37
-23
lines changed

4 files changed

+37
-23
lines changed

report-app/report-server.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
} from '../runner/reporting/report-local-disk';
1414

1515
const app = express();
16-
const reportsLoaderPromise = getReportLoader();
16+
const reportsLoader = await getReportLoader();
1717
const options = getOptions();
1818
const serverDistFolder = dirname(fileURLToPath(import.meta.url));
1919
const browserDistFolder = resolve(serverDistFolder, '../browser');
@@ -23,7 +23,7 @@ let localDataPromise: Promise<FetchedLocalReports> | null = null;
2323
// Endpoint for fetching all available report groups.
2424
app.get('/api/reports', async (_, res) => {
2525
const [remoteGroups, localData] = await Promise.all([
26-
reportsLoaderPromise.then((loader) => loader.getGroupsList()),
26+
reportsLoader.getGroupsList(),
2727
resolveLocalData(options.reportsRoot),
2828
]);
2929
const results = remoteGroups.slice();
@@ -44,8 +44,7 @@ app.get('/api/reports/:id', async (req, res) => {
4444
if (localData.has(id)) {
4545
result = [localData.get(id)!.run];
4646
} else {
47-
const loader = await reportsLoaderPromise;
48-
result = await loader.getGroupedReports(id);
47+
result = await reportsLoader.getGroupedReports(id);
4948
}
5049

5150
res.json(result);
@@ -68,15 +67,21 @@ app.use('/**', (req, res, next) => {
6867
.catch(next);
6968
});
7069

70+
// Support custom endpoints by advanced users.
71+
await reportsLoader.configureEndpoints?.(app);
72+
7173
if (isMainModule(import.meta.url)) {
72-
app.listen(options.port);
74+
app.listen(options.port, () => {
75+
console.log(`Server listening on port: ${options.port}`);
76+
});
7377
}
7478

7579
export const reqHandler = createNodeRequestHandler(app);
7680

7781
interface ReportLoader {
7882
getGroupedReports: (groupId: string) => Promise<{ group: string }[]>;
7983
getGroupsList: () => Promise<{ id: string }[]>;
84+
configureEndpoints?: (expressApp: typeof app) => Promise<void>;
8085
}
8186

8287
/** Gets the server options from the command line. */

report-app/src/app/pages/report-viewer/report-viewer.ts

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -235,14 +235,7 @@ export class ReportViewer {
235235
});
236236

237237
protected getScreenshotUrl(result: AssessmentResult): string | null {
238-
for (let i = result.attemptDetails.length - 1; i > -1; i--) {
239-
const screenshotUrl =
240-
result.attemptDetails[i].buildResult.screenshotPngUrl;
241-
if (screenshotUrl) {
242-
return screenshotUrl;
243-
}
244-
}
245-
return null;
238+
return result.build.screenshotPngUrl ?? null;
246239
}
247240

248241
protected isLoading = this.reportsFetcher.isLoadingSingleReport;

runner/report-cli.ts

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -59,19 +59,26 @@ async function handler(cliArgs: Arguments<Options>): Promise<void> {
5959
);
6060
}
6161

62-
console.log(
63-
formatTitleCard(
64-
[
65-
`View your reports at http://localhost:${cliArgs.port}`,
66-
`Reports are served from ${relative(process.cwd(), reportsDir)}`,
67-
].join('\n')
68-
)
69-
);
70-
7162
await executeCommand(
7263
'node report-app/server/server.mjs',
7364
join(import.meta.dirname, '..'),
7465
environmentVariables,
75-
{ forwardStderrToParent: true, forwardStdoutToParent: true }
66+
{
67+
forwardStderrToParent: true,
68+
forwardStdoutToParent: true,
69+
notifyWhenMatchingStdout: {
70+
pattern: /Server listening on port:/,
71+
notifyFn: () => {
72+
console.log(
73+
formatTitleCard(
74+
[
75+
`View your reports at http://localhost:${cliArgs.port}`,
76+
`Reports are served from ${relative(process.cwd(), reportsDir)}`,
77+
].join('\n')
78+
)
79+
);
80+
},
81+
},
82+
}
7683
);
7784
}

runner/utils/exec.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export function executeCommand(
1313
opts: {
1414
forwardStderrToParent?: boolean;
1515
forwardStdoutToParent?: boolean;
16+
notifyWhenMatchingStdout?: { notifyFn: () => void; pattern: RegExp };
1617
abortSignal?: AbortSignal;
1718
} = {}
1819
): Promise<string> {
@@ -28,6 +29,7 @@ export function executeCommand(
2829

2930
let stdout = '';
3031
let stderr = '';
32+
let notifyWhenMatchingStdout = opts.notifyWhenMatchingStdout;
3133

3234
proc.on('error', (err) => {
3335
reject(err);
@@ -38,6 +40,13 @@ export function executeCommand(
3840
if (opts.forwardStdoutToParent) {
3941
process.stdout.write(c);
4042
}
43+
if (
44+
notifyWhenMatchingStdout &&
45+
notifyWhenMatchingStdout.pattern.test(stdout)
46+
) {
47+
notifyWhenMatchingStdout.notifyFn();
48+
notifyWhenMatchingStdout = undefined;
49+
}
4150
});
4251
proc.stderr!.on('data', (c) => {
4352
stderr += c;

0 commit comments

Comments
 (0)