Работа с веб-представлениями
Важно!
Прекращение поддержки Центра приложений Visual Studio запланировано на 31 марта 2025 г. Хотя вы можете продолжать использовать Центр приложений Visual Studio, пока он не будет полностью выведен из эксплуатации, существует несколько рекомендуемых вариантов, на которые вы можете рассмотреть возможность миграции.
Узнайте больше о сроках поддержки и альтернативных вариантах.
Xamarin.UITest предоставляет API для поиска и взаимодействия с представлениями в собственных мобильных приложениях. Однако некоторые мобильные приложения являются гибридными приложениями, которые используют веб-представления для отображения HTML для пользователя. Android предоставляет , в android.webkit.WebView
то время как приложения iOS могут использовать UIWebView или WKWebView. UIWebView старше и совместим со всеми версиями iOS, а WKWebView — для iOS 8 и более поздних версий.
Взаимодействие с веб-представлениями немного сложнее, так как UITest сначала должен получить ссылку на веб-представление, а затем на содержащиеся в нем элементы DOM.
API WebView в UITest
Существует два API для получения ссылки на элемент управления webview в UITest:
- AppQuery.WebView используется для
UIWebView
элементов управления. - AppQuery.Class используется для
WKWebView
элементов управления.
Каждый из них будет более подробно рассмотрен ниже.
Поиск UIWebView
элемента управления с помощью AppQuery.WebView
UITest предоставляет метод AppQuery.WebView для получения ссылки на UIWebView
элемент управления. Ниже приведен пример фрагмента кода:
>>> app.Query(c=>c.WebView())
Если на экране есть только одно веб-представление, по WebView
умолчанию будет использоваться одно веб-представление. Если на экране есть несколько веб-представлений, WebView(Int32)
можно использовать для изоляции одного из них путем передачи индекса с отсчитываемым от нуля.
Поиск WKWebView
элемента управления
UITest предоставляет метод AppQuery.Class для получения ссылки на WKWebView
элемент управления. Ниже приведен пример фрагмента кода:
>>> app.Query(c=>c.Class("WKWebView"))
Взаимодействие с элементами DOM в элементе управления веб-представления
После изоляции веб-представления существует два main API для взаимодействия с элементами DOM:
- CSS — этот API использует селекторы CSS для поиска элементов модели DOM, отображаемых в веб-представлении.
- XPath — UITest может использовать выражения XPath для поиска элементов DOM в веб-представлении.
Api XPath, хотя и более мощный, также более сложный в использовании. Как правило, предпочтение следует отдавать API CSS и api XPath, используемый при необходимости.
CSS
Элементы HTML можно сопоставить с помощью метода AppQuery.Css . Этот метод принимает селектор CSS и возвращает массив всех соответствующих элементов HTML. Функционально этот API одинаков в Android и iOS.
Например, следующее действие Android содержит android.webkit.WebView
:
В этом фрагменте кода показано, как найти все элементы H1 DOM в веб-представлении:
>>> app.Query(c=>c.Css("H1"))
Query for Css("H1") gave 1 results.
[
[0] {
Id => "",
NodeType => "ELEMENT_NODE",
NodeName => "H1",
Class => "",
Html => "<h1>H1 Header!</h1>",
Value => null,
WebView => "webView1",
TextContent => "H1 Header!",
Rect => {
Width => 1032,
Height => 117,
CenterX => 540,
CenterY => 408,
Top => 44,
Bottom => 83,
Left => 8,
Right => 352,
X => 24,
Y => 351
}
}
]
Если на данном экране несколько веб-представлений, uiTest автоматически будет использовать первое веб-представление. Если веб-представлений несколько, необходимо явно определить веб-представление с помощью IApp.WebView(Int32)
. Например, если на экране есть два веб-представления, и мы хотим найти все элементы H1 во втором веб-представлении:
>>> app.Query(c=>c.WebView(1).Css("H1"))
Query for WebView().Css("H1") gave 1 results.
[
[0] {
Id => "",
NodeType => "ELEMENT_NODE",
NodeName => "H1",
Class => "",
Html => "<h1>H1 Header!</h1>",
Value => null,
WebView => "webView1",
TextContent => "H1 Header!",
Rect => {
Width => 1032,
Height => 117,
CenterX => 540,
CenterY => 408,
Top => 44,
Bottom => 83,
Left => 8,
Right => 352,
X => 24,
Y => 351
}
}
]
Если несколько элементов HTML совпадают с запросом CSS, Index
метод можно использовать для доступа к отдельному элементу в результирующем наборе. Например, в следующем фрагменте кода показано, как получить доступ к третьему элементу ЭЛЕМЕНТОВ HTML с помощью .user
стиля :
>>> app.Tap(c => c.Css(".user").Index(2));
XPath
XPath — это мощный API для поиска модели DOM, но может быть немного сложнее использовать по сравнению с API CSS. UITest может находить элементы DOM с помощью селектора XPath, переданного в метод AppQuery.XPath . Этот API одинаков в Android и iOS.
Следующий фрагмент кода является примером сопоставления элемента H1 DOM из предыдущего раздела с помощью XPath:
>>> app.Query(c=>c.XPath("//h1"))
Query for XPath("//h1") gave 1 results.
[
[0] {
Id => "",
NodeType => "ELEMENT_NODE",
NodeName => "H1",
Class => "",
Html => "<h1>H1 Header!</h1>",
Value => null,
WebView => "webView1",
TextContent => "H1 Header!",
Rect => {
Width => 1032,
Height => 117,
CenterX => 540,
CenterY => 408,
Top => 44,
Bottom => 83,
Left => 8,
Right => 352,
X => 24,
Y => 351
}
}
]
Вызов JavaScript
Также можно найти веб-представления с помощью AppQuery.InvokeJS
метода . Этот метод принимает запрос в виде строки и вызывает JavaScript для элементов представления, соответствующих запросу. При обнаружении элементов представления, отличных от WebView, выполнение будет остановлено и будет создано исключение.
InvokeJS в Android
Вообще говоря, android требует, чтобы JavaScript returns
значение; в противном случае запрос вернет null
:
>>> app.Query (w => w.WebView ().InvokeJS ("document.getElementById('lastname').value"))
[
[0] "null"
]
>>> app.Query (w => w.WebView ().InvokeJS ("return document.getElementById('lastname').value"))
[
[0] "Smith"
]
InvokeJS в iOS
Как правило, в iOS return
не используется:
>>> app.Query (w => w.WebView ().InvokeJS ("return document.getElementById('lastname').value"))
[
[0] ""
]
>>> app.Query (w => w.WebView ().InvokeJS("document.getElementById('lastname').value"))
[
[0] "Smith"
]
Примеры
В этом разделе рассматриваются некоторые распространенные варианты использования, которые можно найти при написании тестов Calabash с использованием веб-представлений.
Прокрутка
Можно прокрутить веб-представление, чтобы вывести элементы DOM на экран. Для этого используются методы IApp.ScrollDownTo
или IApp.ScrollUpTo
. Сигнатура этих методов аналогична:
IApp.ScrollDownTo(Func<AppQuery, AppWebQuery> toQuery,
string withinMarked,
ScrollStrategy strategy,
Nullable<TimeSpan> timeout)
Ниже приведено краткое описание параметров.
toQuery
— это веб-запрос UITest, который находит элемент DOM в веб-представлении.withinMarked
— это строка, которая будет размещать веб-представление на экране. Этот параметр является необязательным, если на экране есть только одно веб-представление. Эта строка будет использоваться дляIApp.Marked
поиска веб-представления на экране.strategy
— этот необязательный параметр сообщает UITest, как прокручивать веб-представление.ScrollStrategy.Gesture
попытается эмулировать прокрутку пользователем путем перетаскивания экрана.ScrollStrategy.Programatic
освобождает UITest для прокрутки самым быстрым способом.ScrollStrategy.Auto
указывает UITest использовать любое сочетание иProgramatic
для прокруткиGesture
(с предпочтением ).Programatic
timeout
— необязательный параметр, указывающий время ожидания UITest до истечения времени ожидания запроса.
В качестве примера использования этих API рассмотрим снимки экрана веб-представления, внедренного в приложение Android:
Если мы рассмотрим иерархию представлений этого действия в REPL, мы увидим следующее:
>>> tree
[[object CalabashRootView] > PhoneWindow$DecorView]
[ActionBarOverlayLayout] id: "decor_content_parent"
[FrameLayout > LinearLayout] id: "content"
[WebView] id: "webView1", label: "WebView"
[dom] id: "show_secret"
[dom] id: "firstname"
[dom] id: "lastname"
[ActionBarContainer] id: "action_bar_container"
[Toolbar] id: "action_bar"
[TextView] text: "TestingWebviews.Droid"
[View] id: "statusBarBackground"
[View] id: "navigationBarBackground"
Выходные tree
данные команды сообщают нам, что веб-представление имеет идентификатор webView1
и содержит три элемента DOM:
- кнопка HTML, вызываемая
show_secret
с разметкой<button id="show_secret">Toggle the Secret</button>
- поле
firstname
ввода HTML с разметкой<input type="text" name="firstname" id='firstname'>
- поле
lastname
ввода HTML с разметкой<input type="text" name="lastname" id='lastname'>
Кнопка show_secret
отображается на экране, но firstname
не отображается.lastname
Прежде чем UITest сможет взаимодействовать с этими элементами DOM, необходимо использовать API прокрутки для просмотра этих полей. В следующем фрагменте из REPL показано, как прокрутить входные элементы HTML в представление с помощью ScrollDownTo
API:
>>> app.ScrollDownTo(c=>c.Css("#firstname"))
Scrolling down to Css("#firstname")
Ввод текста
Ввод текста в элемент ввода HTML осуществляется путем предоставления текста и AppWebQuery
api с помощью AppQuery.EnterText
API . На следующем снимке экрана: веб-представление в приложении Android:
Следующий фрагмент кода будет показан для ввода текста во входной firstname
элемент HTML:
[Test]
public void ScrollDownAndEnterName()
{
app.ScrollDownTo(c => c.Css("input#firstname"), );
app.EnterText(c => c.Css("input#firstname"), "Monkey");
// A more verbose way to enter text, explicitly identifying the webview and ScrollStrategy
app.ScrollDownTo(c => c.Css("input#lastname"), "webView1", ScrollStrategy.Gesture);
app.EnterText(c => c.Css("input#lastname"), "Chimpanzee");
}