Skip to content

Commit

Permalink
Merge pull request #808 from bugsnag/expo-cli-version-compat
Browse files Browse the repository at this point in the history
fix(expo-cli): Ensure appropriate code is inserted based on Bugsnag version
  • Loading branch information
bengourley authored Apr 21, 2020
2 parents 530fb9a + 1bd1738 commit ac70310
Show file tree
Hide file tree
Showing 15 changed files with 213 additions and 26 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Fixed
- Ensure Expo delivery logs event details correctly (instead of `undefined`) [#804](https://github.com/bugsnag/bugsnag-js/pull/804)
- Ensure Expo cli inserts correct code depending on the version of the notifier [#808](https://github.com/bugsnag/bugsnag-js/pull/808)

## 7.0.0 (2020-04-14)

Expand Down
24 changes: 2 additions & 22 deletions packages/expo-cli/commands/install.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ const install = require('../lib/install')
const { onCancel } = require('../lib/utils')
const { blue } = require('kleur')
const semver = require('semver')
const detectInstalled = require('../lib/detect-installed')

module.exports = async (argv, globalOpts) => {
const projectRoot = globalOpts['project-root']
const alreadyInstalled = await checkManifest(projectRoot)
const alreadyInstalled = await detectInstalled(projectRoot)
const isWanted = await confirmWanted(alreadyInstalled, projectRoot)
if (isWanted) {
const version = await selectVersion(projectRoot)
Expand Down Expand Up @@ -44,27 +45,6 @@ const withTool = async (root) => {
}, { onCancel })).tool
}

const keys = maybeObj => {
try {
return Object.keys(maybeObj)
} catch (e) {
return []
}
}

const checkManifest = async (dir) => {
try {
const pkg = JSON.parse(await promisify(readFile)(join(dir, 'package.json'), 'utf8'))
const allDeps = []
.concat(keys(pkg.dependencies))
.concat(keys(pkg.devDependencies))
.concat(keys(pkg.peerDependencies))
return allDeps.includes('@bugsnag/expo')
} catch (e) {
throw new Error('Could not load package.json. Is this the project root?')
}
}

const selectVersion = async (dir) => {
try {
const pkg = JSON.parse(await promisify(readFile)(join(dir, 'package.json'), 'utf8'))
Expand Down
13 changes: 13 additions & 0 deletions packages/expo-cli/lib/detect-installed.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const { promisify } = require('util')
const { readFile } = require('fs')
const { join } = require('path')

module.exports = async (dir) => {
try {
const pkg = JSON.parse(await promisify(readFile)(join(dir, 'package.json'), 'utf8'))
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies, ...pkg.peerDependencies }
return allDeps['@bugsnag/expo']
} catch (e) {
throw new Error('Could not load package.json. Is this the project root?')
}
}
14 changes: 11 additions & 3 deletions packages/expo-cli/lib/insert.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
const { join } = require('path')
const { readFile, writeFile } = require('fs')
const { promisify } = require('util')
const detectInstalled = require('./detect-installed')
const semver = require('semver')

const importRe = /from ["']@bugsnag\/expo["']/
const requireRe = /require\(["']@bugsnag\/expo["']\)/
Expand All @@ -9,10 +11,12 @@ module.exports = async (projectRoot) => {
try {
const appJsPath = join(projectRoot, 'App.js')
const appJs = await promisify(readFile)(appJsPath, 'utf8')
const manifestRange = await detectInstalled(projectRoot)
const isPostV7 = !manifestRange || semver.satisfies('7.0.0', manifestRange)
if (importRe.test(appJs) || requireRe.test(appJs)) {
return '@bugsnag/expo is already imported in App.js'
}
await promisify(writeFile)(appJsPath, `${module.exports.code}\n${appJs}`, 'utf8')
await promisify(writeFile)(appJsPath, `${module.exports.code[isPostV7 ? 'postV7' : 'preV7']}\n${appJs}`, 'utf8')
} catch (e) {
// swallow and rethrow for errors that we can produce better messaging for
if (e.code === 'ENOENT') {
Expand All @@ -22,7 +26,11 @@ module.exports = async (projectRoot) => {
}
}

module.exports.code =
`import Bugsnag from '@bugsnag/expo';
module.exports.code = {
preV7: `import bugsnag from '@bugsnag/expo';
const bugsnagClient = bugsnag();
`,
postV7: `import Bugsnag from '@bugsnag/expo';
Bugsnag.start();
`
}
22 changes: 22 additions & 0 deletions packages/expo-cli/lib/test/detect-installed.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/* global describe, it, expect */

const prepareFixture = require('./lib/prepare-fixture')
const detectInstalled = require('../detect-installed')

describe('expo-cli: detect-installed', () => {
it('should work on a fresh project', async () => {
const projectRoot = await prepareFixture('blank-00')
const version = await detectInstalled(projectRoot)
expect(version).toBe(undefined)
})

it('should work on project with Bugsnag installed', async () => {
const projectRoot = await prepareFixture('already-configured-00')
const version = await detectInstalled(projectRoot)
expect(version).toBe('^7.0.0')

const projectRoot2 = await prepareFixture('already-configured-01')
const version2 = await detectInstalled(projectRoot2)
expect(version2).toBe('7.0.0')
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "bugsnag-test-fixture-00",
"private": "true",
"version": "0.0.0",
"dependencies": {
"@bugsnag/expo": "^7.0.0"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "bugsnag-test-fixture-01",
"private": "true",
"version": "0.0.0",
"dependencies": {
"@bugsnag/expo": "7.0.0"
}
}
24 changes: 24 additions & 0 deletions packages/expo-cli/lib/test/fixtures/already-configured-02/App.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const Bugsnag = require('@bugsnag/expo')
const React = require('react')
const { StyleSheet, Text, View } = require('react-native')

Bugsnag.start()

export default class App extends React.Component {
render () {
return (
<View style={styles.container}>
<Text>Hello Expo!</Text>
</View>
)
}
}

const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center'
}
})
39 changes: 39 additions & 0 deletions packages/expo-cli/lib/test/fixtures/already-configured-02/app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"expo": {
"name": "Bugsnag test fixture",
"slug": "bugsnag-test-fixture",
"privacy": "unlisted",
"sdkVersion": "32.0.0",
"platforms": [
"ios",
"android"
],
"version": "1.0.0",
"orientation": "portrait",
"icon": "./assets/icon.png",
"splash": {
"image": "./assets/splash.png",
"resizeMode": "contain",
"backgroundColor": "#ffffff"
},
"updates": {
"fallbackToCacheTimeout": 0
},
"assetBundlePatterns": [
"**/*"
],
"extra": {
"bugsnag": {
"apiKey": "XoXoXoXoXoXo"
}
},
"hooks": {
"postPublish": [
{
"file": "@bugsnag/expo/hooks/post-publish.js",
"config": {}
}
]
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "bugsnag-test-fixture-02",
"private": "true",
"version": "0.0.0",
"dependencies": {
"@bugsnag/expo": "6.5.1"
}
}
21 changes: 21 additions & 0 deletions packages/expo-cli/lib/test/fixtures/already-installed-00/App.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const React = require('react')
const { StyleSheet, Text, View } = require('react-native')

export default class App extends React.Component {
render () {
return (
<View style={styles.container}>
<Text>Hello Expo!</Text>
</View>
)
}
}

const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center'
}
})
39 changes: 39 additions & 0 deletions packages/expo-cli/lib/test/fixtures/already-installed-00/app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"expo": {
"name": "Bugsnag test fixture",
"slug": "bugsnag-test-fixture",
"privacy": "unlisted",
"sdkVersion": "32.0.0",
"platforms": [
"ios",
"android"
],
"version": "1.0.0",
"orientation": "portrait",
"icon": "./assets/icon.png",
"splash": {
"image": "./assets/splash.png",
"resizeMode": "contain",
"backgroundColor": "#ffffff"
},
"updates": {
"fallbackToCacheTimeout": 0
},
"assetBundlePatterns": [
"**/*"
],
"extra": {
"bugsnag": {
"apiKey": "XoXoXoXoXoXo"
}
},
"hooks": {
"postPublish": [
{
"file": "@bugsnag/expo/hooks/post-publish.js",
"config": {}
}
]
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "bugsnag-test-fixture-03",
"private": "true",
"version": "0.0.0",
"dependencies": {
"@bugsnag/expo": "^6.5.1"
}
}
2 changes: 1 addition & 1 deletion packages/expo-cli/lib/test/fixtures/blank-00/package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "bugsnag-test-fixture",
"name": "bugsnag-test-fixture-04",
"private": "true",
"version": "0.0.0"
}
8 changes: 8 additions & 0 deletions packages/expo-cli/lib/test/insert.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,12 @@ describe('expo-cli: insert', () => {
expect(e.message).toMatch(/The "path" argument must be of type string/)
}
})

it('inserts correct code for pre v7 versions of Bugsnag', async () => {
const projectRoot = await prepareFixture('already-installed-00')
const msg = await insert(projectRoot)
expect(msg).toBe(undefined)
const appJs = await promisify(readFile)(`${projectRoot}/App.js`, 'utf8')
expect(appJs).toMatch(/^import bugsnag from '@bugsnag\/expo';\sconst bugsnagClient = bugsnag\(\);\s/)
})
})

0 comments on commit ac70310

Please sign in to comment.