Skip to content

Commit 258e31c

Browse files
russellwheatleymikehardy
authored andcommitted
refactor(app, ios): wrap SPM cross-podspec state in RNFirebaseSPM module
Replace the three bare globals ($rnfirebase_spm_active, $rnfirebase_spm_version, $firebase_spm_url) threading state between podspec evaluation and post_install with a single RNFirebaseSPM module (activate!/active?/version/url/reset!). active? now self-checks internal consistency, raising Pod::Informative if the active flag is ever true without a recorded version, instead of every downstream helper trusting a bare boolean blindly. Test suite now uses RNFirebaseSPM.reset! for state isolation instead of the previous one-way defined?-based workaround.
1 parent 3253504 commit 258e31c

2 files changed

Lines changed: 142 additions & 82 deletions

File tree

packages/app/__tests__/firebase_spm_test.rb

Lines changed: 37 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -232,8 +232,6 @@ def initialize(aggregate_targets)
232232

233233
class FirebaseSpmTest < Minitest::Test
234234
def setup
235-
# Reset global state before each test
236-
$firebase_spm_url = nil
237235
# Remove spm_dependency if defined from a previous test
238236
if defined?(spm_dependency)
239237
Object.send(:remove_method, :spm_dependency)
@@ -244,8 +242,13 @@ def setup
244242
# than relying on `defined?` alone) is exactly the behavior rnfirebase_spm_disabled?
245243
# is meant to guard against, so tests below assert on it explicitly.
246244
$RNFirebaseDisableSPM = nil
247-
# Same one-way-`defined?` caveat as $RNFirebaseDisableSPM above.
248-
$rnfirebase_spm_active = nil
245+
# `RNFirebaseSPM` gives us a real, deliberate reset primitive for the SPM
246+
# active/version/url state instead of relying on that same one-way-`defined?`
247+
# workaround -- unlike a bare global, `reset!` can put it back to a genuinely
248+
# "never activated" state between tests, not just back to a falsy value.
249+
# Guarded with `defined?` because the very first test's `setup` runs before
250+
# any test has `load`ed firebase_spm.rb yet, so the constant doesn't exist.
251+
RNFirebaseSPM.reset! if defined?(RNFirebaseSPM)
249252
# Reset the `Pod::UI` mock's captured output between tests.
250253
Pod::UI.warnings = []
251254
Pod::UI.messages = []
@@ -389,26 +392,26 @@ def test_disable_spm_unset_uses_spm
389392
def test_reads_spm_url_from_package_json
390393
load_firebase_spm
391394

392-
assert_equal 'https://github.com/firebase/firebase-ios-sdk.git', $firebase_spm_url
395+
assert_equal 'https://github.com/firebase/firebase-ios-sdk.git', RNFirebaseSPM.url
393396
end
394397

395-
# ── $rnfirebase_spm_active tracking (replaces reflecting into RN's `SPM`
398+
# ── RNFirebaseSPM.active? tracking (replaces reflecting into RN's `SPM`
396399
# internal object, which rnfirebase_add_spm_embed_phase used to do) ──
397400

398401
def test_spm_path_sets_active_flag
399402
Object.define_method(:spm_dependency) { |*| nil }
400403
load_firebase_spm
401404

402-
refute $rnfirebase_spm_active
405+
refute RNFirebaseSPM.active?
403406
firebase_dependency(MockSpec.new, '12.10.0', ['FirebaseAuth'], 'Firebase/Auth')
404-
assert $rnfirebase_spm_active
407+
assert RNFirebaseSPM.active?
405408
end
406409

407410
def test_cocoapods_path_does_not_set_active_flag
408411
load_firebase_spm
409412

410413
firebase_dependency(MockSpec.new, '12.10.0', ['FirebaseAuth'], 'Firebase/Auth')
411-
refute $rnfirebase_spm_active
414+
refute RNFirebaseSPM.active?
412415
end
413416

414417
def test_disabled_spm_does_not_set_active_flag_even_if_spm_dependency_defined
@@ -417,15 +420,14 @@ def test_disabled_spm_does_not_set_active_flag_even_if_spm_dependency_defined
417420
$RNFirebaseDisableSPM = true
418421

