'use strict'; /** * Integration tests – job controller (controllers/job.js) * * The job controller is a factory: require('../../controllers/job')({}) * Job._id is an auto-increment numeric field. * deleteJob wraps transaction errors with try/catch so it works on * standalone MongoDB (no replica-set needed). */ const { connectDB, disconnectDB, clearCollection } = require('./jest.setup'); const { mockApplicator, mockClient, mockPilot, mockVehicle, mockJob, mockReq, mockRes, newId, } = require('./mock_data'); let Job, Customer, Client, Pilot, Vehicle; beforeAll(async () => { await connectDB(); Customer = require('../../model/customer'); Client = require('../../model/client'); Pilot = require('../../model/pilot'); Vehicle = require('../../model/vehicle'); Job = require('../../model/job'); }); afterAll(async () => { await disconnectDB(); }); // Job controller is a factory const jobCtl = require('../../controllers/job')({}); describe('job controller – data methods', () => { let applicator, client, pilot, vehicle; beforeAll(async () => { await clearCollection(Job); applicator = await Customer.create(mockApplicator()); client = await Client.create(mockClient(applicator._id)); pilot = await Pilot.create(mockPilot(applicator._id)); vehicle = await Vehicle.create(mockVehicle(applicator._id)); }); afterAll(async () => { await clearCollection(Job); await Client.deleteMany({ _id: client._id }); await Pilot.deleteMany({ _id: pilot._id }); await Vehicle.deleteMany({ _id: vehicle._id }); await Customer.deleteMany({ _id: applicator._id }); }); const makeReq = (extra = {}) => mockReq({ uid: applicator._id, puid: applicator._id, ut: '1', userInfo: { puid: applicator._id, kind: '1', premium: 0, membership: null, markedDelete: false, }, ...extra, }); // ------------------------------------------------------------------------- describe('createJob_post', () => { it('creates a job and returns it', async () => { const body = mockJob(applicator._id); body.client = client._id; body.pilot = pilot._id; body.vehicle = vehicle._id; const req = makeReq({ body }); const res = mockRes(); await jobCtl.createJob_post(req, res); expect(res.json).toHaveBeenCalled(); expect(res._data._id).toBeDefined(); expect(typeof res._data._id).toBe('number'); }); it('throws when puid is missing', async () => { const req = makeReq({ puid: undefined, body: mockJob(applicator._id) }); const res = mockRes(); await expect(jobCtl.createJob_post(req, res)).rejects.toThrow(); }); }); // ------------------------------------------------------------------------- describe('getJobs_get', () => { it('returns jobs for the applicator', async () => { const req = makeReq({ query: {} }); const res = mockRes(); await jobCtl.getJobs_get(req, res); expect(res.json).toHaveBeenCalled(); expect(Array.isArray(res._data)).toBe(true); expect(res._data.length).toBeGreaterThan(0); }); it('returns empty array when puid has no jobs', async () => { const unknownId = newId(); const req = mockReq({ uid: unknownId, puid: unknownId, ut: '1', userInfo: { puid: unknownId, kind: '1', premium: 0, membership: null, markedDelete: false }, query: {}, }); const res = mockRes(); await jobCtl.getJobs_get(req, res); expect(res.json).toHaveBeenCalled(); expect(res._data.length).toBe(0); }); }); // ------------------------------------------------------------------------- describe('getJob_get', () => { let jobId; beforeAll(async () => { const body = mockJob(applicator._id); body.client = client._id; body.pilot = pilot._id; body.vehicle = vehicle._id; const req = makeReq({ body }); const res = mockRes(); await jobCtl.createJob_post(req, res); jobId = res._data._id; }); it('returns a job by numeric id', async () => { const req = makeReq({ params: { job_id: String(jobId) } }); const res = mockRes(); await jobCtl.getJob_get(req, res); expect(res.json).toHaveBeenCalled(); expect(res._data._id).toBe(jobId); }); }); // ------------------------------------------------------------------------- describe('updateJob_put', () => { let jobId; beforeAll(async () => { const body = mockJob(applicator._id); body.client = client._id; body.pilot = pilot._id; body.vehicle = vehicle._id; const req = makeReq({ body }); const res = mockRes(); await jobCtl.createJob_post(req, res); jobId = res._data._id; }); it('updates a job field', async () => { const req = makeReq({ params: { job_id: String(jobId) }, body: { job: { name: 'Updated Job Name' } }, }); const res = mockRes(); await jobCtl.updateJob_put(req, res); expect(res.json).toHaveBeenCalled(); expect(res._data.name).toBe('Updated Job Name'); }); }); // ------------------------------------------------------------------------- describe('deleteJob', () => { let jobId; beforeAll(async () => { const body = mockJob(applicator._id); body.client = client._id; body.pilot = pilot._id; body.vehicle = vehicle._id; const req = makeReq({ body }); const res = mockRes(); await jobCtl.createJob_post(req, res); jobId = res._data._id; }); it('deletes a job (transaction error handled on standalone MongoDB)', async () => { const req = makeReq({ params: { id: String(jobId) } }); const res = mockRes(); // deleteJob wraps the transaction with try/catch – it either succeeds // fully or returns a soft-success; either way res.json is called. await jobCtl.deleteJob(req, res); expect(res.json).toHaveBeenCalled(); }); }); });