A Deno-compatible AT Protocol OAuth client that serves as a drop-in replacement for @atproto/oauth-client-node
at main 8.0 kB view raw
1import { assertEquals, assertInstanceOf } from "@std/assert"; 2import { 3 AuthorizationError, 4 DPoPError, 5 HandleResolutionError, 6 InvalidHandleError, 7 InvalidStateError, 8 OAuthError, 9 PDSDiscoveryError, 10 SessionError, 11 TokenExchangeError, 12} from "../src/errors.ts"; 13 14Deno.test("OAuthError", async (t) => { 15 await t.step("should create basic error with message", () => { 16 const error = new OAuthError("Test message"); 17 assertEquals(error.message, "Test message"); 18 assertEquals(error.name, "OAuthError"); 19 assertEquals(error.cause, undefined); 20 }); 21 22 await t.step("should create error with cause", () => { 23 const cause = new Error("Original error"); 24 const error = new OAuthError("Test message", cause); 25 assertEquals(error.message, "Test message"); 26 assertEquals(error.name, "OAuthError"); 27 assertEquals(error.cause, cause); 28 }); 29 30 await t.step("should be instance of Error", () => { 31 const error = new OAuthError("Test message"); 32 assertInstanceOf(error, Error); 33 assertInstanceOf(error, OAuthError); 34 }); 35}); 36 37Deno.test("InvalidHandleError", async (t) => { 38 await t.step("should create error with handle in message", () => { 39 const error = new InvalidHandleError("invalid.handle"); 40 assertEquals(error.message, "Invalid AT Protocol handle: invalid.handle"); 41 assertEquals(error.name, "InvalidHandleError"); 42 }); 43 44 await t.step("should be instance of OAuthError", () => { 45 const error = new InvalidHandleError("invalid.handle"); 46 assertInstanceOf(error, OAuthError); 47 assertInstanceOf(error, InvalidHandleError); 48 }); 49}); 50 51Deno.test("HandleResolutionError", async (t) => { 52 await t.step("should create error with handle in message", () => { 53 const error = new HandleResolutionError("test.handle"); 54 assertEquals(error.message, "Failed to resolve handle test.handle to DID and PDS"); 55 assertEquals(error.name, "HandleResolutionError"); 56 assertEquals(error.cause, undefined); 57 }); 58 59 await t.step("should create error with cause", () => { 60 const cause = new Error("Network error"); 61 const error = new HandleResolutionError("test.handle", cause); 62 assertEquals(error.message, "Failed to resolve handle test.handle to DID and PDS"); 63 assertEquals(error.name, "HandleResolutionError"); 64 assertEquals(error.cause, cause); 65 }); 66 67 await t.step("should be instance of OAuthError", () => { 68 const error = new HandleResolutionError("test.handle"); 69 assertInstanceOf(error, OAuthError); 70 assertInstanceOf(error, HandleResolutionError); 71 }); 72}); 73 74Deno.test("PDSDiscoveryError", async (t) => { 75 await t.step("should create error with PDS URL in message", () => { 76 const error = new PDSDiscoveryError("https://example.com"); 77 assertEquals(error.message, "Failed to discover OAuth endpoints for PDS: https://example.com"); 78 assertEquals(error.name, "PDSDiscoveryError"); 79 assertEquals(error.cause, undefined); 80 }); 81 82 await t.step("should create error with cause", () => { 83 const cause = new Error("Discovery failed"); 84 const error = new PDSDiscoveryError("https://example.com", cause); 85 assertEquals(error.message, "Failed to discover OAuth endpoints for PDS: https://example.com"); 86 assertEquals(error.name, "PDSDiscoveryError"); 87 assertEquals(error.cause, cause); 88 }); 89 90 await t.step("should be instance of OAuthError", () => { 91 const error = new PDSDiscoveryError("https://example.com"); 92 assertInstanceOf(error, OAuthError); 93 assertInstanceOf(error, PDSDiscoveryError); 94 }); 95}); 96 97Deno.test("TokenExchangeError", async (t) => { 98 await t.step("should create error with message", () => { 99 const error = new TokenExchangeError("Invalid grant"); 100 assertEquals(error.message, "Token exchange failed: Invalid grant"); 101 assertEquals(error.name, "TokenExchangeError"); 102 assertEquals(error.errorCode, undefined); 103 assertEquals(error.cause, undefined); 104 }); 105 106 await t.step("should create error with error code", () => { 107 const error = new TokenExchangeError("Invalid grant", "invalid_grant"); 108 assertEquals(error.message, "Token exchange failed: Invalid grant"); 109 assertEquals(error.name, "TokenExchangeError"); 110 assertEquals(error.errorCode, "invalid_grant"); 111 assertEquals(error.cause, undefined); 112 }); 113 114 await t.step("should create error with error code and cause", () => { 115 const cause = new Error("HTTP 400"); 116 const error = new TokenExchangeError("Invalid grant", "invalid_grant", cause); 117 assertEquals(error.message, "Token exchange failed: Invalid grant"); 118 assertEquals(error.name, "TokenExchangeError"); 119 assertEquals(error.errorCode, "invalid_grant"); 120 assertEquals(error.cause, cause); 121 }); 122 123 await t.step("should be instance of OAuthError", () => { 124 const error = new TokenExchangeError("Invalid grant"); 125 assertInstanceOf(error, OAuthError); 126 assertInstanceOf(error, TokenExchangeError); 127 }); 128}); 129 130Deno.test("DPoPError", async (t) => { 131 await t.step("should create error with message", () => { 132 const error = new DPoPError("Key generation failed"); 133 assertEquals(error.message, "DPoP operation failed: Key generation failed"); 134 assertEquals(error.name, "DPoPError"); 135 assertEquals(error.cause, undefined); 136 }); 137 138 await t.step("should create error with cause", () => { 139 const cause = new Error("Crypto error"); 140 const error = new DPoPError("Key generation failed", cause); 141 assertEquals(error.message, "DPoP operation failed: Key generation failed"); 142 assertEquals(error.name, "DPoPError"); 143 assertEquals(error.cause, cause); 144 }); 145 146 await t.step("should be instance of OAuthError", () => { 147 const error = new DPoPError("Key generation failed"); 148 assertInstanceOf(error, OAuthError); 149 assertInstanceOf(error, DPoPError); 150 }); 151}); 152 153Deno.test("SessionError", async (t) => { 154 await t.step("should create error with message", () => { 155 const error = new SessionError("Invalid session data"); 156 assertEquals(error.message, "Session error: Invalid session data"); 157 assertEquals(error.name, "SessionError"); 158 assertEquals(error.cause, undefined); 159 }); 160 161 await t.step("should create error with cause", () => { 162 const cause = new Error("Serialization failed"); 163 const error = new SessionError("Invalid session data", cause); 164 assertEquals(error.message, "Session error: Invalid session data"); 165 assertEquals(error.name, "SessionError"); 166 assertEquals(error.cause, cause); 167 }); 168 169 await t.step("should be instance of OAuthError", () => { 170 const error = new SessionError("Invalid session data"); 171 assertInstanceOf(error, OAuthError); 172 assertInstanceOf(error, SessionError); 173 }); 174}); 175 176Deno.test("InvalidStateError", async (t) => { 177 await t.step("should create error with fixed message", () => { 178 const error = new InvalidStateError(); 179 assertEquals(error.message, "Invalid or expired OAuth state parameter"); 180 assertEquals(error.name, "InvalidStateError"); 181 assertEquals(error.cause, undefined); 182 }); 183 184 await t.step("should be instance of OAuthError", () => { 185 const error = new InvalidStateError(); 186 assertInstanceOf(error, OAuthError); 187 assertInstanceOf(error, InvalidStateError); 188 }); 189}); 190 191Deno.test("AuthorizationError", async (t) => { 192 await t.step("should create error with error code only", () => { 193 const error = new AuthorizationError("access_denied"); 194 assertEquals(error.message, "Authorization failed: access_denied"); 195 assertEquals(error.name, "AuthorizationError"); 196 }); 197 198 await t.step("should create error with error code and description", () => { 199 const error = new AuthorizationError("access_denied", "User denied the request"); 200 assertEquals(error.message, "Authorization failed: access_denied - User denied the request"); 201 assertEquals(error.name, "AuthorizationError"); 202 }); 203 204 await t.step("should be instance of OAuthError", () => { 205 const error = new AuthorizationError("access_denied"); 206 assertInstanceOf(error, OAuthError); 207 assertInstanceOf(error, AuthorizationError); 208 }); 209});