Files
calendar/packages/features/insights/server/__tests__/buildBaseWhereCondition.test.ts
T
+9
devin-ai-integration[bot]GitHubeunjae@cal.com <eunjae@cal.com>eunjae@cal.com <eunjae@cal.com>eunjae@cal.com <eunjae@cal.com>eunjae@cal.com <eunjae@cal.com>eunjae@cal.com <eunjae@cal.com>eunjae@cal.com <eunjae@cal.com>eunjae@cal.com <eunjae@cal.com>eunjae@cal.com <eunjae@cal.com>eunjae@cal.com <eunjae@cal.com>eunjae@cal.com <eunjae@cal.com>eunjae@cal.com <eunjae@cal.com>eunjae@cal.com <eunjae@cal.com>eunjae@cal.com <eunjae@cal.com>eunjae@cal.com <eunjae@cal.com>Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>eunjae@cal.com <eunjae@cal.com>Eunjae Lee
8889e8566c fix: eventType filter on /insights and add unit tests for buildBaseWhereCondition (#21154)
* test: Add unit tests for buildBaseWhereCondition function

Co-Authored-By: eunjae@cal.com <eunjae@cal.com>

* refactor: Export buildBaseWhereCondition function instead of copying it

Co-Authored-By: eunjae@cal.com <eunjae@cal.com>

* refactor: Remove implementation detail checks from tests

Co-Authored-By: eunjae@cal.com <eunjae@cal.com>

* test: Fix tests to match actual function behavior

Co-Authored-By: eunjae@cal.com <eunjae@cal.com>

* test: Fix test issues with buildBaseWhereCondition

Co-Authored-By: eunjae@cal.com <eunjae@cal.com>

* test: Update tests to match actual function behavior

Co-Authored-By: eunjae@cal.com <eunjae@cal.com>

* fix: Address security issues in buildBaseWhereCondition function

Co-Authored-By: eunjae@cal.com <eunjae@cal.com>

* refactor: Simplify buildBaseWhereCondition function

Co-Authored-By: eunjae@cal.com <eunjae@cal.com>

* refactor: Simplify code and remove isEmptyResponse property

Co-Authored-By: eunjae@cal.com <eunjae@cal.com>

* refactor: Use array of conditions approach for buildBaseWhereCondition

Co-Authored-By: eunjae@cal.com <eunjae@cal.com>

* refactor: Make buildBaseWhereCondition implementation consistent and update tests

Co-Authored-By: eunjae@cal.com <eunjae@cal.com>

* fix: Fix incorrect usage of buildBaseWhereCondition function

Co-Authored-By: eunjae@cal.com <eunjae@cal.com>

* chore: Revert yarn.lock changes

Co-Authored-By: eunjae@cal.com <eunjae@cal.com>

* fix: Comment out non-existent Sentry API method to fix type error

Co-Authored-By: eunjae@cal.com <eunjae@cal.com>

* Revert "fix: Comment out non-existent Sentry API method to fix type error"

This reverts commit 44c21a7396a518c63047b33967cd8af7e6e4f268.

* remove unnecessary if-statement

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: eunjae@cal.com <eunjae@cal.com>
Co-authored-by: Eunjae Lee <hey@eunjae.dev>
2025-05-16 10:10:57 +02:00

298 lines
7.2 KiB
TypeScript

import { describe, expect, it, vi, beforeEach } from "vitest";
import type { readonlyPrisma } from "@calcom/prisma";
import { buildBaseWhereCondition } from "../trpc-router";
const mockTeamFindMany = vi.fn();
const mockMembershipFindMany = vi.fn();
const mockInsightsDb = {
team: {
findMany: mockTeamFindMany,
},
membership: {
findMany: mockMembershipFindMany,
},
} as unknown as typeof readonlyPrisma;
const createMockContext = (overrides = {}) => ({
userIsOwnerAdminOfParentTeam: false,
userOrganizationId: null,
insightsDb: mockInsightsDb,
...overrides,
});
describe("buildBaseWhereCondition", () => {
beforeEach(() => {
vi.resetAllMocks();
});
describe("Basic filtering", () => {
it("should set eventTypeId condition when eventTypeId is provided", async () => {
const ctx = createMockContext();
const result = await buildBaseWhereCondition({
eventTypeId: 123,
ctx,
});
expect(result.whereCondition).toEqual({
OR: [{ eventTypeId: 123 }, { eventParentId: 123 }],
});
});
it("should set userId condition when memberUserId is provided", async () => {
const ctx = createMockContext();
const result = await buildBaseWhereCondition({
memberUserId: 456,
ctx,
});
expect(result.whereCondition).toEqual({
userId: 456,
});
});
it("should set userId and teamId conditions when userId is provided", async () => {
const ctx = createMockContext();
const result = await buildBaseWhereCondition({
userId: 789,
ctx,
});
expect(result.whereCondition).toEqual({
userId: 789,
teamId: null,
});
});
});
describe("Organization-wide queries", () => {
it("should return appropriate where condition when no teams found in organization", async () => {
mockTeamFindMany.mockResolvedValue([]);
const ctx = createMockContext({
userIsOwnerAdminOfParentTeam: true,
userOrganizationId: 100,
});
const result = await buildBaseWhereCondition({
isAll: true,
ctx,
});
expect(result.whereCondition).toEqual({
OR: [
{
teamId: { in: [100] },
isTeamBooking: true,
},
],
});
});
it("should build complex where condition for organization-wide query", async () => {
mockTeamFindMany.mockResolvedValue([{ id: 101 }, { id: 102 }]);
mockMembershipFindMany.mockResolvedValue([{ userId: 201 }, { userId: 202 }]);
const ctx = createMockContext({
userIsOwnerAdminOfParentTeam: true,
userOrganizationId: 100,
});
const result = await buildBaseWhereCondition({
isAll: true,
ctx,
});
expect(result.whereCondition).toEqual({
OR: [
{
teamId: {
in: [100, 101, 102],
},
isTeamBooking: true,
},
{
userId: {
in: [201, 202],
},
isTeamBooking: false,
},
],
});
});
});
describe("Team-specific queries", () => {
it("should build where condition for team-specific query", async () => {
mockMembershipFindMany.mockResolvedValue([{ userId: 301 }, { userId: 302 }]);
const ctx = createMockContext();
const result = await buildBaseWhereCondition({
teamId: 200,
isAll: false,
ctx,
});
expect(result.whereCondition).toEqual({
OR: [
{
teamId: 200,
isTeamBooking: true,
},
{
userId: {
in: [301, 302],
},
isTeamBooking: false,
},
],
});
});
it("should apply both team and eventTypeId conditions when both are provided", async () => {
mockMembershipFindMany.mockResolvedValue([{ userId: 301 }, { userId: 302 }]);
const ctx = createMockContext();
const result = await buildBaseWhereCondition({
teamId: 200,
eventTypeId: 500,
isAll: false,
ctx,
});
expect(result.whereCondition).toEqual({
AND: [
{
OR: [{ eventTypeId: 500 }, { eventParentId: 500 }],
},
{
OR: [
{
teamId: 200,
isTeamBooking: true,
},
{
userId: {
in: [301, 302],
},
isTeamBooking: false,
},
],
},
],
});
});
});
describe("Combined filtering", () => {
it("should combine eventTypeId and memberUserId conditions", async () => {
const ctx = createMockContext();
const result = await buildBaseWhereCondition({
eventTypeId: 123,
memberUserId: 456,
ctx,
});
expect(result.whereCondition).toEqual({
AND: [
{
OR: [{ eventTypeId: 123 }, { eventParentId: 123 }],
},
{
userId: 456,
},
],
});
});
});
describe("Invalid parameters", () => {
it("should handle missing parameters and return restrictive where condition", async () => {
const ctx = createMockContext();
const result = await buildBaseWhereCondition({
ctx,
});
expect(result.whereCondition).toEqual({ id: -1 });
});
it("should handle null teamId with restrictive where condition", async () => {
const ctx = createMockContext();
const result = await buildBaseWhereCondition({
teamId: null,
ctx,
});
expect(result.whereCondition).toEqual({ id: -1 });
});
it("should handle empty team members with proper team condition", async () => {
mockMembershipFindMany.mockResolvedValue([]);
const ctx = createMockContext();
const result = await buildBaseWhereCondition({
teamId: 200,
isAll: false,
ctx,
});
expect(result.whereCondition).toEqual({
OR: [
{
teamId: 200,
isTeamBooking: true,
},
{
userId: {
in: [],
},
isTeamBooking: false,
},
],
});
});
it("should handle rejected team membership differently from empty team", async () => {
mockMembershipFindMany.mockImplementation((params) => {
if (params?.where?.accepted === true) {
// No accepted members
return Promise.resolve([]);
}
return Promise.resolve([{ userId: 601 }, { userId: 602 }]);
});
const ctx = createMockContext();
const result = await buildBaseWhereCondition({
teamId: 200,
isAll: false,
ctx,
});
// Should only include team bookings since there are no accepted members
expect(result.whereCondition).toEqual({
OR: [
{
teamId: 200,
isTeamBooking: true,
},
{
userId: {
in: [], // Empty because no accepted members
},
isTeamBooking: false,
},
],
});
});
});
});