let's assume we have a long list of pages to be added in the base.extend.. how can we deal with it? can we split fixtures in multiple files ? How to do it correctly?
This becomes tricky when you need to handle multiple pages of an app and you need to rename type computersPage for everytime you need to call in same tests ( say do something on a page, click a link, takes to another page tab, again another one... ). If separated as each test, then this approach is good. Though lot of tests to be written.
Thank you! Yes, you can. You create multiple of your own custom ones or even use your custom ones with the built in fixtures (page, request etc..) all inside the same test
Why adding one more layer and complexity adding all the pages in the base page and use them as a fixture? Why not use regular POM and call the pages in the tests? Is there any performance improvement in all this? What's the benefit?
This is a good question. The great thing about fixtures in playwright is the setup and teardown is all controlled behind the scenes. This would also apply to you creating your own page object model classes. Instead of having to instantiate a new class for every test / test file, instead you can extend the fixtures to contain your page object classes. This means all the setup is done in one place (making it easier to maintain), but it also keeps your test files very clean, you just use whatever page objects you need and they only get created for the tests that need them. The more efficient you can make your tests the better.
@@CommitQuality But what would happen if I want to have multiple fixtures in a separate files, and not have all fixtures in a single file. I would need to import 'test' from the last fixture I extended it. Isn't this going to make it more difficult to use? Also, having all the fixtures on a single fixture file will make the file too big. I'm missing something?
Also, I did some testing with the same test. When I use the pages as fixtures the test run time is 19.7s. When I use the regular POM and call the pages in the tests the test run time is 17.6s. So, not really an performance improvement.
That is interesting, was that an average over multiple executions too? I performed similar experiments (but will parallel tests running (executing the same tests multiple times) and saw overall using fixtures was more efficient.
I've followed your helpful videos for the last few months and have created some test files using POM and fixtures. For now we have left our assertions in the tests so I have added the export of expect to my basePage fixture. Locator assertions are available but when I try to do page assertions they don't exist. The error is "Property 'toHaveURL' does not exist on type 'MakeMatchers. Do you have any ideas if there something I am missing/need to import/export?
Hello! Thanks for the support! If you're able to see locator assertions im guessing your importing the expect correctly. Can I check how you are asserting the page? From the page object model you want need to expose the page and then you can assert against it for example... await expect(yourpagefixture.page).toHaveUrl(.....) Should work
@@CommitQuality ah I see where I went wrong instead of (yourpagefixture.page) I tried (yourpagefixture) and (page) but not together. Thanks so much for the quick response, you have made my day! I did in the interim work out how to put those assertions in the pom so now we have options.
Excellent video.. I have done the similar one in my test framework too.. How does it work If I want to create a new context at the start of every test and delete the context at end of the test coupled with the fixture.. I want to do this because I see a bit of flakyness while I run it in CI if I reuse the same context and page..
Thank you! After the await use(YourPageObject) you can call other methods to handle any cleanup you may want to do. So you could have a cleanup method in your class and after the use call, you can say something like YourPageObject.cleanUp();
@@CommitQuality Thanks for taking time to respond. But How do I create context only once as my fixture would be used multiple times in the test.. Would you help me with an example to create and delete the context and page at the start and end or route me to any document if possible..
@@arjunannamalai5696 create a fixture to create context , return it. Similary for closure. Now create another fixture for your tests. So you can call three fixtures, one for creation, test and for closure.. But you have to be mindful of returning factors as you might encounter understanding issues during the course of hefty tests and also when to handover to juniors.
I would suggest instead of defining the types directly, I would create a general type that includes all the POM types inside and then just pass the general type to the extend type as it might be a bit more clear that way. type myPages = {computersPage : ComputersPages(page)} base.extend({})
But then wouldn't that mean that every test, or each test that uses the myPages fixture in reality as access to all of the page fixtures, regardless of whether the test needs them or not? Seems like a window for misuse, "I'll just add that fixture or use the method on that page fixture over there because it's already there even though that page/POM has nothing to do with the scenario I am testing".
Hello, thanks for the video. I tried your solution (in JS), but I've ran into a problem, if I use page object models as fixtures and then I go to test file and try to write lets say "await computersPage." I am not getting auto-sugestions for methods that are in ComputersPage file. Is there any solution to that ?
Excellent video! Hm.. You got me thinking now. I like this more than standard POM. Problem is we already have standard POM on few of our projects and it would be a lot of effort to rewrite it now 😞
Yeah it's definitely got more advantages. If it's something you want to move towards, but seems too big, you could split it into small tech debt tasks? You can create fixtures but not use some of them while moving towards this approach?
@@CommitQuality Yes, that would be right approach for refactoring of POM. I have to learn what am I getting with fixtures, because we are using Playwright Test runner which is creating fixtures automatically by design.
@@lukamlikota8491 Here is some good documentation for the advantages of using fixtures, from the playwright documentation (note that this is vs hooks, but many of the benefits are the same) playwright.dev/docs/test-fixtures#with-fixtures. Personally, I just prefer not having to create an instance in each test file and knowing I can cleanly pull in my custom fixtures for my pages.
@@lukamlikota8491 I do not think Playwright Test "creates" fixtures for you by design. PWT has its own out-of-the-box fixtures that you can use in your tests but you also need to create your own custom fixtures or POM classes, etc., page is an out-of-the-box fixture.
In all honesty, I have not hit this issue yet, however you could always create another basePage class and split everything out. Keeping it very simple you could have basePage that imports other "basePage" classes e.g. basePage is your generic one which imports "basePage2", "basePage3" etc..
@@CommitQuality Trying to tackle this issue right now as I have a pretty large number of pages. I wonder if there might be some way to dynamically import the pages, that way every new page created will automatically be added as a fixture, but not sure if it's possible.
@@ofirpardo5422 I was trying to split the basePage, but had some issues. Tried to split all the fixtures in separate files and use the basePage to expose the elements to the tests. Wanted to do this so when importing test from the basePage, tests get access to all the elements from the other fixtures. Did you guys manage to split it? Can you give any examples?
Hi I am very new to automation. Just started doing the automation using the playwright with javascript I need a small help regarding fixtures. Its not like code is not working. Code is running fine but not getting suggestions I have a fixtures file const base = require('@playwright/test'); import Loginpage_PO from '../pageObjects/LoginPage_PO'; export const test = base.test.extend({ loginPage:async ({ page }, use)=>{ await use( new Loginpage_PO(page)); } }); Test file is as following import {test} from "../support/fixtures/basePage"; test('CSR-Login-01: Verify user able to login using the correct credentials', async ({loginPage}) => { await loginPage.loginCsrPortal(); await loginPage.verifyCsrPortalTitle(); await loginPage.verifyUserLoggedIn(); }) As I am using VS Code while typing loginPage. After dot(.) the suggestions(method of LoginPage_PO) not coming up My playwright version is { "name": "consumerreportsplaywright", "version": "1.0.0", "description": "", "main": "index.js", "scripts": {}, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "@playwright/test": "^1.31.2" } } but when I am doing like following import Loginpage_PO from '../support/pageObjects/LoginPage_PO'; test('CSR-Login-01: Verify user able to login using the correct credentials', async (page) => { const loginpage_PO = new Loginpage_PO(); loginpage_PO.loginCsrPortal(); }) I get the suggestions after dot(.) Anyone knows why this is not working when using the fixtures?
import { test } from "../support/fixtures/basePage"; /** * @type {import('relative path to your LoginPage_PO').default} */ let loginPage; test('CSR-Login-01: Verify user able to login using the correct credentials', async ({ loginPage: page }) => { loginPage = page; // Assign the page object to the loginPage variable await loginPage.loginCsrPortal(); await loginPage.verifyCsrPortalTitle(); await loginPage.verifyUserLoggedIn(); }); Added here @type imports as JSDoc comment
I have been researching Fixtures for some time now and your video was the first that cracked and help me to understand. Well done - thanks!
Thank you for the super thanks! I'm very glad I have helped. If there are any other tutorials needed please let me know
I wanted to give a small super thanks. Its not much but you have really made my life so much easier than if your channel did not exist.
Thank you very much! It means a lot to me and I'm really grateful! I'm glad the videos are helping you too!
great explanation ! thank you ! Definitely helped me !
Tis' so cool and clear! I thought I could never understand how to use it. Thank you!
That's awesome to hear! Thank you :)
Thanks for the useful info. Can you please provide an example using beforeAll hooks with these POM fixtures?
let's assume we have a long list of pages to be added in the base.extend.. how can we deal with it? can we split fixtures in multiple files ? How to do it correctly?
The code is soo clean now! Thanks for the example.
How to handle a new tab with this approach?
Wonder if there's a way to "bring in" ENV VARS as fixtures in PWT?
This becomes tricky when you need to handle multiple pages of an app and you need to rename type computersPage for everytime you need to call in same tests ( say do something on a page, click a link, takes to another page tab, again another one... ). If separated as each test, then this approach is good. Though lot of tests to be written.
Great video.
Question:
Can we use several fixtures in a single test?
Thank you! Yes, you can. You create multiple of your own custom ones or even use your custom ones with the built in fixtures (page, request etc..) all inside the same test
Why adding one more layer and complexity adding all the pages in the base page and use them as a fixture? Why not use regular POM and call the pages in the tests? Is there any performance improvement in all this? What's the benefit?
This is a good question. The great thing about fixtures in playwright is the setup and teardown is all controlled behind the scenes. This would also apply to you creating your own page object model classes. Instead of having to instantiate a new class for every test / test file, instead you can extend the fixtures to contain your page object classes. This means all the setup is done in one place (making it easier to maintain), but it also keeps your test files very clean, you just use whatever page objects you need and they only get created for the tests that need them. The more efficient you can make your tests the better.
@@CommitQuality But what would happen if I want to have multiple fixtures in a separate files, and not have all fixtures in a single file. I would need to import 'test' from the last fixture I extended it. Isn't this going to make it more difficult to use? Also, having all the fixtures on a single fixture file will make the file too big. I'm missing something?
Also, I did some testing with the same test. When I use the pages as fixtures the test run time is 19.7s. When I use the regular POM and call the pages in the tests the test run time is 17.6s. So, not really an performance improvement.
That is interesting, was that an average over multiple executions too? I performed similar experiments (but will parallel tests running (executing the same tests multiple times) and saw overall using fixtures was more efficient.
You can have more than one extended fixtures class and import them quite easily. Im happy to create a video on this.
I've followed your helpful videos for the last few months and have created some test files using POM and fixtures. For now we have left our assertions in the tests so I have added the export of expect to my basePage fixture. Locator assertions are available but when I try to do page assertions they don't exist. The error is "Property 'toHaveURL' does not exist on type 'MakeMatchers. Do you have any ideas if there something I am missing/need to import/export?
Hello! Thanks for the support! If you're able to see locator assertions im guessing your importing the expect correctly. Can I check how you are asserting the page? From the page object model you want need to expose the page and then you can assert against it for example... await expect(yourpagefixture.page).toHaveUrl(.....) Should work
@@CommitQuality ah I see where I went wrong instead of (yourpagefixture.page) I tried (yourpagefixture) and (page) but not together. Thanks so much for the quick response, you have made my day! I did in the interim work out how to put those assertions in the pom so now we have options.
Good workaround though! Glad I could help it's a bit of a weird one isn't it!
could you please explain fixtures in js please.
Fixtures in playwright for Test are the same. The only difference is you have type safety with Typescript.
Excellent video.. I have done the similar one in my test framework too.. How does it work If I want to create a new context at the start of every test and delete the context at end of the test coupled with the fixture.. I want to do this because I see a bit of flakyness while I run it in CI if I reuse the same context and page..
Thank you! After the await use(YourPageObject) you can call other methods to handle any cleanup you may want to do. So you could have a cleanup method in your class and after the use call, you can say something like YourPageObject.cleanUp();
@@CommitQuality Thanks for taking time to respond.
But How do I create context only once as my fixture would be used multiple times in the test..
Would you help me with an example to create and delete the context and page at the start and end or route me to any document if possible..
@@arjunannamalai5696 create a fixture to create context , return it. Similary for closure. Now create another fixture for your tests. So you can call three fixtures, one for creation, test and for closure.. But you have to be mindful of returning factors as you might encounter understanding issues during the course of hefty tests and also when to handover to juniors.
I would suggest instead of defining the types directly, I would create a general type that includes all the POM types inside and then just pass the general type to the extend type as it might be a bit more clear that way.
type myPages = {computersPage : ComputersPages(page)}
base.extend({})
But then wouldn't that mean that every test, or each test that uses the myPages fixture in reality as access to all of the page fixtures, regardless of whether the test needs them or not? Seems like a window for misuse, "I'll just add that fixture or use the method on that page fixture over there because it's already there even though that page/POM has nothing to do with the scenario I am testing".
@@enrisacost4326 What he shows already does that, my suggestion is not related to what you said.
Thank you so much for such a useful video! ANy idea how this could work with parallel runs? Thank you for your content!
It should work completely fine in parallel. Are you having a specific issue?
Hello, thanks for the video. I tried your solution (in JS), but I've ran into a problem, if I use page object models as fixtures and then I go to test file and try to write lets say "await computersPage." I am not getting auto-sugestions for methods that are in ComputersPage file. Is there any solution to that ?
I'm guessing the issue is not knowing the type of object. Have you annotated the classes using JSDoc? You can define what type it is using that.
Excellent video! Hm.. You got me thinking now. I like this more than standard POM. Problem is we already have standard POM on few of our projects and it would be a lot of effort to rewrite it now 😞
I think in this cases POM or fixture is just a preference. But for already logged in user with different auth. it's a really good approach!
Yeah it's definitely got more advantages. If it's something you want to move towards, but seems too big, you could split it into small tech debt tasks? You can create fixtures but not use some of them while moving towards this approach?
@@CommitQuality Yes, that would be right approach for refactoring of POM. I have to learn what am I getting with fixtures, because we are using Playwright Test runner which is creating fixtures automatically by design.
@@lukamlikota8491 Here is some good documentation for the advantages of using fixtures, from the playwright documentation (note that this is vs hooks, but many of the benefits are the same) playwright.dev/docs/test-fixtures#with-fixtures. Personally, I just prefer not having to create an instance in each test file and knowing I can cleanly pull in my custom fixtures for my pages.
@@lukamlikota8491 I do not think Playwright Test "creates" fixtures for you by design. PWT has its own out-of-the-box fixtures that you can use in your tests but you also need to create your own custom fixtures or POM classes, etc., page is an out-of-the-box fixture.
Looks like the file basePage.js will gradually grow bigger and bigger.
Is there any solution to this ?
In all honesty, I have not hit this issue yet, however you could always create another basePage class and split everything out. Keeping it very simple you could have basePage that imports other "basePage" classes e.g. basePage is your generic one which imports "basePage2", "basePage3" etc..
@@CommitQuality Trying to tackle this issue right now as I have a pretty large number of pages. I wonder if there might be some way to dynamically import the pages, that way every new page created will automatically be added as a fixture, but not sure if it's possible.
@@ofirpardo5422 I was trying to split the basePage, but had some issues. Tried to split all the fixtures in separate files and use the basePage to expose the elements to the tests. Wanted to do this so when importing test from the basePage, tests get access to all the elements from the other fixtures.
Did you guys manage to split it? Can you give any examples?
Nice one ❤
Hi
I am very new to automation. Just started doing the automation using the playwright with javascript
I need a small help regarding fixtures. Its not like code is not working. Code is running fine but not getting suggestions
I have a fixtures file
const base = require('@playwright/test');
import Loginpage_PO from '../pageObjects/LoginPage_PO';
export const test = base.test.extend({
loginPage:async ({ page }, use)=>{
await use( new Loginpage_PO(page)); }
});
Test file is as following
import {test} from "../support/fixtures/basePage";
test('CSR-Login-01: Verify user able to login using the correct credentials', async ({loginPage}) => {
await loginPage.loginCsrPortal();
await loginPage.verifyCsrPortalTitle();
await loginPage.verifyUserLoggedIn();
})
As I am using VS Code while typing loginPage.
After dot(.) the suggestions(method of LoginPage_PO) not coming up
My playwright version is
{ "name": "consumerreportsplaywright",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": { "@playwright/test": "^1.31.2"
} }
but when I am doing like following
import Loginpage_PO from '../support/pageObjects/LoginPage_PO';
test('CSR-Login-01: Verify user able to login using the correct credentials', async (page) => {
const loginpage_PO = new Loginpage_PO();
loginpage_PO.loginCsrPortal();
})
I get the suggestions after dot(.)
Anyone knows why this is not working when using the fixtures?
import { test } from "../support/fixtures/basePage";
/**
* @type {import('relative path to your LoginPage_PO').default}
*/
let loginPage;
test('CSR-Login-01: Verify user able to login using the correct credentials', async ({ loginPage: page }) => {
loginPage = page; // Assign the page object to the loginPage variable
await loginPage.loginCsrPortal();
await loginPage.verifyCsrPortalTitle();
await loginPage.verifyUserLoggedIn();
});
Added here @type imports as JSDoc comment