419422
firebase_dependency(MockSpec.new, '12.10.0', ['FirebaseAuth'], 'Firebase/Auth')
420-
refute $rnfirebase_spm_active
423+
refute RNFirebaseSPM.active?
421424
end
422425

423426
# ── rnfirebase_add_spm_embed_phase (invoked automatically by
424427
# rnfirebase_hook_cocoapods_post_install!, tested separately below) ──
425428

426429
def test_embed_phase_noop_when_spm_not_active
427430
load_firebase_spm
428-
$rnfirebase_spm_active = false
429431

430432
installer = MockInstaller.new(nil) # would raise if ever touched
431433
rnfirebase_add_spm_embed_phase(installer)
@@ -434,7 +436,7 @@ def test_embed_phase_noop_when_spm_not_active
434436

435437
def test_embed_phase_noop_without_cp_embed_pods_frameworks_phase
436438
load_firebase_spm
437-
$rnfirebase_spm_active = true
439+
RNFirebaseSPM.activate!('12.10.0')
438440

439441
target = MockTarget.new(['[CP] Some Other Phase'])
440442
user_project = MockUserProject.new([target])
@@ -450,7 +452,7 @@ def test_embed_phase_noop_without_cp_embed_pods_frameworks_phase
450452

451453
def test_embed_phase_adds_phase_when_active_and_cp_phase_present
452454
load_firebase_spm
453-
$rnfirebase_spm_active = true
455+
RNFirebaseSPM.activate!('12.10.0')
454456

455457
target = MockTarget.new(['[CP] Embed Pods Frameworks'])
456458
user_project = MockUserProject.new([target])
@@ -470,7 +472,7 @@ def test_embed_phase_adds_phase_when_active_and_cp_phase_present
470472

471473
def test_embed_phase_is_idempotent_across_repeated_pod_installs
472474
load_firebase_spm
473-
$rnfirebase_spm_active = true
475+
RNFirebaseSPM.activate!('12.10.0')
474476

475477
target = MockTarget.new(['[CP] Embed Pods Frameworks'])
476478
user_project = MockUserProject.new([target])
@@ -491,7 +493,6 @@ def test_embed_phase_is_idempotent_across_repeated_pod_installs
491493

492494
def test_add_core_noop_when_spm_not_active
493495
load_firebase_spm
494-
$rnfirebase_spm_active = false
495496

496497
installer = MockInstaller.new(nil) # would raise if ever touched
497498
rnfirebase_add_spm_core_to_app_target(installer)
@@ -500,9 +501,7 @@ def test_add_core_noop_when_spm_not_active
500501

501502
def test_add_core_noop_without_cp_embed_pods_frameworks_phase
502503
load_firebase_spm
503-
$rnfirebase_spm_active = true
504-
$firebase_spm_url = 'https://github.com/firebase/firebase-ios-sdk.git'
505-
$rnfirebase_spm_version = '12.10.0'
504+
RNFirebaseSPM.activate!('12.10.0')
506505

507506
target = MockTarget.new(['[CP] Some Other Phase'])
508507
user_project = MockUserProject.new([target])
@@ -516,9 +515,7 @@ def test_add_core_noop_without_cp_embed_pods_frameworks_phase
516515

517516
def test_add_core_links_firebase_core_when_active_and_cp_phase_present
518517
load_firebase_spm
519-
$rnfirebase_spm_active = true
520-
$firebase_spm_url = 'https://github.com/firebase/firebase-ios-sdk.git'
521-
$rnfirebase_spm_version = '12.10.0'
518+
RNFirebaseSPM.activate!('12.10.0')
522519

523520
target = MockTarget.new(['[CP] Embed Pods Frameworks'])
524521
user_project = MockUserProject.new([target])
@@ -529,7 +526,7 @@ def test_add_core_links_firebase_core_when_active_and_cp_phase_present
529526
assert_equal 1, target.package_product_dependencies.length
530527
ref = target.package_product_dependencies[0]
531528
assert_equal 'FirebaseCore', ref.product_name
532-
assert_equal $firebase_spm_url, ref.package.repositoryURL
529+
assert_equal RNFirebaseSPM.url, ref.package.repositoryURL
533530

