Как дождаться ответа на POST запрос при нажатии на кнопку

Добрый день. Проблема следующая: при нажатии на кнопку происходит POST-запрос, но т.к. нажатие - это последнее действие в сценарии, то ответ может быть не получен и фактически действие в приложении не завершится, соответственно остальные шаги в тесте провалятся.

Если использовать после нажатия ожидание в 1 сек, то всё работает. Есть ли альтернативные методы ожидания получения ответа на запрос?
ожидание “return jQuery.active == 0” не помогает

А что, после нажатия на странице ничего не меняется?

А как вы его используете в коде?

На самой странице нет, кнопка также доступна для повторного нажатия. Совершенное действие после нажатия увидит только пользователь с другой ролью.

использую сразу после нажатия на кнопку

button.click()
while True
    if self._driver.execute_script("return jQuery.active==0")
        break
  • в примере опечатка? ("return jQuery.activ==0")
  • почему не wait.until ? как-то вроде
WebDriverWait(driver, 15).until(
   lambda driver: driver.execute_script('return jQuery.active;') == 0
)
  • пытались вывести что возвращает jQuery.active ? Точно там никаких проблем?
  • у вас точно используется jquery? (на всякий случай :smiley: )
  • Да, опечатка)
  • через WebDriverWait не пробовал, не знал, что его можно еще так применить.
  • выводил - 0. Если ставить ipdb, то к тому времени как он сработает “return jQuery.active;” уже вернет 0
  • недавно на проекте, но думаю да, frontend написан на javaScript :smile:

То что он написан на JS еще не факт что jQuery :slight_smile: Ну и как писали выше, у вас после получения ответа что то изменяется на странице? Если да, то ожидание нужно привязывать уже на два события, и проверять что оба условия - true.

Внешне на странице ничего не меняется.
Про jQuery согласен :slight_smile: Лучше уточню у программистов, что они используют.

Как вы, когда тестируете вручную, узнаёте, что Ajax запрос прошёл спешно?

  • На странице пользователя одной ролью, при нажатии, в консоли появляется сообщение вида:
    RqCheck: for order: 421
    и ответ:

    mq.js:1181 request: call for service 2 for order: 421
    mq.js:1203 ** requestService: returned: {“id”:1293,“status”:0}

  • На странице пользователя с другой ролью, приходит сообщение, что совершено действие

  • В проекте используется jQuery и не помогло

WebDriverWait(driver, 15).until( lambda driver: driver.execute_script('return jQuery.active;') == 0 )

“return $.active;” попробуй.

тоже нет

добрался до кода приложения:

function requestService(id, serviceRq) 
{	
console.log('request: call for service ' + serviceRq + ' for order: ' + id);
console.log(jQuery.active);
if (!id)
{
	var activePos = getActivePos(null);
	id = gDat.orders.oData[activeOPos].id;
}
console.log(jQuery.active);
var denId  = getDenId(id);

var oRequest = { type : serviceRq, o_id : id, den_id : denId };
console.log(jQuery.active);
call_method('setEvents', oRequest, function(msg) {
	console.log("** requestService: returned: " + JSON.stringify(msg));
	console.log(jQuery.active);
});
};

вывод jQuery.active следующий: 0, 0, 0, 1
Получается, что выход из WebDriverWait срабатывает уже на первом 0

ИМХО Тогда, принудительное ожидание 1 сек. после клика, а потом проверка jQuery.

1 лайк

Возможно вас направит реализация в Protractor . Это надстройка над Webdriver-ом. В ней, например, клик происходит только когда все запросы дождались ответов.
protractor-net/NgWebElement.cs at master · bbaia/protractor-net · GitHub (C#) строка 50, например, ждем все ответы.

Пробовали ждать document.readyState === 'complete' ? Или даже вместе jQuery.active + document.readyState (хотя чисто теоретически если readyState != 'complete', active не может быть == 0).

Судя по jquery/ajax.js at 239169bb2ede6ea6287d82d1d13b0c354f451749 · jquery/jquery · GitHub active этого не проверяет, только смотрит есть ли ajax запросы и сколько их.

document.readyState === 'complete'
на всем протяжении возвращает true

Так проверьте, ловит ли Селениум лог в консоли (по крайней мере, с FF должно работать, а вот с Хромом были проблемы).

  1. При создании браузера добавляем капабилити для логирования:

    driver = webdriver.Firefox(capabilities = {“webdriver.log.driver”: “ALL”})

  2. Получаем логи:

    driver.get_log(‘browser’)

Возвращает список из словарей с полями “timestamp”, “message”, “type”, “level”. Причем только последние, которые еще не отдавались по запросу get_log(). Поэтому перед вызовом POST-а можно 1 раз этот метод вызвать, чтобы буфер был почище :smile:

1 лайк

Для моей задачи, пока это единственное альтернативное решение принудительному ожиданию. Всем спасибо за помощь :smiley: