190 lines
5.9 KiB
JavaScript
190 lines
5.9 KiB
JavaScript
'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();
|
||
});
|
||
});
|
||
});
|