Files
worldmonitor/tests/seed-fuel-prices.test.mjs
Elie Habib b92b22bd20 fix(fuel-prices): tolerate Brazil ANP failure to stop Railway crash-loop (#3085)
* fix(fuel-prices): tolerate Brazil ANP failure to stop Railway crash-loop

Brazil gov.br is structurally unreachable from Railway IPs:
- Decodo proxy 403s all .gov.br CONNECTs by policy
- Direct fetch fails undici TLS handshake from Railway egress

After PR #3082 tightened the publish gate to require zero failed sources,
every run exits 1 -> Railway "Deployment crashed" banner + STALE_SEED.

Add TOLERATED_FAILURES = {'Brazil'}; validateFuel ignores tolerated names
when checking failedSources. Critical regions (US/GB/MY) and the >=30
country floor still gate publish. Brazil's outage stays visible via the
existing [FRESHNESS] log.

* fix(fuel-prices): rotate :prev on tolerated-only failures to keep WoW fresh

Reviewer catch: after tolerating Brazil, allSourcesFresh stays false forever
→ :prev never rotates → panel's WoW stretches into 2-week, 3-week, ... deltas
for every non-Brazil country while still labeled 'week-over-week'.

Gate :prev rotation on untolerated failures only. Tolerated sources are
absent from the snapshot entirely, so rotating is safe (no stale-self-
compare poisoning next week).

* fix(fuel-prices): distinguish tolerated vs untolerated sources in [DEGRADED] log

Greptile P2: the [DEGRADED] message said 'publish will be rejected' even
when only tolerated sources (Brazil) failed — confusing for operators
watching Railway logs.
2026-04-14 12:36:07 +04:00

103 lines
4.0 KiB
JavaScript

import { test } from 'node:test';
import assert from 'node:assert/strict';
import { parseCREStationPrices, validateFuel } from '../scripts/seed-fuel-prices.mjs';
test('parseCREStationPrices extracts regular + diesel per-station prices from CRE XML', () => {
const xml = `<?xml version="1.0" encoding="utf-8"?>
<places>
<place place_id="1">
<gas_price type="regular">22.95</gas_price>
<gas_price type="premium">26.91</gas_price>
</place>
<place place_id="2">
<gas_price type="regular">24.7</gas_price>
<gas_price type="diesel">29.5</gas_price>
</place>
</places>`;
const { regular, diesel } = parseCREStationPrices(xml);
assert.deepEqual(regular, [22.95, 24.7]);
assert.deepEqual(diesel, [29.5]);
});
test('parseCREStationPrices filters out-of-range prices', () => {
// 0.01 and 1000.0 are clearly bad (placeholder/test rows); 15 and 50 are valid MXN/L.
const xml = `<places>
<place><gas_price type="regular">0.01</gas_price></place>
<place><gas_price type="regular">15</gas_price></place>
<place><gas_price type="regular">1000.0</gas_price></place>
<place><gas_price type="regular">50</gas_price></place>
</places>`;
const { regular } = parseCREStationPrices(xml);
assert.deepEqual(regular, [15, 50]);
});
test('parseCREStationPrices handles empty XML', () => {
const { regular, diesel } = parseCREStationPrices('<places></places>');
assert.deepEqual(regular, []);
assert.deepEqual(diesel, []);
});
const HEALTHY_COUNTRIES = [
{ code: 'US' }, { code: 'GB' }, { code: 'MY' }, { code: 'BR' }, { code: 'MX' }, { code: 'NZ' },
...Array.from({ length: 27 }, (_, i) => ({ code: `EU${i}` })),
];
test('validateFuel accepts healthy snapshot (all sources fresh, 33 countries, US+GB+MY present)', () => {
assert.equal(validateFuel({ countries: HEALTHY_COUNTRIES, failedSources: [] }), true);
});
test('validateFuel rejects when an untolerated source failed (no silent degraded publishes)', () => {
assert.equal(
validateFuel({ countries: HEALTHY_COUNTRIES, failedSources: ['Mexico'] }),
false,
'a non-tolerated source failure must block publish; cache TTL serves last healthy snapshot',
);
});
test('validateFuel accepts when only a TOLERATED source (Brazil) failed', () => {
assert.equal(
validateFuel({ countries: HEALTHY_COUNTRIES, failedSources: ['Brazil'] }),
true,
'Brazil ANP is structurally unreachable from Railway; must not gate publish or Railway crash-loops',
);
});
test('validateFuel rejects when country count < 30', () => {
const countries = [
{ code: 'US' }, { code: 'GB' }, { code: 'MY' },
...Array.from({ length: 25 }, (_, i) => ({ code: `EU${i}` })),
];
assert.equal(validateFuel({ countries, failedSources: [] }), false, '28 countries should fail >=30');
});
test('validateFuel rejects when critical source US is missing', () => {
const countries = [
{ code: 'GB' }, { code: 'MY' }, { code: 'BR' }, { code: 'MX' }, { code: 'NZ' },
...Array.from({ length: 27 }, (_, i) => ({ code: `EU${i}` })),
];
assert.equal(validateFuel({ countries, failedSources: [] }), false, 'missing US fails gate');
});
test('validateFuel rejects when critical source GB is missing', () => {
const countries = [
{ code: 'US' }, { code: 'MY' }, { code: 'BR' }, { code: 'MX' }, { code: 'NZ' },
...Array.from({ length: 27 }, (_, i) => ({ code: `EU${i}` })),
];
assert.equal(validateFuel({ countries, failedSources: [] }), false, 'missing GB fails gate');
});
test('validateFuel rejects when critical source MY is missing', () => {
const countries = [
{ code: 'US' }, { code: 'GB' }, { code: 'BR' }, { code: 'MX' }, { code: 'NZ' },
...Array.from({ length: 27 }, (_, i) => ({ code: `EU${i}` })),
];
assert.equal(validateFuel({ countries, failedSources: [] }), false, 'missing MY fails gate');
});
test('validateFuel rejects null/undefined/empty', () => {
assert.equal(validateFuel(null), false);
assert.equal(validateFuel(undefined), false);
assert.equal(validateFuel({}), false);
assert.equal(validateFuel({ countries: [] }), false);
});