at://Press
at main 197 lines 5.3 kB view raw
1import { describe, it, expect, beforeEach, afterEach } from "vitest"; 2 3// Use in-memory SQLite for tests 4process.env.DRAFTS_DB_PATH = ":memory:"; 5 6import { listDrafts, getDraft, saveDraft, deleteDraft, generateRkey, closeDb } from "../../src/lib/drafts"; 7 8describe("drafts", () => { 9 beforeEach(() => { 10 // Reset the DB connection so each test gets a fresh in-memory DB 11 closeDb(); 12 }); 13 14 afterEach(() => { 15 closeDb(); 16 }); 17 18 describe("generateRkey", () => { 19 it("generates valid rkeys matching RKEY_REGEX", () => { 20 const rkey = generateRkey(); 21 expect(rkey).toMatch(/^[a-zA-Z0-9._~-]{1,512}$/); 22 expect(rkey).toHaveLength(13); 23 }); 24 25 it("generates unique rkeys", () => { 26 const keys = new Set(Array.from({ length: 100 }, () => generateRkey())); 27 expect(keys.size).toBe(100); 28 }); 29 }); 30 31 describe("saveDraft / getDraft", () => { 32 it("saves and retrieves a draft", () => { 33 const rkey = saveDraft({ 34 title: "Test Draft", 35 content: "Some content", 36 }); 37 38 const draft = getDraft(rkey); 39 expect(draft).not.toBeNull(); 40 expect(draft!.title).toBe("Test Draft"); 41 expect(draft!.content).toBe("Some content"); 42 expect(draft!.visibility).toBe("author"); 43 expect(draft!.rkey).toBe(rkey); 44 }); 45 46 it("saves with explicit rkey", () => { 47 const rkey = saveDraft({ 48 rkey: "my-custom-rkey", 49 title: "Custom Key", 50 content: "Content", 51 }); 52 53 expect(rkey).toBe("my-custom-rkey"); 54 const draft = getDraft("my-custom-rkey"); 55 expect(draft!.title).toBe("Custom Key"); 56 }); 57 58 it("updates an existing draft via upsert", () => { 59 saveDraft({ 60 rkey: "update-test", 61 title: "Original Title", 62 content: "Original Content", 63 }); 64 65 saveDraft({ 66 rkey: "update-test", 67 title: "Updated Title", 68 content: "Updated Content", 69 }); 70 71 const draft = getDraft("update-test"); 72 expect(draft!.title).toBe("Updated Title"); 73 expect(draft!.content).toBe("Updated Content"); 74 }); 75 76 it("stores and retrieves blobs as JSON", () => { 77 const blobs = [ 78 { 79 $type: "blob" as const, 80 ref: { $link: "bafkreitest123" }, 81 mimeType: "image/png", 82 size: 12345, 83 }, 84 ]; 85 86 saveDraft({ 87 rkey: "blob-test", 88 title: "With Blob", 89 content: "Content", 90 blobs, 91 }); 92 93 const draft = getDraft("blob-test"); 94 expect(draft!.blobs).toHaveLength(1); 95 expect(draft!.blobs![0].ref.$link).toBe("bafkreitest123"); 96 expect(draft!.blobs![0].mimeType).toBe("image/png"); 97 }); 98 99 it("stores null blobs when none provided", () => { 100 saveDraft({ 101 rkey: "no-blob", 102 title: "No Blob", 103 content: "Content", 104 }); 105 106 const draft = getDraft("no-blob"); 107 expect(draft!.blobs).toBeUndefined(); 108 }); 109 110 it("preserves createdAt when provided", () => { 111 const date = "2025-06-01T12:00:00.000Z"; 112 saveDraft({ 113 rkey: "date-test", 114 title: "Dated", 115 content: "Content", 116 createdAt: date, 117 }); 118 119 const draft = getDraft("date-test"); 120 expect(draft!.createdAt).toBe(date); 121 }); 122 123 it("returns null for non-existent rkey", () => { 124 const draft = getDraft("nonexistent"); 125 expect(draft).toBeNull(); 126 }); 127 128 it("sets empty uri and cid on draft entries", () => { 129 saveDraft({ 130 rkey: "fields-test", 131 title: "Fields", 132 content: "Content", 133 }); 134 135 const draft = getDraft("fields-test"); 136 expect(draft!.uri).toBe(""); 137 expect(draft!.cid).toBe(""); 138 }); 139 }); 140 141 describe("listDrafts", () => { 142 it("returns drafts sorted newest first", () => { 143 saveDraft({ 144 rkey: "older", 145 title: "Older Draft", 146 content: "C", 147 createdAt: "2025-01-01T00:00:00Z", 148 }); 149 saveDraft({ 150 rkey: "newer", 151 title: "Newer Draft", 152 content: "C", 153 createdAt: "2025-06-01T00:00:00Z", 154 }); 155 156 const drafts = listDrafts(); 157 expect(drafts).toHaveLength(2); 158 expect(drafts[0].title).toBe("Newer Draft"); 159 expect(drafts[1].title).toBe("Older Draft"); 160 }); 161 162 it("returns empty array when no drafts exist", () => { 163 const drafts = listDrafts(); 164 expect(drafts).toEqual([]); 165 }); 166 }); 167 168 describe("deleteDraft", () => { 169 it("deletes an existing draft", () => { 170 saveDraft({ 171 rkey: "to-delete", 172 title: "Delete Me", 173 content: "Content", 174 }); 175 176 expect(getDraft("to-delete")).not.toBeNull(); 177 const result = deleteDraft("to-delete"); 178 expect(result).toBe(true); 179 expect(getDraft("to-delete")).toBeNull(); 180 }); 181 182 it("returns false when draft does not exist", () => { 183 const result = deleteDraft("nonexistent"); 184 expect(result).toBe(false); 185 }); 186 187 it("removes draft from list", () => { 188 saveDraft({ rkey: "keep", title: "Keep", content: "C" }); 189 saveDraft({ rkey: "remove", title: "Remove", content: "C" }); 190 191 deleteDraft("remove"); 192 const drafts = listDrafts(); 193 expect(drafts).toHaveLength(1); 194 expect(drafts[0].rkey).toBe("keep"); 195 }); 196 }); 197});