Add a real iOS Safari acceptance harness and documentation for terminal verification gates. - Add an `ios:acceptance` script with check, dry-run, and real WebDriver session modes. - Support BrowserStack, Sauce Labs, and LambdaTest credential discovery with redacted capability planning. - Document the real-iOS provisioning workflow and link it from testing docs. - Cover credential selection, URL validation, capability shaping, and CLI behavior with node tests. Files changed: docs/README.md | 1 + docs/ios-acceptance.md | 144 ++++++++++++++++ docs/testing.md | 3 + package.json | 1 + scripts/__tests__/ios-acceptance.test.mjs | 131 +++++++++++++++ scripts/ios-acceptance.mjs | 264 ++++++++++++++++++++++++++++++ scripts/lib/ios-acceptance.mjs | 243 +++++++++++++++++++++++++++ 7 files changed, 787 insertions(+) Fusion-Task-Id: FN-6667 Fusion-Task-Lineage: 9eee6dbe-646e-4fff-a1da-fd59cdd2cb59
8.4 KiB
Real iOS Safari acceptance surface
Purpose
The mobile xterm wide-glyph defect recurred across FN-6390 → FN-6424 → FN-6603 → FN-6638 → FN-6659. Each fix shipped without a real-iOS reproduction because the execution environment had no BrowserStack, Sauce Labs, LambdaTest, or physical-device surface. FN-6641 and FN-6662 therefore had to treat the real-device gate as unavailable instead of verified.
scripts/ios-acceptance.mjs is the reachable-surface plumbing for future terminal acceptance gates:
--checkreports whether real-iOS cloud credentials are present and exits0only when a provider is usable.--dry-runprints the redacted provider/capability plan without opening a network session.- Session mode opens a real iOS Safari W3C WebDriver session, navigates to a served Fusion dashboard URL, captures a PNG screenshot, and always deletes the cloud session in
finally.
The harness is intentionally dependency-light: it uses built-in fetch and does not install Selenium, WebdriverIO, Appium, or provider CLIs.
Real-device options
Option A — physical iPhone or iPad
Use a current iPhone or iPad running Safari with macOS Safari remote Web Inspector:
- Serve the built dashboard on a reachable free port. Use
--port 0or another free port; never use port 4040, which is reserved for the production dashboard. - Open the URL on the physical device.
- In macOS Safari, enable Develop menu and choose Develop → device → page.
- Capture screenshots and measure terminal cell widths through Web Inspector.
This path does not use scripts/ios-acceptance.mjs session mode, but the --check probe should still return non-zero unless cloud credentials are also present. A human verifier records the physical-device evidence in the task document.
Option B — real-iOS cloud WebDriver
Supply exactly one complete credential pair for a supported provider. If multiple pairs are present, the harness chooses BrowserStack → Sauce Labs → LambdaTest.
| Provider | Credential keys | Default hub URL |
|---|---|---|
| BrowserStack | BROWSERSTACK_USERNAME, BROWSERSTACK_ACCESS_KEY |
https://hub-cloud.browserstack.com/wd/hub (upstream-pending-verification) |
| Sauce Labs | SAUCE_USERNAME, SAUCE_ACCESS_KEY |
https://ondemand.us-west-1.saucelabs.com/wd/hub (upstream-pending-verification) |
| LambdaTest | LT_USERNAME, LT_ACCESS_KEY |
https://mobile-hub.lambdatest.com/wd/hub (upstream-pending-verification) |
Hub base URLs are region-configurable:
BROWSERSTACK_HUB_URLSAUCE_HUB_URLLT_HUB_URL
Device defaults are intentionally conservative and may be overridden without code changes:
- BrowserStack:
BROWSERSTACK_IOS_DEVICE,BROWSERSTACK_IOS_VERSION - Sauce Labs:
SAUCE_IOS_DEVICE,SAUCE_IOS_VERSION - LambdaTest:
LT_IOS_DEVICE,LT_IOS_VERSION
The default capability target is real iOS Safari on iPhone 15 / iOS 17; provider-specific options set real-device flags (realMobile, realDevice, or isRealMobile). Do not replace this with Playwright, desktop WebKit, jsdom, or an iOS simulator for terminal acceptance.
Storing credentials safely
Secret values must never be committed, logged, attached, or written into task documents.
Recommended Fusion setup:
- Store each provider credential as a project secret with access policy appropriate for the operator (
autofor unattended gates,promptfor manual approval,denywhen not exportable). - Mark gate credentials
env_exportable=trueand setenv_export_keyto the exact env var name, for exampleBROWSERSTACK_USERNAME. - Enable project
secretsEnv.enabled=trueso task worktrees receive a gitignored.envfile with the materialized keys. - Keep
secretsEnv.requireGitignored=trueso plaintext is never written to a tracked path.
If environment materialization is unavailable, an operator or agent can fall back to fn_secret_get for these exact keys (project scope first, then global) and export them only for the acceptance command. The harness prints key names and missing-key lists, never plaintext values.
Harness usage
Probe availability for FN-6662-style gates:
pnpm ios:acceptance -- --check
# or
node scripts/ios-acceptance.mjs --check
- Exit
0: at least one complete cloud credential pair is present; run the real-iOS gate. - Non-zero: no cloud provider is complete. Record the missing keys and close the observational gate with:
NO-OP: real-iOS surface unavailable — credentials missing, cannot run acceptance gate
Inspect a redacted plan without network access:
BROWSERSTACK_USERNAME=... BROWSERSTACK_ACCESS_KEY=... \
pnpm ios:acceptance -- --dry-run --provider browserstack
Run a real session and capture evidence:
# Serve the dashboard on a free, reachable, non-4040 port first.
DASHBOARD_URL="https://reachable.example.test" \
pnpm ios:acceptance -- --url "$DASHBOARD_URL" --out screenshots/ios-acceptance.png
The JSON result includes provider, device, platformVersion, sessionId, and screenshotPath. The screenshot is a PNG decoded from the WebDriver /screenshot response. Authenticated hub URLs and Authorization headers are never printed.
Serving the dashboard for cloud access
Build and serve the dashboard from the verification worktree, then make it reachable to the selected real-iOS surface:
pnpm build
# Use the project serve/dev command appropriate for the gate and choose --port 0 or a known free non-4040 port.
For cloud devices, use the provider's documented tunnel, a public preview URL, or another approved remote-access path. The harness does not start tunnels or download provider binaries; it only talks to the hosted WebDriver hub over HTTPS.
External Integration Evidence
This harness integrates hosted SaaS WebDriver hubs over W3C WebDriver using built-in fetch; no provider binary is downloaded or executed locally, so checksums are not applicable.
- BrowserStack Automate / Live
- Canonical upstream repo URL: https://github.com/browserstack/browserstack-local-nodejs
- Docs / homepage URL: https://www.browserstack.com/docs/automate (Live: https://www.browserstack.com/live)
- Release / download URL: https://github.com/browserstack/browserstack-local-nodejs/releases/latest —
upstream-pending-verification - WebDriver hub (default, env-overridable via
BROWSERSTACK_HUB_URL):https://hub-cloud.browserstack.com/wd/hub—upstream-pending-verification - Binary / CLI name: N/A for this harness (
fetch-based W3C hub over HTTPS); reference client binarybrowserstack-local - Credential keys:
BROWSERSTACK_USERNAME,BROWSERSTACK_ACCESS_KEY - Checksum: N/A (hosted service, no downloadable artifact bundled)
- Sauce Labs Real Device Cloud
- Canonical upstream repo URL: https://github.com/saucelabs/saucectl
- Docs / homepage URL: https://docs.saucelabs.com (Real Device Cloud: https://saucelabs.com/platform/real-device-cloud)
- Release / download URL: https://github.com/saucelabs/saucectl/releases/latest —
upstream-pending-verification - WebDriver hub (default, env-overridable via
SAUCE_HUB_URL):https://ondemand.us-west-1.saucelabs.com/wd/hub—upstream-pending-verification - Binary / CLI name: N/A for this harness (
fetch-based W3C hub over HTTPS); reference CLIsaucectl - Credential keys:
SAUCE_USERNAME,SAUCE_ACCESS_KEY - Checksum: N/A (hosted service, no downloadable artifact bundled)
- LambdaTest Real Time / Real Device
- Canonical upstream repo URL: https://github.com/LambdaTest/LT
- Docs / homepage URL: https://www.lambdatest.com/support/docs/ (Real Time: https://www.lambdatest.com/real-time-browser-testing)
- Release / download URL: https://github.com/LambdaTest/LT/releases/latest —
upstream-pending-verification - WebDriver hub (default, env-overridable via
LT_HUB_URL):https://mobile-hub.lambdatest.com/wd/hub—upstream-pending-verification - Binary / CLI name: N/A for this harness (
fetch-based W3C hub over HTTPS); reference tunnel binaryLT - Credential keys:
LT_USERNAME,LT_ACCESS_KEY - Checksum: N/A (hosted service, no downloadable artifact bundled)