Files
callstack__agent-device/scripts/__tests__/swift-conditional-compilation.test.ts
Michał Pierzchała d07b837621 test: classify the runner XCTests — pure decisions to a macOS host lane, simulator semantics gated os(iOS) (#1781 A7) (#1861)
Every declared AgentDeviceRunnerUITests method now belongs to a lane, and
the #if guard is the classification: AGENT_DEVICE_RUNNER_UNIT_TESTS alone
means a pure runner decision (runs on the macOS host on every PR — ci.yml's
existing compile job now executes the bundle it builds), '&& os(iOS)' means
runner/XCTest semantics (simulator lanes only). check:xctest-selection
evaluates the guards per platform, derives each lane's reach, and fails on
a flagged identifier that is undeclared or uncompiled on that lane, on a
declared test no lane reaches (found the two tvOS-only tests, dark since
birth — widened to os(tvOS) || os(macOS)), and on testCommand reaching any
lane. The host and nightly lanes assert executed == derived reach, so a
missing -D flag or a guard that compiles a file out reads red, not as a
smaller green. One duplicate test deleted (sparse-verdict assertions folded
into its twin).
2026-08-19 13:59:45 +02:00

70 lines
2.8 KiB
TypeScript

// The `#if` evaluator decides which platform compiles which test, so a wrong answer here
// re-buckets a test silently — which is why it refuses vocabulary it does not know instead of
// guessing, and why that refusal is asserted below alongside the precedence and nesting cases.
import { describe, expect, test } from 'vitest';
import {
activeSource,
evaluateCondition,
PLATFORMS,
UnsupportedConditionError,
type Platform,
} from '../swift-conditional-compilation.ts';
describe('the #if evaluator', () => {
test.each([
['AGENT_DEVICE_RUNNER_UNIT_TESTS', { iOS: true, macOS: true, tvOS: true }],
['os(iOS)', { iOS: true, macOS: false, tvOS: false }],
['!os(macOS)', { iOS: true, macOS: false, tvOS: true }],
['AGENT_DEVICE_RUNNER_UNIT_TESTS && os(iOS)', { iOS: true, macOS: false, tvOS: false }],
['os(tvOS) || os(macOS)', { iOS: false, macOS: true, tvOS: true }],
['os(macOS) || os(tvOS) || os(visionOS)', { iOS: false, macOS: true, tvOS: true }],
['canImport(UIKit)', { iOS: true, macOS: false, tvOS: true }],
['canImport(AppKit)', { iOS: false, macOS: true, tvOS: false }],
['os(iOS) && targetEnvironment(simulator)', { iOS: true, macOS: false, tvOS: false }],
['!(os(iOS) || os(tvOS)) // desktop', { iOS: false, macOS: true, tvOS: false }],
] as const)('%s', (condition, expected) => {
for (const platform of PLATFORMS) {
expect(evaluateCondition(condition, platform)).toBe(expected[platform]);
}
});
test('refuses vocabulary it does not know rather than guessing', () => {
for (const condition of ['swift(>=5.9)', 'canImport(SwiftUI)', 'RELEASE', 'os(iOS) &&']) {
expect(() => evaluateCondition(condition, 'iOS')).toThrow(UnsupportedConditionError);
}
expect(() => activeSource('#if compiler(>=6)\nx\n#endif\n', 'iOS', 'F.swift')).toThrow(
/F\.swift:1/,
);
});
test('blanks inactive branches, follows #elseif/#else, and nests', () => {
const text = [
'#if os(iOS)',
'ios',
'#elseif os(tvOS)',
'tv',
'#else',
'other',
' #if AGENT_DEVICE_RUNNER_UNIT_TESTS',
' nested',
' #endif',
'#endif',
'always',
].join('\n');
const kept = (platform: Platform) =>
activeSource(text, platform)
.split('\n')
.filter((line) => line.trim() !== '');
expect(kept('iOS')).toEqual(['ios', 'always']);
expect(kept('tvOS')).toEqual(['tv', 'always']);
expect(kept('macOS')).toEqual(['other', ' nested', 'always']);
});
test('a nested #if under an inactive branch stays inactive whatever it says', () => {
const text = '#if os(iOS)\n#if os(macOS) || !os(macOS)\ninner\n#endif\n#endif\n';
expect(activeSource(text, 'macOS').trim()).toBe('');
expect(activeSource(text, 'iOS').trim()).toBe('inner');
});
});