Deb
Deb

Reputation: 35

How to return an Array from a function in TypeScript with Protractor?

I have the below code where I need to fill up an array with the drop list elements and return that array from the function so that I assert that array from the jasmine test case.

getAllCategoryName(): string[]{

        var usageCategoryFromPage: string[] =  [];

        E2EUtil.click(this.usageCategoriesPage.pageinationDropDownBtn);

        E2EUtil.click(this.usageCategoriesPage.highestPageRecords);

        element.all(by.xpath("//tbody[@class='ui-datatable-data ui-widget-content ui-datatable-hoverable-rows']/tr[*]/td[1]"))
            .each(function (element, index) {

                element.getText().then(function (text){
                    usageCategoryFromPage.push(text);
                })
            })

            .then(function(){

                console.log("Size of the array from inside the then block " + usageCategoryFromPage.length);

                usageCategoryFromPage.forEach(element => {
                     console.log("Usage Category Elements from inside the the function " + element);
                });

                return usageCategoryFromPage; // size here is 18
            });

        console.log("Usage Category size after the then block "  +usageCategoryFromPage.length)
        usageCategoryFromPage.forEach(element => {
              console.log("From Usage Category Page outside the then function" + element);
        });

        return usageCategoryFromPage; // size here is 0
    }

The problem is that the usageCategoryFromPage array is being returned as 0 outside the then block.

Jasmine test case looks like :

it('Validate the Usage Category droplist values matches with the Usage Categories Table',() => {

        usageCategoriesPage.navigateTo();
        let allCategoryName = usageCategoriesPage.getAllCategoryName();
        allCategoryName.forEach(element => {
            console.log("Array elements printed from the test case " + element);
        });

Can any one please help?

Upvotes: 0

Views: 3635

Answers (1)

yong
yong

Reputation: 13712

1) All protractor API are Async and return promise.

2) You need to consume promise's eventual value in then().

3) If a promise follows then() chain: a promise.then().then()....then(), The eventual value of the promise dependents the return value of the last then() in the then() chain.

For example:

element(all()).each() 
// return a promise and its eventual value is null

element(all()).getText() 
// return a promise and its eventual value is an String Array, 
// each String is the visible text of each found HTML element

var res = element(all()).getText()

.then(txts => {
    // the eventual value of promise: element(all()).getText()
    // will be passed-into the callback function of the next then() 
    // thus txts is the String Array
    // you can determine return anything or not return anything in this callback function

    // assume we return another String Array
    return ['a', 'b'];
})
// the return value in the previous `then()` callback function
// will be passed-into next `then()` callback function
.then(value => {
    // value = ['a', 'b']

    // assume we return the first String in Array
    return value[0]
});

res is a promise following then() chain, its eventual value depends on the last then().

res.then(value=>{
    console.log(value);
    // print out a
})

Fixed code:

getAllCategoryName(): string[]{

    var usageCategoryFromPage: string[] =  [];

    E2EUtil.click(this.usageCategoriesPage.pageinationDropDownBtn);

    E2EUtil.click(this.usageCategoriesPage.highestPageRecords);

    // you missed `return` at here. 
    return element
        .all(by.xpath("//tbody[@class='ui-datatable-data ui-widget-content ui-datatable-hoverable-rows']/tr[*]/td[1]"))
        .each(function (element, index) {
            element.getText().then(function (text){
                usageCategoryFromPage.push(text);
            })
        })
        .then(function(){

            console.log("Size of the array from inside the then block " + usageCategoryFromPage.length);

            usageCategoryFromPage.forEach(element => {
                 console.log("Usage Category Elements from inside the the function " + element);
            });

            return usageCategoryFromPage; // size here is 18
        });
}

it('Validate the Usage Category droplist values matches with the Usage Categories Table',() => {

    usageCategoriesPage.navigateTo();

    let allCategoryName = usageCategoriesPage.getAllCategoryName(); 
    // getAllCategoryName() return a promise, 
    // thus you need to consume the eventual value of promise in then()

    allCategoryName.then(categories => {
        console.log("Array elements printed from the test case " + categories.join(', '));
    });
}

More concise implement of getAllCategoryName() through element.all().getText()

getAllCategoryName(): string[]{

    E2EUtil.click(this.usageCategoriesPage.pageinationDropDownBtn);

    E2EUtil.click(this.usageCategoriesPage.highestPageRecords);

    return element
        .all(by.xpath("//tbody[@class='ui-datatable-data ui-widget-content ui-datatable-hoverable-rows']/tr[*]/td[1]"))
        .getText();
}

Upvotes: 1

Related Questions