feat: incorporar eCMR y mercancias desde 7fbfd30
Traslada los cambios de 7fbfd300b4ea17212c04528145d366a3f00b91e5 conservando la configuracion de entorno de produccion.
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
const test = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const express = require('express');
|
||||
const jwt = require('jsonwebtoken');
|
||||
const db = require('../src/config/db');
|
||||
const writer = require('../src/services/tripCargoWriter');
|
||||
const routes = require('../src/routes/tripsRoutes');
|
||||
const originalQuery = db.query;
|
||||
const originalSave = writer.save;
|
||||
process.env.JWT_SECRET = 'cargo-test-secret';
|
||||
let server;
|
||||
let base;
|
||||
const valid = { id_tipo_embalaje: 1, cantidad: 2, peso: 400, largo: 120, ancho: 80, alto: 150, remontable: true };
|
||||
|
||||
test.before(async () => {
|
||||
const app = express(); app.use(express.json()); app.use('/api', routes);
|
||||
await new Promise(resolve => { server = app.listen(0, '127.0.0.1', resolve); });
|
||||
base = `http://127.0.0.1:${server.address().port}/api/trips`;
|
||||
});
|
||||
test.afterEach(() => { db.query = originalQuery; writer.save = originalSave; });
|
||||
test.after(async () => { await new Promise(resolve => server.close(resolve)); });
|
||||
const request = async (method = 'GET', suffix = '/123/cargo', body, identity = { dni: '12345678A' }) => {
|
||||
const headers = { 'Content-Type': 'application/json' };
|
||||
if (identity) headers.Authorization = `Bearer ${jwt.sign(identity, process.env.JWT_SECRET)}`;
|
||||
const response = await fetch(base + suffix, { method, headers, body: method === 'GET' || body === undefined ? undefined : JSON.stringify(body) });
|
||||
return { status: response.status, body: await response.json() };
|
||||
};
|
||||
for (const method of ['GET', 'POST', 'PUT']) {
|
||||
for (const identity of [null, { id: 1 }]) {
|
||||
test(`${method} requires authenticated driver ${JSON.stringify(identity)}`, async () => {
|
||||
db.query = writer.save = async () => assert.fail('Must not access data');
|
||||
assert.equal((await request(method, method === 'PUT' ? '/123/cargo/7' : '/123/cargo', valid, identity)).status, 401);
|
||||
});
|
||||
}
|
||||
}
|
||||
for (const id of ['0', '-1', '123abc', '2147483648']) {
|
||||
test(`invalid trip ${id}`, async () => {
|
||||
writer.save = async () => assert.fail('Must not save');
|
||||
assert.equal((await request('POST', `/${id}/cargo`, valid)).status, 404);
|
||||
});
|
||||
}
|
||||
test('unknown trip and unauthorized driver cannot read cargo', async () => {
|
||||
db.query = async () => [[]];
|
||||
assert.equal((await request()).status, 404);
|
||||
let calls = 0;
|
||||
db.query = async (sql, params) => {
|
||||
calls++;
|
||||
if (calls === 1) return [[{ id_viaje: 123 }]];
|
||||
assert.deepEqual(params, [123, '12345678A']);
|
||||
return [[]];
|
||||
};
|
||||
assert.equal((await request()).status, 403);
|
||||
assert.equal(calls, 2);
|
||||
});
|
||||
test('reads cargo, active packaging and document status', async () => {
|
||||
let calls = 0;
|
||||
db.query = async (sql, params) => {
|
||||
calls++;
|
||||
if (calls === 1) return [[{ id_viaje: 123, observaciones_mercancia: 'Material' }]];
|
||||
if (calls === 2) return [[{ n_proveedor: 1 }]];
|
||||
if (calls === 3) { assert.deepEqual(params, [123]); return [[{ id_mercancia: 7, peso: '400' }]]; }
|
||||
if (calls === 4) { assert.match(sql, /activo = 1/); return [[{ id_tipo_embalaje: 1 }]]; }
|
||||
assert.deepEqual(params, [123]); return [[{ id_documento: 8 }]];
|
||||
};
|
||||
const response = await request();
|
||||
assert.equal(response.status, 200);
|
||||
assert.equal(response.body.data.ecmr_emitido, true);
|
||||
assert.equal(response.body.data.mercancias[0].id_mercancia, 7);
|
||||
assert.equal(response.body.data.observaciones_mercancia, 'Material');
|
||||
});
|
||||
for (const [field, value] of [
|
||||
['cantidad', 0], ['cantidad', 1.5], ['cantidad', '2'], ['cantidad', null],
|
||||
['peso', -1], ['peso', 1.5], ['peso', 10000000000], ['peso', null],
|
||||
['largo', -10], ['ancho', 2147483648], ['alto', 0.5],
|
||||
['remontable', 'true'], ['remontable', 2], ['id_tipo_embalaje', 0]
|
||||
]) {
|
||||
test(`rejects invalid ${field}=${value}`, async () => {
|
||||
writer.save = async () => assert.fail('Must not save invalid cargo');
|
||||
const response = await request('POST', '/123/cargo', { ...valid, [field]: value });
|
||||
assert.equal(response.status, 422);
|
||||
assert.equal(response.body.field, field);
|
||||
});
|
||||
}
|
||||
for (const editing of [false, true]) {
|
||||
test(`saves ${editing ? 'edited' : 'new'} cargo using server identity and new eCMR versions`, async () => {
|
||||
writer.save = async payload => {
|
||||
assert.equal(payload.dni, '12345678A');
|
||||
assert.equal(payload.trip_id, 123);
|
||||
assert.equal(payload.cargo_id, editing ? 7 : null);
|
||||
assert.equal(payload.mercancia.remontable, 1);
|
||||
assert.equal(payload.database, process.env.DB_NAME);
|
||||
return { status: editing ? 200 : 201, body: { success: true, data: { id_mercancia: 7 }, ecmr_versiones: [{ id_documento: 9, version: 2 }] } };
|
||||
};
|
||||
const response = await request(editing ? 'PUT' : 'POST', editing ? '/123/cargo/7' : '/123/cargo', { ...valid, dni: 'forged', trip_id: 999 });
|
||||
assert.equal(response.status, editing ? 200 : 201);
|
||||
assert.equal(response.body.ecmr_versiones[0].version, 2);
|
||||
});
|
||||
}
|
||||
for (const status of [403, 404, 422, 500]) {
|
||||
test(`propagates transaction failure ${status}`, async () => {
|
||||
writer.save = async () => ({ status, body: { success: false, error: 'Failed' } });
|
||||
const response = await request('POST', '/123/cargo', valid);
|
||||
assert.equal(response.status, status);
|
||||
assert.equal(response.body.success, false);
|
||||
});
|
||||
}
|
||||
test('process failures return 500 without exposing internals', async () => {
|
||||
writer.save = async () => { throw new Error('/private/internal'); };
|
||||
const response = await request('POST', '/123/cargo', valid);
|
||||
assert.equal(response.status, 500);
|
||||
assert.doesNotMatch(response.body.error, /private/);
|
||||
});
|
||||
Reference in New Issue
Block a user