Skip to content

Commit 2ce3686

Browse files
artus9033meta-codesync[bot]
authored andcommitted
fix(test): fix RNTester iOS unit and integration tests (#53848)
Summary: This PR fixes problems with unit & integration tests in the iOS RNTester project, related to: compilation errors, JS problems, missing mocks & outdated baselines. ## Changelog: [Internal] - Re-enabled iOS unit & integration tests, Ruby tests on CI, stripped obsolete build part before running tests, renamed uploaded xcresult artifacts Pull Request resolved: #53848 Test Plan: 1. iOS tests pass: - When run from dedicated xcschemes: <img width="596" height="388" alt="image" src="https://github.com/user-attachments/assets/9f3a038b-f12e-4b12-ab95-93d55eb60d63" /> <img width="611" height="381" alt="image" src="https://github.com/user-attachments/assets/27ff3a6f-57da-4842-a96c-db569e417dc3" /> - When run from the RNTester scheme (command + U): <img width="754" height="384" alt="image" src="https://github.com/user-attachments/assets/0b4a6e70-56da-40c1-b019-b1e87d8df591" /> 2. Ruby scripting tests pass: <img width="655" height="349" alt="image" src="https://github.com/user-attachments/assets/a6a41d16-2744-44c9-bf87-e4a06f228cfb" /> 3. CI - green 4. xcresult artifacts are uploaded <img width="1370" height="478" alt="image" src="https://github.com/user-attachments/assets/1bd0638d-f215-48f7-b798-fadb8799c5f7" /> Reviewed By: huntie Differential Revision: D88733170 Pulled By: cipolleschi fbshipit-source-id: e14c69bede1db34461926726bc796804b365a7a9
1 parent 700d320 commit 2ce3686

40 files changed

Lines changed: 360 additions & 297 deletions

.github/actions/test-ios-rntester/action.yml

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ inputs:
66
default: 2.6.10
77
run-unit-tests:
88
description: whether unit tests should run or not.
9-
default: "false"
9+
default: "true"
1010
flavor:
1111
description: The flavor of the build. Must be one of "Debug", "Release".
1212
default: Debug
@@ -104,15 +104,14 @@ runs:
104104
shell: bash
105105
run: |
106106
echo "zipping tests results"
107-
cd /Users/distiller/Library/Developer/Xcode
108-
XCRESULT_PATH=$(find . -name '*.xcresult')
109-
tar -zcvf xcresults.tar.gz $XCRESULT_PATH
107+
cd /Users/runner/Library/Developer/Xcode
108+
tar -zcvf xcresults.tar.gz "/tmp/RNTesterTestResults"
110109
- name: Upload artifact
111110
uses: actions/upload-artifact@v4.3.4
112111
if: ${{ inputs.run-unit-tests == 'true' }}
113112
with:
114-
name: xcresults
115-
path: /Users/distiller/Library/Developer/Xcode/xcresults.tar.gz
113+
name: xcresults-${{ inputs.flavor }}-${{ inputs.use-frameworks == 'true' && 'dynamic-frameworks' || 'static-libraries' }}-Ruby${{ inputs.ruby-version }}
114+
path: /Users/runner/Library/Developer/Xcode/xcresults.tar.gz
116115
- name: Upload RNTester App
117116
if: ${{ inputs.use-frameworks == 'false' && inputs.ruby-version == '2.6.10' }} # This is needed to avoid conflicts with the artifacts
118117
uses: actions/upload-artifact@v4.3.4
@@ -123,5 +122,5 @@ runs:
123122
if: ${{ inputs.run-unit-tests == 'true' }}
124123
uses: actions/upload-artifact@v4.3.4
125124
with:
126-
name: test-results
125+
name: test-results-${{ inputs.flavor }}-${{ inputs.use-frameworks == 'true' && 'dynamic-frameworks' || 'static-libraries' }}-Ruby${{ inputs.ruby-version }}
127126
path: ./reports/junit

.github/workflows/test-all.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,9 @@ jobs:
7070
- name: Run it
7171
uses: ./.github/actions/test-ios-rntester
7272
with:
73-
flavor: Debug
73+
flavor: ${{ matrix.flavor }}
7474
use-frameworks: true
75-
75+
run-unit-tests: false # tests for dynamic frameworks are already run in the test_ios_rntester job; this is to just a test build from source (no prebuilds)
7676

7777
test_ios_rntester:
7878
runs-on: macos-15-large

packages/react-native/React/Base/RCTBridge.mm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ - (instancetype)initWithDelegate:(id<RCTBridgeDelegate>)delegate
369369
moduleProvider:(RCTBridgeModuleListProvider)block
370370
launchOptions:(NSDictionary *)launchOptions
371371
{
372-
// Only enabld this assertion in OSS
372+
// Only enable this assertion in OSS
373373
#if COCOAPODS
374374
[RCTBridge throwIfOnLegacyArch];
375375
#endif

packages/react-native/React/Base/RCTUtils.mm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -706,7 +706,7 @@ BOOL RCTForceTouchAvailable(void)
706706
[data base64EncodedStringWithOptions:(NSDataBase64EncodingOptions)0]]];
707707
}
708708

