capacitor-testing
Skill75 starsChanged 32 days agoMITView on GitHub
Testing guide for Capacitor apps and plugins. Covers web-layer unit and component tests with Vitest and mocked Capacitor plugins (`vi.mock('@capacitor/core')`, `registerPlugin`), Playwright for the web build, Appium E2E with NATIVE_APP / WEBVIEW context switching, native plugin unit tests with Swift Testing vs XCTest (what can migrate, `CAPPluginCall` patterns, `xcodebuild test` on a simulator) and Android JUnit, plus an agent-driven verification loop on simulators and devices (build, install, launch, screenshot, UI hierarchy, tap, logs) with `xcrun simctl`, `xcrun devicectl`, `adb`, Xcode MCP device tools, and live reload via `npx cap run --url` (Capacitor 9) or `-l --host --port` (Capacitor 8). Use when adding tests, mocking plugins, "does it work on device", verifying a UI change on a simulator, migrating XCTest to Swift Testing, or setting up test CI. Do not use for crash log capture (ios-android-logs), WebView debugging sessions (debugging-capacitor), or build pipelines (capacitor-ci-cd).
1 other project uses a version of this.
Adopted by
Most recently taken up by
- Aver005/agent-skillstheir own version, first seen Feb 14, 2026
Other versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 1
- Aver005/agent-skills★ 2same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository56 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- capacitor-accessibilitySkill
- capacitor-app-intentsSkill
- capacitor-apple-review-preflightSkill
- capacitor-app-storeSkill
- capacitor-app-upgradesSkill
- capacitor-app-upgrade-v4-to-v5Skill
- capacitor-app-upgrade-v5-to-v6Skill
- capacitor-app-upgrade-v6-to-v7Skill
- capacitor-app-upgrade-v7-to-v8Skill
- capacitor-app-upgrade-v8-to-v9Skill
- capacitor-best-practicesSkill
- capacitor-ci-cdSkill
- capacitor-deep-linkingSkill
- capacitor-ios-resizabilitySkill
- capacitor-ios-security-hardeningSkill
- capacitor-keyboardSkill
- capacitor-mcpSkill
- capacitor-offline-firstSkill
- capacitor-performanceSkill
- capacitor-plugin-spm-supportSkill
- capacitor-pluginsSkill
- capacitor-plugin-upgradesSkill
- capacitor-plugin-upgrade-v4-to-v5Skill
- capacitor-plugin-upgrade-v5-to-v6Skill
- capacitor-plugin-upgrade-v6-to-v7Skill
- capacitor-plugin-upgrade-v7-to-v8Skill
- capacitor-plugin-upgrade-v8-to-v9Skill
- capacitor-push-notificationsSkill
- capacitor-securitySkill
- capacitor-splash-screenSkill
- capacitor-uiscene-migrationSkill
- capawesome-live-update-migrationSkill
- capgo-cli-usageSkill
- capgo-cloudSkill
- capgo-live-updatesSkill
- capgo-native-buildsSkill
- capgo-organization-managementSkill
- capgo-release-managementSkill
- capgo-release-workflowsSkill
- cocoapods-to-spmSkill
- cordova-to-capacitorSkill
- debugging-capacitorSkill
- framework-to-capacitorSkill
- ionic-appflow-migrationSkill
- ionic-designSkill
- ionic-enterprise-sdk-migrationSkill
- ios-android-logsSkill
- konsta-uiSkill
- safe-area-handlingSkill
- skill-creatorSkill
- sqlite-to-fast-sqlSkill
- subscription-app-revenueSkill
- tailwind-capacitorSkill
- webapp-to-capacitorSkill
The file
We split this skill into the rules it gives an agent
2 rules. About 0 are common, 1 is distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 37
Only load a reference when its layer is in play.
- Very specific: line 51
Inspect: Read package.json (test runner, framework, @capacitor/* versions), capacitor.config.*, existing test config (vitest.config.*, …
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Testing Capacitor Apps and Plugins
A Capacitor app has three layers to test: the web app (most logic), the native bridge and plugins (Swift/Kotlin), and the running app on a device. Pick the cheapest layer that can catch the bug.
When to Use
TRIGGER when:
- Adding unit, component or E2E tests to a Capacitor app
- Mocking Capacitor or plugin APIs in Vitest / Jest
- Writing or modernizing native unit tests for a plugin (Swift Testing, XCTest, JUnit)
- Verifying a change on a simulator, emulator or device ("test this", "does it work", "check on device")
- E2E tests that cannot find web elements in the app (WebView context)
- Setting up test jobs in CI
Do not use:
- Reading device or crash logs:
ios-android-logs - Safari Web Inspector / Chrome DevTools debugging:
debugging-capacitor - Build, signing and release pipelines:
capacitor-ci-cd - App Intents tests:
capacitor-app-intents(AppIntentsTesting)
Choose the layer
| What changed | Test with | Reference |
| Business logic, state, services that call plugins | Vitest with mocked plugins | references/web-unit-tests.md |
| Components (React, Vue, Angular, Svelte) | Testing Library on Vitest | references/web-unit-tests.md |
| Web flows (routing, forms) | Playwright against the dev server or dist | references/e2e.md |
| Plugin native code (Swift / Kotlin) | Swift Testing or XCTest; JUnit | references/native-plugin-tests.md |
| Full app on device, native UI, permissions, deep links | Agent verification loop; Appium or Maestro for repeatable suites | references/device-verification-loop.md, references/e2e.md |
| CI jobs | GitHub Actions matrix | references/ci.md |
Only load a reference when its layer is in play.
Facts that save time
- Plugins in jsdom run their web implementation, or throw
unimplementedwhen there is none.Capacitor.isNativePlatform()returnsfalsein tests unless you mock@capacitor/core. Mock at the plugin package boundary, not deep inside the app. - E2E tools see the WebView as one native element. Appium must switch to the
WEBVIEW_*context to find DOM elements. Capacitor makes the WebView inspectable in debug builds; for release builds setios.webContentsDebuggingEnabled/android.webContentsDebuggingEnabledincapacitor.config. Never ship release builds with it on by accident. - Detox is not an option. It targets React Native and does not drive Capacitor WebView content.
- Swift Testing cannot replace all XCTest. UI tests (XCUIApplication) and
measure {}performance tests stay XCTest. Unit tests can migrate one class at a time; a file can hold both. - iOS-only plugin packages cannot use
swift testbecause they depend on UIKit and Capacitor. Runxcodebuild test -scheme <Package> -destination 'platform=iOS Simulator,...'. - Capacitor 9 removed the deprecated Swift APIs. Tests that build calls with the old
CAPPluginCall(callbackId:options:success:error:)initializer orCAPPlugin(bridge:pluginId:pluginName:)must move toCAPPluginCall(callbackId:methodName:options:success:error:)and a plaininit(). - Live reload flags changed in Capacitor 9. Capacitor 9:
npx cap run ios --url http://<lan-ip>:5173. Capacitor 8:npx cap run ios -l --host <lan-ip> --port 5173. The Ionic CLI'sionic cap run ios -l --externalis a different tool.
Workflow
- Inspect. Read
package.json(test runner, framework,@capacitor/*versions),capacitor.config.*, existing test config (vitest.config.*,playwright.config.*,wdio.conf.*,.maestro/), and for pluginsPackage.swift, the podspec,ios/Tests/,android/src/test/. - Ask which layer the user wants if the request is general. Suggest the cheapest one that covers the risk.
- Write tests using the matching reference. Follow the project's existing runner and style; do not add a second runner.
- Run them and show the output. A test that was never run is not done.
- For UI-affecting changes, run the device verification loop (references/device-verification-loop.md) and report screenshots and findings.
Verify
# Web layer
npx vitest run
npx playwright test
# Plugin, iOS (from the plugin repo)
xcodebuild test -scheme <PluginPackageName> \
-destination "platform=iOS Simulator,name=$(xcrun simctl list devices available | grep -m1 -o 'iPhone [^(]*' | sed 's/ *$//')"
# Plugin, Android (from the plugin repo)
cd android && ./gradlew test
# App native tests, if the app has a test target
xcodebuild test -project ios/App/App.xcodeproj -scheme App -destination 'platform=iOS Simulator,name=<device>'
# CocoaPods projects: -workspace ios/App/App.xcworkspaceReport: tests added, command run, pass/fail counts, and anything that could not run locally (no simulator, no device, missing Android SDK).
Error Handling
| Symptom | Cause | Fix |
"<Plugin>" plugin is not implemented on web in Vitest | Real plugin running in jsdom | vi.mock('<plugin package>') in the setup file |
| Mock ignored, real plugin still called | Mock path differs from the import path, or the mock is registered after import | Mock the exact specifier the app imports. Put vi.mock in setupFiles or at the top of the test file |
Appium cannot find data-testid elements | Still in the NATIVE_APP context | await driver.switchContext(webviewContext) after waiting for getContexts() to list a WEBVIEW_* entry |
No WEBVIEW_* context | WebView not inspectable (release build) | Use a debug build, or enable webContentsDebuggingEnabled for the test build only |
| Android WebView context fails with a chromedriver version error | Chromedriver does not match the device WebView | Enable Appium's chromedriver autodownload (an insecure feature flag) or pin a matching chromedriver; check the Appium UiAutomator2 docs |
No such module 'Testing' | Old Xcode | Swift Testing needs the Xcode 16+ toolchain. Capacitor 9 needs Xcode 27 anyway |
error: no such module 'UIKit' from swift test | macOS host build of an iOS package | Use xcodebuild test with an iOS Simulator destination |
'init(callbackId:options:success:error:)' is deprecated / unavailable | Old test helper | Add methodName: |
Live reload: error: unknown option '-l' | Capacitor 9 CLI | Use --url http://<lan-ip>:<port> |
| Live reload app shows a blank page | Dev server bound to localhost, or wrong IP | Bind to 0.0.0.0 (Vite: --host), use the LAN IP, same Wi-Fi |
Related Skills
debugging-capacitor: inspect the WebView and native debuggersios-android-logs: stream logs during device runscapacitor-ci-cd: build and release pipelinescapacitor-ios-resizability: what to check in resized windows during device runscapacitor-plugin-upgrade-v8-to-v9: plugin API removals that affect test helpers
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

