BlueSky & more on desktop
lazurite.stormlightlabs.org/
tauri
rust
typescript
bluesky
appview
atproto
solid
1import { createRoot } from "solid-js";
2import { beforeEach, describe, expect, it, vi } from "vitest";
3import { useThreadOverlayNavigation } from "../hooks/useThreadOverlayNavigation";
4
5const navigateMock = vi.hoisted(() => vi.fn());
6const locationState = vi.hoisted(() => ({ pathname: "/timeline", search: "" }));
7
8vi.mock("@solidjs/router", () => ({ useLocation: () => locationState, useNavigate: () => navigateMock }));
9
10describe("useThreadOverlayNavigation", () => {
11 beforeEach(() => {
12 navigateMock.mockReset();
13 locationState.pathname = "/timeline";
14 locationState.search = "";
15 });
16
17 it("opens threads in drawer mode on eligible routes", () => {
18 createRoot((dispose) => {
19 const overlay = useThreadOverlayNavigation();
20 void overlay.openThread("at://did:plc:alice/app.bsky.feed.post/1");
21 dispose();
22 });
23
24 expect(navigateMock).toHaveBeenCalledWith("/timeline?thread=at%3A%2F%2Fdid%3Aplc%3Aalice%2Fapp.bsky.feed.post%2F1");
25 });
26
27 it("opens threads on the dedicated post route for ineligible paths", () => {
28 locationState.pathname = "/search";
29 locationState.search = "?q=test";
30
31 createRoot((dispose) => {
32 const overlay = useThreadOverlayNavigation();
33 void overlay.openThread("at://did:plc:alice/app.bsky.feed.post/2");
34 dispose();
35 });
36
37 expect(navigateMock).toHaveBeenCalledWith("/post/at%3A%2F%2Fdid%3Aplc%3Aalice%2Fapp.bsky.feed.post%2F2");
38 });
39
40 it("closes drawer mode by removing only the thread query param", () => {
41 locationState.pathname = "/notifications";
42 locationState.search = "?foo=bar&thread=at%3A%2F%2Fdid%3Aplc%3Aalice%2Fapp.bsky.feed.post%2F3";
43
44 createRoot((dispose) => {
45 const overlay = useThreadOverlayNavigation();
46 void overlay.closeThread();
47 dispose();
48 });
49
50 expect(navigateMock).toHaveBeenCalledWith("/notifications?foo=bar");
51 });
52});