709-
BOOL RCTIsGzippedData(NSData *__nullable /*data*/); // exposed for unit testing purposes
709+
extern "C" BOOL RCTIsGzippedData(NSData *__nullable /*data*/); // exposed for unit testing purposes
710710
BOOL RCTIsGzippedData(NSData *__nullable data)
711711
{
712712
UInt8 *bytes = (UInt8 *)data.bytes;

packages/react-native/scripts/cocoapods/__tests__/codegen_utils-test.rb

Lines changed: 35 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ class CodegenUtilsTests < Test::Unit::TestCase
3333

3434
def setup
3535
CodegenUtils.set_react_codegen_discovery_done(false)
36-
CodegenUtils.set_react_codegen_podspec_generated(false)
3736
Pod::Config.reset()
3837
@base_path = "~/app/ios"
3938
Pathname.pwd!(@base_path)
@@ -62,8 +61,8 @@ def testUseReactCodegenDiscovery_whenCodegenDisabled_doNothing
6261

6362
# Assert
6463
assert_false(CodegenUtils.react_codegen_discovery_done())
65-
assert_equal(Pod::UI.collected_messages, [])
66-
assert_equal(Pod::UI.collected_warns, [])
64+
assert_equal([], Pod::UI.collected_messages)
65+
assert_equal([], Pod::UI.collected_warns)
6766
end
6867

6968
def testUseReactCodegenDiscovery_whenDiscoveryDone_doNothing
@@ -75,8 +74,8 @@ def testUseReactCodegenDiscovery_whenDiscoveryDone_doNothing
7574

7675
# Assert
7776
assert_true(CodegenUtils.react_codegen_discovery_done())
78-
assert_equal(Pod::UI.collected_messages, ["Skipping use_react_native_codegen_discovery."])
79-
assert_equal(Pod::UI.collected_warns, [])
77+
assert_equal(["Skipping use_react_native_codegen_discovery."], Pod::UI.collected_messages)
78+
assert_equal([], Pod::UI.collected_warns)
8079
end
8180

8281
def testUseReactCodegenDiscovery_whenAppPathUndefined_abort
@@ -89,16 +88,16 @@ def testUseReactCodegenDiscovery_whenAppPathUndefined_abort
8988

9089
# Assert
9190
assert_false(CodegenUtils.react_codegen_discovery_done())
92-
assert_equal(Pod::UI.collected_messages, [])
93-
assert_equal(Pod::UI.collected_warns, [
91+
assert_equal([], Pod::UI.collected_messages)
92+
assert_equal([
9493
'Error: app_path is required for use_react_native_codegen_discovery.',
9594
'If you are calling use_react_native_codegen_discovery! in your Podfile, please remove the call and pass `app_path` and/or `config_file_dir` to `use_react_native!`.'
96-
])
95+
], Pod::UI.collected_warns)
9796
end
9897

99-
# ============================= #
98+
# =========================== #
10099
# Test - CleanUpCodegenFolder #
101-
# ============================= #
100+
# =========================== #
102101

103102
def testCleanUpCodegenFolder_whenCleanupDone_doNothing
104103
# Arrange
@@ -110,9 +109,9 @@ def testCleanUpCodegenFolder_whenCleanupDone_doNothing
110109
CodegenUtils.clean_up_build_folder(rn_path, codegen_dir, dir_manager: DirMock, file_manager: FileMock)
111110

112111
# Assert
113-
assert_equal(FileUtils::FileUtilsStorage.rmrf_invocation_count, 0)
114-
assert_equal(FileUtils::FileUtilsStorage.rmrf_paths, [])
115-
assert_equal(CodegenUtils.cleanup_done(), true)
112+
assert_equal(0, FileUtils::FileUtilsStorage.rmrf_invocation_count)
113+
assert_equal([], FileUtils::FileUtilsStorage.rmrf_paths)
114+
assert_equal(true, CodegenUtils.cleanup_done())
116115
end
117116

118117
def testCleanUpCodegenFolder_whenFolderDoesNotExists_markAsCleanupDone
@@ -125,10 +124,10 @@ def testCleanUpCodegenFolder_whenFolderDoesNotExists_markAsCleanupDone
125124
CodegenUtils.clean_up_build_folder(rn_path, codegen_dir, dir_manager: DirMock, file_manager: FileMock)
126125

127126
# Assert
128-
assert_equal(FileUtils::FileUtilsStorage.rmrf_invocation_count, 0)
129-
assert_equal(FileUtils::FileUtilsStorage.rmrf_paths, [])
130-
assert_equal(DirMock.glob_invocation, [])
131-
assert_equal(CodegenUtils.cleanup_done(), true)
127+
assert_equal(0, FileUtils::FileUtilsStorage.rmrf_invocation_count)
128+
assert_equal([], FileUtils::FileUtilsStorage.rmrf_paths)
129+
assert_equal([], DirMock.glob_invocation)
130+
assert_equal(true, CodegenUtils.cleanup_done())
132131
end
133132

134133
def testCleanUpCodegenFolder_whenFolderExists_deleteItAndSetCleanupDone
@@ -137,29 +136,33 @@ def testCleanUpCodegenFolder_whenFolderExists_deleteItAndSetCleanupDone
137136
codegen_dir = "build/generated/ios"
138137
codegen_path = "#{@base_path}/#{codegen_dir}"
139138
globs = [
140-
"/MyModuleSpecs/MyModule.h",
141-
"#{codegen_path}/MyModuleSpecs/MyModule.mm",
142-
"#{codegen_path}/react/components/MyComponent/ShadowNode.h",
143-
"#{codegen_path}/react/components/MyComponent/ShadowNode.mm",
139+
codegen_path
144140
]
145141
rn_path = '../node_modules/react-native'
146142

147143
DirMock.mocked_existing_dirs(codegen_path)
148144
DirMock.mocked_existing_globs(globs, "#{codegen_path}/*")
149145

146+
original_define_singleton_method = CodegenUtils.method(:assert_codegen_folder_is_empty)
147+
CodegenUtils.define_singleton_method(:assert_codegen_folder_is_empty) do |*args, **kwargs|
148+
# no-op
149+
end
150+
150151
# Act
151152
CodegenUtils.clean_up_build_folder(rn_path, codegen_dir, dir_manager: DirMock, file_manager: FileMock)
152153

153154
# Assert
154-
assert_equal(DirMock.exist_invocation_params, [codegen_path, codegen_path])
155-
assert_equal(DirMock.glob_invocation, ["#{codegen_path}/*", "#{codegen_path}/*"])
156-
assert_equal(FileUtils::FileUtilsStorage.rmrf_invocation_count, 3)
157-
assert_equal(FileUtils::FileUtilsStorage.rmrf_paths, [
158-
globs,
155+
assert_equal([codegen_path], DirMock.exist_invocation_params)
156+
assert_equal(3, FileUtils::FileUtilsStorage.rmrf_invocation_count)
157+
assert_equal([
158+
*globs,
159159
"#{rn_path}/React/Fabric/RCTThirdPartyFabricComponentsProvider.h",
160160
"#{rn_path}/React/Fabric/RCTThirdPartyFabricComponentsProvider.mm",
161-
])
162-
assert_equal(CodegenUtils.cleanup_done(), true)
161+
], FileUtils::FileUtilsStorage.rmrf_paths)
162+
assert_equal(true, CodegenUtils.cleanup_done())
163+
ensure
164+
# Restore original method so other tests are not affected
165+
CodegenUtils.define_singleton_method(:assert_codegen_folder_is_empty, original_define_singleton_method)
163166
end
164167

165168
# ===================================== #
@@ -175,7 +178,7 @@ def test_assertCodegenFolderIsEmpty_whenItDoesNotExists_doesNotAbort
175178
CodegenUtils.assert_codegen_folder_is_empty(codegen_path, dir_manager: DirMock)
176179

177180
# Assert
178-
assert_equal(Pod::UI.collected_warns, [])
181+
assert_equal([], Pod::UI.collected_warns)
179182
end
180183

181184
def test_assertCodegenFolderIsEmpty_whenItExistsAndIsEmpty_doesNotAbort
@@ -189,7 +192,7 @@ def test_assertCodegenFolderIsEmpty_whenItExistsAndIsEmpty_doesNotAbort
189192
CodegenUtils.assert_codegen_folder_is_empty(codegen_path, dir_manager: DirMock)
190193

191194
# Assert
192-
assert_equal(Pod::UI.collected_warns, [])
195+
assert_equal([], Pod::UI.collected_warns)
193196
end
194197

195198
def test_assertCodegenFolderIsEmpty_whenItIsNotEmpty_itAborts
@@ -205,9 +208,9 @@ def test_assertCodegenFolderIsEmpty_whenItIsNotEmpty_itAborts
205208
}
206209

