-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add Expo config plugin (#5480)
* Preparations & Added the `app` plugin * Add perf monitoring plugin * Add crashlytics plugin * eslint ignore `plugin/build` dirs * Add tests READMEs
- Loading branch information
Showing
51 changed files
with
1,888 additions
and
8 deletions.
There are no files selected for viewing
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,5 +1,6 @@ | ||
src/version.js | ||
packages/**/node_modules/** | ||
packages/**/plugin/build/** | ||
node_modules | ||
scripts/ | ||
coverage | ||
|
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
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
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 @@ | ||
module.exports = require('./plugin/build'); |
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
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,19 @@ | ||
## Expo Config Plugin unit tests | ||
|
||
To test the changes to native code applied by config plugins, [snapshot tests](https://jestjs.io/docs/snapshot-testing) are used. Plugin test flow, in short: | ||
|
||
1. A test fixture is loaded. In this case, fixtures are template files (`build.gradle`, `AppDelegate.m` etc.) from [`expo-template-bare-minimum`](https://github.com/expo/expo/tree/master/templates/expo-template-bare-minimum). | ||
2. Plugin changes are applied (e.g. gradle dependency is added). | ||
3. Modified file is compared with previously saved snapshot. If they're equal, the test passes. If not, the test fails and the difference (actual vs expected) is shown. | ||
|
||
You can preview the snapshot files manually, by opening `__snapshots__/*.snap` files. | ||
|
||
### Updating the snapshots | ||
|
||
Snapshot tests are designed to ensure the plugin result will not change. In case you intentionally modified the plugin behavior (e.g. updated gradle dependency versions), you have to update the snapshots, otherwise the tests will fail. There are two ways to do it: | ||
|
||
- Update all snapshots by running `npm run tests:jest -u`. | ||
- Update snapshots interactively, one by one: | ||
1. Run `yarn tests:jest --watchAll` | ||
2. Press `i` to let `jest` display changes and prompt you for updating each snapshot. | ||
> This option is not available, when there are no failing snapshots |
167 changes: 167 additions & 0 deletions
167
packages/app/plugin/__tests__/__snapshots__/androidPlugin.test.ts.snap
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,167 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`Config Plugin Android Tests applies changes to app/build.gradle 1`] = ` | ||
"/* Example build.gradle file from https://github.com/expo/expo/blob/6ab0274b5cb9a9c223e0d453787a522b438b4fcb/templates/expo-template-bare-minimum/android/app/build.gradle */ | ||
apply plugin: \\"com.android.application\\" | ||
import com.android.build.OutputFile | ||
project.ext.react = [ | ||
enableHermes: false | ||
] | ||
apply from: '../../node_modules/react-native-unimodules/gradle.groovy' | ||
apply from: \\"../../node_modules/react-native/react.gradle\\" | ||
apply from: \\"../../node_modules/expo-constants/scripts/get-app-config-android.gradle\\" | ||
apply from: \\"../../node_modules/expo-updates/scripts/create-manifest-android.gradle\\" | ||
def enableSeparateBuildPerCPUArchitecture = false | ||
def enableProguardInReleaseBuilds = false | ||
def jscFlavor = 'org.webkit:android-jsc:+' | ||
def enableHermes = project.ext.react.get(\\"enableHermes\\", false); | ||
android { | ||
compileSdkVersion rootProject.ext.compileSdkVersion | ||
compileOptions { | ||
sourceCompatibility JavaVersion.VERSION_1_8 | ||
targetCompatibility JavaVersion.VERSION_1_8 | ||
} | ||
defaultConfig { | ||
applicationId \\"com.helloworld\\" | ||
minSdkVersion rootProject.ext.minSdkVersion | ||
targetSdkVersion rootProject.ext.targetSdkVersion | ||
versionCode 1 | ||
versionName \\"1.0\\" | ||
} | ||
splits { | ||
abi { | ||
reset() | ||
enable enableSeparateBuildPerCPUArchitecture | ||
universalApk false // If true, also generate a universal APK | ||
include \\"armeabi-v7a\\", \\"x86\\", \\"arm64-v8a\\", \\"x86_64\\" | ||
} | ||
} | ||
signingConfigs { | ||
debug { | ||
storeFile file('debug.keystore') | ||
storePassword 'android' | ||
keyAlias 'androiddebugkey' | ||
keyPassword 'android' | ||
} | ||
} | ||
buildTypes { | ||
debug { | ||
signingConfig signingConfigs.debug | ||
} | ||
release { | ||
// Caution! In production, you need to generate your own keystore file. | ||
// see https://reactnative.dev/docs/signed-apk-android. | ||
signingConfig signingConfigs.debug | ||
minifyEnabled enableProguardInReleaseBuilds | ||
proguardFiles getDefaultProguardFile(\\"proguard-android.txt\\"), \\"proguard-rules.pro\\" | ||
} | ||
} | ||
// applicationVariants are e.g. debug, release | ||
applicationVariants.all { variant -> | ||
variant.outputs.each { output -> | ||
// For each separate APK per architecture, set a unique version code as described here: | ||
// https://developer.android.com/studio/build/configure-apk-splits.html | ||
def versionCodes = [\\"armeabi-v7a\\": 1, \\"x86\\": 2, \\"arm64-v8a\\": 3, \\"x86_64\\": 4] | ||
def abi = output.getFilter(OutputFile.ABI) | ||
if (abi != null) { // null for the universal-debug, universal-release variants | ||
output.versionCodeOverride = | ||
versionCodes.get(abi) * 1048576 + defaultConfig.versionCode | ||
} | ||
} | ||
} | ||
} | ||
dependencies { | ||
implementation fileTree(dir: \\"libs\\", include: [\\"*.jar\\"]) | ||
//noinspection GradleDynamicVersion | ||
implementation \\"com.facebook.react:react-native:+\\" // From node_modules | ||
implementation \\"androidx.swiperefreshlayout:swiperefreshlayout:1.0.0\\" | ||
debugImplementation(\\"com.facebook.flipper:flipper:\${FLIPPER_VERSION}\\") { | ||
exclude group:'com.facebook.fbjni' | ||
} | ||
debugImplementation(\\"com.facebook.flipper:flipper-network-plugin:\${FLIPPER_VERSION}\\") { | ||
exclude group:'com.facebook.flipper' | ||
exclude group:'com.squareup.okhttp3', module:'okhttp' | ||
} | ||
debugImplementation(\\"com.facebook.flipper:flipper-fresco-plugin:\${FLIPPER_VERSION}\\") { | ||
exclude group:'com.facebook.flipper' | ||
} | ||
addUnimodulesDependencies() | ||
if (enableHermes) { | ||
def hermesPath = \\"../../node_modules/hermes-engine/android/\\"; | ||
debugImplementation files(hermesPath + \\"hermes-debug.aar\\") | ||
releaseImplementation files(hermesPath + \\"hermes-release.aar\\") | ||
} else { | ||
implementation jscFlavor | ||
} | ||
} | ||
// Run this once to be able to run the application with BUCK | ||
// puts all compile dependencies into folder libs for BUCK to use | ||
task copyDownloadableDepsToLibs(type: Copy) { | ||
from configurations.compile | ||
into 'libs' | ||
} | ||
apply from: file(\\"../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle\\"); applyNativeModulesAppBuildGradle(project) | ||
apply plugin: 'com.google.gms.google-services'" | ||
`; | ||
|
||
exports[`Config Plugin Android Tests applies changes to project build.gradle 1`] = ` | ||
"// Top-level build file where you can add configuration options common to all sub-projects/modules. | ||
buildscript { | ||
ext { | ||
buildToolsVersion = \\"29.0.3\\" | ||
minSdkVersion = 21 | ||
compileSdkVersion = 30 | ||
targetSdkVersion = 30 | ||
} | ||
repositories { | ||
google() | ||
jcenter() | ||
} | ||
dependencies { | ||
classpath 'com.google.gms:google-services:4.3.8' | ||
classpath(\\"com.android.tools.build:gradle:4.1.0\\") | ||
// NOTE: Do not place your application dependencies here; they belong | ||
// in the individual module build.gradle files | ||
} | ||
} | ||
allprojects { | ||
repositories { | ||
mavenLocal() | ||
maven { | ||
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm | ||
url(\\"$rootDir/../node_modules/react-native/android\\") | ||
} | ||
maven { | ||
// Android JSC is installed from npm | ||
url(\\"$rootDir/../node_modules/jsc-android/dist\\") | ||
} | ||
google() | ||
jcenter() | ||
maven { url 'https://www.jitpack.io' } | ||
} | ||
} | ||
" | ||
`; |
106 changes: 106 additions & 0 deletions
106
packages/app/plugin/__tests__/__snapshots__/iosPlugin.test.ts.snap
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,106 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`Config Plugin iOS Tests tests changes made to AppDelegate.m 1`] = ` | ||
"#import \\"AppDelegate.h\\" | ||
@import Firebase; | ||
#import <React/RCTBridge.h> | ||
#import <React/RCTBundleURLProvider.h> | ||
#import <React/RCTRootView.h> | ||
#import <React/RCTLinkingManager.h> | ||
#import <UMCore/UMModuleRegistry.h> | ||
#import <UMReactNativeAdapter/UMNativeModulesProxy.h> | ||
#import <UMReactNativeAdapter/UMModuleRegistryAdapter.h> | ||
#import <EXSplashScreen/EXSplashScreenService.h> | ||
#import <UMCore/UMModuleRegistryProvider.h> | ||
#if defined(FB_SONARKIT_ENABLED) && __has_include(<FlipperKit/FlipperClient.h>) | ||
#import <FlipperKit/FlipperClient.h> | ||
#import <FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.h> | ||
#import <FlipperKitUserDefaultsPlugin/FKUserDefaultsPlugin.h> | ||
#import <FlipperKitNetworkPlugin/FlipperKitNetworkPlugin.h> | ||
#import <SKIOSNetworkPlugin/SKIOSNetworkAdapter.h> | ||
#import <FlipperKitReactPlugin/FlipperKitReactPlugin.h> | ||
static void InitializeFlipper(UIApplication *application) { | ||
FlipperClient *client = [FlipperClient sharedClient]; | ||
SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults]; | ||
[client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]]; | ||
[client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]]; | ||
[client addPlugin:[FlipperKitReactPlugin new]]; | ||
[client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]]; | ||
[client start]; | ||
} | ||
#endif | ||
@interface AppDelegate () <RCTBridgeDelegate> | ||
@property (nonatomic, strong) UMModuleRegistryAdapter *moduleRegistryAdapter; | ||
@property (nonatomic, strong) NSDictionary *launchOptions; | ||
@end | ||
@implementation AppDelegate | ||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions | ||
{ | ||
#if defined(FB_SONARKIT_ENABLED) && __has_include(<FlipperKit/FlipperClient.h>) | ||
InitializeFlipper(application); | ||
#endif | ||
[FIRApp configure]; | ||
self.moduleRegistryAdapter = [[UMModuleRegistryAdapter alloc] initWithModuleRegistryProvider:[[UMModuleRegistryProvider alloc] init]]; | ||
self.launchOptions = launchOptions; | ||
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; | ||
#ifdef DEBUG | ||
[self initializeReactNativeApp]; | ||
#else | ||
EXUpdatesAppController *controller = [EXUpdatesAppController sharedInstance]; | ||
controller.delegate = self; | ||
[controller startAndShowLaunchScreen:self.window]; | ||
#endif | ||
[super application:application didFinishLaunchingWithOptions:launchOptions]; | ||
return YES; | ||
} | ||
- (RCTBridge *)initializeReactNativeApp | ||
{ | ||
RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:self.launchOptions]; | ||
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@\\"main\\" initialProperties:nil]; | ||
rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1]; | ||
UIViewController *rootViewController = [UIViewController new]; | ||
rootViewController.view = rootView; | ||
self.window.rootViewController = rootViewController; | ||
[self.window makeKeyAndVisible]; | ||
return bridge; | ||
} | ||
- (NSArray<id<RCTBridgeModule>> *)extraModulesForBridge:(RCTBridge *)bridge | ||
{ | ||
NSArray<id<RCTBridgeModule>> *extraModules = [_moduleRegistryAdapter extraModulesForBridge:bridge]; | ||
// If you'd like to export some custom RCTBridgeModules that are not Expo modules, add them here! | ||
return extraModules; | ||
} | ||
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge { | ||
#ifdef DEBUG | ||
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@\\"index\\" fallbackResource:nil]; | ||
#else | ||
return [[EXUpdatesAppController sharedInstance] launchAssetUrl]; | ||
#endif | ||
} | ||
- (void)appController:(EXUpdatesAppController *)appController didStartWithSuccess:(BOOL)success { | ||
appController.bridge = [self initializeReactNativeApp]; | ||
EXSplashScreenService *splashScreenService = (EXSplashScreenService *)[UMModuleRegistryProvider getSingletonModuleForClass:[EXSplashScreenService class]]; | ||
[splashScreenService showSplashScreenFor:self.window.rootViewController]; | ||
} | ||
@end | ||
" | ||
`; |
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,31 @@ | ||
import fs from 'fs/promises'; | ||
import path from 'path'; | ||
|
||
import { applyPlugin } from '../src/android/applyPlugin'; | ||
import { setBuildscriptDependency } from '../src/android/buildscriptDependency'; | ||
|
||
describe('Config Plugin Android Tests', function () { | ||
let appBuildGradle: string; | ||
let projectBuildGradle: string; | ||
|
||
beforeAll(async function () { | ||
projectBuildGradle = await fs.readFile( | ||
path.resolve(__dirname, './fixtures/project_build.gradle'), | ||
{ encoding: 'utf-8' }, | ||
); | ||
|
||
appBuildGradle = await fs.readFile(path.resolve(__dirname, './fixtures/app_build.gradle'), { | ||
encoding: 'utf-8', | ||
}); | ||
}); | ||
|
||
it('applies changes to project build.gradle', async function () { | ||
const result = setBuildscriptDependency(projectBuildGradle); | ||
expect(result).toMatchSnapshot(); | ||
}); | ||
|
||
it('applies changes to app/build.gradle', async function () { | ||
const result = applyPlugin(appBuildGradle); | ||
expect(result).toMatchSnapshot(); | ||
}); | ||
}); |
Oops, something went wrong.
832057c
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.
Successfully deployed to the following URLs:
react-native-firebase – ./
react-native-firebase-invertase.vercel.app
rnfirebase.io
react-native-firebase-git-master-invertase.vercel.app
react-native-firebase.vercel.app