Skip to content

Commit

Permalink
Scheduler tests (jest/enzyme) (#3269)
Browse files Browse the repository at this point in the history
* Setup enzyme and initial ScheduleDialog test

* Added tests for each schedule setting

* Added refreshOptions tests

* Added count out-of-range tests

* Added modal confirm/cancel tests

* Fixed tests failing due to server timezone difference

* Rebased to master
  • Loading branch information
ranbena authored and arikfr committed Jan 13, 2019
1 parent 26252be commit 90a0a7d
Show file tree
Hide file tree
Showing 7 changed files with 3,623 additions and 16 deletions.
4 changes: 4 additions & 0 deletions client/app/__tests__/enzyme_setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';

configure({ adapter: new Adapter() });
5 changes: 5 additions & 0 deletions client/app/__tests__/mocks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import MockDate from 'mockdate';

const date = new Date('2000-01-01T02:00:00.000');

MockDate.set(date);
32 changes: 17 additions & 15 deletions client/app/components/queries/ScheduleDialog.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const DATE_FORMAT = 'YYYY-MM-DD';
const HOUR_FORMAT = 'HH:mm';
const { Option, OptGroup } = Select;

class ScheduleDialog extends React.Component {
export class ScheduleDialog extends React.Component {
static propTypes = {
show: PropTypes.bool.isRequired,
// eslint-disable-next-line react/forbid-prop-types
Expand Down Expand Up @@ -178,7 +178,7 @@ class ScheduleDialog extends React.Component {
>
<div className="schedule-component" ref={this.modalRef}>
<h5>Refresh every</h5>
<div>
<div data-testid="interval">
<Select value={seconds} onChange={this.setInterval} {...selectProps}>
<Option value={null} key="never">Never</Option>
{Object.keys(this.intervals).map(int => (
Expand All @@ -194,7 +194,7 @@ class ScheduleDialog extends React.Component {
{[IntervalEnum.DAYS, IntervalEnum.WEEKS].indexOf(interval) !== -1 ? (
<div className="schedule-component">
<h5>On time</h5>
<div>
<div data-testid="time">
<TimePicker
allowEmpty={false}
defaultValue={moment().hour(hour).minute(minute)}
Expand All @@ -209,23 +209,25 @@ class ScheduleDialog extends React.Component {
{IntervalEnum.WEEKS === interval ? (
<div className="schedule-component">
<h5>On day</h5>
<Radio.Group
size="medium"
defaultValue={this.state.dayOfWeek}
onChange={this.setWeekday}
>
{WEEKDAYS_SHORT.map(day => (
<Radio.Button value={day} key={day} className="input">
{day[0]}
</Radio.Button>
))}
</Radio.Group>
<div data-testid="weekday">
<Radio.Group
size="medium"
defaultValue={this.state.dayOfWeek}
onChange={this.setWeekday}
>
{WEEKDAYS_SHORT.map(day => (
<Radio.Button value={day} key={day} className="input">
{day[0]}
</Radio.Button>
))}
</Radio.Group>
</div>
</div>
) : null}
{interval !== IntervalEnum.NEVER ? (
<div className="schedule-component">
<h5>Ends</h5>
<div className="ends">
<div className="ends" data-testid="ends">
<Radio.Group
size="medium"
value={!!until}
Expand Down
205 changes: 205 additions & 0 deletions client/app/components/queries/ScheduleDialog.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
import React from 'react';
import { mount } from 'enzyme';
import { ScheduleDialog } from './ScheduleDialog';

const defaultProps = {
show: true,
query: {
schedule: {
time: null,
until: null,
interval: null,
day_of_week: null,
},
},
refreshOptions: [
60, 300, 600, // 1, 5 ,10 mins
3600, 36000, 82800, // 1, 10, 23 hours
86400, 172800, 518400, // 1, 2, 6 days
604800, 1209600, // 1, 2, 4 weeks
],
updateQuery: () => {},
onClose: () => {},
};

function getWrapper(schedule = {}, props = {}) {
const defaultSchedule = defaultProps.query.schedule;
props = Object.assign(
{},
defaultProps,
props,
{ query: { schedule: Object.assign({}, defaultSchedule, schedule) } },
);
return [mount(<ScheduleDialog {...props} />), props];
}

function findByTestID(wrapper, id) {
return wrapper.find(`[data-testid="${id}"]`);
}

describe('ScheduleDialog', () => {
describe('Sets correct schedule settings', () => {
test('Sets to "Never"', () => {
const [wrapper] = getWrapper();
const el = findByTestID(wrapper, 'interval');
expect(el).toMatchSnapshot();
});

test('Sets to "5 Minutes"', () => {
const [wrapper] = getWrapper({ interval: 300 });
const el = findByTestID(wrapper, 'interval');
expect(el).toMatchSnapshot();
});

test('Sets to "2 Hours"', () => {
const [wrapper] = getWrapper({ interval: 7200 });
const el = findByTestID(wrapper, 'interval');
expect(el).toMatchSnapshot();
});

describe('Sets to "1 Day 22:15"', () => {
const [wrapper] = getWrapper({
interval: 86400,
time: '22:15',
});

test('Sets to correct interval', () => {
const el = findByTestID(wrapper, 'interval');
expect(el).toMatchSnapshot();
});

test('Sets to correct time', () => {
const el = findByTestID(wrapper, 'time');
expect(el).toMatchSnapshot();
});
});

describe('Sets to "2 Weeks 22:15 Tuesday"', () => {
const [wrapper] = getWrapper({
interval: 1209600,
time: '22:15',
day_of_week: 2,
});

test('Sets to correct interval', () => {
const el = findByTestID(wrapper, 'interval');
expect(el).toMatchSnapshot();
});

test('Sets to correct time', () => {
const el = findByTestID(wrapper, 'time');
expect(el).toMatchSnapshot();
});

test('Sets to correct weekday', () => {
const el = findByTestID(wrapper, 'weekday');
expect(el).toMatchSnapshot();
});
});

describe('Until feature', () => {
test('Until not set', () => {
const [wrapper] = getWrapper({ interval: 300 });
const el = findByTestID(wrapper, 'ends');
expect(el).toMatchSnapshot();
});

test('Until is set', () => {
const [wrapper] = getWrapper({ interval: 300, until: '2030-01-01' });
const el = findByTestID(wrapper, 'ends');
expect(el).toMatchSnapshot();
});
});
});

describe('Adheres to user permissions', () => {
test('Shows correct interval options', () => {
const refreshOptions = [60, 300, 3600, 7200]; // 1 min, 1 hour
const [wrapper] = getWrapper(null, { refreshOptions });

// click select
findByTestID(wrapper, 'interval')
.find('.ant-select')
.simulate('click');

// get dropdown menu items
const options = mount(wrapper
.find('Trigger')
.instance()
.getComponent())
.find('MenuItem');

const texts = options.map(node => node.text());
const expected = ['Never', '1 minute', '5 minutes', '1 hour', '2 hours'];

// eslint-disable-next-line jest/prefer-to-have-length
expect(options.length).toEqual(expected.length);
expect(texts).toEqual(expected);
});
});

describe('Modal Confirm/Cancel feature', () => {
const confirmCb = jest.fn().mockName('confirmCb');
const closeCb = jest.fn().mockName('closeCb');
const initProps = { updateQuery: confirmCb, onClose: closeCb };

beforeEach(() => {
jest.clearAllMocks();
});

test('Query saved on confirm if state changed', () => {
// init
const [wrapper, props] = getWrapper(null, initProps);

// change state
const change = { time: '22:15' };
const newSchedule = Object.assign({}, props.schedule, change);
wrapper.setState({ newSchedule });

// click confirm button
wrapper
.find('.ant-modal-footer')
.find('.ant-btn-primary')
.simulate('click');

// expect calls
expect(confirmCb).toBeCalled();
expect(closeCb).toBeCalled();
});

test('Query not saved on confirm if state unchanged', () => {
// init
const [wrapper] = getWrapper(null, initProps);

// click confirm button
wrapper
.find('.ant-modal-footer')
.find('.ant-btn-primary')
.simulate('click');

// expect calls
expect(confirmCb).not.toBeCalled();
expect(closeCb).toBeCalled();
});

test('Cancel closes modal and query unsaved', () => {
// init
const [wrapper, props] = getWrapper(null, initProps);

// change state
const change = { time: '22:15' };
const newSchedule = Object.assign({}, props.schedule, change);
wrapper.setState({ newSchedule });

// click cancel button
wrapper
.find('.ant-modal-footer')
.find('button:not(.ant-btn-primary)')
.simulate('click');

// expect calls
expect(confirmCb).not.toBeCalled();
expect(closeCb).toBeCalled();
});
});
});
Loading

0 comments on commit 90a0a7d

Please sign in to comment.