-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: prepare html-reporter for pwt GUI integration (#522)
* refactor: rename sqlite-adapter to sqlite-client * chore: re-write hermione.js to typescript * refactor: get rid of init method in sqlite-client * refactor: streamline test result types in sqlite-client * refactor: handle attempt number explicitly * fix: unit test and minor bug fixes * refactor: get rid of plugin-adapter * fix: fix review issues * test: fix tests building * fix: fix test attempt manager, review issues, status computing * fix: fix unit and e2e tests, further refactoring * test: update chrome installation flow * test: update browser-utils package-lock * test: grant chrome for testing exec permissions
- Loading branch information
Showing
52 changed files
with
1,672 additions
and
3,544 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
import os from 'os'; | ||
import path from 'path'; | ||
import Hermione, {TestResult as HermioneTestResult} from 'hermione'; | ||
import _ from 'lodash'; | ||
import PQueue from 'p-queue'; | ||
import {CommanderStatic} from '@gemini-testing/commander'; | ||
|
||
import {cliCommands} from './lib/cli-commands'; | ||
import {hasFailedImages} from './lib/common-utils'; | ||
import {parseConfig} from './lib/config'; | ||
import {SKIPPED, SUCCESS, TestStatus, ToolName, UNKNOWN_ATTEMPT} from './lib/constants'; | ||
import {HtmlReporter} from './lib/plugin-api'; | ||
import {StaticReportBuilder} from './lib/report-builder/static'; | ||
import {formatTestResult, logPathToHtmlReport, logError} from './lib/server-utils'; | ||
import {SqliteClient} from './lib/sqlite-client'; | ||
import {HtmlReporterApi, ImageInfoFull, ReporterOptions} from './lib/types'; | ||
import {createWorkers, CreateWorkersRunner} from './lib/workers/create-workers'; | ||
|
||
export = (hermione: Hermione, opts: Partial<ReporterOptions>): void => { | ||
if (hermione.isWorker() || !opts.enabled) { | ||
return; | ||
} | ||
|
||
const config = parseConfig(opts); | ||
|
||
const htmlReporter = HtmlReporter.create(config, {toolName: ToolName.Hermione}); | ||
|
||
(hermione as Hermione & HtmlReporterApi).htmlReporter = htmlReporter; | ||
|
||
let isCliCommandLaunched = false; | ||
let handlingTestResults: Promise<void>; | ||
let staticReportBuilder: StaticReportBuilder; | ||
|
||
const withMiddleware = <T extends (...args: unknown[]) => unknown>(fn: T): | ||
(...args: Parameters<T>) => ReturnType<T> | undefined => { | ||
return (...args: unknown[]) => { | ||
// If any CLI command was launched, e.g. merge-reports, we need to interrupt regular flow | ||
if (isCliCommandLaunched) { | ||
return; | ||
} | ||
|
||
return fn.call(undefined, ...args) as ReturnType<T>; | ||
}; | ||
}; | ||
|
||
hermione.on(hermione.events.CLI, (commander: CommanderStatic) => { | ||
_.values(cliCommands).forEach((command: string) => { | ||
// eslint-disable-next-line @typescript-eslint/no-var-requires | ||
require(path.resolve(__dirname, 'lib/cli-commands', command))(commander, config, hermione); | ||
|
||
commander.prependListener(`command:${command}`, () => { | ||
isCliCommandLaunched = true; | ||
}); | ||
}); | ||
}); | ||
|
||
hermione.on(hermione.events.INIT, withMiddleware(async () => { | ||
const dbClient = await SqliteClient.create({htmlReporter, reportPath: config.path}); | ||
staticReportBuilder = StaticReportBuilder.create(htmlReporter, config, {dbClient}); | ||
|
||
handlingTestResults = Promise.all([ | ||
staticReportBuilder.saveStaticFiles(), | ||
handleTestResults(hermione, staticReportBuilder) | ||
]).then(async () => { | ||
await staticReportBuilder.finalize(); | ||
}).then(async () => { | ||
await htmlReporter.emitAsync(htmlReporter.events.REPORT_SAVED, {reportPath: config.path}); | ||
}); | ||
|
||
htmlReporter.emit(htmlReporter.events.DATABASE_CREATED, dbClient.getRawConnection()); | ||
})); | ||
|
||
hermione.on(hermione.events.RUNNER_START, withMiddleware((runner) => { | ||
staticReportBuilder.registerWorkers(createWorkers(runner as unknown as CreateWorkersRunner)); | ||
})); | ||
|
||
hermione.on(hermione.events.RUNNER_END, withMiddleware(async () => { | ||
try { | ||
await handlingTestResults; | ||
|
||
logPathToHtmlReport(config); | ||
} catch (e: unknown) { | ||
logError(e as Error); | ||
} | ||
})); | ||
}; | ||
|
||
async function handleTestResults(hermione: Hermione, reportBuilder: StaticReportBuilder): Promise<void> { | ||
return new Promise((resolve, reject) => { | ||
const queue = new PQueue({concurrency: os.cpus().length}); | ||
const promises: Promise<unknown>[] = []; | ||
|
||
hermione.on(hermione.events.TEST_PASS, testResult => { | ||
promises.push(queue.add(async () => { | ||
const formattedResult = formatTestResult(testResult, SUCCESS, UNKNOWN_ATTEMPT, reportBuilder); | ||
await reportBuilder.addSuccess(formattedResult); | ||
}).catch(reject)); | ||
}); | ||
|
||
hermione.on(hermione.events.RETRY, testResult => { | ||
promises.push(queue.add(async () => { | ||
const status = hasFailedImages(testResult.assertViewResults as ImageInfoFull[]) ? TestStatus.FAIL : TestStatus.ERROR; | ||
|
||
const formattedResult = formatTestResult(testResult, status, UNKNOWN_ATTEMPT, reportBuilder); | ||
|
||
await reportBuilder.addFail(formattedResult); | ||
}).catch(reject)); | ||
}); | ||
|
||
hermione.on(hermione.events.TEST_FAIL, testResult => { | ||
promises.push(queue.add(async () => { | ||
const status = hasFailedImages(testResult.assertViewResults as ImageInfoFull[]) ? TestStatus.FAIL : TestStatus.ERROR; | ||
|
||
const formattedResult = formatTestResult(testResult, status, UNKNOWN_ATTEMPT, reportBuilder); | ||
|
||
await reportBuilder.addFail(formattedResult); | ||
}).catch(reject)); | ||
}); | ||
|
||
hermione.on(hermione.events.TEST_PENDING, testResult => { | ||
promises.push(queue.add(async () => { | ||
const formattedResult = formatTestResult(testResult as HermioneTestResult, SKIPPED, UNKNOWN_ATTEMPT, reportBuilder); | ||
|
||
await reportBuilder.addSkipped(formattedResult); | ||
}).catch(reject)); | ||
}); | ||
|
||
hermione.on(hermione.events.RUNNER_END, () => { | ||
return Promise.all(promises).then(() => resolve(), reject); | ||
}); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,5 @@ | ||
export const HERMIONE_TITLE_DELIMITER = ' '; | ||
|
||
export const PWT_TITLE_DELIMITER = ' › '; | ||
|
||
export const UNKNOWN_ATTEMPT = -1; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.