I want to test onDrop method from react-dropzone library in React component. I am using Jest, React Testing Library. I'm creating mock file and I'm trying to drop this files in input, but in console.log files are still equal to an empty array. Do you have any ideas?
package.json
"typescript": "^3.9.7",
"#testing-library/jest-dom": "^5.11.4",
"#testing-library/react": "^11.0.4",
"#types/jest": "^26.0.13",
"jest": "^26.4.2",
"ts-jest": "^26.3.0",
"react-router-dom": "^5.1.2",
"react-dropzone": "^10.1.10",
"#types/react-dropzone": "4.2.0",
ModalImportFile.tsx
import React, { FC, useState } from "react";
import { Box, Button, Dialog, DialogContent, DialogTitle, Grid } from "#material-ui/core";
import { useDropzone } from "react-dropzone";
import AttachFileIcon from "#material-ui/icons/AttachFile";
import DeleteIcon from "#material-ui/icons/Delete";
interface Props {
isOpen: boolean;
}
interface Events {
onClose: () => void;
}
const ModalImportFile: FC<Props & Events> = props => {
const { isOpen } = props as Props;
const { onClose } = props as Events;
const [files, setFiles] = useState<Array<File>>([]);
const { getRootProps, getInputProps, open } = useDropzone({
onDrop: (acceptedFiles: []) => {
setFiles(
acceptedFiles.map((file: File) =>
Object.assign(file, {
preview: URL.createObjectURL(file),
}),
),
);
},
noClick: true,
noKeyboard: true,
});
const getDragZoneContent = () => {
if (files && files.length > 0)
return (
<Box border={1} borderRadius={5} borderColor={"#cecece"} p={2} mb={2}>
<Grid container alignItems="center" justify="space-between">
<Box color="text.primary">{files[0].name}</Box>
<Box ml={1} color="text.secondary">
<Button
startIcon={<DeleteIcon color="error" />}
onClick={() => {
setFiles([]);
}}
/>
</Box>
</Grid>
</Box>
);
return (
<Box border={1} borderRadius={5} borderColor={"#cecece"} p={2} mb={2} style={{ borderStyle: "dashed" }}>
<Grid container alignItems="center">
<Box mr={1} color="text.secondary">
<AttachFileIcon />
</Box>
<Box color="text.secondary">
<Box onClick={open} component="span" marginLeft="5px">
Download
</Box>
</Box>
</Grid>
</Box>
);
};
const closeHandler = () => {
onClose();
setFiles([]);
};
return (
<Dialog open={isOpen} onClose={closeHandler}>
<Box width={520}>
<DialogTitle>Import</DialogTitle>
<DialogContent>
<div data-testid="container" className="container">
<div data-testid="dropzone" {...getRootProps({ className: "dropzone" })}>
<input data-testid="drop-input" {...getInputProps()} />
{getDragZoneContent()}
</div>
</div>
</DialogContent>
</Box>
</Dialog>
);
};
export default ModalImportFile;
ModalImportFile.test.tsx
import React from "react";
import { render, screen, fireEvent } from "#testing-library/react";
import ModalImportFile from "../../components/task/elements/ModalImportFile";
const props = {
isOpen: true,
onClose: jest.fn(),
};
beforeEach(() => jest.clearAllMocks());
describe("<ModalImportFile/>", () => {
it("should drop", async () => {
render(<ModalImportFile {...props} />);
const file = new File([JSON.stringify({ ping: true })], "ping.json", { type: "application/json" });
const data = mockData([file]);
function dispatchEvt(node: any, type: any, data: any) {
const event = new Event(type, { bubbles: true });
Object.assign(event, data);
fireEvent(node, event);
}
function mockData(files: Array<File>) {
return {
dataTransfer: {
files,
items: files.map(file => ({
kind: "file",
type: file.type,
getAsFile: () => file,
})),
types: ["Files"],
},
};
}
const inputEl = screen.getByTestId("drop-input");
dispatchEvt(inputEl, "dragenter", data);
});
}
With the rokki`s answer (https://stackoverflow.com/a/64643985/9405587), I rewrote the test component for easier understanding.
ModalImportFile.test.tsx
import React from "react";
import { render, screen, fireEvent } from "#testing-library/react";
import ModalImportFile from "../../components/task/elements/ModalImportFile";
const props = {
isOpen: true,
onClose: jest.fn(),
};
beforeEach(() => jest.clearAllMocks());
describe("<ModalImportFile/>", () => {
it("should drop", async () => {
render(<ModalImportFile {...props} />);
window.URL.createObjectURL = jest.fn().mockImplementation(() => "url");
const inputEl = screen.getByTestId("drop-input");
const file = new File(["file"], "ping.json", {
type: "application/json",
});
Object.defineProperty(inputEl, "files", {
value: [file],
});
fireEvent.drop(inputEl);
expect(await screen.findByText("ping.json")).toBeInTheDocument();
}
How about changing fireEvent(node, event); to fireEvent.drop(node, event);.
References:
https://jestjs.io/docs/jest-object#jestrequireactualmodulename
requireActual
Returns the actual module instead of a mock, bypassing all checks on whether the module should receive a mock implementation or not.
let dropCallback = null;
let onDragEnterCallback = null;
let onDragLeaveCallback = null;
jest.mock('react-dropzone', () => ({
...jest.requireActual('react-dropzone'),
useDropzone: options => {
dropCallback = options.onDrop;
onDragEnterCallback = options.onDragEnter;
onDragLeaveCallback = options.onDragLeave;
return {
acceptedFiles: [{
path: 'sample4.png'
},
{
path: 'sample3.png'
}
],
fileRejections: [{
file: {
path: 'FileSelector.docx'
},
errors: [{
code: 'file-invalid-type',
message: 'File type must be image/*'
}]
}],
getRootProps: jest.fn(),
getInputProps: jest.fn(),
open: jest.fn()
};
}
}));
it('Should get on drop Function with parameter', async() => {
const accepted = [{
path: 'sample4.png'
},
{
path: 'sample3.png'
},
{
path: 'sample2.png'
}
];
const rejected = [{
file: {
path: 'FileSelector.docx'
},
errors: [{
code: 'file-invalid-type',
message: 'File type must be image/*'
}]
}];
const event = {
bubbles: true,
cancelable: false,
currentTarget: null,
defaultPrevented: true,
eventPhase: 3,
isDefaultPrevented: () => {},
isPropagationStopped: () => {},
isTrusted: true,
target: {
files: {
'0': {
path: 'FileSelector.docx'
},
'1': {
path: 'sample4.png'
},
'2': {
path: 'sample3.png'
},
'3': {
path: 'sample2.png'
}
}
},
timeStamp: 1854316.299999997,
type: 'change'
};
dropCallback(accepted, rejected, event);
onDragEnterCallback();
onDragLeaveCallback();
expect(handleFiles).toHaveBeenCalledTimes(1);
});
Related
Creating test cases for react components using jest/RTL-please i need a guidence for improve my coverage in my test cases ,
My React component is RequestPreferencesEdit.js
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { FormattedMessage, injectIntl } from 'react-intl';
import { Field } from 'react-final-form';
import {
get,
isEmpty,
difference,
} from 'lodash';
import fp from 'lodash/fp';
import {
Row,
Col,
Select,
Checkbox,
Label,
} from '#folio/stripes/components';
import { deliveryFulfillmentValues } from '../../../../constants';
import { addressTypesShape } from '../../../../shapes';
import { nullOrStringIsRequiredTypeValidator } from '../../../../customTypeValidators';
import styles from './RequestPreferencesEdit.css';
class RequestPreferencesEdit extends Component {
static propTypes = {
deliveryAvailable: PropTypes.bool,
servicePoints: PropTypes.arrayOf(PropTypes.object),
addresses: PropTypes.arrayOf(PropTypes.shape({
addressType: PropTypes.string.isRequired,
})),
addressTypes: addressTypesShape,
setFieldValue: PropTypes.func.isRequired,
defaultDeliveryAddressTypeId: nullOrStringIsRequiredTypeValidator,
intl: PropTypes.object.isRequired,
}
componentDidUpdate(prevProps) {
if (this.isDefaultDeliveryAddressResetNeeded(prevProps.addresses, this.props.addresses)) {
this.resetDefaultDeliveryAddress();
}
if (prevProps.deliveryAvailable !== this.props.deliveryAvailable) {
this.onDeliveryCheckboxChange(this.props.deliveryAvailable);
}
}
isDefaultDeliveryAddressResetNeeded(prevAddresses, currentAddresses) {
const byAddressType = address => get(address, 'addressType');
const prevAddressTypeIds = (prevAddresses ?? []).map(byAddressType);
const currentAddressTypeIds = (currentAddresses ?? []).map(byAddressType);
const addressTypesAreChanged = difference(prevAddressTypeIds, currentAddressTypeIds).length !== 0;
const defaultAddressTypeNotExists = !currentAddressTypeIds
.some(addressTypeId => addressTypeId === this.props.defaultDeliveryAddressTypeId);
return addressTypesAreChanged && defaultAddressTypeNotExists;
}
renderDefaultDeliveryAddressSelect() {
return (
<div data-test-default-delivery-address-field>
<Field
name="requestPreferences.defaultDeliveryAddressTypeId"
label={<FormattedMessage id="ui-users.requests.defaultDeliveryAddress" />}
dataOptions={this.getAddressOptions()}
component={Select}
validate={this.defaultDeliveryAddressValidator}
placeholder={this.props.intl.formatMessage({ id: 'ui-users.requests.selectDeliveryAddress' })}
required
/>
</div>
);
}
renderServicePointSelect() {
const { servicePoints, intl } = this.props;
const options = servicePoints.map(servicePoint => ({
value: servicePoint.id,
label: servicePoint.name,
}));
const defaultOption = { value: '', label: intl.formatMessage({ id: 'ui-users.sp.selectServicePoint' }) };
const resultOptions = [defaultOption, ...options];
return (
<Field
name="requestPreferences.defaultServicePointId"
label={<FormattedMessage id="ui-users.requests.defaultPickupServicePoint" />}
dataOptions={resultOptions}
component={Select}
parse={this.defaultServicePointFieldParser}
/>
);
}
defaultServicePointFieldParser(value) {
return value === '' ? null : value;
}
renderFulfillmentPreferenceSelect() {
const { intl } = this.props;
const options = [
{
value: deliveryFulfillmentValues.HOLD_SHELF,
label: intl.formatMessage({ id: 'ui-users.requests.holdShelf' })
},
{
value: deliveryFulfillmentValues.DELIVERY,
label: intl.formatMessage({ id: 'ui-users.requests.delivery' })
},
];
return (
<Field
data-test-fulfillment-preference
name="requestPreferences.fulfillment"
label={<FormattedMessage id="ui-users.requests.fulfillmentPreference" />}
dataOptions={options}
component={Select}
/>
);
}
getAddressOptions() {
const {
addresses,
addressTypes,
} = this.props;
return addresses.reduce((options, address) => {
const { addressType: addressTypeId } = address;
const relatedAddressType = addressTypes
.find((currentAddressType) => currentAddressType.id === addressTypeId);
return [
...options,
{
value: get(relatedAddressType, 'id'),
label: get(relatedAddressType, 'addressType'),
}
];
}, []);
}
// eslint-disable-next-line consistent-return
defaultDeliveryAddressValidator = (value, formData) => {
const nonEmptyAddresses = get(formData, 'personal.addresses', []).filter(address => !isEmpty(address));
if (nonEmptyAddresses.length === 0) {
return <FormattedMessage id="ui-users.addAddressError" />;
}
if (!value) {
return <FormattedMessage id="ui-users.errors.missingRequiredField" />;
}
}
resetDefaultDeliveryAddress() {
this.props.setFieldValue('requestPreferences.defaultDeliveryAddressTypeId', null);
}
onDeliveryCheckboxChange = (deliveryAvailable) => {
const { setFieldValue } = this.props;
const fulfillmentValue = deliveryAvailable ? deliveryFulfillmentValues.HOLD_SHELF : null;
setFieldValue('requestPreferences.fulfillment', fulfillmentValue);
this.resetDefaultDeliveryAddress();
}
render() {
const {
deliveryAvailable,
} = this.props;
return (
<Col xs={12}>
<Row>
<Col
xs={12}
md={6}
>
<Label tagName="div">
<span className={styles.heading}>
<FormattedMessage id="ui-users.requests.preferences" />
</span>
</Label>
</Col>
</Row>
<Row className={styles.rowMargin}>
<Col xs={12} md={6}>
<Field
data-test-hold-shelf-checkbox
name="requestPreferences.holdShelf"
label={<FormattedMessage id="ui-users.requests.holdShelf" />}
checked
disabled
component={Checkbox}
type="checkbox"
/>
</Col>
<Col xs={12} md={6}>
<Field
data-test-delivery-checkbox
name="requestPreferences.delivery"
label={<FormattedMessage id="ui-users.requests.delivery" />}
component={Checkbox}
type="checkbox"
/>
</Col>
</Row>
<Row>
<Col xs={12} md={6}>
{this.renderServicePointSelect()}
</Col>
<Col xs={12} md={6}>
{ deliveryAvailable && this.renderFulfillmentPreferenceSelect() }
</Col>
</Row>
<Row>
<Col mdOffset={6} xs={12} md={6}>
{ deliveryAvailable && this.renderDefaultDeliveryAddressSelect() }
</Col>
</Row>
</Col>
);
}
}
const selectServicePointsWithPickupLocation = fp.pipe([
fp.getOr([], 'folio_users_service_points.records'),
fp.filter(servicePoint => servicePoint.pickupLocation),
fp.uniqBy('id'),
fp.sortBy('name'),
]);
export default connect(
store => ({
servicePoints: selectServicePointsWithPickupLocation(store),
}),
)(injectIntl(RequestPreferencesEdit));
I'm tried to creating test cases for my react component
My test case is
import { render, screen, fireEvent, waitFor } from '#testing-library/react';
import { Form, Field } from 'react-final-form';
import userEvent from '#testing-library/user-event';
import PropTypes from 'prop-types';
import { StripesContext } from '#folio/stripes-core/src/StripesContext';
import '__mock__/stripesComponents.mock';
import renderWithRouter from 'helpers/renderWithRouter';
import { nullOrStringIsRequiredTypeValidator } from '../../../../customTypeValidators';
import RequestPreferencesEdit from './RequestPreferencesEdit';
jest.mock('react-redux', () => ({
connect: () => (ReactComponent) => ReactComponent,
}));
jest.unmock('#folio/stripes/components');
jest.unmock('#folio/stripes/smart-components');
const onSubmit = jest.fn();
const setFieldMock = jest.fn();
let mockrenderServicePointSelect = jest.fn();
let mockrenderFulfillmentPreferenceSelect = jest.fn();
let mockrenderDefaultDeliveryAddressSelect = jest.fn();
let mockUpdateHobbies;
const renderRequestPreferencesEdit = (props) => {
const component = () => (
<>
<RequestPreferencesEdit {...props} />
</>
);
renderWithRouter(
<Form
id="form-user"
onSubmit={onSubmit}
render={component}
renderServicePointSelect= {mockrenderServicePointSelect}
renderFulfillmentPreferenceSelect = {mockrenderFulfillmentPreferenceSelect}
renderDefaultDeliveryAddressSelect={mockrenderDefaultDeliveryAddressSelect}
/>,
<Field
id="form-user"
onSubmit={onSubmit}
render={component}
renderServicePointSelect= {mockrenderServicePointSelect}
renderFulfillmentPreferenceSelect = {mockrenderFulfillmentPreferenceSelect}
renderDefaultDeliveryAddressSelect={mockrenderDefaultDeliveryAddressSelect}
/>
);
};
const props = {
renderServicePointSelect: {mockrenderServicePointSelect},
renderFulfillmentPreferenceSelect: { mockrenderFulfillmentPreferenceSelect},
renderDefaultDeliveryAddressSelect: {mockrenderDefaultDeliveryAddressSelect},
accordionId: 'EditContactInfo',
expanded: true,
onToggle: jest.fn(),
setFieldValue: setFieldMock,
deliveryAvailable: true,
intl: { formatMessage : jest.fn() },
servicePoints: [
{
name: 'servicePointsName',
id: 'd003c876-90f1-40da-90bc-a5dd3dedb9c6a',
name2: 'servicenameDefault',
id1: ''
}
],
addresses: [{
addressType: 'Industrial Zone'
}],
addressTypes: [{
addressType: 'Home',
id: '123123'
},
{
addressType: 'Work',
id: '123123132'
}]
};
//const renderRequestPreferencesEdit1 = () => renderWithRouter(<RequestPreferencesEdit {...props} />);
describe('request preference point', () => {
it('Must be rendered request preferences', () => {
renderRequestPreferencesEdit(props);
screen.debug(undefined, Infinity);
expect(screen.getByText('ui-users.requests.preferences')).toBeTruthy();
});
it('Must be rendered', () => {
renderRequestPreferencesEdit(props);
expect(screen.getByText('ui-users.requests.selectDeliveryAddress')).toBeInTheDocument();
});
it('Must be rendered request null value', () => {
renderRequestPreferencesEdit(props);
//screen.debug(undefined, Infinity);
expect(document.querySelector('ui-users.errors.missingRequiredField')).toBeNull();
});
it('Checkbox selection', async () => {
renderRequestPreferencesEdit(props);
let options = document.querySelector('[name="requestPreferences.holdShelf"]');
userEvent.click(options);
userEvent.selectOptions(document.querySelector('[data-test-fulfillment-preference="true"]'), 'Hold Shelf');
expect(screen.findByDisplayValue('Hold Shelf')).toBeTruthy();
expect(options).toBeChecked();
});
it('Service PointsWith Pickup Location', () => {
renderRequestPreferencesEdit(props);
expect(screen.findByLabelText('folio_users_service_points.records"')).toBeTruthy();
});
it('text conatain * ', () => {
renderRequestPreferencesEdit(props);
expect(screen.getByText('*')).toBeInTheDocument();
});
it('Checkbox selection delevery', async () => {
renderRequestPreferencesEdit(props);
userEvent.click(document.querySelector('[name="requestPreferences.fulfillment"]'));
userEvent.selectOptions(document.querySelector('[data-test-fulfillment-preference="true"]'), 'Delivery');
expect(screen.findByDisplayValue('Delivery')).toBeTruthy();
});
it('Must have defaultPickupServicePoint text ', () => {
renderRequestPreferencesEdit(props);
expect(screen.getByText('ui-users.requests.defaultPickupServicePoint')).toBeInTheDocument();
});
it('Checkbox selection selectServicePoint', async () => {
renderRequestPreferencesEdit(props);
userEvent.click(document.querySelector('[name="requestPreferences.defaultServicePointId"]'));
userEvent.selectOptions(document.querySelector('[ class="selectControl formControl"]'), '');
expect(screen.findByDisplayValue('')).toBeTruthy();
expect(screen.getByText('ui-users.sp.selectServicePoint')).toBeInTheDocument();
});
it('Checkbox selection selectServicePoint value servicePointsName', async () => {
renderRequestPreferencesEdit(props);
userEvent.click(document.querySelector('[name="requestPreferences.defaultServicePointId"]'));
userEvent.selectOptions(document.querySelector('[class="selectControl formControl"]'), 'd003c876-90f1-40da-90bc-a5dd3dedb9c6a');
expect(screen.findByDisplayValue('d003c876-90f1-40da-90bc-a5dd3dedb9c6a')).toBeTruthy();
expect(screen.getByText('servicePointsName')).toBeInTheDocument();
});
it('Checkbox selection selectServicePoint value fulfillmentPreference', async () => {
renderRequestPreferencesEdit(props);
expect(screen.queryByLabelText('ui-users.requests.fulfillmentPreference')).toBeTruthy();
});
it('label value defaultDeliveryAddress must null', async () => {
renderRequestPreferencesEdit(props);
expect(screen.queryByLabelText('ui-users.requests.defaultDeliveryAddress')).toBeNull();
});
it('Checkbox selection selectDeliveryAddress', async () => {
renderRequestPreferencesEdit(props);
userEvent.click(document.querySelector('[name="requestPreferences.defaultDeliveryAddressTypeId"]'));
userEvent.selectOptions(document.querySelector('[class="selectControl placeholder formControl"]'), '');
expect(screen.findByDisplayValue('')).toBeTruthy();
});
it('Checkbox selection selectDeliveryAddress changing', async () => {
renderRequestPreferencesEdit(props);
fireEvent.change(document.querySelector('[name="requestPreferences.defaultDeliveryAddressTypeId"]', { target: { value: 2 } }))
let options = document.querySelector('[name="requestPreferences.defaultDeliveryAddressTypeId"]');
expect(screen.findByDisplayValue(2)).toBeTruthy();
expect(options[0].selected).toBeTruthy();
expect(options[1].selected).toBeFalsy();
});
});
I got 75% coverage only, can any one guide for improve my test cases
maybe it is a weird question, but I am new to unit testing, and can't wrap my head around this one.
import { Field, FieldInputProps, FieldMetaProps, FormikHelpers, FormikValues } from 'formik';
import Slider from 'components/elements/slider';
import FormError from 'components/elements/formerror';
import { useEffect, useState } from 'react';
interface IScheduleSlider {
min?: number;
max?: number;
title: string;
name: string;
unitLabel: string;
conversions: {
first: {
//eslint-disable-next-line
convertFct: (x: number) => number;
label: string;
};
second: {
//eslint-disable-next-line
convertFct: (x: number) => number;
label: string;
};
};
showError?: boolean;
}
const ScheduleSlider = ({ min = 0, max = 100, title, name, unitLabel, conversions, showError = false }: IScheduleSlider) => {
const [error, setError] = useState(false);
console.log(conversions);
useEffect(() => {
if (showError) {
setError(true);
}
}, [showError]);
const getRealValue = (val: number) => (val > max ? max : val);
return (
<Field name={name}>
{({
field,
form: { setFieldValue, setFieldTouched },
meta,
}: {
field: FieldInputProps<never>;
form: FormikHelpers<FormikValues>;
meta: FieldMetaProps<never>;
}) => (
<div className={`schedule-slider ${error ? 'error' : ''}`} data-testid="schedule-slider-test">
<div className="schedule-slider__top">
<h4>{title}</h4>
{typeof conversions?.first?.convertFct === 'function' && typeof conversions?.second?.convertFct === 'function' && (
<div>
<div className="schedule-slider__top--conversion">
<h5>{conversions?.first?.convertFct(field.value)}</h5>
<span>{conversions?.first?.label}</span>
</div>
<div className="schedule-slider__top--conversion">
<h5>{conversions?.second?.convertFct(field.value)}</h5>
<span>{conversions?.second?.label}</span>
</div>
</div>
)}
</div>
<div className="schedule-slider__bottom">
<Slider
max={Math.ceil(max)}
min={min}
value={Math.ceil(field.value)}
onChange={(val: number) => {
setFieldValue(field?.name, getRealValue(val));
setFieldTouched(field?.name, true);
setError(false);
}}
labels={{ left: `${min} ${unitLabel}`, right: `${max} ${unitLabel}` }}
/>
<div className="schedule-slider__value">
<div>
<h3 data-testid="field-test-value">{field.value}</h3>
<span>{unitLabel}</span>
</div>
</div>
</div>
{error && <FormError meta={meta} />}
</div>
)}
</Field>
);
};
export default ScheduleSlider;
This is my tsx file with the component, I have a ScheduleSlider component which in itself contains a formik component, and a react-slider, which has the onChange prop where setFieldValue and setFieldTouched is.
/* eslint-disable testing-library/no-container */
/* eslint-disable testing-library/no-node-access */
import ScheduleSlider from './scheduleslider';
import * as Formik from 'formik';
import { cleanup, fireEvent, render, screen, waitFor } from '#testing-library/react';
import React from 'react';
import userEvent from '#testing-library/user-event';
import { renderWithRedux } from 'test-utils';
describe('render ScheduleSlider', () => {
const mockFn = jest.fn();
const useFormikContextMock = jest.spyOn(Formik, 'useFormikContext');
beforeEach(() => {
useFormikContextMock.mockReturnValue({
setFieldValue: jest.fn(),
setFieldTouched: jest.fn(),
} as unknown as never);
});
afterEach(() => {
jest.clearAllMocks();
cleanup();
});
const defaultId = 'schedule-slider-test';
const sliderId = 'slider-test';
const fieldId = 'field-test-value';
it('render component with props', async () => {
const props = {
min: 0,
max: 100,
title: 'Test title',
name: 'POWER',
unitLabel: 'kWh',
conversions: {
first: {
convertFct: jest.fn().mockImplementation((x) => x),
label: '%',
},
second: {
convertFct: jest.fn().mockImplementation((x) => x),
label: 'km',
},
},
showError: false,
};
const { container } = renderWithRedux(
<Formik.Formik initialValues={{}} enableReinitialize onSubmit={mockFn}>
<ScheduleSlider {...props} />
</Formik.Formik>
);
// const slider = screen.queryByRole('slider');
const slider = screen.getByTestId(sliderId);
expect(container).toBeVisible();
props.conversions.first.convertFct.mockReturnValue('10');
props.conversions.second.convertFct.mockReturnValue('30');
// expect(slider).toBeVisible();
// expect(slider).toHaveClass('slider__thumb slider__thumb-0');
if (slider) {
slider.ariaValueMin = '1';
slider.ariaValueMax = '100';
// screen.getByTestId(fieldId).textContent = '80';
fireEvent.keyDown(slider, { key: 'ArrowLeft', code: 'ArrowLeft', charCode: 37 });
}
// expect(useFormikContextMock).toBeCalled();
// console.log(slider?.ariaValueMin);
// console.log(screen.getByTestId(fieldId).textContent);
console.log(props.conversions.second.convertFct.mock.results);
console.log(container.textContent);
});
it('render with default min, max, showError value', () => {
const props = {
min: undefined,
max: undefined,
title: 'test title',
name: 'schedule',
unitLabel: 'test unit',
conversions: {
first: {
convertFct: jest.fn(),
label: '%',
},
second: {
convertFct: jest.fn(),
label: 'km',
},
},
showError: true,
};
render(
<Formik.Formik initialValues={{}} enableReinitialize onSubmit={mockFn}>
<ScheduleSlider {...props} />
</Formik.Formik>
);
expect(screen.getByTestId(defaultId)).toBeVisible();
});
it('checks for onChange values', () => {
const props = {
min: 0,
max: 100,
title: 'test title',
name: 'schedule',
unitLabel: 'test unit',
conversions: {
first: {
convertFct: jest.fn(),
label: '%',
},
second: {
convertFct: jest.fn(),
label: 'km',
},
},
showError: undefined,
};
render(
<Formik.Formik initialValues={{}} enableReinitialize onSubmit={mockFn}>
<ScheduleSlider {...props} />
</Formik.Formik>
);
expect(screen.getByTestId(defaultId)).toBeVisible();
});
});
And this is my test file, I could render the component, and some of the branches, functions, statemnts are covered, but don't know how to test setFieldValue. Tried to fire events, but I am making some errors and can't see where. Anybody has any idea how to start with this. Sorry for the comments, console.log-s but I was tryng all kinds of solutions
I am using React Testing Library for first time and it seems very confusing. I am stuck on the error since long. I will be very grateful if someone proposes a solution to this problem
Here is my testfile:
import React from 'react';
import { cleanup, fireEvent, screen } from '#testing-library/react';
import { act } from 'react-dom/test-utils';
import { render } from '../../../test-util';
import EmailEditor from '../../../../components/commonComponents/EmailInput/EmailChip';
const mockFn = jest.fn();
const props={
salutation: '',
signature: '',
emailBody: '',
onChangeEmailBody: () => { },
onFocus: () => { },
onBlur: () => { },
disabled: false,
showSalutation: true,
showSignature: true,
allowVariables: false,
showPersonalize: false,
customParams: [],
recommendImgSize: '',
autoFocus: false,
allowFonts: true
}
describe('Email Editor Test cases', () => {
afterEach(cleanup);
it('Determining the ', async () => {
act(() => {
render(<EmailEditor {...props} /> );
});
const OnclickElement = screen.getByText(/Select Personalization Parameter/i)
expect(OnclickElement).toBeInTheDocument();
});
it('should render the button', async () => {
act(() => {
render(<EmailEditor {...props} /> );
});
const OnclickElement = screen.getByTestId(/custom/i)
expect(OnclickElement).toBeInTheDocument();
});
Here are some of the elements which are associated in index.js
<Header style={{ fontSize: window.innerWidth > MOBILE_WIDTH ? '1.15vw' : 12.15 }}>Select Personalization Parameter</Header>
<CustomToolbar key="customToolbar" show={allowVariables && showPersonalize} uniqueKey={uniqueKey} recommendImgSize={recommendImgSize} allowFonts={allowFonts} data-testid = "custom"/>
Please help me with this.
I'm beginner in react/redux and I came across a weird behaviour of my application
every try of dispatching action e.g.
store.dispatch({type: 'no_matter_what_is_here'});
remounting all components even if the state of store doesn't changed over and over and provides infinite rendering of component (component using 'connect' function from 'react-redux' library).
I'm using these libraries:
"dependencies": {
"babel-polyfill": "^6.3.14",
"bluebird": "^3.4.1",
"eventsource-polyfill": "^0.9.6",
"font-awesome-webpack": "0.0.4",
"history": "^4.7.2",
"lodash": "^4.17.4",
"material-ui": "^0.19.1",
"moment": "^2.13.0",
"prop-types": "^15.5.10",
"react": "^15.6.1",
"react-dom": "^15.6.1",
"react-dropzone": "^3.5.1",
"react-modal": "^1.4.0",
"react-redux": "^5.0.2",
"react-router": "^3.0.0",
"react-router-dom": "^4.2.2",
"react-router-redux": "^4.0.6",
"react-scripts": "1.0.13",
"react-tap-event-plugin": "^2.0.1",
"redux": "^3.6.0",
"superagent": "^3.1.0",
"uuid": "^3.0.1"
},
What is the cause of this behaviour?
Code of example component(but it's concern every components in application)
import React, { Component } from 'react';
import store from '../../store';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import _ from 'lodash';
import { CircularProgress } from 'material-ui';
import debounce from '../../modules/debounce';
import { JobAddDialog } from '../job';
import WorkdeckPanel from './workdeckPanel';
import QueuedJobList from './queuedJobList';
import { Label, WarningDialog, InfoDialog } from '../controls';
import { setupActions, jobActions } from '../../actions';
import {
connectTask,
reConnectTask,
cancelTask,
loadStatus,
startTask,
pauseTask,
stopTask,
skipTask,
retryTask,
} from '../../actions/printerActions';
import { getEnumName } from '../../modules/enumHelpers';
import { printerErrorTypeEnum, printerStatusEnum } from '../../constants';
class Status extends Component {
static get propTypes() {
return {
printer: PropTypes.shape({
status: PropTypes.number.isRequired,
}),
jobs: PropTypes.shape({
list: PropTypes.array.isRequired,
}).isRequired,
resources: PropTypes.shape({}).isRequired,
};
}
static get defaultProps() {
return {
printer: {},
jobs: {
list: [],
},
};
}
constructor(props) {
super(props);
this.state = {
showAddDialog: false,
showConfirm: false,
showStop: false,
selectedJobId: null,
};
this.onJobSelected = this.onJobSelected.bind(this);
this.onStatusLoaded = this.onStatusLoaded.bind(this);
}
componentWillMount() {
store.dispatch({type: 'no_matter_what'});
}
componentDidUpdate() {
const { printer } = this.props;
const { showAddDialog } = this.state;
const { isLoading, status } = (printer || {});
if (!isLoading && !showAddDialog
&& [printerStatusEnum.notResponding, printerStatusEnum.confirming, printerStatusEnum.suspended].indexOf(status) === -1) {
debounce(this.onStatusLoaded, 1000);
}
}
onStatusLoaded() {
const { jobs, printer } = this.props;
loadStatus(printer.updateDate)
.then((res) => {
const job = Object.assign({ id: -1 }, printer.job);
const newJob = res.job ? _.find(jobs.list, { id: res.job.id }) : { id: -1 };
if (newJob.id !== job.id) {
return jobActions.loadJobs();
}
return null;
});
}
onJobSelected(selectedJobId) {
this.setState({ selectedJobId });
}
render() {
const { jobs, printer, resources } = this.props;
const { selectedJobId, showAddDialog, showConfirm, showStop } = this.state;
return (
<div className="statusContainer">
<QueuedJobList {...{
jobs, selectedJobId, onJobSelect: this.onJobSelected, onJobAdd: () => { this.setState({ showAddDialog: true }); },
}}
/>
<WorkdeckPanel {...{ jobs,
printer,
selectedJobId,
resources,
onStartClick: () => {
if (printer.job && printer.status === printerStatusEnum.suspended) {
this.setState({ showConfirm: true });
} else {
startTask();
}
},
onStopClick: () => { this.setState({ showStop: true }); },
}}
/>
{ [printerStatusEnum.initializing].indexOf(printer.status) !== -1
? (<InfoDialog {...{
title: resources.get('device.connecting.title'),
show: true,
onCancel: cancelTask }}
>
<div className="iconProgress"><CircularProgress thickness={5} /></div>
<h3 className="textAlert">
<Label path="device.connecting.note" />
</h3>
</InfoDialog>)
: null }
<JobAddDialog {...{
show: showAddDialog,
isQueued: true,
onClose: () => { this.setState({ showAddDialog: false }); },
}}
/>
<ConfirmDialog {...{ printer, showConfirm, onHide: () => { this.setState({ showConfirm: false }); }, resources }} />
<NotRespondingDialog {...this.props} />
<ErrorDialog {...{ showStop, onCancel: () => { this.setState({ showStop: true }); }, printer, resources }} />
<StopDialog {...{ show: showStop, onClose: () => { this.setState({ showStop: false }); }, resources }} />
</div>
);
}
}
const ConfirmDialog = ({ printer, showConfirm, onHide, resources }) => {
const { status, method } = printer;
let onCancel = onHide;
let show = showConfirm;
if (status === printerStatusEnum.confirming) {
onCancel = () => {
onHide();
cancelTask();
};
show = true;
}
if (show) {
return (
<InfoDialog {...{
title: resources.get('device.confirming.title'),
okCaption: resources.get('buttons.continue'),
show,
onCancel,
onOk: () => {
onHide();
startTask();
},
}}
>
<Label {...{ path: 'device.confirming.note', replacements: method }} />
</InfoDialog>);
}
return null;
};
const NotRespondingDialog = (props) => {
const { resources, printer } = props;
if (printer.status === printerStatusEnum.notResponding) {
return (
<WarningDialog {...{
title: resources.get('device.notResponding.title'),
okCaption: resources.get('buttons.retry'),
show: true,
buttons: [
{ type: 'Cancel', onClick: cancelTask },
{ type: 'Retry', onClick: reConnectTask, isPrimary: true },
] }}
>
<Label path="device.notResponding.note" />
</WarningDialog>);
}
return null;
};
const ErrorDialog = ({ showStop, onCancel, printer, resources }) => {
const { status, errorType } = printer;
if (status === printerStatusEnum.inError && !showStop) {
const error = getEnumName(printerErrorTypeEnum, errorType);
let buttons = [
{ type: 'Ok', onClick: pauseTask, isPrimary: true },
];
if (errorType === printerErrorTypeEnum.tubeError) {
buttons = [
{ type: 'Cancel', onClick: onCancel },
{ type: 'Skip', onClick: skipTask },
{ type: 'Retry', onClick: retryTask, isPrimary: true },
];
}
return (
<WarningDialog {...{
title: resources.get(`device.${error}.title`),
show: true,
buttons }}
>
<Label {...{ path: `device.${error}.note` }} />
</WarningDialog>);
}
return null;
};
const StopDialog = ({ show, onClose, resources }) => {
if (show) {
return (
<WarningDialog {...{
title: resources.get('device.stopping.title'),
show: true,
buttons: [
{ type: 'Cancel', onClick: onClose },
{ type: 'Ok', onClick: () => { stopTask().then(() => { onClose(); }); }, isPrimary: true },
] }}
>
<Label className="textInfo" path="device.stopping.note" />
</WarningDialog>);
}
return null;
};
export default connect(
state => ({
jobs: state.jobs,
printer: state.printer,
resources: state.resources,
}),
)(Status);
First of all you should split this code into Presentational Componentes and Containers. Containers keep the logic and the connect with your store. This would make your code less error prone and easier to read.
Regarding your issue you are make this this dispatch store.dispatch({type: 'no_matter_what'}); on componentWillMount. It isn't a good practise as you can read here. I'd recommend you to remove it from there.
Also, I'd look into those bindings you have there. Try to understand if you really need them as they are atm. I don't have enough knowledge but I'd look into this article which is pretty nice (not perfect though).
In this case, I suggest you to use arrow functions and make sure you need this onStatusLoaded binding. You are binding it in the constructor and inside onStatusLoaded you seem to be updating status again every time your component updates, which will cause a cycle.
Your mistake likely in componentDidUpdate method, you need to console each step all values in conditions to catch permament reconcollation:
import React from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { compose } from 'recompose'
import { startWorkflow } from 'wf-dbd-react-ui/es/actions'
import Block from 'wf-dbd-react-ui/es/Block'
import BrowserTitle from 'wf-dbd-react-ui/es/BrowserTitle'
import ScrollToTopOnMount from 'wf-dbd-react-ui/es/ScrollToTopOnMount'
import FormMessages from 'wf-dbd-react-ui/es/FormMessages'
import { globals } from 'wf-dbd-react-ui/es/lib'
import withStrings from 'wf-dbd-react-ui/es/withStrings'
import PanelHeader from './panel-header/PanelHeader'
import AppHubTabs from './app-hub-tabs/AppHubTabs'
import RightRail from '../right-rail/RightRail'
import MessageDisplay from '../common/message-display/MessageDisplay'
import AddPayeeMessage from '../common/add-payee-message/AddPayeeMessage'
import { ADD_PAYEE, SEARCH_PAYEE } from '../workflows/add-payee/constants'
import ChangeFundingAccount from '../common/change-funding-account/ChangeFundingAccount'
import EditPaymentHotTaskModalContainer from '../common/hottask-edit-payment-modal/EditPaymentHotTaskModalContainer'
import DismissReminder from '../common/dismiss-reminder-modal/DismissReminder'
import HistoryTabViewPaymentDetailsModal from '../history-tab/group-history-form/history-tab-hot-task-menu/HistoryTabViewPaymentDetailsModal'
import * as actions from '../../lib/store/hub/actions'
import { getPayeeDetails } from '../../lib/store/payee-details/actions'
import { getPaymentDetails } from '../../lib/store/payment-details/actions'
import { resetPayeeTabFilterOption } from '../../lib/store/payees/actions'
import { closeViewPaymentDetailsModal } from '../../lib/store/history-tab/actions'
import { getHistoricalPayments } from '../../lib/selectors/selectors'
import styles from './AppHub.less'
class AppHub extends React.Component {
componentDidMount() {
const { getPayeeDetails, getPaymentDetails } = this.props
// payee details need to be fetched unconditionally. the cache in saga ensures it is not fetched until required
getPayeeDetails()
getPaymentDetails()
// Fix for for wide page layout issue in ie11 - Problem: ie11 nested flex element issue when window is minimized
Iif (!!window.MSInputMethodContext && !!document.documentMode) { // will be true for only for ie11 browser
document.querySelector('body > div > div > div > div').style.flexBasis = '0%'
}
// end of fix for ie11 wide page layout issue
}
componentWillUnmount() {
const { clearMessages, resetPayeeTabFilterOption } = this.props
clearMessages()
//clearing the selected payees-tab filter option
resetPayeeTabFilterOption()
}
handleTabSelect = activeTabIndexNew => {
const { clearMessages, activeTabIndex, setActiveTabIndex } = this.props
if (activeTabIndexNew !== activeTabIndex) {
setActiveTabIndex(activeTabIndexNew)
clearMessages()
}
}
render() {
const { activeTabIndex,
getString,
successMessage,
errorMessage,
ineligibleAccountMessage,
payees,
noOfHistoricalPayments,
payeesLoaded,
startAddPayeeWorkflow,
shouldShowChangeAccount,
reminderDismissalInProgress,
reminderDueDate,
closeViewPaymentDetailsModal,
isViewPaymentDetailsModalOpen,
viewPaymentData,
showEditPaymentSeriesModal
} = this.props
const panelHeaderId = globals().billpayBusinessUser ? 'app.hub.business.bill.pay.header' : 'app.hub.bill.pay.header'
return (
<Block layout={true} horizontal={true}>
<BrowserTitle title={getString('app.title')} />
<ScrollToTopOnMount />
<Block flex={true} relative={true} className={styles.billPayHub}>
<PanelHeader headerId={panelHeaderId} />
{
successMessage &&
<Block className={styles.message}>
<MessageDisplay messages={successMessage} />
</Block>
}
{
errorMessage &&
<Block className={styles.message}>
<MessageDisplay messages={errorMessage} />
</Block>
}
{
ineligibleAccountMessage && globals().enableDisplayPayeesWithIneligibleAccounts &&
<Block className={styles.message}>
<MessageDisplay messages={ineligibleAccountMessage} focusOnMount={true} />
</Block>
}
<Block className={styles.message}>
<FormMessages formId="makePaymentForm" className="formMessages" />
</Block>
{payeesLoaded && payees.size === 0 && <AddPayeeMessage startAddPayeeWorkflow={startAddPayeeWorkflow} />}
{payeesLoaded && (payees.size > 0 || noOfHistoricalPayments > 0) && (
<AppHubTabs
activeTabIndex={activeTabIndex}
onTabSelect={this.handleTabSelect}
/>
)
}
</Block>
<Block relative={true} styles={styles.rightRailContainer}>
<RightRail />
</Block>
{shouldShowChangeAccount && <ChangeFundingAccount />}
{showEditPaymentSeriesModal && <EditPaymentHotTaskModalContainer />}
{reminderDismissalInProgress && <DismissReminder dueDate={reminderDueDate} />}
{isViewPaymentDetailsModalOpen &&
<HistoryTabViewPaymentDetailsModal
isOpen={isViewPaymentDetailsModalOpen}
closeModal={closeViewPaymentDetailsModal}
viewPaymentData={viewPaymentData}
/>
}
</Block>
)
}
}
AppHub.propTypes = {
activeTabIndex: PropTypes.number.isRequired,
payees: PropTypes.object.isRequired,
noOfHistoricalPayments: PropTypes.number.isRequired,
payeesLoaded: PropTypes.bool,
startAddPayeeWorkflow: PropTypes.func.isRequired,
errorMessage: PropTypes.object,
successMessage: PropTypes.object,
shouldShowChangeAccount: PropTypes.bool,
resetPayeeTabFilterOption: PropTypes.func.isRequired,
getPayeeDetails: PropTypes.func.isRequired,
getPaymentDetails: PropTypes.func.isRequired,
clearMessages: PropTypes.func.isRequired,
setActiveTabIndex: PropTypes.func.isRequired,
getString: PropTypes.func.isRequired,
reminderDismissalInProgress: PropTypes.bool,
reminderDueDate: PropTypes.string,
closeViewPaymentDetailsModal: PropTypes.func.isRequired,
isViewPaymentDetailsModalOpen: PropTypes.bool,
viewPaymentData: PropTypes.object,
showEditPaymentSeriesModal: PropTypes.func.isRequired,
ineligibleAccountMessage: PropTypes.object
}
const mapStateToProps = state => ({
activeTabIndex: state.app.hub.activeHubTab,
successMessage: state.app.hub.successMessage,
errorMessage: state.app.hub.errorMessage,
ineligibleAccountMessage: state.app.hub.ineligibleAccountMessage,
payees: state.app.payees.payees,
noOfHistoricalPayments: getHistoricalPayments(state),
payeesLoaded: state.app.payees.payeesLoaded,
shouldShowChangeAccount: state.app.hub.showChangeAccount,
showEditPaymentSeriesModal: state.app.editPayment.editPaymentModal.isModalOpen,
reminderDismissalInProgress: state.app.hub.reminderDismissalInProgress,
reminderDueDate: state.app.hub.reminderDueDate,
isViewPaymentDetailsModalOpen: state.app.historyTab.isViewPaymentDetailsModalOpen,
viewPaymentData: state.app.historyTab.viewPaymentDetails
})
const mapDispatchToProps = dispatch => ({
setActiveTabIndex: index => dispatch(actions.setHubActiveTab(index)),
clearMessages: () => dispatch(actions.clearMessages()),
startAddPayeeWorkflow: () => dispatch(startWorkflow({ name: ADD_PAYEE, startingView: SEARCH_PAYEE })),
getPayeeDetails: () => dispatch(getPayeeDetails()),
getPaymentDetails: () => dispatch(getPaymentDetails()),
resetPayeeTabFilterOption: () => dispatch(resetPayeeTabFilterOption()),
closeViewPaymentDetailsModal: () => dispatch(closeViewPaymentDetailsModal())
})
export default compose(withStrings, connect(mapStateToProps, mapDispatchToProps))(AppHub)
iamtryingtofindasolutionpleasehelp.iamtryingtofindasolutionpleasehelp.iamtryingtofindasolutionpleasehelp.iamtryingtofindasolutionpleasehelp.iamtryingtofindasolutionpleasehelp.iamtryingtofindasolutionpleasehelp.iamtryingtofindasolutionpleasehelp.iamtryingtofindasolutionpleasehelp.iamtryingtofindasolutionpleasehelp.iamtryingtofindasolutionpleasehelp.iamtryingtofindasolutionpleasehelp.iamtryingtofindasolutionpleasehelp.iamtryingtofindasolutionpleasehelp.iamtryingtofindasolutionpleasehelp.iamtryingtofindasolutionpleasehelp.iamtryingtofindasolutionpleasehelp.iamtryingtofindasolutionpleasehelp.iamtryingtofindasolutionpleasehelp.iamtryingtofindasolutionpleasehelp.iamtryingtofindasolutionpleasehelp.iamtryingtofindasolutionpleasehelp.iamtryingtofindasolutionpleasehelp.iamtryingtofindasolutionpleasehelp.iamtryingtofindasolutionpleasehelp.iamtryingtofindasolutionpleasehelp.
import React from 'react'
import { mount } from 'enzyme'
import MockStoreProvider from 'wf-dbd-react-ui/es/MockStoreProvider'
import Immutable from 'immutable'
import AppHub from '../AppHub'
import AppHubTabs from '../app-hub-tabs/AppHubTabs'
import AddPayeeMessage from '../../common/add-payee-message/AddPayeeMessage'
import PanelHeader from '../panel-header/PanelHeader'
jest.mock('../panel-header/PanelHeader', () => () => 'PanelHeader')
jest.mock('../app-hub-tabs/AppHubTabs', () => () => 'AppHubTabs')
jest.mock('../../common/add-payee-message/AddPayeeMessage', () => () => 'AddPayeeMessage')
jest.mock('../../common/message-display/MessageDisplay', () => () => 'MessageDisplay')
jest.mock('../../right-rail/RightRail', () => () => 'RightRail')
jest.mock('../../history-tab/group-history-form/history-tab-hot-task-menu/HistoryTabViewPaymentDetailsModal', () => () => 'HistoryTabViewPaymentDetailsModal')
describe('AppHub', () => {
let wrapper
describe('when rendered without any payees and payments', () => {
beforeEach(() => {
const getString = jest.fn().mockImplementation(() => 'testString')
const appState = {
hub: {
activeHubTab: 0,
successMessage: { SuccessMessageBean: { globalMessages: [{ level: 'confirm', message: 'message' }] } },
errorMessage: {}
},
payees: {
payees: Immutable.List([]),
enableSubmitBar: false,
payeesLoaded: true
},
paymentAccounts: {
paymentAccounts: Immutable.List([]),
enableSubmitBar: false
},
scheduledPayments: {
paymentsLoaded: false
},
historyTab: {
isViewPaymentDetailsModalOpen: true,
viewPaymentDetails: { key: 'value' },
historicalPayments: {
payments: []
}
},
editPayment: {
editPaymentModal: {
isModalOpen: false
}
}
}
wrapper = mount(
<MockStoreProvider appState={appState}>
<AppHub getString={getString} />
</MockStoreProvider>
)
})
it('should be defined', () => {
expect(AppHub).toBeDefined()
})
it('should render a PanelHeader', () => {
expect(wrapper.find(PanelHeader)).toHaveLength(1)
})
it('should render AddPayeeMessage', () => {
expect(wrapper.find(AddPayeeMessage)).toHaveLength(1)
})
})
describe('when rendered without any payees and historical payments are present', () => {
beforeEach(() => {
const getString = jest.fn().mockImplementation(() => 'testString')
const appState = {
hub: {
activeHubTab: 0,
successMessage: { SuccessMessageBean: { globalMessages: [{ level: 'confirm', message: 'message' }] } },
errorMessage: {}
},
payees: {
payees: Immutable.List([]),
enableSubmitBar: false,
payeesLoaded: true
},
paymentAccounts: {
paymentAccounts: Immutable.List([]),
enableSubmitBar: false
},
scheduledPayments: {
paymentsLoaded: false
},
historyTab: {
isViewPaymentDetailsModalOpen: true,
viewPaymentDetails: { key: 'value' },
historicalPayments: {
payments: [{
mockKey: 'mockValue'
}]
}
},
editPayment: {
editPaymentModal: {
isModalOpen: false
}
}
}
wrapper = mount(
<MockStoreProvider appState={appState}>
<AppHub getString={getString} />
</MockStoreProvider>
)
})
it('should render AppHubTabs', () => {
expect(wrapper.find(AppHubTabs)).toHaveLength(1)
})
it('should render AddPayeeMessage', () => {
expect(wrapper.find(AddPayeeMessage)).toHaveLength(1)
})
})
describe('when rendered with payees and there are no historical payments', () => {
beforeEach(() => {
const getString = jest.fn().mockImplementation(() => 'testString')
const appState = {
hub: {
activeHubTab: 0,
successMessage: { SuccessMessageBean: { globalMessages: [{ level: 'confirm', message: 'message' }] } },
errorMessage: {}
},
payees: {
payees: Immutable.List([{ id: 1 }]),
enableSubmitBar: false,
payeesLoaded: true
},
paymentAccounts: {
paymentAccounts: Immutable.List([]),
enableSubmitBar: false
},
scheduledPayments: {
paymentsLoaded: false
},
historyTab: {
isViewPaymentDetailsModalOpen: true,
viewPaymentDetails: { key: 'value' },
historicalPayments: {
payments: []
}
},
editPayment: {
editPaymentModal: {
isModalOpen: false
}
}
}
wrapper = mount(
<MockStoreProvider appState={appState}>
<AppHub getString={getString} />
</MockStoreProvider>
)
})
it('should render AppHubTabs', () => {
expect(wrapper.find(AppHubTabs)).toHaveLength(1)
})
it('should render AddPayeeMessage', () => {
expect(wrapper.find(AddPayeeMessage)).toHaveLength(0)
})
})
})