const { Pool } = require('pg'); class TestDatabase { constructor() { this.pool = null; this.isConnected = false; } async connect() { if (this.isConnected) { return; } try { this.pool = new Pool({ host: process.env.DB_HOST || 'localhost', port: process.env.DB_PORT || 5432, database: process.env.DB_NAME || 'bookmark_manager_test', user: process.env.DB_USER || 'postgres', password: process.env.DB_PASSWORD || 'password', max: 5, // Smaller pool for tests idleTimeoutMillis: 30000, connectionTimeoutMillis: 2000, }); // Test connection const client = await this.pool.connect(); client.release(); this.isConnected = true; console.log('Test database connected successfully'); } catch (error) { console.error('Test database connection failed:', error.message); this.isConnected = false; throw error; } } async query(text, params = []) { if (!this.isConnected || !this.pool) { throw new Error('Test database not connected'); } try { const result = await this.pool.query(text, params); return result; } catch (error) { console.error('Test database query error:', error.message); throw error; } } async disconnect() { if (this.pool) { await this.pool.end(); this.pool = null; this.isConnected = false; console.log('Test database disconnected'); } } async setupTables() { if (!this.isConnected) { throw new Error('Database not connected'); } try { // Create users table await this.query(` CREATE TABLE IF NOT EXISTS users ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), email VARCHAR(255) UNIQUE NOT NULL, password_hash VARCHAR(255) NOT NULL, is_verified BOOLEAN DEFAULT FALSE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, last_login TIMESTAMP, verification_token VARCHAR(255), reset_token VARCHAR(255), reset_expires TIMESTAMP ) `); // Create bookmarks table await this.query(` CREATE TABLE IF NOT EXISTS bookmarks ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, title VARCHAR(500) NOT NULL, url TEXT NOT NULL, folder VARCHAR(255) DEFAULT '', add_date TIMESTAMP NOT NULL, last_modified TIMESTAMP, icon TEXT, status VARCHAR(20) DEFAULT 'unknown', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) `); // Create indexes await this.query('CREATE INDEX IF NOT EXISTS idx_users_email ON users(email)'); await this.query('CREATE INDEX IF NOT EXISTS idx_bookmarks_user_id ON bookmarks(user_id)'); console.log('Test database tables created successfully'); } catch (error) { console.error('Failed to setup test database tables:', error.message); throw error; } } async cleanupTables() { if (!this.isConnected) { return; } try { await this.query('DELETE FROM bookmarks'); await this.query('DELETE FROM users'); console.log('Test database tables cleaned up'); } catch (error) { console.error('Failed to cleanup test database tables:', error.message); } } } module.exports = new TestDatabase();