mirror of
https://github.com/callstack/react-native-testing-library.git
synced 2026-09-18 23:09:04 +08:00
feat: add debug.deep and debug.shallow (#37)
<!-- Please provide enough information so that others can review your pull request. --> <!-- Keep pull requests small and focused on a single change. --> ### Summary Adds API proposed by https://github.com/callstack/react-native-testing-library/pull/33#issuecomment-430302079. Also component output is now highlighted: <img width="259" alt="screenshot 2018-10-16 at 19 33 25" src="https://user-images.githubusercontent.com/5106466/47035614-c10efb80-d17a-11e8-99ac-00f648880008.png"> ### Test plan Added tests for `debug`.
This commit is contained in:
committed by
GitHub
parent
03e2c4b0f2
commit
05db7bcaac
@@ -273,12 +273,52 @@ Log prettified shallowly rendered component or test instance (just like snapshot
|
|||||||
import { debug } from 'react-native-testing-library';
|
import { debug } from 'react-native-testing-library';
|
||||||
|
|
||||||
debug(<Component />);
|
debug(<Component />);
|
||||||
// console.log:
|
debug.shallow(<Component />); // an alias for `debug`
|
||||||
// <View>
|
|
||||||
// <Text>Component</Text>
|
|
||||||
// </View>
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
logs:
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
<TouchableOpacity
|
||||||
|
activeOpacity={0.2}
|
||||||
|
onPress={[Function bound fn]}
|
||||||
|
>
|
||||||
|
<TextComponent
|
||||||
|
text="Press me"
|
||||||
|
/>
|
||||||
|
</TouchableOpacity>
|
||||||
|
```
|
||||||
|
|
||||||
|
There's also `debug.deep` that renders deeply to stdout.
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
import { debug } from 'react-native-testing-library';
|
||||||
|
|
||||||
|
debug.deep(<Component />);
|
||||||
|
```
|
||||||
|
|
||||||
|
logs:
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
<View
|
||||||
|
accessible={true}
|
||||||
|
isTVSelectable={true}
|
||||||
|
onResponderGrant={[Function bound touchableHandleResponderGrant]}
|
||||||
|
// ... more props
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
\\"opacity\\": 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Text>
|
||||||
|
Press me
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
```
|
||||||
|
|
||||||
|
Optionally you can provide a string message as a second argument to `debug`, which will be displayed right after the component.
|
||||||
|
|
||||||
## `flushMicrotasksQueue`
|
## `flushMicrotasksQueue`
|
||||||
|
|
||||||
Wait for microtasks queue to flush. Useful if you want to wait for some promises with `async/await`.
|
Wait for microtasks queue to flush. Useful if you want to wait for some promises with `async/await`.
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
"react": "16.6.0-alpha.8af6728",
|
"react": "16.6.0-alpha.8af6728",
|
||||||
"react-native": "^0.57.3",
|
"react-native": "^0.57.3",
|
||||||
"react-test-renderer": "16.6.0-alpha.8af6728",
|
"react-test-renderer": "16.6.0-alpha.8af6728",
|
||||||
|
"strip-ansi": "^5.0.0",
|
||||||
"typescript": "^3.1.1"
|
"typescript": "^3.1.1"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`debug 1`] = `
|
||||||
|
"<TouchableOpacity
|
||||||
|
activeOpacity={0.2}
|
||||||
|
onPress={[Function bound fn]}
|
||||||
|
>
|
||||||
|
<TextComponent
|
||||||
|
text=\\"Press me\\"
|
||||||
|
/>
|
||||||
|
</TouchableOpacity>"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`debug.deep 1`] = `
|
||||||
|
"<View
|
||||||
|
accessible={true}
|
||||||
|
isTVSelectable={true}
|
||||||
|
onResponderGrant={[Function bound touchableHandleResponderGrant]}
|
||||||
|
onResponderMove={[Function bound touchableHandleResponderMove]}
|
||||||
|
onResponderRelease={[Function bound touchableHandleResponderRelease]}
|
||||||
|
onResponderTerminate={[Function bound touchableHandleResponderTerminate]}
|
||||||
|
onResponderTerminationRequest={[Function bound touchableHandleResponderTerminationRequest]}
|
||||||
|
onStartShouldSetResponder={[Function bound touchableHandleStartShouldSetResponder]}
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
\\"opacity\\": 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Text>
|
||||||
|
Press me
|
||||||
|
</Text>
|
||||||
|
</View>"
|
||||||
|
`;
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
// @flow
|
||||||
|
/* eslint-disable no-console */
|
||||||
|
import React from 'react';
|
||||||
|
import { TouchableOpacity, Text } from 'react-native';
|
||||||
|
import stripAnsi from 'strip-ansi';
|
||||||
|
import { debug } from '..';
|
||||||
|
|
||||||
|
function TextComponent({ text }) {
|
||||||
|
return <Text>{text}</Text>;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Button extends React.Component<*> {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<TouchableOpacity onPress={this.props.onPress}>
|
||||||
|
<TextComponent text={this.props.text} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test('debug', () => {
|
||||||
|
// $FlowFixMe
|
||||||
|
console.log = jest.fn();
|
||||||
|
const component = <Button onPress={jest.fn} text="Press me" />;
|
||||||
|
debug(component);
|
||||||
|
|
||||||
|
const output = console.log.mock.calls[0][0];
|
||||||
|
|
||||||
|
expect(stripAnsi(output)).not.toEqual(output);
|
||||||
|
expect(stripAnsi(output)).toMatchSnapshot();
|
||||||
|
|
||||||
|
console.log.mockReset();
|
||||||
|
|
||||||
|
debug(component, 'test message');
|
||||||
|
|
||||||
|
expect(console.log).toBeCalledWith(output, 'test message');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('debug.shallow', () => {
|
||||||
|
expect(debug.shallow).toBe(debug);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('debug.deep', () => {
|
||||||
|
// $FlowFixMe
|
||||||
|
console.log = jest.fn();
|
||||||
|
const component = <Button onPress={jest.fn} text="Press me" />;
|
||||||
|
debug.deep(component);
|
||||||
|
|
||||||
|
const output = console.log.mock.calls[0][0];
|
||||||
|
|
||||||
|
expect(stripAnsi(output)).not.toEqual(output);
|
||||||
|
expect(stripAnsi(output)).toMatchSnapshot();
|
||||||
|
|
||||||
|
console.log.mockReset();
|
||||||
|
|
||||||
|
debug.deep(component, 'test message');
|
||||||
|
|
||||||
|
expect(console.log).toBeCalledWith(output, 'test message');
|
||||||
|
});
|
||||||
+21
-2
@@ -1,21 +1,40 @@
|
|||||||
// @flow
|
// @flow
|
||||||
|
/* eslint-disable no-console */
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import prettyFormat, { plugins } from 'pretty-format'; // eslint-disable-line import/no-extraneous-dependencies
|
import prettyFormat, { plugins } from 'pretty-format'; // eslint-disable-line import/no-extraneous-dependencies
|
||||||
import shallow from './shallow';
|
import shallow from './shallow';
|
||||||
|
import render from './render';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Log pretty-printed shallow test component instance
|
* Log pretty-printed shallow test component instance
|
||||||
*/
|
*/
|
||||||
export default function debug(
|
function debugShallow(
|
||||||
instance: ReactTestInstance | React.Element<*>,
|
instance: ReactTestInstance | React.Element<*>,
|
||||||
message?: any
|
message?: any
|
||||||
) {
|
) {
|
||||||
const { output } = shallow(instance);
|
const { output } = shallow(instance);
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.log(format(output), message || '');
|
console.log(format(output), message || '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log pretty-printed deep test component instance
|
||||||
|
*/
|
||||||
|
function debugDeep(instance: React.Element<*>, message?: any) {
|
||||||
|
const { toJSON } = render(instance);
|
||||||
|
|
||||||
|
console.log(format(toJSON()), message || '');
|
||||||
|
}
|
||||||
|
|
||||||
const format = input =>
|
const format = input =>
|
||||||
prettyFormat(input, {
|
prettyFormat(input, {
|
||||||
plugins: [plugins.ReactTestComponent, plugins.ReactElement],
|
plugins: [plugins.ReactTestComponent, plugins.ReactElement],
|
||||||
|
highlight: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const debug = debugShallow;
|
||||||
|
|
||||||
|
debug.shallow = debugShallow;
|
||||||
|
debug.deep = debugDeep;
|
||||||
|
|
||||||
|
export default debug;
|
||||||
|
|||||||
@@ -81,8 +81,15 @@ const shallowTree: { output: React.ReactElement<any> } = shallow(
|
|||||||
|
|
||||||
const waitForFlush: Promise<any> = flushMicrotasksQueue();
|
const waitForFlush: Promise<any> = flushMicrotasksQueue();
|
||||||
|
|
||||||
|
// debug API
|
||||||
debug(<TestComponent />);
|
debug(<TestComponent />);
|
||||||
|
debug(<TestComponent />, 'message');
|
||||||
debug(getByNameString);
|
debug(getByNameString);
|
||||||
|
debug(getByNameString, 'message');
|
||||||
|
debug.shallow(<TestComponent />);
|
||||||
|
debug.shallow(<TestComponent />, 'message');
|
||||||
|
debug.deep(<TestComponent />);
|
||||||
|
debug.deep(<TestComponent />, 'message');
|
||||||
|
|
||||||
const waitBy: Promise<ReactTestInstance> = waitForElement<ReactTestInstance>(
|
const waitBy: Promise<ReactTestInstance> = waitForElement<ReactTestInstance>(
|
||||||
() => tree.getByName('View')
|
() => tree.getByName('View')
|
||||||
|
|||||||
Vendored
+11
-3
@@ -51,6 +51,16 @@ export type WaitForElementFunction = <T = any>(
|
|||||||
interval?: number
|
interval?: number
|
||||||
) => Promise<T>;
|
) => Promise<T>;
|
||||||
|
|
||||||
|
export type DebugFunction = (
|
||||||
|
instance: ReactTestInstance | React.ReactElement<any>,
|
||||||
|
message?: string
|
||||||
|
) => void;
|
||||||
|
|
||||||
|
export type DebugAPI = DebugFunction & {
|
||||||
|
shallow: DebugFunction;
|
||||||
|
deep: (instance: React.ReactElement<any>, message?: string) => void;
|
||||||
|
};
|
||||||
|
|
||||||
export declare const render: (
|
export declare const render: (
|
||||||
component: React.ReactElement<any>,
|
component: React.ReactElement<any>,
|
||||||
options?: RenderOptions
|
options?: RenderOptions
|
||||||
@@ -59,8 +69,6 @@ export declare const shallow: <P = {}>(
|
|||||||
instance: ReactTestInstance | React.ReactElement<P>
|
instance: ReactTestInstance | React.ReactElement<P>
|
||||||
) => { output: React.ReactElement<P> };
|
) => { output: React.ReactElement<P> };
|
||||||
export declare const flushMicrotasksQueue: () => Promise<any>;
|
export declare const flushMicrotasksQueue: () => Promise<any>;
|
||||||
export declare const debug: (
|
export declare const debug: DebugAPI;
|
||||||
instance: ReactTestInstance | React.ReactElement<any>
|
|
||||||
) => void;
|
|
||||||
export declare const fireEvent: FireEventAPI;
|
export declare const fireEvent: FireEventAPI;
|
||||||
export declare const waitForElement: WaitForElementFunction;
|
export declare const waitForElement: WaitForElementFunction;
|
||||||
|
|||||||
@@ -842,6 +842,11 @@ ansi-regex@^3.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
|
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
|
||||||
integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=
|
integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=
|
||||||
|
|
||||||
|
ansi-regex@^4.0.0:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.0.0.tgz#70de791edf021404c3fd615aa89118ae0432e5a9"
|
||||||
|
integrity sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w==
|
||||||
|
|
||||||
ansi-styles@^2.2.1:
|
ansi-styles@^2.2.1:
|
||||||
version "2.2.1"
|
version "2.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
|
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
|
||||||
@@ -6275,6 +6280,13 @@ strip-ansi@^4.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
ansi-regex "^3.0.0"
|
ansi-regex "^3.0.0"
|
||||||
|
|
||||||
|
strip-ansi@^5.0.0:
|
||||||
|
version "5.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.0.0.tgz#f78f68b5d0866c20b2c9b8c61b5298508dc8756f"
|
||||||
|
integrity sha512-Uu7gQyZI7J7gn5qLn1Np3G9vcYGTVqB+lFTytnDJv83dd8T22aGH451P3jueT2/QemInJDfxHB5Tde5OzgG1Ow==
|
||||||
|
dependencies:
|
||||||
|
ansi-regex "^4.0.0"
|
||||||
|
|
||||||
strip-bom@3.0.0, strip-bom@^3.0.0:
|
strip-bom@3.0.0, strip-bom@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
|
resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
|
||||||
|
|||||||
Reference in New Issue
Block a user