Skip to content

new button driver, image driver, testing #2894

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 6 commits into from
Jan 16, 2024
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
26 changes: 26 additions & 0 deletions src/components/button/Button.driver.new.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import {ButtonProps} from './ButtonTypes';
import {useComponentDriver, ComponentProps, usePressableDriver, TextDriver, ImageDriver} from '../../testkit';

export const ButtonDriver = (props: ComponentProps) => {
const driver = usePressableDriver<ButtonProps>(useComponentDriver(props));

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

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

const getLabel = () => {
return labelDriver;
};

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

return {getLabel, getIcon, ...driver};
};
138 changes: 65 additions & 73 deletions src/components/button/__tests__/index.driver.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,155 +1,147 @@
import React, {useState} from 'react';
import {waitFor} from '@testing-library/react-native';
import {waitFor, render} from '@testing-library/react-native';
import View from '../../view';
import Text from '../../text';
import Button from '../index';
import {ImageSourcePropType} from 'react-native';
import {ButtonDriver} from '../Button.driver';
import {TextDriver} from '../../text/Text.driver';
import {ButtonDriver} from '../Button.driver.new';
import {TextDriver} from '../../text/Text.driver.new';

const BUTTON_ID = 'button_test_id';
const CHILDREN_TEXT_ID = 'children_test_id';
const CHILDREN_TEXT = 'custom button text';

