mirror of
https://github.com/callstack/agent-device.git
synced 2026-09-14 20:06:34 +08:00
9d7d60c5e0
* test(coverage): declare every public command's six platform coverage judgments once One row per public command in test/integration/command-coverage/declarations.ts carries the android-emulator, ios-simulator, macOS, tvOS, web and Linux classifications with the same fields the six per-platform manifests use today. Each platform's Record<PublicCommand, ...> is projected from that table at load time by a small per-platform view module, so no projected record is committed. No judgment is derived from another platform's: all six stay authored per command. * test(coverage): read the projected per-platform coverage view The six coverage smoke tests, live harnesses and coverage reports now import the platform view module that projects the declaration table. Both the depgraph blast-radius query and the device-lane test follow the iOS and macOS paths. * test(coverage): delete the six per-platform coverage manifests Their rows now live once, per command, in the declaration table; each platform's record is projected from it at load time. * fix(check-affected): extend macos-coverage and integration-node ownership to command-coverage/ test/integration/command-coverage/declarations.ts now carries the per-command coverage judgments that used to live directly under test/integration/macos-e2e/. Its nested path wasn't matched by macosCoverageOwnership (top-level or macos-e2e/ only) or isNodeIntegrationPath (no nested segments), so it fell through to vitest-related, which can't actually run its node --test consumers. Extend both rules to also match test/integration/command-coverage/.
151 lines
5.5 KiB
TypeScript
151 lines
5.5 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import fs from 'node:fs';
|
|
import path from 'node:path';
|
|
import test from 'node:test';
|
|
|
|
import { mkdtempForTest } from '../../src/__tests__/test-utils/tmp-dir.ts';
|
|
import { PUBLIC_COMMANDS } from '@agent-device/command-registry/catalog';
|
|
import {
|
|
MACOS_COVERAGE_GAP_ISSUE,
|
|
MACOS_LIVE_SCENARIOS,
|
|
MACOS_PLATFORM_COVERAGE,
|
|
MACOS_PLATFORM_COVERAGE_CLASSIFICATION_SUMMARY,
|
|
liveCommandsForScenario,
|
|
} from './macos-e2e/coverage.ts';
|
|
import { writeCoverageReport } from './macos-e2e/coverage-report.ts';
|
|
|
|
test('macOS coverage exhaustively classifies the public catalog', () => {
|
|
const publicCommands = Object.values(PUBLIC_COMMANDS).sort();
|
|
assert.deepEqual(Object.keys(MACOS_PLATFORM_COVERAGE).sort(), publicCommands);
|
|
|
|
for (const command of publicCommands) {
|
|
const entry = MACOS_PLATFORM_COVERAGE[command];
|
|
assert.ok(entry.assertion.trim().length > 0, `${command} needs an observable assertion`);
|
|
if (entry.level === 'known-gap') {
|
|
assert.equal(
|
|
entry.trackingIssue,
|
|
MACOS_COVERAGE_GAP_ISSUE,
|
|
`${command} has the wrong gap issue`,
|
|
);
|
|
continue;
|
|
}
|
|
assert.ok(entry.owner.path.trim().length > 0, `${command} needs an evidence path`);
|
|
assert.ok(entry.owner.test.trim().length > 0, `${command} needs named evidence`);
|
|
if (entry.level === 'live') {
|
|
assert.ok(entry.scenario.trim().length > 0, `${command} needs a live scenario owner`);
|
|
}
|
|
}
|
|
});
|
|
|
|
test('macOS coverage report counts every manifest classification', () => {
|
|
assert.deepEqual(MACOS_PLATFORM_COVERAGE_CLASSIFICATION_SUMMARY, {
|
|
contract: 21,
|
|
gap: 15,
|
|
live: 18,
|
|
total: 54,
|
|
});
|
|
assert.equal(
|
|
MACOS_PLATFORM_COVERAGE_CLASSIFICATION_SUMMARY.live +
|
|
MACOS_PLATFORM_COVERAGE_CLASSIFICATION_SUMMARY.contract +
|
|
MACOS_PLATFORM_COVERAGE_CLASSIFICATION_SUMMARY.gap,
|
|
MACOS_PLATFORM_COVERAGE_CLASSIFICATION_SUMMARY.total,
|
|
);
|
|
});
|
|
|
|
test('macOS live claims reference commands in existing executable scenarios', () => {
|
|
const scenariosById = new Map(MACOS_LIVE_SCENARIOS.map((scenario) => [scenario.id, scenario]));
|
|
const claimedCommands: string[] = [];
|
|
|
|
for (const scenario of MACOS_LIVE_SCENARIOS) {
|
|
const source = readEvidence(scenario.owner);
|
|
for (const command of liveCommandsForScenario(scenario.id)) {
|
|
const entry = MACOS_PLATFORM_COVERAGE[command];
|
|
assert.equal(entry.level, 'live');
|
|
assert.deepEqual(entry.owner, scenario.owner, `${command} owner drifted from its scenario`);
|
|
assert.equal(
|
|
sourceContainsCommand(source, scenario.syntax, command),
|
|
true,
|
|
`${command} is not executed by ${scenario.owner.path}`,
|
|
);
|
|
claimedCommands.push(command);
|
|
}
|
|
}
|
|
|
|
assert.equal(new Set(scenariosById.keys()).size, MACOS_LIVE_SCENARIOS.length);
|
|
assert.equal(new Set(claimedCommands).size, claimedCommands.length);
|
|
assert.equal(
|
|
claimedCommands.length,
|
|
Object.values(MACOS_PLATFORM_COVERAGE).filter((entry) => entry.level === 'live').length,
|
|
);
|
|
});
|
|
|
|
test('macOS non-live evidence owners name existing executable repository evidence', () => {
|
|
for (const [command, entry] of Object.entries(MACOS_PLATFORM_COVERAGE)) {
|
|
if (entry.level === 'live' || entry.level === 'known-gap') continue;
|
|
const evidencePath = path.resolve(entry.owner.path);
|
|
assert.equal(fs.existsSync(evidencePath), true, `${command} owner does not exist`);
|
|
assert.equal(
|
|
fs.readFileSync(evidencePath, 'utf8').includes(entry.owner.test),
|
|
true,
|
|
`${command} owner does not contain named evidence: ${entry.owner.test}`,
|
|
);
|
|
}
|
|
});
|
|
|
|
test('macOS known gaps use one grouped tracking issue', () => {
|
|
const gapIssues = new Set(
|
|
Object.values(MACOS_PLATFORM_COVERAGE)
|
|
.filter((entry) => entry.level === 'known-gap')
|
|
.map((entry) => entry.trackingIssue),
|
|
);
|
|
assert.deepEqual([...gapIssues], [MACOS_COVERAGE_GAP_ISSUE]);
|
|
});
|
|
|
|
test('macOS coverage report persists the manifest rollup and live command list', async () => {
|
|
const artifactDir = await mkdtempForTest('agent-device-macos-coverage-');
|
|
const report = JSON.parse(fs.readFileSync(writeCoverageReport(artifactDir), 'utf8')) as {
|
|
classificationSummary: typeof MACOS_PLATFORM_COVERAGE_CLASSIFICATION_SUMMARY;
|
|
liveCommands: string[];
|
|
liveScenarios: string[];
|
|
};
|
|
|
|
assert.deepEqual(report.classificationSummary, MACOS_PLATFORM_COVERAGE_CLASSIFICATION_SUMMARY);
|
|
assert.deepEqual(
|
|
report.liveCommands.sort(),
|
|
Object.entries(MACOS_PLATFORM_COVERAGE)
|
|
.filter(([, entry]) => entry.level === 'live')
|
|
.map(([command]) => command)
|
|
.sort(),
|
|
);
|
|
assert.deepEqual(
|
|
report.liveScenarios,
|
|
MACOS_LIVE_SCENARIOS.map(({ id }) => id),
|
|
);
|
|
});
|
|
|
|
function readEvidence(owner: { path: string; test: string }): string {
|
|
const evidencePath = path.resolve(owner.path);
|
|
assert.equal(fs.existsSync(evidencePath), true, `${owner.path} does not exist`);
|
|
const source = fs.readFileSync(evidencePath, 'utf8');
|
|
assert.equal(source.includes(owner.test), true, `${owner.path} lacks ${owner.test}`);
|
|
return source;
|
|
}
|
|
|
|
function sourceContainsCommand(
|
|
source: string,
|
|
syntax: (typeof MACOS_LIVE_SCENARIOS)[number]['syntax'],
|
|
command: string,
|
|
): boolean {
|
|
switch (syntax) {
|
|
case 'replay':
|
|
return source.split(/\r?\n/).some((line) => {
|
|
const trimmed = line.trim();
|
|
return trimmed === command || trimmed.startsWith(`${command} `);
|
|
});
|
|
case 'provider-command':
|
|
return source.includes(`command: '${command}'`);
|
|
case 'provider-call-command':
|
|
return source.includes(`callCommand('${command}'`);
|
|
}
|
|
}
|