Help us improve
Share bugs, ideas, or general feedback.
Claude Code skills for react-native-preflight — integrate Maestro E2E testing into React Native projects
npx claudepluginhub rambowasreal/react-native-preflightMaestro E2E testing for React Native — isolated screens, dev catalog, visual regression
Claude Code marketplace entries for the plugin-safe Antigravity Awesome Skills library and its compatible editorial bundles.
Production-ready workflow orchestration with 84 marketplace plugins, 192 local specialized agents, and 156 local skills - optimized for granular installation and minimal token usage
Directory of popular Claude Code extensions including development tools, productivity plugins, and MCP integrations
Share bugs, ideas, or general feedback.
Simplify Maestro E2E testing for React Native. Test screens in isolation, browse a dev catalog, and catch visual regressions — all with zero production overhead.
onNavigatenpm install react-native-preflight
Peer dependencies: expo-linking, react, react-native. expo-router is optional — if installed, navigation works automatically. Without it, provide an onNavigate prop.
Skip the manual setup — this package ships a Claude Code plugin that handles everything: Babel config, StateInjector, screen wrapping, and Maestro YAML generation.
# Add the marketplace and install the plugin
/plugin marketplace add RamboWasReal/react-native-preflight
/plugin install react-native-preflight@react-native-preflight-plugins
Then run:
/react-native-preflight:preflight-setup
Already using Claude Code? This is the fastest way to get started. The plugin auto-detects your project structure (Expo Router or React Navigation) and configures everything.
npx preflight init
Creates .maestro/ directories, adds the preflight deep link scheme to app.json, scaffolds a catalog screen, and configures the Babel plugin.
Use scenario() to register a screen for testing. It wraps the component and makes it discoverable by the catalog and CLI.
import { scenario } from 'react-native-preflight';
export default scenario(
{
id: 'settings',
route: '/settings',
description: 'Settings screen',
inject: async () => {
// Pre-populate stores, query cache, etc.
},
test: ({ see, tap, scroll }) => [
see('Settings'),
tap('dark-mode-toggle'),
scroll('footer', 'down'),
],
},
function SettingsScreen() {
// your component...
},
);
id — Unique identifier, used as Maestro testID and YAML filename
route — Must match the file-based route (Expo Router) or screen name (React Navigation)
inject() — Called BEFORE navigation to set up deterministic state (zero flash)
test() — Optional. Generates Maestro test steps via npx preflight generate:
see('text') — assert visible textsee({ id: 'testID' }) — assert testID visibletap('buttonId') — tap element by testIDlongPress('itemId') — long press element by testIDtype('inputId', 'value') — type text into inputnotSee('text') — assert text not visiblewait(2000) — wait N millisecondsscroll('elementId', 'down') — scroll until element is visible (scrollUntilVisible)swipe('left') — swipe in a direction (default 400ms)swipe('up', 200) — swipe with custom durationback() — press back buttonhideKeyboard() — dismiss the keyboardraw('- setLocation:\n latitude: 45.5') — inject raw Maestro YAMLTest functions can be extracted to separate files and imported:
// e2e/tests/settings.ts
import type { TestHelpers } from 'react-native-preflight';
export const settingsTest = ({ see, tap }: TestHelpers) => [
see('Settings'),
tap('dark-mode-toggle'),
];
// app/settings.tsx
import { settingsTest } from '@/e2e/tests/settings';
export default scenario({ id: 'settings', route: '/settings', test: settingsTest }, SettingsScreen);
The generator follows single-level imports to resolve test steps from external files.
variants — Optional. Test multiple states of the same screen. Each variant inherits route, inject, and test from the base config unless overridden:
export default scenario({
id: 'dashboard',
route: '/dashboard',
variants: {
'with-data': {
inject: () => { /* populate stores with mock data */ },
test: ({ see }) => [see('Welcome back')],
},
'empty-state': {
inject: () => { /* clear all stores */ },
test: ({ see }) => [see('Get started')],
},
},
}, DashboardScreen);
Generates screens/dashboard/with-data.yaml and screens/dashboard/empty-state.yaml.
Wrap your root layout with StateInjector. It listens for preflight:// deep links, calls inject, then navigates.
Expo Router (auto-detected):
// app/_layout.tsx
import { StateInjector } from 'react-native-preflight';
export default function RootLayout() {
return (
<StateInjector>
<Stack />
</StateInjector>
);
}