Skip to content

Remove use of getByTestID in documentation #294

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 24 additions & 22 deletions docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,36 +118,36 @@ Get the rendered component JSON representation, e.g. for snapshot testing.
## `cleanup`

```ts
const cleanup: () => void
const cleanup: () => void;
```

Unmounts React trees that were mounted with `render`.

For example, if you're using the `jest` testing framework, then you would need to use the `afterEach` hook like so:

```jsx
import { cleanup, render } from 'react-native-testing-library'
import { View } from 'react-native'
import { cleanup, render } from 'react-native-testing-library';
import { View } from 'react-native';

afterEach(cleanup)
afterEach(cleanup);

it('renders a view', () => {
render(<View />)
render(<View />);
// ...
})
});
```

The `afterEach(cleanup)` call also works in `describe` blocks:

```jsx
describe('when logged in', () => {
afterEach(cleanup)
afterEach(cleanup);

it('renders the user', () => {
render(<SiteHeader />)
render(<SiteHeader />);
// ...
});
})
});
```

Failing to call `cleanup` when you've called `render` could result in a memory leak and tests which are not "idempotent" (which can lead to difficult to debug errors in your tests).
Expand All @@ -169,12 +169,13 @@ import { render, fireEvent } from 'react-native-testing-library';

test('fire changeText event', () => {
const onEventMock = jest.fn();
const { getByTestId } = render(
// MyComponent renders TextInput with `onChangeText` bound to handleChangeText
<MyComponent testID="change" handleChangeText={onEventMock} />
const { getByPlaceholder } = render(
// MyComponent renders TextInput which has a placeholder 'Enter details'
// and with `onChangeText` bound to handleChangeText
<MyComponent handleChangeText={onEventMock} />
);

fireEvent(getByTestId('change'), 'onChangeText', 'ab');
fireEvent(getByPlaceholder('change'), 'onChangeText', 'ab');
expect(onEventMock).toHaveBeenCalledWith('ab');
});
```
Expand Down Expand Up @@ -215,15 +216,16 @@ import { render, fireEvent } from 'react-native-testing-library';

const onPressMock = jest.fn();

const { getByTestId } = render(
const { getByText } = render(
<View>
<TouchableOpacity onPress={onPressMock} testID="button">
<TouchableOpacity onPress={onPressMock}>
<Text>Press me</Text>
</TouchableOpacity>
</View>
);

fireEvent.press(getByTestId('button'));
fireEvent.press(getByText('Press me'));
expect(onPressMock).toHaveBeenCalled();
```

### `fireEvent.changeText: (element: ReactTestInstance, ...data: Array<any>) => void`
Expand All @@ -237,13 +239,13 @@ import { render, fireEvent } from 'react-native-testing-library';
const onChangeTextMock = jest.fn();
const CHANGE_TEXT = 'content';

const { getByTestId } = render(
const { getByPlaceholder } = render(
<View>
<TextInput testID="text-input" onChangeText={onChangeTextMock} />
<TextInput placeholder="Enter data" onChangeText={onChangeTextMock} />
</View>
);

fireEvent.changeText(getByTestId('text-input'), CHANGE_TEXT);
fireEvent.changeText(getByPlaceholder('Enter data'), CHANGE_TEXT);
```

### `fireEvent.scroll: (element: ReactTestInstance, ...data: Array<any>) => void`
Expand All @@ -265,13 +267,13 @@ const eventData = {
},
};

const { getByTestId } = render(
<ScrollView testID="scroll-view" onScroll={onScrollMock}>
const { getByText } = render(
<ScrollView onScroll={onScrollMock}>
<Text>XD</Text>
</ScrollView>
);

fireEvent.scroll(getByTestId('scroll-view'), eventData);
fireEvent.scroll(getByText('scroll-view'), eventData);
```

#### On a `FlatList`
Expand Down
4 changes: 2 additions & 2 deletions docs/Queries.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ A method returning a `ReactTestInstance` with matching props object

### `ByName`

> This method has been **deprecated** because using it results in fragile tests that may break between minor React Native versions. **DON'T USE IT**. It will be removed in next major release (v2.0). Use [`getByTestId`](#bytestid) instead. It's listed here only for back-compat purposes for early adopters of the library
A method returning a `ReactTestInstance` with matching a React component type. Throws when no matches.
> This method has been **deprecated** because using it results in fragile tests that may break between minor React Native versions. **DON'T USE IT**. It will be removed in next major release (v2.0). Use the other alternatives, such as [`getByText`](#bytext) instead. It's listed here only for back-compat purposes for early adopters of the library
> A method returning a `ReactTestInstance` with matching a React component type. Throws when no matches.

</details>
15 changes: 6 additions & 9 deletions src/__tests__/act.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,8 @@ const UseEffect = ({ callback }: { callback: Function }) => {
const Counter = () => {
const [count, setCount] = React.useState(0);

return (
<Text testID="counter" onPress={() => setCount(count + 1)}>
{count}
</Text>
);
const text = `Total count: ${count}`;
return <Text onPress={() => setCount(count + 1)}>{text}</Text>;
};

test('render should trigger useEffect', () => {
Expand All @@ -37,12 +34,12 @@ test('update should trigger useEffect', () => {
});

test('fireEvent should trigger useState', () => {
const { getByTestId } = render(<Counter />);
const counter = getByTestId('counter');
const { getByText } = render(<Counter />);
const counter = getByText(/Total count/i);

expect(counter.props.children).toEqual(0);
expect(counter.props.children).toEqual('Total count: 0');
fireEvent.press(counter);
expect(counter.props.children).toEqual(1);
expect(counter.props.children).toEqual('Total count: 1');
});

test('should act even if there is no act in react-test-renderer', () => {
Expand Down
70 changes: 40 additions & 30 deletions src/__tests__/fireEvent.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,59 +9,63 @@ import {
} from 'react-native';
import { render, fireEvent } from '..';

const OnPressComponent = ({ onPress }) => (
const OnPressComponent = ({ onPress, text }) => (
<View>
<TouchableOpacity onPress={onPress} testID="button">
<Text testID="text-button">Press me</Text>
<TouchableOpacity onPress={onPress}>
<Text>{text}</Text>
</TouchableOpacity>
</View>
);

const WithoutEventComponent = () => (
<View>
<Text testID="text">Content</Text>
<Text>Without event</Text>
</View>
);

const CustomEventComponent = ({ onCustomEvent }) => (
<TouchableOpacity onPress={onCustomEvent}>
<Text>Click me</Text>
<Text>Custom event component</Text>
</TouchableOpacity>
);

const MyCustomButton = ({ handlePress }) => (
<OnPressComponent onPress={handlePress} />
const MyCustomButton = ({ handlePress, text }) => (
<OnPressComponent onPress={handlePress} text={text} />
);

const CustomEventComponentWithCustomName = ({ handlePress }) => (
<MyCustomButton testID="my-custom-button" handlePress={handlePress} />
<MyCustomButton handlePress={handlePress} text="Custom component" />
);

describe('fireEvent', () => {
test('should invoke specified event', () => {
const onPressMock = jest.fn();
const { getByTestId } = render(<OnPressComponent onPress={onPressMock} />);
const { getByText } = render(
<OnPressComponent onPress={onPressMock} text="Press me" />
);

fireEvent(getByTestId('button'), 'press');
fireEvent(getByText('Press me'), 'press');

expect(onPressMock).toHaveBeenCalled();
});

test('should invoke specified event on parent element', () => {
const onPressMock = jest.fn();
const { getByTestId } = render(<OnPressComponent onPress={onPressMock} />);

fireEvent(getByTestId('text-button'), 'press');
const text = 'New press text';
const { getByText } = render(
<OnPressComponent onPress={onPressMock} text={text} />
);

fireEvent(getByText(text), 'press');
expect(onPressMock).toHaveBeenCalled();
});

test('should throw an Error when event handler was not found', () => {
const { getByTestId } = render(
const { getByText } = render(
<WithoutEventComponent onPress={() => 'this is not passed to children'} />
);

expect(() => fireEvent(getByTestId('text'), 'press')).toThrow(
expect(() => fireEvent(getByText('Without event'), 'press')).toThrow(
'No handler function found for event: "press"'
);
});
Expand All @@ -70,23 +74,26 @@ describe('fireEvent', () => {
const handlerMock = jest.fn();
const EVENT_DATA = 'event data';

const { getByTestId } = render(
const { getByText } = render(
<View>
<CustomEventComponent testID="custom" onCustomEvent={handlerMock} />
<CustomEventComponent onCustomEvent={handlerMock} />
</View>
);

fireEvent(getByTestId('custom'), 'customEvent', EVENT_DATA);
fireEvent(getByText('Custom event component'), 'customEvent', EVENT_DATA);

expect(handlerMock).toHaveBeenCalledWith(EVENT_DATA);
});
});

test('fireEvent.press', () => {
const onPressMock = jest.fn();
const { getByTestId } = render(<OnPressComponent onPress={onPressMock} />);
const text = 'Fireevent press';
const { getByText } = render(
<OnPressComponent onPress={onPressMock} text={text} />
);

fireEvent.press(getByTestId('text-button'));
fireEvent.press(getByText(text));

expect(onPressMock).toHaveBeenCalled();
});
Expand All @@ -101,13 +108,13 @@ test('fireEvent.scroll', () => {
},
};

const { getByTestId } = render(
<ScrollView testID="scroll-view" onScroll={onScrollMock}>
const { getByText } = render(
<ScrollView onScroll={onScrollMock}>
<Text>XD</Text>
</ScrollView>
);

fireEvent.scroll(getByTestId('scroll-view'), eventData);
fireEvent.scroll(getByText('XD'), eventData);

expect(onScrollMock).toHaveBeenCalledWith(eventData);
});
Expand All @@ -116,37 +123,40 @@ test('fireEvent.changeText', () => {
const onChangeTextMock = jest.fn();
const CHANGE_TEXT = 'content';

const { getByTestId } = render(
const { getByPlaceholder } = render(
<View>
<TextInput testID="text-input" onChangeText={onChangeTextMock} />
<TextInput
placeholder="Customer placeholder"
onChangeText={onChangeTextMock}
/>
</View>
);

fireEvent.changeText(getByTestId('text-input'), CHANGE_TEXT);
fireEvent.changeText(getByPlaceholder('Customer placeholder'), CHANGE_TEXT);

expect(onChangeTextMock).toHaveBeenCalledWith(CHANGE_TEXT);
});

test('custom component with custom event name', () => {
const handlePress = jest.fn();

const { getByTestId } = render(
const { getByText } = render(
<CustomEventComponentWithCustomName handlePress={handlePress} />
);

fireEvent(getByTestId('my-custom-button'), 'handlePress');
fireEvent(getByText('Custom component'), 'handlePress');

expect(handlePress).toHaveBeenCalled();
});

test('event with multiple handler parameters', () => {
const handlePress = jest.fn();

const { getByTestId } = render(
const { getByText } = render(
<CustomEventComponentWithCustomName handlePress={handlePress} />
);

fireEvent(getByTestId('my-custom-button'), 'handlePress', 'param1', 'param2');
fireEvent(getByText('Custom component'), 'handlePress', 'param1', 'param2');

expect(handlePress).toHaveBeenCalledWith('param1', 'param2');
});
4 changes: 2 additions & 2 deletions src/__tests__/render.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ test('getAllByTestId, queryAllByTestId', () => {
});

test('getByName, queryByName', () => {
const { getByTestId, getByName, queryByName } = render(<Banana />);
const bananaFresh = getByTestId('bananaFresh');
const { getByText, getByName, queryByName } = render(<Banana />);
const bananaFresh = getByText('not fresh');
const button = getByName('Button');

button.props.onPress();
Expand Down
4 changes: 2 additions & 2 deletions src/__tests__/shallow.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ test('shallow rendering React elements', () => {
});

test('shallow rendering React Test Instance', () => {
const { getByTestId } = render(<TextPress />);
const { output } = shallow(getByTestId('text-button'));
const { getByText } = render(<TextPress />);
const { output } = shallow(getByText('Press me'));

expect(output).toMatchSnapshot();
});
14 changes: 6 additions & 8 deletions src/__tests__/waitForElement.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class Banana extends React.Component<any> {
render() {
return (
<View>
{this.props.fresh && <Text testID="fresh">Fresh</Text>}
{this.props.fresh && <Text>Fresh</Text>}
<TouchableOpacity onPress={this.changeFresh}>
<Text>Change freshness!</Text>
</TouchableOpacity>
Expand All @@ -36,25 +36,23 @@ class BananaContainer extends React.Component<{}, any> {
}

test('waits for element until it stops throwing', async () => {
const { getByTestId, getByName, queryByTestId } = render(<BananaContainer />);
const { getByText, getByName, queryByText } = render(<BananaContainer />);

fireEvent.press(getByName('TouchableOpacity'));

expect(queryByTestId('fresh')).toBeNull();
expect(queryByText('Fresh')).toBeNull();

const freshBananaText = await waitForElement(() => getByTestId('fresh'));
const freshBananaText = await waitForElement(() => getByText('Fresh'));

expect(freshBananaText.props.children).toBe('Fresh');
});

test('waits for element until timeout is met', async () => {
const { getByTestId, getByName } = render(<BananaContainer />);
const { getByText, getByName } = render(<BananaContainer />);

fireEvent.press(getByName('TouchableOpacity'));

await expect(
waitForElement(() => getByTestId('fresh'), 100)
).rejects.toThrow();
await expect(waitForElement(() => getByText('Fresh'), 100)).rejects.toThrow();
});

test('waits for element with custom interval', async () => {
Expand Down