Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Experiment/create ephemeral UI test accts #1898

Open
wants to merge 46 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
225d696
fix: simplify email address names to avoid issues with IMAP
andrewleith Jul 22, 2024
c3eb799
fix: modify Login method to accept email alias to check for when conn…
andrewleith Jul 22, 2024
be37e0b
fix: new accounts go to /services page since they only belong to one …
andrewleith Jul 22, 2024
7971d88
feat: new plugin to generate a random email alias, then call an endpo…
andrewleith Jul 22, 2024
2f4ade7
fix: update cypress config to expose the create-account plugin, and s…
andrewleith Jul 22, 2024
7dc450d
feat: update the login command to get the ephemeral email account bef…
andrewleith Jul 22, 2024
706be29
feat(create-account): update create account task and pass notify test…
andrewleith Sep 13, 2024
d7e7f81
fix(tou_test): success can either be the /accounts page or a /service…
andrewleith Sep 13, 2024
db9a550
chore(email-account): refactor and clean up code a bit; ensure connec…
andrewleith Sep 13, 2024
fb5bd26
feat(config): simplify config
andrewleith Sep 19, 2024
1d3bd62
fix up ids
andrewleith Sep 19, 2024
f199ad4
chore(refactor): refactor login command; add login command for platfo…
andrewleith Sep 20, 2024
c987242
task(cypress config): add back SMS template ID
andrewleith Sep 20, 2024
ac9019a
fix(tou_prompt test): add assertion to ensure success of agreeing to …
andrewleith Sep 20, 2024
b79f8a0
fix(create-account): simplify call to api; remove posting of the pass…
andrewleith Sep 20, 2024
77c143a
chore(email-account): remove debug logging
andrewleith Sep 20, 2024
624da0b
Merge branch 'main' into experiment/create-ephemeral-ui-test-accts
andrewleith Sep 20, 2024
36bfe45
fix: add template category to the test that will be empty for email
andrewleith Sep 23, 2024
213e7e4
fix(create-account): remove pw prop
andrewleith Sep 23, 2024
862a203
Merge branch 'main' into experiment/create-ephemeral-ui-test-accts
andrewleith Sep 27, 2024
689222b
chore: remove debug log
andrewleith Sep 27, 2024
b3082b5
fix: dont try to delete emails when there is none
andrewleith Sep 27, 2024
8e06612
fix: update calls to login across tests
andrewleith Sep 27, 2024
9a7d00d
chore: update test and get values from config
andrewleith Sep 27, 2024
e871344
Merge branch 'main' into experiment/create-ephemeral-ui-test-accts
andrewleith Oct 4, 2024
6978d52
chore: add README, extra npm script
andrewleith Oct 4, 2024
9c64b3b
chore: formatting
andrewleith Oct 4, 2024
b45c710
Merge branch 'main' into experiment/create-ephemeral-ui-test-accts
andrewleith Nov 8, 2024
63a1b92
fix(cypress): update tests to use updated, simplified `cy.login()` co…
andrewleith Nov 8, 2024
d3f2d37
chore: formatting
andrewleith Nov 8, 2024
becd2ab
chore: update config to use staging
andrewleith Nov 8, 2024
7388a22
Merge branch 'main' into experiment/create-ephemeral-ui-test-accts
andrewleith Nov 15, 2024
bbe2bdb
fix(remaining_messages_summary test): add assert to ensure test waits…
andrewleith Nov 15, 2024
c314ea8
chore: remove debug code
andrewleith Nov 15, 2024
0183f84
fix(template_filters test): make sure the scenario ends in no results
andrewleith Nov 15, 2024
213c122
fix(cypress login): use cypress auth to get new user
andrewleith Nov 15, 2024
b2e0597
Merge branch 'experiment/create-ephemeral-ui-test-accts' of https://g…
andrewleith Nov 15, 2024
47a192b
fix failing tests
andrewleith Nov 15, 2024
17a806d
Merge branch 'experiment/create-ephemeral-ui-test-accts' of https://g…
andrewleith Nov 15, 2024
1548f49
fix(cypress config): add back retries
andrewleith Nov 15, 2024
5f53f67
please [review] me
andrewleith Nov 15, 2024
2cec1b1
Merge branch 'experiment/create-ephemeral-ui-test-accts' of https://g…
andrewleith Nov 15, 2024
62a2536
fix: change secret name for new user password so this wont conflict w…
andrewleith Nov 15, 2024
c10d268
chore: README updates
andrewleith Nov 15, 2024
413a870
chore: remove unused import
andrewleith Nov 15, 2024
5aaa300
chore: removed comments
andrewleith Nov 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 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,8 +29,8 @@ module.exports = defineConfig({
return null
},
// Email Account ///
getLastEmail() {
return emailAccount.getLastEmail()
getLastEmail(emailAddress) {
return emailAccount.getLastEmail(emailAddress)
},
deleteAllEmails() {
return emailAccount.deleteAllEmails()
Expand All @@ -40,6 +41,18 @@ module.exports = defineConfig({
createEmailAccount() {
return emailAccount.createEmailAccount();
},
createAccount({ baseUrl, username, secret }) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The result of this call is "cached" in the global object here, which means only one set of test users is generated for every test run or every time you launch the cypress UI. To get a new user, just quit cypress and launch it again.

if (global.acct) {
return global.acct;
} else {
let acct = CreateAccount(baseUrl, username, secret);
global.acct = acct;
return acct
}
},
getUserName() {
return global.stuff;
}
});

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
2 changes: 1 addition & 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,7 @@ let Actions = {
AgreeToTerms: () => {
TouPrompt.Components.Terms().scrollTo('bottom', { ensureScrollable: false });
Components.DismissButton().click();
cy.url().should('include', '/accounts');
cy.url().should('include', '/services');
},
};

Expand Down
18 changes: 17 additions & 1 deletion tests_cypress/cypress/Notify/NotifyAPI.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
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 Expand Up @@ -75,6 +75,22 @@
}
})
},
CreateUITestUser: () => {
var token = Utilities.CreateJWT();
Fixed Show fixed Hide fixed
// generate random 10 char string
var username = Utilities.GenerateID(10);
return cy.request({
failOnStatusCode: false,
url: `${BASE_URL}/cypress/create_user/${username}`,
method: 'GET',
// headers: {
// Authorization: `Bearer ${token}`,
// "Content-Type": 'application/json'
// },
}).then((resp) => {
cy.wrap(resp.body.email_address).as('username');
});
},
}
// const Admin = {
// CreateService: () => {
Expand Down
72 changes: 72 additions & 0 deletions tests_cypress/cypress/plugins/create-account.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
const http = require('http');
const https = require('https');

