From 7710ad2e57f67863117980fa3115897bde78d1d1 Mon Sep 17 00:00:00 2001 From: Keith Grant Date: Tue, 31 Mar 2020 13:59:14 -0700 Subject: [PATCH] move OptionsList to components; add launch prompt tests --- .../LaunchButton/LaunchButton.test.jsx | 2 + .../components/LaunchPrompt/InventoryStep.jsx | 3 +- .../LaunchPrompt/InventoryStep.test.jsx | 40 +++++++ .../components/LaunchPrompt/LaunchPrompt.jsx | 1 + .../LaunchPrompt/LaunchPrompt.test.jsx | 100 ++++++++++++++++++ .../components/Lookup/CredentialLookup.jsx | 2 +- .../Lookup/InstanceGroupsLookup.jsx | 2 +- .../src/components/Lookup/InventoryLookup.jsx | 2 +- .../Lookup/MultiCredentialsLookup.jsx | 2 +- .../components/Lookup/OrganizationLookup.jsx | 2 +- .../src/components/Lookup/ProjectLookup.jsx | 2 +- awx/ui_next/src/components/Lookup/index.js | 1 - .../shared => OptionsList}/OptionsList.jsx | 8 +- .../OptionsList.test.jsx | 0 .../src/components/OptionsList/index.js | 1 + .../InventoryGroupHosts/AssociateModal.jsx | 2 +- 16 files changed, 156 insertions(+), 14 deletions(-) create mode 100644 awx/ui_next/src/components/LaunchPrompt/InventoryStep.test.jsx create mode 100644 awx/ui_next/src/components/LaunchPrompt/LaunchPrompt.test.jsx rename awx/ui_next/src/components/{Lookup/shared => OptionsList}/OptionsList.jsx (92%) rename awx/ui_next/src/components/{Lookup/shared => OptionsList}/OptionsList.test.jsx (100%) create mode 100644 awx/ui_next/src/components/OptionsList/index.js diff --git a/awx/ui_next/src/components/LaunchButton/LaunchButton.test.jsx b/awx/ui_next/src/components/LaunchButton/LaunchButton.test.jsx index 49ae7e16ac..8db633fd8c 100644 --- a/awx/ui_next/src/components/LaunchButton/LaunchButton.test.jsx +++ b/awx/ui_next/src/components/LaunchButton/LaunchButton.test.jsx @@ -30,7 +30,9 @@ describe('LaunchButton', () => { id: 1, type: 'job_template', }; + afterEach(() => jest.clearAllMocks()); + test('renders the expected content', () => { const wrapper = mountWithContexts( {children} diff --git a/awx/ui_next/src/components/LaunchPrompt/InventoryStep.jsx b/awx/ui_next/src/components/LaunchPrompt/InventoryStep.jsx index 03878b63a5..696dc445bc 100644 --- a/awx/ui_next/src/components/LaunchPrompt/InventoryStep.jsx +++ b/awx/ui_next/src/components/LaunchPrompt/InventoryStep.jsx @@ -6,8 +6,7 @@ import { useField } from 'formik'; import { InventoriesAPI } from '@api'; import { getQSConfig, parseQueryString } from '@util/qs'; import useRequest from '@util/useRequest'; -// TODO move OptionsList out of Lookup/shared -import { OptionsList } from '@components/Lookup'; +import OptionsList from '@components/OptionsList'; import ContentLoading from '@components/ContentLoading'; const QS_CONFIG = getQSConfig('inventory', { diff --git a/awx/ui_next/src/components/LaunchPrompt/InventoryStep.test.jsx b/awx/ui_next/src/components/LaunchPrompt/InventoryStep.test.jsx new file mode 100644 index 0000000000..4bac24478c --- /dev/null +++ b/awx/ui_next/src/components/LaunchPrompt/InventoryStep.test.jsx @@ -0,0 +1,40 @@ +import React from 'react'; +import { act } from 'react-dom/test-utils'; +import { Formik } from 'formik'; +import { mountWithContexts } from '@testUtils/enzymeHelpers'; +import InventoryStep from './InventoryStep'; +import { InventoriesAPI } from '@api'; + +jest.mock('@api/models/Inventories'); + +const inventories = [ + { id: 1, name: 'inv one', url: '/inventories/1' }, + { id: 2, name: 'inv two', url: '/inventories/2' }, + { id: 3, name: 'inv three', url: '/inventories/3' }, +]; + +describe('InventoryStep', () => { + beforeEach(() => { + InventoriesAPI.read.mockResolvedValue({ + data: { + results: inventories, + count: 3, + }, + }); + }); + + test('should load inventories', async () => { + let wrapper; + await act(async () => { + wrapper = mountWithContexts( + + + + ); + }); + wrapper.update(); + + expect(InventoriesAPI.read).toHaveBeenCalled(); + expect(wrapper.find('OptionsList').prop('options')).toEqual(inventories); + }); +}); diff --git a/awx/ui_next/src/components/LaunchPrompt/LaunchPrompt.jsx b/awx/ui_next/src/components/LaunchPrompt/LaunchPrompt.jsx index b51e7945ca..e4685262ec 100644 --- a/awx/ui_next/src/components/LaunchPrompt/LaunchPrompt.jsx +++ b/awx/ui_next/src/components/LaunchPrompt/LaunchPrompt.jsx @@ -84,4 +84,5 @@ function LaunchPrompt({ config, resource, onLaunch, onCancel, i18n }) { ); } +export { LaunchPrompt as _LaunchPrompt }; export default withI18n()(LaunchPrompt); diff --git a/awx/ui_next/src/components/LaunchPrompt/LaunchPrompt.test.jsx b/awx/ui_next/src/components/LaunchPrompt/LaunchPrompt.test.jsx new file mode 100644 index 0000000000..edbb0cd7dc --- /dev/null +++ b/awx/ui_next/src/components/LaunchPrompt/LaunchPrompt.test.jsx @@ -0,0 +1,100 @@ +import React from 'react'; +import { act, isElementOfType } from 'react-dom/test-utils'; +import { mountWithContexts } from '@testUtils/enzymeHelpers'; +import LaunchPrompt from './LaunchPrompt'; +import InventoryStep from './InventoryStep'; +import PreviewStep from './PreviewStep'; +import { InventoriesAPI } from '@api'; + +jest.mock('@api/models/Inventories'); + +let config; +const resource = { + id: 1, + type: 'job_template', +}; +const noop = () => {}; + +describe('LaunchPrompt', () => { + beforeEach(() => { + InventoriesAPI.read.mockResolvedValue({ + data: { + results: [{ id: 1, name: 'foo', url: '/inventories/1' }], + count: 1, + }, + }); + + config = { + can_start_without_user_input: false, + passwords_needed_to_start: [], + ask_scm_branch_on_launch: false, + ask_variables_on_launch: false, + ask_tags_on_launch: false, + ask_diff_mode_on_launch: false, + ask_skip_tags_on_launch: false, + ask_job_type_on_launch: false, + ask_limit_on_launch: false, + ask_verbosity_on_launch: false, + ask_inventory_on_launch: false, + ask_credential_on_launch: false, + survey_enabled: false, + variables_needed_to_start: [], + credential_needed_to_start: false, + inventory_needed_to_start: false, + job_template_data: { name: 'JT with prompts', id: 25, description: '' }, + }; + }); + + afterEach(() => jest.clearAllMocks()); + + test('should render Wizard with all steps', async () => { + let wrapper; + await act(async () => { + wrapper = mountWithContexts( + + ); + }); + const steps = wrapper.find('Wizard').prop('steps'); + + expect(steps).toHaveLength(5); + expect(steps[0].name).toEqual('Inventory'); + expect(steps[1].name).toEqual('Credential'); + expect(steps[2].name).toEqual('Other Prompts'); + expect(steps[3].name).toEqual('Survey'); + expect(steps[4].name).toEqual('Preview'); + }); + + test('should add inventory step', async () => { + let wrapper; + await act(async () => { + wrapper = mountWithContexts( + + ); + }); + const steps = wrapper.find('Wizard').prop('steps'); + + expect(steps).toHaveLength(2); + expect(steps[0].name).toEqual('Inventory'); + expect(isElementOfType(steps[0].component, InventoryStep)).toEqual(true); + expect(isElementOfType(steps[1].component, PreviewStep)).toEqual(true); + }); +}); diff --git a/awx/ui_next/src/components/Lookup/CredentialLookup.jsx b/awx/ui_next/src/components/Lookup/CredentialLookup.jsx index 72a587135f..50cf3c27e9 100644 --- a/awx/ui_next/src/components/Lookup/CredentialLookup.jsx +++ b/awx/ui_next/src/components/Lookup/CredentialLookup.jsx @@ -9,7 +9,7 @@ import { getQSConfig, parseQueryString, mergeParams } from '@util/qs'; import { FieldTooltip } from '@components/FormField'; import { FormGroup } from '@patternfly/react-core'; import Lookup from '@components/Lookup'; -import OptionsList from './shared/OptionsList'; +import OptionsList from '@components/OptionsList'; import LookupErrorMessage from './shared/LookupErrorMessage'; const QS_CONFIG = getQSConfig('credentials', { diff --git a/awx/ui_next/src/components/Lookup/InstanceGroupsLookup.jsx b/awx/ui_next/src/components/Lookup/InstanceGroupsLookup.jsx index f0c88576ca..d794ed252c 100644 --- a/awx/ui_next/src/components/Lookup/InstanceGroupsLookup.jsx +++ b/awx/ui_next/src/components/Lookup/InstanceGroupsLookup.jsx @@ -7,8 +7,8 @@ import { FormGroup } from '@patternfly/react-core'; import { InstanceGroupsAPI } from '@api'; import { getQSConfig, parseQueryString } from '@util/qs'; import { FieldTooltip } from '@components/FormField'; +import OptionsList from '@components/OptionsList'; import Lookup from './Lookup'; -import OptionsList from './shared/OptionsList'; import LookupErrorMessage from './shared/LookupErrorMessage'; const QS_CONFIG = getQSConfig('instance_groups', { diff --git a/awx/ui_next/src/components/Lookup/InventoryLookup.jsx b/awx/ui_next/src/components/Lookup/InventoryLookup.jsx index c80b0040fe..92815d943d 100644 --- a/awx/ui_next/src/components/Lookup/InventoryLookup.jsx +++ b/awx/ui_next/src/components/Lookup/InventoryLookup.jsx @@ -6,8 +6,8 @@ import { t } from '@lingui/macro'; import { InventoriesAPI } from '@api'; import { Inventory } from '@types'; import Lookup from '@components/Lookup'; +import OptionsList from '@components/OptionsList'; import { getQSConfig, parseQueryString } from '@util/qs'; -import OptionsList from './shared/OptionsList'; import LookupErrorMessage from './shared/LookupErrorMessage'; const QS_CONFIG = getQSConfig('inventory', { diff --git a/awx/ui_next/src/components/Lookup/MultiCredentialsLookup.jsx b/awx/ui_next/src/components/Lookup/MultiCredentialsLookup.jsx index 1bc80341b9..58bdf359cb 100644 --- a/awx/ui_next/src/components/Lookup/MultiCredentialsLookup.jsx +++ b/awx/ui_next/src/components/Lookup/MultiCredentialsLookup.jsx @@ -7,9 +7,9 @@ import { ToolbarItem, Alert } from '@patternfly/react-core'; import { CredentialsAPI, CredentialTypesAPI } from '@api'; import AnsibleSelect from '@components/AnsibleSelect'; import CredentialChip from '@components/CredentialChip'; +import OptionsList from '@components/OptionsList'; import { getQSConfig, parseQueryString } from '@util/qs'; import Lookup from './Lookup'; -import OptionsList from './shared/OptionsList'; const QS_CONFIG = getQSConfig('credentials', { page: 1, diff --git a/awx/ui_next/src/components/Lookup/OrganizationLookup.jsx b/awx/ui_next/src/components/Lookup/OrganizationLookup.jsx index 7d208fb588..bf5a77aa0a 100644 --- a/awx/ui_next/src/components/Lookup/OrganizationLookup.jsx +++ b/awx/ui_next/src/components/Lookup/OrganizationLookup.jsx @@ -7,8 +7,8 @@ import { OrganizationsAPI } from '@api'; import { Organization } from '@types'; import { FormGroup } from '@patternfly/react-core'; import { getQSConfig, parseQueryString } from '@util/qs'; +import OptionsList from '@components/OptionsList'; import Lookup from './Lookup'; -import OptionsList from './shared/OptionsList'; import LookupErrorMessage from './shared/LookupErrorMessage'; const QS_CONFIG = getQSConfig('organizations', { diff --git a/awx/ui_next/src/components/Lookup/ProjectLookup.jsx b/awx/ui_next/src/components/Lookup/ProjectLookup.jsx index 1a16337e0f..4bd30a3db3 100644 --- a/awx/ui_next/src/components/Lookup/ProjectLookup.jsx +++ b/awx/ui_next/src/components/Lookup/ProjectLookup.jsx @@ -7,9 +7,9 @@ import { FormGroup } from '@patternfly/react-core'; import { ProjectsAPI } from '@api'; import { Project } from '@types'; import { FieldTooltip } from '@components/FormField'; +import OptionsList from '@components/OptionsList'; import { getQSConfig, parseQueryString } from '@util/qs'; import Lookup from './Lookup'; -import OptionsList from './shared/OptionsList'; import LookupErrorMessage from './shared/LookupErrorMessage'; const QS_CONFIG = getQSConfig('project', { diff --git a/awx/ui_next/src/components/Lookup/index.js b/awx/ui_next/src/components/Lookup/index.js index cd9d5bc226..cde48e2bcd 100644 --- a/awx/ui_next/src/components/Lookup/index.js +++ b/awx/ui_next/src/components/Lookup/index.js @@ -3,4 +3,3 @@ export { default as InstanceGroupsLookup } from './InstanceGroupsLookup'; export { default as InventoryLookup } from './InventoryLookup'; export { default as ProjectLookup } from './ProjectLookup'; export { default as MultiCredentialsLookup } from './MultiCredentialsLookup'; -export { default as OptionsList } from './shared/OptionsList'; diff --git a/awx/ui_next/src/components/Lookup/shared/OptionsList.jsx b/awx/ui_next/src/components/OptionsList/OptionsList.jsx similarity index 92% rename from awx/ui_next/src/components/Lookup/shared/OptionsList.jsx rename to awx/ui_next/src/components/OptionsList/OptionsList.jsx index da0e1065e6..e19e85a97c 100644 --- a/awx/ui_next/src/components/Lookup/shared/OptionsList.jsx +++ b/awx/ui_next/src/components/OptionsList/OptionsList.jsx @@ -11,10 +11,10 @@ import { import styled from 'styled-components'; import { withI18n } from '@lingui/react'; import { t } from '@lingui/macro'; -import SelectedList from '../../SelectedList'; -import PaginatedDataList from '../../PaginatedDataList'; -import CheckboxListItem from '../../CheckboxListItem'; -import DataListToolbar from '../../DataListToolbar'; +import SelectedList from '../SelectedList'; +import PaginatedDataList from '../PaginatedDataList'; +import CheckboxListItem from '../CheckboxListItem'; +import DataListToolbar from '../DataListToolbar'; import { QSConfig, SearchColumns, SortColumns } from '@types'; const ModalList = styled.div` diff --git a/awx/ui_next/src/components/Lookup/shared/OptionsList.test.jsx b/awx/ui_next/src/components/OptionsList/OptionsList.test.jsx similarity index 100% rename from awx/ui_next/src/components/Lookup/shared/OptionsList.test.jsx rename to awx/ui_next/src/components/OptionsList/OptionsList.test.jsx diff --git a/awx/ui_next/src/components/OptionsList/index.js b/awx/ui_next/src/components/OptionsList/index.js new file mode 100644 index 0000000000..477d3c08c3 --- /dev/null +++ b/awx/ui_next/src/components/OptionsList/index.js @@ -0,0 +1 @@ +export { default } from './OptionsList'; diff --git a/awx/ui_next/src/screens/Inventory/InventoryGroupHosts/AssociateModal.jsx b/awx/ui_next/src/screens/Inventory/InventoryGroupHosts/AssociateModal.jsx index 4efc5a5d00..493056b50e 100644 --- a/awx/ui_next/src/screens/Inventory/InventoryGroupHosts/AssociateModal.jsx +++ b/awx/ui_next/src/screens/Inventory/InventoryGroupHosts/AssociateModal.jsx @@ -3,7 +3,7 @@ import { useHistory } from 'react-router-dom'; import { withI18n } from '@lingui/react'; import { t } from '@lingui/macro'; import { Button, Modal } from '@patternfly/react-core'; -import OptionsList from '@components/Lookup/shared/OptionsList'; +import OptionsList from '@components/OptionsList'; import useRequest from '@util/useRequest'; import { getQSConfig, parseQueryString } from '@util/qs'; import useSelected from '@util/useSelected';