agmission/Development/server/tests/integration/obstacle.integration.test.js
2026-04-29 09:40:51 -04:00

188 lines
5.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use strict';
/**
* Integration tests obstacle controller (controllers/obstacle.js)
*
* Covers: createObstacle_post, updateObstacle_put, deleteObstacle, near_post
*/
const { connectDB, disconnectDB, clearCollection } = require('./jest.setup');
const { mockReq, mockRes, newId } = require('./mock_data');
let Obstacle;
beforeAll(async () => {
await connectDB();
Obstacle = require('../../model/obstacles');
});
afterAll(async () => {
await disconnectDB();
});
const obstacleCtl = require('../../controllers/obstacle');
describe('obstacle controller data methods', () => {
afterAll(async () => {
await clearCollection(Obstacle);
});
// -------------------------------------------------------------------------
describe('createObstacle_post', () => {
it('creates an obstacle and returns it as a plain object', async () => {
const userId = newId();
const req = mockReq({
uid: userId,
body: {
item: {
name: 'Test Tower',
type: 'USER',
agl: 150,
amsl: 500,
coors: [-80.1234, 25.7617],
},
pUser: String(userId),
},
});
const res = mockRes();
await obstacleCtl.createObstacle_post(req, res);
expect(res.json).toHaveBeenCalled();
const obstacle = res._data;
expect(obstacle._id).toBeDefined();
expect(obstacle.name).toBe('Test Tower');
expect(obstacle.agl).toBe(150);
expect(obstacle.amsl).toBe(500);
});
it('throws AppParamError when body is missing', async () => {
const req = mockReq({ body: null });
const res = mockRes();
await expect(obstacleCtl.createObstacle_post(req, res)).rejects.toThrow();
});
it('throws AppParamError when coordinates are missing', async () => {
const req = mockReq({
body: {
item: { name: 'Bad Obs', agl: 100, coors: [] },
pUser: String(newId()),
},
});
const res = mockRes();
await expect(obstacleCtl.createObstacle_post(req, res)).rejects.toThrow();
});
});
// -------------------------------------------------------------------------
describe('updateObstacle_put', () => {
let obstacleId;
beforeAll(async () => {
const obs = await Obstacle.create({
properties: { name: 'Original', type: 'USER', agl: 100, amsl: 300 },
geometry: { type: 'Point', coordinates: [-80.0, 25.0] },
});
obstacleId = String(obs._id);
});
it('updates name and agl and returns updated obstacle', async () => {
const req = mockReq({
params: { ob_id: obstacleId },
body: { name: 'Updated Tower', agl: 200, amsl: 400 },
});
const res = mockRes();
await obstacleCtl.updateObstacle_put(req, res);
expect(res.json).toHaveBeenCalled();
expect(res._data).toBeTruthy();
expect(res._data.name).toBe('Updated Tower');
expect(res._data.agl).toBe(200);
});
});
// -------------------------------------------------------------------------
describe('deleteObstacle', () => {
let obstacleId;
beforeAll(async () => {
const obs = await Obstacle.create({
properties: { name: 'To Delete', type: 'USER', agl: 50, amsl: 200 },
geometry: { type: 'Point', coordinates: [-79.0, 26.0] },
});
obstacleId = String(obs._id);
});
it('deletes obstacle and returns success message', async () => {
const req = mockReq({ params: { ob_id: obstacleId } });
const res = mockRes();
await obstacleCtl.deleteObstacle(req, res);
expect(res.json).toHaveBeenCalled();
expect(res._data.message).toMatch(/deleted/i);
const found = await Obstacle.findById(obstacleId);
expect(found).toBeNull();
});
it('returns success even when obstacle does not exist', async () => {
const req = mockReq({ params: { ob_id: String(newId()) } });
const res = mockRes();
await obstacleCtl.deleteObstacle(req, res);
expect(res.json).toHaveBeenCalled();
expect(res._data.message).toMatch(/deleted/i);
});
});
// -------------------------------------------------------------------------
describe('near_post', () => {
beforeAll(async () => {
await Obstacle.ensureIndexes();
await Obstacle.create({
properties: { name: 'Miami Tower', type: 'USER', agl: 200, amsl: 600 },
geometry: { type: 'Point', coordinates: [-80.1918, 25.7617] },
});
});
it('returns obstacles near the given center within radius', async () => {
const req = mockReq({
body: { center: { lng: -80.1918, lat: 25.7617 }, min: 0 },
});
const res = mockRes();
await obstacleCtl.near_post(req, res);
expect(res.json).toHaveBeenCalled();
expect(Array.isArray(res._data)).toBe(true);
expect(res._data.length).toBeGreaterThan(0);
});
it('returns empty array when no obstacles are in the vicinity', async () => {
const req = mockReq({
body: { center: { lng: -140.0, lat: 0.0 }, min: 0 },
});
const res = mockRes();
await obstacleCtl.near_post(req, res);
expect(res.json).toHaveBeenCalled();
expect(res._data.length).toBe(0);
});
it('filters by minimum AGL height', async () => {
const req = mockReq({
body: { center: { lng: -80.1918, lat: 25.7617 }, min: 999 },
});
const res = mockRes();
await obstacleCtl.near_post(req, res);
expect(res.json).toHaveBeenCalled();
expect(res._data.length).toBe(0);
});
});
});