207210
# Assert
208-
assert_equal(Pod::UI.collected_warns, [
211+
assert_equal([
209212
"Unable to remove the content of ~/app/ios/./build/generated/ios folder. Please run rm -rf ~/app/ios/./build/generated/ios and try again."
210-
])
213+
], Pod::UI.collected_warns)
211214
end
212215

213216
private

packages/react-native/scripts/cocoapods/__tests__/fabric-test.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,6 @@ def check_pod(name, path: nil, modular_headers: nil, podspec: nil)
5252
if modular_headers != nil then expected_params[:modular_headers] = modular_headers end
5353
if podspec != nil then expected_params[:podspec] = podspec end
5454

55-
assert_equal(params, expected_params)
55+
assert_equal(expected_params, params)
5656
end
5757
end

packages/react-native/scripts/cocoapods/__tests__/jsengine-test.rb

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,11 @@ def test_setupHermes_installsPods
3737
setup_hermes!(:react_native_path => @react_native_path)
3838

3939
# Assert
40-
assert_equal($podInvocationCount, 3)
41-
assert_equal($podInvocation["React-jsi"][:path], "../../ReactCommon/jsi")
40+
assert_equal(2, $podInvocationCount)
4241
hermes_engine_pod_invocation = $podInvocation["hermes-engine"]
43-
assert_equal(hermes_engine_pod_invocation[:podspec], "../../sdks/hermes-engine/hermes-engine.podspec")
44-
assert_equal(hermes_engine_pod_invocation[:tag], "")
45-
assert_equal($podInvocation["React-hermes"][:path], "../../ReactCommon/hermes")
42+
assert_equal("../../sdks/hermes-engine/hermes-engine.podspec", hermes_engine_pod_invocation[:podspec])
43+
assert_equal("", hermes_engine_pod_invocation[:tag])
44+
assert_equal("../../ReactCommon/hermes", $podInvocation["React-hermes"][:path])
4645
end
4746

