Testing Strategy
Relevant source files
The following files were used as context for generating this wiki page:- packages/adapters/convex/test/adapter.test.ts
- packages/plugins/app-invite/tests/app-invite.test.ts
- packages/libraries/tests/src/index.ts
- packages/plugins/legal-consent/tests/legal-consent.test.ts
- packages/adapters/convex/test/schema.test.ts
- packages/libraries/tests/package.json
- packages/plugins/feedback/tests/feedback.test.ts
The testing strategy for better-auth-kit is centered around the vitest framework and a dedicated test helper library, @better-auth-kit/tests. This approach ensures consistency and simplifies the process of writing integration tests for plugins and adapters. Tests are designed to simulate real-world usage by interacting with the API through a test client, validating both successful outcomes and error conditions against a live, but controlled, database.
The core of this strategy is the @better-auth-kit/tests package, which provides a standardized way to instantiate better-auth, create a test client, and manage the test environment, including database state. This allows each plugin and adapter to have a self-contained suite of tests that verify its functionality in isolation and in conjunction with the core better-auth system.
Core Components
The testing architecture relies on several key components working together. vitest is the test runner, while the @better-auth-kit/tests library provides the necessary abstractions for setting up complex test scenarios.
Sources: packages/libraries/tests/package.json:20-22, packages/plugins/legal-consent/package.json:25-26
Test Framework: Vitest
All tests within the repository are written using vitest. Test files utilize the standard describe, it, and expect syntax for structuring test suites and making assertions.
Sources: packages/plugins/app-invite/tests/app-invite.test.ts:1, packages/adapters/convex/test/adapter.test.ts:2
Test Helper Library: @better-auth-kit/tests
This library is fundamental to the testing strategy. It exports a set of utilities designed to streamline the setup of test environments for better-auth plugins and adapters.
The following diagram shows the high-level process of setting up a test instance using the library.
This diagram illustrates how getTestInstance takes an auth configuration and produces a test client and helper utilities for use in tests.
Sources: packages/libraries/tests/README.md:3-4, packages/libraries/tests/src/index.ts
The main functions provided by this library are:
| Function | Description |
|---|---|
getTestInstance | Initializes a betterAuth instance, creates a test client, and returns helpers for signing up/in users and managing the database. This is the primary entry point for most test setups. |
tryCatch | A wrapper for async functions that catches errors and returns a consistent Result object ({ data, error }), simplifying error assertion. |
resetDatabase | A utility to clear specified database tables, ensuring a clean state between test runs. |
sessionSetter | A helper function to extract session cookies from a response and apply them to a Headers object for subsequent authenticated requests. |
Sources: packages/libraries/tests/src/index.ts:20-176
Plugin Testing
Plugin tests verify the behavior of individual plugins, such as app-invite, legal-consent, and feedback. The tests cover API endpoint logic, schema extensions, and custom hooks.
Test Setup and Structure
A typical plugin test file starts by initializing a betterAuth instance with the plugin under test and then passing it to getTestInstance.
// Example from legal-consent.test.ts
import { getTestInstance, tryCatch } from "@better-auth-kit/tests";
import { beforeAll, describe, expect, it } from "vitest";
import { auth } from "./auth"; // A betterAuth instance with the legal-consent plugin
const { resetDatabase, client } = await getTestInstance(auth);
describe("Legal Consent Plugin", () => {
beforeAll(async () => {
await resetDatabase();
});
// ... test cases
});
Sources: packages/plugins/legal-consent/tests/legal-consent.test.ts:1-12, packages/plugins/app-invite/tests/app-invite.test.ts:29-57
API Interaction and Assertions
Tests use the client object returned by getTestInstance to make API calls. The tryCatch helper is often used to handle the response and assert the outcome.
The following sequence diagram illustrates a test for accepting an app invitation, showing the interaction between the test, the client, the auth handler, and the database.
This diagram shows the flow of an API call within a test, from the client request to database operations and the final assertion.
Sources: packages/plugins/app-invite/tests/app-invite.test.ts:61-86, packages/plugins/legal-consent/tests/legal-consent.test.ts:14-26
Tests verify both success and failure paths. For failures, assertions are made on the specific error code returned by the API.
// Example from legal-consent.test.ts
it("Should fail if TOS is not accepted", async () => {
const { data, error } = await tryCatch(
auth.api.signUpEmail({
body: {
// ...
tosAccepted: false,
},
}),
);
expect(data).toBeNull();
expect(error).toBeDefined();
expect(error?.body?.code).toEqual("TOS_MUST_BE_ACCEPTED");
});
Sources: packages/plugins/legal-consent/tests/legal-consent.test.ts:14-26
Adapter Testing
Adapter tests ensure that the database layer functions correctly. The better-auth-kit uses a combination of a standardized adapter test suite and custom tests for adapter-specific features.
Convex Adapter Example
The Convex adapter tests demonstrate this two-pronged approach.
- Standard Test Suite: The
runAdapterTestfunction frombetter-auth/adapters/testis executed. This suite runs a series of generic tests (CRUD operations, user/session management) that every adapter must pass, ensuring a consistent interface. - Custom Tests: Additional tests are written to verify functionality unique to the Convex adapter, such as
findManywithoffsetandlimit.
The test setup for the Convex adapter also includes beforeAll and afterAll hooks to clear the database using Convex-specific mutations.
// From packages/adapters/convex/test/adapter.test.ts
describe("Run BetterAuth Adapter tests", async () => {
const client = new ConvexClient(process.env.CONVEX_URL as string);
beforeAll(async () => {
await client.mutation(api.tests.removeAll, {});
});
afterAll(async () => {
await client.mutation(api.tests.removeAll, {});
});
const adapter = convexAdapter(client);
await runAdapterTest({
getAdapter: async (customOptions = {}) => {
return adapter({ ...customOptions });
},
skipGenerateIdTest: true,
});
// ... custom tests
});
Sources: packages/adapters/convex/test/adapter.test.ts:18-43
Schema Generation Testing
A unique aspect of the Convex adapter testing is the verification of its dynamic schema generation. The generateSchema function builds a schema.ts file based on the core better-auth tables and any additional schemas from plugins.
Tests for this feature work by:
- Calling
generateSchemawith a specificbetterAuthconfiguration (including plugins). - Comparing the generated schema string against a hard-coded, expected output string.
- Using
prettierto format both strings to ensure the comparison is not affected by whitespace differences.
This ensures that any changes to the schema logic or plugin definitions are correctly reflected in the generated Convex schema file.
The following diagram illustrates this testing process.
This flowchart shows how the generated schema is tested against a known-correct version.
Sources: packages/adapters/convex/test/schema.test.ts:47-66, packages/adapters/convex/src/generate-schema/generate-schema-builder.ts
Summary
The testing strategy in better-auth-kit is robust and developer-friendly. By leveraging vitest and the custom @better-auth-kit/tests library, the project maintains a high standard of quality and consistency across its ecosystem of plugins and adapters. The strategy effectively covers API logic, database interactions, and even code generation, ensuring that all components work as expected.