Mobile Application Plugin

The plugin provides functionality to test mobile application on real devices, Android Emulators and iOS Simulators.

Installation

Example 1. build.gradle
implementation(group: 'org.vividus', name: 'vividus-plugin-mobile-app', version: '0.4.8')

Locator

By.<locatorType>(<locatorValue>):<visibility>->filter.<filterType>(<filterValue>)
By. prefix is optional.
  1. locatorType - [mandatory] type of the locator

  2. locatorValue - [mandatory] value of the locator

  3. visibility - [optional] visibility of element (visible by default)

  4. filterType - [optional] type of the filter

  5. 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.

Example 2. Properties
ui.locator.<locatorName>.pattern
ui.locator.<locatorName>.locator-type
  1. locatorName - The name of the reusable locator.

  2. pattern - The pattern of the reusable locator.

  3. locator-type - The base locator type.

Example 3. Definition of custom locator
ui.locator.anyAttOrText.locator-type=xpath
ui.locator.anyAttOrText.pattern=//*[@*='%s' or text()='%s']
Example 4. Usage of custom locator
Given I am on the main application page
Then number of elements found by `anyAttOrText(attribute, text)` is = `1`
Example 5. Usage of custom locator with comma in parameter
Given I am on the main application page
Then number of elements found by `anyAttOrText(attribute, with comma\, text)` is = `1`
Description Pattern Usage Result

The pattern with a single paramter referenced twice.

//[@='%1$s' or text()='%1$s']

customLocator(text)

//[@='text' or text()='text']

The pattern with a , in value.

//[@='%s' or text()='%s']

customLocator(te\,xt1, text2)

//[@='te,xt1' or text()='text2']

The pattern containing % character

//input[@id="username" and text()="%%%s"]

customLocator(admin)

//input[@id="username" and text()="%admin]

The pattern without parameters

//input[@id="username"]

customLocator()

//input[@id="username"]

Filter Types

Type Description Examples

index

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)

textPart

Filter elements by their text parts.

tagName(h3)→filter.textPart(Welcome)

text

Filter elements by their exact text.

tagName(android.widget.EditText)→filter.text(Welcome)

attribute

Filter elements by their attribute values

tagName(android.widget.TextView)→filter.attribute(text=Hi) - android.widget.TextView element has the text attribute with Hi value tagName(android.widget.TextView)→filter.attribute(text) - android.widget.TextView element has the text attribute with any value tagName(android.widget.TextView)→filter.attribute(text=) - android.widget.TextView element has the text attribute with an empty value

Locator Types

Type Platform Description Examples

XPath

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'])

Accessibility ID

any

See Accessibility ID selector strategy

accessibilityId(menu-toggler) or By.accessibilityId(menu-toggler)

ID

any

See ID selector strategy

id(org.vividus:id/menu-toggler) or By.id(menu-toggler)

iOS Class Chain

iOS

See Class Chain Queries for more details

iosClassChain(**/XCUIElementTypeCell[$name BEGINSWITH "A"$]) or By.iosClassChain(**/XCUIElementTypeCell[$name BEGINSWITH "B"$])

Visibility types

Visibility type Usage example Description

VISIBLE

