thrilled-be-testing
Version:
Testing utilities and helpers package with Jest, Supertest, and database testing support for Express applications
354 lines (353 loc) • 11.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.MockFactories = exports.DatabaseMockUtils = exports.AuthMockUtils = exports.createMockPaginatedResponse = exports.createMockPagination = exports.createMockValidationError = exports.createMockErrorResponse = exports.createMockApiResponse = exports.createMockDatabaseRecord = exports.createMockJwtPayload = exports.createMockSession = exports.createMockUser = exports.MockDataFactory = void 0;
/**
* Mock Data Factory
* Generates consistent test data using configurable factories
*/
class MockDataFactory {
static sequence = new Map();
/**
* Set global seed for consistent test data (resets sequences)
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
static setSeed(_seed) {
// Reset sequences for consistent test data
this.sequence.clear();
}
/**
* Get next sequence number for a given key
*/
static getSequence(key) {
const current = this.sequence.get(key) || 0;
const next = current + 1;
this.sequence.set(key, next);
return next;
}
/**
* Generate random string
*/
static randomString(length = 10, prefix = '') {
const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
let result = prefix;
for (let i = 0; i < length; i++) {
result += chars.charAt(Math.floor(Math.random() * chars.length));
}
return result;
}
/**
* Generate random number within range
*/
static randomNumber(min = 1, max = 1000) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
/**
* Generate random email
*/
static randomEmail(domain = 'example.com') {
const username = this.randomString(8, 'user');
return `${username}@${domain}`;
}
/**
* Generate random phone number
*/
static randomPhone(countryCode = '+1') {
const areaCode = this.randomNumber(200, 999);
const exchange = this.randomNumber(200, 999);
const number = this.randomNumber(1000, 9999);
return `${countryCode}${areaCode}${exchange}${number}`;
}
/**
* Generate random date within range
*/
static randomDate(startDate, endDate) {
const start = startDate || new Date(2020, 0, 1);
const end = endDate || new Date();
return new Date(start.getTime() + Math.random() * (end.getTime() - start.getTime()));
}
/**
* Pick random item from array
*/
static randomChoice(items) {
return items[Math.floor(Math.random() * items.length)];
}
/**
* Generate multiple items using a factory
*/
static generateMultiple(factory, count, options = {}) {
const items = [];
for (let i = 0; i < count; i++) {
const overrides = options.sequence ? { id: i + 1 } : {};
items.push(factory(overrides));
}
return items;
}
}
exports.MockDataFactory = MockDataFactory;
/**
* User Mock Factory
*/
const createMockUser = (overrides = {}) => {
const sequence = MockDataFactory['getSequence']('user');
return {
id: sequence,
email: `user${sequence}@example.com`,
name: `Test User ${sequence}`,
first_name: `First${sequence}`,
last_name: `Last${sequence}`,
phone: MockDataFactory.randomPhone(),
address: `${MockDataFactory.randomNumber(100, 999)} Test St`,
role: MockDataFactory.randomChoice(['user', 'admin', 'moderator']),
language_preference: 'en',
is_active: true,
created_at: MockDataFactory.randomDate(),
updated_at: new Date(),
...overrides,
};
};
exports.createMockUser = createMockUser;
/**
* Session Mock Factory
*/
const createMockSession = (overrides = {}) => {
const sequence = MockDataFactory['getSequence']('session');
return {
id: `session-${sequence}`,
user_id: sequence,
device_info: {
userAgent: 'Mozilla/5.0 (Test Browser)',
ip: '192.168.1.100',
platform: 'Test Platform',
},
expires_at: new Date(Date.now() + 24 * 60 * 60 * 1000), // 24 hours
created_at: new Date(),
last_accessed: new Date(),
is_active: true,
...overrides,
};
};
exports.createMockSession = createMockSession;
/**
* JWT Token Mock Factory
*/
const createMockJwtPayload = (overrides = {}) => {
const sequence = MockDataFactory['getSequence']('jwt');
return {
userId: `user-${sequence}`,
sessionId: `session-${sequence}`,
roles: ['user'],
permissions: ['read', 'write'],
userData: {
email: `user${sequence}@example.com`,
name: `Test User ${sequence}`,
},
iat: Math.floor(Date.now() / 1000),
exp: Math.floor(Date.now() / 1000) + 3600, // 1 hour
...overrides,
};
};
exports.createMockJwtPayload = createMockJwtPayload;
/**
* Database Record Mock Factory
*/
const createMockDatabaseRecord = (overrides = {}) => {
const sequence = MockDataFactory['getSequence']('record');
return {
id: sequence,
created_at: new Date(),
updated_at: new Date(),
version: 1,
...overrides,
};
};
exports.createMockDatabaseRecord = createMockDatabaseRecord;
/**
* API Response Mock Factory
*/
const createMockApiResponse = (overrides = {}) => {
return {
success: true,
data: null,
message: 'Operation completed successfully',
timestamp: new Date().toISOString(),
request_id: MockDataFactory.randomString(16),
...overrides,
};
};
exports.createMockApiResponse = createMockApiResponse;
/**
* Error Response Mock Factory
*/
const createMockErrorResponse = (overrides = {}) => {
return {
success: false,
error: {
code: 'GENERIC_ERROR',
message: 'An error occurred',
details: {},
},
timestamp: new Date().toISOString(),
request_id: MockDataFactory.randomString(16),
...overrides,
};
};
exports.createMockErrorResponse = createMockErrorResponse;
/**
* Validation Error Mock Factory
*/
const createMockValidationError = (overrides = {}) => {
return {
success: false,
error: {
code: 'VALIDATION_ERROR',
message: 'Validation failed',
details: [
{
field: 'email',
message: 'Invalid email format',
value: 'invalid-email',
},
],
},
timestamp: new Date().toISOString(),
request_id: MockDataFactory.randomString(16),
...overrides,
};
};
exports.createMockValidationError = createMockValidationError;
/**
* Pagination Mock Factory
*/
const createMockPagination = (overrides = {}) => {
return {
page: 1,
limit: 10,
total: 100,
totalPages: 10,
hasNext: true,
hasPrev: false,
...overrides,
};
};
exports.createMockPagination = createMockPagination;
/**
* Paginated Response Mock Factory
*/
const createMockPaginatedResponse = (overrides = {}) => {
const pagination = (0, exports.createMockPagination)(overrides.pagination);
return {
success: true,
data: [],
pagination,
timestamp: new Date().toISOString(),
request_id: MockDataFactory.randomString(16),
...overrides,
};
};
exports.createMockPaginatedResponse = createMockPaginatedResponse;
/**
* Auth Mock Utilities
*/
class AuthMockUtils {
/**
* Create mock JWT token
*/
static createMockJwtToken(options = {}) {
const payload = (0, exports.createMockJwtPayload)({
userId: options.userId,
sessionId: options.sessionId,
roles: options.roles,
permissions: options.permissions,
});
// In a real implementation, this would use the actual JWT library
// For testing, we create a fake token that can be decoded
const header = Buffer.from(JSON.stringify({ alg: 'HS256', typ: 'JWT' })).toString('base64');
const payloadEncoded = Buffer.from(JSON.stringify(payload)).toString('base64');
const signature = MockDataFactory.randomString(32);
return `${header}.${payloadEncoded}.${signature}`;
}
/**
* Create mock authentication headers
*/
static createAuthHeaders(token) {
return {
'Authorization': `Bearer ${token || this.createMockJwtToken()}`,
'Content-Type': 'application/json',
};
}
/**
* Create mock user session
*/
static createMockUserSession(options = {}) {
return (0, exports.createMockSession)({
user_id: options.userId ? parseInt(options.userId, 10) : undefined,
...options,
});
}
}
exports.AuthMockUtils = AuthMockUtils;
/**
* Database Mock Utilities
*/
class DatabaseMockUtils {
/**
* Create mock database connection
*/
static createMockConnection() {
return {
query: jest.fn().mockResolvedValue({ rows: [], rowCount: 0 }),
connect: jest.fn().mockResolvedValue({
query: jest.fn().mockResolvedValue({ rows: [], rowCount: 0 }),
release: jest.fn(),
}),
end: jest.fn().mockResolvedValue(undefined),
on: jest.fn(),
};
}
/**
* Create mock query result
*/
static createMockQueryResult(rows = [], rowCount) {
return {
rows,
rowCount: rowCount ?? rows.length,
command: 'SELECT',
oid: 0,
fields: [],
};
}
/**
* Setup database mocks for testing
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
static setupDatabaseMocks(_options = {}) {
const mockConnection = this.createMockConnection();
// Mock common queries
// eslint-disable-next-line @typescript-eslint/no-unused-vars
mockConnection.query.mockImplementation((query, _params) => {
if (query.includes('SELECT 1')) {
return Promise.resolve(this.createMockQueryResult([{ '?column?': 1 }]));
}
if (query.includes('COUNT(*)')) {
return Promise.resolve(this.createMockQueryResult([{ count: '0' }]));
}
return Promise.resolve(this.createMockQueryResult());
});
return mockConnection;
}
}
exports.DatabaseMockUtils = DatabaseMockUtils;
/**
* Export all mock factories
*/
exports.MockFactories = {
User: exports.createMockUser,
Session: exports.createMockSession,
JwtPayload: exports.createMockJwtPayload,
DatabaseRecord: exports.createMockDatabaseRecord,
ApiResponse: exports.createMockApiResponse,
ErrorResponse: exports.createMockErrorResponse,
ValidationError: exports.createMockValidationError,
Pagination: exports.createMockPagination,
PaginatedResponse: exports.createMockPaginatedResponse,
};