diff --git a/packages/app/android/template.config.mjs b/packages/app/android/template.config.mjs index 633d7bb94..da3d5af7e 100644 --- a/packages/app/android/template.config.mjs +++ b/packages/app/android/template.config.mjs @@ -190,30 +190,36 @@ export function configure( * @param {ConfigureParams} params * @returns {Configuration} */ -export function getTemplate({ name, testAppPath, targetVersion }) { +export function getTemplate({ + name, + templatePath, + testAppPath, + targetVersion, +}) { const targetVersionNum = toVersionNumber(targetVersion); + // Use the Gradle wrapper from the template matching the target React Native + // version, falling back to the one bundled with the example app. + const wrapperDir = templatePath + ? path.join(templatePath, "android") + : path.join(testAppPath, "example", "android"); return { files: { "build.gradle": buildGradle(), "gradle/wrapper/gradle-wrapper.jar": copyFrom( - testAppPath, - "example", - "android", + wrapperDir, "gradle", "wrapper", "gradle-wrapper.jar" ), "gradle/wrapper/gradle-wrapper.properties": copyFrom( - testAppPath, - "example", - "android", + wrapperDir, "gradle", "wrapper", "gradle-wrapper.properties" ), "gradle.properties": gradleProperties(targetVersionNum), - gradlew: copyFrom(testAppPath, "example", "android", "gradlew"), - "gradlew.bat": copyFrom(testAppPath, "example", "android", "gradlew.bat"), + gradlew: copyFrom(wrapperDir, "gradlew"), + "gradlew.bat": copyFrom(wrapperDir, "gradlew.bat"), "settings.gradle": settingsGradle(name), }, oldFiles: [], diff --git a/packages/app/test/configure/gatherConfig.test.mts.snapshot b/packages/app/test/configure/gatherConfig.test.mts.snapshot index 99c226b31..0c7e0bf18 100644 --- a/packages/app/test/configure/gatherConfig.test.mts.snapshot +++ b/packages/app/test/configure/gatherConfig.test.mts.snapshot @@ -87,17 +87,17 @@ exports[`gatherConfig() > returns configuration for all platforms 1`] = ` "react-native.config.js": "const project = (() => {\\n try {\\n const { configureProjects } = require(\\"react-native-test-app\\");\\n return configureProjects({\\n android: {\\n sourceDir: \\"android\\",\\n },\\n ios: {\\n sourceDir: \\"ios\\",\\n },\\n macos: {\\n sourceDir: \\"macos\\",\\n },\\n visionos: {\\n sourceDir: \\"visionos\\",\\n },\\n windows: {\\n sourceDir: \\"windows\\",\\n solutionFile: \\"windows/Test.sln\\",\\n },\\n });\\n } catch (_) {\\n return undefined;\\n }\\n})();\\n\\nmodule.exports = {\\n ...(project ? { project } : undefined),\\n};\\n", "android/build.gradle": "buildscript {\\n apply(from: {\\n def searchDir = rootDir.toPath()\\n do {\\n def p = searchDir.resolve(\\"node_modules/react-native-test-app/android/dependencies.gradle\\")\\n if (p.toFile().exists()) {\\n return p.toRealPath().toString()\\n }\\n } while (searchDir = searchDir.getParent())\\n throw new GradleException(\\"Could not find \`react-native-test-app\`\\");\\n }())\\n\\n repositories {\\n mavenCentral()\\n google()\\n }\\n\\n dependencies {\\n getReactNativeDependencies().each { dependency ->\\n classpath(dependency)\\n }\\n }\\n}\\n", "android/gradle/wrapper/gradle-wrapper.jar": { - "source": "example/android/gradle/wrapper/gradle-wrapper.jar" + "source": "node_modules/@react-native-community/template/template/android/gradle/wrapper/gradle-wrapper.jar" }, "android/gradle/wrapper/gradle-wrapper.properties": { - "source": "example/android/gradle/wrapper/gradle-wrapper.properties" + "source": "node_modules/@react-native-community/template/template/android/gradle/wrapper/gradle-wrapper.properties" }, "android/gradle.properties": "# Project-wide Gradle settings.\\n\\n# IDE (e.g. Android Studio) users:\\n# Gradle settings configured through the IDE *will override*\\n# any settings specified in this file.\\n\\n# For more details on how to configure your build environment visit\\n# http://www.gradle.org/docs/current/userguide/build_environment.html\\n\\n# Specifies the JVM arguments used for the Gradle Daemon. The setting is\\n# particularly useful for configuring JVM memory settings for build performance.\\n# This does not affect the JVM settings for the Gradle client VM.\\n# The default is \`-Xmx512m -XX:MaxMetaspaceSize=256m\`.\\norg.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8\\n\\n# When configured, Gradle will fork up to org.gradle.workers.max JVMs to execute\\n# projects in parallel. To learn more about parallel task execution, see the\\n# section on Gradle build performance:\\n# https://docs.gradle.org/current/userguide/performance.html#parallel_execution.\\n# Default is \`false\`.\\n#org.gradle.parallel=true\\n\\n# AndroidX package structure to make it clearer which packages are bundled with the\\n# Android operating system, and which are packaged with your app's APK\\n# https://developer.android.com/topic/libraries/support-library/androidx-rn\\nandroid.useAndroidX=true\\n# Automatically convert third-party libraries to use AndroidX\\n#android.enableJetifier=true\\n# Jetifier randomly fails on these libraries\\n#android.jetifier.ignorelist=hermes-android,react-android\\n\\n# Use this property to specify which architecture you want to build.\\n# You can also override it from the CLI using\\n# ./gradlew -PreactNativeArchitectures=x86_64\\nreactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64\\n\\n# Use this property to enable support to the new architecture.\\n# This will allow you to use TurboModules and the Fabric render in\\n# your application. You should enable this flag either if you want\\n# to write custom TurboModules/Fabric components OR use libraries that\\n# are providing them.\\n# Note that this is incompatible with web debugging.\\nnewArchEnabled=true\\n#bridgelessEnabled=true\\n\\n# Uncomment the line below to build React Native from source.\\n#react.buildFromSource=true\\n\\n# Version of Android NDK to build against.\\n#ANDROID_NDK_VERSION=26.1.10909125\\n\\n# Version of Kotlin to build against.\\n#KOTLIN_VERSION=1.8.22\\n\\n# Use this property to enable edge-to-edge display support.\\n# This allows your app to draw behind system bars for an immersive UI.\\n# Note: Only works with ReactActivity and should not be used with custom Activity.\\nedgeToEdgeEnabled=true\\n\\n# Opt out of built-in kotlin and new DSL behavior that ships with AGP 9.\\n# Starting from AGP 10.x these opt outs will be removed.\\nandroid.builtInKotlin=false\\nandroid.newDsl=false\\n", "android/gradlew": { - "source": "example/android/gradlew" + "source": "node_modules/@react-native-community/template/template/android/gradlew" }, "android/gradlew.bat": { - "source": "example/android/gradlew.bat" + "source": "node_modules/@react-native-community/template/template/android/gradlew.bat" }, "android/settings.gradle": "pluginManagement {\\n repositories {\\n gradlePluginPortal()\\n mavenCentral()\\n google()\\n }\\n}\\n\\nrootProject.name = \\"Test\\"\\n\\napply(from: {\\n def searchDir = rootDir.toPath()\\n do {\\n def p = searchDir.resolve(\\"node_modules/react-native-test-app/test-app.gradle\\")\\n if (p.toFile().exists()) {\\n return p.toRealPath().toString()\\n }\\n } while (searchDir = searchDir.getParent())\\n throw new GradleException(\\"Could not find \`react-native-test-app\`\\");\\n}())\\napplyTestAppSettings(settings)\\n", "ios/Podfile": "ws_dir = Pathname.new(__dir__)\\nws_dir = ws_dir.parent until\\n File.exist?(\\"#{ws_dir}/node_modules/react-native-test-app/test_app.rb\\") ||\\n ws_dir.expand_path.to_s == '/'\\nrequire \\"#{ws_dir}/node_modules/react-native-test-app/test_app.rb\\"\\n\\nworkspace 'Test.xcworkspace'\\n\\nuse_test_app! :hermes_enabled => true, :fabric_enabled => true\\n", @@ -155,17 +155,17 @@ exports[`gatherConfig() > returns configuration for arbitrary platforms 1`] = ` "react-native.config.js": "const project = (() => {\\n try {\\n const { configureProjects } = require(\\"react-native-test-app\\");\\n return configureProjects({\\n android: {\\n sourceDir: \\"android\\",\\n },\\n ios: {\\n sourceDir: \\"ios\\",\\n },\\n macos: {\\n sourceDir: \\"macos\\",\\n },\\n visionos: {\\n sourceDir: \\"visionos\\",\\n },\\n windows: {\\n sourceDir: \\"windows\\",\\n solutionFile: \\"windows/Test.sln\\",\\n },\\n });\\n } catch (_) {\\n return undefined;\\n }\\n})();\\n\\nmodule.exports = {\\n ...(project ? { project } : undefined),\\n};\\n", "android/build.gradle": "buildscript {\\n apply(from: {\\n def searchDir = rootDir.toPath()\\n do {\\n def p = searchDir.resolve(\\"node_modules/react-native-test-app/android/dependencies.gradle\\")\\n if (p.toFile().exists()) {\\n return p.toRealPath().toString()\\n }\\n } while (searchDir = searchDir.getParent())\\n throw new GradleException(\\"Could not find \`react-native-test-app\`\\");\\n }())\\n\\n repositories {\\n mavenCentral()\\n google()\\n }\\n\\n dependencies {\\n getReactNativeDependencies().each { dependency ->\\n classpath(dependency)\\n }\\n }\\n}\\n", "android/gradle/wrapper/gradle-wrapper.jar": { - "source": "example/android/gradle/wrapper/gradle-wrapper.jar" + "source": "node_modules/@react-native-community/template/template/android/gradle/wrapper/gradle-wrapper.jar" }, "android/gradle/wrapper/gradle-wrapper.properties": { - "source": "example/android/gradle/wrapper/gradle-wrapper.properties" + "source": "node_modules/@react-native-community/template/template/android/gradle/wrapper/gradle-wrapper.properties" }, "android/gradle.properties": "# Project-wide Gradle settings.\\n\\n# IDE (e.g. Android Studio) users:\\n# Gradle settings configured through the IDE *will override*\\n# any settings specified in this file.\\n\\n# For more details on how to configure your build environment visit\\n# http://www.gradle.org/docs/current/userguide/build_environment.html\\n\\n# Specifies the JVM arguments used for the Gradle Daemon. The setting is\\n# particularly useful for configuring JVM memory settings for build performance.\\n# This does not affect the JVM settings for the Gradle client VM.\\n# The default is \`-Xmx512m -XX:MaxMetaspaceSize=256m\`.\\norg.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8\\n\\n# When configured, Gradle will fork up to org.gradle.workers.max JVMs to execute\\n# projects in parallel. To learn more about parallel task execution, see the\\n# section on Gradle build performance:\\n# https://docs.gradle.org/current/userguide/performance.html#parallel_execution.\\n# Default is \`false\`.\\n#org.gradle.parallel=true\\n\\n# AndroidX package structure to make it clearer which packages are bundled with the\\n# Android operating system, and which are packaged with your app's APK\\n# https://developer.android.com/topic/libraries/support-library/androidx-rn\\nandroid.useAndroidX=true\\n# Automatically convert third-party libraries to use AndroidX\\n#android.enableJetifier=true\\n# Jetifier randomly fails on these libraries\\n#android.jetifier.ignorelist=hermes-android,react-android\\n\\n# Use this property to specify which architecture you want to build.\\n# You can also override it from the CLI using\\n# ./gradlew -PreactNativeArchitectures=x86_64\\nreactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64\\n\\n# Use this property to enable support to the new architecture.\\n# This will allow you to use TurboModules and the Fabric render in\\n# your application. You should enable this flag either if you want\\n# to write custom TurboModules/Fabric components OR use libraries that\\n# are providing them.\\n# Note that this is incompatible with web debugging.\\nnewArchEnabled=true\\n#bridgelessEnabled=true\\n\\n# Uncomment the line below to build React Native from source.\\n#react.buildFromSource=true\\n\\n# Version of Android NDK to build against.\\n#ANDROID_NDK_VERSION=26.1.10909125\\n\\n# Version of Kotlin to build against.\\n#KOTLIN_VERSION=1.8.22\\n\\n# Use this property to enable edge-to-edge display support.\\n# This allows your app to draw behind system bars for an immersive UI.\\n# Note: Only works with ReactActivity and should not be used with custom Activity.\\nedgeToEdgeEnabled=true\\n\\n# Opt out of built-in kotlin and new DSL behavior that ships with AGP 9.\\n# Starting from AGP 10.x these opt outs will be removed.\\nandroid.builtInKotlin=false\\nandroid.newDsl=false\\n", "android/gradlew": { - "source": "example/android/gradlew" + "source": "node_modules/@react-native-community/template/template/android/gradlew" }, "android/gradlew.bat": { - "source": "example/android/gradlew.bat" + "source": "node_modules/@react-native-community/template/template/android/gradlew.bat" }, "android/settings.gradle": "pluginManagement {\\n repositories {\\n gradlePluginPortal()\\n mavenCentral()\\n google()\\n }\\n}\\n\\nrootProject.name = \\"Test\\"\\n\\napply(from: {\\n def searchDir = rootDir.toPath()\\n do {\\n def p = searchDir.resolve(\\"node_modules/react-native-test-app/test-app.gradle\\")\\n if (p.toFile().exists()) {\\n return p.toRealPath().toString()\\n }\\n } while (searchDir = searchDir.getParent())\\n throw new GradleException(\\"Could not find \`react-native-test-app\`\\");\\n}())\\napplyTestAppSettings(settings)\\n", "ios/Podfile": "ws_dir = Pathname.new(__dir__)\\nws_dir = ws_dir.parent until\\n File.exist?(\\"#{ws_dir}/node_modules/react-native-test-app/test_app.rb\\") ||\\n ws_dir.expand_path.to_s == '/'\\nrequire \\"#{ws_dir}/node_modules/react-native-test-app/test_app.rb\\"\\n\\nworkspace 'Test.xcworkspace'\\n\\nuse_test_app! :hermes_enabled => true, :fabric_enabled => true\\n" diff --git a/packages/app/test/configure/getConfig.test.mts b/packages/app/test/configure/getConfig.test.mts index c92fb6135..c474d6ff5 100644 --- a/packages/app/test/configure/getConfig.test.mts +++ b/packages/app/test/configure/getConfig.test.mts @@ -1,6 +1,7 @@ import { deepEqual, ok } from "node:assert/strict"; import * as path from "node:path"; import { describe, it } from "node:test"; +import { getTemplate as getAndroidTemplate } from "../../android/template.config.mjs"; import { getConfig as getConfigActual, getPlatformPackage, @@ -10,6 +11,12 @@ import { templatePath } from "../template.mts"; import { mockParams } from "./mockParams.mts"; describe("getConfig()", () => { + const gradleWrapperFiles = [ + "gradle/wrapper/gradle-wrapper.jar", + "gradle/wrapper/gradle-wrapper.properties", + "gradlew", + "gradlew.bat", + ]; const getConfig: typeof getConfigActual = (params, platform) => getConfigActual({ ...params, templatePath }, platform, true); @@ -79,6 +86,21 @@ describe("getConfig()", () => { "settings.gradle", ]); deepEqual(config.oldFiles, []); + + for (const file of gradleWrapperFiles) { + deepEqual(config.files[file], { + source: path.join(templatePath, "android", file), + }); + } + }); + + it("falls back to the example app's Gradle wrapper without a template", () => { + const { files } = getAndroidTemplate(mockParams()); + for (const file of gradleWrapperFiles) { + deepEqual(files[file], { + source: path.join(".", "example", "android", file), + }); + } }); it("returns iOS specific scripts and additional files", () => {