Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions examples/test-app/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ It is intentionally small, but each surface is dense with durable accessibility
- `Settings`: switch rows, accordion content, loading and error states, retry flow, destructive-confirm modal
- `Automation lab`: long-press, alert-result, app-event, app-state, appearance, orientation, permission-recovery, log canaries, a flattened (`accessible={true}`) text input, and an Apple Pay sheet hosted in `com.apple.PassbookUIService`
- `WebView accessibility`: a deterministic semantic fixture plus live websites with varied HTML for native accessibility snapshot verification
- `Perf lab`: seeded JavaScript render problems for `react-devtools profile`, one per scenario (see [Perf lab](#perf-lab))

Navigation uses Expo Router native bottom tabs, so the tab bar itself is also part of the test surface.

Expand Down Expand Up @@ -234,6 +235,32 @@ installed development build is connected to that server. For Android local
device/emulator runs, also run `adb reverse tcp:8082 tcp:8082` when the device
needs host port forwarding.

## Perf lab

`agent-device-test-app://perf-lab?scenario=<id>` opens one seeded render problem. **Run** (`perf-run`) replays the slow interaction as a fixed burst and sets `perf-status` to `done`. Profile it with:

```bash
agent-device open "agent-device-test-app://perf-lab?scenario=memo-defeated" --platform android
Comment thread
thymikee marked this conversation as resolved.
agent-device react-devtools profile start
agent-device click 'id="perf-run"'
agent-device wait 'id="perf-status" text="done"' 10000
agent-device react-devtools profile stop
```

`profile stop` should report this finding first:

| Scenario | Seeded problem | Expected finding |
| --- | --- | --- |
| `expensive-render` | `PriceHistoryChart` recomputes its trend on every render | `slow-render PriceHistoryChart` |
| `memo-defeated` | `ContactList` passes a new callback and style object to memoized rows | `memo-defeated ContactRow` |
| `context-cascade` | A fast-changing `unread` counter shares one context with the stable user name that badges read | `context-cascade AvatarBadge` |
| `parent-cascade` | Typing re-renders every unmemoized result row | `parent-cascade ResultRow` |
| `render-storm` | `LiveClock` sets state every 16 ms | `render-storm LiveClock` |
| `effect-chain` | `FilteredContacts` copies derived state in an effect | `effect-chain FilteredContacts` |
| `eager-list` | 1,200 tiles mount in one commit instead of a virtualized list; every Run mounts them afresh | `eager-mount ProductTile` |

`src/screens/PerfLabScreen.tsx` imports only React and React Native, so it can be copied into a bare React Native app to check the profiler on other React Native versions.

## Local Agent Device suites

The repo includes two local suites for iterating on the fixture app:
Expand Down
1 change: 1 addition & 0 deletions examples/test-app/app/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ function RootLayoutContent() {
<Stack.Screen name="snapshot-depth" />
<Stack.Screen name="deep-tree" />
<Stack.Screen name="ticker" />
<Stack.Screen name="perf-lab" />
<Stack.Screen name="product/[productId]" />
<Stack.Screen name="webview" />
</Stack>
Expand Down
9 changes: 9 additions & 0 deletions examples/test-app/app/perf-lab.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { useLocalSearchParams } from 'expo-router';

import { isPerfScenario, PerfLabScreen } from '../src/screens/PerfLabScreen';

export default function PerfLabRoute() {
const { scenario } = useLocalSearchParams<{ scenario?: string }>();
const initialScenario = isPerfScenario(scenario) ? scenario : undefined;
return <PerfLabScreen initialScenario={initialScenario} key={initialScenario} />;
}
Loading
Loading