Как выполнить один элемент тогда и потом другой в транспортире - PullRequest
0 голосов
/ 17 декабря 2018

Этот следующий код ведет себя случайным образом, иногда он работает нормально, а иногда выдает ошибку, подобную этой Stale Element Reference Exception

Что я хочу, так это то, что я хочу, чтобы это ниже выполнялось сначала

element(by.id('FiltItemTransDocNo')).sendKeys(grno);

послевыше, я хочу, чтобы это было выполнено ниже

element.all(by.name('chkGrd')).first().click();

я пробовал этот способ, но, похоже, это не сработало

element(by.id('FiltItemTransDocNo')).sendKeys(grno).then(function(el){
     element.all(by.name('chkGrd')).first().click();
});

выручить меня с этим

iПрикрепив изображение, я отправляю ключи в поле «Покупка Rquisition», и в соответствии с этим я получил результат, который покажет только один результат, и я хочу щелкнуть мышью, и если я поставлю условие для видимости, оно всегда будет true, тогда я приведу ктот же номер enter image description here

Ответы [ 3 ]

0 голосов
/ 19 декабря 2018

Быстрая заметка о sendKeys и e1

Быстрая заметка о том, что sendKeys не возвращает WebElement или ElementFinder.Это означает, что e1 в приведенном выше примере, вероятно, не определено.

Устаревшие элементы и изменение DOM

Краткое примечание по предположениям: Ответ имеет предположение, что отправка текста нафильтр будет изменять количество строк или количество элементов на экране.Если после отправки текста на экране отображается одинаковое количество элементов, это не будет работать.Я бы посмотрел комментарий Флорента ниже об ошибке устаревшей ссылки.

Устаревшие элементы обычно возникают, когда DOM изменяется.Если вы используете какую-то структурную директиву в Angular, DOM изменится, если вы используете * ngFor или * ngIf.Я предполагаю, что после того, как вы отфильтруете элемент, вы получите элементы в DOM во время или до того, как DOM действительно изменится в зависимости от вашего фильтра.Это привело бы к устаревшему элементу веб-ссылки.В моем примере ниже я использую async / await с отключенным потоком управления.

Явное ожидание во время фильтра

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

it('should do something', async () => {
  const filterItem = element(by.id('FiltItemTransDocNo'));
  await filterItem.sendKeys(grno);
  await browser.sleep(1000);  // or some other waits
  await element.all(by.name('chkGrd')).first().click();
});

Сравнить строки для element.all

В качестве альтернативы вы можете выполнить проверку сравнения дляколичество element.all предметов, которые у вас есть до и после клика, и только после обновления.

it('should do something', async () => {
  const filterItem = element(by.id('FiltItemTransDocNo'));
  const table = element.all(by.name('chkGrd'));
  const length = await table.count();

  await filterItem.sendKeys(grno);

  // After the filter keys are sent, check to see if the current table
  // count is not equal to the `table.count()`.
  let updated = false;
  await browser.wait(async () => {
    updated = length !== await table.count();
    return updated;
  }, 5000);

  // So if we use the entire 5 seconds and the count has not changed,
  // we should probably fail before clicking on stuff.
  expect(updated).toBeTruthy();

  // now we can click on the next element.
  await element.all(by.name('chkGrd')).first().click();
});

Почему звонит length !== await table.count()?Это потому, что таблица представляет собой обещание получить веб-элемент.Когда вы вызываете метод count, он выполняет действие, сначала разрешив веб-элемент.Это может потенциально отличаться в зависимости от изменения DOM.Затем мы сравниваем текущий счетчик с предыдущим.

Убедившись, что вы используете async / await

В вашем файле конфигурации вам нужно будет указать, что вы отключили поток управления:

exports.config = {
    // In this case, I plan to use a selenium standalone server
    // at http://127.0.0.1:4444/wd/hub. You could also use other 
    // methods like direct connect or starting it up with 'local'.
    seleniumAddress: 'http://127.0.0.1:4444/wd/hub',

    // Required flag to tell Protractor you do not want to use the
    // control flow. This means that you will have to either chain
    // your promises or async / await your actions. Historically
    // jasminewd node module would resolve promises for you. This
    // package will no longer be used in future releases since the
    // control flow is deprecated.
    SELENIUM_PROMISE_MANAGER: false,

    // The rest of your config...
}

Надеюсь, это поможет.

0 голосов
/ 21 декабря 2018

Как я объяснил в ответе на другой вопрос , Protractor и все используемые им инструменты меняются, чтобы использовать обещания родного JavaScript, ожидая, что все переведут свой код в полностью асинхронный стиль кодирования.,К сожалению, они не делают это легким, потому что вы не можете смешать старый стиль кода с новым стилемИтак, обо всем по порядку, убедитесь, что весь ваш набор написан в асинхронном стиле, и вы установили SELENIUM_PROMISE_MANAGER: false в своей конфигурации.

Что происходит в ответ на sendKeys?Если это инициирует вызов AJAX, а ответ на этот вызов изменяет DOM, то вам, вероятно, придется делать то, что предлагает @cnishina, и опрашивать DOM, чтобы дождаться внесения изменений.Однако, если происходят только изменения на стороне клиента Angular, этот код должен работать:

it('should do something', async () => {
  await element(by.id('FiltItemTransDocNo')).sendKeys(grno);
  await element.all(by.name('chkGrd')).first().click();
});

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

0 голосов
/ 17 декабря 2018

Существует несколько решений для ссылки на устаревшие элементы.

Первый:

    let filterItem = element(by.id('FiltItemTransDocNo'));
    browser.wait(ExpectedConditions.visibilityOf(filterItem), 5000, 'Element is not visible.');
    filterItem.sendKeys('some random text');

    let elementToClick = element.all(by.name('chkGrd')).first();
    browser.wait(ExpectedConditions.elementToBeClickable(elementToClick), 5000, 'Element is not clickable.');
    elementToClick.click();

Вы также можете связать их в цепочку:

browser.wait(ExpectedConditions.visibilityOf(filterItem), 5000, 'Element is not visible.').then( () => {
                filterItem.sendKeys('some random text');

                browser.wait(ExpectedConditions.elementToBeClickable(elementToClick), 5000, 'Element is not clickable.').then( () => {
                    elementToClick.click();
                });
            });

Или второй способ обновленияэлемент на устаревшей ошибке:

let filterItem = element(by.id('FiltItemTransDocNo'));

            try {
                filterItem.sendKeys('some random text');
            } catch (e) {
                if (e instanceof StaleElementReferenceError) {
                    filterItem = element(by.id('FiltItemTransDocNo'));
                    filterItem.sendKeys('text');
                }
            }
...