import { DataSource } from 'typeorm'; import { JwtService } from '@nestjs/jwt'; import * as bcrypt from 'bcrypt'; import { v4 as uuidv4 } from 'uuid'; export interface TestUser { id: string; phone: string; name: string; passwordHash: string; accessToken?: string; refreshToken?: string; } export interface TestStore { id: string; ownerId: string; name: string; giro: string; address: string; } export async function createTestUser( dataSource: DataSource, jwtService: JwtService, overrides: Partial<{ phone: string; name: string; password: string }> = {}, ): Promise { const id = uuidv4(); const phone = overrides.phone ?? `+52${Date.now().toString().slice(-10)}`; const name = overrides.name ?? 'Test User'; const password = overrides.password ?? 'testpassword123'; const passwordHash = await bcrypt.hash(password, 10); await dataSource.query( `INSERT INTO users (id, phone, name, "passwordHash", role, "isActive") VALUES ($1, $2, $3, $4, 'USER', true)`, [id, phone, name, passwordHash], ); // Create credit balance for user await dataSource.query( `INSERT INTO credit_balances (id, "userId", balance, "totalPurchased", "totalConsumed", "totalFromReferrals") VALUES ($1, $2, 100, 100, 0, 0)`, [uuidv4(), id], ); // Generate tokens const accessToken = jwtService.sign({ sub: id }); const refreshToken = jwtService.sign( { sub: id }, { secret: 'test-refresh-secret', expiresIn: '7d' }, ); // Save refresh token await dataSource.query( `INSERT INTO refresh_tokens (id, "userId", token, "expiresAt", "isRevoked") VALUES ($1, $2, $3, $4, false)`, [uuidv4(), id, refreshToken, new Date(Date.now() + 7 * 24 * 60 * 60 * 1000)], ); return { id, phone, name, passwordHash, accessToken, refreshToken, }; } export async function createTestStore( dataSource: DataSource, ownerId: string, overrides: Partial<{ name: string; giro: string; address: string }> = {}, ): Promise { const id = uuidv4(); const name = overrides.name ?? 'Test Store'; const giro = overrides.giro ?? 'Abarrotes'; const address = overrides.address ?? 'Test Address 123'; await dataSource.query( `INSERT INTO stores (id, "ownerId", name, giro, address, "isActive") VALUES ($1, $2, $3, $4, $5, true)`, [id, ownerId, name, giro, address], ); return { id, ownerId, name, giro, address }; } export async function createTestCreditPackages( dataSource: DataSource, ): Promise { await dataSource.query(` INSERT INTO credit_packages (id, name, description, credits, "priceMXN", "isPopular", "isActive", "sortOrder") VALUES (uuid_generate_v4(), 'Starter', 'Perfecto para probar', 10, 49.00, false, true, 1), (uuid_generate_v4(), 'Basico', 'Para uso regular', 30, 129.00, false, true, 2), (uuid_generate_v4(), 'Popular', 'El mas vendido', 75, 299.00, true, true, 3) ON CONFLICT DO NOTHING; `); } export async function createTestInventoryItem( dataSource: DataSource, storeId: string, overrides: Partial<{ name: string; brand: string; quantity: number; price: number; }> = {}, ): Promise { const id = uuidv4(); const name = overrides.name ?? 'Test Product'; const brand = overrides.brand ?? 'Test Brand'; const quantity = overrides.quantity ?? 10; const price = overrides.price ?? 99.99; await dataSource.query( `INSERT INTO inventory_items (id, "storeId", name, brand, quantity, "unitPrice", "isActive") VALUES ($1, $2, $3, $4, $5, $6, true)`, [id, storeId, name, brand, quantity, price], ); return id; } export async function createTestNotification( dataSource: DataSource, userId: string, overrides: Partial<{ type: string; title: string; body: string; isRead: boolean; }> = {}, ): Promise { const id = uuidv4(); const type = overrides.type ?? 'SYSTEM'; const title = overrides.title ?? 'Test Notification'; const body = overrides.body ?? 'This is a test notification'; const isRead = overrides.isRead ?? false; await dataSource.query( `INSERT INTO notifications (id, "userId", type, title, body, "isRead") VALUES ($1, $2, $3, $4, $5, $6)`, [id, userId, type, title, body, isRead], ); return id; } export function authHeader(token: string): { Authorization: string } { return { Authorization: `Bearer ${token}` }; }