saasprokit
Testing

Unit Tests

Catalog of Vitest unit tests and coverage gaps

@repo/auth, apps/web, and @repo/database have co-located *.test.{ts,tsx} files. pnpm test (turbo test) runs those three. Setup CLI tests are pnpm test:cli (root vitest.config.mtsscripts/**/*.test.ts) and are not in the turbo graph.

Other test files

FileTestsCovers
packages/auth/billing-authorize.test.ts22isOrgMember, canManageBilling, authorizeBillingAction — the allow/deny matrix from Billing Authorization across member/admin/owner roles, plus the unknown-action fallback
packages/auth/helpers.test.ts21isSubscriptionPendingCancel, isAlreadyCancelingError, isSubscriptionActive across all 8 Stripe subscription statuses, getCurrentPlan, and getStatusDisplayText
packages/auth/admin-bootstrap.test.ts7isBootstrapAdminEmail — the ADMIN_EMAILS bootstrap allowlist (case-insensitivity, CSV parsing with spaces, partial-match rejection, empty/undefined list)
packages/auth/ba-i18n.test.ts9baErrorTranslations, localeFromPathname, localeFromReferer — Better Auth error-code localization and locale-detection helpers
packages/auth/two-factor-hooks.test.ts2TOTP secret rotation — a re-issued secret stays unusable for sign-in until verified, then activates once the user proves possession in session
packages/auth/server-wiring.test.ts1The shipped auth instance registers twoFactorAfterHook — the rotation fix is one deletable line in server.ts, and no other test builds the shipped instance
apps/web/lib/routes.test.ts13orgRoutes, accountRoutes, resolveCallbackUrl, and the AUTH_ROUTE_PREFIXES/PUBLIC_ROUTE_EXACT/PUBLIC_ROUTE_PREFIXES middleware allowlists
apps/web/lib/parsers.test.ts5sortingStateParser (table sort-state URL serialization)
apps/web/app/[locale]/(app)/admin/users/guards.test.ts3guardUserMutation — blocks self-targeting admin mutations, allows the same mutation against another user, always allows revoke-sessions
apps/web/hooks/use-action-result.test.ts15useActionResult — idle-state skip, success/error dispatch, silence on fieldErrors-only failures, and the replay guard under StrictMode
apps/web/lib/auth/action-error.test.ts6toActionError, actionError — server-action error normalization and i18n fallback
apps/web/lib/billing/checkout-queries.test.ts9verifyCheckoutSession — the independent post-checkout verification described in Subscribe & Checkout
apps/web/lib/seo-config.test.ts2Site config carries no kit branding and derives the name from NEXT_PUBLIC_APP_NAME
packages/database/redact.test.ts10argShape — redacts tokens, passwords, emails, and nested Prisma args so query logs stay diagnosable

Auth Permissions — 21 tests

packages/auth/permissions.test.ts

Tests the dual RBAC system (platform-level admin roles + organization-scoped roles) via canOrg, canAdmin, and isAdminAreaRole.

Organization team permissions — 3 tests

#Test Case
1Owner should be able to create, update, and delete teams
2Admin should be able to create, update, and delete teams
3Member should not be able to manage teams

canOrg — 7 tests

#Test Case
4Should gate organization:update to owner and admin only
5Should allow only the owner to delete the organization
6Should require every action listed for a resource
7Should require every resource listed
8Should deny an unknown resource rather than throwing
9Should deny an unknown role rather than throwing
10Should grant when any role in a comma-separated list allows it

canAdmin — 8 tests

#Test Case
11Should grant every user/session mutation to admin
12Should deny every user/session mutation to moderator
13Should deny every user/session mutation to user
14Should deny impersonate-admins even to admin
15Should let admin read organizations and moderator read but not delete
16Should treat null/undefined/empty role as the default user role
17Should OR across a comma-separated role list
18Should deny an unknown role or resource rather than throwing

isAdminAreaRole — 3 tests

#Test Case
19Should admit admin and moderator, reject user
20Should reject null, undefined, and empty as non-staff
21Should admit a comma-separated list containing a staff role

Coverage Gaps

PackageConfigTestsSuggested Test Areas
storagenone0No vitest config at all — quota validation, MIME checking, provider logic
utilsnone0Slug generation/validation, date helpers, payment utils

High-Value Unit Test Candidates

These are pure functions with no external dependencies — ideal for unit testing:

FunctionLocationWhy
getPlanLimits()packages/auth/plans.tsCore billing logic, multiple plan tiers
isPlanHigherTier()packages/auth/plans.tsUpgrade/downgrade decisions
getAnnualSavingsPercent()packages/auth/plans.tsPricing display
checkOrgCreationEligibility()packages/utils/payment.tsOrg creation eligibility
generateSlug()packages/utils/slug.tsUsed across org creation
slugSchemapackages/utils/slug.tsReserved slug validation

Running Unit Tests

pnpm test
pnpm test:cli
pnpm --filter app test
pnpm --filter @repo/database test
pnpm --filter @repo/auth test -- --watch
pnpm --filter @repo/auth test -- --testNamePattern "canOrg"

On this page