import { render } from "@solidjs/testing-library";
import { describe, expect, it, vi } from "vitest";
vi.mock("$lib/api", () => ({ api: { updatePreferences: vi.fn().mockResolvedValue({ ok: true }) } }));
vi.mock(
"$lib/store",
() => ({ prefStore: { prefs: vi.fn(() => ({ tutorial_deck_completed: false })), fetchPrefs: vi.fn() } }),
);
import { DECK_CREATION_STEPS, TutorialProvider, useTutorial } from "../TutorialProvider";
describe("DECK_CREATION_STEPS", () => {
it("has predefined deck creation steps", () => {
expect(DECK_CREATION_STEPS.length).toBeGreaterThan(0);
expect(DECK_CREATION_STEPS[0]).toHaveProperty("id");
expect(DECK_CREATION_STEPS[0]).toHaveProperty("title");
expect(DECK_CREATION_STEPS[0]).toHaveProperty("desc");
});
});
describe("useTutorial", () => {
it("throws error when used outside provider", () => {
expect(() => {
const TestComponent = () => {
useTutorial();
return null;
};
render(() => );
}).toThrow("useTutorial must be used within a TutorialProvider");
});
});
describe("TutorialProvider", () => {
it("provides tutorial context to children", () => {
let tutorial: ReturnType | undefined;
const Consumer = () => {
tutorial = useTutorial();
return null;
};
render(() => (
));
expect(tutorial).toBeDefined();
expect(tutorial!.active()).toBe(false);
expect(tutorial!.currentStepIndex()).toBe(0);
});
it("starts tutorial when startTutorial is called", () => {
let tutorial: ReturnType | undefined;
const Consumer = () => {
tutorial = useTutorial();
return null;
};
render(() => (
));
tutorial!.startTutorial();
expect(tutorial!.active()).toBe(true);
expect(tutorial!.currentStepIndex()).toBe(0);
});
it("advances to next step", () => {
let tutorial: ReturnType | undefined;
const Consumer = () => {
tutorial = useTutorial();
return null;
};
render(() => (
));
tutorial!.startTutorial();
tutorial!.nextStep();
expect(tutorial!.currentStepIndex()).toBe(1);
});
it("goes back to previous step", () => {
let tutorial: ReturnType | undefined;
const Consumer = () => {
tutorial = useTutorial();
return null;
};
render(() => (
));
tutorial!.startTutorial();
tutorial!.nextStep();
tutorial!.nextStep();
tutorial!.prevStep();
expect(tutorial!.currentStepIndex()).toBe(1);
});
it("does not go below step 0", () => {
let tutorial: ReturnType | undefined;
const Consumer = () => {
tutorial = useTutorial();
return null;
};
render(() => (
));
tutorial!.startTutorial();
tutorial!.prevStep();
expect(tutorial!.currentStepIndex()).toBe(0);
});
it("calculates progress correctly", () => {
let tutorial: ReturnType | undefined;
const Consumer = () => {
tutorial = useTutorial();
return null;
};
render(() => (
));
tutorial!.startTutorial();
const stepCount = tutorial!.steps().length;
expect(tutorial!.progress()).toBe((1 / stepCount) * 100);
tutorial!.nextStep();
expect(tutorial!.progress()).toBe((2 / stepCount) * 100);
});
it("registers and unregisters targets", () => {
let tutorial: ReturnType | undefined;
const mockElement = document.createElement("div");
const Consumer = () => {
tutorial = useTutorial();
return null;
};
render(() => (
));
tutorial!.registerTarget("test", mockElement);
expect(tutorial!.targets().get("test")).toBe(mockElement);
tutorial!.unregisterTarget("test");
expect(tutorial!.targets().has("test")).toBe(false);
});
});