vendredi 17 mai 2019

Looping through Protractor's code in `it` statement

Relatively new to writing end to end tests with Protractor. Also relatively inexperienced at working with promises.

I have a case where I need to find a customer who has a valid product with a valid serial number (not all products have a valid serial number). In order to find out if they have a valid serial number, I need to search from a search form, get a list of customers who meet the search criteria, and then click one by one through the list - it's only on viewing the details card that you can tell if the customer has a valid control serial number or not. And if they don't you need to start over again at the search stage, and this time select the next customer on the list. If they don't meet the criteria, then you start over again. When you find a customer who meets your criteria, you break out of the loop.

I can write regular e2e tests with Protractor, but solving this looping issue is proving difficult. I know it must be because I'm dealing with Promises, and am not handling them correctly. Although I've seen examples of looping through protractor code, they often involve a single method that needs to be done to every item in a list. Here I have multiple steps that need to be done in order to arrive at the point where I can find and set my value to break out of the loop.

Here are some of the threads I've looked at trying to resolve this:

My code as it currently stands:

it('should select a customer who has a valid serial number', () => {
    const products = new HomePage();

    let serialIsValid: boolean = false;
    let selectedElement, serialNumber, product, recordCount, recordList;
    recordList = element.all(by.css(`mat-list.desco-list`));
    recordList.then((records) => {
            recordCount = records.length;
            console.log('records', records.length, 'recordCount', recordCount);
        }
    );

    for (let i = 0; i < recordCount; i++) {
        if (serialIsValid === false) {
            const j = i + 1;
            products.btnFormsSelector.click();
            products.formSelectorRepossession.click();
            browser.wait(EC.visibilityOf(products.itemSearch));
            products.itemSearch.element(by.tagName('input')).sendKeys(browser.params.search_string);
            products.itemSearch.element(by.id('btnSearch')).click();
            browser.wait(EC.visibilityOf(products.itemSearch.element(by.id('list-container'))));
            selectedElement = element(by.tagName(`#itemSearch mat-list:nth-child($)`));
            selectedElement.click();
            browser.wait(EC.visibilityOf(products.doStuffForm));
            browser.sleep(1000);
            element(by.css('#successful mat-radio-button:nth-child(1) label')).click();
            browser.sleep(1000);
            expect(element(by.css('.itemDetailsContainer'))).toBeTruthy();
            product = products.productIDNumber.getText();
            product.then((item) => {
                serialNumber = item;
                if (item !== 'Unknown') {
                    expect(serialNumber).not.toContain('Unknown');
                    serialIsValid = true;
                } else {
                    i++
                }
            })
        } else {
            console.log('serial is valid: ' + serialIsValid);
            expect(serialNumber).not.toContain('Unknown');
            break;
        }
    }
    console.log('serial number validity: ', serialIsValid);
})


I have rewritten and reorganized my code several times, including trying to break out my code into functions grouping related steps together (as recommended in one of the threads above, and then trying to chain them together them together, like this:

findValidCustomer() {
        const gotoRepossessionSearch = (function () {...})
        const searchForRecord = (function () {...})
        const populateForm = (function (j) {...})

    for (let i = 0; i < recordCount; i++) {
        const j = i + 1;
        if (serialIsValid === false) {
            gotoProductSearch
                .then(searchForRecord)
                .then(populateForm(j))
                .then(findValidSerial(i))
        } else {
            console.log('serial number validity' + serialIsValid);
            expect(serialIsValid).not.toContain('Unknown');
            break;
        }
    }
    console.log('serial number validity' + serialIsValid);
}

When I've tried to chain them like that, I received this error - TS2345: Argument of type 'number | undefined' is not assignable to parameter of type 'number'

Have edited my code from my actual test and apologies if I've made mistakes in doing so. Would greatly appreciate comments or explanation on how to do this in general though, b/c I know I'm not doing it correctly. Thanks in advance.

Aucun commentaire:

Enregistrer un commentaire