fix: flaky integrations tests (#25218)

* Revert "fix: resolve flaky integration tests (#25030)"

This reverts commit 4e5d4f67d5.

* update

* test

* Remove connection pool setup in Prisma index

Set the connection pool to undefined, removing conditional pooling logic.

* update
This commit is contained in:
Anik Dhabal Babu
2025-11-18 00:04:24 +00:00
committed by GitHub
parent b8530e2d78
commit 44aa26292d
11 changed files with 128 additions and 216 deletions
+1
View File
@@ -5,6 +5,7 @@ permissions:
contents: read
env:
NODE_OPTIONS: --max-old-space-size=4096
INTEGRATION_TESTS: "true"
ALLOWED_HOSTNAMES: ${{ vars.CI_ALLOWED_HOSTNAMES }}
CALENDSO_ENCRYPTION_KEY: ${{ secrets.CI_CALENDSO_ENCRYPTION_KEY }}
DAILY_API_KEY: ${{ secrets.CI_DAILY_API_KEY }}
+1 -3
View File
@@ -19,9 +19,7 @@ export const isAdminGuard = async (req: NextApiRequest) => {
team: {
isOrganization: true,
organizationSettings: {
is: {
isAdminAPIEnabled: true,
},
isAdminAPIEnabled: true,
},
},
OR: [{ role: MembershipRole.OWNER }, { role: MembershipRole.ADMIN }],
@@ -1,7 +1,7 @@
import type { Request, Response } from "express";
import type { NextApiRequest, NextApiResponse } from "next";
import { createMocks } from "node-mocks-http";
import { describe, it, expect } from "vitest";
import { describe, it, expect, beforeAll } from "vitest";
import prisma from "@calcom/prisma";
@@ -11,6 +11,30 @@ type CustomNextApiRequest = NextApiRequest & Request;
type CustomNextApiResponse = NextApiResponse & Response;
describe("PATCH /api/bookings", () => {
beforeAll(async () => {
const acmeOrg = await prisma.team.findFirst({
where: {
slug: "acme",
isOrganization: true,
},
});
if (acmeOrg) {
await prisma.organizationSettings.upsert({
where: {
organizationId: acmeOrg.id,
},
update: {
isAdminAPIEnabled: true,
},
create: {
organizationId: acmeOrg.id,
orgAutoAcceptEmail: "acme.com",
isAdminAPIEnabled: true,
},
});
}
});
it("Returns 403 when user has no permission to the booking", async () => {
const memberUser = await prisma.user.findFirstOrThrow({ where: { email: "member2-acme@example.com" } });
const proUser = await prisma.user.findFirstOrThrow({ where: { email: "pro@example.com" } });
@@ -16,14 +16,33 @@ const DefaultPagination = {
skip: 0,
};
describe("GET /api/bookings", () => {
let proUser: Awaited<ReturnType<typeof prisma.user.findFirstOrThrow>>;
let proUserBooking: Awaited<ReturnType<typeof prisma.booking.findFirstOrThrow>>;
describe("GET /api/bookings", async () => {
beforeAll(async () => {
proUser = await prisma.user.findFirstOrThrow({ where: { email: "pro@example.com" } });
proUserBooking = await prisma.booking.findFirstOrThrow({ where: { userId: proUser.id } });
const acmeOrg = await prisma.team.findFirst({
where: {
slug: "acme",
isOrganization: true,
},
});
if (acmeOrg) {
await prisma.organizationSettings.upsert({
where: {
organizationId: acmeOrg.id,
},
update: {
isAdminAPIEnabled: true,
},
create: {
organizationId: acmeOrg.id,
orgAutoAcceptEmail: "acme.com",
isAdminAPIEnabled: true,
},
});
}
});
const proUser = await prisma.user.findFirstOrThrow({ where: { email: "pro@example.com" } });
const proUserBooking = await prisma.booking.findFirstOrThrow({ where: { userId: proUser.id } });
it("Does not return bookings of other users when user has no permission", async () => {
const memberUser = await prisma.user.findFirstOrThrow({ where: { email: "member2-acme@example.com" } });
@@ -1,7 +1,7 @@
import type { Request, Response } from "express";
import type { NextApiRequest, NextApiResponse } from "next";
import { createMocks } from "node-mocks-http";
import { describe, it, expect } from "vitest";
import { describe, it, expect, beforeAll } from "vitest";
import prisma from "@calcom/prisma";
@@ -12,6 +12,53 @@ type CustomNextApiRequest = NextApiRequest & Request;
type CustomNextApiResponse = NextApiResponse & Response;
describe("isAdmin guard", () => {
beforeAll(async () => {
const acmeOrg = await prisma.team.findFirst({
where: {
slug: "acme",
isOrganization: true,
},
});
if (acmeOrg) {
await prisma.organizationSettings.upsert({
where: {
organizationId: acmeOrg.id,
},
update: {
isAdminAPIEnabled: true,
},
create: {
organizationId: acmeOrg.id,
orgAutoAcceptEmail: "acme.com",
isAdminAPIEnabled: true,
},
});
}
const dunderOrg = await prisma.team.findFirst({
where: {
slug: "dunder-mifflin",
isOrganization: true,
},
});
if (dunderOrg) {
await prisma.organizationSettings.upsert({
where: {
organizationId: dunderOrg.id,
},
update: {
isAdminAPIEnabled: false,
},
create: {
organizationId: dunderOrg.id,
orgAutoAcceptEmail: "dunder-mifflin.com",
isAdminAPIEnabled: false,
},
});
}
});
it("Returns false when user does not exist in the system", async () => {
const { req } = createMocks<CustomNextApiRequest, CustomNextApiResponse>({
method: "POST",
@@ -1,4 +1,4 @@
import { describe, it, expect } from "vitest";
import { describe, it, expect, beforeAll } from "vitest";
import prisma from "@calcom/prisma";
@@ -8,6 +8,30 @@ import {
} from "../../../lib/utils/retrieveScopedAccessibleUsers";
describe("retrieveScopedAccessibleUsers tests", () => {
beforeAll(async () => {
const acmeOrg = await prisma.team.findFirst({
where: {
slug: "acme",
isOrganization: true,
},
});
if (acmeOrg) {
await prisma.organizationSettings.upsert({
where: {
organizationId: acmeOrg.id,
},
update: {
isAdminAPIEnabled: true,
},
create: {
organizationId: acmeOrg.id,
orgAutoAcceptEmail: "acme.com",
isAdminAPIEnabled: true,
},
});
}
});
describe("getAccessibleUsers", () => {
it("Does not return members when only admin user ID is supplied", async () => {
const adminUser = await prisma.user.findFirstOrThrow({ where: { email: "owner1-acme@example.com" } });
+2 -1
View File
@@ -8,8 +8,9 @@ import { excludePendingPaymentsExtension } from "./extensions/exclude-pending-pa
import { PrismaClient, type Prisma } from "./generated/prisma/client";
const connectionString = process.env.DATABASE_URL || "";
const isIntegrationTest = process.env.INTEGRATION_TESTS === "true";
const pool =
process.env.USE_POOL === "true" || process.env.USE_POOL === "1"
!isIntegrationTest && (process.env.USE_POOL === "true" || process.env.USE_POOL === "1")
? new Pool({
connectionString: connectionString,
max: 5,
-58
View File
@@ -1,58 +0,0 @@
/**
* Global setup for integration tests
* Runs once before all integration tests to seed org-admin state
*/
export default async function globalSetup() {
const module = await import("../lib/test-team-repository");
const TestTeamRepository = module.TestTeamRepository;
const teamRepo = await TestTeamRepository.withGlobalPrisma();
const acmeOrg = await teamRepo.findOrganizationBySlug("acme");
if (acmeOrg) {
await teamRepo.upsertOrganizationSettings({
organizationId: acmeOrg.id,
isAdminAPIEnabled: true,
orgAutoAcceptEmail: "acme.com",
});
await teamRepo.ensureMembership({
userEmail: "owner1-acme@example.com",
organizationId: acmeOrg.id,
role: "OWNER",
accepted: true,
});
for (let i = 0; i < 10; i++) {
const memberEmail = `member${i}-acme@example.com`;
const memberUsername = `member${i}-acme`;
const memberName = `Member ${i}`;
await teamRepo.ensureUser({
email: memberEmail,
username: memberUsername,
name: memberName,
});
await teamRepo.ensureMembership({
userEmail: memberEmail,
organizationId: acmeOrg.id,
role: "MEMBER",
accepted: true,
});
}
}
const dunderOrg = await teamRepo.findOrganizationBySlug("dunder-mifflin");
if (dunderOrg) {
await teamRepo.upsertOrganizationSettings({
organizationId: dunderOrg.id,
isAdminAPIEnabled: false,
orgAutoAcceptEmail: "dunder-mifflin.com",
});
}
return async () => {
};
}
-144
View File
@@ -1,144 +0,0 @@
import type { PrismaClient } from "@calcom/prisma";
export class TestTeamRepository {
constructor(private prismaClient: PrismaClient) {}
static async withGlobalPrisma() {
return new TestTeamRepository((await import("@calcom/prisma")).prisma);
}
async findOrganizationBySlug(slug: string) {
return this.prismaClient.team.findFirst({
where: {
slug,
isOrganization: true,
},
select: {
id: true,
slug: true,
name: true,
},
});
}
async upsertOrganizationSettings({
organizationId,
isAdminAPIEnabled,
orgAutoAcceptEmail,
}: {
organizationId: number;
isAdminAPIEnabled: boolean;
orgAutoAcceptEmail?: string;
}) {
return this.prismaClient.organizationSettings.upsert({
where: {
organizationId,
},
update: {
isAdminAPIEnabled,
},
create: {
organizationId,
orgAutoAcceptEmail: orgAutoAcceptEmail || "",
isAdminAPIEnabled,
},
});
}
async findUserMembershipsInOrg({
userEmail,
organizationId,
}: {
userEmail: string;
organizationId: number;
}) {
return this.prismaClient.membership.findMany({
where: {
user: {
email: userEmail,
},
teamId: organizationId,
},
select: {
id: true,
role: true,
accepted: true,
user: {
select: {
id: true,
email: true,
},
},
},
});
}
async ensureUser({
email,
username,
name,
}: {
email: string;
username: string;
name: string;
}) {
return this.prismaClient.user.upsert({
where: { email },
update: {
name,
},
create: {
email,
username,
name,
emailVerified: new Date(),
},
});
}
async ensureMembership({
userEmail,
organizationId,
role,
accepted,
}: {
userEmail: string;
organizationId: number;
role: "OWNER" | "ADMIN" | "MEMBER";
accepted: boolean;
}) {
const user = await this.prismaClient.user.findFirst({
where: { email: userEmail },
});
if (!user) {
throw new Error(`User with email ${userEmail} not found`);
}
const existingMembership = await this.prismaClient.membership.findFirst({
where: {
userId: user.id,
teamId: organizationId,
},
});
if (existingMembership) {
return this.prismaClient.membership.update({
where: { id: existingMembership.id },
data: {
role,
accepted,
},
});
}
return this.prismaClient.membership.create({
data: {
userId: user.id,
teamId: organizationId,
role,
accepted,
},
});
}
}
+1
View File
@@ -84,6 +84,7 @@
"HUBSPOT_CLIENT_SECRET",
"IFFY_API_KEY",
"INTEGRATION_TEST_MODE",
"INTEGRATION_TESTS",
"INTERCOM_SECRET",
"INTERCOM_SECRET",
"INSIGHTS_DATABASE_URL",
-1
View File
@@ -27,7 +27,6 @@ const workspaces = packagedEmbedTestsOnly
name: `IntegrationTests`,
include: ["packages/**/*.integration-test.ts", "apps/**/*.integration-test.ts"],
exclude: ["**/node_modules/**/*", "packages/embeds/**/*"],
globalSetup: new URL("./tests/integration/global-setup.ts", import.meta.url).pathname,
setupFiles: ["setupVitest.ts"],
},
resolve: {