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:
@@ -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 }}
|
||||
|
||||
@@ -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" } });
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 () => {
|
||||
};
|
||||
}
|
||||
@@ -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,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -84,6 +84,7 @@
|
||||
"HUBSPOT_CLIENT_SECRET",
|
||||
"IFFY_API_KEY",
|
||||
"INTEGRATION_TEST_MODE",
|
||||
"INTEGRATION_TESTS",
|
||||
"INTERCOM_SECRET",
|
||||
"INTERCOM_SECRET",
|
||||
"INSIGHTS_DATABASE_URL",
|
||||
|
||||
@@ -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: {
|
||||
|
||||
Reference in New Issue
Block a user