+9








![devin-ai-integration[bot]](/assets/img/avatar_default.png)
devin-ai-integration[bot]
GitHub
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 <eunjae@cal.com>
Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
eunjae@cal.com <eunjae@cal.com>
Eunjae Lee
8889e8566c
* 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>
298 lines
7.2 KiB
TypeScript
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,
|
|
},
|
|
],
|
|
});
|
|
});
|
|
});
|
|
});
|