File: interactive_ash_test.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (432 lines) | stat: -rw-r--r-- 21,192 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_TEST_BASE_ASH_INTERACTIVE_INTERACTIVE_ASH_TEST_H_
#define CHROME_TEST_BASE_ASH_INTERACTIVE_INTERACTIVE_ASH_TEST_H_

#include <memory>

#include "ash/webui/system_apps/public/system_web_app_type.h"
#include "base/memory/weak_ptr.h"
#include "chrome/test/base/mixin_based_in_process_browser_test.h"
#include "chrome/test/interaction/interactive_browser_test.h"
#include "chromeos/ash/components/network/network_type_pattern.h"
#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
#include "content/public/test/browser_test.h"
#include "ui/base/interaction/interaction_sequence.h"

class GURL;
class Profile;

namespace content {
class NavigationHandle;
}

// Sets up Kombucha for ash testing:
// - Provides 1 Kombucha "context" per display, shared by all views::Widgets
// - Provides a default "context widget" so Kombucha can synthesize mouse events
// - Suppresses creating a browser window on startup, because most ash-chrome
//   tests don't need the window and creating it slows down the test
//
// Because this class derives from InProcessBrowserTest the source files must be
// added to a target that defines HAS_OUT_OF_PROC_TEST_RUNNER. The source files
// cannot be in a shared test support target that lacks that define.
//
// For tests that run on a DUT or in a VM, use the subclass AshIntegrationTest,
// which supports running on hardware.
class InteractiveAshTest
    : public InteractiveBrowserTestT<MixinBasedInProcessBrowserTest> {
 public:
  // Helper struct for filling out the Wi-Fi configuration dialog.
  struct WifiDialogConfig {
    std::string ssid = "";
    ::chromeos::network_config::mojom::SecurityType security_type =
        ::chromeos::network_config::mojom::SecurityType::kNone;
    bool is_shared = true;
  };

  InteractiveAshTest();
  InteractiveAshTest(const InteractiveAshTest&) = delete;
  InteractiveAshTest& operator=(const InteractiveAshTest&) = delete;
  ~InteractiveAshTest() override;

  // Sets up a context widget for Kombucha. Call this at the start of each test
  // body. This is needed because InteractiveAshTest doesn't open a browser
  // window by default, but Kombucha needs a widget to simulate mouse events.
  void SetupContextWidget();

  // Installs system web apps (SWAs) like OS Settings, Files, etc. Can be called
  // in SetUpOnMainThread() or in your test body. SWAs are not installed by
  // default because this speeds up tests that don't need the apps.
  void InstallSystemApps();

  // Launches the system web app of type `type`. Associates `element_id` with
  // the app window and returns a Kombucha context for the app window.
  ui::ElementContext LaunchSystemWebApp(
      ash::SystemWebAppType type,
      const ui::ElementIdentifier& element_id);

  // Finds the system web app of type `type` and returns the Kombucha context
  // for the app window.
  ui::ElementContext FindSystemWebApp(ash::SystemWebAppType type);

  // Attempts to close the system web app of type `type`.
  void CloseSystemWebApp(ash::SystemWebAppType type);

  // Navigates the Settings app, which is expected to be associated with
  // `element_id`, to the top-level internet page.
  ui::test::internal::InteractiveTestPrivate::MultiStep
  NavigateSettingsToInternetPage(const ui::ElementIdentifier& element_id);

  // Navigates the Settings app, which is expected to be associated with
  // `element_id`, to the top-level bluetooth page.
  ui::test::internal::InteractiveTestPrivate::MultiStep
  NavigateSettingsToBluetoothPage(const ui::ElementIdentifier& element_id);

  // Navigates the Settings app, which is expected to be associated with
  // `element_id`, to the subpage of the network with type `network_pattern`.
  ui::test::internal::InteractiveTestPrivate::MultiStep
  NavigateSettingsToNetworkSubpage(
      const ui::ElementIdentifier& element_id,
      const ash::NetworkTypePattern network_pattern);

  // Navigates the Settings app, which is expected to be associated with
  // `element_id`, to the details page for the network named `network_name`
  // with type `network_pattern`.
  ui::test::internal::InteractiveTestPrivate::MultiStep
  NavigateToInternetDetailsPage(const ui::ElementIdentifier& element_id,
                                const ash::NetworkTypePattern network_pattern,
                                const std::string& network_name);

  //  Navigates the Settings app, which is expected to be associated with
  // `element_id`, to the Bluetooth details page for the device named
  // `device_name`.
  ui::test::internal::InteractiveTestPrivate::MultiStep
  NavigateToBluetoothDeviceDetailsPage(const ui::ElementIdentifier& element_id,
                                       const std::string& device_name);

  // This function expects the Settings app to already be open and on the
  // detailed page of a cellular network.
  ui::test::internal::InteractiveTestPrivate::MultiStep
  NavigateToApnRevampDetailsPage(const ui::ElementIdentifier& element_id);

  // Navigates the Settings app to the Known Networks subpage.
  ui::test::internal::InteractiveTestPrivate::MultiStep
  NavigateToKnownNetworksPage(const ui::ElementIdentifier& element_id);

  // Navigates the Settings app to the passpoint subscription details page for
  // the passpoint named `passpoint_name`.
  ui::test::internal::InteractiveTestPrivate::MultiStep
  NavigateToPasspointSubscriptionSubpage(
      const ui::ElementIdentifier& element_id,
      const std::string& passpoint_name);

  // This function expects the Settings app to already be open and on the APN
  // subpage.
  ui::test::internal::InteractiveTestPrivate::MultiStep
  OpenAddCustomApnDetailsDialog(const ui::ElementIdentifier& element_id);

  // This function expects the Settings app to already be open and on the APN
  // subpage.
  ui::test::internal::InteractiveTestPrivate::MultiStep OpenApnSelectionDialog(
      const ui::ElementIdentifier& element_id);

  // Open up the "Add built-in VPN" dialog. This function expects the Settings
  // app to already be open.
  ui::test::internal::InteractiveTestPrivate::MultiStep OpenAddBuiltInVpnDialog(
      const ui::ElementIdentifier& element_id);

  // Open up the "Add Wi-Fi" dialog. This function expects the Settings app to
  // already be open.
  ui::test::internal::InteractiveTestPrivate::MultiStep OpenAddWifiDialog(
      const ui::ElementIdentifier& element_id);

  // Completes the "Add Wi-Fi" dialog according to the properties provided by
  // the `config` parameter. This function expects the dialog to already be open
  // prior to being called.
  ui::test::internal::InteractiveTestPrivate::MultiStep CompleteAddWifiDialog(
      const ui::ElementIdentifier& element_id,
      const WifiDialogConfig& config);

  // Opens the Quick Settings bubble.
  ui::test::internal::InteractiveTestPrivate::MultiStep OpenQuickSettings();

  // Navigates to the internet page within Quick Settings. This function expects
  // the Quick Settings to already be open and on the root page.
  ui::test::internal::InteractiveTestPrivate::MultiStep
  NavigateQuickSettingsToNetworkPage();

  // Navigates to the bluetooth page within Quick Settings. This function
  // expects the Quick Settings to already be open and on the root page.
  ui::test::internal::InteractiveTestPrivate::MultiStep
  NavigateQuickSettingsToHotspotPage();

  // Navigates to the bluetooth page within Quick Settings. This function
  // expects the Quick Settings to already be open and on the root page.
  ui::test::internal::InteractiveTestPrivate::MultiStep
  NavigateQuickSettingsToBluetoothPage();

  // Returns the active user profile.
  Profile* GetActiveUserProfile();

  // Convenience method to create a new browser window at `url` for the active
  // user profile. Returns the `NavigationHandle` for the started navigation,
  // which might be null if the navigation couldn't be started. Tests requiring
  // more complex browser setup should use `Navigate()` from
  // browser_navigator.h.
  base::WeakPtr<content::NavigationHandle> CreateBrowserWindow(const GURL& url);

  // MixinBasedInProcessBrowserTest:
  void TearDownOnMainThread() override;

  // Blocks until a window exists with the given title. If a matching window
  // already exists the test will resume immediately.
  ui::test::internal::InteractiveTestPrivate::MultiStep WaitForWindowWithTitle(
      aura::Env* env,
      std::u16string title);

  // Waits for an element identified by `query` to exist in the DOM of an
  // instrumented WebUI identified by `element_id`.
  ui::test::internal::InteractiveTestPrivate::MultiStep WaitForElementExists(
      const ui::ElementIdentifier& element_id,
      const WebContentsInteractionTestUtil::DeepQuery& query);

  // Waits for an element identified by `query` to not exist in the DOM of an
  // instrumented WebUI identified by `element_id`.
  ui::test::internal::InteractiveTestPrivate::MultiStep
  WaitForElementDoesNotExist(
      const ui::ElementIdentifier& element_id,
      const WebContentsInteractionTestUtil::DeepQuery& query);

  // Waits for an element identified by `query` to both exist in the DOM of an
  // instrumented WebUI identified by `element_id` and be enabled.
  InteractiveTestApi::MultiStep WaitForElementEnabled(
      const ui::ElementIdentifier& element_id,
      WebContentsInteractionTestUtil::DeepQuery query);

  // Waits for an element identified by `query` to both exist in the DOM of an
  // instrumented WebUI identified by `element_id` and have a particular value
  // for a boolean property within its managed properties. Managed properties
  // are used to communicate the state of networks to the UI.
  ui::test::internal::InteractiveTestPrivate::MultiStep
  WaitForElementWithManagedPropertyBoolean(
      const ui::ElementIdentifier& element_id,
      const WebContentsInteractionTestUtil::DeepQuery& query,
      const std::string& property,
      bool expected_value);

  // Waits for an element identified by `query` to both exist in the DOM of an
  // instrumented WebUI identified by `element_id` and be disabled.
  InteractiveTestApi::MultiStep WaitForElementDisabled(
      const ui::ElementIdentifier& element_id,
      WebContentsInteractionTestUtil::DeepQuery query);

  // Waits for an element identified by `query` to both exist in the DOM of an
  // instrumented WebUI identified by `element_id` and be checked.
  InteractiveTestApi::MultiStep WaitForElementChecked(
      const ui::ElementIdentifier& element_id,
      WebContentsInteractionTestUtil::DeepQuery query);

  // Waits for an element identified by `query` to both exist in the DOM of an
  // instrumented WebUI identified by `element_id` and be unchecked.
  InteractiveTestApi::MultiStep WaitForElementUnchecked(
      const ui::ElementIdentifier& element_id,
      WebContentsInteractionTestUtil::DeepQuery query);

  // Waits for an element identified by `query` to both exist in the DOM of an
  // instrumented WebUI identified by `element_id` and be expanded.
  InteractiveTestApi::MultiStep WaitForElementExpanded(
      const ui::ElementIdentifier& element_id,
      WebContentsInteractionTestUtil::DeepQuery query);

  // Waits for an element identified by `query` to both exist in the DOM of an
  // instrumented WebUI identified by `element_id` and be opened.
  InteractiveTestApi::MultiStep WaitForElementOpened(
      const ui::ElementIdentifier& element_id,
      WebContentsInteractionTestUtil::DeepQuery query);

  // Waits for an element identified by `query` to both exist in the DOM of an
  // instrumented WebUI identified by `element_id` and be unopened.
  InteractiveTestApi::MultiStep WaitForElementUnopened(
      const ui::ElementIdentifier& element_id,
      WebContentsInteractionTestUtil::DeepQuery query);

  // Waits for an element identified by `query` to exist in the DOM of an
  // instrumented WebUI identified by `element_id` and be focused.
  ui::test::internal::InteractiveTestPrivate::MultiStep WaitForElementFocused(
      const ui::ElementIdentifier& element_id,
      const WebContentsInteractionTestUtil::DeepQuery& query);

  // Waits for an element identified by `query` to both exist in the DOM of an
  // instrumented WebUI identified by `element_id` and have its text, or the
  // text of any of its children, match `expected`.
  ui::test::internal::InteractiveTestPrivate::MultiStep
  WaitForElementTextContains(
      const ui::ElementIdentifier& element_id,
      const WebContentsInteractionTestUtil::DeepQuery& query,
      const std::string& expected);

  // This function is similar to `WaitForElementTextContains()` except it
  // supports non-unique elements. For more info see
  // `FindElementAndDoActionOnChildren()`.
  ui::test::internal::InteractiveTestPrivate::MultiStep
  WaitForAnyElementTextContains(
      const ui::ElementIdentifier& element_id,
      const WebContentsInteractionTestUtil::DeepQuery& root,
      const WebContentsInteractionTestUtil::DeepQuery& selectors,
      const std::string& expected);

  // This function is similar to `WaitForAnyElementTextContains()`
  // it also checks that any sibling of the element contains a certain text
  // `sibling_text`.
  ui::test::internal::InteractiveTestPrivate::MultiStep
  WaitForAnyElementAndSiblingTextContains(
      const ui::ElementIdentifier& element_id,
      const WebContentsInteractionTestUtil::DeepQuery& root,
      const WebContentsInteractionTestUtil::DeepQuery& selectors,
      const WebContentsInteractionTestUtil::DeepQuery& element_with_text,
      const std::string& expected_text,
      const WebContentsInteractionTestUtil::DeepQuery& sibling_element,
      const std::string& sibling_expected_text);

  // Waits for an element identified by `query` to both exist in the DOM of an
  // instrumented WebUI identified by `element_id` and have attribute
  // `attribute`.
  InteractiveTestApi::MultiStep WaitForElementHasAttribute(
      const ui::ElementIdentifier& element_id,
      WebContentsInteractionTestUtil::DeepQuery element,
      const std::string& attribute);

  // Waits for an element identified by `query` to both exist in the DOM of an
  // instrumented WebUI identified by `element_id` and not have attribute
  // `attribute`.
  InteractiveTestApi::MultiStep WaitForElementDoesNotHaveAttribute(
      const ui::ElementIdentifier& element_id,
      WebContentsInteractionTestUtil::DeepQuery element,
      const std::string& attribute);

  // Waits for an element identified by `query` to both exist in the DOM of an
  // instrumented WebUI identified by `element_id` and have a display style of
  // `none`, indicating that the element is not visible.
  InteractiveTestApi::MultiStep WaitForElementDisplayNone(
      const ui::ElementIdentifier& element_id,
      WebContentsInteractionTestUtil::DeepQuery element);

  // Waits for an element identified by `query` to both exist in the DOM of an
  // instrumented WebUI identified by `element_id` and not to have a display
  // style of `none`, indicating that the element is visible.
  InteractiveTestApi::MultiStep WaitForElementDisplayNotNone(
      const ui::ElementIdentifier& element_id,
      WebContentsInteractionTestUtil::DeepQuery element);

  // Waits for a toggle element identified by `query` to both exist in the DOM
  // of an instrumented WebUI identified by `element_id` and to be toggled .
  ui::test::internal::InteractiveTestPrivate::MultiStep WaitForToggleState(
      const ui::ElementIdentifier& element_id,
      const WebContentsInteractionTestUtil::DeepQuery& query,
      bool is_checked);

  // Clears the text value of an input element identified by `query` in
  // the DOM of an instrumented WebUI identified by `element_id` .
  ui::test::internal::InteractiveTestPrivate::MultiStep ClearInputFieldValue(
      const ui::ElementIdentifier& element_id,
      const WebContentsInteractionTestUtil::DeepQuery& query);

  // Waits for an element to render by using `getBoundingClientRect()` to verify
  // the element is visible and ready for interactions. Helps to prevent
  // `element_bounds.IsEmpty()` flakes.
  ui::test::internal::InteractiveTestPrivate::MultiStep WaitForElementToRender(
      const ui::ElementIdentifier& element_id,
      const WebContentsInteractionTestUtil::DeepQuery& query);

  // Clicks on an element in the DOM. `element_id` is the identifier
  // of the WebContents to query. `query` is a
  // WebContentsInteractionTestUtil::DeepQuery path to the element to start
  // with, it can be {} to query the entire page.
  ui::test::internal::InteractiveTestPrivate::MultiStep ClickElement(
      const ui::ElementIdentifier& element_id,
      const WebContentsInteractionTestUtil::DeepQuery& query);

  // This function is similar to `ClickElement()` except it supports non-unique
  // elements. For more info see `FindElementAndDoActionOnChildren()`.
  ui::test::internal::InteractiveTestPrivate::MultiStep
  ClickAnyElementTextContains(
      const ui::ElementIdentifier& element_id,
      const WebContentsInteractionTestUtil::DeepQuery& root,
      const WebContentsInteractionTestUtil::DeepQuery& selectors,
      const std::string& expected);

  // Waits for an element identified by `query` to exist in the DOM of an
  // instrumented WebUI identified by `element_id`. This function expects the
  // element to be a drop-down and will directly update the selected option
  // index to match the first option matching `option`.
  ui::test::internal::InteractiveTestPrivate::MultiStep
  SelectDropdownElementOption(
      const ui::ElementIdentifier& element_id,
      const WebContentsInteractionTestUtil::DeepQuery& query,
      const std::string& option);

  // Sends an instrumented WebUI identified by `element_id` the key presses
  // needed to input the provided text `text`. This function can handle ASCII
  // letters, numbers, the newline character, and a subset of symbols.
  // TODO(crbug.com/40286410) have a more supported way to do this and remove
  // this function.
  ui::test::internal::InteractiveTestPrivate::MultiStep SendTextAsKeyEvents(
      const ui::ElementIdentifier& element_id,
      const std::string& text);

  // Waits for an element identified by `query` to exist in the DOM of an
  // instrumented WebUI identified by `element_id`, which is expected to be a
  // text input field, clears the existing input, clicks the element, and sends
  // the key events needed to type `text`.
  ui::test::internal::InteractiveTestPrivate::MultiStep ClearInputAndEnterText(
      const ui::ElementIdentifier& element_id,
      const WebContentsInteractionTestUtil::DeepQuery& query,
      const std::string& text);

  // Waits for an element identified by `root` to exist in the DOM of an
  // instrumented WebUI identified by `element_id`. When found, this function
  // will search for its children elements by `selectors` and will execute
  // `action` on each element until `action` returns a truthy value.
  ui::test::internal::InteractiveTestPrivate::MultiStep
  FindElementAndDoActionOnChildren(
      const ui::ElementIdentifier& element_id,
      const WebContentsInteractionTestUtil::DeepQuery& root,
      const WebContentsInteractionTestUtil::DeepQuery& selectors,
      const std::string& action);

 private:
  // Helper function that navigates to a top-level page of the Settings app.
  // This function expects the Settings app to already be open. The `path`
  // parameter should correspond to a top-level menu item.
  ui::test::internal::InteractiveTestPrivate::MultiStep NavigateSettingsToPage(
      const ui::ElementIdentifier& element_id,
      const char* path);

  // Helper function that navigates to a detailed page within Quick Settings.
  // This function expects the Quick Settings to already be open and on the root
  // page. The `element_id` parameter should be the drill-in arrow for the
  // desired detailed page.
  ui::test::internal::InteractiveTestPrivate::MultiStep
  NavigateQuickSettingsToPage(const ui::ElementIdentifier& element_id);

  // Returns the JS code that searches for an element selected by
  // `element_with_text` that contains the expected text, and when found will
  // click on the sibling element selected by `element_to_click`.
  const std::string ClickElementWithSiblingContainsText(
      const WebContentsInteractionTestUtil::DeepQuery& element_with_text,
      const std::string& expected,
      const WebContentsInteractionTestUtil::DeepQuery& element_to_click);

  // Returns the JS code that searches for an element selected by
  // `element_with_text` that contains the `expected_text`, and when found will
  // check that a `sibling_element` contains text `sibling_expected_text`.
  const std::string FindMatchingTextsInElementAndSibling(
      const WebContentsInteractionTestUtil::DeepQuery& element_with_text,
      const std::string& expected_text,
      const WebContentsInteractionTestUtil::DeepQuery& sibling_element,
      const std::string& sibling_expected_text);
};

#endif  // CHROME_TEST_BASE_ASH_INTERACTIVE_INTERACTIVE_ASH_TEST_H_