Есть отличная удаленная работа для php+codeception+jenkins+allure+docker спецов. 100% remote! Присоединиться к проекту

Дождаться завершения всех Javascript (Angular JS)

python
angularjs
javascript
webdriver
Теги: #<Tag:0x00007f7b704b7858> #<Tag:0x00007f7b704b7718> #<Tag:0x00007f7b704b75d8> #<Tag:0x00007f7b704b7498>

(Дмитрий Золкин) #1

Подскажите пожалуйста.Можно ли каким либо образом узнать завершилось ли выполнение всех скриптов на странице.?? Получить как то от браузера или еще как то.???

Приложение написано на #angularjs .
Для тестирования использую #webdriver + #python .

Проблема в том, что в тесте я нажимаю кнопку и выполняется #javascript . С сервера получаю информацию.Она запихивается в таблицу.

Есть метод в котором использую find_elements_by_tag_name (ищу там всякие th tr td в таблице).Метод отрабатывает быстрее чем данные попадут в дом.Аналогию метода find_elements_by_tag_name в классе ExpectedCondition не нашел.
Метод примерно следующий:

def get_all_rows_in_table(self, locator):
    try:
        element = WebDriverWait(self.driver, 10).until(
            EC.presence_of_element_located(locator)
        )
        rows = element.find_elements_by_tag_name("tr")
        return rows
    except TimeoutException:
        print u"Таблица не найдена"

def get_cells_text_on_table(self, row):
    list_of_text = []
    list_of_elements = row.find_elements_by_tag_name("td")
    if list_of_elements == []:
        list_of_elements = row.find_elements_by_tag_name("th")
    for cell in list_of_elements:
        if not ("ng-hide" in cell.get_attribute('class')):
            list_of_text.append(cell.text)
    return list_of_text

Когда я вызываю get_cells_text_on_table с параметром rows[1] в таблице еще нету строки с данным текстом. Я получаю, что то вида IndexOutOfRange или что искомый элмент не в доме
Ставить time.sleep(1) не хочется.

Вот и появилась идея ждать пока завершатся скрипты и тогда уже проверять, что отображается на странице.
Можно ли это сделать без всяких Protraktor-ов))) Потому, что я еще в Python новечек можно сказать,а еще и javascript пока времени нет(((


(Roma Marinsky) #2

Ну я бы подождал пока загрузятся все нужные элементы на странице. Для того чтобы дождаться - нужно чётко знать какое количество их должно быть. И только после загрузки всех элемнетов проверить на нужное условие

В тестах должна быть предсказуемая логика


(Дмитрий Золкин) #3

Можно попробовать, но вопрос именно про завершение javascript


(Дмитрий Золкин) #4

А можете кусочек кода, что то сразу не могу сообразить.
Я знаю например, что при нажатии на элемент должна загрузиться таблица и в ней 59 строк.


(Дмитрий Золкин) #5

Просто если я добавлю строку в таблицу мне, что нужно метод переписывать???


(Roma Marinsky) #6

Извини, но не могу сказать как в python
Пока писал на чистом java селениуме, писал while(elements.size() < 58){
sleep(200);
}
Потом уже использовал waitUntil() длинный


(Дмитрий Золкин) #7

Ну sleep Зло…
Хочется узнать неужели никто не задавался таким вопросом…


(Roma Marinsky) #8

Не зло, если тебе надо по простому решить проблему не городя логики. И плюс если у тебя хорошо устроена инкапсуляция потоков тестов.
У тебя тесты мног опоточно бегают?


(Дмитрий Золкин) #9

Нет… Все пока запускается в консоле или из среды.Никаких потоков нету.Есть всякие PageObject + Allure + Pytest+Jenkins. В общем вопрос остается открытым

Эти все варианты я читал мне они чем то не понравилось…
Хочется именно завершения Javascript


(Roma Marinsky) #10

Выполни тогда jsExecutor c командой $(document).ready()


(Roma Marinsky) #11

Или уже ищи как задать ожидание определённого скрипта с помощью jQuery или чистого js


(Дмитрий Золкин) #12

В JQuery есть (я находил на форуме), какая-то переменная, которая отвечает за количество завершенных скриптов. У меня Angular ,как я понимаю там такого нет…
В общем буду искать


(Mykhailo Poliarush) #13

(Дмитрий Золкин) #14

Спасибо большое буду смотреть


(Mykhailo Poliarush) #15

напишите потом что сработало для вас


(Дмитрий Золкин) #16

мне подсказал начальник)) я в Javascript не селен. Но вроде пока работает.
Я создал файлик tools.py.В него написал страшный вот такой код:

class angular_not_active(object):
    def __call__(self, driver):
        hasAngularFinishedScript = "var callback = arguments[arguments.length - 1];\n" + \
                                " angular.element(document.body).injector().get('$browser').notifyWhenNoOutstandingRequests(callback);\n"
        driver.execute_async_script(hasAngularFinishedScript)

Во всех методах, где ждет пока отработает Javascript(angelar) я написал такое:

    def get_all_rows_in_table(self, locator):
        angular_not_active()(self.driver) ---->>>>ДОБАВИЛ ВОТ ТАКОЕ
        try:
            element = WebDriverWait(self.driver, 10).until(
                EC.element_to_be_clickable(locator)
            )
            rows = element.find_elements_by_tag_name("tr")
            return rows
        except TimeoutException:
            print u"Таблица не найдена"

(Roma Marinsky) #17

Какой ужас :slight_smile:


(Сергей Кузьмин) #18

для Python пока похоже нету - для Java



и C#

есть порт Protractor
(для первых двух я же и последние PR сделал, можете посмотреть их upstream:



).

он делает

вот что:

var waitForAngular = function(rootSelector, callback) {
    var el = document.querySelector(rootSelector);
    try {
        if (window.getAngularTestability) {
            window.getAngularTestability(el).whenStable(callback);
            return;
        }
        if (!window.angular) {
            throw new Error("window.angular is undefined");
        }
        if (angular.getTestability) {
            angular.getTestability(el).whenStable(callback);
        } else {
            if (!angular.element(el).injector()) {
                throw new Error("root element (" + rootSelector + ") has no injector.");
            }
            angular.element(el).injector().get('$browser').
            notifyWhenNoOutstandingRequests(callback);
        }
    } catch (err) {
      callback('exception: ' + err.message);
    }
};
// var arguments = []
var log = function(message){ console.log("callback: " + message); return(message); }

var rootSelector = arguments[0] || 'document';
var callback = arguments[1] || log;


то есть в точности то же что и “настоящий” https://github.com/angular/protractor

все работает и проблема с ожиданием окончания работы фреймворка решена.

Кстати - если нужен Python порт - могу написать - займет примерно месяц -