@gdtkit/flow
v0.2.11
Published
Flow-based E2E testing for React Native
Downloads
764
Readme
Flow - UI/E2E tests on React Native
Install
npm install --save-dev @gdtkit/flowSetup
1. Configure Metro
In metro.config.js, wrap your config inside withFlowTest:
const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');
const { withFlowTest } = require('@gdtkit/flow/metro');
const config = {};
module.exports = withFlowTest(
mergeConfig(getDefaultConfig(__dirname), config),
{
flowsDir: __dirname,
},
);2. Init flow
In App.tsx, inside if (__DEV__), call initFlowTest with navigationRef:
import {
NavigationContainer,
createNavigationContainerRef,
} from '@react-navigation/native';
import { initFlowTest } from '@gdtkit/flow';
const navigationRef = createNavigationContainerRef();
if (__DEV__) {
initFlowTest(navigationRef);
// On a physical device: initFlowTest(navigationRef, { host: '192.168.x.x' })
}
export function App() {
return (
<NavigationContainer ref={navigationRef}>
{/* your navigators */}
</NavigationContainer>
);
}You can also pass these config options to initFlowTest:
| Option | Type | Default | Description |
| ----------- | ------------------------------------------ | ------------- | ----------------------------------------------------------- |
| host | string | "localhost" | IP of the dev machine (needed for physical devices) |
| chain | boolean | true | After a passing run, auto-trigger the next screen's .flow |
| onRunDone | (passed: number, failed: number) => void | Alert | Called when a run finishes |
3. Tag your components
Add a testID prop the elements you want to use in your .flow file.
export function LoginScreen() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
return (
<View>
<TextInput
testID='loginEmail'
value={email}
onChangeText={setEmail}
/>
<TextInput
testID='loginPassword'
value={password}
onChangeText={setPassword}
secureTextEntry
/>
<TouchableOpacity testID='loginSubmit' onPress={handleLogin}>
<Text>Login</Text>
</TouchableOpacity>
</View>
);
}Writing .flow files
Name each file after the screen it tests: LoginScreen.flow.
speed = slow
waitFor { screen = LoginScreen }
loginEmail = [email protected]
loginPassword = Password123!
loginSubmit
expect {
screen = HomeScreen
}Syntax
| Line | What it does |
| ---------------------------------- | ------------------------------------------------ |
| speed = fast\|normal\|slow\|1-10 | Typing speed (default: normal) |
| mode = typing\|instant | typing = char by char, instant = all at once |
| waitFor { screen = X } | Wait up to 30s for screen X to appear |
| myInput = [email protected] | Type into the input tagged myInput |
| myButton | Tap the pressable tagged myButton |
| expect { screen = X } | Assert current screen is X |
| expect { visible = [a, b] } | Assert elements a and b are on screen |
Flow chains
When a run passes and the screen changes, it checks by default if a .flow file exists for the new screen and runs it. Disable with chain: false in initFlowTest.
Run tests
Open the React Native dev menu and tap "Run test ▶" — it detects the current screen and runs the matching .flow file automatically.
Alternatively, from the terminal:
npx gdt-flow run path/to/LoginScreen.flowOutput
▶ LoginScreen.flow
✓ waitFor screen = LoginScreen
✓ type loginEmail = "[email protected]"
✓ type loginPassword = "Password123!"
✓ tap loginSubmit
✓ expect screen = HomeScreen
4 passed 0 failed