Use Gradle Lazy API (#32214)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/32214 This Diff updates part of the Gradle plugin to use the Gradle Lazy Api (mostly `Property` classes). This will defer the time when those value are accessed from configuration to execution phase. So far I've converted the `Extension` class that should be our primary entry point to the public API. I haven't converted the tasks as well, therefore we have several `.get()` calls around now. I'll take care of them once I go over the Tasks file as well. Moreover, I added some documentation to the Extention properties, as those will show up in the `build.gradle` autocompletion for our users. On the API point of view, this is going to be a breaking change for users that are testing the Gradle plugin AND are on Gradle Kotlin DSL (which I believe are really limited so I don't think is a problem at the moment). Users relying on `react.gradle` are unaffected. Changelog: [Internal] [Changed] - Use Gradle Lazy API Reviewed By: ShikaSD Differential Revision: D30902517 fbshipit-source-id: 5af4625e901b82f4b1c65bd631aa4bb9b505b2d0
This commit is contained in:
Родитель
c8873fc43a
Коммит
578cba2338
|
@ -9,29 +9,147 @@ package com.facebook.react
|
||||||
|
|
||||||
import com.android.build.gradle.api.BaseVariant
|
import com.android.build.gradle.api.BaseVariant
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import javax.inject.Inject
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.file.DirectoryProperty
|
||||||
|
import org.gradle.api.file.RegularFileProperty
|
||||||
|
import org.gradle.api.provider.ListProperty
|
||||||
|
import org.gradle.api.provider.MapProperty
|
||||||
|
import org.gradle.api.provider.Property
|
||||||
|
|
||||||
open class ReactAppExtension(private val project: Project) {
|
abstract class ReactAppExtension @Inject constructor(project: Project) {
|
||||||
var applyAppPlugin: Boolean = false
|
|
||||||
var composeSourceMapsPath: String = "node_modules/react-native/scripts/compose-source-maps.js"
|
private val objects = project.objects
|
||||||
var bundleAssetName: String = "index.android.bundle"
|
|
||||||
var entryFile: File? = null
|
/**
|
||||||
var bundleCommand: String = "bundle"
|
* Whether the React App plugin should apply its logic or not. Set it to false if you're still
|
||||||
var reactRoot: File = File(project.projectDir, "../../")
|
* relying on `react.gradle` to configure your build. Default: false
|
||||||
var inputExcludes: List<String> = listOf("android/**", "ios/**")
|
*/
|
||||||
var bundleConfig: String? = null
|
val applyAppPlugin: Property<Boolean> = objects.property(Boolean::class.java).convention(false)
|
||||||
var enableVmCleanup: Boolean = true
|
|
||||||
var hermesCommand: String = "node_modules/hermes-engine/%OS-BIN%/hermesc"
|
/**
|
||||||
var cliPath: String? = null
|
* The path to the react root folder. This is the path to the root folder where the `node_modules`
|
||||||
var nodeExecutableAndArgs: List<String> = listOf("node")
|
* folder is present. All the CLI commands will be invoked from this folder as working directory.
|
||||||
var enableHermes: Boolean = false
|
*
|
||||||
var enableHermesForVariant: (BaseVariant) -> Boolean = { enableHermes }
|
* Default: $projectDir/../../
|
||||||
var devDisabledInVariants: List<String> = emptyList()
|
*/
|
||||||
|
val reactRoot: DirectoryProperty =
|
||||||
|
objects.directoryProperty().convention(project.layout.projectDirectory.dir("../../"))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The path to the JS entry file. If not specified, the plugin will try to resolve it using a list
|
||||||
|
* of known locations (e.g. `index.android.js`, `index.js`, etc.).
|
||||||
|
*/
|
||||||
|
val entryFile: RegularFileProperty = objects.fileProperty()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The path to the React Native CLI. If not specified, the plugin will try to resolve it looking
|
||||||
|
* for `react-native` CLI inside `node_modules` in [reactRoot].
|
||||||
|
*/
|
||||||
|
val cliPath: Property<String> = objects.property(String::class.java)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The path to the Node executable and extra args. By default it assumes that you have `node`
|
||||||
|
* installed and configured in your $PATH. Default: ["node"]
|
||||||
|
*/
|
||||||
|
val nodeExecutableAndArgs: ListProperty<String> =
|
||||||
|
objects.listProperty(String::class.java).convention(listOf("node"))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The command to use to invoke bundle. Default is `bundle` and will be invoked on [reactRoot].
|
||||||
|
*/
|
||||||
|
val bundleCommand: Property<String> = objects.property(String::class.java).convention("bundle")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom configuration for the [bundleCommand]. If provided it will be passed over with a
|
||||||
|
* `--config` flag to the bundle command.
|
||||||
|
*/
|
||||||
|
val bundleConfig: Property<String> = objects.property(String::class.java)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Bundle Asset name. This name will be used also for deriving other bundle outputs such as
|
||||||
|
* the packager source map, the compiler source map and the output source map file.
|
||||||
|
*
|
||||||
|
* Default: index.android.bundle
|
||||||
|
*/
|
||||||
|
val bundleAssetName: Property<String> =
|
||||||
|
objects.property(String::class.java).convention("index.android.bundle")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Variant Name to File destination map that allows to specify where is the resource dir for a
|
||||||
|
* specific variant. If a value is supplied, the plugin will copy the bundled resource for that
|
||||||
|
* variant from `generated/res/react/<variant>` into the custom specified location. Default: {}
|
||||||
|
*/
|
||||||
|
val resourcesDir: MapProperty<String, File> =
|
||||||
|
objects.mapProperty(String::class.java, File::class.java).convention(emptyMap())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Variant Name to File destination map that allows to specify where is the asset dir for a
|
||||||
|
* specific variant. If a value is supplied, the plugin will copy the bundled JS for that variant
|
||||||
|
* from `generated/assets/react/<variant>` into the custom specified location. Default: {}
|
||||||
|
*/
|
||||||
|
val jsBundleDir: MapProperty<String, File> =
|
||||||
|
objects.mapProperty(String::class.java, File::class.java).convention(emptyMap())
|
||||||
|
|
||||||
|
/** ANT-style excludes for the bundle command. Default: ["android / **", "ios / **"] */
|
||||||
|
val inputExcludes: ListProperty<String> =
|
||||||
|
objects.listProperty(String::class.java).convention(listOf("android/**", "ios/**"))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggles the VM Cleanup step. If enabled, before the bundle task we will clean up all the
|
||||||
|
* unnecessary files. If disabled, the developers will have to manually cleanup the files.
|
||||||
|
* Default: true
|
||||||
|
*/
|
||||||
|
val enableVmCleanup: Property<Boolean> = objects.property(Boolean::class.java).convention(true)
|
||||||
|
|
||||||
|
/** Extra args that will be passed to the [bundleCommand] Default: [] */
|
||||||
|
val extraPackagerArgs: ListProperty<String> =
|
||||||
|
objects.listProperty(String::class.java).convention(emptyList())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows to disable dev mode for certain variants. That's useful if you have a production variant
|
||||||
|
* (say `canary`) where you don't want dev mode to be enabled. Default: []
|
||||||
|
*/
|
||||||
|
val devDisabledInVariants: ListProperty<String> =
|
||||||
|
objects.listProperty(String::class.java).convention(emptyList())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Variant Name to Boolean map that allows to toggle the bundle command for a specific variant.
|
||||||
|
* Default: {}
|
||||||
|
*/
|
||||||
// todo maybe lambda as for hermes?
|
// todo maybe lambda as for hermes?
|
||||||
var bundleIn: Map<String, Boolean> = emptyMap()
|
val bundleIn: MapProperty<String, Boolean> =
|
||||||
var extraPackagerArgs: List<String> = emptyList()
|
objects.mapProperty(String::class.java, Boolean::class.java).convention(emptyMap())
|
||||||
var hermesFlagsDebug: List<String> = emptyList()
|
|
||||||
var hermesFlagsRelease: List<String> = listOf("-O", "-output-source-map")
|
/** Hermes Config */
|
||||||
var resourcesDir: Map<String, File> = emptyMap()
|
|
||||||
var jsBundleDir: Map<String, File> = emptyMap()
|
/** The command to use to invoke hermes. Default is `hermesc` for the correct OS. */
|
||||||
|
val hermesCommand: Property<String> =
|
||||||
|
objects.property(String::class.java).convention("node_modules/hermes-engine/%OS-BIN%/hermesc")
|
||||||
|
|
||||||
|
/** Toggle Hermes for the whole build. Default: false */
|
||||||
|
val enableHermes: Property<Boolean> = objects.property(Boolean::class.java).convention(false)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Functional interface to selectively enabled Hermes only on specific [BaseVariant] Default: will
|
||||||
|
* return [enableHermes] for all the variants.
|
||||||
|
*/
|
||||||
|
var enableHermesForVariant: (BaseVariant) -> Boolean = { enableHermes.get() }
|
||||||
|
|
||||||
|
/** Flags to pass to Hermes for Debug variants. Default: [] */
|
||||||
|
val hermesFlagsDebug: ListProperty<String> =
|
||||||
|
objects.listProperty(String::class.java).convention(emptyList())
|
||||||
|
|
||||||
|
/** Flags to pass to Hermes for Release variants. Default: ["-O", "-output-source-map"] */
|
||||||
|
val hermesFlagsRelease: ListProperty<String> =
|
||||||
|
objects.listProperty(String::class.java).convention(listOf("-O", "-output-source-map"))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The path to the Compose Source Map script. Default:
|
||||||
|
* "node_modules/react-native/scripts/compose-source-maps.js"
|
||||||
|
*/
|
||||||
|
val composeSourceMapsPath: Property<String> =
|
||||||
|
objects
|
||||||
|
.property(String::class.java)
|
||||||
|
.convention("node_modules/react-native/scripts/compose-source-maps.js")
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ class ReactAppPlugin : Plugin<Project> {
|
||||||
private fun applyAppPlugin(project: Project) {
|
private fun applyAppPlugin(project: Project) {
|
||||||
val config = project.extensions.create("reactApp", ReactAppExtension::class.java, project)
|
val config = project.extensions.create("reactApp", ReactAppExtension::class.java, project)
|
||||||
|
|
||||||
if (config.applyAppPlugin) {
|
if (config.applyAppPlugin.getOrElse(false)) {
|
||||||
project.afterEvaluate {
|
project.afterEvaluate {
|
||||||
val androidConfiguration = project.extensions.getByType(BaseExtension::class.java)
|
val androidConfiguration = project.extensions.getByType(BaseExtension::class.java)
|
||||||
project.configureDevPorts(androidConfiguration)
|
project.configureDevPorts(androidConfiguration)
|
||||||
|
|
|
@ -32,17 +32,16 @@ internal fun Project.configureReactTasks(variant: BaseVariant, config: ReactAppE
|
||||||
val jsBundleDir = File(buildDir, "generated/assets/react/$targetPath")
|
val jsBundleDir = File(buildDir, "generated/assets/react/$targetPath")
|
||||||
val resourcesDir = File(buildDir, "generated/res/react/$targetPath")
|
val resourcesDir = File(buildDir, "generated/res/react/$targetPath")
|
||||||
|
|
||||||
val jsBundleFile = File(jsBundleDir, config.bundleAssetName)
|
val bundleAssetName = config.bundleAssetName.get()
|
||||||
|
val jsBundleFile = File(jsBundleDir, bundleAssetName)
|
||||||
val jsSourceMapsDir = File(buildDir, "generated/sourcemaps/react/$targetPath")
|
val jsSourceMapsDir = File(buildDir, "generated/sourcemaps/react/$targetPath")
|
||||||
val jsIntermediateSourceMapsDir = File(buildDir, "intermediates/sourcemaps/react/$targetPath")
|
val jsIntermediateSourceMapsDir = File(buildDir, "intermediates/sourcemaps/react/$targetPath")
|
||||||
val jsPackagerSourceMapFile =
|
val jsPackagerSourceMapFile = File(jsIntermediateSourceMapsDir, "${bundleAssetName}.packager.map")
|
||||||
File(jsIntermediateSourceMapsDir, "${config.bundleAssetName}.packager.map")
|
val jsCompilerSourceMapFile = File(jsIntermediateSourceMapsDir, "${bundleAssetName}.compiler.map")
|
||||||
val jsCompilerSourceMapFile =
|
val jsOutputSourceMapFile = File(jsSourceMapsDir, "${bundleAssetName}.map")
|
||||||
File(jsIntermediateSourceMapsDir, "${config.bundleAssetName}.compiler.map")
|
|
||||||
val jsOutputSourceMapFile = File(jsSourceMapsDir, "${config.bundleAssetName}.map")
|
|
||||||
|
|
||||||
// Additional node and packager commandline arguments
|
// Additional node and packager commandline arguments
|
||||||
val nodeExecutableAndArgs = config.nodeExecutableAndArgs
|
val nodeExecutableAndArgs = config.nodeExecutableAndArgs.get()
|
||||||
val cliPath = detectedCliPath(project.projectDir, config)
|
val cliPath = detectedCliPath(project.projectDir, config)
|
||||||
|
|
||||||
val execCommand = nodeExecutableAndArgs + cliPath
|
val execCommand = nodeExecutableAndArgs + cliPath
|
||||||
|
@ -54,19 +53,21 @@ internal fun Project.configureReactTasks(variant: BaseVariant, config: ReactAppE
|
||||||
it.group = REACT_GROUP
|
it.group = REACT_GROUP
|
||||||
it.description = "create JS bundle and assets for $targetName."
|
it.description = "create JS bundle and assets for $targetName."
|
||||||
|
|
||||||
it.reactRoot = config.reactRoot
|
it.reactRoot = config.reactRoot.get().asFile
|
||||||
it.sources =
|
it.sources =
|
||||||
fileTree(config.reactRoot) { fileTree -> fileTree.setExcludes(config.inputExcludes) }
|
fileTree(config.reactRoot) { fileTree ->
|
||||||
|
fileTree.setExcludes(config.inputExcludes.get())
|
||||||
|
}
|
||||||
it.execCommand = execCommand
|
it.execCommand = execCommand
|
||||||
it.bundleCommand = config.bundleCommand
|
it.bundleCommand = config.bundleCommand.get()
|
||||||
it.devEnabled = !(variant.name in config.devDisabledInVariants || isRelease)
|
it.devEnabled = !(variant.name in config.devDisabledInVariants.get() || isRelease)
|
||||||
it.entryFile = detectedEntryFile(config)
|
it.entryFile = detectedEntryFile(config)
|
||||||
|
|
||||||
val extraArgs = mutableListOf<String>()
|
val extraArgs = mutableListOf<String>()
|
||||||
|
|
||||||
if (config.bundleConfig != null) {
|
if (config.bundleConfig.isPresent) {
|
||||||
extraArgs.add("--config")
|
extraArgs.add("--config")
|
||||||
extraArgs.add(config.bundleConfig.orEmpty())
|
extraArgs.add(config.bundleConfig.get())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hermes doesn't require JS minification.
|
// Hermes doesn't require JS minification.
|
||||||
|
@ -75,7 +76,7 @@ internal fun Project.configureReactTasks(variant: BaseVariant, config: ReactAppE
|
||||||
extraArgs.add("false")
|
extraArgs.add("false")
|
||||||
}
|
}
|
||||||
|
|
||||||
extraArgs.addAll(config.extraPackagerArgs)
|
extraArgs.addAll(config.extraPackagerArgs.get())
|
||||||
|
|
||||||
it.extraArgs = extraArgs
|
it.extraArgs = extraArgs
|
||||||
|
|
||||||
|
@ -94,11 +95,12 @@ internal fun Project.configureReactTasks(variant: BaseVariant, config: ReactAppE
|
||||||
it.group = REACT_GROUP
|
it.group = REACT_GROUP
|
||||||
it.description = "bundle hermes resources for $targetName"
|
it.description = "bundle hermes resources for $targetName"
|
||||||
|
|
||||||
it.reactRoot = config.reactRoot
|
it.reactRoot = config.reactRoot.get().asFile
|
||||||
it.hermesCommand = detectedHermesCommand(config)
|
it.hermesCommand = detectedHermesCommand(config)
|
||||||
it.hermesFlags = if (isRelease) config.hermesFlagsRelease else config.hermesFlagsDebug
|
it.hermesFlags =
|
||||||
|
if (isRelease) config.hermesFlagsRelease.get() else config.hermesFlagsDebug.get()
|
||||||
it.jsBundleFile = jsBundleFile
|
it.jsBundleFile = jsBundleFile
|
||||||
it.composeSourceMapsCommand = nodeExecutableAndArgs + config.composeSourceMapsPath
|
it.composeSourceMapsCommand = nodeExecutableAndArgs + config.composeSourceMapsPath.get()
|
||||||
it.jsPackagerSourceMapFile = jsPackagerSourceMapFile
|
it.jsPackagerSourceMapFile = jsPackagerSourceMapFile
|
||||||
it.jsCompilerSourceMapFile = jsCompilerSourceMapFile
|
it.jsCompilerSourceMapFile = jsCompilerSourceMapFile
|
||||||
it.jsOutputSourceMapFile = jsOutputSourceMapFile
|
it.jsOutputSourceMapFile = jsOutputSourceMapFile
|
||||||
|
@ -136,15 +138,15 @@ internal fun Project.configureReactTasks(variant: BaseVariant, config: ReactAppE
|
||||||
val mergeAssetsTask = variant.mergeAssetsProvider
|
val mergeAssetsTask = variant.mergeAssetsProvider
|
||||||
val preBundleTask = tasks.named("build${targetName}PreBundle")
|
val preBundleTask = tasks.named("build${targetName}PreBundle")
|
||||||
|
|
||||||
val resourcesDirConfigValue = config.resourcesDir[variant.name]
|
val resourcesDirConfigValue = config.resourcesDir.getting(variant.name)
|
||||||
if (resourcesDirConfigValue != null) {
|
if (resourcesDirConfigValue.isPresent) {
|
||||||
val currentCopyResTask =
|
val currentCopyResTask =
|
||||||
tasks.register("copy${targetName}BundledResources", Copy::class.java) {
|
tasks.register("copy${targetName}BundledResources", Copy::class.java) {
|
||||||
it.group = "react"
|
it.group = "react"
|
||||||
it.description = "copy bundled resources into custom location for $targetName."
|
it.description = "copy bundled resources into custom location for $targetName."
|
||||||
|
|
||||||
it.from(resourcesDir)
|
it.from(resourcesDir)
|
||||||
it.into(file(resourcesDirConfigValue))
|
it.into(file(resourcesDirConfigValue.get()))
|
||||||
|
|
||||||
it.dependsOn(bundleTask)
|
it.dependsOn(bundleTask)
|
||||||
|
|
||||||
|
@ -156,7 +158,7 @@ internal fun Project.configureReactTasks(variant: BaseVariant, config: ReactAppE
|
||||||
}
|
}
|
||||||
|
|
||||||
packageTask.configure {
|
packageTask.configure {
|
||||||
if (config.enableVmCleanup) {
|
if (config.enableVmCleanup.get()) {
|
||||||
it.doFirst { cleanupVMFiles(enableHermes, isRelease, targetPath) }
|
it.doFirst { cleanupVMFiles(enableHermes, isRelease, targetPath) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -168,9 +170,9 @@ internal fun Project.configureReactTasks(variant: BaseVariant, config: ReactAppE
|
||||||
|
|
||||||
it.from(jsBundleDir)
|
it.from(jsBundleDir)
|
||||||
|
|
||||||
val jsBundleDirConfigValue = config.jsBundleDir[targetName]
|
val jsBundleDirConfigValue = config.jsBundleDir.getting(targetName)
|
||||||
if (jsBundleDirConfigValue != null) {
|
if (jsBundleDirConfigValue.isPresent) {
|
||||||
it.into(jsBundleDirConfigValue)
|
it.into(jsBundleDirConfigValue.get())
|
||||||
} else {
|
} else {
|
||||||
it.into(mergeAssetsTask.map { mergeFoldersTask -> mergeFoldersTask.outputDir.get() })
|
it.into(mergeAssetsTask.map { mergeFoldersTask -> mergeFoldersTask.outputDir.get() })
|
||||||
}
|
}
|
||||||
|
@ -225,12 +227,12 @@ private fun Project.cleanupVMFiles(enableHermes: Boolean, isRelease: Boolean, ta
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun BaseVariant.checkBundleEnabled(config: ReactAppExtension): Boolean {
|
private fun BaseVariant.checkBundleEnabled(config: ReactAppExtension): Boolean {
|
||||||
if (name in config.bundleIn) {
|
if (config.bundleIn.getting(name).isPresent) {
|
||||||
return config.bundleIn.getValue(name)
|
return config.bundleIn.getting(name).get()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buildType.name in config.bundleIn) {
|
if (config.bundleIn.getting(buildType.name).isPresent) {
|
||||||
return config.bundleIn.getValue(buildType.name)
|
return config.bundleIn.getting(buildType.name).get()
|
||||||
}
|
}
|
||||||
|
|
||||||
return isRelease
|
return isRelease
|
||||||
|
|
|
@ -21,7 +21,8 @@ import org.apache.tools.ant.taskdefs.condition.Os
|
||||||
* @param config The [ReactAppExtension] configured for this project
|
* @param config The [ReactAppExtension] configured for this project
|
||||||
*/
|
*/
|
||||||
internal fun detectedEntryFile(config: ReactAppExtension): File =
|
internal fun detectedEntryFile(config: ReactAppExtension): File =
|
||||||
detectEntryFile(entryFile = config.entryFile, reactRoot = config.reactRoot)
|
detectEntryFile(
|
||||||
|
entryFile = config.entryFile.orNull?.asFile, reactRoot = config.reactRoot.get().asFile)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Computes the CLI location for React Native. The Algo follows this order:
|
* Computes the CLI location for React Native. The Algo follows this order:
|
||||||
|
@ -36,8 +37,8 @@ internal fun detectedCliPath(
|
||||||
): String =
|
): String =
|
||||||
detectCliPath(
|
detectCliPath(
|
||||||
projectDir = projectDir,
|
projectDir = projectDir,
|
||||||
reactRoot = config.reactRoot,
|
reactRoot = config.reactRoot.get().asFile,
|
||||||
preconfiguredCliPath = config.cliPath)
|
preconfiguredCliPath = config.cliPath.orNull)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Computes the `hermesc` command location. The Algo follows this order:
|
* Computes the `hermesc` command location. The Algo follows this order:
|
||||||
|
@ -47,7 +48,7 @@ internal fun detectedCliPath(
|
||||||
* 3. Fails otherwise
|
* 3. Fails otherwise
|
||||||
*/
|
*/
|
||||||
internal fun detectedHermesCommand(config: ReactAppExtension): String =
|
internal fun detectedHermesCommand(config: ReactAppExtension): String =
|
||||||
detectOSAwareHermesCommand(config.hermesCommand)
|
detectOSAwareHermesCommand(config.hermesCommand.get())
|
||||||
|
|
||||||
private fun detectEntryFile(entryFile: File?, reactRoot: File): File =
|
private fun detectEntryFile(entryFile: File?, reactRoot: File): File =
|
||||||
when {
|
when {
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.facebook.react
|
||||||
|
|
||||||
|
import org.gradle.api.Project
|
||||||
|
|
||||||
|
class TestReactAppExtension(project: Project) : ReactAppExtension(project)
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
package com.facebook.react.tests
|
package com.facebook.react.tests
|
||||||
|
|
||||||
import com.facebook.react.ReactAppExtension
|
import com.facebook.react.TestReactAppExtension
|
||||||
import com.facebook.react.utils.detectedCliPath
|
import com.facebook.react.utils.detectedCliPath
|
||||||
import com.facebook.react.utils.detectedEntryFile
|
import com.facebook.react.utils.detectedEntryFile
|
||||||
import com.facebook.react.utils.detectedHermesCommand
|
import com.facebook.react.utils.detectedHermesCommand
|
||||||
|
@ -24,9 +24,9 @@ class PathUtilsTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun detectedEntryFile_withProvidedVariable() {
|
fun detectedEntryFile_withProvidedVariable() {
|
||||||
val extension = ReactAppExtension(ProjectBuilder.builder().build())
|
val extension = TestReactAppExtension(ProjectBuilder.builder().build())
|
||||||
val expected = tempFolder.newFile("fake.index.js")
|
val expected = tempFolder.newFile("fake.index.js")
|
||||||
extension.entryFile = expected
|
extension.entryFile.set(expected)
|
||||||
|
|
||||||
val actual = detectedEntryFile(extension)
|
val actual = detectedEntryFile(extension)
|
||||||
|
|
||||||
|
@ -35,8 +35,8 @@ class PathUtilsTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun detectedEntryFile_withAndroidEntryPoint() {
|
fun detectedEntryFile_withAndroidEntryPoint() {
|
||||||
val extension = ReactAppExtension(ProjectBuilder.builder().build())
|
val extension = TestReactAppExtension(ProjectBuilder.builder().build())
|
||||||
extension.reactRoot = tempFolder.root
|
extension.reactRoot.set(tempFolder.root)
|
||||||
tempFolder.newFile("index.android.js")
|
tempFolder.newFile("index.android.js")
|
||||||
|
|
||||||
val actual = detectedEntryFile(extension)
|
val actual = detectedEntryFile(extension)
|
||||||
|
@ -46,8 +46,8 @@ class PathUtilsTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun detectedEntryFile_withDefaultEntryPoint() {
|
fun detectedEntryFile_withDefaultEntryPoint() {
|
||||||
val extension = ReactAppExtension(ProjectBuilder.builder().build())
|
val extension = TestReactAppExtension(ProjectBuilder.builder().build())
|
||||||
extension.reactRoot = tempFolder.root
|
extension.reactRoot.set(tempFolder.root)
|
||||||
|
|
||||||
val actual = detectedEntryFile(extension)
|
val actual = detectedEntryFile(extension)
|
||||||
|
|
||||||
|
@ -57,22 +57,22 @@ class PathUtilsTest {
|
||||||
@Test
|
@Test
|
||||||
fun detectedCliPath_withCliPathFromExtension() {
|
fun detectedCliPath_withCliPathFromExtension() {
|
||||||
val project = ProjectBuilder.builder().build()
|
val project = ProjectBuilder.builder().build()
|
||||||
val extension = ReactAppExtension(project)
|
val extension = TestReactAppExtension(project)
|
||||||
val expected = File(project.projectDir, "fake-cli.sh").apply { writeText("#!/bin/bash") }
|
val expected = File(project.projectDir, "fake-cli.sh")
|
||||||
extension.cliPath = "./fake-cli.sh"
|
extension.cliPath.set("fake-cli.sh")
|
||||||
|
|
||||||
val actual = detectedCliPath(project.projectDir, extension)
|
val actual = detectedCliPath(project.projectDir, extension)
|
||||||
|
|
||||||
assertEquals(expected.canonicalPath, File(actual).canonicalPath)
|
assertEquals(expected.toString(), actual)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun detectedCliPath_withCliPathFromExtensionInParentFolder() {
|
fun detectedCliPath_withCliPathFromExtensionInParentFolder() {
|
||||||
val rootProject = ProjectBuilder.builder().build()
|
val rootProject = ProjectBuilder.builder().build()
|
||||||
val project = ProjectBuilder.builder().withParent(rootProject).build()
|
val project = ProjectBuilder.builder().withParent(rootProject).build()
|
||||||
val extension = ReactAppExtension(project)
|
val extension = TestReactAppExtension(project)
|
||||||
val expected = File(rootProject.projectDir, "cli-in-root.sh").apply { writeText("#!/bin/bash") }
|
val expected = File(rootProject.projectDir, "cli-in-root.sh").apply { writeText("#!/bin/bash") }
|
||||||
extension.cliPath = "../cli-in-root.sh"
|
extension.cliPath.set("../cli-in-root.sh")
|
||||||
|
|
||||||
val actual = detectedCliPath(project.projectDir, extension)
|
val actual = detectedCliPath(project.projectDir, extension)
|
||||||
|
|
||||||
|
@ -82,8 +82,8 @@ class PathUtilsTest {
|
||||||
@Test
|
@Test
|
||||||
fun detectedCliPath_withCliFromNodeModules() {
|
fun detectedCliPath_withCliFromNodeModules() {
|
||||||
val project = ProjectBuilder.builder().build()
|
val project = ProjectBuilder.builder().build()
|
||||||
val extension = ReactAppExtension(project)
|
val extension = TestReactAppExtension(project)
|
||||||
extension.reactRoot = tempFolder.root
|
extension.reactRoot.set(tempFolder.root)
|
||||||
val expected =
|
val expected =
|
||||||
File(tempFolder.root, "node_modules/react-native/cli.js").apply {
|
File(tempFolder.root, "node_modules/react-native/cli.js").apply {
|
||||||
parentFile.mkdirs()
|
parentFile.mkdirs()
|
||||||
|
@ -98,16 +98,16 @@ class PathUtilsTest {
|
||||||
@Test(expected = IllegalStateException::class)
|
@Test(expected = IllegalStateException::class)
|
||||||
fun detectedCliPath_failsIfNotFound() {
|
fun detectedCliPath_failsIfNotFound() {
|
||||||
val project = ProjectBuilder.builder().build()
|
val project = ProjectBuilder.builder().build()
|
||||||
val extension = ReactAppExtension(project)
|
val extension = TestReactAppExtension(project)
|
||||||
|
|
||||||
detectedCliPath(project.projectDir, extension)
|
detectedCliPath(project.projectDir, extension)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun detectedHermesCommand_withPathFromExtension() {
|
fun detectedHermesCommand_withPathFromExtension() {
|
||||||
val extension = ReactAppExtension(ProjectBuilder.builder().build())
|
val extension = TestReactAppExtension(ProjectBuilder.builder().build())
|
||||||
val expected = tempFolder.newFile("hermesc")
|
val expected = tempFolder.newFile("hermesc")
|
||||||
extension.hermesCommand = expected.toString()
|
extension.hermesCommand.set(expected.toString())
|
||||||
|
|
||||||
val actual = detectedHermesCommand(extension)
|
val actual = detectedHermesCommand(extension)
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ class PathUtilsTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun detectedHermesCommand_withOSSpecificBin() {
|
fun detectedHermesCommand_withOSSpecificBin() {
|
||||||
val extension = ReactAppExtension(ProjectBuilder.builder().build())
|
val extension = TestReactAppExtension(ProjectBuilder.builder().build())
|
||||||
|
|
||||||
val actual = detectedHermesCommand(extension)
|
val actual = detectedHermesCommand(extension)
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче