Added unit tests.
Some checks failed
farmcontrol/farmcontrol-api/pipeline/head There was a failure building this commit
Some checks failed
farmcontrol/farmcontrol-api/pipeline/head There was a failure building this commit
This commit is contained in:
parent
2d156aa98f
commit
28c94159b4
16
Jenkinsfile
vendored
16
Jenkinsfile
vendored
@ -31,6 +31,22 @@ pipeline {
|
||||
}
|
||||
}
|
||||
|
||||
stage('Run Tests') {
|
||||
steps {
|
||||
nodejs(nodeJSInstallationName: 'Node23') {
|
||||
sh '''
|
||||
export NODE_ENV=test
|
||||
yarn test
|
||||
'''
|
||||
}
|
||||
}
|
||||
post {
|
||||
always {
|
||||
junit 'test-results.xml'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Deploy via SSH') {
|
||||
steps {
|
||||
sshPublisher(publishers: [
|
||||
|
||||
4
babel.config.cjs
Normal file
4
babel.config.cjs
Normal file
@ -0,0 +1,4 @@
|
||||
module.exports = {
|
||||
presets: [['@babel/preset-env', { targets: { node: 'current' } }]],
|
||||
plugins: ['transform-import-meta'],
|
||||
};
|
||||
48
config.json
48
config.json
@ -48,6 +48,54 @@
|
||||
},
|
||||
"otpExpiryMins": 0.5
|
||||
},
|
||||
"test": {
|
||||
"server": {
|
||||
"port": 8788,
|
||||
"logLevel": "error"
|
||||
},
|
||||
"auth": {
|
||||
"enabled": false,
|
||||
"keycloak": {
|
||||
"url": "http://localhost:8080",
|
||||
"realm": "test",
|
||||
"clientId": "test-client"
|
||||
},
|
||||
"requiredRoles": []
|
||||
},
|
||||
"app": {
|
||||
"urlClient": "http://localhost:3000",
|
||||
"urlElectronClient": "http://localhost:5780",
|
||||
"urlApi": "http://localhost:8788/api",
|
||||
"devAuthClient": "http://localhost:3500"
|
||||
},
|
||||
"database": {
|
||||
"mongo": {
|
||||
"url": "mongodb://127.0.0.1:27017/farmcontrol-test",
|
||||
"link": "127.0.0.1:27017"
|
||||
},
|
||||
"redis": {
|
||||
"host": "localhost",
|
||||
"port": 6379,
|
||||
"password": "",
|
||||
"cacheTtl": 30
|
||||
},
|
||||
"nats": {
|
||||
"host": "localhost",
|
||||
"port": 4222
|
||||
}
|
||||
},
|
||||
"storage": {
|
||||
"fileStorage": "./test-uploads",
|
||||
"ceph": {
|
||||
"accessKeyId": "minioadmin",
|
||||
"secretAccessKey": "minioadmin123",
|
||||
"endpoint": "http://127.0.0.1:9000",
|
||||
"region": "us-east-1",
|
||||
"filesBucket": "farmcontrol-test"
|
||||
}
|
||||
},
|
||||
"otpExpiryMins": 0.5
|
||||
},
|
||||
"production": {
|
||||
"server": {
|
||||
"port": 8080,
|
||||
|
||||
22
jest.config.cjs
Normal file
22
jest.config.cjs
Normal file
@ -0,0 +1,22 @@
|
||||
module.exports = {
|
||||
testEnvironment: 'node',
|
||||
transform: {},
|
||||
moduleFileExtensions: ['js', 'json', 'jsx', 'node'],
|
||||
testMatch: ['**/__tests__/**/*.js', '**/?(*.)+(spec|test).js'],
|
||||
verbose: true,
|
||||
reporters: [
|
||||
'default',
|
||||
[
|
||||
'jest-junit',
|
||||
{
|
||||
outputDirectory: '.',
|
||||
outputName: 'test-results.xml',
|
||||
suiteName: 'farmcontrol-api-tests',
|
||||
classNameTemplate: '{classname}',
|
||||
titleTemplate: '{title}',
|
||||
ancestorSeparator: ' › ',
|
||||
usePathForSuiteName: 'true',
|
||||
},
|
||||
],
|
||||
],
|
||||
};
|
||||
10
package.json
10
package.json
@ -41,20 +41,26 @@
|
||||
"@babel/plugin-proposal-object-rest-spread": "^7.20.7",
|
||||
"@babel/preset-env": "^7.28.5",
|
||||
"@babel/register": "^7.28.3",
|
||||
"@jest/globals": "^30.2.0",
|
||||
"babel-jest": "^30.2.0",
|
||||
"babel-plugin-transform-import-meta": "^2.3.3",
|
||||
"concurrently": "^9.2.1",
|
||||
"eslint": "^9.39.1",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-plugin-prettier": "^5.5.4",
|
||||
"jest": "^30.2.0",
|
||||
"jest-junit": "^16.0.0",
|
||||
"prettier": "^3.6.2",
|
||||
"sequelize-cli": "^6.6.3",
|
||||
"standard": "^17.1.2"
|
||||
"standard": "^17.1.2",
|
||||
"supertest": "^7.1.4"
|
||||
},
|
||||
"scripts": {
|
||||
"syncModelsWithWS": "node fcdev.js",
|
||||
"watch:schemas": "nodemon --config nodemon.schemas.json",
|
||||
"dev": "concurrently --names \"API,SCHEMAS\" --prefix-colors \"cyan,yellow\" \"nodemon --exec babel-node --experimental-specifier-resolution=node src/index.js\" \"nodemon --config nodemon.schemas.json\"",
|
||||
"dev:api": "nodemon --exec babel-node --experimental-specifier-resolution=node src/index.js",
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"test": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js",
|
||||
"seed": "node src/mongo/seedData.js",
|
||||
"clear": "node src/mongo/clearDbs.js"
|
||||
},
|
||||
|
||||
68
src/__tests__/users.api.test.js
Normal file
68
src/__tests__/users.api.test.js
Normal file
@ -0,0 +1,68 @@
|
||||
import { jest } from '@jest/globals';
|
||||
import request from 'supertest';
|
||||
|
||||
// Mock Keycloak and Auth
|
||||
jest.unstable_mockModule('../keycloak.js', () => ({
|
||||
keycloak: {
|
||||
middleware: () => (req, res, next) => next(),
|
||||
protect: () => (req, res, next) => next(),
|
||||
},
|
||||
isAuthenticated: (req, res, next) => next(),
|
||||
expressSession: (req, res, next) => next(),
|
||||
}));
|
||||
|
||||
// Mock database connections and initializations in index.js
|
||||
jest.unstable_mockModule('../database/mongo.js', () => ({
|
||||
dbConnect: jest.fn(),
|
||||
}));
|
||||
jest.unstable_mockModule('../database/nats.js', () => ({
|
||||
natsServer: { connect: jest.fn() },
|
||||
}));
|
||||
jest.unstable_mockModule('../database/ceph.js', () => ({
|
||||
initializeBuckets: jest.fn(),
|
||||
uploadFile: jest.fn(),
|
||||
downloadFile: jest.fn(),
|
||||
deleteFile: jest.fn(),
|
||||
fileExists: jest.fn(),
|
||||
listFiles: jest.fn(),
|
||||
getFileMetadata: jest.fn(),
|
||||
getPresignedUrl: jest.fn(),
|
||||
BUCKETS: { FILES: 'test-bucket' },
|
||||
}));
|
||||
|
||||
// Mock the service handlers to avoid database calls
|
||||
jest.unstable_mockModule('../services/management/users.js', () => ({
|
||||
listUsersRouteHandler: jest.fn((req, res) => res.send([{ id: '1', name: 'Mock User' }])),
|
||||
listUsersByPropertiesRouteHandler: jest.fn(),
|
||||
getUserRouteHandler: jest.fn((req, res) => res.send({ id: req.params.id, name: 'Mock User' })),
|
||||
editUserRouteHandler: jest.fn(),
|
||||
getUserStatsRouteHandler: jest.fn(),
|
||||
getUserHistoryRouteHandler: jest.fn(),
|
||||
}));
|
||||
|
||||
const { default: app } = await import('../index.js');
|
||||
const { listUsersRouteHandler, getUserRouteHandler } = await import(
|
||||
'../services/management/users.js'
|
||||
);
|
||||
|
||||
describe('Users API Endpoints', () => {
|
||||
describe('GET /users', () => {
|
||||
it('should return a list of users', async () => {
|
||||
const response = await request(app).get('/users');
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.body).toEqual([{ id: '1', name: 'Mock User' }]);
|
||||
expect(listUsersRouteHandler).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /users/:id', () => {
|
||||
it('should return a single user', async () => {
|
||||
const response = await request(app).get('/users/123');
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.body).toEqual({ id: '123', name: 'Mock User' });
|
||||
expect(getUserRouteHandler).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
163
src/database/__tests__/database.test.js
Normal file
163
src/database/__tests__/database.test.js
Normal file
@ -0,0 +1,163 @@
|
||||
import { jest } from '@jest/globals';
|
||||
|
||||
// Mock src/database/utils.js (where generateId lives)
|
||||
jest.unstable_mockModule('../utils.js', () => ({
|
||||
generateId: jest.fn(() => () => 'test-id'),
|
||||
}));
|
||||
|
||||
// Mock src/utils.js (where most database.js helpers live)
|
||||
jest.unstable_mockModule('../../utils.js', () => ({
|
||||
deleteAuditLog: jest.fn(),
|
||||
distributeDelete: jest.fn(),
|
||||
expandObjectIds: jest.fn((obj) => obj),
|
||||
modelHasRef: jest.fn(() => false),
|
||||
getFieldsByRef: jest.fn(() => []),
|
||||
getQueryToCacheKey: jest.fn(({ model, id }) => `${model}:${id}`),
|
||||
editAuditLog: jest.fn(),
|
||||
distributeUpdate: jest.fn(),
|
||||
newAuditLog: jest.fn(),
|
||||
distributeNew: jest.fn(),
|
||||
distributeChildUpdate: jest.fn(),
|
||||
distributeChildDelete: jest.fn(),
|
||||
distributeChildNew: jest.fn(),
|
||||
distributeStats: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../redis.js', () => ({
|
||||
redisServer: {
|
||||
getKey: jest.fn(),
|
||||
setKey: jest.fn(),
|
||||
deleteKey: jest.fn(),
|
||||
getKeysByPattern: jest.fn(() => []), // Return empty array to avoid iterable error
|
||||
},
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../services/misc/model.js', () => ({
|
||||
getAllModels: jest.fn(() => []),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../schemas/management/auditlog.schema.js', () => ({
|
||||
auditLogModel: {
|
||||
find: jest.fn(),
|
||||
create: jest.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
// Mock fileModel specifically as it's imported by database.js
|
||||
jest.unstable_mockModule('../schemas/management/file.schema.js', () => ({
|
||||
fileModel: {
|
||||
findById: jest.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
// Now import the database utilities
|
||||
const { listObjects, getObject, newObject, editObject, deleteObject } = await import(
|
||||
'../database.js'
|
||||
);
|
||||
|
||||
describe('Database Utilities (CRUD)', () => {
|
||||
let mockModel;
|
||||
|
||||
beforeEach(() => {
|
||||
mockModel = {
|
||||
modelName: 'TestModel',
|
||||
find: jest.fn().mockReturnThis(),
|
||||
findById: jest.fn().mockReturnThis(),
|
||||
findByIdAndUpdate: jest.fn().mockReturnThis(),
|
||||
findByIdAndDelete: jest.fn().mockReturnThis(),
|
||||
create: jest.fn(),
|
||||
sort: jest.fn().mockReturnThis(),
|
||||
skip: jest.fn().mockReturnThis(),
|
||||
limit: jest.fn().mockReturnThis(),
|
||||
populate: jest.fn().mockReturnThis(),
|
||||
select: jest.fn().mockReturnThis(),
|
||||
lean: jest.fn().mockReturnThis(),
|
||||
exec: jest.fn(),
|
||||
};
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('listObjects', () => {
|
||||
it('should return a list of objects', async () => {
|
||||
const mockData = [{ _id: '1', name: 'Test' }];
|
||||
mockModel.lean.mockResolvedValue(mockData);
|
||||
|
||||
const result = await listObjects({ model: mockModel });
|
||||
|
||||
expect(mockModel.find).toHaveBeenCalled();
|
||||
expect(result).toEqual(mockData);
|
||||
});
|
||||
|
||||
it('should handle pagination', async () => {
|
||||
await listObjects({ model: mockModel, page: 2, limit: 10 });
|
||||
expect(mockModel.skip).toHaveBeenCalledWith(10);
|
||||
expect(mockModel.limit).toHaveBeenCalledWith(10);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getObject', () => {
|
||||
it('should return a single object by ID', async () => {
|
||||
const mockData = { _id: '123', name: 'Test' };
|
||||
mockModel.lean.mockResolvedValue(mockData);
|
||||
|
||||
const result = await getObject({ model: mockModel, id: '123' });
|
||||
|
||||
expect(mockModel.findById).toHaveBeenCalledWith('123');
|
||||
expect(result).toEqual(mockData);
|
||||
});
|
||||
|
||||
it('should return 404 if object not found', async () => {
|
||||
mockModel.lean.mockResolvedValue(null);
|
||||
|
||||
const result = await getObject({ model: mockModel, id: '123' });
|
||||
|
||||
expect(result).toEqual({ error: 'Object not found.', code: 404 });
|
||||
});
|
||||
});
|
||||
|
||||
describe('newObject', () => {
|
||||
it('should create a new object', async () => {
|
||||
const newData = { name: 'New' };
|
||||
const createdData = { _id: '456', ...newData };
|
||||
mockModel.create.mockResolvedValue({
|
||||
toObject: () => createdData,
|
||||
_id: '456',
|
||||
});
|
||||
|
||||
const result = await newObject({ model: mockModel, newData });
|
||||
|
||||
expect(mockModel.create).toHaveBeenCalledWith(newData);
|
||||
expect(result).toEqual(createdData);
|
||||
});
|
||||
});
|
||||
|
||||
describe('editObject', () => {
|
||||
it('should update an existing object', async () => {
|
||||
const id = '123';
|
||||
const updateData = { name: 'Updated' };
|
||||
const previousData = { _id: id, name: 'Old' };
|
||||
|
||||
mockModel.lean.mockResolvedValue(previousData);
|
||||
|
||||
const result = await editObject({ model: mockModel, id, updateData });
|
||||
|
||||
expect(mockModel.findByIdAndUpdate).toHaveBeenCalledWith(id, updateData);
|
||||
expect(result).toEqual({ ...previousData, ...updateData });
|
||||
});
|
||||
});
|
||||
|
||||
describe('deleteObject', () => {
|
||||
it('should delete an object', async () => {
|
||||
const id = '123';
|
||||
const mockData = { _id: id, name: 'To be deleted' };
|
||||
mockModel.findByIdAndDelete.mockResolvedValue({
|
||||
toObject: () => mockData,
|
||||
});
|
||||
|
||||
const result = await deleteObject({ model: mockModel, id });
|
||||
|
||||
expect(mockModel.findByIdAndDelete).toHaveBeenCalledWith(id);
|
||||
expect(result).toEqual({ deleted: true, object: mockData });
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -150,4 +150,8 @@ app.use('/salesorders', salesOrderRoutes);
|
||||
app.use('/notes', noteRoutes);
|
||||
|
||||
// Start the application
|
||||
initializeApp();
|
||||
if (process.env.NODE_ENV !== 'test') {
|
||||
initializeApp();
|
||||
}
|
||||
|
||||
export default app;
|
||||
|
||||
154
src/services/finance/__tests__/invoices.test.js
Normal file
154
src/services/finance/__tests__/invoices.test.js
Normal file
@ -0,0 +1,154 @@
|
||||
import { jest } from '@jest/globals';
|
||||
|
||||
// Mock dependencies
|
||||
jest.unstable_mockModule('../../../database/database.js', () => ({
|
||||
listObjects: jest.fn(),
|
||||
getObject: jest.fn(),
|
||||
editObject: jest.fn(),
|
||||
editObjects: jest.fn(),
|
||||
newObject: jest.fn(),
|
||||
deleteObject: jest.fn(),
|
||||
listObjectsByProperties: jest.fn(),
|
||||
getModelStats: jest.fn(),
|
||||
getModelHistory: jest.fn(),
|
||||
checkStates: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/finance/invoice.schema.js', () => ({
|
||||
invoiceModel: { modelName: 'Invoice' },
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/inventory/orderitem.schema.js', () => ({
|
||||
orderItemModel: { modelName: 'OrderItem' },
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/inventory/shipment.schema.js', () => ({
|
||||
shipmentModel: { modelName: 'Shipment' },
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('log4js', () => ({
|
||||
default: {
|
||||
getLogger: () => ({
|
||||
level: 'info',
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
trace: jest.fn(),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
// Import handlers after mocking
|
||||
const {
|
||||
listInvoicesRouteHandler,
|
||||
getInvoiceRouteHandler,
|
||||
newInvoiceRouteHandler,
|
||||
editInvoiceRouteHandler,
|
||||
deleteInvoiceRouteHandler,
|
||||
postInvoiceRouteHandler,
|
||||
} = await import('../invoices.js');
|
||||
|
||||
const { listObjects, getObject, editObject, newObject, deleteObject, checkStates } = await import(
|
||||
'../../../database/database.js'
|
||||
);
|
||||
const { invoiceModel } = await import('../../../database/schemas/finance/invoice.schema.js');
|
||||
|
||||
describe('Invoice Service Route Handlers', () => {
|
||||
let req, res;
|
||||
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
params: {},
|
||||
query: {},
|
||||
body: {},
|
||||
user: { id: 'test-user-id' },
|
||||
};
|
||||
res = {
|
||||
send: jest.fn(),
|
||||
status: jest.fn().mockReturnThis(),
|
||||
};
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('listInvoicesRouteHandler', () => {
|
||||
it('should list invoices', async () => {
|
||||
const mockResult = [{ _id: '1', invoiceNumber: 'INV-001' }];
|
||||
listObjects.mockResolvedValue(mockResult);
|
||||
|
||||
await listInvoicesRouteHandler(req, res);
|
||||
|
||||
expect(listObjects).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getInvoiceRouteHandler', () => {
|
||||
it('should get an invoice by ID', async () => {
|
||||
req.params.id = '123';
|
||||
const mockResult = { _id: '123', invoiceNumber: 'INV-001' };
|
||||
getObject.mockResolvedValue(mockResult);
|
||||
|
||||
await getInvoiceRouteHandler(req, res);
|
||||
|
||||
expect(getObject).toHaveBeenCalledWith(expect.objectContaining({ id: '123' }));
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('newInvoiceRouteHandler', () => {
|
||||
it('should create a new invoice with order items and shipments', async () => {
|
||||
req.body = { order: 'order123', orderType: 'sales' };
|
||||
|
||||
// Mock listObjects for orderItems and shipments
|
||||
listObjects.mockResolvedValueOnce([{ _id: 'oi1', totalAmount: 100, invoicedAmount: 0 }]); // orderItems
|
||||
listObjects.mockResolvedValueOnce([{ _id: 's1', amount: 20, invoicedAmount: 0 }]); // shipments
|
||||
|
||||
const mockInvoice = { _id: 'inv456' };
|
||||
newObject.mockResolvedValue(mockInvoice);
|
||||
|
||||
await newInvoiceRouteHandler(req, res);
|
||||
|
||||
expect(newObject).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockInvoice);
|
||||
});
|
||||
});
|
||||
|
||||
describe('postInvoiceRouteHandler', () => {
|
||||
it('should post a draft invoice and update order items/shipments', async () => {
|
||||
req.params.id = '507f1f77bcf86cd799439011';
|
||||
|
||||
checkStates.mockResolvedValue(true);
|
||||
|
||||
const mockInvoice = {
|
||||
_id: '507f1f77bcf86cd799439011',
|
||||
invoiceOrderItems: [{ orderItem: { _id: 'oi1' }, invoiceAmount: 50, invoiceQuantity: 1 }],
|
||||
invoiceShipments: [{ shipment: { _id: 's1' }, invoiceAmount: 10 }],
|
||||
};
|
||||
getObject.mockResolvedValueOnce(mockInvoice);
|
||||
|
||||
// Mock getObject for individual orderItems and shipments
|
||||
getObject.mockResolvedValueOnce({ _id: 'oi1', invoicedAmount: 0, invoicedQuantity: 0 });
|
||||
getObject.mockResolvedValueOnce({ _id: 's1', invoicedAmount: 0 });
|
||||
|
||||
editObject.mockResolvedValue({ _id: '507f1f77bcf86cd799439011', state: { type: 'sent' } });
|
||||
|
||||
await postInvoiceRouteHandler(req, res);
|
||||
|
||||
expect(checkStates).toHaveBeenCalledWith(expect.objectContaining({ states: ['draft'] }));
|
||||
expect(editObject).toHaveBeenCalled(); // Should be called for items, shipments, and the invoice itself
|
||||
expect(res.send).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should fail if invoice is not in draft state', async () => {
|
||||
req.params.id = '507f1f77bcf86cd799439011';
|
||||
checkStates.mockResolvedValue(false);
|
||||
|
||||
await postInvoiceRouteHandler(req, res);
|
||||
|
||||
expect(res.status).toHaveBeenCalledWith(400);
|
||||
expect(res.send).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ error: 'Invoice is not in draft state.' })
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
124
src/services/finance/__tests__/payments.test.js
Normal file
124
src/services/finance/__tests__/payments.test.js
Normal file
@ -0,0 +1,124 @@
|
||||
import { jest } from '@jest/globals';
|
||||
|
||||
jest.unstable_mockModule('../../../database/database.js', () => ({
|
||||
listObjects: jest.fn(),
|
||||
getObject: jest.fn(),
|
||||
editObject: jest.fn(),
|
||||
editObjects: jest.fn(),
|
||||
newObject: jest.fn(),
|
||||
deleteObject: jest.fn(),
|
||||
listObjectsByProperties: jest.fn(),
|
||||
getModelStats: jest.fn(),
|
||||
getModelHistory: jest.fn(),
|
||||
checkStates: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/finance/payment.schema.js', () => ({
|
||||
paymentModel: { modelName: 'Payment' },
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/finance/invoice.schema.js', () => ({
|
||||
invoiceModel: { modelName: 'Invoice' },
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('log4js', () => ({
|
||||
default: {
|
||||
getLogger: () => ({
|
||||
level: 'info',
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
trace: jest.fn(),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
const {
|
||||
listPaymentsRouteHandler,
|
||||
getPaymentRouteHandler,
|
||||
newPaymentRouteHandler,
|
||||
postPaymentRouteHandler,
|
||||
} = await import('../payments.js');
|
||||
|
||||
const { listObjects, getObject, editObject, newObject, checkStates } = await import(
|
||||
'../../../database/database.js'
|
||||
);
|
||||
const { paymentModel } = await import('../../../database/schemas/finance/payment.schema.js');
|
||||
const { invoiceModel } = await import('../../../database/schemas/finance/invoice.schema.js');
|
||||
|
||||
describe('Payment Service Route Handlers', () => {
|
||||
let req, res;
|
||||
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
params: {},
|
||||
query: {},
|
||||
body: {},
|
||||
user: { id: 'test-user-id' },
|
||||
};
|
||||
res = {
|
||||
send: jest.fn(),
|
||||
status: jest.fn().mockReturnThis(),
|
||||
};
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('listPaymentsRouteHandler', () => {
|
||||
it('should list payments', async () => {
|
||||
const mockResult = [{ _id: '1', amount: 100 }];
|
||||
listObjects.mockResolvedValue(mockResult);
|
||||
|
||||
await listPaymentsRouteHandler(req, res);
|
||||
|
||||
expect(listObjects).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('newPaymentRouteHandler', () => {
|
||||
it('should create a new payment with invoice data', async () => {
|
||||
req.body = { invoice: 'inv123', amount: 100 };
|
||||
const mockInvoice = { _id: 'inv123', vendor: { _id: 'v1' }, client: { _id: 'c1' } };
|
||||
getObject.mockResolvedValueOnce(mockInvoice);
|
||||
const mockPayment = { _id: 'pay456', ...req.body };
|
||||
newObject.mockResolvedValue(mockPayment);
|
||||
|
||||
await newPaymentRouteHandler(req, res);
|
||||
|
||||
expect(getObject).toHaveBeenCalledWith(expect.objectContaining({ id: 'inv123' }));
|
||||
expect(newObject).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockPayment);
|
||||
});
|
||||
});
|
||||
|
||||
describe('postPaymentRouteHandler', () => {
|
||||
it('should post a draft payment', async () => {
|
||||
req.params.id = '507f1f77bcf86cd799439011';
|
||||
checkStates.mockResolvedValue(true);
|
||||
|
||||
const mockPayment = { _id: '507f1f77bcf86cd799439011', invoice: 'inv123' };
|
||||
getObject.mockResolvedValueOnce(mockPayment);
|
||||
getObject.mockResolvedValueOnce({ _id: 'inv123' });
|
||||
editObject.mockResolvedValue({ _id: '507f1f77bcf86cd799439011', state: { type: 'posted' } });
|
||||
|
||||
await postPaymentRouteHandler(req, res);
|
||||
|
||||
expect(checkStates).toHaveBeenCalledWith(expect.objectContaining({ states: ['draft'] }));
|
||||
expect(editObject).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should fail if payment is not in draft state', async () => {
|
||||
req.params.id = '507f1f77bcf86cd799439011';
|
||||
checkStates.mockResolvedValue(false);
|
||||
|
||||
await postPaymentRouteHandler(req, res);
|
||||
|
||||
expect(res.status).toHaveBeenCalledWith(400);
|
||||
expect(res.send).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ error: 'Payment is not in draft state.' })
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
86
src/services/inventory/__tests__/filamentstocks.test.js
Normal file
86
src/services/inventory/__tests__/filamentstocks.test.js
Normal file
@ -0,0 +1,86 @@
|
||||
import { jest } from '@jest/globals';
|
||||
|
||||
jest.unstable_mockModule('../../../database/database.js', () => ({
|
||||
listObjects: jest.fn(),
|
||||
getObject: jest.fn(),
|
||||
editObject: jest.fn(),
|
||||
editObjects: jest.fn(),
|
||||
newObject: jest.fn(),
|
||||
deleteObject: jest.fn(),
|
||||
listObjectsByProperties: jest.fn(),
|
||||
getModelStats: jest.fn(),
|
||||
getModelHistory: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/inventory/filamentstock.schema.js', () => ({
|
||||
filamentStockModel: { modelName: 'FilamentStock' },
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('log4js', () => ({
|
||||
default: {
|
||||
getLogger: () => ({
|
||||
level: 'info',
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
trace: jest.fn(),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
const {
|
||||
listFilamentStocksRouteHandler,
|
||||
getFilamentStockRouteHandler,
|
||||
newFilamentStockRouteHandler,
|
||||
} = await import('../filamentstocks.js');
|
||||
|
||||
const { listObjects, getObject, newObject } = await import('../../../database/database.js');
|
||||
const { filamentStockModel } = await import(
|
||||
'../../../database/schemas/inventory/filamentstock.schema.js'
|
||||
);
|
||||
|
||||
describe('Filament Stock Service Route Handlers', () => {
|
||||
let req, res;
|
||||
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
params: {},
|
||||
query: {},
|
||||
body: {},
|
||||
user: { id: 'test-user-id' },
|
||||
};
|
||||
res = {
|
||||
send: jest.fn(),
|
||||
status: jest.fn().mockReturnThis(),
|
||||
};
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('listFilamentStocksRouteHandler', () => {
|
||||
it('should list filament stocks', async () => {
|
||||
const mockResult = [{ _id: '1', currentWeight: 500 }];
|
||||
listObjects.mockResolvedValue(mockResult);
|
||||
|
||||
await listFilamentStocksRouteHandler(req, res);
|
||||
|
||||
expect(listObjects).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ model: filamentStockModel })
|
||||
);
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('newFilamentStockRouteHandler', () => {
|
||||
it('should create a new filament stock', async () => {
|
||||
req.body = { filament: 'filament123', currentWeight: 1000 };
|
||||
const mockStock = { _id: '456', ...req.body };
|
||||
newObject.mockResolvedValue(mockStock);
|
||||
|
||||
await newFilamentStockRouteHandler(req, res);
|
||||
|
||||
expect(newObject).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockStock);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
100
src/services/inventory/__tests__/orderitems.test.js
Normal file
100
src/services/inventory/__tests__/orderitems.test.js
Normal file
@ -0,0 +1,100 @@
|
||||
import { jest } from '@jest/globals';
|
||||
|
||||
jest.unstable_mockModule('../../../database/database.js', () => ({
|
||||
listObjects: jest.fn(),
|
||||
getObject: jest.fn(),
|
||||
editObject: jest.fn(),
|
||||
editObjects: jest.fn(),
|
||||
newObject: jest.fn(),
|
||||
deleteObject: jest.fn(),
|
||||
listObjectsByProperties: jest.fn(),
|
||||
getModelStats: jest.fn(),
|
||||
getModelHistory: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/inventory/orderitem.schema.js', () => ({
|
||||
orderItemModel: { modelName: 'OrderItem' },
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('log4js', () => ({
|
||||
default: {
|
||||
getLogger: () => ({
|
||||
level: 'info',
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
trace: jest.fn(),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
const {
|
||||
listOrderItemsRouteHandler,
|
||||
getOrderItemRouteHandler,
|
||||
newOrderItemRouteHandler,
|
||||
editOrderItemRouteHandler,
|
||||
deleteOrderItemRouteHandler,
|
||||
} = await import('../orderitems.js');
|
||||
|
||||
const { listObjects, getObject, editObject, newObject, deleteObject } = await import(
|
||||
'../../../database/database.js'
|
||||
);
|
||||
const { orderItemModel } = await import('../../../database/schemas/inventory/orderitem.schema.js');
|
||||
|
||||
describe('Order Item Service Route Handlers', () => {
|
||||
let req, res;
|
||||
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
params: {},
|
||||
query: {},
|
||||
body: {},
|
||||
user: { id: 'test-user-id' },
|
||||
};
|
||||
res = {
|
||||
send: jest.fn(),
|
||||
status: jest.fn().mockReturnThis(),
|
||||
};
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('listOrderItemsRouteHandler', () => {
|
||||
it('should list order items', async () => {
|
||||
const mockResult = [{ _id: '1', name: 'Order Item 1' }];
|
||||
listObjects.mockResolvedValue(mockResult);
|
||||
|
||||
await listOrderItemsRouteHandler(req, res);
|
||||
|
||||
expect(listObjects).toHaveBeenCalledWith(expect.objectContaining({ model: orderItemModel }));
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('newOrderItemRouteHandler', () => {
|
||||
it('should create a new order item', async () => {
|
||||
req.body = { name: 'New Item', quantity: 10, order: 'order123' };
|
||||
const mockItem = { _id: '456', ...req.body, state: { type: 'draft' } };
|
||||
newObject.mockResolvedValue(mockItem);
|
||||
|
||||
await newOrderItemRouteHandler(req, res);
|
||||
|
||||
expect(newObject).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockItem);
|
||||
});
|
||||
});
|
||||
|
||||
describe('editOrderItemRouteHandler', () => {
|
||||
it('should update an order item', async () => {
|
||||
req.params.id = '507f1f77bcf86cd799439011';
|
||||
req.body = { quantity: 20 };
|
||||
const mockResult = { _id: '507f1f77bcf86cd799439011', quantity: 20 };
|
||||
editObject.mockResolvedValue(mockResult);
|
||||
|
||||
await editOrderItemRouteHandler(req, res);
|
||||
|
||||
expect(editObject).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
88
src/services/inventory/__tests__/partstocks.test.js
Normal file
88
src/services/inventory/__tests__/partstocks.test.js
Normal file
@ -0,0 +1,88 @@
|
||||
import { jest } from '@jest/globals';
|
||||
|
||||
jest.unstable_mockModule('../../../database/database.js', () => ({
|
||||
listObjects: jest.fn(),
|
||||
getObject: jest.fn(),
|
||||
editObject: jest.fn(),
|
||||
editObjects: jest.fn(),
|
||||
newObject: jest.fn(),
|
||||
deleteObject: jest.fn(),
|
||||
listObjectsByProperties: jest.fn(),
|
||||
getModelStats: jest.fn(),
|
||||
getModelHistory: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/inventory/partstock.schema.js', () => ({
|
||||
partStockModel: { modelName: 'PartStock' },
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('log4js', () => ({
|
||||
default: {
|
||||
getLogger: () => ({
|
||||
level: 'info',
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
trace: jest.fn(),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
const {
|
||||
listPartStocksRouteHandler,
|
||||
getPartStockRouteHandler,
|
||||
newPartStockRouteHandler,
|
||||
editPartStockRouteHandler,
|
||||
deletePartStockRouteHandler,
|
||||
} = await import('../partstocks.js');
|
||||
|
||||
const { listObjects, getObject, editObject, newObject, deleteObject } = await import(
|
||||
'../../../database/database.js'
|
||||
);
|
||||
const { partStockModel } = await import('../../../database/schemas/inventory/partstock.schema.js');
|
||||
|
||||
describe('Part Stock Service Route Handlers', () => {
|
||||
let req, res;
|
||||
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
params: {},
|
||||
query: {},
|
||||
body: {},
|
||||
user: { id: 'test-user-id' },
|
||||
};
|
||||
res = {
|
||||
send: jest.fn(),
|
||||
status: jest.fn().mockReturnThis(),
|
||||
};
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('listPartStocksRouteHandler', () => {
|
||||
it('should list part stocks', async () => {
|
||||
const mockResult = [{ _id: '1', currentQuantity: 100 }];
|
||||
listObjects.mockResolvedValue(mockResult);
|
||||
|
||||
await listPartStocksRouteHandler(req, res);
|
||||
|
||||
expect(listObjects).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ model: partStockModel })
|
||||
);
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('newPartStockRouteHandler', () => {
|
||||
it('should create a new part stock', async () => {
|
||||
req.body = { part: 'part123', currentQuantity: 50 };
|
||||
const mockStock = { _id: '456', ...req.body };
|
||||
newObject.mockResolvedValue(mockStock);
|
||||
|
||||
await newPartStockRouteHandler(req, res);
|
||||
|
||||
expect(newObject).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockStock);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
122
src/services/inventory/__tests__/purchaseorders.test.js
Normal file
122
src/services/inventory/__tests__/purchaseorders.test.js
Normal file
@ -0,0 +1,122 @@
|
||||
import { jest } from '@jest/globals';
|
||||
|
||||
jest.unstable_mockModule('../../../database/database.js', () => ({
|
||||
listObjects: jest.fn(),
|
||||
getObject: jest.fn(),
|
||||
editObject: jest.fn(),
|
||||
editObjects: jest.fn(),
|
||||
newObject: jest.fn(),
|
||||
deleteObject: jest.fn(),
|
||||
listObjectsByProperties: jest.fn(),
|
||||
getModelStats: jest.fn(),
|
||||
getModelHistory: jest.fn(),
|
||||
checkStates: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/inventory/purchaseorder.schema.js', () => ({
|
||||
purchaseOrderModel: { modelName: 'PurchaseOrder' },
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/inventory/orderitem.schema.js', () => ({
|
||||
orderItemModel: { modelName: 'OrderItem' },
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/inventory/shipment.schema.js', () => ({
|
||||
shipmentModel: { modelName: 'Shipment' },
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('log4js', () => ({
|
||||
default: {
|
||||
getLogger: () => ({
|
||||
level: 'info',
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
trace: jest.fn(),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
const {
|
||||
listPurchaseOrdersRouteHandler,
|
||||
getPurchaseOrderRouteHandler,
|
||||
newPurchaseOrderRouteHandler,
|
||||
postPurchaseOrderRouteHandler,
|
||||
} = await import('../purchaseorders.js');
|
||||
|
||||
const { listObjects, getObject, editObject, newObject, checkStates } = await import(
|
||||
'../../../database/database.js'
|
||||
);
|
||||
const { purchaseOrderModel } = await import(
|
||||
'../../../database/schemas/inventory/purchaseorder.schema.js'
|
||||
);
|
||||
|
||||
describe('Purchase Order Service Route Handlers', () => {
|
||||
let req, res;
|
||||
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
params: {},
|
||||
query: {},
|
||||
body: {},
|
||||
user: { id: 'test-user-id' },
|
||||
};
|
||||
res = {
|
||||
send: jest.fn(),
|
||||
status: jest.fn().mockReturnThis(),
|
||||
};
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('listPurchaseOrdersRouteHandler', () => {
|
||||
it('should list purchase orders', async () => {
|
||||
const mockResult = [{ _id: '1', reference: 'PO-001' }];
|
||||
listObjects.mockResolvedValue(mockResult);
|
||||
|
||||
await listPurchaseOrdersRouteHandler(req, res);
|
||||
|
||||
expect(listObjects).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('postPurchaseOrderRouteHandler', () => {
|
||||
it('should post a draft purchase order and update items/shipments', async () => {
|
||||
req.params.id = '507f1f77bcf86cd799439011';
|
||||
|
||||
checkStates.mockResolvedValue(true);
|
||||
|
||||
listObjects.mockResolvedValueOnce([
|
||||
{ _id: 'oi1', state: { type: 'draft' }, shipment: 's1', _reference: 'ITEM1' },
|
||||
]);
|
||||
listObjects.mockResolvedValueOnce([
|
||||
{ _id: 's1', state: { type: 'draft' }, _reference: 'SHIP1' },
|
||||
]);
|
||||
|
||||
editObject.mockResolvedValue({ _id: '507f1f77bcf86cd799439011', state: { type: 'sent' } });
|
||||
|
||||
await postPurchaseOrderRouteHandler(req, res);
|
||||
|
||||
expect(checkStates).toHaveBeenCalledWith(expect.objectContaining({ states: ['draft'] }));
|
||||
expect(editObject).toHaveBeenCalledTimes(3);
|
||||
expect(res.send).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should fail if an order item is not in draft state', async () => {
|
||||
req.params.id = '507f1f77bcf86cd799439011';
|
||||
checkStates.mockResolvedValue(true);
|
||||
|
||||
listObjects.mockResolvedValueOnce([
|
||||
{ _id: 'oi1', state: { type: 'ordered' }, _reference: 'ITEM1' },
|
||||
]);
|
||||
listObjects.mockResolvedValueOnce([]);
|
||||
|
||||
await postPurchaseOrderRouteHandler(req, res);
|
||||
|
||||
expect(res.status).toHaveBeenCalledWith(400);
|
||||
expect(res.send).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ error: 'Order item ITEM1 not in draft state.' })
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
111
src/services/inventory/__tests__/shipments.test.js
Normal file
111
src/services/inventory/__tests__/shipments.test.js
Normal file
@ -0,0 +1,111 @@
|
||||
import { jest } from '@jest/globals';
|
||||
|
||||
jest.unstable_mockModule('../../../database/database.js', () => ({
|
||||
listObjects: jest.fn(),
|
||||
getObject: jest.fn(),
|
||||
editObject: jest.fn(),
|
||||
editObjects: jest.fn(),
|
||||
newObject: jest.fn(),
|
||||
deleteObject: jest.fn(),
|
||||
listObjectsByProperties: jest.fn(),
|
||||
getModelStats: jest.fn(),
|
||||
getModelHistory: jest.fn(),
|
||||
checkStates: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/inventory/shipment.schema.js', () => ({
|
||||
shipmentModel: { modelName: 'Shipment' },
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/inventory/orderitem.schema.js', () => ({
|
||||
orderItemModel: { modelName: 'OrderItem' },
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('log4js', () => ({
|
||||
default: {
|
||||
getLogger: () => ({
|
||||
level: 'info',
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
trace: jest.fn(),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
const {
|
||||
listShipmentsRouteHandler,
|
||||
getShipmentRouteHandler,
|
||||
newShipmentRouteHandler,
|
||||
shipShipmentRouteHandler,
|
||||
} = await import('../shipments.js');
|
||||
|
||||
const { listObjects, getObject, editObject, newObject, checkStates } = await import(
|
||||
'../../../database/database.js'
|
||||
);
|
||||
const { shipmentModel } = await import('../../../database/schemas/inventory/shipment.schema.js');
|
||||
const { orderItemModel } = await import('../../../database/schemas/inventory/orderitem.schema.js');
|
||||
|
||||
describe('Shipment Service Route Handlers', () => {
|
||||
let req, res;
|
||||
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
params: {},
|
||||
query: {},
|
||||
body: {},
|
||||
user: { id: 'test-user-id' },
|
||||
};
|
||||
res = {
|
||||
send: jest.fn(),
|
||||
status: jest.fn().mockReturnThis(),
|
||||
};
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('listShipmentsRouteHandler', () => {
|
||||
it('should list shipments', async () => {
|
||||
const mockResult = [{ _id: '1', trackingNumber: 'TRACK123' }];
|
||||
listObjects.mockResolvedValue(mockResult);
|
||||
|
||||
await listShipmentsRouteHandler(req, res);
|
||||
|
||||
expect(listObjects).toHaveBeenCalledWith(expect.objectContaining({ model: shipmentModel }));
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('newShipmentRouteHandler', () => {
|
||||
it('should create a new shipment', async () => {
|
||||
req.body = { order: 'order123', trackingNumber: 'TRACK456' };
|
||||
const mockShipment = { _id: '456', ...req.body, state: { type: 'draft' } };
|
||||
newObject.mockResolvedValue(mockShipment);
|
||||
|
||||
await newShipmentRouteHandler(req, res);
|
||||
|
||||
expect(newObject).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockShipment);
|
||||
});
|
||||
});
|
||||
|
||||
describe('shipShipmentRouteHandler', () => {
|
||||
it('should ship a planned shipment and update order items', async () => {
|
||||
req.params.id = '507f1f77bcf86cd799439011';
|
||||
checkStates.mockResolvedValue(true);
|
||||
|
||||
listObjects.mockResolvedValue([
|
||||
{ _id: 'oi1', state: { type: 'ordered' } },
|
||||
{ _id: 'oi2', state: { type: 'ordered' } },
|
||||
]);
|
||||
|
||||
editObject.mockResolvedValue({ _id: '507f1f77bcf86cd799439011', state: { type: 'shipped' } });
|
||||
|
||||
await shipShipmentRouteHandler(req, res);
|
||||
|
||||
expect(checkStates).toHaveBeenCalledWith(expect.objectContaining({ states: ['planned'] }));
|
||||
expect(editObject).toHaveBeenCalledTimes(3); // 2 order items + 1 shipment
|
||||
expect(res.send).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
91
src/services/inventory/__tests__/stockaudits.test.js
Normal file
91
src/services/inventory/__tests__/stockaudits.test.js
Normal file
@ -0,0 +1,91 @@
|
||||
import { jest } from '@jest/globals';
|
||||
|
||||
jest.unstable_mockModule('../../../utils.js', () => ({
|
||||
getAuditLogs: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/database.js', () => ({
|
||||
getModelStats: jest.fn(),
|
||||
getModelHistory: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/inventory/stockaudit.schema.js', () => ({
|
||||
stockAuditModel: {
|
||||
modelName: 'StockAudit',
|
||||
aggregate: jest.fn(),
|
||||
findOne: jest.fn(),
|
||||
create: jest.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('log4js', () => ({
|
||||
default: {
|
||||
getLogger: () => ({
|
||||
level: 'info',
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
trace: jest.fn(),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
const {
|
||||
listStockAuditsRouteHandler,
|
||||
getStockAuditRouteHandler,
|
||||
newStockAuditRouteHandler,
|
||||
} = await import('../stockaudits.js');
|
||||
|
||||
const { getAuditLogs } = await import('../../../utils.js');
|
||||
const { stockAuditModel } = await import('../../../database/schemas/inventory/stockaudit.schema.js');
|
||||
|
||||
describe('Stock Audit Service Route Handlers', () => {
|
||||
let req, res;
|
||||
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
params: {},
|
||||
query: {},
|
||||
body: {},
|
||||
user: { id: 'test-user-id' },
|
||||
};
|
||||
res = {
|
||||
send: jest.fn(),
|
||||
status: jest.fn().mockReturnThis(),
|
||||
};
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('listStockAuditsRouteHandler', () => {
|
||||
it('should list stock audits', async () => {
|
||||
const mockResult = [{ _id: '1', type: 'full' }];
|
||||
stockAuditModel.aggregate.mockResolvedValue(mockResult);
|
||||
|
||||
await listStockAuditsRouteHandler(req, res);
|
||||
|
||||
expect(stockAuditModel.aggregate).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getStockAuditRouteHandler', () => {
|
||||
it('should get a stock audit by ID with audit logs', async () => {
|
||||
req.params.id = '507f1f77bcf86cd799439011';
|
||||
const mockAudit = { _id: '507f1f77bcf86cd799439011', type: 'full', _doc: {} };
|
||||
stockAuditModel.findOne.mockReturnValue({
|
||||
populate: jest.fn().mockReturnValue({
|
||||
populate: jest.fn().mockReturnValue({
|
||||
populate: jest.fn().mockResolvedValue(mockAudit),
|
||||
}),
|
||||
}),
|
||||
});
|
||||
getAuditLogs.mockResolvedValue([]);
|
||||
|
||||
await getStockAuditRouteHandler(req, res);
|
||||
|
||||
expect(getAuditLogs).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
84
src/services/inventory/__tests__/stockevents.test.js
Normal file
84
src/services/inventory/__tests__/stockevents.test.js
Normal file
@ -0,0 +1,84 @@
|
||||
import { jest } from '@jest/globals';
|
||||
|
||||
jest.unstable_mockModule('../../../database/database.js', () => ({
|
||||
listObjects: jest.fn(),
|
||||
getObject: jest.fn(),
|
||||
editObject: jest.fn(),
|
||||
editObjects: jest.fn(),
|
||||
newObject: jest.fn(),
|
||||
deleteObject: jest.fn(),
|
||||
listObjectsByProperties: jest.fn(),
|
||||
getModelStats: jest.fn(),
|
||||
getModelHistory: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/inventory/stockevent.schema.js', () => ({
|
||||
stockEventModel: { modelName: 'StockEvent' },
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('log4js', () => ({
|
||||
default: {
|
||||
getLogger: () => ({
|
||||
level: 'info',
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
trace: jest.fn(),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
const {
|
||||
listStockEventsRouteHandler,
|
||||
getStockEventRouteHandler,
|
||||
newStockEventRouteHandler,
|
||||
} = await import('../stockevents.js');
|
||||
|
||||
const { listObjects, getObject, newObject } = await import('../../../database/database.js');
|
||||
const { stockEventModel } = await import('../../../database/schemas/inventory/stockevent.schema.js');
|
||||
|
||||
describe('Stock Event Service Route Handlers', () => {
|
||||
let req, res;
|
||||
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
params: {},
|
||||
query: {},
|
||||
body: {},
|
||||
user: { id: 'test-user-id' },
|
||||
};
|
||||
res = {
|
||||
send: jest.fn(),
|
||||
status: jest.fn().mockReturnThis(),
|
||||
};
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('listStockEventsRouteHandler', () => {
|
||||
it('should list stock events', async () => {
|
||||
const mockResult = [{ _id: '1', type: 'adjustment' }];
|
||||
listObjects.mockResolvedValue(mockResult);
|
||||
|
||||
await listStockEventsRouteHandler(req, res);
|
||||
|
||||
expect(listObjects).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ model: stockEventModel })
|
||||
);
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('newStockEventRouteHandler', () => {
|
||||
it('should create a new stock event', async () => {
|
||||
req.body = { type: 'adjustment', value: 10 };
|
||||
const mockEvent = { _id: '456', ...req.body };
|
||||
newObject.mockResolvedValue(mockEvent);
|
||||
|
||||
await newStockEventRouteHandler(req, res);
|
||||
|
||||
expect(newObject).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockEvent);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
87
src/services/management/__tests__/auditlogs.test.js
Normal file
87
src/services/management/__tests__/auditlogs.test.js
Normal file
@ -0,0 +1,87 @@
|
||||
import { jest } from '@jest/globals';
|
||||
|
||||
jest.unstable_mockModule('../../../database/database.js', () => ({
|
||||
getModelStats: jest.fn(),
|
||||
getModelHistory: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/management/auditlog.schema.js', () => ({
|
||||
auditLogModel: {
|
||||
modelName: 'AuditLog',
|
||||
find: jest.fn(),
|
||||
findOne: jest.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('log4js', () => ({
|
||||
default: {
|
||||
getLogger: () => ({
|
||||
level: 'info',
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
trace: jest.fn(),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
const { listAuditLogsRouteHandler, getAuditLogRouteHandler } = await import('../auditlogs.js');
|
||||
|
||||
const { auditLogModel } = await import('../../../database/schemas/management/auditlog.schema.js');
|
||||
|
||||
describe('Audit Log Service Route Handlers', () => {
|
||||
let req, res;
|
||||
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
params: {},
|
||||
query: {},
|
||||
body: {},
|
||||
user: { id: 'test-user-id' },
|
||||
};
|
||||
res = {
|
||||
send: jest.fn(),
|
||||
status: jest.fn().mockReturnThis(),
|
||||
};
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('listAuditLogsRouteHandler', () => {
|
||||
it('should list audit logs', async () => {
|
||||
const mockResult = [
|
||||
{ _id: '1', operation: 'edit', parent: 'parent123', _doc: { parent: 'parent123' } },
|
||||
];
|
||||
auditLogModel.find.mockReturnValue({
|
||||
sort: jest.fn().mockReturnThis(),
|
||||
skip: jest.fn().mockReturnThis(),
|
||||
limit: jest.fn().mockReturnThis(),
|
||||
populate: jest.fn().mockResolvedValue(mockResult),
|
||||
});
|
||||
|
||||
await listAuditLogsRouteHandler(req, res);
|
||||
|
||||
expect(auditLogModel.find).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getAuditLogRouteHandler', () => {
|
||||
it('should get an audit log by ID', async () => {
|
||||
req.params.id = '507f1f77bcf86cd799439011';
|
||||
const mockLog = { _id: '507f1f77bcf86cd799439011', operation: 'edit' };
|
||||
auditLogModel.findOne.mockReturnValue({
|
||||
populate: jest.fn().mockReturnValue({
|
||||
populate: jest.fn().mockReturnValue({
|
||||
populate: jest.fn().mockResolvedValue(mockLog),
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
await getAuditLogRouteHandler(req, res);
|
||||
|
||||
expect(auditLogModel.findOne).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockLog);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
84
src/services/management/__tests__/courier.test.js
Normal file
84
src/services/management/__tests__/courier.test.js
Normal file
@ -0,0 +1,84 @@
|
||||
import { jest } from '@jest/globals';
|
||||
|
||||
jest.unstable_mockModule('../../../database/database.js', () => ({
|
||||
listObjects: jest.fn(),
|
||||
getObject: jest.fn(),
|
||||
editObject: jest.fn(),
|
||||
newObject: jest.fn(),
|
||||
deleteObject: jest.fn(),
|
||||
listObjectsByProperties: jest.fn(),
|
||||
getModelStats: jest.fn(),
|
||||
getModelHistory: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/management/courier.schema.js', () => ({
|
||||
courierModel: { modelName: 'Courier' },
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('log4js', () => ({
|
||||
default: {
|
||||
getLogger: () => ({
|
||||
level: 'info',
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
trace: jest.fn(),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
const {
|
||||
listCouriersRouteHandler,
|
||||
getCourierRouteHandler,
|
||||
newCourierRouteHandler,
|
||||
editCourierRouteHandler,
|
||||
} = await import('../courier.js');
|
||||
|
||||
const { listObjects, getObject, editObject, newObject } = await import(
|
||||
'../../../database/database.js'
|
||||
);
|
||||
const { courierModel } = await import('../../../database/schemas/management/courier.schema.js');
|
||||
|
||||
describe('Courier Service Route Handlers', () => {
|
||||
let req, res;
|
||||
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
params: {},
|
||||
query: {},
|
||||
body: {},
|
||||
user: { id: 'test-user-id' },
|
||||
};
|
||||
res = {
|
||||
send: jest.fn(),
|
||||
status: jest.fn().mockReturnThis(),
|
||||
};
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('listCouriersRouteHandler', () => {
|
||||
it('should list couriers', async () => {
|
||||
const mockResult = [{ _id: '1', name: 'FedEx' }];
|
||||
listObjects.mockResolvedValue(mockResult);
|
||||
|
||||
await listCouriersRouteHandler(req, res);
|
||||
|
||||
expect(listObjects).toHaveBeenCalledWith(expect.objectContaining({ model: courierModel }));
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('newCourierRouteHandler', () => {
|
||||
it('should create a new courier', async () => {
|
||||
req.body = { name: 'DHL', email: 'contact@dhl.com' };
|
||||
const mockCourier = { _id: '456', ...req.body };
|
||||
newObject.mockResolvedValue(mockCourier);
|
||||
|
||||
await newCourierRouteHandler(req, res);
|
||||
|
||||
expect(newObject).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockCourier);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
88
src/services/management/__tests__/courierservice.test.js
Normal file
88
src/services/management/__tests__/courierservice.test.js
Normal file
@ -0,0 +1,88 @@
|
||||
import { jest } from '@jest/globals';
|
||||
|
||||
jest.unstable_mockModule('../../../database/database.js', () => ({
|
||||
listObjects: jest.fn(),
|
||||
getObject: jest.fn(),
|
||||
editObject: jest.fn(),
|
||||
newObject: jest.fn(),
|
||||
deleteObject: jest.fn(),
|
||||
listObjectsByProperties: jest.fn(),
|
||||
getModelStats: jest.fn(),
|
||||
getModelHistory: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/management/courierservice.schema.js', () => ({
|
||||
courierServiceModel: { modelName: 'CourierService' },
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('log4js', () => ({
|
||||
default: {
|
||||
getLogger: () => ({
|
||||
level: 'info',
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
trace: jest.fn(),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
const {
|
||||
listCourierServicesRouteHandler,
|
||||
getCourierServiceRouteHandler,
|
||||
newCourierServiceRouteHandler,
|
||||
editCourierServiceRouteHandler,
|
||||
} = await import('../courierservice.js');
|
||||
|
||||
const { listObjects, getObject, editObject, newObject } = await import(
|
||||
'../../../database/database.js'
|
||||
);
|
||||
const { courierServiceModel } = await import(
|
||||
'../../../database/schemas/management/courierservice.schema.js'
|
||||
);
|
||||
|
||||
describe('Courier Service Route Handlers', () => {
|
||||
let req, res;
|
||||
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
params: {},
|
||||
query: {},
|
||||
body: {},
|
||||
user: { id: 'test-user-id' },
|
||||
};
|
||||
res = {
|
||||
send: jest.fn(),
|
||||
status: jest.fn().mockReturnThis(),
|
||||
};
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('listCourierServicesRouteHandler', () => {
|
||||
it('should list courier services', async () => {
|
||||
const mockResult = [{ _id: '1', name: 'Express' }];
|
||||
listObjects.mockResolvedValue(mockResult);
|
||||
|
||||
await listCourierServicesRouteHandler(req, res);
|
||||
|
||||
expect(listObjects).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ model: courierServiceModel })
|
||||
);
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('newCourierServiceRouteHandler', () => {
|
||||
it('should create a new courier service', async () => {
|
||||
req.body = { courier: 'courier123', name: 'Express Delivery' };
|
||||
const mockService = { _id: '456', ...req.body };
|
||||
newObject.mockResolvedValue(mockService);
|
||||
|
||||
await newCourierServiceRouteHandler(req, res);
|
||||
|
||||
expect(newObject).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockService);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
85
src/services/management/__tests__/documentjobs.test.js
Normal file
85
src/services/management/__tests__/documentjobs.test.js
Normal file
@ -0,0 +1,85 @@
|
||||
import { jest } from '@jest/globals';
|
||||
|
||||
jest.unstable_mockModule('../../../database/database.js', () => ({
|
||||
listObjects: jest.fn(),
|
||||
getObject: jest.fn(),
|
||||
editObject: jest.fn(),
|
||||
newObject: jest.fn(),
|
||||
deleteObject: jest.fn(),
|
||||
listObjectsByProperties: jest.fn(),
|
||||
getModelStats: jest.fn(),
|
||||
getModelHistory: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/management/documentjob.schema.js', () => ({
|
||||
documentJobModel: { modelName: 'DocumentJob' },
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('log4js', () => ({
|
||||
default: {
|
||||
getLogger: () => ({
|
||||
level: 'info',
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
trace: jest.fn(),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
const {
|
||||
listDocumentJobsRouteHandler,
|
||||
getDocumentJobRouteHandler,
|
||||
newDocumentJobRouteHandler,
|
||||
} = await import('../documentjobs.js');
|
||||
|
||||
const { listObjects, getObject, newObject } = await import('../../../database/database.js');
|
||||
const { documentJobModel } = await import(
|
||||
'../../../database/schemas/management/documentjob.schema.js'
|
||||
);
|
||||
|
||||
describe('Document Job Service Route Handlers', () => {
|
||||
let req, res;
|
||||
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
params: {},
|
||||
query: {},
|
||||
body: {},
|
||||
user: { id: 'test-user-id' },
|
||||
};
|
||||
res = {
|
||||
send: jest.fn(),
|
||||
status: jest.fn().mockReturnThis(),
|
||||
};
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('listDocumentJobsRouteHandler', () => {
|
||||
it('should list document jobs', async () => {
|
||||
const mockResult = [{ _id: '1', state: { type: 'pending' } }];
|
||||
listObjects.mockResolvedValue(mockResult);
|
||||
|
||||
await listDocumentJobsRouteHandler(req, res);
|
||||
|
||||
expect(listObjects).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ model: documentJobModel })
|
||||
);
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('newDocumentJobRouteHandler', () => {
|
||||
it('should create a new document job', async () => {
|
||||
req.body = { documentTemplate: 'template123', documentPrinter: 'printer123' };
|
||||
const mockJob = { _id: '456', ...req.body };
|
||||
newObject.mockResolvedValue(mockJob);
|
||||
|
||||
await newDocumentJobRouteHandler(req, res);
|
||||
|
||||
expect(newObject).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockJob);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
85
src/services/management/__tests__/documentprinters.test.js
Normal file
85
src/services/management/__tests__/documentprinters.test.js
Normal file
@ -0,0 +1,85 @@
|
||||
import { jest } from '@jest/globals';
|
||||
|
||||
jest.unstable_mockModule('../../../database/database.js', () => ({
|
||||
listObjects: jest.fn(),
|
||||
getObject: jest.fn(),
|
||||
editObject: jest.fn(),
|
||||
newObject: jest.fn(),
|
||||
deleteObject: jest.fn(),
|
||||
listObjectsByProperties: jest.fn(),
|
||||
getModelStats: jest.fn(),
|
||||
getModelHistory: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/management/documentprinter.schema.js', () => ({
|
||||
documentPrinterModel: { modelName: 'DocumentPrinter' },
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('log4js', () => ({
|
||||
default: {
|
||||
getLogger: () => ({
|
||||
level: 'info',
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
trace: jest.fn(),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
const {
|
||||
listDocumentPrintersRouteHandler,
|
||||
getDocumentPrinterRouteHandler,
|
||||
newDocumentPrinterRouteHandler,
|
||||
} = await import('../documentprinters.js');
|
||||
|
||||
const { listObjects, getObject, newObject } = await import('../../../database/database.js');
|
||||
const { documentPrinterModel } = await import(
|
||||
'../../../database/schemas/management/documentprinter.schema.js'
|
||||
);
|
||||
|
||||
describe('Document Printer Service Route Handlers', () => {
|
||||
let req, res;
|
||||
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
params: {},
|
||||
query: {},
|
||||
body: {},
|
||||
user: { id: 'test-user-id' },
|
||||
};
|
||||
res = {
|
||||
send: jest.fn(),
|
||||
status: jest.fn().mockReturnThis(),
|
||||
};
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('listDocumentPrintersRouteHandler', () => {
|
||||
it('should list document printers', async () => {
|
||||
const mockResult = [{ _id: '1', name: 'HP LaserJet' }];
|
||||
listObjects.mockResolvedValue(mockResult);
|
||||
|
||||
await listDocumentPrintersRouteHandler(req, res);
|
||||
|
||||
expect(listObjects).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ model: documentPrinterModel })
|
||||
);
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('newDocumentPrinterRouteHandler', () => {
|
||||
it('should create a new document printer', async () => {
|
||||
req.body = { name: 'Canon Printer', host: 'host123' };
|
||||
const mockPrinter = { _id: '456', ...req.body };
|
||||
newObject.mockResolvedValue(mockPrinter);
|
||||
|
||||
await newDocumentPrinterRouteHandler(req, res);
|
||||
|
||||
expect(newObject).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockPrinter);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
88
src/services/management/__tests__/documentsizes.test.js
Normal file
88
src/services/management/__tests__/documentsizes.test.js
Normal file
@ -0,0 +1,88 @@
|
||||
import { jest } from '@jest/globals';
|
||||
|
||||
jest.unstable_mockModule('../../../database/database.js', () => ({
|
||||
listObjects: jest.fn(),
|
||||
getObject: jest.fn(),
|
||||
editObject: jest.fn(),
|
||||
newObject: jest.fn(),
|
||||
deleteObject: jest.fn(),
|
||||
listObjectsByProperties: jest.fn(),
|
||||
getModelStats: jest.fn(),
|
||||
getModelHistory: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/management/documentsize.schema.js', () => ({
|
||||
documentSizeModel: { modelName: 'DocumentSize' },
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('log4js', () => ({
|
||||
default: {
|
||||
getLogger: () => ({
|
||||
level: 'info',
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
trace: jest.fn(),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
const {
|
||||
listDocumentSizesRouteHandler,
|
||||
getDocumentSizeRouteHandler,
|
||||
newDocumentSizeRouteHandler,
|
||||
editDocumentSizeRouteHandler,
|
||||
} = await import('../documentsizes.js');
|
||||
|
||||
const { listObjects, getObject, editObject, newObject } = await import(
|
||||
'../../../database/database.js'
|
||||
);
|
||||
const { documentSizeModel } = await import(
|
||||
'../../../database/schemas/management/documentsize.schema.js'
|
||||
);
|
||||
|
||||
describe('Document Size Service Route Handlers', () => {
|
||||
let req, res;
|
||||
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
params: {},
|
||||
query: {},
|
||||
body: {},
|
||||
user: { id: 'test-user-id' },
|
||||
};
|
||||
res = {
|
||||
send: jest.fn(),
|
||||
status: jest.fn().mockReturnThis(),
|
||||
};
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('listDocumentSizesRouteHandler', () => {
|
||||
it('should list document sizes', async () => {
|
||||
const mockResult = [{ _id: '1', name: 'A4', width: 210, height: 297 }];
|
||||
listObjects.mockResolvedValue(mockResult);
|
||||
|
||||
await listDocumentSizesRouteHandler(req, res);
|
||||
|
||||
expect(listObjects).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ model: documentSizeModel })
|
||||
);
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('newDocumentSizeRouteHandler', () => {
|
||||
it('should create a new document size', async () => {
|
||||
req.body = { name: 'Letter', width: 216, height: 279 };
|
||||
const mockSize = { _id: '456', ...req.body };
|
||||
newObject.mockResolvedValue(mockSize);
|
||||
|
||||
await newDocumentSizeRouteHandler(req, res);
|
||||
|
||||
expect(newObject).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockSize);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
88
src/services/management/__tests__/documenttemplates.test.js
Normal file
88
src/services/management/__tests__/documenttemplates.test.js
Normal file
@ -0,0 +1,88 @@
|
||||
import { jest } from '@jest/globals';
|
||||
|
||||
jest.unstable_mockModule('../../../database/database.js', () => ({
|
||||
listObjects: jest.fn(),
|
||||
getObject: jest.fn(),
|
||||
editObject: jest.fn(),
|
||||
newObject: jest.fn(),
|
||||
deleteObject: jest.fn(),
|
||||
listObjectsByProperties: jest.fn(),
|
||||
getModelStats: jest.fn(),
|
||||
getModelHistory: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/management/documenttemplate.schema.js', () => ({
|
||||
documentTemplateModel: { modelName: 'DocumentTemplate' },
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('log4js', () => ({
|
||||
default: {
|
||||
getLogger: () => ({
|
||||
level: 'info',
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
trace: jest.fn(),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
const {
|
||||
listDocumentTemplatesRouteHandler,
|
||||
getDocumentTemplateRouteHandler,
|
||||
newDocumentTemplateRouteHandler,
|
||||
editDocumentTemplateRouteHandler,
|
||||
} = await import('../documenttemplates.js');
|
||||
|
||||
const { listObjects, getObject, editObject, newObject } = await import(
|
||||
'../../../database/database.js'
|
||||
);
|
||||
const { documentTemplateModel } = await import(
|
||||
'../../../database/schemas/management/documenttemplate.schema.js'
|
||||
);
|
||||
|
||||
describe('Document Template Service Route Handlers', () => {
|
||||
let req, res;
|
||||
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
params: {},
|
||||
query: {},
|
||||
body: {},
|
||||
user: { id: 'test-user-id' },
|
||||
};
|
||||
res = {
|
||||
send: jest.fn(),
|
||||
status: jest.fn().mockReturnThis(),
|
||||
};
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('listDocumentTemplatesRouteHandler', () => {
|
||||
it('should list document templates', async () => {
|
||||
const mockResult = [{ _id: '1', name: 'Invoice Template' }];
|
||||
listObjects.mockResolvedValue(mockResult);
|
||||
|
||||
await listDocumentTemplatesRouteHandler(req, res);
|
||||
|
||||
expect(listObjects).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ model: documentTemplateModel })
|
||||
);
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('newDocumentTemplateRouteHandler', () => {
|
||||
it('should create a new document template', async () => {
|
||||
req.body = { name: 'New Template', documentSize: 'size123' };
|
||||
const mockTemplate = { _id: '456', ...req.body };
|
||||
newObject.mockResolvedValue(mockTemplate);
|
||||
|
||||
await newDocumentTemplateRouteHandler(req, res);
|
||||
|
||||
expect(newObject).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockTemplate);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
98
src/services/management/__tests__/filaments.test.js
Normal file
98
src/services/management/__tests__/filaments.test.js
Normal file
@ -0,0 +1,98 @@
|
||||
import { jest } from '@jest/globals';
|
||||
|
||||
jest.unstable_mockModule('../../../database/database.js', () => ({
|
||||
listObjects: jest.fn(),
|
||||
getObject: jest.fn(),
|
||||
editObject: jest.fn(),
|
||||
editObjects: jest.fn(),
|
||||
newObject: jest.fn(),
|
||||
listObjectsByProperties: jest.fn(),
|
||||
getModelStats: jest.fn(),
|
||||
getModelHistory: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/management/filament.schema.js', () => ({
|
||||
filamentModel: { modelName: 'Filament' },
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('log4js', () => ({
|
||||
default: {
|
||||
getLogger: () => ({
|
||||
level: 'info',
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
trace: jest.fn(),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
const {
|
||||
listFilamentsRouteHandler,
|
||||
getFilamentRouteHandler,
|
||||
newFilamentRouteHandler,
|
||||
editFilamentRouteHandler,
|
||||
} = await import('../filaments.js');
|
||||
|
||||
const { listObjects, getObject, editObject, newObject } = await import(
|
||||
'../../../database/database.js'
|
||||
);
|
||||
const { filamentModel } = await import('../../../database/schemas/management/filament.schema.js');
|
||||
|
||||
describe('Filament Service Route Handlers', () => {
|
||||
let req, res;
|
||||
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
params: {},
|
||||
query: {},
|
||||
body: {},
|
||||
user: { id: 'test-user-id' },
|
||||
};
|
||||
res = {
|
||||
send: jest.fn(),
|
||||
status: jest.fn().mockReturnThis(),
|
||||
};
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('listFilamentsRouteHandler', () => {
|
||||
it('should list filaments', async () => {
|
||||
const mockResult = [{ _id: '1', name: 'Filament 1' }];
|
||||
listObjects.mockResolvedValue(mockResult);
|
||||
|
||||
await listFilamentsRouteHandler(req, res);
|
||||
|
||||
expect(listObjects).toHaveBeenCalledWith(expect.objectContaining({ model: filamentModel }));
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('newFilamentRouteHandler', () => {
|
||||
it('should create a new filament', async () => {
|
||||
req.body = { name: 'PLA Red', diameter: 1.75, cost: 20 };
|
||||
const mockFilament = { _id: '456', ...req.body };
|
||||
newObject.mockResolvedValue(mockFilament);
|
||||
|
||||
await newFilamentRouteHandler(req, res);
|
||||
|
||||
expect(newObject).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockFilament);
|
||||
});
|
||||
});
|
||||
|
||||
describe('editFilamentRouteHandler', () => {
|
||||
it('should update a filament', async () => {
|
||||
req.params.id = '507f1f77bcf86cd799439011';
|
||||
req.body = { name: 'Updated Filament', cost: 25 };
|
||||
const mockResult = { _id: '507f1f77bcf86cd799439011', ...req.body };
|
||||
editObject.mockResolvedValue(mockResult);
|
||||
|
||||
await editFilamentRouteHandler(req, res);
|
||||
|
||||
expect(editObject).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
123
src/services/management/__tests__/files.test.js
Normal file
123
src/services/management/__tests__/files.test.js
Normal file
@ -0,0 +1,123 @@
|
||||
import { jest } from '@jest/globals';
|
||||
|
||||
jest.unstable_mockModule('../../../database/database.js', () => ({
|
||||
listObjects: jest.fn(),
|
||||
getObject: jest.fn(),
|
||||
editObject: jest.fn(),
|
||||
newObject: jest.fn(),
|
||||
deleteObject: jest.fn(),
|
||||
listObjectsByProperties: jest.fn(),
|
||||
flushFile: jest.fn(),
|
||||
getModelStats: jest.fn(),
|
||||
getModelHistory: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/management/file.schema.js', () => ({
|
||||
fileModel: { modelName: 'File' },
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/ceph.js', () => ({
|
||||
uploadFile: jest.fn(),
|
||||
downloadFile: jest.fn(),
|
||||
deleteFile: jest.fn(),
|
||||
BUCKETS: { FILES: 'test-bucket' },
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../utils.js', () => ({
|
||||
getFileMeta: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('multer', () => {
|
||||
const mockMemoryStorage = jest.fn();
|
||||
const mockMulter = jest.fn(() => ({
|
||||
single: jest.fn(),
|
||||
}));
|
||||
mockMulter.memoryStorage = mockMemoryStorage;
|
||||
return {
|
||||
default: mockMulter,
|
||||
memoryStorage: mockMemoryStorage,
|
||||
};
|
||||
});
|
||||
|
||||
jest.unstable_mockModule('log4js', () => ({
|
||||
default: {
|
||||
getLogger: () => ({
|
||||
level: 'info',
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
trace: jest.fn(),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
const {
|
||||
listFilesRouteHandler,
|
||||
getFileRouteHandler,
|
||||
editFileRouteHandler,
|
||||
flushFileRouteHandler,
|
||||
} = await import('../files.js');
|
||||
|
||||
const { listObjects, getObject, editObject, flushFile } = await import(
|
||||
'../../../database/database.js'
|
||||
);
|
||||
const { fileModel } = await import('../../../database/schemas/management/file.schema.js');
|
||||
|
||||
describe('File Service Route Handlers', () => {
|
||||
let req, res;
|
||||
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
params: {},
|
||||
query: {},
|
||||
body: {},
|
||||
user: { id: 'test-user-id' },
|
||||
};
|
||||
res = {
|
||||
send: jest.fn(),
|
||||
status: jest.fn().mockReturnThis(),
|
||||
};
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('listFilesRouteHandler', () => {
|
||||
it('should list files', async () => {
|
||||
const mockResult = [{ _id: '1', name: 'file.pdf' }];
|
||||
listObjects.mockResolvedValue(mockResult);
|
||||
|
||||
await listFilesRouteHandler(req, res);
|
||||
|
||||
expect(listObjects).toHaveBeenCalledWith(expect.objectContaining({ model: fileModel }));
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getFileRouteHandler', () => {
|
||||
it('should get a file by ID', async () => {
|
||||
req.params.id = '123';
|
||||
const mockFile = { _id: '123', name: 'test.pdf' };
|
||||
getObject.mockResolvedValue(mockFile);
|
||||
|
||||
await getFileRouteHandler(req, res);
|
||||
|
||||
expect(getObject).toHaveBeenCalledWith(expect.objectContaining({ id: '123' }));
|
||||
expect(res.send).toHaveBeenCalledWith(mockFile);
|
||||
});
|
||||
});
|
||||
|
||||
describe('flushFileRouteHandler', () => {
|
||||
it('should flush/delete a file', async () => {
|
||||
req.params.id = '507f1f77bcf86cd799439011';
|
||||
const mockResult = { success: true };
|
||||
flushFile.mockResolvedValue(mockResult);
|
||||
|
||||
await flushFileRouteHandler(req, res);
|
||||
|
||||
expect(flushFile).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ id: '507f1f77bcf86cd799439011' })
|
||||
);
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
99
src/services/management/__tests__/hosts.test.js
Normal file
99
src/services/management/__tests__/hosts.test.js
Normal file
@ -0,0 +1,99 @@
|
||||
import { jest } from '@jest/globals';
|
||||
|
||||
jest.unstable_mockModule('../../../database/database.js', () => ({
|
||||
listObjects: jest.fn(),
|
||||
getObject: jest.fn(),
|
||||
editObject: jest.fn(),
|
||||
newObject: jest.fn(),
|
||||
deleteObject: jest.fn(),
|
||||
listObjectsByProperties: jest.fn(),
|
||||
getModelStats: jest.fn(),
|
||||
getModelHistory: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/management/host.schema.js', () => ({
|
||||
hostModel: { modelName: 'Host' },
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('log4js', () => ({
|
||||
default: {
|
||||
getLogger: () => ({
|
||||
level: 'info',
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
trace: jest.fn(),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
const {
|
||||
listHostsRouteHandler,
|
||||
getHostRouteHandler,
|
||||
newHostRouteHandler,
|
||||
editHostRouteHandler,
|
||||
deleteHostRouteHandler,
|
||||
} = await import('../hosts.js');
|
||||
|
||||
const { listObjects, getObject, editObject, newObject, deleteObject } = await import(
|
||||
'../../../database/database.js'
|
||||
);
|
||||
const { hostModel } = await import('../../../database/schemas/management/host.schema.js');
|
||||
|
||||
describe('Host Service Route Handlers', () => {
|
||||
let req, res;
|
||||
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
params: {},
|
||||
query: {},
|
||||
body: {},
|
||||
user: { id: 'test-user-id' },
|
||||
};
|
||||
res = {
|
||||
send: jest.fn(),
|
||||
status: jest.fn().mockReturnThis(),
|
||||
};
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('listHostsRouteHandler', () => {
|
||||
it('should list hosts', async () => {
|
||||
const mockResult = [{ _id: '1', name: 'Host 1' }];
|
||||
listObjects.mockResolvedValue(mockResult);
|
||||
|
||||
await listHostsRouteHandler(req, res);
|
||||
|
||||
expect(listObjects).toHaveBeenCalledWith(expect.objectContaining({ model: hostModel }));
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('newHostRouteHandler', () => {
|
||||
it('should create a new host', async () => {
|
||||
req.body = { name: 'New Host', address: '192.168.1.100' };
|
||||
const mockHost = { _id: '456', ...req.body };
|
||||
newObject.mockResolvedValue(mockHost);
|
||||
|
||||
await newHostRouteHandler(req, res);
|
||||
|
||||
expect(newObject).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockHost);
|
||||
});
|
||||
});
|
||||
|
||||
describe('editHostRouteHandler', () => {
|
||||
it('should update a host', async () => {
|
||||
req.params.id = '507f1f77bcf86cd799439011';
|
||||
req.body = { name: 'Updated Host' };
|
||||
const mockResult = { _id: '507f1f77bcf86cd799439011', ...req.body };
|
||||
editObject.mockResolvedValue(mockResult);
|
||||
|
||||
await editHostRouteHandler(req, res);
|
||||
|
||||
expect(editObject).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
75
src/services/management/__tests__/materials.test.js
Normal file
75
src/services/management/__tests__/materials.test.js
Normal file
@ -0,0 +1,75 @@
|
||||
import { jest } from '@jest/globals';
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/management/material.schema.js', () => ({
|
||||
materialModel: {
|
||||
modelName: 'Material',
|
||||
aggregate: jest.fn(),
|
||||
findOne: jest.fn(),
|
||||
updateOne: jest.fn(),
|
||||
create: jest.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('log4js', () => ({
|
||||
default: {
|
||||
getLogger: () => ({
|
||||
level: 'info',
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
trace: jest.fn(),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
const {
|
||||
listMaterialsRouteHandler,
|
||||
getMaterialRouteHandler,
|
||||
newMaterialRouteHandler,
|
||||
} = await import('../materials.js');
|
||||
|
||||
const { materialModel } = await import('../../../database/schemas/management/material.schema.js');
|
||||
|
||||
describe('Material Service Route Handlers', () => {
|
||||
let req, res;
|
||||
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
params: {},
|
||||
query: {},
|
||||
body: {},
|
||||
user: { id: 'test-user-id' },
|
||||
};
|
||||
res = {
|
||||
send: jest.fn(),
|
||||
status: jest.fn().mockReturnThis(),
|
||||
};
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('listMaterialsRouteHandler', () => {
|
||||
it('should list materials', async () => {
|
||||
const mockResult = [{ name: 'PLA' }];
|
||||
materialModel.aggregate.mockResolvedValue(mockResult);
|
||||
|
||||
await listMaterialsRouteHandler(req, res);
|
||||
|
||||
expect(materialModel.aggregate).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getMaterialRouteHandler', () => {
|
||||
it('should get a material by ID', async () => {
|
||||
req.params.id = '507f1f77bcf86cd799439011';
|
||||
const mockMaterial = { _id: '507f1f77bcf86cd799439011', name: 'PLA' };
|
||||
materialModel.findOne.mockResolvedValue(mockMaterial);
|
||||
|
||||
await getMaterialRouteHandler(req, res);
|
||||
|
||||
expect(materialModel.findOne).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockMaterial);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
86
src/services/management/__tests__/notetypes.test.js
Normal file
86
src/services/management/__tests__/notetypes.test.js
Normal file
@ -0,0 +1,86 @@
|
||||
import { jest } from '@jest/globals';
|
||||
|
||||
jest.unstable_mockModule('../../../database/database.js', () => ({
|
||||
listObjects: jest.fn(),
|
||||
getObject: jest.fn(),
|
||||
editObject: jest.fn(),
|
||||
newObject: jest.fn(),
|
||||
deleteObject: jest.fn(),
|
||||
listObjectsByProperties: jest.fn(),
|
||||
getModelStats: jest.fn(),
|
||||
getModelHistory: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/management/notetype.schema.js', () => ({
|
||||
noteTypeModel: { modelName: 'NoteType' },
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('log4js', () => ({
|
||||
default: {
|
||||
getLogger: () => ({
|
||||
level: 'info',
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
trace: jest.fn(),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
const {
|
||||
listNoteTypesRouteHandler,
|
||||
getNoteTypeRouteHandler,
|
||||
newNoteTypeRouteHandler,
|
||||
editNoteTypeRouteHandler,
|
||||
} = await import('../notetypes.js');
|
||||
|
||||
const { listObjects, getObject, editObject, newObject } = await import(
|
||||
'../../../database/database.js'
|
||||
);
|
||||
const { noteTypeModel } = await import('../../../database/schemas/management/notetype.schema.js');
|
||||
|
||||
describe('Note Type Service Route Handlers', () => {
|
||||
let req, res;
|
||||
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
params: {},
|
||||
query: {},
|
||||
body: {},
|
||||
user: { id: 'test-user-id' },
|
||||
};
|
||||
res = {
|
||||
send: jest.fn(),
|
||||
status: jest.fn().mockReturnThis(),
|
||||
};
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('listNoteTypesRouteHandler', () => {
|
||||
it('should list note types', async () => {
|
||||
const mockResult = [{ _id: '1', name: 'General' }];
|
||||
listObjects.mockResolvedValue(mockResult);
|
||||
|
||||
await listNoteTypesRouteHandler(req, res);
|
||||
|
||||
expect(listObjects).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ model: noteTypeModel })
|
||||
);
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('newNoteTypeRouteHandler', () => {
|
||||
it('should create a new note type', async () => {
|
||||
req.body = { name: 'Important', color: '#ff0000' };
|
||||
const mockNoteType = { _id: '456', ...req.body };
|
||||
newObject.mockResolvedValue(mockNoteType);
|
||||
|
||||
await newNoteTypeRouteHandler(req, res);
|
||||
|
||||
expect(newObject).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockNoteType);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
124
src/services/management/__tests__/parts.test.js
Normal file
124
src/services/management/__tests__/parts.test.js
Normal file
@ -0,0 +1,124 @@
|
||||
import { jest } from '@jest/globals';
|
||||
|
||||
jest.unstable_mockModule('../../../database/database.js', () => ({
|
||||
listObjects: jest.fn(),
|
||||
getObject: jest.fn(),
|
||||
editObject: jest.fn(),
|
||||
newObject: jest.fn(),
|
||||
deleteObject: jest.fn(),
|
||||
listObjectsByProperties: jest.fn(),
|
||||
getModelStats: jest.fn(),
|
||||
getModelHistory: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/management/part.schema.js', () => ({
|
||||
partModel: { modelName: 'Part' },
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('log4js', () => ({
|
||||
default: {
|
||||
getLogger: () => ({
|
||||
level: 'info',
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
trace: jest.fn(),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
const {
|
||||
listPartsRouteHandler,
|
||||
getPartRouteHandler,
|
||||
newPartRouteHandler,
|
||||
editPartRouteHandler,
|
||||
deletePartRouteHandler,
|
||||
} = await import('../parts.js');
|
||||
|
||||
const { listObjects, getObject, editObject, newObject, deleteObject } = await import(
|
||||
'../../../database/database.js'
|
||||
);
|
||||
const { partModel } = await import('../../../database/schemas/management/part.schema.js');
|
||||
|
||||
describe('Part Service Route Handlers', () => {
|
||||
let req, res;
|
||||
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
params: {},
|
||||
query: {},
|
||||
body: {},
|
||||
user: { id: 'test-user-id' },
|
||||
};
|
||||
res = {
|
||||
send: jest.fn(),
|
||||
status: jest.fn().mockReturnThis(),
|
||||
};
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('listPartsRouteHandler', () => {
|
||||
it('should list parts', async () => {
|
||||
const mockResult = [{ _id: '1', name: 'Part 1' }];
|
||||
listObjects.mockResolvedValue(mockResult);
|
||||
|
||||
await listPartsRouteHandler(req, res);
|
||||
|
||||
expect(listObjects).toHaveBeenCalledWith(expect.objectContaining({ model: partModel }));
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getPartRouteHandler', () => {
|
||||
it('should get a part by ID', async () => {
|
||||
req.params.id = '123';
|
||||
const mockPart = { _id: '123', name: 'Test Part' };
|
||||
getObject.mockResolvedValue(mockPart);
|
||||
|
||||
await getPartRouteHandler(req, res);
|
||||
|
||||
expect(getObject).toHaveBeenCalledWith(expect.objectContaining({ id: '123' }));
|
||||
expect(res.send).toHaveBeenCalledWith(mockPart);
|
||||
});
|
||||
});
|
||||
|
||||
describe('newPartRouteHandler', () => {
|
||||
it('should create a new part', async () => {
|
||||
req.body = { name: 'New Part', price: 10.99 };
|
||||
const mockPart = { _id: '456', ...req.body };
|
||||
newObject.mockResolvedValue(mockPart);
|
||||
|
||||
await newPartRouteHandler(req, res);
|
||||
|
||||
expect(newObject).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockPart);
|
||||
});
|
||||
});
|
||||
|
||||
describe('editPartRouteHandler', () => {
|
||||
it('should update a part', async () => {
|
||||
req.params.id = '507f1f77bcf86cd799439011';
|
||||
req.body = { name: 'Updated Part', price: 15.99 };
|
||||
const mockResult = { _id: '507f1f77bcf86cd799439011', ...req.body };
|
||||
editObject.mockResolvedValue(mockResult);
|
||||
|
||||
await editPartRouteHandler(req, res);
|
||||
|
||||
expect(editObject).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('deletePartRouteHandler', () => {
|
||||
it('should delete a part', async () => {
|
||||
req.params.id = '507f1f77bcf86cd799439011';
|
||||
const mockResult = { _id: '507f1f77bcf86cd799439011' };
|
||||
deleteObject.mockResolvedValue(mockResult);
|
||||
|
||||
await deletePartRouteHandler(req, res);
|
||||
|
||||
expect(deleteObject).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
});
|
||||
98
src/services/management/__tests__/products.test.js
Normal file
98
src/services/management/__tests__/products.test.js
Normal file
@ -0,0 +1,98 @@
|
||||
import { jest } from '@jest/globals';
|
||||
|
||||
jest.unstable_mockModule('../../../database/database.js', () => ({
|
||||
listObjects: jest.fn(),
|
||||
getObject: jest.fn(),
|
||||
editObject: jest.fn(),
|
||||
newObject: jest.fn(),
|
||||
deleteObject: jest.fn(),
|
||||
listObjectsByProperties: jest.fn(),
|
||||
getModelStats: jest.fn(),
|
||||
getModelHistory: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/management/product.schema.js', () => ({
|
||||
productModel: { modelName: 'Product' },
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('log4js', () => ({
|
||||
default: {
|
||||
getLogger: () => ({
|
||||
level: 'info',
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
trace: jest.fn(),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
const {
|
||||
listProductsRouteHandler,
|
||||
getProductRouteHandler,
|
||||
newProductRouteHandler,
|
||||
editProductRouteHandler,
|
||||
deleteProductRouteHandler,
|
||||
} = await import('../products.js');
|
||||
|
||||
const { listObjects, getObject, editObject, newObject, deleteObject } = await import(
|
||||
'../../../database/database.js'
|
||||
);
|
||||
const { productModel } = await import('../../../database/schemas/management/product.schema.js');
|
||||
|
||||
describe('Product Service Route Handlers', () => {
|
||||
let req, res;
|
||||
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
params: {},
|
||||
query: {},
|
||||
body: {},
|
||||
user: { id: 'test-user-id' },
|
||||
};
|
||||
res = {
|
||||
send: jest.fn(),
|
||||
status: jest.fn().mockReturnThis(),
|
||||
};
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('listProductsRouteHandler', () => {
|
||||
it('should list products', async () => {
|
||||
const mockResult = [{ _id: '1', name: 'Product 1' }];
|
||||
listObjects.mockResolvedValue(mockResult);
|
||||
|
||||
await listProductsRouteHandler(req, res);
|
||||
|
||||
expect(listObjects).toHaveBeenCalledWith(expect.objectContaining({ model: productModel }));
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('newProductRouteHandler', () => {
|
||||
it('should create a new product', async () => {
|
||||
req.body = { name: 'New Product', parts: [] };
|
||||
const mockProduct = { _id: '456', ...req.body };
|
||||
newObject.mockResolvedValue(mockProduct);
|
||||
|
||||
await newProductRouteHandler(req, res);
|
||||
|
||||
expect(newObject).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockProduct);
|
||||
});
|
||||
});
|
||||
|
||||
describe('editProductRouteHandler', () => {
|
||||
it('should update a product', async () => {
|
||||
req.params.id = '507f1f77bcf86cd799439011';
|
||||
req.body = { name: 'Updated Product' };
|
||||
const mockResult = { _id: '507f1f77bcf86cd799439011', ...req.body };
|
||||
editObject.mockResolvedValue(mockResult);
|
||||
|
||||
await editProductRouteHandler(req, res);
|
||||
|
||||
expect(editObject).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
});
|
||||
98
src/services/management/__tests__/taxrates.test.js
Normal file
98
src/services/management/__tests__/taxrates.test.js
Normal file
@ -0,0 +1,98 @@
|
||||
import { jest } from '@jest/globals';
|
||||
|
||||
jest.unstable_mockModule('../../../database/database.js', () => ({
|
||||
listObjects: jest.fn(),
|
||||
getObject: jest.fn(),
|
||||
editObject: jest.fn(),
|
||||
newObject: jest.fn(),
|
||||
deleteObject: jest.fn(),
|
||||
listObjectsByProperties: jest.fn(),
|
||||
getModelStats: jest.fn(),
|
||||
getModelHistory: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/management/taxrate.schema.js', () => ({
|
||||
taxRateModel: { modelName: 'TaxRate' },
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('log4js', () => ({
|
||||
default: {
|
||||
getLogger: () => ({
|
||||
level: 'info',
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
trace: jest.fn(),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
const {
|
||||
listTaxRatesRouteHandler,
|
||||
getTaxRateRouteHandler,
|
||||
newTaxRateRouteHandler,
|
||||
editTaxRateRouteHandler,
|
||||
} = await import('../taxrates.js');
|
||||
|
||||
const { listObjects, getObject, editObject, newObject } = await import(
|
||||
'../../../database/database.js'
|
||||
);
|
||||
const { taxRateModel } = await import('../../../database/schemas/management/taxrate.schema.js');
|
||||
|
||||
describe('Tax Rate Service Route Handlers', () => {
|
||||
let req, res;
|
||||
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
params: {},
|
||||
query: {},
|
||||
body: {},
|
||||
user: { id: 'test-user-id' },
|
||||
};
|
||||
res = {
|
||||
send: jest.fn(),
|
||||
status: jest.fn().mockReturnThis(),
|
||||
};
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('listTaxRatesRouteHandler', () => {
|
||||
it('should list tax rates', async () => {
|
||||
const mockResult = [{ _id: '1', name: 'GST', rate: 10 }];
|
||||
listObjects.mockResolvedValue(mockResult);
|
||||
|
||||
await listTaxRatesRouteHandler(req, res);
|
||||
|
||||
expect(listObjects).toHaveBeenCalledWith(expect.objectContaining({ model: taxRateModel }));
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('newTaxRateRouteHandler', () => {
|
||||
it('should create a new tax rate', async () => {
|
||||
req.body = { name: 'VAT', rate: 20, rateType: 'percentage' };
|
||||
const mockTaxRate = { _id: '456', ...req.body };
|
||||
newObject.mockResolvedValue(mockTaxRate);
|
||||
|
||||
await newTaxRateRouteHandler(req, res);
|
||||
|
||||
expect(newObject).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockTaxRate);
|
||||
});
|
||||
});
|
||||
|
||||
describe('editTaxRateRouteHandler', () => {
|
||||
it('should update a tax rate', async () => {
|
||||
req.params.id = '507f1f77bcf86cd799439011';
|
||||
req.body = { rate: 15 };
|
||||
const mockResult = { _id: '507f1f77bcf86cd799439011', rate: 15 };
|
||||
editObject.mockResolvedValue(mockResult);
|
||||
|
||||
await editTaxRateRouteHandler(req, res);
|
||||
|
||||
expect(editObject).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
86
src/services/management/__tests__/taxrecords.test.js
Normal file
86
src/services/management/__tests__/taxrecords.test.js
Normal file
@ -0,0 +1,86 @@
|
||||
import { jest } from '@jest/globals';
|
||||
|
||||
jest.unstable_mockModule('../../../database/database.js', () => ({
|
||||
listObjects: jest.fn(),
|
||||
getObject: jest.fn(),
|
||||
editObject: jest.fn(),
|
||||
newObject: jest.fn(),
|
||||
deleteObject: jest.fn(),
|
||||
listObjectsByProperties: jest.fn(),
|
||||
getModelStats: jest.fn(),
|
||||
getModelHistory: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/management/taxrecord.schema.js', () => ({
|
||||
taxRecordModel: { modelName: 'TaxRecord' },
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('log4js', () => ({
|
||||
default: {
|
||||
getLogger: () => ({
|
||||
level: 'info',
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
trace: jest.fn(),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
const {
|
||||
listTaxRecordsRouteHandler,
|
||||
getTaxRecordRouteHandler,
|
||||
newTaxRecordRouteHandler,
|
||||
editTaxRecordRouteHandler,
|
||||
} = await import('../taxrecords.js');
|
||||
|
||||
const { listObjects, getObject, editObject, newObject } = await import(
|
||||
'../../../database/database.js'
|
||||
);
|
||||
const { taxRecordModel } = await import('../../../database/schemas/management/taxrecord.schema.js');
|
||||
|
||||
describe('Tax Record Service Route Handlers', () => {
|
||||
let req, res;
|
||||
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
params: {},
|
||||
query: {},
|
||||
body: {},
|
||||
user: { id: 'test-user-id' },
|
||||
};
|
||||
res = {
|
||||
send: jest.fn(),
|
||||
status: jest.fn().mockReturnThis(),
|
||||
};
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('listTaxRecordsRouteHandler', () => {
|
||||
it('should list tax records', async () => {
|
||||
const mockResult = [{ _id: '1', amount: 100, taxAmount: 10 }];
|
||||
listObjects.mockResolvedValue(mockResult);
|
||||
|
||||
await listTaxRecordsRouteHandler(req, res);
|
||||
|
||||
expect(listObjects).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ model: taxRecordModel })
|
||||
);
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('newTaxRecordRouteHandler', () => {
|
||||
it('should create a new tax record', async () => {
|
||||
req.body = { taxRate: 'rate123', amount: 100, taxAmount: 10 };
|
||||
const mockRecord = { _id: '456', ...req.body };
|
||||
newObject.mockResolvedValue(mockRecord);
|
||||
|
||||
await newTaxRecordRouteHandler(req, res);
|
||||
|
||||
expect(newObject).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockRecord);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
126
src/services/management/__tests__/users.test.js
Normal file
126
src/services/management/__tests__/users.test.js
Normal file
@ -0,0 +1,126 @@
|
||||
import { jest } from '@jest/globals';
|
||||
|
||||
// Mock dependencies MUST be done before importing the module under test
|
||||
jest.unstable_mockModule('../../../database/database.js', () => ({
|
||||
listObjects: jest.fn(),
|
||||
listObjectsByProperties: jest.fn(),
|
||||
getObject: jest.fn(),
|
||||
editObject: jest.fn(),
|
||||
getModelStats: jest.fn(),
|
||||
getModelHistory: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/management/user.schema.js', () => ({
|
||||
userModel: { findOne: jest.fn() },
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('log4js', () => ({
|
||||
default: {
|
||||
getLogger: () => ({
|
||||
level: 'info',
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
trace: jest.fn(),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
// Now import the modules
|
||||
const { listUsersRouteHandler, getUserRouteHandler, editUserRouteHandler } = await import(
|
||||
'../users.js'
|
||||
);
|
||||
const { listObjects, getObject, editObject } = await import('../../../database/database.js');
|
||||
const { userModel } = await import('../../../database/schemas/management/user.schema.js');
|
||||
|
||||
describe('User Service Route Handlers', () => {
|
||||
let req, res;
|
||||
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
params: {},
|
||||
query: {},
|
||||
body: {},
|
||||
user: { id: 'test-user-id' },
|
||||
};
|
||||
res = {
|
||||
send: jest.fn(),
|
||||
status: jest.fn().mockReturnThis(),
|
||||
};
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('listUsersRouteHandler', () => {
|
||||
it('should list users and send response', async () => {
|
||||
const mockResult = [{ id: '1', name: 'User 1' }];
|
||||
listObjects.mockResolvedValue(mockResult);
|
||||
|
||||
await listUsersRouteHandler(req, res);
|
||||
|
||||
expect(listObjects).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
model: userModel,
|
||||
})
|
||||
);
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
|
||||
it('should handle errors from listObjects', async () => {
|
||||
const mockError = { error: 'Database error', code: 500 };
|
||||
listObjects.mockResolvedValue(mockError);
|
||||
|
||||
await listUsersRouteHandler(req, res);
|
||||
|
||||
expect(res.status).toHaveBeenCalledWith(500);
|
||||
expect(res.send).toHaveBeenCalledWith(mockError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getUserRouteHandler', () => {
|
||||
it('should get a user by id and send response', async () => {
|
||||
req.params.id = '123';
|
||||
const mockUser = { id: '123', name: 'Test User' };
|
||||
getObject.mockResolvedValue(mockUser);
|
||||
|
||||
await getUserRouteHandler(req, res);
|
||||
|
||||
expect(getObject).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
model: userModel,
|
||||
id: '123',
|
||||
})
|
||||
);
|
||||
expect(res.send).toHaveBeenCalledWith(mockUser);
|
||||
});
|
||||
|
||||
it('should handle user not found', async () => {
|
||||
req.params.id = 'invalid';
|
||||
const mockError = { error: 'Not found', code: 404 };
|
||||
getObject.mockResolvedValue(mockError);
|
||||
|
||||
await getUserRouteHandler(req, res);
|
||||
|
||||
expect(res.status).toHaveBeenCalledWith(404);
|
||||
expect(res.send).toHaveBeenCalledWith(mockError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('editUserRouteHandler', () => {
|
||||
it('should edit a user and send response', async () => {
|
||||
req.params.id = '507f1f77bcf86cd799439011'; // valid mongodb id format
|
||||
req.body = { name: 'New Name' };
|
||||
const mockResult = { id: '507f1f77bcf86cd799439011', name: 'New Name' };
|
||||
editObject.mockResolvedValue(mockResult);
|
||||
|
||||
await editUserRouteHandler(req, res);
|
||||
|
||||
expect(editObject).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
model: userModel,
|
||||
updateData: expect.objectContaining({ name: 'New Name' }),
|
||||
})
|
||||
);
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
});
|
||||
99
src/services/management/__tests__/vendors.test.js
Normal file
99
src/services/management/__tests__/vendors.test.js
Normal file
@ -0,0 +1,99 @@
|
||||
import { jest } from '@jest/globals';
|
||||
|
||||
jest.unstable_mockModule('../../../database/database.js', () => ({
|
||||
listObjects: jest.fn(),
|
||||
getObject: jest.fn(),
|
||||
editObject: jest.fn(),
|
||||
newObject: jest.fn(),
|
||||
deleteObject: jest.fn(),
|
||||
listObjectsByProperties: jest.fn(),
|
||||
getModelStats: jest.fn(),
|
||||
getModelHistory: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/management/vendor.schema.js', () => ({
|
||||
vendorModel: { modelName: 'Vendor' },
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('log4js', () => ({
|
||||
default: {
|
||||
getLogger: () => ({
|
||||
level: 'info',
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
trace: jest.fn(),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
const {
|
||||
listVendorsRouteHandler,
|
||||
getVendorRouteHandler,
|
||||
newVendorRouteHandler,
|
||||
editVendorRouteHandler,
|
||||
deleteVendorRouteHandler,
|
||||
} = await import('../vendors.js');
|
||||
|
||||
const { listObjects, getObject, editObject, newObject, deleteObject } = await import(
|
||||
'../../../database/database.js'
|
||||
);
|
||||
const { vendorModel } = await import('../../../database/schemas/management/vendor.schema.js');
|
||||
|
||||
describe('Vendor Service Route Handlers', () => {
|
||||
let req, res;
|
||||
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
params: {},
|
||||
query: {},
|
||||
body: {},
|
||||
user: { id: 'test-user-id' },
|
||||
};
|
||||
res = {
|
||||
send: jest.fn(),
|
||||
status: jest.fn().mockReturnThis(),
|
||||
};
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('listVendorsRouteHandler', () => {
|
||||
it('should list vendors', async () => {
|
||||
const mockResult = [{ _id: '1', name: 'Vendor 1' }];
|
||||
listObjects.mockResolvedValue(mockResult);
|
||||
|
||||
await listVendorsRouteHandler(req, res);
|
||||
|
||||
expect(listObjects).toHaveBeenCalledWith(expect.objectContaining({ model: vendorModel }));
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('newVendorRouteHandler', () => {
|
||||
it('should create a new vendor', async () => {
|
||||
req.body = { name: 'New Vendor', email: 'vendor@example.com' };
|
||||
const mockVendor = { _id: '456', ...req.body };
|
||||
newObject.mockResolvedValue(mockVendor);
|
||||
|
||||
await newVendorRouteHandler(req, res);
|
||||
|
||||
expect(newObject).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockVendor);
|
||||
});
|
||||
});
|
||||
|
||||
describe('editVendorRouteHandler', () => {
|
||||
it('should update a vendor', async () => {
|
||||
req.params.id = '507f1f77bcf86cd799439011';
|
||||
req.body = { name: 'Updated Vendor' };
|
||||
const mockResult = { _id: '507f1f77bcf86cd799439011', ...req.body };
|
||||
editObject.mockResolvedValue(mockResult);
|
||||
|
||||
await editVendorRouteHandler(req, res);
|
||||
|
||||
expect(editObject).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
85
src/services/misc/__tests__/notes.test.js
Normal file
85
src/services/misc/__tests__/notes.test.js
Normal file
@ -0,0 +1,85 @@
|
||||
import { jest } from '@jest/globals';
|
||||
|
||||
jest.unstable_mockModule('../../../database/database.js', () => ({
|
||||
listObjects: jest.fn(),
|
||||
getObject: jest.fn(),
|
||||
editObject: jest.fn(),
|
||||
newObject: jest.fn(),
|
||||
deleteObject: jest.fn(),
|
||||
listObjectsByProperties: jest.fn(),
|
||||
recursivelyDeleteChildObjects: jest.fn(),
|
||||
getModelStats: jest.fn(),
|
||||
getModelHistory: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/misc/note.schema.js', () => ({
|
||||
noteModel: { modelName: 'Note' },
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('log4js', () => ({
|
||||
default: {
|
||||
getLogger: () => ({
|
||||
level: 'info',
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
trace: jest.fn(),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
const {
|
||||
listNotesRouteHandler,
|
||||
getNoteRouteHandler,
|
||||
newNoteRouteHandler,
|
||||
editNoteRouteHandler,
|
||||
} = await import('../../misc/notes.js');
|
||||
|
||||
const { listObjects, getObject, editObject, newObject } = await import(
|
||||
'../../../database/database.js'
|
||||
);
|
||||
const { noteModel } = await import('../../../database/schemas/misc/note.schema.js');
|
||||
|
||||
describe('Note Service Route Handlers', () => {
|
||||
let req, res;
|
||||
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
params: {},
|
||||
query: {},
|
||||
body: {},
|
||||
user: { id: 'test-user-id' },
|
||||
};
|
||||
res = {
|
||||
send: jest.fn(),
|
||||
status: jest.fn().mockReturnThis(),
|
||||
};
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('listNotesRouteHandler', () => {
|
||||
it('should list notes', async () => {
|
||||
const mockResult = [{ _id: '1', content: 'Test note' }];
|
||||
listObjects.mockResolvedValue(mockResult);
|
||||
|
||||
await listNotesRouteHandler(req, res);
|
||||
|
||||
expect(listObjects).toHaveBeenCalledWith(expect.objectContaining({ model: noteModel }));
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('newNoteRouteHandler', () => {
|
||||
it('should create a new note', async () => {
|
||||
req.body = { content: 'New note', noteType: 'type123' };
|
||||
const mockNote = { _id: '456', ...req.body };
|
||||
newObject.mockResolvedValue(mockNote);
|
||||
|
||||
await newNoteRouteHandler(req, res);
|
||||
|
||||
expect(newObject).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockNote);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
106
src/services/production/__tests__/gcodefiles.test.js
Normal file
106
src/services/production/__tests__/gcodefiles.test.js
Normal file
@ -0,0 +1,106 @@
|
||||
import { jest } from '@jest/globals';
|
||||
|
||||
jest.unstable_mockModule('../../../database/database.js', () => ({
|
||||
listObjects: jest.fn(),
|
||||
getObject: jest.fn(),
|
||||
editObject: jest.fn(),
|
||||
newObject: jest.fn(),
|
||||
deleteObject: jest.fn(),
|
||||
listObjectsByProperties: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/production/gcodefile.schema.js', () => ({
|
||||
gcodeFileModel: {
|
||||
modelName: 'GCodeFile',
|
||||
aggregate: jest.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../management/files.js', () => ({
|
||||
getFileContentRouteHandler: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('log4js', () => ({
|
||||
default: {
|
||||
getLogger: () => ({
|
||||
level: 'info',
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
trace: jest.fn(),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
const {
|
||||
listGCodeFilesRouteHandler,
|
||||
getGCodeFileRouteHandler,
|
||||
newGCodeFileRouteHandler,
|
||||
editGCodeFileRouteHandler,
|
||||
deleteGCodeFileRouteHandler,
|
||||
} = await import('../gcodefiles.js');
|
||||
|
||||
const { listObjects, getObject, editObject, newObject, deleteObject } = await import(
|
||||
'../../../database/database.js'
|
||||
);
|
||||
const { gcodeFileModel } = await import('../../../database/schemas/production/gcodefile.schema.js');
|
||||
|
||||
describe('GCodeFile Service Route Handlers', () => {
|
||||
let req, res;
|
||||
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
params: {},
|
||||
query: {},
|
||||
body: {},
|
||||
user: { id: 'test-user-id' },
|
||||
};
|
||||
res = {
|
||||
send: jest.fn(),
|
||||
status: jest.fn().mockReturnThis(),
|
||||
};
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('listGCodeFilesRouteHandler', () => {
|
||||
it('should list gcode files', async () => {
|
||||
const mockResult = [{ _id: '1', name: 'file.gcode' }];
|
||||
listObjects.mockResolvedValue(mockResult);
|
||||
|
||||
await listGCodeFilesRouteHandler(req, res);
|
||||
|
||||
expect(listObjects).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ model: gcodeFileModel })
|
||||
);
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('newGCodeFileRouteHandler', () => {
|
||||
it('should create a new gcode file', async () => {
|
||||
req.body = { name: 'newfile.gcode', file: 'file123' };
|
||||
const mockFile = { _id: '456', ...req.body };
|
||||
newObject.mockResolvedValue(mockFile);
|
||||
|
||||
await newGCodeFileRouteHandler(req, res);
|
||||
|
||||
expect(newObject).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockFile);
|
||||
});
|
||||
});
|
||||
|
||||
describe('editGCodeFileRouteHandler', () => {
|
||||
it('should update a gcode file', async () => {
|
||||
req.params.id = '507f1f77bcf86cd799439011';
|
||||
req.body = { name: 'updated.gcode' };
|
||||
const mockResult = { _id: '507f1f77bcf86cd799439011', ...req.body };
|
||||
editObject.mockResolvedValue(mockResult);
|
||||
|
||||
await editGCodeFileRouteHandler(req, res);
|
||||
|
||||
expect(editObject).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
114
src/services/production/__tests__/jobs.test.js
Normal file
114
src/services/production/__tests__/jobs.test.js
Normal file
@ -0,0 +1,114 @@
|
||||
import { jest } from '@jest/globals';
|
||||
|
||||
// Mock dependencies
|
||||
jest.unstable_mockModule('../../../database/database.js', () => ({
|
||||
listObjects: jest.fn(),
|
||||
getObject: jest.fn(),
|
||||
newObject: jest.fn(),
|
||||
deleteObject: jest.fn(),
|
||||
listObjectsByProperties: jest.fn(),
|
||||
getModelStats: jest.fn(),
|
||||
getModelHistory: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/production/job.schema.js', () => ({
|
||||
jobModel: { modelName: 'Job' },
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/production/subjob.schema.js', () => ({
|
||||
subJobModel: { modelName: 'SubJob' },
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('log4js', () => ({
|
||||
default: {
|
||||
getLogger: () => ({
|
||||
level: 'info',
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
trace: jest.fn(),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
// Import handlers after mocking
|
||||
const { listJobsRouteHandler, getJobRouteHandler, newJobRouteHandler, deleteJobRouteHandler } =
|
||||
await import('../jobs.js');
|
||||
|
||||
const { listObjects, getObject, newObject, deleteObject } = await import(
|
||||
'../../../database/database.js'
|
||||
);
|
||||
const { jobModel } = await import('../../../database/schemas/production/job.schema.js');
|
||||
const { subJobModel } = await import('../../../database/schemas/production/subjob.schema.js');
|
||||
|
||||
describe('Job Service Route Handlers', () => {
|
||||
let req, res;
|
||||
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
params: {},
|
||||
query: {},
|
||||
body: {},
|
||||
user: { id: 'test-user-id' },
|
||||
};
|
||||
res = {
|
||||
send: jest.fn(),
|
||||
status: jest.fn().mockReturnThis(),
|
||||
};
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('listJobsRouteHandler', () => {
|
||||
it('should list jobs', async () => {
|
||||
const mockResult = [{ _id: '1', name: 'Job 1' }];
|
||||
listObjects.mockResolvedValue(mockResult);
|
||||
|
||||
await listJobsRouteHandler(req, res);
|
||||
|
||||
expect(listObjects).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('newJobRouteHandler', () => {
|
||||
it('should create a new job and corresponding subjobs', async () => {
|
||||
req.body = {
|
||||
quantity: 2,
|
||||
printers: ['p1', 'p2'],
|
||||
gcodeFile: 'file123',
|
||||
};
|
||||
|
||||
const mockJob = { _id: 'job123' };
|
||||
newObject.mockResolvedValueOnce(mockJob); // For Job
|
||||
newObject.mockResolvedValue({ _id: 'subjob' }); // For SubJobs
|
||||
|
||||
await newJobRouteHandler(req, res);
|
||||
|
||||
expect(newObject).toHaveBeenCalledTimes(3); // 1 Job + 2 SubJobs
|
||||
expect(res.send).toHaveBeenCalledWith(mockJob);
|
||||
});
|
||||
|
||||
it('should handle errors during job creation', async () => {
|
||||
req.body = { quantity: 1, printers: ['p1'] };
|
||||
newObject.mockResolvedValueOnce({ error: 'Failed', code: 500 });
|
||||
|
||||
await newJobRouteHandler(req, res);
|
||||
|
||||
expect(res.status).toHaveBeenCalledWith(500);
|
||||
expect(res.send).toHaveBeenCalledWith(expect.objectContaining({ error: 'Failed' }));
|
||||
});
|
||||
});
|
||||
|
||||
describe('deleteJobRouteHandler', () => {
|
||||
it('should delete a job', async () => {
|
||||
req.params.id = '507f1f77bcf86cd799439011';
|
||||
const mockResult = { _id: '507f1f77bcf86cd799439011' };
|
||||
deleteObject.mockResolvedValue(mockResult);
|
||||
|
||||
await deleteJobRouteHandler(req, res);
|
||||
|
||||
expect(deleteObject).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
});
|
||||
99
src/services/production/__tests__/printers.test.js
Normal file
99
src/services/production/__tests__/printers.test.js
Normal file
@ -0,0 +1,99 @@
|
||||
import { jest } from '@jest/globals';
|
||||
|
||||
jest.unstable_mockModule('../../../database/database.js', () => ({
|
||||
listObjects: jest.fn(),
|
||||
getObject: jest.fn(),
|
||||
editObject: jest.fn(),
|
||||
newObject: jest.fn(),
|
||||
deleteObject: jest.fn(),
|
||||
listObjectsByProperties: jest.fn(),
|
||||
getModelStats: jest.fn(),
|
||||
getModelHistory: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/production/printer.schema.js', () => ({
|
||||
printerModel: { modelName: 'Printer' },
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('log4js', () => ({
|
||||
default: {
|
||||
getLogger: () => ({
|
||||
level: 'info',
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
trace: jest.fn(),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
const {
|
||||
listPrintersRouteHandler,
|
||||
getPrinterRouteHandler,
|
||||
newPrinterRouteHandler,
|
||||
editPrinterRouteHandler,
|
||||
deletePrinterRouteHandler,
|
||||
} = await import('../printers.js');
|
||||
|
||||
const { listObjects, getObject, editObject, newObject, deleteObject } = await import(
|
||||
'../../../database/database.js'
|
||||
);
|
||||
const { printerModel } = await import('../../../database/schemas/production/printer.schema.js');
|
||||
|
||||
describe('Printer Service Route Handlers', () => {
|
||||
let req, res;
|
||||
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
params: {},
|
||||
query: {},
|
||||
body: {},
|
||||
user: { id: 'test-user-id' },
|
||||
};
|
||||
res = {
|
||||
send: jest.fn(),
|
||||
status: jest.fn().mockReturnThis(),
|
||||
};
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('listPrintersRouteHandler', () => {
|
||||
it('should list printers', async () => {
|
||||
const mockResult = [{ _id: '1', name: 'Printer 1' }];
|
||||
listObjects.mockResolvedValue(mockResult);
|
||||
|
||||
await listPrintersRouteHandler(req, res);
|
||||
|
||||
expect(listObjects).toHaveBeenCalledWith(expect.objectContaining({ model: printerModel }));
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('newPrinterRouteHandler', () => {
|
||||
it('should create a new printer', async () => {
|
||||
req.body = { name: 'New Printer', host: 'host123' };
|
||||
const mockPrinter = { _id: '456', ...req.body };
|
||||
newObject.mockResolvedValue(mockPrinter);
|
||||
|
||||
await newPrinterRouteHandler(req, res);
|
||||
|
||||
expect(newObject).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockPrinter);
|
||||
});
|
||||
});
|
||||
|
||||
describe('editPrinterRouteHandler', () => {
|
||||
it('should update a printer', async () => {
|
||||
req.params.id = '507f1f77bcf86cd799439011';
|
||||
req.body = { name: 'Updated Printer' };
|
||||
const mockResult = { _id: '507f1f77bcf86cd799439011', ...req.body };
|
||||
editObject.mockResolvedValue(mockResult);
|
||||
|
||||
await editPrinterRouteHandler(req, res);
|
||||
|
||||
expect(editObject).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
74
src/services/production/__tests__/subjobs.test.js
Normal file
74
src/services/production/__tests__/subjobs.test.js
Normal file
@ -0,0 +1,74 @@
|
||||
import { jest } from '@jest/globals';
|
||||
|
||||
jest.unstable_mockModule('../../../database/database.js', () => ({
|
||||
listObjects: jest.fn(),
|
||||
getObject: jest.fn(),
|
||||
listObjectsByProperties: jest.fn(),
|
||||
getModelStats: jest.fn(),
|
||||
getModelHistory: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/production/subjob.schema.js', () => ({
|
||||
subJobModel: { modelName: 'SubJob' },
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('log4js', () => ({
|
||||
default: {
|
||||
getLogger: () => ({
|
||||
level: 'info',
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
trace: jest.fn(),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
const { listSubJobsRouteHandler, getSubJobRouteHandler } = await import('../subjobs.js');
|
||||
|
||||
const { listObjects, getObject } = await import('../../../database/database.js');
|
||||
const { subJobModel } = await import('../../../database/schemas/production/subjob.schema.js');
|
||||
|
||||
describe('SubJob Service Route Handlers', () => {
|
||||
let req, res;
|
||||
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
params: {},
|
||||
query: {},
|
||||
body: {},
|
||||
user: { id: 'test-user-id' },
|
||||
};
|
||||
res = {
|
||||
send: jest.fn(),
|
||||
status: jest.fn().mockReturnThis(),
|
||||
};
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('listSubJobsRouteHandler', () => {
|
||||
it('should list sub jobs', async () => {
|
||||
const mockResult = [{ _id: '1', number: 1 }];
|
||||
listObjects.mockResolvedValue(mockResult);
|
||||
|
||||
await listSubJobsRouteHandler(req, res);
|
||||
|
||||
expect(listObjects).toHaveBeenCalledWith(expect.objectContaining({ model: subJobModel }));
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getSubJobRouteHandler', () => {
|
||||
it('should get a sub job by ID', async () => {
|
||||
req.params.id = '123';
|
||||
const mockSubJob = { _id: '123', number: 1 };
|
||||
getObject.mockResolvedValue(mockSubJob);
|
||||
|
||||
await getSubJobRouteHandler(req, res);
|
||||
|
||||
expect(getObject).toHaveBeenCalledWith(expect.objectContaining({ id: '123' }));
|
||||
expect(res.send).toHaveBeenCalledWith(mockSubJob);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
112
src/services/sales/__tests__/clients.test.js
Normal file
112
src/services/sales/__tests__/clients.test.js
Normal file
@ -0,0 +1,112 @@
|
||||
import { jest } from '@jest/globals';
|
||||
|
||||
jest.unstable_mockModule('../../../database/database.js', () => ({
|
||||
listObjects: jest.fn(),
|
||||
getObject: jest.fn(),
|
||||
editObject: jest.fn(),
|
||||
newObject: jest.fn(),
|
||||
deleteObject: jest.fn(),
|
||||
listObjectsByProperties: jest.fn(),
|
||||
getModelStats: jest.fn(),
|
||||
getModelHistory: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/sales/client.schema.js', () => ({
|
||||
clientModel: { modelName: 'Client' },
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('log4js', () => ({
|
||||
default: {
|
||||
getLogger: () => ({
|
||||
level: 'info',
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
trace: jest.fn(),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
const {
|
||||
listClientsRouteHandler,
|
||||
getClientRouteHandler,
|
||||
newClientRouteHandler,
|
||||
editClientRouteHandler,
|
||||
deleteClientRouteHandler,
|
||||
} = await import('../clients.js');
|
||||
|
||||
const { listObjects, getObject, editObject, newObject, deleteObject } = await import(
|
||||
'../../../database/database.js'
|
||||
);
|
||||
const { clientModel } = await import('../../../database/schemas/sales/client.schema.js');
|
||||
|
||||
describe('Client Service Route Handlers', () => {
|
||||
let req, res;
|
||||
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
params: {},
|
||||
query: {},
|
||||
body: {},
|
||||
user: { id: 'test-user-id' },
|
||||
};
|
||||
res = {
|
||||
send: jest.fn(),
|
||||
status: jest.fn().mockReturnThis(),
|
||||
};
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('listClientsRouteHandler', () => {
|
||||
it('should list clients', async () => {
|
||||
const mockResult = [{ _id: '1', name: 'Client 1' }];
|
||||
listObjects.mockResolvedValue(mockResult);
|
||||
|
||||
await listClientsRouteHandler(req, res);
|
||||
|
||||
expect(listObjects).toHaveBeenCalledWith(expect.objectContaining({ model: clientModel }));
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('newClientRouteHandler', () => {
|
||||
it('should create a new client', async () => {
|
||||
req.body = { name: 'New Client', email: 'client@example.com' };
|
||||
const mockClient = { _id: '456', ...req.body };
|
||||
newObject.mockResolvedValue(mockClient);
|
||||
|
||||
await newClientRouteHandler(req, res);
|
||||
|
||||
expect(newObject).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockClient);
|
||||
});
|
||||
});
|
||||
|
||||
describe('editClientRouteHandler', () => {
|
||||
it('should update a client', async () => {
|
||||
req.params.id = '507f1f77bcf86cd799439011';
|
||||
req.body = { name: 'Updated Client' };
|
||||
const mockResult = { _id: '507f1f77bcf86cd799439011', ...req.body };
|
||||
editObject.mockResolvedValue(mockResult);
|
||||
|
||||
await editClientRouteHandler(req, res);
|
||||
|
||||
expect(editObject).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('deleteClientRouteHandler', () => {
|
||||
it('should delete a client', async () => {
|
||||
req.params.id = '507f1f77bcf86cd799439011';
|
||||
const mockResult = { _id: '507f1f77bcf86cd799439011' };
|
||||
deleteObject.mockResolvedValue(mockResult);
|
||||
|
||||
await deleteClientRouteHandler(req, res);
|
||||
|
||||
expect(deleteObject).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
123
src/services/sales/__tests__/salesorders.test.js
Normal file
123
src/services/sales/__tests__/salesorders.test.js
Normal file
@ -0,0 +1,123 @@
|
||||
import { jest } from '@jest/globals';
|
||||
|
||||
// Mock dependencies
|
||||
jest.unstable_mockModule('../../../database/database.js', () => ({
|
||||
listObjects: jest.fn(),
|
||||
getObject: jest.fn(),
|
||||
editObject: jest.fn(),
|
||||
editObjects: jest.fn(),
|
||||
newObject: jest.fn(),
|
||||
deleteObject: jest.fn(),
|
||||
listObjectsByProperties: jest.fn(),
|
||||
getModelStats: jest.fn(),
|
||||
getModelHistory: jest.fn(),
|
||||
checkStates: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/sales/salesorder.schema.js', () => ({
|
||||
salesOrderModel: { modelName: 'SalesOrder' },
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/inventory/orderitem.schema.js', () => ({
|
||||
orderItemModel: { modelName: 'OrderItem' },
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../../database/schemas/inventory/shipment.schema.js', () => ({
|
||||
shipmentModel: { modelName: 'Shipment' },
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('log4js', () => ({
|
||||
default: {
|
||||
getLogger: () => ({
|
||||
level: 'info',
|
||||
debug: jest.fn(),
|
||||
error: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
trace: jest.fn(),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
// Import handlers after mocking
|
||||
const {
|
||||
listSalesOrdersRouteHandler,
|
||||
getSalesOrderRouteHandler,
|
||||
newSalesOrderRouteHandler,
|
||||
postSalesOrderRouteHandler,
|
||||
} = await import('../salesorders.js');
|
||||
|
||||
const { listObjects, getObject, editObject, newObject, checkStates } = await import(
|
||||
'../../../database/database.js'
|
||||
);
|
||||
const { salesOrderModel } = await import('../../../database/schemas/sales/salesorder.schema.js');
|
||||
|
||||
describe('Sales Order Service Route Handlers', () => {
|
||||
let req, res;
|
||||
|
||||
beforeEach(() => {
|
||||
req = {
|
||||
params: {},
|
||||
query: {},
|
||||
body: {},
|
||||
user: { id: 'test-user-id' },
|
||||
};
|
||||
res = {
|
||||
send: jest.fn(),
|
||||
status: jest.fn().mockReturnThis(),
|
||||
};
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('listSalesOrdersRouteHandler', () => {
|
||||
it('should list sales orders', async () => {
|
||||
const mockResult = [{ _id: '1', reference: 'SO-001' }];
|
||||
listObjects.mockResolvedValue(mockResult);
|
||||
|
||||
await listSalesOrdersRouteHandler(req, res);
|
||||
|
||||
expect(listObjects).toHaveBeenCalled();
|
||||
expect(res.send).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('postSalesOrderRouteHandler', () => {
|
||||
it('should post a draft sales order and update items/shipments', async () => {
|
||||
req.params.id = '507f1f77bcf86cd799439011';
|
||||
|
||||
checkStates.mockResolvedValue(true);
|
||||
|
||||
// Mock listObjects for orderItems and shipments
|
||||
listObjects.mockResolvedValueOnce([
|
||||
{ _id: 'oi1', state: { type: 'draft' }, shipment: 's1', _reference: 'ITEM1' },
|
||||
]); // orderItems
|
||||
listObjects.mockResolvedValueOnce([
|
||||
{ _id: 's1', state: { type: 'draft' }, _reference: 'SHIP1' },
|
||||
]); // shipments
|
||||
|
||||
editObject.mockResolvedValue({ _id: '507f1f77bcf86cd799439011', state: { type: 'sent' } });
|
||||
|
||||
await postSalesOrderRouteHandler(req, res);
|
||||
|
||||
expect(checkStates).toHaveBeenCalledWith(expect.objectContaining({ states: ['draft'] }));
|
||||
expect(editObject).toHaveBeenCalledTimes(3); // 1 OrderItem + 1 Shipment + 1 SalesOrder
|
||||
expect(res.send).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should fail if an order item is not in draft state', async () => {
|
||||
req.params.id = '507f1f77bcf86cd799439011';
|
||||
checkStates.mockResolvedValue(true);
|
||||
|
||||
listObjects.mockResolvedValueOnce([
|
||||
{ _id: 'oi1', state: { type: 'ordered' }, _reference: 'ITEM1' },
|
||||
]);
|
||||
listObjects.mockResolvedValueOnce([]);
|
||||
|
||||
await postSalesOrderRouteHandler(req, res);
|
||||
|
||||
expect(res.status).toHaveBeenCalledWith(400);
|
||||
expect(res.send).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ error: 'Order item ITEM1 not in draft state.' })
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user