-
Notifications
You must be signed in to change notification settings - Fork 253
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
launch navigation scenarios via commands
- Loading branch information
1 parent
faa4ed9
commit c43bcff
Showing
7 changed files
with
226 additions
and
208 deletions.
There are no files selected for viewing
199 changes: 17 additions & 182 deletions
199
test/react-native/features/fixtures/app/react_navigation_js/app/App.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,200 +1,35 @@ | ||
import React, { Component } from 'react' | ||
import Bugsnag from '@bugsnag/react-native' | ||
import BugsnagPluginReactNavigation from '@bugsnag/plugin-react-navigation' | ||
import { NavigationContainer } from '@react-navigation/native' | ||
import * as Scenarios from './Scenarios' | ||
import React, { useState, useEffect } from 'react' | ||
import { | ||
View, | ||
Text, | ||
TextInput, | ||
Button, | ||
StyleSheet, | ||
NativeModules | ||
SafeAreaView | ||
} from 'react-native' | ||
|
||
const defaultJsConfig = () => ({ | ||
plugins: [new BugsnagPluginReactNavigation()] | ||
}) | ||
|
||
export default class App extends Component { | ||
constructor (props) { | ||
super(props) | ||
this.state = { | ||
currentScenario: '', | ||
apiKey: '12312312312312312312312312312312', | ||
notifyEndpoint: '', | ||
sessionsEndpoint: '', | ||
scenario: null, | ||
bugsnagStarted: false | ||
} | ||
} | ||
|
||
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.setState(() => ({ currentScenario: newScenario })) | ||
} | ||
|
||
setApiKey = newApiKey => { | ||
this.setState(() => ({ apiKey: newApiKey })) | ||
} | ||
|
||
setNotifyEndpoint = newNotifyEndpoint => { | ||
this.setState(() => ({ notifyEndpoint: newNotifyEndpoint })) | ||
} | ||
|
||
setSessionsEndpoint = newSessionsEndpoint => { | ||
this.setState(() => ({ sessionsEndpoint: newSessionsEndpoint })) | ||
} | ||
|
||
useRealEndpoints = () => { | ||
this.setState({ notifyEndpoint: 'https://notify.bugsnag.com' }) | ||
this.setState({ sessionsEndpoint: 'https://sessions.bugsnag.com' }) | ||
} | ||
|
||
clearPersistentData = () => { | ||
NativeModules.BugsnagTestInterface.clearPersistentData() | ||
} | ||
|
||
pollBugsnagStarted = () => { | ||
setTimeout(() => { | ||
if (Bugsnag.isStarted()) { | ||
this.setState(() => ({ bugsnagStarted: true })) | ||
} else { | ||
this.pollBugsnagStarted() | ||
} | ||
}, 50) | ||
} | ||
import { launchScenario } from './lib/ScenarioLauncher' | ||
|
||
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 ${JSON.stringify(jsConfig)} (js)`) | ||
this.setState({ scenario: scenario }) | ||
this.pollBugsnagStarted() | ||
scenario.run() | ||
} | ||
const App = () => { | ||
const [scenario, setScenario] = useState(null) | ||
|
||
startBugsnag = () => { | ||
console.log(`Starting Bugsnag for scenario: ${this.state.currentScenario}`) | ||
const scenarioName = this.state.currentScenario | ||
const configuration = this.getConfiguration() | ||
const jsConfig = defaultJsConfig() | ||
// eslint-disable-next-line no-new | ||
new Scenarios[scenarioName](configuration, jsConfig) | ||
console.log(` with config: ${JSON.stringify(configuration)} (native) and ${JSON.stringify(jsConfig)} (js)`) | ||
NativeModules.BugsnagTestInterface.startBugsnag(configuration) | ||
.then(() => { | ||
Bugsnag.start(jsConfig) | ||
}) | ||
} | ||
useEffect(() => { | ||
launchScenario(setScenario) | ||
}, []) | ||
|
||
waiting () { | ||
return ( | ||
<View style={styles.container}> | ||
<View style={styles.child}> | ||
return ( | ||
scenario ? scenario() : ( | ||
<SafeAreaView style={styles.container}> | ||
<View> | ||
<Text>React 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 only' | ||
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> | ||
</View> | ||
</SafeAreaView> | ||
) | ||
} | ||
|
||
ready () { | ||
const BugsnagNavigationContainer = Bugsnag.getPlugin('reactNavigation').createNavigationContainer(NavigationContainer) | ||
return this.state.bugsnagStarted ? ( | ||
<BugsnagNavigationContainer> | ||
{this.state.scenario.view()} | ||
</BugsnagNavigationContainer> | ||
) : null | ||
} | ||
|
||
render () { | ||
return this.state.scenario | ||
? this.ready() | ||
: this.waiting() | ||
} | ||
}; | ||
) | ||
} | ||
|
||
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 | ||
} | ||
}) | ||
|
||
export default App |
38 changes: 38 additions & 0 deletions
38
test/react-native/features/fixtures/app/react_navigation_js/app/lib/CommandRunner.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
test/react-native/features/fixtures/app/react_navigation_js/app/lib/ConfigFileReader.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
101 changes: 101 additions & 0 deletions
101
test/react-native/features/fixtures/app/react_navigation_js/app/lib/ScenarioLauncher.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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' && scenario.view) setScenario(scenario.view) | ||
}, 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}'`) | ||
} | ||
} |
Oops, something went wrong.