Утверждение элемента сфокусировано

Согласно Как я утверждаю, элемент сфокусирован? поток, вы можете проверить, сосредоточен ли элемент, переключившись на activeElement() и утверждаем, что это тот же элемент, на который вы рассчитывали:

expect(page.element.getAttribute('id')).toEqual(browser.driver.switchTo().activeElement().getAttribute('id'));

В моём случае фокусированный элемент не имеет id атрибут

Что я должен делать вместо проверки id?

Дополнительный вопрос: Кроме того, как вы можете видеть из моих попыток решить эту проблему, похоже, что я не могу ожидать / утверждать элемент (или веб-элемент) как законченный объект. Зачем?


Я пробовал:

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

Но происходит сбой с ошибкой, которую я даже не могу понять - есть огромный след (около 10 минут для прокрутки в консоли), но нет удобной ошибки внутри.

Я также пытался использовать getWebElement():

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

Но это привело к следующей ошибке:

Ошибка: ожидается вызов с аргументом WebElement, ожидается обещание. Вы хотели использовать.getText()?

Использование последней версии разработки транспортира.

7 ответов

Решение

В своем ответе я собираюсь предположить activeElem а также pageElem оба являются искателями элементов транспортира и указывают на один и тот же веб-элемент.

Сначала ответьте на ваш вопрос о том, почему

expect(activeElem).toEqual(pageElem);

Попадает в бесконечный цикл, это потому, что транспортир залатал жасмин expect чтобы выполнить обещание, прежде чем утверждать, чтобы такие вещи, как expect(activeElem.getText()).toEqual('text'); работает без необходимости

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

Вы могли бы сказать, почему бы просто не выполнить обещание один раз? Но тогда есть вложенные обещания.

Так что теперь вы можете подумать, что это проблема, но на самом деле это не так, потому что вы никогда не сравнили бы два elementFinder в реальном случае использования. ToEqual Жасмин выполняет проверку ссылок, а не глубокое сравнение, поэтому expect(activeElem).toEqual(pageElem), так же, как простое сравнение ссылок: (activeElem === pageElem).toToTruthy()и в этом нет никакого смысла. (Заметка element(by.css('html')) === element(by.css('html')) ложно, потому что это не та же ссылка.)

Итак, чтобы ответить на реальный вопрос для этой темы: как увидеть, имеют ли два elementFinder одинаковые базовые элементы:

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

Странно, что он ожидает только обещание и не может обработать элемент веб-драйвера... У меня была такая же ОГРОМНАЯ трассировка стека, как и у вас.

В любом случае, примете ли вы такое решение: отправьте "глупое" обещание с хорошим комментарием, чтобы объяснить, почему вы должны это сделать. Это скорее обходной путь, чем семантическое решение, которое я допускаю.

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

Это работает для меня;)

РЕДАКТИРОВАТЬ: Бонус ответ

Причина, по которой вы не можете вызвать ожидаемый с помощью WebElement, проистекает из принципа потока управления Webdriver (я уверен, что вы уже знаете об этом) и этой строки в jasminewd, адаптере для jasmine к Webdriver, разработанной и используемой Protractor;)

Для будущих читателей, я создал собственный сопоставитель, чтобы утверждать, активен ли элемент / сосредоточен:

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);
                            });
                        })
                    };
                }
            };
        }
    });
});

Использование:

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

Я решил это с помощью транспортира: ElementFinder.prototype.equals

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

Я не уверен как именно equals работать, если он делает глубокое сравнение, или он как-то сравнивает экземпляры. Но это работает.

Обратите внимание, что вы не можете позвонить activeElement.equals(...) так как это не ElementFinder, это WebElement,

Как насчет использования селекторов CSS и:focus

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

Вы можете просто проверить текст (или что-нибудь еще) элемента:

var currentElement = browser.switchTo().activeElement();
expect(currentElement.getText()).toEqual(page.element.getText());

Вам нужно найти способ сообщить транспортиру / вебдрайверу, как найти ваш элемент на странице. Protractor использует JavaScript для поиска элементов, поэтому доступны любые инструменты для проверки DOM. Транспортир и вебдрайвер оборачивают эти API в различные by ароматизаторы:

http://angular.github.io/protractor/

В дополнение к основным вариантам, Protractor добавляет варианты с поддержкой Angular (так что вы можете осуществлять поиск по Angular привязке и т. Д.).

Если ваш элемент не имеет каких-либо отличительных характеристик, то, возможно, стоит добавить что-то, чтобы облегчить тестирование. Или (хотя это часто осуждается из-за своей хрупкости), вы можете использовать xpath. См. https://github.com/angular/protractor/blob/master/docs/locators.md

Другие вопросы по тегам