Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions tests/validate-architectures.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -182,3 +182,25 @@ test('rejects a sourceUrl carrying a password-only userinfo component', () => {
assert.equal(result.status, 1);
assert.match(result.stderr, /sourceUrl must be an https URL/);
});

// record.id doubles as the error label, so a record that is missing it falls
// back to '<unknown>'. Line coverage cannot see that fallback: the rest of
// each `path: record.id || '<unknown>'` line runs on every malformed record.
// Both fallback sites fire for one id-less record, and the reported label is
// what a maintainer reads to find the offending entry.
test('labels an id-less record <unknown> in every error it raises', () => {
const result = runScriptWithFixtures(
SCRIPT,
catalogFixture([{ title: 'Acme Platform', organization: 'Acme Corp' }]),
);
assert.equal(result.status, 1);
assert.match(
result.stderr,
/\[error\] <unknown>: missing id, title, or organization/,
);
assert.match(
result.stderr,
/\[error\] <unknown>: sourceUrl must be an https URL/,
);
assert.doesNotMatch(result.stderr, /\[error\] undefined:/);
});
30 changes: 30 additions & 0 deletions tests/validate-case-studies.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -259,3 +259,33 @@ test('rejects an entry missing industries entirely', () => {
assert.equal(result.status, 1);
assert.match(result.stderr, /industries must be an array/);
});

// The error label is `entry.id ?? entry.slug ?? 'unknown'`. Both fallback arms
// sit mid-line, so line coverage reports them as run whenever a malformed
// entry is validated at all; only an entry that actually omits `id` reaches
// the slug arm, and only one omitting `slug` too reaches the literal.
test('falls back to the slug when an entry has no id', () => {
const result = runScriptWithFixtures(
SCRIPT,
fixture({
...validData,
caseStudies: [{ ...validEntry, id: undefined }],
}),
);
assert.equal(result.status, 1);
assert.match(result.stderr, /\[error\] example-org: duplicate or missing id/);
assert.doesNotMatch(result.stderr, /\[error\] unknown:/);
});

test('falls back to "unknown" when an entry has neither id nor slug', () => {
const result = runScriptWithFixtures(
SCRIPT,
fixture({
...validData,
caseStudies: [{ ...validEntry, id: undefined, slug: undefined }],
}),
);
assert.equal(result.status, 1);
assert.match(result.stderr, /\[error\] unknown: duplicate or missing id/);
assert.doesNotMatch(result.stderr, /\[error\] undefined:/);
});
31 changes: 31 additions & 0 deletions tests/validate-launch-metrics.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -334,3 +334,34 @@ test('rejects a signal sourceUrl carrying a password-only userinfo component', (
assert.equal(result.status, 1);
assert.match(result.stderr, /sourceUrl must not carry a userinfo component/);
});

// `data.signals || []` keeps a file with no signals key from throwing on
// .length, so the count check reports it as a data problem instead of the
// script dying with a TypeError. The `|| []` arm is invisible to line
// coverage because the assignment line runs for every file.
test('reports a missing signals key as a count failure, not a crash', () => {
const withoutSignals = { ...validData };
delete withoutSignals.signals;
const result = runScriptWithFixtures(SCRIPT, fixture(withoutSignals));
assert.equal(result.status, 1);
assert.match(result.stderr, /signals must define 3-5 signals, got 0/);
assert.doesNotMatch(result.stderr, /TypeError/);
});

// A signal with no id has no natural label, so every error it raises is
// filed under '(missing id)' rather than the empty string `signal.id` would
// otherwise contribute.
test('labels an id-less signal "(missing id)" in every error it raises', () => {
const anonymous = { ...validSignal };
delete anonymous.id;
const result = runScriptWithFixtures(
SCRIPT,
fixture({ ...validData, signals: [...validData.signals, anonymous] }),
);
assert.equal(result.status, 1);
assert.match(
result.stderr,
/\[error\] \(missing id\): duplicate or missing signal id/,
);
assert.doesNotMatch(result.stderr, /\[error\] undefined:/);
});
13 changes: 13 additions & 0 deletions tests/validate-metrics.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -398,3 +398,16 @@ test('accepts a valid breakdown', () => {
);
assert.equal(result.status, 0, result.stderr);
});

// `data.metrics || []` lets the per-metric loop skip a file whose collector
// never wrote a metrics array, so the failure reported is the one that caused
// it rather than an iteration TypeError. The `|| []` arm sits mid-line, so
// line coverage reports it as run on every valid file.
test('reports a metrics-less file by its real failure, not an iteration crash', () => {
const truncated = { ...validData, generated: false };
delete truncated.metrics;
const result = runScriptWithFixtures(SCRIPT, metricsFixture(truncated));
assert.equal(result.status, 1);
assert.match(result.stderr, /generated must be true/);
assert.doesNotMatch(result.stderr, /TypeError/);
});