First pass at automated jt launch tests

This commit is contained in:
mabashian 2018-05-16 16:47:14 -04:00 committed by Jake McDermott
parent a6837343a5
commit 264b0f248a
4 changed files with 214 additions and 25 deletions

View File

@ -35,7 +35,7 @@
</ul>
</div>
</div>
<at-list results="templates">
<at-list results="templates" id="templates_list">
<at-row ng-repeat="template in templates"
ng-class="{'at-Row--active': (template.id === vm.activeId)}"
template-id="{{ template.id }}"

View File

@ -1,20 +1,20 @@
<div class="Prompt">
<div class="Prompt" id="prompt_modal">
<at-modal ng-if="vm.promptDataClone">
<at-tab-group>
<at-tab ng-if="vm.steps.inventory.tab" state="vm.steps.inventory.tab">{{:: vm.strings.get('prompt.INVENTORY') }}</at-tab>
<at-tab ng-if="vm.steps.credential.tab" state="vm.steps.credential.tab">{{:: vm.strings.get('prompt.CREDENTIAL') }}</at-tab>
<at-tab ng-if="vm.steps.other_prompts.tab" state="vm.steps.other_prompts.tab">{{:: vm.strings.get('prompt.OTHER_PROMPTS') }}</at-tab>
<at-tab ng-if="vm.steps.survey.tab" state="vm.steps.survey.tab">{{:: vm.strings.get('prompt.SURVEY') }}</at-tab>
<at-tab state="vm.steps.preview.tab">{{:: vm.strings.get('prompt.PREVIEW') }}</at-tab>
<at-tab id="prompt_inventory_tab" ng-if="vm.steps.inventory.tab" state="vm.steps.inventory.tab">{{:: vm.strings.get('prompt.INVENTORY') }}</at-tab>
<at-tab id="prompt_credential_tab" ng-if="vm.steps.credential.tab" state="vm.steps.credential.tab">{{:: vm.strings.get('prompt.CREDENTIAL') }}</at-tab>
<at-tab id="prompt_other_prompts_tab" ng-if="vm.steps.other_prompts.tab" state="vm.steps.other_prompts.tab">{{:: vm.strings.get('prompt.OTHER_PROMPTS') }}</at-tab>
<at-tab id="prompt_survey_tab" ng-if="vm.steps.survey.tab" state="vm.steps.survey.tab">{{:: vm.strings.get('prompt.SURVEY') }}</at-tab>
<at-tab id="prompt_preview_tab" state="vm.steps.preview.tab">{{:: vm.strings.get('prompt.PREVIEW') }}</at-tab>
</at-tab-group>
<div class="Prompt-step">
<div ng-if="vm.steps.inventory.includeStep" ng-show="vm.steps.inventory.tab._active">
<div ng-if="vm.steps.inventory.includeStep" ng-show="vm.steps.inventory.tab._active" id="prompt_inventory_step">
<prompt-inventory
prompt-data="vm.promptDataClone"
read-only-prompts="vm.readOnlyPrompts">
</prompt-inventory>
</div>
<div ng-if="vm.steps.credential.includeStep" ng-show="vm.steps.credential.tab._active">
<div ng-if="vm.steps.credential.includeStep" ng-show="vm.steps.credential.tab._active" id="prompt_credential_step">
<prompt-credential
prompt-data="vm.promptDataClone"
credential-passwords-form="vm.forms.credentialPasswords"
@ -22,7 +22,7 @@
read-only-prompts="vm.readOnlyPrompts">
</prompt-credential>
</div>
<div ng-if="vm.steps.other_prompts.includeStep" ng-show="vm.steps.other_prompts.tab._active">
<div ng-if="vm.steps.other_prompts.includeStep" ng-show="vm.steps.other_prompts.tab._active" id="prompt_other_prompts_step">
<prompt-other-prompts
prompt-data="vm.promptDataClone"
other-prompts-form="vm.forms.otherPrompts"
@ -31,31 +31,31 @@
read-only-prompts="vm.readOnlyPrompts">
</prompt-other-prompts>
</div>
<div ng-if="vm.steps.survey.includeStep" ng-show="vm.steps.survey.tab._active">
<div ng-if="vm.steps.survey.includeStep" ng-show="vm.steps.survey.tab._active" id="prompt_survey_step">
<prompt-survey
prompt-data="vm.promptDataClone"
survey-form="vm.forms.survey"
read-only-prompts="vm.readOnlyPrompts">
</prompt-survey>
</div>
<div ng-if="vm.steps.preview.tab._active">
<div ng-if="vm.steps.preview.tab._active" id="prompt_preview_step">
<prompt-preview prompt-data="vm.promptDataClone"></prompt-preview>
</div>
</div>
<div class="Prompt-footer">
<button class="Prompt-defaultButton" ng-click="vm.cancel()" ng-show="!vm.readOnlyPrompts">{{:: vm.strings.get('CANCEL') }}</button>
<button class="Prompt-defaultButton" ng-click="vm.cancel()" ng-show="vm.readOnlyPrompts">{{:: vm.strings.get('CLOSE') }}</button>
<button class="Prompt-actionButton" ng-show="vm.steps.inventory.tab._active" ng-click="vm.next(vm.steps.inventory.tab)" ng-disabled="!vm.promptDataClone.prompts.inventory.value.id && !vm.readOnlyPrompts">{{:: vm.strings.get('NEXT') }}</button>
<button class="Prompt-actionButton"
<button id="prompt_cancel" class="Prompt-defaultButton" ng-click="vm.cancel()" ng-show="!vm.readOnlyPrompts">{{:: vm.strings.get('CANCEL') }}</button>
<button id="prompt_close" class="Prompt-defaultButton" ng-click="vm.cancel()" ng-show="vm.readOnlyPrompts">{{:: vm.strings.get('CLOSE') }}</button>
<button id="prompt_inventory_next" class="Prompt-actionButton" ng-show="vm.steps.inventory.tab._active" ng-click="vm.next(vm.steps.inventory.tab)" ng-disabled="!vm.promptDataClone.prompts.inventory.value.id && !vm.readOnlyPrompts">{{:: vm.strings.get('NEXT') }}</button>
<button id="prompt_credential_next" class="Prompt-actionButton"
ng-show="vm.steps.credential.tab._active"
ng-click="vm.next(vm.steps.credential.tab)"
ng-disabled="!vm.readOnlyPrompts &&
((preventCredsWithPasswords && (vm.promptDataClone.prompts.credentials.passwords.ssh_password || vm.promptDataClone.prompts.credentials.passwords.become_password || vm.promptDataClone.prompts.credentials.passwords.ssh_key_unlock || (vm.promptDataClone.prompts.credentials.passwords.vault && vm.promptDataClone.prompts.credentials.passwords.vault.length > 0))) ||
!vm.forms.credentialPasswords.$valid ||
(vm.promptDataClone.credentialTypeMissing && vm.promptDataClone.credentialTypeMissing.length > 0))">{{:: vm.strings.get('NEXT') }}</button>
<button class="Prompt-actionButton" ng-show="vm.steps.other_prompts.tab._active" ng-click="vm.next(vm.steps.other_prompts.tab)" ng-disabled="!vm.readOnlyPrompts && !vm.forms.otherPrompts.$valid">{{:: vm.strings.get('NEXT') }}</button>
<button class="Prompt-actionButton" ng-show="vm.steps.survey.tab._active" ng-click="vm.next(vm.steps.survey.tab)" ng-disabled="!vm.readOnlyPrompts && !vm.forms.survey.$valid">{{:: vm.strings.get('NEXT') }}</button>
<button class="Prompt-actionButton" ng-show="vm.steps.preview.tab._active && !vm.readOnlyPrompts" ng-click="vm.finish()" ng-bind="vm.actionText" ng-disabled="vm.actionButtonClicked"></button>
<button id="prompt_other_prompts_next" class="Prompt-actionButton" ng-show="vm.steps.other_prompts.tab._active" ng-click="vm.next(vm.steps.other_prompts.tab)" ng-disabled="!vm.readOnlyPrompts && !vm.forms.otherPrompts.$valid">{{:: vm.strings.get('NEXT') }}</button>
<button id="prompt_survey_next" class="Prompt-actionButton" ng-show="vm.steps.survey.tab._active" ng-click="vm.next(vm.steps.survey.tab)" ng-disabled="!vm.readOnlyPrompts && !vm.forms.survey.$valid">{{:: vm.strings.get('NEXT') }}</button>
<button id="prompt_finish" class="Prompt-actionButton" ng-show="vm.steps.preview.tab._active && !vm.readOnlyPrompts" ng-click="vm.finish()" ng-bind="vm.actionText" ng-disabled="vm.actionButtonClicked"></button>
</div>
</at-modal>
</div>

