Files
pokemon-inventory/apps/api/tests/application/pricing-service.test.js
T
fragginwagon b8f089a5d9 feat: reconcile application vertical slices
Backfill the completed acquisitions, sales, dashboard, pricing, search, public detail, worker, migration, contracts, validation, tests, and implementation-status changes into one verified application slice.
2026-09-09 22:12:53 -04:00

138 lines
3.7 KiB
JavaScript

import assert from "node:assert/strict";
import test from "node:test";
import { createPricingService } from "../../src/modules/pricing/services/pricing-service.js";
test("records an owned pricing observation and calculates a valuation", async () => {
const service = createPricingService({
pricingRepository: {
async addObservationForSeller({ observation, sellerId }) {
assert.equal(sellerId, "seller-1");
return { status: "CREATED", observation };
},
async markOutliersForSeller() {
return { status: "UPDATED" };
},
async calculateForSeller() {
return {
status: "CALCULATED",
valuation: { valueMinor: 2500 },
observations: [],
};
},
},
});
const observation = await service.addObservation({
sellerId: "seller-1",
productId: "product-1",
inventoryItemId: "inventory-1",
providerId: "manual",
priceMinor: 2500,
sourceIdentifier: "source-1",
conditionId: "condition-1",
});
assert.equal(observation.priceMinor, 2500);
const valuation = await service.calculate({
sellerId: "seller-1",
inventoryItemId: "inventory-1",
});
assert.equal(valuation.valuation.valueMinor, 2500);
});
test("requires a reason for an audited market-value override", async () => {
const service = createPricingService({
pricingRepository: {
async createOverride() {
throw new Error("should not run");
},
},
});
await assert.rejects(
() =>
service.override({
sellerId: "seller-1",
actorUserId: "user-1",
inventoryItemId: "inventory-1",
valueMinor: 2000,
reason: "x",
}),
(error) =>
error.code === "OVERRIDE_REASON_REQUIRED" && error.statusCode === 400,
);
});
test("fails clearly when a requested pricing provider is unavailable", async () => {
const service = createPricingService({
pricingRepository: {},
pricingProviderRegistry: {
get() {
return null;
},
},
});
await assert.rejects(
() =>
service.refresh({
sellerId: "seller-1",
inventoryItemId: "inventory-1",
providerId: "missing",
}),
(error) =>
error.code === "PRICING_PROVIDER_UNAVAILABLE" && error.statusCode === 503,
);
});
test("enqueues a seller-scoped pricing refresh and reads its status", async () => {
const service = createPricingService({
pricingRepository: {},
pricingRefreshJobRepository: {
async create(input) {
return { id: "job-1", status: "PENDING", ...input };
},
async findByIdForSeller(id, sellerId) {
return { id, sellerId, status: "COMPLETED" };
},
},
providerMappingRepository: {
async findActiveForSeller() {
return { providerId: "mapped-provider" };
},
},
});
const job = await service.enqueueRefresh({
sellerId: "seller-1",
inventoryItemId: "item-1",
providerId: "provider-1",
productId: "product-1",
conditionId: "condition-1",
});
assert.equal(job.status, "PENDING");
assert.equal(job.providerId, "mapped-provider");
assert.equal(
(await service.getJob({ sellerId: "seller-1", jobId: job.id })).status,
"COMPLETED",
);
});
test("lists and retries seller-scoped failed pricing jobs", async () => {
const service = createPricingService({
pricingRepository: {},
pricingRefreshJobRepository: {
async listForSeller() {
return [{ id: "job-1", status: "FAILED" }];
},
async retryForSeller() {
return { id: "job-1", status: "PENDING" };
},
},
});
assert.equal((await service.listJobs({ sellerId: "seller-1" })).length, 1);
assert.equal(
(await service.retryJob({ sellerId: "seller-1", jobId: "job-1" })).status,
"PENDING",
);
});