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

190 lines
5.9 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 geoitem controller (controllers/geoitem.js)
*/
const mongoose = require('mongoose');
const { connectDB, disconnectDB, clearCollection } = require('./jest.setup');
const { mockApplicator, mockClient, mockReq, mockRes, newId } = require('./mock_data');
let Area, Customer, Client;
beforeAll(async () => {
await connectDB();
Area = require('../../model/area');
Customer = require('../../model/customer');
Client = require('../../model/client');
});
afterAll(async () => {
await disconnectDB();
});
const geoitemCtl = require('../../controllers/geoitem');
/** Minimal valid GeoJSON Polygon coordinates (a small square) */
function squareCoords() {
return [[[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]]];
}
function mockArea(clientId, overrides = {}) {
return {
properties: {
name: `Area-${Date.now()}`,
type: 0,
color: '#FF0000',
area: 1.5,
},
geometry: {
type: 'Polygon',
coordinates: squareCoords(),
},
client: clientId,
...overrides,
};
}
describe('geoitem controller data methods', () => {
let applicator, client;
beforeAll(async () => {
await clearCollection(Area);
applicator = await Customer.create(mockApplicator());
client = await Client.create(mockClient(applicator._id));
});
afterAll(async () => {
await clearCollection(Area);
await Customer.deleteMany({ _id: { $in: [applicator._id, client._id] } });
});
const makeReq = (extra = {}) =>
mockReq({ uid: applicator._id, puid: applicator._id, ut: '1', ...extra });
// -------------------------------------------------------------------------
describe('findAreas_post', () => {
it('throws when clientId is missing from body', async () => {
const req = makeReq({ body: {} });
const res = mockRes();
await expect(geoitemCtl.findAreas_post(req, res)).rejects.toThrow();
});
it('throws when clientId is not a valid ObjectId', async () => {
const req = makeReq({ body: { clientId: 'not-an-id' } });
const res = mockRes();
await expect(geoitemCtl.findAreas_post(req, res)).rejects.toThrow();
});
it('returns an empty array when no areas exist for the client', async () => {
const req = makeReq({ body: { clientId: client._id.toHexString() } });
const res = mockRes();
await geoitemCtl.findAreas_post(req, res);
expect(res.json).toHaveBeenCalled();
expect(Array.isArray(res._data)).toBe(true);
expect(res._data.length).toBe(0);
});
it('returns areas belonging to the specified client', async () => {
await Area.create(mockArea(client._id));
await Area.create(mockArea(client._id));
const req = makeReq({ body: { clientId: client._id.toHexString() } });
const res = mockRes();
await geoitemCtl.findAreas_post(req, res);
expect(res.json).toHaveBeenCalled();
expect(res._data.length).toBe(2);
// toGeoItems output shape: { _id, properties, geometry, client }
expect(res._data[0]).toHaveProperty('_id');
expect(res._data[0]).toHaveProperty('geometry');
});
it('does not return areas belonging to a different client', async () => {
const otherClient = await Client.create(mockClient(applicator._id));
await Area.create(mockArea(otherClient._id));
const req = makeReq({ body: { clientId: client._id.toHexString() } });
const res = mockRes();
await geoitemCtl.findAreas_post(req, res);
expect(res.json).toHaveBeenCalled();
// Should still only see 2 (created in previous test)
const clientIds = res._data.map(f => String(f.properties?.client ?? ''));
expect(clientIds.every(id => id !== String(otherClient._id) || id === '')).toBe(true);
await Client.deleteMany({ _id: otherClient._id });
});
});
// -------------------------------------------------------------------------
describe('update_post', () => {
it('returns immediately when all update arrays are empty', async () => {
const req = makeReq({ body: { c: [], u: [], r: [] } });
const res = mockRes();
await geoitemCtl.update_post(req, res);
expect(res.end).toHaveBeenCalled();
});
it('returns immediately when body is null', async () => {
const req = makeReq({ body: null });
const res = mockRes();
await geoitemCtl.update_post(req, res);
expect(res.end).toHaveBeenCalled();
});
it('inserts new areas via the c (create) array', async () => {
const area = mockArea(client._id);
const req = makeReq({ body: { c: [area] } });
const res = mockRes();
await geoitemCtl.update_post(req, res);
expect(res.json).toHaveBeenCalled();
expect(res._data).toEqual({ ok: true });
const found = await Area.find({ client: client._id });
expect(found.length).toBeGreaterThan(0);
});
it('removes areas via the r (remove) array', async () => {
const doc = await Area.create(mockArea(client._id));
const countBefore = await Area.countDocuments({ client: client._id });
const req = makeReq({ body: { r: [String(doc._id)] } });
const res = mockRes();
await geoitemCtl.update_post(req, res);
expect(res.json).toHaveBeenCalled();
expect(res._data).toEqual({ ok: true });
const countAfter = await Area.countDocuments({ client: client._id });
expect(countAfter).toBe(countBefore - 1);
});
});
// -------------------------------------------------------------------------
describe('addToLibrary_post', () => {
it('throws when areas array is empty', async () => {
const req = makeReq({ body: { areas: [] } });
const res = mockRes();
await expect(geoitemCtl.addToLibrary_post(req, res)).rejects.toThrow();
});
it('throws when body has no areas field', async () => {
const req = makeReq({ body: {} });
const res = mockRes();
await expect(geoitemCtl.addToLibrary_post(req, res)).rejects.toThrow();
});
});
});