Skip to content
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

new driver for hint testing #2898

Draft
wants to merge 21 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 10 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
11 changes: 11 additions & 0 deletions jestSetup/jest-setup.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {NativeModules, AccessibilityInfo, Animated} from 'react-native';
import React from 'react';
// ========= Mock Object.defineProperty to always allow overriding =========
const originalDefineProperty = Object.defineProperty;
Object.defineProperty = (obj, prop, desc) => {
Expand All @@ -15,6 +16,16 @@ Object.defineProperties = (obj, props) => {
return obj;
};
// =========================================================================
const OriginalReactComponent = React.Component;
Object.defineProperty(React, 'Component', {
value: class MockedReactComponent extends OriginalReactComponent {
M-i-k-e-l marked this conversation as resolved.
Show resolved Hide resolved
componentDidMount() {
super.componentDidMount?.();
this.props.onLayout?.({nativeEvent: {layout: {}}});
this.measureInWindow?.({nativeEvent: {layout: {}}});
}
}
});

global._UILIB_TESTING = true;

Expand Down
90 changes: 90 additions & 0 deletions src/components/hint/Hint.driver.new.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import {HintProps} from './index';
import {TouchableOpacityProps} from '../touchableOpacity';
import {
useComponentDriver,
ComponentProps,
usePressableDriver,
ViewDriver,
ImageDriver,
ModalDriver,
TextDriver
} from '../../testkit';
import {ViewStyle, StyleSheet} from 'react-native';

export const HintDriver = (props: ComponentProps) => {
const driver = usePressableDriver<HintProps>(useComponentDriver(props));

const modalDriver = ModalDriver({
renderTree: props.renderTree,
testID: `${props.testID}.modal`
});

const contentDriver = ViewDriver({
renderTree: props.renderTree,
testID: `${props.testID}.message`
});

const textDriver = TextDriver({
renderTree: props.renderTree,
testID: `${props.testID}.text`
});

const hintPressableDriver = usePressableDriver<TouchableOpacityProps>(useComponentDriver({
renderTree: props.renderTree,
testID: `${props.testID}`
}));

const overlayDriver = usePressableDriver<TouchableOpacityProps>(useComponentDriver({
renderTree: props.renderTree,
testID: `${props.testID}.overlay`
}));

const iconDriver = ImageDriver({
renderTree: props.renderTree,
testID: `${props.testID}.icon`
});

const getModal = () => {
return modalDriver;
};
M-i-k-e-l marked this conversation as resolved.
Show resolved Hide resolved

const getIcon = () => {
return iconDriver;
};

const getBackgroundColor = (): ViewStyle => {
return StyleSheet.flatten(contentDriver.getProps().style).backgroundColor as ViewStyle;
};

const getMessage = () => {
return textDriver.getText();
};

const getHintPressable = () => {
return hintPressableDriver;
};
M-i-k-e-l marked this conversation as resolved.
Show resolved Hide resolved

const getOverlay = () => {
return overlayDriver;
};

const hintPress = () => {
M-i-k-e-l marked this conversation as resolved.
Show resolved Hide resolved
return hintPressableDriver.press();
};

const hintPressOnBackground = () => {
M-i-k-e-l marked this conversation as resolved.
Show resolved Hide resolved
return overlayDriver.press();
};

return {
getBackgroundColor,
getModal,
getIcon,
getMessage,
getHintPressable,
getOverlay,
hintPress,
hintPressOnBackground,
...driver
};
};
138 changes: 102 additions & 36 deletions src/components/hint/__tests__/index.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,69 +1,135 @@
import React from 'react';
import {Hint} from 'react-native-ui-lib';
import {Colors} from '../../../style';
import {findStyle} from '../../../uilib-test-renderer';
import {HintDriver} from '../Hint.driver';
import React, {useRef} from 'react';
import {waitFor, render} from '@testing-library/react-native';
import {Hint, Colors, Button} from 'react-native-ui-lib';
import {HintDriver} from '../Hint.driver.new';

const TEST_ID = 'Hint';

const settingsIcon = require('../../../assets/icons/check.png');

const HintTestComponent = ({
showHint,
color
color,
onPress,
onBackgroundPress,
useTargetFrame = true,
useModal,
useIcon
}: {
showHint: boolean;
color?: string;
onPress?: Function;
onBackgroundPress?: Function;
useTargetFrame?: boolean;
useModal?: boolean;
useIcon?: boolean;
}) => {
const ref = useRef();
return (
<Hint
visible={showHint}
message={'Hint message to hint things'}
position={Hint.positions.TOP}
useSideTip
key={'1'}
targetFrame={{x: 1, y: 1, height: 1, width: 1}}
onBackgroundPress={() => {}}
targetFrame={useTargetFrame && {x: 1, y: 1, height: 1, width: 1}}
onBackgroundPress={onBackgroundPress}
onPress={onPress}
color={color}
removePaddings
enableShadow
testID={'Hint'}
/>
testID={TEST_ID}
useModal={useModal}
icon={useIcon ? settingsIcon : undefined}
ref={ref}
>
<Button round $backgroundDefault/>
</Hint>
);
};

describe('Hint Screen component test', () => {
afterEach(() => {
HintDriver.clear();
});
//TODO: Add test for Hint tip position
describe('Test Hint style:', () => {
it('Test Hint component background color', async () => {
const expectedColor = Colors.$backgroundPrimaryHeavy;
const renderTree = render(<HintTestComponent showHint/>);
const driver = HintDriver({renderTree, testID: TEST_ID});
expect(await driver.getElement()).toBeTruthy();
Copy link
Contributor

Choose a reason for hiding this comment

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

I'de change this to something else, what are we really testing here?


let contentColor = await driver.getBackgroundColor();
expect(contentColor).toBe(expectedColor);

const whiteHintRenderTree = render(<HintTestComponent showHint color={Colors.white}/>);
const whiteHintDriver = HintDriver({renderTree: whiteHintRenderTree, testID: TEST_ID});

it('Test Hint component background color', async () => {
const expectedColor = Colors.$backgroundPrimaryHeavy;
const component = <HintTestComponent showHint/>;
contentColor = await whiteHintDriver.getBackgroundColor();
expect(contentColor).toBe(Colors.white);
});
});

const driver = new HintDriver({component, testID: 'Hint'});
expect(await driver.getElement()).toBeTruthy();
describe('Test Hint icon', () => {
it('Hint should include icon', async () => {
const renderTree = render(<HintTestComponent showHint useIcon/>);
const driver = HintDriver({renderTree, testID: TEST_ID});
expect(driver.getIcon().exists()).toBeTruthy();
});

const hintContent = await driver.getHintContent();
let color = findStyle('backgroundColor', hintContent);
it('Hint shouldn\'t include icon', async () => {
const renderTree = render(<HintTestComponent showHint/>);
const driver = HintDriver({renderTree, testID: TEST_ID});
expect(driver.getIcon().exists()).toBeFalsy();
});
});

expect(color).toBe(expectedColor);
expect(hintContent).toBeTruthy();
describe('Test Hint content', () => {
it('Hint should include message', async () => {
const renderTree = render(<HintTestComponent showHint/>);
const message = renderTree.getByTestId(`${TEST_ID}.text`).props.children;
expect(message).toBe('Hint message to hint things');
});
});

const WhiteHint = <HintTestComponent showHint color={Colors.white}/>;
const WhiteHintDriver = new HintDriver({component: WhiteHint, testID: 'Hint'});
describe('Test Hint modal visibility:', () => {
M-i-k-e-l marked this conversation as resolved.
Show resolved Hide resolved
it('Test Hint modal is not visible when showHint is false', async () => {
const renderTree = render(<HintTestComponent showHint={false}/>);
const driver = HintDriver({renderTree, testID: TEST_ID});
expect(await driver.getModal().exists()).toBeFalsy();
adids1221 marked this conversation as resolved.
Show resolved Hide resolved
});

const WhiteHintContent = await WhiteHintDriver.getHintContent();
color = findStyle('backgroundColor', WhiteHintContent);
expect(color).toBe(Colors.white);
it('Test Hint modal is visible when showHint is true', async () => {
const renderTree = render(<HintTestComponent showHint onBackgroundPress={() => {}}/>);
const driver = HintDriver({renderTree, testID: TEST_ID});
expect(await driver.exists()).toBeTruthy();
expect(await driver.getModal().isVisible()).toBeTruthy();
});
});

it('Test Hint modal is not visible when showHint is false', async () => {
const component = <HintTestComponent showHint={false}/>;
const driver = new HintDriver({component, testID: 'Hint'});
expect(await driver.getHintModal()).toBeFalsy();
describe('Test Hint onPress', () => {
let onPressCallback: jest.Mock;
beforeEach(() => (onPressCallback = jest.fn()));
afterEach(() => onPressCallback.mockClear());

it('should trigger onPress callback', async () => {
const renderTree = render(<HintTestComponent showHint onPress={onPressCallback}/>);
const driver = HintDriver({renderTree, testID: TEST_ID});
driver.hintPress();
await waitFor(() => expect(onPressCallback).toHaveBeenCalledTimes(1));
});

it('should not trigger onPress callback when onPress isn\'t passed', async () => {
const renderTree = render(<HintTestComponent showHint/>);
const driver = HintDriver({renderTree, testID: TEST_ID});
driver.hintPress();
await waitFor(() => expect(onPressCallback).toHaveBeenCalledTimes(0));
});
});

it('Test Hint modal is visible when showHint is true', async () => {
const component = <HintTestComponent showHint/>;
const driver = new HintDriver({component, testID: 'Hint'});
expect(await driver.getElement()).toBeTruthy();
expect(await driver.getHintModal()).toBeTruthy();
describe('Test Hint onBackgroundPress', () => {
it('should not create touchable overlay driver when onBackgroundPress isn\'t passed', async () => {
const renderTree = render(<HintTestComponent showHint/>);
const driver = HintDriver({renderTree, testID: TEST_ID});
expect(driver.getOverlay().exists()).toBeFalsy();
});
});
});
19 changes: 12 additions & 7 deletions src/components/hint/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -425,10 +425,13 @@ class Hint extends Component<HintProps, HintState> {
}
]}
pointerEvents="box-none"
testID={`${testID}.overlay`}
>
{onBackgroundPress && (
<TouchableWithoutFeedback style={StyleSheet.absoluteFillObject} onPress={onBackgroundPress}>
<TouchableWithoutFeedback
style={StyleSheet.absoluteFillObject}
onPress={onBackgroundPress}
testID={`${testID}.overlay`}
>
<View flex/>
</TouchableWithoutFeedback>
)}
Expand Down Expand Up @@ -479,8 +482,12 @@ class Hint extends Component<HintProps, HintState> {
ref={this.hintRef}
>
{customContent}
{!customContent && icon && <Image source={icon} style={[styles.icon, iconStyle]}/>}
{!customContent && <Text recorderTag={'unmask'} style={[styles.hintMessage, messageStyle]}>{message}</Text>}
{!customContent && icon && <Image source={icon} style={[styles.icon, iconStyle]} testID={`${testID}.icon`}/>}
{!customContent && (
<Text recorderTag={'unmask'} style={[styles.hintMessage, messageStyle]} testID={`${testID}.text`}>
{message}
</Text>
)}
</View>
);
}
Expand All @@ -501,9 +508,8 @@ class Hint extends Component<HintProps, HintState> {
this.getHintAnimatedStyle()
]}
pointerEvents="box-none"
testID={testID}
>
<TouchableOpacity activeOpacity={opacity} onPress={onPress}>
<TouchableOpacity activeOpacity={opacity} onPress={onPress} testID={`${testID}`}>
{this.renderContent()}
</TouchableOpacity>
{this.renderHintTip()}
Expand Down Expand Up @@ -552,7 +558,6 @@ class Hint extends Component<HintProps, HintState> {

renderChildren() {
const {targetFrame} = this.props;

if (!targetFrame && isValidElement(this.props.children)) {
return React.cloneElement<any>(this.props.children, {
key: 'clone',
Expand Down
1 change: 1 addition & 0 deletions src/testkit/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export {TextFieldDriver} from '../components/textField/TextField.driver.new';
export {ViewDriver} from '../components/view/View.driver.new';
export {ModalDriver} from '../components/modal/Modal.driver.new';
export {DialogDriver} from '../incubator/Dialog/Dialog.driver.new';
export {HintDriver} from '../components/hint/Hint.driver.new';
export {ButtonDriver} from '../components/button/Button.driver.new';
export {ImageDriver} from '../components/image/Image.driver.new';
export {SwitchDriver} from '../components/switch/switch.driver';
Expand Down