Skip to content

Commit

Permalink
Mobile unit tests: remove custom waitFor implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
jsnajdr committed Dec 21, 2022
1 parent d52df06 commit a9c4199
Show file tree
Hide file tree
Showing 15 changed files with 133 additions and 231 deletions.
42 changes: 15 additions & 27 deletions docs/contributors/code/react-native/integration-test-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,42 +121,32 @@ const radiusSlider = getByTestId( 'Slider Border Radius' );

Note that either a plain string or a regular expression can be passed into these queries. A regular expression is best for querying part of a string (e.g. any element whose accessibility label contains `Unsupported Block. Row 1`). Note that special characters such as `.` need to be escaped.

### Use of `waitFor`
### Use of `find` queries

After rendering the components or firing an event, side effects might happen due to potential state updates so the element we’re looking for might not be yet rendered. In this case, we would need to wait for the element to be available and for this purpose, we can use the `waitFor` function, which periodically executes the provided callback to determine whether the element appeared or not.
After rendering the components or firing an event, side effects might happen due to potential state updates so the element we’re looking for might not be yet rendered. In this case, we would need to wait for the element to be available and for this purpose, we can use the `find*` versions of query functions, which internally use `waitFor` and periodically check whether the element appeared or not.

Here are some examples:

```js
const mediaLibraryButton = await waitFor( () =>
getByText( 'WordPress Media Library' )
);
const mediaLibraryButton = await findByText( 'WordPress Media Library' );
```

```js
const missingBlock = await waitFor( () =>
getByLabelText( /Unsupported Block\. Row 1/ )
);
const missingBlock = await findByLabelText( /Unsupported Block\. Row 1/ );
```

```js
const radiusSlider = await waitFor( () =>
getByTestId( 'Slider Border Radius' )
);
const radiusSlider = await findByTestId( 'Slider Border Radius' );
```

In most cases we’ll use the `waitFor` function, but it’s important to note that it should be restricted to those queries that actually require waiting for the element to be available.

