Files

80 lines
4.7 KiB
TypeScript

import { expect } from "bun:test";
import type { Db } from "@stc/db";
import { bunSqlAdapter } from "../src/server/auth/adapter";
import { forEachDb } from "./helpers";
// biome-ignore lint/suspicious/noExplicitAny: adapter is generic over Better Auth options
const make = (db: Db): any => bunSqlAdapter(db)({});
async function seed(a: ReturnType<typeof make>) {
const people = [
{ name: "Ada", email: "[email protected]", emailVerified: true },
{ name: "Bob", email: "[email protected]", emailVerified: false },
{ name: "Cyd", email: "[email protected]", emailVerified: false },
];
const out = [];
for (const p of people) out.push(await a.create({ model: "user", data: { ...p, createdAt: new Date(), updatedAt: new Date() } }));
return out;
}
forEachDb("adapter create and findOne round-trip types", async (db) => {
const a = make(db);
const [ada] = await seed(a);
expect(typeof ada.id).toBe("string");
const found = await a.findOne({ model: "user", where: [{ field: "email", value: "[email protected]" }] });
expect(found.name).toBe("Ada");
expect(found.emailVerified).toBe(true);
expect(found.createdAt).toBeInstanceOf(Date);
expect(await a.findOne({ model: "user", where: [{ field: "email", value: "nobody@x" }] })).toBeNull();
});
forEachDb("adapter where operators", async (db) => {
const a = make(db);
await seed(a);
const names = async (where: unknown[], extra: Record<string, unknown> = {}) =>
(await a.findMany({ model: "user", where, sortBy: { field: "name", direction: "asc" }, ...extra })).map((u: { name: string }) => u.name);
expect(await names([{ field: "name", operator: "ne", value: "Ada" }])).toEqual(["Bob", "Cyd"]);
expect(await names([{ field: "name", operator: "in", value: ["Ada", "Cyd"] }])).toEqual(["Ada", "Cyd"]);
expect(await names([{ field: "name", operator: "not_in", value: ["Ada"] }])).toEqual(["Bob", "Cyd"]);
expect(await names([{ field: "name", operator: "in", value: [] }])).toEqual([]);
expect(await names([{ field: "email", operator: "contains", value: "example" }])).toEqual(["Ada", "Cyd"]);
expect(await names([{ field: "email", operator: "contains", value: "Example" }])).toEqual(["Bob"]);
expect(await names([{ field: "email", operator: "contains", value: "EXAMPLE.ORG", mode: "insensitive" }])).toEqual(["Bob"]);
expect(await names([{ field: "email", operator: "starts_with", value: "cy" }])).toEqual(["Cyd"]);
expect(await names([{ field: "email", operator: "ends_with", value: ".com" }])).toEqual(["Ada", "Cyd"]);
expect(await names([{ field: "email", value: "[email protected]", mode: "insensitive" }])).toEqual(["Bob"]);
expect(await names([{ field: "name", operator: "gt", value: "Ada" }])).toEqual(["Bob", "Cyd"]);
expect(await names([{ field: "name", operator: "lte", value: "Bob" }])).toEqual(["Ada", "Bob"]);
expect(await names([{ field: "emailVerified", value: false }])).toEqual(["Bob", "Cyd"]);
// AND clauses AND-ed, OR clauses grouped
expect(await names([
{ field: "emailVerified", value: false },
{ field: "name", value: "Ada", connector: "OR" },
{ field: "name", value: "Cyd", connector: "OR" },
])).toEqual(["Cyd"]);
expect(await names([], { limit: 1, offset: 1 })).toEqual(["Bob"]);
expect(await names([], { limit: 2, sortBy: { field: "name", direction: "desc" } })).toEqual(["Cyd", "Bob"]);
expect(await names([{ field: "image", value: null }])).toEqual(["Ada", "Bob", "Cyd"]);
});
forEachDb("adapter update, count, delete, consume, increment", async (db) => {
const a = make(db);
const [ada, bob] = await seed(a);
const up = await a.update({ model: "user", where: [{ field: "id", value: ada.id }], update: { name: "Ada L." } });
expect(up.name).toBe("Ada L.");
expect(await a.updateMany({ model: "user", where: [{ field: "emailVerified", value: false }], update: { image: "x.png" } })).toBe(2);
expect(await a.count({ model: "user", where: [{ field: "image", value: "x.png" }] })).toBe(2);
expect(await a.count({ model: "user" })).toBe(3);
await a.delete({ model: "user", where: [{ field: "id", value: bob.id }] });
expect(await a.count({ model: "user" })).toBe(2);
expect(await a.deleteMany({ model: "user", where: [{ field: "image", value: "x.png" }] })).toBe(1);
const exp = new Date(Date.now() + 60_000);
await a.create({ model: "verification", data: { identifier: "k", value: "v1", expiresAt: exp, createdAt: new Date(), updatedAt: new Date() } });
const consumed = await a.consumeOne({ model: "verification", where: [{ field: "identifier", value: "k" }] });
expect(consumed?.value).toBe("v1");
expect(await a.consumeOne({ model: "verification", where: [{ field: "identifier", value: "k" }] })).toBeNull();
const live = await a.findMany({ model: "verification", where: [{ field: "expiresAt", operator: "gt", value: new Date() }] });
expect(live.length).toBe(0);
});