Работа с веб-представлениями

Важно!

Прекращение поддержки Центра приложений 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:

WebView на устройстве Android

В этом фрагменте кода показано, как найти все элементы 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:

Снимок экрана: WebView, используемый в следующем примере.

Если мы рассмотрим иерархию представлений этого действия в 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:

Снимок экрана: WebView, используемый в следующем примере

Следующий фрагмент кода будет показан для ввода текста во входной 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");

}