You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
138 lines
4.1 KiB
138 lines
4.1 KiB
import { cleanup, fireEvent, render, screen } from "@testing-library/react";
|
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
import type { QuestionField } from "@/lib/schema-adapter";
|
|
import { mapBackendQuestionToFrontend } from "@/lib/schema-adapter";
|
|
import { QuestionSlider } from "./question-slider";
|
|
|
|
let answerValue: any = null;
|
|
const setAnswerValueMock = vi.fn();
|
|
|
|
vi.mock("@/translations/provider", () => ({
|
|
useI18n: () => ({
|
|
locale: "en",
|
|
dictionary: { From: "From", To: "To" },
|
|
}),
|
|
}));
|
|
|
|
vi.mock("./question-answer-storage", () => ({
|
|
useQuestionAnswers: () => ({
|
|
getAnswerValue: () => answerValue,
|
|
setAnswerValue: setAnswerValueMock,
|
|
}),
|
|
}));
|
|
|
|
describe("QuestionSlider", () => {
|
|
beforeEach(() => {
|
|
answerValue = null;
|
|
setAnswerValueMock.mockClear();
|
|
});
|
|
|
|
afterEach(() => {
|
|
cleanup();
|
|
});
|
|
|
|
it("extracts range correctly from backend validation schema", () => {
|
|
const backendQuestion = {
|
|
id: "appearance_health_activity.height_in_centimeters",
|
|
title: "Height in Centimeters",
|
|
type: "scale",
|
|
order: 1,
|
|
required: true,
|
|
is_required: true,
|
|
show_guardian_notice: false,
|
|
validation: { min: 100, max: 230 },
|
|
ui_config: { placeholder_en: "175", private: true },
|
|
logic: null,
|
|
is_visible: true,
|
|
options: [],
|
|
description: "",
|
|
tooltip: "",
|
|
placeholder: "175",
|
|
};
|
|
|
|
const frontendQ = mapBackendQuestionToFrontend(backendQuestion as any, 0);
|
|
expect(frontendQ.extras.range).toEqual([100, 230]);
|
|
});
|
|
|
|
it("renders scale marks correctly across the range", () => {
|
|
const heightQuestion = {
|
|
id: "appearance_health_activity.height_in_centimeters",
|
|
title: "Height in Centimeters",
|
|
type: "scale",
|
|
order: 1,
|
|
required: true,
|
|
baseRequired: true,
|
|
isVisible: true,
|
|
description: "",
|
|
tooltip: "",
|
|
extras: { placeHolder: "175", range: [100, 230], options: [] },
|
|
options: [],
|
|
validation: { min: 100, max: 230 },
|
|
} as QuestionField;
|
|
|
|
answerValue = 178;
|
|
render(<QuestionSlider question={heightQuestion} />);
|
|
|
|
const slider = screen.getByRole("slider") as HTMLInputElement;
|
|
expect(slider.min).toBe("100");
|
|
expect(slider.max).toBe("230");
|
|
expect(slider.value).toBe("178");
|
|
|
|
// The value badge shows 178
|
|
expect(screen.getByText("178")).toBeDefined();
|
|
|
|
// Scale marks should be rendered with multiple ticks (100, 120, ..., 230)
|
|
expect(screen.getByText("100")).toBeDefined();
|
|
expect(screen.getByText("230")).toBeDefined();
|
|
expect(screen.queryByText("0")).toBeNull();
|
|
});
|
|
|
|
it("updates answer value when slider changes", () => {
|
|
const weightQuestion = {
|
|
id: "appearance_health_activity.weight_in_kilograms",
|
|
title: "Weight in Kilograms",
|
|
type: "scale",
|
|
order: 2,
|
|
required: true,
|
|
baseRequired: true,
|
|
isVisible: true,
|
|
description: "",
|
|
tooltip: "",
|
|
extras: { placeHolder: "70", range: [40, 180], options: [] },
|
|
options: [],
|
|
validation: { min: 40, max: 180 },
|
|
} as QuestionField;
|
|
|
|
render(<QuestionSlider question={weightQuestion} />);
|
|
|
|
const slider = screen.getByRole("slider");
|
|
fireEvent.change(slider, { target: { value: "85" } });
|
|
|
|
expect(setAnswerValueMock).toHaveBeenCalledWith(weightQuestion, 85);
|
|
});
|
|
|
|
it("falls back gracefully when range is not in extras but in validation", () => {
|
|
const customQuestion = {
|
|
id: "custom_scale",
|
|
title: "Satisfaction",
|
|
type: "scale",
|
|
order: 3,
|
|
required: true,
|
|
baseRequired: true,
|
|
isVisible: true,
|
|
description: "",
|
|
tooltip: "",
|
|
extras: { placeHolder: "5", range: [0, 0], options: [] },
|
|
options: [],
|
|
validation: { min: 1, max: 10 },
|
|
} as QuestionField;
|
|
|
|
render(<QuestionSlider question={customQuestion} />);
|
|
|
|
const slider = screen.getByRole("slider") as HTMLInputElement;
|
|
expect(slider.min).toBe("1");
|
|
expect(slider.max).toBe("10");
|
|
expect(screen.getByText("1")).toBeDefined();
|
|
expect(screen.getByText("10")).toBeDefined();
|
|
});
|
|
});
|