534531
search_path = '${SYMROOT}/${CONFIGURATION}${EFFECTIVE_PLATFORM_NAME}/'
535532
target.build_configurations.each do |config|
@@ -541,9 +538,7 @@ def test_add_core_links_firebase_core_when_active_and_cp_phase_present
541538

542539
def test_add_core_is_idempotent_across_repeated_pod_installs
543540
load_firebase_spm
544-
$rnfirebase_spm_active = true
545-
$firebase_spm_url = 'https://github.com/firebase/firebase-ios-sdk.git'
546-
$rnfirebase_spm_version = '12.10.0'
541+
RNFirebaseSPM.activate!('12.10.0')
547542

548543
target = MockTarget.new(['[CP] Embed Pods Frameworks'])
549544
user_project = MockUserProject.new([target])
@@ -557,9 +552,7 @@ def test_add_core_is_idempotent_across_repeated_pod_installs
557552

558553
def test_add_core_handles_swift_include_paths_already_set_as_a_string
559554
load_firebase_spm
560-
$rnfirebase_spm_active = true
561-
$firebase_spm_url = 'https://github.com/firebase/firebase-ios-sdk.git'
562-
$rnfirebase_spm_version = '12.10.0'
555+
RNFirebaseSPM.activate!('12.10.0')
563556

564557
target = MockTarget.new(['[CP] Embed Pods Frameworks'])
565558
# Xcode/Xcodeproj may represent a list-type build setting as a
@@ -594,7 +587,7 @@ def test_add_core_handles_swift_include_paths_already_set_as_a_string
594587

595588
def test_remove_core_noop_when_spm_active
596589
load_firebase_spm
597-
$rnfirebase_spm_active = true
590+
RNFirebaseSPM.activate!('12.10.0')
598591

599592
installer = MockInstaller.new(nil) # would raise if ever touched
600593
rnfirebase_remove_spm_core_from_app_target(installer)
@@ -603,8 +596,6 @@ def test_remove_core_noop_when_spm_active
603596

604597
def test_remove_core_noop_when_no_stale_dependency_present
605598
load_firebase_spm
606-
$rnfirebase_spm_active = false
607-
$firebase_spm_url = 'https://github.com/firebase/firebase-ios-sdk.git'
608599

609600
target = MockTarget.new(['[CP] Embed Pods Frameworks'])
610601
user_project = MockUserProject.new([target])
@@ -618,14 +609,12 @@ def test_remove_core_noop_when_no_stale_dependency_present
618609

619610
def test_remove_core_removes_stale_dependency_and_orphaned_package_reference
620611
load_firebase_spm
621-
$rnfirebase_spm_active = false
622-
$firebase_spm_url = 'https://github.com/firebase/firebase-ios-sdk.git'
623612

624613
# Simulate the state left behind by a prior SPM-mode `pod install`: the
625614
# app target still has an explicit FirebaseCore product dependency, and
626615
# the project still has the backing package reference.
627616
pkg = Xcodeproj::Project::Object::XCRemoteSwiftPackageReference.new
628-
pkg.repositoryURL = $firebase_spm_url
617+
pkg.repositoryURL = RNFirebaseSPM.url
629618
ref = Xcodeproj::Project::Object::XCSwiftPackageProductDependency.new
630619
ref.product_name = 'FirebaseCore'
631620
ref.package = pkg
@@ -643,11 +632,9 @@ def test_remove_core_removes_stale_dependency_and_orphaned_package_reference
643632

644633
def test_remove_core_leaves_package_reference_when_still_used_by_another_target
645634
load_firebase_spm
646-
$rnfirebase_spm_active = false
647-
$firebase_spm_url = 'https://github.com/firebase/firebase-ios-sdk.git'
648635

649636
pkg = Xcodeproj::Project::Object::XCRemoteSwiftPackageReference.new
650-
pkg.repositoryURL = $firebase_spm_url
637+
pkg.repositoryURL = RNFirebaseSPM.url
651638

652639
stale_ref = Xcodeproj::Project::Object::XCSwiftPackageProductDependency.new
653640
stale_ref.product_name = 'FirebaseCore'
@@ -672,8 +659,6 @@ def test_remove_core_leaves_package_reference_when_still_used_by_another_target
672659

