// Unit test with `@voltro/testing` — no database, no running server. Importing // `../database/schema` registers the `users` / `actors` / `tenants` tables // globally, so `makeTestContext` auto-wires them into the in-memory store. // `ctx.store` is the SAME mixin-wrapped store the handlers get in production, // so the `deactivation()` mixin columns behave exactly as at runtime. // // The POINT of this template: `deactivation()` is a columns-only mixin (adds // `deactivatedAt` / `deactivatedBy`) with NO read scoping — a deactivated row // stays fully VISIBLE, the deliberate opposite of `softDelete()`. These tests // assert exactly that. Run with `voltro test` (vitest). import { describe, it, expect } from 'vitest' import { makeTestContext, mockStore } from '@voltro/testing' import { database } from '../database/schema' // registers users / actors / tenants import createUser from '../mutations/users.create.mutation.server' import deactivateUser from '../mutations/users.deactivate.mutation.server' const subject = { type: 'user' as const, id: 'user_1', tenantId: 'acme' } describe('users.create', () => { it('inserts a user with an auto-injected id and no deactivation timestamp', async () => { const ctx = makeTestContext({ subject, store: mockStore({ users: [] }) }) const row = await createUser({ email: 'ada@example.com', name: 'Ada' }, ctx) expect(row['email']).toBe('ada@example.com') expect(row['name']).toBe('Ada') expect(row['id']).toBeTruthy() // TypeID auto-injected from id() expect(row['deactivatedAt'] ?? null).toBeNull() // active on creation }) }) describe('users.deactivate', () => { it('stamps deactivatedAt — and the row STAYS visible (unlike softDelete)', async () => { const ctx = makeTestContext({ subject, store: mockStore({ users: [] }) }) const created = await createUser({ email: 'grace@example.com', name: 'Grace' }, ctx) const updated = await deactivateUser({ id: String(created['id']) }, ctx) expect(updated['deactivatedAt']).toBeInstanceOf(Date) // deactivation() adds no defaultWhere, so a plain query still returns the // deactivated row — this is the mixin's whole contract. const rows = await ctx.store.query(database.users.descriptor) expect(rows).toHaveLength(1) expect(String(rows[0]!['id'])).toBe(String(created['id'])) expect(rows[0]!['deactivatedAt']).toBeInstanceOf(Date) }) })