mirror of
https://github.com/formbricks/formbricks.git
synced 2026-05-14 19:38:53 -05:00
fix: fixes displays and responses api about survey status (#8007)
This commit is contained in:
@@ -2,7 +2,12 @@ import { Prisma } from "@prisma/client";
|
||||
import { beforeEach, describe, expect, test, vi } from "vitest";
|
||||
import { prisma } from "@formbricks/database";
|
||||
import { TDisplayCreateInput } from "@formbricks/types/displays";
|
||||
import { DatabaseError, ResourceNotFoundError, ValidationError } from "@formbricks/types/errors";
|
||||
import {
|
||||
DatabaseError,
|
||||
InvalidInputError,
|
||||
ResourceNotFoundError,
|
||||
ValidationError,
|
||||
} from "@formbricks/types/errors";
|
||||
import { validateInputs } from "@/lib/utils/validate";
|
||||
import { getContactByUserId } from "./contact";
|
||||
import { createDisplay } from "./display";
|
||||
@@ -78,6 +83,7 @@ const mockSurvey = {
|
||||
id: surveyId,
|
||||
name: "Test Survey",
|
||||
environmentId,
|
||||
status: "inProgress",
|
||||
} as any;
|
||||
|
||||
describe("createDisplay", () => {
|
||||
@@ -177,6 +183,17 @@ describe("createDisplay", () => {
|
||||
expect(prisma.display.create).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test.each(["draft", "paused", "completed"])(
|
||||
"should throw InvalidInputError when survey status is %s",
|
||||
async (status) => {
|
||||
vi.mocked(getContactByUserId).mockResolvedValue(mockContact);
|
||||
vi.mocked(prisma.survey.findUnique).mockResolvedValue({ ...mockSurvey, status } as any);
|
||||
|
||||
await expect(createDisplay(displayInput)).rejects.toThrow(InvalidInputError);
|
||||
expect(prisma.display.create).not.toHaveBeenCalled();
|
||||
}
|
||||
);
|
||||
|
||||
test("should throw DatabaseError on other Prisma known request errors", async () => {
|
||||
const prismaError = new Prisma.PrismaClientKnownRequestError("Database error", {
|
||||
code: "P2002",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { prisma } from "@formbricks/database";
|
||||
import { TDisplayCreateInput, ZDisplayCreateInput } from "@formbricks/types/displays";
|
||||
import { DatabaseError, ResourceNotFoundError } from "@formbricks/types/errors";
|
||||
import { DatabaseError, InvalidInputError, ResourceNotFoundError } from "@formbricks/types/errors";
|
||||
import { validateInputs } from "@/lib/utils/validate";
|
||||
import { getContactByUserId } from "./contact";
|
||||
|
||||
@@ -41,6 +41,10 @@ export const createDisplay = async (displayInput: TDisplayCreateInput): Promise<
|
||||
throw new ResourceNotFoundError("Survey", surveyId);
|
||||
}
|
||||
|
||||
if (survey.status !== "inProgress") {
|
||||
throw new InvalidInputError("Survey is not accepting submissions");
|
||||
}
|
||||
|
||||
const display = await prisma.display.create({
|
||||
data: {
|
||||
survey: {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { logger } from "@formbricks/logger";
|
||||
import { ZDisplayCreateInput } from "@formbricks/types/displays";
|
||||
import { ResourceNotFoundError } from "@formbricks/types/errors";
|
||||
import { InvalidInputError, ResourceNotFoundError } from "@formbricks/types/errors";
|
||||
import { responses } from "@/app/lib/api/response";
|
||||
import { transformErrorToDetails } from "@/app/lib/api/validator";
|
||||
import { THandlerParams, withV1ApiWrapper } from "@/app/lib/api/with-api-logging";
|
||||
@@ -61,6 +61,12 @@ export const POST = withV1ApiWrapper({
|
||||
return {
|
||||
response: responses.notFoundResponse("Survey", inputValidation.data.surveyId),
|
||||
};
|
||||
} else if (error instanceof InvalidInputError) {
|
||||
return {
|
||||
response: responses.forbiddenResponse(error.message, true, {
|
||||
surveyId: inputValidation.data.surveyId,
|
||||
}),
|
||||
};
|
||||
} else {
|
||||
logger.error({ error, url: req.url }, "Error in POST /api/v1/client/[environmentId]/displays");
|
||||
return {
|
||||
|
||||
@@ -128,6 +128,14 @@ export const POST = withV1ApiWrapper({
|
||||
};
|
||||
}
|
||||
|
||||
if (survey.status !== "inProgress") {
|
||||
return {
|
||||
response: responses.forbiddenResponse("Survey is not accepting submissions", true, {
|
||||
surveyId: survey.id,
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
const singleUseValidationResult = validateSingleUseResponseInput(
|
||||
survey,
|
||||
environmentId,
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { beforeEach, describe, expect, test, vi } from "vitest";
|
||||
import { prisma } from "@formbricks/database";
|
||||
import { DatabaseError, ResourceNotFoundError, ValidationError } from "@formbricks/types/errors";
|
||||
import {
|
||||
DatabaseError,
|
||||
InvalidInputError,
|
||||
ResourceNotFoundError,
|
||||
ValidationError,
|
||||
} from "@formbricks/types/errors";
|
||||
import { validateInputs } from "@/lib/utils/validate";
|
||||
import { TDisplayCreateInputV2 } from "../types/display";
|
||||
import { doesContactExist } from "./contact";
|
||||
@@ -66,6 +71,7 @@ const mockSurvey = {
|
||||
id: surveyId,
|
||||
name: "Test Survey",
|
||||
environmentId,
|
||||
status: "inProgress",
|
||||
} as any;
|
||||
|
||||
describe("createDisplay", () => {
|
||||
@@ -149,6 +155,17 @@ describe("createDisplay", () => {
|
||||
expect(prisma.display.create).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test.each(["draft", "paused", "completed"])(
|
||||
"should throw InvalidInputError when survey status is %s",
|
||||
async (status) => {
|
||||
vi.mocked(doesContactExist).mockResolvedValue(true);
|
||||
vi.mocked(prisma.survey.findUnique).mockResolvedValue({ ...mockSurvey, status } as any);
|
||||
|
||||
await expect(createDisplay(displayInput)).rejects.toThrow(InvalidInputError);
|
||||
expect(prisma.display.create).not.toHaveBeenCalled();
|
||||
}
|
||||
);
|
||||
|
||||
test("should throw DatabaseError on other Prisma known request errors", async () => {
|
||||
const prismaError = new Prisma.PrismaClientKnownRequestError("DB error", {
|
||||
code: "P2002",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { prisma } from "@formbricks/database";
|
||||
import { DatabaseError, ResourceNotFoundError } from "@formbricks/types/errors";
|
||||
import { DatabaseError, InvalidInputError, ResourceNotFoundError } from "@formbricks/types/errors";
|
||||
import {
|
||||
TDisplayCreateInputV2,
|
||||
ZDisplayCreateInputV2,
|
||||
@@ -26,6 +26,10 @@ export const createDisplay = async (displayInput: TDisplayCreateInputV2): Promis
|
||||
throw new ResourceNotFoundError("Survey", surveyId);
|
||||
}
|
||||
|
||||
if (survey.status !== "inProgress") {
|
||||
throw new InvalidInputError("Survey is not accepting submissions");
|
||||
}
|
||||
|
||||
const display = await prisma.display.create({
|
||||
data: {
|
||||
survey: {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ResourceNotFoundError } from "@formbricks/types/errors";
|
||||
import { InvalidInputError, ResourceNotFoundError } from "@formbricks/types/errors";
|
||||
import {
|
||||
TDisplayCreateInputV2,
|
||||
ZDisplayCreateInputV2,
|
||||
@@ -79,6 +79,12 @@ export const POST = async (request: Request, context: Context): Promise<Response
|
||||
return responses.notFoundResponse("Survey", displayInputData.surveyId, true);
|
||||
}
|
||||
|
||||
if (error instanceof InvalidInputError) {
|
||||
return responses.forbiddenResponse(error.message, true, {
|
||||
surveyId: displayInputData.surveyId,
|
||||
});
|
||||
}
|
||||
|
||||
const response = responses.internalServerErrorResponse("Something went wrong. Please try again.", true);
|
||||
reportApiError({
|
||||
request,
|
||||
|
||||
@@ -26,6 +26,7 @@ vi.mock("@/app/lib/api/response", () => ({
|
||||
responses: {
|
||||
badRequestResponse: vi.fn((message) => new Response(message, { status: 400 })),
|
||||
notFoundResponse: vi.fn((message) => new Response(message, { status: 404 })),
|
||||
forbiddenResponse: vi.fn((message) => new Response(message, { status: 403 })),
|
||||
},
|
||||
}));
|
||||
|
||||
@@ -138,6 +139,19 @@ describe("checkSurveyValidity", () => {
|
||||
);
|
||||
});
|
||||
|
||||
test.each(["draft", "paused", "completed"] as const)(
|
||||
"should return forbiddenResponse when survey status is %s",
|
||||
async (status) => {
|
||||
const survey = { ...mockSurvey, status } as TSurvey;
|
||||
const result = await checkSurveyValidity(survey, "env-1", mockResponseInput);
|
||||
expect(result).toBeInstanceOf(Response);
|
||||
expect(result?.status).toBe(403);
|
||||
expect(responses.forbiddenResponse).toHaveBeenCalledWith("Survey is not accepting submissions", true, {
|
||||
surveyId: mockSurvey.id,
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
test("should return null if recaptcha is not enabled", async () => {
|
||||
const survey = { ...mockSurvey, recaptcha: { enabled: false, threshold: 0.5 } };
|
||||
const result = await checkSurveyValidity(survey, "env-1", mockResponseInput);
|
||||
|
||||
@@ -19,6 +19,12 @@ export const checkSurveyValidity = async (
|
||||
return responses.badRequestResponse("Survey does not belong to this environment", undefined, true);
|
||||
}
|
||||
|
||||
if (survey.status !== "inProgress") {
|
||||
return responses.forbiddenResponse("Survey is not accepting submissions", true, {
|
||||
surveyId: survey.id,
|
||||
});
|
||||
}
|
||||
|
||||
const singleUseValidationResult = validateSingleUseResponseInput(survey, environmentId, responseInput);
|
||||
if (singleUseValidationResult) {
|
||||
if ("response" in singleUseValidationResult) {
|
||||
|
||||
@@ -32,6 +32,7 @@ beforeEach(() => {
|
||||
id: mockSurveyId,
|
||||
name: "Test Survey",
|
||||
environmentId: mockEnvironmentId,
|
||||
status: "inProgress",
|
||||
} as any);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user