xpath(//a)

Default visibility option. Only visible elements will be found

INVISIBLE

xpath(//a):i

Only invisible elements will be found

all

xpath(//a):a

Either visible and invisible elements will be found

Properties

The properties marked with bold are mandatory.
Property Name Acceptable values Default Description

mobile-application.session-scope

story

scenario

story

The test lifecycle of the mobile application:

  • the mobile application opens at the first step requiring mobile application interaction

  • the mobile application closes after story or scenario depending on the property value

  • each scenario-level examples table iteration is treated as a separate scenario

An empty property value will lead to the error: "Application session scope is not set".

ui.publish-source-on-failure

true false

true

Whether to publish the application source code on failure or not

ui.context.self-healing

true false

false

Incubating feature.

If the value is set to true, an attempt to reset context will be performed when it becomes stale.

selenium.grid.host

hostname

<empty>

Remote grid host to be used to create a new session

selenium.grid.username

username

<empty>

Remote grid username to be used to create a new session

selenium.grid.password

password

<empty>

Password to be used to create a new session

selenium.grid.platform-name

Android

iOS

Depends on the set profile

Defines the mobile OS to use

selenium.grid.automation-name

UIAutomator2 XCUITest

Depends on the set profile

Defines automation engine to use

Platform Recommended engine

Android

UIAutomator2

iOS

XCUITest

mobile-environment.real-device

true

false

Depends on the set profile

Defines whether the tests run on real device

Profile Value

browserstack/mobile_app

true

mobile_app/ios

false

mobile_app/android

false

mobile-environment.device.folder-for-file-upload

string

Depends on the set profile

Defines a destination folder on a device for a file being uploaded

Profile Value

mobile_app/ios

/private/var/mobile/Media/DCIM/

mobile_app/android

/sdcard/Pictures

proxy.enabled

true false

false

Enable proxy for the whole test run

proxy.host

any host name resolving on the machine

<empty>

Overrides the host which will be used by proxy

proxy.ports

ports range (e.g., 10000-10005)

<empty>

Ports range which could be occupied for proxy

proxy.connectable-host

host.docker.internal

<empty>

Overrides the proxy host which will be passed to browser

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 profile simplifies execution of tests against the local Appium server. It could be used in conjunction with: mobile_app/android, mobile_app/ios, mobile_app/tvos The profile can be enabled by adding mobile_app/local to configuration.profiles property

Default profile configuration

selenium.grid.url=http://127.0.0.1:4723/wd/hub
selenium.grid.platformName=${selenium.grid.platform-name}
selenium.grid.automationName=${selenium.grid.automation-name}

Dynamic variables

Get clipboard text

Gets the text of the system clipboard of simulator or real device

Properties

Property Name Default Description

mobile-environment.wda-bundle-id

empty

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}
Example 6. Verify clipboard content
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

context-height

the height of the context element

context-width

the width of the context element

context-x-coordinate

the absolute X coordinate of the context element

context-y-coordinate

the absolute Y coordinate of the context element

Example 7. Check the size and the location of the image
When I change context to element located `id(userpic)`
Then `${context-height}` is > `0`
Then `${context-width}` is > `0`
Then `${context-x-coordinate}` is > `0`
Then `${context-y-coordinate}` is > `0`

Source code

Variable provides source code of the UI of the application under test.

Variable name

${source-code}
Example 8. Check if element exists on UI
Then `${source-code}` matches `.+Home.+`

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 gloablly-defined capabilities.

Given I start mobile application with capabilities:$capabilities
  • $capabilities - The capabilities to start application with, these capabilies have higher priority than capabilities defined in *.properties files and profiles.

Example 9. Start mobile application with 2 custom capabilities
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 or Bundle identifier from Plist.info for iOS

Example 10. Switch to Safari browser application
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 or Bundle identifier from Plist.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.

Example 11. Reinstall mobile application
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 or Bundle identifier from Plist.info for iOS

Example 12. Terminates Safari browser application
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

Change session settings

Changes the behavior of the Appium session.

When I change Appium session settings:$settings
Example 13. Configure to show invisible elements
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.

Example 14. Upload file
When I upload file `images/avatar.png` to device
Then the avatar icon is displayed with the uploaded image

Switch to Web view by index

This step is deprecated and will be removed in VIVIDUS 0.5.0. The replacement is Switch to Web view by name.

Switches context to a web view by the index, it starts from 1 (see Automating hybrid apps for more information).

When I switch to web view with index `$index`
  • $index - The index of the web view.

Example 15. Switch to web view by index
Then number of elements found by `xpath(html)` is equal to `0`
When I switch to web view with index `1`
Then number of elements found by `xpath(html)` is equal to `1`

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`
Example 16. Switch to web view by name
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
Example 17. 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`
Example 18. Tap on element
When I tap on element located `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`
  • $locator - Locator.

  • $duration - The duration between an element is pressed and released in ISO-8601 format.

Example 19. Tap on element with duration
When I tap on element located `accessibilityId(menu-toggler)` with duration `PT0.5S`

Press key

Presses iOS keys or Android keys.

When I press $key key
  • $key - The key to press.

Example 20. Go to Home screen
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.

Example 21. Go to Home screen
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.

Example 22. Enter password
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.

Example 23. Enter password
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.

Example 24. Type text
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.

Example 25. Type text and keep keyboard opened
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`
Example 26. Clear the field
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
Example 27. Clear text and keep keyboard open
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 swipe x axis position in percentage from 0 to 100, where 0 corresponds to x=1 and 100 corresponds to x = mobile screen width - 1, default value is 0

  • mobile-application.swipe.horizontal.y-position - defines a horizontal swipe y axis position in percentage from 0 to 100, where 0 corresponds to y=1 and 100 corresponds to y = mobile screen height - 1, default value is 50

When I swipe $direction to element located `$locator` with duration $swipeDuration
  • $direction - The direction to swipe: UP, DOWN, LEFT or RIGHT.

  • $locator - Locator.

  • $swipeDuration - The swipe duration in ISO-8601 format.

Example 28. Swipe to an element
Then number of elements found by `accessibilityId(end-of-screen)` is equal to `0`
When I swipe UP to element located `accessibilityId(end-of-screen)` with duration PT1S
Then number of elements found by `accessibilityId(end-of-screen)` is equal to `1`
Example 29. Swipe the context element
Scenario: Switch slides
When I change context to element located `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`

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 or PREVIOUS.

  • $offset - The ofset to pick from a middle of the wheel, see Select Picker Wheel Value guide.

  • $locator - The locator to find XCUIElementTypePickerWheel element.

Example 30. Select next item in the picker wheel
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`
  1. $instrument - The instrument of Xcode Instruments utility. Some useful instruments: Time Profiler, Leaks, File Activity, etc.

  2. $path - The path to the file to save an archive with collected data.

Example 31. Perform profiling during application usage
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 find XCUIElementTypeSlider element.

  • $percent - The target value of the slider in percents.

Example 32. Set value of iOS slider (with range 0:50) to 45
When I set value of iOS slider located `xpath(//XCUIElementTypeSlider)` to `90` percents
Example 33. Set value of iOS slider (with range -50:50) to 20
When I set value of iOS slider located `xpath(//XCUIElementTypeSlider)` to `70` percents
Example 34. Set value of iOS slider (with range 18:65) to 55
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 find android.widget.SeekBar element.

  • $number - The number to set on the slider

Example 35. Set value of Android slider (with range 0:50) to 13
When I set value of Android slider located `xpath(//android.widget.SeekBar)` to `13`
Example 36. Set value of Android slider (with range -50:50) to -25
When I set value of Android slider located `xpath(//android.widget.SeekBar)` to `25`
Example 37. Set value of Android slider (with range 18:65) to 20
When I set value of Android slider located `xpath(//android.widget.SeekBar)` to `2`

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`
Example 38. Verify the number of 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 locator’s visibility 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`
Example 39. Verify the number of elements in the state
Then number of VISIBLE elements found by `tagName(img)` is = `1`

Wait for element appearance

Waits for appearance of an element by the locator.

When I wait until element located `$locator` appears
Example 40. Wait for element appearance
When I wait until element located `name(welcome-image)` appears

Wait for element disappearance

Waits for disappearance of an element by the locator.

When I wait until element located `$locator` disappears
Example 41. Wait for element disappearance
When I wait until element located `name(welcome-image)` disappears

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`
Example 42. Save the text of the context element
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`
Example 43. Save the attribute value of the context element
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`

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`
Example 44. Save 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 `$locator` in scope of current context
Example 45. Change context
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 `$locator`
Example 46. Change 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`

Reset context

Resets the context.

When I reset context
Example 47. 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 exists for duration

Verifies that an element located by locator exists for given duration.

Then element located `$locator` exists for `$duration` duration
Example 48. Element should exists for 5 second
Then element located `id(banner)` exists for `PT5S` duration

Navigate back

Navigates back to the previous view.

When I navigate back
Example 49. 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
  • $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

Example 50. Check items are sorted
Given I am on a page with the 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

Takes a screenshot and publish it to the report.

When I take screenshot

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.

Example 51. Take a screenshot to a path
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
  • UPC-A

  • UPC-E

  • EAN-8

  • EAN-13

  • UPC/EAN Extension 2/5

  • RSS-14

  • RSS-Expanded

  • Code 39

  • Code 93

  • Code 128

  • Codabar

  • ITF

  • QR Code

  • Data Matrix

  • Aztec

  • PDF 417

  • MaxiCode

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`
Example 52. Scan a 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.

Example 53. Disable menus
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 `id(disable)`|

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

Example 54. Check the number of HTTP GET and POST requests matching URL regurlar expression is equal to 1
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.

  • $scopes - The comma-separated set of the variables scopes.

  • $variableName - The variable name to save the HTTP message part.

Example 55. Validate the URL of the matching HTTP request
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`
Example 56. Validate the URL query of the matching HTTP request
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]}`
Example 57. Validate the request data from the matching HTTP message
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`
Example 58. Validate the response data from the matching HTTP message
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

Example 59. Wait for the HTTP request
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 - ExamplesTable representing the list of the headers with columns "name" and "value" specifying HTTP header names and values respectively

Example 60. Add headers to the proxied HTTP request
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
Example 61. Clear the data recorded by the proxy
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
Example 62. Clear the 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 - ExamplesTable representing the list of the headers with columns "name" and "value" specifying HTTP header names and values respectively

Example 63. Hijack a page
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 - ExamplesTable representing the list of the headers with columns "name" and "value" specifying HTTP header names and values respectively

Example 64. Hijack a page
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 - ExamplesTable representing the list of the headers with columns "name" and "value" specifying HTTP header names and values respectively

Example 65. 404 page
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 or OFF.

  • $connectionName - The name of the network connect to toggle.

Connection name Supported platforms Description

WIFI

Android emulators, Android and iOS real devices

Wi-Fi connection

MOBILE_DATA

Android emulators, Android and iOS real devices

Mobile Data connection

AIRPLANE

Android real devices, Android emulators

Airplane Mode

WIFI_AND_MOBILE_DATA

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 activate application with bundle identifier `$bundleId`.
Example 66. Turn OFF Wi-Fi for Android
When I turn OFF `WIFI` network connection
Example 67. Turn OFF Wi-Fi for iOS
When I turn OFF `WIFI` network connection
When I activate application with bundle identifier `my-aplication-bundle-id`