From d5d24e421be3701f5730f61df521b60ac86470a4 Mon Sep 17 00:00:00 2001 From: mabashian Date: Wed, 31 Aug 2022 10:39:53 -0400 Subject: [PATCH] Leverage the IG mixin on the schedules model Move associate/disassociate label methods into mixin Move label/IG saving out to related endpoints off of a schedule --- awx/ui/src/api/mixins/Labels.mixin.js | 14 ++ awx/ui/src/api/models/JobTemplates.js | 14 -- awx/ui/src/api/models/Schedules.js | 3 +- .../LaunchPrompt/LaunchPrompt.test.js | 148 +++++++++++++++++- .../LaunchPrompt/steps/OtherPromptsStep.js | 2 +- .../LaunchPrompt/steps/useCredentialsStep.js | 4 +- .../Schedule/ScheduleAdd/ScheduleAdd.js | 95 +++++------ .../Schedule/ScheduleAdd/ScheduleAdd.test.js | 65 +++++++- .../Schedule/ScheduleEdit/ScheduleEdit.js | 66 +++++--- .../Schedule/shared/ScheduleForm.js | 12 +- .../Schedule/shared/ScheduleForm.test.js | 115 +++++++++++++- 11 files changed, 422 insertions(+), 116 deletions(-) diff --git a/awx/ui/src/api/mixins/Labels.mixin.js b/awx/ui/src/api/mixins/Labels.mixin.js index 12e9402048..98aae12034 100644 --- a/awx/ui/src/api/mixins/Labels.mixin.js +++ b/awx/ui/src/api/mixins/Labels.mixin.js @@ -30,6 +30,20 @@ const LabelsMixin = (parent) => return fetchLabels(); } + + associateLabel(id, label, orgId) { + return this.http.post(`${this.baseUrl}${id}/labels/`, { + name: label.name, + organization: orgId, + }); + } + + disassociateLabel(id, label) { + return this.http.post(`${this.baseUrl}${id}/labels/`, { + id: label.id, + disassociate: true, + }); + } }; export default LabelsMixin; diff --git a/awx/ui/src/api/models/JobTemplates.js b/awx/ui/src/api/models/JobTemplates.js index 7c9c6e02ae..d2c1eb7a5d 100644 --- a/awx/ui/src/api/models/JobTemplates.js +++ b/awx/ui/src/api/models/JobTemplates.js @@ -34,20 +34,6 @@ class JobTemplates extends SchedulesMixin( return this.http.get(`${this.baseUrl}${id}/launch/`); } - associateLabel(id, label, orgId) { - return this.http.post(`${this.baseUrl}${id}/labels/`, { - name: label.name, - organization: orgId, - }); - } - - disassociateLabel(id, label) { - return this.http.post(`${this.baseUrl}${id}/labels/`, { - id: label.id, - disassociate: true, - }); - } - readCredentials(id, params) { return this.http.get(`${this.baseUrl}${id}/credentials/`, { params, diff --git a/awx/ui/src/api/models/Schedules.js b/awx/ui/src/api/models/Schedules.js index eec5ee1396..a32c620538 100644 --- a/awx/ui/src/api/models/Schedules.js +++ b/awx/ui/src/api/models/Schedules.js @@ -1,7 +1,8 @@ import Base from '../Base'; +import InstanceGroupsMixin from '../mixins/InstanceGroups.mixin'; import LabelsMixin from '../mixins/Labels.mixin'; -class Schedules extends LabelsMixin(Base) { +class Schedules extends InstanceGroupsMixin(LabelsMixin(Base)) { constructor(http) { super(http); this.baseUrl = 'api/v2/schedules/'; diff --git a/awx/ui/src/components/LaunchPrompt/LaunchPrompt.test.js b/awx/ui/src/components/LaunchPrompt/LaunchPrompt.test.js index d4e3cee1ef..53ea395af8 100644 --- a/awx/ui/src/components/LaunchPrompt/LaunchPrompt.test.js +++ b/awx/ui/src/components/LaunchPrompt/LaunchPrompt.test.js @@ -1,6 +1,8 @@ import React from 'react'; import { act, isElementOfType } from 'react-dom/test-utils'; import { + ExecutionEnvironmentsAPI, + InstanceGroupsAPI, InventoriesAPI, CredentialsAPI, CredentialTypesAPI, @@ -16,15 +18,15 @@ import CredentialsStep from './steps/CredentialsStep'; import CredentialPasswordsStep from './steps/CredentialPasswordsStep'; import OtherPromptsStep from './steps/OtherPromptsStep'; import PreviewStep from './steps/PreviewStep'; -import executionEnvironmentHelpTextStrings from 'screens/ExecutionEnvironment/shared/ExecutionEnvironment.helptext'; -import { ExecutionEnvironment } from 'types'; import ExecutionEnvironmentStep from './steps/ExecutionEnvironmentStep'; +import InstanceGroupsStep from './steps/InstanceGroupsStep'; jest.mock('../../api/models/Inventories'); jest.mock('../../api/models/ExecutionEnvironments'); jest.mock('../../api/models/CredentialTypes'); jest.mock('../../api/models/Credentials'); jest.mock('../../api/models/JobTemplates'); +jest.mock('../../api/models/InstanceGroups'); let config; const resource = { @@ -66,6 +68,79 @@ describe('LaunchPrompt', () => { spec: [{ type: 'text', variable: 'foo' }], }, }); + InstanceGroupsAPI.read.mockResolvedValue({ + data: { + results: [ + { + id: 2, + type: 'instance_group', + url: '/api/v2/instance_groups/2/', + related: { + jobs: '/api/v2/instance_groups/2/jobs/', + instances: '/api/v2/instance_groups/2/instances/', + }, + name: 'default', + created: '2022-08-30T20:35:05.747132Z', + modified: '2022-08-30T20:35:05.756690Z', + capacity: 177, + consumed_capacity: 0, + percent_capacity_remaining: 100.0, + jobs_running: 0, + jobs_total: 2, + instances: 3, + is_container_group: false, + credential: null, + policy_instance_percentage: 100, + policy_instance_minimum: 0, + policy_instance_list: [], + pod_spec_override: '', + summary_fields: { + user_capabilities: { + edit: true, + delete: false, + }, + }, + }, + ], + count: 1, + }, + }); + ExecutionEnvironmentsAPI.read.mockResolvedValue({ + data: { + results: [ + { + id: 1, + type: 'execution_environment', + url: '/api/v2/execution_environments/1/', + related: { + activity_stream: + '/api/v2/execution_environments/1/activity_stream/', + unified_job_templates: + '/api/v2/execution_environments/1/unified_job_templates/', + copy: '/api/v2/execution_environments/1/copy/', + }, + summary_fields: { + execution_environment: {}, + user_capabilities: { + edit: true, + delete: true, + copy: true, + }, + }, + created: '2022-08-30T20:34:55.842997Z', + modified: '2022-08-30T20:34:55.859874Z', + name: 'AWX EE (latest)', + description: '', + organization: null, + image: 'quay.io/ansible/awx-ee:latest', + managed: false, + credential: null, + pull: '', + }, + ], + count: 1, + }, + }); config = { can_start_without_user_input: false, @@ -80,6 +155,12 @@ describe('LaunchPrompt', () => { ask_verbosity_on_launch: false, ask_inventory_on_launch: false, ask_credential_on_launch: false, + ask_execution_environment_on_launch: false, + ask_labels_on_launch: false, + ask_forks_on_launch: false, + ask_job_slice_count_on_launch: false, + ask_timeout_on_launch: false, + ask_instance_groups_on_launch: false, survey_enabled: false, variables_needed_to_start: [], credential_needed_to_start: false, @@ -100,6 +181,8 @@ describe('LaunchPrompt', () => { ask_inventory_on_launch: true, ask_credential_on_launch: true, ask_scm_branch_on_launch: true, + ask_execution_environment_on_launch: true, + ask_instance_groups_on_launch: true, survey_enabled: true, passwords_needed_to_start: ['ssh_password'], defaults: { @@ -154,14 +237,15 @@ describe('LaunchPrompt', () => { const wizard = await waitForElement(wrapper, 'Wizard'); const steps = wizard.prop('steps'); - expect(steps).toHaveLength(7); + expect(steps).toHaveLength(8); expect(steps[0].name.props.children).toEqual('Inventory'); expect(steps[1].name.props.children).toEqual('Credentials'); expect(steps[2].name.props.children).toEqual('Credential passwords'); expect(steps[3].name.props.children).toEqual('Execution Environment'); - expect(steps[4].name.props.children).toEqual('Other prompts'); - expect(steps[5].name.props.children).toEqual('Survey'); - expect(steps[6].name.props.children).toEqual('Preview'); + expect(steps[4].name.props.children).toEqual('Instance Groups'); + expect(steps[5].name.props.children).toEqual('Other prompts'); + expect(steps[6].name.props.children).toEqual('Survey'); + expect(steps[7].name.props.children).toEqual('Preview'); expect(wizard.find('WizardHeader').prop('title')).toBe('Launch | Foobar'); expect(wizard.find('WizardHeader').prop('description')).toBe( 'Foo Description' @@ -219,6 +303,58 @@ describe('LaunchPrompt', () => { expect(isElementOfType(steps[2].component, PreviewStep)).toEqual(true); }); + test('should add execution environment step', async () => { + let wrapper; + await act(async () => { + wrapper = mountWithContexts( + + ); + }); + const wizard = await waitForElement(wrapper, 'Wizard'); + const steps = wizard.prop('steps'); + + expect(steps).toHaveLength(2); + expect(steps[0].name.props.children).toEqual('Execution Environment'); + expect( + isElementOfType(steps[0].component, ExecutionEnvironmentStep) + ).toEqual(true); + expect(isElementOfType(steps[1].component, PreviewStep)).toEqual(true); + }); + + test('should add instance groups step', async () => { + let wrapper; + await act(async () => { + wrapper = mountWithContexts( + + ); + }); + const wizard = await waitForElement(wrapper, 'Wizard'); + const steps = wizard.prop('steps'); + + expect(steps).toHaveLength(2); + expect(steps[0].name.props.children).toEqual('Instance Groups'); + expect(isElementOfType(steps[0].component, InstanceGroupsStep)).toEqual( + true + ); + expect(isElementOfType(steps[1].component, PreviewStep)).toEqual(true); + }); + test('should add other prompts step', async () => { let wrapper; await act(async () => { diff --git a/awx/ui/src/components/LaunchPrompt/steps/OtherPromptsStep.js b/awx/ui/src/components/LaunchPrompt/steps/OtherPromptsStep.js index 17d23e7710..a52cfeee38 100644 --- a/awx/ui/src/components/LaunchPrompt/steps/OtherPromptsStep.js +++ b/awx/ui/src/components/LaunchPrompt/steps/OtherPromptsStep.js @@ -231,7 +231,7 @@ function LabelsField() { value={field.value} onChange={(labels) => helpers.setValue(labels)} createText={t`Create`} - onError={() => alert('error')} + onError={() => {}} /> ); diff --git a/awx/ui/src/components/LaunchPrompt/steps/useCredentialsStep.js b/awx/ui/src/components/LaunchPrompt/steps/useCredentialsStep.js index bd49a26c77..735ae21a4d 100644 --- a/awx/ui/src/components/LaunchPrompt/steps/useCredentialsStep.js +++ b/awx/ui/src/components/LaunchPrompt/steps/useCredentialsStep.js @@ -10,7 +10,7 @@ const STEP_ID = 'credentials'; export default function useCredentialsStep( launchConfig, resource, - resourceDefaultCredentials, + resourceDefaultCredentials = [], allowCredentialsWithPasswords = false ) { const [field, meta, helpers] = useField('credentials'); @@ -78,6 +78,6 @@ function getInitialValues(launchConfig, resourceDefaultCredentials) { } return { - credentials: resourceDefaultCredentials || [], + credentials: resourceDefaultCredentials, }; } diff --git a/awx/ui/src/components/Schedule/ScheduleAdd/ScheduleAdd.js b/awx/ui/src/components/Schedule/ScheduleAdd/ScheduleAdd.js index 3390c826cc..13d61345f7 100644 --- a/awx/ui/src/components/Schedule/ScheduleAdd/ScheduleAdd.js +++ b/awx/ui/src/components/Schedule/ScheduleAdd/ScheduleAdd.js @@ -4,7 +4,7 @@ import { useHistory, useLocation } from 'react-router-dom'; import { Card } from '@patternfly/react-core'; import yaml from 'js-yaml'; import { parseVariableField } from 'util/yaml'; -import { LabelsAPI, OrganizationsAPI, SchedulesAPI } from 'api'; +import { OrganizationsAPI, SchedulesAPI } from 'api'; import mergeExtraVars from 'util/prompt/mergeExtraVars'; import getSurveyValues from 'util/prompt/getSurveyValues'; import { getAddedAndRemoved } from 'util/lists'; @@ -41,6 +41,7 @@ function ScheduleAdd({ exceptionOptions, timezone, credentials, + labels, ...submitValues } = values; const { added } = getAddedAndRemoved( @@ -76,56 +77,7 @@ function ScheduleAdd({ submitValues.execution_environment = execution_environment.id; } - submitValues.instance_groups = instance_groups - ? instance_groups.map((s) => s.id) - : []; - try { - if (launchConfiguration?.ask_labels_on_launch) { - const labelIds = []; - const newLabels = []; - const labelRequests = []; - let organizationId = resource.organization; - if (values.labels) { - values.labels.forEach((label) => { - if (typeof label.id !== 'number') { - newLabels.push(label); - } else { - labelIds.push(label.id); - } - }); - } - - if (newLabels.length > 0) { - if (!organizationId) { - // eslint-disable-next-line no-useless-catch - try { - const { - data: { results }, - } = await OrganizationsAPI.read(); - organizationId = results[0].id; - } catch (err) { - throw err; - } - } - } - - newLabels.forEach((label) => { - labelRequests.push( - LabelsAPI.create({ - name: label.name, - organization: organizationId, - }).then(({ data }) => { - labelIds.push(data.id); - }) - ); - }); - - await Promise.all(labelRequests); - - submitValues.labels = labelIds; - } - const ruleSet = buildRuleSet(values); const requestData = { ...submitValues, @@ -147,13 +99,46 @@ function ScheduleAdd({ const { data: { id: scheduleId }, } = await apiModel.createSchedule(resource.id, requestData); - if (credentials?.length > 0) { - await Promise.all( - added.map(({ id: credentialId }) => - SchedulesAPI.associateCredential(scheduleId, credentialId) - ) + + let labelsPromises = []; + let credentialsPromises = []; + + if (launchConfiguration?.ask_labels_on_launch && labels) { + let organizationId = resource.organization; + if (!organizationId) { + // eslint-disable-next-line no-useless-catch + try { + const { + data: { results }, + } = await OrganizationsAPI.read(); + organizationId = results[0].id; + } catch (err) { + throw err; + } + } + + labelsPromises = labels.map((label) => + SchedulesAPI.associateLabel(scheduleId, label, organizationId) ); } + + if (launchConfiguration?.ask_credential_on_launch && added?.length > 0) { + credentialsPromises = added.map(({ id: credentialId }) => + SchedulesAPI.associateCredential(scheduleId, credentialId) + ); + } + await Promise.all([labelsPromises, credentialsPromises]); + + if ( + launchConfiguration?.ask_instance_groups_on_launch && + instance_groups + ) { + /* eslint-disable no-await-in-loop, no-restricted-syntax */ + for (const group of instance_groups) { + await SchedulesAPI.associateInstanceGroup(scheduleId, group.id); + } + } + history.push(`${pathRoot}schedules/${scheduleId}`); } catch (err) { setFormSubmitError(err); diff --git a/awx/ui/src/components/Schedule/ScheduleAdd/ScheduleAdd.test.js b/awx/ui/src/components/Schedule/ScheduleAdd/ScheduleAdd.test.js index 870fa15edf..57def9f64e 100644 --- a/awx/ui/src/components/Schedule/ScheduleAdd/ScheduleAdd.test.js +++ b/awx/ui/src/components/Schedule/ScheduleAdd/ScheduleAdd.test.js @@ -1,11 +1,21 @@ import React from 'react'; import { act } from 'react-dom/test-utils'; import { RRule } from 'rrule'; -import { SchedulesAPI, JobTemplatesAPI, InventoriesAPI } from 'api'; +import { + CredentialsAPI, + CredentialTypesAPI, + SchedulesAPI, + JobTemplatesAPI, + InventoriesAPI, +} from 'api'; import { mountWithContexts } from '../../../../testUtils/enzymeHelpers'; import ScheduleAdd from './ScheduleAdd'; -jest.mock('../../../api'); +jest.mock('../../../api/models/Credentials'); +jest.mock('../../../api/models/CredentialTypes'); +jest.mock('../../../api/models/Schedules'); +jest.mock('../../../api/models/JobTemplates'); +jest.mock('../../../api/models/Inventories'); const launchConfig = { can_start_without_user_input: false, @@ -19,7 +29,7 @@ const launchConfig = { ask_limit_on_launch: false, ask_verbosity_on_launch: false, ask_inventory_on_launch: true, - ask_credential_on_launch: false, + ask_credential_on_launch: true, survey_enabled: false, variables_needed_to_start: [], credential_needed_to_start: false, @@ -57,6 +67,33 @@ describe('', () => { ], }); JobTemplatesAPI.createSchedule.mockResolvedValue({ data: { id: 3 } }); + + CredentialTypesAPI.loadAllTypes.mockResolvedValue([ + { id: 1, name: 'ssh', kind: 'ssh' }, + ]); + + CredentialsAPI.read.mockResolvedValue({ + data: { + count: 1, + results: [ + { + id: 10, + name: 'cred 1', + kind: 'ssh', + url: '', + credential_type: 1, + }, + ], + }, + }); + + CredentialsAPI.readOptions.mockResolvedValue({ + data: { + related_search_fields: [], + actions: { GET: { filterabled: true } }, + }, + }); + await act(async () => { wrapper = mountWithContexts( ', () => { description: '', }} launchConfig={launchConfig} + surveyConfig={{}} /> ); }); @@ -390,6 +428,7 @@ describe('', () => { wrapper.find('Button[aria-label="Prompt"]').prop('onClick')() ); wrapper.update(); + // Inventory step expect(wrapper.find('WizardNavItem').at(0).prop('isCurrent')).toBe(true); await act(async () => { wrapper.find('td#check-action-item-1').find('input').simulate('click'); @@ -402,7 +441,21 @@ describe('', () => { wrapper.find('WizardFooterInternal').prop('onNext')() ); wrapper.update(); + // Credential step expect(wrapper.find('WizardNavItem').at(1).prop('isCurrent')).toBe(true); + await act(async () => { + wrapper.find('td#check-action-item-10').find('input').simulate('click'); + }); + wrapper.update(); + expect( + wrapper.find('td#check-action-item-10').find('input').prop('checked') + ).toBe(true); + await act(async () => + wrapper.find('WizardFooterInternal').prop('onNext')() + ); + wrapper.update(); + // Preview step + expect(wrapper.find('WizardNavItem').at(2).prop('isCurrent')).toBe(true); await act(async () => wrapper.find('WizardFooterInternal').prop('onNext')() ); @@ -414,10 +467,7 @@ describe('', () => { frequency: [], skip_tags: '', inventory: { name: 'inventory', id: 45 }, - credentials: [ - { name: 'cred 1', id: 10 }, - { name: 'cred 2', id: 20 }, - ], + credentials: [{ name: 'cred 1', id: 10 }], startDate: '2021-01-28', startTime: '2:15 PM', timezone: 'America/New_York', @@ -434,7 +484,6 @@ describe('', () => { skip_tags: '', }); expect(SchedulesAPI.associateCredential).toBeCalledWith(3, 10); - expect(SchedulesAPI.associateCredential).toBeCalledWith(3, 20); }); test('should submit survey with default values properly, without opening prompt wizard', async () => { diff --git a/awx/ui/src/components/Schedule/ScheduleEdit/ScheduleEdit.js b/awx/ui/src/components/Schedule/ScheduleEdit/ScheduleEdit.js index 22e3ff20b1..3236c3afce 100644 --- a/awx/ui/src/components/Schedule/ScheduleEdit/ScheduleEdit.js +++ b/awx/ui/src/components/Schedule/ScheduleEdit/ScheduleEdit.js @@ -30,7 +30,8 @@ function ScheduleEdit({ values, launchConfiguration, surveyConfiguration, - scheduleCredentials = [] + scheduleCredentials = [], + originalLabels = [] ) => { const { execution_environment, @@ -42,13 +43,9 @@ function ScheduleEdit({ exceptionFrequency, exceptionOptions, timezone, + labels, ...submitValues } = values; - const { added, removed } = getAddedAndRemoved( - [...(resource?.summary_fields.credentials || []), ...scheduleCredentials], - credentials - ); - let extraVars; const surveyValues = getSurveyValues(values); @@ -86,10 +83,6 @@ function ScheduleEdit({ submitValues.execution_environment = execution_environment.id; } - submitValues.instance_groups = instance_groups - ? instance_groups.map((s) => s.id) - : []; - try { if (launchConfiguration?.ask_labels_on_launch) { const labelIds = []; @@ -157,17 +150,52 @@ function ScheduleEdit({ const { data: { id: scheduleId }, } = await SchedulesAPI.update(schedule.id, requestData); - if (values.credentials?.length > 0) { - await Promise.all([ - ...removed.map(({ id }) => - SchedulesAPI.disassociateCredential(scheduleId, id) - ), - ...added.map(({ id }) => - SchedulesAPI.associateCredential(scheduleId, id) - ), - ]); + + const { added: addedCredentials, removed: removedCredentials } = + getAddedAndRemoved( + [ + ...(resource?.summary_fields.credentials || []), + ...scheduleCredentials, + ], + credentials + ); + + const { added: addedLabels, removed: removedLabels } = getAddedAndRemoved( + originalLabels, + labels + ); + + let organizationId = resource.organization; + + if (addedLabels.length > 0) { + if (!organizationId) { + const { + data: { results }, + } = await OrganizationsAPI.read(); + organizationId = results[0].id; + } } + await Promise.all([ + ...removedCredentials.map(({ id }) => + SchedulesAPI.disassociateCredential(scheduleId, id) + ), + ...addedCredentials.map(({ id }) => + SchedulesAPI.associateCredential(scheduleId, id) + ), + ...removedLabels.map((label) => + SchedulesAPI.disassociateLabel(scheduleId, label) + ), + ...addedLabels.map((label) => + SchedulesAPI.associateLabel(scheduleId, label, organizationId) + ), + SchedulesAPI.orderInstanceGroups( + scheduleId, + instance_groups, + resource?.summary_fields.instance_groups || [] + ), + ]); + history.push(`${pathRoot}schedules/${scheduleId}/details`); } catch (err) { setFormSubmitError(err); diff --git a/awx/ui/src/components/Schedule/shared/ScheduleForm.js b/awx/ui/src/components/Schedule/shared/ScheduleForm.js index 6a92fd3625..629e0fe29c 100644 --- a/awx/ui/src/components/Schedule/shared/ScheduleForm.js +++ b/awx/ui/src/components/Schedule/shared/ScheduleForm.js @@ -59,7 +59,7 @@ function ScheduleForm({ useCallback(async () => { const { data } = await SchedulesAPI.readZoneInfo(); - let creds; + let creds = []; let allLabels; if (schedule.id) { if ( @@ -107,7 +107,7 @@ function ScheduleForm({ return { zoneOptions: zones, zoneLinks: data.links, - credentials: creds || [], + credentials: creds, labels: allLabels || [], }; }, [ @@ -467,7 +467,13 @@ function ScheduleForm({ }, }} onSubmit={(values) => { - submitSchedule(values, launchConfig, surveyConfig, credentials); + submitSchedule( + values, + launchConfig, + surveyConfig, + credentials, + labels + ); }} validate={validate} > diff --git a/awx/ui/src/components/Schedule/shared/ScheduleForm.test.js b/awx/ui/src/components/Schedule/shared/ScheduleForm.test.js index 47936fc314..5e1ea28b8d 100644 --- a/awx/ui/src/components/Schedule/shared/ScheduleForm.test.js +++ b/awx/ui/src/components/Schedule/shared/ScheduleForm.test.js @@ -17,11 +17,35 @@ jest.mock('../../../api/models/Inventories'); const credentials = { data: { results: [ - { id: 1, kind: 'cloud', name: 'Cred 1', url: 'www.google.com' }, - { id: 2, kind: 'ssh', name: 'Cred 2', url: 'www.google.com' }, - { id: 3, kind: 'Ansible', name: 'Cred 3', url: 'www.google.com' }, - { id: 4, kind: 'Machine', name: 'Cred 4', url: 'www.google.com' }, - { id: 5, kind: 'Machine', name: 'Cred 5', url: 'www.google.com' }, + { + id: 1, + kind: 'cloud', + name: 'Cred 1', + url: 'www.google.com', + inputs: {}, + }, + { id: 2, kind: 'ssh', name: 'Cred 2', url: 'www.google.com', inputs: {} }, + { + id: 3, + kind: 'Ansible', + name: 'Cred 3', + url: 'www.google.com', + inputs: {}, + }, + { + id: 4, + kind: 'Machine', + name: 'Cred 4', + url: 'www.google.com', + inputs: {}, + }, + { + id: 5, + kind: 'Machine', + name: 'Cred 5', + url: 'www.google.com', + inputs: {}, + }, ], }, }; @@ -39,6 +63,12 @@ const launchData = { ask_verbosity_on_launch: false, ask_inventory_on_launch: true, ask_credential_on_launch: false, + ask_execution_environment_on_launch: false, + ask_labels_on_launch: false, + ask_forks_on_launch: false, + ask_job_slice_count_on_launch: false, + ask_timeout_on_launch: false, + ask_instance_groups_on_launch: false, survey_enabled: false, variables_needed_to_start: [], credential_needed_to_start: false, @@ -153,6 +183,12 @@ describe('', () => { ask_verbosity_on_launch: false, ask_inventory_on_launch: true, ask_credential_on_launch: false, + ask_execution_environment_on_launch: false, + ask_labels_on_launch: false, + ask_forks_on_launch: false, + ask_job_slice_count_on_launch: false, + ask_timeout_on_launch: false, + ask_instance_groups_on_launch: false, survey_enabled: false, variables_needed_to_start: [], credential_needed_to_start: false, @@ -208,6 +244,12 @@ describe('', () => { ask_verbosity_on_launch: false, ask_inventory_on_launch: true, ask_credential_on_launch: false, + ask_execution_environment_on_launch: false, + ask_labels_on_launch: false, + ask_forks_on_launch: false, + ask_job_slice_count_on_launch: false, + ask_timeout_on_launch: false, + ask_instance_groups_on_launch: false, survey_enabled: false, variables_needed_to_start: [], credential_needed_to_start: false, @@ -275,6 +317,12 @@ describe('', () => { ask_verbosity_on_launch: false, ask_inventory_on_launch: true, ask_credential_on_launch: false, + ask_execution_environment_on_launch: false, + ask_labels_on_launch: false, + ask_forks_on_launch: false, + ask_job_slice_count_on_launch: false, + ask_timeout_on_launch: false, + ask_instance_groups_on_launch: false, survey_enabled: false, variables_needed_to_start: [], credential_needed_to_start: false, @@ -406,6 +454,12 @@ describe('', () => { ask_verbosity_on_launch: false, ask_inventory_on_launch: true, ask_credential_on_launch: false, + ask_execution_environment_on_launch: false, + ask_labels_on_launch: false, + ask_forks_on_launch: false, + ask_job_slice_count_on_launch: false, + ask_timeout_on_launch: false, + ask_instance_groups_on_launch: false, survey_enabled: false, variables_needed_to_start: [], credential_needed_to_start: false, @@ -465,6 +519,12 @@ describe('', () => { ask_verbosity_on_launch: false, ask_inventory_on_launch: false, ask_credential_on_launch: false, + ask_execution_environment_on_launch: false, + ask_labels_on_launch: false, + ask_forks_on_launch: false, + ask_job_slice_count_on_launch: false, + ask_timeout_on_launch: false, + ask_instance_groups_on_launch: false, survey_enabled: false, variables_needed_to_start: [], credential_needed_to_start: false, @@ -894,7 +954,7 @@ describe('', () => { jest.clearAllMocks(); }); - test('should make API calls to fetch credentials, launch configuration, and survey configuration', async () => { + test('should make API calls to fetch credentials, labels, and zone info', async () => { await act(async () => { wrapper = mountWithContexts( ', () => { type: 'job_template', name: 'Foo Job Template', description: '', + summary_fields: { + credentials: [], + }, }} launchConfig={{ can_start_without_user_input: true, @@ -919,7 +982,13 @@ describe('', () => { ask_limit_on_launch: false, ask_verbosity_on_launch: false, ask_inventory_on_launch: false, - ask_credential_on_launch: false, + ask_credential_on_launch: true, + ask_execution_environment_on_launch: false, + ask_labels_on_launch: true, + ask_forks_on_launch: false, + ask_job_slice_count_on_launch: false, + ask_timeout_on_launch: false, + ask_instance_groups_on_launch: false, survey_enabled: false, variables_needed_to_start: [], credential_needed_to_start: false, @@ -933,7 +1002,9 @@ describe('', () => { /> ); }); + expect(SchedulesAPI.readZoneInfo).toBeCalled(); expect(SchedulesAPI.readCredentials).toBeCalledWith(27); + expect(SchedulesAPI.readAllLabels).toBeCalledWith(27); }); test('should not call API to get credentials ', async () => { @@ -961,6 +1032,12 @@ describe('', () => { ask_verbosity_on_launch: false, ask_inventory_on_launch: false, ask_credential_on_launch: false, + ask_execution_environment_on_launch: false, + ask_labels_on_launch: false, + ask_forks_on_launch: false, + ask_job_slice_count_on_launch: false, + ask_timeout_on_launch: false, + ask_instance_groups_on_launch: false, survey_enabled: false, variables_needed_to_start: [], credential_needed_to_start: false, @@ -991,6 +1068,30 @@ describe('', () => { name: 'Foo Project', description: '', }} + launchConfig={{ + can_start_without_user_input: true, + 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, + ask_execution_environment_on_launch: false, + ask_labels_on_launch: false, + ask_forks_on_launch: false, + ask_job_slice_count_on_launch: false, + ask_timeout_on_launch: false, + ask_instance_groups_on_launch: false, + survey_enabled: false, + variables_needed_to_start: [], + credential_needed_to_start: false, + inventory_needed_to_start: false, + }} /> ); });