673660
def test_remove_core_ignores_dependencies_from_a_different_package_url
674661
load_firebase_spm
675-
$rnfirebase_spm_active = false
676-
$firebase_spm_url = 'https://github.com/firebase/firebase-ios-sdk.git'
677662

678663
unrelated_pkg = Xcodeproj::Project::Object::XCRemoteSwiftPackageReference.new
679664
unrelated_pkg.repositoryURL = 'https://github.com/some/other-package.git'
@@ -695,7 +680,6 @@ def test_remove_core_ignores_dependencies_from_a_different_package_url
695680

696681
def test_signature_collision_fix_noop_when_spm_not_active
697682
load_firebase_spm
698-
$rnfirebase_spm_active = false
699683

700684
installer = MockInstaller.new(nil) # would raise if ever touched
701685
rnfirebase_fix_spm_archive_signature_collision(installer)
@@ -704,7 +688,7 @@ def test_signature_collision_fix_noop_when_spm_not_active
704688

705689
def test_signature_collision_fix_adds_phase_removing_every_known_artifact
706690
load_firebase_spm
707-
$rnfirebase_spm_active = true
691+
RNFirebaseSPM.activate!('12.10.0')
708692

709693
target = MockTarget.new(['[CP] Embed Pods Frameworks'])
710694
user_project = MockUserProject.new([target])
@@ -723,7 +707,7 @@ def test_signature_collision_fix_adds_phase_removing_every_known_artifact
723707

724708
def test_signature_collision_fix_is_idempotent_across_repeated_pod_installs
725709
load_firebase_spm
726-
$rnfirebase_spm_active = true
710+
RNFirebaseSPM.activate!('12.10.0')
727711

728712
target = MockTarget.new(['[CP] Embed Pods Frameworks'])
729713
user_project = MockUserProject.new([target])
@@ -743,7 +727,6 @@ def test_signature_collision_fix_is_idempotent_across_repeated_pod_installs
743727

744728
def test_fail_fast_noop_when_spm_not_active
745729
load_firebase_spm
746-
$rnfirebase_spm_active = false
747730

748731
installer = MockInstaller.new(nil) # would raise if ever touched
749732
rnfirebase_fail_if_spm_static_linkage!(installer)
@@ -752,7 +735,7 @@ def test_fail_fast_noop_when_spm_not_active
752735

753736
def test_fail_fast_noop_when_spm_active_and_all_targets_dynamic
754737
load_firebase_spm
755-
$rnfirebase_spm_active = true
738+
RNFirebaseSPM.activate!('12.10.0')
756739

