80 lines
3.0 KiB
JavaScript
80 lines
3.0 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import {
|
|
ProductStorageError,
|
|
ProductStorageService,
|
|
productStorageCredentialDigest,
|
|
resolveProductStorageRetrieval
|
|
} from '../dist/products/product-storage-service.js';
|
|
|
|
const credential = 'claim_credential_abcdefghijklmnopqrstuvwxyz012345';
|
|
const digest = productStorageCredentialDigest(credential);
|
|
assert.match(digest, /^[0-9a-f]{64}$/);
|
|
assert.equal(digest.includes(credential), false);
|
|
assert.equal(productStorageCredentialDigest(credential), digest);
|
|
assert.notEqual(productStorageCredentialDigest(`${credential}x`), digest);
|
|
|
|
assert.deepEqual(resolveProductStorageRetrieval('STORED', 5, 2), {
|
|
remainingQuantity: 3, status: 'PARTIALLY_RETRIEVED'
|
|
});
|
|
assert.deepEqual(resolveProductStorageRetrieval('PARTIALLY_RETRIEVED', 3, 3), {
|
|
remainingQuantity: 0, status: 'RETRIEVED'
|
|
});
|
|
for (const [status, quantity] of [['RETRIEVED', 1], ['EXPIRED', 1], ['CANCELLED', 1]]) {
|
|
assert.throws(
|
|
() => resolveProductStorageRetrieval(status, 1, quantity),
|
|
(error) => error instanceof ProductStorageError
|
|
&& error.code === 'PRODUCT_STORAGE_NOT_ACTIVE'
|
|
);
|
|
}
|
|
assert.throws(
|
|
() => resolveProductStorageRetrieval('STORED', 2, 3),
|
|
(error) => error instanceof ProductStorageError
|
|
&& error.code === 'PRODUCT_STORAGE_QUANTITY_EXCEEDED'
|
|
);
|
|
|
|
const manager = {
|
|
tenantId: '7', userId: '31',
|
|
access: {
|
|
roles: ['STORE_ADMIN'], capabilities: ['goods.storage.read', 'goods.storage.manage'],
|
|
storeIds: ['11']
|
|
},
|
|
source: 'MANAGEMENT', traceId: 'm09d3-storage-service',
|
|
ip: '127.0.0.1', userAgent: 'storage-service-test'
|
|
};
|
|
const noSqlPool = {
|
|
async execute() { throw new Error('SQL must not run for rejected input'); },
|
|
async getConnection() { throw new Error('transaction must not start for rejected input'); }
|
|
};
|
|
const service = new ProductStorageService(noSqlPool, {
|
|
now: () => new Date('2026-08-11T07:00:00.000Z'),
|
|
credentialFactory: () => credential
|
|
});
|
|
|
|
await assert.rejects(
|
|
() => service.createManual(manager, {
|
|
requestId: 'storage-create-duplicate', storeId: '11', memberId: '21',
|
|
expiresAt: new Date('2026-08-12T07:00:00.000Z'),
|
|
items: [{ skuId: '5', quantity: 1 }, { skuId: '5', quantity: 1 }]
|
|
}),
|
|
(error) => error instanceof ProductStorageError
|
|
&& error.code === 'PRODUCT_STORAGE_ITEMS_INVALID'
|
|
);
|
|
await assert.rejects(
|
|
() => service.createFromOrder({ ...manager, source: 'CUSTOMER', userId: '21' }, {
|
|
requestId: 'storage-expiry-invalid', sourceOrderId: '101',
|
|
expiresAt: new Date('2026-08-11T07:00:30.000Z')
|
|
}),
|
|
(error) => error instanceof ProductStorageError
|
|
&& error.code === 'PRODUCT_STORAGE_EXPIRY_INVALID'
|
|
);
|
|
await assert.rejects(
|
|
() => service.retrieve({ ...manager, source: 'CUSTOMER', userId: '21' }, '301', {
|
|
requestId: 'storage-retrieve-invalid-credential', claimCredential: 'short',
|
|
items: [{ storageItemId: '401', quantity: 1 }]
|
|
}),
|
|
(error) => error instanceof ProductStorageError
|
|
&& error.code === 'PRODUCT_STORAGE_CREDENTIAL_INVALID'
|
|
);
|
|
|
|
console.log('PASS: M09-D3 credential hashing, retrieval state transitions and input boundaries work.');
|