From c8cf03a54fafb4692604ad5298b29321578b8e57 Mon Sep 17 00:00:00 2001 From: John Mitchell Date: Wed, 21 Jun 2017 15:05:04 -0400 Subject: [PATCH 1/4] move shared multi credential code to service --- .../job-template-add.controller.js | 30 +-- .../job-template-edit.controller.js | 73 +----- .../factories/callback-help-init.factory.js | 119 +-------- .../job_templates/multi-credential/main.js | 4 +- .../multi-credential-modal.directive.js | 116 +++------ .../multi-credential.directive.js | 26 +- .../multi-credential.service.js | 226 ++++++++++++++++++ 7 files changed, 290 insertions(+), 304 deletions(-) create mode 100644 awx/ui/client/src/templates/job_templates/multi-credential/multi-credential.service.js diff --git a/awx/ui/client/src/templates/job_templates/add-job-template/job-template-add.controller.js b/awx/ui/client/src/templates/job_templates/add-job-template/job-template-add.controller.js index 5b886f55de..9af650ae77 100644 --- a/awx/ui/client/src/templates/job_templates/add-job-template/job-template-add.controller.js +++ b/awx/ui/client/src/templates/job_templates/add-job-template/job-template-add.controller.js @@ -9,13 +9,13 @@ '$stateParams', 'JobTemplateForm', 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'ClearScope', 'GetBasePath', 'md5Setup', 'ParseTypeChange', 'Wait', 'Empty', 'ToJSON', 'CallbackHelpInit', 'GetChoices', '$state', - 'CreateSelect2', '$q', 'i18n', 'Inventory', 'Project', 'InstanceGroupsService', + 'CreateSelect2', '$q', 'i18n', 'Inventory', 'Project', 'InstanceGroupsService', 'MultiCredentialService', function( $filter, $scope, $stateParams, JobTemplateForm, GenerateForm, Rest, Alert, ProcessErrors, ClearScope, GetBasePath, md5Setup, ParseTypeChange, Wait, Empty, ToJSON, CallbackHelpInit, GetChoices, - $state, CreateSelect2, $q, i18n, Inventory, Project, InstanceGroupsService + $state, CreateSelect2, $q, i18n, Inventory, Project, InstanceGroupsService, MultiCredentialService ) { Rest.setUrl(GetBasePath('job_templates')); @@ -262,30 +262,12 @@ null, true); } - $scope.selectedCredentials.extra.map(cred => cred.id) - .forEach(function(cred_id) { - - Rest.setUrl(data.related.extra_credentials); - Rest.post({'id': cred_id}) - .success(function () { - }) - .error(function (data, - status) { - ProcessErrors( - $scope, - data, - status, - form, - { - hdr: 'Error!', - msg: 'Failed to add extra credential. Post returned ' + - 'status: ' + - status - }); - }); + MultiCredentialService + .saveExtraCredentials({ + creds: $scope.selectedCredentials.extra, + url: data.related.extra_credentials }); - var orgDefer = $q.defer(); var associationDefer = $q.defer(); Rest.setUrl(data.related.labels); diff --git a/awx/ui/client/src/templates/job_templates/edit-job-template/job-template-edit.controller.js b/awx/ui/client/src/templates/job_templates/edit-job-template/job-template-edit.controller.js index 487d1f9dab..ea1bce9c0c 100644 --- a/awx/ui/client/src/templates/job_templates/edit-job-template/job-template-edit.controller.js +++ b/awx/ui/client/src/templates/job_templates/edit-job-template/job-template-edit.controller.js @@ -17,14 +17,14 @@ export default 'ParseTypeChange', 'Wait', 'Empty', 'Prompt', 'ToJSON', 'GetChoices', 'CallbackHelpInit', 'InitiatePlaybookRun' , 'initSurvey', '$state', 'CreateSelect2', - 'ToggleNotification','$q', 'InstanceGroupsService', 'InstanceGroupsData', + 'ToggleNotification','$q', 'InstanceGroupsService', 'InstanceGroupsData', 'MultiCredentialService', function( $filter, $scope, $rootScope, $location, $stateParams, JobTemplateForm, GenerateForm, Rest, Alert, ProcessErrors, ClearScope, GetBasePath, md5Setup, ParseTypeChange, Wait, Empty, Prompt, ToJSON, GetChoices, CallbackHelpInit, InitiatePlaybookRun, SurveyControllerInit, $state, - CreateSelect2, ToggleNotification, $q, InstanceGroupsService, InstanceGroupsData + CreateSelect2, ToggleNotification, $q, InstanceGroupsService, InstanceGroupsData, MultiCredentialService ) { ClearScope(); @@ -396,71 +396,10 @@ export default null, true); } - let extraCredUrl = data.related.extra_credentials; - - Rest.setUrl(extraCredUrl); - Rest.get() - .then(({data}) => { - let existingCreds = data.results - .map(cred => cred.id); - - let newCreds = $scope.selectedCredentials.extra - .map(cred => cred.id); - - let toAdd, toRemove; - - [toAdd, toRemove] = _.partition(_.xor(existingCreds, newCreds), cred => (newCreds.indexOf(cred) > -1)); - - let destroyResolve = []; - - toRemove.forEach((cred_id) => { - Rest.setUrl(extraCredUrl); - destroyResolve.push( - Rest.post({'id': cred_id, 'disassociate': true}) - .catch(({data, status}) => { - ProcessErrors( - $scope, - data, - status, - form, - { - hdr: 'Error!', - msg: 'Failed to remove extra credential. Post returned ' + - 'status: ' + - status - }); - })); - }); - - $q.all(destroyResolve) - .then(() => { - toAdd.forEach((cred_id) => { - Rest.setUrl(extraCredUrl); - Rest.post({'id': cred_id}) - .catch(({data, status}) => { - ProcessErrors( - $scope, - data, - status, - form, - { - hdr: 'Error!', - msg: 'Failed to add extra credential. Post returned ' + - 'status: ' + - status - }); - }); - }); - }); - - - }) - .catch(({data, status}) => { - ProcessErrors($scope, data, status, form, { - hdr: 'Error!', - msg: 'Failed to get existing extra credentials. GET returned ' + - 'status: ' + status - }); + MultiCredentialService + .findChangedExtraCredentials({ + creds: $scope.selectedCredentials.extra, + url: data.related.extra_credentials }); InstanceGroupsService.editInstanceGroups(instance_group_url, $scope.instance_groups) diff --git a/awx/ui/client/src/templates/job_templates/factories/callback-help-init.factory.js b/awx/ui/client/src/templates/job_templates/factories/callback-help-init.factory.js index 2aa105ff83..5ad9c9d010 100644 --- a/awx/ui/client/src/templates/job_templates/factories/callback-help-init.factory.js +++ b/awx/ui/client/src/templates/job_templates/factories/callback-help-init.factory.js @@ -1,6 +1,6 @@ export default function CallbackHelpInit($q, $location, GetBasePath, Rest, JobTemplateForm, GenerateForm, $stateParams, ProcessErrors, - ParseVariableString, Empty, Wait) { + ParseVariableString, Empty, Wait, MultiCredentialService) { return function(params) { var scope = params.scope, defaultUrl = GetBasePath('job_templates'), @@ -134,114 +134,15 @@ export default scope.can_edit = data.summary_fields.user_capabilities.edit; - scope.selectedCredentials = { - machine: null, - extra: [] - }; - - var credDefers = []; - - if (data.related.credential) { - Rest.setUrl(data.related.credential); - credDefers.push(Rest.get() - .then(({data}) => { - scope.selectedCredentials.machine = data; - }) - .catch(({data, status}) => { - ProcessErrors( - scope, - data, - status, - null, - { - hdr: 'Error!', - msg: 'Failed to get machine credential. ' + - 'Get returned status: ' + - status - }); - })); - } - - if (data.related.extra_credentials) { - Rest.setUrl(data.related.extra_credentials); - credDefers.push(Rest.get() - .then(({data}) => { - scope.selectedCredentials.extra = data.results; - }) - .catch(({data, status}) => { - ProcessErrors( - scope, - data, - status, - null, - { - hdr: 'Error!', - msg: 'Failed to get extra credentials. ' + - 'Get returned status: ' + - status - }); - })); - } - - Rest.setUrl(GetBasePath('credential_types')); - credDefers.push(Rest.get() - .then(({data}) => { - scope.credentialTypeOptions = []; - data.results.forEach((credentialType => { - if(credentialType.kind.match(/^(machine|cloud|network|ssh)$/)) { - scope.credentialTypeOptions.push({ - name: credentialType.name, - value: credentialType.id - }); - } - })); - }) - .catch(({data, status}) => { - ProcessErrors( - scope, - data, - status, - null, - { - hdr: 'Error!', - msg: 'Failed to get credential types. Get returned ' + - 'status: ' + - status - }); - })); - - $q.all(credDefers) - .then(() => { - let machineCred = []; - let extraCreds = []; - - if (scope.selectedCredentials && scope.selectedCredentials.machine) { - let mach = scope.selectedCredentials.machine; - mach.postType = "machine"; - machineCred = [scope.selectedCredentials.machine]; - } - - if (scope.selectedCredentials && scope.selectedCredentials.extra) { - extraCreds = scope.selectedCredentials.extra; - } - - extraCreds = extraCreds.map(function(cred) { - cred.postType = "extra"; - - return cred; + MultiCredentialService.loadCredentials(data) + .then(([selectedCredentials, credTypes, credTypeOptions, + credTags]) => { + scope.selectedCredentials = selectedCredentials; + scope.credential_types = credTypes; + scope.credentialTypeOptions = credTypeOptions; + scope.credentialsToPost = credTags; + scope.$emit('jobTemplateLoaded', master); }); - - let credTags = machineCred.concat(extraCreds); - - scope.credentialsToPost = credTags.map(cred => ({ - name: cred.name, - id: cred.id, - postType: cred.postType, - kind: scope.credentialTypeOptions - .filter(type => parseInt(cred.credential_type) === type.value)[0].name + ":" - })); - scope.$emit('jobTemplateLoaded', master); - }); }) .error(function (data, status) { ProcessErrors(scope, data, status, form, { @@ -256,5 +157,5 @@ export default CallbackHelpInit.$inject = [ '$q', '$location', 'GetBasePath', 'Rest', 'JobTemplateForm', 'GenerateForm', '$stateParams', 'ProcessErrors', 'ParseVariableString', - 'Empty', 'Wait' + 'Empty', 'Wait', 'MultiCredentialService' ]; diff --git a/awx/ui/client/src/templates/job_templates/multi-credential/main.js b/awx/ui/client/src/templates/job_templates/multi-credential/main.js index 3ab35c1e19..948b982e20 100644 --- a/awx/ui/client/src/templates/job_templates/multi-credential/main.js +++ b/awx/ui/client/src/templates/job_templates/multi-credential/main.js @@ -1,7 +1,9 @@ import multiCredential from './multi-credential.directive'; import multiCredentialModal from './multi-credential-modal.directive'; +import multiCredentialService from './multi-credential.service'; export default angular.module('multiCredential', []) .directive('multiCredential', multiCredential) - .directive('multiCredentialModal', multiCredentialModal); + .directive('multiCredentialModal', multiCredentialModal) + .service('MultiCredentialService', multiCredentialService); diff --git a/awx/ui/client/src/templates/job_templates/multi-credential/multi-credential-modal.directive.js b/awx/ui/client/src/templates/job_templates/multi-credential/multi-credential-modal.directive.js index 8772caeb13..30262abbcb 100644 --- a/awx/ui/client/src/templates/job_templates/multi-credential/multi-credential-modal.directive.js +++ b/awx/ui/client/src/templates/job_templates/multi-credential/multi-credential-modal.directive.js @@ -1,5 +1,5 @@ -export default ['templateUrl', 'Rest', 'GetBasePath', 'generateList', '$compile', 'CreateSelect2', 'i18n', - function(templateUrl, Rest, GetBasePath, GenerateList, $compile, CreateSelect2, i18n) { +export default ['templateUrl', 'Rest', 'GetBasePath', 'generateList', '$compile', 'CreateSelect2', 'i18n', 'MultiCredentialService', + function(templateUrl, Rest, GetBasePath, GenerateList, $compile, CreateSelect2, i18n, MultiCredentialService) { return { restrict: 'E', scope: { @@ -12,17 +12,6 @@ export default ['templateUrl', 'Rest', 'GetBasePath', 'generateList', '$compile' link: function(scope, element) { scope.credentialKind = "1"; - $('#multi-credential-modal').on('hidden.bs.modal', function () { - $('#multi-credential-modal').off('hidden.bs.modal'); - $(element).remove(); - }); - - CreateSelect2({ - element: `#multi-credential-kind-select`, - multiple: false, - placeholder: i18n._('Select a credential') - }); - scope.showModal = function() { $('#multi-credential-modal').modal('show'); }; @@ -42,23 +31,21 @@ export default ['templateUrl', 'Rest', 'GetBasePath', 'generateList', '$compile' .append($compile(html)(scope)); }; - // Go out and get the credential types - Rest.setUrl(GetBasePath('credential_types')); - Rest.get() - .success(function (credentialTypeData) { - let credential_types = {}; - scope.credentialTypeOptions = []; - credentialTypeData.results.forEach((credentialType => { - credential_types[credentialType.id] = credentialType; - if(credentialType.kind - .match(/^(machine|cloud|net|ssh)$/)) { - scope.credentialTypeOptions.push({ - name: credentialType.name, - value: credentialType.id - }); - } - })); + $('#multi-credential-modal').on('hidden.bs.modal', function () { + $('#multi-credential-modal').off('hidden.bs.modal'); + $(element).remove(); + }); + + CreateSelect2({ + element: `#multi-credential-kind-select`, + multiple: false, + placeholder: i18n._('Select a credential') + }); + + MultiCredentialService.getCredentialTypes() + .then(({credential_types, credentialTypeOptions}) => { scope.credential_types = credential_types; + scope.credentialTypeOptions = credentialTypeOptions; scope.$emit('multiCredentialModalLinked'); }); }, @@ -66,42 +53,6 @@ export default ['templateUrl', 'Rest', 'GetBasePath', 'generateList', '$compile' controller: ['$scope', 'CredentialList', 'i18n', 'QuerySet', 'GetBasePath', function($scope, CredentialList, i18n, qs, GetBasePath) { - - let updateCredentialTags = function() { - let machineCred = []; - let extraCreds = []; - - if ($scope.selectedCredentials && - $scope.selectedCredentials.machine) { - let mach = $scope.selectedCredentials.machine; - mach.postType = "machine"; - machineCred = [$scope.selectedCredentials.machine]; - } - - if ($scope.selectedCredentials && - $scope.selectedCredentials.extra) { - extraCreds = $scope.selectedCredentials.extra; - } - - extraCreds = extraCreds.map(function(cred) { - cred.postType = "extra"; - - return cred; - }); - - let credTags = machineCred.concat(extraCreds); - - $scope.credTags = credTags.map(cred => ({ - name: cred.name, - id: cred.id, - postType: cred.postType, - kind: $scope.credentialTypeOptions - .filter(type => { - return parseInt(cred.credential_type) === type.value; - })[0].name + ":" - })); - }; - let updateExtraCredentialsList = function() { let extraCredIds = $scope.selectedCredentials.extra .map(cred => cred.id); @@ -111,7 +62,10 @@ export default ['templateUrl', 'Rest', 'GetBasePath', 'generateList', '$compile' .indexOf(cred.id) > - 1) ? 1 : 0; } }); - updateCredentialTags(); + + $scope.credTags = MultiCredentialService + .updateCredentialTags($scope.selectedCredentials, + $scope.credentialTypeOptions); }; let updateMachineCredentialList = function() { @@ -123,14 +77,20 @@ export default ['templateUrl', 'Rest', 'GetBasePath', 'generateList', '$compile' .machine.id) ? 1 : 0; } }); - updateCredentialTags(); + + $scope.credTags = MultiCredentialService + .updateCredentialTags($scope.selectedCredentials, + $scope.credentialTypeOptions); }; let uncheckAllCredentials = function() { $scope.credentials.forEach(cred => { cred.checked = 0; }); - updateCredentialTags(); + + $scope.credTags = MultiCredentialService + .updateCredentialTags($scope.selectedCredentials, + $scope.credentialTypeOptions); }; let init = function() { @@ -264,22 +224,10 @@ export default ['templateUrl', 'Rest', 'GetBasePath', 'generateList', '$compile' }; $scope.removeCredential = function(credToRemove) { - $scope.credTags - .forEach(function(cred) { - if (credToRemove === cred.id) { - if (cred.postType === 'machine') { - $scope.selectedCredentials[cred.postType] = null; - } else { - $scope.selectedCredentials[cred.postType] = $scope - .selectedCredentials[cred.postType] - .filter(cred => cred - .id !== credToRemove); - } - } - }); - - $scope.credTags = $scope.credTags - .filter(cred => cred.id !== credToRemove); + [$scope.selectedCredentials, + $scope.credTags] = MultiCredentialService + .removeCredential(credToRemove, + $scope.selectedCredentials, $scope.credTags); if ($scope.credentials .filter(cred => cred.id === credToRemove).length) { diff --git a/awx/ui/client/src/templates/job_templates/multi-credential/multi-credential.directive.js b/awx/ui/client/src/templates/job_templates/multi-credential/multi-credential.directive.js index bb6a917e49..f575c7fd44 100644 --- a/awx/ui/client/src/templates/job_templates/multi-credential/multi-credential.directive.js +++ b/awx/ui/client/src/templates/job_templates/multi-credential/multi-credential.directive.js @@ -16,8 +16,8 @@ export default ['templateUrl', '$compile', }, restrict: 'E', templateUrl: templateUrl('templates/job_templates/multi-credential/multi-credential'), - controller: ['$scope', - function($scope) { + controller: ['$scope', 'MultiCredentialService', + function($scope, MultiCredentialService) { if (!$scope.selectedCredentials) { $scope.selectedCredentials = { machine: null, @@ -43,23 +43,11 @@ export default ['templateUrl', '$compile', }); $scope.removeCredential = function(credToRemove) { - $scope.credentialsToPost = $scope.credentialsToPost - .filter(function(cred) { - if (cred.id === credToRemove) { - if (cred.postType === 'machine') { - $scope.selectedCredentials.machine = null; - } else { - $scope.selectedCredentials - .extra = $scope.selectedCredentials - .extra - .filter(selectedCred => { - return selectedCred - .id !== credToRemove; - }); - } - } - return cred.id !== credToRemove; - }); + [$scope.selectedCredentials, + $scope.credentialsToPost] = MultiCredentialService + .removeCredential(credToRemove, $scope. + selectedCredentials, + $scope.credentialsToPost); }; } ], diff --git a/awx/ui/client/src/templates/job_templates/multi-credential/multi-credential.service.js b/awx/ui/client/src/templates/job_templates/multi-credential/multi-credential.service.js new file mode 100644 index 0000000000..33d5f7ffba --- /dev/null +++ b/awx/ui/client/src/templates/job_templates/multi-credential/multi-credential.service.js @@ -0,0 +1,226 @@ +export default ['Rest', 'ProcessErrors', '$q', 'GetBasePath', function(Rest, ProcessErrors, $q, GetBasePath) { + let val = {}; + + // given an array of creds, POST them to url and return an array + // of promises + val.saveExtraCredentials = ({creds, url, disassociate = false, + msg = "Failed to add extra credential. POST returned status:"}) => { + if (creds && creds[0] && typeof creds[0] !== 'number') { + creds = creds.map(cred => cred.id); + } + + return creds.map((cred_id) => { + let payload = {'id': cred_id}; + + if (disassociate) { + payload.disassociate = true; + } + + Rest.setUrl(url); + + return Rest.post(payload) + .catch(({data, status}) => { + ProcessErrors( + null, data, status, null, + { + hdr: 'Error!', + msg: `${msg} ${status}` + }); + }); + }); + }; + + // removes credentials no longer a part of the jt, and adds + // new ones + val.findChangedExtraCredentials = ({creds, url}) => { + Rest.setUrl(url); + Rest.get() + .then(({data}) => { + let existingCreds = data.results + .map(cred => cred.id); + + let newCreds = creds + .map(cred => cred.id); + + let [toAdd, toRemove] = _.partition(_.xor(existingCreds, + newCreds), cred => (newCreds.indexOf(cred) > -1)); + + let destroyResolve = []; + + destroyResolve = val.saveExtraCredentials({ + creds: toRemove, + url: url, + disassociate: true, + msg: `Failed to disassociate existing credential. + POST returned status:` + }); + + $q.all(destroyResolve).then(() => { + val.saveExtraCredentials({ + creds: toAdd, + url: url + }); + }); + + + }) + .catch(({data, status}) => { + ProcessErrors(null, data, status, null, { + hdr: 'Error!', + msg: 'Failed to get existing extra credentials. GET ' + + 'returned status: ' + status + }); + }); + }; + + // calls credential types and returns the data needed to set up the + // credential type selector + val.getCredentialTypes = () => { + Rest.setUrl(GetBasePath('credential_types')); + return Rest.get() + .then(({data}) => { + let credential_types = {}, credentialTypeOptions = []; + + data.results.forEach((credentialType => { + credential_types[credentialType.id] = credentialType; + if(credentialType.kind + .match(/^(machine|cloud|net|ssh)$/)) { + credentialTypeOptions.push({ + name: credentialType.name, + value: credentialType.id + }); + } + })); + + return { + credential_types, + credentialTypeOptions + }; + }) + .catch(({data, status}) => { + ProcessErrors(null, data, status, null, { + hdr: 'Error!', + msg: 'Failed to get credential types. GET returned ' + + 'status: ' + status + }); + }); + }; + + // converts structured selected credential data into array for tag-based + // view + val.updateCredentialTags = (creds, typeOpts) => { + let machineCred = []; + let extraCreds = []; + + if (creds.machine) { + let mach = creds.machine; + mach.postType = "machine"; + machineCred = [mach]; + } + + if (creds.extra) { + extraCreds = creds.extra + .map((cred) => { + cred.postType = "extra"; + + return cred; + }); + } + + return machineCred.concat(extraCreds).map(cred => ({ + name: cred.name, + id: cred.id, + postType: cred.postType, + kind: typeOpts + .filter(type => { + return parseInt(cred.credential_type) === type.value; + })[0].name + ":" + })); + }; + + // remove credential from structured selected credential data and tag-view + // array + val.removeCredential = (credToRemove, structuredObj, tagArr) => { + tagArr.forEach((cred) => { + if (credToRemove === cred.id) { + if (cred.postType === 'machine') { + structuredObj[cred.postType] = null; + } else { + structuredObj[cred.postType] = structuredObj[cred.postType] + .filter(cred => cred + .id !== credToRemove); + } + } + }); + + tagArr = tagArr + .filter(cred => cred.id !== credToRemove); + + return [structuredObj, tagArr]; + }; + + // load all relevant credential data to populate job template edit form + val.loadCredentials = (data) => { + let selectedCredentials = { + machine: null, + extra: [] + }, credTypes, credTypeOptions, credTags; + + let credDefers = []; + + // get machine credential + if (data.related.credential) { + Rest.setUrl(data.related.credential); + credDefers.push(Rest.get() + .then(({data}) => { + selectedCredentials.machine = data; + }) + .catch(({data, status}) => { + ProcessErrors( + null, data, status, null, + { + hdr: 'Error!', + msg: 'Failed to get machine credential. ' + + 'Get returned status: ' + + status + }); + })); + } + + // get extra credentials + if (data.related.extra_credentials) { + Rest.setUrl(data.related.extra_credentials); + credDefers.push(Rest.get() + .then(({data}) => { + selectedCredentials.extra = data.results; + }) + .catch(({data, status}) => { + ProcessErrors(null, data, status, null, + { + hdr: 'Error!', + msg: 'Failed to get extra credentials. ' + + 'Get returned status: ' + + status + }); + })); + } + + // get credential types + credDefers.push(val.getCredentialTypes() + .then(({credential_types, credentialTypeOptions}) => { + credTypes = credential_types; + credTypeOptions = credentialTypeOptions; + })); + + return $q.all(credDefers).then(() => { + // get credential tags + credTags = val + .updateCredentialTags(selectedCredentials, credTypeOptions); + + return [selectedCredentials, credTypes, credTypeOptions, + credTags]; + }); + }; + + return val; +}]; From 8d6408fb5341458f553874e21b20e7d65f13a22f Mon Sep 17 00:00:00 2001 From: John Mitchell Date: Wed, 21 Jun 2017 15:40:13 -0400 Subject: [PATCH 2/4] add MultiCredentialService.updateCredentialTags unit tests --- .../multi-credential.service-test.js | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 awx/ui/tests/spec/multi-credential/multi-credential.service-test.js diff --git a/awx/ui/tests/spec/multi-credential/multi-credential.service-test.js b/awx/ui/tests/spec/multi-credential/multi-credential.service-test.js new file mode 100644 index 0000000000..60b24b52a5 --- /dev/null +++ b/awx/ui/tests/spec/multi-credential/multi-credential.service-test.js @@ -0,0 +1,100 @@ +'use strict' + +describe('MultiCredentialService', () => { + let MultiCredentialService; + + beforeEach(angular.mock.module('multiCredential', + ($provide) => { + ['Rest', 'ProcessErrors', '$q', 'GetBasePath'] + .forEach(item => $provide.value(item, {})); + })); + + beforeEach(angular.mock.inject((_MultiCredentialService_) => { + MultiCredentialService = _MultiCredentialService_; + })); + + describe('updateCredentialTags', () => { + it('should return array of selected credentials (empty)', () => { + let creds = { + machine: null, + extra: [] + }; + + let typeOpts = []; + + let expected = []; + + let actual = MultiCredentialService + .updateCredentialTags(creds, typeOpts); + + let equal = _.isEqual(expected.sort(), actual.sort()); + + expect(equal).toBe(true); + }); + + it('should return array of selected credentials (populated)', () => { + let creds = { + machine: { + credential_type: 1, + id: 3, + name: 'ssh' + }, + extra: [ + { + credential_type: 2, + id: 4, + name: 'aws' + }, + { + credential_type: 3, + id: 5, + name: 'gce' + } + ] + }; + + let typeOpts = [ + { + name: 'SSH', + value: 1 + }, + { + name: 'Amazon Web Services', + value: 2 + }, + { + name: 'Google Compute Engine', + value: 3 + } + ]; + + let expected = [ + { + name: 'ssh', + id: 3, + postType: 'machine', + kind: 'SSH:' + }, + { + name: 'aws', + id: 4, + postType: 'extra', + kind: 'Amazon Web Services:' + }, + { + name: 'gce', + id: 5, + postType: 'extra', + kind: 'Google Compute Engine:' + } + ]; + + let actual = MultiCredentialService + .updateCredentialTags(creds, typeOpts); + + let equal = _.isEqual(expected.sort(), actual.sort()); + + expect(equal).toBe(true); + }); + }); +}); From 74e03083f13fbc5271c6ed3a5dc32251590a566d Mon Sep 17 00:00:00 2001 From: John Mitchell Date: Wed, 21 Jun 2017 15:49:41 -0400 Subject: [PATCH 3/4] propogate unnecessary unchecking of machine cred to multicredential modal (previous prompt on launch fix) --- .../multi-credential/multi-credential-modal.directive.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/awx/ui/client/src/templates/job_templates/multi-credential/multi-credential-modal.directive.js b/awx/ui/client/src/templates/job_templates/multi-credential/multi-credential-modal.directive.js index 30262abbcb..4b629e9bba 100644 --- a/awx/ui/client/src/templates/job_templates/multi-credential/multi-credential-modal.directive.js +++ b/awx/ui/client/src/templates/job_templates/multi-credential/multi-credential-modal.directive.js @@ -140,7 +140,7 @@ export default ['templateUrl', 'Rest', 'GetBasePath', 'generateList', '$compile' $scope.selectedCredentials.extra.length > 0 && parseInt($scope.credentialKind) !== 1) { updateExtraCredentialsList(); - } else { + } else if (parseInt($scope.credentialKind) !== 1) { uncheckAllCredentials(); } } From 2f255cc521c2f1c78ad9d37572397201206b2745 Mon Sep 17 00:00:00 2001 From: John Mitchell Date: Wed, 21 Jun 2017 16:10:25 -0400 Subject: [PATCH 4/4] removeCred unit test and skeleton for other service function --- .../multi-credential.service-test.js | 242 ++++++++++++++++++ 1 file changed, 242 insertions(+) diff --git a/awx/ui/tests/spec/multi-credential/multi-credential.service-test.js b/awx/ui/tests/spec/multi-credential/multi-credential.service-test.js index 60b24b52a5..9f47abd231 100644 --- a/awx/ui/tests/spec/multi-credential/multi-credential.service-test.js +++ b/awx/ui/tests/spec/multi-credential/multi-credential.service-test.js @@ -13,6 +13,53 @@ describe('MultiCredentialService', () => { MultiCredentialService = _MultiCredentialService_; })); + describe('saveExtraCredentials', () => { + xit('should handle creds as array of objects and array of ids', () => { + expect(false).toBe(true); + }); + + xit('should post creds with add payload', () => { + expect(false).toBe(true); + }); + + xit('should post creds with disassociate payload', () => { + expect(false).toBe(true); + }); + + xit('should call ProcessErrors when post fails', () => { + expect(false).toBe(true); + }); + }); + + describe('findChangedExtraCredentials', () => { + xit('should find which creds to add and post them', () => { + expect(false).toBe(true); + }); + + xit('should find which creds to remove and disassociate them', () => { + expect(false).toBe(true); + }); + + xit('should not post/disassociate non-changed creds', () => { + expect(false).toBe(true); + }); + + xit('should call ProcessErrors when any get/post fails', () => { + expect(false).toBe(true); + }); + }); + + describe('getCredentialTypes', () => { + xit('should get cred types and return them directly, as well ' + + 'as options for building credential type select box', () => { + expect(false).toBe(true); + }); + + xit('should call ProcessErrors when getting cred types fails', () => { + expect(false).toBe(true); + }); + }); + describe('updateCredentialTags', () => { it('should return array of selected credentials (empty)', () => { let creds = { @@ -97,4 +144,199 @@ describe('MultiCredentialService', () => { expect(equal).toBe(true); }); }); + + describe('removeCredential', () => { + it('should remove machine cred from structured obj and tag arr', () => { + let credToRemove = 3; + + let structuredObj = { + machine: { + credential_type: 1, + id: 3, + name: 'ssh' + }, + extra: [ + { + credential_type: 2, + id: 4, + name: 'aws' + }, + { + credential_type: 3, + id: 5, + name: 'gce' + } + ] + }; + + let tagArr = [ + { + name: 'ssh', + id: 3, + postType: 'machine', + kind: 'SSH:' + }, + { + name: 'aws', + id: 4, + postType: 'extra', + kind: 'Amazon Web Services:' + }, + { + name: 'gce', + id: 5, + postType: 'extra', + kind: 'Google Compute Engine:' + } + ]; + + let expected = [ + { + machine: null, + extra: [ + { + credential_type: 2, + id: 4, + name: 'aws' + }, + { + credential_type: 3, + id: 5, + name: 'gce' + } + ] + }, + [ + { + name: 'aws', + id: 4, + postType: 'extra', + kind: 'Amazon Web Services:' + }, + { + name: 'gce', + id: 5, + postType: 'extra', + kind: 'Google Compute Engine:' + } + ] + ]; + + let actual = MultiCredentialService + .removeCredential(credToRemove, structuredObj, tagArr); + + let equal = _.isEqual(expected.sort(), actual.sort()); + + expect(equal).toBe(true); + }); + + it('should remove extra cred from structured obj and tag arr', () => { + let credToRemove = 4; + + let structuredObj = { + machine: { + credential_type: 1, + id: 3, + name: 'ssh' + }, + extra: [ + { + credential_type: 2, + id: 4, + name: 'aws' + }, + { + credential_type: 3, + id: 5, + name: 'gce' + } + ] + }; + + let tagArr = [ + { + name: 'ssh', + id: 3, + postType: 'machine', + kind: 'SSH:' + }, + { + name: 'aws', + id: 4, + postType: 'extra', + kind: 'Amazon Web Services:' + }, + { + name: 'gce', + id: 5, + postType: 'extra', + kind: 'Google Compute Engine:' + } + ]; + + let expected = [ + { + machine: { + credential_type: 1, + id: 3, + name: 'ssh' + }, + extra: [ + { + credential_type: 3, + id: 5, + name: 'gce' + } + ] + }, + [ + { + name: 'ssh', + id: 3, + postType: 'machine', + kind: 'SSH:' + }, + { + name: 'gce', + id: 5, + postType: 'extra', + kind: 'Google Compute Engine:' + } + ] + ]; + + let actual = MultiCredentialService + .removeCredential(credToRemove, structuredObj, tagArr); + + let equal = _.isEqual(expected.sort(), actual.sort()); + + expect(equal).toBe(true); + }); + }); + + describe('loadCredentials', () => { + xit('should call to get machine credential data', () => { + expect(false).toBe(true); + }); + + xit('should call ProcessErrors if machine cred get fails', () => { + expect(false).toBe(true); + }); + + xit('should call to get extra credentials data', () => { + expect(false).toBe(true); + }); + + xit('should call ProcessErrors if extra creds get fails', () => { + expect(false).toBe(true); + }); + + xit('should call to get credential types', () => { + expect(false).toBe(true); + }); + + xit('should call to update cred tags once GETs have completed', () => { + expect(false).toBe(true); + }); + }); });