diff --git a/server/models/index.js b/server/models/index.js index b4bee75..232fcb3 100644 --- a/server/models/index.js +++ b/server/models/index.js @@ -5,86 +5,98 @@ if (process.env.NODE_ENV !== 'test') { require('dotenv').config(); } -// Configure database based on environment -let sequelize; -if (process.env.NODE_ENV === 'test') { - // Use SQLite file database for testing to allow sharing between modules - sequelize = new Sequelize({ - dialect: 'sqlite', - storage: './test.db', - logging: false - }); +// Check if models are already initialized (for tests) +if (global.__TEST_MODELS__) { + module.exports = global.__TEST_MODELS__; } else { - // Use PostgreSQL for production/development - sequelize = new Sequelize( - process.env.DB_NAME || 'drone_detection', - process.env.DB_USER || 'postgres', - process.env.DB_PASSWORD || 'password', - { - host: process.env.DB_HOST || 'localhost', - port: process.env.DB_PORT || 5432, - dialect: 'postgres', - logging: process.env.NODE_ENV === 'development' ? console.log : false, - pool: { - max: 5, - min: 0, - acquire: 30000, - idle: 10000 + // Configure database based on environment + let sequelize; + if (process.env.NODE_ENV === 'test') { + // Use SQLite in-memory database for testing + sequelize = new Sequelize({ + dialect: 'sqlite', + storage: ':memory:', + logging: false + }); + } else { + // Use PostgreSQL for production/development + sequelize = new Sequelize( + process.env.DB_NAME || 'drone_detection', + process.env.DB_USER || 'postgres', + process.env.DB_PASSWORD || 'password', + { + host: process.env.DB_HOST || 'localhost', + port: process.env.DB_PORT || 5432, + dialect: 'postgres', + logging: process.env.NODE_ENV === 'development' ? console.log : false, + pool: { + max: 5, + min: 0, + acquire: 30000, + idle: 10000 + } } - } - ); + ); + } + + // Import models + const Device = require('./Device')(sequelize); + const DroneDetection = require('./DroneDetection')(sequelize); + const Heartbeat = require('./Heartbeat')(sequelize); + const User = require('./User')(sequelize); + const AlertRule = require('./AlertRule')(sequelize); + const AlertLog = require('./AlertLog')(sequelize); + const Tenant = require('./Tenant')(sequelize); + const ManagementUser = require('./ManagementUser')(sequelize); + + // Define associations + Device.hasMany(DroneDetection, { foreignKey: 'device_id', as: 'detections' }); + DroneDetection.belongsTo(Device, { foreignKey: 'device_id', as: 'device' }); + + Device.hasMany(Heartbeat, { foreignKey: 'device_id', as: 'heartbeats' }); + Heartbeat.belongsTo(Device, { foreignKey: 'device_id', as: 'device' }); + + User.hasMany(AlertRule, { foreignKey: 'user_id', as: 'alertRules' }); + AlertRule.belongsTo(User, { foreignKey: 'user_id', as: 'user' }); + + AlertRule.hasMany(AlertLog, { foreignKey: 'alert_rule_id', as: 'logs' }); + AlertLog.belongsTo(AlertRule, { foreignKey: 'alert_rule_id', as: 'rule' }); + + DroneDetection.hasMany(AlertLog, { foreignKey: 'detection_id', as: 'alerts' }); + AlertLog.belongsTo(DroneDetection, { foreignKey: 'detection_id', as: 'detection' }); + + // Tenant associations + Tenant.hasMany(User, { foreignKey: 'tenant_id', as: 'users' }); + User.belongsTo(Tenant, { foreignKey: 'tenant_id', as: 'tenant' }); + + Tenant.hasMany(Device, { foreignKey: 'tenant_id', as: 'devices' }); + Device.belongsTo(Tenant, { foreignKey: 'tenant_id', as: 'tenant' }); + + // Auto-sync database in test mode + if (process.env.NODE_ENV === 'test') { + sequelize.sync({ force: true }).then(() => { + console.log('🗄️ Test database tables created'); + }).catch(error => { + console.error('❌ Test database sync failed:', error); + }); + } + + const models = { + sequelize, + Device, + DroneDetection, + Heartbeat, + User, + AlertRule, + AlertLog, + Tenant, + ManagementUser + }; + + // Store models globally for tests + if (process.env.NODE_ENV === 'test') { + global.__TEST_MODELS__ = models; + } + + module.exports = models; } - -// Import models -const Device = require('./Device')(sequelize); -const DroneDetection = require('./DroneDetection')(sequelize); -const Heartbeat = require('./Heartbeat')(sequelize); -const User = require('./User')(sequelize); -const AlertRule = require('./AlertRule')(sequelize); -const AlertLog = require('./AlertLog')(sequelize); -const Tenant = require('./Tenant')(sequelize); -const ManagementUser = require('./ManagementUser')(sequelize); - -// Define associations -Device.hasMany(DroneDetection, { foreignKey: 'device_id', as: 'detections' }); -DroneDetection.belongsTo(Device, { foreignKey: 'device_id', as: 'device' }); - -Device.hasMany(Heartbeat, { foreignKey: 'device_id', as: 'heartbeats' }); -Heartbeat.belongsTo(Device, { foreignKey: 'device_id', as: 'device' }); - -User.hasMany(AlertRule, { foreignKey: 'user_id', as: 'alertRules' }); -AlertRule.belongsTo(User, { foreignKey: 'user_id', as: 'user' }); - -AlertRule.hasMany(AlertLog, { foreignKey: 'alert_rule_id', as: 'logs' }); -AlertLog.belongsTo(AlertRule, { foreignKey: 'alert_rule_id', as: 'rule' }); - -DroneDetection.hasMany(AlertLog, { foreignKey: 'detection_id', as: 'alerts' }); -AlertLog.belongsTo(DroneDetection, { foreignKey: 'detection_id', as: 'detection' }); - -// Tenant associations -Tenant.hasMany(User, { foreignKey: 'tenant_id', as: 'users' }); -User.belongsTo(Tenant, { foreignKey: 'tenant_id', as: 'tenant' }); - -Tenant.hasMany(Device, { foreignKey: 'tenant_id', as: 'devices' }); -Device.belongsTo(Tenant, { foreignKey: 'tenant_id', as: 'tenant' }); - -// Auto-sync database in test mode -if (process.env.NODE_ENV === 'test') { - sequelize.sync({ force: true }).then(() => { - console.log('🗄️ Test database tables created'); - }).catch(error => { - console.error('❌ Test database sync failed:', error); - }); -} - -module.exports = { - sequelize, - Device, - DroneDetection, - Heartbeat, - User, - AlertRule, - AlertLog, - Tenant, - ManagementUser -}; diff --git a/server/tests/setup.js b/server/tests/setup.js index 8399ba2..9511cb3 100644 --- a/server/tests/setup.js +++ b/server/tests/setup.js @@ -1,5 +1,21 @@ // IMPORTANT: Set environment variables FIRST, before any other imports -process.env.NODE_ENV = 'test'; +proces // Return test context + models = { + sequelize, + Device, + DroneDetection, + Heartbeat, + User, + AlertRule, + AlertLog, + Tenant, + ManagementUser + }; + + // Store models globally so routes can access them + global.__TEST_MODELS__ = models; + + return { sequelize, models };est'; process.env.JWT_SECRET = 'test-jwt-secret-key-for-testing-only'; process.env.DATABASE_URL = ':memory:'; process.env.DB_DIALECT = 'sqlite'; @@ -20,7 +36,7 @@ afterEach(() => { // Test database configuration const testDatabase = { dialect: 'sqlite', - storage: './test.db', // Use same file database as models/index.js + storage: ':memory:', // In-memory database for fast tests logging: false, // Disable SQL logging in tests sync: { force: true } // Always recreate tables for tests }; @@ -32,6 +48,9 @@ let models; * Setup test environment before all tests */ async function setupTestEnvironment() { + // Clear any existing global models + delete global.__TEST_MODELS__; + // Create test database connection sequelize = new Sequelize(testDatabase);