learn and share notes on atproto (wip) 馃
malfestio.stormlightlabs.org/
readability
solid
axum
atproto
srs
1import { render } from "@solidjs/testing-library";
2import { describe, expect, it, vi } from "vitest";
3
4vi.mock("$lib/api", () => ({ api: { updatePreferences: vi.fn().mockResolvedValue({ ok: true }) } }));
5
6vi.mock(
7 "$lib/store",
8 () => ({ prefStore: { prefs: vi.fn(() => ({ tutorial_deck_completed: false })), fetchPrefs: vi.fn() } }),
9);
10
11import { DECK_CREATION_STEPS, TutorialProvider, useTutorial } from "../TutorialProvider";
12
13describe("DECK_CREATION_STEPS", () => {
14 it("has predefined deck creation steps", () => {
15 expect(DECK_CREATION_STEPS.length).toBeGreaterThan(0);
16 expect(DECK_CREATION_STEPS[0]).toHaveProperty("id");
17 expect(DECK_CREATION_STEPS[0]).toHaveProperty("title");
18 expect(DECK_CREATION_STEPS[0]).toHaveProperty("desc");
19 });
20});
21
22describe("useTutorial", () => {
23 it("throws error when used outside provider", () => {
24 expect(() => {
25 const TestComponent = () => {
26 useTutorial();
27 return null;
28 };
29 render(() => <TestComponent />);
30 }).toThrow("useTutorial must be used within a TutorialProvider");
31 });
32});
33
34describe("TutorialProvider", () => {
35 it("provides tutorial context to children", () => {
36 let tutorial: ReturnType<typeof useTutorial> | undefined;
37
38 const Consumer = () => {
39 tutorial = useTutorial();
40 return null;
41 };
42
43 render(() => (
44 <TutorialProvider>
45 <Consumer />
46 </TutorialProvider>
47 ));
48
49 expect(tutorial).toBeDefined();
50 expect(tutorial!.active()).toBe(false);
51 expect(tutorial!.currentStepIndex()).toBe(0);
52 });
53
54 it("starts tutorial when startTutorial is called", () => {
55 let tutorial: ReturnType<typeof useTutorial> | undefined;
56
57 const Consumer = () => {
58 tutorial = useTutorial();
59 return null;
60 };
61
62 render(() => (
63 <TutorialProvider>
64 <Consumer />
65 </TutorialProvider>
66 ));
67
68 tutorial!.startTutorial();
69 expect(tutorial!.active()).toBe(true);
70 expect(tutorial!.currentStepIndex()).toBe(0);
71 });
72
73 it("advances to next step", () => {
74 let tutorial: ReturnType<typeof useTutorial> | undefined;
75
76 const Consumer = () => {
77 tutorial = useTutorial();
78 return null;
79 };
80
81 render(() => (
82 <TutorialProvider>
83 <Consumer />
84 </TutorialProvider>
85 ));
86
87 tutorial!.startTutorial();
88 tutorial!.nextStep();
89 expect(tutorial!.currentStepIndex()).toBe(1);
90 });
91
92 it("goes back to previous step", () => {
93 let tutorial: ReturnType<typeof useTutorial> | undefined;
94
95 const Consumer = () => {
96 tutorial = useTutorial();
97 return null;
98 };
99
100 render(() => (
101 <TutorialProvider>
102 <Consumer />
103 </TutorialProvider>
104 ));
105
106 tutorial!.startTutorial();
107 tutorial!.nextStep();
108 tutorial!.nextStep();
109 tutorial!.prevStep();
110 expect(tutorial!.currentStepIndex()).toBe(1);
111 });
112
113 it("does not go below step 0", () => {
114 let tutorial: ReturnType<typeof useTutorial> | undefined;
115
116 const Consumer = () => {
117 tutorial = useTutorial();
118 return null;
119 };
120
121 render(() => (
122 <TutorialProvider>
123 <Consumer />
124 </TutorialProvider>
125 ));
126
127 tutorial!.startTutorial();
128 tutorial!.prevStep();
129 expect(tutorial!.currentStepIndex()).toBe(0);
130 });
131
132 it("calculates progress correctly", () => {
133 let tutorial: ReturnType<typeof useTutorial> | undefined;
134
135 const Consumer = () => {
136 tutorial = useTutorial();
137 return null;
138 };
139
140 render(() => (
141 <TutorialProvider>
142 <Consumer />
143 </TutorialProvider>
144 ));
145
146 tutorial!.startTutorial();
147 const stepCount = tutorial!.steps().length;
148 expect(tutorial!.progress()).toBe((1 / stepCount) * 100);
149
150 tutorial!.nextStep();
151 expect(tutorial!.progress()).toBe((2 / stepCount) * 100);
152 });
153
154 it("registers and unregisters targets", () => {
155 let tutorial: ReturnType<typeof useTutorial> | undefined;
156 const mockElement = document.createElement("div");
157
158 const Consumer = () => {
159 tutorial = useTutorial();
160 return null;
161 };
162
163 render(() => (
164 <TutorialProvider>
165 <Consumer />
166 </TutorialProvider>
167 ));
168
169 tutorial!.registerTarget("test", mockElement);
170 expect(tutorial!.targets().get("test")).toBe(mockElement);
171
172 tutorial!.unregisterTarget("test");
173 expect(tutorial!.targets().has("test")).toBe(false);
174 });
175});