From b5899c193a9471bba4c6eb9742204e7f5d3472af Mon Sep 17 00:00:00 2001 From: Jake McDermott Date: Tue, 10 Oct 2017 19:14:04 -0400 Subject: [PATCH 1/2] update object fields and commands --- awx/ui/test/e2e/objects/inventories.js | 23 ++- awx/ui/test/e2e/objects/organizations.js | 4 + awx/ui/test/e2e/objects/projects.js | 2 +- .../objects/sections/createTableSection.js | 69 ++++--- .../test/e2e/objects/sections/lookupModal.js | 3 +- awx/ui/test/e2e/objects/sections/search.js | 7 +- awx/ui/test/e2e/objects/templates.js | 172 +++++++++++++++++- 7 files changed, 245 insertions(+), 35 deletions(-) diff --git a/awx/ui/test/e2e/objects/inventories.js b/awx/ui/test/e2e/objects/inventories.js index 5a87c039f3..9fe5761ef5 100644 --- a/awx/ui/test/e2e/objects/inventories.js +++ b/awx/ui/test/e2e/objects/inventories.js @@ -20,6 +20,11 @@ const standardInvDetails = createFormSection({ '#inventory_form .ui-spinner-input', '#inventory_form .ScheduleToggle-switch' ] + }, + labels: { + name: 'Name', + description: 'Description', + organization: 'Organization' } }); @@ -83,7 +88,7 @@ module.exports = { } }, list: { - selector: 'div[ui-view="list"]', + selector: '.Panel', elements: { badge: 'span[class~="badge"]', title: 'div[class="List-titleText"]', @@ -109,5 +114,19 @@ module.exports = { elements: { cancel: 'button[class*="Form-cancelButton"]', save: 'button[class*="Form-saveButton"]' - } + }, + commands: [{ + selectAdd (name) { + this.api.waitForElementVisible('button span[class="List-dropdownCarat"]'); + this.expect.element('button span[class="List-dropdownCarat"]').enabled; + this.api.click('button span[class="List-dropdownCarat"]'); + + this.api.useXpath(); + this.api.waitForElementVisible(`.//a[normalize-space(text())="${name}"]`); + this.api.click(`//a[normalize-space(text())="${name}"]`); + this.api.useCss(); + + return this; + } + }] }; diff --git a/awx/ui/test/e2e/objects/organizations.js b/awx/ui/test/e2e/objects/organizations.js index d1927affbd..e6f8b36398 100644 --- a/awx/ui/test/e2e/objects/organizations.js +++ b/awx/ui/test/e2e/objects/organizations.js @@ -15,6 +15,10 @@ const details = createFormSection({ '#organization_form .Form-lookupButton', '#organization_form #InstanceGroups' ] + }, + labels: { + name: 'Name', + description: 'Description' } }); diff --git a/awx/ui/test/e2e/objects/projects.js b/awx/ui/test/e2e/objects/projects.js index 75194e727b..fcdfeb35bb 100644 --- a/awx/ui/test/e2e/objects/projects.js +++ b/awx/ui/test/e2e/objects/projects.js @@ -50,7 +50,7 @@ module.exports = { } }, list: { - selector: 'div[ui-view="list"]', + selector: '.Panel', elements: { badge: 'span[class~="badge"]', title: 'div[class="List-titleText"]', diff --git a/awx/ui/test/e2e/objects/sections/createTableSection.js b/awx/ui/test/e2e/objects/sections/createTableSection.js index 54dfd67eba..96607940e5 100644 --- a/awx/ui/test/e2e/objects/sections/createTableSection.js +++ b/awx/ui/test/e2e/objects/sections/createTableSection.js @@ -26,32 +26,51 @@ const header = { }] }; -module.exports = ({ elements, sections, commands }) => ({ - selector: 'table', - sections: { - header, - dynamicSection - }, - commands: [{ - findRowByText (text) { - return this.section.dynamicSection.create({ - elements, - sections, - commands, - name: `row[${text}]`, - locateStrategy: 'xpath', - selector: `.//tbody/tr/td//*[normalize-space(text())='${text}']/ancestor::tr` - }); +const createTableSection = ({ elements, sections, commands }) => { + const tableSection = { + selector: 'table', + sections: { + header, + dynamicSection }, - waitForRowCount (count) { - const countReached = `tbody tr:nth-of-type(${count})`; - this.waitForElementPresent(countReached); + commands: [{ + findRowByText (text) { + return this.section.dynamicSection.create({ + elements, + sections, + commands, + name: `row[${text}]`, + locateStrategy: 'xpath', + selector: `.//tbody/tr/td//*[normalize-space(text())='${text}']/ancestor::tr` + }); + }, + findRowByIndex (index) { + return this.section.dynamicSection.create({ + elements, + sections, + commands, + name: `row[${index}]`, + locateStrategy: 'xpath', + selector: `.//tbody/tr[${index}]` + }); + }, + clickRowByIndex (index) { + this.findRowByIndex(index).click('@self'); + return this; + }, + waitForRowCount (count) { + const countReached = this.findRowByIndex(count); + countReached.waitForElementVisible('@self', 10000); - const countExceeded = `tbody tr:nth-of-type(${count + 1})`; - this.waitForElementNotPresent(countExceeded); + const countExceeded = this.findRowByIndex(count + 1); + countExceeded.waitForElementNotPresent('@self', 10000); - return this; - } - }] -}); + return this; + } + }] + }; + return tableSection; +}; + +module.exports = createTableSection; diff --git a/awx/ui/test/e2e/objects/sections/lookupModal.js b/awx/ui/test/e2e/objects/sections/lookupModal.js index 15c0b3bee8..4f34511323 100644 --- a/awx/ui/test/e2e/objects/sections/lookupModal.js +++ b/awx/ui/test/e2e/objects/sections/lookupModal.js @@ -8,7 +8,8 @@ const lookupModal = { close: 'i[class="fa fa-times-circle"]', title: 'div[class^="Form-title"]', select: 'button[class*="save"]', - cancel: 'button[class*="cancel"]' + cancel: 'button[class*="cancel"]', + save: 'button[class*="save"]' }, sections: { search, diff --git a/awx/ui/test/e2e/objects/sections/search.js b/awx/ui/test/e2e/objects/sections/search.js index 2fedb8fa37..9feed81554 100644 --- a/awx/ui/test/e2e/objects/sections/search.js +++ b/awx/ui/test/e2e/objects/sections/search.js @@ -1,9 +1,10 @@ const search = { selector: 'smart-search', + locateStrategy: 'css selector', elements: { - clearAll: '.SmartSearch-clearAll', - searchButton: '.SmartSearch-searchButton', - input: '.SmartSearch-input', + clearAll: 'a[class*="clear"]', + searchButton: 'i[class$="search"]', + input: 'input', tags: '.SmartSearch-tagContainer' } }; diff --git a/awx/ui/test/e2e/objects/templates.js b/awx/ui/test/e2e/objects/templates.js index b200315427..cfa23b9874 100644 --- a/awx/ui/test/e2e/objects/templates.js +++ b/awx/ui/test/e2e/objects/templates.js @@ -1,3 +1,5 @@ +import _ from 'lodash'; + import actions from './sections/actions'; import breadcrumb from './sections/breadcrumb'; import createFormSection from './sections/createFormSection'; @@ -20,9 +22,25 @@ const details = createFormSection({ '#job_template_form .ui-spinner-input', '#job_template_form .ScheduleToggle-switch' ] + }, + labels: { + name: 'Name', + description: 'Description', + playbook: 'Playbook' + } }); +const lookupInventory = _.merge({}, lookupModal, { + locateStrategy: 'xpath', + selector: './/div[text()="Select inventory"]/ancestor::div[contains(@class, "modal-content")]' +}); + +const lookupProject = _.merge({}, lookupModal, { + locateStrategy: 'xpath', + selector: './/div[text()="Select project"]/ancestor::div[contains(@class, "modal-content")]' +}); + module.exports = { url () { return `${this.api.globals.launch_url}/#/templates`; @@ -31,7 +49,8 @@ module.exports = { header, navigation, breadcrumb, - lookupModal, + lookupInventory, + lookupProject, addJobTemplate: { selector: 'div[ui-view="form"]', sections: { @@ -71,7 +90,7 @@ module.exports = { } }, list: { - selector: 'div[ui-view="list"]', + selector: '.Panel', elements: { badge: 'span[class~="badge"]', title: 'div[class="List-titleText"]', @@ -95,5 +114,152 @@ module.exports = { elements: { cancel: 'button[class*="Form-cancelButton"]', save: 'button[class*="Form-saveButton"]' - } + }, + commands: [{ + clickWhenEnabled (selector) { + this.api.waitForElementVisible(selector); + this.expect.element(selector).enabled; + this.click(selector); + return this; + }, + selectAdd (name) { + this.clickWhenEnabled('button span[class="List-dropdownCarat"]'); + + this.api + .useXpath() + .waitForElementVisible(`.//a[normalize-space(text())="${name}"]`) + .click(`//a[normalize-space(text())="${name}"]`) + .useCss(); + + return this; + }, + selectPlaybook (name) { + this.clickWhenEnabled('label[for="playbook"] + div span[class$="arrow"]'); + + this.api + .useXpath() + .waitForElementVisible(`//li[contains(text(), "${name}")]`) + .click(`//li[contains(text(), "${name}")]`) + .useCss(); + + return this; + }, + selectInventory (name) { + this.clickWhenEnabled('label[for="inventory"] + div i[class$="search"]'); + + this.api + .waitForElementVisible('div.spinny') + .waitForElementNotVisible('div.spinny'); + + this.section.lookupInventory.section.search + .waitForElementVisible('@input') + .waitForElementVisible('@searchButton') + .sendKeys('@input', name) + .click('@searchButton') + .waitForElementVisible('div.spinny') + .waitForElementNotVisible('div.spinny'); + + this.section.lookupInventory.section.table + .waitForRowCount(1) + .clickRowByIndex(1); + + this.section.lookupInventory.expect.element('@save').enabled; + + this.section.lookupInventory + .click('@save'); + + return this; + }, + selectProject (name) { + this.clickWhenEnabled('label[for="project"] + div i[class$="search"]'); + + this.api + .waitForElementVisible('div.spinny') + .waitForElementNotVisible('div.spinny'); + + this.section.lookupProject.section.search + .waitForElementVisible('@input') + .waitForElementVisible('@searchButton') + .sendKeys('@input', name) + .click('@searchButton') + .waitForElementVisible('div.spinny') + .waitForElementNotVisible('div.spinny'); + + this.section.lookupProject.section.table + .waitForRowCount(1) + .clickRowByIndex(1); + + this.section.lookupProject.expect.element('@save').enabled; + + this.section.lookupProject + .click('@save') + .waitForElementVisible('div.spinny') + .waitForElementNotVisible('div.spinny'); + + return this; + }, + selectVaultCredential (name) { + this.clickWhenEnabled('label[for="credential"] + div i[class$="search"]'); + + this.api + .waitForElementVisible('div.spinny') + .waitForElementNotVisible('div.spinny') + .waitForElementVisible('#multi-credential-kind-select + span span[class$="arrow"]') + .click('#multi-credential-kind-select + span span[class$="arrow"]') + .useXpath() + .waitForElementVisible('//li[contains(text(), "Vault")]') + .click('//li[contains(text(), "Vault")]') + .useCss() + .waitForElementVisible('div.spinny') + .waitForElementNotVisible('div.spinny') + .waitForElementVisible('multi-credential-modal smart-search input') + .waitForElementVisible('multi-credential-modal smart-search i[class$="search"]') + .sendKeys('multi-credential-modal smart-search input', name) + .click('multi-credential-modal smart-search i[class$="search"]') + .waitForElementVisible('div.spinny') + .waitForElementNotVisible('div.spinny') + .click('multi-credential-modal smart-search a[class*="clear"]') + .waitForElementVisible('div.spinny') + .waitForElementNotVisible('div.spinny') + .sendKeys('multi-credential-modal smart-search input', name) + .click('multi-credential-modal smart-search i[class$="search"]') + .waitForElementVisible('div.spinny') + .waitForElementNotVisible('div.spinny') + .waitForElementNotPresent('multi-credential-modal tbody tr:nth-child(2)') + .waitForElementVisible('multi-credential-modal tbody tr:nth-child(1) input[type="radio"]') + .click('multi-credential-modal tbody tr:nth-child(1) input[type="radio"]') + .click('multi-credential-modal button[class*="save"]') + .waitForElementVisible('div.spinny') + .waitForElementNotVisible('div.spinny'); + + return this; + }, + selectMachineCredential (name) { + this.clickWhenEnabled('label[for="credential"] + div i[class$="search"]'); + + this.api + .waitForElementVisible('div.spinny') + .waitForElementNotVisible('div.spinny') + .waitForElementVisible('#multi-credential-kind-select + span span[class$="arrow"]') + .click('#multi-credential-kind-select + span span[class$="arrow"]') + .useXpath() + .waitForElementVisible('//li[contains(text(), "Machine")]') + .click('//li[contains(text(), "Machine")]') + .useCss() + .waitForElementVisible('multi-credential-modal smart-search input') + .waitForElementVisible('multi-credential-modal smart-search i[class$="search"]') + .sendKeys('multi-credential-modal smart-search input', name) + .click('multi-credential-modal smart-search i[class$="search"]') + .waitForElementVisible('div.spinny') + .waitForElementNotVisible('div.spinny') + .waitForElementNotPresent('multi-credential-modal tbody tr:nth-child(2)') + .waitForElementVisible('multi-credential-modal tbody tr:nth-child(1) input[type="radio"]') + .click('multi-credential-modal tbody tr:nth-child(1) input[type="radio"]') + .click('multi-credential-modal button[class*="save"]') + .waitForElementVisible('div.spinny') + .waitForElementNotVisible('div.spinny'); + + return this; + } + }] }; From 113d62a95f21a243d959eab1a0b4b7f225da7f9e Mon Sep 17 00:00:00 2001 From: Jake McDermott Date: Tue, 10 Oct 2017 19:39:30 -0400 Subject: [PATCH 2/2] add smoke test --- awx/ui/test/e2e/nightwatch.conf.js | 5 + awx/ui/test/e2e/tests/smoke-vars.yml | 7 + awx/ui/test/e2e/tests/smoke.js | 273 +++++++++++++++++++++++++++ awx/ui/test/e2e/tests/smoke.yml | 10 + 4 files changed, 295 insertions(+) create mode 100644 awx/ui/test/e2e/tests/smoke-vars.yml create mode 100644 awx/ui/test/e2e/tests/smoke.js create mode 100644 awx/ui/test/e2e/tests/smoke.yml diff --git a/awx/ui/test/e2e/nightwatch.conf.js b/awx/ui/test/e2e/nightwatch.conf.js index ed200626e4..ab5bb24ef0 100644 --- a/awx/ui/test/e2e/nightwatch.conf.js +++ b/awx/ui/test/e2e/nightwatch.conf.js @@ -22,6 +22,11 @@ module.exports = { browserName: 'chrome' } }, + smoke: { + disable_colors: true, + skip_testcases_on_fail: true, + filter: 'smoke.js' + }, debug: { selenium_port: 9515, selenium_host: 'localhost', diff --git a/awx/ui/test/e2e/tests/smoke-vars.yml b/awx/ui/test/e2e/tests/smoke-vars.yml new file mode 100644 index 0000000000..7834c3944f --- /dev/null +++ b/awx/ui/test/e2e/tests/smoke-vars.yml @@ -0,0 +1,7 @@ +$ANSIBLE_VAULT;1.1;AES256 +36663862313439656164323336396466323737666532643061323738646337623166653338663939 +6365663839623936363566393461643961363963613333650a333463653831386463646564376265 +39376362376231303064326464303738343136643931336432396638333933356337383866326539 +3830316634306466310a366234333566613733633232623434363434376534663466393833666435 +36373961636564353865653162393266383135363362336139613435323464356136393034636539 +6166663537623261336262363732346238343066393861643134 diff --git a/awx/ui/test/e2e/tests/smoke.js b/awx/ui/test/e2e/tests/smoke.js new file mode 100644 index 0000000000..b3193d6d9c --- /dev/null +++ b/awx/ui/test/e2e/tests/smoke.js @@ -0,0 +1,273 @@ +import uuid from 'uuid'; + +const id = uuid().substr(0, 8); + +const INVENTORY_NAME = `inventory-${id}`; +const MACHINE_CREDENTIAL_NAME = `credential-machine-${id}`; +const ORGANIZATION_NAME = `organization-${id}`; +const PROJECT_NAME = `project-${id}`; +const PROJECT_URL = 'https://github.com/ansible/awx'; +const PROJECT_BRANCH = 'devel'; +const PLAYBOOK_NAME = 'awx/ui/test/e2e/tests/smoke.yml'; +const TEMPLATE_NAME = `template-${id}`; +const VAULT_CREDENTIAL_NAME = `credential-vault-${id}`; +const VAULT_CREDENTIAL_PASSWORD = 'VAULT_CREDENTIAL_PASSWORD'; + +module.exports = { + 'login to awx': client => { + client.login(); + client.resizeWindow(1200, 800); + client.waitForAngular(); + }, + 'create organization': client => { + const organizations = client.page.organizations(); + const { details } = organizations.section.add.section; + + organizations.section.navigation.waitForElementVisible('@organizations'); + organizations.section.navigation.expect.element('@organizations').enabled; + organizations.section.navigation.click('@organizations'); + + organizations.waitForElementVisible('div.spinny'); + organizations.waitForElementNotVisible('div.spinny'); + + organizations.section.list.expect.element('@add').visible; + organizations.section.list.expect.element('@add').enabled; + organizations.section.list.click('@add'); + + details.waitForElementVisible('@name'); + details.expect.element('@name').enabled; + + details.setValue('@name', ORGANIZATION_NAME); + + organizations.waitForElementVisible('@save'); + organizations.expect.element('@save').enabled; + organizations.click('@save'); + + organizations.waitForElementVisible('div.spinny'); + organizations.waitForElementNotVisible('div.spinny'); + }, + 'create project': client => { + const projects = client.page.projects(); + + projects.navigate(); + projects.waitForElementVisible('div.spinny'); + projects.waitForElementNotVisible('div.spinny'); + + projects.section.list.waitForElementVisible('@add'); + projects.section.list.expect.element('@add').enabled; + projects.section.list.click('@add'); + + projects.waitForElementVisible('label[for="name"] + div input'); + projects.waitForElementVisible('label[for="organization"] + div input'); + projects.waitForElementPresent('label[for="scm_type"] + div > div select option[value="git"]'); + + projects.setValue('label[for="name"] + div input', PROJECT_NAME); + projects.clearValue('label[for="organization"] + div input'); + projects.setValue('label[for="organization"] + div input', ORGANIZATION_NAME); + projects.click('label[for="scm_type"] + div > div select option[value="git"]'); + + projects.waitForElementVisible('.sourceSubForm'); + projects.waitForElementVisible('label[for="scm_url"] + div input'); + projects.waitForElementVisible('label[for="scm_branch"] + div input'); + + projects.setValue('label[for="scm_url"] + div input', PROJECT_URL); + projects.setValue('label[for="scm_branch"] + div input', PROJECT_BRANCH); + + projects.expect.element('#project_save_btn').enabled; + projects.click('#project_save_btn'); + + projects.waitForElementVisible('div.spinny'); + projects.waitForElementNotVisible('div.spinny'); + + projects.expect.element('smart-search input').enabled; + projects.sendKeys('smart-search input', `${PROJECT_NAME}${client.Keys.ENTER}`); + + projects.waitForElementVisible('div.spinny'); + projects.waitForElementNotVisible('div.spinny'); + + projects.waitForElementVisible('div.spinny', 120000); + projects.waitForElementNotVisible('div.spinny'); + projects.expect.element('i[class$="success"]').visible; + }, + 'create inventory': client => { + const inventories = client.page.inventories(); + const details = inventories.section.addStandardInventory.section.standardInvDetails; + + inventories.section.navigation.waitForElementVisible('@inventories'); + inventories.section.navigation.expect.element('@inventories').enabled; + inventories.section.navigation.click('@inventories'); + + inventories.waitForElementVisible('div.spinny'); + inventories.waitForElementNotVisible('div.spinny'); + + inventories.selectAdd('Inventory'); + + details.waitForElementVisible('@name'); + details.waitForElementVisible('@organization'); + + details.expect.element('@name').enabled; + details.expect.element('@organization').enabled; + + details.setValue('@name', INVENTORY_NAME); + details.setValue('@organization', ORGANIZATION_NAME); + + inventories.waitForElementVisible('@save'); + inventories.expect.element('@save').enabled; + + inventories.click('@save'); + + inventories.waitForElementVisible('div.spinny'); + inventories.waitForElementNotVisible('div.spinny'); + }, + 'create host': client => { + const addHost = './/span[text()="+ ADD HOST"]'; + + client.expect.element('#hosts_tab').enabled; + client.expect.element('#hosts_tab').css('opacity').equal('1'); + client.expect.element('#hosts_tab').css('background-color').contain('255, 255, 255'); + client.click('#hosts_tab'); + + client.waitForElementVisible('div.spinny'); + client.waitForElementNotVisible('div.spinny'); + + client.expect.element('#hosts_tab').css('background-color').contain('132, 137, 146'); + + client.useXpath(); + client.waitForElementVisible(addHost); + client.expect.element(addHost).enabled; + client.click(addHost); + client.useCss(); + + client.waitForElementVisible('#host_name'); + client.sendKeys('#host_name', 'localhost'); + + client.click('div[class="CodeMirror-scroll"]'); + client.sendKeys('.CodeMirror textarea', client.Keys.ENTER); + client.sendKeys('.CodeMirror textarea', 'ansible_connection: local'); + client.click('#host_host_variables_parse_type label[class$="hollow"]'); + client.click('#host_host_variables_parse_type label[class$="hollow"]'); + + client.expect.element('#host_save_btn').enabled; + client.click('#host_save_btn'); + + client.waitForElementVisible('div.spinny'); + client.waitForElementNotVisible('div.spinny'); + }, + 'create vault credential': client => { + const credentials = client.page.credentials(); + const { details } = credentials.section.add.section; + + credentials.section.navigation.waitForElementVisible('@credentials'); + credentials.section.navigation.expect.element('@credentials').enabled; + credentials.section.navigation.click('@credentials'); + + credentials.waitForElementVisible('div.spinny'); + credentials.waitForElementNotVisible('div.spinny'); + + credentials.section.list.waitForElementVisible('@add'); + credentials.section.list.expect.element('@add').enabled; + credentials.section.list.click('@add'); + + details.waitForElementVisible('@save'); + details.clearAndSelectType('Vault'); + details.setValue('@organization', ORGANIZATION_NAME); + details.setValue('@name', VAULT_CREDENTIAL_NAME); + + details.section.vault.setValue('@vaultPassword', VAULT_CREDENTIAL_PASSWORD); + + details.expect.element('@save').enabled; + details.click('@save'); + + credentials.waitForElementVisible('div.spinny'); + credentials.waitForElementNotVisible('div.spinny'); + }, + 'create machine credential': client => { + const credentials = client.page.credentials(); + const { details } = credentials.section.add.section; + + credentials.section.navigation.waitForElementVisible('@credentials'); + credentials.section.navigation.expect.element('@credentials').enabled; + credentials.section.navigation.click('@credentials'); + + credentials.waitForElementVisible('div.spinny'); + credentials.waitForElementNotVisible('div.spinny'); + + credentials.section.list.waitForElementVisible('@add'); + credentials.section.list.expect.element('@add').enabled; + credentials.section.list.click('@add'); + + details.waitForElementVisible('@save'); + details.clearAndSelectType('Machine'); + details.setValue('@organization', ORGANIZATION_NAME); + details.setValue('@name', MACHINE_CREDENTIAL_NAME); + + details.expect.element('@save').enabled; + details.click('@save'); + + credentials.waitForElementVisible('div.spinny'); + credentials.waitForElementNotVisible('div.spinny'); + }, + 'create job template': client => { + const templates = client.page.templates(); + + templates.navigate(); + templates.waitForElementVisible('div.spinny'); + templates.waitForElementNotVisible('div.spinny'); + + templates.selectAdd('Job Template'); + templates.selectInventory(INVENTORY_NAME); + templates.selectProject(PROJECT_NAME); + templates.selectVaultCredential(VAULT_CREDENTIAL_NAME); + templates.selectMachineCredential(MACHINE_CREDENTIAL_NAME); + templates.selectPlaybook(PLAYBOOK_NAME); + templates.sendKeys('label[for="name"] + div input', TEMPLATE_NAME); + + templates.expect.element('#job_template_save_btn').enabled; + templates.click('#job_template_save_btn'); + + templates.waitForElementVisible('div.spinny'); + templates.waitForElementNotVisible('div.spinny'); + + templates.expect.element('#job_template_save_btn').enabled; + }, + 'launch job': client => { + const templates = client.page.templates(); + + templates.waitForElementVisible('smart-search input'); + templates.expect.element('smart-search input').enabled; + + templates.sendKeys('smart-search input', `${TEMPLATE_NAME}${client.Keys.ENTER}`); + templates.waitForElementVisible('div.spinny'); + templates.waitForElementNotVisible('div.spinny'); + + templates.sendKeys('smart-search input', `${TEMPLATE_NAME}${client.Keys.ENTER}`); + templates.waitForElementVisible('div.spinny'); + templates.waitForElementNotVisible('div.spinny'); + + templates.waitForElementPresent('i[class$="launch"]'); + templates.waitForElementNotPresent('i[class$="launch"]:nth-of-type(2)'); + + templates.expect.element('.List-titleBadge').text.equal('1'); + + templates.waitForElementVisible('i[class$="launch"]'); + templates.click('i[class$="launch"]'); + }, + 'verify expected job results': client => { + const output = './/span[normalize-space(text())=\'"msg": "Hello World!"\']'; + const running = 'i[class$="icon-job-running"]'; + const success = 'i[class$="icon-job-successful"]'; + + client.waitForElementVisible('div.spinny'); + client.waitForElementNotVisible('div.spinny'); + + client.waitForElementVisible('.JobResults-detailsPanel'); + client.waitForElementNotPresent(running, 60000); + client.waitForElementVisible(success, 60000); + + client.useXpath(); + client.waitForElementVisible(output, 60000); + client.useCss(); + + client.end(); + } +}; diff --git a/awx/ui/test/e2e/tests/smoke.yml b/awx/ui/test/e2e/tests/smoke.yml new file mode 100644 index 0000000000..f85e892dff --- /dev/null +++ b/awx/ui/test/e2e/tests/smoke.yml @@ -0,0 +1,10 @@ +--- +- hosts: all + tasks: + - name: Import Vault Variables + include_vars: smoke-vars.yml + no_log: true + + - name: Display Vault Message + debug: + msg: '{{ vault_message }}'