From e7a15d478d97f0e800a92cce94ef3e62bb6bff95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ely=C3=A9zer=20Rezende?= Date: Wed, 7 Aug 2019 11:39:39 -0400 Subject: [PATCH] Add app token e2e --- awx/ui/test/e2e/fixtures.js | 21 +++--- awx/ui/test/e2e/objects/applications.js | 7 ++ awx/ui/test/e2e/objects/users.js | 76 ++++++++++++++++++++- awx/ui/test/e2e/tests/test-applications.js | 77 +++++++++++++++++++++- awx/ui/test/e2e/tests/test-users-crud.js | 5 +- 5 files changed, 170 insertions(+), 16 deletions(-) diff --git a/awx/ui/test/e2e/fixtures.js b/awx/ui/test/e2e/fixtures.js index 5e3143182c..5e8c662d58 100644 --- a/awx/ui/test/e2e/fixtures.js +++ b/awx/ui/test/e2e/fixtures.js @@ -438,17 +438,22 @@ const getUser = ( // where a user and org both exist, but the user is not in the organization. // this ensures a new user is always created. username = `user-${uuid().substr(0, 8)}`, - isSuperuser = false + password = AWX_E2E_PASSWORD, + isSuperuser = false, + isSystemAuditor = false, + email = `email-${uuid().substr(0, 8)}@example.com`, + firstName = `first-name-${uuid().substr(0, 8)}`, + lastName = `last-name-${uuid().substr(0, 8)}` ) => getOrganization(namespace) .then(organization => getOrCreate(`/organizations/${organization.id}/users/`, { - username: `${username}-${uuid().substr(0, 8)}`, + email, + first_name: firstName, + is_superuser: isSuperuser, + is_system_auditor: isSystemAuditor, + last_name: lastName, organization: organization.id, - first_name: 'firstname', - last_name: 'lastname', - email: 'null@ansible.com', - is_superuser: `${isSuperuser}`, - is_system_auditor: false, - password: AWX_E2E_PASSWORD + password, + username, }, ['username'])); /* Retrieves a job template admin, and creates it if it does not exist. diff --git a/awx/ui/test/e2e/objects/applications.js b/awx/ui/test/e2e/objects/applications.js index e703505340..e34d762ecd 100644 --- a/awx/ui/test/e2e/objects/applications.js +++ b/awx/ui/test/e2e/objects/applications.js @@ -18,6 +18,7 @@ const addEditElements = { redirectUris: '#application_redirect_uris_group input', clientType: '#application_client_type_group select', save: 'button[type=save]', + tokensTab: 'div.card button.at-Tab:nth-of-type(2)', }; const authorizationGrantTypeOptions = { @@ -131,6 +132,12 @@ module.exports = { } }) } + }, + tokens: { + selector: 'div.card', + elements: { + list: '.at-List-container', + } } }, elements: { diff --git a/awx/ui/test/e2e/objects/users.js b/awx/ui/test/e2e/objects/users.js index b3b7abcd27..9662fef019 100644 --- a/awx/ui/test/e2e/objects/users.js +++ b/awx/ui/test/e2e/objects/users.js @@ -92,6 +92,63 @@ module.exports = { this.expect.element('.List-titleBadge').text.to.contain('1'); this.expect.element(row).text.contain(username); }, + createToken (username, token, callback) { + this.search(username); + const editButton = `${row} i[class*="fa-pencil"]`; + this + .waitForElementVisible(editButton) + .click(editButton); + this.section.tokens + .waitForElementVisible('@tokensTab') + .click('@tokensTab') + .waitForSpinny() + .click('@add'); + const { createToken } = this.section; + createToken.waitForElementVisible('@application'); + this.expect.element(this.section.breadcrumb.selector).text.to.contain(`USERS ${username} TOKENS CREATE TOKEN`); + if (token.application) { + createToken.setValue('@application', token.application); + } + if (token.description) { + createToken.setValue('@description', token.description); + } + if (token.scope) { + createToken + .click('@scope') + .click(`option[label=${token.scope}]`); + } + createToken.click('@saveButton'); + this.waitForSpinny() + .waitForElementVisible('#alert-modal-msg'); + + const tokenInfo = { + token: null, + refreshToken: null, + expires: null, + }; + + this.getText( + '#alert-modal-msg .PopupModal:nth-of-type(1) .PopupModal-value', + (result) => { tokenInfo.token = result.value; } + ); + this.getText( + '#alert-modal-msg .PopupModal:nth-of-type(2) .PopupModal-value', + (result) => { tokenInfo.refreshToken = result.value; } + ); + this.getText( + '#alert-modal-msg .PopupModal:nth-of-type(3) .PopupModal-value', + (result) => { tokenInfo.expires = result.value; } + ); + + this.findThenClick('#alert_ok_btn', 'css') + .waitForElementNotVisible('#alert-modal-msg'); + + this.api.perform(() => { + if (typeof callback === 'function') { + callback.call(this.api, tokenInfo); + } + }); + }, }], sections: { header, @@ -134,7 +191,24 @@ module.exports = { } }) } - } + }, + tokens: { + selector: 'div[ui-view="form"]', + elements: { + add: '#button-add', + tokensTab: '#tokens_tab', + }, + }, + createToken: { + selector: 'div[ui-view="preFormView"]', + elements: { + application: 'input[tabindex="1"]', + description: 'input[tabindex="2"]', + scope: 'select[tabindex="3"]', + cancelButton: 'button[type="cancel"]', + saveButton: 'button[type="save"]', + } + }, }, elements: { cancel: 'button[class*="Form-cancelButton"]', diff --git a/awx/ui/test/e2e/tests/test-applications.js b/awx/ui/test/e2e/tests/test-applications.js index 9d70eb6067..8d0b191d3f 100644 --- a/awx/ui/test/e2e/tests/test-applications.js +++ b/awx/ui/test/e2e/tests/test-applications.js @@ -1,8 +1,12 @@ /* Tests for applications. */ import uuid from 'uuid'; -import { getOrganization } from '../fixtures'; +import { + getOrganization, + getUser +} from '../fixtures'; const row = '.at-List-container .at-Row'; +const editLink = `${row} a.ng-binding`; const testID = uuid().substr(0, 8); const namespace = 'test-applications'; @@ -17,13 +21,26 @@ const store = { redirectUris: `https://example.com/${testID}/`, // clientType: `client-type-${testID}`, }, + adminUser: { + username: `admin-${testID}`, + password: `admin-${testID}`, + isSuperuser: true, + }, }; let data; module.exports = { before: (client, done) => { - const resources = [getOrganization(namespace)]; + const resources = [ + getOrganization(store.organization.name), + getUser( + namespace, + store.adminUser.username, + store.adminUser.password, + store.adminUser.isSuperuser + ), + ]; Promise.all(resources) .then(([org]) => { data = { org }; @@ -53,7 +70,6 @@ module.exports = { applications.load(); client.waitForSpinny(); applications.search(store.application.name); - const editLink = `${row} a.ng-binding`; client .waitForElementVisible(editLink) .expect.element(editLink).text.to.equal(store.application.name); @@ -74,6 +90,61 @@ module.exports = { .waitForElementVisible('@description') .expect.element('@description').value.to.equal(store.application.description); }, + 'add a read scoped application token': client => { + client.logout(); + client.login(store.adminUser.username, store.adminUser.password); + + // Given the application created on the previous test + const token = { + application: store.application.name, + description: `Read scoped token for ${store.application.name}`, + scope: 'Read', + }; + const users = client.page.users(); + users.load(); + client.waitForSpinny(); + users.createToken(store.adminUser.username, token, (tokenInfo) => { + const applications = client.page.applications(); + applications.load(); + client.waitForSpinny(); + applications.search(store.application.name); + client.findThenClick(editLink, 'css'); + applications.section.edit + .waitForElementVisible('@tokensTab') + .click('@tokensTab') + .waitForSpinny(); + // FIXME: Search is not properly working, update this when it is working. + applications.section.tokens.expect.element('@list').text.to.contain(`${store.adminUser.username}\n${token.description}\nEXPIRATION ${tokenInfo.expires}`); + }); + }, + 'add a write scoped application token': client => { + // Given the application created on the previous test + const token = { + application: store.application.name, + description: `Write scoped token for ${store.application.name}`, + scope: 'Write', + }; + + const users = client.page.users(); + users.load(); + client.waitForSpinny(); + users.createToken(store.adminUser.username, token, (tokenInfo) => { + const applications = client.page.applications(); + applications.load(); + client.waitForSpinny(); + applications.search(store.application.name); + client.findThenClick(editLink, 'css'); + applications.section.edit + .waitForElementVisible('@tokensTab') + .click('@tokensTab') + .waitForSpinny(); + // FIXME: Search is not properly working, update this when it is working. + applications.section.tokens.expect.element('@list').text.to.contain(`${store.adminUser.username}\n${token.description}\nEXPIRATION ${tokenInfo.expires}`); + }); + + client.logout(); + client.login(); + }, 'delete an application': client => { // Given the application created on the create application test const applications = client.page.applications(); diff --git a/awx/ui/test/e2e/tests/test-users-crud.js b/awx/ui/test/e2e/tests/test-users-crud.js index 5403538270..648a7f4b33 100644 --- a/awx/ui/test/e2e/tests/test-users-crud.js +++ b/awx/ui/test/e2e/tests/test-users-crud.js @@ -54,15 +54,12 @@ module.exports = { }); const resources = [ getOrganization(store.organization.name), - getAuditor(store.auditor.username), - getUser(store.user.username), - getUser(store.admin.username, true) ]; Promise.all(resources) .then(([organization, auditor, user, admin]) => { store.organization.name = `${store.organization.name}-organization`; - data = { organization, auditor, user, admin }; + data = { organization }; done(); }); client.login();