WIP! A BB-style forum, on the ATmosphere!
We're still working... we'll be back soon when we have something to show off!
node
typescript
hono
htmx
atproto
1import { describe, it, expect } from "vitest";
2import { getTableName, getTableColumns } from "drizzle-orm";
3import {
4 forums,
5 categories,
6 users,
7 memberships,
8 posts,
9 modActions,
10} from "../schema.js";
11
12describe("database schema", () => {
13 describe("forums table", () => {
14 it("has the correct table name", () => {
15 expect(getTableName(forums)).toBe("forums");
16 });
17
18 it("has expected columns", () => {
19 const cols = getTableColumns(forums);
20 expect(cols).toHaveProperty("id");
21 expect(cols).toHaveProperty("did");
22 expect(cols).toHaveProperty("rkey");
23 expect(cols).toHaveProperty("cid");
24 expect(cols).toHaveProperty("name");
25 expect(cols).toHaveProperty("description");
26 expect(cols).toHaveProperty("indexedAt");
27 });
28
29 it("has did and rkey as not-null", () => {
30 const cols = getTableColumns(forums);
31 expect(cols.did.notNull).toBe(true);
32 expect(cols.rkey.notNull).toBe(true);
33 });
34 });
35
36 describe("categories table", () => {
37 it("has the correct table name", () => {
38 expect(getTableName(categories)).toBe("categories");
39 });
40
41 it("has expected columns", () => {
42 const cols = getTableColumns(categories);
43 expect(cols).toHaveProperty("id");
44 expect(cols).toHaveProperty("did");
45 expect(cols).toHaveProperty("rkey");
46 expect(cols).toHaveProperty("cid");
47 expect(cols).toHaveProperty("name");
48 expect(cols).toHaveProperty("description");
49 expect(cols).toHaveProperty("slug");
50 expect(cols).toHaveProperty("sortOrder");
51 expect(cols).toHaveProperty("forumId");
52 expect(cols).toHaveProperty("createdAt");
53 expect(cols).toHaveProperty("indexedAt");
54 });
55 });
56
57 describe("users table", () => {
58 it("has the correct table name", () => {
59 expect(getTableName(users)).toBe("users");
60 });
61
62 it("uses did as primary key", () => {
63 const cols = getTableColumns(users);
64 expect(cols.did.primary).toBe(true);
65 });
66
67 it("has handle as optional", () => {
68 const cols = getTableColumns(users);
69 expect(cols.handle.notNull).toBe(false);
70 });
71 });
72
73 describe("memberships table", () => {
74 it("has the correct table name", () => {
75 expect(getTableName(memberships)).toBe("memberships");
76 });
77
78 it("has expected columns", () => {
79 const cols = getTableColumns(memberships);
80 expect(cols).toHaveProperty("id");
81 expect(cols).toHaveProperty("did");
82 expect(cols).toHaveProperty("rkey");
83 expect(cols).toHaveProperty("cid");
84 expect(cols).toHaveProperty("forumId");
85 expect(cols).toHaveProperty("forumUri");
86 expect(cols).toHaveProperty("role");
87 expect(cols).toHaveProperty("roleUri");
88 expect(cols).toHaveProperty("joinedAt");
89 expect(cols).toHaveProperty("createdAt");
90 expect(cols).toHaveProperty("indexedAt");
91 });
92
93 it("has did and forumUri as not-null", () => {
94 const cols = getTableColumns(memberships);
95 expect(cols.did.notNull).toBe(true);
96 expect(cols.forumUri.notNull).toBe(true);
97 });
98 });
99
100 describe("posts table", () => {
101 it("has the correct table name", () => {
102 expect(getTableName(posts)).toBe("posts");
103 });
104
105 it("has expected columns for the unified post model", () => {
106 const cols = getTableColumns(posts);
107 expect(cols).toHaveProperty("id");
108 expect(cols).toHaveProperty("did");
109 expect(cols).toHaveProperty("rkey");
110 expect(cols).toHaveProperty("cid");
111 expect(cols).toHaveProperty("text");
112 expect(cols).toHaveProperty("forumUri");
113 expect(cols).toHaveProperty("rootPostId");
114 expect(cols).toHaveProperty("parentPostId");
115 expect(cols).toHaveProperty("rootUri");
116 expect(cols).toHaveProperty("parentUri");
117 expect(cols).toHaveProperty("createdAt");
118 expect(cols).toHaveProperty("indexedAt");
119 expect(cols).toHaveProperty("bannedByMod");
120 expect(cols).toHaveProperty("deletedByUser");
121 });
122
123 it("has text as not-null", () => {
124 const cols = getTableColumns(posts);
125 expect(cols.text.notNull).toBe(true);
126 });
127
128 it("has bannedByMod defaulting to false", () => {
129 const cols = getTableColumns(posts);
130 expect(cols.bannedByMod.notNull).toBe(true);
131 expect(cols.bannedByMod.hasDefault).toBe(true);
132 });
133
134 it("has deletedByUser defaulting to false", () => {
135 const cols = getTableColumns(posts);
136 expect(cols.deletedByUser.notNull).toBe(true);
137 expect(cols.deletedByUser.hasDefault).toBe(true);
138 });
139
140 it("has rootPostId and parentPostId as nullable (topics have no parent)", () => {
141 const cols = getTableColumns(posts);
142 expect(cols.rootPostId.notNull).toBe(false);
143 expect(cols.parentPostId.notNull).toBe(false);
144 });
145 });
146
147 describe("modActions table", () => {
148 it("has the correct table name", () => {
149 expect(getTableName(modActions)).toBe("mod_actions");
150 });
151
152 it("has expected columns", () => {
153 const cols = getTableColumns(modActions);
154 expect(cols).toHaveProperty("id");
155 expect(cols).toHaveProperty("did");
156 expect(cols).toHaveProperty("rkey");
157 expect(cols).toHaveProperty("cid");
158 expect(cols).toHaveProperty("action");
159 expect(cols).toHaveProperty("subjectDid");
160 expect(cols).toHaveProperty("subjectPostUri");
161 expect(cols).toHaveProperty("forumId");
162 expect(cols).toHaveProperty("reason");
163 expect(cols).toHaveProperty("createdBy");
164 expect(cols).toHaveProperty("expiresAt");
165 expect(cols).toHaveProperty("createdAt");
166 expect(cols).toHaveProperty("indexedAt");
167 });
168
169 it("has action and createdBy as not-null", () => {
170 const cols = getTableColumns(modActions);
171 expect(cols.action.notNull).toBe(true);
172 expect(cols.createdBy.notNull).toBe(true);
173 });
174 });
175
176 describe("all tables export correctly", () => {
177 it("exports six tables", () => {
178 const tables = [forums, categories, users, memberships, posts, modActions];
179 expect(tables).toHaveLength(6);
180 tables.forEach((table) => {
181 expect(table).toBeDefined();
182 });
183 });
184 });
185});