159 lines
5.1 KiB
JavaScript
159 lines
5.1 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
|
|
import { createInventoryItemService } from '../../src/modules/inventory/services/inventory-item-service.js';
|
|
|
|
function createService({ product, condition }) {
|
|
return createInventoryItemService({
|
|
productRepository: { async findById() { return product; } },
|
|
conditionRepository: { async findById() { return condition; } },
|
|
inventoryItemRepository: {
|
|
async create(inventoryItem) { return inventoryItem; },
|
|
async listBySellerId() { return []; },
|
|
async archiveByIdsForSeller(inventoryItemIds) {
|
|
return inventoryItemIds.map((id) => ({ id, status: 'ARCHIVED' }));
|
|
},
|
|
},
|
|
});
|
|
}
|
|
|
|
test('creates an inventory item when its condition belongs to the product category', async () => {
|
|
const service = createService({
|
|
product: { id: 'product-id', sellerId: 'seller-id', categoryId: 'cards' },
|
|
condition: { id: 'condition-id', categoryId: 'cards' },
|
|
});
|
|
|
|
const inventoryItem = await service.create({
|
|
productId: 'product-id',
|
|
conditionId: 'condition-id',
|
|
sellerId: 'seller-id',
|
|
notes: ' Near mint ',
|
|
});
|
|
|
|
assert.deepEqual(inventoryItem, {
|
|
productId: 'product-id',
|
|
conditionId: 'condition-id',
|
|
notes: 'Near mint',
|
|
});
|
|
});
|
|
|
|
test('archives owned active inventory items in bulk', async () => {
|
|
const service = createInventoryItemService({
|
|
productRepository: { async findById() { return null; } },
|
|
conditionRepository: { async findById() { return null; } },
|
|
inventoryItemRepository: {
|
|
async listBySellerId() {
|
|
return [
|
|
{ id: 'item-1', status: 'ACTIVE' },
|
|
{ id: 'item-2', status: 'ACTIVE' },
|
|
];
|
|
},
|
|
async archiveByIdsForSeller(ids) {
|
|
return ids.map((id) => ({ id, status: 'ARCHIVED' }));
|
|
},
|
|
},
|
|
});
|
|
|
|
assert.deepEqual(
|
|
await service.archiveMany({ inventoryItemIds: ['item-1', 'item-2'], sellerId: 'seller-id' }),
|
|
[
|
|
{ id: 'item-1', status: 'ARCHIVED' },
|
|
{ id: 'item-2', status: 'ARCHIVED' },
|
|
],
|
|
);
|
|
});
|
|
|
|
test('does not archive sold inventory items', async () => {
|
|
const service = createInventoryItemService({
|
|
productRepository: { async findById() { return null; } },
|
|
conditionRepository: { async findById() { return null; } },
|
|
inventoryItemRepository: {
|
|
async listBySellerId() { return [{ id: 'item-1', status: 'SOLD' }]; },
|
|
async archiveByIdsForSeller() { throw new Error('should not update'); },
|
|
},
|
|
});
|
|
|
|
await assert.rejects(
|
|
() => service.archiveMany({ inventoryItemIds: ['item-1'], sellerId: 'seller-id' }),
|
|
/Inventory status cannot transition from SOLD to ARCHIVED/,
|
|
);
|
|
});
|
|
|
|
test('enqueues pricing refresh jobs for owned inventory items', async () => {
|
|
const enqueued = [];
|
|
const service = createInventoryItemService({
|
|
productRepository: { async findById() { return null; } },
|
|
conditionRepository: { async findById() { return null; } },
|
|
inventoryItemRepository: {
|
|
async listBySellerId() {
|
|
return [{ id: 'item-1', productId: 'product-1', conditionId: 'condition-1', status: 'ACTIVE' }];
|
|
},
|
|
},
|
|
pricingService: {
|
|
async enqueueRefresh(input) {
|
|
enqueued.push(input);
|
|
return { id: 'job-1', status: 'PENDING' };
|
|
},
|
|
},
|
|
});
|
|
|
|
const jobs = await service.refreshPricingMany({
|
|
inventoryItemIds: ['item-1'],
|
|
sellerId: 'seller-id',
|
|
providerId: 'fixture-provider',
|
|
});
|
|
|
|
assert.deepEqual(enqueued, [{
|
|
sellerId: 'seller-id',
|
|
inventoryItemId: 'item-1',
|
|
providerId: 'fixture-provider',
|
|
productId: 'product-1',
|
|
conditionId: 'condition-1',
|
|
}]);
|
|
assert.deepEqual(jobs, [{ id: 'job-1', status: 'PENDING' }]);
|
|
});
|
|
|
|
test('updates Product tags for selected owned inventory items', async () => {
|
|
const updates = [];
|
|
const service = createInventoryItemService({
|
|
productRepository: { async findById() { return null; } },
|
|
conditionRepository: { async findById() { return null; } },
|
|
inventoryItemRepository: {
|
|
async listBySellerId() {
|
|
return [
|
|
{ id: 'item-1', productId: 'product-1', conditionId: 'condition-1' },
|
|
{ id: 'item-2', productId: 'product-1', conditionId: 'condition-1' },
|
|
];
|
|
},
|
|
async updateProductTagsByIdsForSeller(...input) {
|
|
updates.push(input);
|
|
return [{ id: 'product-1', tags: ['binder', 'keep'] }];
|
|
},
|
|
},
|
|
});
|
|
|
|
assert.deepEqual(await service.updateTagsMany({
|
|
inventoryItemIds: ['item-1', 'item-2'],
|
|
sellerId: 'seller-id',
|
|
addTags: ['Binder'],
|
|
removeTags: ['sell'],
|
|
}), [{ id: 'product-1', tags: ['binder', 'keep'] }]);
|
|
assert.deepEqual(updates, [[['item-1', 'item-2'], 'seller-id', ['Binder'], ['sell']]]);
|
|
});
|
|
|
|
test('rejects conditions from another category', async () => {
|
|
const service = createService({
|
|
product: { id: 'product-id', sellerId: 'seller-id', categoryId: 'cards' },
|
|
condition: { id: 'condition-id', categoryId: 'merchandise' },
|
|
});
|
|
|
|
await assert.rejects(
|
|
() =>
|
|
service.create({
|
|
productId: 'product-id',
|
|
conditionId: 'condition-id',
|
|
sellerId: 'seller-id',
|
|
}),
|
|
(error) => error.code === 'CONDITION_CATEGORY_MISMATCH',
|
|
);
|
|
}); |