learn and share notes on atproto (wip) 馃 malfestio.stormlightlabs.org/
readability solid axum atproto srs
at main 114 lines 4.1 kB view raw
1import type { Note } from "$lib/model"; 2import { cleanup, fireEvent, render, screen } from "@solidjs/testing-library"; 3import type { JSX } from "solid-js"; 4import { afterEach, describe, expect, it, vi } from "vitest"; 5import { NotesSidebar } from "../NotesSidebar"; 6 7vi.mock( 8 "@solidjs/router", 9 () => ({ 10 A: (props: { href: string; class: string; children: JSX.Element; "data-testid"?: string }) => ( 11 <a href={props.href} class={props.class} data-testid={props["data-testid"]}>{props.children}</a> 12 ), 13 }), 14); 15 16const mockNotes: Note[] = [{ 17 id: "note-1", 18 owner_did: "did:plc:test", 19 title: "First Note", 20 body: "Content with [[Second Note]] link", 21 tags: ["rust", "learning"], 22 visibility: { type: "Private" }, 23 created_at: "2026-01-01T00:00:00Z", 24 updated_at: "2026-01-03T00:00:00Z", 25}, { 26 id: "note-2", 27 owner_did: "did:plc:test", 28 title: "Second Note", 29 body: "This links to [[First Note]]", 30 tags: ["rust", "advanced"], 31 visibility: { type: "Private" }, 32 created_at: "2026-01-01T00:00:00Z", 33 updated_at: "2026-01-02T00:00:00Z", 34}, { 35 id: "note-3", 36 owner_did: "did:plc:test", 37 title: "Orphan Note", 38 body: "No wikilinks here", 39 tags: ["learning"], 40 visibility: { type: "Private" }, 41 created_at: "2026-01-01T00:00:00Z", 42 updated_at: "2026-01-01T00:00:00Z", 43}]; 44 45describe("NotesSidebar", () => { 46 afterEach(cleanup); 47 48 it("renders the sidebar", () => { 49 render(() => <NotesSidebar notes={mockNotes} />); 50 expect(screen.getByTestId("notes-sidebar")).toBeInTheDocument(); 51 }); 52 53 it("displays filter buttons with counts", () => { 54 render(() => <NotesSidebar notes={mockNotes} />); 55 expect(screen.getByTestId("filter-all")).toHaveTextContent("All (3)"); 56 expect(screen.getByTestId("filter-linked")).toHaveTextContent("Linked (2)"); 57 expect(screen.getByTestId("filter-orphaned")).toHaveTextContent("Orphaned (1)"); 58 }); 59 60 it("displays unique tags with correct counts", () => { 61 render(() => <NotesSidebar notes={mockNotes} />); 62 63 expect(screen.getByTestId("tag-rust")).toHaveTextContent("#rust"); 64 expect(screen.getByTestId("tag-rust")).toHaveTextContent("2"); 65 66 expect(screen.getByTestId("tag-learning")).toHaveTextContent("#learning"); 67 expect(screen.getByTestId("tag-learning")).toHaveTextContent("2"); 68 69 expect(screen.getByTestId("tag-advanced")).toHaveTextContent("#advanced"); 70 expect(screen.getByTestId("tag-advanced")).toHaveTextContent("1"); 71 }); 72 73 it("displays recent notes sorted by update date", () => { 74 render(() => <NotesSidebar notes={mockNotes} />); 75 76 const recentLinks = screen.getAllByTestId(/^recent-/); 77 expect(recentLinks[0]).toHaveAttribute("href", "/notes/note-1"); 78 expect(recentLinks[1]).toHaveAttribute("href", "/notes/note-2"); 79 expect(recentLinks[2]).toHaveAttribute("href", "/notes/note-3"); 80 }); 81 82 it("calls onFilterSelect when filter clicked", async () => { 83 const onFilterSelect = vi.fn(); 84 render(() => <NotesSidebar notes={mockNotes} onFilterSelect={onFilterSelect} />); 85 86 await fireEvent.click(screen.getByTestId("filter-linked")); 87 expect(onFilterSelect).toHaveBeenCalledWith("linked"); 88 89 await fireEvent.click(screen.getByTestId("filter-orphaned")); 90 expect(onFilterSelect).toHaveBeenCalledWith("orphaned"); 91 }); 92 93 it("calls onTagSelect when tag clicked", async () => { 94 const onTagSelect = vi.fn(); 95 render(() => <NotesSidebar notes={mockNotes} onTagSelect={onTagSelect} />); 96 97 await fireEvent.click(screen.getByTestId("tag-rust")); 98 expect(onTagSelect).toHaveBeenCalledWith("rust"); 99 }); 100 101 it("toggles tag selection off when same tag clicked", async () => { 102 const onTagSelect = vi.fn(); 103 render(() => <NotesSidebar notes={mockNotes} selectedTag="rust" onTagSelect={onTagSelect} />); 104 105 await fireEvent.click(screen.getByTestId("tag-rust")); 106 expect(onTagSelect).toHaveBeenCalledWith(undefined); 107 }); 108 109 it("handles empty notes array", () => { 110 render(() => <NotesSidebar notes={[]} />); 111 expect(screen.getByTestId("notes-sidebar")).toBeInTheDocument(); 112 expect(screen.getByTestId("filter-all")).toHaveTextContent("All (0)"); 113 }); 114});