learn and share notes on atproto (wip) 馃 malfestio.stormlightlabs.org/
readability solid axum atproto srs
at main 95 lines 3.1 kB view raw
1import "fake-indexeddb/auto"; 2import { api } from "$lib/api"; 3import type { Note } from "$lib/model"; 4import { MemoryRouter, Route } from "@solidjs/router"; 5import { cleanup, render, screen, waitFor } from "@solidjs/testing-library"; 6import { afterEach, describe, expect, it, type Mock, vi } from "vitest"; 7import Notes from "../Notes"; 8 9vi.mock("$lib/api", () => ({ api: { getNotes: vi.fn() } })); 10vi.mock("$lib/store", () => ({ authStore: { user: vi.fn(() => ({ did: "did:plc:test" })) } })); 11vi.mock("$lib/sync-store", () => ({ syncStore: { getLocalNotes: vi.fn().mockResolvedValue([]) } })); 12vi.mock("$lib/density-context", () => ({ useDensity: vi.fn(() => "comfortable") })); 13 14const mockNotes: Note[] = [{ 15 id: "note-1", 16 owner_did: "did:plc:test123", 17 title: "First Note", 18 body: "Content of first note", 19 tags: ["rust"], 20 visibility: { type: "Private" }, 21 created_at: "2026-01-01T10:00:00Z", 22 updated_at: "2026-01-01T12:00:00Z", 23}, { 24 id: "note-2", 25 owner_did: "did:plc:test123", 26 title: "Second Note", 27 body: "Content of second note", 28 tags: ["learning"], 29 visibility: { type: "Public" }, 30 created_at: "2026-01-01T11:00:00Z", 31 updated_at: "2026-01-01T13:00:00Z", 32}]; 33 34describe("Notes page", () => { 35 afterEach(() => { 36 cleanup(); 37 vi.clearAllMocks(); 38 }); 39 40 it("renders page header", async () => { 41 (api.getNotes as Mock).mockResolvedValue({ ok: true, json: async () => mockNotes }); 42 render(() => ( 43 <MemoryRouter> 44 <Route path="/" component={Notes} /> 45 </MemoryRouter> 46 )); 47 expect(screen.getByRole("heading", { name: "Notes" })).toBeInTheDocument(); 48 expect(screen.getByText("Your personal knowledge base")).toBeInTheDocument(); 49 }); 50 51 it("renders notes from API", async () => { 52 (api.getNotes as Mock).mockResolvedValue({ ok: true, json: async () => mockNotes }); 53 render(() => ( 54 <MemoryRouter> 55 <Route path="/" component={Notes} /> 56 </MemoryRouter> 57 )); 58 await waitFor(() => { 59 expect(screen.getByText("First Note")).toBeInTheDocument(); 60 expect(screen.getByText("Second Note")).toBeInTheDocument(); 61 }); 62 }); 63 64 it("shows empty state when no notes", async () => { 65 (api.getNotes as Mock).mockResolvedValue({ ok: true, json: async () => [] }); 66 render(() => ( 67 <MemoryRouter> 68 <Route path="/" component={Notes} /> 69 </MemoryRouter> 70 )); 71 await waitFor(() => { 72 expect(screen.getByText("No notes yet")).toBeInTheDocument(); 73 }); 74 }); 75 76 it("has New Note button", () => { 77 (api.getNotes as Mock).mockResolvedValue({ ok: true, json: async () => [] }); 78 render(() => ( 79 <MemoryRouter> 80 <Route path="/" component={Notes} /> 81 </MemoryRouter> 82 )); 83 expect(screen.getByRole("link", { name: /new note/i })).toBeInTheDocument(); 84 }); 85 86 it("has search input", () => { 87 (api.getNotes as Mock).mockResolvedValue({ ok: true, json: async () => [] }); 88 render(() => ( 89 <MemoryRouter> 90 <Route path="/" component={Notes} /> 91 </MemoryRouter> 92 )); 93 expect(screen.getByPlaceholderText("Search notes...")).toBeInTheDocument(); 94 }); 95});