Files
calendar/apps/web/playwright/fixtures/workflows.ts
T
ecc5e66fd4 fix(e2e): replace false-passing assertions and hard-coded waits in test suite (#28486)
* fix(e2e): replace always-passing assertions and hard-coded waits

- Replace toBeTruthy() on Locator objects with toBeVisible() (always-passing)
- Replace toBeTruthy() on boolean expressions with toBe(true) for clarity
- Replace hardcoded waitForTimeout() with element-based waits (waitFor/toBeVisible)
- Fix strict mode violation: getByTestId("away-emoji").first()
- Fix error assertion: infinite redirect error shown as toast → getByTestId("toast-error")
- Fix isDisabled() no-op → await expect().toBeDisabled() in workflows fixture
- Fix alby setup: add waitForURL(), remove unverifiable "Connect with Alby" assertion
- Fix stripe/paypal: replace no-op isDisabled() with toBeChecked() on paypal switch

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(e2e): fix stale comment in stripe price test

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(e2e): address cubic review feedback on assertion patterns

- workflows.ts: replace non-retrying isDisabled() snapshot with toBeDisabled()
- out-of-office.e2e.ts: add .first() for away-emoji strict mode, use toast-error testid, remove unused const t
- payment-apps.e2e.ts: replace always-passing toBeTruthy() with toHaveURL() assertion

* fix

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Romit <85230081+romitg2@users.noreply.github.com>
Co-authored-by: Romit <romitgabani1.work@gmail.com>
2026-03-25 05:25:49 +00:00

182 lines
5.5 KiB
TypeScript

import type { Locator } from "@playwright/test";
import { expect, type Page } from "@playwright/test";
import prisma from "@calcom/prisma";
import { WorkflowTriggerEvents } from "@calcom/prisma/enums";
import type { Fixtures } from "@calcom/web/playwright/lib/fixtures";
import { localize } from "../lib/localize";
type CreateWorkflowProps = {
name?: string;
isTeam?: true;
trigger?: WorkflowTriggerEvents;
};
const subjectPattern = /^Reminder: /i;
export function createWorkflowPageFixture(page: Page) {
const createWorkflow = async (props: CreateWorkflowProps) => {
const { name, isTeam, trigger } = props;
if (isTeam) {
await page.getByTestId("create-button-dropdown").click();
await page.getByTestId("option-team-1").click();
} else {
await page.getByTestId("create-button").click();
}
await page.getByTestId(`workflow-option-card-scratch`).click();
await page.getByTestId("continue-button").click();
if (name) {
await fillNameInput(name);
}
await page.locator("#trigger-select").click();
await page.getByTestId(`select-option-${trigger ?? WorkflowTriggerEvents.BEFORE_EVENT}`).click();
if (isTeam) {
await page
.getByText(/Apply to all team/i)
.first()
.click();
} else {
await selectEventType("30 min");
}
const workflow = await saveWorkflow();
for (const step of workflow.steps) {
await prisma.workflowStep.update({
where: { id: step.id },
data: { verifiedAt: new Date() },
});
}
await page.getByTestId("go-back-button").click();
};
const saveWorkflow = async () => {
const submitPromise = page.waitForResponse("/api/trpc/workflows/update?batch=1");
const saveButton = page.getByTestId("save-workflow");
await saveButton.click();
const response = await submitPromise;
expect(response.status()).toBe(200);
const responseData = await response.json();
return responseData[0].result.data.json.workflow;
};
const assertListCount = async (count: number) => {
const workflowListCount = page.locator('[data-testid="workflow-list"] > li');
await expect(workflowListCount.first()).toBeVisible();
await page.reload();
await expect(workflowListCount).toHaveCount(count);
};
const fillNameInput = async (name: string) => {
await page.getByTestId("edit-workflow-name-button").click();
const nameInput = page.getByTestId("workflow-name");
await nameInput.fill(name);
await nameInput.blur();
};
const editSelectedWorkflow = async (name: string) => {
const selectedWorkflow = page.getByTestId("workflow-list").getByTestId(nameToTestId(name));
const editButton = selectedWorkflow.getByRole("button").nth(0);
await editButton.click();
};
const hasWorkflowInList = async (name: string, negate?: true) => {
const selectedWorkflow = page.getByTestId("workflow-list").getByTestId(nameToTestId(name));
if (negate) {
await expect(selectedWorkflow).toBeHidden();
} else {
await expect(selectedWorkflow).toBeVisible();
}
};
const deleteAndConfirm = async (workflow: Locator) => {
const deleteButton = workflow.getByTestId("delete-button");
const confirmDeleteText = (await localize("en"))("confirm_delete_workflow");
await deleteButton.click();
await page.getByRole("button", { name: confirmDeleteText }).click();
};
const selectEventType = async (name: string) => {
await page.getByTestId("multi-select-check-boxes").click();
await page.getByText(name, { exact: true }).click();
};
const hasReadonlyBadge = async () => {
const readOnlyBadge = page.getByText((await localize("en"))("readonly"));
await expect(readOnlyBadge).toBeVisible();
};
const selectedWorkflowPage = async (name: string) => {
await page.getByTestId("workflow-list").getByTestId(nameToTestId(name)).click();
};
const workflowOptionsAreDisabled = async (workflow: string, negate?: boolean) => {
const getWorkflowButton = async (buttonTestId: string) =>
page.getByTestId(nameToTestId(workflow)).getByTestId(buttonTestId);
const [editButton, deleteButton] = await Promise.all([
getWorkflowButton("edit-button"),
getWorkflowButton("delete-button"),
]);
await expect(editButton).toBeDisabled();
await expect(deleteButton).toBeDisabled();
};
const assertWorkflowWasTriggered = async (emails: Fixtures["emails"], emailsToBeReceived: string[]) => {
const message = await emails.messages();
emailsToBeReceived.forEach((email) => {
expect(message?.items).toEqual(
expect.arrayContaining([
expect.objectContaining({
subject: expect.stringMatching(subjectPattern),
to: email,
}),
])
);
});
};
const assertWorkflowReminders = async (eventTypeId: number, count: number) => {
const booking = await prisma.booking.findFirst({
where: {
eventTypeId,
},
});
const workflowReminders = await prisma.workflowReminder.findMany({
where: {
bookingUid: booking?.uid ?? "",
},
});
expect(workflowReminders).toHaveLength(count);
};
function nameToTestId(name: string) {
return `workflow-${name.split(" ").join("-").toLowerCase()}`;
}
return {
createWorkflow,
saveWorkflow,
assertListCount,
fillNameInput,
editSelectedWorkflow,
hasWorkflowInList,
deleteAndConfirm,
selectEventType,
hasReadonlyBadge,
selectedWorkflowPage,
workflowOptionsAreDisabled,
assertWorkflowReminders,
assertWorkflowWasTriggered,
};
}