Files
suaveplan/packages/identity/auth/better-auth-surrealdb/tests/integration/schema-write-compatibility.test.ts
2026-05-27 23:47:53 +01:00

132 lines
4.3 KiB
TypeScript

import { SurrealAdapter } from "@suaveplan/surrealdb";
import {
afterAll,
beforeAll,
describe,
expect,
it,
} from "@suaveplan/testing/runner";
import { SurrealDBFixture } from "@suaveplan/testing-integration-surrealdb";
import { createBetterAuthSurrealAdapter } from "../../src/adapter/adapter.js";
import { applyBetterAuthSchema } from "../../src/schema/schema.js";
let fixture: SurrealDBFixture | null = null;
let client: SurrealAdapter | null = null;
let adapter: ReturnType<typeof createBetterAuthSurrealAdapter>;
beforeAll(async () => {
fixture = new SurrealDBFixture();
const cfg = await fixture.start();
client = new SurrealAdapter({
url: cfg.url,
namespace: cfg.namespace,
database: cfg.database,
username: cfg.username,
password: cfg.password,
});
await client.connect();
await applyBetterAuthSchema(client);
// Bootstrap the user table — schema only extends it.
await client.execute("DEFINE TABLE OVERWRITE user SCHEMAFULL;");
await client.execute(
"DEFINE FIELD OVERWRITE email ON user TYPE option<string>;"
);
await client.execute(
"DEFINE FIELD OVERWRITE phoneNumber ON user TYPE option<string>;"
);
adapter = createBetterAuthSurrealAdapter({ client });
}, 120_000);
afterAll(async () => {
if (client) {
await client.disconnect();
client = null;
}
if (fixture) {
await fixture.stop();
fixture = null;
}
}, 60_000);
describe("schema write compatibility", () => {
it("applied schema accepts canonical Better-Auth row writes", {
timeout: 60000,
}, async () => {
await adapter.create({
model: "user",
data: {
id: "u_compat_1",
email: "compat@x",
emailVerified: false,
} as unknown as Record<string, unknown>,
});
// session — record<user> userId
const session = (await adapter.create({
model: "session",
data: {
id: "s_compat_1",
userId: "u_compat_1",
token: "tok",
} as unknown as Record<string, unknown>,
})) as { id: string; userId: string };
expect(session.userId).toBe("u_compat_1");
// account — string userId
const account = (await adapter.create({
model: "account",
data: {
id: "a_compat_1",
userId: "u_compat_1",
providerId: "p",
accountId: "a",
password: "",
} as unknown as Record<string, unknown>,
})) as { id: string; userId: string };
expect(account.userId).toBe("u_compat_1");
// organization + member — record<user>, record<organization>
await adapter.create({
model: "organization",
data: {
id: "o_compat_1",
name: "Acme",
slug: "acme-compat",
} as unknown as Record<string, unknown>,
});
const member = (await adapter.create({
model: "member",
data: {
id: "m_compat_1",
userId: "u_compat_1",
organizationId: "o_compat_1",
role: "admin",
} as unknown as Record<string, unknown>,
})) as { userId: string; organizationId: string };
expect(member.userId).toBe("u_compat_1");
expect(member.organizationId).toBe("o_compat_1");
// oauth_access_token — string userId (not in default linkFields)
const tok = (await adapter.create({
model: "oauth_access_token",
data: {
id: "t_compat_1",
userId: "u_compat_1",
accessToken: "a",
refreshToken: "r",
} as unknown as Record<string, unknown>,
})) as { userId: string };
expect(tok.userId).toBe("u_compat_1");
});
it("applyBetterAuthSchema is idempotent against real SurrealDB", {
timeout: 60000,
}, async () => {
if (!client) throw new Error("client not ready");
await applyBetterAuthSchema(client);
await applyBetterAuthSchema(client);
// Re-application succeeds; idempotency proven by no throw.
expect(true).toBe(true);
});
});