## Stripes Component Interactors One of the advantages of having a custom design system and component library is that we don't start from scratch when writing tests that target an application using it. We know very precicesly what shape the structure the DOM will take, and we can use that knowledge to our advantage when it comes to writing tests. For most components in the [stripes-components](https://github.com/folio-org/stripes-components#stripes-components) library, there is a corresponding interactor that can be used in your tests. For example, to interact with a stripes Button in a Jest test, you would do something like the following: ```js import { Button, Heading } from '@folio/stripes-testing'; import { App } from '../app'; describe('My Page', () => { beforeEach(() => render()); it('can click a button to reveal a secret message', async () => { await Button('Click Me!').click(); await Heading('Thank You!').exists(); }); }) ``` You can use these interactors inside any testing framework that runs in the same runtime environment as the DOM such as Karma, Jest, Cypress, or BigTest Platform. However, they cannot be used with test runners that runs tests in a remote runtime environment that does not include the DOM under test such as Selenium, or Nightmare. See the [general guide for working with interactors](https://frontside.com/interactors) for more information ### How do I write interactors for my own application? The simplest answer to this question is that in the vast majority of cases, you should not need to write your own interactors for your application. One of the goals of the `@folio/stripes-testing` library is that if your application is built with stripes components, then the ability to simulate any user interaction is baked in for free. Even though your application is built out of many complex components, your user still interacts _directly_ with the low-level input components like "button", "textfield". ### What about complex, repetitive actions like filling out a form? Sometimes there are interactions that span many different components that need to be captured so that they can be used multiple times in multiple test cases. In this instance, you might be tempted to make a custom interactor to encapsulate this process. However, consider using a simple `async` function instead that itself uses interactors under the hood to manipulate the actual components: ```js export async function Login(username, password) { await TextField('username').fillIn(useranme); await TextField({ placeholder: 'password' }).fillIn(password); } ``` you can now use this function anywhere inside your test code: ```js beforeEach(Login('abfab', 'absolutely-fabulous')); ``` ## What if I still think that there is an interactor missing? If an `async` function won't do, and you think that what's called for is an interactor, then you might have found a gap in the `@stripes/testing` library itself. In that case, you can follow the guide for [creating a custom interactor](https://frontside.com/bigtest/docs/interactors/write-your-own) and make a pull request to this package. ### Table of Contents #### Stripes-components - [`Accordion`](#accordion) - [`AutoSuggest`](#autosuggest) - [`Avatar`](#avatar) - [`Badge`](#badge) - [`Button`](#button) - [`ButtonGroup`](#buttongroup) - [`Checkbox`](#checkbox) - [`Dropdown`](#dropdown) - [`Datepicker`](#datepicker) ([`Calendar Widget`](#calendar-widget)) - [`IconButton`](#iconbutton) - [`KeyValue`](#keyvalue) - [`Layer`](#layer) - [`List`](#list) ([`ListItem`](#listitem)) - [`MultiColumnList`](#multicolumnlist) ([`MultiColumnListCell`](#multicolumnlistcell)) - [`MultiSelect`](#multiselect) ([`MultiSelectOption](#multiselectoption)) - [`NavList`](#navlist) - [`Pane`](#pane) ([`PaneHeader`](#paneheader)) - [`RadioButton`](#radiobutton) - [`RichTextEditor`](#richtexteditor) - [`SearchField`](#searchField) - [`Select`](#select) - [`Selection`](#selection) - [`TextArea`](#textarea) - [`TextField`](#textfield) - [`Tooltip`](#tooltip) #### Stripes-smart-components - [`AddressList`](#addresslist) - [`AddressEdit`](#addressedit) - [`EditableList`](#editablelist) - [`EditableListRow`](#editablelistrow) - [`EntryManager`](#entrymanager-smart-component) #### Accordion The accordion element ##### Synopsis ```js import { Accordion } from '@folio/stripes-testing'; Accordion('Location').is({ open: true }); ``` ##### Locator Accordions are identified by their header. For example: ```js Accordion('Categories').exists(); ``` ##### Actions - `clickHeader()`: clicks on an accordion to either open or close it - `focus`: transfers focus to the open/close toggle of this accordion ##### Filters - `id`: _string_ = the DOM element id of this accordion. The `id` filter is provided for debugging, but should not generally be used in tests since it is not a user-facing value - `label`: _string_ = the user identifying text of this accordion. This is the same value as the locator. - `open`: _boolean_ = `true` if this accordion is expanded, `false`, if not - `focused`: _boolean_ = `true` if the keyboard focus is anywhere inside this accordion - `index`: _number_ = the 0 based index of this accordion with in a pane set. So for example `Accordion('Users').has({ index: 2 })` would assert that the "Users" accordion was 3rd in its accordion set. #### AddressList Renders a fieldgroup of common address form fields. Related: [AddressEdit](#addressedit), [AddressView](#addressview) ##### Synopsis ```js import { AddressList } from '@folio/stripes-testing'; // expand collapsed address list AddressList().toggleMore(); // add address to address list... AddressList().addAddress(); // assert that Address list displays 2 addresses AddressList().has({ count: 3 }); ``` ##### actions - `toggleMore`: clicks the expansions - `clickEdit`: _number_ - clicks the edit button at the given index - `addAddress`: clicks the add button, exposes a new address form - `deleteAddress`: _number_ - deletes the address at a given index ##### filters count: number of visible address views in the list #### AddressEdit ##### Synopsis ```js import { AddressEdit } from '@folio/stripes-testing'; // find address form at index 1 AddressEdit({ index: 1 }); // find address form with validation errors AddressEdit({ error: true }); // save the values (click the save button on the address form) AddressEdit().save(); ``` ##### Actions - `save` - Clicks the save button - `cancel` - Clicks the cancel button - `delete` - Clicks the delete button ##### Filters - `index`: _number_ - filters by index. - `error`: _boolean_ - whether or not the form contains an error. #### AutoSuggest Type-ahead suggestion list component using a text field. ##### Synopsis ```js // find via visible label AutoSuggest('country').exists(); // fill in value to the field AutoSuggest.fillIn('blue'); ``` ##### Locator Located via the visible label text. ##### Filters - `open`: _boolean_ = `true` if the avatar is rendering its fallback svg graphic. - `selected`: _string_ = filter by the selected option from the suggestion list. - `value`: _string_ = filter/assert by the value of the text input. ##### Actions - `fillIn`: _string_ = focuses, fills, blurs the text field. - `enterFilter`: _string_ = focuses, and fills the text field with a string (opens suggestion list). - `select`: _string_ = clicks the suggestion labeled with the provided string. #### Avatar Avatar component used for displaying a profile picture. ##### Synopsis ```js // interact with a single Avatar instance... Avatar().exists(); // interact with an avatar instance containing image with filename containing 'pic' Avatar(including('pic')).exists(); ``` ##### Locator A specific avatar can be located via the image filename, via `including` or `matches`. ##### Filters - `placeholder`: _boolean_ = `true` if the avatar is rendering its fallback svg graphic. - `image`: _boolean_ = `true` if the avatar is rendering an `` tag. #### Badge Renders a circular icon with small text content (a number/count). ##### Locator Locate via the containing text ('1'). ##### Synopsis ```js // interact with a single Badge instance... Badge().exists(); // badge containing the number 2... Badge('2'); // assert value.... Badge.has({ value: 2 }); ``` ##### Locator Locate via the text content/number within the badge. ##### Filters - `color`: _string_ = one of `primary`, `red`, `default` - use with `including` or `matches` - `value`: _string_ = text rendered within the badge. #### Button The Button element ##### Synopsis ```js import { Button } from '@folio/stripes-testing'; Button('Click Me').click(); ``` ##### Locator Buttons are located by their text content. For example: ```js Button('Click Me').has({ text: 'Click Me' }); ``` ##### Actions - `click()`: clicks the button ##### Filters - `id`: _string_ = the DOM element id of this button. The `id` filter is provided for debugging, but should not generally be used in tests since it is not a user-facing value - `text`: _string_ = the text content of the button. This is the same value as the locator. - `href`: _string_ = the `href` of the button, if provided - `button`: _boolean_ = `true` if the button is a `