-
Notifications
You must be signed in to change notification settings - Fork 24.4k
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
[general][enhancement] Move JS-native version check to its own module + unit tests + prefix Obj-C macro w/RCT #16403
Changes from all commits
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,54 @@ | ||
/** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* @providesModule ReactNativeVersionCheck | ||
* @flow | ||
* @format | ||
*/ | ||
'use strict'; | ||
|
||
const {PlatformConstants} = require('NativeModules'); | ||
const ReactNativeVersion = require('ReactNativeVersion'); | ||
|
||
/** | ||
* Checks that the version of this React Native JS is compatible with the native | ||
* code, throwing an error if it isn't. | ||
* | ||
* The existence of this module is part of the public interface of React Native | ||
* even though it is used only internally within React Native. React Native | ||
* implementations for other platforms (ex: Windows) may override this module | ||
* and rely on its existence as a separate module. | ||
*/ | ||
exports.checkVersions = function checkVersions(): void { | ||
if (!PlatformConstants) { | ||
return; | ||
} | ||
|
||
const nativeVersion = PlatformConstants.reactNativeVersion; | ||
if ( | ||
ReactNativeVersion.version.major !== nativeVersion.major || | ||
ReactNativeVersion.version.minor !== nativeVersion.minor | ||
) { | ||
throw new Error( | ||
`React Native version mismatch.\n\nJavaScript version: ${_formatVersion( | ||
ReactNativeVersion.version, | ||
)}\n` + | ||
`Native version: ${_formatVersion(nativeVersion)}\n\n` + | ||
'Make sure that you have rebuilt the native code. If the problem ' + | ||
'persists try clearing the Watchman and packager caches with ' + | ||
'`watchman watch-del-all && react-native start --reset-cache`.', | ||
); | ||
} | ||
}; | ||
|
||
function _formatVersion(version): string { | ||
return ( | ||
`${version.major}.${version.minor}.${version.patch}` + | ||
(version.prerelease !== null ? `-${version.prerelease}` : '') | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
/** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
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. Same |
||
* | ||
* @format | ||
*/ | ||
'use strict'; | ||
|
||
describe('checkVersion', () => { | ||
describe('in development', () => { | ||
_setDevelopmentModeForTests(true); | ||
_defineCheckVersionTests(); | ||
}); | ||
|
||
describe('in production', () => { | ||
_setDevelopmentModeForTests(false); | ||
_defineCheckVersionTests(); | ||
}); | ||
}); | ||
|
||
function _setDevelopmentModeForTests(dev) { | ||
let originalDev; | ||
|
||
beforeAll(() => { | ||
originalDev = global.__DEV__; | ||
global.__DEV__ = dev; | ||
}); | ||
|
||
afterAll(() => { | ||
global.__DEV__ = originalDev; | ||
}); | ||
} | ||
|
||
function _defineCheckVersionTests() { | ||
afterEach(() => { | ||
jest.resetModules(); | ||
}); | ||
|
||
it('passes when all the versions are zero', () => { | ||
jest.dontMock('ReactNativeVersion'); | ||
_mockNativeVersion(0, 0, 0); | ||
|
||
const ReactNativeVersion = require('ReactNativeVersion'); | ||
const ReactNativeVersionCheck = require('ReactNativeVersionCheck'); | ||
expect(ReactNativeVersion).toMatchObject({ | ||
version: {major: 0, minor: 0, patch: 0, prerelease: null}, | ||
}); | ||
expect(() => ReactNativeVersionCheck.checkVersions()).not.toThrow(); | ||
}); | ||
|
||
it('passes when the minor matches when the major is zero', () => { | ||
_mockJsVersion(0, 1, 0); | ||
_mockNativeVersion(0, 1, 0); | ||
|
||
const ReactNativeVersionCheck = require('ReactNativeVersionCheck'); | ||
expect(() => ReactNativeVersionCheck.checkVersions()).not.toThrow(); | ||
}); | ||
|
||
it("throws when the minor doesn't match when the major is zero", () => { | ||
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. Can you add a test for major don't match too so we cover all cases 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. Yep, will do. We can't add a test for checking that the major matches since we don't have that logic right now, we'll need to add it later if/when we shift RN versions over by one point (RN 51, RN 52, etc...). |
||
_mockJsVersion(0, 1, 0); | ||
_mockNativeVersion(0, 2, 0); | ||
|
||
const ReactNativeVersionCheck = require('ReactNativeVersionCheck'); | ||
expect(() => ReactNativeVersionCheck.checkVersions()).toThrowError( | ||
/React Native version mismatch/, | ||
); | ||
}); | ||
|
||
it("throws when the major doesn't match", () => { | ||
_mockJsVersion(1, 0, 0); | ||
_mockNativeVersion(2, 0, 0); | ||
|
||
const ReactNativeVersionCheck = require('ReactNativeVersionCheck'); | ||
expect(() => ReactNativeVersionCheck.checkVersions()).toThrowError( | ||
/React Native version mismatch/, | ||
); | ||
}); | ||
|
||
it("doesn't throw if the patch doesn't match", () => { | ||
_mockJsVersion(0, 1, 0); | ||
_mockNativeVersion(0, 1, 2); | ||
|
||
const ReactNativeVersionCheck = require('ReactNativeVersionCheck'); | ||
expect(() => ReactNativeVersionCheck.checkVersions()).not.toThrow(); | ||
}); | ||
|
||
it("doesn't throw if the prerelease doesn't match", () => { | ||
_mockJsVersion(0, 1, 0, 'beta.0'); | ||
_mockNativeVersion(0, 1, 0, 'alpha.1'); | ||
|
||
const ReactNativeVersionCheck = require('ReactNativeVersionCheck'); | ||
expect(() => ReactNativeVersionCheck.checkVersions()).not.toThrow(); | ||
}); | ||
} | ||
|
||
function _mockJsVersion(major = 0, minor = 0, patch = 0, prerelease = null) { | ||
jest.doMock('ReactNativeVersion', () => ({ | ||
version: {major, minor, patch, prerelease}, | ||
})); | ||
} | ||
|
||
function _mockNativeVersion( | ||
major = 0, | ||
minor = 0, | ||
patch = 0, | ||
prerelease = null, | ||
) { | ||
jest.doMock('NativeModules', () => ({ | ||
PlatformConstants: { | ||
reactNativeVersion: {major, minor, patch, prerelease}, | ||
}, | ||
})); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can add
@format
pragma to tell tools this file uses prettier.