Skip to content

Commit

Permalink
Experiment/create ephemeral UI test accts (#1898)
Browse files Browse the repository at this point in the history
* fix: simplify email address names to avoid issues with IMAP

* fix: modify Login method to accept email alias to check for when connecting to IMAP

* fix: new accounts go to /services page since they only belong to one service

* feat: new plugin to generate a random email alias, then call an endpoint on the API to create a UI testing account with it

* fix: update cypress config to expose the create-account plugin, and store the email address while cypress is running

* feat: update the login command to get the ephemeral email account before logging in

* feat(create-account): update create account task and pass notify test user pw

* fix(tou_test): success can either be the /accounts page or a /services/ page

* chore(email-account): refactor and clean up code a bit; ensure connections are always closed and not dangling

* feat(config): simplify config

* fix up ids

* chore(refactor): refactor login command; add login command for platform admin

* task(cypress config): add back SMS template ID

* fix(tou_prompt test): add assertion to ensure success of agreeing to terms

* fix(create-account): simplify call to api; remove posting of the password since API already has this secret

* chore(email-account): remove debug logging

* fix: add template category to the test that will be empty for email

* fix(create-account): remove pw prop

* chore: remove debug log

* fix: dont try to delete emails when there is none

* fix: update calls to login across tests

* chore: update test and get values from config

* chore: add README, extra npm script

* chore: formatting

* fix(cypress): update tests to use updated, simplified `cy.login()` command

* chore: formatting

* chore: update config to use staging

* fix(remaining_messages_summary test): add assert to ensure test waits for language to change

* chore: remove debug code

* fix(template_filters test): make sure the scenario ends in no results

* fix(cypress login): use cypress auth to get new user

* fix failing tests

* fix(cypress config): add back retries

* please [review] me

* fix: change secret name for new user password so this wont conflict with existing PRs

* chore: README updates

* chore: remove unused import

* chore: removed comments

* chore: update README

* fix(cypress/README): remove duplicate info
  • Loading branch information
andrewleith authored Feb 18, 2025
1 parent 46d557f commit 76a5502
Show file tree
Hide file tree
Showing 30 changed files with 267 additions and 194 deletions.
48 changes: 48 additions & 0 deletions tests_cypress/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Notify + Cypress 🎉

## Setup
This folder contains Cypress tests suites. In order to run them, you'll need to install cypress and its dependencies. If you're running inside the dev container, rebuild your dev container to get the necessary packages.

## Running the tests
### In your devcontainer
There are some issues getting the cypress UI to launch within the devcontainer. For now, you can run the headless tests inside the dev container but if you want to launch the cypress UI you will need to do that outside of the dev container.

There are 3 helper scripts in `package.json` to run 2 of the test suites. Run these from the `tests_cypress/` folder:
- `npm run cypress`: this will open Cypress with its UI and you can choose any test suite to run
- `npm run a11y`: this will run the accessibility tests in headless mode using the electron browser
- `npm run ci`: this will run the headless CI tests in headless mode using the electron browser

### Outside of your devcontainer
To launch the cypress UI, where you can choose your test suite and visually debug and inspect tests, run (from the `tests_cypress/` folder):
- `npm run cypress`: this will open the cypress UI where you can choose which tests to run and in which browser

### Local installation
To install cypress locally, use the following command, from the `tests_cypress/` folder:
```bash
npm install
npx cypress install
```

## Configuration
- `cypress.env.json`: this file contains sensitive items like api keys and passphrases that you'll need to run the tests. You'll need to add the file `cypress.env.json` into the `tests_cypress/` folder and its contents can be found in 1password.
- `config.js`: this file contains non-sensitive items like template ids and hostnames that you'll need to run the tests

### `cypress.env.json` contents
| key | description |
| -------------------------- | ----------------------------------------------- |
| ADMIN_SECRET | Secret admin uses to authenticate against API |
| ADMIN_USERNAME | Username admin uses to authenticate against API |
| NOTIFY_USER | Notify user used by the tests |
| NOTIFY_PASSWORD | Password of NOTIFY_USER (deprecated) |
| IMAP_PASSWORD | IMAP password of gmail account for NOTIFY_USER |
| CYPRESS_AUTH_USER_NAME | Username for the Cypress auth client |
| CYPRESS_AUTH_CLIENT_SECRET | Secret for the Cypress auth client |
| CYPRESS_USER_PASSWORD | Password for the Cypress user |
| IMAP_PASSWORD | IMAP password of gmail account for NOTIFY_USER |

### Target environment 🎯
The tests are configured to run against the staging environment by default. To run the tests against your local environment, you will need to update the `ConfigToUse` variable in `config.js` file to use `LOCAL` instead of `STAGING`. For example:
```js
const ConfigToUse = { ...config.COMMON, ...config.LOCAL };
```

71 changes: 12 additions & 59 deletions tests_cypress/config.js
Original file line number Diff line number Diff line change
@@ -1,39 +1,20 @@
let COMMON = {
Services: {
Cypress: 'd4e8a7f4-2b8a-4c9a-8b3f-9c2d4e8a7f4b'
},
Templates: {
'SMOKE_TEST_EMAIL': 'f47ac10b-58cc-4372-a567-0e02b2c3d479',
'SMOKE_TEST_SMS': 'e4b8f8d0-6a3b-4b9e-8c2b-1f2d3e4a5b6c',
},
};

let STAGING = {
CONFIG_NAME: "STAGING",
Hostnames: {
API: 'https://api.staging.notification.cdssandbox.xyz',
Admin: 'https://staging.notification.cdssandbox.xyz',
DDAPI: 'https://api.document.staging.notification.cdssandbox.xyz',
},
Services: {
Notify: 'd6aa2c68-a2d9-4437-ab19-3ae8eb202553',
Cypress: '5c8a0501-2aa8-433a-ba51-cefb8063ab93'
},
Templates: {
'FILE_ATTACH_TEMPLATE_ID': '7246c71e-3d60-458b-96af-af17a5b07659',
'SIMPLE_EMAIL_TEMPLATE_ID': '939dafde-1b60-47f0-a6d5-c9080d92a4a8',
'VARIABLES_EMAIL_TEMPLATE_ID': '1101a00a-11b7-4036-865c-add43fcff7c9',
'SMOKE_TEST_EMAIL': '5e26fae6-3565-44d5-bfed-b18680b6bd39',
'SMOKE_TEST_EMAIL_BULK': '04145882-0f21-4d57-940d-69883fc23e77',
'SMOKE_TEST_EMAIL_ATTACH': 'bf85def8-01b4-4c72-98a8-86f2bc10f2a4',
'SMOKE_TEST_EMAIL_LINK': '37924e87-038d-48b8-b122-f6dddefd56d5',
'SMOKE_TEST_SMS': '16cae0b3-1d44-47ad-a537-fd12cc0646b6'
},
Users: {
Team: ['andrew.leith+bannertest@cds-snc.ca'],
NonTeam: ['person@example.com'],
Simulated: ['simulate-delivered-2@notification.canada.ca', 'simulate-delivered-3@notification.canada.ca', 'success@simulator.amazonses.com'],
SimulatedPhone: ['+16132532222', '+16132532223', '+16132532224']
},
Organisations: {
'DEFAULT_ORG_ID': '4eef762f-383d-4068-81ca-c2c5c186eb16',
'NO_CUSTOM_BRANDING_ORG_ID': '4eef762f-383d-4068-81ca-c2c5c186eb16'
},
ReplyTos: {
Default: '24e5288d-8bfa-4ad4-93aa-592c11a694cd',
Second: '797865c4-788b-4184-91ae-8e45eb07e40b'
},
viewports: [320, 375, 640, 768]
};

let LOCAL = {
Expand All @@ -43,43 +24,15 @@ let LOCAL = {
Admin: 'http://localhost:6012',
DDAPI: 'http://localhost:7000',
},
Services: {
Notify: 'd6aa2c68-a2d9-4437-ab19-3ae8eb202553',
Cypress: '5c8a0501-2aa8-433a-ba51-cefb8063ab93'
},
Templates: {
'FILE_ATTACH_TEMPLATE_ID': 'e52acc48-dcb9-4f70-81cf-b87d0ceaef1b',
'SIMPLE_EMAIL_TEMPLATE_ID': '0894dc6c-1b07-465e-91f0-aa76f202a83f',
'VARIABLES_EMAIL_TEMPLATE_ID': 'fa00aa13-87fd-4bc7-9349-ba9270347055',
'SMOKE_TEST_EMAIL': '08673acf-fef1-408d-8ce7-7809907595b2',
'SMOKE_TEST_EMAIL_BULK': 'efbd319b-4de8-41c7-850f-93ec0490d3c2',
'SMOKE_TEST_EMAIL_ATTACH': 'cbd5307f-8662-4cea-9b8e-3bc672bf005c',
'SMOKE_TEST_EMAIL_LINK': '94cce202-b171-440f-b0c1-734368ca9494',
'SMOKE_TEST_SMS': 'a9fff158-a745-417a-b1ec-ceebcba6614f'
},
Users: {
Team: ['william.banks+admin@cds-snc.ca'],
NonTeam: ['person@example.com'],
Simulated: ['simulate-delivered-2@notification.canada.ca', 'simulate-delivered-3@notification.canada.ca', 'success@simulator.amazonses.com'],
SimulatedPhone: ['+16132532222', '+16132532223', '+16132532224']
},
Organisations: {
'DEFAULT_ORG_ID': 'ff9e5ddd-926f-4ae2-bc87-f5104262ca17',
'NO_CUSTOM_BRANDING_ORG_ID': '39b3230e-300a-42f4-bfb7-40b20b704d44'
},
ReplyTos: {
Default: '8c2a9b22-8fec-4ad9-bca8-658abbb7406e',
Second: 'fc4d2266-5594-47d0-8056-7bef62d59177'
},
viewports: [320, 375, 640, 768]
};

const config = {
COMMON,
STAGING,
LOCAL,
};

// choose which config to use here
const ConfigToUse = config.STAGING;
const ConfigToUse = { ...config.COMMON, ...config.STAGING };

module.exports = ConfigToUse;
20 changes: 15 additions & 5 deletions tests_cypress/cypress.config.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
var config = require('./config');

const { defineConfig } = require("cypress");
const EmailAccount = require("./cypress/plugins/email-account")
const EmailAccount = require("./cypress/plugins/email-account");
const CreateAccount = require("./cypress/plugins/create-account");
const htmlvalidate = require("cypress-html-validate/plugin");

module.exports = defineConfig({
Expand All @@ -28,18 +29,27 @@ module.exports = defineConfig({
return null
},
// Email Account ///
getLastEmail() {
return emailAccount.getLastEmail()
getLastEmail(emailAddress) {
return emailAccount.getLastEmail(emailAddress)
},
deleteAllEmails() {
return emailAccount.deleteAllEmails()
},
fetchEmail(acct) {
return emailAccount.fetchEmail(acct)
},
createEmailAccount() {
return emailAccount.createEmailAccount();
createAccount({ baseUrl, username, secret }) {
if (global.acct) {
return global.acct;
} else {
let acct = CreateAccount(baseUrl, username, secret);
global.acct = acct;
return acct
}
},
getUserName() {
return global.acct;
}
});

on('before:browser:launch', (browser = {}, launchOptions) => {
Expand Down
4 changes: 2 additions & 2 deletions tests_cypress/cypress/Notify/Admin/Pages/LoginPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ let Actions = {
},
Login: (email, password, agreeToTerms=true) => {
cy.clearCookie(ADMIN_COOKIE); // clear auth cookie
cy.task('deleteAllEmails'); // purge email inbox to make getting the 2fa code easier
// cy.task('deleteAllEmails'); // purge email inbox to make getting the 2fa code easier

// login with username and password
cy.visit(LoginPage.URL);
Expand All @@ -29,7 +29,7 @@ let Actions = {

// get email 2fa code
recurse(
() => cy.task('getLastEmail', {} ), // Cypress commands to retry
() => cy.task('getLastEmail', email), // Cypress commands to retry
Cypress._.isObject, // keep retrying until the task returns an object
{
log: true,
Expand Down
3 changes: 3 additions & 0 deletions tests_cypress/cypress/Notify/Admin/Pages/TemplatesPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ let Actions = {
cy.contains('a', template_name).first().click();
cy.contains('h1', template_name).should('be.visible');
},
SelectTemplateById: (service_id, template_id) => {
cy.get(`a[href="/services/${service_id}/templates/${template_id}"]`).click();
},
GotoAddRecipients: () => {
Components.YesAddRecipients().click();
//cy.contains('h1', 'Add recipients').should('be.visible');
Expand Down
6 changes: 5 additions & 1 deletion tests_cypress/cypress/Notify/Admin/Pages/TouPrompt.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ let Actions = {
AgreeToTerms: () => {
TouPrompt.Components.Terms().scrollTo('bottom', { ensureScrollable: false });
Components.DismissButton().click();
cy.url().should('include', '/accounts');
// depending on how many services a user has, the app either goes to the /accounts page
// or to a specific service page - either means success
cy.url().should('match', /\/(accounts|services)/);
cy.get('h1').should('not.contain', 'Before you continue');

},
};

Expand Down
2 changes: 1 addition & 1 deletion tests_cypress/cypress/Notify/NotifyAPI.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const Utilities = {
return jwt.jws.JWS.sign("HS256", JSON.stringify(headers), JSON.stringify(claims), Cypress.env('ADMIN_SECRET'));
},
GenerateID: (length = 10) => {
const nanoid = customAlphabet('1234567890abcdef-_', length)
const nanoid = customAlphabet('1234567890abcdef', length)
return nanoid()
}
};
Expand Down
2 changes: 1 addition & 1 deletion tests_cypress/cypress/e2e/admin/a11y/app_pages.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ const pages = [
describe(`A11Y - App pages [${config.CONFIG_NAME}]`, () => {
for (const page of pages) {
it(`${page.name}`, () => {
cy.login(Cypress.env("NOTIFY_USER"), Cypress.env("NOTIFY_PASSWORD"));
cy.login();
cy.a11yScan(page.route, {
a11y: true,
htmlValidate: true,
Expand Down
2 changes: 1 addition & 1 deletion tests_cypress/cypress/e2e/admin/branding/a11y.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ describe("Branding A11Y", () => {
// stop the recurring dashboard fetch requests
cy.intercept("GET", "**/dashboard.json", {});

cy.login(Cypress.env("NOTIFY_USER"), Cypress.env("NOTIFY_PASSWORD"));
cy.login();
});

// perform a11yScan on all pages in the branding_pages array
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ describe("Branding settings", () => {
// stop the recurring dashboard fetch requests
cy.intercept("GET", "**/dashboard.json", {});

cy.login(Cypress.env("NOTIFY_USER"), Cypress.env("NOTIFY_PASSWORD"));
cy.login();

cy.visit(`/services/${config.Services.Cypress}/service-settings`);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ describe("Edit Branding", () => {
// stop the recurring dashboard fetch requests
cy.intercept("GET", "**/dashboard.json", {});

cy.login(Cypress.env("NOTIFY_USER"), Cypress.env("NOTIFY_PASSWORD"));
cy.login();

cy.visit(`/services/${config.Services.Cypress}/edit-branding`);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ describe("Branding request", () => {
beforeEach(() => {
// stop the recurring dashboard fetch requests
cy.intercept("GET", "**/dashboard.json", {});
cy.login(Cypress.env("NOTIFY_USER"), Cypress.env("NOTIFY_PASSWORD"));
cy.login();
cy.visit(`/services/${config.Services.Cypress}/branding-request`);
});

Expand Down
2 changes: 1 addition & 1 deletion tests_cypress/cypress/e2e/admin/branding/review-pool.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {

describe("Review Pool", () => {
beforeEach(() => {
cy.login(Cypress.env("NOTIFY_USER"), Cypress.env("NOTIFY_PASSWORD"));
cy.login();
cy.visit(`/services/${config.Services.Cypress}/review-pool`);
});
context("General page functionality", () => {
Expand Down
2 changes: 1 addition & 1 deletion tests_cypress/cypress/e2e/admin/login.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ describe("Basic login", () => {
});

it("displays notify service page", () => {
cy.visit(`/services/${config.Services.Notify}`);
cy.visit(`/services/${config.Services.Cypress}`);
cy.contains("h1", "Dashboard").should("be.visible");
});
});
2 changes: 1 addition & 1 deletion tests_cypress/cypress/e2e/admin/menu/disclosure_menu.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ describe("Mobile menu", () => {
});

it("Re-focus on the menu button when the menu closes (signed in)", () => {
cy.login(Cypress.env("NOTIFY_USER"), Cypress.env("NOTIFY_PASSWORD"));
cy.login();

cy.visit("/");
MainMenu.OpenMenu();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { Admin } from "../../../Notify/NotifyAPI";

describe("Template Categories", () => {
beforeEach(() => {
cy.login(Cypress.env("NOTIFY_ADMIN_USER"), Cypress.env("NOTIFY_PASSWORD"));
cy.loginAsPlatformAdmin();
cy.visit(`/template-categories`);
});

Expand Down
2 changes: 1 addition & 1 deletion tests_cypress/cypress/e2e/admin/qualtrics.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ describe("Qualtrics", () => {
});

it("survey button appears and survey opens", () => {
cy.visit(`/services/${config.Services.Notify}`);
cy.visit(`/services/${config.Services.Cypress}`);
cy.contains("h1", "Dashboard").should("be.visible");
cy.get("#QSIFeedbackButton-btn").should("be.visible"); // qualtrics survey button
cy.get("#QSIFeedbackButton-btn").click(); // click the button
Expand Down
4 changes: 2 additions & 2 deletions tests_cypress/cypress/e2e/admin/service-settings.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ describe("Service Settings", () => {
// stop the recurring dashboard fetch requests
cy.intercept("GET", "**/dashboard.json", {});

cy.login(Cypress.env("NOTIFY_USER"), Cypress.env("NOTIFY_PASSWORD"));
cy.login();

cy.visit(
config.Hostnames.Admin +
Expand All @@ -30,7 +30,7 @@ describe("Platform Admin Service Settings", () => {
beforeEach(() => {
// stop the recurring dashboard fetch requests
cy.intercept("GET", "**/dashboard.json", {});
cy.login(Cypress.env("NOTIFY_ADMIN_USER"), Cypress.env("NOTIFY_PASSWORD"));
cy.login();
cy.visit(
config.Hostnames.Admin +
`/services/${config.Services.Cypress}/service-settings`,
Expand Down
2 changes: 1 addition & 1 deletion tests_cypress/cypress/e2e/admin/sign_out/sign_out.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ describe("Sign out", () => {

it("Redirects to session timeout page when logged in (multiple pages)", () => {
["/home", "/features"].forEach((page) => {
cy.login(Cypress.env("NOTIFY_USER"), Cypress.env("NOTIFY_PASSWORD"));
cy.login();
vistPageAndFastForwardTime(page);

// asserts
Expand Down
6 changes: 3 additions & 3 deletions tests_cypress/cypress/e2e/admin/sitemap/sitemap.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ describe(`Sitemap`, () => {
});

it("Does display the 'You' group when logged in", () => {
cy.login(Cypress.env("NOTIFY_USER"), Cypress.env("NOTIFY_PASSWORD"));
cy.login();
cy.visit(path);

cy.getByTestId("sitemap-group").contains("Your GC Notify");
Expand All @@ -75,13 +75,13 @@ describe(`Sitemap`, () => {
cy.get('a[href="/sitemap"]').should("be.visible");
});
it("Has the sitemap link on app pages when logged in", () => {
cy.login(Cypress.env("NOTIFY_USER"), Cypress.env("NOTIFY_PASSWORD"));
cy.login();
cy.visit("/activity");

cy.get(`#${sitemap_footer_id}`).should("be.visible");
});
it("Has the sitemap link on GCA pages when logged in", () => {
cy.login(Cypress.env("NOTIFY_USER"), Cypress.env("NOTIFY_PASSWORD"));
cy.login();
cy.visit("/features");

cy.get('a[href="/sitemap"]').should("be.visible");
Expand Down
2 changes: 1 addition & 1 deletion tests_cypress/cypress/e2e/admin/template-categories.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { TemplatesPage as Page } from "../../Notify/Admin/Pages/all";

describe("Template categories", () => {
beforeEach(() => {
cy.login(Cypress.env("NOTIFY_USER"), Cypress.env("NOTIFY_PASSWORD"));
cy.login();
cy.visit(`/services/${config.Services.Cypress}/templates`);
});

Expand Down
Loading

0 comments on commit 76a5502

Please sign in to comment.