Testing
The testing skill provides knowledge for writing and running UI test flows for React Native feature verification. Covers test runner selection, timing rules, flow structure, multi-device testing, auth pre-flight, and permission handling.
When loaded
Section titled “When loaded”Activates when Claude encounters tasks involving Maestro tests, E2E flows, testIDs, UI test execution, network mocking, store state inspection, or test assertions.
Key Knowledge Areas
Section titled “Key Knowledge Areas”Test Runner: maestro-runner (preferred)
Section titled “Test Runner: maestro-runner (preferred)”A Go-based drop-in replacement for Maestro with the same YAML syntax:
| Metric | Maestro (Java) | maestro-runner (Go) |
|---|---|---|
| Binary size | ~300MB (with JVM) | 21MB |
| Startup time | 2-4s | <100ms |
| Memory | ~400MB | ~30MB |
| Flow execution | Baseline | 2-3x faster |
Critical Timing Rule
Section titled “Critical Timing Rule”After any UI interaction, React needs time to commit updates to the fiber tree.
Correct sequence:
device_find/ Maestro tapdevice_snapshot/ MaestroassertVisible(wait for settle)cdp_store_state(now safe to read)
Wrong (race condition): tapping then immediately querying CDP returns stale state.
Optimized Test Loop
Section titled “Optimized Test Loop”Per-step timing with maestro-runner + JPEG: ~1.4s (2.2x faster than Maestro + PNG baseline of ~3.1s).
Maestro Flow Patterns
Section titled “Maestro Flow Patterns”- Basic structure:
appIdheader + step list - Never use
clearState: truewith Expo Dev Client (wipes Metro URL) - Navigation via deep links or testID taps
- Assertions:
assertVisible,assertNotVisible, text content matching
testID Conventions
Section titled “testID Conventions”- Stable semantic names:
add-to-cart-btn,cart-badge,search-input - Dynamic IDs for list items:
testID={`product-item-${item.id}`} - Every
Pressable,TouchableOpacity,Button,TextInput, and scrollable container must have a testID
Component Tree Token Efficiency
Section titled “Component Tree Token Efficiency”- Never call
cdp_component_treewithout afilterparameter (full dumps produce 10K+ tokens) - Fiber tree presence does not mean screen visibility
Auth Pre-flight
Section titled “Auth Pre-flight”Before testing, checks cdp_navigation_state for auth screens. If logged out:
- Scans for Maestro subflows (prefer login over registration)
- Strips
clearState: truefor Dev Client builds - Wraps subflows with
appIdif missing - Runs via maestro-runner, verifies arrival at main screen
Permission Pre-flight
Section titled “Permission Pre-flight”For permission-gated flows, queries and sets the correct state:
| Platform | Query | Grant | Revoke | Reset |
|---|---|---|---|---|
| Android | dumpsys | pm grant | pm revoke | pm reset-permissions |
| iOS Sim | Not supported | simctl privacy grant | simctl privacy revoke | simctl privacy reset |
Network Mocking
Section titled “Network Mocking”Injects mocks via cdp_evaluate using global.__RN_AGENT_MOCKS__ before navigating to the screen under test.
Zustand Store Inspection
Section titled “Zustand Store Inspection”Zustand v4+ uses useSyncExternalStore (not React Context), so fiber tree walking cannot detect stores. Projects must register store hooks:
if (__DEV__) { global.__ZUSTAND_STORES__ = { auth: useAuthStore, cart: useCartStore, };}Then cdp_store_state(path="cart.items") reads the live state.