Highly ambitious ATProtocol AppView service and sdks
at fix-postgres 176 lines 6.1 kB view raw
1import { assertEquals, assertExists } from "jsr:@std/assert"; 2import { 3 normalizeLexicons, 4 nsidToPascalCase, 5 nsidToNamespace, 6 defNameToPascalCase, 7 capitalizeFirst, 8 sanitizeIdentifier, 9 isPropertyRequired, 10 isFieldSortable, 11 createProject, 12 generateUsageExample, 13 generateHeaderComment, 14 type Lexicon, 15 type LexiconRecord, 16} from "../src/mod.ts"; 17 18Deno.test("normalizeLexicons - handles both id and nsid properties", () => { 19 const input = [ 20 { id: "app.bsky.actor.profile", definitions: {} }, 21 { nsid: "com.example.post", defs: {} }, 22 { id: "network.slices.slice", definitions: {} }, 23 ]; 24 25 const result = normalizeLexicons(input); 26 27 assertEquals(result[0].id, "app.bsky.actor.profile"); 28 assertEquals(result[1].id, "com.example.post"); 29 assertEquals(result[1].definitions, {}); 30 assertEquals(result[2].id, "network.slices.slice"); 31}); 32 33Deno.test("nsidToPascalCase - converts NSID to PascalCase", () => { 34 assertEquals(nsidToPascalCase("app.bsky.actor.profile"), "AppBskyActorProfile"); 35 assertEquals(nsidToPascalCase("com.example.my-post"), "ComExampleMyPost"); 36 assertEquals(nsidToPascalCase("network.slices.slice"), "NetworkSlicesSlice"); 37}); 38 39Deno.test("nsidToNamespace - converts NSID to namespace format", () => { 40 assertEquals(nsidToNamespace("app.bsky.embed.defs"), "AppBskyEmbedDefs"); 41 assertEquals(nsidToNamespace("com.example.test-case"), "ComExampleTestCase"); 42}); 43 44Deno.test("defNameToPascalCase - converts definition names", () => { 45 assertEquals(defNameToPascalCase("aspectRatio"), "AspectRatio"); 46 assertEquals(defNameToPascalCase("my-property"), "MyProperty"); 47 assertEquals(defNameToPascalCase("test_case"), "TestCase"); 48}); 49 50Deno.test("capitalizeFirst - capitalizes first letter", () => { 51 assertEquals(capitalizeFirst("hello"), "Hello"); 52 assertEquals(capitalizeFirst("world"), "World"); 53 assertEquals(capitalizeFirst(""), ""); 54}); 55 56Deno.test("sanitizeIdentifier - converts hyphens to camelCase", () => { 57 assertEquals(sanitizeIdentifier("cyber-meteor-1637"), "cyberMeteor1637"); 58 assertEquals(sanitizeIdentifier("test-name"), "testName"); 59 assertEquals(sanitizeIdentifier("already-camel-case"), "alreadyCamelCase"); 60 assertEquals(sanitizeIdentifier("single"), "single"); 61 assertEquals(sanitizeIdentifier("with_underscore"), "withUnderscore"); 62 assertEquals(sanitizeIdentifier("mixed-name_test"), "mixedNameTest"); 63}); 64 65Deno.test("isPropertyRequired - checks if property is required", () => { 66 const record: LexiconRecord = { 67 type: "record", 68 required: ["name", "email"], 69 properties: { 70 name: { type: "string" }, 71 email: { type: "string" }, 72 age: { type: "integer" }, 73 }, 74 }; 75 76 assertEquals(isPropertyRequired(record, "name"), true); 77 assertEquals(isPropertyRequired(record, "email"), true); 78 assertEquals(isPropertyRequired(record, "age"), false); 79}); 80 81Deno.test("isFieldSortable - identifies sortable field types", () => { 82 assertEquals(isFieldSortable({ type: "string" }), true); 83 assertEquals(isFieldSortable({ type: "integer" }), true); 84 assertEquals(isFieldSortable({ type: "number" }), true); 85 assertEquals(isFieldSortable({ type: "datetime" }), true); 86 assertEquals(isFieldSortable({ type: "string", format: "datetime" }), true); 87 assertEquals(isFieldSortable({ type: "string", format: "at-identifier" }), true); 88 assertEquals(isFieldSortable({ type: "string", format: "at-uri" }), true); 89 90 assertEquals(isFieldSortable({ type: "array" }), false); 91 assertEquals(isFieldSortable({ type: "object" }), false); 92 assertEquals(isFieldSortable({ type: "blob" }), false); 93}); 94 95Deno.test("createProject - creates ts-morph project", () => { 96 const project = createProject(); 97 assertExists(project); 98 assertEquals(typeof project.createSourceFile, "function"); 99}); 100 101Deno.test("generateUsageExample - creates usage documentation", () => { 102 const lexicons: Lexicon[] = [ 103 { 104 id: "com.example.post", 105 definitions: { 106 main: { 107 type: "record", 108 record: { 109 type: "record", 110 properties: { 111 text: { type: "string" }, 112 }, 113 }, 114 }, 115 }, 116 }, 117 ]; 118 119 const result = generateUsageExample(lexicons, "at://test/slice"); 120 121 assertEquals(typeof result, "string"); 122 assertEquals(result.includes("com.example.post"), true); 123 assertEquals(result.includes("at://test/slice"), true); 124 assertEquals(result.includes("client.com.example.post.getRecords()"), true); 125}); 126 127Deno.test("generateUsageExample - handles network.slices lexicons", () => { 128 const lexicons: Lexicon[] = [ 129 { 130 id: "network.slices.slice", 131 definitions: { 132 main: { 133 type: "record", 134 record: { 135 type: "record", 136 properties: { 137 name: { type: "string" }, 138 }, 139 }, 140 }, 141 }, 142 }, 143 ]; 144 145 const result = generateUsageExample(lexicons, "at://test/slice"); 146 147 assertEquals(typeof result, "string"); 148 // Should fallback to using network.slices lexicons when no other record types exist 149 assertEquals(result.includes("network.slices.slice"), true); 150}); 151 152Deno.test("generateHeaderComment - creates header with imports", () => { 153 const lexicons: Lexicon[] = [ 154 { id: "test.lexicon", definitions: {} }, 155 ]; 156 157 const usageExample = "/** Example usage */"; 158 const result = generateHeaderComment(lexicons, usageExample); 159 160 assertEquals(typeof result, "string"); 161 assertEquals(result.includes("Generated TypeScript client"), true); 162 assertEquals(result.includes("Lexicons: 1"), true); 163 assertEquals(result.includes(usageExample), true); 164 assertEquals(result.includes("@slices/client"), true); 165 assertEquals(result.includes("@slices/oauth"), true); 166}); 167 168Deno.test("generateHeaderComment - generates consistent imports", () => { 169 const lexicons: Lexicon[] = []; 170 const usageExample = "/** Example */"; 171 const result = generateHeaderComment(lexicons, usageExample); 172 173 assertEquals(result.includes("SlicesClient"), true); 174 assertEquals(result.includes("@slices/client"), true); 175 assertEquals(result.includes("@slices/oauth"), true); 176});