Mobile Application Plugin
The plugin provides functionality to test mobile application on real devices, Android Emulators and iOS Simulators.
Installation
-
Copy the below line to
dependencies
section of the projectbuild.gradle
fileExample 1. build.gradleimplementation(group: 'org.vividus', name: 'vividus-plugin-mobile-app', version: '0.5.4')
-
If the project was imported to the IDE before adding new plugin, re-generate the configuration files for the used IDE and then refresh the project in the used IDE.
Locator
By.<locatorType>(<locatorValue>):<visibility>->filter.<filterType>(<filterValue>)
By. prefix is optional. |
-
locatorType
- [mandatory] type of the locator -
locatorValue
- [mandatory] value of the locator -
visibility
- [optional] visibility of element (visible by default) -
filterType
- [optional] type of the filter -
filterValue
- [required if filter type defined] value of the filter
Reusable locators
Feature allows to define custom reusable locator types via properties. These new locator types should rely on one of the already existing ones.
ui.locator.<locatorName>.pattern
ui.locator.<locatorName>.locator-type
-
locatorName
- The name of the reusable locator. Supported characters areA-Z, a-z, -
. -
pattern
- The pattern of the reusable locator. -
locator-type
- The base locator type.
ui.locator.anyAttOrText.locator-type=xpath
ui.locator.anyAttOrText.pattern=//*[@*='%s' or text()='%s']
Given I am on main application page
Then number of elements found by `anyAttOrText(attribute, text)` is = `1`
Given I am on main application page
Then number of elements found by `anyAttOrText(attribute, with comma\, text)` is = `1`
Description | Pattern | Usage | Result |
---|---|---|---|
Single parameter doesn’t require comma escaping. |
|
|
|
The pattern with a single parameter was referenced twice. |
|
|
|
The pattern with a |
|
|
|
The pattern containing |
|
|
|
The pattern without parameters |
|
|
|
The pattern with two parameter placeholders was used with invalid number of parameters. |
|
|
|
Filter Types
Type | Description | Examples |
---|---|---|
|
Get an element by the specified index from a collection of elements found by a locator. Indexes start from 1. |
tagName(div)→filter.index(2) |
|
Filter elements by their text parts. |
tagName(h3)→filter.textPart(Welcome) |
|
Filter elements by their exact text. |
tagName(android.widget.EditText)→filter.text(Welcome) |
|
Filter elements by their attribute values |
|
Locator Types
Type | Platform | Description | Examples |
---|---|---|---|
|
any |
Search the app XML source using xpath (not recommended, has performance issues) |
xpath(//android.widget.TextView[@text='Home']) or By.xpath(//XCUIElementTypeStaticText[@value='Home']) |
|
any |
See Accessibility ID selector strategy |
accessibilityId(menu-toggler) or By.accessibilityId(menu-toggler) |
|
any |
See ID selector strategy |
id(org.vividus:id/menu-toggler) or By.id(menu-toggler) |
|
|
See Class Chain Queries for more details |
iosClassChain(**/XCUIElementTypeCell[$name BEGINSWITH "A"$]) or By.iosClassChain(**/XCUIElementTypeCell[$name BEGINSWITH "B"$]) |
|
|
See iOS Predicate Syntax for more details |
iosNsPredicate(name BEGINSWITH 'A') or By.iosNsPredicate(name BEGINSWITH 'B') |
Properties
The properties marked with bold are mandatory. |
Property Name | Acceptable values | Default | Description | ||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
|
|
|
The test lifecycle of the mobile application:
An empty property value will lead to the error: "Application session scope is not set". |
||||||||
|
|
|
Whether to publish the application source code on failure or not |
||||||||
|
|
|
If the value is set to |
||||||||
|
hostname |
|
Remote grid host to be used to create a new session |
||||||||
|
username |
|
Remote grid username to be used to create a new session |
||||||||
|
password |
|
Password to be used to create a new session |
||||||||
|
ISO-8601 Durations format |
|
Total duration to wait for UI condition |
||||||||
|
ISO-8601 Durations format |
|
Used together with |
||||||||
|
The value between 0 and 1 e.g. 0.75 |
|
Enables compressions of the images published to the report using the specified compression quality. If 1 is set then no compression will be performed. It may help to decrease total report size. |
||||||||
|
|
Depends on the set profile |
Defines the mobile OS to use |
||||||||
|
|
Depends on the set profile |
Defines automation engine to use
|
||||||||
|
|
Depends on the set profile |
Defines whether the tests run on real device
|
||||||||
|
|
Depends on the set profile |
Defines a destination folder on a device for a file being uploaded
|
||||||||
|
|
|
Enable proxy for the whole test run |
||||||||
|
|
|
Enable proxy recording |
||||||||
|
any host name resolving on the machine |
|
Overrides the host which will be used by proxy |
||||||||
|
ports range (e.g., |
|
Ports range which could be occupied for proxy |
||||||||
|
|
|
Overrides the proxy host which will be passed to browser |
||||||||
|
|
|
Enables publishing of attachments with HAR to each failed step. |
||||||||
|
|
|
Whether to disable verification of upstream servers SSL certificates |
||||||||
|
HAR capture types: |
|
List of HAR capture types |
||||||||
|
|
|
Whether to enable MITM proxy for the whole test run |
||||||||
|
|
|
The MITM type using the corresponding certificates. |
||||||||
|
keystore type |
|
The keystore type |
||||||||
|
path to keystore |
|
The relative to |
||||||||
|
password for keystore |
|
The password for keystore |
||||||||
|
keystore alias |
|
The alias for certificate entry in keystore |
Meta Tags
@proxy
- some steps require proxy to be turned on: it can be done by setting the corresponding properties or by switching on this meta tag at story level.
For device configuration, we need to perform the following steps: install CA certificate(download CA certificate from a browserup repository), configure device proxy, and configure the test app to allow proxy in cases of necessity. |
Profiles
iOS
The profile can be enabled by adding mobile_app/ios
to configuration.profiles
property
Default profile configuration
selenium.grid.platform-name=iOS
selenium.grid.automation-name=XCUITest
tvOS
The profile can be enabled by adding mobile_app/tvos
to configuration.profiles
property
Default profile configuration
selenium.grid.platform-name=tvOS
selenium.grid.automation-name=XCUITest
Android
The profile can be enabled by adding mobile_app/android
to configuration.profiles
property
Default profile configuration
selenium.grid.platform-name=Android
selenium.grid.automation-name=UIAutomator2
Local
The local profiles can be used in conjunction with:
-
mobile_app/android
, -
mobile_app/ios
, -
mobile_app/tvos
.
mobile_app/local
The profile simplifies configuration of tests execution against the local Appium 1.x server.
configuration.profiles=mobile_app/local,mobile_app/ios
mobile_app/local2
The profile simplifies configuration of tests execution against the local Appium 2.x server.
configuration.profiles=mobile_app/local2,mobile_app/android
Dynamic variables
Get clipboard text
Gets the text of the system clipboard of simulator or real device
Properties
Property Name | Default | Description |
---|---|---|
|
|
The property is for iOS real devices only and it specifies the WebDriverAgent bundle ID used to get clipboard text. The property value may vary depending on test cloud providers and can be found in the XCode logs. |
${clipboard-text}
Then `${clipboard-text}` is equal to `uarlouski@gmail.com`
Context element rectangle
The set of dynamic variables provides ability to access context element coordinates, width and height.
The variables rely on the contextual approach: it is necessary to switch context to the target element. |
In case of missing search context the error will be logged and -1 will be returned as a result
|
Variable name
Variable name | Description |
---|---|
|
the height of the context element |
|
the width of the context element |
|
the absolute |
|
the absolute |
When I change context to element located by `id(userpic)`
Then `${context-height}` is > `0`
Then `${context-width}` is > `0`
Then `${context-x-coordinate}` is > `0`
Then `${context-y-coordinate}` is > `0`
Steps
Start mobile application
Starts mobile application with capabilities from user’s *.properties
files and profiles set by a user.
Given I start mobile application
Start mobile application with capabilities
Starts mobile application with capabilities from user’s *.properties
files and profiles set by a user.
Additionally the step takes a list of capabilities as an argument that overrides globally-defined capabilities.
Given I start mobile application with capabilities:$capabilities
-
$capabilities
- The capabilities to start application with, these capabilities have higher priority than capabilities defined in*.properties
files and profiles.
Given I start mobile application with capabilities:
|name |value|
|bstack:options.networkLogs |true |
|appium:options.clearSystemFiles|false|
Activate mobile application
Activates the existing application on the device/emulator/simulator and moves it to the foreground. The application should be already running in order to activate it.
When I activate application with bundle identifier `$bundleId`
-
$bundleId
-Package name
for Android orBundle identifier
fromPlist.info
for iOS
When I activate application with bundle identifier `com.apple.mobilesafari`
Reinstall mobile application
Removes the mobile application from device/emulator/simulator and installs it again.
When I reinstall mobile application with bundle identifier `$bundleId`
-
$bundleId
-Package name
for Android orBundle identifier
fromPlist.info
for iOS.
The key benefit is that instead of the full remote session recreation (which includes device re-allocation in testing clouds, like SauceLabs, BrowserStack, etc.) achivable via the following example:
When I close mobile application
Given I start mobile application with capabilities:
|name |value|
|fullReset|true |
the step re-uses the current session which significantly improves performance.
When I reinstall mobile application with bundle identifier `vividus-mobile.app`
Terminate mobile application
Terminates the running application on the device/emulator/simulator and navigates to the home device screen. The remote session will not be closed.
When I terminate application with bundle identifier `$bundleId`
-
$bundleId
-Package name
for Android orBundle identifier
fromPlist.info
for iOS
When I terminate application with bundle identifier `com.apple.mobilesafari`
Close mobile application
Closes the mobile application and quits the remote session.
When I close mobile application
Run mobile application in background
Runs mobile application in the background for specific period of time and either activates the app after a certain amount of time, or leave the app deactivated (when PT-1S is used). See Appium docs for more details.
When I send mobile application to background for `$period` period
-
$period
- The period of time in ISO-8601 Durations format.
When I send mobile application to background for `PT5S` period
Then number of elements found by `accessibilityId(login-button)` is equal to `1`
Change session settings
Changes the behavior of the Appium session.
When I change Appium session settings:$settings
-
$settings
- The settings to set.
When I change Appium session settings:
|name |value|
|allowInvisibleElements|true |
Upload a file to the device
Uploads a file to the device/emulator/simulator.
When I upload file `$filePath` to device
-
$filePath
- The path of the file to upload to the device.
The destination folder on the device for the uploaded file is configured by mobile-environment.device.folder-for-file-upload property. See more information in the properties section.
|
When I upload file `images/avatar.png` to device
Then the avatar icon is displayed with the uploaded image
Upload the file with data to the device
Upload the file with data to the device/emulator/simulator.
When I upload file with name `$fileName` and data `$data` to device
-
$data
- The data to store as a file. -
$fileName
- The name of the uploaded file.
The destination folder on the device for the uploaded file is configured by mobile-environment.device.folder-for-file-upload property. See more information in the properties section.
|
When I execute HTTP GET request for resource with URL `https://raw.githubusercontent.com/vividus-framework/vividus/master/vividus-tests/src/main/resources/baselines/context.png`
When I upload file with name `context.png` and data `${response-as-bytes}` to device
Then image is displayed in gallery
When I upload file with name `message.txt` and data `This is a message` to device
Then message file is displayed in file explorer
Delete a file from the device
Deletes a file from the device/emulator/simulator.
When I delete file `$filePath` from device
Argument | Platform | Description | Examples |
---|---|---|---|
|
iOS |
The path to an existing remote file on the device. This variable can be prefixed with bundle id, so then the file will be deleted from the corresponding application container instead of the default media folder. Use |
|
Android |
The full path to the remote file or a file inside an application bundle |
|
When I delete file `/sdcard/Pictures/avatar.png` from device
On iOS real device to add or delete photo or video to/from "Camera Roll" you need upload/delete photos or videos to/from /DCIM/100APPLE/ folder and then trigger a rebuild of the "Camera Roll" database by deleting the old databases. You can accomplish it by deleting following files: /PhotoData/Photos.sqlite, /PhotoData/Photos.sqlite-shm, /PhotoData/Photos.sqlite-wal. Restart device is necessary after that. |
On iOS simulator to delete photo or video from "Camera Roll" you need to delete photo or video from /Media/DCIM/100APPLE/ and then trigger a rebuild of the "Camera Roll" database by deleting the old databases. You can accomplish it by deleting following files: /Media/PhotoData/Photos.sqlite, /Media/PhotoData/Photos.sqlite-shm, /Media/PhotoData/Photos.sqlite-wal. And then restart simulator. |
Switch to Web view by name
Switches context to a web view with name that matches the rule (see Automating hybrid apps for more information). Also, Appium capabilities for iOS and Android are available for the fine-tuning configuration.
When I switch to web view with name that $comparisonRule `$value`
-
$comparisonRule
- The web view name comparison rule. -
$value
- The value to find the target web view.
Then number of elements found by `xpath(html)` is equal to `0`
When I switch to web view with name that contains `vividustestapp`
Then number of elements found by `xpath(html)` is equal to `1`
Switch to native context
Switches context to a mobile native context. See Automating hybrid apps for more information.
When I switch to native context
Then number of elements found by `xpath(html)` is equal to `1`
When I switch to native context
Then number of elements found by `xpath(html)` is equal to `0`
Tap on element
Taps on the element located by the locator.
The atomic actions performed are:
-
press on the element;
-
release.
When I tap on element located `$locator`
When I tap on element located by `$locator`
-
$locator
- Locator.
When I tap on element located by `accessibilityId(menu-toggler)`
Tap on element with duration
Taps on the element located by the locator with the specified duration.
The atomic actions performed are:
-
press on the element;
-
wait for the duration;
-
release.
When I tap on element located `$locator` with duration `$duration`
When I tap on element located by `$locator` with duration `$duration`
-
$locator
- Locator. -
$duration
- The duration between an element is pressed and released in ISO-8601 Durations format.
When I tap on element located by `accessibilityId(menu-toggler)` with duration `PT0.5S`
Double tap on element
Performs double tap on the element located by the locator.
The step is supported for Android and iOS platforms. |
When I double tap on element located by `$locator`
-
$locator
- Locator.
When I double tap on element located by `accessibilityId(increment)`
Press key
Presses iOS keys or Android keys.
When I press $key key
-
$key
- The key to press.
When I press Home key
Long press key
Performs long press of iOS keys or Android keys.
to modify long press duration for iOS and tvOS you could use mobile-application.long-press-duration property.
|
When I long press $key key
-
$key
- The key to perform long press action.
When I long press Home key
Press keys
Presses a sequence of iOS keys or Android keys.
When I press keys:$keys
-
$keys
- The keys to press.
When I press keys:
|key|
|P |
|a |
|s |
|1 |
|$ |
Type text sequentially
Types the provided text
All the characters will be treated as is and passed sequentially. To send special key like HOME please use Press keys.
|
When I type text `$text`
-
$text
- The text to type.
When I type text `pas1$`
Type text in a field
Types the text into the element located by the locator.
The existing text is re-written by the text passed into the step. |
The atomic actions performed are:
-
type text into the element;
-
hide keyboard.
For iOS real devices the hide keyboard action works only for
XCUIElementTypeTextField elements and skipped for XCUIElementTypeTextView
elements, in case of XCUIElementTypeTextView element tap outside the text view
is performed to close the keyboard.
|
When I type `$text` in field located `$locator`
-
$text
- The text to type into the element. -
$locator
- Locator.
When I type `Bob` in field located `accessibilityId(username)`
Type text and keep keyboard opened
Only types text into the element. The keyboard hiding is skipped.
When I type `$text` in field located `$locator` and keep keyboard opened
-
$text
- The text to type into the element. -
$locator
- Locator.
When I type `Bob` in field located `accessibilityId(username)` and keep keyboard opened
Clear field
Clears the field located by the locator.
The atomic actions performed are:
-
clear the field;
-
hide keyboard.
For iOS real devices the hide keyboard action works only for
XCUIElementTypeTextField elements and skipped for XCUIElementTypeTextView
elements, in case of XCUIElementTypeTextView element tap outside the text view
is performed to close the keyboard.
|
When I clear field located `$locator`
-
$locator
- Locator.
When I clear field located `accessibilityId(username)`
Clear field and keep keyboard open
Only clears the field located by the locator. The keyboard hiding is skipped.
When I clear field located `$locator` and keep keyboard open
-
$locator
- Locator.
When I clear field located `accessibilityId(username)` and keep keyboard open
Swipe to an element
Swipes to an element in either UP
, DOWN
, LEFT
or RIGHT
direction with
the specified swipe duration.
The step takes into account the current context. If you need to perform swipe on the element, you need to switch the context to this element. |
Properties
-
mobile-application.swipe.limit
- defines max numbers of swipes to perform (if it’s reached the swipe process is stopped and the error is thrown) -
mobile-application.swipe.stabilization-duration
- defines a duration to wait after swipe until view becomes stable -
mobile-application.swipe.vertical.x-position
- defines a vertical swipex
axis position in percentage from0
to100
, where0
corresponds tox=1
and100
corresponds tox = mobile screen width - 1
, default value is0
-
mobile-application.swipe.horizontal.y-position
- defines a horizontal swipey
axis position in percentage from0
to100
, where0
corresponds toy=1
and100
corresponds toy = mobile screen height - 1
, default value is50
When I swipe $direction to element located `$locator` with duration $swipeDuration
When I swipe $direction to element located by `$locator` with duration $swipeDuration
-
$direction
- The direction to swipe:UP
,DOWN
,LEFT
orRIGHT
. -
$locator
- Locator. -
$swipeDuration
- The swipe duration in ISO-8601 Durations format.
Then number of elements found by `accessibilityId(end-of-screen)` is equal to `0`
When I swipe UP to element located by `accessibilityId(end-of-screen)` with duration PT1S
Then number of elements found by `accessibilityId(end-of-screen)` is equal to `1`
Scenario: Switch slides
When I change context to element located by `accessibilityId(carousel)`
Then number of elements found by `accessibilityId(slide 2)` is equal to `0`
When I swipe LEFT to element located `accessibilityId(slide 2)` with duration PT1S
Then number of elements found by `accessibilityId(slide 2)` is equal to `1`
Execute sequence of touch actions
Executes the sequence of touch actions.
When I execute sequence of touch actions: $actions
-
$actions
- The table with actions to execute.Table 1. Possible actions type
argument
Argument example TAP
Element locator or empty
By.id(Name)
TAP_AND_HOLD
Element locator or empty
By.id(Name)
MOVE_TO
Element locator
By.id(username)
MOVE_BY_OFFSET
Point, that specifies x and y distance to move from its current position or from upper left corner (0,0), if the pointer has not previously been moved
(10, 15) where x is 10 and y is 15
RELEASE
empty
WAIT
Duration
PT1S - wait 1 second
RELEASE action releases the finger at the current touch location. For example, it can be used in the following
sequence of actions:`TAP_AND_HOLD` → MOVE_BY_OFFSET → RELEASE
|
When I execute sequence of touch actions:
|type |argument |
|TAP_AND_HOLD |By.id(Hello World)|
|MOVE_BY_OFFSET|(0,200) |
|RELEASE | |
Zoom in/out
Performs zoom in/out
The step takes into account the current context. If you need to perform zoom on the element, you need to switch the context to this element. |
Properties
Property Name | Acceptable values | Default value | Description |
---|---|---|---|
|
size in percentage |
|
The size of the top part of the context to be excluded from zoom area |
|
size in percentage |
|
The size of the bottom part of the context to be excluded from zoom area |
|
size in percentage |
|
The size of the right part of the context to be excluded from zoom area |
|
size in percentage |
|
The size of the left part of the context to be excluded from zoom area |
The indent percentage value should be from The sum of The sum of |
mobile-application.zoom.indent.top=30
mobile-application.zoom.indent.bottom=30
mobile-application.zoom.indent.right=20
mobile-application.zoom.indent.left=20
Step
When I zoom $zoomType context
-
$zoomType
- The type of zoom:IN
orOUT
When I zoom in context
When I wait until element located by `xpath(<welcomeMessageXpath>)` disappears
When I zoom out context
When I wait until element located by `xpath(<welcomeMessageXpath>)` appears
Select date in date picker
Selects a next or previous picker wheel value in date picker
-
Only
iOS
platform is supported. -
The target element must be of type
XCUIElementTypePickerWheel
.
When I select $direction value with `$offset` offset in picker wheel located `$locator`
-
$direction
- The direction to search the value:NEXT
orPREVIOUS
. -
$offset
- The ofset to pick from a middle of the wheel, see Select Picker Wheel Value guide. -
$locator
- The locator to findXCUIElementTypePickerWheel
element.
When I select next value with `0.1` offset in picker wheel located `xpath(//XCUIElementTypePickerWheel)->filter.index(3)`
Recording iOS Performance metrics
Records performance metrics of iOS application. It is based on the Instruments utility distributed by Xcode which provides a number of built-in analyses and measurements. See Capturing Performance Data for Native iOS Apps and Getting Started with Instruments for more information.
Appium server should be started with the --relaxed-security flag. This is because Instruments can gather data from the system as a whole, not just the AUT. (It’s thus a security risk to expose potentially sensitive system information to Appium sessions running from a remote client). |
Archive with results contains *.trace file which could be opened by XCode. There is possibility to parse this file using XCode’s utility xctrace and use generated data in tests |
When I start recording `$instrument` metrics
When I stop recording `$instrument` metrics and save results to file `$path`
-
$instrument
- The instrument of Xcode Instruments utility. Some useful instruments: Time Profiler, Leaks, File Activity, etc. -
$path
- The path to the file to save an archive with collected data.
When I start recording `Time Profiler` metrics
!-- set of actions to measure performance
When I stop recording `Time Profiler` metrics and save results to file `${outputDirectory}/time_profiler.zip`
Set slider value
iOS
Sets the slider value in percents.
-
The accuracy of setting the slider value is not guaranteed and may vary depending on the device screen resolution.
-
The target element must be of type
XCUIElementTypeSlider
. -
The percent number must be between 0 and 100 inclusively.
When I set value of iOS slider located `$locator` to `$percent` percents
-
$locator
- The locator to findXCUIElementTypeSlider
element. -
$percent
- The target value of the slider in percents.
When I set value of iOS slider located `xpath(//XCUIElementTypeSlider)` to `90` percents
When I set value of iOS slider located `xpath(//XCUIElementTypeSlider)` to `70` percents
When I set value of iOS slider located `xpath(//XCUIElementTypeSlider)` to `80` percents
Android
Sets the slider value to the number relatively to the slider leftmost side of its range.
-
The step is expected to set accurate value without deviations.
-
The target element must be of type
android.widget.SeekBar
. -
The number must be greater than or equal to 0.
-
Make sure the passed number does not exceed the right limit of the slider, this may lead to unexpected failure.
When I set value of Android slider located `$locator` to `$number`
-
$locator
- The locator to findandroid.widget.SeekBar
element. -
$number
- The number to set on the slider
When I set value of Android slider located `xpath(//android.widget.SeekBar)` to `13`
When I set value of Android slider located `xpath(//android.widget.SeekBar)` to `25`
When I set value of Android slider located `xpath(//android.widget.SeekBar)` to `2`
Wait for element appearance
Waits for appearance of the element by the locator.
It’s forbidden to use Visibility types in the locator. |
When I wait until element by located `$locator` appears
Deprecated syntax (will be removed in VIVIDUS 0.6.0):
When I wait until element located `$locator` appears
-
$locator
- Locator.
When I wait until element located by `name(welcome-image)` appears
Wait for element disappearance
Waits for disappearance of the element by the locator.
If the element doesn’t exist on the page/context, the step will immediately complete successfully. Checking the element on the page (if needed) should be done in a separate step (e.g. Wait for element appearance or Validate elements). |
It’s forbidden to use Visibility types in the locator. |
When I wait until element located by `$locator` disappears
Deprecated syntax (will be removed in VIVIDUS 0.6.0):
When I wait until element located `$locator` disappears
-
$locator
- Locator.
When I wait until element located by `name(welcome-image)` disappears
Wait for expected elements number
Waits for the expected number of elements located by locator.
In order to wait for invisible elements one rely on Visibility types. |
When I wait until number of elements located by `$locator` is $comparisonRule $number
-
$locator
- Locator. -
$comparisonRule
- The comparison rule. -
$number
- The expected number of the elements.
When I wait until number of elements located by `tagName(img)` is equal to `5`
When I wait until number of elements located by `tagName(img):1` is equal to `5`
Verify elements number
Verifies if the number of elements located by locator matches the desired number.
Then number of elements found by `$locator` is $comparisonRule `$quantity`
-
$locator
- Locator. -
$comparisonRule
- The comparison rule. -
$quantity
- The expected number of the elements.
Then number of elements found by `tagName(img)` is equal to `5`
Verify elements state
Verifies if the number of elements located by locator matches the number condition and all of them are in the desired state.
If you describe number condition as equal to 5 in case if there are 10 elements by this locator and only 5 of them in the desired state. You will get two failed assertions. The first one about number condition violation. The second one about state check failure. |
In case when Visibility types are used and checked state are equal (For an example ':i' and 'NOT_VISIBLE') exception will be thrown. In such cases please use step: Verify elements number. Contradictory visibility parameters (locator - ':i' and checked state - 'VISIBLE') are also not allowed. |
Then number of $state elements found by `$locator` is $comparisonRule `$quantity`
-
$state
- State -
$locator
- Locator. -
$comparisonRule
- The comparison rule. -
$quantity
- The expected number of elements.
Then number of VISIBLE elements found by `tagName(img)` is = `1`
Save the text of the context
Saves the text of the context element into a variable.
Step will throw an error if the context element is not set. |
When I save text of context element to $scopes variable `$variableName`
-
$variableName
- The name of the variable to save the text.
When I change context to element located by `id(username)`
When I save text of context element to SCENARIO variable `username`
Saves the attribute value of the context
Saves the attribute value of the context element into a variable.
Step will throw an error if the context element is not set. |
When I save `$attributeName` attribute value of context element to $scopes variable `$variableName`
-
$attributeName
- The name of an element attribute. -
$variableName
- The name of the variable to save the attribute value.
When I change context to element located by `id(username)`
When I save `innerText` attribute value of context element to SCENARIO variable `username`
Save the attribute value of the element
Saves the attribute value of the element located by locator into a variable.
When I save `$attributeName` attribute value of element located `$locator` to $scopes variable `$variableName`
-
$attributeName
- The name of an element attribute. -
$locator
- Locator. -
$variableName
- The name of the variable to save the attribute value.
Save the attribute value of the element
When I save `innerText` attribute value of element located `By.id(username)` to SCENARIO variable `username`
Save number of elements
Saves number of elements located by locator into a variable.
When I save number of elements located `$locator` to $scopes variable `$variableName`
-
$locator
- Locator. -
$variableName
- The name of the variable to save the number of elements.
When I save number of elements located `tagName(a)` to scenario variable `numberOfLinks`
Then `${numberOfLinks}` is equal to `1`
Change context
Changes the context to an element located by locator for limiting area of subsequent UI interactions.
When I change context to element located by `$locator` in scope of current context
Deprecated syntax (will be removed in VIVIDUS 0.7.0):
When I change context to element located `$locator` in scope of current context
-
$locator
- Locator.
Then number of elements found by `By.xpath(html)` is equal to `1`
When I change context to element located by `xpath(//body)` in scope of current context
Then number of elements found by `By.xpath(html)` is equal to `0`
Reset and change context
Resets current context and changes the context to an element located by locator for limiting area of subsequent UI interactions.
When I change context to element located by `$locator`
Deprecated syntax (will be removed in VIVIDUS 0.7.0):
When I change context to element located `$locator`
-
$locator
- Locator.
Then number of elements found by `By.xpath(html)` is equal to `1`
When I change context to element located by `xpath(//body)`
Then number of elements found by `By.xpath(html)` is equal to `0`
Reset context
Resets the context.
When I reset context
Then number of elements found by `By.xpath(html)` is equal to `1`
When I change context to element located by `xpath(//body)`
Then number of elements found by `By.xpath(html)` is equal to `0`
When I reset context
Then number of elements found by `By.xpath(html)` is equal to `1`
Element existence during the time period
Validates the element located by the locator has existed for the period specified by the duration.
The actions performed by the step:
-
check the search context is set,
-
search for the element to validate existence (this search may include wait for element appearance if it’s configured),
-
validate the element has presented for the period specified by the duration.
Then element located by `$locator` exists for `$duration` duration
Deprecated syntax (will be removed in VIVIDUS 0.6.0):
Then element located `$locator` exists for `$duration` duration
-
$locator
- The Locator to find an element. -
$duration
- The period of time the element should have existed in ISO-8601 Durations format.
Then element located by `id(banner)` exists for `PT5S` duration
Navigate back
Navigates back to the previous view.
When I navigate back
Then number of elements found by `xpath(//*[@*='Welcome'])` is equal to `1`
When I navigate back
Then number of elements found by `xpath(//*[@*='Welcome'])` is equal to `0`
Verify elements order
Gets a collection of elements by locator and checks that they are sorted by their text in the specified order. The collection should have more than 1 element with not empty text, otherwise the step fails.
Then elements located $locator are sorted by text in $sortingOrder order
Then elements located by $locator are sorted by text in $sortingOrder order
-
$locator
- Locator. -
$sortingOrder
Plain | Readable | Description |
---|---|---|
ASCENDING |
ascending |
Verify that elements are sorted in ascending order |
DESCENDING |
descending |
Verify that elements are sorted in descending order |
CASE_INSENSITIVE_ASCENDING |
case-insensitive ascending |
Verify that elements are sorted in case-insensitive ascending order |
CASE_INSENSITIVE_DESCENDING |
case-insensitive descending |
Verify that elements are sorted in case-insensitive descending order |
Given I am on page with URL `https://grocery.by`
When I click on element located by `id(a-z)`
Then elements located by `xpath(//span[@id='item-to-purchase'])` are sorted by text in ascending order
Take a screenshot and save it to the folder
Takes a screenshot and saves it to the default folder defined by user.
The full path to a screenshot will be posted to logs and allure |
When I take screenshot and save it to folder `$path`
-
$path
- The absolute or relative path to the folder to save taken screenshot.
When I take screenshot and save it to folder `${screenshot-directory}/#{generate(Ancient.god)}.png`
Scan barcode
Scan a barcode and save its value to the variable with the specified name. Only the first founded barcode will be scanned.
Supported Code Formats
1D product | 1D industrial | 2D |
---|---|---|
|
|
|
Actions performed at this step:
-
Takes a viewport screenshot
-
Scans a barcode from the screenshot and save its value to the variable
When I scan barcode from screen and save result to $scopes variable `$variableName`
-
$variableName
- The name of the variable to save the value of the barcode.
When I scan barcode from screen and save result to scenario variable `qrCodeLink`
Then `${qrCodeLink}` is equal to `https://www.example.com`
Perform steps while elements exist
Executes the steps while the found elements exist.
To avoid infinite loops the iterationLimit parameter is used. If iteration’s limit reached the step will fail. |
When I find $comparisonRule `$number` elements `$locator` and while they exist do up to $iterationLimit iteration of$stepsToExecute
Alias:
When I find $comparisonRule '$number' elements $locator and while they exist do up to $iterationLimit iteration of$stepsToExecute
-
$comparisonRule
- The comparison rule. -
$number
- The number of elements to find. -
$locator
- Locator. -
$iterationLimit
- The maximum number of iterations to perform. -
$stepsToExecute
- The ExamplesTable with a single column containing the steps to execute.
When I find >= `0` elements `xpath(//*[@class='menu enabled'])` and while they exist do up to 10 iteration of
|step |
|When I click on element located by `id(disable)`|
Execute JavaScript with arguments
Executes JavaScript via JavascriptExecutor. Step executes the script either without any arguments or with String
or Object
argument types.
When I execute javascript `$script` with arguments:$arguments
-
$script
- The JavaScript code to execute. -
$arguments
- The examples table with set of arguments and their type:-
value
- The value of the argument. -
type
- The type of the argument. Eitherstring
orobject
.
-
When I execute javascript `document.querySelector('#assistant').remove()` with arguments:
When I execute javascript `sauce:inject-image` with arguments:
|value |type |
|iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=|string|
When I execute javascript `sauce:throttleCPU` with arguments:
|value |type |
|{"rate" : 4}|object|
Execute JavaScript and save result.
Executes JavaScript code and saves result into variable.
When I execute javascript `$jsCode` and save result to $scopes variable `$variableName`
-
$jsCode
- Any JavaScript code. In order to save a result return statement should be used. -
$variableName
- The variable name to script execution result.
Given I am on page with URL `https://vividus-test-site.onrender.com/`
When I execute javascript `return JSON.stringify(window.performance.timing)` and save result to scenario variable `timings`
Then number of JSON elements from `${timings}` by JSON path `$.connectStart` is = 1
Scan barcode from context
Scan a barcode from the specified context and save its value to the variable with the specified name. If context not set - takes a screenshot of the current screen. Only the first found barcode will be scanned.
Supported Code Formats
1D product | 1D industrial | 2D |
---|---|---|
|
|
|
Actions performed at this step:
-
Takes a screenshot of the specified context. If it’s not set - takes a screenshot of the current screen (viewport and system bars)
-
Scans a barcode from the screenshot and save its value to the variable
When I scan barcode from context and save result to $scopes variable `$variableName`
-
$variableName
- The name of the variable to save the value of the barcode.
When I change context to element located by `xpath(//android.view.ViewGroup[@resource-id='qrContainer'])`
When I scan barcode from context and save result to scenario variable `qrCodeLink`
Then `${qrCodeLink}` is equal to `https://www.example.com`
Proxy Steps
Check the number of HTTP requests
This step requires proxy to be turned on. It can be done in properties or by switching on @proxy meta tag at the story level.
The actions preformed by the step:
-
extract HTTP messages from the recorded proxy archive
-
filter out the HTTP messages with the response status code
302 Moved Temporarily
-
find HTTP requests matching the provided HTTP methods and the URL regular expression
-
check that the total number of the found HTTP messages satisfies the desired condition
In case of failure the full HTTP archive (HAR) is attached to the report.
Then number of HTTP $httpMethods requests with URL pattern `$urlPattern` is $comparisonRule `$number`
-
$httpMethods
- The comma-separated HTTP methods to filter by -
$urlPattern
- The regular expression to match HTTP request URL -
$comparisonRule
- Comparison Rule -
$number
- The number to compare with
Then number of HTTP GET, POST requests with URL pattern `http://httpbin\.org/get` is equal to `1`
Capture HTTP message
Save the HTTP message part from the HTTP request with given URL-pattern into the variable with specified name and the scopes.
This step requires proxy to be turned on. It can be done in properties or by switching on @proxy meta tag at the story level.
The actions preformed by the step:
-
extract HTTP messages from the recorded proxy archive
-
filter out the HTTP messages with the response status code
302 Moved Temporarily
-
find HTTP requests matching the provided HTTP methods and the URL regular expression
-
check that total number of the found HTTP messages is equal to
1
-
save the HTTP message part to the specified variable
In case of failure the full HTTP archive (HAR) is attached to the report.
When I capture HTTP $httpMethods request with URL pattern `$urlPattern` and save $httpMessagePart to $scopes variable `$variableName`
-
$httpMethods
- The "or"-separated set of HTTP methods to filter by, e.g.GET or POST or PUT
. -
$urlPattern
- The regular expression to match HTTP request URL. -
$httpMessagePart
- The HTTP message part to save. One of:-
URL
- The request URL. -
URL query
- The request URL query parameters. -
request data
- The request data includes the following keys:-
query
- The URL query is stored as a collection of key and value pairs, where key is the name of the query parameter and value is the list of query parameter values. The query parameter values are accessible via zero-based index. -
requestBody.mimeType
- The MIME type of posted data, the variable will not be saved if MIME type is not present. -
requestBody.text
- The posted data as plain text, the variable will not be saved if the request body is not present. -
requestBodyParameters
- The form data parameters are stored as a collection of key and value pairs, where key is the name of the form parameter and value is the list of form parameter values. The form parameter values are accessible via zero-based index. -
responseStatus
- The response status, the variable will not be saved if the response is not present.
-
-
response data
- The response data includes the following keys:-
responseBody.mimeType
- The MIME type of response data, the variable will not be saved if MIME type is not present. -
responseBody.text
- The response data as plain text, the variable will not be saved if the response body is not present.
-
-
-
$variableName
- The variable name to save the HTTP message part.
Given I start mobile application
When I capture HTTP GET or POST request with URL pattern `.*/search.*=vividus` and save URL to scenario variable `URL`
Then `${URL}` is equal to `https://www.google.com/search?q=vividus`
Given I start mobile application
When I capture HTTP GET request with URL pattern `.*/search.*=vividus` and save URL query to scenario variable `query`
Then `${query.q[0]}` is equal to `vividus`
Then `${query.q}` is equal to `[vividus]`
Then `${query}` is equal to `{q=[vividus]}`
Given I start mobile application
When I capture HTTP GET request with URL pattern `https://www.google.com/search?q=vividus` and save request data to scenario variable `data`
Then `${data.query}` is equal to `{}`
Then `${data.requestBodyParameters}` is equal to `{delivery=, custtel=, comments=, custemail=, custname=}`
Then `${data.requestBody}` is not equal to `null`
Then `${data.responseStatus}` is equal to `200`
Given I start mobile application
When I capture HTTP GET request with URL pattern `https://www.google.com/search?q=vividus` and save request data to scenario variable `data`
Then `${data.responseBody.text}` is equal to `{"status": "ok"}`
Then `${data.responseBody.mimeType}` is equal to `application/json`
Wait for the HTTP request
This step requires proxy to be turned on. It can be done in properties or by switching on @proxy meta tag at the story level. Waits for the HTTP requests matching the provided HTTP methods and URL regular expression. If no HTTP request is sent and wait timeout is reached, then the step will fail.
When I wait until HTTP $httpMethods request with URL pattern `$urlPattern` exists in proxy log
-
$httpMethods
- the "or"-separated HTTP methods to filter by, e.g. 'GET or POST or PUT' -
$urlPattern
- the regular expression to match HTTP request URL
Given I start mobile application
When I wait until HTTP GET or POST request with URL pattern `https://www.google.com/search?q=vividus` exists in proxy log
Then number of HTTP GET or POST requests with URL pattern `https://www.google.com/search?q=vividus` is equal to `1`
Add headers to the HTTP request
This step requires proxy to be turned on. It can be done in properties or by switching on @proxy meta tag at the story level. Add headers to the proxied HTTP request satisfying the desired condition
When I add headers to proxied requests with URL pattern which $comparisonRule `$url`:$headers
-
$comparisonRule
- String comparison rule -
$url
- The input value of URL to filter by -
$headers
- The ExamplesTable representing the list of the headers with columns "name" and "value" specifying HTTP header names and values respectively
When I add headers to proxied requests with URL pattern which is equal to `https://www.google.com/search?q=vividus`:
|name |value |
|testName1|testValue1|
|testName2|testValue2|
Given I start mobile application
Then a JSON element from '${response}' by the JSON path '$.headers' is equal to '
{
"Testname1": "testValue1",
"Testname2": "testValue2"
}
'ignoring extra fields
Clear the recordings
This step requires proxy to be turned on. It can be done in properties or by switching on @proxy meta tag at the story level. The step clears the HTTP requests and responses recorded by the proxy
When I clear proxy log
Given I start mobile application
When I clear proxy log
Then number of HTTP GET requests with URL pattern 'https://www.google.com/search?q=vividus' is equal to `0`
Clear the mocks
This step requires proxy to be turned on. It can be done in properties or by switching on @proxy meta tag at the story level. The step clears previously created mocks
When I clear proxy mocks
When I mock HTTP responses with request URL which CONTAINS `vividus` using response code `200`, content `#{loadResource(page.html)}` and headers:
|name |value |
|Content-Type|text/html|
When I clear proxy mocks
Given I start mobile application
Then number of elements found by `id(sw)` is = `0`
Mock the HTTP response by methods with content
This step requires proxy to be turned on. It can be done in properties or by switching on @proxy meta tag at the story level. Mocks HTTP response by methods with a provided content
No actual request will be executed. Short-circuited response will be returned. |
When I mock HTTP $httpMethods responses with request URL which $comparisonRule `$url` using response code `$responseCode`, content `$payload` and headers:$headers
-
$httpMethods
- The "or"-separated set of HTTP methods to filter by, e.g.GET or POST or PUT
. -
$rule
- String comparison rule -
$url
- The input value of URL to filter by -
$code
- The response status code -
$content
- The content to send within a response -
$headers
- The ExamplesTable representing the list of the headers with columns "name" and "value" specifying HTTP header names and values respectively
When I mock HTTP POST responses with request URL which CONTAINS `example` using response code `202`, content `#{loadResource(mocked-example.json)}` and headers:
|name |value |
|Content-Type|application/json|
Mock the HTTP response with content
This step requires proxy to be turned on. It can be done in properties or by switching on @proxy meta tag at the story level. Mocks HTTP response with a provided content
No actual request will be executed. Short-circuited response will be returned. |
When I mock HTTP responses with request URL which $comparisonRule `$url` using response code `$responseCode`, content `$payload` and headers:$headers
-
$rule
- String comparison rule -
$url
- The input value of URL to filter by -
$code
- The response status code -
$content
- The content to send within a response -
$headers
- The ExamplesTable representing the list of the headers with columns "name" and "value" specifying HTTP header names and values respectively
When I mock HTTP responses with request URL which CONTAINS `example.com` using response code `200`, content `#{loadResourceAsByteArray(page.html)}` and headers:
|name |value |
|Content-Type|text/html|
Mock the HTTP response without content
This step requires proxy to be turned on. It can be done in properties or by switching on @proxy meta tag at the story level. Mocks HTTP response
No actual request will be executed. Short-circuited response will be returned. |
When I mock HTTP responses with request URL which $comparisonRule `$url` using response code `$responseCode` and headers:$headers
-
$rule
- String comparison rule -
$url
- The input value of URL to filter by -
$code
- The response status code -
$headers
- The ExamplesTable representing the list of the headers with columns "name" and "value" specifying HTTP header names and values respectively
When I mock HTTP responses with request URL which CONTAINS `example.com` using response code `404` and headers:
|name |value|
|Content-Length|0 |
Change network connection
Turns ON/OFF network connection.
To be able to use this step in the cloud testing platform, review the documentation related to simulating the mobile network conditions on the selected platform. |
When I turn $toggle `$connectionName` network connection
-
$toggle
- The modes of the toggle:ON
orOFF
. -
$connectionName
- The name of the network connect to toggle.
Connection name | Supported platforms | Description |
---|---|---|
|
Android emulators, Android and iOS real devices |
Wi-Fi connection |
|
Android emulators, Android and iOS real devices |
Mobile Data connection |
|
Android real devices, Android emulators |
Airplane Mode |
|
Android real devices, Android emulators |
Mobile Data and Wi-Fi connections |
For iOS real devices: to return to the application you must use the step:
|
When I turn OFF `WIFI` network connection
When I turn OFF `WIFI` network connection
When I activate application with bundle identifier `my-application-bundle-id`
Change device screen orientation
Changes the device screen orientation.
When I change device screen orientation to $orientation
-
$orientation
- The device screen orientation, eitherportrait
orlandscape
.
When I change device screen orientation to portrait