/* eslint-disable max-lines */ import React from 'react'; import { Provider } from 'react-redux'; import { mount } from '@theforeman/test'; import { fireEvent, screen, render, act } from '@testing-library/react'; import { MockedProvider } from '@apollo/client/testing'; import * as api from 'foremanReact/redux/API'; import { JobWizard } from '../../../JobWizard'; import * as selectors from '../../../JobWizardSelectors'; import { jobTemplateResponse, jobTemplate, testSetup, mockApi, jobCategories, gqlMock, } from '../../../__tests__/fixtures'; import { WIZARD_TITLES } from '../../../JobWizardConstants'; const lodash = require('lodash'); lodash.debounce = fn => fn; const store = testSetup(selectors, api); mockApi(api); jest.useFakeTimers(); describe('AdvancedFields', () => { it('should save data between steps for advanced fields', async () => { const wrapper = mount( ); // setup wrapper.find('.pf-c-button.pf-c-select__toggle-button').simulate('click'); wrapper .find('.pf-c-select__menu-item') .first() .simulate('click'); // test expect(wrapper.find('.pf-c-wizard__nav-link.pf-m-disabled')).toHaveLength( 0 ); wrapper .find('.pf-c-wizard__nav-link') .at(2) .simulate('click'); // Advanced step await act(async () => { jest.runAllTimers(); // to handle pf4 date picker popover }); const effectiveUserInput = () => wrapper.find('input#effective-user'); const advancedTemplateInput = () => wrapper.find('.pf-c-form__group-control textarea'); const effectiveUesrValue = 'effective user new value'; const advancedTemplateInputValue = 'advanced input new value'; effectiveUserInput().getDOMNode().value = effectiveUesrValue; effectiveUserInput().simulate('change'); wrapper.update(); advancedTemplateInput().getDOMNode().value = advancedTemplateInputValue; advancedTemplateInput().simulate('change'); expect(effectiveUserInput().prop('value')).toEqual(effectiveUesrValue); expect(advancedTemplateInput().prop('value')).toEqual( advancedTemplateInputValue ); wrapper .find('.pf-c-wizard__nav-link') .at(1) .simulate('click'); expect(wrapper.find('.pf-c-wizard__nav-link.pf-m-current').text()).toEqual( 'Target hosts and inputs' ); wrapper .find('.pf-c-wizard__nav-link') .at(2) .simulate('click'); // Advanced step await act(async () => { jest.runOnlyPendingTimers(); // to handle pf4 date picker popover }); expect(effectiveUserInput().prop('value')).toEqual(effectiveUesrValue); expect(advancedTemplateInput().prop('value')).toEqual( advancedTemplateInputValue ); }); it('fill template fields', async () => { render( ); await act(async () => { fireEvent.click(screen.getByText(WIZARD_TITLES.advanced)); jest.runOnlyPendingTimers(); // to handle pf4 date picker popover }); const searchValue = 'search test'; const textValue = 'I am a text'; const dateValue = '2022/06/24'; const timeValue = '12:34:56'; const textField = screen.getByLabelText('adv plain hidden', { selector: 'textarea', }); const selectField = screen.getByLabelText('adv plain select toggle'); const resourceSelectField = screen.getByLabelText( 'adv resource select toggle' ); const searchField = screen.getByPlaceholderText('Filter...'); const dateField = screen.getByLabelText('adv date datepicker'); const timeField = screen.getByLabelText('adv date timepicker'); fireEvent.click(selectField); await act(async () => { await fireEvent.click(screen.getByText('option 2')); fireEvent.click(screen.getAllByText(WIZARD_TITLES.advanced)[0]); // to remove focus fireEvent.click(resourceSelectField); fireEvent.click(screen.getByText('resource2')); fireEvent.change(textField, { target: { value: textValue }, }); fireEvent.change(searchField, { target: { value: searchValue }, }); await fireEvent.change(dateField, { target: { value: dateValue }, }); fireEvent.change(timeField, { target: { value: timeValue }, }); jest.runAllTimers(); // to handle pf4 date picker popover }); expect( screen.getByLabelText('adv plain hidden', { selector: 'textarea', }).value ).toBe(textValue); expect(searchField.value).toBe(searchValue); expect(screen.getByLabelText('adv date datepicker').value).toBe(dateValue); expect(timeField.value).toBe(timeValue); await act(async () => { fireEvent.click(screen.getByText(WIZARD_TITLES.categoryAndTemplate)); }); expect(screen.getAllByText(WIZARD_TITLES.categoryAndTemplate)).toHaveLength( 3 ); await act(async () => { await fireEvent.click(screen.getByText(WIZARD_TITLES.advanced)); jest.runOnlyPendingTimers(); }); expect(textField.value).toBe(textValue); expect(searchField.value).toBe(searchValue); expect(dateField.value).toBe(dateValue); expect(timeField.value).toBe(timeValue); expect(screen.queryAllByText('option 1')).toHaveLength(0); expect(screen.queryAllByText('option 2')).toHaveLength(1); expect(screen.queryAllByDisplayValue('resource1')).toHaveLength(0); expect(screen.queryAllByDisplayValue('resource2')).toHaveLength(1); }); it('fill defaults into fields', async () => { render( ); await act(async () => { fireEvent.click(screen.getByText(WIZARD_TITLES.advanced)); jest.runAllTimers(); // to handle pf4 date picker popover }); expect( screen.getByLabelText('ssh user', { selector: 'input', }).value ).toBe(''); expect( screen.getByLabelText('effective user', { selector: 'input', }).value ).toBe('default effective user'); expect( screen.getByLabelText('timeout to kill', { selector: 'input', }).value ).toBe('2'); expect( screen.getByLabelText('description preview', { selector: 'input', }).value ).toBe( 'template1 with inputs adv plain hidden="Default val" adv plain select="" adv resource select="" adv search="" adv date="" plain hidden="Default val"' ); }); it('DescriptionField', async () => { render( ); await act(async () => { fireEvent.click(screen.getByText(WIZARD_TITLES.advanced)); jest.runAllTimers(); // to handle pf4 date picker popover }); const textField = screen.getByLabelText('adv plain hidden', { selector: 'textarea', }); await act(async () => { await fireEvent.change(textField, { target: { value: 'test command' }, }); }); const descriptionValue = 'Run %{adv plain hidden} %{wrong command name}'; await act(async () => { fireEvent.click(screen.getByText('Edit job description template')); }); const editText = screen.getByLabelText('description edit', { selector: 'input', }); await fireEvent.change(editText, { target: { value: descriptionValue }, }); await act(async () => { fireEvent.click(screen.getByText('Preview job description')); }); expect( screen.getByLabelText('description preview', { selector: 'input', }).value ).toBe('Run test command %{wrong command name}'); }); it('DescriptionField with no inputs', async () => { jest.spyOn(api, 'get'); jest.spyOn(selectors, 'selectTemplateInputs'); jest.spyOn(selectors, 'selectAdvancedTemplateInputs'); selectors.selectTemplateInputs.mockImplementation(() => []); selectors.selectAdvancedTemplateInputs.mockImplementation(() => []); 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, advanced_template_inputs: [], template_inputs: [], }, }); } else if (action.key === 'JOB_TEMPLATES') { handleSuccess && handleSuccess({ data: { results: [jobTemplate] }, }); } return { type: 'get', ...action }; }); render( ); await act(async () => { fireEvent.click(screen.getByText(WIZARD_TITLES.advanced)); jest.runAllTimers(); // to handle pf4 date picker popover }); expect( screen.getByLabelText('description preview', { selector: 'input', }).value ).toBe('template1'); }); it('DescriptionField with description_format', async () => { jest.spyOn(api, 'get'); jest.spyOn(selectors, 'selectTemplateInputs'); selectors.selectTemplateInputs.mockImplementation(() => [ { name: 'command', required: true, input_type: 'user', description: 'some Description', advanced: true, value_type: 'plain', resource_type: 'ansible_roles', default: 'Default val', hidden_value: true, }, ]); 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, job_template: { ...jobTemplateResponse.job_template, description_format: 'Run %{command}', }, template_inputs: [ { name: 'command', required: true, input_type: 'user', description: 'some Description', advanced: true, value_type: 'plain', resource_type: 'ansible_roles', default: 'Default val', hidden_value: true, }, ], }, }); } else if (action.key === 'JOB_TEMPLATES') { handleSuccess && handleSuccess({ data: { results: [jobTemplate] }, }); } return { type: 'get', ...action }; }); render( ); await act(async () => { fireEvent.click(screen.getByText(WIZARD_TITLES.advanced)); jest.runAllTimers(); // to handle pf4 date picker popover }); expect( screen.getByLabelText('description preview', { selector: 'input', }).value ).toBe('Run Default val'); }); it('search resources action', async () => { jest.useFakeTimers(); mockApi(api); const newStore = testSetup(selectors, api); render( ); await act(async () => { fireEvent.click(screen.getByText(WIZARD_TITLES.advanced)); jest.runAllTimers(); // to handle pf4 date picker popover }); const resourceSelectField = screen.getByLabelText( 'adv resource select typeahead input' ); await act(async () => { await fireEvent.change(resourceSelectField, { target: { value: 'some search' }, }); jest.runAllTimers(); }); expect(newStore.getActions()).toMatchSnapshot('resource search'); }); });