test: e2e for workflows (#9657)

* create test files

* add first e2e test

* finish first e2e test

* code clean up

* fix event type create button data-testid

* enable sandbox mode for non production environments

* comment out code for testing

* Revert "comment out code for testing"

This reverts commit 5553dacce2.

* clean up comments

* prettier

* use NEXT_PUBLIC_IS_E2E

* use todo fn

---------

Co-authored-by: CarinaWolli <wollencarina@gmail.com>
Co-authored-by: Alan <alannnc@gmail.com>
Co-authored-by: Keith Williams <keithwillcode@gmail.com>
Co-authored-by: Shivam Kalra <shivamkalra98@gmail.com>
pull/10297/head^2
Carina Wollendorfer 2023-07-21 11:36:39 -04:00 committed by GitHub
parent 337192697f
commit 1aa3077706
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 108 additions and 2 deletions

View File

@ -0,0 +1,76 @@
import { expect } from "@playwright/test";
import dayjs from "@calcom/dayjs";
import prisma from "@calcom/prisma";
import { WorkflowMethods } from "@calcom/prisma/enums";
import { test } from "./lib/fixtures";
import { selectFirstAvailableTimeSlotNextMonth, todo } from "./lib/testUtils";
test.afterEach(({ users }) => users.deleteAll());
test.describe("Workflow tests", () => {
test.describe("User Workflows", () => {
test("Create default reminder workflow & trigger when event type is booked", async ({ page, users }) => {
const user = await users.create();
const [eventType] = user.eventTypes;
await user.login();
await page.goto(`/workflows`);
await page.click('[data-testid="create-button"]');
// select first event type
await page.getByText("Select...").click();
await page.getByText(eventType.title, { exact: true }).click();
// name workflow
await page.fill('[data-testid="workflow-name"]', "Test workflow");
// save workflow
await page.click('[data-testid="save-workflow"]');
// check if workflow is saved
await expect(page.locator('[data-testid="workflow-list"] > li')).toHaveCount(1);
// book event type
await page.goto(`/${user.username}/${eventType.slug}`);
await selectFirstAvailableTimeSlotNextMonth(page);
await page.fill('[name="name"]', "Test");
await page.fill('[name="email"]', "test@example.com");
await page.press('[name="email"]', "Enter");
// Make sure booking is completed
await expect(page.locator("[data-testid=success-page]")).toBeVisible();
const booking = await prisma.booking.findFirst({
where: {
eventTypeId: eventType.id,
},
});
// check if workflow triggered
const workflowReminders = await prisma.workflowReminder.findMany({
where: {
bookingUid: booking?.uid ?? "",
},
});
expect(workflowReminders).toHaveLength(1);
const scheduledDate = dayjs(booking?.startTime).subtract(1, "day").toDate();
expect(workflowReminders[0].method).toBe(WorkflowMethods.EMAIL);
expect(workflowReminders[0].scheduledDate.toISOString()).toBe(scheduledDate.toISOString());
});
// add all other actions to this workflow and test if they triggered
// cancel booking and test if workflow reminders are deleted
// test all other triggers
});
test.describe("Team Workflows", () => {
todo("Admin can create and update team workflow");
todo("Members can not create and update team workflows");
});
});

View File

@ -32,6 +32,8 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
return;
}
const sandboxMode = process.env.NEXT_PUBLIC_IS_E2E ? true : false;
//delete batch_ids with already past scheduled date from scheduled_sends
const remindersToDelete = await prisma.workflowReminder.findMany({
where: {
@ -251,6 +253,11 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
batchId: batchId,
sendAt: dayjs(reminder.scheduledDate).unix(),
replyTo: reminder.booking.user?.email || senderEmail,
mailSettings: {
sandboxMode: {
enable: sandboxMode,
},
},
});
}

View File

@ -118,6 +118,7 @@ export default function WorkflowDetailsPage(props: Props) {
<div className="pl-2 pr-3 md:sticky md:top-6 md:h-0 md:pl-0">
<div className="mb-5">
<TextField
data-testid="workflow-name"
disabled={props.readOnly}
label={`${t("workflow_name")}:`}
type="text"

View File

@ -65,7 +65,7 @@ export default function WorkflowListPage({ workflows }: Props) {
<>
{workflows && workflows.length > 0 ? (
<div className="bg-default border-subtle overflow-hidden rounded-md border sm:mx-0">
<ul className="divide-subtle divide-y">
<ul className="divide-subtle divide-y" data-testid="workflow-list">
{workflows.map((workflow) => (
<li key={workflow.id}>
<div className="first-line:group hover:bg-muted flex w-full items-center justify-between p-4 sm:px-6">

View File

@ -274,6 +274,7 @@ export default function WorkflowStepContainer(props: WorkflowStepProps) {
<Select
isSearchable={false}
className="text-sm"
id="trigger-select"
isDisabled={props.readOnly}
onChange={(val) => {
if (val) {

View File

@ -61,6 +61,8 @@ export const scheduleEmailReminder = async (
return;
}
const sandboxMode = process.env.NEXT_PUBLIC_IS_E2E ? true : false;
let name = "";
let attendeeName = "";
let timeZone = "";
@ -153,6 +155,11 @@ export const scheduleEmailReminder = async (
html: emailContent.emailBody,
batchId: batchIdResponse[1].batch_id,
replyTo: evt.organizer.email,
mailSettings: {
sandboxMode: {
enable: sandboxMode,
},
},
});
}
} else {
@ -166,6 +173,11 @@ export const scheduleEmailReminder = async (
html: emailContent.emailBody,
batchId: batchIdResponse[1].batch_id,
replyTo: evt.organizer.email,
mailSettings: {
sandboxMode: {
enable: sandboxMode,
},
},
});
}
} catch (error) {
@ -194,6 +206,11 @@ export const scheduleEmailReminder = async (
batchId: batchIdResponse[1].batch_id,
sendAt: scheduledDate.unix(),
replyTo: evt.organizer.email,
mailSettings: {
sandboxMode: {
enable: sandboxMode,
},
},
});
await prisma.workflowReminder.create({

View File

@ -262,7 +262,9 @@ function WorkflowPage() {
CTA={
!readOnly && (
<div>
<Button type="submit">{t("save")}</Button>
<Button data-testid="save-workflow" type="submit">
{t("save")}
</Button>
</div>
)
}

View File

@ -86,6 +86,7 @@ export function CreateButton(props: CreateBtnProps) {
? createFunction(options[0].teamId || undefined)
: null
}
data-testid="create-button"
StartIcon={Plus}
loading={isLoading}
variant={disableMobileButton ? "button" : "fab"}
@ -98,6 +99,7 @@ export function CreateButton(props: CreateBtnProps) {
<Button
variant={disableMobileButton ? "button" : "fab"}
StartIcon={Plus}
data-testid="create-button-dropdown"
loading={isLoading}
{...restProps}>
{buttonText ? buttonText : t("new")}