mirror of
https://github.com/lukevella/rallly.git
synced 2025-08-03 00:19:03 +02:00
⬆️ v3.0.0 (#704)
This commit is contained in:
parent
735056f25f
commit
c22b3abc4d
385 changed files with 19912 additions and 5250 deletions
|
@ -42,7 +42,9 @@ test.describe.serial(() => {
|
|||
await page.goto("/login");
|
||||
|
||||
// your login page test logic
|
||||
await page.getByPlaceholder("jessie.smith@example.com").type(testUserEmail);
|
||||
await page
|
||||
.getByPlaceholder("jessie.smith@example.com")
|
||||
.type(testUserEmail);
|
||||
|
||||
await page.getByText("Continue").click();
|
||||
|
||||
|
@ -58,7 +60,9 @@ test.describe.serial(() => {
|
|||
await page.getByText("Create an account").waitFor();
|
||||
|
||||
await page.getByPlaceholder("Jessie Smith").type("Test User");
|
||||
await page.getByPlaceholder("jessie.smith@example.com").type(testUserEmail);
|
||||
await page
|
||||
.getByPlaceholder("jessie.smith@example.com")
|
||||
.type(testUserEmail);
|
||||
|
||||
await page.click("text=Continue");
|
||||
|
||||
|
@ -72,7 +76,7 @@ test.describe.serial(() => {
|
|||
|
||||
await page.getByText("Continue").click();
|
||||
|
||||
await expect(page.getByText("Your details")).toBeVisible();
|
||||
await expect(page.getByText("No polls")).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -83,7 +87,9 @@ test.describe.serial(() => {
|
|||
await page.getByText("Create an account").waitFor();
|
||||
|
||||
await page.getByPlaceholder("Jessie Smith").type("Test User");
|
||||
await page.getByPlaceholder("jessie.smith@example.com").type(testUserEmail);
|
||||
await page
|
||||
.getByPlaceholder("jessie.smith@example.com")
|
||||
.type(testUserEmail);
|
||||
|
||||
await page.click("text=Continue");
|
||||
|
||||
|
@ -101,7 +107,9 @@ test.describe.serial(() => {
|
|||
test("can login with magic link", async ({ page }) => {
|
||||
await page.goto("/login");
|
||||
|
||||
await page.getByPlaceholder("jessie.smith@example.com").type(testUserEmail);
|
||||
await page
|
||||
.getByPlaceholder("jessie.smith@example.com")
|
||||
.type(testUserEmail);
|
||||
|
||||
await page.getByText("Continue").click();
|
||||
|
||||
|
@ -121,13 +129,15 @@ test.describe.serial(() => {
|
|||
|
||||
page.getByText("Click here").click();
|
||||
|
||||
await expect(page.getByText("Your details")).toBeVisible();
|
||||
await expect(page.getByText("No polls")).toBeVisible();
|
||||
});
|
||||
|
||||
test("can login with verification code", async ({ page }) => {
|
||||
await page.goto("/login");
|
||||
|
||||
await page.getByPlaceholder("jessie.smith@example.com").type(testUserEmail);
|
||||
await page
|
||||
.getByPlaceholder("jessie.smith@example.com")
|
||||
.type(testUserEmail);
|
||||
|
||||
await page.getByText("Continue").click();
|
||||
|
||||
|
@ -137,7 +147,7 @@ test.describe.serial(() => {
|
|||
|
||||
await page.getByText("Continue").click();
|
||||
|
||||
await expect(page.getByText("Your details")).toBeVisible();
|
||||
await expect(page.getByText("No polls")).toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
import { expect, Page, test } from "@playwright/test";
|
||||
import smtpTester, { SmtpTester } from "smtp-tester";
|
||||
import { NewPollPage } from "tests/new-poll-page";
|
||||
|
||||
test.describe.serial(() => {
|
||||
let pollUrl: string;
|
||||
let page: Page;
|
||||
|
||||
let mailServer: SmtpTester;
|
||||
test.beforeAll(async () => {
|
||||
test.beforeAll(async ({ browser }) => {
|
||||
page = await browser.newPage();
|
||||
mailServer = smtpTester.init(4025);
|
||||
});
|
||||
|
||||
|
@ -13,79 +15,32 @@ test.describe.serial(() => {
|
|||
mailServer.stop();
|
||||
});
|
||||
|
||||
test("create a new poll", async ({ page }) => {
|
||||
await page.goto("/new");
|
||||
await page.type('[placeholder="Monthly Meetup"]', "Monthly Meetup");
|
||||
// click on label to focus on input
|
||||
await page.click('text="Location"');
|
||||
await page.keyboard.type("Joe's Coffee Shop");
|
||||
test("create a new poll", async () => {
|
||||
const newPollPage = new NewPollPage(page);
|
||||
|
||||
await page.click('text="Description"');
|
||||
await newPollPage.goto();
|
||||
await newPollPage.createPollAndCloseDialog();
|
||||
|
||||
await page.keyboard.type("This is a test description");
|
||||
|
||||
await page.click('text="Continue"');
|
||||
|
||||
await page.click('[title="Next month"]');
|
||||
|
||||
// Select a few days
|
||||
await page.click("text=/^5$/");
|
||||
await page.click("text=/^7$/");
|
||||
await page.click("text=/^10$/");
|
||||
await page.click("text=/^15$/");
|
||||
|
||||
await page.click('text="Continue"');
|
||||
|
||||
await page.type('[placeholder="Jessie Smith"]', "John");
|
||||
await page.type(
|
||||
'[placeholder="jessie.smith@example.com"]',
|
||||
"john.doe@example.com",
|
||||
);
|
||||
|
||||
await page.click('text="Create poll"');
|
||||
|
||||
const title = page.getByTestId("poll-title");
|
||||
|
||||
await title.waitFor();
|
||||
|
||||
await expect(title).toHaveText("Monthly Meetup");
|
||||
await expect(page.getByTestId("poll-title")).toHaveText("Monthly Meetup");
|
||||
|
||||
const { email } = await mailServer.captureOne("john.doe@example.com", {
|
||||
wait: 5000,
|
||||
});
|
||||
|
||||
expect(email.headers.subject).toBe("Let's find a date for Monthly Meetup");
|
||||
|
||||
pollUrl = page.url();
|
||||
});
|
||||
|
||||
test("notifications", async ({ page }) => {
|
||||
await page.goto(pollUrl);
|
||||
await page.getByTestId("notifications-toggle").click();
|
||||
|
||||
expect(page.getByTestId("login-modal")).toBeVisible();
|
||||
});
|
||||
|
||||
// delete the poll we just created
|
||||
test("delete existing poll", async ({ page }) => {
|
||||
await page.goto(pollUrl);
|
||||
test("delete existing poll", async () => {
|
||||
const manageButton = page.getByText("Manage");
|
||||
await manageButton.waitFor();
|
||||
await manageButton.click();
|
||||
await page.click("text=Delete poll");
|
||||
|
||||
const deletePollForm = page.locator("data-testid=delete-poll-form");
|
||||
const deletePollDialog = page.getByRole("dialog");
|
||||
|
||||
// button should be disabled
|
||||
await expect(deletePollForm.locator("text=Delete poll")).toBeDisabled();
|
||||
deletePollDialog.getByRole("button", { name: "delete" }).click();
|
||||
|
||||
// enter confirmation text
|
||||
await page.type("[placeholder=delete-me]", "delete-me");
|
||||
|
||||
// button should now be enabled
|
||||
await deletePollForm.locator("text=Delete poll").click();
|
||||
|
||||
// expect delete message to appear
|
||||
await expect(page.locator("text=Deleted poll")).toBeVisible();
|
||||
await page.waitForURL("/polls");
|
||||
});
|
||||
});
|
||||
|
|
9
apps/web/tests/edit-options-page.ts
Normal file
9
apps/web/tests/edit-options-page.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
import { Page } from "@playwright/test";
|
||||
|
||||
export class EditOptionsPage {
|
||||
constructor(public readonly page: Page) {}
|
||||
|
||||
async switchToSpecifyTimes() {
|
||||
await this.page.click("[data-testid='specify-times-switch']");
|
||||
}
|
||||
}
|
|
@ -1,19 +1,33 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
import { expect, Page, test } from "@playwright/test";
|
||||
import smtpTester, { SmtpTester } from "smtp-tester";
|
||||
import { EditOptionsPage } from "tests/edit-options-page";
|
||||
import { NewPollPage } from "tests/new-poll-page";
|
||||
|
||||
test.describe("edit options", () => {
|
||||
test("should show warning when deleting options with votes in them", async ({
|
||||
page,
|
||||
}) => {
|
||||
await page.goto("/demo");
|
||||
let page: Page;
|
||||
let editOptionsPage: EditOptionsPage;
|
||||
let mailServer: SmtpTester;
|
||||
|
||||
await expect(page.locator('text="Lunch Meeting"')).toBeVisible();
|
||||
test.beforeAll(async ({ browser }) => {
|
||||
page = await browser.newPage();
|
||||
mailServer = smtpTester.init(4025);
|
||||
const newPollPage = new NewPollPage(page);
|
||||
await newPollPage.goto();
|
||||
const pollPage = await newPollPage.createPollAndCloseDialog();
|
||||
await pollPage.addParticipant("Mark");
|
||||
editOptionsPage = await pollPage.editOptions();
|
||||
});
|
||||
|
||||
test.afterAll(async () => {
|
||||
mailServer.stop();
|
||||
});
|
||||
|
||||
test("should show warning when deleting options with votes in them", async () => {
|
||||
editOptionsPage.switchToSpecifyTimes();
|
||||
|
||||
await page.click("text='Manage'");
|
||||
await page.click("text='Edit options'");
|
||||
await page.click("[data-testid='specify-times-switch']");
|
||||
await page.click("text='12:00 PM'");
|
||||
await page.click("text='1:00 PM'");
|
||||
await page.locator("div[role='dialog']").locator("text='Save'").click();
|
||||
await page.getByRole("button", { name: "Save" }).click();
|
||||
await expect(page.locator('text="Are you sure?"')).toBeVisible();
|
||||
await page.click("text='Delete'");
|
||||
});
|
||||
|
|
|
@ -4,12 +4,12 @@ test("should show correct language if supported", async ({ browser }) => {
|
|||
const context = await browser.newContext({ locale: "de" });
|
||||
const page = await context.newPage();
|
||||
await page.goto("/");
|
||||
await expect(page.locator("text=Los geht's")).toBeVisible();
|
||||
await expect(page.locator("text=Neue Umfrage")).toBeVisible();
|
||||
});
|
||||
|
||||
test("should default to english", async ({ browser }) => {
|
||||
const context = await browser.newContext({ locale: "mt" });
|
||||
const page = await context.newPage();
|
||||
await page.goto("/new");
|
||||
await expect(page.locator("h1", { hasText: "Create new" })).toBeVisible();
|
||||
await expect(page.locator("text=New Poll")).toBeVisible();
|
||||
});
|
||||
|
|
20
apps/web/tests/invite-page.ts
Normal file
20
apps/web/tests/invite-page.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
import { Page } from "@playwright/test";
|
||||
|
||||
export class InvitePage {
|
||||
constructor(public readonly page: Page) {}
|
||||
|
||||
async addParticipant(name: string, email?: string) {
|
||||
const page = this.page;
|
||||
|
||||
await page.locator("data-testid=vote-selector >> nth=0").click();
|
||||
await page.locator("data-testid=vote-selector >> nth=2").click();
|
||||
await page.click("button >> text='Continue'");
|
||||
|
||||
await page.type('[placeholder="Jessie Smith"]', name);
|
||||
if (email) {
|
||||
await page.type('[placeholder="jessie.smith@example.com"]', email);
|
||||
}
|
||||
|
||||
await page.click("text='Submit'");
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
|
||||
test("should be able to vote and comment on a poll", async ({ page }) => {
|
||||
test.skip("should be able to vote and comment on a poll", async ({ page }) => {
|
||||
await page.setViewportSize({ width: 375, height: 667 });
|
||||
await page.goto("/demo");
|
||||
|
||||
|
|
130
apps/web/tests/mocks.ts
Normal file
130
apps/web/tests/mocks.ts
Normal file
|
@ -0,0 +1,130 @@
|
|||
import { prisma, VoteType } from "@rallly/database";
|
||||
import dayjs from "dayjs";
|
||||
import { nanoid } from "nanoid";
|
||||
|
||||
const participantData: Array<{ name: string; votes: VoteType[] }> = [
|
||||
{
|
||||
name: "Reed",
|
||||
votes: ["yes", "no", "yes", "no"],
|
||||
},
|
||||
{
|
||||
name: "Susan",
|
||||
votes: ["yes", "yes", "yes", "no"],
|
||||
},
|
||||
{
|
||||
name: "Johnny",
|
||||
votes: ["no", "no", "yes", "yes"],
|
||||
},
|
||||
{
|
||||
name: "Ben",
|
||||
votes: ["yes", "yes", "yes", "yes"],
|
||||
},
|
||||
];
|
||||
|
||||
const optionValues = ["2022-12-14", "2022-12-15", "2022-12-16", "2022-12-17"];
|
||||
|
||||
export const createPoll = async () => {
|
||||
const pollId = nanoid();
|
||||
|
||||
const adminUrlId = nanoid();
|
||||
|
||||
const options: Array<{ start: Date; id: string }> = [];
|
||||
|
||||
for (let i = 0; i < optionValues.length; i++) {
|
||||
options.push({ id: nanoid(), start: new Date(optionValues[i]) });
|
||||
}
|
||||
|
||||
const participants: Array<{
|
||||
name: string;
|
||||
id: string;
|
||||
userId: string;
|
||||
createdAt: Date;
|
||||
}> = [];
|
||||
|
||||
const votes: Array<{
|
||||
optionId: string;
|
||||
participantId: string;
|
||||
type: VoteType;
|
||||
}> = [];
|
||||
|
||||
for (let i = 0; i < participantData.length; i++) {
|
||||
const { name, votes: participantVotes } = participantData[i];
|
||||
const participantId = nanoid();
|
||||
participants.push({
|
||||
id: participantId,
|
||||
name,
|
||||
userId: "user-demo",
|
||||
createdAt: dayjs()
|
||||
.add(i * -1, "minutes")
|
||||
.toDate(),
|
||||
});
|
||||
|
||||
options.forEach((option, index) => {
|
||||
votes.push({
|
||||
optionId: option.id,
|
||||
participantId,
|
||||
type: participantVotes[index],
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
await prisma.poll.create({
|
||||
data: {
|
||||
id: pollId,
|
||||
title: "Lunch Meeting",
|
||||
location: "Starbucks, 901 New York Avenue",
|
||||
description: `Hey everyone, please choose the dates when you are available to meet for our monthly get together. Looking forward to see you all!`,
|
||||
demo: true,
|
||||
adminUrlId,
|
||||
participantUrlId: nanoid(),
|
||||
userId: "guest-user",
|
||||
options: {
|
||||
createMany: {
|
||||
data: options,
|
||||
},
|
||||
},
|
||||
participants: {
|
||||
createMany: {
|
||||
data: participants,
|
||||
},
|
||||
},
|
||||
votes: {
|
||||
createMany: {
|
||||
data: votes,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return pollId;
|
||||
};
|
||||
|
||||
export const deletePoll = async (pollId: string) => {
|
||||
await prisma.$transaction([
|
||||
prisma.vote.deleteMany({
|
||||
where: {
|
||||
pollId,
|
||||
},
|
||||
}),
|
||||
prisma.option.deleteMany({
|
||||
where: {
|
||||
pollId,
|
||||
},
|
||||
}),
|
||||
prisma.participant.deleteMany({
|
||||
where: {
|
||||
pollId,
|
||||
},
|
||||
}),
|
||||
prisma.comment.deleteMany({
|
||||
where: {
|
||||
pollId,
|
||||
},
|
||||
}),
|
||||
prisma.poll.deleteMany({
|
||||
where: {
|
||||
id: pollId,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
};
|
50
apps/web/tests/new-poll-page.ts
Normal file
50
apps/web/tests/new-poll-page.ts
Normal file
|
@ -0,0 +1,50 @@
|
|||
import { Page } from "@playwright/test";
|
||||
import { PollPage } from "tests/poll-page";
|
||||
|
||||
export class NewPollPage {
|
||||
constructor(public readonly page: Page) {}
|
||||
|
||||
async goto() {
|
||||
await this.page.goto("/new");
|
||||
}
|
||||
|
||||
async createPollAndCloseDialog() {
|
||||
const pollPage = await this.createPoll();
|
||||
await pollPage.closeDialog();
|
||||
return pollPage;
|
||||
}
|
||||
async createPoll() {
|
||||
const page = this.page;
|
||||
|
||||
await page.type('[placeholder="Monthly Meetup"]', "Monthly Meetup");
|
||||
// click on label to focus on input
|
||||
await page.click('text="Location"');
|
||||
await page.keyboard.type("Joe's Coffee Shop");
|
||||
|
||||
await page.click('text="Description"');
|
||||
|
||||
await page.keyboard.type("This is a test description");
|
||||
|
||||
await page.click('text="Continue"');
|
||||
|
||||
await page.click('[title="Next month"]');
|
||||
|
||||
// Select a few days
|
||||
await page.click("text=/^5$/");
|
||||
await page.click("text=/^7$/");
|
||||
await page.click("text=/^10$/");
|
||||
await page.click("text=/^15$/");
|
||||
|
||||
await page.click('text="Continue"');
|
||||
|
||||
await page.type('[placeholder="Jessie Smith"]', "John");
|
||||
await page.type(
|
||||
'[placeholder="jessie.smith@example.com"]',
|
||||
"john.doe@example.com",
|
||||
);
|
||||
|
||||
await page.click('text="Create poll"');
|
||||
|
||||
return new PollPage(page);
|
||||
}
|
||||
}
|
89
apps/web/tests/poll-page.ts
Normal file
89
apps/web/tests/poll-page.ts
Normal file
|
@ -0,0 +1,89 @@
|
|||
import { Page } from "@playwright/test";
|
||||
import { EditOptionsPage } from "tests/edit-options-page";
|
||||
import { InvitePage } from "tests/invite-page";
|
||||
|
||||
export class PollPage {
|
||||
constructor(public readonly page: Page) {}
|
||||
|
||||
async closeDialog() {
|
||||
const page = this.page;
|
||||
|
||||
const dialog = page.getByRole("dialog");
|
||||
|
||||
await dialog.waitFor({ state: "visible" });
|
||||
|
||||
const closeDialogButton = dialog.getByRole("button", { name: "Close" });
|
||||
|
||||
await closeDialogButton.waitFor({ state: "visible" });
|
||||
|
||||
await closeDialogButton.click();
|
||||
}
|
||||
|
||||
async addComment() {
|
||||
const page = this.page;
|
||||
|
||||
await page.getByText("Leave a comment on this poll").click();
|
||||
await page
|
||||
.getByPlaceholder("Leave a comment on this poll")
|
||||
.fill("This is a comment!");
|
||||
await page.getByPlaceholder("Your name…").fill("Test user");
|
||||
|
||||
await page.getByRole("button", { name: "Add Comment" }).click();
|
||||
}
|
||||
|
||||
async openShareDialog() {
|
||||
const page = this.page;
|
||||
|
||||
await page.getByRole("button", { name: "Share" }).click();
|
||||
|
||||
return page.getByRole("dialog");
|
||||
}
|
||||
|
||||
async copyInviteLink() {
|
||||
this.openShareDialog();
|
||||
await this.page.getByRole("button", { name: "invite/" }).click();
|
||||
return (await this.page.evaluate(
|
||||
"navigator.clipboard.readText()",
|
||||
)) as string;
|
||||
}
|
||||
|
||||
async editOptions() {
|
||||
const page = this.page;
|
||||
|
||||
const pollUrl = page.url();
|
||||
await page.getByRole("button", { name: "Manage" }).click();
|
||||
|
||||
await page.getByRole("menuitem", { name: "Edit options" }).click();
|
||||
|
||||
await page.waitForURL(`${pollUrl}/edit-options`);
|
||||
|
||||
return new EditOptionsPage(page);
|
||||
}
|
||||
|
||||
async addParticipant(name: string, email?: string) {
|
||||
const page = this.page;
|
||||
await page.getByTestId("add-participant-button").click();
|
||||
|
||||
await page.locator("data-testid=vote-selector >> nth=0").click();
|
||||
await page.locator("data-testid=vote-selector >> nth=2").click();
|
||||
await page.click("button >> text='Continue'");
|
||||
|
||||
await page.type('[placeholder="Jessie Smith"]', name);
|
||||
if (email) {
|
||||
await page.type('[placeholder="jessie.smith@example.com"]', email);
|
||||
}
|
||||
|
||||
await page.click("text='Submit'");
|
||||
}
|
||||
|
||||
async gotoInvitePage() {
|
||||
const page = this.page;
|
||||
|
||||
const inviteLink = await this.copyInviteLink();
|
||||
|
||||
await page.goto(inviteLink);
|
||||
|
||||
await page.waitForURL(inviteLink);
|
||||
return new InvitePage(page);
|
||||
}
|
||||
}
|
|
@ -1,33 +1,32 @@
|
|||
import { expect, Page, Request, test } from "@playwright/test";
|
||||
import { load } from "cheerio";
|
||||
import smtpTester, { SmtpTester } from "smtp-tester";
|
||||
import { PollPage } from "tests/poll-page";
|
||||
|
||||
test.describe.parallel(() => {
|
||||
let adminPage: Page;
|
||||
import { NewPollPage } from "./new-poll-page";
|
||||
|
||||
test.describe(() => {
|
||||
let page: Page;
|
||||
let pollPage: PollPage;
|
||||
let touchRequest: Promise<Request>;
|
||||
let participantUrl: string;
|
||||
let editSubmissionUrl: string;
|
||||
|
||||
let mailServer: SmtpTester;
|
||||
test.beforeAll(async () => {
|
||||
mailServer = smtpTester.init(4025);
|
||||
});
|
||||
|
||||
test.afterAll(async () => {
|
||||
mailServer.stop();
|
||||
});
|
||||
|
||||
test.beforeAll(async ({ browser }) => {
|
||||
const context = await browser.newContext();
|
||||
adminPage = await context.newPage();
|
||||
touchRequest = adminPage.waitForRequest(
|
||||
mailServer = smtpTester.init(4025);
|
||||
page = await browser.newPage();
|
||||
touchRequest = page.waitForRequest(
|
||||
(request) =>
|
||||
request.method() === "POST" &&
|
||||
request.url().includes("/api/trpc/polls.touch"),
|
||||
);
|
||||
await adminPage.goto("/demo");
|
||||
await adminPage.waitForSelector('text="Lunch Meeting"');
|
||||
const newPollPage = new NewPollPage(page);
|
||||
await newPollPage.goto();
|
||||
pollPage = await newPollPage.createPollAndCloseDialog();
|
||||
});
|
||||
|
||||
test.afterAll(async () => {
|
||||
mailServer.stop();
|
||||
});
|
||||
|
||||
test("should call touch endpoint", async () => {
|
||||
|
@ -36,48 +35,31 @@ test.describe.parallel(() => {
|
|||
});
|
||||
|
||||
test("should be able to comment", async () => {
|
||||
await adminPage.getByPlaceholder("Your name…").fill("Test user");
|
||||
await adminPage
|
||||
.getByPlaceholder("Leave a comment on this poll")
|
||||
.fill("This is a comment!");
|
||||
await adminPage.click("text='Comment'");
|
||||
|
||||
const comment = adminPage.locator("data-testid=comment");
|
||||
await pollPage.addComment();
|
||||
const comment = page.locator("data-testid=comment");
|
||||
await expect(comment.locator("text='This is a comment!'")).toBeVisible();
|
||||
await expect(comment.locator("text=You")).toBeVisible();
|
||||
});
|
||||
|
||||
test("copy participant link", async () => {
|
||||
await adminPage.click("text='Share'");
|
||||
await adminPage.click("text='Copy link'");
|
||||
participantUrl = await adminPage.evaluate("navigator.clipboard.readText()");
|
||||
|
||||
expect(participantUrl).toMatch(/\/p\/[a-zA-Z0-9]+/);
|
||||
const inviteLink = await pollPage.copyInviteLink();
|
||||
await pollPage.closeDialog();
|
||||
expect(inviteLink).toMatch(/\/invite\/[a-zA-Z0-9]+/);
|
||||
});
|
||||
|
||||
test("should be able to vote with an email", async ({
|
||||
page: participantPage,
|
||||
}) => {
|
||||
await participantPage.goto(participantUrl);
|
||||
await participantPage.locator("data-testid=vote-selector >> nth=0").click();
|
||||
await participantPage.locator("data-testid=vote-selector >> nth=2").click();
|
||||
await participantPage.click("button >> text='Continue'");
|
||||
test("should be able to vote with an email", async () => {
|
||||
const invitePage = await pollPage.gotoInvitePage();
|
||||
|
||||
await participantPage.type('[placeholder="Jessie Smith"]', "Anne");
|
||||
await participantPage.type(
|
||||
'[placeholder="jessie.smith@example.com"]',
|
||||
"test@example.com",
|
||||
);
|
||||
await participantPage.click("text='Submit'");
|
||||
await invitePage.addParticipant("Anne", "test@example.com");
|
||||
|
||||
await expect(participantPage.locator("text='Anne'")).toBeVisible();
|
||||
await expect(page.locator("text='Anne'")).toBeVisible();
|
||||
|
||||
const { email } = await mailServer.captureOne("test@example.com", {
|
||||
wait: 5000,
|
||||
});
|
||||
|
||||
expect(email.headers.subject).toBe(
|
||||
"Thanks for responding to Lunch Meeting",
|
||||
"Thanks for responding to Monthly Meetup",
|
||||
);
|
||||
|
||||
const $ = load(email.html);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue