Skip to content

Desktop testing: declare and select WDIO cases by input lane, platform and scope - #4464

Merged
Jason Morse (JasonVMo) merged 3 commits into
mainfrom
user/jasonvmo/input-selection
Nov 7, 2026
Merged

Jason Morse (JasonVMo) merged 3 commits into
mainfrom
user/jasonvmo/input-selection

Conversation

@JasonVMo

Copy link
Copy Markdown
Contributor

Platforms Impacted

  • iOS
  • macOS
  • win32 (Office)
  • windows
  • android

Description of changes

Part 1 of 3 in a planned sequence for controlling and assessing physical and accessible input in desktop tests. WDIO cases now declare how they run, and a run selects the cases that apply to its input lane, platform and scope. This is test tooling only: no product or native code and no CI workflow changes. The follow-ups are separate PRs: migrate the remaining story callbacks and replace their skip gates, split CI into accessible and physical lanes, then enforce and attribute input policy in the session.

Related: #4349 and #4431 (Win32 Storybook accessibility and physical-input CI lanes). This PR changes no workflow, so lane CI is left to the follow-ups.

Declaring a case. desktopIt(name, descriptor?, run) declares a Storybook case. desktopIt and desktopDescribe from @fluentui-react-native/desktop-test/jasmine declare WebdriverIO Jasmine specs. The descriptor is a strict static literal:

Field Meaning
requires Host capabilities the case needs. They derive its input lane.
input accessible, physical or both. Defaults to what requires derives, else both, and can only narrow a derived both.
platforms Endpoints (macos, windows, win32) as an allowlist or a ! negation list, never mixed. Omitted means all.
scope Keyed custom values such as { 'rn.renderer': ['fabric'] }. Consumers add their own keys through the desktop config's testScopes and testScope.
unsupported, quarantine Declared gaps with a reason and issue (and an expires date for quarantine) that replace run-time skip. An expired quarantine fails the run.

keyboard, physical-click and wheel derive physical, accessibility-click derives accessible, and the rest derive both. The new click requirement is lane-neutral: element.click() is an accessibility click in the accessible lane and a physical click in the physical lane.

Selecting and accounting.

  • storybook test, driver and smoke take --input accessible or --input physical. Without the flag the lane comes from DESKTOP_INPUT, then from the driver a test attaches to. With no lane, every case runs as before (compatibility mode).
  • Selection order is platform, scope, input, then declared gaps. Excluded cases are not tests: they are counted in the selection totals and listed by test --list with their first reason.
  • The accessible lane masks keyboard, physical click and wheel at the host. test --input accessible stops as an infrastructure failure when an attached driver does not report all three as unavailable.
  • A lane run is incomplete, not passed, when it has a run-time skip, an undeclared unsupported case, an empty selection or nothing executed. A failure outranks incomplete.
  • Extraction rejects browser.keys, setValue, addValue, clearValue and key, pointer or wheel actions in any case that can run in the accessible lane, unless the case declares the matching requirement.

