mirror of
https://github.com/formbricks/formbricks.git
synced 2025-12-21 13:40:31 -06:00
chore: 576 test coverage: apps/web/modules/survey/list/lib (#5706)
This commit is contained in:
201
apps/web/modules/survey/list/lib/environment.test.ts
Normal file
201
apps/web/modules/survey/list/lib/environment.test.ts
Normal file
@@ -0,0 +1,201 @@
|
||||
// Retain only vitest import here
|
||||
// Import modules after mocks
|
||||
import { cache as libCacheImport } from "@/lib/cache";
|
||||
import { validateInputs } from "@/lib/utils/validate";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { beforeEach, describe, expect, test, vi } from "vitest";
|
||||
import { prisma } from "@formbricks/database";
|
||||
import { logger } from "@formbricks/logger";
|
||||
import { DatabaseError, ResourceNotFoundError } from "@formbricks/types/errors";
|
||||
import { doesEnvironmentExist, getEnvironment, getProjectIdIfEnvironmentExists } from "./environment";
|
||||
|
||||
// Mock dependencies
|
||||
vi.mock("@/lib/cache", () => ({
|
||||
cache: vi.fn((workFn: () => Promise<any>, _cacheKey?: string, _options?: any) =>
|
||||
vi.fn(async () => await workFn())
|
||||
),
|
||||
}));
|
||||
|
||||
vi.mock("@/lib/environment/cache", () => ({
|
||||
environmentCache: {
|
||||
tag: {
|
||||
byId: vi.fn((id) => `environment-${id}`),
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock("@/lib/utils/validate");
|
||||
|
||||
vi.mock("@formbricks/database", () => ({
|
||||
prisma: {
|
||||
environment: {
|
||||
findUnique: vi.fn(),
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock("@formbricks/logger", () => ({
|
||||
logger: {
|
||||
error: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock("react", async () => {
|
||||
const actualReact = await vi.importActual("react");
|
||||
return {
|
||||
...actualReact,
|
||||
cache: vi.fn((fnToMemoize: (...args: any[]) => any) => fnToMemoize),
|
||||
};
|
||||
});
|
||||
|
||||
const mockEnvironmentId = "clxko31qs000008jya8v4ah0a";
|
||||
const mockProjectId = "clxko31qt000108jyd64v5688";
|
||||
|
||||
describe("doesEnvironmentExist", () => {
|
||||
beforeEach(() => {
|
||||
vi.resetAllMocks();
|
||||
// No need to call mockImplementation for libCacheImport or reactCacheImport here anymore
|
||||
});
|
||||
|
||||
test("should return environmentId if environment exists", async () => {
|
||||
vi.mocked(prisma.environment.findUnique).mockResolvedValue({ id: mockEnvironmentId });
|
||||
|
||||
const result = await doesEnvironmentExist(mockEnvironmentId);
|
||||
|
||||
expect(result).toBe(mockEnvironmentId);
|
||||
expect(prisma.environment.findUnique).toHaveBeenCalledWith({
|
||||
where: { id: mockEnvironmentId },
|
||||
select: { id: true },
|
||||
});
|
||||
// Check if mocks were called as expected by the new setup
|
||||
expect(libCacheImport).toHaveBeenCalledTimes(1);
|
||||
// Check that the function returned by libCacheImport was called
|
||||
const libCacheReturnedFn = vi.mocked(libCacheImport).mock.results[0].value;
|
||||
expect(libCacheReturnedFn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test("should throw ResourceNotFoundError if environment does not exist", async () => {
|
||||
vi.mocked(prisma.environment.findUnique).mockResolvedValue(null);
|
||||
|
||||
await expect(doesEnvironmentExist(mockEnvironmentId)).rejects.toThrow(ResourceNotFoundError);
|
||||
expect(prisma.environment.findUnique).toHaveBeenCalledWith({
|
||||
where: { id: mockEnvironmentId },
|
||||
select: { id: true },
|
||||
});
|
||||
expect(libCacheImport).toHaveBeenCalledTimes(1);
|
||||
// Check that the function returned by libCacheImport was called
|
||||
const libCacheReturnedFn = vi.mocked(libCacheImport).mock.results[0].value;
|
||||
expect(libCacheReturnedFn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getProjectIdIfEnvironmentExists", () => {
|
||||
beforeEach(() => {
|
||||
vi.resetAllMocks();
|
||||
});
|
||||
|
||||
test("should return projectId if environment exists", async () => {
|
||||
vi.mocked(prisma.environment.findUnique).mockResolvedValue({ projectId: mockProjectId }); // Ensure correct mock value
|
||||
|
||||
const result = await getProjectIdIfEnvironmentExists(mockEnvironmentId);
|
||||
|
||||
expect(result).toBe(mockProjectId);
|
||||
expect(prisma.environment.findUnique).toHaveBeenCalledWith({
|
||||
where: { id: mockEnvironmentId },
|
||||
select: { projectId: true },
|
||||
});
|
||||
expect(libCacheImport).toHaveBeenCalledTimes(1);
|
||||
// Check that the function returned by libCacheImport was called
|
||||
const libCacheReturnedFn = vi.mocked(libCacheImport).mock.results[0].value;
|
||||
expect(libCacheReturnedFn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test("should throw ResourceNotFoundError if environment does not exist", async () => {
|
||||
vi.mocked(prisma.environment.findUnique).mockResolvedValue(null);
|
||||
|
||||
await expect(getProjectIdIfEnvironmentExists(mockEnvironmentId)).rejects.toThrow(ResourceNotFoundError);
|
||||
expect(prisma.environment.findUnique).toHaveBeenCalledWith({
|
||||
where: { id: mockEnvironmentId },
|
||||
select: { projectId: true },
|
||||
});
|
||||
expect(libCacheImport).toHaveBeenCalledTimes(1);
|
||||
// Check that the function returned by libCacheImport was called
|
||||
const libCacheReturnedFn = vi.mocked(libCacheImport).mock.results[0].value;
|
||||
expect(libCacheReturnedFn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getEnvironment", () => {
|
||||
beforeEach(() => {
|
||||
vi.resetAllMocks();
|
||||
});
|
||||
|
||||
test("should return environment if it exists", async () => {
|
||||
const mockEnvData = { id: mockEnvironmentId, type: "production" as const };
|
||||
vi.mocked(prisma.environment.findUnique).mockResolvedValue(mockEnvData);
|
||||
|
||||
const result = await getEnvironment(mockEnvironmentId);
|
||||
|
||||
expect(result).toEqual(mockEnvData);
|
||||
expect(validateInputs).toHaveBeenCalledWith([mockEnvironmentId, expect.any(Object)]);
|
||||
expect(prisma.environment.findUnique).toHaveBeenCalledWith({
|
||||
where: { id: mockEnvironmentId },
|
||||
select: { id: true, type: true },
|
||||
});
|
||||
expect(libCacheImport).toHaveBeenCalledTimes(1);
|
||||
// Check that the function returned by libCacheImport was called
|
||||
const libCacheReturnedFn = vi.mocked(libCacheImport).mock.results[0].value;
|
||||
expect(libCacheReturnedFn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test("should return null if environment does not exist (as per select, though findUnique would return null directly)", async () => {
|
||||
vi.mocked(prisma.environment.findUnique).mockResolvedValue(null);
|
||||
|
||||
const result = await getEnvironment(mockEnvironmentId);
|
||||
expect(result).toBeNull();
|
||||
expect(validateInputs).toHaveBeenCalledWith([mockEnvironmentId, expect.any(Object)]);
|
||||
expect(prisma.environment.findUnique).toHaveBeenCalledWith({
|
||||
where: { id: mockEnvironmentId },
|
||||
select: { id: true, type: true },
|
||||
});
|
||||
// Additional checks for cache mocks
|
||||
expect(libCacheImport).toHaveBeenCalledTimes(1);
|
||||
// Check that the function returned by libCacheImport was called
|
||||
const libCacheReturnedFn = vi.mocked(libCacheImport).mock.results[0].value;
|
||||
expect(libCacheReturnedFn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test("should throw DatabaseError if PrismaClientKnownRequestError occurs", async () => {
|
||||
const prismaError = new Prisma.PrismaClientKnownRequestError("Test Prisma Error", {
|
||||
code: "P2001",
|
||||
clientVersion: "2.0.0", // Ensure clientVersion is a string
|
||||
});
|
||||
vi.mocked(prisma.environment.findUnique).mockRejectedValue(prismaError);
|
||||
|
||||
await expect(getEnvironment(mockEnvironmentId)).rejects.toThrow(DatabaseError);
|
||||
expect(validateInputs).toHaveBeenCalledWith([mockEnvironmentId, expect.any(Object)]);
|
||||
expect(logger.error).toHaveBeenCalledWith(prismaError, "Error fetching environment");
|
||||
expect(libCacheImport).toHaveBeenCalledTimes(1);
|
||||
// Check that the function returned by libCacheImport was called
|
||||
const libCacheReturnedFn = vi.mocked(libCacheImport).mock.results[0].value;
|
||||
expect(libCacheReturnedFn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test("should re-throw error if a generic error occurs", async () => {
|
||||
const genericError = new Error("Test Generic Error");
|
||||
vi.mocked(prisma.environment.findUnique).mockRejectedValue(genericError);
|
||||
|
||||
await expect(getEnvironment(mockEnvironmentId)).rejects.toThrow(genericError);
|
||||
expect(validateInputs).toHaveBeenCalledWith([mockEnvironmentId, expect.any(Object)]);
|
||||
expect(logger.error).not.toHaveBeenCalled();
|
||||
expect(libCacheImport).toHaveBeenCalledTimes(1);
|
||||
// Check that the function returned by libCacheImport was called
|
||||
const libCacheReturnedFn = vi.mocked(libCacheImport).mock.results[0].value;
|
||||
expect(libCacheReturnedFn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
// Remove the global afterEach if it was only for vi.useRealTimers() and no fake timers are used.
|
||||
// vi.resetAllMocks() in beforeEach is generally the preferred way to ensure test isolation for mocks.
|
||||
// The specific afterEach(() => { vi.clearAllMocks(); }) inside each describe block can also be removed.
|
||||
// For consistency, I'll remove the afterEach blocks from the describe suites.
|
||||
817
apps/web/modules/survey/list/lib/survey.test.ts
Normal file
817
apps/web/modules/survey/list/lib/survey.test.ts
Normal file
@@ -0,0 +1,817 @@
|
||||
import { actionClassCache } from "@/lib/actionClass/cache";
|
||||
import { cache } from "@/lib/cache";
|
||||
import { segmentCache } from "@/lib/cache/segment";
|
||||
import { projectCache } from "@/lib/project/cache";
|
||||
import { responseCache } from "@/lib/response/cache";
|
||||
import { surveyCache } from "@/lib/survey/cache";
|
||||
import { checkForInvalidImagesInQuestions } from "@/lib/survey/utils";
|
||||
import { validateInputs } from "@/lib/utils/validate";
|
||||
import { buildOrderByClause, buildWhereClause } from "@/modules/survey/lib/utils";
|
||||
import { doesEnvironmentExist } from "@/modules/survey/list/lib/environment";
|
||||
import { getProjectWithLanguagesByEnvironmentId } from "@/modules/survey/list/lib/project";
|
||||
import { createId } from "@paralleldrive/cuid2";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { cache as reactCache } from "react";
|
||||
import { beforeEach, describe, expect, test, vi } from "vitest";
|
||||
import { prisma } from "@formbricks/database";
|
||||
import { logger } from "@formbricks/logger";
|
||||
import { TActionClassType } from "@formbricks/types/action-classes";
|
||||
import { DatabaseError, ResourceNotFoundError } from "@formbricks/types/errors";
|
||||
import { TProjectWithLanguages, TSurvey } from "../types/surveys";
|
||||
// Import the module to be tested
|
||||
import {
|
||||
copySurveyToOtherEnvironment,
|
||||
deleteSurvey,
|
||||
getSurvey,
|
||||
getSurveyCount,
|
||||
getSurveys,
|
||||
getSurveysSortedByRelevance,
|
||||
surveySelect,
|
||||
} from "./survey";
|
||||
|
||||
// Mocked modules
|
||||
vi.mock("@/lib/cache", () => ({
|
||||
cache: vi.fn((fn, _options) => fn), // Return the function itself, not its execution result
|
||||
}));
|
||||
|
||||
vi.mock("react", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("react")>();
|
||||
return {
|
||||
...actual,
|
||||
cache: vi.fn((fn) => fn), // Return the function itself, as reactCache is a HOF
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("@/lib/actionClass/cache", () => ({
|
||||
actionClassCache: {
|
||||
revalidate: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock("@/lib/cache/segment", () => ({
|
||||
segmentCache: {
|
||||
revalidate: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock("@/lib/project/cache", () => ({
|
||||
projectCache: {
|
||||
revalidate: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock("@/lib/response/cache", () => ({
|
||||
responseCache: {
|
||||
revalidate: vi.fn(),
|
||||
tag: {
|
||||
byEnvironmentId: vi.fn((id) => `response-env-${id}`),
|
||||
bySurveyId: vi.fn((id) => `response-survey-${id}`),
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock("@/lib/survey/cache", () => ({
|
||||
surveyCache: {
|
||||
revalidate: vi.fn(),
|
||||
tag: {
|
||||
byEnvironmentId: vi.fn((id) => `survey-env-${id}`),
|
||||
byId: vi.fn((id) => `survey-${id}`),
|
||||
byActionClassId: vi.fn((id) => `survey-actionclass-${id}`),
|
||||
byResultShareKey: vi.fn((key) => `survey-resultsharekey-${key}`),
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock("@/lib/survey/utils", () => ({
|
||||
checkForInvalidImagesInQuestions: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("@/lib/utils/validate", () => ({
|
||||
validateInputs: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("@/modules/survey/lib/utils", () => ({
|
||||
buildOrderByClause: vi.fn((sortBy) => (sortBy ? [{ [sortBy]: "desc" }] : [])),
|
||||
buildWhereClause: vi.fn((filterCriteria) => (filterCriteria ? { name: filterCriteria.name } : {})),
|
||||
}));
|
||||
|
||||
vi.mock("@/modules/survey/list/lib/environment", () => ({
|
||||
doesEnvironmentExist: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("@/modules/survey/list/lib/project", () => ({
|
||||
getProjectWithLanguagesByEnvironmentId: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("@paralleldrive/cuid2", () => ({
|
||||
createId: vi.fn(() => "new_cuid2_id"),
|
||||
}));
|
||||
|
||||
vi.mock("@formbricks/database", () => ({
|
||||
prisma: {
|
||||
survey: {
|
||||
findMany: vi.fn(),
|
||||
findUnique: vi.fn(),
|
||||
count: vi.fn(),
|
||||
delete: vi.fn(),
|
||||
create: vi.fn(),
|
||||
},
|
||||
segment: {
|
||||
delete: vi.fn(),
|
||||
findFirst: vi.fn(),
|
||||
},
|
||||
language: {
|
||||
// Added for language connectOrCreate in copySurvey
|
||||
findUnique: vi.fn(),
|
||||
create: vi.fn(),
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock("@formbricks/logger", () => ({
|
||||
logger: {
|
||||
error: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
// Helper to reset mocks
|
||||
const resetMocks = () => {
|
||||
vi.mocked(cache).mockClear();
|
||||
vi.mocked(reactCache).mockClear();
|
||||
vi.mocked(actionClassCache.revalidate).mockClear();
|
||||
vi.mocked(segmentCache.revalidate).mockClear();
|
||||
vi.mocked(projectCache.revalidate).mockClear();
|
||||
vi.mocked(responseCache.revalidate).mockClear();
|
||||
vi.mocked(surveyCache.revalidate).mockClear();
|
||||
vi.mocked(checkForInvalidImagesInQuestions).mockClear();
|
||||
vi.mocked(validateInputs).mockClear();
|
||||
vi.mocked(buildOrderByClause).mockClear();
|
||||
vi.mocked(buildWhereClause).mockClear();
|
||||
vi.mocked(doesEnvironmentExist).mockClear();
|
||||
vi.mocked(getProjectWithLanguagesByEnvironmentId).mockClear();
|
||||
vi.mocked(createId).mockClear();
|
||||
vi.mocked(prisma.survey.findMany).mockReset();
|
||||
vi.mocked(prisma.survey.findUnique).mockReset();
|
||||
vi.mocked(prisma.survey.count).mockReset();
|
||||
vi.mocked(prisma.survey.delete).mockReset();
|
||||
vi.mocked(prisma.survey.create).mockReset();
|
||||
vi.mocked(prisma.segment.delete).mockReset();
|
||||
vi.mocked(prisma.segment.findFirst).mockReset();
|
||||
vi.mocked(logger.error).mockClear();
|
||||
};
|
||||
|
||||
const makePrismaKnownError = () =>
|
||||
new Prisma.PrismaClientKnownRequestError("Test Prisma Error", {
|
||||
code: "P2001",
|
||||
clientVersion: "test",
|
||||
meta: {},
|
||||
});
|
||||
|
||||
// Sample data
|
||||
const environmentId = "env_1";
|
||||
const surveyId = "survey_1";
|
||||
const userId = "user_1";
|
||||
|
||||
const mockSurveyPrisma = {
|
||||
id: surveyId,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
name: "Test Survey",
|
||||
type: "web" as any,
|
||||
creator: { name: "Test User" },
|
||||
status: "draft" as any,
|
||||
singleUse: null,
|
||||
environmentId,
|
||||
_count: { responses: 10 },
|
||||
};
|
||||
|
||||
describe("getSurveyCount", () => {
|
||||
beforeEach(() => {
|
||||
resetMocks();
|
||||
});
|
||||
|
||||
test("should return survey count successfully", async () => {
|
||||
vi.mocked(prisma.survey.count).mockResolvedValue(5);
|
||||
const count = await getSurveyCount(environmentId);
|
||||
expect(count).toBe(5);
|
||||
expect(prisma.survey.count).toHaveBeenCalledWith({
|
||||
where: { environmentId },
|
||||
});
|
||||
expect(validateInputs).toHaveBeenCalledWith([environmentId, expect.any(Object)]);
|
||||
});
|
||||
|
||||
test("should throw DatabaseError on Prisma error", async () => {
|
||||
const prismaError = makePrismaKnownError();
|
||||
vi.mocked(prisma.survey.count).mockRejectedValue(prismaError);
|
||||
await expect(getSurveyCount(environmentId)).rejects.toThrow(DatabaseError);
|
||||
expect(logger.error).toHaveBeenCalledWith(prismaError, "Error getting survey count");
|
||||
});
|
||||
|
||||
test("should rethrow unknown error", async () => {
|
||||
const unknownError = new Error("Unknown error");
|
||||
vi.mocked(prisma.survey.count).mockRejectedValue(unknownError);
|
||||
await expect(getSurveyCount(environmentId)).rejects.toThrow(unknownError);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getSurvey", () => {
|
||||
beforeEach(() => {
|
||||
resetMocks();
|
||||
});
|
||||
|
||||
test("should return a survey if found", async () => {
|
||||
const prismaSurvey = { ...mockSurveyPrisma, _count: { responses: 5 } };
|
||||
vi.mocked(prisma.survey.findUnique).mockResolvedValue(prismaSurvey);
|
||||
|
||||
const survey = await getSurvey(surveyId);
|
||||
|
||||
expect(survey).toEqual({ ...prismaSurvey, responseCount: 5 });
|
||||
expect(prisma.survey.findUnique).toHaveBeenCalledWith({
|
||||
where: { id: surveyId },
|
||||
select: surveySelect,
|
||||
});
|
||||
expect(surveyCache.tag.byId).toHaveBeenCalledWith(surveyId);
|
||||
expect(responseCache.tag.bySurveyId).toHaveBeenCalledWith(surveyId);
|
||||
});
|
||||
|
||||
test("should return null if survey not found", async () => {
|
||||
vi.mocked(prisma.survey.findUnique).mockResolvedValue(null);
|
||||
const survey = await getSurvey(surveyId);
|
||||
expect(survey).toBeNull();
|
||||
});
|
||||
|
||||
test("should throw DatabaseError on Prisma error", async () => {
|
||||
const prismaError = makePrismaKnownError();
|
||||
vi.mocked(prisma.survey.findUnique).mockRejectedValue(prismaError);
|
||||
await expect(getSurvey(surveyId)).rejects.toThrow(DatabaseError);
|
||||
expect(logger.error).toHaveBeenCalledWith(prismaError, "Error getting survey");
|
||||
});
|
||||
|
||||
test("should rethrow unknown error", async () => {
|
||||
const unknownError = new Error("Unknown error");
|
||||
vi.mocked(prisma.survey.findUnique).mockRejectedValue(unknownError);
|
||||
await expect(getSurvey(surveyId)).rejects.toThrow(unknownError);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getSurveys", () => {
|
||||
beforeEach(() => {
|
||||
resetMocks();
|
||||
});
|
||||
|
||||
const mockPrismaSurveys = [
|
||||
{ ...mockSurveyPrisma, id: "s1", name: "Survey 1", _count: { responses: 1 } },
|
||||
{ ...mockSurveyPrisma, id: "s2", name: "Survey 2", _count: { responses: 2 } },
|
||||
];
|
||||
const expectedSurveys: TSurvey[] = mockPrismaSurveys.map((s) => ({
|
||||
...s,
|
||||
responseCount: s._count.responses,
|
||||
}));
|
||||
|
||||
test("should return surveys with default parameters", async () => {
|
||||
vi.mocked(prisma.survey.findMany).mockResolvedValue(mockPrismaSurveys);
|
||||
const surveys = await getSurveys(environmentId);
|
||||
|
||||
expect(surveys).toEqual(expectedSurveys);
|
||||
expect(prisma.survey.findMany).toHaveBeenCalledWith({
|
||||
where: { environmentId, ...buildWhereClause() },
|
||||
select: surveySelect,
|
||||
orderBy: buildOrderByClause(),
|
||||
take: undefined,
|
||||
skip: undefined,
|
||||
});
|
||||
expect(surveyCache.tag.byEnvironmentId).toHaveBeenCalledWith(environmentId);
|
||||
expect(responseCache.tag.byEnvironmentId).toHaveBeenCalledWith(environmentId);
|
||||
});
|
||||
|
||||
test("should return surveys with limit and offset", async () => {
|
||||
vi.mocked(prisma.survey.findMany).mockResolvedValue([mockPrismaSurveys[0]]);
|
||||
const surveys = await getSurveys(environmentId, 1, 1);
|
||||
|
||||
expect(surveys).toEqual([expectedSurveys[0]]);
|
||||
expect(prisma.survey.findMany).toHaveBeenCalledWith({
|
||||
where: { environmentId, ...buildWhereClause() },
|
||||
select: surveySelect,
|
||||
orderBy: buildOrderByClause(),
|
||||
take: 1,
|
||||
skip: 1,
|
||||
});
|
||||
});
|
||||
|
||||
test("should return surveys with filterCriteria", async () => {
|
||||
const filterCriteria: any = { name: "Test", sortBy: "createdAt" };
|
||||
vi.mocked(buildWhereClause).mockReturnValue({ AND: [{ name: { contains: "Test" } }] }); // Mock correct return type
|
||||
vi.mocked(buildOrderByClause).mockReturnValue([{ createdAt: "desc" }]); // Mock specific return
|
||||
vi.mocked(prisma.survey.findMany).mockResolvedValue(mockPrismaSurveys);
|
||||
|
||||
const surveys = await getSurveys(environmentId, undefined, undefined, filterCriteria);
|
||||
|
||||
expect(surveys).toEqual(expectedSurveys);
|
||||
expect(buildWhereClause).toHaveBeenCalledWith(filterCriteria);
|
||||
expect(buildOrderByClause).toHaveBeenCalledWith("createdAt");
|
||||
expect(prisma.survey.findMany).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
where: { environmentId, AND: [{ name: { contains: "Test" } }] }, // Check with correct structure
|
||||
orderBy: [{ createdAt: "desc" }], // Check the mocked order by
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
test("should throw DatabaseError on Prisma error", async () => {
|
||||
const prismaError = makePrismaKnownError();
|
||||
vi.mocked(prisma.survey.findMany).mockRejectedValue(prismaError);
|
||||
await expect(getSurveys(environmentId)).rejects.toThrow(DatabaseError);
|
||||
expect(logger.error).toHaveBeenCalledWith(prismaError, "Error getting surveys");
|
||||
});
|
||||
|
||||
test("should rethrow unknown error", async () => {
|
||||
const unknownError = new Error("Unknown error");
|
||||
vi.mocked(prisma.survey.findMany).mockRejectedValue(unknownError);
|
||||
await expect(getSurveys(environmentId)).rejects.toThrow(unknownError);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getSurveysSortedByRelevance", () => {
|
||||
beforeEach(() => {
|
||||
resetMocks();
|
||||
});
|
||||
|
||||
const mockInProgressPrisma = {
|
||||
...mockSurveyPrisma,
|
||||
id: "s_inprog",
|
||||
status: "inProgress" as any,
|
||||
_count: { responses: 3 },
|
||||
};
|
||||
const mockOtherPrisma = {
|
||||
...mockSurveyPrisma,
|
||||
id: "s_other",
|
||||
status: "completed" as any,
|
||||
_count: { responses: 5 },
|
||||
};
|
||||
|
||||
const expectedInProgressSurvey: TSurvey = { ...mockInProgressPrisma, responseCount: 3 };
|
||||
const expectedOtherSurvey: TSurvey = { ...mockOtherPrisma, responseCount: 5 };
|
||||
|
||||
test("should fetch inProgress surveys first, then others if limit not met", async () => {
|
||||
vi.mocked(prisma.survey.count).mockResolvedValue(1); // 1 inProgress survey
|
||||
vi.mocked(prisma.survey.findMany)
|
||||
.mockResolvedValueOnce([mockInProgressPrisma]) // In-progress surveys
|
||||
.mockResolvedValueOnce([mockOtherPrisma]); // Additional surveys
|
||||
|
||||
const surveys = await getSurveysSortedByRelevance(environmentId, 2, 0);
|
||||
|
||||
expect(surveys).toEqual([expectedInProgressSurvey, expectedOtherSurvey]);
|
||||
expect(prisma.survey.count).toHaveBeenCalledWith({
|
||||
where: { environmentId, status: "inProgress", ...buildWhereClause() },
|
||||
});
|
||||
expect(prisma.survey.findMany).toHaveBeenNthCalledWith(1, {
|
||||
where: { environmentId, status: "inProgress", ...buildWhereClause() },
|
||||
select: surveySelect,
|
||||
orderBy: buildOrderByClause("updatedAt"),
|
||||
take: 2,
|
||||
skip: 0,
|
||||
});
|
||||
expect(prisma.survey.findMany).toHaveBeenNthCalledWith(2, {
|
||||
where: { environmentId, status: { not: "inProgress" }, ...buildWhereClause() },
|
||||
select: surveySelect,
|
||||
orderBy: buildOrderByClause("updatedAt"),
|
||||
take: 1,
|
||||
skip: 0,
|
||||
});
|
||||
});
|
||||
|
||||
test("should only fetch inProgress surveys if limit is met", async () => {
|
||||
vi.mocked(prisma.survey.count).mockResolvedValue(1);
|
||||
vi.mocked(prisma.survey.findMany).mockResolvedValueOnce([mockInProgressPrisma]);
|
||||
|
||||
const surveys = await getSurveysSortedByRelevance(environmentId, 1, 0);
|
||||
expect(surveys).toEqual([expectedInProgressSurvey]);
|
||||
expect(prisma.survey.findMany).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test("should throw DatabaseError on Prisma error", async () => {
|
||||
const prismaError = makePrismaKnownError();
|
||||
vi.mocked(prisma.survey.count).mockRejectedValue(prismaError);
|
||||
await expect(getSurveysSortedByRelevance(environmentId)).rejects.toThrow(DatabaseError);
|
||||
expect(logger.error).toHaveBeenCalledWith(prismaError, "Error getting surveys sorted by relevance");
|
||||
|
||||
resetMocks(); // Reset for the next part of the test
|
||||
vi.mocked(prisma.survey.count).mockResolvedValue(0); // Make count succeed
|
||||
vi.mocked(prisma.survey.findMany).mockRejectedValue(prismaError); // Error on findMany
|
||||
await expect(getSurveysSortedByRelevance(environmentId)).rejects.toThrow(DatabaseError);
|
||||
});
|
||||
|
||||
test("should rethrow unknown error", async () => {
|
||||
const unknownError = new Error("Unknown error");
|
||||
vi.mocked(prisma.survey.count).mockRejectedValue(unknownError);
|
||||
await expect(getSurveysSortedByRelevance(environmentId)).rejects.toThrow(unknownError);
|
||||
});
|
||||
});
|
||||
|
||||
describe("deleteSurvey", () => {
|
||||
beforeEach(() => {
|
||||
resetMocks();
|
||||
});
|
||||
|
||||
const mockDeletedSurveyData = {
|
||||
id: surveyId,
|
||||
environmentId,
|
||||
segment: null,
|
||||
type: "web" as any,
|
||||
resultShareKey: "sharekey1",
|
||||
triggers: [{ actionClass: { id: "action_1" } }],
|
||||
};
|
||||
|
||||
test("should delete a survey and revalidate caches (no private segment)", async () => {
|
||||
vi.mocked(prisma.survey.delete).mockResolvedValue(mockDeletedSurveyData as any);
|
||||
const result = await deleteSurvey(surveyId);
|
||||
|
||||
expect(result).toBe(true);
|
||||
expect(prisma.survey.delete).toHaveBeenCalledWith({
|
||||
where: { id: surveyId },
|
||||
select: expect.objectContaining({ id: true, environmentId: true, segment: expect.anything() }),
|
||||
});
|
||||
expect(responseCache.revalidate).toHaveBeenCalledWith({ surveyId, environmentId });
|
||||
expect(surveyCache.revalidate).toHaveBeenCalledWith({
|
||||
id: surveyId,
|
||||
environmentId,
|
||||
resultShareKey: "sharekey1",
|
||||
});
|
||||
expect(surveyCache.revalidate).toHaveBeenCalledWith({ actionClassId: "action_1" });
|
||||
expect(prisma.segment.delete).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test("should revalidate segment cache for non-private segment if segment exists", async () => {
|
||||
const surveyWithPublicSegment = {
|
||||
...mockDeletedSurveyData,
|
||||
segment: { id: "segment_public_1", isPrivate: false },
|
||||
};
|
||||
vi.mocked(prisma.survey.delete).mockResolvedValue(surveyWithPublicSegment as any);
|
||||
|
||||
await deleteSurvey(surveyId);
|
||||
|
||||
expect(prisma.segment.delete).not.toHaveBeenCalled();
|
||||
expect(segmentCache.revalidate).toHaveBeenCalledWith({ id: "segment_public_1", environmentId });
|
||||
});
|
||||
|
||||
test("should throw DatabaseError on Prisma error", async () => {
|
||||
const prismaError = makePrismaKnownError();
|
||||
vi.mocked(prisma.survey.delete).mockRejectedValue(prismaError);
|
||||
await expect(deleteSurvey(surveyId)).rejects.toThrow(DatabaseError);
|
||||
expect(logger.error).toHaveBeenCalledWith(prismaError, "Error deleting survey");
|
||||
});
|
||||
|
||||
test("should rethrow unknown error", async () => {
|
||||
const unknownError = new Error("Unknown error");
|
||||
vi.mocked(prisma.survey.delete).mockRejectedValue(unknownError);
|
||||
await expect(deleteSurvey(surveyId)).rejects.toThrow(unknownError);
|
||||
});
|
||||
});
|
||||
|
||||
const mockExistingSurveyDetails = {
|
||||
name: "Original Survey",
|
||||
type: "web" as any,
|
||||
languages: [{ default: true, enabled: true, language: { code: "en", alias: "English" } }],
|
||||
welcomeCard: { enabled: true, headline: { default: "Welcome!" } },
|
||||
questions: [{ id: "q1", type: "openText", headline: { default: "Question 1" } }],
|
||||
endings: [{ type: "default", headline: { default: "Thanks!" } }],
|
||||
variables: [{ id: "var1", name: "Var One" }],
|
||||
hiddenFields: { enabled: true, fieldIds: ["hf1"] },
|
||||
surveyClosedMessage: { enabled: false },
|
||||
singleUse: { enabled: false },
|
||||
projectOverwrites: null,
|
||||
styling: { theme: {} },
|
||||
segment: null,
|
||||
followUps: [{ name: "Follow Up 1", trigger: {}, action: {} }],
|
||||
triggers: [
|
||||
{
|
||||
actionClass: {
|
||||
id: "ac1",
|
||||
name: "Code Action",
|
||||
environmentId,
|
||||
description: "",
|
||||
type: "code" as TActionClassType,
|
||||
key: "code_action_key",
|
||||
noCodeConfig: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
actionClass: {
|
||||
id: "ac2",
|
||||
name: "No-Code Action",
|
||||
environmentId,
|
||||
description: "",
|
||||
type: "noCode" as TActionClassType,
|
||||
key: null,
|
||||
noCodeConfig: { type: "url" },
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
describe("copySurveyToOtherEnvironment", () => {
|
||||
const targetEnvironmentId = "env_target";
|
||||
const sourceProjectId = "proj_source";
|
||||
const targetProjectId = "proj_target";
|
||||
|
||||
const mockSourceProject: TProjectWithLanguages = {
|
||||
id: sourceProjectId,
|
||||
languages: [{ code: "en", alias: "English" }],
|
||||
};
|
||||
const mockTargetProject: TProjectWithLanguages = {
|
||||
id: targetProjectId,
|
||||
languages: [{ code: "en", alias: "English" }],
|
||||
};
|
||||
|
||||
const mockNewSurveyResult = {
|
||||
id: "new_cuid2_id",
|
||||
environmentId: targetEnvironmentId,
|
||||
segment: null,
|
||||
triggers: [
|
||||
{ actionClass: { id: "new_ac1", name: "Code Action", environmentId: targetEnvironmentId } },
|
||||
{ actionClass: { id: "new_ac2", name: "No-Code Action", environmentId: targetEnvironmentId } },
|
||||
],
|
||||
languages: [{ language: { code: "en" } }],
|
||||
resultShareKey: null,
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
resetMocks();
|
||||
vi.mocked(createId).mockReturnValue("new_cuid2_id");
|
||||
vi.mocked(prisma.survey.findUnique).mockResolvedValue(mockExistingSurveyDetails as any);
|
||||
vi.mocked(doesEnvironmentExist).mockResolvedValue(environmentId);
|
||||
vi.mocked(getProjectWithLanguagesByEnvironmentId)
|
||||
.mockResolvedValueOnce(mockSourceProject)
|
||||
.mockResolvedValueOnce(mockTargetProject);
|
||||
vi.mocked(prisma.survey.create).mockResolvedValue(mockNewSurveyResult as any);
|
||||
vi.mocked(prisma.segment.findFirst).mockResolvedValue(null);
|
||||
});
|
||||
|
||||
test("should copy survey to a different environment successfully", async () => {
|
||||
const newSurvey = await copySurveyToOtherEnvironment(
|
||||
environmentId,
|
||||
surveyId,
|
||||
targetEnvironmentId,
|
||||
userId
|
||||
);
|
||||
|
||||
expect(newSurvey).toBeDefined();
|
||||
expect(prisma.survey.create).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
data: expect.objectContaining({
|
||||
id: "new_cuid2_id",
|
||||
name: `${mockExistingSurveyDetails.name} (copy)`,
|
||||
environment: { connect: { id: targetEnvironmentId } },
|
||||
creator: { connect: { id: userId } },
|
||||
status: "draft",
|
||||
triggers: {
|
||||
create: [
|
||||
expect.objectContaining({
|
||||
actionClass: {
|
||||
connectOrCreate: {
|
||||
where: {
|
||||
key_environmentId: { key: "code_action_key", environmentId: targetEnvironmentId },
|
||||
},
|
||||
create: expect.objectContaining({ name: "Code Action", key: "code_action_key" }),
|
||||
},
|
||||
},
|
||||
}),
|
||||
expect.objectContaining({
|
||||
actionClass: {
|
||||
connectOrCreate: {
|
||||
where: {
|
||||
name_environmentId: { name: "No-Code Action", environmentId: targetEnvironmentId },
|
||||
},
|
||||
create: expect.objectContaining({
|
||||
name: "No-Code Action",
|
||||
noCodeConfig: { type: "url" },
|
||||
}),
|
||||
},
|
||||
},
|
||||
}),
|
||||
],
|
||||
},
|
||||
}),
|
||||
})
|
||||
);
|
||||
expect(checkForInvalidImagesInQuestions).toHaveBeenCalledWith(mockExistingSurveyDetails.questions);
|
||||
expect(actionClassCache.revalidate).toHaveBeenCalledTimes(2);
|
||||
expect(surveyCache.revalidate).toHaveBeenCalledWith(expect.objectContaining({ id: "new_cuid2_id" }));
|
||||
expect(surveyCache.revalidate).toHaveBeenCalledWith({ actionClassId: "ac1" });
|
||||
expect(surveyCache.revalidate).toHaveBeenCalledWith({ actionClassId: "ac2" });
|
||||
});
|
||||
|
||||
test("should copy survey to the same environment successfully", async () => {
|
||||
vi.mocked(getProjectWithLanguagesByEnvironmentId).mockReset();
|
||||
vi.mocked(getProjectWithLanguagesByEnvironmentId).mockResolvedValue(mockSourceProject);
|
||||
|
||||
await copySurveyToOtherEnvironment(environmentId, surveyId, environmentId, userId);
|
||||
|
||||
expect(getProjectWithLanguagesByEnvironmentId).toHaveBeenCalledTimes(1);
|
||||
expect(prisma.survey.create).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
data: expect.objectContaining({
|
||||
environment: { connect: { id: environmentId } },
|
||||
triggers: {
|
||||
create: [
|
||||
{ actionClass: { connect: { id: "ac1" } } },
|
||||
{ actionClass: { connect: { id: "ac2" } } },
|
||||
],
|
||||
},
|
||||
}),
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
test("should handle private segment: create new private segment in target", async () => {
|
||||
const surveyWithPrivateSegment = {
|
||||
...mockExistingSurveyDetails,
|
||||
segment: { id: "seg_private", isPrivate: true, filters: [{ type: "user", value: "test" }] },
|
||||
};
|
||||
vi.mocked(prisma.survey.findUnique).mockResolvedValue(surveyWithPrivateSegment as any);
|
||||
|
||||
const mockNewSurveyWithSegment = { ...mockNewSurveyResult, segment: { id: "new_seg_private" } };
|
||||
vi.mocked(prisma.survey.create).mockResolvedValue(mockNewSurveyWithSegment as any);
|
||||
|
||||
await copySurveyToOtherEnvironment(environmentId, surveyId, targetEnvironmentId, userId);
|
||||
|
||||
expect(prisma.survey.create).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
data: expect.objectContaining({
|
||||
segment: {
|
||||
create: {
|
||||
title: "new_cuid2_id",
|
||||
isPrivate: true,
|
||||
filters: surveyWithPrivateSegment.segment.filters,
|
||||
environment: { connect: { id: targetEnvironmentId } },
|
||||
},
|
||||
},
|
||||
}),
|
||||
})
|
||||
);
|
||||
expect(segmentCache.revalidate).toHaveBeenCalledWith({
|
||||
id: "new_seg_private",
|
||||
environmentId: targetEnvironmentId,
|
||||
});
|
||||
});
|
||||
|
||||
test("should handle public segment: connect if same env, create new if different env (no existing in target)", async () => {
|
||||
const surveyWithPublicSegment = {
|
||||
...mockExistingSurveyDetails,
|
||||
segment: { id: "seg_public", title: "Public Segment", isPrivate: false, filters: [] },
|
||||
};
|
||||
vi.mocked(prisma.survey.findUnique).mockResolvedValue(surveyWithPublicSegment as any);
|
||||
vi.mocked(getProjectWithLanguagesByEnvironmentId)
|
||||
.mockReset() // for same env part
|
||||
.mockResolvedValueOnce(mockSourceProject);
|
||||
|
||||
// Case 1: Same environment
|
||||
await copySurveyToOtherEnvironment(environmentId, surveyId, environmentId, userId); // target is same
|
||||
expect(prisma.survey.create).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
data: expect.objectContaining({
|
||||
segment: { connect: { id: "seg_public" } },
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
// Reset for different env part
|
||||
resetMocks();
|
||||
vi.mocked(createId).mockReturnValue("new_cuid2_id");
|
||||
vi.mocked(prisma.survey.findUnique).mockResolvedValue(surveyWithPublicSegment as any);
|
||||
vi.mocked(doesEnvironmentExist).mockResolvedValue(environmentId);
|
||||
vi.mocked(getProjectWithLanguagesByEnvironmentId)
|
||||
.mockResolvedValueOnce(mockSourceProject)
|
||||
.mockResolvedValueOnce(mockTargetProject);
|
||||
vi.mocked(prisma.survey.create).mockResolvedValue(mockNewSurveyResult as any);
|
||||
vi.mocked(prisma.segment.findFirst).mockResolvedValue(null); // No existing public segment with same title in target
|
||||
|
||||
// Case 2: Different environment, segment with same title does not exist in target
|
||||
await copySurveyToOtherEnvironment(environmentId, surveyId, targetEnvironmentId, userId);
|
||||
expect(prisma.survey.create).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
data: expect.objectContaining({
|
||||
segment: {
|
||||
create: {
|
||||
title: "Public Segment",
|
||||
isPrivate: false,
|
||||
filters: [],
|
||||
environment: { connect: { id: targetEnvironmentId } },
|
||||
},
|
||||
},
|
||||
}),
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
test("should handle public segment: create new with appended timestamp if different env and segment with same title exists in target", async () => {
|
||||
const surveyWithPublicSegment = {
|
||||
...mockExistingSurveyDetails,
|
||||
segment: { id: "seg_public", title: "Public Segment", isPrivate: false, filters: [] },
|
||||
};
|
||||
resetMocks();
|
||||
vi.mocked(createId).mockReturnValue("new_cuid2_id");
|
||||
vi.mocked(prisma.survey.findUnique).mockResolvedValue(surveyWithPublicSegment as any);
|
||||
vi.mocked(doesEnvironmentExist).mockResolvedValue(environmentId);
|
||||
vi.mocked(getProjectWithLanguagesByEnvironmentId)
|
||||
.mockResolvedValueOnce(mockSourceProject)
|
||||
.mockResolvedValueOnce(mockTargetProject);
|
||||
vi.mocked(prisma.survey.create).mockResolvedValue(mockNewSurveyResult as any);
|
||||
vi.mocked(prisma.segment.findFirst).mockResolvedValue({ id: "existing_target_seg" } as any); // Segment with same title EXISTS
|
||||
const dateNowSpy = vi.spyOn(Date, "now").mockReturnValue(1234567890);
|
||||
|
||||
await copySurveyToOtherEnvironment(environmentId, surveyId, targetEnvironmentId, userId);
|
||||
expect(prisma.survey.create).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
data: expect.objectContaining({
|
||||
segment: {
|
||||
create: {
|
||||
title: `Public Segment-1234567890`,
|
||||
isPrivate: false,
|
||||
filters: [],
|
||||
environment: { connect: { id: targetEnvironmentId } },
|
||||
},
|
||||
},
|
||||
}),
|
||||
})
|
||||
);
|
||||
dateNowSpy.mockRestore();
|
||||
});
|
||||
|
||||
test("should throw ResourceNotFoundError if source environment not found", async () => {
|
||||
vi.mocked(doesEnvironmentExist).mockResolvedValueOnce(null);
|
||||
await expect(
|
||||
copySurveyToOtherEnvironment(environmentId, surveyId, targetEnvironmentId, userId)
|
||||
).rejects.toThrow(new ResourceNotFoundError("Environment", environmentId));
|
||||
});
|
||||
|
||||
test("should throw ResourceNotFoundError if source project not found", async () => {
|
||||
vi.mocked(getProjectWithLanguagesByEnvironmentId).mockReset().mockResolvedValueOnce(null);
|
||||
await expect(
|
||||
copySurveyToOtherEnvironment(environmentId, surveyId, targetEnvironmentId, userId)
|
||||
).rejects.toThrow(new ResourceNotFoundError("Project", environmentId));
|
||||
});
|
||||
|
||||
test("should throw ResourceNotFoundError if existing survey not found", async () => {
|
||||
vi.mocked(prisma.survey.findUnique).mockResolvedValue(null);
|
||||
await expect(
|
||||
copySurveyToOtherEnvironment(environmentId, surveyId, targetEnvironmentId, userId)
|
||||
).rejects.toThrow(new ResourceNotFoundError("Survey", surveyId));
|
||||
});
|
||||
|
||||
test("should throw ResourceNotFoundError if target environment not found (different env copy)", async () => {
|
||||
vi.mocked(doesEnvironmentExist).mockResolvedValueOnce(environmentId).mockResolvedValueOnce(null);
|
||||
await expect(
|
||||
copySurveyToOtherEnvironment(environmentId, surveyId, targetEnvironmentId, userId)
|
||||
).rejects.toThrow(new ResourceNotFoundError("Environment", targetEnvironmentId));
|
||||
});
|
||||
|
||||
test("should throw DatabaseError on Prisma create error", async () => {
|
||||
const prismaError = makePrismaKnownError();
|
||||
vi.mocked(prisma.survey.create).mockRejectedValue(prismaError);
|
||||
await expect(
|
||||
copySurveyToOtherEnvironment(environmentId, surveyId, targetEnvironmentId, userId)
|
||||
).rejects.toThrow(DatabaseError);
|
||||
expect(logger.error).toHaveBeenCalledWith(prismaError, "Error copying survey to other environment");
|
||||
});
|
||||
|
||||
test("should rethrow unknown error during copy", async () => {
|
||||
const unknownError = new Error("Some unknown error during copy");
|
||||
vi.mocked(prisma.survey.create).mockRejectedValue(unknownError);
|
||||
await expect(
|
||||
copySurveyToOtherEnvironment(environmentId, surveyId, targetEnvironmentId, userId)
|
||||
).rejects.toThrow(unknownError);
|
||||
});
|
||||
|
||||
test("should handle survey with no languages", async () => {
|
||||
const surveyWithoutLanguages = { ...mockExistingSurveyDetails, languages: [] };
|
||||
vi.mocked(prisma.survey.findUnique).mockResolvedValue(surveyWithoutLanguages as any);
|
||||
|
||||
await copySurveyToOtherEnvironment(environmentId, surveyId, targetEnvironmentId, userId);
|
||||
expect(prisma.survey.create).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
data: expect.objectContaining({
|
||||
languages: undefined,
|
||||
}),
|
||||
})
|
||||
);
|
||||
expect(projectCache.revalidate).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test("should handle survey with no triggers", async () => {
|
||||
const surveyWithoutTriggers = { ...mockExistingSurveyDetails, triggers: [] };
|
||||
vi.mocked(prisma.survey.findUnique).mockResolvedValue(surveyWithoutTriggers as any);
|
||||
|
||||
await copySurveyToOtherEnvironment(environmentId, surveyId, targetEnvironmentId, userId);
|
||||
expect(prisma.survey.create).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
data: expect.objectContaining({
|
||||
triggers: { create: [] },
|
||||
}),
|
||||
})
|
||||
);
|
||||
expect(surveyCache.revalidate).not.toHaveBeenCalledWith(
|
||||
expect.objectContaining({ actionClassId: expect.any(String) })
|
||||
);
|
||||
});
|
||||
});
|
||||
68
apps/web/modules/survey/list/lib/utils.test.ts
Normal file
68
apps/web/modules/survey/list/lib/utils.test.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import { describe, expect, test } from "vitest";
|
||||
import type { TSurveyFilters } from "@formbricks/types/surveys/types";
|
||||
import { getFormattedFilters } from "./utils";
|
||||
|
||||
describe("getFormattedFilters", () => {
|
||||
test("returns empty object when no filters provided", () => {
|
||||
const result = getFormattedFilters({} as TSurveyFilters, "user1");
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
|
||||
test("includes name filter", () => {
|
||||
const result = getFormattedFilters({ name: "surveyName" } as TSurveyFilters, "user1");
|
||||
expect(result).toEqual({ name: "surveyName" });
|
||||
});
|
||||
|
||||
test("includes status filter when array is non-empty", () => {
|
||||
const result = getFormattedFilters({ status: ["active", "inactive"] } as any, "user1");
|
||||
expect(result).toEqual({ status: ["active", "inactive"] });
|
||||
});
|
||||
|
||||
test("ignores status filter when empty array", () => {
|
||||
const result = getFormattedFilters({ status: [] } as any, "user1");
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
|
||||
test("includes type filter when array is non-empty", () => {
|
||||
const result = getFormattedFilters({ type: ["typeA"] } as any, "user1");
|
||||
expect(result).toEqual({ type: ["typeA"] });
|
||||
});
|
||||
|
||||
test("ignores type filter when empty array", () => {
|
||||
const result = getFormattedFilters({ type: [] } as any, "user1");
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
|
||||
test("includes createdBy filter when array is non-empty", () => {
|
||||
const result = getFormattedFilters({ createdBy: ["ownerA", "ownerB"] } as any, "user1");
|
||||
expect(result).toEqual({ createdBy: { userId: "user1", value: ["ownerA", "ownerB"] } });
|
||||
});
|
||||
|
||||
test("ignores createdBy filter when empty array", () => {
|
||||
const result = getFormattedFilters({ createdBy: [] } as any, "user1");
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
|
||||
test("includes sortBy filter", () => {
|
||||
const result = getFormattedFilters({ sortBy: "date" } as any, "user1");
|
||||
expect(result).toEqual({ sortBy: "date" });
|
||||
});
|
||||
|
||||
test("combines multiple filters", () => {
|
||||
const input: TSurveyFilters = {
|
||||
name: "nameVal",
|
||||
status: ["draft"],
|
||||
type: ["link", "app"],
|
||||
createdBy: ["you"],
|
||||
sortBy: "name",
|
||||
};
|
||||
const result = getFormattedFilters(input, "userX");
|
||||
expect(result).toEqual({
|
||||
name: "nameVal",
|
||||
status: ["draft"],
|
||||
type: ["link", "app"],
|
||||
createdBy: { userId: "userX", value: ["you"] },
|
||||
sortBy: "name",
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user