/* * Copyright (c) Meta Platforms, Inc. and 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.utils import org.assertj.core.api.Assertions.assertThat import org.intellij.lang.annotations.Language import org.junit.Rule import org.junit.Test import org.junit.rules.TemporaryFolder class JsonUtilsTest { @get:Rule val tempFolder = TemporaryFolder() @Test fun fromPackageJson_withInvalidJson_returnsNull() { val invalidJson = createJsonFile("""¯\_(ツ)_/¯""") assertThat(JsonUtils.fromPackageJson(invalidJson)).isNull() } @Test fun fromPackageJson_withEmptyJson_returnsEmptyObject() { val invalidJson = createJsonFile("""{}""") val parsed = JsonUtils.fromPackageJson(invalidJson) assertThat(parsed).isNotNull() assertThat(parsed?.codegenConfig).isNull() } @Test fun fromPackageJson_withOldJsonConfig_returnsAnEmptyLibrary() { val oldJsonConfig = createJsonFile( """ { "name": "yet another npm package", "codegenConfig": { "libraries": [ { "name": "an awesome library", "jsSrcsDir": "../js/", "android": {} } ] } } """ .trimIndent()) val parsed = JsonUtils.fromPackageJson(oldJsonConfig)!! assertThat(parsed.codegenConfig?.name).isNull() assertThat(parsed.codegenConfig?.jsSrcsDir).isNull() assertThat(parsed.codegenConfig?.android).isNull() } @Test fun fromPackageJson_withValidJson_parsesCorrectly() { val validJson = createJsonFile( """ { "name": "yet another npm package", "codegenConfig": { "name": "an awesome library", "jsSrcsDir": "../js/", "android": { "javaPackageName": "com.awesome.library" }, "ios": { "other ios only keys": "which are ignored during parsing" } } } """ .trimIndent()) val parsed = JsonUtils.fromPackageJson(validJson)!! assertThat("an awesome library").isEqualTo(parsed.codegenConfig!!.name) assertThat("../js/").isEqualTo(parsed.codegenConfig!!.jsSrcsDir) assertThat("com.awesome.library").isEqualTo(parsed.codegenConfig!!.android!!.javaPackageName) } @Test fun fromReactNativePackageJson_withInvalidJson_returnsNull() { val invalidJson = createJsonFile("""¯\_(ツ)_/¯""") assertThat(JsonUtils.fromPackageJson(invalidJson)).isNull() } @Test fun fromReactNativePackageJson_withEmptyJson_returnsEmptyObject() { val invalidJson = createJsonFile("""{}""") val parsed = JsonUtils.fromPackageJson(invalidJson) assertThat(parsed).isNotNull() assertThat(parsed?.version).isNull() } @Test fun fromReactNativePackageJson_withValidJson_parsesJsonCorrectly() { val validJson = createJsonFile( """ { "version": "1000.0.0" } """ .trimIndent()) val parsed = JsonUtils.fromPackageJson(validJson)!! assertThat("1000.0.0").isEqualTo(parsed.version) } @Test fun fromAutolinkingConfigJson_withInvalidJson_returnsNull() { val invalidJson = createJsonFile("""¯\_(ツ)_/¯""") assertThat(JsonUtils.fromAutolinkingConfigJson(invalidJson)).isNull() } @Test fun fromAutolinkingConfigJson_withSimpleJson_returnsIt() { val validJson = createJsonFile( """ { "reactNativeVersion": "1000.0.0" } """ .trimIndent()) val parsed = JsonUtils.fromAutolinkingConfigJson(validJson)!! assertThat("1000.0.0").isEqualTo(parsed.reactNativeVersion) } @Test fun fromAutolinkingConfigJson_withProjectSpecified_canParseIt() { val validJson = createJsonFile( """ { "reactNativeVersion": "1000.0.0", "project": { "ios": { "sourceDir": "./packages/rn-tester", "xcodeProject": { "name": "RNTesterPods.xcworkspace", "isWorkspace": true }, "automaticPodsInstallation": false }, "android": { "sourceDir": "./packages/rn-tester", "appName": "RN-Tester", "packageName": "com.facebook.react.uiapp", "applicationId": "com.facebook.react.uiapp", "mainActivity": ".RNTesterActivity", "watchModeCommandParams": [ "--mode HermesDebug" ], "dependencyConfiguration": "implementation" } } } """ .trimIndent()) val parsed = JsonUtils.fromAutolinkingConfigJson(validJson)!! assertThat("./packages/rn-tester").isEqualTo(parsed.project!!.android!!.sourceDir) assertThat("RN-Tester").isEqualTo(parsed.project!!.android!!.appName) assertThat("com.facebook.react.uiapp").isEqualTo(parsed.project!!.android!!.packageName) assertThat("com.facebook.react.uiapp").isEqualTo(parsed.project!!.android!!.applicationId) assertThat(".RNTesterActivity").isEqualTo(parsed.project!!.android!!.mainActivity) assertThat("--mode HermesDebug") .isEqualTo(parsed.project!!.android!!.watchModeCommandParams!![0]) assertThat("implementation").isEqualTo(parsed.project!!.android!!.dependencyConfiguration) } @Test fun fromAutolinkingConfigJson_withInfoLogs_sanitizeAndParseIt() { @Suppress("JsonStandardCompliance") val validJson = createJsonFile( """ > AwesomeProject@0.0.1 npx > rnc-cli config { "reactNativeVersion": "1000.0.0", "project": { "ios": { "sourceDir": "./packages/rn-tester", "xcodeProject": { "name": "RNTesterPods.xcworkspace", "isWorkspace": true }, "automaticPodsInstallation": false }, "android": { "sourceDir": "./packages/rn-tester", "appName": "RN-Tester", "packageName": "com.facebook.react.uiapp", "applicationId": "com.facebook.react.uiapp", "mainActivity": ".RNTesterActivity", "watchModeCommandParams": [ "--mode HermesDebug" ], "dependencyConfiguration": "implementation" } } } """ .trimIndent()) val parsed = JsonUtils.fromAutolinkingConfigJson(validJson)!! assertThat("./packages/rn-tester").isEqualTo(parsed.project!!.android!!.sourceDir) assertThat("RN-Tester").isEqualTo(parsed.project!!.android!!.appName) assertThat("com.facebook.react.uiapp").isEqualTo(parsed.project!!.android!!.packageName) assertThat("com.facebook.react.uiapp").isEqualTo(parsed.project!!.android!!.applicationId) assertThat(".RNTesterActivity").isEqualTo(parsed.project!!.android!!.mainActivity) assertThat("--mode HermesDebug") .isEqualTo(parsed.project!!.android!!.watchModeCommandParams!![0]) assertThat("implementation").isEqualTo(parsed.project!!.android!!.dependencyConfiguration) } @Test fun fromAutolinkingConfigJson_withDependenciesSpecified_canParseIt() { val validJson = createJsonFile( """ { "reactNativeVersion": "1000.0.0", "dependencies": { "@react-native/oss-library-example": { "root": "./node_modules/@react-native/oss-library-example", "name": "@react-native/oss-library-example", "platforms": { "ios": { "podspecPath": "./node_modules/@react-native/oss-library-example/OSSLibraryExample.podspec", "version": "0.0.1", "configurations": [], "scriptPhases": [] }, "android": { "sourceDir": "./node_modules/@react-native/oss-library-example/android", "packageImportPath": "import com.facebook.react.osslibraryexample.OSSLibraryExamplePackage;", "packageInstance": "new OSSLibraryExamplePackage()", "buildTypes": ["staging", "debug", "release"], "libraryName": "OSSLibraryExampleSpec", "componentDescriptors": [ "SampleNativeComponentComponentDescriptor" ], "cmakeListsPath": "./node_modules/@react-native/oss-library-example/android/build/generated/source/codegen/jni/CMakeLists.txt", "cxxModuleCMakeListsModuleName": null, "cxxModuleCMakeListsPath": null, "cxxModuleHeaderName": null, "dependencyConfiguration": "implementation", "isPureCxxDependency": false } } } } } """ .trimIndent()) val parsed = JsonUtils.fromAutolinkingConfigJson(validJson)!! assertThat("./node_modules/@react-native/oss-library-example") .isEqualTo(parsed.dependencies!!["@react-native/oss-library-example"]!!.root) assertThat("@react-native/oss-library-example") .isEqualTo(parsed.dependencies!!["@react-native/oss-library-example"]!!.name) assertThat("react-native_oss-library-example") .isEqualTo(parsed.dependencies!!["@react-native/oss-library-example"]!!.nameCleansed) assertThat("./node_modules/@react-native/oss-library-example/android") .isEqualTo( parsed.dependencies!!["@react-native/oss-library-example"]!! .platforms!! .android!! .sourceDir) assertThat("import com.facebook.react.osslibraryexample.OSSLibraryExamplePackage;") .isEqualTo( parsed.dependencies!!["@react-native/oss-library-example"]!! .platforms!! .android!! .packageImportPath) assertThat("new OSSLibraryExamplePackage()") .isEqualTo( parsed.dependencies!!["@react-native/oss-library-example"]!! .platforms!! .android!! .packageInstance) assertThat(listOf("staging", "debug", "release")) .isEqualTo( parsed.dependencies!!["@react-native/oss-library-example"]!! .platforms!! .android!! .buildTypes) assertThat("OSSLibraryExampleSpec") .isEqualTo( parsed.dependencies!!["@react-native/oss-library-example"]!! .platforms!! .android!! .libraryName) assertThat(listOf("SampleNativeComponentComponentDescriptor")) .isEqualTo( parsed.dependencies!!["@react-native/oss-library-example"]!! .platforms!! .android!! .componentDescriptors) assertThat( "./node_modules/@react-native/oss-library-example/android/build/generated/source/codegen/jni/CMakeLists.txt") .isEqualTo( parsed.dependencies!!["@react-native/oss-library-example"]!! .platforms!! .android!! .cmakeListsPath) assertThat( parsed.dependencies!!["@react-native/oss-library-example"]!! .platforms!! .android!! .cxxModuleHeaderName) .isNull() assertThat( parsed.dependencies!!["@react-native/oss-library-example"]!! .platforms!! .android!! .cxxModuleCMakeListsPath) .isNull() assertThat( parsed.dependencies!!["@react-native/oss-library-example"]!! .platforms!! .android!! .cxxModuleCMakeListsModuleName) .isNull() assertThat("implementation") .isEqualTo( parsed.dependencies!!["@react-native/oss-library-example"]!! .platforms!! .android!! .dependencyConfiguration) assertThat( parsed.dependencies!!["@react-native/oss-library-example"]!! .platforms!! .android!! .isPureCxxDependency!!) .isFalse() } private fun createJsonFile(@Language("JSON") input: String) = tempFolder.newFile().apply { writeText(input) } }