-
Notifications
You must be signed in to change notification settings - Fork 4.5k
Description
🚀 Feature Request
Hi!
It would be great if Playwright supported an optional hook that would allow developers to execute custom logic related to their tests before Playwright spawns the tested application (i.e. executes webServer.command
).
With that, I am proposing two new hooks:
interface ProjectConfig {
runnerSetup?: string
runnerTeardown?: string
}
Mirroring the globalSetup
and globalTeardown
hooks, the newly proposed ones allow you to include a setup/teardown file and await that respective logic before spawning your tested app.
With the proposed hooks, here's the order of things:
- runnerSetup
- webServer
- globalSetup
- beforeAll
- afterAll
- globalTeardown
- runnerTeardown
Example
Basic usage
The runnerSetup
and runnerTeardown
hooks behave identically to globalSetup
and globalTeardown
, in a sense that they expect the specified modules to have a default export describing the logic to run:
// runner-setup.ts
export default async function runnerSetup() {
setupLogic()
}
// runner-teardown.ts
export default async function runnerTeardown() {
teardownLogic()
}
// playwright.config.ts
export default defineConfig({
runnerSetup: './runner-setup.ts',
runnerTeardown: './runner-teardown.ts',
})
Shorthand teardown declaration
Similar to the globalSetup
optionally returning the teardown callback, I propose the runnerSetup
support the same pattern:
export default async runnerSetup({ context }) {
const container = await new PostgresContainer().start()
return async () => {
await container.stop()
}
}
This is extremely handy to help manage persisted resources, like my testcontainer above.
Motivation
Currently, there's no way to run custom logic before the webServer
step of Playwright:
webServer
is a static object, not a function to allow logic (primarily async one) to run before spawning the app (and spawning the app dynamically based on that logic).globalSetup
runs afterwebServer
, making it impossible to influence the spawned app (e.g. by providing differentenv
based on some async logic). This is intended as you expect your tested app to be up by this point to create browsers and do custom browser/page-related setup.
Because of this, it becomes redundantly complex to introduce trivial custom logic related to the test run. Take the aforementioned Testcontainers as an example. Without the proposed hooks, I need to:
- Introduce a custom script.
- Start the testcontainer there.
- Spawn the entire Playwright process dynamically to provide dynamic env variables.
- Manage the spawned PW process.
- Close the testcontainer manually.
This is an extreme level of complexity for something as small as spawning something alongside but before my tested app. I strongly suggest you consider this proposal to simplify such setups as I believe they are rather common.
Any other approaches, like chaining shell scripts or creating a custom webServer.command
, suffer from the same issue: they introduce redundant complexity because you are trying to manage a test runner-related resource outside of that test runner.