agmission/Development/server/tests/integration/geoitem.integration.test.js
Devin Major 6ff07c9d74
All checks were successful
Server Tests / Mocha – Unit & Utility Tests (push) Successful in 1m13s
Server Tests / Jest – Integration Tests (push) Successful in 1m43s
additional integration tests
2026-05-08 14:51:04 -04:00

234 lines
7.2 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, mockJob, 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();
});
});
// -------------------------------------------------------------------------
describe('search_post', () => {
let Job, jobId;
beforeAll(async () => {
Job = require('../../model/job');
const body = mockJob(applicator._id);
body.client = client._id;
const jobDoc = await Job.create(body);
jobId = jobDoc._id; // numeric auto-increment id
});
it('throws when jobId is missing', async () => {
const req = makeReq({
ut: '1',
body: { byPuid: String(applicator._id) },
});
const res = mockRes();
await expect(geoitemCtl.search_post(req, res)).rejects.toThrow();
});
it('throws when byPuid is invalid', async () => {
const req = makeReq({
ut: '1',
body: { jobId: jobId, byPuid: 'bad-id' },
});
const res = mockRes();
await expect(geoitemCtl.search_post(req, res)).rejects.toThrow();
});
it('returns geo items for a valid job', async () => {
const req = makeReq({
ut: '1',
body: { jobId: jobId, byPuid: String(applicator._id) },
});
const res = mockRes();
await geoitemCtl.search_post(req, res);
expect(res.json).toHaveBeenCalled();
expect(Array.isArray(res._data)).toBe(true);
});
});
});