Как использовать транспортир, чтобы проверить, виден ли элемент?


111

Я пытаюсь проверить, виден ли элемент с помощью транспортира. Вот как выглядит элемент:

<i class="icon-spinner icon-spin ng-hide" ng-show="saving"></i>

Находясь в консоли Chrome, я могу использовать этот селектор jQuery, чтобы проверить, виден ли элемент:

$('[ng-show=saving].icon-spin')
[
<i class=​"icon-spinner icon-spin ng-hide" ng-show=​"saving">​</i>​
]
> $('[ng-show=saving].icon-spin:visible')
[]

Однако, когда я пытаюсь сделать то же самое в транспортире, я получаю эту ошибку во время выполнения:

InvalidElementStateError: 
invalid element state: Failed to execute 'querySelectorAll' on 'Document': 
'[ng-show=saving].icon-spin:visible' is not a valid selector.

Почему это неверно? Как проверить видимость с помощью транспортира?


Привет, @limp_chimp, мой ответ ниже помог тебе?
Лео Галуччи

@limp_chimp для таких вещей, как видимость, подумайте об использовании модульных тестов DOM клиента AngularJS. Их намного быстрее запускать и легче развивать.
Offirmo

Ответы:


144

Это должно сделать это:

expect($('[ng-show=saving].icon-spin').isDisplayed()).toBe(true);

Помните, что транспортир - $это не jQuery, и :visibleон еще не является частью доступных селекторов CSS + псевдоселекторов.

Дополнительная информация на https://stackoverflow.com/a/13388700/511069


1
Ой, чувак. Так круто. Это именно то, что мне нужно было определить. Большое спасибо, чувак.
racl101

2
В приведенном ниже ответе также используется, isDisplayed()но просто расширяется, чтобы разрешить обещание полноты, хотя этот шаг является необязательным и предназначен только для включения условных операторов в ваши тесты, что является плохой практикой. @asenovm, не могли бы вы уточнить свой комментарий "Это просто неправильно"?
Лео Галлуччи,

@LeoGallucci, isDisplayed () возвращает ElementFinder, а не логическое значение.
asenovm 09

1
Пожалуйста, не .toBeTruthy();используйте .toBe(true)вместо этого. .toBeTruthy();будет соответствовать таким вещам, как [], 'false', 42. В основном все, что ожидает 0, "", null, undefined, NaN или false, является правдой.
Брайан

78

Правильный способ проверить видимость элемента с помощью Protractor - вызвать isDisplayedметод. Вы должны быть осторожны, так isDisplayedкак не возвращает логическое значение, а скорееpromise предоставляет оцененную видимость. Я видел много примеров кода, которые неправильно используют этот метод и поэтому не оценивают его фактическую видимость.

Пример получения видимости элемента:

element(by.className('your-class-name')).isDisplayed().then(function (isVisible) {
    if (isVisible) {
        // element is visible
    } else {
        // element is not visible
    }
});

Однако вам это не нужно, если вы просто проверяете видимость элемента (в отличие от его получения), потому что транспортир исправляет Jasmine expect (), поэтому он всегда ожидает выполнения обещаний. См. Github.com/angular/jasminewd

Итак, вы можете просто сделать:

expect(element(by.className('your-class-name')).isDisplayed()).toBeTruthy();

Поскольку вы используете AngularJSдля управления видимостью этого элемента, вы также можете проверить его атрибут класса ng-hideследующим образом:

var spinner = element.by.css('i.icon-spin');
expect(spinner.getAttribute('class')).not.toMatch('ng-hide'); // expect element to be visible

8

У меня была аналогичная проблема, я хотел вернуть только те элементы, которые были видны в объекте страницы. Я обнаружил, что могу использовать CSS :not. В случае этой проблемы это должно сделать вас ...

expect($('i.icon-spinner:not(.ng-hide)').isDisplayed()).toBeTruthy();

В контексте объекта страницы вы можете получить ТОЛЬКО те элементы, которые также видимы таким образом. Например. учитывая страницу с несколькими элементами, где видны только некоторые, вы можете использовать:

this.visibileIcons = $$('i.icon:not(.ng-hide)'); 

Это вернет вам все видимые i.icons


1
isDisplayed () должен находиться в области ожидания, как объяснил @leoGallucci.
Полосатый

5

Если в DOM есть несколько элементов с одинаковым именем класса. Но виден только один элемент.

element.all(by.css('.text-input-input')).filter(function(ele){
        return ele.isDisplayed();
    }).then(function(filteredElement){
        filteredElement[0].click();
    });

В этом примере фильтр берет набор элементов и возвращает единственный видимый элемент с помощью isDisplayed () .


Это отличный ответ; рассмотрим случай, когда такого элемента нет! $ ('. text-input-input') элегантно предупредит пользователя; это может потерпеть неудачу, потому что filteredElement.length === 0?
The Red Pea

1

Этот ответ будет достаточно надежным, чтобы работать для элементов, которых нет на странице, поэтому он будет корректно завершаться ошибкой (без исключения), если селектор не смог найти элемент.

const nameSelector = '[data-automation="name-input"]';
const nameInputIsDisplayed = () => {
    return $$(nameSelector).count()
        .then(count => count !== 0)
}
it('should be displayed', () => {
    nameInputIsDisplayed().then(isDisplayed => {
        expect(isDisplayed).toBeTruthy()
    })
})

1

Ждать видимости

const EC = protractor.ExpectedConditions;
browser.wait(EC.visibilityOf(element(by.css('.icon-spinner icon-spin ng-hide')))).then(function() {
  //do stuff
})

Трюк с Xpath для поиска только видимых элементов

element(by.xpath('//i[not(contains(@style,"display:none")) and @class="icon-spinner icon-spin ng-hide"]))

1
 element(by.className('your-class-name')).isDisplayed().then(function (isVisible) {
if (isVisible) {
    // element is visible
} else {
    // element is not visible
}
}).catch(function(err){
console.log("Element is not found");
})

0

Вот несколько фрагментов кода, которые можно использовать для фреймворка, который использует Typescript, транспортир, жасмин.

browser.wait(until.visibilityOf(OversightAutomationOR.lblContentModal), 3000, "Modal text is present");

// Утверждение текста

OversightAutomationOR.lblContentModal.getText().then(text => {
                    this.assertEquals(text.toString().trim(), AdminPanelData.lblContentModal);
                });

// Утверждение элемента

expect(OnboardingFormsOR.masterFormActionCloneBtn.isDisplayed()).to.eventually.equal(true

    );

OnboardingFormsOR.customFormActionViewBtn.isDisplayed().then((isDisplayed) => {
                        expect(isDisplayed).to.equal(true);
                });

// Утверждение формы

formInfoSection.getText().then((text) => {
                        const vendorInformationCount = text[0].split("\n");
                        let found = false;
                        for (let i = 0; i < vendorInformationCount.length; i++) {
                            if (vendorInformationCount[i] === customLabel) {
                                found = true;
                            };
                        };
                        expect(found).to.equal(true);
                    });     
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.