-
Notifications
You must be signed in to change notification settings - Fork 64
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: ability to run unit tests in browser
- Loading branch information
Showing
58 changed files
with
3,603 additions
and
430 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
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
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
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
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
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,42 @@ | ||
import { ViteServer } from "./vite/server"; | ||
import { MainRunner as NodejsEnvRunner } from ".."; | ||
import { TestCollection } from "../../test-collection"; | ||
import { Config } from "../../config"; | ||
import { Interceptor } from "../../events"; | ||
import type { Stats as RunnerStats } from "../../stats"; | ||
|
||
export class MainRunner extends NodejsEnvRunner { | ||
#viteServer: ViteServer; | ||
|
||
constructor(config: Config, interceptors: Interceptor[]) { | ||
super(config, interceptors); | ||
|
||
this.#viteServer = ViteServer.create(config); | ||
} | ||
|
||
async run(testCollection: TestCollection, stats: RunnerStats): Promise<void> { | ||
try { | ||
await this.#viteServer.start(); | ||
} catch (err) { | ||
throw new Error(`Vite server failed to start: ${(err as Error).message}`); | ||
} | ||
|
||
this.useBaseUrlFromVite(); | ||
await super.run(testCollection, stats); | ||
} | ||
|
||
private useBaseUrlFromVite(): void { | ||
const viteBaseUrl = this.#viteServer.baseUrl!; | ||
|
||
this.config.baseUrl = viteBaseUrl; | ||
for (const broConfig of Object.values(this.config.browsers)) { | ||
broConfig.baseUrl = viteBaseUrl; | ||
} | ||
} | ||
|
||
cancel(): void { | ||
super.cancel(); | ||
|
||
this.#viteServer.close(); | ||
} | ||
} |
26 changes: 26 additions & 0 deletions
26
src/runner/browser-env/vite/browser-modules/communicator.ts
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,26 @@ | ||
import { prepareError } from "./errors/index.js"; | ||
import { BrowserEventNames, BrowserMessage, WorkerEventNames, WorkerMessage } from "./types.js"; | ||
|
||
export class ViteBrowserCommunicator { | ||
static create<T extends ViteBrowserCommunicator>(this: new () => T): T { | ||
return new this(); | ||
} | ||
|
||
subscribeOnMessage(event: WorkerEventNames, handler: (msg: WorkerMessage) => Promise<void>): void { | ||
import.meta.hot?.on(event, handler); | ||
} | ||
|
||
sendMessage(event: BrowserEventNames, msg?: Partial<BrowserMessage>): void { | ||
if (msg && msg.errors) { | ||
msg.errors = msg.errors.map(prepareError); | ||
} | ||
|
||
import.meta.hot?.send(event, { | ||
pid: window.__hermione__.pid, | ||
runUuid: window.__hermione__.runUuid, | ||
cmdUuid: window.__hermione__.cmdUuid, | ||
errors: [], | ||
...msg, | ||
}); | ||
} | ||
} |
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,14 @@ | ||
export const DOCUMENT_TITLE = "Hermione Browser Test"; | ||
export const VITE_OVERLAY_SELECTOR = "vite-error-overlay"; | ||
|
||
export const VITE_SELECTORS = { | ||
overlay: "vite-error-overlay", | ||
overlayMessage: ".message", | ||
overlayStack: ".stack", | ||
overlayFile: ".file", | ||
overlayFrame: ".frame", | ||
overlayTip: ".tip", | ||
}; | ||
|
||
export const HERMIONE_BROWSER_EVENT_SUFFIX = "hermione:browser"; | ||
export const HERMIONE_WORKER_EVENT_SUFFIX = "hermione:worker"; |
11 changes: 11 additions & 0 deletions
11
src/runner/browser-env/vite/browser-modules/errors/base.ts
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,11 @@ | ||
export class BaseError extends Error { | ||
constructor({ message, stack }: { message: string; stack?: string }) { | ||
super(message); | ||
|
||
this.name = this.constructor.name; | ||
|
||
if (stack) { | ||
this.stack = stack; | ||
} | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
src/runner/browser-env/vite/browser-modules/errors/browser.ts
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,23 @@ | ||
import { BaseError } from "./base.js"; | ||
|
||
interface BrowserErrorData { | ||
message: string; | ||
stack?: string; | ||
file?: string; | ||
} | ||
|
||
export class BrowserError extends BaseError { | ||
file?: string; | ||
|
||
static create<T extends BrowserError>(this: new (opts: BrowserErrorData) => T, opts: BrowserErrorData): T { | ||
return new this(opts); | ||
} | ||
|
||
constructor({ message, stack, file }: BrowserErrorData) { | ||
super({ message, stack }); | ||
|
||
if (file) { | ||
this.file = file; | ||
} | ||
} | ||
} |
58 changes: 58 additions & 0 deletions
58
src/runner/browser-env/vite/browser-modules/errors/index.ts
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,58 @@ | ||
import { BrowserError } from "./browser.js"; | ||
import { LoadPageError } from "./load-page.js"; | ||
import { ViteError } from "./vite.js"; | ||
import { getSelectorTextFromShadowRoot } from "../utils/index.js"; | ||
import { DOCUMENT_TITLE, VITE_SELECTORS } from "../constants.js"; | ||
|
||
export type ErrorOnPageLoad = LoadPageError | ViteError | BrowserError; | ||
export type ErrorOnRunRunnable = ViteError | BrowserError | Error; | ||
export type AvailableError = ErrorOnPageLoad | Error; | ||
|
||
const getLoadPageErrors = (): LoadPageError[] => { | ||
if (document.title === DOCUMENT_TITLE && window.__hermione__) { | ||
return []; | ||
} | ||
|
||
return [LoadPageError.create()]; | ||
}; | ||
|
||
const getViteErrors = (): ViteError[] => { | ||
const viteErrorElem = document.querySelector(VITE_SELECTORS.overlay); | ||
|
||
if (!viteErrorElem || !viteErrorElem.shadowRoot) { | ||
return []; | ||
} | ||
|
||
const shadowRoot = viteErrorElem.shadowRoot; | ||
|
||
const message = getSelectorTextFromShadowRoot(VITE_SELECTORS.overlayMessage, shadowRoot); | ||
const stack = getSelectorTextFromShadowRoot(VITE_SELECTORS.overlayStack, shadowRoot); | ||
const file = getSelectorTextFromShadowRoot(VITE_SELECTORS.overlayFile, shadowRoot); | ||
const frame = getSelectorTextFromShadowRoot(VITE_SELECTORS.overlayFrame, shadowRoot); | ||
const tip = getSelectorTextFromShadowRoot(VITE_SELECTORS.overlayTip, shadowRoot); | ||
|
||
return [ViteError.create({ message, stack, file, frame, tip })]; | ||
}; | ||
|
||
const getBrowserErrors = (): BrowserError[] => { | ||
return window.__hermione__.errors; | ||
}; | ||
|
||
const findErrors = (errors: AvailableError | AvailableError[] = []): AvailableError[] => { | ||
return [errors, getViteErrors(), getBrowserErrors()].flat().filter(Boolean); | ||
}; | ||
|
||
export const findErrorsOnPageLoad = (): ErrorOnPageLoad[] => { | ||
return findErrors(getLoadPageErrors()); | ||
}; | ||
|
||
export const findErrorsOnRunRunnable = (runnableError?: Error): AvailableError[] => { | ||
return findErrors(runnableError); | ||
}; | ||
|
||
export const prepareError = (error: Error): Error => { | ||
// in order to correctly pass errors through websocket | ||
return JSON.parse(JSON.stringify(error, Object.getOwnPropertyNames(error))); | ||
}; | ||
|
||
export { BrowserError, LoadPageError, ViteError }; |
Oops, something went wrong.