4847
end

packages/react-native/scripts/cocoapods/__tests__/local_podspec_patch-test.rb

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,12 @@ def test_podsToUpdate_whenNoFilesExists_returnLocalPodspecs
3434
local_podspec = LocalPodspecPatch.pods_to_update(:react_native_path => react_native_path, dir_manager: DirMock, file_manager: FileMock)
3535

3636
# Assert
37-
assert_equal(local_podspec, [])
38-
assert_equal(DirMock.glob_invocation, ["#{react_native_path}/third-party-podspecs/*"])
39-
assert_equal(FileMock.exist_invocation_params, [
37+
assert_equal([], local_podspec)
38+
assert_equal(["#{react_native_path}/third-party-podspecs/*"], DirMock.glob_invocation)
39+
assert_equal([
4040
FileMock.join(mocked_pwd, "Pods/Local Podspecs", "boost.podspec.json"),
4141
FileMock.join(mocked_pwd, "Pods/Local Podspecs", "DoubleConversion.podspec.json"),
42-
])
42+
], FileMock.exist_invocation_params)
4343
end
4444

4545
def test_podsToUpdate_whenFilesExistsWithSameVersions_returnsEmpty
@@ -53,12 +53,12 @@ def test_podsToUpdate_whenFilesExistsWithSameVersions_returnsEmpty
5353
local_podspec = LocalPodspecPatch.pods_to_update(:react_native_path => react_native_path, dir_manager: DirMock, file_manager: FileMock)
5454

