Skip to content

Commit 2a9a4ee

Browse files
authored
test: add Linux platform command coverage manifest (#1921)
* test: add Linux platform command coverage manifest * test: address platform coverage review feedback
1 parent 96afa9d commit 2a9a4ee

6 files changed

Lines changed: 413 additions & 71 deletions

File tree

.github/workflows/ios.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ on:
4545
- 'test/integration/replays/macos/**'
4646
- 'test/integration/android-**'
4747
- 'test/integration/smoke-android-**'
48+
- 'test/integration/smoke-linux-**'
49+
- 'test/integration/linux-e2e/**'
4850
- 'test/integration/smoke-web-**'
4951
- 'test/integration/web-e2e/**'
5052
push:

test/integration/android-emulator-e2e/coverage-manifest.ts

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { PUBLIC_COMMANDS } from '../../../src/command-catalog.ts';
22
import { ANDROID_AUDIO_CONTRACT_EVIDENCE } from '../../../src/daemon/handlers/__tests__/session-audio.coverage.ts';
33
import { ANDROID_INSTALL_SOURCE_CONTRACT_EVIDENCE } from '../../../src/platforms/__tests__/install-source.coverage.ts';
44
import { ANDROID_LIFECYCLE_CONTRACT_EVIDENCE } from '../provider-scenarios/android-lifecycle.coverage.ts';
5+
import { buildCoverageClassificationSummary } from '../support/coverage-classification.ts';
56
import {
67
defineAndroidContractEvidence,
78
type AndroidContractEvidence,
@@ -18,14 +19,6 @@ export type AndroidEmulatorCoverageEntry =
1819
}
1920
| { assertion: string; level: 'capability-denial' };
2021

21-
export type AndroidEmulatorCoverageClassificationSummary = {
22-
capabilityDenial: number;
23-
contract: number;
24-
gap: number;
25-
live: number;
26-
total: number;
27-
};
28-
2922
const C = PUBLIC_COMMANDS;
3023
const live = (scenario: string, assertion: string): AndroidEmulatorCoverageEntry => ({
3124
assertion,
@@ -220,29 +213,3 @@ export function liveCommandsForScenario(scenarioId: string): PublicCommand[] {
220213
.filter(([, entry]) => entry.level === 'live' && entry.scenario === scenarioId)
221214
.map(([command]) => command as PublicCommand);
222215
}
223-
224-
function buildCoverageClassificationSummary(
225-
entries: readonly AndroidEmulatorCoverageEntry[],
226-
): AndroidEmulatorCoverageClassificationSummary {
227-
const summary: AndroidEmulatorCoverageClassificationSummary = {
228-
capabilityDenial: 0,
229-
contract: 0,
230-
gap: 0,
231-
live: 0,
232-
total: entries.length,
233-
};
234-
for (const entry of entries) {
235-
switch (entry.level) {
236-
case 'live':
237-
summary.live += 1;
238-
break;
239-
case 'command-contract':
240-
summary.contract += 1;
241-
break;
242-
case 'capability-denial':
243-
summary.capabilityDenial += 1;
244-
break;
245-
}
246-
}
247-
return summary;
248-
}
Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
import { PUBLIC_COMMANDS } from '../../../src/command-catalog.ts';
2+
import { buildCoverageClassificationSummary } from '../support/coverage-classification.ts';
3+
4+
type PublicCommand = (typeof PUBLIC_COMMANDS)[keyof typeof PUBLIC_COMMANDS];
5+
6+
type RepositoryEvidence = {
7+
path: string;
8+
test: string;
9+
};
10+
11+
type CapabilityDeclarationEvidence = RepositoryEvidence & {
12+
declaration: string;
13+
};
14+
15+
export type LinuxPlatformCoverageEntry =
16+
| {
17+
assertion: string;
18+
level: 'live' | 'command-contract';
19+
owner: RepositoryEvidence;
20+
}
21+
| {
22+
assertion: string;
23+
level: 'capability-denial';
24+
owner: CapabilityDeclarationEvidence;
25+
}
26+
| {
27+
assertion: string;
28+
level: 'known-gap';
29+
trackingIssue: number;
30+
};
31+
32+
export const LINUX_COVERAGE_GAP_ISSUE = 1915;
33+
34+
export const LINUX_REPLAY_EVIDENCE: RepositoryEvidence = {
35+
path: 'test/integration/replays/linux/01-desktop-smoke.ad',
36+
test: '# Smoke test for Linux desktop automation on CI.',
37+
};
38+
39+
const LINUX_PROVIDER_EVIDENCE: RepositoryEvidence = {
40+
path: 'test/integration/provider-scenarios/linux-desktop.test.ts',
41+
test: 'Provider-backed integration Linux desktop flow uses semantic desktop and input providers',
42+
};
43+
44+
const LINUX_RUNTIME_EVIDENCE: RepositoryEvidence = {
45+
path: 'packages/platform-linux/src/runtime.test.ts',
46+
test: 'classifies the Linux $name lifecycle denominator against the legacy dispatch cell',
47+
};
48+
49+
const LINUX_CAPABILITY_DECLARATION_PATH = 'src/core/command-descriptor/registry.ts';
50+
const LINUX_CAPABILITY_DECLARATION = 'linux: LINUX_NONE';
51+
52+
const C = PUBLIC_COMMANDS;
53+
const live = (assertion: string): LinuxPlatformCoverageEntry => ({
54+
assertion,
55+
level: 'live',
56+
owner: LINUX_REPLAY_EVIDENCE,
57+
});
58+
const contract = (path: string, test: string, assertion: string): LinuxPlatformCoverageEntry => ({
59+
assertion,
60+
level: 'command-contract',
61+
owner: { path, test },
62+
});
63+
const denial = (command: string, assertion: string): LinuxPlatformCoverageEntry => ({
64+
assertion,
65+
level: 'capability-denial',
66+
owner: {
67+
path: LINUX_CAPABILITY_DECLARATION_PATH,
68+
test: `name: '${command}'`,
69+
declaration: LINUX_CAPABILITY_DECLARATION,
70+
},
71+
});
72+
const gap = (assertion: string): LinuxPlatformCoverageEntry => ({
73+
assertion,
74+
level: 'known-gap',
75+
trackingIssue: LINUX_COVERAGE_GAP_ISSUE,
76+
});
77+
78+
/**
79+
* One primary, observable owner for every public command on the Linux desktop.
80+
*
81+
* Live rows are limited to the existing Linux replay. Contract rows cite the
82+
* existing provider scenario or dedicated Linux unit/runtime evidence; they do
83+
* not turn mocked provider calls into live desktop claims. Capability denials
84+
* are derived from the owning command-descriptor matrix. Known gaps are
85+
* explicit follow-up work, not an implicit claim that a generic command works.
86+
*/
87+
export const LINUX_PLATFORM_COVERAGE = {
88+
[C.artifacts]: gap('No Linux-specific artifact inventory command evidence exists yet'),
89+
[C.devices]: contract(
90+
LINUX_PROVIDER_EVIDENCE.path,
91+
LINUX_PROVIDER_EVIDENCE.test,
92+
'Linux provider scenario inventories the selected desktop device through the daemon client',
93+
),
94+
[C.capabilities]: gap('No Linux-specific capabilities command evidence exists yet'),
95+
[C.doctor]: gap('No Linux-specific doctor command evidence exists yet'),
96+
[C.apps]: contract(
97+
LINUX_RUNTIME_EVIDENCE.path,
98+
LINUX_RUNTIME_EVIDENCE.test,
99+
'Linux runtime facts explicitly report native app inventory unavailable',
100+
),
101+
[C.boot]: contract(
102+
LINUX_RUNTIME_EVIDENCE.path,
103+
LINUX_RUNTIME_EVIDENCE.test,
104+
'Linux runtime facts explicitly report boot unavailable for the desktop owner',
105+
),
106+
[C.shutdown]: gap('No Linux-specific shutdown command evidence exists yet'),
107+
[C.appState]: contract(
108+
LINUX_RUNTIME_EVIDENCE.path,
109+
LINUX_RUNTIME_EVIDENCE.test,
110+
'Linux runtime facts explicitly report app state unavailable',
111+
),
112+
[C.perf]: denial('perf', 'Linux capability declaration rejects native performance inspection'),
113+
[C.logs]: gap('No Linux-specific app-log command evidence exists yet'),
114+
[C.events]: gap('No Linux-specific session event command evidence exists yet'),
115+
[C.network]: contract(
116+
LINUX_RUNTIME_EVIDENCE.path,
117+
LINUX_RUNTIME_EVIDENCE.test,
118+
'Linux runtime facts explicitly report network capture unavailable',
119+
),
120+
[C.audio]: denial('audio', 'Linux capability declaration rejects native audio probing'),
121+
[C.replay]: gap('No Linux-specific replay command evidence exists yet'),
122+
[C.test]: gap('No Linux-specific test-suite command evidence exists yet'),
123+
[C.clipboard]: contract(
124+
'src/platforms/linux/__tests__/clipboard.test.ts',
125+
'writeLinuxClipboard uses xclip with stdin on X11',
126+
'Linux clipboard writes through the supported X11 host-tool seam',
127+
),
128+
[C.keyboard]: denial('keyboard', 'Linux capability declaration rejects native keyboard control'),
129+
[C.install]: gap('No Linux-specific application installation command evidence exists yet'),
130+
[C.reinstall]: gap('No Linux-specific application reinstallation command evidence exists yet'),
131+
[C.push]: gap('No Linux-specific push delivery command evidence exists yet'),
132+
[C.triggerAppEvent]: denial(
133+
'trigger-app-event',
134+
'Linux capability declaration rejects native application event delivery',
135+
),
136+
[C.open]: live('the existing Linux replay opens gnome-calculator'),
137+
[C.prepare]: contract(
138+
LINUX_RUNTIME_EVIDENCE.path,
139+
LINUX_RUNTIME_EVIDENCE.test,
140+
'Linux runtime facts explicitly report Apple runner preparation unavailable',
141+
),
142+
[C.batch]: gap('No Linux-specific batch command evidence exists yet'),
143+
[C.close]: contract(
144+
LINUX_PROVIDER_EVIDENCE.path,
145+
LINUX_PROVIDER_EVIDENCE.test,
146+
'Linux provider scenario closes the calculator and observes the desktop close call',
147+
),
148+
[C.snapshot]: live('the existing Linux replay captures the calculator accessibility tree'),
149+
[C.diff]: gap('No Linux-specific snapshot diff command evidence exists yet'),
150+
[C.wait]: live('the existing Linux replay waits for an observable calculator landmark'),
151+
[C.alert]: denial('alert', 'Linux capability declaration rejects native alert operations'),
152+
[C.settings]: denial(
153+
'settings',
154+
'Linux capability declaration rejects native device settings operations',
155+
),
156+
[C.reactNative]: denial(
157+
'react-native',
158+
'Linux capability declaration rejects React Native inspection',
159+
),
160+
[C.record]: gap('No Linux-specific recording command evidence exists yet'),
161+
[C.trace]: gap('No Linux-specific trace command evidence exists yet'),
162+
[C.find]: gap('No Linux-specific find command evidence exists yet'),
163+
[C.click]: contract(
164+
LINUX_PROVIDER_EVIDENCE.path,
165+
LINUX_PROVIDER_EVIDENCE.test,
166+
'Linux provider scenario executes primary, secondary, middle, and double clicks',
167+
),
168+
[C.fill]: contract(
169+
LINUX_PROVIDER_EVIDENCE.path,
170+
LINUX_PROVIDER_EVIDENCE.test,
171+
'Linux provider scenario fills both a snapshot ref and coordinate target',
172+
),
173+
[C.longPress]: contract(
174+
LINUX_PROVIDER_EVIDENCE.path,
175+
LINUX_PROVIDER_EVIDENCE.test,
176+
'Linux provider scenario executes a coordinate long press',
177+
),
178+
[C.hover]: denial('hover', 'Linux capability declaration rejects pointer-only hover input'),
179+
[C.press]: contract(
180+
LINUX_PROVIDER_EVIDENCE.path,
181+
LINUX_PROVIDER_EVIDENCE.test,
182+
'Linux provider scenario presses a snapshot ref and coordinate target',
183+
),
184+
[C.type]: contract(
185+
'src/platforms/linux/__tests__/input-actions.test.ts',
186+
'typeLinux uses ydotool type',
187+
'Linux type dispatch uses the Wayland ydotool type primitive',
188+
),
189+
[C.get]: contract(
190+
LINUX_PROVIDER_EVIDENCE.path,
191+
LINUX_PROVIDER_EVIDENCE.test,
192+
'Linux provider scenario reads the pressed snapshot ref text',
193+
),
194+
[C.is]: live('the existing Linux replay verifies a calculator landmark exists'),
195+
[C.back]: contract(
196+
LINUX_PROVIDER_EVIDENCE.path,
197+
LINUX_PROVIDER_EVIDENCE.test,
198+
'Linux provider scenario dispatches Alt+Left through the semantic input provider',
199+
),
200+
[C.gesture]: contract(
201+
LINUX_PROVIDER_EVIDENCE.path,
202+
LINUX_PROVIDER_EVIDENCE.test,
203+
'Linux provider scenario executes a single-pointer pan through the semantic drag provider',
204+
),
205+
[C.home]: contract(
206+
LINUX_PROVIDER_EVIDENCE.path,
207+
LINUX_PROVIDER_EVIDENCE.test,
208+
'Linux provider scenario dispatches Super+D through the semantic input provider',
209+
),
210+
[C.tvRemote]: denial('tv-remote', 'Linux capability declaration rejects TV remote input'),
211+
[C.orientation]: denial(
212+
'orientation',
213+
'Linux capability declaration rejects native orientation changes',
214+
),
215+
[C.scroll]: contract(
216+
'src/platforms/linux/__tests__/input-actions.test.ts',
217+
'scrollLinux uses ydotool mousemove --wheel for vertical scroll',
218+
'Linux scroll dispatch uses the Wayland ydotool wheel primitive',
219+
),
220+
[C.swipe]: gap('No Linux-specific public swipe command evidence exists yet'),
221+
[C.focus]: contract(
222+
LINUX_PROVIDER_EVIDENCE.path,
223+
LINUX_PROVIDER_EVIDENCE.test,
224+
'Linux provider scenario focuses a coordinate target',
225+
),
226+
[C.screenshot]: live('the existing Linux replay creates a screenshot artifact'),
227+
[C.viewport]: contract(
228+
LINUX_RUNTIME_EVIDENCE.path,
229+
LINUX_RUNTIME_EVIDENCE.test,
230+
'Linux runtime facts explicitly report viewport changes unavailable',
231+
),
232+
[C.appSwitcher]: denial(
233+
'app-switcher',
234+
'Linux capability declaration rejects native app-switcher navigation',
235+
),
236+
[C.installFromSource]: gap('No Linux-specific source-install command evidence exists yet'),
237+
} satisfies Record<PublicCommand, LinuxPlatformCoverageEntry>;
238+
239+
export const LINUX_PLATFORM_COVERAGE_CLASSIFICATION_SUMMARY = buildCoverageClassificationSummary(
240+
Object.values(LINUX_PLATFORM_COVERAGE),
241+
);
242+
243+
export function liveCommandsForLinuxReplay(): PublicCommand[] {
244+
return Object.entries(LINUX_PLATFORM_COVERAGE)
245+
.filter(([, entry]) => entry.level === 'live')
246+
.map(([command]) => command as PublicCommand);
247+
}

0 commit comments

Comments
 (0)