By package.

  • desktop-driver: descriptor types and validation (authoring/input), pure selection and click-mode resolution (authoring/selection), the requirement preflight, and the union of configured and environment input masks in NativeDesktopHost. The new authoring/input export is a leaf with only type imports, so config-loading code can use it from source.
  • desktop-test: lane-aware reporting and run summaries (reporting/lane), the Jasmine adapter (./jasmine), --input, and validated testScopes and testScope.
  • storybook-desktop: --input on the CLI, manifest cases extraction, selection and lane verdicts (testing/selection, testing/laneVerdict), the direct-call check, and the desktopIt helper.
  • native-core: the Callout, legacy Callout and FocusZone story tests use desktopIt (22 cases). All 20 run-time skip( calls become requires and declared gaps, such as the Win32 Tab-exit gap (Components: Add popup-family transactions and owner-relative focus restoration #4377).
  • apps/E2E: ButtonV1.spec.win.ts is migrated as the Jasmine pilot.
  • References, READMEs and two patch changesets (desktop-driver, desktop-test and storybook-desktop together; native-core).

Known limits.

  • Hosted macOS keeps running without a lane (compatibility mode): it masks only physical click, and an accessible-only lane would drop keyboard coverage that passes there today. --input accessible works on a managed Mac, and macOS lanes are a follow-up.
  • A delegated report session (DESKTOP_REPORT_CONTEXT) ignores the parent's lane option and enforces its own cohort.
  • The direct-call check reads callbacks only. Input hidden behind a helper is caught at run time by the accessible-lane host mask.
  • rn.renderer is not re-verified against the session's reported renderer.
  • A desktop-test lane run against the unmigrated apps/E2E specs stops and lists the undeclared specs until they migrate.
  • --input all is not implemented.

Review order: authoring/input.ts and authoring/selection.ts in desktop-driver, then reporting/lane.ts in desktop-test and testing/selection.ts in storybook-desktop. The rest follows from them.

Verification

Automated, in each changed workspace (desktop-driver, desktop-test, storybook-desktop, desktop-driver-mcp, native-core, apps/E2E):

  • yarn build and yarn lint: passed in all six.
  • yarn format: passed in desktop-driver, desktop-test, storybook-desktop and native-core.
  • yarn test: passed. desktop-driver 842 tests (61 skipped), desktop-test 168, storybook-desktop 285 (2 skipped), desktop-driver-mcp 26, native-core 56, apps/E2E 7. The runs include the real-WDIO lane contracts against a fake host (contracts in desktop-test, wdioRunner in storybook-desktop).

From the repository root:

  • yarn oxfmt --check: passed.
  • yarn check-agent-instructions: passed.
  • yarn lage test-links: passed, 90 tasks, 0 failed.
  • yarn change:check: passed.
  • yarn clean-lage-cache, then yarn lage buildci: passed, 178 tasks, 0 failed.

Not run: native or physical-input runs against a real app and driver, and hosted CI for lane runs (this PR changes no workflow). The contracts use a fake host, so they are not native qualification.

Before After
Story tests feature-check inside the callback and call skip(reason) at run time. A run cannot select by input modality, platform or scope. Cases declare requires, platforms, scope and known gaps. --input accessible or --input physical selects them, masks the host for the accessible lane and reports what it excluded.

Pull request checklist

This PR has considered (when applicable):

  • Automated Tests
  • Documentation and examples
  • Keyboard Accessibility
  • Voiceover
  • Internationalization and Right-to-left Layouts

Keyboard accessibility, VoiceOver and internationalization do not apply: there are no product UI or native behavior changes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Finish part 1 of the input-lane work started in f5a90cd. Cases declare
how they run with desktopIt, and a run selects the cases that apply to its
input lane, platform and scope and accounts for everything it excludes.

desktop-driver
- Add pure case selection and click-mode resolution, and move the
  requirement preflight and click-mode helpers here.
- Add the authoring/input leaf export so config-loading code can import
  scope helpers from source without the authoring index.

desktop-test
- Report the lane: a lane run is incomplete when it has skipped or
  undeclared-unsupported results, an empty selection or nothing executed.
- Add the Jasmine adapter (desktop-test/jasmine) with desktopIt and
  desktopDescribe, plus config-level test scopes and --input.

storybook-desktop
- Add --input accessible|physical to storybook test, driver and smoke.
  The lane comes from the flag, DESKTOP_INPUT or the attached driver.
- Select cases before they run, resolve declared gaps, assess each
  cohort, and reject direct input calls in declared cases at extraction.
- Fail closed when an accessible lane attaches to a driver that does not
  mask keyboard, physical click and wheel input.

native-core and apps/E2E
- Migrate the native-core Callout and FocusZone tests and
  ButtonV1.spec.win.ts to desktopIt.

Update the package references and add patch changesets.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

github-actions Bot commented Nov 7, 2026

Copy link
Copy Markdown
Contributor

Bundle size report

Tree-shaken, minified production esbuild bundles with React and React Native runtimes externalized.

Scenario Modules-Mac (Δ) Modules-Win (Δ) Size-Mac (Δ) Size-Win (Δ)
components-button 79 (+1) 80 (+1) 72.78k (-842b) 72.71k (-842b)
components-catalog 228 (+1) 229 (+1) 228.46k (-855b) 228.38k (-855b)
design-themed-root 55 (+4) 56 (+4) 56.26k (+998b) 56.18k (+998b)
design-color-lib 6 (+0) 6 (+0) 6.27k (+0b) 6.27k (+0b)
design-theme-state-legacy-source 49 (+1) 50 (+1) 52.96k (-841b) 52.89k (-841b)
design-legacy-theme 42 (+0) 42 (+0) 39.11k (+0b) 42.91k (+0b)
design-legacy-theme-from-flex 58 (+4) 58 (+4) 60.70k (+824b) 64.51k (+822b)
design-fluent-light-theme 7 (+0) 7 (+0) 18.74k (+0b) 22.59k (+0b)
design-fluent-theme 35 (+0) 35 (+0) 27.46k (+4b) 31.25k (-1b)
design-fluent-hc-theme 32 (+0) 32 (+0) 27.34k (+0b) 31.13k (+0b)
design-flex-theme 29 (-4) 29 (-4) 14.30k (-9.07k) 14.29k (-9.07k)
design-flex-cool-theme 26 (New) 26 (New) 12.51k (New) 12.50k (New)
design-flex-warm-theme 26 (-7) 26 (-7) 12.28k (-11.15k) 12.27k (-11.15k)

The job is advisory: size changes are reported but do not fail the pull request. Bundle or analysis errors still fail.


View bundle-size workflow run

@JasonVMo
Jason Morse (JasonVMo) enabled auto-merge (squash) November 7, 2026 02:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants