Files
pokemon-inventory/apps/api/tests/application/pricing-provider.test.js
T
2026-09-10 01:46:58 -04:00

130 lines
3.8 KiB
JavaScript

import assert from "node:assert/strict";
import test from "node:test";
import {
createPricingProvider,
createPricingProviderRegistry,
} from "../../src/modules/pricing/providers/pricing-provider.js";
import { createFixturePricingProvider } from "../../src/modules/pricing/providers/fixture-pricing-provider.js";
import {
assertProductionPricingProviderConfig,
createHttpPricingProvider,
} from "../../src/modules/pricing/providers/http-pricing-provider.js";
test("registers pricing providers behind a validated adapter contract", async () => {
const provider = createPricingProvider({
id: "example",
async observe() {
return [{ priceMinor: 2500, sourceIdentifier: "example-1" }];
},
});
const registry = createPricingProviderRegistry([provider]);
assert.equal(registry.get("example"), provider);
assert.deepEqual(await registry.get("example").observe({}), [
{ priceMinor: 2500, sourceIdentifier: "example-1" },
]);
assert.deepEqual(registry.list(), [provider]);
});
test("rejects malformed provider adapters and responses", async () => {
assert.throws(
() => createPricingProvider({ id: "broken" }),
/observe function is required/,
);
const provider = createPricingProvider({
id: "broken",
async observe() {
return null;
},
});
await assert.rejects(
() => provider.observe({}),
/must return an observation array/,
);
});
test("fixture provider returns deterministic normalized observations", async () => {
const [observation] = await createFixturePricingProvider().observe({
productId: "product-1",
inventoryItemId: "item-1",
conditionId: "condition-1",
});
assert.deepEqual(observation, {
productId: "product-1",
inventoryItemId: "item-1",
conditionId: "condition-1",
priceMinor: 2500,
currency: "USD",
sourceIdentifier: "fixture-item-1",
qualityScore: 50,
});
});
test("http provider rejects insecure or malformed external provider URLs", () => {
assert.throws(
() =>
createHttpPricingProvider({
id: "http-provider",
endpoint: "http://provider.example/prices",
}),
/HTTPS/i,
);
assert.throws(
() =>
createHttpPricingProvider({
id: "http-provider",
endpoint: "not-a-url",
}),
/valid https URL/i,
);
});
test("requires a secure external provider in production", () => {
assert.throws(
() => assertProductionPricingProviderConfig({ fixtureEnabled: true, endpoint: "https://provider.example/prices" }),
/fixture pricing provider must be disabled/i,
);
assert.throws(
() => assertProductionPricingProviderConfig({ fixtureEnabled: false, endpoint: "" }),
/endpoint is required/i,
);
assert.throws(
() => assertProductionPricingProviderConfig({ fixtureEnabled: false, endpoint: "http://provider.example/prices" }),
/must use HTTPS/i,
);
assert.doesNotThrow(() => assertProductionPricingProviderConfig({
fixtureEnabled: false,
endpoint: "https://provider.example/prices",
}));
});
test("http provider sends mapping context and normalizes its response", async () => {
let request;
const provider = createHttpPricingProvider({
id: "http-provider",
endpoint: "https://provider.example/prices",
token: "test-token",
async fetchImplementation(url, options) {
request = { url: String(url), options };
return {
ok: true,
async json() {
return { observations: [{ priceMinor: 2500 }] };
},
};
},
});
assert.deepEqual(
await provider.observe({
externalIdentifier: "catalog-1",
searchQuery: "Charizard",
}),
[{ priceMinor: 2500 }],
);
assert.match(request.url, /externalIdentifier=catalog-1/);
assert.equal(request.options.headers.authorization, "Bearer test-token");
});