diff --git a/cypress/integration/authorisation/authorisation_steps.js b/cypress/integration/authorisation/authorisation_steps.js index c07a39e..27395e5 100644 --- a/cypress/integration/authorisation/authorisation_steps.js +++ b/cypress/integration/authorisation/authorisation_steps.js @@ -2,27 +2,27 @@ import { And, When, Then, But } from 'cypress-cucumber-preprocessor/steps' import TransactionsPage from '../../pages/transactions_page' When('I see the transactions page', () => { - TransactionsPage.mainHeading().contains('Transactions to be billed') + TransactionsPage.confirm() }) Then('I should see the admin menu', () => { - TransactionsPage.adminMenu().should('be.visible') + TransactionsPage.adminMenu.menuLink().should('be.visible') }) But('I should not see the admin menu', () => { - TransactionsPage.adminMenu().should('not.exist') + TransactionsPage.adminMenu.menuLink().should('not.exist') }) Then('I should see the billing menu', () => { - TransactionsPage.billingMenu().should('be.visible') + TransactionsPage.annualBillingMenu.menuLink().should('be.visible') }) But('I should not see the billing menu', () => { - TransactionsPage.billingMenu().should('not.exist') + TransactionsPage.annualBillingMenu.menuLink().should('not.exist') }) Then('I should see the transactions menu', () => { - TransactionsPage.transactionMenu().should('be.visible') + TransactionsPage.transactionsMenu.menuLink().should('be.visible') }) And('I should see download transactions', () => { @@ -35,5 +35,5 @@ But('I should not see download transactions', () => { Then('I should only see the {string} regime', (regime) => { cy.get('.navbar-text').contains(regime, { matchCase: false }) - TransactionsPage.regimeMenu().should('not.exist') + TransactionsPage.regimeMenu.menuLink().should('not.exist') }) diff --git a/cypress/integration/common/email.js b/cypress/integration/common/email.js index 8b7f1eb..84dcf24 100644 --- a/cypress/integration/common/email.js +++ b/cypress/integration/common/email.js @@ -6,9 +6,9 @@ import AddUserPage from '../../pages/add_user_page' import EditUserPage from '../../pages/edit_user_page' import ForgotPasswordPage from '../../pages/forgot_password_page' import LastEmailPage from '../../pages/last_email_page' -import MainMenu from '../../pages/menus/main_menu' import ResendUnlockPage from '../../pages/resend_unlock_page' import SignInPage from '../../pages/sign_in_page' +import TransactionsPage from '../../pages/transactions_page' import UsersPage from '../../pages/users_page' Given('I am a new user', () => { @@ -32,21 +32,19 @@ Given('I am an existing user', () => { When('a new account is created for me', () => { cy.signIn(Cypress.config().users.admin.email) - MainMenu.admin.getOption('User Management', '').click() + TransactionsPage.adminMenu.getOption('User Management', '').click() - UsersPage.addUserAccount().click() + UsersPage.addUserAccountButton().click() cy.get('@user').then((user) => { - AddUserPage.email().type(user.email) - AddUserPage.firstName().type(user.firstName) - AddUserPage.lastName().type(user.lastName) + AddUserPage.emailInput().type(user.email) + AddUserPage.firstNameInput().type(user.firstName) + AddUserPage.lastNameInput().type(user.lastName) - AddUserPage.regimeAccess('Waste').click() - AddUserPage.addAndInviteUser().click() - - cy.get('.col > .alert') - .should('contain.text', 'User account created') + AddUserPage.regimeAccessCheckbox('Waste').click() + AddUserPage.submitButton().click() }) + cy.alertShouldContain('User account created') }) And('I accept the invitation', () => { @@ -59,11 +57,11 @@ And('I accept the invitation', () => { const link = LastEmailPage.extractInvitationLink(lastEmail.last_email.body) cy.visit(link).then(() => { - AcceptInvitePage.mainHeading().should('contain', 'Set a password') + AcceptInvitePage.confirm() - AcceptInvitePage.password().type(Cypress.env('PASSWORD'), { log: false }) - AcceptInvitePage.passwordConfirmation().type(Cypress.env('PASSWORD'), { log: false }) - AcceptInvitePage.setPassword().click() + AcceptInvitePage.passwordInput().type(Cypress.env('PASSWORD'), { log: false }) + AcceptInvitePage.passwordConfirmationInput().type(Cypress.env('PASSWORD'), { log: false }) + AcceptInvitePage.submitButton().click() }) }) }) @@ -72,19 +70,19 @@ And('I accept the invitation', () => { Then('I will be signed in with my new account', () => { cy.get('@user').then((user) => { const username = `${user.firstName} ${user.lastName}` - MainMenu.user.menuLink().should('contain', username) + TransactionsPage.userMenu.menuLink().should('contain', username) }) }) And('I incorrectly enter my password 5 times', () => { cy.get('@user').then((user) => { - SignInPage.email().type(user.email) + SignInPage.emailInput().type(user.email) for (let i = 0; i < 5; i++) { - SignInPage.password().clear() - SignInPage.password().type(generateStringHelper()) + SignInPage.passwordInput().clear() + SignInPage.passwordInput().type(generateStringHelper()) - SignInPage.logIn().click() + SignInPage.submitButton().click() } }) }) @@ -93,18 +91,16 @@ And('I have forgotten my password', () => { SignInPage.visit() SignInPage.forgotPasswordLink().click() - ForgotPasswordPage.mainHeading().should('contain', 'Forgot your password?') + ForgotPasswordPage.confirm() cy.get('@user').then((user) => { - ForgotPasswordPage.email().type(user.email) - ForgotPasswordPage.sendMeResetPasswordInstructions().click() + ForgotPasswordPage.emailInput().type(user.email) + ForgotPasswordPage.submitButton().click() }) - cy.get('.col > .alert') - .should( - 'contain.text', - 'If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes.' - ) + cy.alertShouldContain( + 'If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes.' + ) }) When('I follow the link to unlock my account', () => { @@ -125,17 +121,15 @@ And('request another unlock email', () => { ResendUnlockPage.confirm() cy.get('@user').then((user) => { - ResendUnlockPage.email().type(user.email) - ResendUnlockPage.resendUnlockInstructions().click() + ResendUnlockPage.emailInput().type(user.email) + ResendUnlockPage.submitButton().click() }) }) Then('I will see confirmation my account is unlocked', () => { - cy.get('.col > .alert') - .should( - 'contain.text', - 'Your account has been unlocked successfully. Please sign in to continue.' - ) + cy.alertShouldContain( + 'Your account has been unlocked successfully. Please sign in to continue.' + ) }) But('I miss the first invitation email', () => { @@ -153,7 +147,7 @@ But('I miss the first invitation email', () => { But('I miss the first unlock email', () => { cy.get('@user').then((user) => { - LastEmailPage.lastEmail([user.email, 'Your account has been locked']) + LastEmailPage.lastEmail([`Hello ${user.firstName} ${user.lastName}`, 'account has been locked']) cy.get('@lastEmail').then((lastEmail) => { const link = LastEmailPage.extractUnlockAccountLink(lastEmail.last_email.body) @@ -164,18 +158,18 @@ But('I miss the first unlock email', () => { }) And('request another invitation email', () => { - MainMenu.admin.getOption('User Management', '').click() + TransactionsPage.adminMenu.getOption('User Management', '').click() cy.get('@user').then((user) => { - UsersPage.searchName().type(user.lastName) - UsersPage.search().click() + UsersPage.searchNameInput().type(user.lastName) + UsersPage.submitButton().click() - UsersPage.searchResults().each((element, index) => { + UsersPage.searchResultsTable().each((element, index) => { cy.get(`.table-responsive > tbody > tr:nth-child(${index + 1}) td`).eq(2).invoke('text').then((email) => { if (email === user.email) { cy.get(`.table-responsive > tbody > tr:nth-child(${index + 1})`).invoke('attr', 'id').then((id) => { - UsersPage.searchResultEdit(id).click() - EditUserPage.resendInvite().click() + UsersPage.searchResultEditButton(id).click() + EditUserPage.resendInviteButton().click() }) } }) @@ -184,17 +178,11 @@ And('request another invitation email', () => { }) Then('the TCM will confirm the user has been reinvited', () => { - cy.get('.col > .alert') - .should( - 'contain.text', - 'User reinvited' - ) + cy.alertShouldContain('User reinvited') }) Then('I will see confirmation an unlock email has been sent', () => { - cy.get('.col > .alert') - .should( - 'contain.text', - 'If your account exists, you will receive an email with instructions for how to unlock it in a few minutes.' - ) + cy.alertShouldContain( + 'If your account exists, you will receive an email with instructions for how to unlock it in a few minutes.' + ) }) diff --git a/cypress/integration/common/sign_in.js b/cypress/integration/common/sign_in.js index e01d7c8..ca5b53f 100644 --- a/cypress/integration/common/sign_in.js +++ b/cypress/integration/common/sign_in.js @@ -3,8 +3,8 @@ import SignInPage from '../../pages/sign_in_page' Given('I sign in as the {string} user', (user) => { SignInPage.visit() - SignInPage.email().type(Cypress.config().users[user].email) - SignInPage.password().type(Cypress.env('PASSWORD')) + SignInPage.emailInput().type(Cypress.config().users[user].email) + SignInPage.passwordInput().type(Cypress.env('PASSWORD')) - SignInPage.logIn().click() + SignInPage.submitButton().click() }) diff --git a/cypress/integration/common/transactions.js b/cypress/integration/common/transactions.js new file mode 100644 index 0000000..9640cd7 --- /dev/null +++ b/cypress/integration/common/transactions.js @@ -0,0 +1,10 @@ +import { When } from 'cypress-cucumber-preprocessor/steps' +import TransactionsPage from '../../pages/transactions_page' + +When('I select the {string} regime', (regimeName) => { + cy.task('regime', regimeName).then((regime) => { + cy.wrap(regime).as('regime') + + TransactionsPage.regimeMenu.getOption(regime.name).click() + }) +}) diff --git a/cypress/integration/email/expired_tokens/expired_tokens.js b/cypress/integration/email/expired_tokens/expired_tokens.js index 43ceff1..cf24e70 100644 --- a/cypress/integration/email/expired_tokens/expired_tokens.js +++ b/cypress/integration/email/expired_tokens/expired_tokens.js @@ -22,18 +22,16 @@ And('request another reset password email', () => { SignInPage.visit() SignInPage.forgotPasswordLink().click() - ForgotPasswordPage.mainHeading().should('contain', 'Forgot your password?') + ForgotPasswordPage.confirm() cy.get('@user').then((user) => { - ForgotPasswordPage.email().type(user.email) - ForgotPasswordPage.sendMeResetPasswordInstructions().click() + ForgotPasswordPage.emailInput().type(user.email) + ForgotPasswordPage.submitButton().click() }) - cy.get('.col > .alert') - .should( - 'contain.text', - 'If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes.' - ) + cy.alertShouldContain( + 'If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes.' + ) }) And('I try to accept the first invitation email', () => { @@ -55,20 +53,16 @@ When('I try to accept the first reset password email', () => { cy.visit(firstLink).then(() => { ChangePasswordPage.confirm() - ChangePasswordPage.password().type(Cypress.env('PASSWORD'), { log: false }) - ChangePasswordPage.passwordConfirmation().type(Cypress.env('PASSWORD'), { log: false }) - ChangePasswordPage.changeMyPassword().click() + ChangePasswordPage.passwordInput().type(Cypress.env('PASSWORD'), { log: false }) + ChangePasswordPage.passwordConfirmationInput().type(Cypress.env('PASSWORD'), { log: false }) + ChangePasswordPage.submitButton().click() }) }) }) Then('the TCM will confuse me and not be helpful', () => { cy.log('User redirected to the sign in page with no message about token being invalid') - cy.get('.col > .alert') - .should( - 'contain.text', - 'You need to sign in before continuing' - ) + cy.alertShouldContain('You need to sign in before continuing') cy.url().should('include', '/auth/sign_in') }) diff --git a/cypress/integration/email/general/general_steps.js b/cypress/integration/email/general/general_steps.js index 6e7e912..54ca6f5 100644 --- a/cypress/integration/email/general/general_steps.js +++ b/cypress/integration/email/general/general_steps.js @@ -11,11 +11,11 @@ When('I follow the link to reset my password', () => { const link = LastEmailPage.extractResetPasswordLink(lastEmail.last_email.body) cy.visit(link).then(() => { - ChangePasswordPage.mainHeading().should('contain', 'Change your password') + ChangePasswordPage.confirm() - ChangePasswordPage.password().type(Cypress.env('PASSWORD'), { log: false }) - ChangePasswordPage.passwordConfirmation().type(Cypress.env('PASSWORD'), { log: false }) - ChangePasswordPage.changeMyPassword().click() + ChangePasswordPage.passwordInput().type(Cypress.env('PASSWORD'), { log: false }) + ChangePasswordPage.passwordConfirmationInput().type(Cypress.env('PASSWORD'), { log: false }) + ChangePasswordPage.submitButton().click() }) }) }) diff --git a/cypress/integration/export_data/export_data.js b/cypress/integration/export_data/export_data.js index 9f6a46a..621c9ff 100644 --- a/cypress/integration/export_data/export_data.js +++ b/cypress/integration/export_data/export_data.js @@ -1,15 +1,9 @@ -import { When, Then, And } from 'cypress-cucumber-preprocessor/steps' +import { Then, And } from 'cypress-cucumber-preprocessor/steps' import ExportDataPage from '../../pages/export_data_page' import TransactionsPage from '../../pages/transactions_page' -When('I select the {string} regime', (regime) => { - TransactionsPage.regimeMenu().click() - TransactionsPage.regimeMenuItem(regime).click() -}) - And('I proceed to view file download details', () => { - TransactionsPage.transactionMenu().click() - TransactionsPage.downloadTransactionDataMenuItem().click() + TransactionsPage.transactionsMenu.getOption('Download Transaction Data').click() }) Then('I can view the Data Protection Notice', () => { @@ -17,6 +11,5 @@ Then('I can view the Data Protection Notice', () => { }) And('I can download transaction data', () => { - ExportDataPage.downloadBtn().should('have.attr', 'href', '/regimes/pas/data_export/download') - // DownloadTransactionFilePage.downloadBtn().click() + ExportDataPage.downloadButton().should('have.attr', 'href', '/regimes/pas/data_export/download') }) diff --git a/cypress/integration/legacy/cfd/cfd_steps.js b/cypress/integration/legacy/cfd/cfd_steps.js index 65a5d2c..67e103d 100644 --- a/cypress/integration/legacy/cfd/cfd_steps.js +++ b/cypress/integration/legacy/cfd/cfd_steps.js @@ -43,10 +43,10 @@ Before(() => { Given('I sign in as the {word} user', (regime) => { SignInPage.visit() - SignInPage.email().type(Cypress.config().users[regime].email) - SignInPage.password().type(Cypress.env('PASSWORD')) + SignInPage.emailInput().type(Cypress.config().users[regime].email) + SignInPage.passwordInput().type(Cypress.env('PASSWORD')) - SignInPage.logIn().click() + SignInPage.submitButton().click() }) Then('the user menu is visible', () => { diff --git a/cypress/integration/legacy/pas/pas_steps.js b/cypress/integration/legacy/pas/pas_steps.js index 3d2924d..3d34833 100644 --- a/cypress/integration/legacy/pas/pas_steps.js +++ b/cypress/integration/legacy/pas/pas_steps.js @@ -43,10 +43,10 @@ Before(() => { Given('I sign in as the {word} user', (regime) => { SignInPage.visit() - SignInPage.email().type(Cypress.config().users[regime].email) - SignInPage.password().type(Cypress.env('PASSWORD')) + SignInPage.emailInput().type(Cypress.config().users[regime].email) + SignInPage.passwordInput().type(Cypress.env('PASSWORD')) - SignInPage.logIn().click() + SignInPage.submitButton().click() }) Then('the user menu is visible', () => { diff --git a/cypress/integration/legacy/wml/wml_steps.js b/cypress/integration/legacy/wml/wml_steps.js index 401b76c..2f58c16 100644 --- a/cypress/integration/legacy/wml/wml_steps.js +++ b/cypress/integration/legacy/wml/wml_steps.js @@ -43,10 +43,10 @@ Before(() => { Given('I sign in as the {word} user', (regime) => { SignInPage.visit() - SignInPage.email().type(Cypress.config().users[regime].email) - SignInPage.password().type(Cypress.env('PASSWORD')) + SignInPage.emailInput().type(Cypress.config().users[regime].email) + SignInPage.passwordInput().type(Cypress.env('PASSWORD')) - SignInPage.logIn().click() + SignInPage.submitButton().click() }) Then('the user menu is visible', () => { diff --git a/cypress/integration/review_annual_billing.feature b/cypress/integration/review_annual_billing.feature index b65bb9a..8fb13ce 100644 --- a/cypress/integration/review_annual_billing.feature +++ b/cypress/integration/review_annual_billing.feature @@ -1,21 +1,19 @@ Feature: Review Annual Billing Background: - Given I sign in as the 'admin' user + Given I sign in as the 'admin' user When I select the 'Waste' regime - And I proceed to review Annual Billing details + And I proceed to review Annual Billing details Scenario: Review Annual Billing - Then I can view a list of Annual Billing Data Files - + Then I can view a list of Annual Billing Data Files Scenario: Review Annual Billing File Details - And I can view a list of Annual Billing Data Files - And I select an Annual Billing File to review + And I can view a list of Annual Billing Data Files + And I select an Annual Billing File to review Then I can view the details of the selected Annual Billing File Scenario: Navigate back to Review Annual Billing - And I can view a list of Annual Billing Data Files - And I select an Annual Billing File to review + And I can view a list of Annual Billing Data Files + And I select an Annual Billing File to review Then I can navigate back to Review Annual Billing - diff --git a/cypress/integration/review_annual_billing/annual_billing_steps.js b/cypress/integration/review_annual_billing/annual_billing_steps.js index 076f2b5..62f0167 100644 --- a/cypress/integration/review_annual_billing/annual_billing_steps.js +++ b/cypress/integration/review_annual_billing/annual_billing_steps.js @@ -1,17 +1,13 @@ -import { When, Then, And } from 'cypress-cucumber-preprocessor/steps' +import { Then, And } from 'cypress-cucumber-preprocessor/steps' import AnnualBillingPage from '../../pages/annual_billing_page' import AnnualBillingFileDetailsPage from '../../pages/annual_billing_file_details_page' import TransactionsPage from '../../pages/transactions_page' -When('I select the {string} regime', (regime) => { - TransactionsPage.regimeMenu().click() - TransactionsPage.regimeMenuItem(regime).click() -}) - And('I proceed to review Annual Billing details', () => { - TransactionsPage.annualBillingDataMenuItem().click() - TransactionsPage.reviewAnnualBillingDataMenuItem().click() - AnnualBillingPage.mainHeading().should('be.visible') + cy.get('@regime').then((regime) => { + TransactionsPage.annualBillingMenu.getOption('Review Annual Billing Data', regime.slug).click() + }) + AnnualBillingPage.confirm() }) Then('I can view a list of Annual Billing Data Files', () => { @@ -20,7 +16,7 @@ Then('I can view a list of Annual Billing Data Files', () => { And('I select an Annual Billing File to review', () => { AnnualBillingPage.fileNameLink().click() - AnnualBillingFileDetailsPage.mainHeading().should('be.visible') + AnnualBillingFileDetailsPage.confirm() }) Then('I can view the details of the selected Annual Billing File', () => { @@ -29,6 +25,6 @@ Then('I can view the details of the selected Annual Billing File', () => { }) And('I can navigate back to Review Annual Billing', () => { - AnnualBillingFileDetailsPage.backBtn().click() + AnnualBillingFileDetailsPage.backButton().click() AnnualBillingPage.mainHeading().should('be.visible') }) diff --git a/cypress/integration/sign_in/sign_in_steps.js b/cypress/integration/sign_in/sign_in_steps.js index 64f0846..d10b6b7 100644 --- a/cypress/integration/sign_in/sign_in_steps.js +++ b/cypress/integration/sign_in/sign_in_steps.js @@ -3,11 +3,12 @@ import SignInPage from '../../pages/sign_in_page' Given('I visit the sign in page', () => { SignInPage.visit() + SignInPage.confirm() }) When('I enter my credentials', () => { - SignInPage.email().type(Cypress.config().users.system.email) - SignInPage.password().type(Cypress.env('PASSWORD')) + SignInPage.emailInput().type(Cypress.config().users.system.email) + SignInPage.passwordInput().type(Cypress.env('PASSWORD')) - SignInPage.logIn().click() + SignInPage.submitButton().click() }) diff --git a/cypress/integration/transactions.feature b/cypress/integration/transactions.feature index 15f3c5e..b4d56f8 100644 --- a/cypress/integration/transactions.feature +++ b/cypress/integration/transactions.feature @@ -5,5 +5,5 @@ Feature: Transactions Scenario: Search for customer When I select the 'Water Quality' regime - And I search for the customer 'A60425822C' - Then I see only results for customer 'A60425822C' + And I search for the customer 'A61000001C' + Then I see only results for customer 'A61000001C' diff --git a/cypress/integration/transactions/transaction_steps.js b/cypress/integration/transactions/transaction_steps.js index 46593c8..89a9625 100644 --- a/cypress/integration/transactions/transaction_steps.js +++ b/cypress/integration/transactions/transaction_steps.js @@ -1,4 +1,4 @@ -import { Then, When, And, Before } from 'cypress-cucumber-preprocessor/steps' +import { Then, And, Before } from 'cypress-cucumber-preprocessor/steps' import TransactionsPage from '../../pages/transactions_page' Before(() => { @@ -17,23 +17,14 @@ Before(() => { // available throughout, and to keep the tests a little cleaner. // // https://docs.cypress.io/guides/guides/network-requests.html#Waiting - cy.server() - cy.route({ - method: 'GET', - url: '/regimes/cfd/transactions*' - }).as('getTransactions') -}) - -When('I select the {string} regime', (regime) => { - TransactionsPage.regimeMenu().click() - TransactionsPage.regimeMenuItem(regime).click() + cy.intercept('GET', '**/regimes/*/transactions?search=*').as('getSearch') }) And('I search for the customer {string}', (customer) => { - TransactionsPage.search().type(customer) - TransactionsPage.searchBtn().click() + TransactionsPage.searchInput().type(customer) + TransactionsPage.submitButton().click() - cy.wait('@getTransactions') + cy.wait('@getSearch') }) Then('I see only results for customer {string}', (customer) => { diff --git a/cypress/pages/accept_invite_page.js b/cypress/pages/accept_invite_page.js index 3308d27..842428b 100644 --- a/cypress/pages/accept_invite_page.js +++ b/cypress/pages/accept_invite_page.js @@ -1,23 +1,20 @@ -class AcceptInvitePage { - static visit (inviteLink) { - cy.visit(inviteLink) - } +import BasePage from './base_page' - static mainHeading () { - return cy.get('h2') +class AcceptInvitePage extends BasePage { + static confirm () { + cy.get('h1').should('contain', 'Set a password') + cy.url().should('include', '/auth/invitation/accept') } - static password () { + // Elements + + static passwordInput () { return cy.get('input#user_password') } - static passwordConfirmation () { + static passwordConfirmationInput () { return cy.get('input#user_password_confirmation') } - - static setPassword () { - return cy.get('input[name="commit"]') - } } export default AcceptInvitePage diff --git a/cypress/pages/add_user_page.js b/cypress/pages/add_user_page.js index 0f4d29d..5ac4c2c 100644 --- a/cypress/pages/add_user_page.js +++ b/cypress/pages/add_user_page.js @@ -1,36 +1,34 @@ -class AddUserPage { - static mainHeading () { - return cy.get('h1') - } +import BaseAppPage from './base_app_page' - static email () { - return cy.get('input#user_email') +class AddUserPage extends BaseAppPage { + static confirm () { + cy.get('h1').should('contain', 'Add User Account') + cy.url().should('include', '/users/new') } - static firstName () { - return cy.get('input#user_first_name') + // elements + + static cancelButton () { + return cy.get('a.btn-secondary') } - static lastName () { - return cy.get('input#user_last_name') + static emailInput () { + return cy.get('input#user_email') } - static enabled () { + static enabledCheckbox () { return cy.get('input#user_enabled') } - static role (option) { - const options = { - 'Read-only User': 'input#role_read_only', - 'Read-only + Export': 'input#role_read_only_export', - 'Billing Admin': 'role_billing', - 'System Admin': 'role_admin' - } + static firstNameInput () { + return cy.get('input#user_first_name') + } - return cy.get(options[option]) + static lastNameInput () { + return cy.get('input#user_last_name') } - static regimeAccess (option) { + static regimeAccessCheckbox (option) { const options = { Installations: 'input#user_regime_users_attributes_0_enabled', Waste: 'input#user_regime_users_attributes_1_enabled', @@ -40,12 +38,15 @@ class AddUserPage { return cy.get(options[option]) } - static addAndInviteUser () { - return cy.get('input[name="commit"]') - } + static roleRadioButton (option) { + const options = { + 'Read-only User': 'input#role_read_only', + 'Read-only + Export': 'input#role_read_only_export', + 'Billing Admin': 'role_billing', + 'System Admin': 'role_admin' + } - static cancel () { - return cy.get('a.btn-secondary') + return cy.get(options[option]) } } diff --git a/cypress/pages/annual_billing_file_details_page.js b/cypress/pages/annual_billing_file_details_page.js index 26e203d..eced960 100644 --- a/cypress/pages/annual_billing_file_details_page.js +++ b/cypress/pages/annual_billing_file_details_page.js @@ -1,8 +1,13 @@ -class AnnualBillingFileDetailsPage { - static mainHeading () { - return cy.get('h1') +import BaseAppPage from './base_app_page' + +class AnnualBillingFileDetailsPage extends BaseAppPage { + static confirm () { + cy.get('h1').should('contain', 'Annual Billing Data File Details') + cy.url().should('include', '/annual_billing_data_files') } + // Elements + static errorsHeading () { return cy.get('h2') } @@ -11,7 +16,7 @@ class AnnualBillingFileDetailsPage { return cy.get('.panel') } - static backBtn () { + static backButton () { return cy.get('.btn.btn-secondary') } } diff --git a/cypress/pages/annual_billing_page.js b/cypress/pages/annual_billing_page.js index 525ccca..9532bb0 100644 --- a/cypress/pages/annual_billing_page.js +++ b/cypress/pages/annual_billing_page.js @@ -1,14 +1,19 @@ -class AnnualBillingPage { - static mainHeading () { - return cy.get('h1') +import BaseAppPage from './base_app_page' + +class AnnualBillingPage extends BaseAppPage { + static confirm () { + cy.get('h1').should('contain', 'Annual Billing Data Files') + cy.url().should('include', '/annual_billing_data_files') } + // Elements + static dataFilesTable () { return cy.get('.table') } static fileNameLink () { - return cy.get('.table > tbody > tr > td > [href="/regimes/wml/annual_billing_data_files/48"]') + return cy.get('.table > tbody > tr:nth-child(1) > td:nth-child(1)') } } diff --git a/cypress/pages/base_app_page.js b/cypress/pages/base_app_page.js new file mode 100644 index 0000000..d284bde --- /dev/null +++ b/cypress/pages/base_app_page.js @@ -0,0 +1,32 @@ +import AdminMenu from './menus/admin_menu' +import AnnualBillingMenu from './menus/annual_billing_menu' +import BasePage from './base_page' +import RegimeMenu from './menus/regime_menu' +import TransactionsMenu from './menus/transactions_menu' +import UserMenu from './menus/user_menu' + +class BaseAppPage extends BasePage { + // Menus + + static get adminMenu () { + return AdminMenu + } + + static get annualBillingMenu () { + return AnnualBillingMenu + } + + static get regimeMenu () { + return RegimeMenu + } + + static get transactionsMenu () { + return TransactionsMenu + } + + static get userMenu () { + return UserMenu + } +} + +export default BaseAppPage diff --git a/cypress/pages/base_page.js b/cypress/pages/base_page.js new file mode 100644 index 0000000..7fdac4f --- /dev/null +++ b/cypress/pages/base_page.js @@ -0,0 +1,21 @@ +class BasePage { + static confirm () { + throw new Error("Extending class must implement 'confirm()'") + } + + // Elements + + static appVersion () { + return cy.get('.app-version') + } + + static mainHeading () { + return cy.get('h1') + } + + static submitButton () { + return cy.get('input[name="commit"]') + } +} + +export default BasePage diff --git a/cypress/pages/change_password_page.js b/cypress/pages/change_password_page.js index bb91db7..268166b 100644 --- a/cypress/pages/change_password_page.js +++ b/cypress/pages/change_password_page.js @@ -1,24 +1,20 @@ -class ChangePasswordPage { +import BasePage from './base_page' + +class ChangePasswordPage extends BasePage { static confirm () { cy.get('h1').should('contain', 'Change your password') cy.url().should('include', '/auth/password') } - static mainHeading () { - return cy.get('h1') - } + // Elements - static password () { + static passwordInput () { return cy.get('input#user_password') } - static passwordConfirmation () { + static passwordConfirmationInput () { return cy.get('input#user_password_confirmation') } - - static changeMyPassword () { - return cy.get('input[name="commit"]') - } } export default ChangePasswordPage diff --git a/cypress/pages/edit_user_page.js b/cypress/pages/edit_user_page.js index ed9dea3..2872ebb 100644 --- a/cypress/pages/edit_user_page.js +++ b/cypress/pages/edit_user_page.js @@ -1,32 +1,30 @@ -class AddUserPage { - static mainHeading () { - return cy.get('h1') - } +import BaseAppPage from './base_app_page' - static firstName () { - return cy.get('input#user_first_name') +class EditUserPage extends BaseAppPage { + static confirm () { + cy.get('h1').should('contain', 'Edit User Account') + cy.url().should('include', '/edit') } - static lastName () { - return cy.get('input#user_last_name') + // elements + + static cancelButton () { + return cy.get('a.btn-secondary') } - static enabled () { + static enabledCheckbox () { return cy.get('input#user_enabled') } - static role (option) { - const options = { - 'Read-only User': 'input#role_read_only', - 'Read-only + Export': 'input#role_read_only_export', - 'Billing Admin': 'role_billing', - 'System Admin': 'role_admin' - } + static firstNameInput () { + return cy.get('input#user_first_name') + } - return cy.get(options[option]) + static lastNameInput () { + return cy.get('input#user_last_name') } - static regimeAccess (option) { + static regimeAccessCheckbox (option) { const options = { Installations: 'input#user_regime_users_attributes_0_enabled', Waste: 'input#user_regime_users_attributes_1_enabled', @@ -36,17 +34,20 @@ class AddUserPage { return cy.get(options[option]) } - static updateUser () { - return cy.get('input[name="commit"]') - } - - static resendInvite () { + static resendInviteButton () { return cy.get('a.btn-warning') } - static cancel () { - return cy.get('a.btn-secondary') + static roleRadioButton (option) { + const options = { + 'Read-only User': 'input#role_read_only', + 'Read-only + Export': 'input#role_read_only_export', + 'Billing Admin': 'role_billing', + 'System Admin': 'role_admin' + } + + return cy.get(options[option]) } } -export default AddUserPage +export default EditUserPage diff --git a/cypress/pages/export_data_page.js b/cypress/pages/export_data_page.js index d3ff91b..c1698ff 100644 --- a/cypress/pages/export_data_page.js +++ b/cypress/pages/export_data_page.js @@ -1,13 +1,18 @@ -class ExportDataPage { - static mainHeading () { - return cy.get('h1') +import BaseAppPage from './base_app_page' + +class ExportDataPage extends BaseAppPage { + static confirm () { + cy.get('h1').should('contain', 'Download Transaction Data') + cy.url().should('include', '/data_export') } + // Elements + static dataProtectionNotice () { return cy.get('h5') } - static downloadBtn () { + static downloadButton () { return cy.get('.btn.btn-primary') } } diff --git a/cypress/pages/forgot_password_page.js b/cypress/pages/forgot_password_page.js index 4bcc2fc..9d81657 100644 --- a/cypress/pages/forgot_password_page.js +++ b/cypress/pages/forgot_password_page.js @@ -1,14 +1,15 @@ -class ForgotPasswordPage { - static mainHeading () { - return cy.get('h1') - } +import BasePage from './base_page' - static email () { - return cy.get('input#user_email') +class ForgotPasswordPage extends BasePage { + static confirm () { + cy.get('h1').should('contain', 'Forgot your password?') + cy.url().should('include', '/auth/password/new') } - static sendMeResetPasswordInstructions () { - return cy.get('input[name=commit]') + // Elements + + static emailInput () { + return cy.get('input#user_email') } } diff --git a/cypress/pages/menus/annual_billing_menu.js b/cypress/pages/menus/annual_billing_menu.js new file mode 100644 index 0000000..cfe02a4 --- /dev/null +++ b/cypress/pages/menus/annual_billing_menu.js @@ -0,0 +1,23 @@ +class AnnualBillingMenu { + static get selector () { + return '[aria-labelledby="navbarAnnualBillingSelectorLink"]' + } + + static options (regimeSlug) { + return { + 'Review Annual Billing Data': `[href="/regimes/${regimeSlug}/annual_billing_data_files"]` + } + } + + static menuLink () { + return cy.get('#navbarAnnualBillingSelectorLink') + } + + static getOption (optionText, regimeSlug) { + this.menuLink().click() + + return cy.get(`${this.selector} > ${this.options(regimeSlug)[optionText]}`) + } +} + +export default AnnualBillingMenu diff --git a/cypress/pages/resend_unlock_page.js b/cypress/pages/resend_unlock_page.js index 41b7504..432514f 100644 --- a/cypress/pages/resend_unlock_page.js +++ b/cypress/pages/resend_unlock_page.js @@ -1,20 +1,16 @@ -class ResendUnlockPage { +import BasePage from './base_page' + +class ResendUnlockPage extends BasePage { static confirm () { cy.get('h1').should('contain', 'Resend unlock instructions') cy.url().should('include', '/auth/unlock') } - static mainHeading () { - return cy.get('h1') - } + // Elements - static email () { + static emailInput () { return cy.get('#user_email') } - - static resendUnlockInstructions () { - return cy.get('[name=commit]') - } } export default ResendUnlockPage diff --git a/cypress/pages/sign_in_page.js b/cypress/pages/sign_in_page.js index 33051b6..00c921a 100644 --- a/cypress/pages/sign_in_page.js +++ b/cypress/pages/sign_in_page.js @@ -1,28 +1,29 @@ -class SignInPage { - static visit () { - cy.visit('/auth/sign_in') - } +import BasePage from './base_page' - static mainHeading () { - return cy.get('h1') +class SignInPage extends BasePage { + static confirm () { + cy.get('h1').should('contain', 'Sign in') + cy.url().should('include', '/auth/sign_in') } - static email () { - return cy.get('#user_email') + static visit () { + cy.visit('/auth/sign_in') } - static password () { - return cy.get('#user_password') - } + // Elements - static logIn () { - return cy.get('[name=commit]') + static emailInput () { + return cy.get('#user_email') } static forgotPasswordLink () { return cy.get('a[href="/auth/password/new"]') } + static passwordInput () { + return cy.get('#user_password') + } + static resendUnlockLink () { return cy.get('a[href="/auth/unlock/new"]') } diff --git a/cypress/pages/transactions_page.js b/cypress/pages/transactions_page.js index 6c1b1a8..8300444 100644 --- a/cypress/pages/transactions_page.js +++ b/cypress/pages/transactions_page.js @@ -1,22 +1,23 @@ -class TransactionsPage { +import BaseAppPage from './base_app_page' + +class TransactionsPage extends BaseAppPage { + static confirm () { + cy.get('h1').should('contain', 'Transactions to be billed') + // As transactions is the root path when authenticated we can't guarantee we'll have a url to assert against. + // This is why we don't have an assertion against the url like other page objects + } + static visit () { - // Transactions is the root path. You just have to be authenticated - // to see it + // Transactions is the root path. You just have to be authenticated to see it cy.visit('/') } - static mainHeading () { - return cy.get('h1') - } + // Elements - static search () { + static searchInput () { return cy.get('#search') } - static searchBtn () { - return cy.get('[name=commit]') - } - static resultsTable () { return cy.get('.table') } @@ -24,56 +25,6 @@ class TransactionsPage { static customerColumn () { return cy.get('.table > tbody > tr > td:nth-child(4)') } - - static transactionMenu () { - return cy.get('#navbarTransactionsSelectorLink') - } - - static adminMenu () { - return cy.get('#navbarAdminSelectorLink') - } - - static billingMenu () { - return cy.get('#navbarAnnualBillingSelectorLink') - } - - static regimeMenu () { - return cy.get('#navbarRegimeSelectorLink') - } - - static regimeMenuItem (regime) { - let slug - - switch (regime) { - case 'Water Quality': - slug = 'cfd' - break - case 'Installations': - slug = 'pas' - break - case 'Waste': - slug = 'wml' - break - } - - return cy.get(`.nav-item.show > .dropdown-menu > [href="/regimes/${slug}/transactions"]`) - } - - static downloadTransactionDataMenuItem () { - return cy.get(':nth-child(1) > .nav-item > .dropdown-menu > [href="/regimes/pas/data_export"]') - } - - static annualBillingDataMenuItem () { - return cy.get('#navbarAnnualBillingSelectorLink') - } - - static reviewAnnualBillingDataMenuItem () { - return cy.get(':nth-child(1) > .dropdown > div > [href="/regimes/wml/annual_billing_data_files"]') - } - - static regionDropDown () { - return cy.get('#region') - } } export default TransactionsPage diff --git a/cypress/pages/users_page.js b/cypress/pages/users_page.js index 51d91c3..fee5fe9 100644 --- a/cypress/pages/users_page.js +++ b/cypress/pages/users_page.js @@ -1,26 +1,27 @@ -class UsersPage { - static mainHeading () { - return cy.get('h1') +import BaseAppPage from './base_app_page' + +class UsersPage extends BaseAppPage { + static confirm () { + cy.get('h1').should('contain', 'Users') + cy.url().should('include', '/users') } - static addUserAccount () { + // Elements + + static addUserAccountButton () { return cy.get('button#new-user') } - static searchName () { + static searchNameInput () { return cy.get('input#search[type="search"]') } - static searchResults () { - return cy.get('table.table-responsive > tbody > tr') - } - - static searchResultEdit (id) { + static searchResultEditButton (id) { return cy.get(`a.btn-success[href="/users/${id}/edit"]`) } - static search () { - return cy.get('[name=commit]') + static searchResultsTable () { + return cy.get('table.table-responsive > tbody > tr') } } diff --git a/cypress/plugins/index.js b/cypress/plugins/index.js index 79714cc..fce9692 100644 --- a/cypress/plugins/index.js +++ b/cypress/plugins/index.js @@ -125,6 +125,22 @@ module.exports = (on, config) => { reject(error) }) }) + }, + + regime (identifier) { + const regimes = { + pas: 'Installations', + wml: 'Waste', + cfd: 'Water Quality' + } + let result + for (const [key, value] of Object.entries(regimes)) { + if (key === identifier.toLowerCase() || value.toLowerCase() === identifier.toLowerCase()) { + result = { slug: key, name: value } + } + } + + return result } }) diff --git a/cypress/support/commands.js b/cypress/support/commands.js index f696cc3..6bf78b2 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -33,9 +33,9 @@ import SignInPage from '../pages/sign_in_page' */ Cypress.Commands.add('signIn', (email, password = Cypress.env('PASSWORD')) => { SignInPage.visit() - SignInPage.email().type(email) - SignInPage.password().type(password, { log: false }) - SignInPage.logIn().click() + SignInPage.emailInput().type(email) + SignInPage.passwordInput().type(password, { log: false }) + SignInPage.submitButton().click() }) /** @@ -119,3 +119,17 @@ Cypress.Commands.add('addUser', (user) => { }) }) }) + +/** + * Use when you want to check an alert contains a certain message + * + * An action will often lead to alert appearing that is shown on the page after the one we have been interacting with. + * To avoid importing the landing page into steps just to check its alert i.e. if we'd added this method to BasePage.js, + * we instead add it as a custom command. + * + * It means we can check the alert without first having to declare the page we are on. But having it as a command means + * we can define in just one place what the selector for our alerts is. + */ +Cypress.Commands.add('alertShouldContain', (text) => { + cy.get('.col > .alert').should('contain.text', text) +})