Failed expectation: "Expected [ ] to be empty array."

7.7k Views Asked by At

Here is the failing test:

describe("Checking errors", function () {
    var scope = {};

    beforeEach(function () {
        browser.get("/#endpoint");
        browser.waitForAngular();

        scope.page = new MyPage();
    });

    it("should not show any errors", function () {
        expect(scope.page.errors).toBeEmptyArray();
    });
});

where MyPage is a Page Object:

var MyPage = function () {
    this.errors = element.all(by.css("div.error-block b.error"))
        .filter(function (elm) {
            return elm.isDisplayed().then(function (value) {
                return value;
            });
        })
        .map(function (elm) {
            return elm.getText();
        });
};

module.exports = MyPage;

where errors supposed to be an array of visible error texts found on a page.

Here is the error we are getting:

Failures:

  1) Checking errors should not show any errors
   Message:
     Expected [  ] to be empty array.
   Stacktrace:
     Error: Failed expectation

FYI, toBeEmptyArray() matcher is coming from jasmine-matchers third-party.


I've tried to print out the value of scope.page.errors this way:

scope.page.errors.then(function (errors) {
    console.log(errors);
});

And it is printed out as []. Array.isArray(errors) returns true.

From what I see, scope.page.errors is an empty array, but the expectation fails. What I a missing?

2

There are 2 best solutions below

3
On BEST ANSWER

the answer is four lines down in the protractor src.

ElementArrayFinder extends Promise, while jasmine-matchers checks first checks that errors is an actual array exactly how Array.isArray is done , which will return false;

This is also consistent with expect(scope.page.errors.length).toBe(0) being undefined because promises do not have lengths.

Just run errors.then on your promise, and test that the argument is [] You've also shown that can be done when you ran scope.page.errors.then

1
On
Inside test script your code line "scope.page = new MyPage();" is creating new empty MyPage object.Code which you have written in application script is creating page object locally and its not bounded with any angular scope.When there is requirement of testing such objects you need to replicate code for page object creation in beforeEach(); block of test script.And test it.
 describe("Checking errors", function () {
    var scope = {};
     var MyPage ;
    beforeEach(function () {
        browser.get("/#endpoint");
        browser.waitForAngular();

       MyPage = function () {
    this.errors = element.all(by.css("div.error-block b.error"))
        .filter(function (elm) {
            return elm.isDisplayed().then(function (value) {
                return value;
            });
        })
        .map(function (elm) {
            return elm.getText();
        });
};
    });

    it("should not show any errors", function () {
        expect(MyPage.errors).toBeEmptyArray();
    });
});