Understanding Text Filters in AskUI
Tags: askui, testing, automation, development
Published: 2023-01-20 08:26:25

This tutorial demonstrates different methods to handle text elements with AskUI. AskUI offers four different methods:

- `containsText()`
- `withExactText()`
- `withText()`
- `withTextRegex()`


## Requirements
- [AskUI](https://docs.askui.com/docs/general/Getting%20Started/getting-started) installed and set up.

For a convenient demonstration, we will use a [Flutter web demo](https://gallery.flutter.dev/#/demo) provided by Flutter. 

------

## Basic Text Matching

The simplest way to interact with a text element is to use `withText()`. Go to the demo app page and run the code below:

```ts
await aui.moveMouseTo().text().withText('matrial').exec();
await aui.mouseLeftClick().exec();
```


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sf78i4wzywfio3qscl77.gif)


`withText()` tries to find a text that matches the whole sequence. In most test cases, you will want to stick to this method, as it supports **Fuzzy Matching** and tolerates misspelled text. **Note that the above example code has two typos**. `matrial` doesn't match the text in the demo app, which is `Material`, although AskUI will find the text element that roughly matches the text on the screen.

------

## Match a Substring within a Text

Even though the the method `withText()` is handy and quite reliable, you might face a test case where you know only a fraction of the text element that you want to interact with. In such a case, `containsText()` is the method you might want to use:

```ts
await aui.moveMouseTo().text().containsText('Bottom').exec();
await aui.mouseLeftClick().exec();
```


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mj2d76jo4lhmlyy2kftv.gif)

Be aware that even if the method `containsText()` also supports **Fuzzy Matching**, it won't match the whole sequence by just a few characters. Try to use this code with the given demo app:

```ts
// this will fail
await aui.moveMouseTo().text().containsText('Bottm').exec(); 
```

You will notice that AskUI fails to match the given text `Bottm`, whereas this code will work:

```ts
// this will success
await aui.moveMouseTo().text().containsText('Bottm appbar').exec(); 
// this will also success
await aui.moveMouseTo().text().containsText('Bottom').exec(); 
```

The biggest difference between `withText()` and `containsText()` is whether it matches the text as a whole sequence or not. Matching many texts with a repeating affix could be a practical use case for the `containsText()`.

It is recommended to experiment enough with these methonds to find a better option that suits your specific case, since it's not easy to predict if the given text can be fuzzy-matched with target texts.

------

## Match the Exact Text

If you already know what text you are looking for, or if there are too many similar text elements, we could use the method `withExactText()`.

From the main page of the demo app, go to `Material`->`Data tables`. You will see a table with different foods given with nutrition factors for each of them.

Let's say that we want to click on the items that has exactly **25.0 gm of Fat**. In our demo app, only the **Doughnut** is the matching item. Run this code and see how `withText()` matches the text:

```ts

// Use this helper function to calculate the centroid of the detected elements.
function getCentroid(element: any): any {
    let x = (element.bndbox.xmax - element.bndbox.xmin) / 2.0 + element.bndbox.xmin;
    let y = (element.bndbox.ymax - element.bndbox.ymin) / 2.0 + element.bndbox.ymin;
    return { x: x, y: y };
}

// Find all the text elements that matches '25.0'
const elts = await aui.get().text().withText('25.0').exec();

// Then, iterate through the found elements and click on them
for(let i=0; i<elts.length; ++i){
    const centroid = getCentroid(elts[i]);
    await aui.moveMouse(Math.round(centroid.x), Math.round(centroid.y)).exec();
    await aui.mouseLeftClick().exec();
}

```



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ri8olzc4on00e2ks68tc.gif)

You will see that AskUI clicks not only the **25.0** but also the **26.0**, which is the fat of the **Apple pie**. The result of this test code may differ in your case, because of the different screen resolution and the rendered-size of the demo app.

It will give you a clear idea where you will need to use the method `withExactText()` instead of `withText()`. Try to run the same code after replacing the `withText()` to `withExactText()`:

```ts
// Find all the text elements that matches '25.0' exactly
const elts = await aui.get().text().withExactText('25.0').exec();

// Then, iterate through the found elements and click on them
for(let i=0; i<elts.length; ++i){
    const centroid = getCentroid(elts[i]);
    await aui.moveMouse(Math.round(centroid.x), Math.round(centroid.y)).exec();
    await aui.mouseLeftClick().exec();
}
```



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a4ezh4qzll0905vqbkad.gif)

## Match Text with Regular Expression

The method `withTextRegex()` supports **Regular Expression** to match any text in the most flexible way. Although it might be tricky to use regex due to its esoteric appearance, it is maybe one of the best solution when it comes to character matching.

On the same page of the demo app, let's say that we want to click on the items whoes Calorie is between 300 and 500 `(cal>=300 && cal<500)`. Since regex doesn't support numeric comparison, we will try to match the digits in a sequence:

```ts
// Find all the text that matches the expression
const cals = await aui.get().text().withTextRegex('[3-4][0-9]{2}').exec();

// Then, iterate through the found elements and click on them
for(let i=0; i<cals.length; ++i){
    const coord = getCentroid(cals[i]);
    console.log(cals[i].text, coord);
    await aui.moveMouse(Math.round(coord.x), Math.round(coord.y)).exec();
    await aui.mouseLeftClick().exec();
}
```

The regular expression `[3-4][0-9]{2}` means,
- **[3-4]**: Match one character between 3 and 4.
- **[0-9]**: Match one character between 0 and 9.
- **{2}**: Repeat the previous expression ([0-9]) two times.

As the result, it will try to match every text that has a sequence starting with the digit 3 or 4, and then has any two digits in a row.



## Conclusion

When using AskUI for automated tests, text elements are playing a big role, since they typically appear more distinctively than other elements such as icons or textfields. Hence, knowing the benefits of using different text filters can become critical in scaffolding a robust test suite.

If you got any issue by following this tutorial, or if you want to share your AskUI use case, you can join our community on [Discord](https://bit.ly/3T2je6C)!