fix: adds eslint rules for using test and refactors the current tests (#5397)

This commit is contained in:
Anshuman Pandey
2025-04-17 09:02:03 +05:30
committed by GitHub
parent ff2f7660a6
commit 01e5700340
105 changed files with 750 additions and 705 deletions

View File

@@ -1,4 +1,9 @@
{
"github.copilot.chat.codeGeneration.instructions": [
{
"text": "When generating tests, always use vitest and use the `test` function instead of `it`."
}
],
"sonarlint.connectedMode.project": {
"connectionId": "formbricks",
"projectKey": "formbricks_formbricks"

View File

@@ -3,7 +3,7 @@ import { act, cleanup, render, screen } from "@testing-library/react";
import { getServerSession } from "next-auth";
import { redirect } from "next/navigation";
import React from "react";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { beforeEach, describe, expect, test, vi } from "vitest";
import { canUserAccessOrganization } from "@formbricks/lib/organization/auth";
import { getOrganization } from "@formbricks/lib/organization/service";
import { getUser } from "@formbricks/lib/user/service";
@@ -71,7 +71,7 @@ describe("ProjectOnboardingLayout", () => {
cleanup();
});
it("redirects to /auth/login if there is no session", async () => {
test("redirects to /auth/login if there is no session", async () => {
// Mock no session
vi.mocked(getServerSession).mockResolvedValueOnce(null);
@@ -85,7 +85,7 @@ describe("ProjectOnboardingLayout", () => {
expect(layoutElement).toBeUndefined();
});
it("throws an error if user does not exist", async () => {
test("throws an error if user does not exist", async () => {
vi.mocked(getServerSession).mockResolvedValueOnce({
user: { id: "user-123" },
});
@@ -99,7 +99,7 @@ describe("ProjectOnboardingLayout", () => {
).rejects.toThrow("common.user_not_found");
});
it("throws AuthorizationError if user cannot access organization", async () => {
test("throws AuthorizationError if user cannot access organization", async () => {
vi.mocked(getServerSession).mockResolvedValueOnce({ user: { id: "user-123" } });
vi.mocked(getUser).mockResolvedValueOnce({ id: "user-123" } as TUser);
vi.mocked(canUserAccessOrganization).mockResolvedValueOnce(false);
@@ -112,7 +112,7 @@ describe("ProjectOnboardingLayout", () => {
).rejects.toThrow("common.not_authorized");
});
it("throws an error if organization does not exist", async () => {
test("throws an error if organization does not exist", async () => {
vi.mocked(getServerSession).mockResolvedValueOnce({ user: { id: "user-123" } });
vi.mocked(getUser).mockResolvedValueOnce({ id: "user-123" } as TUser);
vi.mocked(canUserAccessOrganization).mockResolvedValueOnce(true);
@@ -126,7 +126,7 @@ describe("ProjectOnboardingLayout", () => {
).rejects.toThrow("common.organization_not_found");
});
it("renders child content plus PosthogIdentify & ToasterClient if everything is valid", async () => {
test("renders child content plus PosthogIdentify & ToasterClient if everything is valid", async () => {
// Provide valid data
vi.mocked(getServerSession).mockResolvedValueOnce({ user: { id: "user-123" } });
vi.mocked(getUser).mockResolvedValueOnce({ id: "user-123", name: "Test User" } as TUser);

View File

@@ -2,7 +2,7 @@ import { environmentIdLayoutChecks } from "@/modules/environments/lib/utils";
import { cleanup, render, screen } from "@testing-library/react";
import { Session } from "next-auth";
import { redirect } from "next/navigation";
import { afterEach, describe, expect, it, vi } from "vitest";
import { afterEach, describe, expect, test, vi } from "vitest";
import { getEnvironment } from "@formbricks/lib/environment/service";
import { TEnvironment } from "@formbricks/types/environment";
import { TOrganization } from "@formbricks/types/organizations";
@@ -41,7 +41,7 @@ describe("SurveyEditorEnvironmentLayout", () => {
vi.clearAllMocks();
});
it("renders successfully when environment is found", async () => {
test("renders successfully when environment is found", async () => {
vi.mocked(environmentIdLayoutChecks).mockResolvedValueOnce({
t: ((key: string) => key) as any, // Mock translation function, we don't need to implement it for the test
session: { user: { id: "user1" } } as Session,
@@ -62,7 +62,7 @@ describe("SurveyEditorEnvironmentLayout", () => {
expect(screen.getByTestId("child")).toHaveTextContent("Survey Editor Content");
});
it("throws an error when environment is not found", async () => {
test("throws an error when environment is not found", async () => {
vi.mocked(environmentIdLayoutChecks).mockResolvedValueOnce({
t: ((key: string) => key) as any,
session: { user: { id: "user1" } } as Session,
@@ -79,7 +79,7 @@ describe("SurveyEditorEnvironmentLayout", () => {
).rejects.toThrow("common.environment_not_found");
});
it("calls redirect when session is null", async () => {
test("calls redirect when session is null", async () => {
vi.mocked(environmentIdLayoutChecks).mockResolvedValueOnce({
t: ((key: string) => key) as any,
session: undefined as unknown as Session,
@@ -98,7 +98,7 @@ describe("SurveyEditorEnvironmentLayout", () => {
).rejects.toThrow("Redirect called");
});
it("throws error if user is null", async () => {
test("throws error if user is null", async () => {
vi.mocked(environmentIdLayoutChecks).mockResolvedValueOnce({
t: ((key: string) => key) as any,
session: { user: { id: "user1" } } as Session,

View File

@@ -2,7 +2,7 @@ import "@testing-library/jest-dom/vitest";
import { cleanup, render } from "@testing-library/react";
import { Session } from "next-auth";
import { usePostHog } from "posthog-js/react";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { beforeEach, describe, expect, test, vi } from "vitest";
import { TOrganizationBilling } from "@formbricks/types/organizations";
import { TUser } from "@formbricks/types/user";
import { PosthogIdentify } from "./PosthogIdentify";
@@ -18,7 +18,7 @@ describe("PosthogIdentify", () => {
cleanup();
});
it("identifies the user and sets groups when isPosthogEnabled is true", () => {
test("identifies the user and sets groups when isPosthogEnabled is true", () => {
const mockIdentify = vi.fn();
const mockGroup = vi.fn();
@@ -72,7 +72,7 @@ describe("PosthogIdentify", () => {
});
});
it("does nothing if isPosthogEnabled is false", () => {
test("does nothing if isPosthogEnabled is false", () => {
const mockIdentify = vi.fn();
const mockGroup = vi.fn();
@@ -95,7 +95,7 @@ describe("PosthogIdentify", () => {
expect(mockGroup).not.toHaveBeenCalled();
});
it("does nothing if session user is missing", () => {
test("does nothing if session user is missing", () => {
const mockIdentify = vi.fn();
const mockGroup = vi.fn();
@@ -120,7 +120,7 @@ describe("PosthogIdentify", () => {
expect(mockGroup).not.toHaveBeenCalled();
});
it("identifies user but does not group if environmentId/organizationId not provided", () => {
test("identifies user but does not group if environmentId/organizationId not provided", () => {
const mockIdentify = vi.fn();
const mockGroup = vi.fn();

View File

@@ -2,7 +2,7 @@ import { environmentIdLayoutChecks } from "@/modules/environments/lib/utils";
import { cleanup, render, screen } from "@testing-library/react";
import { Session } from "next-auth";
import { redirect } from "next/navigation";
import { afterEach, describe, expect, it, vi } from "vitest";
import { afterEach, describe, expect, test, vi } from "vitest";
import { getMembershipByUserIdOrganizationId } from "@formbricks/lib/membership/service";
import { getProjectByEnvironmentId } from "@formbricks/lib/project/service";
import { TMembership } from "@formbricks/types/memberships";
@@ -53,7 +53,7 @@ describe("EnvLayout", () => {
cleanup();
});
it("renders successfully when all dependencies return valid data", async () => {
test("renders successfully when all dependencies return valid data", async () => {
vi.mocked(environmentIdLayoutChecks).mockResolvedValueOnce({
t: ((key: string) => key) as any, // Mock translation function, we don't need to implement it for the test
session: { user: { id: "user1" } } as Session,
@@ -77,7 +77,7 @@ describe("EnvLayout", () => {
expect(screen.getByTestId("child")).toHaveTextContent("Content");
});
it("throws error if project is not found", async () => {
test("throws error if project is not found", async () => {
vi.mocked(environmentIdLayoutChecks).mockResolvedValueOnce({
t: ((key: string) => key) as any,
session: { user: { id: "user1" } } as Session,
@@ -97,7 +97,7 @@ describe("EnvLayout", () => {
).rejects.toThrow("common.project_not_found");
});
it("throws error if membership is not found", async () => {
test("throws error if membership is not found", async () => {
vi.mocked(environmentIdLayoutChecks).mockResolvedValueOnce({
t: ((key: string) => key) as any,
session: { user: { id: "user1" } } as Session,
@@ -115,7 +115,7 @@ describe("EnvLayout", () => {
).rejects.toThrow("common.membership_not_found");
});
it("calls redirect when session is null", async () => {
test("calls redirect when session is null", async () => {
vi.mocked(environmentIdLayoutChecks).mockResolvedValueOnce({
t: ((key: string) => key) as any,
session: undefined as unknown as Session,
@@ -134,7 +134,7 @@ describe("EnvLayout", () => {
).rejects.toThrow("Redirect called");
});
it("throws error if user is null", async () => {
test("throws error if user is null", async () => {
vi.mocked(environmentIdLayoutChecks).mockResolvedValueOnce({
t: ((key: string) => key) as any,
session: { user: { id: "user1" } } as Session,

View File

@@ -6,7 +6,7 @@ import {
import { getEnvironmentAuth } from "@/modules/environments/lib/utils";
import { TEnvironmentAuth } from "@/modules/environments/types/environment-auth";
import { getTranslate } from "@/tolgee/server";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { beforeEach, describe, expect, test, vi } from "vitest";
import { getUser } from "@formbricks/lib/user/service";
import { TUser } from "@formbricks/types/user";
import Page from "./page";
@@ -84,7 +84,7 @@ describe("Page", () => {
vi.mocked(getWhiteLabelPermission).mockResolvedValue(true);
});
it("renders the page with organization settings", async () => {
test("renders the page with organization settings", async () => {
const props = {
params: Promise.resolve({ environmentId: "env-123" }),
};
@@ -94,7 +94,7 @@ describe("Page", () => {
expect(result).toBeTruthy();
});
it("renders if session user id empty", async () => {
test("renders if session user id empty", async () => {
mockEnvironmentAuth.session.user.id = "";
vi.mocked(getEnvironmentAuth).mockResolvedValue(mockEnvironmentAuth);
@@ -108,7 +108,7 @@ describe("Page", () => {
expect(result).toBeTruthy();
});
it("handles getEnvironmentAuth error", async () => {
test("handles getEnvironmentAuth error", async () => {
vi.mocked(getEnvironmentAuth).mockRejectedValue(new Error("Authentication error"));
const props = {

View File

@@ -1,7 +1,7 @@
import "@testing-library/jest-dom/vitest";
import { cleanup, fireEvent, render, screen, waitFor } from "@testing-library/react";
import toast from "react-hot-toast";
import { afterEach, describe, expect, it, vi } from "vitest";
import { afterEach, describe, expect, test, vi } from "vitest";
import { TEnvironment } from "@formbricks/types/environment";
import { TSurvey } from "@formbricks/types/surveys/types";
import { TUser } from "@formbricks/types/user";
@@ -85,7 +85,7 @@ describe("SurveyAnalysisCTA - handleCopyLink", () => {
cleanup();
});
it("calls copySurveyLink and clipboard.writeText on success", async () => {
test("calls copySurveyLink and clipboard.writeText on success", async () => {
render(
<SurveyAnalysisCTA
survey={dummySurvey}
@@ -108,7 +108,7 @@ describe("SurveyAnalysisCTA - handleCopyLink", () => {
});
});
it("shows error toast on failure", async () => {
test("shows error toast on failure", async () => {
refreshSingleUseIdSpy.mockImplementationOnce(() => Promise.reject(new Error("fail")));
render(
<SurveyAnalysisCTA

View File

@@ -1,7 +1,7 @@
import "@testing-library/jest-dom/vitest";
import { cleanup, render, screen } from "@testing-library/react";
import { getServerSession } from "next-auth";
import { afterEach, describe, expect, it, vi } from "vitest";
import { afterEach, describe, expect, test, vi } from "vitest";
import { getUser } from "@formbricks/lib/user/service";
import { TUser } from "@formbricks/types/user";
import AppLayout from "./layout";
@@ -59,7 +59,7 @@ describe("(app) AppLayout", () => {
cleanup();
});
it("renders child content and all sub-components when user exists", async () => {
test("renders child content and all sub-components when user exists", async () => {
vi.mocked(getServerSession).mockResolvedValueOnce({ user: { id: "user-123" } });
vi.mocked(getUser).mockResolvedValueOnce({ id: "user-123", email: "test@example.com" } as TUser);
@@ -77,7 +77,7 @@ describe("(app) AppLayout", () => {
expect(screen.getByTestId("formbricks-client")).toBeInTheDocument();
});
it("skips FormbricksClient if no user is present", async () => {
test("skips FormbricksClient if no user is present", async () => {
vi.mocked(getServerSession).mockResolvedValueOnce(null);
const element = await AppLayout({

View File

@@ -1,6 +1,6 @@
import "@testing-library/jest-dom/vitest";
import { render, screen } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import { describe, expect, test, vi } from "vitest";
import AppLayout from "../(auth)/layout";
vi.mock("@formbricks/lib/constants", () => ({
@@ -18,7 +18,7 @@ vi.mock("@/modules/ui/components/no-mobile-overlay", () => ({
}));
describe("(auth) AppLayout", () => {
it("renders the NoMobileOverlay and IntercomClient, plus children", async () => {
test("renders the NoMobileOverlay and IntercomClient, plus children", async () => {
const appLayoutElement = await AppLayout({
children: <div data-testid="child-content">Hello from children!</div>,
});

View File

@@ -1,7 +1,7 @@
import { hashApiKey } from "@/modules/api/v2/management/lib/utils";
import { getApiKeyWithPermissions } from "@/modules/organization/settings/api-keys/lib/api-key";
import { hasPermission } from "@/modules/organization/settings/api-keys/lib/utils";
import { describe, expect, it, vi } from "vitest";
import { describe, expect, test, vi } from "vitest";
import { prisma } from "@formbricks/database";
import { TAPIKeyEnvironmentPermission } from "@formbricks/types/auth";
import { authenticateRequest } from "./auth";
@@ -20,7 +20,7 @@ vi.mock("@/modules/api/v2/management/lib/utils", () => ({
}));
describe("getApiKeyWithPermissions", () => {
it("should return API key data with permissions when valid key is provided", async () => {
test("returns API key data with permissions when valid key is provided", async () => {
const mockApiKeyData = {
id: "api-key-id",
organizationId: "org-id",
@@ -51,7 +51,7 @@ describe("getApiKeyWithPermissions", () => {
});
});
it("should return null when API key is not found", async () => {
test("returns null when API key is not found", async () => {
vi.mocked(prisma.apiKey.findUnique).mockResolvedValue(null);
const result = await getApiKeyWithPermissions("invalid-key");
@@ -85,31 +85,31 @@ describe("hasPermission", () => {
},
];
it("should return true for manage permission with any method", () => {
test("returns true for manage permission with any method", () => {
expect(hasPermission(permissions, "env-1", "GET")).toBe(true);
expect(hasPermission(permissions, "env-1", "POST")).toBe(true);
expect(hasPermission(permissions, "env-1", "DELETE")).toBe(true);
});
it("should handle write permission correctly", () => {
test("handles write permission correctly", () => {
expect(hasPermission(permissions, "env-2", "GET")).toBe(true);
expect(hasPermission(permissions, "env-2", "POST")).toBe(true);
expect(hasPermission(permissions, "env-2", "DELETE")).toBe(false);
});
it("should handle read permission correctly", () => {
test("handles read permission correctly", () => {
expect(hasPermission(permissions, "env-3", "GET")).toBe(true);
expect(hasPermission(permissions, "env-3", "POST")).toBe(false);
expect(hasPermission(permissions, "env-3", "DELETE")).toBe(false);
});
it("should return false for non-existent environment", () => {
test("returns false for non-existent environment", () => {
expect(hasPermission(permissions, "env-4", "GET")).toBe(false);
});
});
describe("authenticateRequest", () => {
it("should return authentication data for valid API key", async () => {
test("should return authentication data for valid API key", async () => {
const request = new Request("http://localhost", {
headers: { "x-api-key": "valid-api-key" },
});
@@ -159,13 +159,13 @@ describe("authenticateRequest", () => {
});
});
it("should return null when no API key is provided", async () => {
test("returns null when no API key is provided", async () => {
const request = new Request("http://localhost");
const result = await authenticateRequest(request);
expect(result).toBeNull();
});
it("should return null when API key is invalid", async () => {
test("returns null when API key is invalid", async () => {
const request = new Request("http://localhost", {
headers: { "x-api-key": "invalid-api-key" },
});

View File

@@ -1,4 +1,4 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
import { beforeEach, describe, expect, test, vi } from "vitest";
import { prisma } from "@formbricks/database";
import { DatabaseError } from "@formbricks/types/errors";
import { getActionClasses } from "./action-classes";
@@ -43,7 +43,7 @@ describe("getActionClasses", () => {
vi.clearAllMocks();
});
it("should successfully fetch action classes for given environment IDs", async () => {
test("successfully fetches action classes for given environment IDs", async () => {
// Mock the prisma findMany response
vi.mocked(prisma.actionClass.findMany).mockResolvedValue(mockActionClasses);
@@ -61,14 +61,14 @@ describe("getActionClasses", () => {
});
});
it("should throw DatabaseError when prisma query fails", async () => {
test("throws DatabaseError when prisma query fails", async () => {
// Mock the prisma findMany to throw an error
vi.mocked(prisma.actionClass.findMany).mockRejectedValue(new Error("Database error"));
await expect(getActionClasses(mockEnvironmentIds)).rejects.toThrow(DatabaseError);
});
it("should handle empty environment IDs array", async () => {
test("handles empty environment IDs array", async () => {
// Mock the prisma findMany response
vi.mocked(prisma.actionClass.findMany).mockResolvedValue([]);

View File

@@ -1,7 +1,7 @@
import Intercom from "@intercom/messenger-js-sdk";
import "@testing-library/jest-dom/vitest";
import { cleanup, render } from "@testing-library/react";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
import { TUser } from "@formbricks/types/user";
import { IntercomClient } from "./IntercomClient";
@@ -26,7 +26,7 @@ describe("IntercomClient", () => {
global.window.Intercom = originalWindowIntercom;
});
it("calls Intercom with user data when isIntercomConfigured is true and user is provided", () => {
test("calls Intercom with user data when isIntercomConfigured is true and user is provided", () => {
const testUser = {
id: "test-id",
name: "Test User",
@@ -55,7 +55,7 @@ describe("IntercomClient", () => {
});
});
it("calls Intercom with user data without createdAt", () => {
test("calls Intercom with user data without createdAt", () => {
const testUser = {
id: "test-id",
name: "Test User",
@@ -83,7 +83,7 @@ describe("IntercomClient", () => {
});
});
it("calls Intercom with minimal params if user is not provided", () => {
test("calls Intercom with minimal params if user is not provided", () => {
render(
<IntercomClient isIntercomConfigured={true} intercomAppId="my-app-id" intercomUserHash="my-user-hash" />
);
@@ -94,7 +94,7 @@ describe("IntercomClient", () => {
});
});
it("does not call Intercom if isIntercomConfigured is false", () => {
test("does not call Intercom if isIntercomConfigured is false", () => {
render(
<IntercomClient
isIntercomConfigured={false}
@@ -106,7 +106,7 @@ describe("IntercomClient", () => {
expect(Intercom).not.toHaveBeenCalled();
});
it("shuts down Intercom on unmount", () => {
test("shuts down Intercom on unmount", () => {
const { unmount } = render(
<IntercomClient isIntercomConfigured={true} intercomAppId="my-app-id" intercomUserHash="my-user-hash" />
);
@@ -120,7 +120,7 @@ describe("IntercomClient", () => {
expect(mockWindowIntercom).toHaveBeenCalledWith("shutdown");
});
it("logs an error if Intercom initialization fails", () => {
test("logs an error if Intercom initialization fails", () => {
// Spy on console.error
const consoleErrorSpy = vi.spyOn(console, "error").mockImplementation(() => {});
@@ -141,7 +141,7 @@ describe("IntercomClient", () => {
consoleErrorSpy.mockRestore();
});
it("logs an error if isIntercomConfigured is true but no intercomAppId is provided", () => {
test("logs an error if isIntercomConfigured is true but no intercomAppId is provided", () => {
const consoleErrorSpy = vi.spyOn(console, "error").mockImplementation(() => {});
render(
@@ -159,7 +159,7 @@ describe("IntercomClient", () => {
consoleErrorSpy.mockRestore();
});
it("logs an error if isIntercomConfigured is true but no intercomUserHash is provided", () => {
test("logs an error if isIntercomConfigured is true but no intercomUserHash is provided", () => {
const consoleErrorSpy = vi.spyOn(console, "error").mockImplementation(() => {});
const testUser = {
id: "test-id",

View File

@@ -1,5 +1,5 @@
import { cleanup, render, screen } from "@testing-library/react";
import { afterEach, describe, expect, it, vi } from "vitest";
import { afterEach, describe, expect, test, vi } from "vitest";
import { TUser } from "@formbricks/types/user";
import { IntercomClientWrapper } from "./IntercomClientWrapper";
@@ -31,7 +31,7 @@ describe("IntercomClientWrapper", () => {
cleanup();
});
it("renders IntercomClient with computed user hash when user is provided", () => {
test("renders IntercomClient with computed user hash when user is provided", () => {
const testUser = { id: "user-123", name: "Test User", email: "test@example.com" } as TUser;
render(<IntercomClientWrapper user={testUser} />);
@@ -48,7 +48,7 @@ describe("IntercomClientWrapper", () => {
expect(props.user).toEqual(testUser);
});
it("renders IntercomClient without computing a hash when no user is provided", () => {
test("renders IntercomClient without computing a hash when no user is provided", () => {
render(<IntercomClientWrapper user={null} />);
const intercomClientEl = screen.getByTestId("mock-intercom-client");

View File

@@ -3,7 +3,7 @@ import { getTolgee } from "@/tolgee/server";
import { cleanup, render, screen } from "@testing-library/react";
import { TolgeeInstance } from "@tolgee/react";
import React from "react";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { beforeEach, describe, expect, test, vi } from "vitest";
import RootLayout from "./layout";
// Mock dependencies for the layout
@@ -81,7 +81,7 @@ describe("RootLayout", () => {
process.env.VERCEL = "1";
});
it("renders the layout with the correct structure and providers", async () => {
test("renders the layout with the correct structure and providers", async () => {
const fakeLocale = "en-US";
// Mock getLocale to resolve to a fake locale
vi.mocked(getLocale).mockResolvedValue(fakeLocale);

View File

@@ -1,5 +1,5 @@
import cuid2 from "@paralleldrive/cuid2";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
import * as crypto from "@formbricks/lib/crypto";
import { generateSurveySingleUseId, validateSurveySingleUseId } from "./singleUseSurveys";
@@ -45,21 +45,21 @@ describe("generateSurveySingleUseId", () => {
vi.resetAllMocks();
});
it("returns unencrypted cuid when isEncrypted is false", () => {
test("returns unencrypted cuid when isEncrypted is false", () => {
const result = generateSurveySingleUseId(false);
expect(result).toBe(mockCuid);
expect(crypto.symmetricEncrypt).not.toHaveBeenCalled();
});
it("returns encrypted cuid when isEncrypted is true", () => {
test("returns encrypted cuid when isEncrypted is true", () => {
const result = generateSurveySingleUseId(true);
expect(result).toBe(mockEncryptedCuid);
expect(crypto.symmetricEncrypt).toHaveBeenCalledWith(mockCuid, "test-encryption-key");
});
it("returns undefined when cuid is not valid", () => {
test("returns undefined when cuid is not valid", () => {
vi.mocked(cuid2.isCuid).mockReturnValue(false);
const result = validateSurveySingleUseId(mockEncryptedCuid);
@@ -67,7 +67,7 @@ describe("generateSurveySingleUseId", () => {
expect(result).toBeUndefined();
});
it("returns undefined when decryption fails", () => {
test("returns undefined when decryption fails", () => {
vi.mocked(crypto.symmetricDecrypt).mockImplementation(() => {
throw new Error("Decryption failed");
});
@@ -77,7 +77,7 @@ describe("generateSurveySingleUseId", () => {
expect(result).toBeUndefined();
});
it("throws error when ENCRYPTION_KEY is not set in generateSurveySingleUseId", async () => {
test("throws error when ENCRYPTION_KEY is not set in generateSurveySingleUseId", async () => {
// Temporarily mock ENCRYPTION_KEY as undefined
vi.doMock("@formbricks/lib/constants", () => ({
ENCRYPTION_KEY: undefined,
@@ -90,7 +90,7 @@ describe("generateSurveySingleUseId", () => {
expect(() => generateSurveySingleUseIdNoKey(true)).toThrow("ENCRYPTION_KEY is not set");
});
it("throws error when ENCRYPTION_KEY is not set in validateSurveySingleUseId for symmetric encryption", async () => {
test("throws error when ENCRYPTION_KEY is not set in validateSurveySingleUseId for symmetric encryption", async () => {
// Temporarily mock ENCRYPTION_KEY as undefined
vi.doMock("@formbricks/lib/constants", () => ({
ENCRYPTION_KEY: undefined,
@@ -103,7 +103,7 @@ describe("generateSurveySingleUseId", () => {
expect(() => validateSurveySingleUseIdNoKey(mockEncryptedCuid)).toThrow("ENCRYPTION_KEY is not set");
});
it("throws error when FORMBRICKS_ENCRYPTION_KEY is not set in validateSurveySingleUseId for AES128", async () => {
test("throws error when FORMBRICKS_ENCRYPTION_KEY is not set in validateSurveySingleUseId for AES128", async () => {
// Temporarily mock FORMBRICKS_ENCRYPTION_KEY as undefined
vi.doMock("@formbricks/lib/constants", () => ({
ENCRYPTION_KEY: "test-encryption-key",

View File

@@ -1,6 +1,6 @@
import * as Sentry from "@sentry/nextjs";
import { cleanup, render, screen } from "@testing-library/react";
import { afterEach, describe, expect, it, vi } from "vitest";
import { afterEach, describe, expect, test, vi } from "vitest";
import { SentryProvider } from "./SentryProvider";
vi.mock("@sentry/nextjs", async () => {
@@ -22,7 +22,7 @@ describe("SentryProvider", () => {
cleanup();
});
it("calls Sentry.init when sentryDsn is provided", () => {
test("calls Sentry.init when sentryDsn is provided", () => {
const sentryDsn = "https://examplePublicKey@o0.ingest.sentry.io/0";
const initSpy = vi.spyOn(Sentry, "init").mockImplementation(() => undefined);
@@ -47,7 +47,7 @@ describe("SentryProvider", () => {
);
});
it("does not call Sentry.init when sentryDsn is not provided", () => {
test("does not call Sentry.init when sentryDsn is not provided", () => {
const initSpy = vi.spyOn(Sentry, "init").mockImplementation(() => undefined);
render(
@@ -59,7 +59,7 @@ describe("SentryProvider", () => {
expect(initSpy).not.toHaveBeenCalled();
});
it("renders children", () => {
test("renders children", () => {
const sentryDsn = "https://examplePublicKey@o0.ingest.sentry.io/0";
render(
<SentryProvider sentryDsn={sentryDsn}>
@@ -69,7 +69,7 @@ describe("SentryProvider", () => {
expect(screen.getByTestId("child")).toHaveTextContent("Test Content");
});
it("processes beforeSend correctly", () => {
test("processes beforeSend correctly", () => {
const sentryDsn = "https://examplePublicKey@o0.ingest.sentry.io/0";
const initSpy = vi.spyOn(Sentry, "init").mockImplementation(() => undefined);

View File

@@ -1,5 +1,5 @@
import { getIsMultiOrgEnabled } from "@/modules/ee/license-check/lib/utils";
import { describe, expect, it, vi } from "vitest";
import { describe, expect, test, vi } from "vitest";
import { getOrganizationsWhereUserIsSingleOwner } from "@formbricks/lib/organization/service";
import { deleteUser } from "@formbricks/lib/user/service";
import { OperationNotAllowedError } from "@formbricks/types/errors";
@@ -30,7 +30,7 @@ vi.mock("@/lib/utils/action-client", () => ({
}));
describe("deleteUserAction", () => {
it("deletes user successfully when multi-org is enabled", async () => {
test("deletes user successfully when multi-org is enabled", async () => {
const ctx = { user: { id: "test-user" } };
vi.mocked(deleteUser).mockResolvedValueOnce({ id: "test-user" } as TUser);
vi.mocked(getOrganizationsWhereUserIsSingleOwner).mockResolvedValueOnce([]);
@@ -44,7 +44,7 @@ describe("deleteUserAction", () => {
expect(getIsMultiOrgEnabled).toHaveBeenCalledTimes(1);
});
it("deletes user successfully when multi-org is disabled but user is not sole owner of any org", async () => {
test("deletes user successfully when multi-org is disabled but user is not sole owner of any org", async () => {
const ctx = { user: { id: "another-user" } };
vi.mocked(deleteUser).mockResolvedValueOnce({ id: "another-user" } as TUser);
vi.mocked(getOrganizationsWhereUserIsSingleOwner).mockResolvedValueOnce([]);
@@ -58,7 +58,7 @@ describe("deleteUserAction", () => {
expect(getIsMultiOrgEnabled).toHaveBeenCalledTimes(1);
});
it("throws OperationNotAllowedError when user is sole owner in at least one org and multi-org is disabled", async () => {
test("throws OperationNotAllowedError when user is sole owner in at least one org and multi-org is disabled", async () => {
const ctx = { user: { id: "sole-owner-user" } };
vi.mocked(deleteUser).mockResolvedValueOnce({ id: "test-user" } as TUser);
vi.mocked(getOrganizationsWhereUserIsSingleOwner).mockResolvedValueOnce([

View File

@@ -1,6 +1,6 @@
import { cleanup, fireEvent, render, screen, waitFor } from "@testing-library/react";
import * as nextAuth from "next-auth/react";
import { afterEach, describe, expect, it, vi } from "vitest";
import { afterEach, describe, expect, test, vi } from "vitest";
import { TOrganization } from "@formbricks/types/organizations";
import { TUser } from "@formbricks/types/user";
import * as actions from "./actions";
@@ -32,7 +32,7 @@ describe("DeleteAccountModal", () => {
cleanup();
});
it("renders modal with correct props", () => {
test("renders modal with correct props", () => {
render(
<DeleteAccountModal
open={true}
@@ -48,7 +48,7 @@ describe("DeleteAccountModal", () => {
expect(screen.getByText("Org2")).toBeInTheDocument();
});
it("disables delete button when email does not match", () => {
test("disables delete button when email does not match", () => {
render(
<DeleteAccountModal
open={true}
@@ -65,7 +65,7 @@ describe("DeleteAccountModal", () => {
expect(input).toHaveValue("wrong@example.com");
});
it("allows account deletion flow (non-cloud)", async () => {
test("allows account deletion flow (non-cloud)", async () => {
const deleteUserAction = vi
.spyOn(actions, "deleteUserAction")
.mockResolvedValue("deleted-user-id" as any); // the return doesn't matter here
@@ -96,7 +96,7 @@ describe("DeleteAccountModal", () => {
});
});
it("allows account deletion flow (cloud)", async () => {
test("allows account deletion flow (cloud)", async () => {
const deleteUserAction = vi
.spyOn(actions, "deleteUserAction")
.mockResolvedValue("deleted-user-id" as any); // the return doesn't matter here
@@ -133,7 +133,7 @@ describe("DeleteAccountModal", () => {
});
});
it("handles deletion errors", async () => {
test("handles deletion errors", async () => {
const deleteUserAction = vi.spyOn(actions, "deleteUserAction").mockRejectedValue(new Error("fail"));
render(

View File

@@ -1,5 +1,5 @@
import { cleanup, render } from "@testing-library/react";
import { afterEach, describe, expect, it, vi } from "vitest";
import { afterEach, describe, expect, test, vi } from "vitest";
import { RatingSmiley } from "./index";
// Mock the smiley components from ../SingleResponseCard/components/Smileys
@@ -64,7 +64,7 @@ describe("RatingSmiley", () => {
const activeClass = "fill-rating-fill";
// Test branch: range === 10 => iconsIdx = [0,1,2,...,9]
it("renders correct icon for range 10 when active", () => {
test("renders correct icon for range 10 when active", () => {
// For idx 0, iconsIdx[0] === 0, which corresponds to TiredFace.
const { getByTestId } = render(<RatingSmiley active={true} idx={0} range={10} addColors={true} />);
const icon = getByTestId("TiredFace");
@@ -72,7 +72,7 @@ describe("RatingSmiley", () => {
expect(icon.className).toContain(activeClass);
});
it("renders correct icon for range 10 when inactive", () => {
test("renders correct icon for range 10 when inactive", () => {
const { getByTestId } = render(<RatingSmiley active={false} idx={0} range={10} />);
const icon = getByTestId("TiredFace");
expect(icon).toBeDefined();
@@ -80,7 +80,7 @@ describe("RatingSmiley", () => {
});
// Test branch: range === 7 => iconsIdx = [1,3,4,5,6,8,9]
it("renders correct icon for range 7 when active", () => {
test("renders correct icon for range 7 when active", () => {
// For idx 0, iconsIdx[0] === 1, which corresponds to WearyFace.
const { getByTestId } = render(<RatingSmiley active={true} idx={0} range={7} addColors={true} />);
const icon = getByTestId("WearyFace");
@@ -89,7 +89,7 @@ describe("RatingSmiley", () => {
});
// Test branch: range === 5 => iconsIdx = [3,4,5,6,7]
it("renders correct icon for range 5 when active", () => {
test("renders correct icon for range 5 when active", () => {
// For idx 0, iconsIdx[0] === 3, which corresponds to FrowningFace.
const { getByTestId } = render(<RatingSmiley active={true} idx={0} range={5} addColors={true} />);
const icon = getByTestId("FrowningFace");
@@ -98,7 +98,7 @@ describe("RatingSmiley", () => {
});
// Test branch: range === 4 => iconsIdx = [4,5,6,7]
it("renders correct icon for range 4 when active", () => {
test("renders correct icon for range 4 when active", () => {
// For idx 0, iconsIdx[0] === 4, corresponding to ConfusedFace.
const { getByTestId } = render(<RatingSmiley active={true} idx={0} range={4} addColors={true} />);
const icon = getByTestId("ConfusedFace");
@@ -107,7 +107,7 @@ describe("RatingSmiley", () => {
});
// Test branch: range === 3 => iconsIdx = [4,5,7]
it("renders correct icon for range 3 when active", () => {
test("renders correct icon for range 3 when active", () => {
// For idx 0, iconsIdx[0] === 4, corresponding to ConfusedFace.
const { getByTestId } = render(<RatingSmiley active={true} idx={0} range={3} addColors={true} />);
const icon = getByTestId("ConfusedFace");

View File

@@ -1,6 +1,6 @@
import { cleanup, render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { afterEach, describe, expect, it, vi } from "vitest";
import { afterEach, describe, expect, test, vi } from "vitest";
import { getEnabledLanguages, getLanguageLabel } from "@formbricks/lib/i18n/utils";
import { TSurvey, TSurveyLanguage } from "@formbricks/types/surveys/types";
import { LanguageDropdown } from "./LanguageDropdown";
@@ -27,7 +27,7 @@ describe("LanguageDropdown", () => {
cleanup();
});
it("renders nothing when enabledLanguages length is 1", () => {
test("renders nothing when enabledLanguages length is 1", () => {
vi.mocked(getEnabledLanguages).mockReturnValueOnce([{ language: { code: "en" } } as TSurveyLanguage]);
render(
<LanguageDropdown survey={dummySurveySingle} setLanguage={setLanguageMock} locale={dummyLocale} />
@@ -36,7 +36,7 @@ describe("LanguageDropdown", () => {
expect(screen.queryByRole("button")).toBeNull();
});
it("renders button and toggles dropdown when multiple languages exist", async () => {
test("renders button and toggles dropdown when multiple languages exist", async () => {
vi.mocked(getEnabledLanguages).mockReturnValue(dummySurveyMultiple.languages);
vi.mocked(getLanguageLabel).mockImplementation((code: string, _locale: string) => code.toUpperCase());
@@ -66,7 +66,7 @@ describe("LanguageDropdown", () => {
});
});
it("closes dropdown when clicking outside", async () => {
test("closes dropdown when clicking outside", async () => {
vi.mocked(getEnabledLanguages).mockReturnValue(dummySurveyMultiple.languages);
vi.mocked(getLanguageLabel).mockImplementation((code: string, _locale: string) => code);

View File

@@ -1,5 +1,5 @@
import { cleanup, render, screen } from "@testing-library/react";
import { afterEach, describe, expect, it } from "vitest";
import { afterEach, describe, expect, test } from "vitest";
import { SurveyLinkDisplay } from "./SurveyLinkDisplay";
describe("SurveyLinkDisplay", () => {
@@ -7,14 +7,14 @@ describe("SurveyLinkDisplay", () => {
cleanup();
});
it("renders the Input when surveyUrl is provided", () => {
test("renders the Input when surveyUrl is provided", () => {
const surveyUrl = "http://example.com/s/123";
render(<SurveyLinkDisplay surveyUrl={surveyUrl} />);
const input = screen.getByTestId("survey-url-input");
expect(input).toBeInTheDocument();
});
it("renders loading state when surveyUrl is empty", () => {
test("renders loading state when surveyUrl is empty", () => {
render(<SurveyLinkDisplay surveyUrl="" />);
const loadingDiv = screen.getByTestId("loading-div");
expect(loadingDiv).toBeInTheDocument();

View File

@@ -4,7 +4,7 @@ import { copySurveyLink } from "@/modules/survey/lib/client-utils";
import { generateSingleUseIdAction } from "@/modules/survey/list/actions";
import { cleanup, fireEvent, render, screen, waitFor } from "@testing-library/react";
import { toast } from "react-hot-toast";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
import { ShareSurveyLink } from "./index";
const dummySurvey = {
@@ -91,7 +91,7 @@ describe("ShareSurveyLink", () => {
cleanup();
});
it("calls getUrl on mount and sets surveyUrl accordingly with singleUse enabled and default language", async () => {
test("calls getUrl on mount and sets surveyUrl accordingly with singleUse enabled and default language", async () => {
// Inline mocks for this test
vi.mocked(generateSingleUseIdAction).mockResolvedValue({ data: "dummySuId" });
@@ -113,7 +113,7 @@ describe("ShareSurveyLink", () => {
expect(url).not.toContain("lang=");
});
it("appends language query when language is changed from default", async () => {
test("appends language query when language is changed from default", async () => {
vi.mocked(generateSingleUseIdAction).mockResolvedValue({ data: "dummySuId" });
const setSurveyUrl = vi.fn();
@@ -133,7 +133,7 @@ describe("ShareSurveyLink", () => {
});
});
it("preview button opens new window with preview query", async () => {
test("preview button opens new window with preview query", async () => {
vi.mocked(generateSingleUseIdAction).mockResolvedValue({ data: "dummySuId" });
const setSurveyUrl = vi.fn().mockReturnValue(`${dummySurveyDomain}/s/${dummySurvey.id}?suId=dummySuId`);
@@ -157,7 +157,7 @@ describe("ShareSurveyLink", () => {
});
});
it("copy button writes surveyUrl to clipboard and shows toast", async () => {
test("copy button writes surveyUrl to clipboard and shows toast", async () => {
vi.mocked(getFormattedErrorMessage).mockReturnValue("common.copied_to_clipboard");
vi.mocked(copySurveyLink).mockImplementation((url: string, newId: string) => `${url}?suId=${newId}`);
@@ -182,7 +182,7 @@ describe("ShareSurveyLink", () => {
});
});
it("download QR code button calls downloadQRCode", async () => {
test("download QR code button calls downloadQRCode", async () => {
const dummyDownloadQRCode = vi.fn();
vi.mocked(getFormattedErrorMessage).mockReturnValue("common.copied_to_clipboard");
vi.mocked(useSurveyQRCode).mockReturnValue({ downloadQRCode: dummyDownloadQRCode } as any);
@@ -204,7 +204,7 @@ describe("ShareSurveyLink", () => {
expect(dummyDownloadQRCode).toHaveBeenCalled();
});
it("renders regenerate button when survey.singleUse.enabled is true and calls generateNewSingleUseLink", async () => {
test("renders regenerate button when survey.singleUse.enabled is true and calls generateNewSingleUseLink", async () => {
vi.mocked(generateSingleUseIdAction).mockResolvedValue({ data: "dummySuId" });
const setSurveyUrl = vi.fn();
@@ -225,7 +225,7 @@ describe("ShareSurveyLink", () => {
});
});
it("handles error when generating single-use link fails", async () => {
test("handles error when generating single-use link fails", async () => {
vi.mocked(generateSingleUseIdAction).mockResolvedValue({ data: undefined });
vi.mocked(getFormattedErrorMessage).mockReturnValue("Failed to generate link");

View File

@@ -9,7 +9,7 @@ import {
getProjectIdFromResponseNoteId,
} from "@/lib/utils/helper";
import { getTag } from "@/lib/utils/services";
import { describe, expect, it, vi } from "vitest";
import { describe, expect, test, vi } from "vitest";
import { deleteResponse, getResponse } from "@formbricks/lib/response/service";
import {
createResponseNote,
@@ -86,7 +86,7 @@ vi.mock("@/lib/utils/action-client", () => ({
}));
describe("createTagAction", () => {
it("successfully creates a tag", async () => {
test("successfully creates a tag", async () => {
vi.mocked(checkAuthorizationUpdated).mockResolvedValueOnce(true);
vi.mocked(getOrganizationIdFromEnvironmentId).mockResolvedValueOnce("org1");
await createTagAction({ ...dummyTagInput, ...dummyCtx });
@@ -98,7 +98,7 @@ describe("createTagAction", () => {
});
describe("createTagToResponseAction", () => {
it("adds tag to response when environments match", async () => {
test("adds tag to response when environments match", async () => {
vi.mocked(getEnvironmentIdFromResponseId).mockResolvedValueOnce("env1");
vi.mocked(getTag).mockResolvedValueOnce({ environmentId: "env1" });
await createTagToResponseAction({ ...dummyTagToResponseInput, ...dummyCtx });
@@ -111,7 +111,7 @@ describe("createTagToResponseAction", () => {
);
});
it("throws error when environments do not match", async () => {
test("throws error when environments do not match", async () => {
vi.mocked(getEnvironmentIdFromResponseId).mockResolvedValueOnce("env1");
vi.mocked(getTag).mockResolvedValueOnce({ environmentId: "differentEnv" });
await expect(createTagToResponseAction({ ...dummyTagToResponseInput, ...dummyCtx })).rejects.toThrow(
@@ -121,7 +121,7 @@ describe("createTagToResponseAction", () => {
});
describe("deleteTagOnResponseAction", () => {
it("deletes tag on response when environments match", async () => {
test("deletes tag on response when environments match", async () => {
vi.mocked(getEnvironmentIdFromResponseId).mockResolvedValueOnce("env1");
vi.mocked(getTag).mockResolvedValueOnce({ environmentId: "env1" });
await deleteTagOnResponseAction({ ...dummyTagToResponseInput, ...dummyCtx });
@@ -134,7 +134,7 @@ describe("deleteTagOnResponseAction", () => {
);
});
it("throws error when environments do not match", async () => {
test("throws error when environments do not match", async () => {
vi.mocked(getEnvironmentIdFromResponseId).mockResolvedValueOnce("env1");
vi.mocked(getTag).mockResolvedValueOnce({ environmentId: "differentEnv" });
await expect(deleteTagOnResponseAction({ ...dummyTagToResponseInput, ...dummyCtx })).rejects.toThrow(
@@ -144,7 +144,7 @@ describe("deleteTagOnResponseAction", () => {
});
describe("deleteResponseAction", () => {
it("deletes response successfully", async () => {
test("deletes response successfully", async () => {
vi.mocked(checkAuthorizationUpdated).mockResolvedValueOnce(true);
await deleteResponseAction({ ...dummyResponseIdInput, ...dummyCtx });
expect(checkAuthorizationUpdated).toHaveBeenCalled();
@@ -155,7 +155,7 @@ describe("deleteResponseAction", () => {
});
describe("updateResponseNoteAction", () => {
it("updates response note successfully", async () => {
test("updates response note successfully", async () => {
vi.mocked(checkAuthorizationUpdated).mockResolvedValueOnce(true);
await updateResponseNoteAction({ ...dummyResponseNoteInput, ...dummyCtx });
expect(checkAuthorizationUpdated).toHaveBeenCalled();
@@ -169,7 +169,7 @@ describe("updateResponseNoteAction", () => {
});
describe("resolveResponseNoteAction", () => {
it("resolves response note successfully", async () => {
test("resolves response note successfully", async () => {
vi.mocked(checkAuthorizationUpdated).mockResolvedValueOnce(true);
await resolveResponseNoteAction({ responseNoteId: "note1", ...dummyCtx });
expect(checkAuthorizationUpdated).toHaveBeenCalled();
@@ -180,7 +180,7 @@ describe("resolveResponseNoteAction", () => {
});
describe("createResponseNoteAction", () => {
it("creates a response note successfully", async () => {
test("creates a response note successfully", async () => {
vi.mocked(checkAuthorizationUpdated).mockResolvedValueOnce(true);
await createResponseNoteAction({ ...dummyCreateNoteInput, ...dummyCtx });
expect(checkAuthorizationUpdated).toHaveBeenCalled();
@@ -195,7 +195,7 @@ describe("createResponseNoteAction", () => {
});
describe("getResponseAction", () => {
it("retrieves response successfully", async () => {
test("retrieves response successfully", async () => {
vi.mocked(checkAuthorizationUpdated).mockResolvedValueOnce(true);
await getResponseAction({ ...dummyGetResponseInput, ...dummyCtx });
expect(checkAuthorizationUpdated).toHaveBeenCalled();

View File

@@ -1,5 +1,5 @@
import { cleanup, render, screen } from "@testing-library/react";
import { afterEach, describe, expect, it, vi } from "vitest";
import { afterEach, describe, expect, test, vi } from "vitest";
import { TSurveyHiddenFields } from "@formbricks/types/surveys/types";
import { HiddenFields } from "./HiddenFields";
@@ -16,7 +16,7 @@ describe("HiddenFields", () => {
cleanup();
});
it("renders empty container when no fieldIds are provided", () => {
test("renders empty container when no fieldIds are provided", () => {
render(
<HiddenFields hiddenFields={{ fieldIds: [] } as unknown as TSurveyHiddenFields} responseData={{}} />
);
@@ -24,7 +24,7 @@ describe("HiddenFields", () => {
expect(container).toBeDefined();
});
it("renders nothing for fieldIds with no corresponding response data", () => {
test("renders nothing for fieldIds with no corresponding response data", () => {
render(
<HiddenFields
hiddenFields={{ fieldIds: ["field1"] } as unknown as TSurveyHiddenFields}
@@ -34,7 +34,7 @@ describe("HiddenFields", () => {
expect(screen.queryByText("field1")).toBeNull();
});
it("renders field and value when responseData exists and is a string", async () => {
test("renders field and value when responseData exists and is a string", async () => {
render(
<HiddenFields
hiddenFields={{ fieldIds: ["field1", "field2"] } as unknown as TSurveyHiddenFields}
@@ -46,7 +46,7 @@ describe("HiddenFields", () => {
expect(screen.queryByText("field2")).toBeNull();
});
it("renders empty text when responseData value is not a string", () => {
test("renders empty text when responseData value is not a string", () => {
render(
<HiddenFields
hiddenFields={{ fieldIds: ["field1"] } as unknown as TSurveyHiddenFields}
@@ -58,7 +58,7 @@ describe("HiddenFields", () => {
expect(valueParagraphs.length).toBeGreaterThan(0);
});
it("displays tooltip content for hidden field", async () => {
test("displays tooltip content for hidden field", async () => {
render(
<HiddenFields
hiddenFields={{ fieldIds: ["field1"] } as unknown as TSurveyHiddenFields}

View File

@@ -1,5 +1,5 @@
import { cleanup, render, screen } from "@testing-library/react";
import { afterEach, describe, expect, it, vi } from "vitest";
import { afterEach, describe, expect, test, vi } from "vitest";
import { parseRecallInfo } from "@formbricks/lib/utils/recall";
import { TSurveyQuestion } from "@formbricks/types/surveys/types";
import { QuestionSkip } from "./QuestionSkip";
@@ -34,7 +34,7 @@ describe("QuestionSkip", () => {
cleanup();
});
it("renders nothing when skippedQuestions is falsy", () => {
test("renders nothing when skippedQuestions is falsy", () => {
render(
<QuestionSkip
skippedQuestions={undefined}
@@ -47,7 +47,7 @@ describe("QuestionSkip", () => {
expect(screen.queryByText("headline2")).toBeNull();
});
it("renders welcomeCard branch", () => {
test("renders welcomeCard branch", () => {
render(
<QuestionSkip
skippedQuestions={["f1"]}
@@ -60,7 +60,7 @@ describe("QuestionSkip", () => {
expect(screen.getByText("common.welcome_card")).toBeInTheDocument();
});
it("renders skipped branch with tooltip and parsed headlines", () => {
test("renders skipped branch with tooltip and parsed headlines", () => {
vi.mocked(parseRecallInfo).mockReturnValueOnce("parsed: headline1");
vi.mocked(parseRecallInfo).mockReturnValueOnce("parsed: headline2");
@@ -79,7 +79,7 @@ describe("QuestionSkip", () => {
expect(screen.getByText("parsed: headline2")).toBeInTheDocument();
});
it("renders aborted branch with closed message and parsed headlines", () => {
test("renders aborted branch with closed message and parsed headlines", () => {
vi.mocked(parseRecallInfo).mockReturnValueOnce("parsed: headline1");
vi.mocked(parseRecallInfo).mockReturnValueOnce("parsed: headline2");

View File

@@ -1,5 +1,5 @@
import { cleanup, render, screen } from "@testing-library/react";
import { afterEach, describe, expect, it, vi } from "vitest";
import { afterEach, describe, expect, test, vi } from "vitest";
import { RenderResponse } from "./RenderResponse";
// Mocks for dependencies
@@ -53,7 +53,7 @@ describe("RenderResponse", () => {
const defaultQuestion = { id: "q1", type: "Unknown" } as any;
const dummyLanguage = "default";
it("returns '-' for empty responseData (string)", () => {
test("returns '-' for empty responseData (string)", () => {
const { container } = render(
<RenderResponse
responseData={""}
@@ -65,7 +65,7 @@ describe("RenderResponse", () => {
expect(container.textContent).toBe("-");
});
it("returns '-' for empty responseData (array)", () => {
test("returns '-' for empty responseData (array)", () => {
const { container } = render(
<RenderResponse
responseData={[]}
@@ -77,7 +77,7 @@ describe("RenderResponse", () => {
expect(container.textContent).toBe("-");
});
it("returns '-' for empty responseData (object)", () => {
test("returns '-' for empty responseData (object)", () => {
const { container } = render(
<RenderResponse
responseData={{}}
@@ -89,7 +89,7 @@ describe("RenderResponse", () => {
expect(container.textContent).toBe("-");
});
it("renders RatingResponse for 'Rating' question with number", () => {
test("renders RatingResponse for 'Rating' question with number", () => {
const question = { ...defaultQuestion, type: "rating", scale: 5, range: [1, 5] };
render(
<RenderResponse responseData={4} question={question} survey={defaultSurvey} language={dummyLanguage} />
@@ -97,7 +97,7 @@ describe("RenderResponse", () => {
expect(screen.getByTestId("RatingResponse")).toHaveTextContent("Rating: 4");
});
it("renders formatted date for 'Date' question", () => {
test("renders formatted date for 'Date' question", () => {
const question = { ...defaultQuestion, type: "date" };
const dateStr = new Date("2023-01-01T12:00:00Z").toISOString();
render(
@@ -111,7 +111,7 @@ describe("RenderResponse", () => {
expect(screen.getByText(/formatted_/)).toBeInTheDocument();
});
it("renders PictureSelectionResponse for 'PictureSelection' question", () => {
test("renders PictureSelectionResponse for 'PictureSelection' question", () => {
const question = { ...defaultQuestion, type: "pictureSelection", choices: ["a", "b"] };
render(
<RenderResponse
@@ -126,7 +126,7 @@ describe("RenderResponse", () => {
);
});
it("renders FileUploadResponse for 'FileUpload' question", () => {
test("renders FileUploadResponse for 'FileUpload' question", () => {
const question = { ...defaultQuestion, type: "fileUpload" };
render(
<RenderResponse
@@ -139,7 +139,7 @@ describe("RenderResponse", () => {
expect(screen.getByTestId("FileUploadResponse")).toHaveTextContent("FileUpload: file1,file2");
});
it("renders Matrix response", () => {
test("renders Matrix response", () => {
const question = { id: "q1", type: "matrix", rows: ["row1", "row2"] } as any;
// getLocalizedValue returns the row value itself
const responseData = { row1: "answer1", row2: "answer2" };
@@ -155,7 +155,7 @@ describe("RenderResponse", () => {
expect(screen.getByText("row2:processed:answer2")).toBeInTheDocument();
});
it("renders ArrayResponse for 'Address' question", () => {
test("renders ArrayResponse for 'Address' question", () => {
const question = { ...defaultQuestion, type: "address" };
render(
<RenderResponse
@@ -168,7 +168,7 @@ describe("RenderResponse", () => {
expect(screen.getByTestId("ArrayResponse")).toHaveTextContent("addr1,addr2");
});
it("renders ResponseBadges for 'Cal' question (string)", () => {
test("renders ResponseBadges for 'Cal' question (string)", () => {
const question = { ...defaultQuestion, type: "cal" };
render(
<RenderResponse
@@ -181,7 +181,7 @@ describe("RenderResponse", () => {
expect(screen.getByTestId("ResponseBadges")).toHaveTextContent("Value");
});
it("renders ResponseBadges for 'Consent' question (number)", () => {
test("renders ResponseBadges for 'Consent' question (number)", () => {
const question = { ...defaultQuestion, type: "consent" };
render(
<RenderResponse responseData={5} question={question} survey={defaultSurvey} language={dummyLanguage} />
@@ -189,7 +189,7 @@ describe("RenderResponse", () => {
expect(screen.getByTestId("ResponseBadges")).toHaveTextContent("5");
});
it("renders ResponseBadges for 'CTA' question (string)", () => {
test("renders ResponseBadges for 'CTA' question (string)", () => {
const question = { ...defaultQuestion, type: "cta" };
render(
<RenderResponse
@@ -202,7 +202,7 @@ describe("RenderResponse", () => {
expect(screen.getByTestId("ResponseBadges")).toHaveTextContent("Click");
});
it("renders ResponseBadges for 'MultipleChoiceSingle' question (string)", () => {
test("renders ResponseBadges for 'MultipleChoiceSingle' question (string)", () => {
const question = { ...defaultQuestion, type: "multipleChoiceSingle" };
render(
<RenderResponse
@@ -215,7 +215,7 @@ describe("RenderResponse", () => {
expect(screen.getByTestId("ResponseBadges")).toHaveTextContent("option1");
});
it("renders ResponseBadges for 'MultipleChoiceMulti' question (array)", () => {
test("renders ResponseBadges for 'MultipleChoiceMulti' question (array)", () => {
const question = { ...defaultQuestion, type: "multipleChoiceMulti" };
render(
<RenderResponse
@@ -228,7 +228,7 @@ describe("RenderResponse", () => {
expect(screen.getByTestId("ResponseBadges")).toHaveTextContent("opt1,opt2");
});
it("renders ResponseBadges for 'NPS' question (number)", () => {
test("renders ResponseBadges for 'NPS' question (number)", () => {
const question = { ...defaultQuestion, type: "nps" };
render(
<RenderResponse responseData={9} question={question} survey={defaultSurvey} language={dummyLanguage} />
@@ -236,7 +236,7 @@ describe("RenderResponse", () => {
expect(screen.getByTestId("ResponseBadges")).toHaveTextContent("9");
});
it("renders RankingRespone for 'Ranking' question", () => {
test("renders RankingRespone for 'Ranking' question", () => {
const question = { ...defaultQuestion, type: "ranking" };
render(
<RenderResponse
@@ -249,7 +249,7 @@ describe("RenderResponse", () => {
expect(screen.getByTestId("RankingRespone")).toHaveTextContent("first,second");
});
it("renders default branch for unknown question type with string", () => {
test("renders default branch for unknown question type with string", () => {
const question = { ...defaultQuestion, type: "unknown" };
render(
<RenderResponse
@@ -262,7 +262,7 @@ describe("RenderResponse", () => {
expect(screen.getByText("hyper:some text")).toBeInTheDocument();
});
it("renders default branch for unknown question type with array", () => {
test("renders default branch for unknown question type with array", () => {
const question = { ...defaultQuestion, type: "unknown" };
render(
<RenderResponse

View File

@@ -1,6 +1,6 @@
import { cleanup, render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { afterEach, describe, expect, it, vi } from "vitest";
import { afterEach, describe, expect, test, vi } from "vitest";
import { TResponseNote } from "@formbricks/types/responses";
import { TUser } from "@formbricks/types/user";
import { createResponseNoteAction, resolveResponseNoteAction, updateResponseNoteAction } from "../actions";
@@ -84,7 +84,7 @@ describe("ResponseNotes", () => {
cleanup();
});
it("renders collapsed view when isOpen is false", () => {
test("renders collapsed view when isOpen is false", () => {
render(
<ResponseNotes
user={dummyUser}
@@ -99,7 +99,7 @@ describe("ResponseNotes", () => {
expect(screen.getByText(/note/i)).toBeInTheDocument();
});
it("opens panel on click when collapsed", async () => {
test("opens panel on click when collapsed", async () => {
render(
<ResponseNotes
user={dummyUser}
@@ -115,7 +115,7 @@ describe("ResponseNotes", () => {
expect(setIsOpen).toHaveBeenCalledWith(true);
});
it("submits a new note", async () => {
test("submits a new note", async () => {
vi.mocked(createResponseNoteAction).mockResolvedValueOnce("createdNote" as any);
render(
<ResponseNotes
@@ -140,7 +140,7 @@ describe("ResponseNotes", () => {
});
});
it("edits an existing note", async () => {
test("edits an existing note", async () => {
vi.mocked(updateResponseNoteAction).mockResolvedValueOnce("updatedNote" as any);
render(
<ResponseNotes
@@ -169,7 +169,7 @@ describe("ResponseNotes", () => {
});
});
it("resolves a note", async () => {
test("resolves a note", async () => {
vi.mocked(resolveResponseNoteAction).mockResolvedValueOnce(undefined);
render(
<ResponseNotes

View File

@@ -1,7 +1,7 @@
import { act, cleanup, render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import toast from "react-hot-toast";
import { afterEach, describe, expect, it, vi } from "vitest";
import { afterEach, describe, expect, test, vi } from "vitest";
import { TTag } from "@formbricks/types/tags";
import { createTagAction, createTagToResponseAction, deleteTagOnResponseAction } from "../actions";
import { ResponseTagsWrapper } from "./ResponseTagsWrapper";
@@ -62,7 +62,7 @@ describe("ResponseTagsWrapper", () => {
cleanup();
});
it("renders settings button when not readOnly and navigates on click", async () => {
test("renders settings button when not readOnly and navigates on click", async () => {
render(
<ResponseTagsWrapper
tags={dummyTags}
@@ -78,7 +78,7 @@ describe("ResponseTagsWrapper", () => {
expect(dummyRouterPush).toHaveBeenCalledWith(`/environments/${dummyEnvironmentId}/project/tags`);
});
it("does not render settings button when readOnly", () => {
test("does not render settings button when readOnly", () => {
render(
<ResponseTagsWrapper
tags={dummyTags}
@@ -92,7 +92,7 @@ describe("ResponseTagsWrapper", () => {
expect(screen.queryByRole("button")).toBeNull();
});
it("renders provided tags", () => {
test("renders provided tags", () => {
render(
<ResponseTagsWrapper
tags={dummyTags}
@@ -108,7 +108,7 @@ describe("ResponseTagsWrapper", () => {
expect(screen.getByText("Tag Two")).toBeInTheDocument();
});
it("calls deleteTagOnResponseAction on tag delete success", async () => {
test("calls deleteTagOnResponseAction on tag delete success", async () => {
vi.mocked(deleteTagOnResponseAction).mockResolvedValueOnce({ data: "deleted" } as any);
render(
<ResponseTagsWrapper
@@ -128,7 +128,7 @@ describe("ResponseTagsWrapper", () => {
});
});
it("shows toast error on deleteTagOnResponseAction error", async () => {
test("shows toast error on deleteTagOnResponseAction error", async () => {
vi.mocked(deleteTagOnResponseAction).mockRejectedValueOnce(new Error("delete error"));
render(
<ResponseTagsWrapper
@@ -149,7 +149,7 @@ describe("ResponseTagsWrapper", () => {
});
});
it("creates a new tag via TagsCombobox and calls updateFetchedResponses on success", async () => {
test("creates a new tag via TagsCombobox and calls updateFetchedResponses on success", async () => {
vi.mocked(createTagAction).mockResolvedValueOnce({ data: { id: "newTagId", name: "NewTag" } } as any);
vi.mocked(createTagToResponseAction).mockResolvedValueOnce({ data: "tagAdded" } as any);
render(
@@ -174,7 +174,7 @@ describe("ResponseTagsWrapper", () => {
});
});
it("handles createTagAction failure and shows toast error", async () => {
test("handles createTagAction failure and shows toast error", async () => {
vi.mocked(createTagAction).mockResolvedValueOnce({
error: { details: [{ issue: "Unique constraint failed on the fields" }] },
} as any);
@@ -198,7 +198,7 @@ describe("ResponseTagsWrapper", () => {
});
});
it("calls addTag correctly via TagsCombobox", async () => {
test("calls addTag correctly via TagsCombobox", async () => {
vi.mocked(createTagToResponseAction).mockResolvedValueOnce({ data: "tagAdded" } as any);
render(
<ResponseTagsWrapper
@@ -218,7 +218,7 @@ describe("ResponseTagsWrapper", () => {
});
});
it("clears tagIdToHighlight after timeout", async () => {
test("clears tagIdToHighlight after timeout", async () => {
vi.useFakeTimers();
render(

View File

@@ -1,5 +1,5 @@
import { cleanup, render, screen } from "@testing-library/react";
import { afterEach, describe, expect, it, vi } from "vitest";
import { afterEach, describe, expect, test, vi } from "vitest";
import { TResponseVariables } from "@formbricks/types/responses";
import { TSurveyVariables } from "@formbricks/types/surveys/types";
import { ResponseVariables } from "./ResponseVariables";
@@ -46,7 +46,7 @@ describe("ResponseVariables", () => {
cleanup();
});
it("renders nothing when no variable in variablesData meets type check", () => {
test("renders nothing when no variable in variablesData meets type check", () => {
render(
<ResponseVariables
variables={dummyVariables}
@@ -57,7 +57,7 @@ describe("ResponseVariables", () => {
expect(screen.queryByText("Variable Two")).toBeNull();
});
it("renders variables with valid response data", () => {
test("renders variables with valid response data", () => {
render(<ResponseVariables variables={dummyVariables} variablesData={dummyVariablesData} />);
expect(screen.getByText("Variable One")).toBeInTheDocument();
expect(screen.getByText("Variable Two")).toBeInTheDocument();
@@ -66,13 +66,13 @@ describe("ResponseVariables", () => {
expect(screen.getByText("abc")).toBeInTheDocument();
});
it("renders FileDigitIcon for number type and FileType2Icon for string type", () => {
test("renders FileDigitIcon for number type and FileType2Icon for string type", () => {
render(<ResponseVariables variables={dummyVariables} variablesData={dummyVariablesData} />);
expect(screen.getByTestId("FileDigitIcon")).toBeInTheDocument();
expect(screen.getByTestId("FileType2Icon")).toBeInTheDocument();
});
it("displays tooltip content with 'common.variable'", () => {
test("displays tooltip content with 'common.variable'", () => {
render(<ResponseVariables variables={dummyVariables} variablesData={dummyVariablesData} />);
// TooltipContent mock always renders its children directly.
expect(screen.getAllByText("common.variable")[0]).toBeInTheDocument();

View File

@@ -1,5 +1,5 @@
import { cleanup, render, screen } from "@testing-library/react";
import { afterEach, describe, expect, it, vi } from "vitest";
import { afterEach, describe, expect, test, vi } from "vitest";
import { TResponse } from "@formbricks/types/responses";
import { TSurvey } from "@formbricks/types/surveys/types";
import { SingleResponseCardBody } from "./SingleResponseCardBody";
@@ -65,17 +65,17 @@ describe("SingleResponseCardBody", () => {
language: "en",
} as unknown as TResponse;
it("renders welcomeCard branch when enabled", () => {
test("renders welcomeCard branch when enabled", () => {
render(<SingleResponseCardBody survey={dummySurvey} response={dummyResponse} skippedQuestions={[]} />);
expect(screen.getAllByTestId("QuestionSkip")[0]).toHaveTextContent("welcomeCard");
});
it("renders VerifiedEmail when enabled and response verified", () => {
test("renders VerifiedEmail when enabled and response verified", () => {
render(<SingleResponseCardBody survey={dummySurvey} response={dummyResponse} skippedQuestions={[]} />);
expect(screen.getByTestId("VerifiedEmail")).toBeInTheDocument();
});
it("renders RenderResponse for valid answer", () => {
test("renders RenderResponse for valid answer", () => {
const surveyCopy = { ...dummySurvey, welcomeCard: { enabled: false } } as TSurvey;
const responseCopy = { ...dummyResponse, data: { q1: "answer1", q2: "" } };
render(<SingleResponseCardBody survey={surveyCopy} response={responseCopy} skippedQuestions={[]} />);
@@ -83,7 +83,7 @@ describe("SingleResponseCardBody", () => {
expect(screen.getByTestId("RenderResponse")).toHaveTextContent("answer1");
});
it("renders QuestionSkip for invalid answer", () => {
test("renders QuestionSkip for invalid answer", () => {
const surveyCopy = { ...dummySurvey, welcomeCard: { enabled: false } } as TSurvey;
const responseCopy = { ...dummyResponse, data: { q1: "", q2: "" } };
render(
@@ -93,23 +93,23 @@ describe("SingleResponseCardBody", () => {
expect(screen.getAllByTestId("QuestionSkip")[1]).toBeInTheDocument();
});
it("renders ResponseVariables when variables exist", () => {
test("renders ResponseVariables when variables exist", () => {
render(<SingleResponseCardBody survey={dummySurvey} response={dummyResponse} skippedQuestions={[]} />);
expect(screen.getByTestId("ResponseVariables")).toBeInTheDocument();
});
it("renders HiddenFields when hiddenFields enabled", () => {
test("renders HiddenFields when hiddenFields enabled", () => {
render(<SingleResponseCardBody survey={dummySurvey} response={dummyResponse} skippedQuestions={[]} />);
expect(screen.getByTestId("HiddenFields")).toBeInTheDocument();
});
it("renders completion indicator when response finished", () => {
test("renders completion indicator when response finished", () => {
render(<SingleResponseCardBody survey={dummySurvey} response={dummyResponse} skippedQuestions={[]} />);
expect(screen.getByTestId("CheckCircle2Icon")).toBeInTheDocument();
expect(screen.getByText("common.completed")).toBeInTheDocument();
});
it("processes question mapping correctly with skippedQuestions modification", () => {
test("processes question mapping correctly with skippedQuestions modification", () => {
// Provide one question valid and one not valid, with skippedQuestions for the invalid one.
const surveyCopy = { ...dummySurvey, welcomeCard: { enabled: false } } as TSurvey;
const responseCopy = { ...dummyResponse, data: { q1: "answer1", q2: "" } };

View File

@@ -1,7 +1,7 @@
import { isSubmissionTimeMoreThan5Minutes } from "@/modules/analysis/components/SingleResponseCard/util";
import { cleanup, render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { afterEach, describe, expect, it, vi } from "vitest";
import { afterEach, describe, expect, test, vi } from "vitest";
import { TEnvironment } from "@formbricks/types/environment";
import { TResponse } from "@formbricks/types/responses";
import { TSurvey } from "@formbricks/types/surveys/types";
@@ -65,7 +65,7 @@ describe("SingleResponseCardHeader", () => {
const dummyUser = { id: "user1", email: "user1@example.com" } as TUser;
const dummyLocale = "en-US";
it("renders response view with contact (user exists)", () => {
test("renders response view with contact (user exists)", () => {
vi.mocked(isSubmissionTimeMoreThan5Minutes).mockReturnValue(true);
render(
<SingleResponseCardHeader
@@ -84,7 +84,7 @@ describe("SingleResponseCardHeader", () => {
expect(screen.getByRole("link")).toBeInTheDocument();
});
it("renders response view with no contact (anonymous)", () => {
test("renders response view with no contact (anonymous)", () => {
const responseNoContact = { ...dummyResponse, contact: null };
render(
<SingleResponseCardHeader
@@ -101,7 +101,7 @@ describe("SingleResponseCardHeader", () => {
expect(screen.getByText("common.anonymous")).toBeInTheDocument();
});
it("renders people view", () => {
test("renders people view", () => {
render(
<SingleResponseCardHeader
pageType="people"
@@ -119,7 +119,7 @@ describe("SingleResponseCardHeader", () => {
expect(screen.getByTestId("SurveyStatusIndicator")).toBeInTheDocument();
});
it("renders language label when response.language is not default", () => {
test("renders language label when response.language is not default", () => {
const modifiedResponse = { ...dummyResponse, language: "fr" };
render(
<SingleResponseCardHeader
@@ -136,7 +136,7 @@ describe("SingleResponseCardHeader", () => {
expect(screen.getByText("fr_en-US")).toBeInTheDocument();
});
it("renders enabled trash icon and handles click", async () => {
test("renders enabled trash icon and handles click", async () => {
vi.mocked(isSubmissionTimeMoreThan5Minutes).mockReturnValue(true);
const setDeleteDialogOpen = vi.fn();
render(
@@ -156,7 +156,7 @@ describe("SingleResponseCardHeader", () => {
expect(setDeleteDialogOpen).toHaveBeenCalledWith(true);
});
it("renders disabled trash icon when deletion not allowed", async () => {
test("renders disabled trash icon when deletion not allowed", async () => {
vi.mocked(isSubmissionTimeMoreThan5Minutes).mockReturnValue(false);
render(
<SingleResponseCardHeader

View File

@@ -1,5 +1,5 @@
import { cleanup, render } from "@testing-library/react";
import { afterEach, describe, expect, it } from "vitest";
import { afterEach, describe, expect, test } from "vitest";
import {
ConfusedFace,
FrowningFace,
@@ -27,34 +27,34 @@ describe("Smileys", () => {
cleanup();
});
it("renders TiredFace", () => {
test("renders TiredFace", () => {
checkSvg(TiredFace);
});
it("renders WearyFace", () => {
test("renders WearyFace", () => {
checkSvg(WearyFace);
});
it("renders PerseveringFace", () => {
test("renders PerseveringFace", () => {
checkSvg(PerseveringFace);
});
it("renders FrowningFace", () => {
test("renders FrowningFace", () => {
checkSvg(FrowningFace);
});
it("renders ConfusedFace", () => {
test("renders ConfusedFace", () => {
checkSvg(ConfusedFace);
});
it("renders NeutralFace", () => {
test("renders NeutralFace", () => {
checkSvg(NeutralFace);
});
it("renders SlightlySmilingFace", () => {
test("renders SlightlySmilingFace", () => {
checkSvg(SlightlySmilingFace);
});
it("renders SmilingFaceWithSmilingEyes", () => {
test("renders SmilingFaceWithSmilingEyes", () => {
checkSvg(SmilingFaceWithSmilingEyes);
});
it("renders GrinningFaceWithSmilingEyes", () => {
test("renders GrinningFaceWithSmilingEyes", () => {
checkSvg(GrinningFaceWithSmilingEyes);
});
it("renders GrinningSquintingFace", () => {
test("renders GrinningSquintingFace", () => {
checkSvg(GrinningSquintingFace);
});
});

View File

@@ -1,5 +1,5 @@
import { cleanup, render, screen } from "@testing-library/react";
import { afterEach, describe, expect, it, vi } from "vitest";
import { afterEach, describe, expect, test, vi } from "vitest";
import { VerifiedEmail } from "./VerifiedEmail";
vi.mock("lucide-react", () => ({
@@ -15,14 +15,14 @@ describe("VerifiedEmail", () => {
cleanup();
});
it("renders verified email text and value when provided", () => {
test("renders verified email text and value when provided", () => {
render(<VerifiedEmail responseData={{ verifiedEmail: "test@example.com" }} />);
expect(screen.getByText("common.verified_email")).toBeInTheDocument();
expect(screen.getByText("test@example.com")).toBeInTheDocument();
expect(screen.getByTestId("MailIcon")).toBeInTheDocument();
});
it("renders empty value when verifiedEmail is not a string", () => {
test("renders empty value when verifiedEmail is not a string", () => {
render(<VerifiedEmail responseData={{ verifiedEmail: 123 }} />);
expect(screen.getByText("common.verified_email")).toBeInTheDocument();
const emptyParagraph = screen.getByText("", { selector: "p.ph-no-capture" });

View File

@@ -1,7 +1,7 @@
import { cleanup, render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import toast from "react-hot-toast";
import { afterEach, describe, expect, it, vi } from "vitest";
import { afterEach, describe, expect, test, vi } from "vitest";
import { TEnvironment } from "@formbricks/types/environment";
import { TResponse } from "@formbricks/types/responses";
import { TSurvey } from "@formbricks/types/surveys/types";
@@ -81,7 +81,7 @@ describe("SingleResponseCard", () => {
cleanup();
});
it("renders as a plain div when survey is draft and isReadOnly", () => {
test("renders as a plain div when survey is draft and isReadOnly", () => {
const draftSurvey = { ...dummySurvey, status: "draft" } as TSurvey;
render(
<SingleResponseCard
@@ -103,7 +103,7 @@ describe("SingleResponseCard", () => {
expect(screen.queryByRole("link")).toBeNull();
});
it("calls deleteResponseAction and refreshes router on successful deletion", async () => {
test("calls deleteResponseAction and refreshes router on successful deletion", async () => {
render(
<SingleResponseCard
survey={dummySurvey}
@@ -131,7 +131,7 @@ describe("SingleResponseCard", () => {
expect(dummyDeleteResponses).toHaveBeenCalledWith([dummyResponse.id]);
});
it("calls toast.error when deleteResponseAction throws error", async () => {
test("calls toast.error when deleteResponseAction throws error", async () => {
vi.mocked(deleteResponseAction).mockRejectedValueOnce(new Error("Delete failed"));
render(
<SingleResponseCard
@@ -157,7 +157,7 @@ describe("SingleResponseCard", () => {
});
});
it("calls updateResponse when getResponseAction returns updated response", async () => {
test("calls updateResponse when getResponseAction returns updated response", async () => {
vi.mocked(getResponseAction).mockResolvedValueOnce({ data: { updated: true } as any });
render(
<SingleResponseCard

View File

@@ -1,49 +1,49 @@
import { describe, expect, it } from "vitest";
import { describe, expect, test } from "vitest";
import { isSubmissionTimeMoreThan5Minutes, isValidValue } from "./util";
describe("isValidValue", () => {
it("returns false for an empty string", () => {
test("returns false for an empty string", () => {
expect(isValidValue("")).toBe(false);
});
it("returns false for a blank string", () => {
test("returns false for a blank string", () => {
expect(isValidValue(" ")).toBe(false);
});
it("returns true for a non-empty string", () => {
test("returns true for a non-empty string", () => {
expect(isValidValue("hello")).toBe(true);
});
it("returns true for numbers", () => {
test("returns true for numbers", () => {
expect(isValidValue(0)).toBe(true);
expect(isValidValue(42)).toBe(true);
});
it("returns false for an empty array", () => {
test("returns false for an empty array", () => {
expect(isValidValue([])).toBe(false);
});
it("returns true for a non-empty array", () => {
test("returns true for a non-empty array", () => {
expect(isValidValue(["item"])).toBe(true);
});
it("returns false for an empty object", () => {
test("returns false for an empty object", () => {
expect(isValidValue({})).toBe(false);
});
it("returns true for a non-empty object", () => {
test("returns true for a non-empty object", () => {
expect(isValidValue({ key: "value" })).toBe(true);
});
});
describe("isSubmissionTimeMoreThan5Minutes", () => {
it("returns true if submission time is more than 5 minutes ago", () => {
test("returns true if submission time is more than 5 minutes ago", () => {
const currentTime = new Date();
const oldTime = new Date(currentTime.getTime() - 6 * 60 * 1000); // 6 minutes ago
expect(isSubmissionTimeMoreThan5Minutes(oldTime)).toBe(true);
});
it("returns false if submission time is less than or equal to 5 minutes ago", () => {
test("returns false if submission time is less than or equal to 5 minutes ago", () => {
const currentTime = new Date();
const recentTime = new Date(currentTime.getTime() - 4 * 60 * 1000); // 4 minutes ago
expect(isSubmissionTimeMoreThan5Minutes(recentTime)).toBe(false);

View File

@@ -1,6 +1,6 @@
import { cleanup } from "@testing-library/react";
import { isValidElement } from "react";
import { afterEach, describe, expect, it, vi } from "vitest";
import { afterEach, describe, expect, test, vi } from "vitest";
import { renderHyperlinkedContent } from "./utils";
describe("renderHyperlinkedContent", () => {
@@ -8,7 +8,7 @@ describe("renderHyperlinkedContent", () => {
cleanup();
});
it("returns a single span element when input has no url", () => {
test("returns a single span element when input has no url", () => {
const input = "Hello world";
const elements = renderHyperlinkedContent(input);
expect(elements).toHaveLength(1);
@@ -19,7 +19,7 @@ describe("renderHyperlinkedContent", () => {
expect(element.props.children).toEqual("Hello world");
});
it("splits input with a valid url into span, anchor, span", () => {
test("splits input with a valid url into span, anchor, span", () => {
const input = "Visit https://example.com for info";
const elements = renderHyperlinkedContent(input);
// Expect three elements: before text, URL link, after text.
@@ -36,7 +36,7 @@ describe("renderHyperlinkedContent", () => {
expect(elements[2].props.children).toEqual(" for info");
});
it("handles multiple valid urls in the input", () => {
test("handles multiple valid urls in the input", () => {
const input = "Link1: https://example.com and Link2: https://vitejs.dev";
const elements = renderHyperlinkedContent(input);
// Expected parts: "Link1: ", "https://example.com", " and Link2: ", "https://vitejs.dev", ""
@@ -47,7 +47,7 @@ describe("renderHyperlinkedContent", () => {
expect(elements[3].props.href).toEqual("https://vitejs.dev");
});
it("renders a span instead of anchor when URL constructor throws", () => {
test("renders a span instead of anchor when URL constructor throws", () => {
// Force global.URL to throw for this test.
const originalURL = global.URL;
vi.spyOn(global, "URL").mockImplementation(() => {

View File

@@ -3,7 +3,7 @@ import { authenticateRequest } from "@/modules/api/v2/auth/authenticate-request"
import { checkRateLimitAndThrowError } from "@/modules/api/v2/lib/rate-limit";
import { handleApiError } from "@/modules/api/v2/lib/utils";
import { ApiErrorResponseV2 } from "@/modules/api/v2/types/api-error";
import { describe, expect, it, vi } from "vitest";
import { describe, expect, test, vi } from "vitest";
import { z } from "zod";
import { err, ok, okVoid } from "@formbricks/types/error-handlers";
@@ -25,7 +25,7 @@ vi.mock("@/modules/api/v2/lib/utils", () => ({
}));
describe("apiWrapper", () => {
it("should handle request and return response", async () => {
test("should handle request and return response", async () => {
const request = new Request("http://localhost", {
headers: { "x-api-key": "valid-api-key" },
});
@@ -49,7 +49,7 @@ describe("apiWrapper", () => {
expect(handler).toHaveBeenCalled();
});
it("should handle errors and return error response", async () => {
test("should handle errors and return error response", async () => {
const request = new Request("http://localhost", {
headers: { "x-api-key": "invalid-api-key" },
});
@@ -67,7 +67,7 @@ describe("apiWrapper", () => {
expect(handler).not.toHaveBeenCalled();
});
it("should parse body schema correctly", async () => {
test("should parse body schema correctly", async () => {
const request = new Request("http://localhost", {
method: "POST",
body: JSON.stringify({ key: "value" }),
@@ -100,7 +100,7 @@ describe("apiWrapper", () => {
);
});
it("should handle body schema errors", async () => {
test("should handle body schema errors", async () => {
const request = new Request("http://localhost", {
method: "POST",
body: JSON.stringify({ key: 123 }),
@@ -131,7 +131,7 @@ describe("apiWrapper", () => {
expect(handler).not.toHaveBeenCalled();
});
it("should parse query schema correctly", async () => {
test("should parse query schema correctly", async () => {
const request = new Request("http://localhost?key=value");
vi.mocked(authenticateRequest).mockResolvedValue(
@@ -160,7 +160,7 @@ describe("apiWrapper", () => {
);
});
it("should handle query schema errors", async () => {
test("should handle query schema errors", async () => {
const request = new Request("http://localhost?foo%ZZ=abc");
vi.mocked(authenticateRequest).mockResolvedValue(
@@ -187,7 +187,7 @@ describe("apiWrapper", () => {
expect(handler).not.toHaveBeenCalled();
});
it("should parse params schema correctly", async () => {
test("should parse params schema correctly", async () => {
const request = new Request("http://localhost");
vi.mocked(authenticateRequest).mockResolvedValue(
@@ -217,7 +217,7 @@ describe("apiWrapper", () => {
);
});
it("should handle no external params", async () => {
test("should handle no external params", async () => {
const request = new Request("http://localhost");
vi.mocked(authenticateRequest).mockResolvedValue(
@@ -245,7 +245,7 @@ describe("apiWrapper", () => {
expect(handler).not.toHaveBeenCalled();
});
it("should handle params schema errors", async () => {
test("should handle params schema errors", async () => {
const request = new Request("http://localhost");
vi.mocked(authenticateRequest).mockResolvedValue(
@@ -273,7 +273,7 @@ describe("apiWrapper", () => {
expect(handler).not.toHaveBeenCalled();
});
it("should handle rate limit errors", async () => {
test("should handle rate limit errors", async () => {
const request = new Request("http://localhost", {
headers: { "x-api-key": "valid-api-key" },
});

View File

@@ -1,5 +1,5 @@
import { hashApiKey } from "@/modules/api/v2/management/lib/utils";
import { describe, expect, it, vi } from "vitest";
import { describe, expect, test, vi } from "vitest";
import { prisma } from "@formbricks/database";
import { authenticateRequest } from "../authenticate-request";
@@ -17,7 +17,7 @@ vi.mock("@/modules/api/v2/management/lib/utils", () => ({
}));
describe("authenticateRequest", () => {
it("should return authentication data if apiKey is valid", async () => {
test("should return authentication data if apiKey is valid", async () => {
const request = new Request("http://localhost", {
headers: { "x-api-key": "valid-api-key" },
});
@@ -87,7 +87,7 @@ describe("authenticateRequest", () => {
}
});
it("should return unauthorized error if apiKey is not found", async () => {
test("should return unauthorized error if apiKey is not found", async () => {
const request = new Request("http://localhost", {
headers: { "x-api-key": "invalid-api-key" },
});
@@ -101,7 +101,7 @@ describe("authenticateRequest", () => {
}
});
it("should return unauthorized error if apiKey is missing", async () => {
test("should return unauthorized error if apiKey is missing", async () => {
const request = new Request("http://localhost");
const result = await authenticateRequest(request);

View File

@@ -1,5 +1,5 @@
import { logApiRequest } from "@/modules/api/v2/lib/utils";
import { describe, expect, it, vi } from "vitest";
import { describe, expect, test, vi } from "vitest";
import { apiWrapper } from "../api-wrapper";
import { authenticatedApiClient } from "../authenticated-api-client";
@@ -12,7 +12,7 @@ vi.mock("@/modules/api/v2/lib/utils", () => ({
}));
describe("authenticatedApiClient", () => {
it("should log request and return response", async () => {
test("should log request and return response", async () => {
const request = new Request("http://localhost", {
headers: { "x-api-key": "valid-api-key" },
});

View File

@@ -1,7 +1,7 @@
import { fetchEnvironmentIdFromSurveyIds } from "@/modules/api/v2/management/lib/services";
import { ApiErrorResponseV2 } from "@/modules/api/v2/types/api-error";
import { createId } from "@paralleldrive/cuid2";
import { describe, expect, it, vi } from "vitest";
import { describe, expect, test, vi } from "vitest";
import { err, ok } from "@formbricks/types/error-handlers";
import { getEnvironmentId, getEnvironmentIdFromSurveyIds } from "../helper";
import { fetchEnvironmentId } from "../services";
@@ -12,7 +12,7 @@ vi.mock("../services", () => ({
}));
describe("Tests for getEnvironmentId", () => {
it("should return environmentId for surveyId", async () => {
test("should return environmentId for surveyId", async () => {
vi.mocked(fetchEnvironmentId).mockResolvedValue(ok({ environmentId: "env-id" }));
const result = await getEnvironmentId("survey-id", false);
@@ -22,7 +22,7 @@ describe("Tests for getEnvironmentId", () => {
}
});
it("should return environmentId for responseId", async () => {
test("should return environmentId for responseId", async () => {
vi.mocked(fetchEnvironmentId).mockResolvedValue(ok({ environmentId: "env-id" }));
const result = await getEnvironmentId("response-id", true);
@@ -32,7 +32,7 @@ describe("Tests for getEnvironmentId", () => {
}
});
it("should return error if getSurveyAndEnvironmentId fails", async () => {
test("should return error if getSurveyAndEnvironmentId fails", async () => {
vi.mocked(fetchEnvironmentId).mockResolvedValue(
err({ type: "not_found" } as unknown as ApiErrorResponseV2)
);
@@ -49,7 +49,7 @@ describe("getEnvironmentIdFromSurveyIds", () => {
const envId1 = createId();
const envId2 = createId();
it("returns the common environment id when all survey ids are in the same environment", async () => {
test("returns the common environment id when all survey ids are in the same environment", async () => {
vi.mocked(fetchEnvironmentIdFromSurveyIds).mockResolvedValueOnce({
ok: true,
data: [envId1, envId1],
@@ -58,7 +58,7 @@ describe("getEnvironmentIdFromSurveyIds", () => {
expect(result).toEqual(ok(envId1));
});
it("returns error when surveys are not in the same environment", async () => {
test("returns error when surveys are not in the same environment", async () => {
vi.mocked(fetchEnvironmentIdFromSurveyIds).mockResolvedValueOnce({
ok: true,
data: [envId1, envId2],
@@ -73,7 +73,7 @@ describe("getEnvironmentIdFromSurveyIds", () => {
}
});
it("returns error when API call fails", async () => {
test("returns error when API call fails", async () => {
const apiError = {
type: "server_error",
details: [{ field: "api", issue: "failed" }],

View File

@@ -1,7 +1,7 @@
import { buildCommonFilterQuery, pickCommonFilter } from "@/modules/api/v2/management/lib/utils";
import { TGetResponsesFilter } from "@/modules/api/v2/management/responses/types/responses";
import { Prisma } from "@prisma/client";
import { describe, expect, it, vi } from "vitest";
import { describe, expect, test, vi } from "vitest";
import { getResponsesQuery } from "../utils";
vi.mock("@/modules/api/v2/management/lib/utils", () => ({
@@ -10,17 +10,17 @@ vi.mock("@/modules/api/v2/management/lib/utils", () => ({
}));
describe("getResponsesQuery", () => {
it("adds surveyId to where clause if provided", () => {
test("adds surveyId to where clause if provided", () => {
const result = getResponsesQuery(["env-id"], { surveyId: "survey123" } as TGetResponsesFilter);
expect(result?.where?.surveyId).toBe("survey123");
});
it("adds contactId to where clause if provided", () => {
test("adds contactId to where clause if provided", () => {
const result = getResponsesQuery(["env-id"], { contactId: "contact123" } as TGetResponsesFilter);
expect(result?.where?.contactId).toBe("contact123");
});
it("calls pickCommonFilter & buildCommonFilterQuery with correct arguments", () => {
test("calls pickCommonFilter & buildCommonFilterQuery with correct arguments", () => {
vi.mocked(pickCommonFilter).mockReturnValueOnce({ someFilter: true } as any);
vi.mocked(buildCommonFilterQuery).mockReturnValueOnce({ where: { combined: true } as any });

View File

@@ -1,6 +1,6 @@
import { buildCommonFilterQuery, pickCommonFilter } from "@/modules/api/v2/management/lib/utils";
import { TGetWebhooksFilter } from "@/modules/api/v2/management/webhooks/types/webhooks";
import { describe, expect, it, vi } from "vitest";
import { describe, expect, test, vi } from "vitest";
import { getWebhooksQuery } from "../utils";
vi.mock("@/modules/api/v2/management/lib/utils", () => ({
@@ -11,7 +11,7 @@ vi.mock("@/modules/api/v2/management/lib/utils", () => ({
describe("getWebhooksQuery", () => {
const environmentId = "env-123";
it("adds surveyIds condition when provided", () => {
test("adds surveyIds condition when provided", () => {
const params = { surveyIds: ["survey1"] } as TGetWebhooksFilter;
const result = getWebhooksQuery([environmentId], params);
expect(result).toBeDefined();
@@ -21,14 +21,14 @@ describe("getWebhooksQuery", () => {
});
});
it("calls pickCommonFilter and buildCommonFilterQuery when baseFilter is present", () => {
test("calls pickCommonFilter and buildCommonFilterQuery when baseFilter is present", () => {
vi.mocked(pickCommonFilter).mockReturnValue({ someFilter: "test" } as any);
getWebhooksQuery([environmentId], { surveyIds: ["survey1"] } as TGetWebhooksFilter);
expect(pickCommonFilter).toHaveBeenCalled();
expect(buildCommonFilterQuery).toHaveBeenCalled();
});
it("buildCommonFilterQuery is not called if no baseFilter is picked", () => {
test("buildCommonFilterQuery is not called if no baseFilter is picked", () => {
vi.mocked(pickCommonFilter).mockReturnValue(undefined as any);
getWebhooksQuery([environmentId], {} as any);
expect(buildCommonFilterQuery).not.toHaveBeenCalled();

View File

@@ -1,7 +1,7 @@
import { webhookCache } from "@/lib/cache/webhook";
import { TGetWebhooksFilter, TWebhookInput } from "@/modules/api/v2/management/webhooks/types/webhooks";
import { WebhookSource } from "@prisma/client";
import { describe, expect, it, vi } from "vitest";
import { describe, expect, test, vi } from "vitest";
import { prisma } from "@formbricks/database";
import { captureTelemetry } from "@formbricks/lib/telemetry";
import { createWebhook, getWebhooks } from "../webhook";
@@ -37,7 +37,7 @@ describe("getWebhooks", () => {
];
const count = fakeWebhooks.length;
it("returns ok response with webhooks and meta", async () => {
test("returns ok response with webhooks and meta", async () => {
vi.mocked(prisma.$transaction).mockResolvedValueOnce([fakeWebhooks, count]);
const result = await getWebhooks(environmentId, params as TGetWebhooksFilter);
@@ -53,7 +53,7 @@ describe("getWebhooks", () => {
}
});
it("returns error when prisma.$transaction throws", async () => {
test("returns error when prisma.$transaction throws", async () => {
vi.mocked(prisma.$transaction).mockRejectedValueOnce(new Error("Test error"));
const result = await getWebhooks(environmentId, params as TGetWebhooksFilter);
@@ -87,7 +87,7 @@ describe("createWebhook", () => {
updatedAt: new Date(),
};
it("creates a webhook and revalidates cache", async () => {
test("creates a webhook and revalidates cache", async () => {
vi.mocked(prisma.webhook.create).mockResolvedValueOnce(createdWebhook);
const result = await createWebhook(inputWebhook);
@@ -104,7 +104,7 @@ describe("createWebhook", () => {
}
});
it("returns error when creation fails", async () => {
test("returns error when creation fails", async () => {
vi.mocked(prisma.webhook.create).mockRejectedValueOnce(new Error("Creation failed"));
const result = await createWebhook(inputWebhook);

View File

@@ -1,4 +1,4 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
import { beforeEach, describe, expect, test, vi } from "vitest";
import { logger } from "@formbricks/logger";
import { OrganizationAccessType } from "@formbricks/types/api-key";
import { hasOrganizationIdAndAccess } from "./utils";
@@ -8,7 +8,7 @@ describe("hasOrganizationIdAndAccess", () => {
vi.restoreAllMocks();
});
it("should return false and log error if authentication has no organizationId", () => {
test("should return false and log error if authentication has no organizationId", () => {
const spyError = vi.spyOn(logger, "error").mockImplementation(() => {});
const authentication = {
organizationAccess: { accessControl: { read: true } },
@@ -21,7 +21,7 @@ describe("hasOrganizationIdAndAccess", () => {
);
});
it("should return false and log error if param organizationId does not match authentication organizationId", () => {
test("should return false and log error if param organizationId does not match authentication organizationId", () => {
const spyError = vi.spyOn(logger, "error").mockImplementation(() => {});
const authentication = {
organizationId: "org2",
@@ -35,7 +35,7 @@ describe("hasOrganizationIdAndAccess", () => {
);
});
it("should return false if access type is missing in organizationAccess", () => {
test("should return false if access type is missing in organizationAccess", () => {
const authentication = {
organizationId: "org1",
organizationAccess: { accessControl: {} },
@@ -45,7 +45,7 @@ describe("hasOrganizationIdAndAccess", () => {
expect(result).toBe(false);
});
it("should return true if organizationId and access type are valid", () => {
test("should return true if organizationId and access type are valid", () => {
const authentication = {
organizationId: "org1",
organizationAccess: { accessControl: { read: true } },

View File

@@ -3,7 +3,7 @@ import {
TProjectTeamInput,
ZProjectZTeamUpdateSchema,
} from "@/modules/api/v2/organizations/[organizationId]/project-teams/types/project-teams";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { beforeEach, describe, expect, test, vi } from "vitest";
import { TypeOf } from "zod";
import { prisma } from "@formbricks/database";
import { createProjectTeam, deleteProjectTeam, getProjectTeams, updateProjectTeam } from "../project-teams";
@@ -27,7 +27,7 @@ describe("ProjectTeams Lib", () => {
});
describe("getProjectTeams", () => {
it("returns projectTeams with meta on success", async () => {
test("returns projectTeams with meta on success", async () => {
const mockTeams = [{ id: "projTeam1", organizationId: "orgx", projectId: "p1", teamId: "t1" }];
(prisma.$transaction as any).mockResolvedValueOnce([mockTeams, mockTeams.length]);
const result = await getProjectTeams("orgx", { skip: 0, limit: 10 } as TGetProjectTeamsFilter);
@@ -41,7 +41,7 @@ describe("ProjectTeams Lib", () => {
}
});
it("returns internal_server_error on exception", async () => {
test("returns internal_server_error on exception", async () => {
(prisma.$transaction as any).mockRejectedValueOnce(new Error("DB error"));
const result = await getProjectTeams("orgx", { skip: 0, limit: 10 } as TGetProjectTeamsFilter);
expect(result.ok).toBe(false);
@@ -52,7 +52,7 @@ describe("ProjectTeams Lib", () => {
});
describe("createProjectTeam", () => {
it("creates a projectTeam successfully", async () => {
test("creates a projectTeam successfully", async () => {
const mockCreated = { id: "ptx", projectId: "p1", teamId: "t1", organizationId: "orgx" };
(prisma.projectTeam.create as any).mockResolvedValueOnce(mockCreated);
const result = await createProjectTeam({
@@ -65,7 +65,7 @@ describe("ProjectTeams Lib", () => {
}
});
it("returns internal_server_error on error", async () => {
test("returns internal_server_error on error", async () => {
(prisma.projectTeam.create as any).mockRejectedValueOnce(new Error("Create error"));
const result = await createProjectTeam({
projectId: "p1",
@@ -79,7 +79,7 @@ describe("ProjectTeams Lib", () => {
});
describe("updateProjectTeam", () => {
it("updates a projectTeam successfully", async () => {
test("updates a projectTeam successfully", async () => {
(prisma.projectTeam.update as any).mockResolvedValueOnce({
id: "pt01",
projectId: "p1",
@@ -95,7 +95,7 @@ describe("ProjectTeams Lib", () => {
}
});
it("returns internal_server_error on error", async () => {
test("returns internal_server_error on error", async () => {
(prisma.projectTeam.update as any).mockRejectedValueOnce(new Error("Update error"));
const result = await updateProjectTeam("t1", "p1", { permission: "READ" } as unknown as TypeOf<
typeof ZProjectZTeamUpdateSchema
@@ -108,7 +108,7 @@ describe("ProjectTeams Lib", () => {
});
describe("deleteProjectTeam", () => {
it("deletes a projectTeam successfully", async () => {
test("deletes a projectTeam successfully", async () => {
(prisma.projectTeam.delete as any).mockResolvedValueOnce({
projectId: "p1",
teamId: "t1",
@@ -122,7 +122,7 @@ describe("ProjectTeams Lib", () => {
}
});
it("returns internal_server_error on error", async () => {
test("returns internal_server_error on error", async () => {
(prisma.projectTeam.delete as any).mockRejectedValueOnce(new Error("Delete error"));
const result = await deleteProjectTeam("t1", "p1");
expect(result.ok).toBe(false);

View File

@@ -1,6 +1,6 @@
import { teamCache } from "@/lib/cache/team";
import { PrismaClientKnownRequestError } from "@prisma/client/runtime/library";
import { describe, expect, it, vi } from "vitest";
import { describe, expect, test, vi } from "vitest";
import { prisma } from "@formbricks/database";
import { PrismaErrorType } from "@formbricks/database/types/error";
import { deleteTeam, getTeam, updateTeam } from "../teams";
@@ -25,7 +25,7 @@ const mockTeam = {
describe("Teams Lib", () => {
describe("getTeam", () => {
it("returns the team when found", async () => {
test("returns the team when found", async () => {
(prisma.team.findUnique as any).mockResolvedValueOnce(mockTeam);
const result = await getTeam("org456", "team123");
expect(result.ok).toBe(true);
@@ -37,7 +37,7 @@ describe("Teams Lib", () => {
});
});
it("returns a not_found error when team is missing", async () => {
test("returns a not_found error when team is missing", async () => {
(prisma.team.findUnique as any).mockResolvedValueOnce(null);
const result = await getTeam("org456", "team123");
expect(result.ok).toBe(false);
@@ -49,7 +49,7 @@ describe("Teams Lib", () => {
}
});
it("returns an internal_server_error when prisma throws", async () => {
test("returns an internal_server_error when prisma throws", async () => {
(prisma.team.findUnique as any).mockRejectedValueOnce(new Error("DB error"));
const result = await getTeam("org456", "team123");
expect(result.ok).toBe(false);
@@ -60,7 +60,7 @@ describe("Teams Lib", () => {
});
describe("deleteTeam", () => {
it("deletes the team and revalidates cache", async () => {
test("deletes the team and revalidates cache", async () => {
(prisma.team.delete as any).mockResolvedValueOnce(mockTeam);
// Mock teamCache.revalidate
const revalidateMock = vi.spyOn(teamCache, "revalidate").mockImplementation(() => {});
@@ -82,7 +82,7 @@ describe("Teams Lib", () => {
}
});
it("returns not_found error on known prisma error", async () => {
test("returns not_found error on known prisma error", async () => {
(prisma.team.delete as any).mockRejectedValueOnce(
new PrismaClientKnownRequestError("Not found", {
code: PrismaErrorType.RecordDoesNotExist,
@@ -100,7 +100,7 @@ describe("Teams Lib", () => {
}
});
it("returns internal_server_error on exception", async () => {
test("returns internal_server_error on exception", async () => {
(prisma.team.delete as any).mockRejectedValueOnce(new Error("Delete failed"));
const result = await deleteTeam("org456", "team123");
expect(result.ok).toBe(false);
@@ -114,7 +114,7 @@ describe("Teams Lib", () => {
const updateInput = { name: "Updated Team" };
const updatedTeam = { ...mockTeam, ...updateInput };
it("updates the team successfully and revalidates cache", async () => {
test("updates the team successfully and revalidates cache", async () => {
(prisma.team.update as any).mockResolvedValueOnce(updatedTeam);
const revalidateMock = vi.spyOn(teamCache, "revalidate").mockImplementation(() => {});
const result = await updateTeam("org456", "team123", updateInput);
@@ -136,7 +136,7 @@ describe("Teams Lib", () => {
}
});
it("returns not_found error when update fails due to missing team", async () => {
test("returns not_found error when update fails due to missing team", async () => {
(prisma.team.update as any).mockRejectedValueOnce(
new PrismaClientKnownRequestError("Not found", {
code: PrismaErrorType.RecordDoesNotExist,
@@ -154,7 +154,7 @@ describe("Teams Lib", () => {
}
});
it("returns internal_server_error on generic exception", async () => {
test("returns internal_server_error on generic exception", async () => {
(prisma.team.update as any).mockRejectedValueOnce(new Error("Update failed"));
const result = await updateTeam("org456", "team123", updateInput);
expect(result.ok).toBe(false);

View File

@@ -1,5 +1,5 @@
import { TGetTeamsFilter } from "@/modules/api/v2/organizations/[organizationId]/teams/types/teams";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { beforeEach, describe, expect, test, vi } from "vitest";
import { prisma } from "@formbricks/database";
import { organizationCache } from "@formbricks/lib/organization/cache";
import { createTeam, getTeams } from "../teams";
@@ -32,7 +32,7 @@ vi.spyOn(organizationCache, "revalidate").mockImplementation(() => {});
describe("Teams Lib", () => {
describe("createTeam", () => {
it("creates a team successfully and revalidates cache", async () => {
test("creates a team successfully and revalidates cache", async () => {
(prisma.team.create as any).mockResolvedValueOnce(mockTeam);
const teamInput = { name: "Test Team" };
@@ -49,7 +49,7 @@ describe("Teams Lib", () => {
if (result.ok) expect(result.data).toEqual(mockTeam);
});
it("returns internal error when prisma.team.create fails", async () => {
test("returns internal error when prisma.team.create fails", async () => {
(prisma.team.create as any).mockRejectedValueOnce(new Error("Create error"));
const teamInput = { name: "Test Team" };
const organizationId = "org456";
@@ -63,7 +63,7 @@ describe("Teams Lib", () => {
describe("getTeams", () => {
const filter = { limit: 10, skip: 0 };
it("returns teams with meta on success", async () => {
test("returns teams with meta on success", async () => {
const teamsArray = [mockTeam];
// Simulate prisma transaction return [teams, count]
(prisma.$transaction as any).mockResolvedValueOnce([teamsArray, teamsArray.length]);
@@ -80,7 +80,7 @@ describe("Teams Lib", () => {
}
});
it("returns internal_server_error when prisma transaction fails", async () => {
test("returns internal_server_error when prisma transaction fails", async () => {
(prisma.$transaction as any).mockRejectedValueOnce(new Error("Transaction error"));
const organizationId = "org456";
const result = await getTeams(organizationId, filter as TGetTeamsFilter);

View File

@@ -1,6 +1,6 @@
import { buildCommonFilterQuery, pickCommonFilter } from "@/modules/api/v2/management/lib/utils";
import { Prisma } from "@prisma/client";
import { describe, expect, it, vi } from "vitest";
import { describe, expect, test, vi } from "vitest";
import { getTeamsQuery } from "../utils";
// Mock the common utils functions
@@ -12,12 +12,12 @@ vi.mock("@/modules/api/v2/management/lib/utils", () => ({
describe("getTeamsQuery", () => {
const organizationId = "org123";
it("returns base query when no params provided", () => {
test("returns base query when no params provided", () => {
const result = getTeamsQuery(organizationId);
expect(result.where).toEqual({ organizationId });
});
it("returns unchanged query if pickCommonFilter returns null/undefined", () => {
test("returns unchanged query if pickCommonFilter returns null/undefined", () => {
vi.mocked(pickCommonFilter).mockReturnValueOnce(null as any);
const params: any = { someParam: "test" };
const result = getTeamsQuery(organizationId, params);
@@ -26,7 +26,7 @@ describe("getTeamsQuery", () => {
expect(result.where).toEqual({ organizationId });
});
it("calls buildCommonFilterQuery and returns updated query when base filter exists", () => {
test("calls buildCommonFilterQuery and returns updated query when base filter exists", () => {
const baseFilter = { key: "value" };
vi.mocked(pickCommonFilter).mockReturnValueOnce(baseFilter as any);
// Simulate buildCommonFilterQuery to merge base query with baseFilter

View File

@@ -1,6 +1,6 @@
import { teamCache } from "@/lib/cache/team";
import { TGetUsersFilter } from "@/modules/api/v2/organizations/[organizationId]/users/types/users";
import { describe, expect, it, vi } from "vitest";
import { describe, expect, test, vi } from "vitest";
import { prisma } from "@formbricks/database";
import { membershipCache } from "@formbricks/lib/membership/cache";
import { userCache } from "@formbricks/lib/user/cache";
@@ -45,7 +45,7 @@ vi.spyOn(teamCache, "revalidate").mockImplementation(() => {});
describe("Users Lib", () => {
describe("getUsers", () => {
it("returns users with meta on success", async () => {
test("returns users with meta on success", async () => {
const usersArray = [mockUser];
(prisma.$transaction as any).mockResolvedValueOnce([usersArray, usersArray.length]);
const result = await getUsers("org456", { limit: 10, skip: 0 } as TGetUsersFilter);
@@ -68,7 +68,7 @@ describe("Users Lib", () => {
}
});
it("returns internal_server_error if prisma fails", async () => {
test("returns internal_server_error if prisma fails", async () => {
(prisma.$transaction as any).mockRejectedValueOnce(new Error("Transaction error"));
const result = await getUsers("org456", { limit: 10, skip: 0 } as TGetUsersFilter);
expect(result.ok).toBe(false);
@@ -79,7 +79,7 @@ describe("Users Lib", () => {
});
describe("createUser", () => {
it("creates user and revalidates caches", async () => {
test("creates user and revalidates caches", async () => {
(prisma.user.create as any).mockResolvedValueOnce(mockUser);
const result = await createUser(
{ name: "Test User", email: "test@example.com", role: "member" },
@@ -92,7 +92,7 @@ describe("Users Lib", () => {
}
});
it("returns internal_server_error if creation fails", async () => {
test("returns internal_server_error if creation fails", async () => {
(prisma.user.create as any).mockRejectedValueOnce(new Error("Create error"));
const result = await createUser({ name: "fail", email: "fail@example.com", role: "manager" }, "org456");
expect(result.ok).toBe(false);
@@ -103,7 +103,7 @@ describe("Users Lib", () => {
});
describe("updateUser", () => {
it("updates user and revalidates caches", async () => {
test("updates user and revalidates caches", async () => {
(prisma.user.findUnique as any).mockResolvedValueOnce(mockUser);
(prisma.$transaction as any).mockResolvedValueOnce([{ ...mockUser, name: "Updated User" }]);
const result = await updateUser({ email: mockUser.email, name: "Updated User" }, "org456");
@@ -114,7 +114,7 @@ describe("Users Lib", () => {
}
});
it("returns not_found if user doesn't exist", async () => {
test("returns not_found if user doesn't exist", async () => {
(prisma.user.findUnique as any).mockResolvedValueOnce(null);
const result = await updateUser({ email: "unknown@example.com" }, "org456");
expect(result.ok).toBe(false);
@@ -123,7 +123,7 @@ describe("Users Lib", () => {
}
});
it("returns internal_server_error if update fails", async () => {
test("returns internal_server_error if update fails", async () => {
(prisma.user.findUnique as any).mockResolvedValueOnce(mockUser);
(prisma.$transaction as any).mockRejectedValueOnce(new Error("Update error"));
const result = await updateUser({ email: mockUser.email }, "org456");
@@ -135,7 +135,7 @@ describe("Users Lib", () => {
});
describe("createUser with teams", () => {
it("creates user with existing teams", async () => {
test("creates user with existing teams", async () => {
(prisma.team.findMany as any).mockResolvedValueOnce([
{ id: "team123", name: "MyTeam", projectTeams: [{ projectId: "proj789" }] },
]);
@@ -157,7 +157,7 @@ describe("Users Lib", () => {
});
describe("updateUser with team changes", () => {
it("removes a team and adds new team", async () => {
test("removes a team and adds new team", async () => {
(prisma.user.findUnique as any).mockResolvedValueOnce({
...mockUser,
teamUsers: [{ team: { id: "team123", name: "OldTeam", projectTeams: [{ projectId: "proj789" }] } }],

View File

@@ -1,6 +1,6 @@
import { buildCommonFilterQuery, pickCommonFilter } from "@/modules/api/v2/management/lib/utils";
import { TGetUsersFilter } from "@/modules/api/v2/organizations/[organizationId]/users/types/users";
import { describe, expect, it, vi } from "vitest";
import { describe, expect, test, vi } from "vitest";
import { getUsersQuery } from "../utils";
vi.mock("@/modules/api/v2/management/lib/utils", () => ({
@@ -9,7 +9,7 @@ vi.mock("@/modules/api/v2/management/lib/utils", () => ({
}));
describe("getUsersQuery", () => {
it("returns default query if no params are provided", () => {
test("returns default query if no params are provided", () => {
const result = getUsersQuery("org123");
expect(result).toEqual({
where: {
@@ -22,7 +22,7 @@ describe("getUsersQuery", () => {
});
});
it("includes email filter if email param is provided", () => {
test("includes email filter if email param is provided", () => {
const result = getUsersQuery("org123", { email: "test@example.com" } as TGetUsersFilter);
expect(result.where?.email).toEqual({
contains: "test@example.com",
@@ -30,12 +30,12 @@ describe("getUsersQuery", () => {
});
});
it("includes id filter if id param is provided", () => {
test("includes id filter if id param is provided", () => {
const result = getUsersQuery("org123", { id: "user123" } as TGetUsersFilter);
expect(result.where?.id).toBe("user123");
});
it("applies baseFilter if pickCommonFilter returns something", () => {
test("applies baseFilter if pickCommonFilter returns something", () => {
vi.mocked(pickCommonFilter).mockReturnValueOnce({ someField: "test" } as unknown as ReturnType<
typeof pickCommonFilter
>);

View File

@@ -1,6 +1,6 @@
import { randomBytes } from "crypto";
import { Provider } from "next-auth/providers/index";
import { afterEach, describe, expect, it, vi } from "vitest";
import { afterEach, describe, expect, test, vi } from "vitest";
import { prisma } from "@formbricks/database";
import { EMAIL_VERIFICATION_DISABLED } from "@formbricks/lib/constants";
import { createToken } from "@formbricks/lib/jwt";
@@ -40,13 +40,13 @@ describe("authOptions", () => {
describe("CredentialsProvider (credentials) - email/password login", () => {
const credentialsProvider = getProviderById("credentials");
it("should throw error if credentials are not provided", async () => {
test("should throw error if credentials are not provided", async () => {
await expect(credentialsProvider.options.authorize(undefined, {})).rejects.toThrow(
"Invalid credentials"
);
});
it("should throw error if user not found", async () => {
test("should throw error if user not found", async () => {
vi.spyOn(prisma.user, "findUnique").mockResolvedValue(null);
const credentials = { email: mockUser.email, password: mockPassword };
@@ -56,7 +56,7 @@ describe("authOptions", () => {
);
});
it("should throw error if user has no password stored", async () => {
test("should throw error if user has no password stored", async () => {
vi.spyOn(prisma.user, "findUnique").mockResolvedValue({
id: mockUser.id,
email: mockUser.email,
@@ -70,7 +70,7 @@ describe("authOptions", () => {
);
});
it("should throw error if password verification fails", async () => {
test("should throw error if password verification fails", async () => {
vi.spyOn(prisma.user, "findUnique").mockResolvedValue({
id: mockUserId,
email: mockUser.email,
@@ -84,7 +84,7 @@ describe("authOptions", () => {
);
});
it("should successfully login when credentials are valid", async () => {
test("should successfully login when credentials are valid", async () => {
const fakeUser = {
id: mockUserId,
email: mockUser.email,
@@ -108,7 +108,7 @@ describe("authOptions", () => {
});
describe("Two-Factor Backup Code login", () => {
it("should throw error if backup codes are missing", async () => {
test("should throw error if backup codes are missing", async () => {
const mockUser = {
id: mockUserId,
email: "2fa@example.com",
@@ -130,13 +130,13 @@ describe("authOptions", () => {
describe("CredentialsProvider (token) - Token-based email verification", () => {
const tokenProvider = getProviderById("token");
it("should throw error if token is not provided", async () => {
test("should throw error if token is not provided", async () => {
await expect(tokenProvider.options.authorize({}, {})).rejects.toThrow(
"Either a user does not match the provided token or the token is invalid"
);
});
it("should throw error if token is invalid or user not found", async () => {
test("should throw error if token is invalid or user not found", async () => {
const credentials = { token: "badtoken" };
await expect(tokenProvider.options.authorize(credentials, {})).rejects.toThrow(
@@ -144,7 +144,7 @@ describe("authOptions", () => {
);
});
it("should throw error if email is already verified", async () => {
test("should throw error if email is already verified", async () => {
vi.spyOn(prisma.user, "findUnique").mockResolvedValue(mockUser);
const credentials = { token: createToken(mockUser.id, mockUser.email) };
@@ -154,7 +154,7 @@ describe("authOptions", () => {
);
});
it("should update user and verify email when token is valid", async () => {
test("should update user and verify email when token is valid", async () => {
vi.spyOn(prisma.user, "findUnique").mockResolvedValue({ id: mockUser.id, emailVerified: null });
vi.spyOn(prisma.user, "update").mockResolvedValue({
...mockUser,
@@ -175,7 +175,7 @@ describe("authOptions", () => {
describe("Callbacks", () => {
describe("jwt callback", () => {
it("should add profile information to token if user is found", async () => {
test("should add profile information to token if user is found", async () => {
vi.spyOn(prisma.user, "findFirst").mockResolvedValue({
id: mockUser.id,
locale: mockUser.locale,
@@ -194,7 +194,7 @@ describe("authOptions", () => {
});
});
it("should return token unchanged if no existing user is found", async () => {
test("should return token unchanged if no existing user is found", async () => {
vi.spyOn(prisma.user, "findFirst").mockResolvedValue(null);
const token = { email: "nonexistent@example.com" };
@@ -207,7 +207,7 @@ describe("authOptions", () => {
});
describe("session callback", () => {
it("should add user profile to session", async () => {
test("should add user profile to session", async () => {
const token = {
id: "user6",
profile: { id: "user6", email: "user6@example.com" },
@@ -223,7 +223,7 @@ describe("authOptions", () => {
});
describe("signIn callback", () => {
it("should throw error if email is not verified and email verification is enabled", async () => {
test("should throw error if email is not verified and email verification is enabled", async () => {
const user = { ...mockUser, emailVerified: null };
const account = { provider: "credentials" } as any;
// EMAIL_VERIFICATION_DISABLED is imported from constants.
@@ -239,7 +239,7 @@ describe("authOptions", () => {
describe("Two-Factor Authentication (TOTP)", () => {
const credentialsProvider = getProviderById("credentials");
it("should throw error if TOTP code is missing when 2FA is enabled", async () => {
test("should throw error if TOTP code is missing when 2FA is enabled", async () => {
const mockUser = {
id: mockUserId,
email: "2fa@example.com",
@@ -256,7 +256,7 @@ describe("authOptions", () => {
);
});
it("should throw error if two factor secret is missing", async () => {
test("should throw error if two factor secret is missing", async () => {
const mockUser = {
id: mockUserId,
email: "2fa@example.com",

View File

@@ -1,5 +1,5 @@
import { Response } from "node-fetch";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { beforeEach, describe, expect, test, vi } from "vitest";
import { validateInputs } from "@formbricks/lib/utils/validate";
import { logger } from "@formbricks/logger";
import { createBrevoCustomer } from "./brevo";
@@ -20,7 +20,7 @@ describe("createBrevoCustomer", () => {
vi.clearAllMocks();
});
it("should return early if BREVO_API_KEY is not defined", async () => {
test("should return early if BREVO_API_KEY is not defined", async () => {
vi.doMock("@formbricks/lib/constants", () => ({
BREVO_API_KEY: undefined,
BREVO_LIST_ID: "123",
@@ -35,7 +35,7 @@ describe("createBrevoCustomer", () => {
expect(validateInputs).not.toHaveBeenCalled();
});
it("should log an error if fetch fails", async () => {
test("should log an error if fetch fails", async () => {
const loggerSpy = vi.spyOn(logger, "error");
vi.mocked(global.fetch).mockRejectedValueOnce(new Error("Fetch failed"));
@@ -45,7 +45,7 @@ describe("createBrevoCustomer", () => {
expect(loggerSpy).toHaveBeenCalledWith(expect.any(Error), "Error sending user to Brevo");
});
it("should log the error response if fetch status is not 200", async () => {
test("should log the error response if fetch status is not 200", async () => {
const loggerSpy = vi.spyOn(logger, "error");
vi.mocked(global.fetch).mockResolvedValueOnce(

View File

@@ -2,7 +2,7 @@ import { Authenticator } from "@otplib/core";
import type { AuthenticatorOptions } from "@otplib/core/authenticator";
import { createDigest, createRandomBytes } from "@otplib/plugin-crypto";
import { keyDecoder, keyEncoder } from "@otplib/plugin-thirty-two";
import { describe, expect, it, vi } from "vitest";
import { describe, expect, test, vi } from "vitest";
import { totpAuthenticatorCheck } from "./totp";
vi.mock("@otplib/core");
@@ -14,7 +14,7 @@ describe("totpAuthenticatorCheck", () => {
const secret = "JBSWY3DPEHPK3PXP";
const opts: Partial<AuthenticatorOptions> = { window: [1, 0] };
it("should check a TOTP token with a base32-encoded secret", () => {
test("should check a TOTP token with a base32-encoded secret", () => {
const checkMock = vi.fn().mockReturnValue(true);
(Authenticator as unknown as vi.Mock).mockImplementation(() => ({
check: checkMock,
@@ -33,7 +33,7 @@ describe("totpAuthenticatorCheck", () => {
expect(result).toBe(true);
});
it("should use default window if none is provided", () => {
test("should use default window if none is provided", () => {
const checkMock = vi.fn().mockReturnValue(true);
(Authenticator as unknown as vi.Mock).mockImplementation(() => ({
check: checkMock,
@@ -52,7 +52,7 @@ describe("totpAuthenticatorCheck", () => {
expect(result).toBe(true);
});
it("should throw an error for invalid token format", () => {
test("should throw an error for invalid token format", () => {
(Authenticator as unknown as vi.Mock).mockImplementation(() => ({
check: () => {
throw new Error("Invalid token format");
@@ -64,7 +64,7 @@ describe("totpAuthenticatorCheck", () => {
}).toThrow("Invalid token format");
});
it("should throw an error for invalid secret format", () => {
test("should throw an error for invalid secret format", () => {
(Authenticator as unknown as vi.Mock).mockImplementation(() => ({
check: () => {
throw new Error("Invalid secret format");
@@ -76,7 +76,7 @@ describe("totpAuthenticatorCheck", () => {
}).toThrow("Invalid secret format");
});
it("should return false if token verification fails", () => {
test("should return false if token verification fails", () => {
const checkMock = vi.fn().mockReturnValue(false);
(Authenticator as unknown as vi.Mock).mockImplementation(() => ({
check: checkMock,

View File

@@ -1,5 +1,5 @@
import { Prisma } from "@prisma/client";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { beforeEach, describe, expect, test, vi } from "vitest";
import { prisma } from "@formbricks/database";
import { PrismaErrorType } from "@formbricks/database/types/error";
import { userCache } from "@formbricks/lib/user/cache";
@@ -43,7 +43,7 @@ describe("User Management", () => {
});
describe("createUser", () => {
it("creates a user successfully", async () => {
test("creates a user successfully", async () => {
vi.mocked(prisma.user.create).mockResolvedValueOnce(mockPrismaUser);
const result = await createUser({
@@ -56,7 +56,7 @@ describe("User Management", () => {
expect(userCache.revalidate).toHaveBeenCalled();
});
it("throws InvalidInputError when email already exists", async () => {
test("throws InvalidInputError when email already exists", async () => {
const errToThrow = new Prisma.PrismaClientKnownRequestError("Mock error message", {
code: PrismaErrorType.UniqueConstraintViolation,
clientVersion: "0.0.1",
@@ -76,7 +76,7 @@ describe("User Management", () => {
describe("updateUser", () => {
const mockUpdateData = { name: "Updated Name" };
it("updates a user successfully", async () => {
test("updates a user successfully", async () => {
vi.mocked(prisma.user.update).mockResolvedValueOnce({ ...mockPrismaUser, name: mockUpdateData.name });
const result = await updateUser(mockUser.id, mockUpdateData);
@@ -85,7 +85,7 @@ describe("User Management", () => {
expect(userCache.revalidate).toHaveBeenCalled();
});
it("throws ResourceNotFoundError when user doesn't exist", async () => {
test("throws ResourceNotFoundError when user doesn't exist", async () => {
const errToThrow = new Prisma.PrismaClientKnownRequestError("Mock error message", {
code: PrismaErrorType.RecordDoesNotExist,
clientVersion: "0.0.1",
@@ -99,7 +99,7 @@ describe("User Management", () => {
describe("updateUserLastLoginAt", () => {
const mockUpdateData = { name: "Updated Name" };
it("updates a user successfully", async () => {
test("updates a user successfully", async () => {
vi.mocked(prisma.user.update).mockResolvedValueOnce({ ...mockPrismaUser, name: mockUpdateData.name });
const result = await updateUserLastLoginAt(mockUser.email);
@@ -108,7 +108,7 @@ describe("User Management", () => {
expect(userCache.revalidate).toHaveBeenCalled();
});
it("throws ResourceNotFoundError when user doesn't exist", async () => {
test("throws ResourceNotFoundError when user doesn't exist", async () => {
const errToThrow = new Prisma.PrismaClientKnownRequestError("Mock error message", {
code: PrismaErrorType.RecordDoesNotExist,
clientVersion: "0.0.1",
@@ -122,7 +122,7 @@ describe("User Management", () => {
describe("getUserByEmail", () => {
const mockEmail = "test@example.com";
it("retrieves a user by email successfully", async () => {
test("retrieves a user by email successfully", async () => {
const mockUser = {
id: "user123",
email: mockEmail,
@@ -136,7 +136,7 @@ describe("User Management", () => {
expect(result).toEqual(mockUser);
});
it("throws DatabaseError on prisma error", async () => {
test("throws DatabaseError on prisma error", async () => {
vi.mocked(prisma.user.findFirst).mockRejectedValueOnce(new Error("Database error"));
await expect(getUserByEmail(mockEmail)).rejects.toThrow();
@@ -146,7 +146,7 @@ describe("User Management", () => {
describe("getUser", () => {
const mockUserId = "cm5xj580r00000cmgdj9ohups";
it("retrieves a user by id successfully", async () => {
test("retrieves a user by id successfully", async () => {
const mockUser = {
id: mockUserId,
};
@@ -157,7 +157,7 @@ describe("User Management", () => {
expect(result).toEqual(mockUser);
});
it("returns null when user doesn't exist", async () => {
test("returns null when user doesn't exist", async () => {
vi.mocked(prisma.user.findUnique).mockResolvedValueOnce(null);
const result = await getUser(mockUserId);
@@ -165,7 +165,7 @@ describe("User Management", () => {
expect(result).toBeNull();
});
it("throws DatabaseError on prisma error", async () => {
test("throws DatabaseError on prisma error", async () => {
vi.mocked(prisma.user.findUnique).mockRejectedValueOnce(new Error("Database error"));
await expect(getUser(mockUserId)).rejects.toThrow();

View File

@@ -1,4 +1,4 @@
import { describe, expect, it } from "vitest";
import { describe, expect, test } from "vitest";
import { hashPassword, verifyPassword } from "./utils";
describe("Password Utils", () => {
@@ -6,7 +6,7 @@ describe("Password Utils", () => {
const hashedPassword = "$2a$12$LZsLq.9nkZlU0YDPx2aLNelnwD/nyavqbewLN.5.Q5h/UxRD8Ymcy";
describe("hashPassword", () => {
it("should hash a password", async () => {
test("should hash a password", async () => {
const hashedPassword = await hashPassword(password);
expect(typeof hashedPassword).toBe("string");
@@ -14,7 +14,7 @@ describe("Password Utils", () => {
expect(hashedPassword.length).toBe(60);
});
it("should generate different hashes for the same password", async () => {
test("should generate different hashes for the same password", async () => {
const hash1 = await hashPassword(password);
const hash2 = await hashPassword(password);
@@ -23,13 +23,13 @@ describe("Password Utils", () => {
});
describe("verifyPassword", () => {
it("should verify a correct password", async () => {
test("should verify a correct password", async () => {
const isValid = await verifyPassword(password, hashedPassword);
expect(isValid).toBe(true);
});
it("should reject an incorrect password", async () => {
test("should reject an incorrect password", async () => {
const isValid = await verifyPassword("WrongPassword123!", hashedPassword);
expect(isValid).toBe(false);

View File

@@ -4,7 +4,7 @@ import "@testing-library/jest-dom/vitest";
import { cleanup, fireEvent, render, screen, waitFor } from "@testing-library/react";
import { useSearchParams } from "next/navigation";
import toast from "react-hot-toast";
import { afterEach, describe, expect, it, vi } from "vitest";
import { afterEach, describe, expect, test, vi } from "vitest";
import { createEmailTokenAction } from "../../../auth/actions";
import { SignupForm } from "./signup-form";
@@ -129,7 +129,7 @@ describe("SignupForm", () => {
cleanup();
});
it("toggles the signup form on button click", () => {
test("toggles the signup form on button click", () => {
render(<SignupForm {...defaultProps} />);
// Initially, the signup form is hidden.
@@ -149,7 +149,7 @@ describe("SignupForm", () => {
expect(screen.getByTestId("signup-password")).toBeInTheDocument();
});
it("submits the form successfully", async () => {
test("submits the form successfully", async () => {
// Set up mocks for the API actions.
vi.mocked(createUserAction).mockResolvedValue({ data: true } as any);
vi.mocked(createEmailTokenAction).mockResolvedValue({ data: "token123" });
@@ -194,7 +194,7 @@ describe("SignupForm", () => {
expect(pushMock).toHaveBeenCalledWith("/auth/verification-requested?token=token123");
});
it("submits the form successfully when turnstile is configured", async () => {
test("submits the form successfully when turnstile is configured", async () => {
// Override props to enable Turnstile
const props = {
...defaultProps,
@@ -246,7 +246,7 @@ describe("SignupForm", () => {
expect(pushMock).toHaveBeenCalledWith("/auth/signup-without-verification-success");
});
it("submits the form successfully when turnstile is configured, but createEmailTokenAction don't return data", async () => {
test("submits the form successfully when turnstile is configured, but createEmailTokenAction don't return data", async () => {
// Override props to enable Turnstile
const props = {
...defaultProps,
@@ -298,7 +298,7 @@ describe("SignupForm", () => {
});
});
it("shows an error message if turnstile is configured, but no token is received", async () => {
test("shows an error message if turnstile is configured, but no token is received", async () => {
// Override props to enable Turnstile
const props = {
...defaultProps,
@@ -332,7 +332,7 @@ describe("SignupForm", () => {
});
});
it("Invite token is in the search params", async () => {
test("Invite token is in the search params", async () => {
// Set up mocks for the API actions
vi.mocked(createUserAction).mockResolvedValue({ data: true } as any);
vi.mocked(createEmailTokenAction).mockResolvedValue({ data: "token123" });

View File

@@ -1,6 +1,6 @@
import { inviteCache } from "@/lib/cache/invite";
import { Prisma } from "@prisma/client";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { beforeEach, describe, expect, test, vi } from "vitest";
import { prisma } from "@formbricks/database";
import { PrismaErrorType } from "@formbricks/database/types/error";
import { logger } from "@formbricks/logger";
@@ -63,7 +63,7 @@ describe("Invite Management", () => {
});
describe("deleteInvite", () => {
it("deletes an invite successfully and invalidates cache", async () => {
test("deletes an invite successfully and invalidates cache", async () => {
vi.mocked(prisma.invite.delete).mockResolvedValue(mockInvite);
const result = await deleteInvite(mockInviteId);
@@ -79,7 +79,7 @@ describe("Invite Management", () => {
});
});
it("throws DatabaseError when invite doesn't exist", async () => {
test("throws DatabaseError when invite doesn't exist", async () => {
const errToThrow = new Prisma.PrismaClientKnownRequestError("Record not found", {
code: PrismaErrorType.RecordDoesNotExist,
clientVersion: "0.0.1",
@@ -89,7 +89,7 @@ describe("Invite Management", () => {
await expect(deleteInvite(mockInviteId)).rejects.toThrow(DatabaseError);
});
it("throws DatabaseError for other Prisma errors", async () => {
test("throws DatabaseError for other Prisma errors", async () => {
const errToThrow = new Prisma.PrismaClientKnownRequestError("Database error", {
code: "P2002",
clientVersion: "0.0.1",
@@ -99,7 +99,7 @@ describe("Invite Management", () => {
await expect(deleteInvite(mockInviteId)).rejects.toThrow(DatabaseError);
});
it("throws DatabaseError for generic errors", async () => {
test("throws DatabaseError for generic errors", async () => {
vi.mocked(prisma.invite.delete).mockRejectedValue(new Error("Generic error"));
await expect(deleteInvite(mockInviteId)).rejects.toThrow(DatabaseError);
@@ -107,7 +107,7 @@ describe("Invite Management", () => {
});
describe("getInvite", () => {
it("retrieves an invite with creator details successfully", async () => {
test("retrieves an invite with creator details successfully", async () => {
vi.mocked(prisma.invite.findUnique).mockResolvedValue(mockInvite);
const result = await getInvite(mockInviteId);
@@ -131,7 +131,7 @@ describe("Invite Management", () => {
});
});
it("returns null when invite doesn't exist", async () => {
test("returns null when invite doesn't exist", async () => {
vi.mocked(prisma.invite.findUnique).mockResolvedValue(null);
const result = await getInvite(mockInviteId);
@@ -139,7 +139,7 @@ describe("Invite Management", () => {
expect(result).toBeNull();
});
it("throws DatabaseError on prisma error", async () => {
test("throws DatabaseError on prisma error", async () => {
const errToThrow = new Prisma.PrismaClientKnownRequestError("Database error", {
code: "P2002",
clientVersion: "0.0.1",
@@ -149,7 +149,7 @@ describe("Invite Management", () => {
await expect(getInvite(mockInviteId)).rejects.toThrow(DatabaseError);
});
it("throws DatabaseError for generic errors", async () => {
test("throws DatabaseError for generic errors", async () => {
vi.mocked(prisma.invite.findUnique).mockRejectedValue(new Error("Generic error"));
await expect(getInvite(mockInviteId)).rejects.toThrow(DatabaseError);
@@ -157,7 +157,7 @@ describe("Invite Management", () => {
});
describe("getIsValidInviteToken", () => {
it("returns true for valid invite", async () => {
test("returns true for valid invite", async () => {
vi.mocked(prisma.invite.findUnique).mockResolvedValue(mockInvite);
const result = await getIsValidInviteToken(mockInviteId);
@@ -168,7 +168,7 @@ describe("Invite Management", () => {
});
});
it("returns false when invite doesn't exist", async () => {
test("returns false when invite doesn't exist", async () => {
vi.mocked(prisma.invite.findUnique).mockResolvedValue(null);
const result = await getIsValidInviteToken(mockInviteId);
@@ -176,7 +176,7 @@ describe("Invite Management", () => {
expect(result).toBe(false);
});
it("returns false for expired invite", async () => {
test("returns false for expired invite", async () => {
const expiredInvite = {
...mockInvite,
expiresAt: new Date(Date.now() - 24 * 60 * 60 * 1000), // 24 hours ago
@@ -195,7 +195,7 @@ describe("Invite Management", () => {
);
});
it("returns false and logs error when database error occurs", async () => {
test("returns false and logs error when database error occurs", async () => {
const error = new Error("Database error");
vi.mocked(prisma.invite.findUnique).mockRejectedValue(error);
@@ -205,7 +205,7 @@ describe("Invite Management", () => {
expect(logger.error).toHaveBeenCalledWith(error, "Error getting invite");
});
it("returns false for invite with null expiresAt", async () => {
test("returns false for invite with null expiresAt", async () => {
const invalidInvite = {
...mockInvite,
expiresAt: null,
@@ -224,7 +224,7 @@ describe("Invite Management", () => {
);
});
it("returns false for invite with invalid expiresAt", async () => {
test("returns false for invite with invalid expiresAt", async () => {
const invalidInvite = {
...mockInvite,
expiresAt: new Date("invalid-date"),

View File

@@ -1,5 +1,5 @@
import posthog from "posthog-js";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
import { captureFailedSignup, verifyTurnstileToken } from "./utils";
beforeEach(() => {
@@ -16,7 +16,7 @@ describe("verifyTurnstileToken", () => {
const secretKey = "test-secret";
const token = "test-token";
it("should return true when verification is successful", async () => {
test("should return true when verification is successful", async () => {
const mockResponse = { success: true };
(global.fetch as any).mockResolvedValue({
ok: true,
@@ -36,7 +36,7 @@ describe("verifyTurnstileToken", () => {
);
});
it("should return false when response is not ok", async () => {
test("should return false when response is not ok", async () => {
(global.fetch as any).mockResolvedValue({
ok: false,
status: 400,
@@ -46,14 +46,14 @@ describe("verifyTurnstileToken", () => {
expect(result).toBe(false);
});
it("should return false when verification fails", async () => {
test("should return false when verification fails", async () => {
(global.fetch as any).mockRejectedValue(new Error("Network error"));
const result = await verifyTurnstileToken(secretKey, token);
expect(result).toBe(false);
});
it("should return false when request times out", async () => {
test("should return false when request times out", async () => {
const mockAbortError = new Error("The operation was aborted");
mockAbortError.name = "AbortError";
(global.fetch as any).mockRejectedValue(mockAbortError);
@@ -64,7 +64,7 @@ describe("verifyTurnstileToken", () => {
});
describe("captureFailedSignup", () => {
it("should capture TELEMETRY_FAILED_SIGNUP event with email and name", () => {
test("should capture TELEMETRY_FAILED_SIGNUP event with email and name", () => {
const captureSpy = vi.spyOn(posthog, "capture");
const email = "test@example.com";
const name = "Test User";

View File

@@ -7,7 +7,7 @@ import {
import "@testing-library/jest-dom/vitest";
import { cleanup, render, screen } from "@testing-library/react";
import { notFound } from "next/navigation";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
import { verifyInviteToken } from "@formbricks/lib/jwt";
import { findMatchingLocale } from "@formbricks/lib/utils/locale";
import { SignupPage } from "./page";
@@ -111,7 +111,7 @@ describe("SignupPage", () => {
cleanup();
});
it("renders the signup page with all components when signup is enabled", async () => {
test("renders the signup page with all components when signup is enabled", async () => {
// Mock the license check functions to return true
vi.mocked(getIsMultiOrgEnabled).mockResolvedValue(true);
vi.mocked(getisSsoEnabled).mockResolvedValue(true);
@@ -132,7 +132,7 @@ describe("SignupPage", () => {
expect(screen.getByTestId("signup-form")).toBeInTheDocument();
});
it("calls notFound when signup is disabled and no valid invite token is provided", async () => {
test("calls notFound when signup is disabled and no valid invite token is provided", async () => {
// Mock the license check functions to return false
vi.mocked(getIsMultiOrgEnabled).mockResolvedValue(false);
vi.mocked(verifyInviteToken).mockImplementation(() => {
@@ -144,7 +144,7 @@ describe("SignupPage", () => {
expect(notFound).toHaveBeenCalled();
});
it("calls notFound when invite token is invalid", async () => {
test("calls notFound when invite token is invalid", async () => {
// Mock the license check functions to return false
vi.mocked(getIsMultiOrgEnabled).mockResolvedValue(false);
vi.mocked(verifyInviteToken).mockImplementation(() => {
@@ -156,7 +156,7 @@ describe("SignupPage", () => {
expect(notFound).toHaveBeenCalled();
});
it("calls notFound when invite token is valid but invite is not found", async () => {
test("calls notFound when invite token is valid but invite is not found", async () => {
// Mock the license check functions to return false
vi.mocked(getIsMultiOrgEnabled).mockResolvedValue(false);
vi.mocked(verifyInviteToken).mockReturnValue({
@@ -170,7 +170,7 @@ describe("SignupPage", () => {
expect(notFound).toHaveBeenCalled();
});
it("renders the page with email from search params", async () => {
test("renders the page with email from search params", async () => {
// Mock the license check functions to return true
vi.mocked(getIsMultiOrgEnabled).mockResolvedValue(true);
vi.mocked(getisSsoEnabled).mockResolvedValue(true);

View File

@@ -1,5 +1,5 @@
import jwt from "jsonwebtoken";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { beforeEach, describe, expect, test, vi } from "vitest";
import { ENCRYPTION_KEY, SURVEY_URL } from "@formbricks/lib/constants";
import * as crypto from "@formbricks/lib/crypto";
import * as contactSurveyLink from "./contact-survey-link";
@@ -53,7 +53,7 @@ describe("Contact Survey Link", () => {
});
describe("getContactSurveyLink", () => {
it("creates a survey link with encrypted contact and survey IDs", () => {
test("creates a survey link with encrypted contact and survey IDs", () => {
const result = contactSurveyLink.getContactSurveyLink(mockContactId, mockSurveyId);
// Verify encryption was called for both IDs
@@ -77,7 +77,7 @@ describe("Contact Survey Link", () => {
});
});
it("adds expiration to the token when expirationDays is provided", () => {
test("adds expiration to the token when expirationDays is provided", () => {
const expirationDays = 7;
contactSurveyLink.getContactSurveyLink(mockContactId, mockSurveyId, expirationDays);
@@ -92,7 +92,7 @@ describe("Contact Survey Link", () => {
);
});
it("throws an error when ENCRYPTION_KEY is not available", async () => {
test("throws an error when ENCRYPTION_KEY is not available", async () => {
// Reset modules so the new mock is used by the module under test
vi.resetModules();
// Remock constants to simulate missing ENCRYPTION_KEY
@@ -115,7 +115,7 @@ describe("Contact Survey Link", () => {
});
describe("verifyContactSurveyToken", () => {
it("verifies and decrypts a valid token", () => {
test("verifies and decrypts a valid token", () => {
const result = contactSurveyLink.verifyContactSurveyToken(mockToken);
// Verify JWT verify was called
@@ -131,7 +131,7 @@ describe("Contact Survey Link", () => {
});
});
it("throws an error when token verification fails", () => {
test("throws an error when token verification fails", () => {
vi.mocked(jwt.verify).mockImplementation(() => {
throw new Error("Token verification failed");
});
@@ -147,7 +147,7 @@ describe("Contact Survey Link", () => {
}
});
it("throws an error when token has invalid format", () => {
test("throws an error when token has invalid format", () => {
// Mock JWT.verify to return an incomplete payload
vi.mocked(jwt.verify).mockReturnValue({
// Missing surveyId
@@ -168,7 +168,7 @@ describe("Contact Survey Link", () => {
}
});
it("throws an error when ENCRYPTION_KEY is not available", async () => {
test("throws an error when ENCRYPTION_KEY is not available", async () => {
vi.resetModules();
vi.doMock("@formbricks/lib/constants", () => ({
ENCRYPTION_KEY: undefined,

View File

@@ -1,6 +1,6 @@
import { cleanup, render, screen } from "@testing-library/react";
import { FormProvider, useForm } from "react-hook-form";
import { afterEach, describe, expect, it, vi } from "vitest";
import { afterEach, describe, expect, test, vi } from "vitest";
import { AddMemberRole } from "./add-member-role";
// Mock dependencies
@@ -39,7 +39,7 @@ describe("AddMemberRole Component", () => {
};
describe("Rendering", () => {
it("renders role selector when user is owner", () => {
test("renders role selector when user is owner", () => {
render(
<FormWrapper
defaultValues={defaultValues}
@@ -54,7 +54,7 @@ describe("AddMemberRole Component", () => {
expect(roleLabel).toBeInTheDocument();
});
it("does not render anything when user is member", () => {
test("does not render anything when user is member", () => {
render(
<FormWrapper
defaultValues={defaultValues}
@@ -69,7 +69,7 @@ describe("AddMemberRole Component", () => {
expect(screen.getByTestId("child")).toBeInTheDocument();
});
it("disables the role selector when canDoRoleManagement is false", () => {
test("disables the role selector when canDoRoleManagement is false", () => {
render(
<FormWrapper
defaultValues={defaultValues}
@@ -86,7 +86,7 @@ describe("AddMemberRole Component", () => {
});
describe("Default values", () => {
it("displays the default role value", () => {
test("displays the default role value", () => {
render(
<FormWrapper
defaultValues={defaultValues}

View File

@@ -1,6 +1,6 @@
import { cleanup, render, screen } from "@testing-library/react";
import { useRouter } from "next/navigation";
import { type Mock, afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { type Mock, afterEach, beforeEach, describe, expect, test, vi } from "vitest";
import { EditMembershipRole } from "./edit-membership-role";
// Mock dependencies
@@ -52,7 +52,7 @@ describe("EditMembershipRole Component", () => {
};
describe("Rendering", () => {
it("renders a dropdown when user is owner", () => {
test("renders a dropdown when user is owner", () => {
render(<EditMembershipRole {...defaultProps} />);
const button = screen.queryByRole("button-role");
@@ -60,7 +60,7 @@ describe("EditMembershipRole Component", () => {
expect(button).toHaveTextContent("Member");
});
it("renders a badge when user is not owner or manager", () => {
test("renders a badge when user is not owner or manager", () => {
render(<EditMembershipRole {...defaultProps} currentUserRole="member" />);
const badge = screen.queryByRole("badge-role");
@@ -69,21 +69,21 @@ describe("EditMembershipRole Component", () => {
expect(button).not.toBeInTheDocument();
});
it("disables the dropdown when editing own role", () => {
test("disables the dropdown when editing own role", () => {
render(<EditMembershipRole {...defaultProps} memberId="user-456" userId="user-456" />);
const button = screen.getByRole("button-role");
expect(button).toBeDisabled();
});
it("disables the dropdown when the user is the only owner", () => {
test("disables the dropdown when the user is the only owner", () => {
render(<EditMembershipRole {...defaultProps} memberRole="owner" doesOrgHaveMoreThanOneOwner={false} />);
const button = screen.getByRole("button-role");
expect(button).toBeDisabled();
});
it("disables the dropdown when a manager tries to edit an owner", () => {
test("disables the dropdown when a manager tries to edit an owner", () => {
render(<EditMembershipRole {...defaultProps} currentUserRole="manager" memberRole="owner" />);
const button = screen.getByRole("button-role");

View File

@@ -1,6 +1,6 @@
import { cleanup, fireEvent, render, screen } from "@testing-library/react";
import { signIn } from "next-auth/react";
import { afterEach, describe, expect, it, vi } from "vitest";
import { afterEach, describe, expect, test, vi } from "vitest";
import { FORMBRICKS_LOGGED_IN_WITH_LS } from "@formbricks/lib/localStorage";
import { AzureButton } from "./azure-button";
@@ -28,18 +28,18 @@ describe("AzureButton", () => {
vi.clearAllMocks();
});
it("renders correctly with default props", () => {
test("renders correctly with default props", () => {
render(<AzureButton {...defaultProps} />);
const button = screen.getByRole("button", { name: "auth.continue_with_azure" });
expect(button).toBeInTheDocument();
});
it("renders with last used indicator when lastUsed is true", () => {
test("renders with last used indicator when lastUsed is true", () => {
render(<AzureButton {...defaultProps} lastUsed={true} />);
expect(screen.getByText("auth.last_used")).toBeInTheDocument();
});
it("sets localStorage item and calls signIn on click", async () => {
test("sets localStorage item and calls signIn on click", async () => {
render(<AzureButton {...defaultProps} />);
const button = screen.getByRole("button", { name: "auth.continue_with_azure" });
fireEvent.click(button);
@@ -51,7 +51,7 @@ describe("AzureButton", () => {
});
});
it("uses inviteUrl in callbackUrl when provided", async () => {
test("uses inviteUrl in callbackUrl when provided", async () => {
const inviteUrl = "https://example.com/invite";
render(<AzureButton {...defaultProps} inviteUrl={inviteUrl} />);
const button = screen.getByRole("button", { name: "auth.continue_with_azure" });
@@ -63,7 +63,7 @@ describe("AzureButton", () => {
});
});
it("handles signup source correctly", async () => {
test("handles signup source correctly", async () => {
render(<AzureButton {...defaultProps} source="signup" />);
const button = screen.getByRole("button", { name: "auth.continue_with_azure" });
fireEvent.click(button);
@@ -74,7 +74,7 @@ describe("AzureButton", () => {
});
});
it("triggers direct redirect when directRedirect is true", () => {
test("triggers direct redirect when directRedirect is true", () => {
render(<AzureButton {...defaultProps} directRedirect={true} />);
expect(signIn).toHaveBeenCalledWith("azure-ad", {
redirect: true,

View File

@@ -1,6 +1,6 @@
import { cleanup, fireEvent, render, screen } from "@testing-library/react";
import { signIn } from "next-auth/react";
import { afterEach, describe, expect, it, vi } from "vitest";
import { afterEach, describe, expect, test, vi } from "vitest";
import { FORMBRICKS_LOGGED_IN_WITH_LS } from "@formbricks/lib/localStorage";
import { GithubButton } from "./github-button";
@@ -28,18 +28,18 @@ describe("GithubButton", () => {
vi.clearAllMocks();
});
it("renders correctly with default props", () => {
test("renders correctly with default props", () => {
render(<GithubButton {...defaultProps} />);
const button = screen.getByRole("button", { name: "auth.continue_with_github" });
expect(button).toBeInTheDocument();
});
it("renders with last used indicator when lastUsed is true", () => {
test("renders with last used indicator when lastUsed is true", () => {
render(<GithubButton {...defaultProps} lastUsed={true} />);
expect(screen.getByText("auth.last_used")).toBeInTheDocument();
});
it("sets localStorage item and calls signIn on click", async () => {
test("sets localStorage item and calls signIn on click", async () => {
render(<GithubButton {...defaultProps} />);
const button = screen.getByRole("button", { name: "auth.continue_with_github" });
fireEvent.click(button);
@@ -51,7 +51,7 @@ describe("GithubButton", () => {
});
});
it("uses inviteUrl in callbackUrl when provided", async () => {
test("uses inviteUrl in callbackUrl when provided", async () => {
const inviteUrl = "https://example.com/invite";
render(<GithubButton {...defaultProps} inviteUrl={inviteUrl} />);
const button = screen.getByRole("button", { name: "auth.continue_with_github" });
@@ -63,7 +63,7 @@ describe("GithubButton", () => {
});
});
it("handles signup source correctly", async () => {
test("handles signup source correctly", async () => {
render(<GithubButton {...defaultProps} source="signup" />);
const button = screen.getByRole("button", { name: "auth.continue_with_github" });
fireEvent.click(button);

View File

@@ -1,6 +1,6 @@
import { cleanup, fireEvent, render, screen } from "@testing-library/react";
import { signIn } from "next-auth/react";
import { afterEach, describe, expect, it, vi } from "vitest";
import { afterEach, describe, expect, test, vi } from "vitest";
import { FORMBRICKS_LOGGED_IN_WITH_LS } from "@formbricks/lib/localStorage";
import { GoogleButton } from "./google-button";
@@ -28,18 +28,18 @@ describe("GoogleButton", () => {
vi.clearAllMocks();
});
it("renders correctly with default props", () => {
test("renders correctly with default props", () => {
render(<GoogleButton {...defaultProps} />);
const button = screen.getByRole("button", { name: "auth.continue_with_google" });
expect(button).toBeInTheDocument();
});
it("renders with last used indicator when lastUsed is true", () => {
test("renders with last used indicator when lastUsed is true", () => {
render(<GoogleButton {...defaultProps} lastUsed={true} />);
expect(screen.getByText("auth.last_used")).toBeInTheDocument();
});
it("sets localStorage item and calls signIn on click", async () => {
test("sets localStorage item and calls signIn on click", async () => {
render(<GoogleButton {...defaultProps} />);
const button = screen.getByRole("button", { name: "auth.continue_with_google" });
fireEvent.click(button);
@@ -51,7 +51,7 @@ describe("GoogleButton", () => {
});
});
it("uses inviteUrl in callbackUrl when provided", async () => {
test("uses inviteUrl in callbackUrl when provided", async () => {
const inviteUrl = "https://example.com/invite";
render(<GoogleButton {...defaultProps} inviteUrl={inviteUrl} />);
const button = screen.getByRole("button", { name: "auth.continue_with_google" });
@@ -63,7 +63,7 @@ describe("GoogleButton", () => {
});
});
it("handles signup source correctly", async () => {
test("handles signup source correctly", async () => {
render(<GoogleButton {...defaultProps} source="signup" />);
const button = screen.getByRole("button", { name: "auth.continue_with_google" });
fireEvent.click(button);

View File

@@ -1,6 +1,6 @@
import { cleanup, fireEvent, render, screen } from "@testing-library/react";
import { signIn } from "next-auth/react";
import { afterEach, describe, expect, it, vi } from "vitest";
import { afterEach, describe, expect, test, vi } from "vitest";
import { FORMBRICKS_LOGGED_IN_WITH_LS } from "@formbricks/lib/localStorage";
import { OpenIdButton } from "./open-id-button";
@@ -28,25 +28,25 @@ describe("OpenIdButton", () => {
vi.clearAllMocks();
});
it("renders correctly with default props", () => {
test("renders correctly with default props", () => {
render(<OpenIdButton {...defaultProps} />);
const button = screen.getByRole("button", { name: "auth.continue_with_openid" });
expect(button).toBeInTheDocument();
});
it("renders with custom text when provided", () => {
test("renders with custom text when provided", () => {
const customText = "Custom OpenID Text";
render(<OpenIdButton {...defaultProps} text={customText} />);
const button = screen.getByRole("button", { name: customText });
expect(button).toBeInTheDocument();
});
it("renders with last used indicator when lastUsed is true", () => {
test("renders with last used indicator when lastUsed is true", () => {
render(<OpenIdButton {...defaultProps} lastUsed={true} />);
expect(screen.getByText("auth.last_used")).toBeInTheDocument();
});
it("sets localStorage item and calls signIn on click", async () => {
test("sets localStorage item and calls signIn on click", async () => {
render(<OpenIdButton {...defaultProps} />);
const button = screen.getByRole("button", { name: "auth.continue_with_openid" });
fireEvent.click(button);
@@ -58,7 +58,7 @@ describe("OpenIdButton", () => {
});
});
it("uses inviteUrl in callbackUrl when provided", async () => {
test("uses inviteUrl in callbackUrl when provided", async () => {
const inviteUrl = "https://example.com/invite";
render(<OpenIdButton {...defaultProps} inviteUrl={inviteUrl} />);
const button = screen.getByRole("button", { name: "auth.continue_with_openid" });
@@ -70,7 +70,7 @@ describe("OpenIdButton", () => {
});
});
it("handles signup source correctly", async () => {
test("handles signup source correctly", async () => {
render(<OpenIdButton {...defaultProps} source="signup" />);
const button = screen.getByRole("button", { name: "auth.continue_with_openid" });
fireEvent.click(button);
@@ -81,7 +81,7 @@ describe("OpenIdButton", () => {
});
});
it("triggers direct redirect when directRedirect is true", () => {
test("triggers direct redirect when directRedirect is true", () => {
render(<OpenIdButton {...defaultProps} directRedirect={true} />);
expect(signIn).toHaveBeenCalledWith("openid", {
redirect: true,

View File

@@ -2,7 +2,7 @@ import { doesSamlConnectionExistAction } from "@/modules/ee/sso/actions";
import { cleanup, fireEvent, render, screen } from "@testing-library/react";
import { signIn } from "next-auth/react";
import toast from "react-hot-toast";
import { afterEach, describe, expect, it, vi } from "vitest";
import { afterEach, describe, expect, test, vi } from "vitest";
import { FORMBRICKS_LOGGED_IN_WITH_LS } from "@formbricks/lib/localStorage";
import { SamlButton } from "./saml-button";
@@ -44,18 +44,18 @@ describe("SamlButton", () => {
vi.clearAllMocks();
});
it("renders correctly with default props", () => {
test("renders correctly with default props", () => {
render(<SamlButton {...defaultProps} />);
const button = screen.getByRole("button", { name: "auth.continue_with_saml" });
expect(button).toBeInTheDocument();
});
it("renders with last used indicator when lastUsed is true", () => {
test("renders with last used indicator when lastUsed is true", () => {
render(<SamlButton {...defaultProps} lastUsed={true} />);
expect(screen.getByText("auth.last_used")).toBeInTheDocument();
});
it("sets localStorage item and calls signIn on click when SAML connection exists", async () => {
test("sets localStorage item and calls signIn on click when SAML connection exists", async () => {
vi.mocked(doesSamlConnectionExistAction).mockResolvedValue({ data: true });
render(<SamlButton {...defaultProps} />);
const button = screen.getByRole("button", { name: "auth.continue_with_saml" });
@@ -76,7 +76,7 @@ describe("SamlButton", () => {
);
});
it("shows error toast when SAML connection does not exist", async () => {
test("shows error toast when SAML connection does not exist", async () => {
vi.mocked(doesSamlConnectionExistAction).mockResolvedValue({ data: false });
render(<SamlButton {...defaultProps} />);
const button = screen.getByRole("button", { name: "auth.continue_with_saml" });
@@ -87,7 +87,7 @@ describe("SamlButton", () => {
expect(signIn).not.toHaveBeenCalled();
});
it("uses inviteUrl in callbackUrl when provided", async () => {
test("uses inviteUrl in callbackUrl when provided", async () => {
vi.mocked(doesSamlConnectionExistAction).mockResolvedValue({ data: true });
const inviteUrl = "https://example.com/invite";
render(<SamlButton {...defaultProps} inviteUrl={inviteUrl} />);
@@ -108,7 +108,7 @@ describe("SamlButton", () => {
);
});
it("handles signup source correctly", async () => {
test("handles signup source correctly", async () => {
vi.mocked(doesSamlConnectionExistAction).mockResolvedValue({ data: true });
render(<SamlButton {...defaultProps} source="signup" />);
const button = screen.getByRole("button", { name: "auth.continue_with_saml" });

View File

@@ -1,5 +1,5 @@
import { cleanup, render, screen } from "@testing-library/react";
import { afterEach, describe, expect, it, vi } from "vitest";
import { afterEach, describe, expect, test, vi } from "vitest";
import { SSOOptions } from "./sso-options";
// Mock environment variables
@@ -81,7 +81,7 @@ describe("SSOOptions Component", () => {
source: "signin" as const,
};
it("renders all SSO options when all are enabled", () => {
test("renders all SSO options when all are enabled", () => {
render(<SSOOptions {...defaultProps} />);
expect(screen.getByTestId("google-button")).toBeInTheDocument();
@@ -91,7 +91,7 @@ describe("SSOOptions Component", () => {
expect(screen.getByTestId("saml-button")).toBeInTheDocument();
});
it("only renders enabled SSO options", () => {
test("only renders enabled SSO options", () => {
render(
<SSOOptions
{...defaultProps}
@@ -108,7 +108,7 @@ describe("SSOOptions Component", () => {
expect(screen.getByTestId("saml-button")).toBeInTheDocument();
});
it("passes correct props to OpenID button", () => {
test("passes correct props to OpenID button", () => {
render(<SSOOptions {...defaultProps} />);
const openIdButton = screen.getByTestId("openid-button");
@@ -116,7 +116,7 @@ describe("SSOOptions Component", () => {
expect(openIdButton).toHaveTextContent("auth.continue_with_oidc");
});
it("passes correct props to SAML button", () => {
test("passes correct props to SAML button", () => {
render(<SSOOptions {...defaultProps} />);
const samlButton = screen.getByTestId("saml-button");
@@ -125,7 +125,7 @@ describe("SSOOptions Component", () => {
expect(samlButton).toHaveAttribute("data-product", "test-product");
});
it("passes correct source prop to all buttons", () => {
test("passes correct source prop to all buttons", () => {
render(<SSOOptions {...defaultProps} source="signup" />);
expect(screen.getByTestId("google-button")).toHaveAttribute("data-source", "signup");

View File

@@ -2,7 +2,7 @@ import { createBrevoCustomer } from "@/modules/auth/lib/brevo";
import { createUser, getUserByEmail, updateUser } from "@/modules/auth/lib/user";
import type { TSamlNameFields } from "@/modules/auth/types/auth";
import { getIsSamlSsoEnabled, getisSsoEnabled } from "@/modules/ee/license-check/lib/utils";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { beforeEach, describe, expect, test, vi } from "vitest";
import { prisma } from "@formbricks/database";
import { createAccount } from "@formbricks/lib/account/service";
import { createMembership } from "@formbricks/lib/membership/service";
@@ -91,7 +91,7 @@ describe("handleSsoCallback", () => {
});
describe("Early return conditions", () => {
it("should return false if SSO is not enabled", async () => {
test("should return false if SSO is not enabled", async () => {
vi.mocked(getisSsoEnabled).mockResolvedValue(false);
const result = await handleSsoCallback({
@@ -103,7 +103,7 @@ describe("handleSsoCallback", () => {
expect(result).toBe(false);
});
it("should return false if user email is missing", async () => {
test("should return false if user email is missing", async () => {
const result = await handleSsoCallback({
user: { ...mockUser, email: "" },
account: mockAccount,
@@ -113,7 +113,7 @@ describe("handleSsoCallback", () => {
expect(result).toBe(false);
});
it("should return false if account type is not oauth", async () => {
test("should return false if account type is not oauth", async () => {
const result = await handleSsoCallback({
user: mockUser,
account: { ...mockAccount, type: "credentials" },
@@ -123,7 +123,7 @@ describe("handleSsoCallback", () => {
expect(result).toBe(false);
});
it("should return false if provider is SAML and SAML SSO is not enabled", async () => {
test("should return false if provider is SAML and SAML SSO is not enabled", async () => {
vi.mocked(getIsSamlSsoEnabled).mockResolvedValue(false);
const result = await handleSsoCallback({
@@ -137,7 +137,7 @@ describe("handleSsoCallback", () => {
});
describe("Existing user handling", () => {
it("should return true if user with account already exists and email is the same", async () => {
test("should return true if user with account already exists and email is the same", async () => {
vi.mocked(prisma.user.findFirst).mockResolvedValue({
...mockUser,
email: mockUser.email,
@@ -166,7 +166,7 @@ describe("handleSsoCallback", () => {
});
});
it("should update user email if user with account exists but email changed", async () => {
test("should update user email if user with account exists but email changed", async () => {
const existingUser = {
...mockUser,
id: "existing-user-id",
@@ -188,7 +188,7 @@ describe("handleSsoCallback", () => {
expect(updateUser).toHaveBeenCalledWith(existingUser.id, { email: mockUser.email });
});
it("should throw error if user with account exists, email changed, and another user has the new email", async () => {
test("should throw error if user with account exists, email changed, and another user has the new email", async () => {
const existingUser = {
...mockUser,
id: "existing-user-id",
@@ -216,7 +216,7 @@ describe("handleSsoCallback", () => {
);
});
it("should return true if user with email already exists", async () => {
test("should return true if user with email already exists", async () => {
vi.mocked(prisma.user.findFirst).mockResolvedValue(null);
vi.mocked(getUserByEmail).mockResolvedValue({
id: "existing-user-id",
@@ -237,7 +237,7 @@ describe("handleSsoCallback", () => {
});
describe("New user creation", () => {
it("should create a new user if no existing user found", async () => {
test("should create a new user if no existing user found", async () => {
vi.mocked(prisma.user.findFirst).mockResolvedValue(null);
vi.mocked(getUserByEmail).mockResolvedValue(null);
vi.mocked(createUser).mockResolvedValue(mockCreatedUser());
@@ -260,7 +260,7 @@ describe("handleSsoCallback", () => {
expect(createBrevoCustomer).toHaveBeenCalledWith({ id: mockUser.id, email: mockUser.email });
});
it("should create organization and membership for new user when DEFAULT_ORGANIZATION_ID is set", async () => {
test("should create organization and membership for new user when DEFAULT_ORGANIZATION_ID is set", async () => {
vi.mocked(prisma.user.findFirst).mockResolvedValue(null);
vi.mocked(getUserByEmail).mockResolvedValue(null);
vi.mocked(createUser).mockResolvedValue(mockCreatedUser());
@@ -292,7 +292,7 @@ describe("handleSsoCallback", () => {
});
});
it("should use existing organization if it exists", async () => {
test("should use existing organization if it exists", async () => {
vi.mocked(prisma.user.findFirst).mockResolvedValue(null);
vi.mocked(getUserByEmail).mockResolvedValue(null);
vi.mocked(createUser).mockResolvedValue(mockCreatedUser());
@@ -313,7 +313,7 @@ describe("handleSsoCallback", () => {
});
describe("OpenID Connect name handling", () => {
it("should use oidcUser.name when available", async () => {
test("should use oidcUser.name when available", async () => {
const openIdUser = mockOpenIdUser({
name: "Direct Name",
given_name: "John",
@@ -341,7 +341,7 @@ describe("handleSsoCallback", () => {
);
});
it("should use given_name + family_name when name is not available", async () => {
test("should use given_name + family_name when name is not available", async () => {
const openIdUser = mockOpenIdUser({
name: undefined,
given_name: "John",
@@ -369,7 +369,7 @@ describe("handleSsoCallback", () => {
);
});
it("should use preferred_username when name and given_name/family_name are not available", async () => {
test("should use preferred_username when name and given_name/family_name are not available", async () => {
const openIdUser = mockOpenIdUser({
name: undefined,
given_name: undefined,
@@ -398,7 +398,7 @@ describe("handleSsoCallback", () => {
);
});
it("should fallback to email username when no OIDC name fields are available", async () => {
test("should fallback to email username when no OIDC name fields are available", async () => {
const openIdUser = mockOpenIdUser({
name: undefined,
given_name: undefined,
@@ -430,7 +430,7 @@ describe("handleSsoCallback", () => {
});
describe("SAML name handling", () => {
it("should use samlUser.name when available", async () => {
test("should use samlUser.name when available", async () => {
const samlUser = {
...mockUser,
name: "Direct Name",
@@ -459,7 +459,7 @@ describe("handleSsoCallback", () => {
);
});
it("should use firstName + lastName when name is not available", async () => {
test("should use firstName + lastName when name is not available", async () => {
const samlUser = {
...mockUser,
name: "",
@@ -490,7 +490,7 @@ describe("handleSsoCallback", () => {
});
describe("Organization handling", () => {
it("should handle invalid DEFAULT_ORGANIZATION_ID gracefully", async () => {
test("should handle invalid DEFAULT_ORGANIZATION_ID gracefully", async () => {
vi.mocked(prisma.user.findFirst).mockResolvedValue(null);
vi.mocked(getUserByEmail).mockResolvedValue(null);
vi.mocked(createUser).mockResolvedValue(mockCreatedUser());
@@ -509,7 +509,7 @@ describe("handleSsoCallback", () => {
expect(createMembership).not.toHaveBeenCalled();
});
it("should handle membership creation failure gracefully", async () => {
test("should handle membership creation failure gracefully", async () => {
vi.mocked(prisma.user.findFirst).mockResolvedValue(null);
vi.mocked(getUserByEmail).mockResolvedValue(null);
vi.mocked(createUser).mockResolvedValue(mockCreatedUser());
@@ -528,7 +528,7 @@ describe("handleSsoCallback", () => {
});
describe("Error handling", () => {
it("should handle prisma errors gracefully", async () => {
test("should handle prisma errors gracefully", async () => {
vi.mocked(prisma.user.findFirst).mockRejectedValue(new Error("Database error"));
await expect(
@@ -540,7 +540,7 @@ describe("handleSsoCallback", () => {
).rejects.toThrow("Database error");
});
it("should handle locale finding errors gracefully", async () => {
test("should handle locale finding errors gracefully", async () => {
vi.mocked(findMatchingLocale).mockRejectedValue(new Error("Locale error"));
vi.mocked(prisma.user.findFirst).mockResolvedValue(null);
vi.mocked(getUserByEmail).mockResolvedValue(null);

View File

@@ -1,28 +1,28 @@
import { describe, expect, it } from "vitest";
import { describe, expect, test } from "vitest";
import { getCallbackUrl } from "../utils";
describe("getCallbackUrl", () => {
it("should return base URL with source when no inviteUrl is provided", () => {
test("should return base URL with source when no inviteUrl is provided", () => {
const result = getCallbackUrl(undefined, "test-source");
expect(result).toBe("/?source=test-source");
});
it("should append source parameter to inviteUrl with existing query parameters", () => {
test("should append source parameter to inviteUrl with existing query parameters", () => {
const result = getCallbackUrl("https://example.com/invite?param=value", "test-source");
expect(result).toBe("https://example.com/invite?param=value&source=test-source");
});
it("should append source parameter to inviteUrl without existing query parameters", () => {
test("should append source parameter to inviteUrl without existing query parameters", () => {
const result = getCallbackUrl("https://example.com/invite", "test-source");
expect(result).toBe("https://example.com/invite?source=test-source");
});
it("should handle empty source parameter", () => {
test("should handle empty source parameter", () => {
const result = getCallbackUrl("https://example.com/invite", "");
expect(result).toBe("https://example.com/invite?source=");
});
it("should handle undefined source parameter", () => {
test("should handle undefined source parameter", () => {
const result = getCallbackUrl("https://example.com/invite", undefined);
expect(result).toBe("https://example.com/invite?source=undefined");
});

View File

@@ -7,7 +7,7 @@ import { uploadFile } from "@/modules/ui/components/file-input/lib/utils";
import "@testing-library/jest-dom/vitest";
import { cleanup, render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { beforeEach, describe, expect, test, vi } from "vitest";
import { TOrganization } from "@formbricks/types/organizations";
import { TUser } from "@formbricks/types/user";
import { EmailCustomizationSettings } from "./email-customization-settings";
@@ -48,7 +48,7 @@ describe("EmailCustomizationSettings", () => {
cleanup();
});
it("renders the logo if one is set and shows Replace/Remove buttons", () => {
test("renders the logo if one is set and shows Replace/Remove buttons", () => {
render(<EmailCustomizationSettings {...defaultProps} />);
const logoImage = screen.getByTestId("email-customization-preview-image");
@@ -64,7 +64,7 @@ describe("EmailCustomizationSettings", () => {
expect(screen.getByTestId("remove-logo-button")).toBeInTheDocument();
});
it("calls removeOrganizationEmailLogoUrlAction when removing logo", async () => {
test("calls removeOrganizationEmailLogoUrlAction when removing logo", async () => {
vi.mocked(removeOrganizationEmailLogoUrlAction).mockResolvedValue({
data: true,
});
@@ -81,7 +81,7 @@ describe("EmailCustomizationSettings", () => {
});
});
it("calls updateOrganizationEmailLogoUrlAction after uploading and clicking save", async () => {
test("calls updateOrganizationEmailLogoUrlAction after uploading and clicking save", async () => {
vi.mocked(uploadFile).mockResolvedValueOnce({
uploaded: true,
url: "https://example.com/new-uploaded-logo.png",
@@ -111,7 +111,7 @@ describe("EmailCustomizationSettings", () => {
});
});
it("sends test email if a logo is saved and the user clicks 'Send Test Email'", async () => {
test("sends test email if a logo is saved and the user clicks 'Send Test Email'", async () => {
vi.mocked(sendTestEmailAction).mockResolvedValue({
data: { success: true },
});
@@ -127,13 +127,13 @@ describe("EmailCustomizationSettings", () => {
});
});
it("displays upgrade prompt if hasWhiteLabelPermission is false", () => {
test("displays upgrade prompt if hasWhiteLabelPermission is false", () => {
render(<EmailCustomizationSettings {...defaultProps} hasWhiteLabelPermission={false} />);
// Check for text about upgrading
expect(screen.getByText(/customize_email_with_a_higher_plan/i)).toBeInTheDocument();
});
it("shows read-only warning if isReadOnly is true", () => {
test("shows read-only warning if isReadOnly is true", () => {
render(<EmailCustomizationSettings {...defaultProps} isReadOnly />);
expect(

View File

@@ -1,7 +1,7 @@
import "@testing-library/jest-dom/vitest";
import { cleanup, render, screen } from "@testing-library/react";
import { TFnType } from "@tolgee/react";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { beforeEach, describe, expect, test, vi } from "vitest";
import { EmailTemplate } from "./email-template";
const mockTranslate: TFnType = (key) => key;
@@ -25,7 +25,7 @@ describe("EmailTemplate", () => {
cleanup();
});
it("renders the default logo if no custom logo is provided", async () => {
test("renders the default logo if no custom logo is provided", async () => {
const emailTemplateElement = await EmailTemplate({
children: <div>Test Content</div>,
logoUrl: undefined,
@@ -39,7 +39,7 @@ describe("EmailTemplate", () => {
expect(logoImage).toHaveAttribute("src", "https://example.com/mock-logo.png");
});
it("renders the custom logo if provided", async () => {
test("renders the custom logo if provided", async () => {
const emailTemplateElement = await EmailTemplate({
...defaultProps,
});
@@ -51,7 +51,7 @@ describe("EmailTemplate", () => {
expect(logoImage).toHaveAttribute("src", "https://example.com/custom-logo.png");
});
it("renders the children content", async () => {
test("renders the children content", async () => {
const emailTemplateElement = await EmailTemplate({
...defaultProps,
});
@@ -61,7 +61,7 @@ describe("EmailTemplate", () => {
expect(screen.getByTestId("child-text")).toBeInTheDocument();
});
it("renders the imprint and privacy policy links if provided", async () => {
test("renders the imprint and privacy policy links if provided", async () => {
const emailTemplateElement = await EmailTemplate({
...defaultProps,
});
@@ -72,7 +72,7 @@ describe("EmailTemplate", () => {
expect(screen.getByText("emails.privacy_policy")).toBeInTheDocument();
});
it("renders the imprint address if provided", async () => {
test("renders the imprint address if provided", async () => {
const emailTemplateElement = await EmailTemplate({
...defaultProps,
});

View File

@@ -2,7 +2,7 @@ import { getTranslate } from "@/tolgee/server";
import "@testing-library/jest-dom/vitest";
import { cleanup, render, screen } from "@testing-library/react";
import { DefaultParamType, TFnType, TranslationKey } from "@tolgee/react/server";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
import { FollowUpEmail } from "./follow-up";
vi.mock("@formbricks/lib/constants", () => ({
@@ -33,7 +33,7 @@ describe("FollowUpEmail", () => {
cleanup();
});
it("renders the default logo if no custom logo is provided", async () => {
test("renders the default logo if no custom logo is provided", async () => {
const followUpEmailElement = await FollowUpEmail({
...defaultProps,
logoUrl: undefined,
@@ -46,7 +46,7 @@ describe("FollowUpEmail", () => {
expect(logoImage).toHaveAttribute("src", "https://example.com/mock-logo.png");
});
it("renders the custom logo if provided", async () => {
test("renders the custom logo if provided", async () => {
const followUpEmailElement = await FollowUpEmail({
...defaultProps,
});
@@ -58,7 +58,7 @@ describe("FollowUpEmail", () => {
expect(logoImage).toHaveAttribute("src", "https://example.com/custom-logo.png");
});
it("renders the HTML content", async () => {
test("renders the HTML content", async () => {
const followUpEmailElement = await FollowUpEmail({
...defaultProps,
});
@@ -68,7 +68,7 @@ describe("FollowUpEmail", () => {
expect(screen.getByText("Test HTML Content")).toBeInTheDocument();
});
it("renders the imprint and privacy policy links if provided", async () => {
test("renders the imprint and privacy policy links if provided", async () => {
const followUpEmailElement = await FollowUpEmail({
...defaultProps,
});
@@ -79,7 +79,7 @@ describe("FollowUpEmail", () => {
expect(screen.getByText("emails.privacy_policy")).toBeInTheDocument();
});
it("renders the imprint address if provided", async () => {
test("renders the imprint address if provided", async () => {
const followUpEmailElement = await FollowUpEmail({
...defaultProps,
});

View File

@@ -1,7 +1,7 @@
import "@testing-library/jest-dom/vitest";
import { cleanup, render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { afterEach, describe, expect, it, vi } from "vitest";
import { afterEach, describe, expect, test, vi } from "vitest";
import { TProject } from "@formbricks/types/project";
import { AddApiKeyModal } from "./add-api-key-modal";
@@ -100,7 +100,7 @@ describe("AddApiKeyModal", () => {
vi.clearAllMocks();
});
it("renders the modal with initial state", () => {
test("renders the modal with initial state", () => {
render(<AddApiKeyModal {...defaultProps} />);
const modalTitle = screen.getByText("environments.project.api_keys.add_api_key", {
selector: "div.text-xl",
@@ -111,7 +111,7 @@ describe("AddApiKeyModal", () => {
expect(screen.getByText("environments.project.api_keys.project_access")).toBeInTheDocument();
});
it("handles label input", async () => {
test("handles label input", async () => {
render(<AddApiKeyModal {...defaultProps} />);
const labelInput = screen.getByPlaceholderText("e.g. GitHub, PostHog, Slack") as HTMLInputElement;
@@ -119,7 +119,7 @@ describe("AddApiKeyModal", () => {
expect(labelInput.value).toBe("Test API Key");
});
it("handles permission changes", async () => {
test("handles permission changes", async () => {
render(<AddApiKeyModal {...defaultProps} />);
const addButton = screen.getByRole("button", { name: /add_permission/i });
@@ -138,7 +138,7 @@ describe("AddApiKeyModal", () => {
expect(updatedButton).toBeInTheDocument();
});
it("adds and removes permissions", async () => {
test("adds and removes permissions", async () => {
render(<AddApiKeyModal {...defaultProps} />);
// Add new permission
@@ -158,7 +158,7 @@ describe("AddApiKeyModal", () => {
expect(screen.getAllByRole("button", { name: "" })).toHaveLength(1);
});
it("submits form with correct data", async () => {
test("submits form with correct data", async () => {
render(<AddApiKeyModal {...defaultProps} />);
// Fill in label
@@ -191,7 +191,7 @@ describe("AddApiKeyModal", () => {
});
});
it("submits form with correct data including organization access toggles", async () => {
test("submits form with correct data including organization access toggles", async () => {
render(<AddApiKeyModal {...defaultProps} />);
// Fill in label
@@ -220,7 +220,7 @@ describe("AddApiKeyModal", () => {
});
});
it("disables submit button when label is empty and there are not environment permissions", async () => {
test("disables submit button when label is empty and there are not environment permissions", async () => {
render(<AddApiKeyModal {...defaultProps} />);
const submitButton = screen.getByRole("button", {
name: "environments.project.api_keys.add_api_key",
@@ -238,7 +238,7 @@ describe("AddApiKeyModal", () => {
expect(submitButton).not.toBeDisabled();
});
it("closes modal and resets form on cancel", async () => {
test("closes modal and resets form on cancel", async () => {
render(<AddApiKeyModal {...defaultProps} />);
// Type something into the label

View File

@@ -1,6 +1,6 @@
import "@testing-library/jest-dom/vitest";
import { render } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import { describe, expect, test, vi } from "vitest";
import { TProject } from "@formbricks/types/project";
import { getApiKeysWithEnvironmentPermissions } from "../lib/api-key";
import { ApiKeyList } from "./api-key-list";
@@ -108,7 +108,7 @@ const mockApiKeys = [
];
describe("ApiKeyList", () => {
it("renders EditAPIKeys with correct props", async () => {
test("renders EditAPIKeys with correct props", async () => {
// Mock the getApiKeysWithEnvironmentPermissions function to return our mock data
(getApiKeysWithEnvironmentPermissions as unknown as ReturnType<typeof vi.fn>).mockResolvedValue(
mockApiKeys
@@ -128,7 +128,7 @@ describe("ApiKeyList", () => {
expect(container).toBeInTheDocument();
});
it("handles empty api keys", async () => {
test("handles empty api keys", async () => {
// Mock the getApiKeysWithEnvironmentPermissions function to return empty array
(getApiKeysWithEnvironmentPermissions as unknown as ReturnType<typeof vi.fn>).mockResolvedValue([]);
@@ -146,7 +146,7 @@ describe("ApiKeyList", () => {
expect(container).toBeInTheDocument();
});
it("passes isReadOnly prop correctly", async () => {
test("passes isReadOnly prop correctly", async () => {
(getApiKeysWithEnvironmentPermissions as unknown as ReturnType<typeof vi.fn>).mockResolvedValue(
mockApiKeys
);

View File

@@ -3,7 +3,7 @@ import "@testing-library/jest-dom/vitest";
import { cleanup, render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import toast from "react-hot-toast";
import { afterEach, describe, expect, it, test, vi } from "vitest";
import { afterEach, describe, expect, test, vi } from "vitest";
import { TProject } from "@formbricks/types/project";
import { createApiKeyAction, deleteApiKeyAction, updateApiKeyAction } from "../actions";
import { TApiKeyWithEnvironmentPermission } from "../types/api-keys";
@@ -125,33 +125,33 @@ describe("EditAPIKeys", () => {
projects: mockProjects,
};
it("renders the API keys list", () => {
test("renders the API keys list", () => {
render(<EditAPIKeys {...defaultProps} />);
expect(screen.getByText("common.label")).toBeInTheDocument();
expect(screen.getByText("Test Key 1")).toBeInTheDocument();
expect(screen.getByText("Test Key 2")).toBeInTheDocument();
});
it("renders empty state when no API keys", () => {
test("renders empty state when no API keys", () => {
render(<EditAPIKeys {...defaultProps} apiKeys={[]} />);
expect(screen.getByText("environments.project.api_keys.no_api_keys_yet")).toBeInTheDocument();
});
it("shows add API key button when not readonly", () => {
test("shows add API key button when not readonly", () => {
render(<EditAPIKeys {...defaultProps} />);
expect(
screen.getByRole("button", { name: "environments.settings.api_keys.add_api_key" })
).toBeInTheDocument();
});
it("hides add API key button when readonly", () => {
test("hides add API key button when readonly", () => {
render(<EditAPIKeys {...defaultProps} isReadOnly={true} />);
expect(
screen.queryByRole("button", { name: "environments.settings.api_keys.add_api_key" })
).not.toBeInTheDocument();
});
it("opens add API key modal when clicking add button", async () => {
test("opens add API key modal when clicking add button", async () => {
render(<EditAPIKeys {...defaultProps} />);
const addButton = screen.getByRole("button", { name: "environments.settings.api_keys.add_api_key" });
await userEvent.click(addButton);
@@ -163,7 +163,7 @@ describe("EditAPIKeys", () => {
expect(modalTitle).toBeInTheDocument();
});
it("handles API key deletion", async () => {
test("handles API key deletion", async () => {
(deleteApiKeyAction as unknown as ReturnType<typeof vi.fn>).mockResolvedValue({ data: true });
render(<EditAPIKeys {...defaultProps} />);
@@ -222,7 +222,7 @@ describe("EditAPIKeys", () => {
expect(toast.success).toHaveBeenCalledWith("environments.project.api_keys.api_key_updated");
});
it("handles API key creation", async () => {
test("handles API key creation", async () => {
const newApiKey: TApiKeyWithEnvironmentPermission = {
id: "key3",
label: "New Key",
@@ -275,7 +275,7 @@ describe("EditAPIKeys", () => {
expect(toast.success).toHaveBeenCalledWith("environments.project.api_keys.api_key_created");
});
it("handles copy to clipboard", async () => {
test("handles copy to clipboard", async () => {
// Mock the clipboard writeText method
const writeText = vi.fn();
Object.assign(navigator, {

View File

@@ -2,7 +2,7 @@ import { ApiKeyPermission } from "@prisma/client";
import "@testing-library/jest-dom/vitest";
import { cleanup, render, screen } from "@testing-library/react";
import React from "react";
import { afterEach, describe, expect, it, vi } from "vitest";
import { afterEach, describe, expect, test, vi } from "vitest";
import { TProject } from "@formbricks/types/project";
import { TApiKeyWithEnvironmentPermission } from "../types/api-keys";
import { ViewPermissionModal } from "./view-permission-modal";
@@ -106,13 +106,13 @@ describe("ViewPermissionModal", () => {
apiKey: mockApiKey,
};
it("renders the modal with correct title", () => {
test("renders the modal with correct title", () => {
render(<ViewPermissionModal {...defaultProps} />);
// Check the localized text for the modal's title
expect(screen.getByText(mockApiKey.label)).toBeInTheDocument();
});
it("renders all permissions for the API key", () => {
test("renders all permissions for the API key", () => {
render(<ViewPermissionModal {...defaultProps} />);
// The same key has two environment permissions
const projectNames = screen.getAllByText("Project 1");
@@ -123,7 +123,7 @@ describe("ViewPermissionModal", () => {
expect(screen.getByText("write")).toBeInTheDocument();
});
it("displays correct project and environment names", () => {
test("displays correct project and environment names", () => {
render(<ViewPermissionModal {...defaultProps} />);
// Check for 'Project 1', 'production', 'development'
const projectNames = screen.getAllByText("Project 1");
@@ -132,14 +132,14 @@ describe("ViewPermissionModal", () => {
expect(screen.getByText("development")).toBeInTheDocument();
});
it("displays correct permission levels", () => {
test("displays correct permission levels", () => {
render(<ViewPermissionModal {...defaultProps} />);
// Check if permission levels 'read' and 'write' appear
expect(screen.getByText("read")).toBeInTheDocument();
expect(screen.getByText("write")).toBeInTheDocument();
});
it("handles API key with no permissions", () => {
test("handles API key with no permissions", () => {
render(<ViewPermissionModal {...defaultProps} apiKey={apiKeyWithoutPermissions} />);
// Ensure environment/permission section is empty
expect(screen.queryByText("Project 1")).not.toBeInTheDocument();
@@ -147,7 +147,7 @@ describe("ViewPermissionModal", () => {
expect(screen.queryByText("development")).not.toBeInTheDocument();
});
it("displays organizationAccess toggles", () => {
test("displays organizationAccess toggles", () => {
render(<ViewPermissionModal {...defaultProps} apiKey={mockApiKeyWithOrgAccess} />);
expect(screen.getByTestId("organization-access-accessControl-read")).toBeChecked();

View File

@@ -1,6 +1,6 @@
import { apiKeyCache } from "@/lib/cache/api-key";
import { ApiKey, ApiKeyPermission, Prisma } from "@prisma/client";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { beforeEach, describe, expect, test, vi } from "vitest";
import { prisma } from "@formbricks/database";
import { DatabaseError } from "@formbricks/types/errors";
import { TApiKeyWithEnvironmentPermission } from "../types/api-keys";
@@ -69,7 +69,7 @@ describe("API Key Management", () => {
});
describe("getApiKeysWithEnvironmentPermissions", () => {
it("retrieves API keys successfully", async () => {
test("retrieves API keys successfully", async () => {
vi.mocked(prisma.apiKey.findMany).mockResolvedValueOnce([mockApiKeyWithEnvironments]);
vi.mocked(apiKeyCache.tag.byOrganizationId).mockReturnValue("org-tag");
@@ -95,7 +95,7 @@ describe("API Key Management", () => {
});
});
it("throws DatabaseError on prisma error", async () => {
test("throws DatabaseError on prisma error", async () => {
const errToThrow = new Prisma.PrismaClientKnownRequestError("Mock error message", {
code: "P2002",
clientVersion: "0.0.1",
@@ -108,7 +108,7 @@ describe("API Key Management", () => {
});
describe("deleteApiKey", () => {
it("deletes an API key successfully", async () => {
test("deletes an API key successfully", async () => {
vi.mocked(prisma.apiKey.delete).mockResolvedValueOnce(mockApiKey);
const result = await deleteApiKey(mockApiKey.id);
@@ -122,7 +122,7 @@ describe("API Key Management", () => {
expect(apiKeyCache.revalidate).toHaveBeenCalled();
});
it("throws DatabaseError on prisma error", async () => {
test("throws DatabaseError on prisma error", async () => {
const errToThrow = new Prisma.PrismaClientKnownRequestError("Mock error message", {
code: "P2002",
clientVersion: "0.0.1",
@@ -158,7 +158,7 @@ describe("API Key Management", () => {
],
};
it("creates an API key successfully", async () => {
test("creates an API key successfully", async () => {
vi.mocked(prisma.apiKey.create).mockResolvedValueOnce(mockApiKey);
const result = await createApiKey("org123", "user123", mockApiKeyData);
@@ -168,7 +168,7 @@ describe("API Key Management", () => {
expect(apiKeyCache.revalidate).toHaveBeenCalled();
});
it("creates an API key with environment permissions successfully", async () => {
test("creates an API key with environment permissions successfully", async () => {
vi.mocked(prisma.apiKey.create).mockResolvedValueOnce(mockApiKeyWithEnvironments);
const result = await createApiKey("org123", "user123", {
@@ -181,7 +181,7 @@ describe("API Key Management", () => {
expect(apiKeyCache.revalidate).toHaveBeenCalled();
});
it("throws DatabaseError on prisma error", async () => {
test("throws DatabaseError on prisma error", async () => {
const errToThrow = new Prisma.PrismaClientKnownRequestError("Mock error message", {
code: "P2002",
clientVersion: "0.0.1",
@@ -194,7 +194,7 @@ describe("API Key Management", () => {
});
describe("updateApiKey", () => {
it("updates an API key successfully", async () => {
test("updates an API key successfully", async () => {
const updatedApiKey = { ...mockApiKey, label: "Updated API Key" };
vi.mocked(prisma.apiKey.update).mockResolvedValueOnce(updatedApiKey);
@@ -205,7 +205,7 @@ describe("API Key Management", () => {
expect(apiKeyCache.revalidate).toHaveBeenCalled();
});
it("throws DatabaseError on prisma error", async () => {
test("throws DatabaseError on prisma error", async () => {
const errToThrow = new Prisma.PrismaClientKnownRequestError("Mock error message", {
code: "P2002",
clientVersion: "0.0.1",

View File

@@ -1,5 +1,5 @@
import { Prisma } from "@prisma/client";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { beforeEach, describe, expect, test, vi } from "vitest";
import { prisma } from "@formbricks/database";
import { projectCache } from "@formbricks/lib/project/cache";
import { DatabaseError } from "@formbricks/types/errors";
@@ -68,7 +68,7 @@ describe("Projects Management", () => {
});
describe("getProjectsByOrganizationId", () => {
it("retrieves projects by organization ID successfully", async () => {
test("retrieves projects by organization ID successfully", async () => {
vi.mocked(prisma.project.findMany).mockResolvedValueOnce(mockProjects);
vi.mocked(projectCache.tag.byOrganizationId).mockReturnValue("org-tag");
@@ -87,7 +87,7 @@ describe("Projects Management", () => {
});
});
it("returns empty array when no projects exist", async () => {
test("returns empty array when no projects exist", async () => {
vi.mocked(prisma.project.findMany).mockResolvedValueOnce([]);
vi.mocked(projectCache.tag.byOrganizationId).mockReturnValue("org-tag");
@@ -106,7 +106,7 @@ describe("Projects Management", () => {
});
});
it("throws DatabaseError on prisma error", async () => {
test("throws DatabaseError on prisma error", async () => {
const errToThrow = new Prisma.PrismaClientKnownRequestError("Mock error message", {
code: "P2002",
clientVersion: "0.0.1",
@@ -117,7 +117,7 @@ describe("Projects Management", () => {
await expect(getProjectsByOrganizationId("org123")).rejects.toThrow(DatabaseError);
});
it("bubbles up unexpected errors", async () => {
test("bubbles up unexpected errors", async () => {
const unexpectedError = new Error("Unexpected error");
vi.mocked(prisma.project.findMany).mockRejectedValueOnce(unexpectedError);
vi.mocked(projectCache.tag.byOrganizationId).mockReturnValue("org-tag");

View File

@@ -2,7 +2,7 @@ import { getIsSamlSsoEnabled, getisSsoEnabled } from "@/modules/ee/license-check
import { getTranslate } from "@/tolgee/server";
import "@testing-library/jest-dom/vitest";
import { render, screen } from "@testing-library/react";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { beforeEach, describe, expect, test, vi } from "vitest";
import { findMatchingLocale } from "@formbricks/lib/utils/locale";
import { SignupPage } from "./page";
@@ -84,7 +84,7 @@ describe("SignupPage", () => {
vi.mocked(getTranslate).mockResolvedValue((key) => key);
});
it("renders the signup page correctly", async () => {
test("renders the signup page correctly", async () => {
const page = await SignupPage();
render(page);

View File

@@ -2,7 +2,7 @@ import { getFormattedErrorMessage } from "@/lib/utils/helper";
import { generateSingleUseIdAction } from "@/modules/survey/list/actions";
import { act, renderHook, waitFor } from "@testing-library/react";
import toast from "react-hot-toast";
import { describe, expect, it, vi } from "vitest";
import { describe, expect, test, vi } from "vitest";
import { TSurvey } from "@formbricks/types/surveys/types";
import { useSingleUseId } from "./useSingleUseId";
@@ -31,7 +31,7 @@ describe("useSingleUseId", () => {
},
} as TSurvey;
it("should initialize singleUseId to undefined", () => {
test("should initialize singleUseId to undefined", () => {
vi.mocked(generateSingleUseIdAction).mockResolvedValueOnce({ data: "mockSingleUseId" });
const { result } = renderHook(() => useSingleUseId(mockSurvey));
@@ -40,7 +40,7 @@ describe("useSingleUseId", () => {
expect(result.current.singleUseId).toBeUndefined();
});
it("should fetch and set singleUseId if singleUse is enabled", async () => {
test("should fetch and set singleUseId if singleUse is enabled", async () => {
vi.mocked(generateSingleUseIdAction).mockResolvedValueOnce({ data: "mockSingleUseId" });
const { result, rerender } = renderHook((props) => useSingleUseId(props), {
@@ -66,7 +66,7 @@ describe("useSingleUseId", () => {
expect(result.current.singleUseId).toBe("mockSingleUseId");
});
it("should return undefined and not call the API if singleUse is disabled", async () => {
test("should return undefined and not call the API if singleUse is disabled", async () => {
const disabledSurvey = {
...mockSurvey,
singleUse: {
@@ -83,7 +83,7 @@ describe("useSingleUseId", () => {
expect(generateSingleUseIdAction).not.toHaveBeenCalled();
});
it("should show toast error if the API call fails", async () => {
test("should show toast error if the API call fails", async () => {
vi.mocked(generateSingleUseIdAction).mockResolvedValueOnce({ serverError: "Something went wrong" });
const { result } = renderHook(() => useSingleUseId(mockSurvey));
@@ -96,7 +96,7 @@ describe("useSingleUseId", () => {
expect(toast.error).toHaveBeenCalledWith("Formatted error");
});
it("should refreshSingleUseId on demand", async () => {
test("should refreshSingleUseId on demand", async () => {
// Set up the initial mock response
vi.mocked(generateSingleUseIdAction).mockResolvedValueOnce({ data: "initialId" });

View File

@@ -1,15 +1,15 @@
import { describe, expect, it } from "vitest";
import { describe, expect, test } from "vitest";
import { copySurveyLink } from "../client-utils";
describe("copySurveyLink", () => {
it("appends singleUseId when provided", () => {
test("appends singleUseId when provided", () => {
const surveyUrl = "http://example.com/survey";
const singleUseId = "12345";
const result = copySurveyLink(surveyUrl, singleUseId);
expect(result).toBe("http://example.com/survey?suId=12345");
});
it("returns original surveyUrl when singleUseId is not provided", () => {
test("returns original surveyUrl when singleUseId is not provided", () => {
const surveyUrl = "http://example.com/survey";
const result = copySurveyLink(surveyUrl);
expect(result).toBe(surveyUrl);

View File

@@ -1,6 +1,6 @@
import { getSurvey } from "@/modules/survey/lib/survey";
import { getProjectByEnvironmentId } from "@/modules/survey/link/lib/project";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { beforeEach, describe, expect, test, vi } from "vitest";
import { IS_FORMBRICKS_CLOUD, SURVEY_URL, WEBAPP_URL } from "@formbricks/lib/constants";
import { COLOR_DEFAULTS } from "@formbricks/lib/styling/constants";
import { TSurvey, TSurveyWelcomeCard } from "@formbricks/types/surveys/types";
@@ -40,29 +40,29 @@ describe("Metadata Utils", () => {
});
describe("getNameForURL", () => {
it("replaces spaces with %20", () => {
test("replaces spaces with %20", () => {
const result = getNameForURL("Hello World");
expect(result).toBe("Hello%20World");
});
it("handles strings with no spaces correctly", () => {
test("handles strings with no spaces correctly", () => {
const result = getNameForURL("HelloWorld");
expect(result).toBe("HelloWorld");
});
it("handles strings with multiple spaces", () => {
test("handles strings with multiple spaces", () => {
const result = getNameForURL("Hello World Test");
expect(result).toBe("Hello%20%20World%20%20Test");
});
});
describe("getBrandColorForURL", () => {
it("replaces # with %23", () => {
test("replaces # with %23", () => {
const result = getBrandColorForURL("#ff0000");
expect(result).toBe("%23ff0000");
});
it("handles strings with no # correctly", () => {
test("handles strings with no # correctly", () => {
const result = getBrandColorForURL("ff0000");
expect(result).toBe("ff0000");
});
@@ -72,7 +72,7 @@ describe("Metadata Utils", () => {
const mockSurveyId = "survey-123";
const mockEnvironmentId = "env-456";
it("returns default metadata when survey is not found", async () => {
test("returns default metadata when survey is not found", async () => {
const result = await getBasicSurveyMetadata(mockSurveyId);
expect(getSurvey).toHaveBeenCalledWith(mockSurveyId);
@@ -83,7 +83,7 @@ describe("Metadata Utils", () => {
});
});
it("uses welcome card headline when available", async () => {
test("uses welcome card headline when available", async () => {
const mockSurvey = {
id: mockSurveyId,
environmentId: mockEnvironmentId,
@@ -115,7 +115,7 @@ describe("Metadata Utils", () => {
});
});
it("falls back to survey name when welcome card is not enabled", async () => {
test("falls back to survey name when welcome card is not enabled", async () => {
const mockSurvey = {
id: mockSurveyId,
environmentId: mockEnvironmentId,
@@ -137,7 +137,7 @@ describe("Metadata Utils", () => {
});
});
it("adds Formbricks to title when IS_FORMBRICKS_CLOUD is true", async () => {
test("adds Formbricks to title when IS_FORMBRICKS_CLOUD is true", async () => {
// Change the mock for this specific test
(IS_FORMBRICKS_CLOUD as unknown as ReturnType<typeof vi.fn>).mockReturnValue(true);
@@ -162,7 +162,7 @@ describe("Metadata Utils", () => {
});
describe("getSurveyOpenGraphMetadata", () => {
it("generates correct OpenGraph metadata", () => {
test("generates correct OpenGraph metadata", () => {
const surveyId = "survey-123";
const surveyName = "Test Survey";
const brandColor = COLOR_DEFAULTS.brandColor.replace("#", "%23");
@@ -190,7 +190,7 @@ describe("Metadata Utils", () => {
});
});
it("handles survey names with spaces correctly", () => {
test("handles survey names with spaces correctly", () => {
const surveyId = "survey-123";
const surveyName = "Test Survey With Spaces";
const result = getSurveyOpenGraphMetadata(surveyId, surveyName);

View File

@@ -1,6 +1,6 @@
import { TSurvey } from "@/modules/survey/list/types/surveys";
import { cleanup, render, screen } from "@testing-library/react";
import { afterEach, describe, expect, it, vi } from "vitest";
import { afterEach, describe, expect, test, vi } from "vitest";
import { SurveyCard } from "../survey-card";
// Mock constants
@@ -52,7 +52,7 @@ describe("SurveyCard", () => {
cleanup();
});
it("renders survey card with a draft link when not readOnly", () => {
test("renders survey card with a draft link when not readOnly", () => {
render(
// ...existing code for test wrapper if needed...
<SurveyCard
@@ -70,7 +70,7 @@ describe("SurveyCard", () => {
expect(link).toHaveAttribute("href", `/environments/${environmentId}/surveys/${dummySurvey.id}/edit`);
});
it("displays no clickable link when readOnly and survey is draft", () => {
test("displays no clickable link when readOnly and survey is draft", () => {
render(
<SurveyCard
survey={{ ...dummySurvey, status: "draft" } as unknown as TSurvey}
@@ -87,7 +87,7 @@ describe("SurveyCard", () => {
expect(link).toBeNull();
});
it("renders summary link when survey status is not draft", () => {
test("renders summary link when survey status is not draft", () => {
render(
<SurveyCard
survey={{ ...dummySurvey, status: "inProgress" } as unknown as TSurvey}

View File

@@ -1,7 +1,7 @@
import { TSurvey } from "@/modules/survey/list/types/surveys";
import { cleanup, fireEvent, render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { afterEach, describe, expect, it, vi } from "vitest";
import { afterEach, describe, expect, test, vi } from "vitest";
import { SurveyDropDownMenu } from "../survey-dropdown-menu";
// Mock constants
@@ -52,7 +52,7 @@ describe("SurveyDropDownMenu", () => {
cleanup();
});
it("calls copySurveyLink when copy link is clicked", async () => {
test("calls copySurveyLink when copy link is clicked", async () => {
const mockRefresh = vi.fn().mockResolvedValue("fakeSingleUseId");
const mockDeleteSurvey = vi.fn();
const mockDuplicateSurvey = vi.fn();
@@ -88,7 +88,7 @@ describe("SurveyDropDownMenu", () => {
});
});
it("shows edit and delete items when not disabled", async () => {
test("shows edit and delete items when not disabled", async () => {
render(
<SurveyDropDownMenu
environmentId="env123"

View File

@@ -1,6 +1,6 @@
import { cleanup, render, screen } from "@testing-library/react";
import { Session } from "next-auth";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
import { TOrganization } from "@formbricks/types/organizations";
import { TUser } from "@formbricks/types/user";
import { EnvironmentIdBaseLayout } from "./index";
@@ -51,7 +51,7 @@ vi.mock("@/app/(app)/environments/[environmentId]/components/PosthogIdentify", (
}));
describe("EnvironmentIdBaseLayout", () => {
it("renders correctly with provided props and children", async () => {
test("renders correctly with provided props and children", async () => {
const dummySession: Session = { user: { id: "user1" } } as Session;
const dummyUser: TUser = { id: "user1", email: "user1@example.com" } as TUser;
const dummyOrganization: TOrganization = { id: "org1", name: "Org1", billing: {} } as TOrganization;

View File

@@ -1,7 +1,7 @@
import { cleanup, render, waitFor } from "@testing-library/react";
import posthog, { CaptureResult } from "posthog-js";
import React from "react";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { beforeEach, describe, expect, test, vi } from "vitest";
import { PHProvider, PostHogPageview } from "./index";
vi.mock("next/navigation", () => ({
@@ -20,7 +20,7 @@ describe("PostHogPageview", () => {
cleanup();
});
it("does not initialize or capture when posthogEnabled is false", async () => {
test("does not initialize or capture when posthogEnabled is false", async () => {
let captureResult: CaptureResult = { uuid: "test-uuid", event: "$pageview", properties: {} };
const initSpy = vi.spyOn(posthog, "init").mockImplementation(() => posthog);
const captureSpy = vi.spyOn(posthog, "capture").mockImplementation(() => captureResult);
@@ -33,7 +33,7 @@ describe("PostHogPageview", () => {
});
});
it("logs an error if postHogApiHost is missing", async () => {
test("logs an error if postHogApiHost is missing", async () => {
const consoleErrorSpy = vi.spyOn(console, "error").mockImplementation(() => {});
render(<PostHogPageview posthogEnabled={true} postHogApiKey="test-key" />);
@@ -45,7 +45,7 @@ describe("PostHogPageview", () => {
});
});
it("logs an error if postHogApiKey is missing", async () => {
test("logs an error if postHogApiKey is missing", async () => {
const consoleErrorSpy = vi.spyOn(console, "error").mockImplementation(() => {});
render(<PostHogPageview posthogEnabled={true} postHogApiHost="test-host" />);
@@ -57,7 +57,7 @@ describe("PostHogPageview", () => {
});
});
it("initializes posthog and captures a pageview when enabled and credentials are provided", async () => {
test("initializes posthog and captures a pageview when enabled and credentials are provided", async () => {
let captureResult: CaptureResult = { uuid: "test-uuid", event: "$pageview", properties: {} };
const initSpy = vi.spyOn(posthog, "init").mockImplementation(() => posthog);
const captureSpy = vi.spyOn(posthog, "capture").mockImplementation(() => captureResult);
@@ -80,7 +80,7 @@ describe("PHProvider", () => {
cleanup();
});
it("wraps children with PostHogProvider when posthogEnabled is true", () => {
test("wraps children with PostHogProvider when posthogEnabled is true", () => {
// Here we simply verify that the children are rendered.
// The PostHogProvider from "posthog-js/react" acts as a context provider
// so we verify that our children appear in the output.
@@ -93,7 +93,7 @@ describe("PHProvider", () => {
expect(getByText("Child Content")).toBeInTheDocument();
});
it("renders children directly when posthogEnabled is false", () => {
test("renders children directly when posthogEnabled is false", () => {
const Child = () => <div>Child Content</div>;
const { getByText } = render(
<PHProvider posthogEnabled={false}>

View File

@@ -22,11 +22,12 @@ We use Vitest as our primary testing framework. All unit tests follow these conv
2. **Test Organization**
```typescript
import { describe, expect, it } from "vitest";
import { describe, expect, test } from "vitest";
describe("ComponentName or FeatureName", () => {
describe("functionName or scenario", () => {
it("should describe expected behavior", () => {
// We use the `test` function instead of `it` throught our test suite
test("should describe expected behavior", () => {
// test implementation
});
});

View File

@@ -1,3 +1,7 @@
module.exports = {
extends: ["turbo", "prettier"],
plugins: ["@vitest"],
rules: {
"@vitest/consistent-test-it": ["error", { fn: "test", withinDescribe: "test" }],
},
};

View File

@@ -1,7 +1,9 @@
module.exports = {
extends: ["next", "turbo", "prettier"],
plugins: ["@vitest"],
rules: {
"@next/next/no-html-link-for-pages": "off",
"react/jsx-key": "off",
"@vitest/consistent-test-it": ["error", { fn: "test", withinDescribe: "test" }],
},
};

View File

@@ -1,3 +1,7 @@
module.exports = {
extends: ["turbo", "prettier", "plugin:react-hooks/recommended"],
plugins: ["@vitest"],
rules: {
"@vitest/consistent-test-it": ["error", { fn: "test", withinDescribe: "test" }],
},
};

View File

@@ -31,4 +31,8 @@ module.exports = {
},
},
ignorePatterns: ["node_modules/", "dist/", "*.config.js", "*.config.ts", "*.d.ts"],
plugins: ["@vitest"],
rules: {
"@vitest/consistent-test-it": ["error", { fn: "test", withinDescribe: "test" }],
},
};

View File

@@ -38,8 +38,10 @@ module.exports = {
},
},
ignorePatterns: ["node_modules/", "dist/"],
plugins: ["@vitest"],
// add rules configurations here
rules: {
"import/no-default-export": "off",
"@vitest/consistent-test-it": ["error", { fn: "test", withinDescribe: "test" }],
},
};

View File

@@ -13,6 +13,7 @@
"eslint-plugin-i18n-json": "4.0.1",
"eslint-plugin-react": "7.37.5",
"eslint-plugin-react-hooks": "5.2.0",
"eslint-plugin-react-refresh": "0.4.19"
"eslint-plugin-react-refresh": "0.4.19",
"@vitest/eslint-plugin": "1.1.42"
}
}

View File

@@ -34,9 +34,10 @@ module.exports = {
},
},
ignorePatterns: ["node_modules/", "dist/", ".eslintrc.js", "**/*.css"],
// add rules configurations here
plugins: ["@vitest"],
rules: {
"import/no-default-export": "off",
"@vitest/consistent-test-it": ["error", { fn: "test", withinDescribe: "test" }],
},
overrides: [
{

View File

@@ -8,7 +8,7 @@ import {
mockEnvironment,
} from "./__mocks__/data.mock";
import { Prisma } from "@prisma/client";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
import { testInputValidation } from "vitestSetup";
import { PrismaErrorType } from "@formbricks/database/types/error";
import { DatabaseError } from "@formbricks/types/errors";
@@ -30,7 +30,7 @@ beforeEach(() => {
describe("Tests for createDisplay service", () => {
describe("Happy Path", () => {
it("Creates a new display when a userId exists", async () => {
test("Creates a new display when a userId exists", async () => {
prisma.environment.findUnique.mockResolvedValue(mockEnvironment);
prisma.display.create.mockResolvedValue(mockDisplayWithPersonId);
@@ -38,7 +38,7 @@ describe("Tests for createDisplay service", () => {
expect(display).toEqual(mockDisplayWithPersonId);
});
it("Creates a new display when a userId does not exists", async () => {
test("Creates a new display when a userId does not exists", async () => {
prisma.display.create.mockResolvedValue(mockDisplay);
const display = await createDisplay(mockDisplayInput);
@@ -49,7 +49,7 @@ describe("Tests for createDisplay service", () => {
describe("Sad Path", () => {
testInputValidation(createDisplay, "123");
it("Throws DatabaseError on PrismaClientKnownRequestError occurrence", async () => {
test("Throws DatabaseError on PrismaClientKnownRequestError occurrence", async () => {
const mockErrorMessage = "Mock error message";
prisma.environment.findUnique.mockResolvedValue(mockEnvironment);
const errToThrow = new Prisma.PrismaClientKnownRequestError(mockErrorMessage, {
@@ -62,7 +62,7 @@ describe("Tests for createDisplay service", () => {
await expect(createDisplay(mockDisplayInputWithUserId)).rejects.toThrow(DatabaseError);
});
it("Throws a generic Error for other exceptions", async () => {
test("Throws a generic Error for other exceptions", async () => {
const mockErrorMessage = "Mock error message";
prisma.display.create.mockRejectedValue(new Error(mockErrorMessage));
@@ -73,7 +73,7 @@ describe("Tests for createDisplay service", () => {
describe("Tests for delete display service", () => {
describe("Happy Path", () => {
it("Deletes a display", async () => {
test("Deletes a display", async () => {
prisma.display.delete.mockResolvedValue(mockDisplay);
const display = await deleteDisplay(mockDisplay.id);
@@ -81,7 +81,7 @@ describe("Tests for delete display service", () => {
});
});
describe("Sad Path", () => {
it("Throws DatabaseError on PrismaClientKnownRequestError occurrence", async () => {
test("Throws DatabaseError on PrismaClientKnownRequestError occurrence", async () => {
const mockErrorMessage = "Mock error message";
const errToThrow = new Prisma.PrismaClientKnownRequestError(mockErrorMessage, {
code: PrismaErrorType.UniqueConstraintViolation,
@@ -93,7 +93,7 @@ describe("Tests for delete display service", () => {
await expect(deleteDisplay(mockDisplay.id)).rejects.toThrow(DatabaseError);
});
it("Throws a generic Error for other exceptions", async () => {
test("Throws a generic Error for other exceptions", async () => {
const mockErrorMessage = "Mock error message";
prisma.display.delete.mockRejectedValue(new Error(mockErrorMessage));

View File

@@ -1,18 +1,18 @@
import { describe, expect, it } from "vitest";
import { describe, expect, test } from "vitest";
import { createI18nString } from "./utils";
describe("createI18nString", () => {
it("should create an i18n string from a regular string", () => {
test("should create an i18n string from a regular string", () => {
const result = createI18nString("Hello", ["default"]);
expect(result).toEqual({ default: "Hello" });
});
it("should create a new i18n string with i18n enabled from a previous i18n string", () => {
test("should create a new i18n string with i18n enabled from a previous i18n string", () => {
const result = createI18nString({ default: "Hello" }, ["default", "es"]);
expect(result).toEqual({ default: "Hello", es: "" });
});
it("should add a new field key value pair when a new language is added", () => {
test("should add a new field key value pair when a new language is added", () => {
const i18nObject = { default: "Hello", es: "Hola" };
const newLanguages = ["default", "es", "de"];
const result = createI18nString(i18nObject, newLanguages);
@@ -23,7 +23,7 @@ describe("createI18nString", () => {
});
});
it("should remove the translation that are not present in newLanguages", () => {
test("should remove the translation that are not present in newLanguages", () => {
const i18nObject = { default: "Hello", es: "hola" };
const newLanguages = ["default"];
const result = createI18nString(i18nObject, newLanguages);

View File

@@ -14,14 +14,14 @@ import { DatabaseError, ValidationError } from "@formbricks/types/errors";
import { createLanguage, deleteLanguage, updateLanguage } from "../service";
const testInputValidation = async (service: Function, ...args: any[]): Promise<void> => {
it("it should throw a ValidationError if the inputs are invalid", async () => {
test("it should throw a ValidationError if the inputs are invalid", async () => {
await expect(service(...args)).rejects.toThrow(ValidationError);
});
};
describe("Tests for createLanguage service", () => {
describe("Happy Path", () => {
it("Creates a new Language", async () => {
test("Creates a new Language", async () => {
prismaMock.language.create.mockResolvedValue(mockLanguage);
const language = await createLanguage(mockProjectId, mockEnvironmentId, mockLanguageInput);
@@ -32,7 +32,7 @@ describe("Tests for createLanguage service", () => {
describe("Sad Path", () => {
testInputValidation(createLanguage, "123");
it("Throws DatabaseError on PrismaClientKnownRequestError occurrence", async () => {
test("Throws DatabaseError on PrismaClientKnownRequestError occurrence", async () => {
const mockErrorMessage = "Mock error message";
const errToThrow = new Prisma.PrismaClientKnownRequestError(mockErrorMessage, {
code: PrismaErrorType.UniqueConstraintViolation,
@@ -46,7 +46,7 @@ describe("Tests for createLanguage service", () => {
);
});
it("Throws a generic Error for other exceptions", async () => {
test("Throws a generic Error for other exceptions", async () => {
const mockErrorMessage = "Mock error message";
prismaMock.language.create.mockRejectedValue(new Error(mockErrorMessage));
@@ -59,7 +59,7 @@ describe("Tests for createLanguage service", () => {
describe("Tests for updateLanguage Service", () => {
describe("Happy Path", () => {
it("Updates a language", async () => {
test("Updates a language", async () => {
prismaMock.language.update.mockResolvedValue(mockUpdatedLanguage);
const language = await updateLanguage(mockEnvironmentId, mockLanguageId, mockLanguageUpdate);
@@ -70,7 +70,7 @@ describe("Tests for updateLanguage Service", () => {
describe("Sad Path", () => {
testInputValidation(updateLanguage, "123", "123");
it("Throws DatabaseError on PrismaClientKnownRequestError", async () => {
test("Throws DatabaseError on PrismaClientKnownRequestError", async () => {
const mockErrorMessage = "Mock error message";
const errToThrow = new Prisma.PrismaClientKnownRequestError(mockErrorMessage, {
code: PrismaErrorType.UniqueConstraintViolation,
@@ -84,7 +84,7 @@ describe("Tests for updateLanguage Service", () => {
);
});
it("Throws a generic Error for other unexpected issues", async () => {
test("Throws a generic Error for other unexpected issues", async () => {
const mockErrorMessage = "Mock error message";
prismaMock.language.update.mockRejectedValue(new Error(mockErrorMessage));
@@ -97,7 +97,7 @@ describe("Tests for updateLanguage Service", () => {
describe("Tests for deleteLanguage", () => {
describe("Happy Path", () => {
it("Deletes a Language", async () => {
test("Deletes a Language", async () => {
prismaMock.language.delete.mockResolvedValue(mockLanguage);
const language = await deleteLanguage(mockLanguageId, mockProjectId);
@@ -107,7 +107,7 @@ describe("Tests for deleteLanguage", () => {
describe("Sad Path", () => {
testInputValidation(deleteLanguage, "123");
it("Throws DatabaseError on PrismaClientKnownRequestError occurrence", async () => {
test("Throws DatabaseError on PrismaClientKnownRequestError occurrence", async () => {
const mockErrorMessage = "Mock error message";
const errToThrow = new Prisma.PrismaClientKnownRequestError(mockErrorMessage, {
code: PrismaErrorType.UniqueConstraintViolation,
@@ -119,7 +119,7 @@ describe("Tests for deleteLanguage", () => {
await expect(deleteLanguage(mockLanguageId, mockProjectId)).rejects.toThrow(DatabaseError);
});
it("Throws a generic Error for other exceptions", async () => {
test("Throws a generic Error for other exceptions", async () => {
const mockErrorMessage = "Mock error message";
prismaMock.language.delete.mockRejectedValue(new Error(mockErrorMessage));

View File

@@ -13,7 +13,7 @@ import {
mockTags,
} from "./__mocks__/data.mock";
import { Prisma } from "@prisma/client";
import { beforeEach, describe, expect, it } from "vitest";
import { beforeEach, describe, expect, test } from "vitest";
import { testInputValidation } from "vitestSetup";
import { PrismaErrorType } from "@formbricks/database/types/error";
import { DatabaseError, ResourceNotFoundError } from "@formbricks/types/errors";
@@ -93,7 +93,7 @@ beforeEach(() => {
describe("Tests for getResponsesBySingleUseId", () => {
describe("Happy Path", () => {
it("Retrieves responses linked to a specific single-use ID", async () => {
test("Retrieves responses linked to a specific single-use ID", async () => {
const responses = await getResponseBySingleUseId(mockSurveyId, mockSingleUseId);
expect(responses).toEqual(expectedResponseWithoutPerson);
});
@@ -102,7 +102,7 @@ describe("Tests for getResponsesBySingleUseId", () => {
describe("Sad Path", () => {
testInputValidation(getResponseBySingleUseId, "123#", "123#");
it("Throws DatabaseError on PrismaClientKnownRequestError occurrence", async () => {
test("Throws DatabaseError on PrismaClientKnownRequestError occurrence", async () => {
const mockErrorMessage = "Mock error message";
const errToThrow = new Prisma.PrismaClientKnownRequestError(mockErrorMessage, {
code: PrismaErrorType.UniqueConstraintViolation,
@@ -114,7 +114,7 @@ describe("Tests for getResponsesBySingleUseId", () => {
await expect(getResponseBySingleUseId(mockSurveyId, mockSingleUseId)).rejects.toThrow(DatabaseError);
});
it("Throws a generic Error for other exceptions", async () => {
test("Throws a generic Error for other exceptions", async () => {
const mockErrorMessage = "Mock error message";
prisma.response.findUnique.mockRejectedValue(new Error(mockErrorMessage));
@@ -125,7 +125,7 @@ describe("Tests for getResponsesBySingleUseId", () => {
describe("Tests for getResponse service", () => {
describe("Happy Path", () => {
it("Retrieves a specific response by its ID", async () => {
test("Retrieves a specific response by its ID", async () => {
const response = await getResponse(mockResponse.id);
expect(response).toEqual(expectedResponseWithoutPerson);
});
@@ -134,13 +134,13 @@ describe("Tests for getResponse service", () => {
describe("Sad Path", () => {
testInputValidation(getResponse, "123#");
it("Throws ResourceNotFoundError if no response is found", async () => {
test("Throws ResourceNotFoundError if no response is found", async () => {
prisma.response.findUnique.mockResolvedValue(null);
const response = await getResponse(mockResponse.id);
expect(response).toBeNull();
});
it("Throws DatabaseError on PrismaClientKnownRequestError", async () => {
test("Throws DatabaseError on PrismaClientKnownRequestError", async () => {
const mockErrorMessage = "Mock error message";
const errToThrow = new Prisma.PrismaClientKnownRequestError(mockErrorMessage, {
code: PrismaErrorType.UniqueConstraintViolation,
@@ -152,7 +152,7 @@ describe("Tests for getResponse service", () => {
await expect(getResponse(mockResponse.id)).rejects.toThrow(DatabaseError);
});
it("Throws a generic Error for other unexpected issues", async () => {
test("Throws a generic Error for other unexpected issues", async () => {
const mockErrorMessage = "Mock error message";
prisma.response.findUnique.mockRejectedValue(new Error(mockErrorMessage));
@@ -163,7 +163,7 @@ describe("Tests for getResponse service", () => {
describe("Tests for getSurveySummary service", () => {
describe("Happy Path", () => {
it("Returns a summary of the survey responses", async () => {
test("Returns a summary of the survey responses", async () => {
prisma.survey.findUnique.mockResolvedValue(mockSurveyOutput);
prisma.response.findMany.mockResolvedValue([mockResponse]);
prisma.contactAttributeKey.findMany.mockResolvedValueOnce([mockContactAttributeKey]);
@@ -176,7 +176,7 @@ describe("Tests for getSurveySummary service", () => {
describe("Sad Path", () => {
testInputValidation(getSurveySummary, 1);
it("Throws DatabaseError on PrismaClientKnownRequestError", async () => {
test("Throws DatabaseError on PrismaClientKnownRequestError", async () => {
const mockErrorMessage = "Mock error message";
const errToThrow = new Prisma.PrismaClientKnownRequestError(mockErrorMessage, {
code: PrismaErrorType.UniqueConstraintViolation,
@@ -190,7 +190,7 @@ describe("Tests for getSurveySummary service", () => {
await expect(getSurveySummary(mockSurveyId)).rejects.toThrow(DatabaseError);
});
it("Throws a generic Error for unexpected problems", async () => {
test("Throws a generic Error for unexpected problems", async () => {
const mockErrorMessage = "Mock error message";
prisma.survey.findUnique.mockResolvedValue(mockSurveyOutput);
@@ -204,7 +204,7 @@ describe("Tests for getSurveySummary service", () => {
describe("Tests for getResponseDownloadUrl service", () => {
describe("Happy Path", () => {
it("Returns a download URL for the csv response file", async () => {
test("Returns a download URL for the csv response file", async () => {
prisma.survey.findUnique.mockResolvedValue(mockSurveyOutput);
prisma.response.count.mockResolvedValue(1);
prisma.response.findMany.mockResolvedValue([mockResponse]);
@@ -214,7 +214,7 @@ describe("Tests for getResponseDownloadUrl service", () => {
expect(fileExtension).toEqual("csv");
});
it("Returns a download URL for the xlsx response file", async () => {
test("Returns a download URL for the xlsx response file", async () => {
prisma.survey.findUnique.mockResolvedValue(mockSurveyOutput);
prisma.response.count.mockResolvedValue(1);
prisma.response.findMany.mockResolvedValue([mockResponse]);
@@ -228,7 +228,7 @@ describe("Tests for getResponseDownloadUrl service", () => {
describe("Sad Path", () => {
testInputValidation(getResponseDownloadUrl, mockSurveyId, 123);
it("Throws error if response file is of different format than expected", async () => {
test("Throws error if response file is of different format than expected", async () => {
prisma.survey.findUnique.mockResolvedValue(mockSurveyOutput);
prisma.response.count.mockResolvedValue(1);
prisma.response.findMany.mockResolvedValue([mockResponse]);
@@ -238,7 +238,7 @@ describe("Tests for getResponseDownloadUrl service", () => {
expect(fileExtension).not.toEqual("xlsx");
});
it("Throws DatabaseError on PrismaClientKnownRequestError, when the getResponseCountBySurveyId fails", async () => {
test("Throws DatabaseError on PrismaClientKnownRequestError, when the getResponseCountBySurveyId fails", async () => {
const mockErrorMessage = "Mock error message";
const errToThrow = new Prisma.PrismaClientKnownRequestError(mockErrorMessage, {
code: PrismaErrorType.UniqueConstraintViolation,
@@ -250,7 +250,7 @@ describe("Tests for getResponseDownloadUrl service", () => {
await expect(getResponseDownloadUrl(mockSurveyId, "csv")).rejects.toThrow(DatabaseError);
});
it("Throws DatabaseError on PrismaClientKnownRequestError, when the getResponses fails", async () => {
test("Throws DatabaseError on PrismaClientKnownRequestError, when the getResponses fails", async () => {
const mockErrorMessage = "Mock error message";
const errToThrow = new Prisma.PrismaClientKnownRequestError(mockErrorMessage, {
code: PrismaErrorType.UniqueConstraintViolation,
@@ -264,7 +264,7 @@ describe("Tests for getResponseDownloadUrl service", () => {
await expect(getResponseDownloadUrl(mockSurveyId, "csv")).rejects.toThrow(DatabaseError);
});
it("Throws a generic Error for unexpected problems", async () => {
test("Throws a generic Error for unexpected problems", async () => {
const mockErrorMessage = "Mock error message";
// error from getSurvey
@@ -277,7 +277,7 @@ describe("Tests for getResponseDownloadUrl service", () => {
describe("Tests for getResponsesByEnvironmentId", () => {
describe("Happy Path", () => {
it("Obtains all responses associated with a specific environment ID", async () => {
test("Obtains all responses associated with a specific environment ID", async () => {
const responses = await getResponsesByEnvironmentId(mockEnvironmentId);
expect(responses).toEqual([expectedResponseWithoutPerson]);
});
@@ -286,7 +286,7 @@ describe("Tests for getResponsesByEnvironmentId", () => {
describe("Sad Path", () => {
testInputValidation(getResponsesByEnvironmentId, "123#");
it("Throws DatabaseError on PrismaClientKnownRequestError", async () => {
test("Throws DatabaseError on PrismaClientKnownRequestError", async () => {
const mockErrorMessage = "Mock error message";
const errToThrow = new Prisma.PrismaClientKnownRequestError(mockErrorMessage, {
code: PrismaErrorType.UniqueConstraintViolation,
@@ -298,7 +298,7 @@ describe("Tests for getResponsesByEnvironmentId", () => {
await expect(getResponsesByEnvironmentId(mockEnvironmentId)).rejects.toThrow(DatabaseError);
});
it("Throws a generic Error for any other unhandled exceptions", async () => {
test("Throws a generic Error for any other unhandled exceptions", async () => {
const mockErrorMessage = "Mock error message";
prisma.response.findMany.mockRejectedValue(new Error(mockErrorMessage));
@@ -309,7 +309,7 @@ describe("Tests for getResponsesByEnvironmentId", () => {
describe("Tests for updateResponse Service", () => {
describe("Happy Path", () => {
it("Updates a response (finished = true)", async () => {
test("Updates a response (finished = true)", async () => {
const response = await updateResponse(mockResponse.id, getMockUpdateResponseInput(true));
expect(response).toEqual({
...expectedResponseWithoutPerson,
@@ -317,7 +317,7 @@ describe("Tests for updateResponse Service", () => {
});
});
it("Updates a response (finished = false)", async () => {
test("Updates a response (finished = false)", async () => {
const response = await updateResponse(mockResponse.id, getMockUpdateResponseInput(false));
expect(response).toEqual({
...expectedResponseWithoutPerson,
@@ -330,14 +330,14 @@ describe("Tests for updateResponse Service", () => {
describe("Sad Path", () => {
testInputValidation(updateResponse, "123#", {});
it("Throws ResourceNotFoundError if no response is found", async () => {
test("Throws ResourceNotFoundError if no response is found", async () => {
prisma.response.findUnique.mockResolvedValue(null);
await expect(updateResponse(mockResponse.id, getMockUpdateResponseInput())).rejects.toThrow(
ResourceNotFoundError
);
});
it("Throws DatabaseError on PrismaClientKnownRequestError", async () => {
test("Throws DatabaseError on PrismaClientKnownRequestError", async () => {
const mockErrorMessage = "Mock error message";
const errToThrow = new Prisma.PrismaClientKnownRequestError(mockErrorMessage, {
code: PrismaErrorType.UniqueConstraintViolation,
@@ -351,7 +351,7 @@ describe("Tests for updateResponse Service", () => {
);
});
it("Throws a generic Error for other unexpected issues", async () => {
test("Throws a generic Error for other unexpected issues", async () => {
const mockErrorMessage = "Mock error message";
prisma.response.update.mockRejectedValue(new Error(mockErrorMessage));
@@ -362,7 +362,7 @@ describe("Tests for updateResponse Service", () => {
describe("Tests for deleteResponse service", () => {
describe("Happy Path", () => {
it("Successfully deletes a response based on its ID", async () => {
test("Successfully deletes a response based on its ID", async () => {
const response = await deleteResponse(mockResponse.id);
expect(response).toEqual(expectedResponseWithoutPerson);
});
@@ -371,7 +371,7 @@ describe("Tests for deleteResponse service", () => {
describe("Sad Path", () => {
testInputValidation(deleteResponse, "123#");
it("Throws DatabaseError on PrismaClientKnownRequestError", async () => {
test("Throws DatabaseError on PrismaClientKnownRequestError", async () => {
const mockErrorMessage = "Mock error message";
const errToThrow = new Prisma.PrismaClientKnownRequestError(mockErrorMessage, {
code: PrismaErrorType.UniqueConstraintViolation,
@@ -383,7 +383,7 @@ describe("Tests for deleteResponse service", () => {
await expect(deleteResponse(mockResponse.id)).rejects.toThrow(DatabaseError);
});
it("Throws a generic Error for any unhandled exception during deletion", async () => {
test("Throws a generic Error for any unhandled exception during deletion", async () => {
const mockErrorMessage = "Mock error message";
prisma.response.delete.mockRejectedValue(new Error(mockErrorMessage));
@@ -394,14 +394,14 @@ describe("Tests for deleteResponse service", () => {
describe("Tests for getResponseCountBySurveyId service", () => {
describe("Happy Path", () => {
it("Counts the total number of responses for a given survey ID", async () => {
test("Counts the total number of responses for a given survey ID", async () => {
prisma.survey.findUnique.mockResolvedValue(mockSurveyOutput);
const count = await getResponseCountBySurveyId(mockSurveyId);
expect(count).toEqual(1);
});
it("Returns zero count when there are no responses for a given survey ID", async () => {
test("Returns zero count when there are no responses for a given survey ID", async () => {
prisma.response.count.mockResolvedValue(0);
const count = await getResponseCountBySurveyId(mockSurveyId);
expect(count).toEqual(0);
@@ -411,7 +411,7 @@ describe("Tests for getResponseCountBySurveyId service", () => {
describe("Sad Path", () => {
testInputValidation(getResponseCountBySurveyId, "123#");
it("Throws a generic Error for other unexpected issues", async () => {
test("Throws a generic Error for other unexpected issues", async () => {
const mockErrorMessage = "Mock error message";
prisma.response.count.mockRejectedValue(new Error(mockErrorMessage));
prisma.survey.findUnique.mockResolvedValue(mockSurveyOutput);

View File

@@ -1,7 +1,7 @@
import { prisma } from "../../__mocks__/database";
import { Prisma } from "@prisma/client";
import { evaluateLogic } from "surveyLogic/utils";
import { beforeEach, describe, expect, it } from "vitest";
import { beforeEach, describe, expect, test } from "vitest";
import { testInputValidation } from "vitestSetup";
import { PrismaErrorType } from "@formbricks/database/types/error";
import { DatabaseError, ResourceNotFoundError } from "@formbricks/types/errors";
@@ -13,7 +13,6 @@ import {
mockSurveyOutput,
mockSurveyWithLogic,
mockTransformedSurveyOutput,
mockUser,
updateSurveyInput,
} from "./__mock__/survey.mock";
@@ -22,7 +21,7 @@ beforeEach(() => {
});
describe("evaluateLogic with mockSurveyWithLogic", () => {
it("should return true when q1 answer is blue", () => {
test("should return true when q1 answer is blue", () => {
const data = { q1: "blue" };
const variablesData = {};
@@ -36,7 +35,7 @@ describe("evaluateLogic with mockSurveyWithLogic", () => {
expect(result).toBe(true);
});
it("should return false when q1 answer is not blue", () => {
test("should return false when q1 answer is not blue", () => {
const data = { q1: "red" };
const variablesData = {};
@@ -50,7 +49,7 @@ describe("evaluateLogic with mockSurveyWithLogic", () => {
expect(result).toBe(false);
});
it("should return true when q1 is blue and q2 is pizza", () => {
test("should return true when q1 is blue and q2 is pizza", () => {
const data = { q1: "blue", q2: "pizza" };
const variablesData = {};
@@ -64,7 +63,7 @@ describe("evaluateLogic with mockSurveyWithLogic", () => {
expect(result).toBe(true);
});
it("should return false when q1 is blue but q2 is not pizza", () => {
test("should return false when q1 is blue but q2 is not pizza", () => {
const data = { q1: "blue", q2: "burger" };
const variablesData = {};
@@ -78,7 +77,7 @@ describe("evaluateLogic with mockSurveyWithLogic", () => {
expect(result).toBe(false);
});
it("should return true when q2 is pizza or q3 is Inception", () => {
test("should return true when q2 is pizza or q3 is Inception", () => {
const data = { q2: "pizza", q3: "Inception" };
const variablesData = {};
@@ -92,7 +91,7 @@ describe("evaluateLogic with mockSurveyWithLogic", () => {
expect(result).toBe(true);
});
it("should return true when var1 is equal to single select question value", () => {
test("should return true when var1 is equal to single select question value", () => {
const data = { q4: "lmao" };
const variablesData = { siog1dabtpo3l0a3xoxw2922: "lmao" };
@@ -106,7 +105,7 @@ describe("evaluateLogic with mockSurveyWithLogic", () => {
expect(result).toBe(true);
});
it("should return false when var1 is not equal to single select question value", () => {
test("should return false when var1 is not equal to single select question value", () => {
const data = { q4: "lol" };
const variablesData = { siog1dabtpo3l0a3xoxw2922: "damn" };
@@ -120,7 +119,7 @@ describe("evaluateLogic with mockSurveyWithLogic", () => {
expect(result).toBe(false);
});
it("should return true when var2 is greater than 30 and less than open text number value", () => {
test("should return true when var2 is greater than 30 and less than open text number value", () => {
const data = { q5: "40" };
const variablesData = { km1srr55owtn2r7lkoh5ny1u: 35 };
@@ -134,7 +133,7 @@ describe("evaluateLogic with mockSurveyWithLogic", () => {
expect(result).toBe(true);
});
it("should return false when var2 is not greater than 30 or greater than open text number value", () => {
test("should return false when var2 is not greater than 30 or greater than open text number value", () => {
const data = { q5: "40" };
const variablesData = { km1srr55owtn2r7lkoh5ny1u: 25 };
@@ -148,7 +147,7 @@ describe("evaluateLogic with mockSurveyWithLogic", () => {
expect(result).toBe(false);
});
it("should return for complex condition", () => {
test("should return for complex condition", () => {
const data = { q6: ["lmao", "XD"], q1: "green", q2: "pizza", q3: "inspection", name: "pizza" };
const variablesData = { siog1dabtpo3l0a3xoxw2922: "tokyo" };
@@ -165,13 +164,13 @@ describe("evaluateLogic with mockSurveyWithLogic", () => {
describe("Tests for getSurvey", () => {
describe("Happy Path", () => {
it("Returns a survey", async () => {
test("Returns a survey", async () => {
prisma.survey.findUnique.mockResolvedValueOnce(mockSurveyOutput);
const survey = await getSurvey(mockId);
expect(survey).toEqual(mockTransformedSurveyOutput);
});
it("Returns null if survey is not found", async () => {
test("Returns null if survey is not found", async () => {
prisma.survey.findUnique.mockResolvedValueOnce(null);
const survey = await getSurvey(mockId);
expect(survey).toBeNull();
@@ -181,7 +180,7 @@ describe("Tests for getSurvey", () => {
describe("Sad Path", () => {
testInputValidation(getSurvey, "123#");
it("should throw a DatabaseError error if there is a PrismaClientKnownRequestError", async () => {
test("should throw a DatabaseError error if there is a PrismaClientKnownRequestError", async () => {
const mockErrorMessage = "Mock error message";
const errToThrow = new Prisma.PrismaClientKnownRequestError(mockErrorMessage, {
code: PrismaErrorType.UniqueConstraintViolation,
@@ -191,7 +190,7 @@ describe("Tests for getSurvey", () => {
await expect(getSurvey(mockId)).rejects.toThrow(DatabaseError);
});
it("should throw an error if there is an unknown error", async () => {
test("should throw an error if there is an unknown error", async () => {
const mockErrorMessage = "Mock error message";
prisma.survey.findUnique.mockRejectedValue(new Error(mockErrorMessage));
await expect(getSurvey(mockId)).rejects.toThrow(Error);
@@ -201,13 +200,13 @@ describe("Tests for getSurvey", () => {
describe("Tests for getSurveysByActionClassId", () => {
describe("Happy Path", () => {
it("Returns an array of surveys for a given actionClassId", async () => {
test("Returns an array of surveys for a given actionClassId", async () => {
prisma.survey.findMany.mockResolvedValueOnce([mockSurveyOutput]);
const surveys = await getSurveysByActionClassId(mockId);
expect(surveys).toEqual([mockTransformedSurveyOutput]);
});
it("Returns an empty array if no surveys are found", async () => {
test("Returns an empty array if no surveys are found", async () => {
prisma.survey.findMany.mockResolvedValueOnce([]);
const surveys = await getSurveysByActionClassId(mockId);
expect(surveys).toEqual([]);
@@ -217,7 +216,7 @@ describe("Tests for getSurveysByActionClassId", () => {
describe("Sad Path", () => {
testInputValidation(getSurveysByActionClassId, "123#");
it("should throw an error if there is an unknown error", async () => {
test("should throw an error if there is an unknown error", async () => {
const mockErrorMessage = "Unknown error occurred";
prisma.survey.findMany.mockRejectedValue(new Error(mockErrorMessage));
await expect(getSurveysByActionClassId(mockId)).rejects.toThrow(Error);
@@ -227,13 +226,13 @@ describe("Tests for getSurveysByActionClassId", () => {
describe("Tests for getSurveys", () => {
describe("Happy Path", () => {
it("Returns an array of surveys for a given environmentId, limit(optional) and offset(optional)", async () => {
test("Returns an array of surveys for a given environmentId, limit(optional) and offset(optional)", async () => {
prisma.survey.findMany.mockResolvedValueOnce([mockSurveyOutput]);
const surveys = await getSurveys(mockId);
expect(surveys).toEqual([mockTransformedSurveyOutput]);
});
it("Returns an empty array if no surveys are found", async () => {
test("Returns an empty array if no surveys are found", async () => {
prisma.survey.findMany.mockResolvedValueOnce([]);
const surveys = await getSurveys(mockId);
@@ -244,7 +243,7 @@ describe("Tests for getSurveys", () => {
describe("Sad Path", () => {
testInputValidation(getSurveysByActionClassId, "123#");
it("should throw a DatabaseError error if there is a PrismaClientKnownRequestError", async () => {
test("should throw a DatabaseError error if there is a PrismaClientKnownRequestError", async () => {
const mockErrorMessage = "Mock error message";
const errToThrow = new Prisma.PrismaClientKnownRequestError(mockErrorMessage, {
code: PrismaErrorType.UniqueConstraintViolation,
@@ -255,7 +254,7 @@ describe("Tests for getSurveys", () => {
await expect(getSurveys(mockId)).rejects.toThrow(DatabaseError);
});
it("should throw an error if there is an unknown error", async () => {
test("should throw an error if there is an unknown error", async () => {
const mockErrorMessage = "Unknown error occurred";
prisma.survey.findMany.mockRejectedValue(new Error(mockErrorMessage));
await expect(getSurveys(mockId)).rejects.toThrow(Error);
@@ -268,7 +267,7 @@ describe("Tests for updateSurvey", () => {
prisma.actionClass.findMany.mockResolvedValueOnce([mockActionClass]);
});
describe("Happy Path", () => {
it("Updates a survey successfully", async () => {
test("Updates a survey successfully", async () => {
prisma.survey.findUnique.mockResolvedValueOnce(mockSurveyOutput);
prisma.organization.findFirst.mockResolvedValueOnce(mockOrganizationOutput);
prisma.survey.update.mockResolvedValueOnce(mockSurveyOutput);
@@ -280,14 +279,14 @@ describe("Tests for updateSurvey", () => {
describe("Sad Path", () => {
testInputValidation(updateSurvey, "123#");
it("Throws ResourceNotFoundError if the survey does not exist", async () => {
test("Throws ResourceNotFoundError if the survey does not exist", async () => {
prisma.survey.findUnique.mockRejectedValueOnce(
new ResourceNotFoundError("Survey", updateSurveyInput.id)
);
await expect(updateSurvey(updateSurveyInput)).rejects.toThrow(ResourceNotFoundError);
});
it("should throw a DatabaseError error if there is a PrismaClientKnownRequestError", async () => {
test("should throw a DatabaseError error if there is a PrismaClientKnownRequestError", async () => {
const mockErrorMessage = "Mock error message";
const errToThrow = new Prisma.PrismaClientKnownRequestError(mockErrorMessage, {
code: PrismaErrorType.UniqueConstraintViolation,
@@ -299,7 +298,7 @@ describe("Tests for updateSurvey", () => {
await expect(updateSurvey(updateSurveyInput)).rejects.toThrow(DatabaseError);
});
it("should throw an error if there is an unknown error", async () => {
test("should throw an error if there is an unknown error", async () => {
const mockErrorMessage = "Unknown error occurred";
prisma.survey.findUnique.mockResolvedValueOnce(mockSurveyOutput);
prisma.survey.update.mockRejectedValue(new Error(mockErrorMessage));
@@ -314,7 +313,7 @@ describe("Tests for updateSurvey", () => {
// });
// describe("Happy Path", () => {
// it("Creates a survey successfully", async () => {
// test("Creates a survey successfully", async () => {
// prisma.survey.create.mockResolvedValueOnce(mockSurveyOutput);
// prisma.organization.findFirst.mockResolvedValueOnce(mockOrganizationOutput);
// prisma.actionClass.findMany.mockResolvedValue([mockActionClass]);
@@ -346,7 +345,7 @@ describe("Tests for updateSurvey", () => {
// describe("Sad Path", () => {
// testInputValidation(createSurvey, "123#", createSurveyInput);
// it("should throw an error if there is an unknown error", async () => {
// test("should throw an error if there is an unknown error", async () => {
// const mockErrorMessage = "Unknown error occurred";
// prisma.survey.delete.mockRejectedValue(new Error(mockErrorMessage));
// await expect(createSurvey(mockId, createSurveyInput)).rejects.toThrow(Error);
@@ -360,7 +359,7 @@ describe("Tests for updateSurvey", () => {
// });
// describe("Happy Path", () => {
// it("Duplicates a survey successfully", async () => {
// test("Duplicates a survey successfully", async () => {
// prisma.survey.findUnique.mockResolvedValueOnce(mockSurveyOutput);
// prisma.survey.create.mockResolvedValueOnce(mockSurveyOutput);
// // @ts-expect-error
@@ -378,14 +377,14 @@ describe("Tests for updateSurvey", () => {
// describe("Sad Path", () => {
// testInputValidation(copySurveyToOtherEnvironment, "123#", "123#", "123#", "123#", "123#");
// it("Throws ResourceNotFoundError if the survey does not exist", async () => {
// test("Throws ResourceNotFoundError if the survey does not exist", async () => {
// prisma.survey.findUnique.mockRejectedValueOnce(new ResourceNotFoundError("Survey", mockId));
// await expect(copySurveyToOtherEnvironment(mockId, mockId, mockId, mockId)).rejects.toThrow(
// ResourceNotFoundError
// );
// });
// it("should throw an error if there is an unknown error", async () => {
// test("should throw an error if there is an unknown error", async () => {
// const mockErrorMessage = "Unknown error occurred";
// prisma.survey.create.mockRejectedValue(new Error(mockErrorMessage));
// await expect(copySurveyToOtherEnvironment(mockId, mockId, mockId, mockId)).rejects.toThrow(Error);
@@ -406,7 +405,7 @@ describe("Tests for updateSurvey", () => {
// prisma.attributeClass.findMany.mockResolvedValueOnce([mockAttributeClass]);
// });
// it("Returns synced surveys", async () => {
// test("Returns synced surveys", async () => {
// prisma.survey.findMany.mockResolvedValueOnce([mockSyncSurveyOutput]);
// prisma.person.findUnique.mockResolvedValueOnce(mockPrismaPerson);
// prisma.response.findMany.mockResolvedValue([mockResponseWithMockPerson]);
@@ -418,7 +417,7 @@ describe("Tests for updateSurvey", () => {
// expect(surveys).toEqual([mockTransformedSyncSurveyOutput]);
// });
// it("Returns an empty array if no surveys are found", async () => {
// test("Returns an empty array if no surveys are found", async () => {
// prisma.survey.findMany.mockResolvedValueOnce([]);
// prisma.person.findUnique.mockResolvedValueOnce(mockPrismaPerson);
// const surveys = await getSyncSurveys(mockId, mockPrismaPerson.id, "desktop", {
@@ -431,7 +430,7 @@ describe("Tests for updateSurvey", () => {
// describe("Sad Path", () => {
// testInputValidation(getSyncSurveys, "123#", {});
// it("does not find a Project", async () => {
// test("does not find a Project", async () => {
// prisma.project.findFirst.mockResolvedValueOnce(null);
// await expect(
@@ -439,7 +438,7 @@ describe("Tests for updateSurvey", () => {
// ).rejects.toThrow(Error);
// });
// it("should throw an error if there is an unknown error", async () => {
// test("should throw an error if there is an unknown error", async () => {
// const mockErrorMessage = "Unknown error occurred";
// prisma.actionClass.findMany.mockResolvedValueOnce([mockActionClass]);
// prisma.survey.create.mockRejectedValue(new Error(mockErrorMessage));
@@ -452,12 +451,12 @@ describe("Tests for updateSurvey", () => {
describe("Tests for getSurveyCount service", () => {
describe("Happy Path", () => {
it("Counts the total number of surveys for a given environment ID", async () => {
test("Counts the total number of surveys for a given environment ID", async () => {
const count = await getSurveyCount(mockId);
expect(count).toEqual(1);
});
it("Returns zero count when there are no surveys for a given environment ID", async () => {
test("Returns zero count when there are no surveys for a given environment ID", async () => {
prisma.survey.count.mockResolvedValue(0);
const count = await getSurveyCount(mockId);
expect(count).toEqual(0);
@@ -467,7 +466,7 @@ describe("Tests for getSurveyCount service", () => {
describe("Sad Path", () => {
testInputValidation(getSurveyCount, "123#");
it("Throws a generic Error for other unexpected issues", async () => {
test("Throws a generic Error for other unexpected issues", async () => {
const mockErrorMessage = "Mock error message";
prisma.survey.count.mockRejectedValue(new Error(mockErrorMessage));

Some files were not shown because too many files have changed in this diff Show More