-
Notifications
You must be signed in to change notification settings - Fork 31
feat: Implement jest mocks for react-native. #535
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 39 commits
75725a5
9e0ea68
799200d
7833f46
db3697f
4f04b46
d248241
4944307
f4ee714
e8b3649
a877514
2531181
8f9cec6
b2657ff
75583b3
efbf89c
60cd0a1
a5341e6
ad47e51
fbc8178
7750714
3e3252a
f737935
26692ce
af3fcc4
f4b52b9
99c789f
d95b070
d4bbdeb
c578a19
1d92d09
0728fdf
4dc3bf2
3ef8baa
b32dedf
d36a2ad
1f2163e
6e3caf7
3e146e8
78fd823
3d45157
3f5b48c
61aefc7
a4fad23
23e7dac
beef6b0
4fdbdbd
e9493ed
d2cb48e
0760dab
7bd782f
210f710
2fc00e4
32d4a22
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| # Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files | ||
|
|
||
| # dependencies | ||
| node_modules/ | ||
|
|
||
| # Expo | ||
| .expo/ | ||
| dist/ | ||
| web-build/ | ||
|
|
||
| # Native | ||
| *.orig.* | ||
| *.jks | ||
| *.p8 | ||
| *.p12 | ||
| *.key | ||
| *.mobileprovision | ||
|
|
||
| # Metro | ||
| .metro-health-check* | ||
|
|
||
| # debug | ||
| npm-debug.* | ||
| yarn-debug.* | ||
| yarn-error.* | ||
|
|
||
| # macOS | ||
| .DS_Store | ||
| *.pem | ||
|
|
||
| # local env files | ||
| .env*.local | ||
|
|
||
| # typescript | ||
| *.tsbuildinfo | ||
|
|
||
| # vscode | ||
| .vscode |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| import { StyleSheet } from 'react-native'; | ||
| import { | ||
| AutoEnvAttributes, | ||
| LDProvider, | ||
| ReactNativeLDClient, | ||
| LDOptions, | ||
| } from '@launchdarkly/react-native-client-sdk'; | ||
| import Welcome from './src/welcome'; | ||
|
|
||
| const options: LDOptions = { | ||
| debug: true, | ||
| } | ||
| //TODO Set MOBILE_KEY in .env file to a mobile key in your project/environment. | ||
| const MOBILE_KEY = 'YOUR_MOBILE_KEY'; | ||
| const featureClient = new ReactNativeLDClient(MOBILE_KEY, AutoEnvAttributes.Enabled, options); | ||
|
|
||
| const userContext = { kind: 'user', key: '', anonymous: true }; | ||
|
|
||
| export default function App() { | ||
| featureClient.identify(userContext).catch((e: any) => console.log(e)); | ||
|
|
||
| return ( | ||
| <LDProvider client={featureClient}> | ||
| <Welcome /> | ||
| </LDProvider> | ||
| ); | ||
| } | ||
|
|
||
| const styles = StyleSheet.create({ | ||
| container: { | ||
| flex: 1, | ||
| backgroundColor: '#fff', | ||
| alignItems: 'center', | ||
| justifyContent: 'center', | ||
| }, | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| { | ||
| "expo": { | ||
| "name": "react-native-jest-example", | ||
| "slug": "react-native-jest-example", | ||
| "version": "0.0.1", | ||
| "orientation": "portrait", | ||
| "icon": "./assets/icon.png", | ||
| "userInterfaceStyle": "light", | ||
| "splash": { | ||
| "image": "./assets/splash.png", | ||
| "resizeMode": "contain", | ||
| "backgroundColor": "#ffffff" | ||
| }, | ||
| "ios": { | ||
| "supportsTablet": true, | ||
| "bundleIdentifier": "com.anonymous.reactnativejestexample" | ||
| }, | ||
| "android": { | ||
| "adaptiveIcon": { | ||
| "foregroundImage": "./assets/adaptive-icon.png", | ||
| "backgroundColor": "#ffffff" | ||
| }, | ||
| "package": "com.anonymous.reactnativejestexample" | ||
| }, | ||
| "web": { | ||
| "favicon": "./assets/favicon.png" | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| module.exports = function (api) { | ||
| api.cache(true); | ||
| return { | ||
| presets: ['babel-preset-expo', '@babel/preset-typescript'], | ||
|
|
||
| }; | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| // We have to use a custom entrypoint for monorepo workspaces to work. | ||
| // https://docs.expo.dev/guides/monorepos/#change-default-entrypoint | ||
| import { registerRootComponent } from 'expo'; | ||
|
|
||
| import App from './App'; | ||
|
|
||
| // registerRootComponent calls AppRegistry.registerComponent('main', () => App); | ||
| // It also ensures that whether you load the app in Expo Go or in a native build, | ||
| // the environment is set up appropriately | ||
| registerRootComponent(App); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| module.exports = { | ||
| preset: 'jest-expo', | ||
| setupFiles: ['@launchdarkly/jest/react-native'], | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| // We need to use a custom metro config for monorepo workspaces to work. | ||
| // https://docs.expo.dev/guides/monorepos/#modify-the-metro-config | ||
| /** | ||
| * @type {import('expo/metro-config')} | ||
| */ | ||
| const { getDefaultConfig } = require('expo/metro-config'); | ||
| const path = require('path'); | ||
|
|
||
| // Find the project and workspace directories | ||
| const projectRoot = __dirname; | ||
|
|
||
| const findWorkspaceRoot = require('find-yarn-workspace-root'); | ||
|
|
||
| const workspaceRoot = findWorkspaceRoot(__dirname); // Absolute path or null | ||
|
|
||
| const config = getDefaultConfig(projectRoot); | ||
|
|
||
| // 1. Watch all files within the monorepo | ||
| config.watchFolders = [workspaceRoot]; | ||
| // 2. Let Metro know where to resolve packages and in what order | ||
| config.resolver.nodeModulesPaths = [ | ||
| path.resolve(projectRoot, 'node_modules'), | ||
| path.resolve(workspaceRoot, 'node_modules'), | ||
| ]; | ||
| // 3. Force Metro to resolve (sub)dependencies only from the `nodeModulesPaths` | ||
| config.resolver.disableHierarchicalLookup = true; | ||
|
|
||
| module.exports = config; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| { | ||
| "name": "react-native-jest-example", | ||
| "version": "0.0.1", | ||
| "main": "index.js", | ||
| "scripts": { | ||
| "start": "expo start", | ||
| "android": "expo run:android", | ||
| "ios": "expo run:ios", | ||
| "test": "jest", | ||
| "clean": "rm -rf node_modules && rm -rf package-lock.json && rm -rf yarn.lock" | ||
| }, | ||
| "dependencies": { | ||
| "@launchdarkly/react-native-client-sdk": "workspace:^", | ||
| "expo": "^51.0.26", | ||
| "expo-status-bar": "~1.12.1", | ||
| "find-yarn-workspace-root": "^2.0.0", | ||
| "react": "^18.2.0", | ||
| "react-native": "0.74.5" | ||
| }, | ||
| "devDependencies": { | ||
| "@babel/core": "^7.20.0", | ||
| "@babel/preset-env": "^7.25.4", | ||
| "@babel/preset-react": "^7.24.7", | ||
| "@babel/runtime": "^7.25.4", | ||
| "@launchdarkly/jest": "workspace:^", | ||
| "@react-native/babel-preset": "^0.75.2", | ||
| "@testing-library/react-native": "^12.6.1", | ||
| "@types/jest": "^29.5.12", | ||
| "@types/react": "~18.2.45", | ||
| "jest": "^29.7.0", | ||
| "jest-expo": "^51.0.4", | ||
| "react-test-renderer": "^18.2.0", | ||
| "typescript": "^5.1.3" | ||
| }, | ||
| "packageManager": "[email protected]", | ||
| "installConfig": { | ||
| "hoistingLimits": "workspaces" | ||
| }, | ||
| "private": true | ||
| } |
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This looks good. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| /** | ||
| * @jest-environment jsdom | ||
| */ | ||
|
|
||
| import { mockFlags, resetLDMocks } from '@launchdarkly/jest/react-native'; | ||
| import { screen, render } from '@testing-library/react-native'; | ||
| import { useLDClient } from '@launchdarkly/react-native-client-sdk'; | ||
| import Welcome from './welcome'; | ||
|
|
||
| describe('Welcome component test', () => { | ||
|
|
||
| afterEach(() => { | ||
| resetLDMocks(); | ||
| }); | ||
|
|
||
| test('mock boolean flag correctly', () => { | ||
| mockFlags({ 'my-boolean-flag': true }); | ||
| render(<Welcome />); | ||
| expect(screen.getByText('Flag value is true')).toBeTruthy(); | ||
| }); | ||
|
|
||
| test('mock ldClient correctly', () => { | ||
| const current = useLDClient(); | ||
|
|
||
| current?.track('event'); | ||
| expect(current.track).toHaveBeenCalledTimes(1); | ||
| }); | ||
|
|
||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| import { StyleSheet, Text, View } from 'react-native'; | ||
| import { useLDClient } from '@launchdarkly/react-native-client-sdk'; | ||
|
|
||
| export default function Welcome() { | ||
|
|
||
| const ldClient = useLDClient(); | ||
|
|
||
| const flagValue = ldClient.boolVariation('my-boolean-flag', false); | ||
|
|
||
| return ( | ||
| <View style={styles.container}> | ||
| <Text>Welcome to LaunchDarkly</Text> | ||
| <Text>Flag value is {`${flagValue}`}</Text> | ||
| </View> | ||
| ); | ||
| } | ||
|
|
||
| const styles = StyleSheet.create({ | ||
| container: { | ||
| flex: 1, | ||
| backgroundColor: '#fff', | ||
| alignItems: 'center', | ||
| justifyContent: 'center', | ||
| }, | ||
| }); | ||
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| { | ||
| "extends": "./tsconfig.json", | ||
| "include": [ | ||
| "/**/*.ts", | ||
| "/**/*.tsx", | ||
| "/*.js", | ||
| "/*.tsx" | ||
| ], | ||
| "exclude": ["node_modules"] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| { | ||
| "extends": "expo/tsconfig.base", | ||
| "compilerOptions": { | ||
| "strict": true, | ||
| "moduleResolution": "bundler", | ||
| "jsx": "react-jsx" | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -55,9 +55,18 @@ | |
| "eslint-plugin-prettier": "^5.0.0", | ||
| "jest": "^29.5.0", | ||
| "prettier": "^3.0.0", | ||
| "react-test-renderer": "^18.3.1", | ||
| "rimraf": "^5.0.1", | ||
| "ts-jest": "^29.1.0", | ||
| "typedoc": "0.25.0", | ||
| "typescript": "5.1.6" | ||
| }, | ||
| "dependencies": { | ||
| "@launchdarkly/react-native-client-sdk": "workspace:^", | ||
|
||
| "@testing-library/react-hooks": "^8.0.1", | ||
| "@testing-library/react-native": "^12.7.2", | ||
| "@types/lodash": "^4.17.7", | ||
| "launchdarkly-react-client-sdk": "^3.4.0", | ||
| "react": "^18.3.1" | ||
| } | ||
| } | ||

Uh oh!
There was an error while loading. Please reload this page.