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 { parseAtUri } from "../at-uri.js";
3
4describe("parseAtUri", () => {
5 describe("valid URIs", () => {
6 it("parses a standard post URI", () => {
7 const result = parseAtUri(
8 "at://did:plc:abc123/space.atbb.post/3lbk7xxx"
9 );
10
11 expect(result).toEqual({
12 did: "did:plc:abc123",
13 collection: "space.atbb.post",
14 rkey: "3lbk7xxx",
15 });
16 });
17
18 it("parses a forum URI with 'self' rkey", () => {
19 const result = parseAtUri(
20 "at://did:plc:forum/space.atbb.forum.forum/self"
21 );
22
23 expect(result).toEqual({
24 did: "did:plc:forum",
25 collection: "space.atbb.forum.forum",
26 rkey: "self",
27 });
28 });
29
30 it("parses a category URI", () => {
31 const result = parseAtUri(
32 "at://did:plc:forum/space.atbb.forum.category/cat1"
33 );
34
35 expect(result).toEqual({
36 did: "did:plc:forum",
37 collection: "space.atbb.forum.category",
38 rkey: "cat1",
39 });
40 });
41
42 it("parses a membership URI", () => {
43 const result = parseAtUri(
44 "at://did:plc:user123/space.atbb.membership/mem1"
45 );
46
47 expect(result).toEqual({
48 did: "did:plc:user123",
49 collection: "space.atbb.membership",
50 rkey: "mem1",
51 });
52 });
53
54 it("parses a did:web DID", () => {
55 const result = parseAtUri(
56 "at://did:web:example.com/space.atbb.post/abc"
57 );
58
59 expect(result).toEqual({
60 did: "did:web:example.com",
61 collection: "space.atbb.post",
62 rkey: "abc",
63 });
64 });
65
66 it("parses a Bluesky post URI", () => {
67 const result = parseAtUri(
68 "at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.post/3lbk7abc"
69 );
70
71 expect(result).toEqual({
72 did: "did:plc:z72i7hdynmk6r22z27h6tvur",
73 collection: "app.bsky.feed.post",
74 rkey: "3lbk7abc",
75 });
76 });
77
78 it("handles rkey with special characters", () => {
79 const result = parseAtUri(
80 "at://did:plc:abc/space.atbb.post/rkey-with.dots_and-dashes"
81 );
82
83 expect(result).toEqual({
84 did: "did:plc:abc",
85 collection: "space.atbb.post",
86 rkey: "rkey-with.dots_and-dashes",
87 });
88 });
89 });
90
91 describe("invalid URIs", () => {
92 it("returns null for empty string", () => {
93 expect(parseAtUri("")).toBeNull();
94 });
95
96 it("returns null for a plain string", () => {
97 expect(parseAtUri("not-a-uri")).toBeNull();
98 });
99
100 it("returns null for an HTTP URL", () => {
101 expect(parseAtUri("https://example.com/path")).toBeNull();
102 });
103
104 it("returns null for a URI missing the rkey", () => {
105 expect(
106 parseAtUri("at://did:plc:abc/space.atbb.post")
107 ).toBeNull();
108 });
109
110 it("returns null for a URI missing collection and rkey", () => {
111 expect(parseAtUri("at://did:plc:abc")).toBeNull();
112 });
113
114 it("returns null for a URI with only the scheme", () => {
115 expect(parseAtUri("at://")).toBeNull();
116 });
117
118 it("returns null for a URI with wrong scheme", () => {
119 expect(
120 parseAtUri("http://did:plc:abc/space.atbb.post/rkey")
121 ).toBeNull();
122 });
123 });
124
125 describe("edge cases", () => {
126 it("returns all three components as strings", () => {
127 const result = parseAtUri(
128 "at://did:plc:test/space.atbb.post/abc123"
129 );
130
131 expect(result).not.toBeNull();
132 expect(typeof result!.did).toBe("string");
133 expect(typeof result!.collection).toBe("string");
134 expect(typeof result!.rkey).toBe("string");
135 });
136
137 it("does not match URIs with trailing slash", () => {
138 // The regex uses (.+)$ for rkey, so trailing slash is included in rkey
139 const result = parseAtUri(
140 "at://did:plc:abc/space.atbb.post/rkey/"
141 );
142
143 // rkey would be "rkey/" which includes the trailing slash
144 expect(result).toEqual({
145 did: "did:plc:abc",
146 collection: "space.atbb.post",
147 rkey: "rkey/",
148 });
149 });
150
151 it("does not match a URI with empty path segments", () => {
152 expect(parseAtUri("at:////")).toBeNull();
153 });
154
155 it("handles numeric rkey (TID format)", () => {
156 const result = parseAtUri(
157 "at://did:plc:abc/space.atbb.post/3lbk7xyzhij2q"
158 );
159
160 expect(result).toEqual({
161 did: "did:plc:abc",
162 collection: "space.atbb.post",
163 rkey: "3lbk7xyzhij2q",
164 });
165 });
166 });
167});