Skip to content

Commit

Permalink
convert react-native-navigation scenarios
Browse files Browse the repository at this point in the history
  • Loading branch information
yousif-bugsnag committed Sep 16, 2024
1 parent ead3991 commit 7db5a2d
Show file tree
Hide file tree
Showing 8 changed files with 253 additions and 167 deletions.
Original file line number Diff line number Diff line change
@@ -1,137 +1,24 @@
import { Navigation } from 'react-native-navigation'
import HomeScreen from './screens/Home'
import DetailsScreen from './screens/Details'
import { NativeModules, View, Text, Button, TextInput, StyleSheet } from 'react-native'
import * as React from 'react'
import Bugsnag from '@bugsnag/react-native'
import * as Scenarios from './Scenarios'
import BugsnagReactNativeNavigation from '@bugsnag/plugin-react-native-navigation'
import { Component } from 'react'
import { View, Text, StyleSheet } from 'react-native'
import React, { useEffect } from 'react'
import { launchScenario } from './lib/ScenarioLauncher'

const defaultJsConfig = () => ({
plugins: [new BugsnagReactNativeNavigation(Navigation)]
})

export default class AppScreen extends Component {
constructor (props) {
super(props)
this.state = {
currentScenario: '',
apiKey: '12312312312312312312312312312312',
notifyEndpoint: '',
sessionsEndpoint: '',
scenario: null
}
}

getConfiguration = () => {
var config = {
apiKey: this.state.apiKey,
autoTrackSessions: false
}

if (this.state.notifyEndpoint && this.state.sessionsEndpoint) {
config.endpoints = {
notify: this.state.notifyEndpoint,
sessions: this.state.sessionsEndpoint
}
}
return config
}

setScenario = newScenario => {
this.state.currentScenario = newScenario
}

clearPersistentData = () => {
NativeModules.BugsnagTestInterface.clearPersistentData()
}
console.reportErrorsAsExceptions = false

startScenario = () => {
console.log(`Running scenario: ${this.state.currentScenario}`)
const scenarioName = this.state.currentScenario
const configuration = this.getConfiguration()
const jsConfig = defaultJsConfig()
const scenario = new Scenarios[scenarioName](configuration, jsConfig)
console.log(` with config: ${JSON.stringify(configuration)} (native) and ${jsConfig} (js)`)
Navigation.setRoot({
root: {
stack: {
children: [
{
component: {
name: 'Home'
}
}
]
}
}
})
this.state.scenario = scenario
scenario.run()
}
export const AppScreen = () => {
useEffect(() => {
launchScenario()
}, [])

startBugsnag = () => {
console.log(`Starting Bugsnag for scenario: ${this.state.currentScenario}`)
const scenarioName = this.state.currentScenario
const configuration = this.getConfiguration()
const jsConfig = defaultJsConfig()
const scenario = new Scenarios[scenarioName](configuration, jsConfig)
console.log(` with config: ${JSON.stringify(configuration)} (native) and ${jsConfig} (js)`)
NativeModules.BugsnagTestInterface.startBugsnag(configuration)
.then(() => {
Bugsnag.start(jsConfig)
this.state.scenario = scenario
})
}

render () {
return (
<View style={styles.container}>
<View style={styles.child}>
<Text>React Native Navigation Test App</Text>
<TextInput style={styles.textInput}
placeholder='Scenario Name'
accessibilityLabel='scenario_name'
onChangeText={this.setScenario} />

<Button style={styles.clickyButton}
accessibilityLabel='clear_data'
title='Clear Persistent Data'
onPress={this.clearPersistentData}/>
<Button style={styles.clickyButton}
accessibilityLabel='start_bugsnag'
title='Start Bugsnag'
onPress={this.startBugsnag}/>
<Button style={styles.clickyButton}
accessibilityLabel='run_scenario'
title='Run scenario'
onPress={this.startScenario}/>

<Text>Configuration</Text>
<TextInput placeholder='Notify endpoint'
style={styles.textInput}
accessibilityLabel='notify_endpoint'
value={this.state.notifyEndpoint}
onChangeText={this.setNotifyEndpoint} />
<TextInput placeholder='Sessions endpoint'
style={styles.textInput}
accessibilityLabel='sessions_endpoint'
value={this.state.sessionsEndpoint}
onChangeText={this.setSessionsEndpoint} />
<TextInput placeholder='API key'
style={styles.textInput}
accessibilityLabel='api_key'
value={this.state.apiKey}
onChangeText={this.setApiKey} />
<Button style={styles.clickyButton}
accessibilityLabel='use_dashboard_endpoints'
title='Use dashboard endpoints'
onPress={this.useRealEndpoints}/>
</View>
return (
<SafeAreaView style={styles.container}>
<View>
<Text>React Native Navigation Test App</Text>
</View>
)
}
</SafeAreaView>
)
}

Navigation.registerComponent('App', () => AppScreen)
Expand All @@ -155,30 +42,6 @@ Navigation.events().registerAppLaunchedListener(async () => {

const styles = StyleSheet.create({
container: {
flexDirection: 'column',
flex: 1,
backgroundColor: '#eaefea',
alignItems: 'center',
justifyContent: 'center',
paddingTop: '15%'
},
child: {
flex: 1
},
textInput: {
backgroundColor: '#fff',
borderWidth: 0.5,
borderColor: '#000',
borderRadius: 4,
margin: 5,
padding: 5
},
clickyButton: {
backgroundColor: '#acbcef',
borderWidth: 0.5,
borderColor: '#000',
borderRadius: 4,
margin: 5,
padding: 5
}
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { getMazeRunnerAddress } from './ConfigFileReader'

const INTERVAL = 500

let mazeAddress

const delay = ms => new Promise(resolve => setTimeout(resolve, ms))

export async function getCurrentCommand () {
if (!mazeAddress) {
mazeAddress = await getMazeRunnerAddress()
}

const url = `http://${mazeAddress}/command`
console.error(`[Bugsnag CommandRunner] Fetching command from ${url}`)

while (true) {
try {
// eslint-disable-next-line no-undef
const response = await fetch(url)
const text = await response.text()
console.error(`[Bugsnag CommandRunner] Response from maze runner: ${text}`)

const command = JSON.parse(text)

// keep polling until a scenario command is received
if (command.action !== 'noop') {
console.error(`[Bugsnag CommandRunner] Received command from maze runner: ${JSON.stringify(command)}`)

return command
}
} catch (err) {
console.error(`[Bugsnag CommandRunner] Error fetching command from maze runner: ${err.message}`, err)
}

await delay(INTERVAL)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Platform } from 'react-native'
import { Dirs, FileSystem } from 'react-native-file-access'

const TIMEOUT = 60000

const delay = ms => new Promise(resolve => setTimeout(resolve, ms))

const getMazeRunnerAddress = async () => {
let configFilePath
const startTime = Date.now()

// poll for the config file to exist
while (Date.now() - startTime < TIMEOUT) {
const configFileDir = Platform.OS === 'android' ? '/data/local/tmp' : Dirs.DocumentDir
configFilePath = `${configFileDir}/fixture_config.json`
const configFileExists = await FileSystem.exists(configFilePath)

if (configFileExists) {
const configFile = await FileSystem.readFile(configFilePath)
console.error(`[Bugsnag ConfigFileReader] found config file at '${configFilePath}'. contents: ${configFile}`)
const config = JSON.parse(configFile)
return `${config.maze_address}`
}

await delay(500)
}

console.error(`[Bugsnag ConfigFileReader] no config file found at ${configFilePath}, falling back to 'localhost:9339'`)
return 'localhost:9339'
}

module.exports.getMazeRunnerAddress = getMazeRunnerAddress
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import * as Scenarios from '../Scenarios'
import { getCurrentCommand } from './CommandRunner'
import { NativeModules } from 'react-native'
import Bugsnag from '@bugsnag/react-native'

async function runScenario (scenarioName, apiKey, notifyEndpoint, sessionEndpoint, scenarioData, setScenario) {
console.error(`[Bugsnag ScenarioLauncher] running scenario: ${scenarioName}`)

const nativeConfig = {
apiKey,
autoTrackSessions: false,
endpoints: {
notify: notifyEndpoint,
sessions: sessionEndpoint
}
}

const jsConfig = {}

// create the scenario and allow it to modify the configuration
const scenario = new Scenarios[scenarioName](nativeConfig, jsConfig, scenarioData)

console.error(`[Bugsnag ScenarioLauncher] with config: ${JSON.stringify(nativeConfig)} (native) and ${JSON.stringify(jsConfig)} (js)`)

// clear persistent data
console.error('[Bugsnag ScenarioLauncher] clearing persistent data')
NativeModules.BugsnagTestInterface.clearPersistentData()

// start the native client
console.error('[Bugsnag ScenarioLauncher] starting native Bugsnag')
await NativeModules.BugsnagTestInterface.startBugsnag(nativeConfig)

// start the js client
console.error('[Bugsnag ScenarioLauncher] starting js Bugsnag')
Bugsnag.start(jsConfig)

// run the scenario
console.error('launching scenario')
setTimeout(() => {
scenario.run()
if (typeof setScenario === 'function') setScenario(scenario)
}, 1)
}

async function startBugsnag (scenarioName, apiKey, notifyEndpoint, sessionEndpoint, scenarioData) {
console.error(`[Bugsnag ScenarioLauncher] starting Bugsnag for scenario: ${scenarioName}`)
const nativeConfig = {
apiKey,
autoTrackSessions: false,
endpoints: {
notify: notifyEndpoint,
sessions: sessionEndpoint
}
}

const jsConfig = {}

// create the scenario and allow it to modify the configuration
// eslint-disable-next-line no-unused-vars
const scenario = new Scenarios[scenarioName](nativeConfig, jsConfig, scenarioData)

console.error(`[Bugsnag ScenarioLauncher] with config: ${JSON.stringify(nativeConfig)} (native) and ${JSON.stringify(jsConfig)} (js)`)

// start the native client
console.error('[Bugsnag ScenarioLauncher] starting native Bugsnag')
await NativeModules.BugsnagTestInterface.startBugsnag(nativeConfig)

// start the js client
console.error('[Bugsnag ScenarioLauncher] starting js Bugsnag')
Bugsnag.start(jsConfig)
}

export async function launchScenario (setScenario) {
const command = await getCurrentCommand()

switch (command.action) {
case 'run-scenario':
// eslint-disable-next-line no-return-await
return await runScenario(
command.scenario_name,
command.api_key,
command.notify,
command.sessions,
command.scenario_data,
setScenario
)

case 'start-bugsnag':
// eslint-disable-next-line no-return-await
return await startBugsnag(
command.scenario_name,
command.api_key,
command.notify,
command.sessions,
command.scenario_data
)

default:
throw new Error(`Unknown action '${command.action}'`)
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,27 @@
import Scenario from './Scenario'
import { Navigation } from 'react-native-navigation'
import BugsnagReactNativeNavigation from '@bugsnag/plugin-react-native-navigation'

export class ReactNavigationBreadcrumbsDisabledScenario extends Scenario {
constructor (configuration, jsConfig) {
super()
configuration.enabledBreadcrumbTypes = []
jsConfig.plugins = [new BugsnagReactNativeNavigation(Navigation)]
}

run () {
Navigation.setRoot({
root: {
stack: {
children: [
{
component: {
name: 'Home'
}
}
]
}
}
})
}
}
Loading

0 comments on commit 7db5a2d

Please sign in to comment.