chore: [app dir bootstrapping 2] ensure tests do not have explicit timeouts (#11970)

pull/11804/head^2
Greg Pabian 2023-10-21 01:57:13 +02:00 committed by GitHub
parent 2a8f7412dd
commit e91fe12219
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 43 additions and 62 deletions

View File

@ -53,7 +53,7 @@ test.describe("free user", () => {
// book same time spot again
await bookTimeSlot(page);
await expect(page.locator("[data-testid=booking-fail]")).toBeVisible({ timeout: 1000 });
await page.locator("[data-testid=booking-fail]").waitFor({ state: "visible" });
});
});

View File

@ -1,5 +1,6 @@
import type { Frame, Page } from "@playwright/test";
import { expect } from "@playwright/test";
import EventEmitter from "events";
import type { IncomingMessage, ServerResponse } from "http";
import { createServer } from "http";
// eslint-disable-next-line no-restricted-imports
@ -35,7 +36,27 @@ export function createHttpServer(opts: { requestHandler?: RequestHandler } = {})
res.end();
},
} = opts;
const eventEmitter = new EventEmitter();
const requestList: Request[] = [];
const waitForRequestCount = (count: number) =>
new Promise<void>((resolve) => {
if (requestList.length === count) {
resolve();
return;
}
const pushHandler = () => {
if (requestList.length !== count) {
return;
}
eventEmitter.off("push", pushHandler);
resolve();
};
eventEmitter.on("push", pushHandler);
});
const server = createServer((req, res) => {
const buffer: unknown[] = [];
@ -49,6 +70,7 @@ export function createHttpServer(opts: { requestHandler?: RequestHandler } = {})
_req.body = json;
requestList.push(_req);
eventEmitter.emit("push");
requestHandler({ req: _req, res });
});
});
@ -58,34 +80,16 @@ export function createHttpServer(opts: { requestHandler?: RequestHandler } = {})
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const port: number = (server.address() as any).port;
const url = `http://localhost:${port}`;
return {
port,
close: () => server.close(),
requestList,
url,
waitForRequestCount,
};
}
/**
* When in need to wait for any period of time you can use waitFor, to wait for your expectations to pass.
*/
export async function waitFor(fn: () => Promise<unknown> | unknown, opts: { timeout?: number } = {}) {
let finished = false;
const timeout = opts.timeout ?? 5000; // 5s
const timeStart = Date.now();
while (!finished) {
try {
await fn();
finished = true;
} catch {
if (Date.now() - timeStart >= timeout) {
throw new Error("waitFor timed out");
}
await new Promise((resolve) => setTimeout(resolve, 0));
}
}
}
export async function selectFirstAvailableTimeSlotNextMonth(page: Page | Frame) {
// Let current month dates fully render.
await page.click('[data-testid="incrementMonth"]');

View File

@ -8,7 +8,7 @@ import { WebhookTriggerEvents } from "@calcom/prisma/enums";
import type { CalendarEvent } from "@calcom/types/Calendar";
import { test } from "./lib/fixtures";
import { createHttpServer, waitFor, selectFirstAvailableTimeSlotNextMonth } from "./lib/testUtils";
import { createHttpServer, selectFirstAvailableTimeSlotNextMonth } from "./lib/testUtils";
async function getLabelText(field: Locator) {
return await field.locator("label").first().locator("span").first().innerText();
@ -215,13 +215,7 @@ test.describe("Manage Booking Questions", () => {
async function runTestStepsCommonForTeamAndUserEventType(
page: Page,
context: PlaywrightTestArgs["context"],
webhookReceiver: {
port: number;
close: () => import("http").Server;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
requestList: (import("http").IncomingMessage & { body?: any })[];
url: string;
}
webhookReceiver: Awaited<ReturnType<typeof addWebhook>>
) {
await page.click('[href$="tabName=advanced"]');
@ -311,12 +305,11 @@ async function runTestStepsCommonForTeamAndUserEventType(
await page.locator('[data-testid="field-response"][data-fob-field="how-are-you"]').innerText()
).toBe("I am great!");
await waitFor(() => {
expect(webhookReceiver.requestList.length).toBe(1);
});
await webhookReceiver.waitForRequestCount(1);
const [request] = webhookReceiver.requestList;
// @ts-expect-error body is unknown
const payload = request.body.payload;
expect(payload.responses).toMatchObject({
@ -667,9 +660,7 @@ async function expectWebhookToBeCalled(
};
}
) {
await waitFor(() => {
expect(webhookReceiver.requestList.length).toBe(1);
});
await webhookReceiver.waitForRequestCount(1);
const [request] = webhookReceiver.requestList;
const body = request.body;

View File

@ -10,7 +10,6 @@ import {
bookOptinEvent,
createHttpServer,
selectFirstAvailableTimeSlotNextMonth,
waitFor,
gotoRoutingLink,
createUserWithSeatedEventAndAttendees,
} from "./lib/testUtils";
@ -78,10 +77,7 @@ test.describe("BOOKING_CREATED", async () => {
await page.fill('[name="email"]', "test@example.com");
await page.press('[name="email"]', "Enter");
// --- check that webhook was called
await waitFor(() => {
expect(webhookReceiver.requestList.length).toBe(1);
});
await webhookReceiver.waitForRequestCount(1);
const [request] = webhookReceiver.requestList;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@ -209,10 +205,8 @@ test.describe("BOOKING_REJECTED", async () => {
await page.click('[data-testid="rejection-confirm"]');
await page.waitForResponse((response) => response.url().includes("/api/trpc/bookings/confirm"));
// --- check that webhook was called
await waitFor(() => {
expect(webhookReceiver.requestList.length).toBe(1);
});
await webhookReceiver.waitForRequestCount(1);
const [request] = webhookReceiver.requestList;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const body = request.body as any;
@ -332,9 +326,8 @@ test.describe("BOOKING_REQUESTED", async () => {
// --- check that webhook was called
await waitFor(() => {
expect(webhookReceiver.requestList.length).toBe(1);
});
await webhookReceiver.waitForRequestCount(1);
const [request] = webhookReceiver.requestList;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const body = request.body as any;
@ -442,9 +435,7 @@ test.describe("BOOKING_RESCHEDULED", async () => {
expect(newBooking).not.toBeNull();
// --- check that webhook was called
await waitFor(() => {
expect(webhookReceiver.requestList.length).toBe(1);
});
await webhookReceiver.waitForRequestCount(1);
const [request] = webhookReceiver.requestList;
@ -520,9 +511,7 @@ test.describe("BOOKING_RESCHEDULED", async () => {
expect(newBooking).not.toBeNull();
// --- check that webhook was called
await waitFor(() => {
expect(webhookReceiver.requestList.length).toBe(1);
});
await webhookReceiver.waitForRequestCount(1);
const [firstRequest] = webhookReceiver.requestList;
@ -541,9 +530,7 @@ test.describe("BOOKING_RESCHEDULED", async () => {
await expect(page).toHaveURL(/.*booking/);
await waitFor(() => {
expect(webhookReceiver.requestList.length).toBe(2);
});
await webhookReceiver.waitForRequestCount(2);
const [_, secondRequest] = webhookReceiver.requestList;
@ -597,9 +584,8 @@ test.describe("FORM_SUBMITTED", async () => {
await page.fill(`[data-testid="form-field-${fieldName}"]`, "John Doe");
page.click('button[type="submit"]');
await waitFor(() => {
expect(webhookReceiver.requestList.length).toBe(1);
});
await webhookReceiver.waitForRequestCount(1);
const [request] = webhookReceiver.requestList;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const body = request.body as any;
@ -656,9 +642,9 @@ test.describe("FORM_SUBMITTED", async () => {
const fieldName = "name";
await page.fill(`[data-testid="form-field-${fieldName}"]`, "John Doe");
page.click('button[type="submit"]');
await waitFor(() => {
expect(webhookReceiver.requestList.length).toBe(1);
});
await webhookReceiver.waitForRequestCount(1);
const [request] = webhookReceiver.requestList;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const body = request.body as any;