import assert from "node:assert/strict"; import test from "node:test"; import { createPricingProvider, createPricingProviderRegistry, } from "../../api/src/modules/pricing/providers/pricing-provider.js"; import { getPricingJobRetentionCutoff, processNextPersistentPricingRefreshJob, purgeCompletedPricingRefreshJobs, runPricingRefreshJob, } from "../src/pricing-refresh-worker.js"; test("calculates a UTC retention cutoff and purges completed jobs before it", async () => { const now = new Date("2026-09-09T12:00:00.000Z"); const cutoff = getPricingJobRetentionCutoff({ now, retentionDays: 30 }); assert.equal(cutoff.toISOString(), "2026-08-10T12:00:00.000Z"); let receivedCutoff; const deleted = await purgeCompletedPricingRefreshJobs({ jobRepository: { async purgeCompletedBefore(value) { receivedCutoff = value; return 3; }, }, now, retentionDays: 30, }); assert.equal(deleted, 3); assert.equal(receivedCutoff.toISOString(), cutoff.toISOString()); }); test("rejects invalid pricing job retention days", () => { assert.throws( () => getPricingJobRetentionCutoff({ retentionDays: 0 }), /positive integer/, ); }); test("completes a pricing refresh through the provider and pricing service boundaries", async () => { const providerRegistry = createPricingProviderRegistry([ createPricingProvider({ id: "fixture-provider", async observe() { return [{ priceMinor: 2500, sourceIdentifier: "fixture-1" }]; }, }), ]); const saved = []; const result = await runPricingRefreshJob({ job: { id: "job-1", type: "PRICING_REFRESH", providerId: "fixture-provider", sellerId: "seller-1", productId: "product-1", inventoryItemId: "inventory-1", conditionId: "condition-1", }, providerRegistry, pricingService: { async addObservation(input) { saved.push(input); return input; }, async calculate() { return { valuation: { valueMinor: 2500 } }; }, }, }); assert.equal(result.status, "COMPLETED"); assert.equal(result.valuation.valuation.valueMinor, 2500); assert.equal(saved[0].providerId, "fixture-provider"); }); test("fails a refresh clearly when a provider is unavailable", async () => { const result = await runPricingRefreshJob({ job: { id: "job-2", type: "PRICING_REFRESH", providerId: "missing" }, providerRegistry: createPricingProviderRegistry(), pricingService: {}, }); assert.equal(result.status, "FAILED"); assert.match(result.error, /not configured/); }); test("persists completed and failed outcomes through the job repository", async () => { const calls = []; const jobRepository = { async claimNext() { return { id: "job-3", type: "PRICING_REFRESH", providerId: "fixture" }; }, async complete(id, observations, valuation) { calls.push(["complete", id, observations, valuation]); }, async fail(id, error) { calls.push(["fail", id, error]); }, }; await processNextPersistentPricingRefreshJob({ jobRepository, async pricingRefreshJob() { return { status: "COMPLETED", observations: [{ id: "observation-1" }], valuation: { valueMinor: 2500 }, }; }, }); assert.deepEqual(calls, [ ["complete", "job-3", [{ id: "observation-1" }], { valueMinor: 2500 }], ]); }); test("persists failed pricing refresh outcomes through the repository", async () => { const calls = []; await processNextPersistentPricingRefreshJob({ jobRepository: { async claimNext() { return { id: "job-4" }; }, async complete() { throw new Error("not expected"); }, async fail(id, error) { calls.push([id, error]); }, }, async pricingRefreshJob() { return { status: "FAILED", error: "Provider unavailable." }; }, }); assert.deepEqual(calls, [["job-4", "Provider unavailable."]]); });