- Move fixture-provider.test.ts up to test/ (test:unit's glob is packages/*/test/*.test.ts, deliberately shallow, so a nested test/fixtures/ file was silently never run). The fixture module itself (fixture-provider.ts, the capture script, the JSON fixture) stays in test/fixtures/; only the *.test.ts file moved, importing it via ./fixtures/fixture-provider.ts. - Harden capture-protocol-params.mjs: refuse to write a fixture whose costModels/coinsPerUtxoByte/keyDeposit could have come from OgmiosProvider's own `??` fallback defaults instead of a genuine response. The brief's sanity numbers (minFeeA 45, minFeeB 156253, ...) are literally those same fallback literals, so matching them proves nothing; costModels has no populated fallback, so a well-formed, appropriately-sized cost model per Plutus version is the one signal a schema-mismatched response cannot fake. - packages/builder/tsconfig.json: include test/**/* so `npm run typecheck` actually checks builder's test files (it previously covered src/**/* only, unlike packages/shared). Needed allowImportingTsExtensions for the now-in-scope relative .ts-suffixed imports across every existing test file. Surfaced one real pre-existing gap: auth.test.ts calls loadAuthConfig with deliberately minimal env objects, but the exported signature demanded the full env.d.ts-augmented NodeJS.ProcessEnv (7 required custom fields) even though the function only ever reads MCP_AUTH_TOKENS. Narrowed the parameter to Record<string, string | undefined> - the function's real contract - which is a type-only change with a single production call site (index.ts's parameterless loadAuthConfig()) that already relies on the default. Verified: test:unit 117/117 (was 113 - the 4 fixture tests were never counted before), typecheck 0 errors, test:smoke 28/28, build unaffected. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
56 lines
2.6 KiB
JavaScript
56 lines
2.6 KiB
JavaScript
// packages/builder/test/fixtures/capture-protocol-params.mjs
|
|
//
|
|
// One-time capture: writes Lucid-format protocol parameters from the live
|
|
// Vector testnet Ogmios endpoint into protocol-params.fixture.json, using
|
|
// OgmiosProvider's own mapping so the fixture can never drift from the
|
|
// conversion logic. Run manually after `npm run build`:
|
|
//
|
|
// node packages/builder/test/fixtures/capture-protocol-params.mjs
|
|
//
|
|
// Never runs in CI — unit tests read the checked-in JSON.
|
|
import { writeFileSync } from 'node:fs';
|
|
import { resolve, dirname } from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
import { OgmiosProvider } from '@apexfusion/vector-mcp-shared/provider';
|
|
|
|
const ogmiosUrl = process.env.VECTOR_OGMIOS_URL || 'https://ogmios.vector.testnet.apexfusion.org';
|
|
const provider = new OgmiosProvider({ ogmiosUrl, submitUrl: 'http://unused.invalid', koiosUrl: '' });
|
|
const params = await provider.getProtocolParameters();
|
|
|
|
// Refuse to write a fixture that could have come from OgmiosProvider's own
|
|
// `??` fallback defaults instead of a real response. Several numeric fields
|
|
// (minFeeA, minFeeB, coinsPerUtxoByte, keyDeposit, ...) fall back to
|
|
// hardcoded literals on a schema mismatch, so matching those literals proves
|
|
// nothing on its own — a broken RPC response is indistinguishable from a
|
|
// testnet that genuinely uses standard values. costModels has no such
|
|
// populated fallback (provider.ts's only fallback there is `{}`), so a
|
|
// well-formed, appropriately-sized cost model per Plutus version is the one
|
|
// signal that cannot be produced by falling through to a default.
|
|
function sizeOf(x) {
|
|
if (Array.isArray(x)) return x.length;
|
|
if (x && typeof x === 'object') return Object.keys(x).length;
|
|
return 0;
|
|
}
|
|
|
|
const failures = [];
|
|
for (const version of ['PlutusV1', 'PlutusV2', 'PlutusV3']) {
|
|
const size = sizeOf(params.costModels?.[version]);
|
|
if (size < 100) {
|
|
failures.push(`costModels.${version} has ${size} entries, want >= 100`);
|
|
}
|
|
}
|
|
if (typeof params.coinsPerUtxoByte !== 'bigint') {
|
|
failures.push(`coinsPerUtxoByte is ${typeof params.coinsPerUtxoByte}, want bigint`);
|
|
}
|
|
if (typeof params.keyDeposit !== 'bigint') {
|
|
failures.push(`keyDeposit is ${typeof params.keyDeposit}, want bigint`);
|
|
}
|
|
if (failures.length > 0) {
|
|
throw new Error('capture looks like fallback defaults, refusing to write: ' + failures.join('; '));
|
|
}
|
|
|
|
const json = JSON.stringify(params, (_k, v) => (typeof v === 'bigint' ? { __bigint: v.toString() } : v), 2);
|
|
const out = resolve(dirname(fileURLToPath(import.meta.url)), 'protocol-params.fixture.json');
|
|
writeFileSync(out, json + '\n');
|
|
console.log(`wrote ${out}`);
|