/* eslint-disable max-lines */
import React from 'react';
import { Provider } from 'react-redux';
import configureMockStore from 'redux-mock-store';
import { fireEvent, screen, render, act } from '@testing-library/react';
import * as api from 'foremanReact/redux/API';
import { JobWizard } from '../../../JobWizard';
import * as selectors from '../../../JobWizardSelectors';
import { jobTemplate, jobTemplateResponse } from '../../../__tests__/fixtures';
const lodash = require('lodash');
lodash.debounce = fn => fn;
jest.spyOn(api, 'get');
jest.spyOn(selectors, 'selectJobTemplate');
jest.spyOn(selectors, 'selectJobTemplates');
jest.spyOn(selectors, 'selectJobCategories');
const jobCategories = ['Ansible Commands', 'Puppet', 'Services'];
selectors.selectJobCategories.mockImplementation(() => jobCategories);
selectors.selectJobTemplates.mockImplementation(() => [
jobTemplate,
{ ...jobTemplate, id: 2, name: 'template2' },
]);
selectors.selectJobTemplate.mockImplementation(() => jobTemplateResponse);
api.get.mockImplementation(({ handleSuccess, ...action }) => {
if (action.key === 'JOB_CATEGORIES') {
handleSuccess && handleSuccess({ data: { job_categories: jobCategories } });
} else if (action.key === 'JOB_TEMPLATE') {
handleSuccess &&
handleSuccess({
data: jobTemplateResponse,
});
} else if (action.key === 'JOB_TEMPLATES') {
handleSuccess &&
handleSuccess({
data: { results: [jobTemplateResponse.job_template] },
});
}
return { type: 'get', ...action };
});
const mockStore = configureMockStore([]);
const store = mockStore({});
jest.useFakeTimers();
describe('Schedule', () => {
it('should save date time between steps ', async () => {
render(
);
await act(async () => {
fireEvent.click(screen.getByText('Schedule'));
});
const newStartDate = '2020/03/12';
const newStartTime = '12:03';
const newEndsDate = '2030/03/12';
const newEndsTime = '17:34';
const startsDateField = screen.getByLabelText('starts at datepicker');
const endsDateField = screen.getByLabelText('ends datepicker');
const startsTimeField = screen.getByLabelText('starts at timepicker');
const endsTimeField = screen.getByLabelText('ends timepicker');
const staticQuery = screen.getByLabelText('Static query');
const dynamicQuery = screen.getByLabelText('Dynamic query');
const purpose = screen.getByLabelText('purpose');
const newPurposeLabel = 'some fun text';
expect(staticQuery.checked).toBeTruthy();
await act(async () => {
await fireEvent.change(startsDateField, {
target: { value: newStartDate },
});
await fireEvent.change(startsTimeField, {
target: { value: newStartTime },
});
await fireEvent.change(purpose, {
target: { value: newPurposeLabel },
});
await fireEvent.change(endsDateField, { target: { value: newEndsDate } });
await fireEvent.change(endsTimeField, { target: { value: newEndsTime } });
await fireEvent.click(dynamicQuery);
jest.runAllTimers(); // to handle pf4 date picker popover useTimer
});
await act(async () => {
fireEvent.click(screen.getByText('Category and Template'));
});
expect(screen.getAllByText('Category and Template')).toHaveLength(3);
await act(async () => {
fireEvent.click(screen.getByText('Schedule'));
jest.runAllTimers();
});
expect(startsDateField.value).toBe(newStartDate);
expect(startsTimeField.value).toBe(newStartTime);
expect(endsDateField.value).toBe(newEndsDate);
expect(endsTimeField.value).toBe(newEndsTime);
expect(dynamicQuery.checked).toBeTruthy();
expect(purpose.value).toBe(newPurposeLabel);
});
it('should remove start date time on execute now', async () => {
render(
);
await act(async () => {
fireEvent.click(screen.getByText('Schedule'));
});
const executeNow = screen.getByLabelText('Execute now');
const executeFuture = screen.getByLabelText(
'Schedule for future execution'
);
expect(executeNow.checked).toBeTruthy();
const newStartDate = '2020/03/12';
const newStartTime = '12:03';
const startsDateField = screen.getByLabelText('starts at datepicker');
const startsTimeField = screen.getByLabelText('starts at timepicker');
await act(async () => {
await fireEvent.change(startsDateField, {
target: { value: newStartDate },
});
await fireEvent.change(startsTimeField, {
target: { value: newStartTime },
});
await jest.runOnlyPendingTimers();
});
expect(startsDateField.value).toBe(newStartDate);
expect(startsTimeField.value).toBe(newStartTime);
expect(executeFuture.checked).toBeTruthy();
await act(async () => {
await fireEvent.click(executeNow);
jest.runAllTimers();
});
expect(executeNow.checked).toBeTruthy();
expect(startsDateField.value).toBe('');
expect(startsTimeField.value).toBe('');
});
it('should disable end date on never ends', async () => {
render(
);
await act(async () => {
await fireEvent.click(screen.getByText('Schedule'));
jest.runAllTimers();
});
const neverEnds = screen.getByLabelText('Never ends');
expect(neverEnds.checked).toBeFalsy();
const endsDateField = screen.getByLabelText('ends datepicker');
const endsTimeField = screen.getByLabelText('ends timepicker');
fireEvent.click(
screen.getByLabelText('Does not repeat', { selector: 'button' })
);
await act(async () => {
fireEvent.click(screen.getByText('Cronline'));
});
expect(endsDateField.disabled).toBeFalsy();
expect(endsTimeField.disabled).toBeFalsy();
await act(async () => {
fireEvent.click(neverEnds);
});
expect(neverEnds.checked).toBeTruthy();
expect(endsDateField.disabled).toBeTruthy();
expect(endsTimeField.disabled).toBeTruthy();
});
it('should change between repeat on states', async () => {
render(
);
await act(async () => {
fireEvent.click(screen.getByText('Schedule'));
jest.runAllTimers(); // to handle pf4 date picker popover useTimer
});
expect(
screen.getByPlaceholderText('Repeat N times').hasAttribute('disabled')
).toBeTruthy();
expect(screen.getByText('Review Details').disabled).toBeFalsy();
await act(async () => {
fireEvent.click(
screen.getByLabelText('Does not repeat', { selector: 'button' })
);
});
await act(async () => {
fireEvent.click(screen.getByText('Cronline'));
});
expect(screen.getByText('Review Details').disabled).toBeTruthy();
const newRepeatTimes = '3';
const repeatNTimes = screen.getByPlaceholderText('Repeat N times');
expect(repeatNTimes.value).toBe('');
await act(async () => {
fireEvent.change(repeatNTimes, {
target: { value: newRepeatTimes },
});
});
expect(repeatNTimes.value).toBe(newRepeatTimes);
const newCronline = '1 2';
const cronline = screen.getByLabelText('cronline');
expect(cronline.value).toBe('');
await act(async () => {
fireEvent.change(cronline, {
target: { value: newCronline },
});
});
expect(cronline.value).toBe(newCronline);
expect(screen.getByText('Review Details').disabled).toBeFalsy();
await act(async () => {
fireEvent.click(screen.getByText('Category and Template'));
});
expect(screen.getAllByText('Category and Template')).toHaveLength(3);
await act(async () => {
fireEvent.click(screen.getByText('Schedule'));
jest.runAllTimers();
});
expect(screen.queryAllByText('Schedule')).toHaveLength(3);
expect(repeatNTimes.value).toBe(newRepeatTimes);
expect(cronline.value).toBe(newCronline);
fireEvent.click(screen.getByText('Cronline'));
await act(async () => {
fireEvent.click(screen.getByText('Monthly'));
});
expect(screen.getByText('Review Details').disabled).toBeTruthy();
const newDays = '1,2,3';
const days = screen.getByLabelText('days');
expect(days.value).toBe('');
await act(async () => {
fireEvent.change(days, {
target: { value: newDays },
});
fireEvent.click(repeatNTimes);
});
expect(days.value).toBe(newDays);
expect(screen.getByText('Review Details').disabled).toBeTruthy();
const newAtMonthly = '13:07';
const at = () => screen.getByLabelText('repeat-at');
expect(at().value).toBe('');
await act(async () => {
fireEvent.change(at(), {
target: { value: newAtMonthly },
});
});
expect(at().value).toBe(newAtMonthly);
expect(screen.getByText('Review Details').disabled).toBeFalsy();
fireEvent.click(screen.getByText('Monthly'));
await act(async () => {
fireEvent.click(screen.getByText('Weekly'));
});
expect(screen.getByText('Review Details').disabled).toBeTruthy();
const dayTue = screen.getByLabelText('Tue checkbox');
const daySat = screen.getByLabelText('Sat checkbox');
expect(dayTue.checked).toBe(false);
expect(daySat.checked).toBe(false);
await act(async () => {
fireEvent.click(dayTue);
fireEvent.change(dayTue, {
target: { checked: true },
});
});
await act(async () => {
fireEvent.click(daySat);
fireEvent.change(daySat, {
target: { checked: true },
});
});
expect(dayTue.checked).toBe(true);
expect(daySat.checked).toBe(true);
const newAtWeekly = '17:53';
expect(at().value).toBe(newAtMonthly);
await act(async () => {
fireEvent.change(at(), {
target: { value: newAtWeekly },
});
});
expect(at().value).toBe(newAtWeekly);
expect(screen.getByText('Review Details').disabled).toBeFalsy();
fireEvent.click(screen.getByText('Weekly'));
await act(async () => {
fireEvent.click(screen.getByText('Daily'));
});
expect(screen.getByText('Review Details').disabled).toBeFalsy();
await act(async () => {
fireEvent.change(at(), {
target: { value: '' },
});
});
expect(screen.getByText('Review Details').disabled).toBeTruthy();
const newAtDaily = '17:07';
expect(at().value).toBe('');
await act(async () => {
fireEvent.change(at(), {
target: { value: newAtDaily },
});
});
expect(at().value).toBe(newAtDaily);
expect(screen.getByText('Review Details').disabled).toBeFalsy();
fireEvent.click(screen.getByText('Daily'));
await act(async () => {
fireEvent.click(screen.getByText('Hourly'));
});
expect(screen.getByText('Review Details').disabled).toBeTruthy();
const newMinutes = '6';
const atHourly = screen.getByLabelText('repeat-at-minute-typeahead');
expect(atHourly.value).toBe('');
await act(async () => {
fireEvent.click(screen.getByLabelText('select minute toggle'));
});
await act(async () => {
fireEvent.click(screen.getByText(newMinutes));
});
expect(screen.getByText('Review Details').disabled).toBeFalsy();
expect(atHourly.value).toBe(newMinutes);
});
it('should show invalid error on start date after end', async () => {
render(
);
await act(async () => {
await fireEvent.click(screen.getByText('Schedule'));
jest.runAllTimers();
});
const neverEnds = screen.getByLabelText('Never ends');
expect(neverEnds.checked).toBeFalsy();
const startsDateField = screen.getByLabelText('starts at datepicker');
const endsDateField = screen.getByLabelText('ends datepicker');
expect(
screen.queryAllByText('End time needs to be after start time')
).toHaveLength(0);
expect(screen.getByText('Review Details').disabled).toBeFalsy();
await act(async () => {
await fireEvent.change(startsDateField, {
target: { value: '2020/10/15' },
});
await fireEvent.change(endsDateField, {
target: { value: '2020/10/14' },
});
await jest.runOnlyPendingTimers();
});
expect(
screen.queryAllByText('End time needs to be after start time')
).toHaveLength(1);
expect(screen.getByText('Review Details').disabled).toBeTruthy();
});
it('purpose and ends should be disabled when no reaccurence ', async () => {
render(
);
await act(async () => {
await fireEvent.click(screen.getByText('Schedule'));
jest.runAllTimers();
});
const endsDateField = screen.getByLabelText('ends datepicker');
const endsTimeField = screen.getByLabelText('ends timepicker');
const purpose = screen.getByLabelText('purpose');
expect(endsDateField.disabled).toBeTruthy();
expect(endsTimeField.disabled).toBeTruthy();
expect(purpose.disabled).toBeTruthy();
await act(async () => {
fireEvent.click(
screen.getByLabelText('Does not repeat', { selector: 'button' })
);
});
await act(async () => {
fireEvent.click(screen.getByText('Cronline'));
});
expect(endsDateField.disabled).toBeFalsy();
expect(endsTimeField.disabled).toBeFalsy();
expect(purpose.disabled).toBeFalsy();
});
});