Fixes: 1. media.ts: wrap placeholder generation in try-catch 2. toolbar.ts: check r.ok, display error message in popover
130 lines
4.1 KiB
TypeScript
130 lines
4.1 KiB
TypeScript
import { describe, it, expect } from "vitest";
|
|
|
|
import { atproto, type AtprotoAuthConfig } from "../src/auth.js";
|
|
|
|
const AUTH_ROUTES_RE = /^@emdash-cms\/auth-atproto\/routes\//;
|
|
|
|
describe("atproto auth config", () => {
|
|
describe("AuthProviderDescriptor contract", () => {
|
|
it("returns id 'atproto'", () => {
|
|
const descriptor = atproto();
|
|
expect(descriptor.id).toBe("atproto");
|
|
});
|
|
|
|
it("has label 'Atmosphere'", () => {
|
|
const descriptor = atproto();
|
|
expect(descriptor.label).toBe("Atmosphere");
|
|
});
|
|
|
|
it("points adminEntry to the admin module", () => {
|
|
const descriptor = atproto();
|
|
expect(descriptor.adminEntry).toBe("@emdash-cms/auth-atproto/admin");
|
|
});
|
|
|
|
it("defaults config to empty object when no options provided", () => {
|
|
const descriptor = atproto();
|
|
expect(descriptor.config).toEqual({});
|
|
});
|
|
|
|
it("defaults config to empty object when undefined is passed", () => {
|
|
const descriptor = atproto(undefined);
|
|
expect(descriptor.config).toEqual({});
|
|
});
|
|
|
|
it("declares routes pointing to auth package", () => {
|
|
const descriptor = atproto();
|
|
expect(descriptor.routes).toBeDefined();
|
|
expect(descriptor.routes!.length).toBe(4);
|
|
for (const route of descriptor.routes!) {
|
|
expect(route.entrypoint).toMatch(AUTH_ROUTES_RE);
|
|
}
|
|
});
|
|
|
|
it("declares storage collections for OAuth state", () => {
|
|
const descriptor = atproto();
|
|
expect(descriptor.storage).toBeDefined();
|
|
expect(descriptor.storage).toHaveProperty("states");
|
|
expect(descriptor.storage).toHaveProperty("sessions");
|
|
});
|
|
|
|
it("declares publicRoutes with specific paths", () => {
|
|
const descriptor = atproto();
|
|
expect(descriptor.publicRoutes).toBeDefined();
|
|
expect(descriptor.publicRoutes).toContain("/_emdash/api/auth/atproto/");
|
|
// Should not have overly broad prefixes
|
|
expect(descriptor.publicRoutes).not.toContain("/_emdash/.well-known/");
|
|
});
|
|
});
|
|
|
|
describe("config passthrough", () => {
|
|
it("passes allowedDIDs through", () => {
|
|
const config: AtprotoAuthConfig = {
|
|
allowedDIDs: ["did:plc:abc123", "did:web:example.com"],
|
|
};
|
|
const descriptor = atproto(config);
|
|
const result = descriptor.config as AtprotoAuthConfig;
|
|
expect(result.allowedDIDs).toEqual(["did:plc:abc123", "did:web:example.com"]);
|
|
});
|
|
|
|
it("passes defaultRole through", () => {
|
|
const descriptor = atproto({ defaultRole: 20 });
|
|
const result = descriptor.config as AtprotoAuthConfig;
|
|
expect(result.defaultRole).toBe(20);
|
|
});
|
|
|
|
it("passes allowedHandles through", () => {
|
|
const config: AtprotoAuthConfig = {
|
|
allowedHandles: ["*.example.com", "alice.bsky.social"],
|
|
};
|
|
const descriptor = atproto(config);
|
|
const result = descriptor.config as AtprotoAuthConfig;
|
|
expect(result.allowedHandles).toEqual(["*.example.com", "alice.bsky.social"]);
|
|
});
|
|
|
|
it("passes full config through unchanged", () => {
|
|
const config: AtprotoAuthConfig = {
|
|
allowedDIDs: ["did:plc:me123"],
|
|
allowedHandles: ["*.example.com"],
|
|
defaultRole: 40,
|
|
};
|
|
const descriptor = atproto(config);
|
|
expect(descriptor.config).toEqual(config);
|
|
});
|
|
|
|
it("does not mutate the input config", () => {
|
|
const config: AtprotoAuthConfig = {
|
|
allowedDIDs: ["did:plc:alice123"],
|
|
allowedHandles: ["*.example.com"],
|
|
defaultRole: 30,
|
|
};
|
|
const original = {
|
|
...config,
|
|
allowedDIDs: [...config.allowedDIDs!],
|
|
allowedHandles: [...config.allowedHandles!],
|
|
};
|
|
atproto(config);
|
|
expect(config).toEqual(original);
|
|
});
|
|
});
|
|
|
|
describe("descriptor shape invariants", () => {
|
|
it("id is always a non-empty string", () => {
|
|
const descriptor = atproto();
|
|
expect(typeof descriptor.id).toBe("string");
|
|
expect(descriptor.id.length).toBeGreaterThan(0);
|
|
});
|
|
|
|
it("label is always a non-empty string", () => {
|
|
const descriptor = atproto();
|
|
expect(typeof descriptor.label).toBe("string");
|
|
expect(descriptor.label.length).toBeGreaterThan(0);
|
|
});
|
|
|
|
it("adminEntry is always a non-empty string", () => {
|
|
const descriptor = atproto();
|
|
expect(typeof descriptor.adminEntry).toBe("string");
|
|
expect(descriptor.adminEntry!.length).toBeGreaterThan(0);
|
|
});
|
|
});
|
|
});
|