-
Notifications
You must be signed in to change notification settings - Fork 3.7k
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
[Feature] global beforeEach/beforeAll hooks #9468
Comments
This comment was marked as outdated.
This comment was marked as outdated.
Hi @yury-s I'm using JavaScript not ts, and seem to keep getting an error: Using config at C:\Users\tom\OneDrive\Documents\projects\vs-code\Playwright-test-training\playwright.config.js My hooks.js (now renamed to hooks.mjs but still ge the same error) is:
and main test file hooks_ex.spec.js contains:
any chance you could help? many thanks |
As the error says you need to rename |
You also should not mix require with import, this worked locally: // hooks_ex.spec.mjs
import { expect } from '@playwright/test';
import test from './hooks.mjs'
test.describe('Security Tests', () => {
test('Login Sanity Test @smoke', async ({ page }) => {
const locator = page.locator('body');
await expect(locator).toContainText('not Logged in');
await page.fill('id=username', 'edgewords');
await page.fill('id=password', 'edgewords123');
await page.click('text=Submit');
const logOut = page.locator('text=Log Out');
await expect(logOut).toBeVisible({ timeout: 10000 });
await page.close();
});
}); |
Brilliant, thanks @yury-s that's fixed it, all working. |
@Tomsk666 sorry for misleading you, this will not work as I thought, if you run with --workers=1 the hooks will only run in the test file that happens to be executed first, the rest will run without the hooks. The best way to achieve what you need today will likely be something like this: import { sharedBeforeEachFunction } from './hooks.mjs'
test.beforeEach(sharedBeforeEachFunction);
test('Login Sanity Test @smoke', async ({ page }) => {
}); Unfortunately this requires calling test.beforeEach in each test file. |
Another way (more convoluted but also more idiomatic to playwright) to do this is to define your beforeAll/Each methods as fixtures that run automatically. The documentation covering this is quite scarce at the moment but if it works for you we can add some examples there. // fixtures.js
const base = require('@playwright/test');
module.exports = base.test.extend({
sharedBeforeAll: [ async ({}, use) => {
console.log('Before All');
await use();
console.log('After All');
}, { scope: 'worker', auto: true } ], // starts automatically for every worker - we pass "auto" for that.
sharedBeforeEach: [ async ({}, use) => {
console.log('Before Each');
await use();
console.log('After Each');
}, { scope: 'test', auto: true } ], // starts automatically for every test - we pass "auto" for that.
}); The tests files will look like this: // @ts-check
const test = require('./fixtures');
test('basic test 1', async ({ page }) => {
}); This is not completely equivalent to beforeAll() in every file since it will run once per worker process (see this doc to learn mode about playwright test runner model) but it may be even better for you depending on the use case. |
Thanks @yury-s I'll try some of these options out & see how I get on. |
Changed this issue to a feature request, let's see if there is enough upvotes to implement it. |
I will support the global hook feature. global hook is easier to use than the fixture pattern. I am willing to contribute this feature. |
@yury-s that would be great to have this feature, I have tried using a |
Waiting for any update on this feature request 💯 |
@yury-s Any plan to implement this feature...it would be great to have global hooks for easier handling |
Up |
Is there a plan to implement this feature? It would be super helpful |
this is really needed |
We had some trouble implementing a global beforeEach, using the initial suggestion here. It only ran before some early tests (but not once per worker, perhaps once per core regardless of worker-setting?). However it looks like we have now found a solution based on the ideas here: import { test as base } from '@playwright/test'
export const test = base.extend({
page: async ({ baseURL, page }, use) => {
// We have a few cases where we need our app to know it's running in Playwright.
// This is inspired by Cypress that auto-injects window.Cypress.
await page.addInitScript(() => {
(window as any).Playwright = true
})
// Here we can enable logging of all requests, which is useful to see sometimes.
// We also block some unnecessary third-party requests to speed up the tests.
await page.route('**/*', route => {
...
})
use(page)
},
}); And in our tests we import |
Have to agree with @Krisell here. For some reason, my auto fixture for beforeEach only runs one time, instead on each test unless I run the suite in debug mode...not sure why that makes a difference but it does. Here's my example:
Where I have two tests here using the extended fixture:
Which results in my Also just want to say that the above solution works for now but would love to use my own auto fixture instead of extending |
Any updates on this? Would love this feature |
+1 for this |
+1 |
yury-s This is a highly recommended feature for all tests, Please add in the feature quickly. UPVOTES (1000) |
This feature would help a lot, hope it will be implemented soon. |
It would be great if you implement global beforeEach and afterEach. |
+1 |
Following this, I was able to get essentially the equivalent of a beforeEach and afterEach for each test case (even with just 1 worker), so thought I'd post it here for others. Hope it helps! |
+1 |
3 similar comments
+1 |
+1 |
+1 |
I've expanded on this to be able to intercept multiple api calls for different pages, e.g. this is my homepage-setup.ts:
|
Thanks @Krisell, we ran into an issue where we want to disable JS-based animations on our app and your solution of introducing a global flag worked :) With regards to this:
...our solution is simply to setup an eslint {
files: ['**/*.e2e.ts'],
rules: {
'no-restricted-imports': [
'error',
{
paths: [
name: '@playwright/test',
importNames: ['test'],
message: 'Please import `test` from fixtures.ts instead',
},
],
},
],
},
}, |
That is brilliant, thanks! It looks like the default import can also be used as the |
These fixture-based solutions seem impractical because they require changing every test file to change the |
@silverwind I might be missing something but I am not seeing an issue here. I don't think it's that difficult to replace the We have this setup enabled on our relatively large monorepo and it took under an hour to migrate the code. |
Sure, it's not a hard refactor, but it's still code churn that could be avoided if only there were an better API. For example in Jest, one can have global beforeEach/afterEach defined in a setup file, which is ideal imho: |
Instead of having the same test.beforeEach hook defined in every file, how do I only define the beforeEach hook in a single file (say hooks.js) at a global level, so then each file can use that hook?
In other words define my hooks in a single file once, but hooks are then used by all of my tests in all my spec files?
Thanks
The text was updated successfully, but these errors were encountered: