Skip to content
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

Add React Navigation tests to dynamic fixture setup #2201

Merged
merged 6 commits into from
Sep 23, 2024
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
2 changes: 0 additions & 2 deletions .buildkite/basic/react-native-android-pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ steps:
manual:
permit_on_passed: true
env:
SKIP_NAVIGATION_SCENARIOS: "true"
RN_VERSION: "{{matrix}}"
RCT_NEW_ARCH_ENABLED: "0"
concurrency: 25
Expand Down Expand Up @@ -111,7 +110,6 @@ steps:
manual:
permit_on_passed: true
env:
SKIP_NAVIGATION_SCENARIOS: "true"
RCT_NEW_ARCH_ENABLED: "1"
RN_VERSION: "{{matrix}}"
concurrency: 25
Expand Down
2 changes: 0 additions & 2 deletions .buildkite/basic/react-native-ios-pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ steps:
manual:
permit_on_passed: true
env:
SKIP_NAVIGATION_SCENARIOS: "true"
RN_VERSION: "{{matrix}}"
RCT_NEW_ARCH_ENABLED: "0"
concurrency: 25
Expand Down Expand Up @@ -110,7 +109,6 @@ steps:
- --aws-public-ip
env:
RCT_NEW_ARCH_ENABLED: "1"
SKIP_NAVIGATION_SCENARIOS: "true"
RN_VERSION: "{{matrix}}"
retry:
manual:
Expand Down
18 changes: 18 additions & 0 deletions .buildkite/full/pipeline.full.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
steps:

#
# Java 11 Android builder base - used by React Native and React Native CLI (< 0.73)
#
- label: ":docker: Build Java 11 Android Builder base image"
key: "android-builder-base-java-11"
timeout_in_minutes: 30
plugins:
- docker-compose#v4.12.0:
build: android-builder-base-java-11
image-repository: 855461928731.dkr.ecr.us-west-1.amazonaws.com/js
cache-from: android-builder-base-java-11:855461928731.dkr.ecr.us-west-1.amazonaws.com/js:android-builder-base-java-11
- docker-compose#v4.12.0:
push: android-builder-base-java-11:855461928731.dkr.ecr.us-west-1.amazonaws.com/js:android-builder-base-java-11
retry:
automatic:
- exit_status: "*"
limit: 1

#
# Upload full React Native pipelines
#
Expand Down
2 changes: 0 additions & 2 deletions .buildkite/full/react-native-android-pipeline.full.yml
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,6 @@ steps:
manual:
permit_on_passed: true
env:
SKIP_NAVIGATION_SCENARIOS: "true"
RN_VERSION: "{{matrix}}"
RCT_NEW_ARCH_ENABLED: "0"
concurrency: 25
Expand Down Expand Up @@ -362,7 +361,6 @@ steps:
manual:
permit_on_passed: true
env:
SKIP_NAVIGATION_SCENARIOS: "true"
RCT_NEW_ARCH_ENABLED: "1"
RN_VERSION: "{{matrix}}"
concurrency: 25
Expand Down
2 changes: 0 additions & 2 deletions .buildkite/full/react-native-ios-pipeline.full.yml
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,6 @@ steps:
manual:
permit_on_passed: true
env:
SKIP_NAVIGATION_SCENARIOS: "true"
RN_VERSION: "{{matrix}}"
RCT_NEW_ARCH_ENABLED: "0"
concurrency: 25
Expand Down Expand Up @@ -329,7 +328,6 @@ steps:
- --aws-public-ip
env:
RCT_NEW_ARCH_ENABLED: "1"
SKIP_NAVIGATION_SCENARIOS: "true"
RN_VERSION: "{{matrix}}"
retry:
manual:
Expand Down
18 changes: 0 additions & 18 deletions .buildkite/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,6 @@ steps:
queue: macos-14
command: scripts/license_finder.sh

#
# Java 11 Android builder base - used by React Native and React Native CLI (< 0.73)
#
- label: ":docker: Build Java 11 Android Builder base image"
key: "android-builder-base-java-11"
timeout_in_minutes: 30
plugins:
- docker-compose#v4.12.0:
build: android-builder-base-java-11
image-repository: 855461928731.dkr.ecr.us-west-1.amazonaws.com/js
cache-from: android-builder-base-java-11:855461928731.dkr.ecr.us-west-1.amazonaws.com/js:android-builder-base-java-11
- docker-compose#v4.12.0:
push: android-builder-base-java-11:855461928731.dkr.ecr.us-west-1.amazonaws.com/js:android-builder-base-java-11
retry:
automatic:
- exit_status: "*"
limit: 1

#
# Publish/package notifier
#
Expand Down
204 changes: 136 additions & 68 deletions scripts/generate-react-native-fixture.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,33 @@ if (!process.env.REGISTRY_URL) {

const notifierVersion = process.env.NOTIFIER_VERSION || common.determineVersion()

const rnVersion = process.env.RN_VERSION
const reactNativeVersion = process.env.RN_VERSION
const ROOT_DIR = resolve(__dirname, '../')

const isNewArchEnabled = process.env.RCT_NEW_ARCH_ENABLED === 'true' || process.env.RCT_NEW_ARCH_ENABLED === '1'

let fixturePath = 'test/react-native/features/fixtures/generated/'
if (process.env.RCT_NEW_ARCH_ENABLED === '1') {
if (isNewArchEnabled) {
fixturePath += 'new-arch/'
} else {
fixturePath += 'old-arch/'
}

const fixtureDir = resolve(ROOT_DIR, fixturePath, rnVersion)
const fixtureDir = resolve(ROOT_DIR, fixturePath, reactNativeVersion)

const replacementFilesDir = resolve(ROOT_DIR, 'test/react-native/features/fixtures/app/dynamic/')

const DEPENDENCIES = [
'react-native-file-access@3.0.4'
'react-native-file-access@3.0.4',
`@bugsnag/react-native@${notifierVersion}`
]

const REACT_NAVIGATION_DEPENDENCIES = [
`@bugsnag/plugin-react-navigation@${notifierVersion}`,
'@react-navigation/native',
'@react-navigation/native-stack',
'react-native-screens',
'react-native-safe-area-context'
]

if (!process.env.SKIP_GENERATE_FIXTURE) {
Expand All @@ -40,76 +51,16 @@ if (!process.env.SKIP_GENERATE_FIXTURE) {
}

// create the test fixture
const RNInitArgs = [`react-native@${process.env.RN_VERSION}`, 'init', 'reactnative', '--directory', fixtureDir, '--version', rnVersion, '--npm', '--skip-install']
const RNInitArgs = [`react-native@${process.env.RN_VERSION}`, 'init', 'reactnative', '--directory', fixtureDir, '--version', reactNativeVersion, '--npm', '--skip-install']
execFileSync('npx', RNInitArgs, { stdio: 'inherit' })

// replace the App.js/App.tsx file with our own App.js file
fs.readdirSync(resolve(fixtureDir))
.filter((file) => /App\.[tj]sx?$/.test(file))
.map((file) => fs.unlinkSync(resolve(fixtureDir, file)))
replaceGeneratedFixtureFiles()

fs.copyFileSync(
resolve(replacementFilesDir, 'App.js'),
resolve(fixtureDir, 'App.js')
)

// replace the AndroidManifest.xml file with our own
fs.copyFileSync(
resolve(replacementFilesDir, 'android/AndroidManifest.xml'),
resolve(fixtureDir, 'android/app/src/main/AndroidManifest.xml')
)

// replace the Info.plist file with our own
fs.copyFileSync(
resolve(replacementFilesDir, 'ios/Info.plist'),
resolve(fixtureDir, 'ios/reactnative/Info.plist')
)

// copy the exportOptions.plist file
fs.copyFileSync(
resolve(replacementFilesDir, 'ios/exportOptions.plist'),
resolve(fixtureDir, 'exportOptions.plist')
)

// update pbxproj
let pbxProjContents = fs.readFileSync(`${fixtureDir}/ios/reactnative.xcodeproj/project.pbxproj`, 'utf8')
pbxProjContents = pbxProjContents.replaceAll('org.reactjs.native.example', 'com.bugsnag.fixtures')

fs.writeFileSync(`${fixtureDir}/ios/reactnative.xcodeproj/project.pbxproj`, pbxProjContents)

// update Podfile
let podfileContents = fs.readFileSync(`${fixtureDir}/ios/Podfile`, 'utf8')

// use static frameworks (this fixes an issue with react-native-file-access on 0.75)
if (parseFloat(rnVersion) >= 0.75) {
podfileContents = podfileContents.replace(/target 'reactnative' do/, 'use_frameworks! :linkage => :static\ntarget \'reactnative\' do')
}

// disable Flipper
if (podfileContents.includes('use_flipper!')) {
podfileContents = podfileContents.replace(/use_flipper!/, '# use_flipper!')
} else if (podfileContents.includes(':flipper_configuration')) {
podfileContents = podfileContents.replace(/:flipper_configuration/, '# :flipper_configuration')
}

fs.writeFileSync(`${fixtureDir}/ios/Podfile`, podfileContents)

const fixtureDependencyArgs = DEPENDENCIES.join(' ')

// install test fixture dependencies and local packages
execSync(`npm install --save ${fixtureDependencyArgs}`, { cwd: fixtureDir, stdio: 'inherit' })

// install @bugsnag/react-native from the registry
execSync(`npm install --save @bugsnag/react-native@${notifierVersion} --registry ${process.env.REGISTRY_URL}`, { cwd: fixtureDir, stdio: 'inherit' })

// install the scenario launcher package
const scenarioLauncherPackage = `${ROOT_DIR}/test/react-native/features/fixtures/scenario-launcher`
execSync(`npm pack ${scenarioLauncherPackage} --pack-destination ${fixtureDir}`, { cwd: ROOT_DIR, stdio: 'inherit' })
execSync('npm install --save bugsnag-react-native-scenarios-1.0.0.tgz', { cwd: fixtureDir, stdio: 'inherit' })
installFixtureDependencies()
}

if (process.env.BUILD_ANDROID === 'true' || process.env.BUILD_ANDROID === '1') {
if (process.env.RCT_NEW_ARCH_ENABLED === 'true' || process.env.RCT_NEW_ARCH_ENABLED === '1') {
if (isNewArchEnabled) {
// If we're building with the new architecture, replace the gradle.properties file
fs.copyFileSync(
resolve(replacementFilesDir, 'android/newarch.gradle.properties'),
Expand Down Expand Up @@ -163,3 +114,120 @@ if (process.env.BUILD_IOS === 'true' || process.env.BUILD_IOS === '1') {

execFileSync('xcrun', exportArgs, { cwd: fixtureDir, stdio: 'inherit' })
}

function installFixtureDependencies () {
if (!isNewArchEnabled) {
DEPENDENCIES.push(...REACT_NAVIGATION_DEPENDENCIES)
}

const fixtureDependencyArgs = DEPENDENCIES.join(' ')

// install test fixture dependencies
execSync(`npm install --save ${fixtureDependencyArgs} --registry ${process.env.REGISTRY_URL}`, { cwd: fixtureDir, stdio: 'inherit' })

// install the scenario launcher package
const scenarioLauncherPackage = `${ROOT_DIR}/test/react-native/features/fixtures/scenario-launcher`
execSync(`npm pack ${scenarioLauncherPackage} --pack-destination ${fixtureDir}`, { cwd: ROOT_DIR, stdio: 'inherit' })
execSync('npm install --save bugsnag-react-native-scenarios-1.0.0.tgz', { cwd: fixtureDir, stdio: 'inherit' })
}

/** Replace native files generated by react-native cli with pre-configured files */
function replaceGeneratedFixtureFiles () {
// replace the App.js/App.tsx file with our own App.js file
fs.readdirSync(resolve(fixtureDir))
.filter((file) => /App\.[tj]sx?$/.test(file))
.map((file) => fs.unlinkSync(resolve(fixtureDir, file)))

fs.copyFileSync(
resolve(replacementFilesDir, 'App.js'),
resolve(fixtureDir, 'App.js')
)

// replace the AndroidManifest.xml file with our own
fs.copyFileSync(
resolve(replacementFilesDir, 'android/AndroidManifest.xml'),
resolve(fixtureDir, 'android/app/src/main/AndroidManifest.xml')
)

// replace the Info.plist file with our own
fs.copyFileSync(
resolve(replacementFilesDir, 'ios/Info.plist'),
resolve(fixtureDir, 'ios/reactnative/Info.plist')
)

// copy the exportOptions.plist file
fs.copyFileSync(
resolve(replacementFilesDir, 'ios/exportOptions.plist'),
resolve(fixtureDir, 'exportOptions.plist')
)

// update pbxproj
let pbxProjContents = fs.readFileSync(`${fixtureDir}/ios/reactnative.xcodeproj/project.pbxproj`, 'utf8')
pbxProjContents = pbxProjContents.replaceAll('org.reactjs.native.example', 'com.bugsnag.fixtures')

fs.writeFileSync(`${fixtureDir}/ios/reactnative.xcodeproj/project.pbxproj`, pbxProjContents)

// update Podfile
let podfileContents = fs.readFileSync(`${fixtureDir}/ios/Podfile`, 'utf8')

// use static frameworks (this fixes an issue with react-native-file-access on 0.75)
if (parseFloat(reactNativeVersion) >= 0.75) {
podfileContents = podfileContents.replace(/target 'reactnative' do/, 'use_frameworks! :linkage => :static\ntarget \'reactnative\' do')
}

// disable Flipper
if (podfileContents.includes('use_flipper!')) {
podfileContents = podfileContents.replace(/use_flipper!/, '# use_flipper!')
} else if (podfileContents.includes(':flipper_configuration')) {
podfileContents = podfileContents.replace(/:flipper_configuration/, '# :flipper_configuration')
}

fs.writeFileSync(`${fixtureDir}/ios/Podfile`, podfileContents)

// react navigation setup
if (!isNewArchEnabled) {
configureReactNavigationAndroid()
}
}

function configureReactNavigationAndroid () {
const fileExtension = parseFloat(reactNativeVersion) < 0.73 ? 'java' : 'kt'
let mainActivityPattern, mainActivityReplacement
if (fileExtension === 'java') {
mainActivityPattern = 'public class MainActivity extends ReactActivity {'
mainActivityReplacement = `
import android.os.Bundle;
public class MainActivity extends ReactActivity {
/**
* Required for react-navigation/native implementation
* https://reactnavigation.org/docs/getting-started/#installing-dependencies-into-a-bare-react-native-project
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(null);
}
`
} else if (fileExtension === 'kt') {
mainActivityPattern = 'class MainActivity : ReactActivity() {'
mainActivityReplacement = `
import android.os.Bundle
class MainActivity : ReactActivity() {
/**
* Required for react-navigation/native implementation
* https://reactnavigation.org/docs/getting-started/#installing-dependencies-into-a-bare-react-native-project
*/
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(null)
}
`
}

const mainActivityPath = `${fixtureDir}/android/app/src/main/java/com/reactnative/MainActivity.${fileExtension}`
let mainActivityContents = fs.readFileSync(mainActivityPath, 'utf8')
mainActivityContents = mainActivityContents.replace(mainActivityPattern, mainActivityReplacement)
fs.writeFileSync(mainActivityPath, mainActivityContents)
}
18 changes: 11 additions & 7 deletions test/react-native/features/fixtures/app/dynamic/App.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
import React, { useEffect } from 'react'
import React, { useEffect, useState } from 'react'
import { SafeAreaView, StyleSheet, View, Text } from 'react-native'
import { launchScenario } from '@bugsnag/react-native-scenarios'

const App = () => {
const [scenario, setScenario] = useState(null)

useEffect(() => {
launchScenario()
launchScenario(setScenario)
}, [])

return (
<SafeAreaView style={styles.container}>
<View>
<Text>React Native Test App</Text>
</View>
</SafeAreaView>
scenario !== null ? scenario.view() : (
<SafeAreaView style={styles.container}>
<View>
<Text>React Native Test App</Text>
</View>
</SafeAreaView>
)
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
"react-native-navigation": "*"
},
"peerDependencies": {
"@bugsnag/plugin-react-navigation": "*",
"@react-navigation/native": "*",
"@react-navigation/native-stack": "*",
"react": "*",
"react-native": "*",
"react-native-file-access": "*"
Expand Down
Loading
Loading