Savvi Studio

Testing Examples

These examples demonstrate testing patterns with database fixtures.

Referenced by: testing.md, best-practices.md

Example 1: Basic Test with Fixtures

import { test } from '@/test-utils-integration/config/database.context';
import { createResource, getResource } from '@db/graph';

test('creates and retrieves resource', async ({ newDbClient }) => {
    // Create
    const id = await createResource(newDbClient, {
        p_type_namespace: 'test.user',
        p_external_id: 'alice',
        p_data: { name: 'Alice' }
    });
    
    // Verify
    const resources = await getResource(newDbClient, { p_id: id });
    expect(resources.length).toBe(1);
    expect(resources[0].external_id).toBe('alice');
    expect(resources[0].data.name).toBe('Alice');
});

Example 2: Test Factory Pattern

// tests/utils/factories/database-fixtures.ts
import { createResource } from '@db/graph';
import { PoolClient } from 'pg';

export async function createTestUser(
    client: PoolClient,
    overrides?: {
        external_id?: string;
        data?: Record<string, unknown>;
    }
) {
    return await createResource(client, {
        p_type_namespace: 'test.user',
        p_external_id: overrides?.external_id ?? `user-${Date.now()}`,
        p_data: overrides?.data ?? { role: 'tester' }
    });
}

export async function createTestDocument(
    client: PoolClient,
    userId: bigint,
    overrides?: {
        external_id?: string;
        data?: Record<string, unknown>;
    }
) {
    return await createResource(client, {
        p_type_namespace: 'doc.document',
        p_external_id: overrides?.external_id ?? `doc-${Date.now()}`,
        p_data: overrides?.data ?? { title: 'Test Doc' },
        p_creator_id: userId
    });
}

// Using factories in tests
import { test } from '@/test-utils-integration/config/database.context';
import { createTestUser, createTestDocument } from '@/test-utils-integration/utils/database-fixtures';

test('uses factories', async ({ newDbClient }) => {
    const userId = await createTestUser(newDbClient);
    const docId = await createTestDocument(newDbClient, userId, {
        data: { title: 'Custom Title' }
    });
    
    expect(docId).toBeDefined();
});

Example 3: Multiple Fixtures Test

import { test } from '@/test-utils-integration/config/database.context';
import { createResource } from '@db/graph';

test('uses multiple fixtures', async ({ mgmtClient, newDbClient }) => {
    // mgmtClient for admin operations
    const dbCount = await mgmtClient.query(
        'SELECT count(*) FROM pg_database'
    );
    
    // newDbClient for application queries
    const id = await createResource(newDbClient, {
        p_type_namespace: 'test.type',
        p_external_id: 'test-id'
    });
    
    expect(id).toBeDefined();
});

Example 4: Migration Test

import { test } from '@/test-utils-integration/config/database.context';

test('migrations complete successfully', async ({ migration }) => {
    expect(migration.success).toBe(true);
    expect(migration.errors).toHaveLength(0);
    expect(migration.filesExecuted).toBeGreaterThan(0);
});

test('required schemas exist', async ({ newDbClient }) => {
    const result = await newDbClient.query(`
        SELECT schema_name 
        FROM information_schema.schemata 
        WHERE schema_name IN ('auth', 'graph', 'studio')
    `);
    
    expect(result.rows).toHaveLength(3);
});

test('required function exists', async ({ newDbClient }) => {
    const result = await newDbClient.query(`
        SELECT proname 
        FROM pg_proc p
        JOIN pg_namespace n ON p.pronamespace = n.oid
        WHERE n.nspname = 'graph' AND p.proname = 'create_resource'
    `);
    
    expect(result.rows).toHaveLength(1);
});

Example 5: Test with Cleanup

import { test } from '@/test-utils-integration/config/database.context';
import { createResource } from '@db/graph';

test('with manual cleanup', async ({ newDbClient }) => {
    const id = await createResource(newDbClient, {
        p_type_namespace: 'test.type',
        p_external_id: 'cleanup-test'
    });
    
    // Test logic...
    
    // Cleanup
    await newDbClient.query(
        'DELETE FROM graph.resource WHERE id = $1',
        [id]
    );
});

Example 6: Test with Transaction Isolation

import { test } from '@/test-utils-integration/config/database.context';
import { createResource } from '@db/graph';

test('isolated with transaction', async ({ newDbClient }) => {
    await newDbClient.query('BEGIN');
    
    try {
        // Test operations
        const id = await createResource(newDbClient, {
            p_type_namespace: 'test.type',
            p_external_id: 'isolated'
        });
        
        expect(id).toBeDefined();
        
        // Rollback to clean up
    } finally {
        await newDbClient.query('ROLLBACK');
    }
});

Example 7: Test Authentication Flow

import { test } from '@/test-utils-integration/config/database.context';
import { login } from '@db/studio';
import { sessionId } from '@db/auth';

test('authentication flow', async ({ newDbClient }) => {
    await login(newDbClient, { p_jwt_token: testToken });
    
    const sid = await sessionId(newDbClient);
    expect(sid).toBeDefined();
    
    // More test assertions...
});