// TODO: This tests are flaky and only fail on CI - we should investigate why
describe('Button', () => {
afterEach(() => {
ButtonDriver.clear();
});

it('should render a button', async () => {
const component = WrapperScreenWithButton();
const buttonDriver = new ButtonDriver({component, testID: BUTTON_ID});

const renderTree = render(<WrapperScreenWithButton/>);
const buttonDriver = ButtonDriver({renderTree, testID: 'button_test_id'});
expect(await buttonDriver.exists()).toBeTruthy();
});

describe('custom button', () => {
it('should render a custom button', async () => {
const component = WrapperScreenWithCustomButton();
const buttonDriver = new ButtonDriver({component, testID: BUTTON_ID});

const renderTree = render(<WrapperScreenWithCustomButton/>);
const buttonDriver = ButtonDriver({renderTree, testID: 'button_test_id'});
expect(buttonDriver.exists()).toBeTruthy();
});

it('should render the children with correct text', async () => {
const component = WrapperScreenWithCustomButton();
const buttonDriver = new ButtonDriver({component, testID: BUTTON_ID});

const renderTree = render(<WrapperScreenWithCustomButton/>);
const buttonDriver = ButtonDriver({renderTree, testID: 'button_test_id'});
expect(buttonDriver.exists()).toBeTruthy();

const childrenTextDriver = new TextDriver({component, testID: CHILDREN_TEXT_ID});

expect(await childrenTextDriver.getTextContent()).toEqual(CHILDREN_TEXT);
const childrenTextDriver = TextDriver({renderTree, testID: CHILDREN_TEXT_ID});
expect(await childrenTextDriver.getText()).toEqual(CHILDREN_TEXT);
});
});

describe('OnPress', () => {
let onPressCallback: jest.Mock;
beforeEach(() => onPressCallback = jest.fn());
beforeEach(() => (onPressCallback = jest.fn()));
afterEach(() => onPressCallback.mockClear());

it.skip('should trigger onPress callback', async () => {
const component = WrapperScreenWithButton({onPress: onPressCallback});
const buttonDriver = new ButtonDriver({component, testID: BUTTON_ID});

it('should trigger onPress callback', async () => {
const props = {onPress: onPressCallback};
const renderTree = render(<WrapperScreenWithButton {...props}/>);
const buttonDriver = ButtonDriver({renderTree, testID: 'button_test_id'});
buttonDriver.press();

await waitFor(() => expect(onPressCallback).toHaveBeenCalledTimes(1));
});

it('should not trigger onPress callback if button disabled', async () => {
const component = WrapperScreenWithButton({onPress: onPressCallback, disabled: true});
const buttonDriver = new ButtonDriver({component, testID: BUTTON_ID});

const props = {disabled: true, onPress: onPressCallback};
const renderTree = render(<WrapperScreenWithButton {...props}/>);
const buttonDriver = ButtonDriver({renderTree, testID: 'button_test_id'});
buttonDriver.press();

await waitFor(() => expect(onPressCallback).toHaveBeenCalledTimes(0));
});
});

describe('label', () => {
const LABEL = 'mock label';
it('should render a button with correct content', async () => {
const component = WrapperScreenWithButton({label: LABEL});
const buttonDriver = new ButtonDriver({component, testID: BUTTON_ID});

expect(await buttonDriver.getLabelContent()).toEqual(LABEL);
const props = {label: LABEL};
const renderTree = render(<WrapperScreenWithButton {...props}/>);
const buttonDriver = ButtonDriver({renderTree, testID: 'button_test_id'});
expect(await buttonDriver.getLabel().getText()).toEqual(LABEL);
});

it('should render a button with correct label content. ', async () => {
const component = WrapperScreenWithButton({label: LABEL});
const buttonDriver = new ButtonDriver({component, testID: BUTTON_ID});

expect(await buttonDriver.getLabelContent()).toEqual(LABEL);
const props = {label: LABEL};
const renderTree = render(<WrapperScreenWithButton {...props}/>);
const buttonDriver = ButtonDriver({renderTree, testID: 'button_test_id'});
expect(await buttonDriver.getLabel().getText()).toEqual(LABEL);
});

it('should render a button without label. ', async () => {
const component = WrapperScreenWithButton();
const buttonDriver = new ButtonDriver({component, testID: BUTTON_ID});

expect(await buttonDriver.isLabelExists()).toBeFalsy();
const renderTree = render(<WrapperScreenWithButton/>);
const buttonDriver = ButtonDriver({renderTree, testID: 'button_test_id'});
expect(await buttonDriver.getLabel().exists()).toBeFalsy();
});
});

describe('icon', () => {
it('should render a button without an icon. ', async () => {
const component = WrapperScreenWithButton();
const buttonDriver = new ButtonDriver({component, testID: BUTTON_ID});

expect(await buttonDriver.isIconExists()).toBeFalsy();
const renderTree = render(<WrapperScreenWithButton/>);
const buttonDriver = ButtonDriver({renderTree, testID: 'button_test_id'});
expect(await buttonDriver.getIcon().exists()).toBeFalsy();
});

it('should render a button with icon. ', async () => {
const ICON = 12;
const component = WrapperScreenWithButton({iconSource: ICON});
const buttonDriver = new ButtonDriver({component, testID: BUTTON_ID});
const props = {iconSource: ICON};
const renderTree = render(<WrapperScreenWithButton {...props}/>);
const buttonDriver = ButtonDriver({renderTree, testID: 'button_test_id'});

expect(await buttonDriver.isIconExists()).toBeTruthy();
expect(await buttonDriver.getIcon().exists()).toBeTruthy();
});
});

describe('more complicated screen', () => {
//todo take it out of this file. to the demo screens maybe
it('should change text values according to state changes from buttons pressing', async () => {
const component = StatefulScreenWithTextsAndButtonss();
const text1Driver = new TextDriver({testID: `text_1`, component});
const text2Driver = new TextDriver({testID: `text_2`, component});
const button1Driver = new ButtonDriver({testID: `${BUTTON_ID}1`, component});
const button2Driver = new ButtonDriver({testID: `${BUTTON_ID}2`, component});
const renderTree = render(StatefulScreenWithTextsAndButtonss());
const text1Driver = TextDriver({testID: `text_1`, renderTree});
const text2Driver = TextDriver({testID: `text_2`, renderTree});
const button2Driver = ButtonDriver({testID: `${BUTTON_ID}2`, renderTree});
const button1Driver = ButtonDriver({testID: `${BUTTON_ID}1`, renderTree});

expect(await text1Driver.getTextContent()).toBe('button 1 pressed 0 times');
expect(await text2Driver.getTextContent()).toBe('button 2 pressed 0 times');
expect(await text1Driver.getText()).toBe('button 1 pressed 0 times');
expect(await text2Driver.getText()).toBe('button 2 pressed 0 times');

await button1Driver.press();
await button1Driver.press();
await button2Driver.press();

await waitFor(async () => expect(await text1Driver.getTextContent()).toBe('button 1 pressed 2 times'));
await waitFor(async () => expect(await text2Driver.getTextContent()).toBe('button 2 pressed 1 times'));
await waitFor(async () => expect(await text1Driver.getText()).toBe('button 1 pressed 2 times'));
await waitFor(async () => expect(await text2Driver.getText()).toBe('button 2 pressed 1 times'));
});
});
});

function WrapperScreenWithButton(buttonProps: {
onPress?: () => void;
label?: string;
iconSource?: ImageSourcePropType;
disabled?: boolean;
} = {}) {
onPress?: () => void;
label?: string;
iconSource?: ImageSourcePropType;
disabled?: boolean;
} = {}) {
const {onPress, label, iconSource, disabled} = buttonProps;
return (<View testID={'wrapper_screen_test_id'}>
<Button testID={BUTTON_ID} onPress={onPress} label={label} iconSource={iconSource} disabled={disabled}/>
</View>);
return (
<View testID={'wrapper_screen_test_id'}>
<Button testID={BUTTON_ID} onPress={onPress} label={label} iconSource={iconSource} disabled={disabled}/>
</View>
);
}

function WrapperScreenWithCustomButton(buttonProps: {onPress?: () => void} = {}) {
const {onPress} = buttonProps;
return (<View testID={'wrapper_screen_test_id'}>
<Button testID={BUTTON_ID} onPress={onPress}>
<Text testID={CHILDREN_TEXT_ID}>{CHILDREN_TEXT}</Text>
</Button>
</View>);
return (
<View testID={'wrapper_screen_test_id'}>
<Button testID={BUTTON_ID} onPress={onPress}>
<Text testID={CHILDREN_TEXT_ID}>{CHILDREN_TEXT}</Text>
</Button>
</View>
);
}

const StatefulScreenWithTextsAndButtonss = () => <StatefulScreenWithTextsAndButtons/>;
Expand All @@ -159,8 +151,8 @@ const StatefulScreenWithTextsAndButtons = () => {
const [count2, setCount2] = useState(0);
return (
<View testID={'stateful_wrapper_screen_test_id'}>
<Text testID={'text_1'} >{`button 1 pressed ${count1} times`}</Text>
<Text testID={'text_2'} >{`button 2 pressed ${count2} times`}</Text>
<Text testID={'text_1'}>{`button 1 pressed ${count1} times`}</Text>
<Text testID={'text_2'}>{`button 2 pressed ${count2} times`}</Text>
<Button testID={`${BUTTON_ID}1`} onPress={() => setCount1(count1 + 1)}/>
<Button testID={`${BUTTON_ID}2`} onPress={() => setCount2(count2 + 1)}/>
</View>
Expand Down
6 changes: 6 additions & 0 deletions src/components/image/Image.driver.new.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import {useComponentDriver, ComponentProps} from '../../testkit/new/Component.driver';

export const ImageDriver = (props: ComponentProps) => {
const driver = useComponentDriver(props);
return driver;
};
2 changes: 2 additions & 0 deletions src/testkit/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ export {SortableListItemDriver} from '../components/sortableList/SortableListIte
export {TextDriver} from '../components/text/Text.driver.new';
export {TextFieldDriver} from '../components/textField/TextField.driver.new';
export {ViewDriver} from '../components/view/View.driver.new';
export {ButtonDriver} from '../components/button/Button.driver.new';
export {ImageDriver} from '../components/image/Image.driver.new';