// TODO: This duplicates some code in Notify/NotifyAPI.js and should be consolidated
const Utilities = {
CreateJWT: (username, secret) => {
const jwt = require('jsrsasign');
const claims = {
'iss': username,
'iat': Math.round(Date.now() / 1000)
}

const headers = { alg: "HS256", typ: "JWT" };
return jwt.jws.JWS.sign("HS256", JSON.stringify(headers), JSON.stringify(claims), secret);
},
GenerateID: (length = 10) => {
const characters = '0123456789abcdefghijklmnopqrstuvwxyz';
let result = '';
const charactersLength = characters.length;
for (let i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}
};

const createAccount = async (baseUrl, username, secret) => {
// return a generated id
const token = Utilities.CreateJWT(username, secret);
const generatedUsername = Utilities.GenerateID(10);
const url = `${baseUrl}/cypress/create_user/${generatedUsername}`;
console.log('generatedUsername', generatedUsername);

return new Promise((resolve, reject) => {
const options = {
method: 'GET', // or 'POST', depending on your API
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": 'application/json'
}
};

const getHttpModule = (url) => url.startsWith('https://') ? https : http;

const req = getHttpModule(url).request(url, options, (res) => {
let data = '';

res.on('data', (chunk) => {
data += chunk;
});

res.on('end', () => {
try {
const parsedData = JSON.parse(data);
resolve(parsedData);
} catch (e) {
reject(e);
}
});
});

req.on('error', (error) => {
reject(error); // Reject the promise on request error
});

req.end();
});

};


module.exports = createAccount;
58 changes: 37 additions & 21 deletions tests_cypress/cypress/plugins/email-account.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,42 +75,58 @@ const emailAccount = async () => {
* Utility method for getting the last email
* for the Ethereal email account
*/
async getLastEmail() {
async getLastEmail(emailAddress) {
// makes debugging very simple
// console.log('Getting the last email')
console.log('Getting the last email', emailAddress)

try {
const connection = await imaps.connect(emailConfig)

// grab up to 50 emails from the inbox
await connection.openBox('INBOX')
const searchCriteria = ['1:50', 'UNDELETED']
const searchCriteria = ['UNSEEN'];
const fetchOptions = {
bodies: [''],
}
struct: true,
};
const messages = await connection.search(searchCriteria, fetchOptions)
// and close the connection to avoid it hanging
connection.end()

// connection.end();
if (!messages.length) {
// console.log('Cannot find any emails')
console.log('Cannot find any emails')
return null
} else {
// console.log('There are %d messages', messages.length)
// grab the last email
const mail = await simpleParser(
messages[messages.length - 1].parts[0].body,
)
// console.log(mail.subject)
// console.log(mail.text)
let latestMail = null;
let uidsToDelete = [];
for (const message of messages) {

const mail = await simpleParser(message.parts[0].body);
const to_address = mail.to.value[0].address;
console.log('to_address', to_address)
console.log('email', emailAddress);
console.log('---')
if (to_address == emailAddress) {
console.log('mafch found')
uidsToDelete.push(message.attributes.uid);
latestMail = {
subject: mail.subject,
text: mail.text,
html: mail.html,
}
}
}

console.log('deleting', uidsToDelete);
try {
await connection.deleteMessage(uidsToDelete);
await connection.imap.expunge();
}
catch (e) {
console.error('delete error', e)
}

connection.end()

// and returns the main fields
return {
subject: mail.subject,
text: mail.text,
html: mail.html,
}
return latestMail;
}
} catch (e) {
// and close the connection to avoid it hanging
Expand Down
9 changes: 6 additions & 3 deletions tests_cypress/cypress/support/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import config from "../../config";

import LoginPage from "../Notify/Admin/Pages/LoginPage";
import { Admin } from "../Notify/NotifyAPI";
Fixed Show fixed Hide fixed

// keep track of what we test so we dont test the same thing twice
let links_checked = [];
Expand Down Expand Up @@ -97,8 +98,10 @@
return cy.get(`[data-testid=${selector}]`, ...args)
});

Cypress.Commands.add('login', (username, password, agreeToTerms = true) => {
cy.session([username, password, agreeToTerms], () => {
LoginPage.Login(username, password, agreeToTerms);
Cypress.Commands.add('login', (un, password, agreeToTerms = true) => {
cy.task('createAccount', { baseUrl: config.Hostnames.API, username: Cypress.env('ADMIN_USERNAME'), secret: Cypress.env('ADMIN_SECRET') }).then((acct) => {
cy.session([acct.email_address, password, agreeToTerms], () => {
LoginPage.Login(acct.email_address, password, agreeToTerms);
});
});
});
Loading