typescriptplaywrightplaywright-testplaywright-typescript

How do I export a function that returns a Playwright `expect` object from a typescript module?


I am abstracting some common code that's been copypasted between multiple Playwright projects into a shared library that my team can use across all our test suites. Methods that return Expect instances are seemingly impossible to export, due to returning non-annotatable types.

As an example, the following is a function that constructs an expect.poll which can be used in a test with normal expect chaining, reloading the page under test between attempts. (LinkablePage is one of our local abstract pageobject classes, and is irrelevant to this question except as the location of the reload() operation.)

export function reloadAndPoll<Texpect, Tpoll>(
    expecter: Expect<Texpect>, 
    page: LinkablePage,
    pollFunction: () => Promise<Tpoll>, 
    testBeforeReload = true
) {
    let n = 0;
    return expecter.poll(async () => {
        if (!testBeforeReload || n++ > 0)
            await page.reload();
        return pollFunction();
    });
}

The inferred return type of reloadAndPoll is PollMatchers<Promise<void>, Tpoll, Texpect>, which I cannot explicitly annotate, as PollMatchers is not exported by Playwright.

Typescript throws the following two errors:

Return type of exported function has or is using name 'GenericAssertions'
from external module "<redacted>/node_modules/playwright/types/test"
but cannot be named.ts(4058)

Return type of exported function has or is using name 'SnapshotAssertions'
from external module "<redacted>/node_modules/playwright/types/test"
but cannot be named.ts(4058)

Since type PollMatchers<R, T, ExtendedMatchers>, and interface GenericAssertions and interface SnapshotAssertions on which it depends are not exported by Playwright, there seems to be no way for any other library to export values of those types. Casting to any would obviously break the ability to use these functions within a test by chaining assertions from them.

Is there a way to export expect.poll return values from a module in a useful way, or is this an impossible dream?


Solution

  • Even though Playwright doesn't export the type you need, you can still refer to it via the instantiation expression expecter.poll<Tpoll>:

    export function reloadAndPoll<Texpect, Tpoll>(
        expecter: Expect<Texpect>, 
        page: LinkablePage,
        pollFunction: () => Promise<Tpoll>, 
        testBeforeReload = true
    ): ReturnType<typeof expecter.poll<Tpoll>> {
        let n = 0;
        return expecter.poll(async () => {
            if (!testBeforeReload || n++ > 0)
                await page.reload();
            return pollFunction();
        });
    }
    

    (Playground)