Files
dbis_core-lite/tests/utils/test-helpers.ts
2026-02-09 21:51:45 -08:00

144 lines
3.9 KiB
TypeScript

import { Pool } from 'pg';
import { OperatorService } from '../../src/gateway/auth/operator-service';
import { OperatorRole } from '../../src/gateway/auth/types';
import { JWTService } from '../../src/gateway/auth/jwt';
import type { PaymentRequest } from '../../src/gateway/validation/payment-validation';
import { PaymentType, Currency } from '../../src/models/payment';
/**
* Test utilities and helpers
*/
export class TestHelpers {
private static testDbPool: Pool | null = null;
/**
* Get test database connection
*/
static getTestDb(): Pool {
if (!this.testDbPool) {
this.testDbPool = new Pool({
connectionString: process.env.TEST_DATABASE_URL || 'postgresql://postgres:postgres@localhost:5432/dbis_core_test',
});
}
return this.testDbPool;
}
/**
* Clean test database
* Fast cleanup with timeout protection
*/
static async cleanDatabase(): Promise<void> {
const pool = this.getTestDb();
let client;
try {
client = await pool.connect();
// Set statement timeout to prevent hanging (5 seconds)
await client.query('SET statement_timeout = 5000');
// Fast cleanup - just delete test operators, skip truncate to save time
// Tests will handle their own data cleanup
await client.query('DELETE FROM operators WHERE operator_id LIKE $1 OR operator_id LIKE $2', ['E2E_%', 'TEST_%']);
} catch (error: any) {
// Ignore cleanup errors - tests can continue
// Don't log warnings in test environment to reduce noise
} finally {
if (client) {
try {
client.release();
} catch (releaseError: any) {
// Ignore release errors
}
}
}
}
/**
* Create test operator
* Handles duplicate key errors by returning existing operator
* Has timeout protection to prevent hanging
*/
static async createTestOperator(
operatorId: string,
role: OperatorRole,
password: string = 'Test123!@#'
) {
const pool = this.getTestDb();
// First, try to get existing operator (faster)
try {
const result = await pool.query(
'SELECT * FROM operators WHERE operator_id = $1',
[operatorId]
);
if (result.rows.length > 0) {
return result.rows[0];
}
} catch (error: any) {
// Ignore query errors, continue to create
}
// If not found, create new operator
try {
return await OperatorService.createOperator(
operatorId,
`Test ${role}`,
password,
role,
`${operatorId.toLowerCase()}@test.com`,
true // Skip password policy for tests
);
} catch (error: any) {
// If operator already exists (race condition), try to get it again
if (error.message?.includes('duplicate key') || error.message?.includes('already exists')) {
const result = await pool.query(
'SELECT * FROM operators WHERE operator_id = $1',
[operatorId]
);
if (result.rows.length > 0) {
return result.rows[0];
}
}
throw error;
}
}
/**
* Generate test JWT token
*/
static generateTestToken(operatorId: string, id: string, role: OperatorRole): string {
return JWTService.generateToken({
operatorId,
id,
role,
});
}
/**
* Create test payment request
*/
static createTestPaymentRequest(): PaymentRequest {
return {
type: PaymentType.CUSTOMER_CREDIT_TRANSFER,
amount: 1000.00,
currency: Currency.USD,
senderAccount: 'ACC001',
senderBIC: 'TESTBIC1',
receiverAccount: 'ACC002',
receiverBIC: 'TESTBIC2',
beneficiaryName: 'Test Beneficiary',
purpose: 'Test payment',
};
}
/**
* Sleep utility for tests
*/
static sleep(ms: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms));
}
}