199 lines
6.4 KiB
JavaScript
199 lines
6.4 KiB
JavaScript
'use strict';
|
||
|
||
/**
|
||
* Integration tests – api_pub controller (controllers/api_pub.js)
|
||
*/
|
||
|
||
const { connectDB, disconnectDB, clearCollection } = require('./jest.setup');
|
||
const { mockApplicator, mockClient, mockJob, mockReq, mockRes } = require('./mock_data');
|
||
|
||
let Job, App, AppFile, Customer, Client;
|
||
|
||
beforeAll(async () => {
|
||
await connectDB();
|
||
({ Job, App, AppFile } = require('../../model'));
|
||
Customer = require('../../model/customer');
|
||
Client = require('../../model/client');
|
||
});
|
||
|
||
afterAll(async () => {
|
||
await disconnectDB();
|
||
});
|
||
|
||
const apiPubCtl = require('../../controllers/api_pub');
|
||
|
||
/** Generate a unique integer job id that won't collide across tests */
|
||
let _nextJobId = 900001;
|
||
function nextJobId() { return _nextJobId++; }
|
||
|
||
describe('api_pub controller', () => {
|
||
let applicator, client, jobRecord;
|
||
|
||
beforeAll(async () => {
|
||
await clearCollection(Job);
|
||
await clearCollection(App);
|
||
await clearCollection(AppFile);
|
||
|
||
applicator = await Customer.create(mockApplicator());
|
||
client = await Client.create(mockClient(applicator._id));
|
||
|
||
const jobId = nextJobId();
|
||
jobRecord = await Job.create(
|
||
mockJob(applicator._id, {
|
||
_id: jobId,
|
||
client: client._id,
|
||
})
|
||
);
|
||
});
|
||
|
||
afterAll(async () => {
|
||
await clearCollection(Job);
|
||
await clearCollection(App);
|
||
await clearCollection(AppFile);
|
||
await Customer.deleteMany({ _id: { $in: [applicator._id, client._id] } });
|
||
});
|
||
|
||
const makeReq = (extra = {}) =>
|
||
mockReq({ uid: applicator._id, puid: applicator._id, ut: '1', ...extra });
|
||
|
||
// -------------------------------------------------------------------------
|
||
describe('getSessions', () => {
|
||
it('throws AppParamError when jobId is not a number', async () => {
|
||
const req = makeReq({ params: { jobId: 'not-a-number' } });
|
||
const res = mockRes();
|
||
await expect(apiPubCtl.getSessions(req, res)).rejects.toThrow();
|
||
});
|
||
|
||
it('throws JOB_NOT_FOUND for a job that does not exist', async () => {
|
||
const req = makeReq({ params: { jobId: '999999' } });
|
||
const res = mockRes();
|
||
await expect(apiPubCtl.getSessions(req, res)).rejects.toThrow();
|
||
});
|
||
|
||
it('throws AppAuthError when uid does not own the job', async () => {
|
||
const other = await Customer.create(mockApplicator());
|
||
const req = mockReq({
|
||
uid: other._id,
|
||
puid: other._id,
|
||
params: { jobId: String(jobRecord._id) },
|
||
});
|
||
const res = mockRes();
|
||
await expect(apiPubCtl.getSessions(req, res)).rejects.toThrow();
|
||
await Customer.deleteMany({ _id: other._id });
|
||
});
|
||
|
||
it('returns empty data array when job has no apps', async () => {
|
||
const req = makeReq({ params: { jobId: String(jobRecord._id) } });
|
||
const res = mockRes();
|
||
|
||
await apiPubCtl.getSessions(req, res);
|
||
|
||
expect(res.json).toHaveBeenCalled();
|
||
expect(res._data.jobId).toBe(jobRecord._id);
|
||
expect(res._data.data).toEqual([]);
|
||
});
|
||
|
||
it('returns sessions when apps exist for the job', async () => {
|
||
const app = await App.create({
|
||
_id: require('mongoose').Types.ObjectId(),
|
||
jobId: jobRecord._id,
|
||
fileName: 'testflight.agn',
|
||
fileSize: 0,
|
||
markedDelete: false,
|
||
});
|
||
const req = makeReq({ params: { jobId: String(jobRecord._id) } });
|
||
const res = mockRes();
|
||
|
||
await apiPubCtl.getSessions(req, res);
|
||
|
||
expect(res.json).toHaveBeenCalled();
|
||
expect(res._data.data.length).toBe(1);
|
||
expect(String(res._data.data[0].sessionId)).toBe(String(app._id));
|
||
|
||
await App.deleteMany({ _id: app._id });
|
||
});
|
||
});
|
||
|
||
// -------------------------------------------------------------------------
|
||
describe('getAreas', () => {
|
||
it('throws when jobId is not a number', async () => {
|
||
const req = makeReq({ params: { jobId: 'abc' } });
|
||
const res = mockRes();
|
||
await expect(apiPubCtl.getAreas(req, res)).rejects.toThrow();
|
||
});
|
||
|
||
it('throws JOB_NOT_FOUND when job does not exist', async () => {
|
||
const req = makeReq({ params: { jobId: '999998' } });
|
||
const res = mockRes();
|
||
await expect(apiPubCtl.getAreas(req, res)).rejects.toThrow();
|
||
});
|
||
|
||
it('returns a GeoJSON FeatureCollection with empty features when job has no areas', async () => {
|
||
const req = makeReq({ params: { jobId: String(jobRecord._id) } });
|
||
const res = mockRes();
|
||
|
||
await apiPubCtl.getAreas(req, res);
|
||
|
||
expect(res.json).toHaveBeenCalled();
|
||
expect(res._data.type).toBe('FeatureCollection');
|
||
expect(Array.isArray(res._data.features)).toBe(true);
|
||
expect(res._data.features.length).toBe(0);
|
||
});
|
||
|
||
it('returns area features when sprayAreas are defined on the job', async () => {
|
||
const area = {
|
||
properties: { name: 'Block A', area: 2.5 },
|
||
geometry: {
|
||
type: 'Polygon',
|
||
coordinates: [[[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]]],
|
||
},
|
||
};
|
||
await Job.findByIdAndUpdate(jobRecord._id, { sprayAreas: [area] });
|
||
|
||
const req = makeReq({ params: { jobId: String(jobRecord._id) } });
|
||
const res = mockRes();
|
||
|
||
await apiPubCtl.getAreas(req, res);
|
||
|
||
expect(res.json).toHaveBeenCalled();
|
||
expect(res._data.features.length).toBe(1);
|
||
expect(res._data.features[0].properties.name).toBe('Block A');
|
||
|
||
// Cleanup
|
||
await Job.findByIdAndUpdate(jobRecord._id, { sprayAreas: [] });
|
||
});
|
||
});
|
||
|
||
// -------------------------------------------------------------------------
|
||
describe('getSessionRecords', () => {
|
||
it('throws when jobId is not a number', async () => {
|
||
const mongoose = require('mongoose');
|
||
const req = makeReq({
|
||
params: { jobId: 'abc', fileId: new mongoose.Types.ObjectId().toHexString() },
|
||
});
|
||
const res = mockRes();
|
||
await expect(apiPubCtl.getSessionRecords(req, res)).rejects.toThrow();
|
||
});
|
||
|
||
it('throws when fileId is not a valid ObjectId', async () => {
|
||
const req = makeReq({
|
||
params: { jobId: String(jobRecord._id), fileId: 'invalid' },
|
||
});
|
||
const res = mockRes();
|
||
await expect(apiPubCtl.getSessionRecords(req, res)).rejects.toThrow();
|
||
});
|
||
|
||
it('throws NOT_FOUND when AppFile does not exist', async () => {
|
||
const mongoose = require('mongoose');
|
||
const req = makeReq({
|
||
params: {
|
||
jobId: String(jobRecord._id),
|
||
fileId: new mongoose.Types.ObjectId().toHexString(),
|
||
},
|
||
});
|
||
const res = mockRes();
|
||
await expect(apiPubCtl.getSessionRecords(req, res)).rejects.toThrow();
|
||
});
|
||
});
|
||
});
|