1# Copyright (c) Meta Platforms, Inc. and affiliates. 2# 3# This source code is licensed under the MIT license found in the 4# LICENSE file in the root directory of this source tree. 5 6require "test/unit" 7require_relative "../codegen.rb" 8require_relative "./test_utils/PodMock.rb" 9require_relative "./test_utils/PathnameMock.rb" 10require_relative "./test_utils/FileMock.rb" 11require_relative "./test_utils/DirMock.rb" 12require_relative "./test_utils/systemUtils.rb" 13require_relative "./test_utils/CodegenUtilsMock.rb" 14 15class CodegenTests < Test::Unit::TestCase 16 :third_party_provider_header 17 :third_party_provider_implementation 18 :base_path 19 :prefix 20 :tmp_schema_list_file 21 22 def setup 23 Pod::Config.reset() 24 25 @prefix = "../.." 26 @third_party_provider_header = "RCTThirdPartyFabricComponentsProvider.h" 27 @third_party_provider_implementation = "RCTThirdPartyFabricComponentsProvider.mm" 28 @base_path = "~/app/ios" 29 @tmp_schema_list_file = "tmpSchemaList.txt" 30 Pathname.pwd!(@base_path) 31 Pod::Config.instance.installation_root.relative_path_from = @base_path 32 end 33 34 def teardown 35 system_reset_commands() 36 Pod::UI.reset() 37 Pod::Executable.reset() 38 Pathname.reset() 39 FileMock.reset() 40 DirMock.reset() 41 end 42 43 # ============================================== # 44 # Test - setup_fabric # 45 # ============================================== # 46 def testCheckAndGenerateEmptyThirdPartyProvider_whenFileAlreadyExists_doNothing() 47 48 # Arrange 49 FileMock.mocked_existing_files([ 50 @prefix + "/React/Fabric/" + @third_party_provider_header, 51 @prefix + "/React/Fabric/" + @third_party_provider_implementation, 52 ]) 53 54 # Act 55 checkAndGenerateEmptyThirdPartyProvider!(@prefix, false, dir_manager: DirMock, file_manager: FileMock) 56 57 # Assert 58 assert_equal(Pathname.pwd_invocation_count, 1) 59 assert_equal(Pod::Config.instance.installation_root.relative_path_from_invocation_count, 1) 60 assert_equal(FileMock.exist_invocation_params, [ 61 @prefix + "/React/Fabric/" + @third_party_provider_header, 62 @prefix + "/React/Fabric/" + @third_party_provider_implementation, 63 ]) 64 assert_equal(DirMock.exist_invocation_params, []) 65 assert_equal(Pod::UI.collected_messages, []) 66 assert_equal($collected_commands, []) 67 assert_equal(FileMock.open_files.length, 0) 68 assert_equal(Pod::Executable.executed_commands.length, 0) 69 end 70 71 def testCheckAndGenerateEmptyThirdPartyProvider_whenHeaderMissingAndCodegenMissing_raiseError() 72 73 # Arrange 74 FileMock.mocked_existing_files([ 75 @base_path + "/build/" + @third_party_provider_implementation, 76 ]) 77 78 # Act 79 assert_raise { 80 checkAndGenerateEmptyThirdPartyProvider!(@prefix, false, dir_manager: DirMock, file_manager: FileMock) 81 } 82 83 # Assert 84 assert_equal(Pathname.pwd_invocation_count, 1) 85 assert_equal(Pod::Config.instance.installation_root.relative_path_from_invocation_count, 1) 86 assert_equal(FileMock.exist_invocation_params, [ 87 @prefix + "/React/Fabric/" + @third_party_provider_header 88 ]) 89 assert_equal(DirMock.exist_invocation_params, [ 90 @base_path + "/"+ @prefix + "/../react-native-codegen", 91 @base_path + "/"+ @prefix + "/../@react-native/codegen", 92 ]) 93 assert_equal(Pod::UI.collected_messages, []) 94 assert_equal($collected_commands, []) 95 assert_equal(FileMock.open_files.length, 0) 96 assert_equal(Pod::Executable.executed_commands.length, 0) 97 end 98 99 def testCheckAndGenerateEmptyThirdPartyProvider_whenImplementationMissingAndCodegenrepoExists_dontBuildCodegen() 100 101 # Arrange 102 FileMock.mocked_existing_files([ 103 @prefix + "/React/Fabric/" + @third_party_provider_header, 104 @prefix + "/React/Fabric/tmpSchemaList.txt" 105 ]) 106 107 DirMock.mocked_existing_dirs([ 108 @base_path + "/"+ @prefix + "/../react-native-codegen", 109 @base_path + "/"+ @prefix + "/../react-native-codegen/lib" 110 ]) 111 112 # Act 113 checkAndGenerateEmptyThirdPartyProvider!(@prefix, false, dir_manager: DirMock, file_manager: FileMock) 114 115 # Assert 116 assert_equal(Pathname.pwd_invocation_count, 1) 117 assert_equal(Pod::Config.instance.installation_root.relative_path_from_invocation_count, 1) 118 assert_equal(FileMock.exist_invocation_params, [ 119 @prefix + "/React/Fabric/" + @third_party_provider_header, 120 @prefix + "/React/Fabric/" + @third_party_provider_implementation, 121 @prefix + "/React/Fabric/tmpSchemaList.txt", 122 ]) 123 assert_equal(DirMock.exist_invocation_params, [ 124 @base_path + "/"+ @prefix + "/../react-native-codegen", 125 @base_path + "/"+ @prefix + "/../react-native-codegen/lib", 126 ]) 127 assert_equal(Pod::UI.collected_messages, ["[Codegen] generating an empty RCTThirdPartyFabricComponentsProvider"]) 128 assert_equal($collected_commands, []) 129 assert_equal(FileMock.open_invocation_count, 1) 130 assert_equal(FileMock.open_files_with_mode[@prefix + "/React/Fabric/tmpSchemaList.txt"], 'w') 131 assert_equal(FileMock.open_files[0].collected_write, ["[]"]) 132 assert_equal(FileMock.open_files[0].fsync_invocation_count, 1) 133 assert_equal(Pod::Executable.executed_commands[0], { 134 "command" => "node", 135 "arguments" => [ 136 @base_path + "/" + @prefix + "/scripts/generate-provider-cli.js", 137 "--platform", 'ios', 138 "--schemaListPath", @prefix + "/React/Fabric/tmpSchemaList.txt", 139 "--outputDir", @prefix + "/React/Fabric" 140 ] 141 }) 142 assert_equal(FileMock.delete_invocation_count, 1) 143 assert_equal(FileMock.deleted_files, [ @prefix + "/React/Fabric/tmpSchemaList.txt"]) 144 end 145 146 def testCheckAndGenerateEmptyThirdPartyProvider_whenBothMissing_buildCodegen() 147 # Arrange 148 codegen_cli_path = @base_path + "/" + @prefix + "/../@react-native/codegen" 149 DirMock.mocked_existing_dirs([ 150 codegen_cli_path, 151 ]) 152 # Act 153 checkAndGenerateEmptyThirdPartyProvider!(@prefix, false, dir_manager: DirMock, file_manager: FileMock) 154 155 # Assert 156 assert_equal(Pathname.pwd_invocation_count, 1) 157 assert_equal(Pod::Config.instance.installation_root.relative_path_from_invocation_count, 1) 158 assert_equal(FileMock.exist_invocation_params, [ 159 @prefix + "/React/Fabric/" + @third_party_provider_header, 160 @prefix + "/React/Fabric/" + @tmp_schema_list_file 161 ]) 162 assert_equal(DirMock.exist_invocation_params, [ 163 @base_path + "/" + @prefix + "/../react-native-codegen", 164 codegen_cli_path, 165 codegen_cli_path + "/lib", 166 ]) 167 assert_equal(Pod::UI.collected_messages, [ 168 "[Codegen] building #{codegen_cli_path}.", 169 "[Codegen] generating an empty RCTThirdPartyFabricComponentsProvider" 170 ]) 171 assert_equal($collected_commands, ["~/app/ios/../../../@react-native/codegen/scripts/oss/build.sh"]) 172 assert_equal(FileMock.open_files[0].collected_write, ["[]"]) 173 assert_equal(FileMock.open_files[0].fsync_invocation_count, 1) 174 assert_equal(Pod::Executable.executed_commands[0], { 175 "command" => "node", 176 "arguments" => [ 177 @base_path + "/" + @prefix + "/scripts/generate-provider-cli.js", 178 "--platform", 'ios', 179 "--schemaListPath", @prefix + "/React/Fabric/" + @tmp_schema_list_file, 180 "--outputDir", @prefix + "/React/Fabric" 181 ] 182 }) 183 end 184 185 # ================= # 186 # Test - RunCodegen # 187 # ================= # 188 def testRunCodegen_whenNewArchEnabled_runsCodegen 189 # Arrange 190 app_path = "~/app" 191 config_file = "" 192 codegen_utils_mock = CodegenUtilsMock.new() 193 194 # Act 195 run_codegen!(app_path, config_file, :new_arch_enabled => true, :codegen_utils => codegen_utils_mock) 196 197 # Assert 198 assert_equal(codegen_utils_mock.use_react_native_codegen_discovery_params, [{ 199 :app_path=>"~/app", 200 :codegen_disabled=>false, 201 :codegen_output_dir=>"build/generated/ios", 202 :config_file_dir=>"", 203 :fabric_enabled=>false, 204 :folly_version=>"2021.07.22.00", 205 :react_native_path=>"../node_modules/react-native" 206 }]) 207 assert_equal(codegen_utils_mock.get_react_codegen_spec_params, []) 208 assert_equal(codegen_utils_mock.generate_react_codegen_spec_params, []) 209 end 210 211 def testRunCodegen_whenNewArchDisabled_runsCodegen 212 # Arrange 213 app_path = "~/app" 214 config_file = "" 215 package_json_file = "~/app/package.json" 216 codegen_specs = { "name" => "ABI49_0_0React-Codegen" } 217 codegen_utils_mock = CodegenUtilsMock.new(:react_codegen_spec => codegen_specs) 218 219 # Act 220 run_codegen!( 221 app_path, 222 config_file, 223 :new_arch_enabled => false, 224 :fabric_enabled => true, 225 :package_json_file => package_json_file, 226 :codegen_utils => codegen_utils_mock) 227 228 # Assert 229 assert_equal(codegen_utils_mock.use_react_native_codegen_discovery_params, []) 230 assert_equal(codegen_utils_mock.get_react_codegen_spec_params, [{ 231 :fabric_enabled => true, 232 :folly_version=>"2021.07.22.00", 233 :package_json_file => "~/app/package.json", 234 :script_phases => nil 235 }]) 236 assert_equal(codegen_utils_mock.generate_react_codegen_spec_params, [{ 237 :codegen_output_dir=>"build/generated/ios", 238 :react_codegen_spec=>{"name"=>"ABI49_0_0React-Codegen"} 239 }]) 240 241 end 242end 243