Files
callstack__agent-device/scripts/check-affected/device-lanes.test.ts
Michał Pierzchała d57aa69777 test: add macOS platform command coverage manifest (#1922)
* test: add macOS platform command coverage manifest

* fix: remove unused macOS coverage type exports

* test: route macOS coverage away from iOS lane

* fix: account for host-dependent macOS audio capability

* fix: run macOS coverage manifest in CI
2026-08-21 12:39:35 +02:00

192 lines
7.4 KiB
TypeScript

// Device-lane ownership (#1781 A9-2): planted paths per family, and the two properties the
// ios.yml routing leans on — an Apple-owned change carries its iOS checks in a narrow plan, and
// a tooling change beside it still fails open to the full set.
import assert from 'node:assert/strict';
import { test } from 'node:test';
import { deviceLaneLeaf, deviceLanesFor, isDeviceLaneSurface, isUnitTest } from './device-lanes.ts';
import { selectChecks, type CheckId } from './model.ts';
const IOS: readonly CheckId[] = ['replay-ios', 'replay-ios-device'];
function lanes(file: string): CheckId[] {
const plan = selectChecks({ changedFiles: [file] });
assert.equal(plan.failOpen, false, `${file} must not fail open`);
return plan.checks.filter((id) =>
/^macos-coverage$|^replay-|^web-smoke$|^swift-runner-|^macos-helper$|^android-helpers$/.test(
id,
),
);
}
test('a TypeScript-only Apple change selects the iOS and macOS lanes without a Swift build', () => {
for (const file of [
'src/platforms/apple/core/apps.ts',
'packages/platform-apple/src/runtime.ts',
'src/platforms/apple/os/macos/desktop.ts',
]) {
assert.deepEqual(lanes(file), ['replay-ios', 'replay-ios-device', 'replay-macos'], file);
assert.ok(
selectChecks({ changedFiles: [file] }).reasons.some(
(reason) => reason.rule === 'own:device-lane:apple',
),
);
}
assert.deepEqual(lanes('src/daemon/snapshot-presentation/ios/action-shelf.ts'), [...IOS]);
assert.deepEqual(lanes('test/integration/replays/macos/01-desktop.ad'), ['replay-macos']);
});
test('a Swift runner change selects both builds and every Apple lane', () => {
assert.deepEqual(lanes('apple/runner/AgentDeviceRunner/Sources/Foo.swift'), [
'swift-runner-ios',
'swift-runner-macos',
'replay-ios',
'replay-ios-device',
'replay-macos',
]);
});
test('an iOS replay script and the iOS smoke files own the iOS lanes', () => {
for (const file of [
'test/integration/replays/ios/simulator/01-settings.ad',
'test/integration/replays/ios/fixture/02-checkout-release.ad',
'test/integration/smoke-ios-simulator.test.ts',
'test/integration/ios-simulator-e2e/live-runner.ts',
'test/integration/ios-simulator-e2e-cleanup.test.ts',
]) {
assert.deepEqual(lanes(file), [...IOS], file);
}
});
test('the macOS coverage manifest selects its executable gate and macOS replay lane', () => {
assert.deepEqual(lanes('test/integration/smoke-macos-coverage.test.ts'), [
'macos-coverage',
'replay-macos',
]);
assert.deepEqual(lanes('test/integration/macos-e2e/coverage-manifest.ts'), [
'macos-coverage',
'replay-macos',
]);
});
test('shared runtime surface owns every device lane', () => {
for (const file of [
'src/daemon/handlers/session.ts',
'packages/kernel/src/errors.ts',
'src/daemon/android-system-dialog.ts', // naming convention in a shared dir, not a boundary
'test/integration/smoke-daemon-clean.test.ts',
'src/platforms/install-source.ts',
]) {
assert.equal(deviceLaneLeaf(file), 'shared', file);
assert.deepEqual(lanes(file), [
'web-smoke',
'replay-ios',
'replay-ios-device',
'replay-macos',
'replay-linux',
'replay-android',
]);
}
});
test('another family owns only its own lanes, so an Android-only change carries no iOS check', () => {
assert.deepEqual(lanes('src/platforms/android/perf.ts'), ['replay-android']);
assert.deepEqual(lanes('packages/platform-android/src/inventory.ts'), ['replay-android']);
assert.deepEqual(lanes('android/snapshot-helper/src/main/java/X.java'), [
'android-helpers',
'replay-android',
]);
assert.deepEqual(lanes('test/integration/replays/android/emulator/01-settings.ad'), [
'replay-android',
]);
assert.deepEqual(lanes('test/integration/smoke-android-emulator.test.ts'), ['replay-android']);
assert.deepEqual(lanes('test/integration/android-emulator-e2e/live-runner.ts'), [
'replay-android',
]);
assert.deepEqual(lanes('src/platforms/linux/snapshot.ts'), ['replay-linux']);
assert.deepEqual(lanes('linux/atspi-dump.py'), ['replay-linux']);
assert.deepEqual(lanes('src/platforms/web/provider.ts'), ['web-smoke']);
assert.deepEqual(lanes('test/integration/smoke-web-platform.test.ts'), ['web-smoke']);
// Families with no CI lane fall through to the static gates only.
assert.deepEqual(lanes('src/platforms/harmonyos/hdc.ts'), []);
assert.deepEqual(lanes('packages/platform-vega/src/index.ts'), []);
});
test('the fixture app owns the mobile lanes whichever subtree changes', () => {
assert.deepEqual(lanes('examples/test-app/app/index.tsx'), [
'replay-ios',
'replay-ios-device',
'replay-android',
]);
assert.equal(deviceLaneLeaf('examples/test-app/modules/lab/android/build.gradle'), 'fixture-app');
});
test('unit tests under src/ and packages/*/src own no lane', () => {
for (const file of [
'src/daemon/selectors.test.ts',
'src/__tests__/contracts/interaction-guarantees.test.ts',
'src/platforms/apple/__tests__/apps.test.ts',
'packages/platform-apple/src/runtime.test.ts',
]) {
assert.ok(isUnitTest(file), file);
assert.ok(!isDeviceLaneSurface(file), file);
assert.deepEqual(lanes(file), [], file);
}
// Non-TypeScript under __tests__ is a fixture the selector cannot place, not a unit test.
assert.ok(!isUnitTest('src/__tests__/test-utils/android-ime-capture.raw.json'));
// Package tests outside src/ have no owner and keep failing open.
assert.ok(!isUnitTest('packages/maestro/test/conformance/verify.test.ts'));
assert.equal(
selectChecks({ changedFiles: ['packages/maestro/test/conformance/verify.test.ts'] }).failOpen,
true,
);
});
test('a mixed tree is shared, and two Apple leaves are still Apple', () => {
assert.equal(deviceLaneLeaf('src/platforms/apple/os/macos/x.ts'), 'apple');
assert.equal(deviceLaneLeaf('test/integration/android-emulator-e2e/ios/x.ts'), 'shared');
assert.deepEqual(deviceLanesFor('src/platforms/apple/os/macos/x.ts').lanes, [
'replay-ios',
'replay-ios-device',
'replay-macos',
]);
});
test('the surface never narrows a file the selector could not otherwise place', () => {
for (const file of [
'src/global.d.ts',
'src/foo.json',
'test/integration/ios-simulator-e2e/a.png',
]) {
assert.ok(!isDeviceLaneSurface(file), file);
assert.equal(selectChecks({ changedFiles: [file] }).failOpen, true, file);
}
});
test('a golden table owns the parity unit test and both runner builds', () => {
const plan = selectChecks({ changedFiles: ['contracts/fixtures/tap-point-policy.json'] });
assert.equal(plan.failOpen, false);
for (const id of ['unit', 'swift-runner-ios', 'swift-runner-macos'] as const) {
assert.ok(plan.checks.includes(id), id);
}
assert.ok(plan.reasons.some((reason) => reason.rule === 'own:golden-table'));
});
test('a tooling change beside an Android-only change still fails open to the full set', () => {
for (const tooling of [
'.github/workflows/ios.yml',
'.github/actions/setup-apple-runner-build/action.yml',
'package.json',
'pnpm-lock.yaml',
'tsconfig.json',
'vitest.config.ts',
'scripts/check-affected/device-lanes.ts',
'packages/platform-android/package.json',
]) {
const plan = selectChecks({ changedFiles: ['src/platforms/android/perf.ts', tooling] });
assert.equal(plan.failOpen, true, tooling);
assert.ok(plan.checks.includes('swift-runner-ios'), tooling);
assert.ok(plan.checks.includes('replay-ios'), tooling);
}
});