NOTE: The `react-native-testing-library` package provides the `query*` and `find*` functions for this purpose too, but we should avoid using them for now because there’s a [known issue](https://github.com/callstack/react-native-testing-library/issues/379) that would make the test fail.
In most cases we’ll use the `find*` functions, but it’s important to note that it should be restricted to those queries that actually require waiting for the element to be available.

### `within` queries

It’s also possible to query elements contained in other elements via the `within` function, here is an example:

```js
const missingBlock = await waitFor( () =>
getByLabelText( /Unsupported Block\. Row 1/ )
);
const missingBlock = await findByLabelText( /Unsupported Block\. Row 1/ );
const translatedTableTitle = within( missingBlock ).getByText( 'Tabla' );
```

Expand Down Expand Up @@ -236,7 +226,7 @@ Here is an example of how to insert a Paragraph block:

```js
// Open the inserter menu
fireEvent.press( await waitFor( () => getByLabelText( 'Add block' ) ) );
fireEvent.press( await findByLabelText( 'Add block' ) );

const blockList = getByTestId( 'InserterUI-Blocks' );
// onScroll event used to force the FlatList to render all items
Expand All @@ -249,7 +239,7 @@ fireEvent.scroll( blockList, {
} );

// Insert a Paragraph block
fireEvent.press( await waitFor( () => getByText( `Paragraph` ) ) );
fireEvent.press( await findByText( `Paragraph` ) );
```

### Open block settings
Expand All @@ -259,7 +249,7 @@ The block settings can be accessed by tapping the "Open Settings" button after s
```js
fireEvent.press( block );

const settingsButton = await waitFor( () => getByLabelText( 'Open Settings' ) );
const settingsButton = await findByLabelText( 'Open Settings' );
fireEvent.press( settingsButton );
```

Expand Down Expand Up @@ -301,9 +291,7 @@ fireEvent.scroll( blockList, {
Sliders found in bottom sheets should be queried using their `testID`:

```js
const radiusSlider = await waitFor( () =>
getByTestId( 'Slider Border Radius' )
);
const radiusSlider = await findByTestId( 'Slider Border Radius' );
fireEvent( radiusSlider, 'valueChange', '30' );
```

Expand All @@ -314,8 +302,8 @@ Note that a slider’s `testID` is "Slider " + label. So for a slider with a lab
One caveat when adding blocks is that if they contain inner blocks, these inner blocks are not rendered. The following example shows how we can make a Buttons block render its inner Button blocks (assumes we’ve already obtained a reference to the Buttons block as `buttonsBlock`):

```js
const innerBlockListWrapper = await waitFor( () =>
within( buttonsBlock ).getByTestId( 'block-list-wrapper' )
const innerBlockListWrapper = await within( buttonsBlock ).findByTestId(
'block-list-wrapper'
);
fireEvent( innerBlockListWrapper, 'layout', {
nativeEvent: {
Expand All @@ -325,8 +313,8 @@ fireEvent( innerBlockListWrapper, 'layout', {
},
} );

const buttonInnerBlock = await waitFor( () =>
within( buttonsBlock ).getByLabelText( /Button Block\. Row 1/ )
const buttonInnerBlock = await within( buttonsBlock ).findByLabelText(
/Button Block\. Row 1/
);
fireEvent.press( buttonInnerBlock );
```
Expand Down
40 changes: 16 additions & 24 deletions packages/block-library/src/columns/test/edit.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import {
openBlockSettings,
within,
getBlock,
waitFor,
dismissModal,
waitForModalVisible,
} from 'test/helpers';

/**
Expand Down Expand Up @@ -117,19 +117,17 @@ describe( 'Columns block', () => {

it( 'reaches the minimum limit of number of column blocks', async () => {
const screen = await initializeEditor();
const { getByLabelText, getByTestId } = screen;

// Add block
await addBlock( screen, 'Columns' );

// Wait for the variations modal to be visible
await waitFor(
() => getByTestId( 'block-variation-modal' ).props.isVisible
const blockVariationModal = await screen.findByTestId(
'block-variation-modal'
);
await waitForModalVisible( blockVariationModal );

// Select a column variation
const blockVariationModal = getByTestId( 'block-variation-modal' );
await waitFor( () => blockVariationModal.props.isVisible );
const threeColumnLayout =
within( blockVariationModal ).getByLabelText(
/33 \/ 33 \/ 33 block/
Expand All @@ -144,7 +142,7 @@ describe( 'Columns block', () => {
await openBlockSettings( screen );

// Update the number of columns by adding one
const columnsControl = getByLabelText( /Number of columns/ );
const columnsControl = screen.getByLabelText( /Number of columns/ );
fireEvent( columnsControl, 'accessibilityAction', {
nativeEvent: { actionName: 'increment' },
} );
Expand Down Expand Up @@ -249,20 +247,19 @@ describe( 'Columns block', () => {
const screen = await initializeEditor( {
initialHtml: TWO_COLUMNS_BLOCK_HTML,
} );
const { getByLabelText } = screen;

// Get block
const columnsBlock = await getBlock( screen, 'Columns' );
fireEvent.press( columnsBlock );

// Open vertical alignment menu
const verticalAlignmentButton = getByLabelText(
const verticalAlignmentButton = screen.getByLabelText(
/Change vertical alignment/
);
fireEvent.press( verticalAlignmentButton );

// Get Align top button
const verticalTopAlignmentButton = getByLabelText( /Align top/ );
const verticalTopAlignmentButton = screen.getByLabelText( /Align top/ );
fireEvent.press( verticalTopAlignmentButton );

// Get the first column
Expand All @@ -273,7 +270,8 @@ describe( 'Columns block', () => {
fireEvent.press( verticalAlignmentButton );

// Get Align bottom button
const verticalBottomAlignmentButton = getByLabelText( /Align bottom/ );
const verticalBottomAlignmentButton =
screen.getByLabelText( /Align bottom/ );
fireEvent.press( verticalBottomAlignmentButton );

expect( getEditorHtml() ).toMatchSnapshot();
Expand Down Expand Up @@ -310,19 +308,17 @@ describe( 'Columns block', () => {
describe( 'when using columns percentage mechanism', () => {
it( "updates the slider's input value", async () => {
const screen = await initializeEditor();
const { getByLabelText, getByTestId } = screen;

// Add block
await addBlock( screen, 'Columns' );

// Wait for the variations modal to be visible
await waitFor(
() => getByTestId( 'block-variation-modal' ).props.isVisible
const blockVariationModal = await screen.findByTestId(
'block-variation-modal'
);
await waitForModalVisible( blockVariationModal );

// Select a column variation
const blockVariationModal = getByTestId( 'block-variation-modal' );
await waitFor( () => blockVariationModal.props.isVisible );
const threeColumnLayout =
within( blockVariationModal ).getByLabelText(
/33 \/ 33 \/ 33 block/
Expand All @@ -337,7 +333,7 @@ describe( 'Columns block', () => {
await openBlockSettings( screen );

// Get width control
const widthControl = getByLabelText( /Width. Value is/ );
const widthControl = screen.getByLabelText( /Width. Value is/ );
fireEvent.press( within( widthControl ).getByText( '33.3' ) );
const widthTextInput =
within( widthControl ).getByDisplayValue( '33.3' );
Expand Down Expand Up @@ -406,21 +402,17 @@ describe( 'Columns block', () => {
'sets the predefined percentages for %s',
async ( layout ) => {
const screen = await initializeEditor();
const { getByTestId } = screen;

// Add block
await addBlock( screen, 'Columns' );

// Wait for the variations modal to be visible
await waitFor(
() => getByTestId( 'block-variation-modal' ).props.isVisible
const blockVariationModal = await screen.findByTestId(
'block-variation-modal'
);
await waitForModalVisible( blockVariationModal );

// Select a column variation
const blockVariationModal = getByTestId(
'block-variation-modal'
);
await waitFor( () => blockVariationModal.props.isVisible );
const columnLayout =
within( blockVariationModal ).getByLabelText( layout );
fireEvent.press( columnLayout );
Expand Down
31 changes: 17 additions & 14 deletions packages/block-library/src/cover/test/edit.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
initializeEditor,
render,
fireEvent,
waitFor,
waitForModalVisible,
within,
getBlock,
openBlockSettings,
Expand Down Expand Up @@ -185,14 +185,14 @@ describe( 'when an image is attached', () => {
} );

it( 'toggles a fixed background', async () => {
const { getByText } = render(
const screen = render(
<CoverEdit
attributes={ attributes }
setAttributes={ setAttributes }
/>
);
const fixedBackgroundButton = await waitFor( () =>
getByText( 'Fixed background' )
const fixedBackgroundButton = await screen.findByText(
'Fixed background'
);
fireEvent.press( fixedBackgroundButton );

Expand Down Expand Up @@ -256,21 +256,24 @@ describe( 'when an image is attached', () => {
} );

it( 'discards canceled focal point changes', async () => {
const { getByText, getByLabelText } = render(
const screen = render(
<CoverEdit
attributes={ attributes }
setAttributes={ setAttributes }
/>
);
const editFocalPointButton = await waitFor( () =>
getByText( 'Edit focal point' )
const editFocalPointButton = await screen.findByText(
'Edit focal point'
);
fireEvent.press( editFocalPointButton );
fireEvent.press(
getByText( ( attributes.focalPoint.x * 100 ).toString() )
screen.getByText( ( attributes.focalPoint.x * 100 ).toString() )
);
fireEvent.changeText(
screen.getByLabelText( 'X-Axis Position' ),
'80'
);
fireEvent.changeText( getByLabelText( 'X-Axis Position' ), '80' );
fireEvent.press( getByLabelText( 'Go back' ) );
fireEvent.press( screen.getByLabelText( 'Go back' ) );

expect( setAttributes ).not.toHaveBeenCalledWith(
expect.objectContaining( {
Expand Down Expand Up @@ -356,7 +359,7 @@ describe( 'color settings', () => {

// Wait for Block Settings to be visible.
const blockSettingsModal = screen.getByTestId( 'block-settings-modal' );
await waitFor( () => blockSettingsModal.props.isVisible );
await waitForModalVisible( blockSettingsModal );

// Open the overlay color settings.
const colorOverlay = await screen.findByLabelText( 'Color. Empty' );
Expand Down Expand Up @@ -391,7 +394,7 @@ describe( 'color settings', () => {

// Wait for Block Settings to be visible.
const blockSettingsModal = screen.getByTestId( 'block-settings-modal' );
await waitFor( () => blockSettingsModal.props.isVisible );
await waitForModalVisible( blockSettingsModal );

// Open the overlay color settings.
const colorOverlay = await screen.findByLabelText( 'Color. Empty' );
Expand Down Expand Up @@ -447,7 +450,7 @@ describe( 'color settings', () => {

// Wait for Block Settings to be visible.
const blockSettingsModal = screen.getByTestId( 'block-settings-modal' );
await waitFor( () => blockSettingsModal.props.isVisible );
await waitForModalVisible( blockSettingsModal );

// Open the overlay color settings.
const colorOverlay = await screen.findByLabelText( 'Color. Empty' );
Expand Down Expand Up @@ -503,7 +506,7 @@ describe( 'color settings', () => {

// Wait for Block Settings to be visible.
const blockSettingsModal = screen.getByTestId( 'block-settings-modal' );
await waitFor( () => blockSettingsModal.props.isVisible );
await waitForModalVisible( blockSettingsModal );

// Open the overlay color settings.
const colorOverlay = await screen.findByLabelText( 'Color. Empty' );
Expand Down
Loading

1 comment on commit a9c4199

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Flaky tests detected.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/3756994989
📝 Reported issues:

Please sign in to comment.