757740
installer = MockInstaller.new([
758741
MockAggregateTarget.new(nil, name: 'Pods-testing', static_linkage: false)
@@ -764,7 +747,7 @@ def test_fail_fast_noop_when_spm_active_and_all_targets_dynamic
764747

765748
def test_fail_fast_raises_pod_informative_when_spm_active_and_a_target_is_static
766749
load_firebase_spm
767-
$rnfirebase_spm_active = true
750+
RNFirebaseSPM.activate!('12.10.0')
768751

769752
installer = MockInstaller.new([
770753
MockAggregateTarget.new(nil, name: 'Pods-testing', static_linkage: true)
@@ -780,7 +763,7 @@ def test_fail_fast_raises_pod_informative_when_spm_active_and_a_target_is_static
780763

781764
def test_fail_fast_ignores_aggregate_targets_own_always_static_build_type
782765
load_firebase_spm
783-
$rnfirebase_spm_active = true
766+
RNFirebaseSPM.activate!('12.10.0')
784767

785768
# Regression test for the exact bug that broke every SPM CI job: real
786769
# CocoaPods' `AggregateTarget#build_as_static?` is `true` unconditionally
@@ -804,7 +787,7 @@ def target.build_as_static?
804787

805788
def test_fail_fast_lists_every_static_target_by_name
806789
load_firebase_spm
807-
$rnfirebase_spm_active = true
790+
RNFirebaseSPM.activate!('12.10.0')
808791

809792
installer = MockInstaller.new([
810793
MockAggregateTarget.new(nil, name: 'Pods-testing', static_linkage: true),
@@ -924,7 +907,7 @@ def test_hook_warns_and_noops_when_hook_method_does_not_exist
924907

925908
def test_hook_raises_and_skips_original_hook_when_spm_static_linkage_detected
926909
load_firebase_spm
927-
$rnfirebase_spm_active = true
910+
RNFirebaseSPM.activate!('12.10.0')
928911

929912
klass = new_fake_cocoapods_installer_class
930913
klass.send(:attr_reader, :aggregate_targets)
@@ -983,7 +966,6 @@ def test_hook_does_not_warn_when_already_hooked
983966

984967
def test_verify_embed_phase_noop_when_spm_not_active
985968
load_firebase_spm
986-
$rnfirebase_spm_active = false
987969

988970
installer = MockInstaller.new(nil) # would raise if ever touched
989971
rnfirebase_verify_spm_embed_phase_applied!(installer)
@@ -992,7 +974,7 @@ def test_verify_embed_phase_noop_when_spm_not_active
992974

993975
def test_verify_embed_phase_noop_without_cp_embed_pods_frameworks_phase
994976
load_firebase_spm
995-
$rnfirebase_spm_active = true
977+
RNFirebaseSPM.activate!('12.10.0')
996978

997979
# No `'[CP] Embed Pods Frameworks'` phase => this target never needed
998980
# the RNFB embed phase in the first place, so its absence isn't a failure.
@@ -1006,7 +988,7 @@ def test_verify_embed_phase_noop_without_cp_embed_pods_frameworks_phase
1006988

1007989
def test_verify_embed_phase_noop_when_phase_present
1008990
load_firebase_spm
1009-
$rnfirebase_spm_active = true
991+
RNFirebaseSPM.activate!('12.10.0')
1010992

1011993
target = MockTarget.new(['[CP] Embed Pods Frameworks'])
1012994
user_project = MockUserProject.new([target])
@@ -1020,7 +1002,7 @@ def test_verify_embed_phase_noop_when_phase_present
10201002

10211003
def test_verify_embed_phase_raises_pod_informative_when_phase_missing_on_target_that_needs_it
10221004
load_firebase_spm
1023-
$rnfirebase_spm_active = true
1005+
RNFirebaseSPM.activate!('12.10.0')
10241006

10251007
# Simulates `rnfirebase_add_spm_embed_phase` having silently failed to
10261008
# add its phase to a target that has `'[CP] Embed Pods Frameworks'` --
@@ -1039,7 +1021,7 @@ def test_verify_embed_phase_raises_pod_informative_when_phase_missing_on_target_
10391021

10401022
def test_verify_embed_phase_lists_every_missing_target_by_name
10411023
load_firebase_spm
1042-
$rnfirebase_spm_active = true
1024+
RNFirebaseSPM.activate!('12.10.0')
10431025

10441026
missing_target = MockTarget.new(['[CP] Embed Pods Frameworks'], name: 'missing-target')
10451027
present_target = MockTarget.new(['[CP] Embed Pods Frameworks'], name: 'present-target')
@@ -1061,7 +1043,7 @@ def test_verify_embed_phase_lists_every_missing_target_by_name
10611043

10621044
def test_hook_raises_when_embed_phase_did_not_actually_apply
10631045
load_firebase_spm
1064-
$rnfirebase_spm_active = true
1046+
RNFirebaseSPM.activate!('12.10.0')
10651047
# Stub out the real embed-phase logic so it does nothing, simulating the
10661048
# silent-failure scenario `rnfirebase_verify_spm_embed_phase_applied!` guards
10671049
# against (e.g. a future Xcodeproj/Xcode-project shape it doesn't handle).
@@ -1089,7 +1071,7 @@ def test_hook_raises_when_embed_phase_did_not_actually_apply
10891071

10901072
def test_hook_does_not_raise_when_embed_phase_applied_correctly
10911073
load_firebase_spm
1092-
$rnfirebase_spm_active = true
1074+
RNFirebaseSPM.activate!('12.10.0')
10931075

10941076
klass = new_fake_cocoapods_installer_class
10951077
klass.send(:attr_reader, :aggregate_targets)

0 commit comments

Comments
 (0)