Home > Mobile >  How to read a columns data into a variable and share it in all test functions (single spec), in Test
How to read a columns data into a variable and share it in all test functions (single spec), in Test

Time:09-30

I've read multiple posts on here about reading in table data, however, every post is how to read and use that data within a single test function. How do I read a table in, and use it in any test function within a test spec?

If I write this into a test function it works and gives back all the info correctly:

import { sAdmin } from "..authentication";
import TablePage from "../TablePage";

const tablePage = new TablePage();

fixture `A fixture`
    .page`https://subdomain.example.com/#/table`
    .beforeEach( async t => {
        await t
            .resizeWindow(1284, 722)
            .useRole(sAdmin);
    });

// this will work, but this won't share context with any other test function in the spec
// this should be initialized at the start to be able to verify search clears
test(`A test`, async t => {
    const tableColumn = await tablePage.woNumber;
    const tableCount = await tablePage.woNumber.count;
    const cellData = [];

    for (let i = 0; i < tableCount; i  ) {
        const text = await tableColumn.nth(i).innerText;

        cellData.push(text);
    }

    console.log('in spec - tableCount', tableCount);
    console.log('in spec - cellData', cellData);
});

The output of both console logs is correct:

in spec - tableCount 4
in spec - cellData [ '0007', '0003', '0005', '0006' ]

I've tried an async function in my test spec, and in my page object model (POM). Async function won't work in my spec unless it's within a test function. The one in the POM works, it'll get called, however i can't do const tableCount = await tablePage.woNumber.count; it will yell at me that I can't use a selector like that. It's because of the modifier .count. I adjusted the .count to be within the for loop but that just returned undefined or other data that didn't help.

Example of the async function in my page object model (TablePage)

async rowCount() {
    const tableColumn = await tablePage.fooSelector;
    const tableCount = await tablePage.fooSelector;
    const cellData = [];

    for (let i = 0; i < tableCount.count; i  ) {
        const text = await tableColumn.nth(i).innerText;

        cellData.push(text);
    }

    console.log('in page - tableColumn', tableColumn);
    console.log('in page - tableCount', tableCount);
    console.log('in page - cellData', cellData);

    return tableCount;
};

It's called with this in my spec file, not sure where to call it though:

const count = tablePage.rowCount();

I need this to run after the page has loaded to grab the cell data, and allow me to share context across all tests within this spec file at the very minimum. I'd prefer to put it in my POM, so it can be used elsewhere in other tests. But I'd settle for it working in my test spec without it being in a test function so it can be shared across all tests in the spec file.

I've tried to do a fixture context, but that also had issues and returned undefined. Here is a before with context that I tried, that didn't work.

.before( async ctx => {

    const tableColumn = await tablePage.fooSelector;
    const tableCount = await tablePage.fooSelector;

    for (let i = 0; i < tableCount.count; i  ) {
        const text = await tableColumn.nth(i).innerText;

        ctx.cellData.push(text);
    }

    // console.log('in spec - tableCount', tableCount);
    // console.log('in in spec - cellData', cellData);
})

These console logs return undefined, or objects instead of the text.

Any help would be greatly appreciated. Here are resources I referenced already:

TestCafe - Storing results of Selector in variable

How do I can get a text of all the cells of the table using testcafe

Testcafe get text from element

https://testcafe.io/documentation/402670/reference/test-api/domnodestate

EDIT: I'm still looking for a way to share context of the data I get, I wasn't able to return the data back to the test spec. Maybe if I do more tinkering I can share the values I've obtained.

Here is my solution that doesn't share context, but it does let me prevent code reuse in every test function.

Page Object Model

import { Selector, t } from "testcafe";

class TablePage{
    constructor() {
        this.searchInput = Selector('#searchInput');
        this.tableCount = Selector('.class-selector');
    };

    async validateSearchResults(selector, searchText) {
        await t
            .typeText(this.searchInput, searchText)
            .pressKey('enter');

        const rowCount = await this.tableCount.count;
        let searchResults = []

        for (let i = 0; i < rowCount; i  ) {
            let text = await selector.nth(i).innerText;

            searchResults.push(text);
            await t.expect(searchResults[i]).contains(searchText);
        }
    };

}

export default TablePage;

Spec File

import { sAdmin } from "..authentication";
import TablePage from "../TablePage";

const tablePage = new TablePage();

fixture `Test search functionality`
    .page`https://examplepage.com`
    .beforeEach( async t => {
        await t
            .useRole(sAdmin)
    });

test(`User can search via order number`, async t => {
    await tablePage.validateSearchResults(tablePage.tableCount, 'foo');
});

CodePudding user response:

The const tableCount = await tablePage.selector.count; looks correct and should work. Also, it's necessary to call the async method with await keyword:

const count = await tablePage.rowCount();

Here is an example of a similar approach:

table-page.js:

import { Selector } from 'testcafe';

export class TablePage {
    constructor () {
        this.tableCells = Selector('#ContentHolder_grid_DXDataRow0 td');
        this.cellData   = [];
        this.cellCount  = 0;
    }

    async initCellData () {
        this.cellCount = await this.tableCells.count;

        for (let i = 0; i < this.cellCount; i  ) {
            const text = await this.tableCells.nth(i).innerText;

            this.cellData.push(text);
        }
    }
}

test.js:

import { TablePage } from './table-page';

let page = null;

fixture `New Fixture`
    .page `https://demos.devexpress.com/ASPxGridViewDemos/DataBinding/QueryBuilderControl.aspx`
    .beforeEach(async () => {
        page = new TablePage();

        await page.initCellData();
    });
    
test(`New Test`, async t => {    
    console.log('cells count: ', page.cellCount);
    console.log('cells data: ', page.cellData);
});
  • Related