简体   繁体   中英

Protractor - TypeError: undefined is not a function

This question serves two purposes, to try to solve this specific error and to try to understand protractor best practices. So, I have the following failing code for the test:

var newRow = element.all(by.repeater("employee in ec.employees")).last();

newRow.then(function(row) {
    row.findElements(by.tagName("td")).then(function(cells) {
        expect(cells.get(0).getText()).toBe("9988776655000");
        expect(cells.get(1).getText()).toBe("Test name");
        expect(cells.get(2).getText()).toBe("Test surname");
    });
});

The reason:

TypeError: Undefined is not a function

and it's pointing to the 2nd row of code newRow.then(...) .

My relevant HTML:

<tr ng-repeat="employee in ec.employees">
    <td>{{employee.jmbg}}</td>
    <td>{{employee.name}}</td>
    <td>{{employee.surname}}</td>
</tr>

Now, I've already seen dozens of posts for this error on SO, but all are specific and as far as I could find there wasn't one similar to my case. So, other than the question of why my code doesn't work, I wanted to ask was it better to use ElementFinder.findElement/s function, or is there an alternative?

The element.all(...).last() returns an ElementFinder , so you cannot use it like a promise. Change your code to find the elements directly on the newRow variable. Here's how -

var newRow = element.all(by.repeater("employee in ec.employees")).last();

newRow.findElements(by.tagName("td")).then(function(cells) {
    expect(cells.get(0).getText()).toBe("9988776655000");
    expect(cells.get(1).getText()).toBe("Test name");
    expect(cells.get(2).getText()).toBe("Test surname");
});

Hope this helps.

Since you are using bindings in the tags I would recommend looking for those instead of grabbing the rows themselves. This way if you change the order of the rows in the future or add additional ones the tests are less likely to break. Try something like the following:

var newRow = element.all(by.repeater("employee in ec.employees")).last();

newRow.then(function(row) {
    expect(row.element(by.binding('employee.jmbg'))).toBe('9988776655000');
    expect(row.element(by.binding('employee.name'))).toBe('Test name');
    expect(row.element(by.binding('employee.surname'))).toBe('Test surname');
});

If you have an Angular directive, binding, repeater, model or a specific css path that you can target you should try and utilize them in your selectors to make your tests more reliable. I would also look into creating PageObjects for your tests to reduce the amount of repeated code that can appear in your tests.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM