Search code examples
e2e-testingplaywright

Implementing Custom Fixtures using config with new Playwright 0.1101


I hope this isn't TL;DR. I really need help with Playwright.

In short: Does anybody know how to migrate a fixture setup to config with Playwright v.01101? There isn't documentation on how to do this.

Versions of Playwright/Test prior to v0.1101 enabled customize fixtures that you could override or extend from the Playwright/Test modules. I took advantage of this to implement a page object model (POM). Here is my example fixture:

// In tests/fixtures.ts
import { folio as baseFolio } from '@playwright/test'; //now missing in v.0.1101
import { IndexPage } from "../PO/IndexPage";

require('dotenv').config();
const baseURL = process.env.BASE_URL;

// Extend built-in fixtures and declare types for new fixtures
const builder = baseFolio.extend<{ indexPage: IndexPage }>();

// In fixtures.ts
builder.indexPage.init(async ({ page }, runTest) => {
    // get built-in page and wrap with POM
    const indexPage = new IndexPage(page, baseURL);

    // pass this to your test
    runTest(indexPage);
});

// Build and export the modified fixtures
const folio = builder.build();
export const it = folio.it;
export const expect = folio.expect;
export const describe = folio.describe;

Here is an example of a test I run with this POM:

// In tests/e2e.spec.ts
import { IndexPage } from '../PO/IndexPage';
import { describe, it, expect } from './fixtures'
        
it('EN/FR', async ({ indexPage }) => {
     await indexPage.navigateHome();
     await indexPage.getCurrentLanguage()
     await assertGreetingLanguage(indexPage);
     await indexPage.toggleLanguage();
     await assertGreetingLanguage(indexPage);
});

async function assertGreetingLanguage(indexPage: IndexPage) {
    const lang = await indexPage.getCurrentLanguage();
    const greeting = lang === 'English' ? 'Welcome!' : 'Bienvenue!';
    // console.log(`LANG: ${lang} Greet: ${greeting}`);
    expect(await indexPage.getGreeting()).toBe(greeting);
    // expect(await indexPage.getGreeting()).not.toBe(greeting);
}

With v0.1101 though, it seems fixtures aren't supported anymore, and instead can be setup with a config file. Of course, Folio is what implements this config setup.


Solution

  • Resolved. :)

    Playwright got back to me on this Github issue. Here's how it's done. Official documentation coming soon:

    // config.ts
    
    import { PlaywrightEnv, newTestType, setConfig, TestInfo, reporters, setReporters } from "@playwright/test";
    import { IndexPage } from "./PO/IndexPage";
    
    
    require('dotenv').config();
    const baseURL = process.env.BASE_URL;
    
    setConfig({
        testDir: __dirname,  // Search for tests in this directory.
        timeout: 30000,  // Each test is given 30 seconds.
        // timeout: 90000,  // Each test is given 90 seconds.
        retries: 0,  // Failing tests will be retried at most two times.
    });
    
    setReporters([
        // Report to the terminal with "line" reporter.
        new reporters.line(),
        // Additionally, output a JUnit XML file.
        new reporters.junit({ outputFile: 'junit.xml', stripANSIControlSequences: true }),
        new reporters.list(),
    ]);
    
    // Extend the default environment to add any test arguments, for example POMs.
    class MyEnv extends PlaywrightEnv {
        async beforeEach(testInfo: TestInfo) {
            // Get all default arguments, including Page.
            const result = await super.beforeEach(testInfo);
            // Create your POM.
            const indexPage = new IndexPage(result.page, baseURL);
            // Return default arguments and new POM.
            return { ...result, indexPage };
        }
    }
    
    // Declare "indexPage" test argument for types in IDE.
    export const test = newTestType<{ indexPage: IndexPage }>();
    export { expect } from "@playwright/test";
    
    // Run tests in three browsers.
    const options = {
        // Launch options:
        headless: true,
        slowMo: 50,
        // Context options:
        viewport: { width: 800, height: 600 },
        ignoreHTTPSErrors: true,
        // Testing options:
        // video: 'retain-on-failure',
        screenshot: 'only-on-failure'
    };
    
    // Run tests in three browsers.
    test.runWith(new MyEnv('chromium', options), { tag: 'chromium' });
    test.runWith(new MyEnv('firefox', options), { tag: 'firefox' });
    test.runWith(new MyEnv('webkit', options), { tag: 'webkit' });