-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Labels
Description
code logic example
// test-setup/database.ts
import { Pool } from 'pg';
import { Knex, knex } from 'knex';
export class TestDatabase {
private db: Knex;
constructor() {
// Connect to test database
this.db = knex({
client: 'postgresql',
connection: process.env.TEST_DATABASE_URL,
pool: { min: 2, max: 10 }
});
}
async setup() {
try {
// Run migrations to ensure schema is up to date
await this.db.migrate.latest({
directory: './migrations'
});
// Run any base seeds needed (e.g., system configs, constants)
await this.db.seed.run({
directory: './seeds/base'
});
} catch (error) {
console.error('Database setup failed:', error);
throw error;
}
}
async cleanup() {
// Clean up all test data - order matters due to foreign keys
await this.db.raw('TRUNCATE TABLE organizations CASCADE');
await this.db.raw('TRUNCATE TABLE users CASCADE');
await this.db.raw('TRUNCATE TABLE wallets CASCADE');
// ... other tables
}
async createTestData(testCase: string) {
// Create isolated data for specific test case
const testOrg = await this.db('organizations').insert({
name: `Test Org ${testCase}`,
created_at: new Date(),
// ... other fields
}).returning('*');
return testOrg[0];
}
}
// test-setup/api-client.ts
export class TestApiClient {
private baseUrl: string;
private authToken?: string;
constructor() {
this.baseUrl = process.env.API_URL!;
}
async authenticate() {
// Get auth token for API requests
const response = await fetch(`${this.baseUrl}/auth/login`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: process.env.TEST_ADMIN_EMAIL,
password: process.env.TEST_ADMIN_PASSWORD
})
});
const { token } = await response.json();
this.authToken = token;
}
async createOrganization(data: any) {
const response = await fetch(`${this.baseUrl}/api/organizations`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${this.authToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
return response.json();
}
// Add other API methods as needed
}
// test-setup/test-context.ts
import { test as base } from '@playwright/test';
import { TestDatabase } from './database';
import { TestApiClient } from './api-client';
// Define your test fixtures
type TestFixtures = {
db: TestDatabase;
api: TestApiClient;
testOrg: any;
};
// Create the test with fixtures
export const test = base.extend<TestFixtures>({
// Database fixture - shared across all tests in a worker
db: [async ({}, use) => {
const db = new TestDatabase();
await db.setup();
await use(db);
await db.cleanup();
}, { scope: 'worker' }],
// API client fixture - new for each test
api: async ({}, use) => {
const api = new TestApiClient();
await api.authenticate();
await use(api);
},
// Test organization fixture - new for each test
testOrg: async ({ db, api }, use) => {
// Create test organization using API
const org = await api.createOrganization({
name: `Test Org ${Date.now()}`,
type: 'business'
});
await use(org);
// Cleanup after test
await db.cleanup();
}
});
// Example test using the setup
test('complete organization onboarding', async ({ page, testOrg, api }) => {
// Start from onboarding page with real org ID
await page.goto(`${process.env.PORTAL_URL}/onboarding/${testOrg.id}`);
// Fill onboarding form
await page.fill('[data-testid="business-name"]', 'Updated Name Inc');
await page.fill('[data-testid="tax-id"]', '123456789');
await page.click('[data-testid="submit-button"]');
// Verify in real database via API
const updatedOrg = await api.getOrganization(testOrg.id);
expect(updatedOrg.name).toBe('Updated Name Inc');
expect(updatedOrg.status).toBe('active');
});