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

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();
});
});