-
Notifications
You must be signed in to change notification settings - Fork 64
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: ability to run unit tests in browser #880
Conversation
@@ -8,7 +8,7 @@ | |||
"typings" | |||
], | |||
"scripts": { | |||
"build": "tsc && npm run copy-static && npm run build-bundle -- --minify", | |||
"build": "tsc --build && npm run copy-static && npm run build-bundle -- --minify", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In order to build browser modules separately (used esm)
"glob-extra": "5.0.2", | ||
"import-meta-resolve": "4.0.0", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ponyfill for import.meta.resolve
from esm
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐴fill =)
|
||
testRunEnv: option({ | ||
defaultValue: defaults.testRunEnv, | ||
validate: value => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Valid values:
nodejs
browser
["browser", {viteConfig: string | object | function}]
src/hermione.ts
Outdated
@@ -82,7 +84,10 @@ export class Hermione extends BaseHermione { | |||
this._config.system.mochaOpts.timeout = 0; | |||
} | |||
|
|||
const runner = MainRunner.create(this._config, this._interceptors); | |||
const runner = (isRunInNodeJsEnv(this._config) ? NodejsEnvRunner : BrowserEnvRunner).create( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
depending on the value in testRunEnv
run nodejs runner or browser runner
}: WaitMessageOpts): Promise<BrowserPayload> { | ||
return new Promise((resolve, reject) => { | ||
const timerId = | ||
timeout > 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If repl mode is use then it set runnable.timeout = 0
so I don't need to use any setTimeout
import type { Test } from "../../../../test-reader/test-object/test"; | ||
import type { Hook } from "../../../../test-reader/test-object/hook"; | ||
|
||
export const wrapExecutionThread = (runUuid: string): typeof NodejsEnvExecutionThread => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Solution which gives me ability to pass runUuid
and generate ExecutionThread
class for browser. I use it because ExecutionThread
class is used inside NodejsEnvTestRunner
and I need some api to set it, but ExecutionThread
from nodejs don't need this.
} | ||
|
||
async _call(runnable: Test | Hook): Promise<void> { | ||
const cmdUuid = crypto.randomUUID(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
generates uniq for each event
return super.run({ ...opts, ExecutionThreadCls: wrapExecutionThread(this.#runUuid) }); | ||
} | ||
|
||
_getPreparePageActions(browser: Browser, history: BrowserHistory): (() => Promise<void>)[] { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
redefine method from parent in order to be able run action before user hook/test
@@ -117,6 +118,19 @@ module.exports = class TestRunner { | |||
return results; | |||
} | |||
|
|||
_getPreparePageActions(browser, history) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add API to be able to redefine it through browser runner
f6f2c1d
to
1aeb516
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall, really cool addition! I have no critical review issues.
Left a few questions and comments below, also discussed if it's worth it to consider using socket.io and separate WS server in the future. For now, I don't think any severe changes are necessary and it's surely better to get this shipped faster.
bf2f69a
to
66e0bd1
Compare
66e0bd1
to
ff047db
Compare
cc72645
to
02af7e2
Compare
cf51ec1
to
d000370
Compare
d000370
to
5a76453
Compare
What is done
The ability to run tests in a browser environment is implemented (previously, it was possible to run only in nodejs env). Now you can run the unit tests in the browser. The launch of the component tests will be implemented in the next PR.
To run browser tests, you must specify
system.testRunEnv: "browser"
. And to use your vite config -system.testRunEnv: ["browser", {viteConfig: {...}}]
. Browser tests are run separately from tests in node js.Implementation scheme:
Vite is used as the server that compiles the test code and displays it in the browser. All browser tests go to the url of the vite server. Vite also has presets with support popular frameworks: react, vue, etc.
The logic about launching browsers, managing them, and reading tests in the master and the worker process has not changed. Only a new browser runner has been added, which start the Vite server and sets up communication between workers and browsers via websocket. It also generates the necessary index.html page in memory that the browser opens. On this page, mocha is connected, which downloads passed test file, parses all the tests and saves them in its data structure. The worker is responsible for starting the launch of hooks (
beforEach
,afterEach
) and tests (it
). Which sends a vite message via the websocket which test needs to be run. fullTitle is used to identify which runnable must be run. The browser launches the required runnable and returns the result. If there were errors, the test fails, and if everything is OK, the test is successful.User documentation will be added along with the implementation of component testing (next PR).