View File

@ -11,7 +11,7 @@ import pagination from './sections/pagination';
import permissions from './sections/permissions';
import search from './sections/search';
const details = createFormSection({
const jtDetails = createFormSection({
selector: 'form',
props: {
formElementSelectors: [
@ -31,6 +31,25 @@ const details = createFormSection({
}
});
const wfjtDetails = createFormSection({
selector: 'form',
props: {
formElementSelectors: [
'#workflow_job_template_form .Form-textInput',
'#workflow_job_template_form select.Form-dropDown',
'#workflow_job_template_form .Form-textArea',
'#workflow_job_template_form input[type="checkbox"]',
'#workflow_job_template_form .ui-spinner-input',
'#workflow_job_template_form .ScheduleToggle-switch'
]
},
labels: {
name: 'Name',
description: 'Description'
}
});
const lookupInventory = _.merge({}, lookupModal, {
locateStrategy: 'xpath',
selector: './/div[text()="Select inventory"]/ancestor::div[contains(@class, "modal-content")]'
@ -54,7 +73,7 @@ module.exports = {
addJobTemplate: {
selector: 'div[ui-view="form"]',
sections: {
details
jtDetails
},
elements: {
title: 'div[class^="Form-title"]'
@ -63,7 +82,7 @@ module.exports = {
editJobTemplate: {
selector: 'div[ui-view="form"]',
sections: {
details,
jtDetails,
permissions
},
elements: {
@ -73,7 +92,7 @@ module.exports = {
addWorkflowJobTemplate: {
selector: 'div[ui-view="form"]',
sections: {
details
wfjtDetails
},
elements: {
title: 'div[class^="Form-title"]'
@ -82,7 +101,7 @@ module.exports = {
editWorkflowJobTemplate: {
selector: 'div[ui-view="form"]',
sections: {
details,
wfjtDetails,
permissions
},
elements: {
@ -90,7 +109,7 @@ module.exports = {
}
},
list: {
selector: '.Panel',
selector: '.at-Panel',
elements: {
badge: 'span[class~="badge"]',
title: 'div[class="List-titleText"]',

View File

@ -0,0 +1,170 @@
import { post, patch } from '../api';
import {
getOrCreate,
getProject,
getInventory
} from '../fixtures';
let templateReferences = {};
module.exports = {
before: (client, done) => {
const resources = [
getProject('test-launch-jt'),
getInventory('test-launch-jt')
];
Promise.all(resources)
.then(([project, inventory]) => {
const noPromptPromise = getOrCreate('/job_templates/', {
name: `test-launch-jt-no-prompts`,
inventory: inventory.id,
project: project.id,
playbook: 'hello_world.yml',
});
const promptNoPassPromise = getOrCreate('/job_templates/', {
name: `test-launch-jt-prompts-no-pass`,
inventory: inventory.id,
ask_inventory_on_launch: true,
project: project.id,
playbook: 'hello_world.yml',
ask_diff_mode_on_launch: true,
ask_variables_on_launch: true,
ask_limit_on_launch: true,
ask_tags_on_launch: true,
ask_skip_tags_on_launch: true,
ask_job_type_on_launch: true,
ask_verbosity_on_launch: true,
ask_credential_on_launch: true
});
Promise.all([noPromptPromise, promptNoPassPromise])
.then(([noPrompt, promptNoPass]) => {
templateReferences = {noPrompt, promptNoPass};
let surveyPost = post(promptNoPass.related.survey_spec, {
name: "",
description: "",
spec: [{
question_name: "Foo",
question_description: "",
required: true,
type: "text",
variable: "foo",
min: 0,
max: 1024,
default: "bar",
choices: "",
new_question: true
}]
});
let surveyPatch = patch(promptNoPass.url, { survey_enabled: true });
Promise.all([surveyPost, surveyPatch])
.then(done);
});
});
},
'login to awx': client => {
client.login();
client.resizeWindow(1200, 800);
client.waitForAngular();
},
'expected jt launch with no prompts to navigate to job details': client => {
const templates = client.page.templates();
templates.load();
templates.waitForElementVisible('input[class*="SmartSearch-input"]');
templates.section.list.section.search
.sendKeys('@input', `id:${templateReferences.noPrompt.id}`);
// work in progress trying to check search input for correct text
// templates.section.list.section.search.getText('@input', function(result) {
// client.assert.equal(result.value, `id:${templateReferences.noPrompt.id}`);
// });
templates.section.list.section.search.click('i[class$="search"]');
templates.waitForElementVisible('div.spinny');
templates.waitForElementNotVisible('div.spinny');
templates.expect.element(`#templates_list .at-Row[id="row-${templateReferences.noPrompt.id}"]`).visible;
templates.expect.element('i[class*="icon-launch"]').visible;
templates.expect.element('i[class*="icon-launch"]').enabled;
templates.click('i[class*="icon-launch"]');
templates.waitForElementVisible('div.spinny');
templates.waitForElementNotVisible('div.spinny');
client.waitForElementVisible('at-job-details');
},
'expected jt launch with prompts but no changes to navigate to job details': client => {
const templates = client.page.templates();
templates.load();
templates.waitForElementVisible('input[class*="SmartSearch-input"]', 5000);
templates.section.list.section.search
.sendKeys('@input', `id:${templateReferences.promptNoPass.id}`);
templates.section.list.section.search.click('i[class$="search"]');
templates.waitForElementVisible('div.spinny');
templates.waitForElementNotVisible('div.spinny');
templates.expect.element(`#templates_list .at-Row[id="row-${templateReferences.promptNoPass.id}"]`).visible;
templates.expect.element('i[class*="icon-launch"]').visible;
templates.expect.element('i[class*="icon-launch"]').enabled;
templates.click('i[class*="icon-launch"]');
templates.waitForElementVisible('.Prompt-previewTag');
templates.expect.element('#prompt_inventory_tab').visible;
templates.expect.element('#prompt_inventory_tab').to.have.attribute('class').which.contains('at-Tab--active');
templates.expect.element('#prompt_inventory_next').visible;
templates.expect.element('#prompt_inventory_next').enabled;
templates.click('#prompt_inventory_next');
templates.waitForElementVisible('#prompt_credential_step');
templates.expect.element('#prompt_credential_tab').visible;
templates.expect.element('#prompt_credential_tab').to.have.attribute('class').which.contains('at-Tab--active');
templates.expect.element('#prompt_credential_next').visible;
templates.expect.element('#prompt_credential_next').enabled;
templates.click('#prompt_credential_next');
templates.waitForElementVisible('#prompt_other_prompts_step');
templates.expect.element('#prompt_other_prompts_tab').visible;
templates.expect.element('#prompt_other_prompts_tab').to.have.attribute('class').which.contains('at-Tab--active');
templates.expect.element('#prompt_other_prompts_next').visible;
templates.expect.element('#prompt_other_prompts_next').enabled;
templates.click('#prompt_other_prompts_next');
templates.waitForElementVisible('#prompt_survey_step');
templates.expect.element('#prompt_survey_tab').visible;
templates.expect.element('#prompt_survey_tab').to.have.attribute('class').which.contains('at-Tab--active');
templates.expect.element('#prompt_survey_next').visible;
templates.expect.element('#prompt_survey_next').enabled;
templates.click('#prompt_survey_next');
templates.waitForElementVisible('#prompt_preview_step');
templates.expect.element('#prompt_preview_tab').visible;
templates.expect.element('#prompt_preview_tab').to.have.attribute('class').which.contains('at-Tab--active');
templates.expect.element('#prompt_finish').visible;
templates.expect.element('#prompt_finish').enabled;
templates.click('#prompt_finish');
templates.waitForElementVisible('div.spinny');
templates.waitForElementNotVisible('div.spinny');
client.waitForElementVisible('at-job-details');
client.end();
}
};