@te-code/testing
v1.1.0
Published
Standardized testing utilities for TE Code ecosystem
Maintainers
Readme
@te-code/testing
Standardized testing utilities for TE Code projects. Provides consistent mocks, fixtures, helpers, and custom matchers for Vitest.
Full Documentation: docs/
Installation
Local Development (TE Code Ecosystem)
# 1. Build the testing library first
cd "D:\Travis Eric\TE Code\te-testing"
pnpm install
pnpm build
# 2. Link from your project
cd "D:\Travis Eric\TE Code\your-project"
pnpm link ../te-testingFuture: npm Registry
# When published to npm:
pnpm add -D @te-code/testingExample Files
Copy from examples/ directory:
vitest.config.example.ts- Vitest configurationsetup.example.ts- Test setup filecomprehensive.test.example.ts- All features demo
Quick Start
1. Configure Vitest
// vitest.config.ts
import { defineConfig } from 'vitest/config';
import { teVitestConfig } from '@te-code/testing/vitest-preset';
export default defineConfig({
...teVitestConfig,
});2. Setup Test File
// test/setup.ts
import '@te-code/testing/matchers'; // Custom assertions3. Write Tests
import { createUser, createMockSupabaseClient, testApiRoute } from '@te-code/testing';
import handler from '@/pages/api/users';
describe('Users API', () => {
it('should create a user', async () => {
const user = createUser({ email: '[email protected]' });
const result = await testApiRoute(handler, {
method: 'POST',
body: user,
});
expect(result).toBeSuccessful();
expect(result.body).toHaveProperty('id');
});
});Modules
Mocks (@te-code/testing/mocks)
Supabase
import {
createMockSupabaseClient,
createAuthenticatedSupabaseClient,
resetSupabaseMocks,
} from '@te-code/testing/mocks';
// Basic mock
const supabase = createMockSupabaseClient();
// With authenticated user
const supabase = createAuthenticatedSupabaseClient({
user: { id: 'user-1', email: '[email protected]' },
});
// With pre-seeded data
const supabase = createMockSupabaseClient({
data: {
users: [{ id: '1', name: 'Test User' }],
posts: [{ id: '1', user_id: '1', title: 'Hello' }],
},
});
// Query like normal
const { data } = await supabase.from('users').select('*').eq('id', '1');Teneo Auth
import {
createMockTeneoAuth,
createAuthenticatedTeneoAuth,
createMockJWT,
decodeMockJWT,
} from '@te-code/testing/mocks';
// Unauthenticated
const auth = createMockTeneoAuth();
// Authenticated with credits
const auth = createAuthenticatedTeneoAuth({
user: { id: 'user-1', credits: 100 },
});
// Use credits
const result = await auth.useCredits(10);
expect(result.success).toBe(true);
expect(result.remaining).toBe(90);Stripe
import { createMockStripe, createMockStripeEvent } from '@te-code/testing/mocks';
const stripe = createMockStripe({
customerId: 'cus_test',
priceId: 'price_test',
});
// Create checkout session
const session = await stripe.checkout.sessions.create({
mode: 'subscription',
line_items: [{ price: 'price_test', quantity: 1 }],
});
expect(session.url).toContain('checkout.stripe.com');
// Test webhook
const event = createMockStripeEvent('customer.subscription.created', {
id: 'sub_test',
customer: 'cus_test',
});Next.js API Routes
import {
testApiRoute,
testAppRouterRoute,
createBearerAuthHeader,
} from '@te-code/testing/mocks';
// Pages Router
const result = await testApiRoute(handler, {
method: 'POST',
body: { name: 'Test' },
headers: createBearerAuthHeader('token'),
});
expect(result.status).toBe(201);
// App Router
const response = await testAppRouterRoute(POST, {
method: 'POST',
body: { name: 'Test' },
});
const data = await response.json();Fixtures (@te-code/testing/fixtures)
Users
import {
createUser,
createAdminUser,
createProUser,
createSession,
users,
} from '@te-code/testing/fixtures';
// Create unique user
const user = createUser({ name: 'John' });
// Pre-built fixtures
const admin = users.admin;
const pro = users.pro;
// With session
const session = createSession(user);Financial (for FinForensics, etc.)
import {
createEntity,
createAccount,
createTransaction,
createTransactionBatch,
entities,
accounts,
} from '@te-code/testing/fixtures';
// Create entities
const person = createPersonEntity({ name: 'John Doe' });
const business = createBusinessEntity({ name: 'Acme Corp' });
// Create account
const checking = createAccount({
entity_id: person.id,
bank_name: 'Wells Fargo',
account_type: 'checking',
});
// Create transactions
const income = createCreditTransaction({ amount: 5000, description: 'PAYROLL' });
const expense = createDebitTransaction({ amount: 150, description: 'AMAZON' });
// Batch create
const transactions = createTransactionBatch({
count: 100,
startDate: '2024-01-01',
endDate: '2024-12-31',
account_id: checking.id,
});
// Pre-built for divorce/custody scenarios
const { husband, wife, business } = entities;
const { husbandChecking, wifeChecking } = accounts;Helpers (@te-code/testing/helpers)
import {
wait,
waitFor,
withEnv,
createDeferred,
expectError,
freezeDate,
suppressConsole,
captureConsole,
} from '@te-code/testing/helpers';
// Timing
await wait(100);
await waitFor(() => element.isVisible());
// Environment
await withEnv({ API_URL: 'http://test' }, async () => {
expect(process.env.API_URL).toBe('http://test');
});
// Controlled async
const deferred = createDeferred<User>();
fetchUser.mockReturnValue(deferred.promise);
// ... trigger loading state ...
deferred.resolve({ name: 'John' });
// Error assertions
await expectError(
() => validateEmail('invalid'),
{ message: /invalid email/i, code: 'VALIDATION_ERROR' }
);
// Date freezing
const restore = freezeDate('2024-06-15');
expect(new Date().toISOString()).toContain('2024-06-15');
restore();
// Console capture
const { output, restore } = captureConsole(['warn']);
triggerDeprecationWarning();
expect(output.warn).toContainEqual(expect.stringContaining('deprecated'));
restore();Custom Matchers (@te-code/testing/matchers)
Import in your setup file:
import '@te-code/testing/matchers';API Response Matchers
expect(response).toHaveStatus(200);
expect(response).toBeSuccessful(); // 2xx
expect(response).toBeClientError(); // 4xx
expect(response).toBeServerError(); // 5xx
expect(response).toHaveJsonBody({ success: true });
expect(response).toHaveHeader('content-type', 'application/json');Supabase Matchers
expect({ data, error }).toBeSupabaseSuccess();
expect({ data, error }).toBeSupabaseError('not found');
expect({ data, error }).toHaveSupabaseData([{ id: '1' }]);Auth Matchers
expect(user).toHaveRole('admin');
expect(user).toHaveCredits(100);
expect(user).toHaveCredits(50, 'at least');
expect(session).toBeValidSession();
expect(session).toBeExpiredSession();Date Matchers
expect(date).toBeWithinRange('2024-01-01', '2024-12-31');
expect(createdAt).toBeRecent(5000); // Within 5 secondsFinancial Matchers
expect(total).toEqualCurrency(99.99);
expect({ credits: 1000, debits: 750 }).toBalance(250);Vitest Preset (@te-code/testing/vitest-preset)
import { defineConfig } from 'vitest/config';
import {
teVitestConfig,
teVitestConfigDom,
mergeWithTePreset,
} from '@te-code/testing/vitest-preset';
// Basic Node.js project
export default defineConfig(teVitestConfig);
// React/DOM project
export default defineConfig(teVitestConfigDom);
// With customizations
export default defineConfig(
mergeWithTePreset({
test: {
setupFiles: ['./test/setup.ts'],
coverage: {
thresholds: {
lines: 80,
},
},
},
})
);Best Practices
Reset State Between Tests
import { resetSupabaseMocks, resetUserCounter, resetFinancialCounters } from '@te-code/testing';
afterEach(() => {
resetSupabaseMocks();
resetUserCounter();
resetFinancialCounters();
});Use Factories for Unique Data
// Good - unique IDs each time
const user1 = createUser({ name: 'Alice' });
const user2 = createUser({ name: 'Bob' });
// Avoid - shared fixtures can cause test pollution
const user = users.basic; // Use for read-only scenariosType Safety
import type { TestUser, TestTransaction } from '@te-code/testing';
function processUser(user: TestUser) {
// Full type inference
}Project Structure
@te-code/testing/
├── src/
│ ├── index.ts # Main entry point
│ ├── types.ts # Type definitions
│ ├── mocks/
│ │ ├── index.ts
│ │ ├── supabase.ts
│ │ ├── teneo-auth.ts
│ │ ├── stripe.ts
│ │ └── next-api.ts
│ ├── fixtures/
│ │ ├── index.ts
│ │ ├── users.ts
│ │ └── financial.ts
│ ├── helpers/
│ │ └── index.ts
│ ├── matchers/
│ │ └── index.ts
│ └── vitest-preset.ts
└── package.jsonPython Testing Patterns
While this package focuses on TypeScript/Vitest testing, we also maintain patterns for Python automation workflows:
Covers:
- Testing external CLI dependencies (Claude CLI, git, npm, etc.)
- Pre-flight validation for automation workflows
- Cost-aware testing for AI operations
- Layered test architecture (Infrastructure → Environment → Execution)
- Safe, non-destructive test tasks
- Dependency-aware test results
Use when testing:
- Overnight task runners
- CLI integrations
- AI-powered automation
- Python automation scripts
License
MIT
