Search code examples
testingautomated-testsparameter-passingtestcafecustom-selectors

Passing arguments to TestCafe Selector in page model


I'm wanting to pass a string into an object in a page model for use by a .withText selection. I can do this with a function on that page and it works, but I have to call it differently than objects defined on the page.

I've tried playing with the FilterFn for .filter (and .find) with no luck. Perhaps that's just what I need but need help with it, or perhaps I'm just overthinking it.

Excerpt of example page model

export class AreaPage {
    public pageTitle = Selector("#container h1").withText("My Area Title");

    public async pageSubtitle(areaName: string) {
        return await Selector("#container h2").withText(areaName);
    }
}

Excerpt of example test

test("test some code", async (t) => {
    await t
    .click(areaPage.pageTitle)
    .click(await areaPage.PageSubtitle("my subtitle"));
}

Granted, I may not want to "click" these titles, but it demonstrates the differences in how the calls to these page components must be made. I also know that I could capture the objects and do validations within the test, but that defeats part of what I'm trying to do.

Written as above, it works, but I want our QA folks to be able to use them the same way (i.e. without the "await" embedded in the last line of the test). If I remove the await, I get the error:

Argument of type 'Promise<Selector>' is not assignable to parameter of type 'string | Selector | NodeSnapshot | SelectorPromise | ((...args: any[]) => Node | Node[] | NodeList | HTMLCollection)'.
  Type 'Promise<Selector>' is missing the following properties from type 'SelectorPromise': childElementCount, childNodeCount, hasChildElements, hasChildNodes, and 51 more.ts(2345)

(...which just cramps my brain)

How might I write the page object pageSubtitle to accept a parameter yet otherwise function like the pageTitle object?


Solution

  • You're awaiting the Selector promise twice - this leads to the error.   Try to modify your test and page model as follows:

    Page model:

    export class AreaPage {
        public pageTitle = Selector("#container h1").withText("My Area Title");
    
        public pageSubtitle(areaName: string) {
            return Selector("#container h2").withText(areaName);
        }
    }
    

    Test:

    test("test some code", async (t) => {
        await t
            .click(areaPage.pageTitle)
            .click(pageModel.pageSubtitle("my subtitle"));
    }