Skip to content

Commit

Permalink
Task/improve cypress ci (#1842)
Browse files Browse the repository at this point in the history
* task: change cypress CI so that it runs whatever tests are imported by `admin/ci.cy.js`; this will make it easier to add future tests as we build them

* chore(cypress): add improved login method that re-uses sessions between tests to avoid extra logins

* chore: fix sign_out tests filename as it was incorrect

* fix: update `app_pages.cy.js` test to use new `cy.login` implementation

* task: update `make format` to also run on cypress test code

* chore: formatting

* fix: use correct path 🤦‍♂️
  • Loading branch information
andrewleith authored May 14, 2024
1 parent 469354d commit 399be08
Show file tree
Hide file tree
Showing 13 changed files with 322 additions and 234 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test-admin-deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -179,4 +179,4 @@ jobs:
build: npx cypress info
working-directory: tests_cypress
spec: |
cypress/e2e/admin/a11y/app_pages.cy.js
cypress/e2e/admin/ci.cy.js
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ format:
flake8 ./app ./tests
isort --check-only ./app ./tests
mypy ./
npx prettier --write app/assets/javascripts app/assets/stylesheets
npx prettier --write app/assets/javascripts app/assets/stylesheets tests_cypress/cypress/e2e

.PHONY: tailwind
tailwind:
Expand Down
4 changes: 2 additions & 2 deletions tests_cypress/cypress/e2e/admin/a11y/all.cy.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
// import './gca_pages.cy';
import './app_pages.cy';
import './gca_pages.cy';
import "./app_pages.cy";
import "./gca_pages.cy";
160 changes: 105 additions & 55 deletions tests_cypress/cypress/e2e/admin/a11y/app_pages.cy.js
Original file line number Diff line number Diff line change
@@ -1,51 +1,101 @@
/// <reference types="cypress" />

import config from "../../../../config";
import { LoginPage } from "../../../Notify/Admin/Pages/all";


const pages = [
{ name: "Landing page", route: "/accounts" },
{ name: "Your profile", route: "/user-profile" },
{ name: "Dashboard", route: `/services/${config.Services.Cypress}` },
{ name: "Dashboard > Notification reports", route: `/services/${config.Services.Cypress}/notifications/email?status=sending,delivered,failed` },
{ name: "Dashboard > Problem emails", route: `/services/${config.Services.Cypress}/problem-emails` },
{ name: "Dashboard > Monthly usage", route: `/services/${config.Services.Cypress}/monthly` },
{ name: "Dashboard > Template usage", route: `/services/${config.Services.Cypress}/template-usage` },
{ name: "Dashboard > Create template", route: `/services/${config.Services.Cypress}/templates/create?source=dashboard` },
{ name: "Dashboard > Select template", route: `/services/${config.Services.Cypress}/templates?view=sending` },
{ name: "API", route: `/services/${config.Services.Cypress}/api` },
{ name: "API > Keys", route: `/services/${config.Services.Cypress}/api/keys` },
{ name: "API > Keys > Create", route: `/services/${config.Services.Cypress}/api/keys/create` },
{ name: "API > Safelist", route: `/services/${config.Services.Cypress}/api/safelist` },
{ name: "API > Callbacks", route: `/services/${config.Services.Cypress}/api/callbacks/delivery-status-callback` },
{ name: "Team members", route: `/services/${config.Services.Cypress}/users` },
{ name: "Settings", route: `/services/${config.Services.Cypress}/service-settings` },
{ name: "Settings > Change service name", route: `/services/${config.Services.Cypress}/service-settings/name` },
{ name: "Templates", route: `/services/${config.Services.Cypress}/templates` },
{ name: "Template > View template", route: `/services/${config.Services.Cypress}/templates/${config.Templates.SMOKE_TEST_EMAIL}` },
{ name: "Template > Edit template", route: `/services/${config.Services.Cypress}/templates/${config.Templates.SMOKE_TEST_EMAIL}/edit` },
{ name: "Template > Preview template", route: `/services/${config.Services.Cypress}/templates/${config.Templates.SMOKE_TEST_EMAIL}/preview` },
{ name: "GC Notify Activity", route: '/activity' },
{ name: "Contact us", route: '/contact' },
{ name: "Create an account", route: '/register' },
{ name: "Sign in", route: '/sign-in' },
{ name: "Landing page", route: "/accounts" },
{ name: "Your profile", route: "/user-profile" },
{ name: "Dashboard", route: `/services/${config.Services.Cypress}` },
{
name: "Dashboard > Notification reports",
route: `/services/${config.Services.Cypress}/notifications/email?status=sending,delivered,failed`,
},
{
name: "Dashboard > Problem emails",
route: `/services/${config.Services.Cypress}/problem-emails`,
},
{
name: "Dashboard > Monthly usage",
route: `/services/${config.Services.Cypress}/monthly`,
},
{
name: "Dashboard > Template usage",
route: `/services/${config.Services.Cypress}/template-usage`,
},
{
name: "Dashboard > Create template",
route: `/services/${config.Services.Cypress}/templates/create?source=dashboard`,
},
{
name: "Dashboard > Select template",
route: `/services/${config.Services.Cypress}/templates?view=sending`,
},
{ name: "API", route: `/services/${config.Services.Cypress}/api` },
{
name: "API > Keys",
route: `/services/${config.Services.Cypress}/api/keys`,
},
{
name: "API > Keys > Create",
route: `/services/${config.Services.Cypress}/api/keys/create`,
},
{
name: "API > Safelist",
route: `/services/${config.Services.Cypress}/api/safelist`,
},
{
name: "API > Callbacks",
route: `/services/${config.Services.Cypress}/api/callbacks/delivery-status-callback`,
},
{ name: "Team members", route: `/services/${config.Services.Cypress}/users` },
{
name: "Settings",
route: `/services/${config.Services.Cypress}/service-settings`,
},
{
name: "Settings > Change service name",
route: `/services/${config.Services.Cypress}/service-settings/name`,
},
{
name: "Templates",
route: `/services/${config.Services.Cypress}/templates`,
},
{
name: "Template > View template",
route: `/services/${config.Services.Cypress}/templates/${config.Templates.SMOKE_TEST_EMAIL}`,
},
{
name: "Template > Edit template",
route: `/services/${config.Services.Cypress}/templates/${config.Templates.SMOKE_TEST_EMAIL}/edit`,
},
{
name: "Template > Preview template",
route: `/services/${config.Services.Cypress}/templates/${config.Templates.SMOKE_TEST_EMAIL}/preview`,
},
{ name: "GC Notify Activity", route: "/activity" },
{ name: "Contact us", route: "/contact" },
{ name: "Create an account", route: "/register" },
{ name: "Sign in", route: "/sign-in" },
];

describe(`A11Y - App pages [${config.CONFIG_NAME}]`, () => {
retryableBefore(() => {
LoginPage.Login(Cypress.env('NOTIFY_USER'), Cypress.env('NOTIFY_PASSWORD'));
cy.task('log', "Running against:" + Cypress.config('baseUrl'))
});
retryableBefore(() => {
cy.login(Cypress.env("NOTIFY_USER"), Cypress.env("NOTIFY_PASSWORD"));
cy.task("log", "Running against:" + Cypress.config("baseUrl"));
});

for (const page of pages) {
it(`${page.name}`, () => {
cy.a11yScan(page.route, { a11y: true, htmlValidate: true, mimeTypes: false, deadLinks: false });
});
}
for (const page of pages) {
it(`${page.name}`, () => {
cy.a11yScan(page.route, {
a11y: true,
htmlValidate: true,
mimeTypes: false,
deadLinks: false,
});
});
}
});


/**
* A `before()` alternative that gets run when a failing test is retried.
*
Expand All @@ -58,24 +108,24 @@ describe(`A11Y - App pages [${config.CONFIG_NAME}]`, () => {
* https://stackoverflow.com/questions/71285827/cypress-e2e-before-hook-not-working-on-retries
*/
function retryableBefore(fn) {
let shouldRun = true;
let shouldRun = true;

// we use beforeEach as cypress will run this on retry attempt
// we just abort early if we detected that it's already run
beforeEach(() => {
if (!shouldRun) return;
shouldRun = false;
fn();
});
// we use beforeEach as cypress will run this on retry attempt
// we just abort early if we detected that it's already run
beforeEach(() => {
if (!shouldRun) return;
shouldRun = false;
fn();
});

// When a test fails we flip the `shouldRun` flag back to true
// so when cypress retries and runs the `beforeEach()` before
// the test that failed, we'll run the `fn()` logic once more.
Cypress.on('test:after:run', (result) => {
if (result.state === 'failed') {
if (result.currentRetry < result.retries) {
shouldRun = true;
}
// When a test fails we flip the `shouldRun` flag back to true
// so when cypress retries and runs the `beforeEach()` before
// the test that failed, we'll run the `fn()` logic once more.
Cypress.on("test:after:run", (result) => {
if (result.state === "failed") {
if (result.currentRetry < result.retries) {
shouldRun = true;
}
});
};
}
});
}
84 changes: 45 additions & 39 deletions tests_cypress/cypress/e2e/admin/a11y/gca_pages.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,52 +2,58 @@

import config from "../../../../config";

const langs = ['en', 'fr'];
const langs = ["en", "fr"];

const fullPageList = [
{ en: '/accessibility', fr: '/accessibilite' },
{ en: '/features', fr: '/fonctionnalites' },
{ en: '/formatting-emails', fr: '/guide-mise-en-forme' },
{ en: '/service-level-agreement', fr: '/accord-niveaux-de-service' },
{ en: '/terms', fr: '/conditions-dutilisation' },
{ en: '/guidance', fr: '/guides-reference' },
{ en: '/home', fr: '/accueil' },
{ en: '/message-delivery-status', fr: '/etat-livraison-messages' },
{ en: '/other-services', fr: '/autres-services' },
{ en: '/privacy', fr: '/confidentialite' },
{ en: '/security', fr: '/securite' },
{ en: '/sending-custom-content', fr: '/envoyer-contenu-personnalise' },
{ en: '/service-level-objectives', fr: '/objectifs-niveau-de-service' },
{ en: '/system-status', fr: '/etat-du-systeme' },
{ en: '/understanding-delivery-and-failure', fr: '/comprendre-statut-de-livraison' },
{ en: '/updating-contact-information', fr: '/maintenir-a-jour-les-coordonnees' },
{ en: '/using-a-spreadsheet', fr: '/utiliser-une-feuille-de-calcul' },
{ en: '/why-gc-notify', fr: '/pourquoi-notification-gc' },
{ en: '/new-features', fr: '/nouvelles-fonctionnalites' },
{ en: "/accessibility", fr: "/accessibilite" },
{ en: "/features", fr: "/fonctionnalites" },
{ en: "/formatting-emails", fr: "/guide-mise-en-forme" },
{ en: "/service-level-agreement", fr: "/accord-niveaux-de-service" },
{ en: "/terms", fr: "/conditions-dutilisation" },
{ en: "/guidance", fr: "/guides-reference" },
{ en: "/home", fr: "/accueil" },
{ en: "/message-delivery-status", fr: "/etat-livraison-messages" },
{ en: "/other-services", fr: "/autres-services" },
{ en: "/privacy", fr: "/confidentialite" },
{ en: "/security", fr: "/securite" },
{ en: "/sending-custom-content", fr: "/envoyer-contenu-personnalise" },
{ en: "/service-level-objectives", fr: "/objectifs-niveau-de-service" },
{ en: "/system-status", fr: "/etat-du-systeme" },
{
en: "/understanding-delivery-and-failure",
fr: "/comprendre-statut-de-livraison",
},
{
en: "/updating-contact-information",
fr: "/maintenir-a-jour-les-coordonnees",
},
{ en: "/using-a-spreadsheet", fr: "/utiliser-une-feuille-de-calcul" },
{ en: "/why-gc-notify", fr: "/pourquoi-notification-gc" },
{ en: "/new-features", fr: "/nouvelles-fonctionnalites" },
];

describe(`GCA a11y tests [${config.CONFIG_NAME}]`, () => {
for (const lang of langs) {
const currentLang = (lang === 'en' ? 'English' : 'Francais');
context(currentLang, () => {
for (const page of fullPageList) {
it(`${page[lang]}`, () => {
cy.a11yScan(page[lang]);
});
}
for (const lang of langs) {
const currentLang = lang === "en" ? "English" : "Francais";
context(currentLang, () => {
for (const page of fullPageList) {
it(`${page[lang]}`, () => {
cy.a11yScan(page[lang]);
});
}
}
});
}
});

describe('Language toggle works on all pages', () => {
for (const page of fullPageList) {
it(`${page.en}`, () => {
cy.visit(page.en);
cy.get('#header-lang').click();
cy.url().should('contain', page.fr);
describe("Language toggle works on all pages", () => {
for (const page of fullPageList) {
it(`${page.en}`, () => {
cy.visit(page.en);
cy.get("#header-lang").click();
cy.url().should("contain", page.fr);

cy.get('#header-lang').click();
cy.url().should('contain', page.en);
});
}
cy.get("#header-lang").click();
cy.url().should("contain", page.en);
});
}
});
6 changes: 3 additions & 3 deletions tests_cypress/cypress/e2e/admin/all.cy.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// import './gca_pages.cy';
import './login.cy';
import './register.cy';
import './qualtrics.cy';
import "./login.cy";
import "./register.cy";
import "./qualtrics.cy";
2 changes: 2 additions & 0 deletions tests_cypress/cypress/e2e/admin/ci.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import "./a11y/app_pages.cy";
import "./sign_out/sign_out.cy";
67 changes: 33 additions & 34 deletions tests_cypress/cypress/e2e/admin/login.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,36 @@
import config from "../../../config";
import { LoginPage } from "../../Notify/Admin/Pages/all";

describe('Basic login', () => {

// Login to notify before the test suite starts
before(() => {
LoginPage.Login(Cypress.env('NOTIFY_USER'), Cypress.env('NOTIFY_PASSWORD'));

// ensure we logged in correctly
cy.contains('h1', 'Sign-in history').should('be.visible');
});

// Before each test, persist the auth cookie so we don't have to login again
beforeEach(() => {
// stop the recurring dashboard fetch requests
cy.intercept('GET', '**/dashboard.json', {});
});

// Clear cookies for the next suite of tests
after(() => {
cy.clearCookie('notify_admin_session');
});

it('succeeds and ADMIN displays accounts page', () => {
cy.visit("/accounts");

cy.injectAxe();
cy.checkA11y();
cy.contains('h1', 'Your services').should('be.visible');
});

it('displays notify service page', () => {
cy.visit(`/services/${config.Services.Notify}`);
cy.contains('h1', 'Dashboard').should('be.visible');
});
});
describe("Basic login", () => {
// Login to notify before the test suite starts
before(() => {
LoginPage.Login(Cypress.env("NOTIFY_USER"), Cypress.env("NOTIFY_PASSWORD"));

// ensure we logged in correctly
cy.contains("h1", "Sign-in history").should("be.visible");
});

// Before each test, persist the auth cookie so we don't have to login again
beforeEach(() => {
// stop the recurring dashboard fetch requests
cy.intercept("GET", "**/dashboard.json", {});
});

// Clear cookies for the next suite of tests
after(() => {
cy.clearCookie("notify_admin_session");
});

it("succeeds and ADMIN displays accounts page", () => {
cy.visit("/accounts");

cy.injectAxe();
cy.checkA11y();
cy.contains("h1", "Your services").should("be.visible");
});

it("displays notify service page", () => {
cy.visit(`/services/${config.Services.Notify}`);
cy.contains("h1", "Dashboard").should("be.visible");
});
});
Loading

0 comments on commit 399be08

Please sign in to comment.