mirror of
https://github.com/formbricks/formbricks.git
synced 2026-04-20 19:30:41 -05:00
make work with blocks
This commit is contained in:
+90
-19
@@ -4,10 +4,12 @@ import { z } from "zod";
|
||||
import { ZId } from "@formbricks/types/common";
|
||||
import { OperationNotAllowedError, ResourceNotFoundError, UnknownError } from "@formbricks/types/errors";
|
||||
import { TResponseInput } from "@formbricks/types/responses";
|
||||
import { TSurveyQuestionTypeEnum } from "@formbricks/types/surveys/types";
|
||||
import { TSurveyElementTypeEnum } from "@formbricks/types/surveys/elements";
|
||||
import { getEmailTemplateHtml } from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/lib/emailTemplate";
|
||||
import { createResponseWithQuotaEvaluation } from "@/app/api/v1/client/[environmentId]/responses/lib/response";
|
||||
import { getLocalizedValue } from "@/lib/i18n/utils";
|
||||
import { getSurvey, updateSurvey } from "@/lib/survey/service";
|
||||
import { getElementsFromBlocks } from "@/lib/survey/utils";
|
||||
import { authenticatedActionClient } from "@/lib/utils/action-client";
|
||||
import { checkAuthorizationUpdated } from "@/lib/utils/action-client/action-client-middleware";
|
||||
import { AuthenticatedActionClientCtx } from "@/lib/utils/action-client/types/context";
|
||||
@@ -320,19 +322,24 @@ export const generateTestResponsesAction = authenticatedActionClient
|
||||
throw new OperationNotAllowedError("Survey does not belong to the specified environment");
|
||||
}
|
||||
|
||||
const supportedQuestionTypes = [
|
||||
TSurveyQuestionTypeEnum.OpenText,
|
||||
TSurveyQuestionTypeEnum.NPS,
|
||||
TSurveyQuestionTypeEnum.Rating,
|
||||
const supportedElementTypes = [
|
||||
TSurveyElementTypeEnum.OpenText,
|
||||
TSurveyElementTypeEnum.NPS,
|
||||
TSurveyElementTypeEnum.Rating,
|
||||
TSurveyElementTypeEnum.MultipleChoiceSingle,
|
||||
TSurveyElementTypeEnum.MultipleChoiceMulti,
|
||||
TSurveyElementTypeEnum.PictureSelection,
|
||||
TSurveyElementTypeEnum.Ranking,
|
||||
TSurveyElementTypeEnum.Matrix,
|
||||
];
|
||||
|
||||
const supportedQuestions = survey.questions.filter((question) =>
|
||||
supportedQuestionTypes.includes(question.type)
|
||||
);
|
||||
// Extract elements from blocks
|
||||
const elements = getElementsFromBlocks(survey.blocks);
|
||||
const supportedElements = elements.filter((element) => supportedElementTypes.includes(element.type));
|
||||
|
||||
if (supportedQuestions.length === 0) {
|
||||
if (supportedElements.length === 0) {
|
||||
throw new OperationNotAllowedError(
|
||||
"Survey does not contain any supported question types (OpenText, NPS, or Rating)"
|
||||
"Survey does not contain any supported question types (OpenText, NPS, Rating, Multiple Choice, Picture Selection, Ranking, or Matrix)"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -340,16 +347,80 @@ export const generateTestResponsesAction = authenticatedActionClient
|
||||
const createdResponses: string[] = [];
|
||||
|
||||
for (let i = 0; i < responsesToCreate; i++) {
|
||||
const responseData: Record<string, string | number> = {};
|
||||
const responseData: Record<string, string | number | string[] | Record<string, string>> = {};
|
||||
|
||||
for (const question of supportedQuestions) {
|
||||
if (question.type === TSurveyQuestionTypeEnum.OpenText) {
|
||||
responseData[question.id] = generateLoremIpsum();
|
||||
} else if (question.type === TSurveyQuestionTypeEnum.NPS) {
|
||||
responseData[question.id] = Math.floor(Math.random() * 11);
|
||||
} else if (question.type === TSurveyQuestionTypeEnum.Rating) {
|
||||
const range = "range" in question && typeof question.range === "number" ? question.range : 5;
|
||||
responseData[question.id] = Math.floor(Math.random() * range) + 1;
|
||||
for (const element of supportedElements) {
|
||||
if (element.type === TSurveyElementTypeEnum.OpenText) {
|
||||
responseData[element.id] = generateLoremIpsum();
|
||||
} else if (element.type === TSurveyElementTypeEnum.NPS) {
|
||||
responseData[element.id] = Math.floor(Math.random() * 11);
|
||||
} else if (element.type === TSurveyElementTypeEnum.Rating) {
|
||||
const range = "range" in element && typeof element.range === "number" ? element.range : 5;
|
||||
responseData[element.id] = Math.floor(Math.random() * range) + 1;
|
||||
} else if (element.type === TSurveyElementTypeEnum.MultipleChoiceSingle) {
|
||||
// Single choice: pick one random option, store the label
|
||||
if ("choices" in element && Array.isArray(element.choices) && element.choices.length > 0) {
|
||||
const randomIndex = Math.floor(Math.random() * element.choices.length);
|
||||
const selectedChoice = element.choices[randomIndex];
|
||||
// For "other" option, generate custom text; otherwise use the choice label
|
||||
responseData[element.id] =
|
||||
selectedChoice.id === "other"
|
||||
? generateLoremIpsum()
|
||||
: getLocalizedValue(selectedChoice.label, "default");
|
||||
}
|
||||
} else if (element.type === TSurveyElementTypeEnum.MultipleChoiceMulti) {
|
||||
// Multi choice: pick 1-3 random options, store the labels
|
||||
if ("choices" in element && Array.isArray(element.choices) && element.choices.length > 0) {
|
||||
const numSelections = Math.min(Math.floor(Math.random() * 3) + 1, element.choices.length);
|
||||
const shuffled = [...element.choices].sort(() => Math.random() - 0.5);
|
||||
responseData[element.id] = shuffled.slice(0, numSelections).map((choice) => {
|
||||
// For "other" option, generate custom text; otherwise use the choice label
|
||||
return choice.id === "other"
|
||||
? generateLoremIpsum()
|
||||
: getLocalizedValue(choice.label, "default");
|
||||
});
|
||||
}
|
||||
} else if (element.type === TSurveyElementTypeEnum.PictureSelection) {
|
||||
// Picture selection: single or multi based on allowMulti
|
||||
if ("choices" in element && Array.isArray(element.choices) && element.choices.length > 0) {
|
||||
const allowMulti = "allowMulti" in element ? element.allowMulti : false;
|
||||
if (allowMulti) {
|
||||
const numSelections = Math.min(Math.floor(Math.random() * 3) + 1, element.choices.length);
|
||||
const shuffled = [...element.choices].sort(() => Math.random() - 0.5);
|
||||
responseData[element.id] = shuffled.slice(0, numSelections).map((choice) => choice.id);
|
||||
} else {
|
||||
const randomIndex = Math.floor(Math.random() * element.choices.length);
|
||||
responseData[element.id] = element.choices[randomIndex].id;
|
||||
}
|
||||
}
|
||||
} else if (element.type === TSurveyElementTypeEnum.Ranking) {
|
||||
// Ranking: all options in random order, store the labels
|
||||
if ("choices" in element && Array.isArray(element.choices) && element.choices.length > 0) {
|
||||
const shuffled = [...element.choices].sort(() => Math.random() - 0.5);
|
||||
responseData[element.id] = shuffled.map((choice) => {
|
||||
// For "other" option, generate custom text; otherwise use the choice label
|
||||
return choice.id === "other"
|
||||
? generateLoremIpsum()
|
||||
: getLocalizedValue(choice.label, "default");
|
||||
});
|
||||
}
|
||||
} else if (element.type === TSurveyElementTypeEnum.Matrix) {
|
||||
// Matrix: for each row, pick a random column
|
||||
if (
|
||||
"rows" in element &&
|
||||
"columns" in element &&
|
||||
Array.isArray(element.rows) &&
|
||||
Array.isArray(element.columns) &&
|
||||
element.rows.length > 0 &&
|
||||
element.columns.length > 0
|
||||
) {
|
||||
const matrixData: Record<string, string> = {};
|
||||
for (const row of element.rows) {
|
||||
const randomColumnIndex = Math.floor(Math.random() * element.columns.length);
|
||||
matrixData[row.id] = element.columns[randomColumnIndex].id;
|
||||
}
|
||||
responseData[element.id] = matrixData;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user