aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/server/db/schema-crdt.test.ts
blob: 4860cb9c540f96a3f3abff58140c71ad03f9ab89 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import { getTableName } from "drizzle-orm";
import { describe, expect, it } from "vitest";
import {
	CrdtEntityType,
	type CrdtEntityTypeValue,
	crdtDocuments,
} from "./schema-crdt";

describe("CRDT Schema", () => {
	describe("CrdtEntityType", () => {
		it("should have all required entity types", () => {
			expect(CrdtEntityType.Deck).toBe("deck");
			expect(CrdtEntityType.NoteType).toBe("noteType");
			expect(CrdtEntityType.NoteFieldType).toBe("noteFieldType");
			expect(CrdtEntityType.Note).toBe("note");
			expect(CrdtEntityType.NoteFieldValue).toBe("noteFieldValue");
			expect(CrdtEntityType.Card).toBe("card");
			expect(CrdtEntityType.ReviewLog).toBe("reviewLog");
		});

		it("should be immutable (const assertion)", () => {
			// TypeScript const assertion ensures immutability at compile time
			// We verify the object structure matches expected values
			const entityTypes = Object.values(CrdtEntityType);
			expect(entityTypes).toHaveLength(7);
			expect(entityTypes).toContain("deck");
			expect(entityTypes).toContain("noteType");
			expect(entityTypes).toContain("noteFieldType");
			expect(entityTypes).toContain("note");
			expect(entityTypes).toContain("noteFieldValue");
			expect(entityTypes).toContain("card");
			expect(entityTypes).toContain("reviewLog");
		});
	});

	describe("CrdtEntityTypeValue type", () => {
		it("should accept valid entity type values", () => {
			// Type checking at compile time, runtime verification
			const validTypes: CrdtEntityTypeValue[] = [
				"deck",
				"noteType",
				"noteFieldType",
				"note",
				"noteFieldValue",
				"card",
				"reviewLog",
			];
			expect(validTypes).toHaveLength(7);
		});
	});

	describe("crdtDocuments table", () => {
		it("should have correct table name", () => {
			expect(getTableName(crdtDocuments)).toBe("crdt_documents");
		});

		it("should have required columns", () => {
			const columns = Object.keys(crdtDocuments);
			expect(columns).toContain("id");
			expect(columns).toContain("userId");
			expect(columns).toContain("entityType");
			expect(columns).toContain("entityId");
			expect(columns).toContain("binary");
			expect(columns).toContain("syncVersion");
			expect(columns).toContain("createdAt");
			expect(columns).toContain("updatedAt");
		});

		it("should have id as UUID primary key", () => {
			const idColumn = crdtDocuments.id;
			// Drizzle internally uses 'string' for UUID dataType
			expect(idColumn.dataType).toBe("string");
			expect(idColumn.primary).toBe(true);
			// Verify column name maps to correct DB column
			expect(idColumn.name).toBe("id");
		});

		it("should have userId as UUID with foreign key reference", () => {
			const userIdColumn = crdtDocuments.userId;
			expect(userIdColumn.dataType).toBe("string");
			expect(userIdColumn.notNull).toBe(true);
			expect(userIdColumn.name).toBe("user_id");
		});

		it("should have entityType as varchar", () => {
			const entityTypeColumn = crdtDocuments.entityType;
			expect(entityTypeColumn.dataType).toBe("string");
			expect(entityTypeColumn.notNull).toBe(true);
			expect(entityTypeColumn.name).toBe("entity_type");
		});

		it("should have entityId as UUID", () => {
			const entityIdColumn = crdtDocuments.entityId;
			expect(entityIdColumn.dataType).toBe("string");
			expect(entityIdColumn.notNull).toBe(true);
			expect(entityIdColumn.name).toBe("entity_id");
		});

		it("should have binary as varchar for base64 storage", () => {
			const binaryColumn = crdtDocuments.binary;
			expect(binaryColumn.dataType).toBe("string");
			expect(binaryColumn.notNull).toBe(true);
		});

		it("should have syncVersion as integer with default 0", () => {
			const syncVersionColumn = crdtDocuments.syncVersion;
			expect(syncVersionColumn.dataType).toBe("number");
			expect(syncVersionColumn.notNull).toBe(true);
			expect(syncVersionColumn.default).toBe(0);
		});

		it("should have createdAt as timestamp with timezone", () => {
			const createdAtColumn = crdtDocuments.createdAt;
			expect(createdAtColumn.dataType).toBe("date");
			expect(createdAtColumn.notNull).toBe(true);
			expect(createdAtColumn.name).toBe("created_at");
		});

		it("should have updatedAt as timestamp with timezone", () => {
			const updatedAtColumn = crdtDocuments.updatedAt;
			expect(updatedAtColumn.dataType).toBe("date");
			expect(updatedAtColumn.notNull).toBe(true);
			expect(updatedAtColumn.name).toBe("updated_at");
		});
	});
});