В предыдущей статье я объяснил, что означает с технической точки зрения “завершение загрузки страницы”.
Повторю вкратце основную мысль: Selenium (и, я думаю, большинство других инструментов тоже) использует свойство document.readyState для определения момента окончания загрузки страницы.
А вот как именно он это делает – сейчас расскажу. Точнее говоря, не “как”, а “когда”.
На первый взгляд всё кажется просто.
Свойство document.readyState может принимать всего три различных значения:
- loading означает, что страница находится в процессе загрузки
- interactive означает, что основная часть страницы загрузилась, пользователь может с ней взаимодействовать, но ещё продолжается загрузка дополнительных ресурсов (например, картинок)
- complete означает, что страница “полностью загружена”
Выполняем команду get, чтобы открыть в браузере страницу с указанным адресом, после чего ждём, когда свойство document.readyState приобретёт значение complete.
Увы, этого недостаточно.
Если немного подумать – вспоминается команда click, выполняющая проход по ссылке. После неё тоже надо ожидать завершения загрузки страницы.
Но и этим дело не ограничивается.
Новая страница может начать загружаться после любого действия пользователя.
На любое действие пользователя (не только на клик, но и, например, нажатие клавиши или наведение мыши на какой-то элемент) может быть зарегистрирован JavaScript-обработчик, который может активировать загрузку новой страницы. Выходит, что после любой команды нужно пытаться подождать, не загрузится ли новая страница? Выходит, так.
Однако и это ещё не всё.
Иногда страница перезагружается сама собой, по таймауту, даже если не выполнялось никаких действий.
Как Selenium может отследить это? Нереально…
Что же делать?
Разрабочики Selenium нашли остроумное решение.
Да, для выполнения какого-либо действия на странице нужно, чтобы она была загружена, то есть свойство document.readyState приобрело нужное значение. Но вовсе необязательно ждать этого после выполнения команды. Гораздо лучше ждать перед выполнением команды.
Перед выполнением каждой команды Selenium ждёт, пока свойство document.readyState примет нужное значение.
Например, выполняется команда get, начинает загружаться страница. Но Selenium не ждёт завершения загрузки, вместо этого он достаточно быстро сообщает, что команда get успешно выполнена.
После этого мы пытаемся найти на странице какой-нибудь элемент, чтобы совершить с ним какое-нибудь действие, то есть выполняем команду findElement. В этот момент Selenium замечает, что свойство document.readyState ещё не приобрело значение complete, то есть страница всё ещё загружается. И тогда он приостанавливает выполнение команды поиска элемента и ждёт, пока страница догрузится.
Таким образом, выполняя ту или иную команду, Selenium вообще не заботится о том, будет после этого загружаться новая страница или нет. Если будет – разберёмся с этим перед выполнением следующей команды.
Согласитесь, красиво?
P.S. А зачем котик на картинке, которая ссылается на эту статью? Ну вот такие у меня ассоциации :)
Selenium, как кот в засаде, ждёт, когда браузер “расслабится” – и в этот момент набрасывается на него и выполняет команду!