How to use Relative Selector in Shirates - Part 1 -
Tags: appium, android, ios, testautomation
Published: 2022-10-18 16:05:25

This article is an introduction of how to use [Shirates](https://dev.to/wave1008/introducing-shirates-a-mobile-testing-automation-tool-3nmc), a mobile testing automation tool.

## Selector expression
You can use **selector expression** for selecting an element in the screen. This is simple and powerful expression(See [How to use selector expression in Shirates](https://dev.to/wave1008/how-to-use-selector-expression-in-shirates-2po4)).

## Relative selector
Once you selected an element on the screen, you might want to get another element around the element relatively. In this case, you can use Shirates's **relative selector**.

## Relative selector(Direction based)
You can get a **Widget** relatively with direction right, below, left, above.

![direction](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/34bwnrnvsn79wz5jlcqn.png)

## Relative selectors

| relative selector | description               |
|:------------------|:--------------------------|
| :right            | widget in right direction |
| :rightInput       | input in right direction  |
| :rightLabel       | label in right direction  |
| :rightImage       | image in right direction  |
| :rightButton      | button in right direction |
| :rightSwitch      | switch in right direction |
| :below            | widget in below direction |
| :belowInput       | input in below direction  |
| :belowLabel       | label in below direction  |
| :belowImage       | image in below direction  |
| :belowButton      | button in below direction |
| :belowSwitch      | switch in below direction |
| :left             | widget in left direction  |
| :leftInput        | input in left direction   |
| :leftLabel        | label in left direction   |
| :leftImage        | image in left direction   |
| :leftButton       | button in left direction  |
| :leftSwitch       | switch in left direction  |
| :above            | widget in above direction |
| :aboveInput       | input in above direction  |
| :aboveLabel       | label in above direction  |
| :aboveImage       | image in above direction  |
| :aboveButton      | button in above direction |
| :aboveSwitch      | switch in above direction |

Additional **Widget type**(input, label, image, button, switch) can be specified.

## Widget
Built-in widget information is as follows.

| widget | corresponding (Android)                                                          | corresponding (iOS)                                         |
|:-------|:---------------------------------------------------------------------------------|:------------------------------------------------------------|
| label  | android.widget.TextView                                                          | XCUIElementTypeStaticText                                   |
| input  | android.widget.EditText                                                          | XCUIElementTypeTextField<br/>XCUIElementTypeSecureTextField |
| image  | android.widget.ImageView                                                         | XCUIElementTypeImage                                        |
| button | android.widget.Button<br/>android.widget.ImageButton<br/>android.widget.CheckBox | XCUIElementTypeButton                                       |
| switch | android.widget.Switch                                                            | XCUIElementTypeSwitch                                       |
| widget | (all of the above)                                                               | (all of the above)                                          |

---

## Selector command examples

| example                     | description                                                                                                                                                           |
|:----------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `<text1>:right`             | Select the first element that text is "text1", then select the first widget in right direction.                                                                       |
| `<text1>:right(2)`          | Select the first element that text is "text1", then select the second widget in right direction. This is equivalent to `<text1>:right(pos=2)` or `<text1>:right([2])` |
| `<text1>:rightSwitch`       | Select the first element that text is "text1", then select the first switch in right direction.                                                                       |
| `<text1>:right(text2)`      | Select the first element that text is "text1", then select the first widget that text is "text2" in right direction.                                                  |
| `<text1>:right:belowButton` | Select the first element that text is "text1", then select the first widget in right direction, then select the 1st button in below direction.                         |

<br>

<br>

### Usage of right selector (Android)

from TextView1


![direction right android](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ofcoqrq4lv395xm1a1c9.png)


<br>

### Usage of right selector (iOS)

from StaticText1

![direction right ios](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q2tgea70w3349exwqsym.png)

### Search range

Right selector searches in right direction between the top and the bottom of base element.

![search range](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wewrxu7fgufheilzlit7.png)

## Material
You can get complete sample project from [https://github.com/wave1008/shirates-samples-selectors].

### SelectWithDirectionTest
```kotlin
import org.junit.jupiter.api.Order
import org.junit.jupiter.api.Test
import shirates.core.driver.commandextension.*
import shirates.core.testcode.UITest

class SelectWithDirectionTest : UITest() {

    @Test
    @Order(10)
    fun selectWithDirection() {

        scenario {
            case(1) {
                condition {
                    it.restartApp()
                }.action {
                    it.select("<Battery>:below")
                }.expectation {
                    it.textIs("100%")
                }
            }
            case(2) {
                action {
                    it.select("<Battery>:leftImage")
                }.expectation {
                    it.classIs("android.widget.ImageView")
                }
            }
            case(3) {
                action {
                    it.select("<Battery>:above(2)")
                }.expectation {
                    it.textIs("Notifications")
                }
            }
            case(4) {
                condition {
                    it.tap("Search settings")
                }.action {
                    it.select("<@Back>:right")
                }.expectation {
                    it.classIs("android.widget.EditText")
                }
            }
        }
    }

}
```

### Test Result

#### HTML-Report

![HTML-Report](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/520cld45rdmyezu82kcq.png)


#### Spec-Report


![Spec-Report](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c0jry9vk7rp0dk932f8c.png)



---

## For more information
See [Relative selector(Direction based)](https://github.com/ldi-github/shirates-core/blob/main/doc/markdown/basic/selector_and_nickname/relative_selector/relative_selector_direction.md)

---

## Conclusion
Once you selected an element on the screen, you can get another element around the element relatively using Shirates's **relative selector**.

You can get a **widget**(input, label, image, button, switch) relatively with direction right, below, left, above.