5555
# Assert
56-
assert_equal(local_podspec, [])
57-
assert_equal(DirMock.glob_invocation, ["#{react_native_path}/third-party-podspecs/*"])
58-
assert_equal(FileMock.exist_invocation_params, [
56+
assert_equal([], local_podspec)
57+
assert_equal(["#{react_native_path}/third-party-podspecs/*"], DirMock.glob_invocation)
58+
assert_equal([
5959
FileMock.join(mocked_pwd, "Pods/Local Podspecs", "boost.podspec.json"),
6060
FileMock.join(mocked_pwd, "Pods/Local Podspecs", "DoubleConversion.podspec.json"),
61-
])
61+
], FileMock.exist_invocation_params)
6262
end
6363

6464
def test_podsToUpdate_whenFilesExistsWithDifferentVersions_returnsThem
@@ -72,15 +72,15 @@ def test_podsToUpdate_whenFilesExistsWithDifferentVersions_returnsThem
7272
local_podspec = LocalPodspecPatch.pods_to_update(:react_native_path => react_native_path, dir_manager: DirMock, file_manager: FileMock)
7373

7474
# Assert
75-
assert_equal(local_podspec, [
75+
assert_equal([
7676
"boost",
7777
"DoubleConversion"
78-
])
79-
assert_equal(DirMock.glob_invocation, ["#{react_native_path}/third-party-podspecs/*"])
80-
assert_equal(FileMock.exist_invocation_params, [
78+
], local_podspec)
79+
assert_equal(["#{react_native_path}/third-party-podspecs/*"], DirMock.glob_invocation)
80+
assert_equal([
8181
FileMock.join(mocked_pwd, "Pods/Local Podspecs", "boost.podspec.json"),
8282
FileMock.join(mocked_pwd, "Pods/Local Podspecs", "DoubleConversion.podspec.json"),
83-
])
83+
], FileMock.exist_invocation_params)
8484
end
8585

8686
# ======================================== #
@@ -101,10 +101,10 @@ def test_patchDetectChangesWithPodfile_whenAlreadyChanged_returnSameChangeSet()
101101

102102
new_changes = Pod::Lockfile.new().patch_detect_changes_with_podfile(changes)
103103

104-
assert_equal(new_changes, {
104+
assert_equal({
105105
:unchanged => ["some_pod"],
106106
:changed => ["boost", "DoubleConversion", "another_pod"]
107-
})
107+
}, new_changes)
108108
end
109109

110110
def test_patchDetectChangesWithPodfile_whenLocalPodsUnchanged_movesLocalPodsToChangeSet()
@@ -122,10 +122,10 @@ def test_patchDetectChangesWithPodfile_whenLocalPodsUnchanged_movesLocalPodsToCh
122122

123123
new_changes = Pod::Lockfile.new().patch_detect_changes_with_podfile(changes)
124124

125-
assert_equal(new_changes, {
125+
assert_equal({
126126
:unchanged => ["first_pod"],
127127
:changed => ["another_pod", "boost", "DoubleConversion"]
128-
})
128+
}, new_changes)
129129
end
130130

131131
# ========= #

0 commit comments

Comments
 (0)