394 lines
15 KiB
JavaScript
394 lines
15 KiB
JavaScript
const { describe, it, beforeEach, afterEach, before, after } = require('mocha');
|
|
const { expect } = require('chai');
|
|
const sinon = require('sinon');
|
|
const request = require('supertest');
|
|
const express = require('express');
|
|
const detectionsRoutes = require('../../routes/detections');
|
|
const { authenticateToken } = require('../../middleware/auth');
|
|
const { setupTestEnvironment, teardownTestEnvironment, cleanDatabase, createTestUser, createTestTenant, createTestDevice, createTestDetection, generateTestToken } = require('../setup');
|
|
|
|
describe('Detections Routes', () => {
|
|
let app, models, sequelize;
|
|
|
|
before(async () => {
|
|
({ models, sequelize } = await setupTestEnvironment());
|
|
|
|
// Setup express app for testing
|
|
app = express();
|
|
app.use(express.json());
|
|
app.use(authenticateToken);
|
|
app.use('/detections', detectionsRoutes);
|
|
});
|
|
|
|
after(async () => {
|
|
await teardownTestEnvironment();
|
|
});
|
|
|
|
beforeEach(async () => {
|
|
await cleanDatabase();
|
|
});
|
|
|
|
describe('GET /detections', () => {
|
|
it('should return detections for user tenant', async () => {
|
|
const tenant = await createTestTenant({ slug: 'test-tenant' });
|
|
const user = await createTestUser({ tenant_id: tenant.id });
|
|
const device = await createTestDevice({ tenant_id: tenant.id });
|
|
const detection = await createTestDetection({ device_id: device.id });
|
|
const token = generateTestToken(user, tenant);
|
|
|
|
const response = await request(app)
|
|
.get('/detections')
|
|
.set('Authorization', `Bearer ${token}`);
|
|
|
|
expect(response.status).to.equal(200);
|
|
expect(response.body.success).to.be.true;
|
|
expect(response.body.data.detections).to.be.an('array');
|
|
expect(response.body.data.detections).to.have.length(1);
|
|
expect(response.body.data.detections[0].id).to.equal(detection.id);
|
|
});
|
|
|
|
it('should not return detections from other tenants', async () => {
|
|
const tenant1 = await createTestTenant({ slug: 'tenant1' });
|
|
const tenant2 = await createTestTenant({ slug: 'tenant2' });
|
|
|
|
const user1 = await createTestUser({ tenant_id: tenant1.id });
|
|
const device1 = await createTestDevice({ tenant_id: tenant1.id });
|
|
const device2 = await createTestDevice({ tenant_id: tenant2.id });
|
|
|
|
await createTestDetection({ device_id: device1.id });
|
|
await createTestDetection({ device_id: device2.id });
|
|
|
|
const token = generateTestToken(user1, tenant1);
|
|
|
|
const response = await request(app)
|
|
.get('/detections')
|
|
.set('Authorization', `Bearer ${token}`);
|
|
|
|
expect(response.status).to.equal(200);
|
|
expect(response.body.data.detections).to.have.length(1);
|
|
});
|
|
|
|
it('should support pagination', async () => {
|
|
const tenant = await createTestTenant();
|
|
const user = await createTestUser({ tenant_id: tenant.id });
|
|
const device = await createTestDevice({ tenant_id: tenant.id });
|
|
|
|
// Create multiple detections
|
|
for (let i = 0; i < 15; i++) {
|
|
await createTestDetection({ device_id: device.id });
|
|
}
|
|
|
|
const token = generateTestToken(user, tenant);
|
|
|
|
const response = await request(app)
|
|
.get('/detections?page=1&limit=10')
|
|
.set('Authorization', `Bearer ${token}`);
|
|
|
|
expect(response.status).to.equal(200);
|
|
expect(response.body.data.detections).to.have.length(10);
|
|
expect(response.body.data.pagination.totalPages).to.equal(2);
|
|
expect(response.body.data.pagination.hasNextPage).to.be.true;
|
|
});
|
|
|
|
it('should support sorting', async () => {
|
|
const tenant = await createTestTenant();
|
|
const user = await createTestUser({ tenant_id: tenant.id });
|
|
const device = await createTestDevice({ tenant_id: tenant.id });
|
|
|
|
const detection1 = await createTestDetection({
|
|
device_id: device.id,
|
|
server_timestamp: new Date('2023-01-01')
|
|
});
|
|
const detection2 = await createTestDetection({
|
|
device_id: device.id,
|
|
server_timestamp: new Date('2023-01-02')
|
|
});
|
|
|
|
const token = generateTestToken(user, tenant);
|
|
|
|
const response = await request(app)
|
|
.get('/detections?sort=server_timestamp&order=desc')
|
|
.set('Authorization', `Bearer ${token}`);
|
|
|
|
expect(response.status).to.equal(200);
|
|
expect(response.body.data.detections[0].id).to.equal(detection2.id);
|
|
});
|
|
|
|
it('should support filtering by device', async () => {
|
|
const tenant = await createTestTenant();
|
|
const user = await createTestUser({ tenant_id: tenant.id });
|
|
const device1 = await createTestDevice({ tenant_id: tenant.id });
|
|
const device2 = await createTestDevice({ tenant_id: tenant.id });
|
|
|
|
await createTestDetection({ device_id: device1.id });
|
|
await createTestDetection({ device_id: device2.id });
|
|
|
|
const token = generateTestToken(user, tenant);
|
|
|
|
const response = await request(app)
|
|
.get(`/detections?device_id=${device1.id}`)
|
|
.set('Authorization', `Bearer ${token}`);
|
|
|
|
expect(response.status).to.equal(200);
|
|
expect(response.body.data.detections).to.have.length(1);
|
|
expect(response.body.data.detections[0].device_id).to.equal(device1.id);
|
|
});
|
|
|
|
it('should support filtering by drone type', async () => {
|
|
const tenant = await createTestTenant();
|
|
const user = await createTestUser({ tenant_id: tenant.id });
|
|
const device = await createTestDevice({ tenant_id: tenant.id });
|
|
|
|
await createTestDetection({ device_id: device.id, drone_type: 2 });
|
|
await createTestDetection({ device_id: device.id, drone_type: 3 });
|
|
|
|
const token = generateTestToken(user, tenant);
|
|
|
|
const response = await request(app)
|
|
.get('/detections?drone_type=2')
|
|
.set('Authorization', `Bearer ${token}`);
|
|
|
|
expect(response.status).to.equal(200);
|
|
expect(response.body.data.detections).to.have.length(1);
|
|
expect(response.body.data.detections[0].drone_type).to.equal(2);
|
|
});
|
|
|
|
it('should support filtering by date range', async () => {
|
|
const tenant = await createTestTenant();
|
|
const user = await createTestUser({ tenant_id: tenant.id });
|
|
const device = await createTestDevice({ tenant_id: tenant.id });
|
|
|
|
await createTestDetection({
|
|
device_id: device.id,
|
|
server_timestamp: new Date('2023-01-01')
|
|
});
|
|
await createTestDetection({
|
|
device_id: device.id,
|
|
server_timestamp: new Date('2023-02-01')
|
|
});
|
|
|
|
const token = generateTestToken(user, tenant);
|
|
|
|
const response = await request(app)
|
|
.get('/detections?start_date=2023-01-15&end_date=2023-02-15')
|
|
.set('Authorization', `Bearer ${token}`);
|
|
|
|
expect(response.status).to.equal(200);
|
|
expect(response.body.data.detections).to.have.length(1);
|
|
});
|
|
|
|
it('should exclude drone type 0 by default', async () => {
|
|
const tenant = await createTestTenant();
|
|
const user = await createTestUser({ tenant_id: tenant.id });
|
|
const device = await createTestDevice({ tenant_id: tenant.id });
|
|
|
|
await createTestDetection({ device_id: device.id, drone_type: 0 });
|
|
await createTestDetection({ device_id: device.id, drone_type: 2 });
|
|
|
|
const token = generateTestToken(user, tenant);
|
|
|
|
const response = await request(app)
|
|
.get('/detections')
|
|
.set('Authorization', `Bearer ${token}`);
|
|
|
|
expect(response.status).to.equal(200);
|
|
expect(response.body.data.detections).to.have.length(1);
|
|
expect(response.body.data.detections[0].drone_type).to.equal(2);
|
|
});
|
|
|
|
it('should enhance detections with drone type info', async () => {
|
|
const tenant = await createTestTenant();
|
|
const user = await createTestUser({ tenant_id: tenant.id });
|
|
const device = await createTestDevice({ tenant_id: tenant.id });
|
|
const detection = await createTestDetection({
|
|
device_id: device.id,
|
|
drone_type: 2
|
|
});
|
|
|
|
const token = generateTestToken(user, tenant);
|
|
|
|
const response = await request(app)
|
|
.get('/detections')
|
|
.set('Authorization', `Bearer ${token}`);
|
|
|
|
expect(response.status).to.equal(200);
|
|
const returnedDetection = response.body.data.detections[0];
|
|
expect(returnedDetection.drone_type_info).to.exist;
|
|
expect(returnedDetection.drone_type_info.name).to.exist;
|
|
expect(returnedDetection.drone_type_info.threat_level).to.exist;
|
|
});
|
|
|
|
it('should include device information', async () => {
|
|
const tenant = await createTestTenant();
|
|
const user = await createTestUser({ tenant_id: tenant.id });
|
|
const device = await createTestDevice({
|
|
tenant_id: tenant.id,
|
|
name: 'Test Device'
|
|
});
|
|
await createTestDetection({ device_id: device.id });
|
|
|
|
const token = generateTestToken(user, tenant);
|
|
|
|
const response = await request(app)
|
|
.get('/detections')
|
|
.set('Authorization', `Bearer ${token}`);
|
|
|
|
expect(response.status).to.equal(200);
|
|
const detection = response.body.data.detections[0];
|
|
expect(detection.device).to.exist;
|
|
expect(detection.device.name).to.equal('Test Device');
|
|
});
|
|
|
|
it('should reject request without tenant', async () => {
|
|
const user = await createTestUser();
|
|
const token = generateTestToken(user); // No tenant
|
|
|
|
const response = await request(app)
|
|
.get('/detections')
|
|
.set('Authorization', `Bearer ${token}`);
|
|
|
|
expect(response.status).to.equal(400);
|
|
expect(response.body.success).to.be.false;
|
|
expect(response.body.message).to.equal('Unable to determine tenant');
|
|
});
|
|
|
|
it('should reject request for inactive tenant', async () => {
|
|
const tenant = await createTestTenant({
|
|
slug: 'inactive-tenant',
|
|
is_active: false
|
|
});
|
|
const user = await createTestUser({ tenant_id: tenant.id });
|
|
const token = generateTestToken(user, tenant);
|
|
|
|
const response = await request(app)
|
|
.get('/detections')
|
|
.set('Authorization', `Bearer ${token}`);
|
|
|
|
expect(response.status).to.equal(404);
|
|
expect(response.body.success).to.be.false;
|
|
});
|
|
|
|
it('should handle invalid pagination parameters', async () => {
|
|
const tenant = await createTestTenant();
|
|
const user = await createTestUser({ tenant_id: tenant.id });
|
|
const token = generateTestToken(user, tenant);
|
|
|
|
const response = await request(app)
|
|
.get('/detections?page=-1&limit=1000')
|
|
.set('Authorization', `Bearer ${token}`);
|
|
|
|
expect(response.status).to.equal(200);
|
|
// Should use default values
|
|
expect(response.body.data.pagination.page).to.equal(1);
|
|
expect(response.body.data.pagination.limit).to.equal(20);
|
|
});
|
|
});
|
|
|
|
describe('GET /detections/:id', () => {
|
|
it('should return specific detection', async () => {
|
|
const tenant = await createTestTenant();
|
|
const user = await createTestUser({ tenant_id: tenant.id });
|
|
const device = await createTestDevice({ tenant_id: tenant.id });
|
|
const detection = await createTestDetection({ device_id: device.id });
|
|
const token = generateTestToken(user, tenant);
|
|
|
|
const response = await request(app)
|
|
.get(`/detections/${detection.id}`)
|
|
.set('Authorization', `Bearer ${token}`);
|
|
|
|
expect(response.status).to.equal(200);
|
|
expect(response.body.success).to.be.true;
|
|
expect(response.body.data.id).to.equal(detection.id);
|
|
});
|
|
|
|
it('should not return detection from other tenant', async () => {
|
|
const tenant1 = await createTestTenant({ slug: 'tenant1' });
|
|
const tenant2 = await createTestTenant({ slug: 'tenant2' });
|
|
|
|
const user1 = await createTestUser({ tenant_id: tenant1.id });
|
|
const device2 = await createTestDevice({ tenant_id: tenant2.id });
|
|
const detection2 = await createTestDetection({ device_id: device2.id });
|
|
|
|
const token = generateTestToken(user1, tenant1);
|
|
|
|
const response = await request(app)
|
|
.get(`/detections/${detection2.id}`)
|
|
.set('Authorization', `Bearer ${token}`);
|
|
|
|
expect(response.status).to.equal(404);
|
|
expect(response.body.success).to.be.false;
|
|
});
|
|
|
|
it('should return 404 for non-existent detection', async () => {
|
|
const tenant = await createTestTenant();
|
|
const user = await createTestUser({ tenant_id: tenant.id });
|
|
const token = generateTestToken(user, tenant);
|
|
|
|
const response = await request(app)
|
|
.get('/detections/99999')
|
|
.set('Authorization', `Bearer ${token}`);
|
|
|
|
expect(response.status).to.equal(404);
|
|
expect(response.body.success).to.be.false;
|
|
});
|
|
|
|
it('should include enhanced detection data', async () => {
|
|
const tenant = await createTestTenant();
|
|
const user = await createTestUser({ tenant_id: tenant.id });
|
|
const device = await createTestDevice({ tenant_id: tenant.id });
|
|
const detection = await createTestDetection({
|
|
device_id: device.id,
|
|
drone_type: 2
|
|
});
|
|
const token = generateTestToken(user, tenant);
|
|
|
|
const response = await request(app)
|
|
.get(`/detections/${detection.id}`)
|
|
.set('Authorization', `Bearer ${token}`);
|
|
|
|
expect(response.status).to.equal(200);
|
|
expect(response.body.data.drone_type_info).to.exist;
|
|
expect(response.body.data.device).to.exist;
|
|
});
|
|
});
|
|
|
|
describe('DELETE /detections/:id', () => {
|
|
it('should delete detection with admin role', async () => {
|
|
const tenant = await createTestTenant();
|
|
const user = await createTestUser({
|
|
tenant_id: tenant.id,
|
|
role: 'admin'
|
|
});
|
|
const device = await createTestDevice({ tenant_id: tenant.id });
|
|
const detection = await createTestDetection({ device_id: device.id });
|
|
const token = generateTestToken(user, tenant);
|
|
|
|
const response = await request(app)
|
|
.delete(`/detections/${detection.id}`)
|
|
.set('Authorization', `Bearer ${token}`);
|
|
|
|
expect(response.status).to.equal(200);
|
|
expect(response.body.success).to.be.true;
|
|
expect(response.body.message).to.equal('Detection deleted successfully');
|
|
});
|
|
|
|
it('should reject deletion without proper permissions', async () => {
|
|
const tenant = await createTestTenant();
|
|
const user = await createTestUser({
|
|
tenant_id: tenant.id,
|
|
role: 'viewer'
|
|
});
|
|
const device = await createTestDevice({ tenant_id: tenant.id });
|
|
const detection = await createTestDetection({ device_id: device.id });
|
|
const token = generateTestToken(user, tenant);
|
|
|
|
const response = await request(app)
|
|
.delete(`/detections/${detection.id}`)
|
|
.set('Authorization', `Bearer ${token}`);
|
|
|
|
expect(response.status).to.equal(403);
|
|
expect(response.body.success).to.be.false;
|
|
});
|
|
});
|
|
});
|