cy.signupViaApi, cy.fetchLatestConfirmToken (parses the mailpit inbox), cy.confirmViaApi, cy.loginViaApi, cy.logoutViaApi, plus composed seedConfirmedUser/seedAdmin/seedPostAs/seedFeaturedPost so each spec can build its own fixture without going through the UI for setup.
235 lines
5.7 KiB
TypeScript
235 lines
5.7 KiB
TypeScript
/// <reference types="cypress" />
|
|
|
|
interface MailpitAddress {
|
|
Address: string;
|
|
Name: string;
|
|
}
|
|
|
|
interface MailpitMessageSummary {
|
|
ID: string;
|
|
From: MailpitAddress;
|
|
To: MailpitAddress[];
|
|
Subject: string;
|
|
Snippet: string;
|
|
Created: string;
|
|
}
|
|
|
|
interface MailpitMessages {
|
|
total: number;
|
|
unread: number;
|
|
count: number;
|
|
messages: MailpitMessageSummary[];
|
|
}
|
|
|
|
interface MailpitMessageBody {
|
|
ID: string;
|
|
Text: string;
|
|
HTML: string;
|
|
}
|
|
|
|
interface SignupArgs {
|
|
email: string;
|
|
displayName: string;
|
|
}
|
|
|
|
interface ConfirmArgs {
|
|
token: string;
|
|
password: string;
|
|
}
|
|
|
|
interface LoginArgs {
|
|
email: string;
|
|
password: string;
|
|
}
|
|
|
|
interface SeedConfirmedUserArgs {
|
|
email: string;
|
|
displayName: string;
|
|
password: string;
|
|
}
|
|
|
|
type SeedAdminArgs = SeedConfirmedUserArgs;
|
|
|
|
interface SeedPostArgs {
|
|
email: string;
|
|
password: string;
|
|
title: string;
|
|
body: string;
|
|
}
|
|
|
|
interface CreatedPost {
|
|
id: number;
|
|
userId: number;
|
|
authorDisplayName: string;
|
|
title: string;
|
|
body: string;
|
|
createdAt: string;
|
|
featureSlot: number | null;
|
|
}
|
|
|
|
interface SeedFeaturedPostArgs {
|
|
adminEmail: string;
|
|
adminPassword: string;
|
|
postId: number;
|
|
slot: number;
|
|
}
|
|
|
|
declare global {
|
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
namespace Cypress {
|
|
interface Chainable {
|
|
resetDb(): Chainable<null>;
|
|
seedDb(): Chainable<null>;
|
|
promoteAdmin(email: string): Chainable<null>;
|
|
clearMail(): Chainable<null>;
|
|
getMail(): Chainable<MailpitMessages>;
|
|
getMailBody(id: string): Chainable<MailpitMessageBody>;
|
|
signupViaApi(args: SignupArgs): Chainable<void>;
|
|
fetchLatestConfirmToken(email: string): Chainable<string>;
|
|
confirmViaApi(args: ConfirmArgs): Chainable<void>;
|
|
loginViaApi(args: LoginArgs): Chainable<void>;
|
|
logoutViaApi(): Chainable<void>;
|
|
seedConfirmedUser(args: SeedConfirmedUserArgs): Chainable<void>;
|
|
seedAdmin(args: SeedAdminArgs): Chainable<void>;
|
|
seedPostAs(args: SeedPostArgs): Chainable<CreatedPost>;
|
|
seedFeaturedPost(args: SeedFeaturedPostArgs): Chainable<void>;
|
|
}
|
|
}
|
|
}
|
|
|
|
const apiBase = "/api";
|
|
|
|
Cypress.Commands.add("resetDb", function () {
|
|
return cy.task<null>("db:reset");
|
|
});
|
|
|
|
Cypress.Commands.add("seedDb", function () {
|
|
return cy.task<null>("db:seed");
|
|
});
|
|
|
|
Cypress.Commands.add("promoteAdmin", function (email: string) {
|
|
return cy.task<null>("db:promote", email);
|
|
});
|
|
|
|
Cypress.Commands.add("clearMail", function () {
|
|
return cy.task<null>("mailpit:clear");
|
|
});
|
|
|
|
Cypress.Commands.add("getMail", function () {
|
|
return cy.task<MailpitMessages>("mailpit:messages");
|
|
});
|
|
|
|
Cypress.Commands.add("getMailBody", function (id: string) {
|
|
return cy.task<MailpitMessageBody>("mailpit:message", id);
|
|
});
|
|
|
|
Cypress.Commands.add("signupViaApi", function (args: SignupArgs) {
|
|
cy.request({
|
|
method: "POST",
|
|
url: `${apiBase}/signup`,
|
|
body: { email: args.email, displayName: args.displayName },
|
|
}).then(function (response) {
|
|
expect(response.status).to.equal(201);
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add("fetchLatestConfirmToken", function (email: string) {
|
|
return cy.getMail().then(function (inbox) {
|
|
const match = inbox.messages.find(function (message) {
|
|
return message.To.some(function (to) {
|
|
return to.Address.toLowerCase() === email.toLowerCase();
|
|
});
|
|
});
|
|
if (!match) {
|
|
throw new Error(`no mailpit message for ${email}`);
|
|
}
|
|
return cy.getMailBody(match.ID).then(function (body) {
|
|
const text = body.Text || body.HTML;
|
|
const tokenMatch = text.match(/token=([a-f0-9]+)/);
|
|
if (!tokenMatch) {
|
|
throw new Error("confirmation token not found in mail body");
|
|
}
|
|
return tokenMatch[1];
|
|
});
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add("confirmViaApi", function (args: ConfirmArgs) {
|
|
cy.request({
|
|
method: "POST",
|
|
url: `${apiBase}/confirm-email`,
|
|
body: { token: args.token, password: args.password },
|
|
}).then(function (response) {
|
|
expect(response.status).to.equal(200);
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add("loginViaApi", function (args: LoginArgs) {
|
|
cy.request({
|
|
method: "POST",
|
|
url: `${apiBase}/login`,
|
|
body: { email: args.email, password: args.password },
|
|
}).then(function (response) {
|
|
expect(response.status).to.equal(200);
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add("logoutViaApi", function () {
|
|
cy.request({
|
|
method: "POST",
|
|
url: `${apiBase}/logout`,
|
|
failOnStatusCode: false,
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add(
|
|
"seedConfirmedUser",
|
|
function (args: SeedConfirmedUserArgs) {
|
|
cy.signupViaApi({ email: args.email, displayName: args.displayName });
|
|
cy.fetchLatestConfirmToken(args.email).then(function (token) {
|
|
cy.confirmViaApi({ token, password: args.password });
|
|
});
|
|
cy.logoutViaApi();
|
|
},
|
|
);
|
|
|
|
Cypress.Commands.add("seedAdmin", function (args: SeedAdminArgs) {
|
|
cy.seedConfirmedUser({
|
|
email: args.email,
|
|
displayName: args.displayName,
|
|
password: args.password,
|
|
});
|
|
cy.promoteAdmin(args.email);
|
|
});
|
|
|
|
Cypress.Commands.add("seedPostAs", function (args: SeedPostArgs) {
|
|
cy.loginViaApi({ email: args.email, password: args.password });
|
|
return cy
|
|
.request({
|
|
method: "POST",
|
|
url: `${apiBase}/posts`,
|
|
body: { title: args.title, body: args.body },
|
|
})
|
|
.then(function (response) {
|
|
expect(response.status).to.equal(201);
|
|
cy.logoutViaApi();
|
|
return response.body.post as CreatedPost;
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add(
|
|
"seedFeaturedPost",
|
|
function (args: SeedFeaturedPostArgs) {
|
|
cy.loginViaApi({ email: args.adminEmail, password: args.adminPassword });
|
|
cy.request({
|
|
method: "POST",
|
|
url: `${apiBase}/admin/posts/feature`,
|
|
body: { postId: args.postId, slot: args.slot },
|
|
}).then(function (response) {
|
|
expect(response.status).to.equal(200);
|
|
});
|
|
cy.logoutViaApi();
|
|
},
|
|
);
|
|
|
|
export {};
|