Skip to content Skip to sidebar Skip to footer

Asserting An Element Is Focused

According to the How do I assert an element is focused? thread, you can check if an element is focused by switching to an activeElement() and assert this is the same element you've

Solution 1:

In my answer I'm going to assume activeElem and pageElem are both protractor element finders, and are pointing to the same web element.

First to answer your question about why

expect(activeElem).toEqual(pageElem);

Gets into an infinite loop, it's because protractor patched jasmine's expect to resolve the promise before asserting, so that things like expect(activeElem.getText()).toEqual('text'); works without having to do

activeElem.getText().then(function(text) {
  expect(text).toEqual('text');
})

You could say, why not just resolve the promise once? But then there are nested promises.

So now you might be thinking this is an issue, but it really isn't because you would never compare two elementFinders in a real use case. Jasmine's toEqual does a reference check, and not a deep compare, so expect(activeElem).toEqual(pageElem), is just the same as a simple reference comparison: (activeElem === pageElem).toToTruthy(), and there's really no point doing that. (Note element(by.css('html')) === element(by.css('html')) is false because it's not the same reference.)

So, to answer the real question for this thread: how to see if two elementFinders have the same underlying webelements:

expect(activeElem.getId()).toEqual(pageElem.getId());

Solution 2:

It's weird that it's expecting a promise only and could not handle a webdriver element... I had the same HUGE stacktrace as you.

Anyway, would you accept this kind of solution: send a "dumb" promise with a nice comment to justify why you had to do that. It's more a workaround than a semantic solution I admit.

expect(page.element.getInnerHtml())
  .toEqual(browser.driver.switchTo().activeElement().getInnerHtml());

It's working for me ;)

EDIT: Bonus answer

The reason you can't call expect with a WebElement comes from the Webdriver Control Flow Principle (I'm sure you already know about) and this line in jasminewd, the adapter for jasmine to Webdriver developped and used by Protractor ;)


Solution 3:

For the future readers, I've created a custom matcher to assert if an element is active/focused:

beforeEach(function() {
    jasmine.addMatchers({
        toBeActive: function() {
            return {
                compare: function(elm) {
                    return {
                        pass: elm.getId().then(function (activeElementID) {
                            return browser.driver.switchTo().activeElement().getId().then(function (currentElementID) {
                                return jasmine.matchersUtil.equals(currentElementID, activeElementID);
                            });
                        })
                    };
                }
            };
        }
    });
});

Usage:

expect(element(by.css("#myid")).toBeActive();

Solution 4:

What about using CSS selectors and :focus

expect(element.all(by.css('#myid:focus')).count()).toBe(1);

Solution 5:

I solved it by using protractor's: ElementFinder.prototype.equals

const activeElement = await browser.driver.switchTo().activeElement();
const potentialyFocusedElement = await component.$('your-locator');
const isFocused = await potentialyFocusedElement.equals(activeElement);

I am not sure how exactly equals work, if it does a deep compare, or it somehow compares instances. But it works.

Note that you can not call activeElement.equals(...) since it is not an ElementFinder, it is a WebElement.


Post a Comment for "Asserting An Element Is Focused"