From b3529f479c5195ab7154805cf66d8a37146ea45a Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Mon, 16 Dec 2024 21:54:23 +0200
Subject: [PATCH 01/51] temp: migrate test-app `ios` files to `ios-old`.

---
 detox/test/{ios => ios-old}/.xcode.env               |  0
 detox/test/{ios => ios-old}/Podfile                  |  0
 .../example.xcodeproj/project.pbxproj                |  0
 .../xcshareddata/xcschemes/example.xcscheme          |  0
 .../xcshareddata/xcschemes/example_ci.xcscheme       |  0
 detox/test/{ios => ios-old}/example/AppDelegate.h    |  0
 detox/test/{ios => ios-old}/example/AppDelegate.m    |  0
 .../example/Base.lproj/LaunchScreen.xib              |  0
 .../example/CustomKeyboardViewController.h           |  0
 .../example/CustomKeyboardViewController.m           |  0
 .../Images.xcassets/AppIcon.appiconset/Contents.json |  0
 detox/test/{ios => ios-old}/example/Info.plist       |  0
 detox/test/{ios => ios-old}/example/NativeModule.h   |  0
 detox/test/{ios => ios-old}/example/NativeModule.m   |  0
 .../{ios => ios-old}/example/PrivacyInfo.xcprivacy   |  0
 .../{ios => ios-old}/example/example.entitlements    |  0
 detox/test/{ios => ios-old}/example/main.m           |  0
 .../test/{ios => ios-old}/exampleUITests/Info.plist  |  0
 .../{ios => ios-old}/exampleUITests/exampleUITests.m |  0
 detox/test/{ios => ios-old}/example_ci.entitlements  |  0
 .../ios/example.xcworkspace/contents.xcworkspacedata | 10 ----------
 .../xcshareddata/WorkspaceSettings.xcsettings        | 12 ------------
 22 files changed, 22 deletions(-)
 rename detox/test/{ios => ios-old}/.xcode.env (100%)
 rename detox/test/{ios => ios-old}/Podfile (100%)
 rename detox/test/{ios => ios-old}/example.xcodeproj/project.pbxproj (100%)
 rename detox/test/{ios => ios-old}/example.xcodeproj/xcshareddata/xcschemes/example.xcscheme (100%)
 rename detox/test/{ios => ios-old}/example.xcodeproj/xcshareddata/xcschemes/example_ci.xcscheme (100%)
 rename detox/test/{ios => ios-old}/example/AppDelegate.h (100%)
 rename detox/test/{ios => ios-old}/example/AppDelegate.m (100%)
 rename detox/test/{ios => ios-old}/example/Base.lproj/LaunchScreen.xib (100%)
 rename detox/test/{ios => ios-old}/example/CustomKeyboardViewController.h (100%)
 rename detox/test/{ios => ios-old}/example/CustomKeyboardViewController.m (100%)
 rename detox/test/{ios => ios-old}/example/Images.xcassets/AppIcon.appiconset/Contents.json (100%)
 rename detox/test/{ios => ios-old}/example/Info.plist (100%)
 rename detox/test/{ios => ios-old}/example/NativeModule.h (100%)
 rename detox/test/{ios => ios-old}/example/NativeModule.m (100%)
 rename detox/test/{ios => ios-old}/example/PrivacyInfo.xcprivacy (100%)
 rename detox/test/{ios => ios-old}/example/example.entitlements (100%)
 rename detox/test/{ios => ios-old}/example/main.m (100%)
 rename detox/test/{ios => ios-old}/exampleUITests/Info.plist (100%)
 rename detox/test/{ios => ios-old}/exampleUITests/exampleUITests.m (100%)
 rename detox/test/{ios => ios-old}/example_ci.entitlements (100%)
 delete mode 100644 detox/test/ios/example.xcworkspace/contents.xcworkspacedata
 delete mode 100644 detox/test/ios/example.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings

diff --git a/detox/test/ios/.xcode.env b/detox/test/ios-old/.xcode.env
similarity index 100%
rename from detox/test/ios/.xcode.env
rename to detox/test/ios-old/.xcode.env
diff --git a/detox/test/ios/Podfile b/detox/test/ios-old/Podfile
similarity index 100%
rename from detox/test/ios/Podfile
rename to detox/test/ios-old/Podfile
diff --git a/detox/test/ios/example.xcodeproj/project.pbxproj b/detox/test/ios-old/example.xcodeproj/project.pbxproj
similarity index 100%
rename from detox/test/ios/example.xcodeproj/project.pbxproj
rename to detox/test/ios-old/example.xcodeproj/project.pbxproj
diff --git a/detox/test/ios/example.xcodeproj/xcshareddata/xcschemes/example.xcscheme b/detox/test/ios-old/example.xcodeproj/xcshareddata/xcschemes/example.xcscheme
similarity index 100%
rename from detox/test/ios/example.xcodeproj/xcshareddata/xcschemes/example.xcscheme
rename to detox/test/ios-old/example.xcodeproj/xcshareddata/xcschemes/example.xcscheme
diff --git a/detox/test/ios/example.xcodeproj/xcshareddata/xcschemes/example_ci.xcscheme b/detox/test/ios-old/example.xcodeproj/xcshareddata/xcschemes/example_ci.xcscheme
similarity index 100%
rename from detox/test/ios/example.xcodeproj/xcshareddata/xcschemes/example_ci.xcscheme
rename to detox/test/ios-old/example.xcodeproj/xcshareddata/xcschemes/example_ci.xcscheme
diff --git a/detox/test/ios/example/AppDelegate.h b/detox/test/ios-old/example/AppDelegate.h
similarity index 100%
rename from detox/test/ios/example/AppDelegate.h
rename to detox/test/ios-old/example/AppDelegate.h
diff --git a/detox/test/ios/example/AppDelegate.m b/detox/test/ios-old/example/AppDelegate.m
similarity index 100%
rename from detox/test/ios/example/AppDelegate.m
rename to detox/test/ios-old/example/AppDelegate.m
diff --git a/detox/test/ios/example/Base.lproj/LaunchScreen.xib b/detox/test/ios-old/example/Base.lproj/LaunchScreen.xib
similarity index 100%
rename from detox/test/ios/example/Base.lproj/LaunchScreen.xib
rename to detox/test/ios-old/example/Base.lproj/LaunchScreen.xib
diff --git a/detox/test/ios/example/CustomKeyboardViewController.h b/detox/test/ios-old/example/CustomKeyboardViewController.h
similarity index 100%
rename from detox/test/ios/example/CustomKeyboardViewController.h
rename to detox/test/ios-old/example/CustomKeyboardViewController.h
diff --git a/detox/test/ios/example/CustomKeyboardViewController.m b/detox/test/ios-old/example/CustomKeyboardViewController.m
similarity index 100%
rename from detox/test/ios/example/CustomKeyboardViewController.m
rename to detox/test/ios-old/example/CustomKeyboardViewController.m
diff --git a/detox/test/ios/example/Images.xcassets/AppIcon.appiconset/Contents.json b/detox/test/ios-old/example/Images.xcassets/AppIcon.appiconset/Contents.json
similarity index 100%
rename from detox/test/ios/example/Images.xcassets/AppIcon.appiconset/Contents.json
rename to detox/test/ios-old/example/Images.xcassets/AppIcon.appiconset/Contents.json
diff --git a/detox/test/ios/example/Info.plist b/detox/test/ios-old/example/Info.plist
similarity index 100%
rename from detox/test/ios/example/Info.plist
rename to detox/test/ios-old/example/Info.plist
diff --git a/detox/test/ios/example/NativeModule.h b/detox/test/ios-old/example/NativeModule.h
similarity index 100%
rename from detox/test/ios/example/NativeModule.h
rename to detox/test/ios-old/example/NativeModule.h
diff --git a/detox/test/ios/example/NativeModule.m b/detox/test/ios-old/example/NativeModule.m
similarity index 100%
rename from detox/test/ios/example/NativeModule.m
rename to detox/test/ios-old/example/NativeModule.m
diff --git a/detox/test/ios/example/PrivacyInfo.xcprivacy b/detox/test/ios-old/example/PrivacyInfo.xcprivacy
similarity index 100%
rename from detox/test/ios/example/PrivacyInfo.xcprivacy
rename to detox/test/ios-old/example/PrivacyInfo.xcprivacy
diff --git a/detox/test/ios/example/example.entitlements b/detox/test/ios-old/example/example.entitlements
similarity index 100%
rename from detox/test/ios/example/example.entitlements
rename to detox/test/ios-old/example/example.entitlements
diff --git a/detox/test/ios/example/main.m b/detox/test/ios-old/example/main.m
similarity index 100%
rename from detox/test/ios/example/main.m
rename to detox/test/ios-old/example/main.m
diff --git a/detox/test/ios/exampleUITests/Info.plist b/detox/test/ios-old/exampleUITests/Info.plist
similarity index 100%
rename from detox/test/ios/exampleUITests/Info.plist
rename to detox/test/ios-old/exampleUITests/Info.plist
diff --git a/detox/test/ios/exampleUITests/exampleUITests.m b/detox/test/ios-old/exampleUITests/exampleUITests.m
similarity index 100%
rename from detox/test/ios/exampleUITests/exampleUITests.m
rename to detox/test/ios-old/exampleUITests/exampleUITests.m
diff --git a/detox/test/ios/example_ci.entitlements b/detox/test/ios-old/example_ci.entitlements
similarity index 100%
rename from detox/test/ios/example_ci.entitlements
rename to detox/test/ios-old/example_ci.entitlements
diff --git a/detox/test/ios/example.xcworkspace/contents.xcworkspacedata b/detox/test/ios/example.xcworkspace/contents.xcworkspacedata
deleted file mode 100644
index 7f5c3aab58..0000000000
--- a/detox/test/ios/example.xcworkspace/contents.xcworkspacedata
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<Workspace
-   version = "1.0">
-   <FileRef
-      location = "group:example.xcodeproj">
-   </FileRef>
-   <FileRef
-      location = "group:Pods/Pods.xcodeproj">
-   </FileRef>
-</Workspace>
diff --git a/detox/test/ios/example.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/detox/test/ios/example.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
deleted file mode 100644
index 307a9da219..0000000000
--- a/detox/test/ios/example.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>BuildSystemType</key>
-	<string>Latest</string>
-	<key>DisableBuildSystemDeprecationWarning</key>
-	<true/>
-	<key>PreviewsEnabled</key>
-	<false/>
-</dict>
-</plist>

From 1cc1f6b9c3117ec106baa6a5d60daf952f8a98bb Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Mon, 16 Dec 2024 21:59:15 +0200
Subject: [PATCH 02/51] test(app): create new iOS project from template.

---
 detox/test/ios/.xcode.env                     |  11 +
 detox/test/ios/Podfile                        |  40 +
 .../ios/example.xcodeproj/project.pbxproj     | 690 ++++++++++++++++++
 .../xcshareddata/xcschemes/example.xcscheme   |  88 +++
 detox/test/ios/example/AppDelegate.h          |   6 +
 detox/test/ios/example/AppDelegate.mm         |  31 +
 .../AppIcon.appiconset/Contents.json          |  53 ++
 .../ios/example/Images.xcassets/Contents.json |   6 +
 detox/test/ios/example/Info.plist             |  52 ++
 .../test/ios/example/LaunchScreen.storyboard  |  47 ++
 detox/test/ios/example/PrivacyInfo.xcprivacy  |  37 +
 detox/test/ios/example/main.m                 |  10 +
 detox/test/ios/exampleTests/Info.plist        |  24 +
 detox/test/ios/exampleTests/exampleTests.m    |  66 ++
 14 files changed, 1161 insertions(+)
 create mode 100644 detox/test/ios/.xcode.env
 create mode 100644 detox/test/ios/Podfile
 create mode 100644 detox/test/ios/example.xcodeproj/project.pbxproj
 create mode 100644 detox/test/ios/example.xcodeproj/xcshareddata/xcschemes/example.xcscheme
 create mode 100644 detox/test/ios/example/AppDelegate.h
 create mode 100644 detox/test/ios/example/AppDelegate.mm
 create mode 100644 detox/test/ios/example/Images.xcassets/AppIcon.appiconset/Contents.json
 create mode 100644 detox/test/ios/example/Images.xcassets/Contents.json
 create mode 100644 detox/test/ios/example/Info.plist
 create mode 100644 detox/test/ios/example/LaunchScreen.storyboard
 create mode 100644 detox/test/ios/example/PrivacyInfo.xcprivacy
 create mode 100644 detox/test/ios/example/main.m
 create mode 100644 detox/test/ios/exampleTests/Info.plist
 create mode 100644 detox/test/ios/exampleTests/exampleTests.m

diff --git a/detox/test/ios/.xcode.env b/detox/test/ios/.xcode.env
new file mode 100644
index 0000000000..3d5782c715
--- /dev/null
+++ b/detox/test/ios/.xcode.env
@@ -0,0 +1,11 @@
+# This `.xcode.env` file is versioned and is used to source the environment
+# used when running script phases inside Xcode.
+# To customize your local environment, you can create an `.xcode.env.local`
+# file that is not versioned.
+
+# NODE_BINARY variable contains the PATH to the node executable.
+#
+# Customize the NODE_BINARY variable here.
+# For example, to use nvm with brew, add the following line
+# . "$(brew --prefix nvm)/nvm.sh" --no-use
+export NODE_BINARY=$(command -v node)
diff --git a/detox/test/ios/Podfile b/detox/test/ios/Podfile
new file mode 100644
index 0000000000..e0a72606ec
--- /dev/null
+++ b/detox/test/ios/Podfile
@@ -0,0 +1,40 @@
+# Resolve react_native_pods.rb with node to allow for hoisting
+require Pod::Executable.execute_command('node', ['-p',
+  'require.resolve(
+    "react-native/scripts/react_native_pods.rb",
+    {paths: [process.argv[1]]},
+  )', __dir__]).strip
+
+platform :ios, min_ios_version_supported
+prepare_react_native_project!
+
+linkage = ENV['USE_FRAMEWORKS']
+if linkage != nil
+  Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green
+  use_frameworks! :linkage => linkage.to_sym
+end
+
+target 'example' do
+  config = use_native_modules!
+
+  use_react_native!(
+    :path => config[:reactNativePath],
+    # An absolute path to your application root.
+    :app_path => "#{Pod::Config.instance.installation_root}/.."
+  )
+
+  target 'exampleTests' do
+    inherit! :complete
+    # Pods for testing
+  end
+
+  post_install do |installer|
+    # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202
+    react_native_post_install(
+      installer,
+      config[:reactNativePath],
+      :mac_catalyst_enabled => false,
+      # :ccache_enabled => true
+    )
+  end
+end
diff --git a/detox/test/ios/example.xcodeproj/project.pbxproj b/detox/test/ios/example.xcodeproj/project.pbxproj
new file mode 100644
index 0000000000..b588372d76
--- /dev/null
+++ b/detox/test/ios/example.xcodeproj/project.pbxproj
@@ -0,0 +1,690 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 54;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		00E356F31AD99517003FC87E /* exampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* exampleTests.m */; };
+		0C80B921A6F3F58F76C31292 /* libPods-example.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DCACB8F33CDC322A6C60F78 /* libPods-example.a */; };
+		13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; };
+		13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
+		13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
+		7699B88040F8A987B510C191 /* libPods-example-exampleTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 19F6CBCC0A4E27FBF8BF4A61 /* libPods-example-exampleTests.a */; };
+		81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+		00E356F41AD99517003FC87E /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 13B07F861A680F5B00A75B9A;
+			remoteInfo = example;
+		};
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+		00E356EE1AD99517003FC87E /* exampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = exampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+		00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+		00E356F21AD99517003FC87E /* exampleTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = exampleTests.m; sourceTree = "<group>"; };
+		13B07F961A680F5B00A75B9A /* example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = example.app; sourceTree = BUILT_PRODUCTS_DIR; };
+		13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = example/AppDelegate.h; sourceTree = "<group>"; };
+		13B07FB01A68108700A75B9A /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = example/AppDelegate.mm; sourceTree = "<group>"; };
+		13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = example/Images.xcassets; sourceTree = "<group>"; };
+		13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = example/Info.plist; sourceTree = "<group>"; };
+		13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = example/main.m; sourceTree = "<group>"; };
+		13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = PrivacyInfo.xcprivacy; path = example/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
+		19F6CBCC0A4E27FBF8BF4A61 /* libPods-example-exampleTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-example-exampleTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
+		3B4392A12AC88292D35C810B /* Pods-example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example.debug.xcconfig"; path = "Target Support Files/Pods-example/Pods-example.debug.xcconfig"; sourceTree = "<group>"; };
+		5709B34CF0A7D63546082F79 /* Pods-example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example.release.xcconfig"; path = "Target Support Files/Pods-example/Pods-example.release.xcconfig"; sourceTree = "<group>"; };
+		5B7EB9410499542E8C5724F5 /* Pods-example-exampleTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example-exampleTests.debug.xcconfig"; path = "Target Support Files/Pods-example-exampleTests/Pods-example-exampleTests.debug.xcconfig"; sourceTree = "<group>"; };
+		5DCACB8F33CDC322A6C60F78 /* libPods-example.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-example.a"; sourceTree = BUILT_PRODUCTS_DIR; };
+		81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = example/LaunchScreen.storyboard; sourceTree = "<group>"; };
+		89C6BE57DB24E9ADA2F236DE /* Pods-example-exampleTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example-exampleTests.release.xcconfig"; path = "Target Support Files/Pods-example-exampleTests/Pods-example-exampleTests.release.xcconfig"; sourceTree = "<group>"; };
+		ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		00E356EB1AD99517003FC87E /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				7699B88040F8A987B510C191 /* libPods-example-exampleTests.a in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		13B07F8C1A680F5B00A75B9A /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				0C80B921A6F3F58F76C31292 /* libPods-example.a in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		00E356EF1AD99517003FC87E /* exampleTests */ = {
+			isa = PBXGroup;
+			children = (
+				00E356F21AD99517003FC87E /* exampleTests.m */,
+				00E356F01AD99517003FC87E /* Supporting Files */,
+			);
+			path = exampleTests;
+			sourceTree = "<group>";
+		};
+		00E356F01AD99517003FC87E /* Supporting Files */ = {
+			isa = PBXGroup;
+			children = (
+				00E356F11AD99517003FC87E /* Info.plist */,
+			);
+			name = "Supporting Files";
+			sourceTree = "<group>";
+		};
+		13B07FAE1A68108700A75B9A /* example */ = {
+			isa = PBXGroup;
+			children = (
+				13B07FAF1A68108700A75B9A /* AppDelegate.h */,
+				13B07FB01A68108700A75B9A /* AppDelegate.mm */,
+				13B07FB51A68108700A75B9A /* Images.xcassets */,
+				13B07FB61A68108700A75B9A /* Info.plist */,
+				81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */,
+				13B07FB71A68108700A75B9A /* main.m */,
+				13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */,
+			);
+			name = example;
+			sourceTree = "<group>";
+		};
+		2D16E6871FA4F8E400B85C8A /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
+				5DCACB8F33CDC322A6C60F78 /* libPods-example.a */,
+				19F6CBCC0A4E27FBF8BF4A61 /* libPods-example-exampleTests.a */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
+		832341AE1AAA6A7D00B99B32 /* Libraries */ = {
+			isa = PBXGroup;
+			children = (
+			);
+			name = Libraries;
+			sourceTree = "<group>";
+		};
+		83CBB9F61A601CBA00E9B192 = {
+			isa = PBXGroup;
+			children = (
+				13B07FAE1A68108700A75B9A /* example */,
+				832341AE1AAA6A7D00B99B32 /* Libraries */,
+				00E356EF1AD99517003FC87E /* exampleTests */,
+				83CBBA001A601CBA00E9B192 /* Products */,
+				2D16E6871FA4F8E400B85C8A /* Frameworks */,
+				BBD78D7AC51CEA395F1C20DB /* Pods */,
+			);
+			indentWidth = 2;
+			sourceTree = "<group>";
+			tabWidth = 2;
+			usesTabs = 0;
+		};
+		83CBBA001A601CBA00E9B192 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				13B07F961A680F5B00A75B9A /* example.app */,
+				00E356EE1AD99517003FC87E /* exampleTests.xctest */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		BBD78D7AC51CEA395F1C20DB /* Pods */ = {
+			isa = PBXGroup;
+			children = (
+				3B4392A12AC88292D35C810B /* Pods-example.debug.xcconfig */,
+				5709B34CF0A7D63546082F79 /* Pods-example.release.xcconfig */,
+				5B7EB9410499542E8C5724F5 /* Pods-example-exampleTests.debug.xcconfig */,
+				89C6BE57DB24E9ADA2F236DE /* Pods-example-exampleTests.release.xcconfig */,
+			);
+			path = Pods;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+		00E356ED1AD99517003FC87E /* exampleTests */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "exampleTests" */;
+			buildPhases = (
+				A55EABD7B0C7F3A422A6CC61 /* [CP] Check Pods Manifest.lock */,
+				00E356EA1AD99517003FC87E /* Sources */,
+				00E356EB1AD99517003FC87E /* Frameworks */,
+				00E356EC1AD99517003FC87E /* Resources */,
+				C59DA0FBD6956966B86A3779 /* [CP] Embed Pods Frameworks */,
+				F6A41C54EA430FDDC6A6ED99 /* [CP] Copy Pods Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				00E356F51AD99517003FC87E /* PBXTargetDependency */,
+			);
+			name = exampleTests;
+			productName = exampleTests;
+			productReference = 00E356EE1AD99517003FC87E /* exampleTests.xctest */;
+			productType = "com.apple.product-type.bundle.unit-test";
+		};
+		13B07F861A680F5B00A75B9A /* example */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "example" */;
+			buildPhases = (
+				C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */,
+				13B07F871A680F5B00A75B9A /* Sources */,
+				13B07F8C1A680F5B00A75B9A /* Frameworks */,
+				13B07F8E1A680F5B00A75B9A /* Resources */,
+				00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
+				00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */,
+				E235C05ADACE081382539298 /* [CP] Copy Pods Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = example;
+			productName = example;
+			productReference = 13B07F961A680F5B00A75B9A /* example.app */;
+			productType = "com.apple.product-type.application";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		83CBB9F71A601CBA00E9B192 /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastUpgradeCheck = 1210;
+				TargetAttributes = {
+					00E356ED1AD99517003FC87E = {
+						CreatedOnToolsVersion = 6.2;
+						TestTargetID = 13B07F861A680F5B00A75B9A;
+					};
+					13B07F861A680F5B00A75B9A = {
+						LastSwiftMigration = 1120;
+					};
+				};
+			};
+			buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "example" */;
+			compatibilityVersion = "Xcode 12.0";
+			developmentRegion = en;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+				Base,
+			);
+			mainGroup = 83CBB9F61A601CBA00E9B192;
+			productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				13B07F861A680F5B00A75B9A /* example */,
+				00E356ED1AD99517003FC87E /* exampleTests */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+		00E356EC1AD99517003FC87E /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		13B07F8E1A680F5B00A75B9A /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */,
+				13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+		00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+				"$(SRCROOT)/.xcode.env.local",
+				"$(SRCROOT)/.xcode.env",
+			);
+			name = "Bundle React Native code and images";
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "set -e\n\nWITH_ENVIRONMENT=\"$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"$REACT_NATIVE_PATH/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"\n";
+		};
+		00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputFileListPaths = (
+				"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-frameworks-${CONFIGURATION}-input-files.xcfilelist",
+			);
+			name = "[CP] Embed Pods Frameworks";
+			outputFileListPaths = (
+				"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-frameworks-${CONFIGURATION}-output-files.xcfilelist",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-frameworks.sh\"\n";
+			showEnvVarsInLog = 0;
+		};
+		A55EABD7B0C7F3A422A6CC61 /* [CP] Check Pods Manifest.lock */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputFileListPaths = (
+			);
+			inputPaths = (
+				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+				"${PODS_ROOT}/Manifest.lock",
+			);
+			name = "[CP] Check Pods Manifest.lock";
+			outputFileListPaths = (
+			);
+			outputPaths = (
+				"$(DERIVED_FILE_DIR)/Pods-example-exampleTests-checkManifestLockResult.txt",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+			showEnvVarsInLog = 0;
+		};
+		C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputFileListPaths = (
+			);
+			inputPaths = (
+				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+				"${PODS_ROOT}/Manifest.lock",
+			);
+			name = "[CP] Check Pods Manifest.lock";
+			outputFileListPaths = (
+			);
+			outputPaths = (
+				"$(DERIVED_FILE_DIR)/Pods-example-checkManifestLockResult.txt",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+			showEnvVarsInLog = 0;
+		};
+		C59DA0FBD6956966B86A3779 /* [CP] Embed Pods Frameworks */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputFileListPaths = (
+				"${PODS_ROOT}/Target Support Files/Pods-example-exampleTests/Pods-example-exampleTests-frameworks-${CONFIGURATION}-input-files.xcfilelist",
+			);
+			name = "[CP] Embed Pods Frameworks";
+			outputFileListPaths = (
+				"${PODS_ROOT}/Target Support Files/Pods-example-exampleTests/Pods-example-exampleTests-frameworks-${CONFIGURATION}-output-files.xcfilelist",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-example-exampleTests/Pods-example-exampleTests-frameworks.sh\"\n";
+			showEnvVarsInLog = 0;
+		};
+		E235C05ADACE081382539298 /* [CP] Copy Pods Resources */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputFileListPaths = (
+				"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-resources-${CONFIGURATION}-input-files.xcfilelist",
+			);
+			name = "[CP] Copy Pods Resources";
+			outputFileListPaths = (
+				"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-resources-${CONFIGURATION}-output-files.xcfilelist",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-resources.sh\"\n";
+			showEnvVarsInLog = 0;
+		};
+		F6A41C54EA430FDDC6A6ED99 /* [CP] Copy Pods Resources */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputFileListPaths = (
+				"${PODS_ROOT}/Target Support Files/Pods-example-exampleTests/Pods-example-exampleTests-resources-${CONFIGURATION}-input-files.xcfilelist",
+			);
+			name = "[CP] Copy Pods Resources";
+			outputFileListPaths = (
+				"${PODS_ROOT}/Target Support Files/Pods-example-exampleTests/Pods-example-exampleTests-resources-${CONFIGURATION}-output-files.xcfilelist",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-example-exampleTests/Pods-example-exampleTests-resources.sh\"\n";
+			showEnvVarsInLog = 0;
+		};
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		00E356EA1AD99517003FC87E /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				00E356F31AD99517003FC87E /* exampleTests.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		13B07F871A680F5B00A75B9A /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */,
+				13B07FC11A68108700A75B9A /* main.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+		00E356F51AD99517003FC87E /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 13B07F861A680F5B00A75B9A /* example */;
+			targetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */;
+		};
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+		00E356F61AD99517003FC87E /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 5B7EB9410499542E8C5724F5 /* Pods-example-exampleTests.debug.xcconfig */;
+			buildSettings = {
+				BUNDLE_LOADER = "$(TEST_HOST)";
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				INFOPLIST_FILE = exampleTests/Info.plist;
+				IPHONEOS_DEPLOYMENT_TARGET = 15.1;
+				LD_RUNPATH_SEARCH_PATHS = (
+					"$(inherited)",
+					"@executable_path/Frameworks",
+					"@loader_path/Frameworks",
+				);
+				OTHER_LDFLAGS = (
+					"-ObjC",
+					"-lc++",
+					"$(inherited)",
+				);
+				PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/example.app/example";
+			};
+			name = Debug;
+		};
+		00E356F71AD99517003FC87E /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 89C6BE57DB24E9ADA2F236DE /* Pods-example-exampleTests.release.xcconfig */;
+			buildSettings = {
+				BUNDLE_LOADER = "$(TEST_HOST)";
+				COPY_PHASE_STRIP = NO;
+				INFOPLIST_FILE = exampleTests/Info.plist;
+				IPHONEOS_DEPLOYMENT_TARGET = 15.1;
+				LD_RUNPATH_SEARCH_PATHS = (
+					"$(inherited)",
+					"@executable_path/Frameworks",
+					"@loader_path/Frameworks",
+				);
+				OTHER_LDFLAGS = (
+					"-ObjC",
+					"-lc++",
+					"$(inherited)",
+				);
+				PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/example.app/example";
+			};
+			name = Release;
+		};
+		13B07F941A680F5B00A75B9A /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 3B4392A12AC88292D35C810B /* Pods-example.debug.xcconfig */;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				CLANG_ENABLE_MODULES = YES;
+				CURRENT_PROJECT_VERSION = 1;
+				ENABLE_BITCODE = NO;
+				INFOPLIST_FILE = example/Info.plist;
+				IPHONEOS_DEPLOYMENT_TARGET = 15.1;
+				LD_RUNPATH_SEARCH_PATHS = (
+					"$(inherited)",
+					"@executable_path/Frameworks",
+				);
+				MARKETING_VERSION = 1.0;
+				OTHER_LDFLAGS = (
+					"$(inherited)",
+					"-ObjC",
+					"-lc++",
+				);
+				PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
+				PRODUCT_NAME = example;
+				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+				SWIFT_VERSION = 5.0;
+				VERSIONING_SYSTEM = "apple-generic";
+			};
+			name = Debug;
+		};
+		13B07F951A680F5B00A75B9A /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 5709B34CF0A7D63546082F79 /* Pods-example.release.xcconfig */;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				CLANG_ENABLE_MODULES = YES;
+				CURRENT_PROJECT_VERSION = 1;
+				INFOPLIST_FILE = example/Info.plist;
+				IPHONEOS_DEPLOYMENT_TARGET = 15.1;
+				LD_RUNPATH_SEARCH_PATHS = (
+					"$(inherited)",
+					"@executable_path/Frameworks",
+				);
+				MARKETING_VERSION = 1.0;
+				OTHER_LDFLAGS = (
+					"$(inherited)",
+					"-ObjC",
+					"-lc++",
+				);
+				PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
+				PRODUCT_NAME = example;
+				SWIFT_VERSION = 5.0;
+				VERSIONING_SYSTEM = "apple-generic";
+			};
+			name = Release;
+		};
+		83CBBA201A601CBA00E9B192 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
+				CLANG_CXX_LANGUAGE_STANDARD = "c++20";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+				COPY_PHASE_STRIP = NO;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				ENABLE_TESTABILITY = YES;
+				"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 15.1;
+				LD_RUNPATH_SEARCH_PATHS = (
+					/usr/lib/swift,
+					"$(inherited)",
+				);
+				LIBRARY_SEARCH_PATHS = (
+					"\"$(SDKROOT)/usr/lib/swift\"",
+					"\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"",
+					"\"$(inherited)\"",
+				);
+				MTL_ENABLE_DEBUG_INFO = YES;
+				ONLY_ACTIVE_ARCH = YES;
+				OTHER_CPLUSPLUSFLAGS = (
+					"$(OTHER_CFLAGS)",
+					"-DFOLLY_NO_CONFIG",
+					"-DFOLLY_MOBILE=1",
+					"-DFOLLY_USE_LIBCPP=1",
+					"-DFOLLY_CFG_NO_COROUTINES=1",
+					"-DFOLLY_HAVE_CLOCK_GETTIME=1",
+				);
+				SDKROOT = iphoneos;
+			};
+			name = Debug;
+		};
+		83CBBA211A601CBA00E9B192 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
+				CLANG_CXX_LANGUAGE_STANDARD = "c++20";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+				COPY_PHASE_STRIP = YES;
+				ENABLE_NS_ASSERTIONS = NO;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 15.1;
+				LD_RUNPATH_SEARCH_PATHS = (
+					/usr/lib/swift,
+					"$(inherited)",
+				);
+				LIBRARY_SEARCH_PATHS = (
+					"\"$(SDKROOT)/usr/lib/swift\"",
+					"\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"",
+					"\"$(inherited)\"",
+				);
+				MTL_ENABLE_DEBUG_INFO = NO;
+				OTHER_CPLUSPLUSFLAGS = (
+					"$(OTHER_CFLAGS)",
+					"-DFOLLY_NO_CONFIG",
+					"-DFOLLY_MOBILE=1",
+					"-DFOLLY_USE_LIBCPP=1",
+					"-DFOLLY_CFG_NO_COROUTINES=1",
+					"-DFOLLY_HAVE_CLOCK_GETTIME=1",
+				);
+				SDKROOT = iphoneos;
+				VALIDATE_PRODUCT = YES;
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "exampleTests" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				00E356F61AD99517003FC87E /* Debug */,
+				00E356F71AD99517003FC87E /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "example" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				13B07F941A680F5B00A75B9A /* Debug */,
+				13B07F951A680F5B00A75B9A /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "example" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				83CBBA201A601CBA00E9B192 /* Debug */,
+				83CBBA211A601CBA00E9B192 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */;
+}
diff --git a/detox/test/ios/example.xcodeproj/xcshareddata/xcschemes/example.xcscheme b/detox/test/ios/example.xcodeproj/xcshareddata/xcschemes/example.xcscheme
new file mode 100644
index 0000000000..fef9df78ab
--- /dev/null
+++ b/detox/test/ios/example.xcodeproj/xcshareddata/xcschemes/example.xcscheme
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1210"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
+               BuildableName = "example.app"
+               BlueprintName = "example"
+               ReferencedContainer = "container:example.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+      <Testables>
+         <TestableReference
+            skipped = "NO">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "00E356ED1AD99517003FC87E"
+               BuildableName = "exampleTests.xctest"
+               BlueprintName = "exampleTests"
+               ReferencedContainer = "container:example.xcodeproj">
+            </BuildableReference>
+         </TestableReference>
+      </Testables>
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
+            BuildableName = "example.app"
+            BlueprintName = "example"
+            ReferencedContainer = "container:example.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
+            BuildableName = "example.app"
+            BlueprintName = "example"
+            ReferencedContainer = "container:example.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/detox/test/ios/example/AppDelegate.h b/detox/test/ios/example/AppDelegate.h
new file mode 100644
index 0000000000..5d2808256c
--- /dev/null
+++ b/detox/test/ios/example/AppDelegate.h
@@ -0,0 +1,6 @@
+#import <RCTAppDelegate.h>
+#import <UIKit/UIKit.h>
+
+@interface AppDelegate : RCTAppDelegate
+
+@end
diff --git a/detox/test/ios/example/AppDelegate.mm b/detox/test/ios/example/AppDelegate.mm
new file mode 100644
index 0000000000..ba286dc79e
--- /dev/null
+++ b/detox/test/ios/example/AppDelegate.mm
@@ -0,0 +1,31 @@
+#import "AppDelegate.h"
+
+#import <React/RCTBundleURLProvider.h>
+
+@implementation AppDelegate
+
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
+{
+  self.moduleName = @"example";
+  // You can add your custom initial props in the dictionary below.
+  // They will be passed down to the ViewController used by React Native.
+  self.initialProps = @{};
+
+  return [super application:application didFinishLaunchingWithOptions:launchOptions];
+}
+
+- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
+{
+  return [self bundleURL];
+}
+
+- (NSURL *)bundleURL
+{
+#if DEBUG
+  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
+#else
+  return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
+#endif
+}
+
+@end
diff --git a/detox/test/ios/example/Images.xcassets/AppIcon.appiconset/Contents.json b/detox/test/ios/example/Images.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000000..81213230de
--- /dev/null
+++ b/detox/test/ios/example/Images.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,53 @@
+{
+  "images" : [
+    {
+      "idiom" : "iphone",
+      "scale" : "2x",
+      "size" : "20x20"
+    },
+    {
+      "idiom" : "iphone",
+      "scale" : "3x",
+      "size" : "20x20"
+    },
+    {
+      "idiom" : "iphone",
+      "scale" : "2x",
+      "size" : "29x29"
+    },
+    {
+      "idiom" : "iphone",
+      "scale" : "3x",
+      "size" : "29x29"
+    },
+    {
+      "idiom" : "iphone",
+      "scale" : "2x",
+      "size" : "40x40"
+    },
+    {
+      "idiom" : "iphone",
+      "scale" : "3x",
+      "size" : "40x40"
+    },
+    {
+      "idiom" : "iphone",
+      "scale" : "2x",
+      "size" : "60x60"
+    },
+    {
+      "idiom" : "iphone",
+      "scale" : "3x",
+      "size" : "60x60"
+    },
+    {
+      "idiom" : "ios-marketing",
+      "scale" : "1x",
+      "size" : "1024x1024"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/detox/test/ios/example/Images.xcassets/Contents.json b/detox/test/ios/example/Images.xcassets/Contents.json
new file mode 100644
index 0000000000..2d92bd53fd
--- /dev/null
+++ b/detox/test/ios/example/Images.xcassets/Contents.json
@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
diff --git a/detox/test/ios/example/Info.plist b/detox/test/ios/example/Info.plist
new file mode 100644
index 0000000000..3241dd140b
--- /dev/null
+++ b/detox/test/ios/example/Info.plist
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en</string>
+	<key>CFBundleDisplayName</key>
+	<string>example</string>
+	<key>CFBundleExecutable</key>
+	<string>$(EXECUTABLE_NAME)</string>
+	<key>CFBundleIdentifier</key>
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>$(PRODUCT_NAME)</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>$(MARKETING_VERSION)</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>$(CURRENT_PROJECT_VERSION)</string>
+	<key>LSRequiresIPhoneOS</key>
+	<true/>
+	<key>NSAppTransportSecurity</key>
+	<dict>
+	  <!-- Do not change NSAllowsArbitraryLoads to true, or you will risk app rejection! -->
+		<key>NSAllowsArbitraryLoads</key>
+		<false/>
+		<key>NSAllowsLocalNetworking</key>
+		<true/>
+	</dict>
+	<key>NSLocationWhenInUseUsageDescription</key>
+	<string></string>
+	<key>UILaunchStoryboardName</key>
+	<string>LaunchScreen</string>
+	<key>UIRequiredDeviceCapabilities</key>
+	<array>
+		<string>arm64</string>
+	</array>
+	<key>UISupportedInterfaceOrientations</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+		<string>UIInterfaceOrientationLandscapeLeft</string>
+		<string>UIInterfaceOrientationLandscapeRight</string>
+	</array>
+	<key>UIViewControllerBasedStatusBarAppearance</key>
+	<false/>
+</dict>
+</plist>
diff --git a/detox/test/ios/example/LaunchScreen.storyboard b/detox/test/ios/example/LaunchScreen.storyboard
new file mode 100644
index 0000000000..a2139fff8b
--- /dev/null
+++ b/detox/test/ios/example/LaunchScreen.storyboard
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15702" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
+    <device id="retina4_7" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15704"/>
+        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <scenes>
+        <!--View Controller-->
+        <scene sceneID="EHf-IW-A2E">
+            <objects>
+                <viewController id="01J-lp-oVM" sceneMemberID="viewController">
+                    <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
+                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <subviews>
+                            <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="example" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="GJd-Yh-RWb">
+                                <rect key="frame" x="0.0" y="202" width="375" height="43"/>
+                                <fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                            <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Powered by React Native" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="MN2-I3-ftu">
+                                <rect key="frame" x="0.0" y="626" width="375" height="21"/>
+                                <fontDescription key="fontDescription" type="system" pointSize="17"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                        </subviews>
+                        <color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
+                        <constraints>
+                            <constraint firstItem="Bcu-3y-fUS" firstAttribute="bottom" secondItem="MN2-I3-ftu" secondAttribute="bottom" constant="20" id="OZV-Vh-mqD"/>
+                            <constraint firstItem="Bcu-3y-fUS" firstAttribute="centerX" secondItem="GJd-Yh-RWb" secondAttribute="centerX" id="Q3B-4B-g5h"/>
+                            <constraint firstItem="MN2-I3-ftu" firstAttribute="centerX" secondItem="Bcu-3y-fUS" secondAttribute="centerX" id="akx-eg-2ui"/>
+                            <constraint firstItem="MN2-I3-ftu" firstAttribute="leading" secondItem="Bcu-3y-fUS" secondAttribute="leading" id="i1E-0Y-4RG"/>
+                            <constraint firstItem="GJd-Yh-RWb" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="bottom" multiplier="1/3" constant="1" id="moa-c2-u7t"/>
+                            <constraint firstItem="GJd-Yh-RWb" firstAttribute="leading" secondItem="Bcu-3y-fUS" secondAttribute="leading" symbolic="YES" id="x7j-FC-K8j"/>
+                        </constraints>
+                        <viewLayoutGuide key="safeArea" id="Bcu-3y-fUS"/>
+                    </view>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="52.173913043478265" y="375"/>
+        </scene>
+    </scenes>
+</document>
diff --git a/detox/test/ios/example/PrivacyInfo.xcprivacy b/detox/test/ios/example/PrivacyInfo.xcprivacy
new file mode 100644
index 0000000000..41b8317f06
--- /dev/null
+++ b/detox/test/ios/example/PrivacyInfo.xcprivacy
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>NSPrivacyAccessedAPITypes</key>
+	<array>
+		<dict>
+			<key>NSPrivacyAccessedAPIType</key>
+			<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
+			<key>NSPrivacyAccessedAPITypeReasons</key>
+			<array>
+				<string>C617.1</string>
+			</array>
+		</dict>
+		<dict>
+			<key>NSPrivacyAccessedAPIType</key>
+			<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
+			<key>NSPrivacyAccessedAPITypeReasons</key>
+			<array>
+				<string>CA92.1</string>
+			</array>
+		</dict>
+		<dict>
+			<key>NSPrivacyAccessedAPIType</key>
+			<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
+			<key>NSPrivacyAccessedAPITypeReasons</key>
+			<array>
+				<string>35F9.1</string>
+			</array>
+		</dict>
+	</array>
+	<key>NSPrivacyCollectedDataTypes</key>
+	<array/>
+	<key>NSPrivacyTracking</key>
+	<false/>
+</dict>
+</plist>
diff --git a/detox/test/ios/example/main.m b/detox/test/ios/example/main.m
new file mode 100644
index 0000000000..d645c7246c
--- /dev/null
+++ b/detox/test/ios/example/main.m
@@ -0,0 +1,10 @@
+#import <UIKit/UIKit.h>
+
+#import "AppDelegate.h"
+
+int main(int argc, char *argv[])
+{
+  @autoreleasepool {
+    return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
+  }
+}
diff --git a/detox/test/ios/exampleTests/Info.plist b/detox/test/ios/exampleTests/Info.plist
new file mode 100644
index 0000000000..ba72822e87
--- /dev/null
+++ b/detox/test/ios/exampleTests/Info.plist
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en</string>
+	<key>CFBundleExecutable</key>
+	<string>$(EXECUTABLE_NAME)</string>
+	<key>CFBundleIdentifier</key>
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>$(PRODUCT_NAME)</string>
+	<key>CFBundlePackageType</key>
+	<string>BNDL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+</dict>
+</plist>
diff --git a/detox/test/ios/exampleTests/exampleTests.m b/detox/test/ios/exampleTests/exampleTests.m
new file mode 100644
index 0000000000..6f944301f0
--- /dev/null
+++ b/detox/test/ios/exampleTests/exampleTests.m
@@ -0,0 +1,66 @@
+#import <UIKit/UIKit.h>
+#import <XCTest/XCTest.h>
+
+#import <React/RCTLog.h>
+#import <React/RCTRootView.h>
+
+#define TIMEOUT_SECONDS 600
+#define TEXT_TO_LOOK_FOR @"Welcome to React"
+
+@interface exampleTests : XCTestCase
+
+@end
+
+@implementation exampleTests
+
+- (BOOL)findSubviewInView:(UIView *)view matching:(BOOL (^)(UIView *view))test
+{
+  if (test(view)) {
+    return YES;
+  }
+  for (UIView *subview in [view subviews]) {
+    if ([self findSubviewInView:subview matching:test]) {
+      return YES;
+    }
+  }
+  return NO;
+}
+
+- (void)testRendersWelcomeScreen
+{
+  UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController];
+  NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS];
+  BOOL foundElement = NO;
+
+  __block NSString *redboxError = nil;
+#ifdef DEBUG
+  RCTSetLogFunction(
+      ^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) {
+        if (level >= RCTLogLevelError) {
+          redboxError = message;
+        }
+      });
+#endif
+
+  while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) {
+    [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
+    [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
+
+    foundElement = [self findSubviewInView:vc.view
+                                  matching:^BOOL(UIView *view) {
+                                    if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) {
+                                      return YES;
+                                    }
+                                    return NO;
+                                  }];
+  }
+
+#ifdef DEBUG
+  RCTSetLogFunction(RCTDefaultLogFunction);
+#endif
+
+  XCTAssertNil(redboxError, @"RedBox error: %@", redboxError);
+  XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS);
+}
+
+@end

From 09eebd85e54e05645e2f0fd9eb544ffd4e8562c4 Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Mon, 16 Dec 2024 22:04:59 +0200
Subject: [PATCH 03/51] test(ios): remove example native tests.

---
 .../ios/example.xcodeproj/project.pbxproj     | 216 +-----------------
 detox/test/ios/exampleTests/Info.plist        |  24 --
 detox/test/ios/exampleTests/exampleTests.m    |  66 ------
 3 files changed, 9 insertions(+), 297 deletions(-)
 delete mode 100644 detox/test/ios/exampleTests/Info.plist
 delete mode 100644 detox/test/ios/exampleTests/exampleTests.m

diff --git a/detox/test/ios/example.xcodeproj/project.pbxproj b/detox/test/ios/example.xcodeproj/project.pbxproj
index b588372d76..be0da5db37 100644
--- a/detox/test/ios/example.xcodeproj/project.pbxproj
+++ b/detox/test/ios/example.xcodeproj/project.pbxproj
@@ -7,29 +7,15 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
-		00E356F31AD99517003FC87E /* exampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* exampleTests.m */; };
 		0C80B921A6F3F58F76C31292 /* libPods-example.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DCACB8F33CDC322A6C60F78 /* libPods-example.a */; };
 		13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; };
 		13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
 		13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
-		7699B88040F8A987B510C191 /* libPods-example-exampleTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 19F6CBCC0A4E27FBF8BF4A61 /* libPods-example-exampleTests.a */; };
 		81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
+		90CCD0BA1322566EB1285DC2 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */; };
 /* End PBXBuildFile section */
 
-/* Begin PBXContainerItemProxy section */
-		00E356F41AD99517003FC87E /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
-			proxyType = 1;
-			remoteGlobalIDString = 13B07F861A680F5B00A75B9A;
-			remoteInfo = example;
-		};
-/* End PBXContainerItemProxy section */
-
 /* Begin PBXFileReference section */
-		00E356EE1AD99517003FC87E /* exampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = exampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
-		00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
-		00E356F21AD99517003FC87E /* exampleTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = exampleTests.m; sourceTree = "<group>"; };
 		13B07F961A680F5B00A75B9A /* example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = example.app; sourceTree = BUILT_PRODUCTS_DIR; };
 		13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = example/AppDelegate.h; sourceTree = "<group>"; };
 		13B07FB01A68108700A75B9A /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = example/AppDelegate.mm; sourceTree = "<group>"; };
@@ -48,14 +34,6 @@
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
-		00E356EB1AD99517003FC87E /* Frameworks */ = {
-			isa = PBXFrameworksBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				7699B88040F8A987B510C191 /* libPods-example-exampleTests.a in Frameworks */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
 		13B07F8C1A680F5B00A75B9A /* Frameworks */ = {
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
@@ -67,23 +45,6 @@
 /* End PBXFrameworksBuildPhase section */
 
 /* Begin PBXGroup section */
-		00E356EF1AD99517003FC87E /* exampleTests */ = {
-			isa = PBXGroup;
-			children = (
-				00E356F21AD99517003FC87E /* exampleTests.m */,
-				00E356F01AD99517003FC87E /* Supporting Files */,
-			);
-			path = exampleTests;
-			sourceTree = "<group>";
-		};
-		00E356F01AD99517003FC87E /* Supporting Files */ = {
-			isa = PBXGroup;
-			children = (
-				00E356F11AD99517003FC87E /* Info.plist */,
-			);
-			name = "Supporting Files";
-			sourceTree = "<group>";
-		};
 		13B07FAE1A68108700A75B9A /* example */ = {
 			isa = PBXGroup;
 			children = (
@@ -120,7 +81,6 @@
 			children = (
 				13B07FAE1A68108700A75B9A /* example */,
 				832341AE1AAA6A7D00B99B32 /* Libraries */,
-				00E356EF1AD99517003FC87E /* exampleTests */,
 				83CBBA001A601CBA00E9B192 /* Products */,
 				2D16E6871FA4F8E400B85C8A /* Frameworks */,
 				BBD78D7AC51CEA395F1C20DB /* Pods */,
@@ -134,7 +94,6 @@
 			isa = PBXGroup;
 			children = (
 				13B07F961A680F5B00A75B9A /* example.app */,
-				00E356EE1AD99517003FC87E /* exampleTests.xctest */,
 			);
 			name = Products;
 			sourceTree = "<group>";
@@ -153,27 +112,6 @@
 /* End PBXGroup section */
 
 /* Begin PBXNativeTarget section */
-		00E356ED1AD99517003FC87E /* exampleTests */ = {
-			isa = PBXNativeTarget;
-			buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "exampleTests" */;
-			buildPhases = (
-				A55EABD7B0C7F3A422A6CC61 /* [CP] Check Pods Manifest.lock */,
-				00E356EA1AD99517003FC87E /* Sources */,
-				00E356EB1AD99517003FC87E /* Frameworks */,
-				00E356EC1AD99517003FC87E /* Resources */,
-				C59DA0FBD6956966B86A3779 /* [CP] Embed Pods Frameworks */,
-				F6A41C54EA430FDDC6A6ED99 /* [CP] Copy Pods Resources */,
-			);
-			buildRules = (
-			);
-			dependencies = (
-				00E356F51AD99517003FC87E /* PBXTargetDependency */,
-			);
-			name = exampleTests;
-			productName = exampleTests;
-			productReference = 00E356EE1AD99517003FC87E /* exampleTests.xctest */;
-			productType = "com.apple.product-type.bundle.unit-test";
-		};
 		13B07F861A680F5B00A75B9A /* example */ = {
 			isa = PBXNativeTarget;
 			buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "example" */;
@@ -203,10 +141,6 @@
 			attributes = {
 				LastUpgradeCheck = 1210;
 				TargetAttributes = {
-					00E356ED1AD99517003FC87E = {
-						CreatedOnToolsVersion = 6.2;
-						TestTargetID = 13B07F861A680F5B00A75B9A;
-					};
 					13B07F861A680F5B00A75B9A = {
 						LastSwiftMigration = 1120;
 					};
@@ -226,25 +160,18 @@
 			projectRoot = "";
 			targets = (
 				13B07F861A680F5B00A75B9A /* example */,
-				00E356ED1AD99517003FC87E /* exampleTests */,
 			);
 		};
 /* End PBXProject section */
 
 /* Begin PBXResourcesBuildPhase section */
-		00E356EC1AD99517003FC87E /* Resources */ = {
-			isa = PBXResourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
 		13B07F8E1A680F5B00A75B9A /* Resources */ = {
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
 				81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */,
 				13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
+				90CCD0BA1322566EB1285DC2 /* PrivacyInfo.xcprivacy in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -284,28 +211,6 @@
 			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-frameworks.sh\"\n";
 			showEnvVarsInLog = 0;
 		};
-		A55EABD7B0C7F3A422A6CC61 /* [CP] Check Pods Manifest.lock */ = {
-			isa = PBXShellScriptBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			inputFileListPaths = (
-			);
-			inputPaths = (
-				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
-				"${PODS_ROOT}/Manifest.lock",
-			);
-			name = "[CP] Check Pods Manifest.lock";
-			outputFileListPaths = (
-			);
-			outputPaths = (
-				"$(DERIVED_FILE_DIR)/Pods-example-exampleTests-checkManifestLockResult.txt",
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-			shellPath = /bin/sh;
-			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
-			showEnvVarsInLog = 0;
-		};
 		C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
@@ -328,23 +233,6 @@
 			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
 			showEnvVarsInLog = 0;
 		};
-		C59DA0FBD6956966B86A3779 /* [CP] Embed Pods Frameworks */ = {
-			isa = PBXShellScriptBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			inputFileListPaths = (
-				"${PODS_ROOT}/Target Support Files/Pods-example-exampleTests/Pods-example-exampleTests-frameworks-${CONFIGURATION}-input-files.xcfilelist",
-			);
-			name = "[CP] Embed Pods Frameworks";
-			outputFileListPaths = (
-				"${PODS_ROOT}/Target Support Files/Pods-example-exampleTests/Pods-example-exampleTests-frameworks-${CONFIGURATION}-output-files.xcfilelist",
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-			shellPath = /bin/sh;
-			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-example-exampleTests/Pods-example-exampleTests-frameworks.sh\"\n";
-			showEnvVarsInLog = 0;
-		};
 		E235C05ADACE081382539298 /* [CP] Copy Pods Resources */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
@@ -362,34 +250,9 @@
 			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-resources.sh\"\n";
 			showEnvVarsInLog = 0;
 		};
-		F6A41C54EA430FDDC6A6ED99 /* [CP] Copy Pods Resources */ = {
-			isa = PBXShellScriptBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			inputFileListPaths = (
-				"${PODS_ROOT}/Target Support Files/Pods-example-exampleTests/Pods-example-exampleTests-resources-${CONFIGURATION}-input-files.xcfilelist",
-			);
-			name = "[CP] Copy Pods Resources";
-			outputFileListPaths = (
-				"${PODS_ROOT}/Target Support Files/Pods-example-exampleTests/Pods-example-exampleTests-resources-${CONFIGURATION}-output-files.xcfilelist",
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-			shellPath = /bin/sh;
-			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-example-exampleTests/Pods-example-exampleTests-resources.sh\"\n";
-			showEnvVarsInLog = 0;
-		};
 /* End PBXShellScriptBuildPhase section */
 
 /* Begin PBXSourcesBuildPhase section */
-		00E356EA1AD99517003FC87E /* Sources */ = {
-			isa = PBXSourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				00E356F31AD99517003FC87E /* exampleTests.m in Sources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
 		13B07F871A680F5B00A75B9A /* Sources */ = {
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
@@ -401,66 +264,7 @@
 		};
 /* End PBXSourcesBuildPhase section */
 
-/* Begin PBXTargetDependency section */
-		00E356F51AD99517003FC87E /* PBXTargetDependency */ = {
-			isa = PBXTargetDependency;
-			target = 13B07F861A680F5B00A75B9A /* example */;
-			targetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */;
-		};
-/* End PBXTargetDependency section */
-
 /* Begin XCBuildConfiguration section */
-		00E356F61AD99517003FC87E /* Debug */ = {
-			isa = XCBuildConfiguration;
-			baseConfigurationReference = 5B7EB9410499542E8C5724F5 /* Pods-example-exampleTests.debug.xcconfig */;
-			buildSettings = {
-				BUNDLE_LOADER = "$(TEST_HOST)";
-				GCC_PREPROCESSOR_DEFINITIONS = (
-					"DEBUG=1",
-					"$(inherited)",
-				);
-				INFOPLIST_FILE = exampleTests/Info.plist;
-				IPHONEOS_DEPLOYMENT_TARGET = 15.1;
-				LD_RUNPATH_SEARCH_PATHS = (
-					"$(inherited)",
-					"@executable_path/Frameworks",
-					"@loader_path/Frameworks",
-				);
-				OTHER_LDFLAGS = (
-					"-ObjC",
-					"-lc++",
-					"$(inherited)",
-				);
-				PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
-				PRODUCT_NAME = "$(TARGET_NAME)";
-				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/example.app/example";
-			};
-			name = Debug;
-		};
-		00E356F71AD99517003FC87E /* Release */ = {
-			isa = XCBuildConfiguration;
-			baseConfigurationReference = 89C6BE57DB24E9ADA2F236DE /* Pods-example-exampleTests.release.xcconfig */;
-			buildSettings = {
-				BUNDLE_LOADER = "$(TEST_HOST)";
-				COPY_PHASE_STRIP = NO;
-				INFOPLIST_FILE = exampleTests/Info.plist;
-				IPHONEOS_DEPLOYMENT_TARGET = 15.1;
-				LD_RUNPATH_SEARCH_PATHS = (
-					"$(inherited)",
-					"@executable_path/Frameworks",
-					"@loader_path/Frameworks",
-				);
-				OTHER_LDFLAGS = (
-					"-ObjC",
-					"-lc++",
-					"$(inherited)",
-				);
-				PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
-				PRODUCT_NAME = "$(TARGET_NAME)";
-				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/example.app/example";
-			};
-			name = Release;
-		};
 		13B07F941A680F5B00A75B9A /* Debug */ = {
 			isa = XCBuildConfiguration;
 			baseConfigurationReference = 3B4392A12AC88292D35C810B /* Pods-example.debug.xcconfig */;
@@ -584,7 +388,11 @@
 					"-DFOLLY_CFG_NO_COROUTINES=1",
 					"-DFOLLY_HAVE_CLOCK_GETTIME=1",
 				);
+				OTHER_LDFLAGS = "$(inherited)  ";
+				REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
 				SDKROOT = iphoneos;
+				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG";
+				USE_HERMES = true;
 			};
 			name = Debug;
 		};
@@ -649,7 +457,10 @@
 					"-DFOLLY_CFG_NO_COROUTINES=1",
 					"-DFOLLY_HAVE_CLOCK_GETTIME=1",
 				);
+				OTHER_LDFLAGS = "$(inherited)  ";
+				REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
 				SDKROOT = iphoneos;
+				USE_HERMES = true;
 				VALIDATE_PRODUCT = YES;
 			};
 			name = Release;
@@ -657,15 +468,6 @@
 /* End XCBuildConfiguration section */
 
 /* Begin XCConfigurationList section */
-		00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "exampleTests" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				00E356F61AD99517003FC87E /* Debug */,
-				00E356F71AD99517003FC87E /* Release */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Release;
-		};
 		13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "example" */ = {
 			isa = XCConfigurationList;
 			buildConfigurations = (
diff --git a/detox/test/ios/exampleTests/Info.plist b/detox/test/ios/exampleTests/Info.plist
deleted file mode 100644
index ba72822e87..0000000000
--- a/detox/test/ios/exampleTests/Info.plist
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>CFBundleDevelopmentRegion</key>
-	<string>en</string>
-	<key>CFBundleExecutable</key>
-	<string>$(EXECUTABLE_NAME)</string>
-	<key>CFBundleIdentifier</key>
-	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
-	<key>CFBundleInfoDictionaryVersion</key>
-	<string>6.0</string>
-	<key>CFBundleName</key>
-	<string>$(PRODUCT_NAME)</string>
-	<key>CFBundlePackageType</key>
-	<string>BNDL</string>
-	<key>CFBundleShortVersionString</key>
-	<string>1.0</string>
-	<key>CFBundleSignature</key>
-	<string>????</string>
-	<key>CFBundleVersion</key>
-	<string>1</string>
-</dict>
-</plist>
diff --git a/detox/test/ios/exampleTests/exampleTests.m b/detox/test/ios/exampleTests/exampleTests.m
deleted file mode 100644
index 6f944301f0..0000000000
--- a/detox/test/ios/exampleTests/exampleTests.m
+++ /dev/null
@@ -1,66 +0,0 @@
-#import <UIKit/UIKit.h>
-#import <XCTest/XCTest.h>
-
-#import <React/RCTLog.h>
-#import <React/RCTRootView.h>
-
-#define TIMEOUT_SECONDS 600
-#define TEXT_TO_LOOK_FOR @"Welcome to React"
-
-@interface exampleTests : XCTestCase
-
-@end
-
-@implementation exampleTests
-
-- (BOOL)findSubviewInView:(UIView *)view matching:(BOOL (^)(UIView *view))test
-{
-  if (test(view)) {
-    return YES;
-  }
-  for (UIView *subview in [view subviews]) {
-    if ([self findSubviewInView:subview matching:test]) {
-      return YES;
-    }
-  }
-  return NO;
-}
-
-- (void)testRendersWelcomeScreen
-{
-  UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController];
-  NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS];
-  BOOL foundElement = NO;
-
-  __block NSString *redboxError = nil;
-#ifdef DEBUG
-  RCTSetLogFunction(
-      ^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) {
-        if (level >= RCTLogLevelError) {
-          redboxError = message;
-        }
-      });
-#endif
-
-  while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) {
-    [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
-    [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
-
-    foundElement = [self findSubviewInView:vc.view
-                                  matching:^BOOL(UIView *view) {
-                                    if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) {
-                                      return YES;
-                                    }
-                                    return NO;
-                                  }];
-  }
-
-#ifdef DEBUG
-  RCTSetLogFunction(RCTDefaultLogFunction);
-#endif
-
-  XCTAssertNil(redboxError, @"RedBox error: %@", redboxError);
-  XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS);
-}
-
-@end

From 687ff849dce028a4f0f49f90d38f9481d3b35657 Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Mon, 16 Dec 2024 22:08:31 +0200
Subject: [PATCH 04/51] chore(ios): update git to ignore generated files.

---
 .gitignore | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/.gitignore b/.gitignore
index 3b3be7903f..04bcacd415 100644
--- a/.gitignore
+++ b/.gitignore
@@ -81,8 +81,8 @@ fabric.properties
 # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
 
 ## Build generated
-ios/build/
-ios/DerivedData/
+*/*/ios/build/
+*/*/ios/DerivedData/
 
 ## Various settings
 *.pbxuser
@@ -93,12 +93,12 @@ ios/DerivedData/
 !default.mode2v3
 *.perspectivev3
 !default.perspectivev3
-ios/xcuserdata/
+*/*/ios/xcuserdata/
 
 ## Other
 *.moved-aside
 *.xcuserstate
-ios/.xcode.env.local
+*/*/ios/.xcode.env.local
 
 ## Obj-C/Swift specific
 *.hmap

From b6df6c9fc4e639616097fd913f432a727661b49c Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Mon, 16 Dec 2024 22:11:39 +0200
Subject: [PATCH 05/51] test(ios): update app's bundle-id and build commands.

---
 detox/test/e2e/detox.config.js                   | 4 ++--
 detox/test/ios/example.xcodeproj/project.pbxproj | 4 ++--
 detox/test/ios/example/Info.plist                | 1 -
 3 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/detox/test/e2e/detox.config.js b/detox/test/e2e/detox.config.js
index d2c8fde741..591c4e3fdb 100644
--- a/detox/test/e2e/detox.config.js
+++ b/detox/test/e2e/detox.config.js
@@ -53,7 +53,7 @@ const config = {
       type: 'ios.app',
       name: 'example',
       binaryPath: 'ios/build/Build/Products/Debug-iphonesimulator/example.app',
-      build: 'set -o pipefail && xcodebuild -workspace ios/example.xcworkspace -UseNewBuildSystem=YES -scheme example_ci -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build -quiet',
+      build: 'set -o pipefail && xcodebuild -workspace ios/example.xcworkspace -scheme example -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build -quiet',
       start: 'react-native start',
       bundleId: 'com.wix.detox-example',
     },
@@ -62,7 +62,7 @@ const config = {
       type: 'ios.app',
       name: 'example',
       binaryPath: 'ios/build/Build/Products/Release-iphonesimulator/example.app',
-      build: 'set -o pipefail && export CODE_SIGNING_REQUIRED=NO && export RCT_NO_LAUNCH_PACKAGER=true && xcodebuild -workspace ios/example.xcworkspace -UseNewBuildSystem=YES -scheme example_ci -configuration Release -sdk iphonesimulator -derivedDataPath ios/build -quiet',
+      build: 'set -o pipefail && export CODE_SIGNING_REQUIRED=NO && export RCT_NO_LAUNCH_PACKAGER=true && xcodebuild -workspace ios/example.xcworkspace -scheme example -configuration Release -sdk iphonesimulator -derivedDataPath ios/build -quiet',
     },
 
     'android.debug': {
diff --git a/detox/test/ios/example.xcodeproj/project.pbxproj b/detox/test/ios/example.xcodeproj/project.pbxproj
index be0da5db37..0431ea1c42 100644
--- a/detox/test/ios/example.xcodeproj/project.pbxproj
+++ b/detox/test/ios/example.xcodeproj/project.pbxproj
@@ -285,7 +285,7 @@
 					"-ObjC",
 					"-lc++",
 				);
-				PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
+				PRODUCT_BUNDLE_IDENTIFIER = "com.wix.detox-example";
 				PRODUCT_NAME = example;
 				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
 				SWIFT_VERSION = 5.0;
@@ -312,7 +312,7 @@
 					"-ObjC",
 					"-lc++",
 				);
-				PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
+				PRODUCT_BUNDLE_IDENTIFIER = "com.wix.detox-example";
 				PRODUCT_NAME = example;
 				SWIFT_VERSION = 5.0;
 				VERSIONING_SYSTEM = "apple-generic";
diff --git a/detox/test/ios/example/Info.plist b/detox/test/ios/example/Info.plist
index 3241dd140b..a496c6c863 100644
--- a/detox/test/ios/example/Info.plist
+++ b/detox/test/ios/example/Info.plist
@@ -26,7 +26,6 @@
 	<true/>
 	<key>NSAppTransportSecurity</key>
 	<dict>
-	  <!-- Do not change NSAllowsArbitraryLoads to true, or you will risk app rejection! -->
 		<key>NSAllowsArbitraryLoads</key>
 		<false/>
 		<key>NSAllowsLocalNetworking</key>

From 7cad1c8705029bb1326e2b5751128a44627f1914 Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Mon, 16 Dec 2024 22:17:05 +0200
Subject: [PATCH 06/51] test(ios): link Detox framework with project.

---
 .../ios/example.xcodeproj/project.pbxproj     | 53 +++++++++++++++++++
 1 file changed, 53 insertions(+)

diff --git a/detox/test/ios/example.xcodeproj/project.pbxproj b/detox/test/ios/example.xcodeproj/project.pbxproj
index 0431ea1c42..40f965f656 100644
--- a/detox/test/ios/example.xcodeproj/project.pbxproj
+++ b/detox/test/ios/example.xcodeproj/project.pbxproj
@@ -11,10 +11,28 @@
 		13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; };
 		13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
 		13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
+		609DDB892D10C21800028574 /* Detox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 609DDB852D10C20800028574 /* Detox.framework */; };
 		81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
 		90CCD0BA1322566EB1285DC2 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */; };
 /* End PBXBuildFile section */
 
+/* Begin PBXContainerItemProxy section */
+		609DDB842D10C20800028574 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 609DDB772D10C20700028574 /* Detox.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 394767971DBF985400D72256;
+			remoteInfo = Detox;
+		};
+		609DDB862D10C20800028574 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 609DDB772D10C20700028574 /* Detox.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = 3928EFA51E47404900C19B6E;
+			remoteInfo = DetoxUserNotificationTests;
+		};
+/* End PBXContainerItemProxy section */
+
 /* Begin PBXFileReference section */
 		13B07F961A680F5B00A75B9A /* example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = example.app; sourceTree = BUILT_PRODUCTS_DIR; };
 		13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = example/AppDelegate.h; sourceTree = "<group>"; };
@@ -28,6 +46,7 @@
 		5709B34CF0A7D63546082F79 /* Pods-example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example.release.xcconfig"; path = "Target Support Files/Pods-example/Pods-example.release.xcconfig"; sourceTree = "<group>"; };
 		5B7EB9410499542E8C5724F5 /* Pods-example-exampleTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example-exampleTests.debug.xcconfig"; path = "Target Support Files/Pods-example-exampleTests/Pods-example-exampleTests.debug.xcconfig"; sourceTree = "<group>"; };
 		5DCACB8F33CDC322A6C60F78 /* libPods-example.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-example.a"; sourceTree = BUILT_PRODUCTS_DIR; };
+		609DDB772D10C20700028574 /* Detox.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Detox.xcodeproj; path = /Users/asafk/Development/Detox/detox/ios/Detox.xcodeproj; sourceTree = "<absolute>"; };
 		81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = example/LaunchScreen.storyboard; sourceTree = "<group>"; };
 		89C6BE57DB24E9ADA2F236DE /* Pods-example-exampleTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example-exampleTests.release.xcconfig"; path = "Target Support Files/Pods-example-exampleTests/Pods-example-exampleTests.release.xcconfig"; sourceTree = "<group>"; };
 		ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
@@ -38,6 +57,7 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				609DDB892D10C21800028574 /* Detox.framework in Frameworks */,
 				0C80B921A6F3F58F76C31292 /* libPods-example.a in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -69,6 +89,15 @@
 			name = Frameworks;
 			sourceTree = "<group>";
 		};
+		609DDB802D10C20800028574 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				609DDB852D10C20800028574 /* Detox.framework */,
+				609DDB872D10C20800028574 /* DetoxUserNotificationTests.xctest */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
 		832341AE1AAA6A7D00B99B32 /* Libraries */ = {
 			isa = PBXGroup;
 			children = (
@@ -79,6 +108,7 @@
 		83CBB9F61A601CBA00E9B192 = {
 			isa = PBXGroup;
 			children = (
+				609DDB772D10C20700028574 /* Detox.xcodeproj */,
 				13B07FAE1A68108700A75B9A /* example */,
 				832341AE1AAA6A7D00B99B32 /* Libraries */,
 				83CBBA001A601CBA00E9B192 /* Products */,
@@ -157,6 +187,12 @@
 			mainGroup = 83CBB9F61A601CBA00E9B192;
 			productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
 			projectDirPath = "";
+			projectReferences = (
+				{
+					ProductGroup = 609DDB802D10C20800028574 /* Products */;
+					ProjectRef = 609DDB772D10C20700028574 /* Detox.xcodeproj */;
+				},
+			);
 			projectRoot = "";
 			targets = (
 				13B07F861A680F5B00A75B9A /* example */,
@@ -164,6 +200,23 @@
 		};
 /* End PBXProject section */
 
+/* Begin PBXReferenceProxy section */
+		609DDB852D10C20800028574 /* Detox.framework */ = {
+			isa = PBXReferenceProxy;
+			fileType = wrapper.framework;
+			path = Detox.framework;
+			remoteRef = 609DDB842D10C20800028574 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		609DDB872D10C20800028574 /* DetoxUserNotificationTests.xctest */ = {
+			isa = PBXReferenceProxy;
+			fileType = wrapper.cfbundle;
+			path = DetoxUserNotificationTests.xctest;
+			remoteRef = 609DDB862D10C20800028574 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+/* End PBXReferenceProxy section */
+
 /* Begin PBXResourcesBuildPhase section */
 		13B07F8E1A680F5B00A75B9A /* Resources */ = {
 			isa = PBXResourcesBuildPhase;

From 35cdb2d27329f8a043045b98e1746abf82ee4f72 Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Mon, 16 Dec 2024 22:27:11 +0200
Subject: [PATCH 07/51] test(ios): update Podfile with dependencies.

---
 detox/test/ios/Podfile | 58 +++++++++++++++++++++++++++++++++---------
 1 file changed, 46 insertions(+), 12 deletions(-)

diff --git a/detox/test/ios/Podfile b/detox/test/ios/Podfile
index e0a72606ec..8f849b7800 100644
--- a/detox/test/ios/Podfile
+++ b/detox/test/ios/Podfile
@@ -1,13 +1,51 @@
-# Resolve react_native_pods.rb with node to allow for hoisting
-require Pod::Executable.execute_command('node', ['-p',
-  'require.resolve(
-    "react-native/scripts/react_native_pods.rb",
-    {paths: [process.argv[1]]},
-  )', __dir__]).strip
+# Set RCT_NEW_ARCH_ENABLED to '0' if not defined
+ENV['RCT_NEW_ARCH_ENABLED'] = '0' unless ENV['RCT_NEW_ARCH_ENABLED']
+
+if ENV["REACT_NATIVE_VERSION"] && ENV["REACT_NATIVE_VERSION"].match(/0.71.*/)
+  require_relative '../node_modules/react-native/scripts/react_native_pods'
+  require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
+  require_relative '../node_modules/react-native-permissions/scripts/setup'
+else
+  # Resolve react_native_pods.rb with node to allow for hoisting
+  require Pod::Executable.execute_command('node', ['-p',
+    'require.resolve(
+      "react-native/scripts/react_native_pods.rb",
+      {paths: [process.argv[1]]},
+    )', __dir__]).strip
+
+  require Pod::Executable.execute_command('node', ['-p',
+    'require.resolve(
+      "react-native-permissions/scripts/setup.rb",
+      {paths: [process.argv[1]]},
+    )', __dir__]).strip
+end
 
 platform :ios, min_ios_version_supported
 prepare_react_native_project!
 
+# Configure permissions
+setup_permissions([
+  'AppTrackingTransparency',
+  'Bluetooth',
+  'Calendars',
+  'Camera',
+  'Contacts',
+  'FaceID',
+  'LocationAccuracy',
+  'LocationAlways',
+  'LocationWhenInUse',
+  'MediaLibrary',
+  'Microphone',
+  'Motion',
+  'Notifications',
+  'PhotoLibrary',
+  'PhotoLibraryAddOnly',
+  'Reminders',
+  'Siri',
+  'SpeechRecognition',
+  'StoreKit',
+])
+
 linkage = ENV['USE_FRAMEWORKS']
 if linkage != nil
   Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green
@@ -19,17 +57,13 @@ target 'example' do
 
   use_react_native!(
     :path => config[:reactNativePath],
-    # An absolute path to your application root.
     :app_path => "#{Pod::Config.instance.installation_root}/.."
   )
 
-  target 'exampleTests' do
-    inherit! :complete
-    # Pods for testing
-  end
+  # Add React Native Slider
+  pod 'react-native-slider', :path => '../node_modules/@react-native-community/slider'
 
   post_install do |installer|
-    # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202
     react_native_post_install(
       installer,
       config[:reactNativePath],

From b8a4b2f6426e9649dbbaef2ce7bb70405cb4c4e4 Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Mon, 16 Dec 2024 22:51:05 +0200
Subject: [PATCH 08/51] test(ios): update `AppDelegate.mm` with deps.

---
 detox/test/ios/example/AppDelegate.mm | 95 ++++++++++++++++++++++++---
 1 file changed, 86 insertions(+), 9 deletions(-)

diff --git a/detox/test/ios/example/AppDelegate.mm b/detox/test/ios/example/AppDelegate.mm
index ba286dc79e..fbb3aee217 100644
--- a/detox/test/ios/example/AppDelegate.mm
+++ b/detox/test/ios/example/AppDelegate.mm
@@ -1,30 +1,107 @@
 #import "AppDelegate.h"
-
 #import <React/RCTBundleURLProvider.h>
+#import <React/RCTLinkingManager.h>
+#import <UserNotifications/UserNotifications.h>
+#import <CoreSpotlight/CoreSpotlight.h>
+
+// Shake event handling
+@interface ShakeEventEmitter : RCTEventEmitter
+@end
+
+static ShakeEventEmitter* _shakeInstance;
+
+@implementation ShakeEventEmitter
+RCT_EXPORT_MODULE();
+
+- (instancetype)init {
+    self = [super init];
+    _shakeInstance = self;
+    return self;
+}
+
+- (NSArray<NSString *> *)supportedEvents {
+    return @[@"ShakeEvent"];
+}
+
+- (void)sendShakeEvent {
+    [self sendEventWithName:@"ShakeEvent" body:nil];
+}
+
++ (BOOL)requiresMainQueueSetup {
+    return YES;
+}
+@end
+
+// Custom ViewController for shake detection
+@interface ShakeDetectViewController : UIViewController
+@property (nonatomic, weak) RCTBridge* bridge;
+@end
+
+@implementation ShakeDetectViewController
+- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event {
+    if(event.subtype == UIEventSubtypeMotionShake) {
+        [_shakeInstance sendShakeEvent];
+    }
+}
+@end
+
+@interface AppDelegate () <UNUserNotificationCenterDelegate>
+@end
 
 @implementation AppDelegate
 
 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
 {
-  self.moduleName = @"example";
-  // You can add your custom initial props in the dictionary below.
-  // They will be passed down to the ViewController used by React Native.
-  self.initialProps = @{};
+    self.moduleName = @"example";
+    self.initialProps = @{};
+
+    // Setup notification delegate
+    [UNUserNotificationCenter currentNotificationCenter].delegate = self;
 
-  return [super application:application didFinishLaunchingWithOptions:launchOptions];
+    return [super application:application didFinishLaunchingWithOptions:launchOptions];
+}
+
+// URL scheme handling
+- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options
+{
+    return [RCTLinkingManager application:application openURL:url options:options];
+}
+
+// Universal links and Spotlight search handling
+- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void(^)(NSArray<id<UIUserActivityRestoring>> *))restorationHandler
+{
+    return [RCTLinkingManager application:application continueUserActivity:userActivity restorationHandler:restorationHandler];
+}
+
+// Push notification handling
+- (void)userNotificationCenter:(UNUserNotificationCenter *)center
+       willPresentNotification:(UNNotification *)notification
+         withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler
+{
+    completionHandler(UNNotificationPresentationOptionList |
+                      UNNotificationPresentationOptionBanner |
+                      UNNotificationPresentationOptionBadge |
+                      UNNotificationPresentationOptionSound);
+}
+
+- (void)userNotificationCenter:(UNUserNotificationCenter *)center
+didReceiveNotificationResponse:(UNNotificationResponse *)response
+         withCompletionHandler:(void (^)(void))completionHandler
+{
+    completionHandler();
 }
 
 - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
 {
-  return [self bundleURL];
+    return [self bundleURL];
 }
 
 - (NSURL *)bundleURL
 {
 #if DEBUG
-  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
+    return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
 #else
-  return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
+    return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
 #endif
 }
 

From 336d83d2da18bb830cc52a959bea2dfc8920bced Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Mon, 16 Dec 2024 23:37:04 +0200
Subject: [PATCH 09/51] test(ios): add `NativeModule`.

---
 detox/test/ios/ReactModules/NativeModule.h    |   6 +
 detox/test/ios/ReactModules/NativeModule.mm   | 119 ++++++++++++++++++
 .../ios/example.xcodeproj/project.pbxproj     |  14 +++
 3 files changed, 139 insertions(+)
 create mode 100644 detox/test/ios/ReactModules/NativeModule.h
 create mode 100644 detox/test/ios/ReactModules/NativeModule.mm

diff --git a/detox/test/ios/ReactModules/NativeModule.h b/detox/test/ios/ReactModules/NativeModule.h
new file mode 100644
index 0000000000..7bde08a0f8
--- /dev/null
+++ b/detox/test/ios/ReactModules/NativeModule.h
@@ -0,0 +1,6 @@
+#import <React/RCTBridgeModule.h>
+#import <Foundation/Foundation.h>
+
+@interface NativeModule : NSObject <RCTBridgeModule>
+
+@end
diff --git a/detox/test/ios/ReactModules/NativeModule.mm b/detox/test/ios/ReactModules/NativeModule.mm
new file mode 100644
index 0000000000..08f07b45fc
--- /dev/null
+++ b/detox/test/ios/ReactModules/NativeModule.mm
@@ -0,0 +1,119 @@
+#import "NativeModule.h"
+#import <UIKit/UIKit.h>
+#import <React/RCTRootView.h>
+
+static int CALL_COUNTER = 0;
+
+@implementation NativeModule
+
+RCT_EXPORT_MODULE();
+
+RCT_EXPORT_METHOD(echoWithoutResponse:(NSString *)str)
+{
+  // NSLog(@"NativeModule echoWithoutResponse called");
+  CALL_COUNTER++;
+}
+
+RCT_EXPORT_METHOD(echoWithResponse:(NSString *)str
+                          resolver:(RCTPromiseResolveBlock)resolve
+                          rejecter:(RCTPromiseRejectBlock)reject)
+{
+  CALL_COUNTER++;
+  resolve(str);
+  // NSLog(@"NativeModule echoWithResponse called");
+}
+
+RCT_EXPORT_METHOD(nativeSetTimeout:(NSTimeInterval)delay block:(RCTResponseSenderBlock)block)
+{
+	dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+		dispatch_async(dispatch_get_main_queue(), ^{
+			block(@[]);
+		});
+	});
+}
+
+RCT_EXPORT_METHOD(switchToNativeRoot)
+{
+  dispatch_async(dispatch_get_main_queue(), ^{
+    UIViewController* newRoot = [UIViewController new];
+    newRoot.view.backgroundColor = [UIColor whiteColor];
+    UILabel* label = [UILabel new];
+    label.text = @"this is a new native root";
+    [label sizeToFit];
+    [[newRoot view] addSubview:label];
+    label.center = newRoot.view.center;
+
+    id<UIApplicationDelegate> delegate = [[UIApplication sharedApplication] delegate];
+    [[delegate window]setRootViewController:newRoot];
+    [[delegate window] makeKeyAndVisible];
+  });
+}
+
+RCT_EXPORT_METHOD(switchToMultipleReactRoots)
+{
+  dispatch_async(dispatch_get_main_queue(), ^{
+    id<UIApplicationDelegate> delegate = [[UIApplication sharedApplication] delegate];
+    RCTBridge* bridge = ((RCTRootView*)delegate.window.rootViewController.view).bridge;
+
+    UIViewController* newRoot = [UIViewController new];
+    newRoot.view = [[RCTRootView alloc]initWithBridge:bridge moduleName:@"example" initialProperties:nil];
+    newRoot.tabBarItem.title = @"1";
+
+
+    UIViewController* newRoot2 = [UIViewController new];
+    newRoot2.view = [[RCTRootView alloc]initWithBridge:bridge moduleName:@"example" initialProperties:nil];
+    newRoot2.tabBarItem.title = @"2";
+
+    UIViewController* newRoot3 = [UIViewController new];
+    newRoot3.view = [[RCTRootView alloc]initWithBridge:bridge moduleName:@"example" initialProperties:nil];
+    newRoot3.tabBarItem.title = @"3";
+
+    UIViewController* newRoot4 = [UIViewController new];
+    newRoot4.view = [[RCTRootView alloc]initWithBridge:bridge moduleName:@"example" initialProperties:nil];
+    newRoot4.tabBarItem.title = @"4";
+
+    UITabBarController* tbc = [UITabBarController new];
+    tbc.viewControllers = @[newRoot, newRoot2, newRoot3, newRoot4];
+
+    [[delegate window]setRootViewController:tbc];
+    [[delegate window] makeKeyAndVisible];
+  });
+}
+
+RCT_EXPORT_METHOD(sendNotification:(NSString*)notification name:(NSString*)name)
+{
+	dispatch_async(dispatch_get_main_queue(), ^{
+		[NSNotificationCenter.defaultCenter postNotificationName:notification object:nil userInfo:@{@"name": name}];
+	});
+}
+
+RCT_EXPORT_METHOD(presentOverlayWindow) {
+    static UIWindow *overlayWindow;
+
+    dispatch_async(dispatch_get_main_queue(), ^{
+        CGRect screenBounds = UIScreen.mainScreen.bounds;
+        overlayWindow = [[UIWindow alloc] initWithFrame:screenBounds];
+        overlayWindow.accessibilityIdentifier = @"OverlayWindow";
+
+        [overlayWindow setWindowLevel:UIWindowLevelStatusBar];
+        [overlayWindow setHidden:NO];
+
+        [overlayWindow makeKeyAndVisible];
+    });
+}
+
+RCT_EXPORT_METHOD(presentOverlayView) {
+    static UIView *overlayView;
+
+    dispatch_async(dispatch_get_main_queue(), ^{
+        CGRect screenBounds = UIScreen.mainScreen.bounds;
+        overlayView = [[UIView alloc] initWithFrame:screenBounds];
+        overlayView.userInteractionEnabled = YES;
+        overlayView.accessibilityIdentifier = @"OverlayView";
+
+        UIWindow *keyWindow = UIApplication.sharedApplication.keyWindow;
+        [keyWindow addSubview:overlayView];
+    });
+}
+
+@end
diff --git a/detox/test/ios/example.xcodeproj/project.pbxproj b/detox/test/ios/example.xcodeproj/project.pbxproj
index 40f965f656..4b28ac8a73 100644
--- a/detox/test/ios/example.xcodeproj/project.pbxproj
+++ b/detox/test/ios/example.xcodeproj/project.pbxproj
@@ -12,6 +12,7 @@
 		13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
 		13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
 		609DDB892D10C21800028574 /* Detox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 609DDB852D10C20800028574 /* Detox.framework */; };
+		609DDBE42D10D45500028574 /* NativeModule.mm in Sources */ = {isa = PBXBuildFile; fileRef = 609DDBE32D10D45500028574 /* NativeModule.mm */; };
 		81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
 		90CCD0BA1322566EB1285DC2 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */; };
 /* End PBXBuildFile section */
@@ -47,6 +48,8 @@
 		5B7EB9410499542E8C5724F5 /* Pods-example-exampleTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example-exampleTests.debug.xcconfig"; path = "Target Support Files/Pods-example-exampleTests/Pods-example-exampleTests.debug.xcconfig"; sourceTree = "<group>"; };
 		5DCACB8F33CDC322A6C60F78 /* libPods-example.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-example.a"; sourceTree = BUILT_PRODUCTS_DIR; };
 		609DDB772D10C20700028574 /* Detox.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Detox.xcodeproj; path = /Users/asafk/Development/Detox/detox/ios/Detox.xcodeproj; sourceTree = "<absolute>"; };
+		609DDBE22D10D45500028574 /* NativeModule.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NativeModule.h; sourceTree = "<group>"; };
+		609DDBE32D10D45500028574 /* NativeModule.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = NativeModule.mm; sourceTree = "<group>"; };
 		81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = example/LaunchScreen.storyboard; sourceTree = "<group>"; };
 		89C6BE57DB24E9ADA2F236DE /* Pods-example-exampleTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example-exampleTests.release.xcconfig"; path = "Target Support Files/Pods-example-exampleTests/Pods-example-exampleTests.release.xcconfig"; sourceTree = "<group>"; };
 		ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
@@ -75,6 +78,7 @@
 				81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */,
 				13B07FB71A68108700A75B9A /* main.m */,
 				13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */,
+				609DDBE12D10D44F00028574 /* ReactModules */,
 			);
 			name = example;
 			sourceTree = "<group>";
@@ -98,6 +102,15 @@
 			name = Products;
 			sourceTree = "<group>";
 		};
+		609DDBE12D10D44F00028574 /* ReactModules */ = {
+			isa = PBXGroup;
+			children = (
+				609DDBE22D10D45500028574 /* NativeModule.h */,
+				609DDBE32D10D45500028574 /* NativeModule.mm */,
+			);
+			path = ReactModules;
+			sourceTree = "<group>";
+		};
 		832341AE1AAA6A7D00B99B32 /* Libraries */ = {
 			isa = PBXGroup;
 			children = (
@@ -310,6 +323,7 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				609DDBE42D10D45500028574 /* NativeModule.mm in Sources */,
 				13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */,
 				13B07FC11A68108700A75B9A /* main.m in Sources */,
 			);

From c8589fa42d2cd6aedf4e102379555c72daa4bff0 Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Mon, 16 Dec 2024 23:53:31 +0200
Subject: [PATCH 10/51] test(ios): refactor legacy `NativeModule`.

---
 detox/test/ios/ReactModules/NativeModule.mm | 215 ++++++++++++--------
 1 file changed, 132 insertions(+), 83 deletions(-)

diff --git a/detox/test/ios/ReactModules/NativeModule.mm b/detox/test/ios/ReactModules/NativeModule.mm
index 08f07b45fc..bd80781919 100644
--- a/detox/test/ios/ReactModules/NativeModule.mm
+++ b/detox/test/ios/ReactModules/NativeModule.mm
@@ -2,118 +2,167 @@
 #import <UIKit/UIKit.h>
 #import <React/RCTRootView.h>
 
-static int CALL_COUNTER = 0;
+@interface NativeModule ()
+@property (nonatomic, strong) UIWindow *overlayWindow;
+@property (nonatomic, strong) UIView *overlayView;
+@property (nonatomic, assign) NSInteger callCounter;
+@end
 
 @implementation NativeModule
 
 RCT_EXPORT_MODULE();
 
-RCT_EXPORT_METHOD(echoWithoutResponse:(NSString *)str)
-{
-  // NSLog(@"NativeModule echoWithoutResponse called");
-  CALL_COUNTER++;
+#pragma mark - Lifecycle Methods
+
+- (instancetype)init {
+    self = [super init];
+    if (self) {
+        _callCounter = 0;
+    }
+    return self;
+}
+
+#pragma mark - Echo Methods
+
+RCT_EXPORT_METHOD(echoWithoutResponse:(NSString *)str) {
+    self.callCounter++;
 }
 
 RCT_EXPORT_METHOD(echoWithResponse:(NSString *)str
-                          resolver:(RCTPromiseResolveBlock)resolve
-                          rejecter:(RCTPromiseRejectBlock)reject)
-{
-  CALL_COUNTER++;
-  resolve(str);
-  // NSLog(@"NativeModule echoWithResponse called");
-}
-
-RCT_EXPORT_METHOD(nativeSetTimeout:(NSTimeInterval)delay block:(RCTResponseSenderBlock)block)
-{
-	dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
-		dispatch_async(dispatch_get_main_queue(), ^{
-			block(@[]);
-		});
-	});
-}
-
-RCT_EXPORT_METHOD(switchToNativeRoot)
-{
-  dispatch_async(dispatch_get_main_queue(), ^{
-    UIViewController* newRoot = [UIViewController new];
-    newRoot.view.backgroundColor = [UIColor whiteColor];
-    UILabel* label = [UILabel new];
-    label.text = @"this is a new native root";
-    [label sizeToFit];
-    [[newRoot view] addSubview:label];
-    label.center = newRoot.view.center;
+                  resolver:(RCTPromiseResolveBlock)resolve
+                  rejecter:(RCTPromiseRejectBlock)reject) {
+    self.callCounter++;
+    resolve(str);
+}
 
-    id<UIApplicationDelegate> delegate = [[UIApplication sharedApplication] delegate];
-    [[delegate window]setRootViewController:newRoot];
-    [[delegate window] makeKeyAndVisible];
-  });
+#pragma mark - Timing Methods
+
+RCT_EXPORT_METHOD(nativeSetTimeout:(NSTimeInterval)delay
+                  block:(RCTResponseSenderBlock)block) {
+    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)),
+                   dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+        [self executeOnMainThread:^{
+            block(@[]);
+        }];
+    });
 }
 
-RCT_EXPORT_METHOD(switchToMultipleReactRoots)
-{
-  dispatch_async(dispatch_get_main_queue(), ^{
-    id<UIApplicationDelegate> delegate = [[UIApplication sharedApplication] delegate];
-    RCTBridge* bridge = ((RCTRootView*)delegate.window.rootViewController.view).bridge;
+#pragma mark - Navigation Methods
 
-    UIViewController* newRoot = [UIViewController new];
-    newRoot.view = [[RCTRootView alloc]initWithBridge:bridge moduleName:@"example" initialProperties:nil];
-    newRoot.tabBarItem.title = @"1";
+RCT_EXPORT_METHOD(switchToNativeRoot) {
+    [self executeOnMainThread:^{
+        UIViewController *newRoot = [self createNativeRootViewController];
+        [self updateRootViewController:newRoot];
+    }];
+}
 
+RCT_EXPORT_METHOD(switchToMultipleReactRoots) {
+    [self executeOnMainThread:^{
+        UITabBarController *tabController = [self createTabBarControllerWithBridge];
+        [self updateRootViewController:tabController];
+    }];
+}
 
-    UIViewController* newRoot2 = [UIViewController new];
-    newRoot2.view = [[RCTRootView alloc]initWithBridge:bridge moduleName:@"example" initialProperties:nil];
-    newRoot2.tabBarItem.title = @"2";
+#pragma mark - Notification Methods
 
-    UIViewController* newRoot3 = [UIViewController new];
-    newRoot3.view = [[RCTRootView alloc]initWithBridge:bridge moduleName:@"example" initialProperties:nil];
-    newRoot3.tabBarItem.title = @"3";
+RCT_EXPORT_METHOD(sendNotification:(NSString*)notification
+                  name:(NSString*)name) {
+    [self executeOnMainThread:^{
+        [NSNotificationCenter.defaultCenter postNotificationName:notification
+                                                          object:nil
+                                                        userInfo:@{@"name": name}];
+    }];
+}
 
-    UIViewController* newRoot4 = [UIViewController new];
-    newRoot4.view = [[RCTRootView alloc]initWithBridge:bridge moduleName:@"example" initialProperties:nil];
-    newRoot4.tabBarItem.title = @"4";
+#pragma mark - Overlay Methods
 
-    UITabBarController* tbc = [UITabBarController new];
-    tbc.viewControllers = @[newRoot, newRoot2, newRoot3, newRoot4];
+RCT_EXPORT_METHOD(presentOverlayWindow) {
+    [self executeOnMainThread:^{
+        [self setupAndShowOverlayWindow];
+    }];
+}
 
-    [[delegate window]setRootViewController:tbc];
-    [[delegate window] makeKeyAndVisible];
-  });
+RCT_EXPORT_METHOD(presentOverlayView) {
+    [self executeOnMainThread:^{
+        [self setupAndShowOverlayView];
+    }];
 }
 
-RCT_EXPORT_METHOD(sendNotification:(NSString*)notification name:(NSString*)name)
-{
-	dispatch_async(dispatch_get_main_queue(), ^{
-		[NSNotificationCenter.defaultCenter postNotificationName:notification object:nil userInfo:@{@"name": name}];
-	});
+#pragma mark - Private Helper Methods
+
+- (void)executeOnMainThread:(void (^)(void))block {
+    if ([NSThread isMainThread]) {
+        block();
+    } else {
+        dispatch_async(dispatch_get_main_queue(), block);
+    }
 }
 
-RCT_EXPORT_METHOD(presentOverlayWindow) {
-    static UIWindow *overlayWindow;
+- (UIViewController *)createNativeRootViewController {
+    UIViewController *newRoot = [UIViewController new];
+    newRoot.view.backgroundColor = UIColor.whiteColor;
 
-    dispatch_async(dispatch_get_main_queue(), ^{
-        CGRect screenBounds = UIScreen.mainScreen.bounds;
-        overlayWindow = [[UIWindow alloc] initWithFrame:screenBounds];
-        overlayWindow.accessibilityIdentifier = @"OverlayWindow";
+    UILabel *label = [UILabel new];
+    label.text = @"this is a new native root";
+    [label sizeToFit];
+    [newRoot.view addSubview:label];
+    label.center = newRoot.view.center;
 
-        [overlayWindow setWindowLevel:UIWindowLevelStatusBar];
-        [overlayWindow setHidden:NO];
+    return newRoot;
+}
 
-        [overlayWindow makeKeyAndVisible];
-    });
+- (UITabBarController *)createTabBarControllerWithBridge {
+    RCTBridge *bridge = [self getCurrentBridge];
+    NSArray *viewControllers = @[
+        [self createReactRootViewController:bridge title:@"1"],
+        [self createReactRootViewController:bridge title:@"2"],
+        [self createReactRootViewController:bridge title:@"3"],
+        [self createReactRootViewController:bridge title:@"4"]
+    ];
+
+    UITabBarController *tabController = [UITabBarController new];
+    tabController.viewControllers = viewControllers;
+    return tabController;
 }
 
-RCT_EXPORT_METHOD(presentOverlayView) {
-    static UIView *overlayView;
+- (UIViewController *)createReactRootViewController:(RCTBridge *)bridge
+                                              title:(NSString *)title {
+    UIViewController *viewController = [UIViewController new];
+    viewController.view = [[RCTRootView alloc] initWithBridge:bridge
+                                                   moduleName:@"example"
+                                            initialProperties:nil];
+    viewController.tabBarItem.title = title;
+    return viewController;
+}
 
-    dispatch_async(dispatch_get_main_queue(), ^{
-        CGRect screenBounds = UIScreen.mainScreen.bounds;
-        overlayView = [[UIView alloc] initWithFrame:screenBounds];
-        overlayView.userInteractionEnabled = YES;
-        overlayView.accessibilityIdentifier = @"OverlayView";
+- (RCTBridge *)getCurrentBridge {
+    id<UIApplicationDelegate> delegate = UIApplication.sharedApplication.delegate;
+    return ((RCTRootView *)delegate.window.rootViewController.view).bridge;
+}
 
-        UIWindow *keyWindow = UIApplication.sharedApplication.keyWindow;
-        [keyWindow addSubview:overlayView];
-    });
+- (void)updateRootViewController:(UIViewController *)viewController {
+    id<UIApplicationDelegate> delegate = UIApplication.sharedApplication.delegate;
+    [delegate.window setRootViewController:viewController];
+    [delegate.window makeKeyAndVisible];
+}
+
+- (void)setupAndShowOverlayWindow {
+    CGRect screenBounds = UIScreen.mainScreen.bounds;
+    self.overlayWindow = [[UIWindow alloc] initWithFrame:screenBounds];
+    self.overlayWindow.accessibilityIdentifier = @"OverlayWindow";
+    [self.overlayWindow setWindowLevel:UIWindowLevelStatusBar];
+    [self.overlayWindow setHidden:NO];
+    [self.overlayWindow makeKeyAndVisible];
+}
+
+- (void)setupAndShowOverlayView {
+    CGRect screenBounds = UIScreen.mainScreen.bounds;
+    self.overlayView = [[UIView alloc] initWithFrame:screenBounds];
+    self.overlayView.userInteractionEnabled = YES;
+    self.overlayView.accessibilityIdentifier = @"OverlayView";
+
+    UIWindow *keyWindow = UIApplication.sharedApplication.keyWindow;
+    [keyWindow addSubview:self.overlayView];
 }
 
 @end

From 294a164f2e59c5c5c4437dec66e766914a038b3b Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Mon, 16 Dec 2024 23:56:18 +0200
Subject: [PATCH 11/51] test(ios): add background modes capabilities.

---
 detox/test/ios/example.xcodeproj/project.pbxproj | 4 ++++
 detox/test/ios/example/Info.plist                | 5 +++++
 detox/test/ios/example/example.entitlements      | 8 ++++++++
 3 files changed, 17 insertions(+)
 create mode 100644 detox/test/ios/example/example.entitlements

diff --git a/detox/test/ios/example.xcodeproj/project.pbxproj b/detox/test/ios/example.xcodeproj/project.pbxproj
index 4b28ac8a73..a26cec6e87 100644
--- a/detox/test/ios/example.xcodeproj/project.pbxproj
+++ b/detox/test/ios/example.xcodeproj/project.pbxproj
@@ -47,6 +47,7 @@
 		5709B34CF0A7D63546082F79 /* Pods-example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example.release.xcconfig"; path = "Target Support Files/Pods-example/Pods-example.release.xcconfig"; sourceTree = "<group>"; };
 		5B7EB9410499542E8C5724F5 /* Pods-example-exampleTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example-exampleTests.debug.xcconfig"; path = "Target Support Files/Pods-example-exampleTests/Pods-example-exampleTests.debug.xcconfig"; sourceTree = "<group>"; };
 		5DCACB8F33CDC322A6C60F78 /* libPods-example.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-example.a"; sourceTree = BUILT_PRODUCTS_DIR; };
+		60493BD72D10D967002853A0 /* example.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = example.entitlements; path = example/example.entitlements; sourceTree = "<group>"; };
 		609DDB772D10C20700028574 /* Detox.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Detox.xcodeproj; path = /Users/asafk/Development/Detox/detox/ios/Detox.xcodeproj; sourceTree = "<absolute>"; };
 		609DDBE22D10D45500028574 /* NativeModule.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NativeModule.h; sourceTree = "<group>"; };
 		609DDBE32D10D45500028574 /* NativeModule.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = NativeModule.mm; sourceTree = "<group>"; };
@@ -71,6 +72,7 @@
 		13B07FAE1A68108700A75B9A /* example */ = {
 			isa = PBXGroup;
 			children = (
+				60493BD72D10D967002853A0 /* example.entitlements */,
 				13B07FAF1A68108700A75B9A /* AppDelegate.h */,
 				13B07FB01A68108700A75B9A /* AppDelegate.mm */,
 				13B07FB51A68108700A75B9A /* Images.xcassets */,
@@ -338,6 +340,7 @@
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				CLANG_ENABLE_MODULES = YES;
+				CODE_SIGN_ENTITLEMENTS = example/example.entitlements;
 				CURRENT_PROJECT_VERSION = 1;
 				ENABLE_BITCODE = NO;
 				INFOPLIST_FILE = example/Info.plist;
@@ -366,6 +369,7 @@
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				CLANG_ENABLE_MODULES = YES;
+				CODE_SIGN_ENTITLEMENTS = example/example.entitlements;
 				CURRENT_PROJECT_VERSION = 1;
 				INFOPLIST_FILE = example/Info.plist;
 				IPHONEOS_DEPLOYMENT_TARGET = 15.1;
diff --git a/detox/test/ios/example/Info.plist b/detox/test/ios/example/Info.plist
index a496c6c863..edcff4bcd0 100644
--- a/detox/test/ios/example/Info.plist
+++ b/detox/test/ios/example/Info.plist
@@ -33,6 +33,11 @@
 	</dict>
 	<key>NSLocationWhenInUseUsageDescription</key>
 	<string></string>
+	<key>UIBackgroundModes</key>
+	<array>
+		<string>fetch</string>
+		<string>remote-notification</string>
+	</array>
 	<key>UILaunchStoryboardName</key>
 	<string>LaunchScreen</string>
 	<key>UIRequiredDeviceCapabilities</key>
diff --git a/detox/test/ios/example/example.entitlements b/detox/test/ios/example/example.entitlements
new file mode 100644
index 0000000000..21d95c45f3
--- /dev/null
+++ b/detox/test/ios/example/example.entitlements
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>com.apple.developer.siri</key>
+	<true/>
+</dict>
+</plist>

From 47625f01e36d158c45aa502c3926bfe4fd28d16d Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Tue, 17 Dec 2024 00:01:10 +0200
Subject: [PATCH 12/51] test(ios): enable upside-down rotation.

---
 detox/test/ios/example/Info.plist | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/detox/test/ios/example/Info.plist b/detox/test/ios/example/Info.plist
index edcff4bcd0..a7513950b8 100644
--- a/detox/test/ios/example/Info.plist
+++ b/detox/test/ios/example/Info.plist
@@ -46,9 +46,16 @@
 	</array>
 	<key>UISupportedInterfaceOrientations</key>
 	<array>
+		<string>UIInterfaceOrientationLandscapeLeft</string>
+		<string>UIInterfaceOrientationLandscapeRight</string>
 		<string>UIInterfaceOrientationPortrait</string>
+		<string>UIInterfaceOrientationPortraitUpsideDown</string>
+	</array>
+	<key>UISupportedInterfaceOrientations~ipad</key>
+	<array>
 		<string>UIInterfaceOrientationLandscapeLeft</string>
 		<string>UIInterfaceOrientationLandscapeRight</string>
+		<string>UIInterfaceOrientationPortrait</string>
 	</array>
 	<key>UIViewControllerBasedStatusBarAppearance</key>
 	<false/>

From d1800f16aab9242059ddde2a22dada11f38c8169 Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Tue, 17 Dec 2024 00:03:03 +0200
Subject: [PATCH 13/51] test(ios): update `Info.plist` with missing keys.

---
 detox/test/ios/example/Info.plist | 67 ++++++++++++++++++++++++++-----
 1 file changed, 56 insertions(+), 11 deletions(-)

diff --git a/detox/test/ios/example/Info.plist b/detox/test/ios/example/Info.plist
index a7513950b8..81b3f8f622 100644
--- a/detox/test/ios/example/Info.plist
+++ b/detox/test/ios/example/Info.plist
@@ -4,8 +4,6 @@
 <dict>
 	<key>CFBundleDevelopmentRegion</key>
 	<string>en</string>
-	<key>CFBundleDisplayName</key>
-	<string>example</string>
 	<key>CFBundleExecutable</key>
 	<string>$(EXECUTABLE_NAME)</string>
 	<key>CFBundleIdentifier</key>
@@ -17,11 +15,24 @@
 	<key>CFBundlePackageType</key>
 	<string>APPL</string>
 	<key>CFBundleShortVersionString</key>
-	<string>$(MARKETING_VERSION)</string>
+	<string>1.0</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
+	<key>CFBundleURLTypes</key>
+	<array>
+		<dict>
+			<key>CFBundleTypeRole</key>
+			<string>Editor</string>
+			<key>CFBundleURLName</key>
+			<string>detoxtesturlscheme.test.app</string>
+			<key>CFBundleURLSchemes</key>
+			<array>
+				<string>detoxtesturlscheme</string>
+			</array>
+		</dict>
+	</array>
 	<key>CFBundleVersion</key>
-	<string>$(CURRENT_PROJECT_VERSION)</string>
+	<string>1</string>
 	<key>LSRequiresIPhoneOS</key>
 	<true/>
 	<key>NSAppTransportSecurity</key>
@@ -31,8 +42,42 @@
 		<key>NSAllowsLocalNetworking</key>
 		<true/>
 	</dict>
+	<key>NSAppleMusicUsageDescription</key>
+	<string></string>
+	<key>NSBluetoothAlwaysUsageDescription</key>
+	<string></string>
+	<key>NSBluetoothPeripheralUsageDescription</key>
+	<string></string>
+	<key>NSCalendarsUsageDescription</key>
+	<string></string>
+	<key>NSCameraUsageDescription</key>
+	<string></string>
+	<key>NSContactsUsageDescription</key>
+	<string></string>
+	<key>NSFaceIDUsageDescription</key>
+	<string></string>
+	<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
+	<string></string>
+	<key>NSLocationTemporaryUsageDescriptionDictionary</key>
+	<dict/>
 	<key>NSLocationWhenInUseUsageDescription</key>
 	<string></string>
+	<key>NSMicrophoneUsageDescription</key>
+	<string></string>
+	<key>NSMotionUsageDescription</key>
+	<string></string>
+	<key>NSPhotoLibraryAddUsageDescription</key>
+	<string></string>
+	<key>NSPhotoLibraryUsageDescription</key>
+	<string></string>
+	<key>NSRemindersUsageDescription</key>
+	<string></string>
+	<key>NSSiriUsageDescription</key>
+	<string></string>
+	<key>NSSpeechRecognitionUsageDescription</key>
+	<string></string>
+	<key>NSUserTrackingUsageDescription</key>
+	<string></string>
 	<key>UIBackgroundModes</key>
 	<array>
 		<string>fetch</string>
@@ -44,20 +89,20 @@
 	<array>
 		<string>arm64</string>
 	</array>
+	<key>UIRequiresFullScreen</key>
+	<true/>
 	<key>UISupportedInterfaceOrientations</key>
 	<array>
+		<string>UIInterfaceOrientationPortrait</string>
 		<string>UIInterfaceOrientationLandscapeLeft</string>
 		<string>UIInterfaceOrientationLandscapeRight</string>
-		<string>UIInterfaceOrientationPortrait</string>
 		<string>UIInterfaceOrientationPortraitUpsideDown</string>
 	</array>
-	<key>UISupportedInterfaceOrientations~ipad</key>
+	<key>UIViewControllerBasedStatusBarAppearance</key>
+	<true/>
+	<key>WKBackgroundModes</key>
 	<array>
-		<string>UIInterfaceOrientationLandscapeLeft</string>
-		<string>UIInterfaceOrientationLandscapeRight</string>
-		<string>UIInterfaceOrientationPortrait</string>
+		<string>remote-notification</string>
 	</array>
-	<key>UIViewControllerBasedStatusBarAppearance</key>
-	<false/>
 </dict>
 </plist>

From e54f55826a951e8dbaf905be9eb1e4a98ac1666c Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Tue, 17 Dec 2024 00:10:27 +0200
Subject: [PATCH 14/51] test(ios): copy command line arguments from legacy ios
 project.

---
 .../xcshareddata/xcschemes/example.xcscheme   | 74 +++++++++++++++++++
 1 file changed, 74 insertions(+)

diff --git a/detox/test/ios/example.xcodeproj/xcshareddata/xcschemes/example.xcscheme b/detox/test/ios/example.xcodeproj/xcshareddata/xcschemes/example.xcscheme
index fef9df78ab..ba996697dc 100644
--- a/detox/test/ios/example.xcodeproj/xcshareddata/xcschemes/example.xcscheme
+++ b/detox/test/ios/example.xcodeproj/xcshareddata/xcschemes/example.xcscheme
@@ -60,6 +60,80 @@
             ReferencedContainer = "container:example.xcodeproj">
          </BuildableReference>
       </BuildableProductRunnable>
+      <CommandLineArguments>
+         <CommandLineArgument
+            argument = "-detoxURLOverride test://ttt"
+            isEnabled = "NO">
+         </CommandLineArgument>
+         <CommandLineArgument
+            argument = "-detoxDebugVisibility YES"
+            isEnabled = "YES">
+         </CommandLineArgument>
+         <CommandLineArgument
+            argument = "-detoxSourceAppOverride com.apple.mobilesafari"
+            isEnabled = "NO">
+         </CommandLineArgument>
+         <CommandLineArgument
+            argument = "-detoxUserNotificationDataURL /Users/lnatan/Desktop/Code/Detox/detox/ios/DetoxUserNotificationTests/user_notification_push_trigger.json"
+            isEnabled = "NO">
+         </CommandLineArgument>
+         <CommandLineArgument
+            argument = "-detoxWaitForDebugger 9000"
+            isEnabled = "NO">
+         </CommandLineArgument>
+         <CommandLineArgument
+            argument = "-recordingPath /Users/lnatan/Desktop/from_detox.dtxrec"
+            isEnabled = "NO">
+         </CommandLineArgument>
+         <CommandLineArgument
+            argument = "-detoxPrintBusyIdleResources YES"
+            isEnabled = "NO">
+         </CommandLineArgument>
+         <CommandLineArgument
+            argument = "-detoxUserActivityDataURL /Users/lnatan/Desktop/user-activity.json"
+            isEnabled = "NO">
+         </CommandLineArgument>
+         <CommandLineArgument
+            argument = "-enableAppDelegateVerboseLogging YES"
+            isEnabled = "NO">
+         </CommandLineArgument>
+         <CommandLineArgument
+            argument = "-recordingPath /Users/lnatan/Desktop/test"
+            isEnabled = "NO">
+         </CommandLineArgument>
+         <CommandLineArgument
+            argument = "-samplingInterval 0.1"
+            isEnabled = "NO">
+         </CommandLineArgument>
+         <CommandLineArgument
+            argument = "-detoxURLBlacklistRegex &apos;(&quot;.*localhost.*&quot;, &quot;http://192.168.1.253:19001/onchange&quot;,&quot;https://e.crashlytics.com/spi/v2/events&quot;)&apos;"
+            isEnabled = "NO">
+         </CommandLineArgument>
+         <CommandLineArgument
+            argument = "-detoxEnableSynchronization NO"
+            isEnabled = "NO">
+         </CommandLineArgument>
+         <CommandLineArgument
+            argument = "-DTXEnableVerboseSyncSystem YES"
+            isEnabled = "NO">
+         </CommandLineArgument>
+         <CommandLineArgument
+            argument = "-DTXEnableVerboseSyncResources YES"
+            isEnabled = "NO">
+         </CommandLineArgument>
+         <CommandLineArgument
+            argument = "-detoxEnableSyncDebug YES"
+            isEnabled = "NO">
+         </CommandLineArgument>
+         <CommandLineArgument
+            argument = "-detoxDisableTouchIndicators YES"
+            isEnabled = "NO">
+         </CommandLineArgument>
+         <CommandLineArgument
+            argument = "-detoxDisableAnimationSpeedup YES"
+            isEnabled = "NO">
+         </CommandLineArgument>
+      </CommandLineArguments>
    </LaunchAction>
    <ProfileAction
       buildConfiguration = "Release"

From 23edfc94ec33e9830642e8fcd7091e6fc4da83de Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Tue, 17 Dec 2024 00:15:09 +0200
Subject: [PATCH 15/51] feat(iOS): support new `RCTScrollViewComponentView`.

---
 detox/ios/Detox/Invocation/Element.swift | 35 +++++++++++++++---------
 1 file changed, 22 insertions(+), 13 deletions(-)

diff --git a/detox/ios/Detox/Invocation/Element.swift b/detox/ios/Detox/Invocation/Element.swift
index 70f8d8a426..8442e7fb91 100644
--- a/detox/ios/Detox/Invocation/Element.swift
+++ b/detox/ios/Detox/Invocation/Element.swift
@@ -73,19 +73,28 @@ class Element : NSObject {
 		return element
 	}
 	
-	private func extractScrollView() -> UIScrollView {
-		if let view = self.view as? UIScrollView {
-			return view
-		}
-		else if let view = self.view as? WKWebView {
-			return view.scrollView
-		} else if ReactNativeSupport.isReactNativeApp && NSStringFromClass(type(of: view)) == "RCTScrollView" {
-			return (view.value(forKey: "scrollView") as! UIScrollView)
-		}
-		
-		dtx_fatalError("View “\(self.view.dtx_shortDescription)” is not an instance of “UIScrollView”", viewDescription: debugAttributes)
-	}
-	
+    private func extractScrollView() -> UIScrollView {
+        if let view = self.view as? UIScrollView {
+            return view
+        }
+
+        if let webView = self.view as? WKWebView {
+            return webView.scrollView
+        }
+
+        if ReactNativeSupport.isReactNativeApp {
+            let className = NSStringFromClass(type(of: view))
+            switch className {
+                case "RCTScrollView", "RCTScrollViewComponentView":
+                    return (view.value(forKey: "scrollView") as! UIScrollView)
+                default:
+                    break
+            }
+        }
+
+        dtx_fatalError("View “\(self.view.dtx_shortDescription)” is not an instance of “UIScrollView”", viewDescription: debugAttributes)
+    }
+
 	override var description: String {
 		return String(format: "MATCHER(%@)%@", predicate.description, index != nil ? " AT INDEX(\(index!))" : "")
 	}

From 488c203ea7dada24b3df6bc677bcfb097ced4b99 Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Tue, 17 Dec 2024 00:34:41 +0200
Subject: [PATCH 16/51] feat(ios): support new-arch's
 `RCTParagraphComponentView`.

---
 detox/ios/Detox/Invocation/Predicate.swift    |  8 +-
 .../ios/Detox/Utilities/NSObject+DontCrash.m  | 97 ++++++++++++++-----
 2 files changed, 77 insertions(+), 28 deletions(-)

diff --git a/detox/ios/Detox/Invocation/Predicate.swift b/detox/ios/Detox/Invocation/Predicate.swift
index cd264f5194..ffd19d873c 100644
--- a/detox/ios/Detox/Invocation/Predicate.swift
+++ b/detox/ios/Detox/Invocation/Predicate.swift
@@ -66,7 +66,9 @@ class Predicate : CustomStringConvertible, CustomDebugStringConvertible {
           return ValuePredicate(kind: kind, modifiers: modifiers, value: label, requiresAccessibilityElement: true, isRegex: isRegex)
         } else {
           //Will crash if RN app and neither class exists
-          let RCTTextViewClass : AnyClass = NSClassFromString("RCTText") ?? NSClassFromString("RCTTextView")!
+          let RCTTextViewClass : AnyClass =
+            NSClassFromString("RCTParagraphComponentView") ??
+            NSClassFromString("RCTText") ?? NSClassFromString("RCTTextView")!
 
           let descendantPredicate = DescendantPredicate(predicate: AndCompoundPredicate(predicates: [
             try KindOfPredicate(kind: Kind.type, modifiers: [], className: NSStringFromClass(RCTTextViewClass)),
@@ -89,7 +91,9 @@ class Predicate : CustomStringConvertible, CustomDebugStringConvertible {
 
         if ReactNativeSupport.isReactNativeApp == true {
           //Will crash if RN app and neither class exists
-          let RCTTextViewClass : AnyClass = NSClassFromString("RCTText") ?? NSClassFromString("RCTTextView")!
+          let RCTTextViewClass : AnyClass =
+            NSClassFromString("RCTParagraphComponentView") ??
+            NSClassFromString("RCTText") ?? NSClassFromString("RCTTextView")!
           orPredicates.append(try KindOfPredicate(kind: Kind.type, modifiers: [], className: NSStringFromClass(RCTTextViewClass)))
         }
 
diff --git a/detox/ios/Detox/Utilities/NSObject+DontCrash.m b/detox/ios/Detox/Utilities/NSObject+DontCrash.m
index eb72d4169c..f880071c2d 100644
--- a/detox/ios/Detox/Utilities/NSObject+DontCrash.m
+++ b/detox/ios/Detox/Utilities/NSObject+DontCrash.m
@@ -7,36 +7,81 @@
 
 #import "NSObject+DontCrash.h"
 
+@interface NSObject (DontCrashPrivate)
++ (Class)dtx_classForName:(NSString *)className;
+- (nullable NSString *)dtx_extractTextFromRCTComponent;
+@end
+
 @implementation NSObject (DontCrash)
 
-- (id)_dtx_text
-{
-	if([self respondsToSelector:@selector(text)])
-	{
-		return [(UITextView*)self text];
-	}
-	
-	static Class RCTTextView;
-	static dispatch_once_t onceToken;
-	dispatch_once(&onceToken, ^{
-		RCTTextView = NSClassFromString(@"RCTTextView");
-	});
-	if(RCTTextView != nil && [self isKindOfClass:RCTTextView])
-	{
-		return [(NSTextStorage*)[self valueForKey:@"textStorage"] string];
-	}
-	
-	return nil;
+#pragma mark - Public Methods
+
+- (id)_dtx_text {
+    if ([self respondsToSelector:@selector(text)]) {
+        return [(UITextView *)self text];
+    }
+
+    NSString *reactText = [self dtx_extractTextFromRCTComponent];
+    if (reactText) {
+        return reactText;
+    }
+
+    return nil;
+}
+
+- (id)_dtx_placeholder {
+    if ([self respondsToSelector:@selector(placeholder)]) {
+        return [(UITextField *)self placeholder];
+    }
+    return nil;
+}
+
+@end
+
+@implementation NSObject (DontCrashPrivate)
+
+#pragma mark - Private Methods
+
++ (Class)dtx_classForName:(NSString *)className {
+    static NSMutableDictionary<NSString *, Class> *classCache;
+    static dispatch_once_t onceToken;
+
+    dispatch_once(&onceToken, ^{
+        classCache = [NSMutableDictionary dictionary];
+    });
+
+    Class cachedClass = classCache[className];
+    if (!cachedClass) {
+        cachedClass = NSClassFromString(className);
+        if (cachedClass) {
+            classCache[className] = cachedClass;
+        }
+    }
+
+    return cachedClass;
 }
 
-- (id)_dtx_placeholder
-{
-	if([self respondsToSelector:@selector(placeholder)])
-	{
-		return [(UITextField*)self placeholder];
-	}
-	
-	return nil;
+- (nullable NSString *)dtx_extractTextFromRCTComponent {
+    static Class RCTTextViewClass;
+    static Class RCTParagraphComponentViewClass;
+    static dispatch_once_t onceToken;
+
+    dispatch_once(&onceToken, ^{
+        RCTTextViewClass = [self.class dtx_classForName:@"RCTTextView"];
+        RCTParagraphComponentViewClass = [self.class dtx_classForName:@"RCTParagraphComponentView"];
+    });
+
+    if (RCTTextViewClass && [self isKindOfClass:RCTTextViewClass]) {
+        NSTextStorage *textStorage = [self valueForKey:@"textStorage"];
+        return [textStorage string];
+    }
+
+    if (RCTParagraphComponentViewClass && [self isKindOfClass:RCTParagraphComponentViewClass]) {
+        NSAttributedString *attributedText = [self valueForKey:@"attributedText"];
+        return [attributedText string];
+    }
+
+    return nil;
 }
 
 @end

From 67e1f6048fa425b62c76f9103b0bdbd1b625c27d Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Tue, 17 Dec 2024 00:49:47 +0200
Subject: [PATCH 17/51] feat(ios): support React Native new arch app-reloading.

---
 .../ReactNativeSupport/ReactNativeSupport.m   | 50 +++++++++++--------
 1 file changed, 30 insertions(+), 20 deletions(-)

diff --git a/detox/ios/Detox/Utilities/ReactNativeSupport/ReactNativeSupport.m b/detox/ios/Detox/Utilities/ReactNativeSupport/ReactNativeSupport.m
index b04284cce2..ab54a09089 100644
--- a/detox/ios/Detox/Utilities/ReactNativeSupport/ReactNativeSupport.m
+++ b/detox/ios/Detox/Utilities/ReactNativeSupport/ReactNativeSupport.m
@@ -28,26 +28,36 @@ + (BOOL)isReactNativeApp
 
 + (void)reloadApp
 {
-	if([DTXReactNativeSupport hasReactNative] == NO)
-	{
-		return;
-	}
-	
-	id<RN_RCTBridge> bridge = [NSClassFromString(@"RCTBridge") valueForKey:@"currentBridge"];
-	
-	SEL reqRelSel = NSSelectorFromString(@"requestReload");
-	if([bridge respondsToSelector:reqRelSel])
-	{
-		//Call RN public API to request reload.
-		[bridge requestReload];
-	}
-	else
-	{
-		//Legacy call to reload RN.
-		[[NSNotificationCenter defaultCenter] postNotificationName:RCTReloadNotification
-															object:nil
-														  userInfo:nil];
-	}
+    // Early return if React Native is not present
+    if (![DTXReactNativeSupport hasReactNative]) {
+        return;
+    }
+
+    // Try legacy reload approach (without new arch)
+    id<RN_RCTBridge> bridge = [NSClassFromString(@"RCTBridge") valueForKey:@"currentBridge"];
+    if ([bridge respondsToSelector:@selector(requestReload)]) {
+        [bridge requestReload];
+        return;
+    }
+
+    // Try New Architecture reload approach
+    NSObject<UIApplicationDelegate> *appDelegate = UIApplication.sharedApplication.delegate;
+    NSObject *rootViewFactory = [appDelegate valueForKey:@"rootViewFactory"];
+    NSObject *reactHost = [rootViewFactory valueForKey:@"reactHost"];
+
+    SEL reloadCommand = NSSelectorFromString(@"didReceiveReloadCommand");
+    if (reactHost && [reactHost respondsToSelector:reloadCommand]) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
+        [reactHost performSelector:reloadCommand];
+#pragma clang diagnostic pop
+        return;
+    }
+
+    // Fallback to legacy^2 reload approach
+    [[NSNotificationCenter defaultCenter] postNotificationName:RCTReloadNotification
+                                                        object:nil
+                                                      userInfo:nil];
 }
 
 + (void)waitForReactNativeLoadWithCompletionHandler:(void (^)(void))handler

From ba95461e604935f7d28907493f5da17617f64e1e Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Tue, 17 Dec 2024 01:03:47 +0200
Subject: [PATCH 18/51] test(ios): add example-ci scheme (no Detox linkage).

---
 detox/test/e2e/detox.config.js                |   4 +-
 .../ios/example.xcodeproj/project.pbxproj     | 196 ++++++++++++++++++
 2 files changed, 198 insertions(+), 2 deletions(-)

diff --git a/detox/test/e2e/detox.config.js b/detox/test/e2e/detox.config.js
index 591c4e3fdb..da4ee2381a 100644
--- a/detox/test/e2e/detox.config.js
+++ b/detox/test/e2e/detox.config.js
@@ -53,7 +53,7 @@ const config = {
       type: 'ios.app',
       name: 'example',
       binaryPath: 'ios/build/Build/Products/Debug-iphonesimulator/example.app',
-      build: 'set -o pipefail && xcodebuild -workspace ios/example.xcworkspace -scheme example -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build -quiet',
+      build: 'set -o pipefail && xcodebuild -workspace ios/example.xcworkspace -scheme example-ci -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build -quiet',
       start: 'react-native start',
       bundleId: 'com.wix.detox-example',
     },
@@ -62,7 +62,7 @@ const config = {
       type: 'ios.app',
       name: 'example',
       binaryPath: 'ios/build/Build/Products/Release-iphonesimulator/example.app',
-      build: 'set -o pipefail && export CODE_SIGNING_REQUIRED=NO && export RCT_NO_LAUNCH_PACKAGER=true && xcodebuild -workspace ios/example.xcworkspace -scheme example -configuration Release -sdk iphonesimulator -derivedDataPath ios/build -quiet',
+      build: 'set -o pipefail && export CODE_SIGNING_REQUIRED=NO && export RCT_NO_LAUNCH_PACKAGER=true && xcodebuild -workspace ios/example.xcworkspace -scheme example-ci -configuration Release -sdk iphonesimulator -derivedDataPath ios/build -quiet',
     },
 
     'android.debug': {
diff --git a/detox/test/ios/example.xcodeproj/project.pbxproj b/detox/test/ios/example.xcodeproj/project.pbxproj
index a26cec6e87..d4d24ad8a7 100644
--- a/detox/test/ios/example.xcodeproj/project.pbxproj
+++ b/detox/test/ios/example.xcodeproj/project.pbxproj
@@ -11,6 +11,13 @@
 		13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; };
 		13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
 		13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
+		60493BDE2D10E7E4002853A0 /* NativeModule.mm in Sources */ = {isa = PBXBuildFile; fileRef = 609DDBE32D10D45500028574 /* NativeModule.mm */; };
+		60493BDF2D10E7E4002853A0 /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; };
+		60493BE02D10E7E4002853A0 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
+		60493BE32D10E7E4002853A0 /* libPods-example.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DCACB8F33CDC322A6C60F78 /* libPods-example.a */; };
+		60493BE52D10E7E4002853A0 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
+		60493BE62D10E7E4002853A0 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
+		60493BE72D10E7E4002853A0 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */; };
 		609DDB892D10C21800028574 /* Detox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 609DDB852D10C20800028574 /* Detox.framework */; };
 		609DDBE42D10D45500028574 /* NativeModule.mm in Sources */ = {isa = PBXBuildFile; fileRef = 609DDBE32D10D45500028574 /* NativeModule.mm */; };
 		81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
@@ -48,6 +55,7 @@
 		5B7EB9410499542E8C5724F5 /* Pods-example-exampleTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example-exampleTests.debug.xcconfig"; path = "Target Support Files/Pods-example-exampleTests/Pods-example-exampleTests.debug.xcconfig"; sourceTree = "<group>"; };
 		5DCACB8F33CDC322A6C60F78 /* libPods-example.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-example.a"; sourceTree = BUILT_PRODUCTS_DIR; };
 		60493BD72D10D967002853A0 /* example.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = example.entitlements; path = example/example.entitlements; sourceTree = "<group>"; };
+		60493BEE2D10E7E4002853A0 /* example-ci.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "example-ci.app"; sourceTree = BUILT_PRODUCTS_DIR; };
 		609DDB772D10C20700028574 /* Detox.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Detox.xcodeproj; path = /Users/asafk/Development/Detox/detox/ios/Detox.xcodeproj; sourceTree = "<absolute>"; };
 		609DDBE22D10D45500028574 /* NativeModule.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NativeModule.h; sourceTree = "<group>"; };
 		609DDBE32D10D45500028574 /* NativeModule.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = NativeModule.mm; sourceTree = "<group>"; };
@@ -66,6 +74,14 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		60493BE12D10E7E4002853A0 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				60493BE32D10E7E4002853A0 /* libPods-example.a in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 /* End PBXFrameworksBuildPhase section */
 
 /* Begin PBXGroup section */
@@ -139,6 +155,7 @@
 			isa = PBXGroup;
 			children = (
 				13B07F961A680F5B00A75B9A /* example.app */,
+				60493BEE2D10E7E4002853A0 /* example-ci.app */,
 			);
 			name = Products;
 			sourceTree = "<group>";
@@ -178,6 +195,27 @@
 			productReference = 13B07F961A680F5B00A75B9A /* example.app */;
 			productType = "com.apple.product-type.application";
 		};
+		60493BDB2D10E7E4002853A0 /* example-ci */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 60493BEB2D10E7E4002853A0 /* Build configuration list for PBXNativeTarget "example-ci" */;
+			buildPhases = (
+				60493BDC2D10E7E4002853A0 /* [CP] Check Pods Manifest.lock */,
+				60493BDD2D10E7E4002853A0 /* Sources */,
+				60493BE12D10E7E4002853A0 /* Frameworks */,
+				60493BE42D10E7E4002853A0 /* Resources */,
+				60493BE82D10E7E4002853A0 /* Bundle React Native code and images */,
+				60493BE92D10E7E4002853A0 /* [CP] Embed Pods Frameworks */,
+				60493BEA2D10E7E4002853A0 /* [CP] Copy Pods Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = "example-ci";
+			productName = example;
+			productReference = 60493BEE2D10E7E4002853A0 /* example-ci.app */;
+			productType = "com.apple.product-type.application";
+		};
 /* End PBXNativeTarget section */
 
 /* Begin PBXProject section */
@@ -211,6 +249,7 @@
 			projectRoot = "";
 			targets = (
 				13B07F861A680F5B00A75B9A /* example */,
+				60493BDB2D10E7E4002853A0 /* example-ci */,
 			);
 		};
 /* End PBXProject section */
@@ -243,6 +282,16 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		60493BE42D10E7E4002853A0 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				60493BE52D10E7E4002853A0 /* LaunchScreen.storyboard in Resources */,
+				60493BE62D10E7E4002853A0 /* Images.xcassets in Resources */,
+				60493BE72D10E7E4002853A0 /* PrivacyInfo.xcprivacy in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 /* End PBXResourcesBuildPhase section */
 
 /* Begin PBXShellScriptBuildPhase section */
@@ -279,6 +328,78 @@
 			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-frameworks.sh\"\n";
 			showEnvVarsInLog = 0;
 		};
+		60493BDC2D10E7E4002853A0 /* [CP] Check Pods Manifest.lock */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputFileListPaths = (
+			);
+			inputPaths = (
+				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+				"${PODS_ROOT}/Manifest.lock",
+			);
+			name = "[CP] Check Pods Manifest.lock";
+			outputFileListPaths = (
+			);
+			outputPaths = (
+				"$(DERIVED_FILE_DIR)/Pods-example-checkManifestLockResult.txt",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+			showEnvVarsInLog = 0;
+		};
+		60493BE82D10E7E4002853A0 /* Bundle React Native code and images */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+				"$(SRCROOT)/.xcode.env.local",
+				"$(SRCROOT)/.xcode.env",
+			);
+			name = "Bundle React Native code and images";
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "set -e\n\nWITH_ENVIRONMENT=\"$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"$REACT_NATIVE_PATH/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"\n";
+		};
+		60493BE92D10E7E4002853A0 /* [CP] Embed Pods Frameworks */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputFileListPaths = (
+				"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-frameworks-${CONFIGURATION}-input-files.xcfilelist",
+			);
+			name = "[CP] Embed Pods Frameworks";
+			outputFileListPaths = (
+				"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-frameworks-${CONFIGURATION}-output-files.xcfilelist",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-frameworks.sh\"\n";
+			showEnvVarsInLog = 0;
+		};
+		60493BEA2D10E7E4002853A0 /* [CP] Copy Pods Resources */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputFileListPaths = (
+				"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-resources-${CONFIGURATION}-input-files.xcfilelist",
+			);
+			name = "[CP] Copy Pods Resources";
+			outputFileListPaths = (
+				"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-resources-${CONFIGURATION}-output-files.xcfilelist",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-resources.sh\"\n";
+			showEnvVarsInLog = 0;
+		};
 		C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;
@@ -331,6 +452,16 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		60493BDD2D10E7E4002853A0 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				60493BDE2D10E7E4002853A0 /* NativeModule.mm in Sources */,
+				60493BDF2D10E7E4002853A0 /* AppDelegate.mm in Sources */,
+				60493BE02D10E7E4002853A0 /* main.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 /* End PBXSourcesBuildPhase section */
 
 /* Begin XCBuildConfiguration section */
@@ -390,6 +521,62 @@
 			};
 			name = Release;
 		};
+		60493BEC2D10E7E4002853A0 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 3B4392A12AC88292D35C810B /* Pods-example.debug.xcconfig */;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				CLANG_ENABLE_MODULES = YES;
+				CODE_SIGN_ENTITLEMENTS = example/example.entitlements;
+				CURRENT_PROJECT_VERSION = 1;
+				ENABLE_BITCODE = NO;
+				INFOPLIST_FILE = example/Info.plist;
+				IPHONEOS_DEPLOYMENT_TARGET = 15.1;
+				LD_RUNPATH_SEARCH_PATHS = (
+					"$(inherited)",
+					"@executable_path/Frameworks",
+				);
+				MARKETING_VERSION = 1.0;
+				OTHER_LDFLAGS = (
+					"$(inherited)",
+					"-ObjC",
+					"-lc++",
+				);
+				PRODUCT_BUNDLE_IDENTIFIER = "com.wix.detox-example";
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+				SWIFT_VERSION = 5.0;
+				VERSIONING_SYSTEM = "apple-generic";
+			};
+			name = Debug;
+		};
+		60493BED2D10E7E4002853A0 /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 5709B34CF0A7D63546082F79 /* Pods-example.release.xcconfig */;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				CLANG_ENABLE_MODULES = YES;
+				CODE_SIGN_ENTITLEMENTS = example/example.entitlements;
+				CURRENT_PROJECT_VERSION = 1;
+				INFOPLIST_FILE = example/Info.plist;
+				IPHONEOS_DEPLOYMENT_TARGET = 15.1;
+				LD_RUNPATH_SEARCH_PATHS = (
+					"$(inherited)",
+					"@executable_path/Frameworks",
+				);
+				MARKETING_VERSION = 1.0;
+				OTHER_LDFLAGS = (
+					"$(inherited)",
+					"-ObjC",
+					"-lc++",
+				);
+				PRODUCT_BUNDLE_IDENTIFIER = "com.wix.detox-example";
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SWIFT_VERSION = 5.0;
+				VERSIONING_SYSTEM = "apple-generic";
+			};
+			name = Release;
+		};
 		83CBBA201A601CBA00E9B192 /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
@@ -548,6 +735,15 @@
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Release;
 		};
+		60493BEB2D10E7E4002853A0 /* Build configuration list for PBXNativeTarget "example-ci" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				60493BEC2D10E7E4002853A0 /* Debug */,
+				60493BED2D10E7E4002853A0 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
 		83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "example" */ = {
 			isa = XCConfigurationList;
 			buildConfigurations = (

From d7f7f9762e4b55a6554d14326dc21c02ccfb1cd4 Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Tue, 17 Dec 2024 01:48:01 +0200
Subject: [PATCH 19/51] test(ios): refactor Podfile.

---
 detox/test/ios/Podfile | 84 ++++++++++++++++++++++++------------------
 1 file changed, 48 insertions(+), 36 deletions(-)

diff --git a/detox/test/ios/Podfile b/detox/test/ios/Podfile
index 8f849b7800..1f6f217d59 100644
--- a/detox/test/ios/Podfile
+++ b/detox/test/ios/Podfile
@@ -1,25 +1,53 @@
 # Set RCT_NEW_ARCH_ENABLED to '0' if not defined
 ENV['RCT_NEW_ARCH_ENABLED'] = '0' unless ENV['RCT_NEW_ARCH_ENABLED']
 
-if ENV["REACT_NATIVE_VERSION"] && ENV["REACT_NATIVE_VERSION"].match(/0.71.*/)
-  require_relative '../node_modules/react-native/scripts/react_native_pods'
-  require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
-  require_relative '../node_modules/react-native-permissions/scripts/setup'
-else
-  # Resolve react_native_pods.rb with node to allow for hoisting
-  require Pod::Executable.execute_command('node', ['-p',
-    'require.resolve(
-      "react-native/scripts/react_native_pods.rb",
-      {paths: [process.argv[1]]},
-    )', __dir__]).strip
+def load_react_native_config
+  if ENV["REACT_NATIVE_VERSION"] && ENV["REACT_NATIVE_VERSION"].match(/0.71.*/)
+    require_relative '../node_modules/react-native/scripts/react_native_pods'
+    require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
+    require_relative '../node_modules/react-native-permissions/scripts/setup'
+  else
+    # Resolve react_native_pods.rb with node to allow for hoisting
+    require Pod::Executable.execute_command('node', ['-p',
+      'require.resolve(
+        "react-native/scripts/react_native_pods.rb",
+        {paths: [process.argv[1]]},
+      )', __dir__]).strip
 
-  require Pod::Executable.execute_command('node', ['-p',
-    'require.resolve(
-      "react-native-permissions/scripts/setup.rb",
-      {paths: [process.argv[1]]},
-    )', __dir__]).strip
+    require Pod::Executable.execute_command('node', ['-p',
+      'require.resolve(
+        "react-native-permissions/scripts/setup.rb",
+        {paths: [process.argv[1]]},
+      )', __dir__]).strip
+  end
+end
+
+def configure_target(target_name)
+  target target_name do
+    config = use_native_modules!
+
+    use_react_native!(
+      :path => config[:reactNativePath],
+      :app_path => "#{Pod::Config.instance.installation_root}/.."
+    )
+
+    # Add React Native Slider
+    pod 'react-native-slider', :path => '../node_modules/@react-native-community/slider'
+
+    post_install do |installer|
+      react_native_post_install(
+        installer,
+        config[:reactNativePath],
+        :mac_catalyst_enabled => false,
+        # :ccache_enabled => true
+      )
+    end
+  end
 end
 
+# Load configurations
+load_react_native_config
+
 platform :ios, min_ios_version_supported
 prepare_react_native_project!
 
@@ -46,29 +74,13 @@ setup_permissions([
   'StoreKit',
 ])
 
+# Configure frameworks linkage
 linkage = ENV['USE_FRAMEWORKS']
 if linkage != nil
   Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green
   use_frameworks! :linkage => linkage.to_sym
 end
 
-target 'example' do
-  config = use_native_modules!
-
-  use_react_native!(
-    :path => config[:reactNativePath],
-    :app_path => "#{Pod::Config.instance.installation_root}/.."
-  )
-
-  # Add React Native Slider
-  pod 'react-native-slider', :path => '../node_modules/@react-native-community/slider'
-
-  post_install do |installer|
-    react_native_post_install(
-      installer,
-      config[:reactNativePath],
-      :mac_catalyst_enabled => false,
-      # :ccache_enabled => true
-    )
-  end
-end
+# Configure targets
+configure_target('example')
+configure_target('example-ci')

From 23c726a284004d938ddb40cee84c7cd048554976 Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Tue, 17 Dec 2024 02:07:01 +0200
Subject: [PATCH 20/51] chore(deps): update DetoxSync with new-arch sync
 support.

---
 detox/ios/DetoxSync | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/detox/ios/DetoxSync b/detox/ios/DetoxSync
index f69efdbd95..0567db9243 160000
--- a/detox/ios/DetoxSync
+++ b/detox/ios/DetoxSync
@@ -1 +1 @@
-Subproject commit f69efdbd9580f3c336ca5c3caed2926afb651793
+Subproject commit 0567db92434d1fc0232748f0cf2da55228fe699a

From 5492e6aff608227b9cdb4153fcd886a026d490c7 Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Tue, 17 Dec 2024 02:07:36 +0200
Subject: [PATCH 21/51] chore(ios): add manual test env vars for debugging.

---
 .../xcshareddata/xcschemes/example.xcscheme     | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/detox/test/ios/example.xcodeproj/xcshareddata/xcschemes/example.xcscheme b/detox/test/ios/example.xcodeproj/xcshareddata/xcschemes/example.xcscheme
index ba996697dc..1c65e14823 100644
--- a/detox/test/ios/example.xcodeproj/xcshareddata/xcschemes/example.xcscheme
+++ b/detox/test/ios/example.xcodeproj/xcshareddata/xcschemes/example.xcscheme
@@ -134,6 +134,23 @@
             isEnabled = "NO">
          </CommandLineArgument>
       </CommandLineArguments>
+      <EnvironmentVariables>
+         <EnvironmentVariable
+            key = "detoxServer"
+            value = "ws://localhost:8099"
+            isEnabled = "NO">
+         </EnvironmentVariable>
+         <EnvironmentVariable
+            key = "detoxSessionId"
+            value = "com.wix.detox-example"
+            isEnabled = "NO">
+         </EnvironmentVariable>
+         <EnvironmentVariable
+            key = "detoxDisableHierarchyDump"
+            value = "YES"
+            isEnabled = "NO">
+         </EnvironmentVariable>
+      </EnvironmentVariables>
    </LaunchAction>
    <ProfileAction
       buildConfiguration = "Release"

From bdcddea4b207e7506b9ffaad9d7d260560866d20 Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Tue, 17 Dec 2024 02:25:57 +0200
Subject: [PATCH 22/51] test(ios): fix test-app Podfile.

---
 detox/test/ios/Podfile | 20 +++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/detox/test/ios/Podfile b/detox/test/ios/Podfile
index 1f6f217d59..1371970962 100644
--- a/detox/test/ios/Podfile
+++ b/detox/test/ios/Podfile
@@ -22,6 +22,7 @@ def load_react_native_config
   end
 end
 
+# Configure target with common settings
 def configure_target(target_name)
   target target_name do
     config = use_native_modules!
@@ -33,15 +34,6 @@ def configure_target(target_name)
 
     # Add React Native Slider
     pod 'react-native-slider', :path => '../node_modules/@react-native-community/slider'
-
-    post_install do |installer|
-      react_native_post_install(
-        installer,
-        config[:reactNativePath],
-        :mac_catalyst_enabled => false,
-        # :ccache_enabled => true
-      )
-    end
   end
 end
 
@@ -84,3 +76,13 @@ end
 # Configure targets
 configure_target('example')
 configure_target('example-ci')
+
+# Post install hook (moved outside of targets)
+post_install do |installer|
+  react_native_post_install(
+    installer,
+    config[:reactNativePath],
+    :mac_catalyst_enabled => false,
+    # :ccache_enabled => true
+  )
+end

From 6c280b8bb02db7a6615c49da05c6bdb09b16e7bd Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Tue, 17 Dec 2024 09:01:17 +0200
Subject: [PATCH 23/51] test(ios): fix test-app Podfile.

---
 detox/test/ios/Podfile                        | 82 ++++++++-----------
 .../ios/example.xcodeproj/project.pbxproj     | 48 +++++++----
 2 files changed, 66 insertions(+), 64 deletions(-)

diff --git a/detox/test/ios/Podfile b/detox/test/ios/Podfile
index 1371970962..cacd6701d5 100644
--- a/detox/test/ios/Podfile
+++ b/detox/test/ios/Podfile
@@ -1,49 +1,29 @@
-# Set RCT_NEW_ARCH_ENABLED to '0' if not defined
-ENV['RCT_NEW_ARCH_ENABLED'] = '0' unless ENV['RCT_NEW_ARCH_ENABLED']
+ENV['RCT_NEW_ARCH_ENABLED'] = '0'
 
-def load_react_native_config
-  if ENV["REACT_NATIVE_VERSION"] && ENV["REACT_NATIVE_VERSION"].match(/0.71.*/)
+if ENV["REACT_NATIVE_VERSION"] && ENV["REACT_NATIVE_VERSION"].match(/0.(70|71).*/)
     require_relative '../node_modules/react-native/scripts/react_native_pods'
     require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
     require_relative '../node_modules/react-native-permissions/scripts/setup'
-  else
+else
     # Resolve react_native_pods.rb with node to allow for hoisting
-    require Pod::Executable.execute_command('node', ['-p',
-      'require.resolve(
-        "react-native/scripts/react_native_pods.rb",
-        {paths: [process.argv[1]]},
-      )', __dir__]).strip
+    def node_require(script)
+      # Resolve script with node to allow for hoisting
+      require Pod::Executable.execute_command('node', ['-p',
+        "require.resolve(
+          '#{script}',
+          {paths: [process.argv[1]]},
+        )", __dir__]).strip
+    end
 
-    require Pod::Executable.execute_command('node', ['-p',
-      'require.resolve(
-        "react-native-permissions/scripts/setup.rb",
-        {paths: [process.argv[1]]},
-      )', __dir__]).strip
-  end
+    node_require('react-native/scripts/react_native_pods.rb')
+    node_require('react-native-permissions/scripts/setup.rb')
 end
 
-# Configure target with common settings
-def configure_target(target_name)
-  target target_name do
-    config = use_native_modules!
-
-    use_react_native!(
-      :path => config[:reactNativePath],
-      :app_path => "#{Pod::Config.instance.installation_root}/.."
-    )
-
-    # Add React Native Slider
-    pod 'react-native-slider', :path => '../node_modules/@react-native-community/slider'
-  end
-end
-
-# Load configurations
-load_react_native_config
-
 platform :ios, min_ios_version_supported
-prepare_react_native_project!
 
-# Configure permissions
+install! 'cocoapods', :deterministic_uuids => false
+
+# Comment unwanted permissions
 setup_permissions([
   'AppTrackingTransparency',
   'Bluetooth',
@@ -66,23 +46,31 @@ setup_permissions([
   'StoreKit',
 ])
 
-# Configure frameworks linkage
-linkage = ENV['USE_FRAMEWORKS']
-if linkage != nil
-  Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green
-  use_frameworks! :linkage => linkage.to_sym
+def shared_pods
+    config = use_native_modules!
+
+    use_react_native!(
+      :path => config[:reactNativePath],
+      :app_path => "#{Pod::Config.instance.installation_root}/.."
+    )
+
+    # Shared pods
+    pod 'react-native-slider', :path => '../node_modules/@react-native-community/slider'
 end
 
-# Configure targets
-configure_target('example')
-configure_target('example-ci')
+target 'example' do
+  shared_pods
+end
+
+target 'example-ci' do
+  shared_pods
+end
 
-# Post install hook (moved outside of targets)
 post_install do |installer|
+  config = use_native_modules!
   react_native_post_install(
     installer,
     config[:reactNativePath],
-    :mac_catalyst_enabled => false,
-    # :ccache_enabled => true
+    :mac_catalyst_enabled => false
   )
 end
diff --git a/detox/test/ios/example.xcodeproj/project.pbxproj b/detox/test/ios/example.xcodeproj/project.pbxproj
index d4d24ad8a7..856f9965fe 100644
--- a/detox/test/ios/example.xcodeproj/project.pbxproj
+++ b/detox/test/ios/example.xcodeproj/project.pbxproj
@@ -7,14 +7,14 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
-		0C80B921A6F3F58F76C31292 /* libPods-example.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DCACB8F33CDC322A6C60F78 /* libPods-example.a */; };
+		0C80B921A6F3F58F76C31292 /* BuildFile in Frameworks */ = {isa = PBXBuildFile; };
 		13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; };
 		13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
 		13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
+		213E1077F464B28612297B3E /* libPods-example.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 467D00885FA51E1E9B0E8063 /* libPods-example.a */; };
 		60493BDE2D10E7E4002853A0 /* NativeModule.mm in Sources */ = {isa = PBXBuildFile; fileRef = 609DDBE32D10D45500028574 /* NativeModule.mm */; };
 		60493BDF2D10E7E4002853A0 /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; };
 		60493BE02D10E7E4002853A0 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
-		60493BE32D10E7E4002853A0 /* libPods-example.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DCACB8F33CDC322A6C60F78 /* libPods-example.a */; };
 		60493BE52D10E7E4002853A0 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
 		60493BE62D10E7E4002853A0 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
 		60493BE72D10E7E4002853A0 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */; };
@@ -22,6 +22,7 @@
 		609DDBE42D10D45500028574 /* NativeModule.mm in Sources */ = {isa = PBXBuildFile; fileRef = 609DDBE32D10D45500028574 /* NativeModule.mm */; };
 		81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
 		90CCD0BA1322566EB1285DC2 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */; };
+		CA25A6405AF58BA742F7FD47 /* libPods-example-ci.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1CB0FE045763B5363B2E7054 /* libPods-example-ci.a */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
@@ -50,15 +51,18 @@
 		13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = example/main.m; sourceTree = "<group>"; };
 		13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = PrivacyInfo.xcprivacy; path = example/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
 		19F6CBCC0A4E27FBF8BF4A61 /* libPods-example-exampleTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-example-exampleTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
+		1CB0FE045763B5363B2E7054 /* libPods-example-ci.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-example-ci.a"; sourceTree = BUILT_PRODUCTS_DIR; };
 		3B4392A12AC88292D35C810B /* Pods-example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example.debug.xcconfig"; path = "Target Support Files/Pods-example/Pods-example.debug.xcconfig"; sourceTree = "<group>"; };
+		467D00885FA51E1E9B0E8063 /* libPods-example.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-example.a"; sourceTree = BUILT_PRODUCTS_DIR; };
+		4D1FDAD5197836A927FA2D03 /* Pods-example-ci.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example-ci.debug.xcconfig"; path = "Target Support Files/Pods-example-ci/Pods-example-ci.debug.xcconfig"; sourceTree = "<group>"; };
 		5709B34CF0A7D63546082F79 /* Pods-example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example.release.xcconfig"; path = "Target Support Files/Pods-example/Pods-example.release.xcconfig"; sourceTree = "<group>"; };
 		5B7EB9410499542E8C5724F5 /* Pods-example-exampleTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example-exampleTests.debug.xcconfig"; path = "Target Support Files/Pods-example-exampleTests/Pods-example-exampleTests.debug.xcconfig"; sourceTree = "<group>"; };
-		5DCACB8F33CDC322A6C60F78 /* libPods-example.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-example.a"; sourceTree = BUILT_PRODUCTS_DIR; };
 		60493BD72D10D967002853A0 /* example.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = example.entitlements; path = example/example.entitlements; sourceTree = "<group>"; };
 		60493BEE2D10E7E4002853A0 /* example-ci.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "example-ci.app"; sourceTree = BUILT_PRODUCTS_DIR; };
 		609DDB772D10C20700028574 /* Detox.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Detox.xcodeproj; path = /Users/asafk/Development/Detox/detox/ios/Detox.xcodeproj; sourceTree = "<absolute>"; };
 		609DDBE22D10D45500028574 /* NativeModule.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NativeModule.h; sourceTree = "<group>"; };
 		609DDBE32D10D45500028574 /* NativeModule.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = NativeModule.mm; sourceTree = "<group>"; };
+		80C930B7D5D6C25DA27372A5 /* Pods-example-ci.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example-ci.release.xcconfig"; path = "Target Support Files/Pods-example-ci/Pods-example-ci.release.xcconfig"; sourceTree = "<group>"; };
 		81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = example/LaunchScreen.storyboard; sourceTree = "<group>"; };
 		89C6BE57DB24E9ADA2F236DE /* Pods-example-exampleTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example-exampleTests.release.xcconfig"; path = "Target Support Files/Pods-example-exampleTests/Pods-example-exampleTests.release.xcconfig"; sourceTree = "<group>"; };
 		ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
@@ -70,7 +74,8 @@
 			buildActionMask = 2147483647;
 			files = (
 				609DDB892D10C21800028574 /* Detox.framework in Frameworks */,
-				0C80B921A6F3F58F76C31292 /* libPods-example.a in Frameworks */,
+				0C80B921A6F3F58F76C31292 /* BuildFile in Frameworks */,
+				213E1077F464B28612297B3E /* libPods-example.a in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -78,7 +83,7 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				60493BE32D10E7E4002853A0 /* libPods-example.a in Frameworks */,
+				CA25A6405AF58BA742F7FD47 /* libPods-example-ci.a in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -105,8 +110,9 @@
 			isa = PBXGroup;
 			children = (
 				ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
-				5DCACB8F33CDC322A6C60F78 /* libPods-example.a */,
 				19F6CBCC0A4E27FBF8BF4A61 /* libPods-example-exampleTests.a */,
+				1CB0FE045763B5363B2E7054 /* libPods-example-ci.a */,
+				467D00885FA51E1E9B0E8063 /* libPods-example.a */,
 			);
 			name = Frameworks;
 			sourceTree = "<group>";
@@ -167,6 +173,8 @@
 				5709B34CF0A7D63546082F79 /* Pods-example.release.xcconfig */,
 				5B7EB9410499542E8C5724F5 /* Pods-example-exampleTests.debug.xcconfig */,
 				89C6BE57DB24E9ADA2F236DE /* Pods-example-exampleTests.release.xcconfig */,
+				4D1FDAD5197836A927FA2D03 /* Pods-example-ci.debug.xcconfig */,
+				80C930B7D5D6C25DA27372A5 /* Pods-example-ci.release.xcconfig */,
 			);
 			path = Pods;
 			sourceTree = "<group>";
@@ -343,7 +351,7 @@
 			outputFileListPaths = (
 			);
 			outputPaths = (
-				"$(DERIVED_FILE_DIR)/Pods-example-checkManifestLockResult.txt",
+				"$(DERIVED_FILE_DIR)/Pods-example-ci-checkManifestLockResult.txt",
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
@@ -372,15 +380,15 @@
 			files = (
 			);
 			inputFileListPaths = (
-				"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-frameworks-${CONFIGURATION}-input-files.xcfilelist",
+				"${PODS_ROOT}/Target Support Files/Pods-example-ci/Pods-example-ci-frameworks-${CONFIGURATION}-input-files.xcfilelist",
 			);
 			name = "[CP] Embed Pods Frameworks";
 			outputFileListPaths = (
-				"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-frameworks-${CONFIGURATION}-output-files.xcfilelist",
+				"${PODS_ROOT}/Target Support Files/Pods-example-ci/Pods-example-ci-frameworks-${CONFIGURATION}-output-files.xcfilelist",
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-frameworks.sh\"\n";
+			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-example-ci/Pods-example-ci-frameworks.sh\"\n";
 			showEnvVarsInLog = 0;
 		};
 		60493BEA2D10E7E4002853A0 /* [CP] Copy Pods Resources */ = {
@@ -389,15 +397,15 @@
 			files = (
 			);
 			inputFileListPaths = (
-				"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-resources-${CONFIGURATION}-input-files.xcfilelist",
+				"${PODS_ROOT}/Target Support Files/Pods-example-ci/Pods-example-ci-resources-${CONFIGURATION}-input-files.xcfilelist",
 			);
 			name = "[CP] Copy Pods Resources";
 			outputFileListPaths = (
-				"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-resources-${CONFIGURATION}-output-files.xcfilelist",
+				"${PODS_ROOT}/Target Support Files/Pods-example-ci/Pods-example-ci-resources-${CONFIGURATION}-output-files.xcfilelist",
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-resources.sh\"\n";
+			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-example-ci/Pods-example-ci-resources.sh\"\n";
 			showEnvVarsInLog = 0;
 		};
 		C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */ = {
@@ -523,7 +531,7 @@
 		};
 		60493BEC2D10E7E4002853A0 /* Debug */ = {
 			isa = XCBuildConfiguration;
-			baseConfigurationReference = 3B4392A12AC88292D35C810B /* Pods-example.debug.xcconfig */;
+			baseConfigurationReference = 4D1FDAD5197836A927FA2D03 /* Pods-example-ci.debug.xcconfig */;
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				CLANG_ENABLE_MODULES = YES;
@@ -552,7 +560,7 @@
 		};
 		60493BED2D10E7E4002853A0 /* Release */ = {
 			isa = XCBuildConfiguration;
-			baseConfigurationReference = 5709B34CF0A7D63546082F79 /* Pods-example.release.xcconfig */;
+			baseConfigurationReference = 80C930B7D5D6C25DA27372A5 /* Pods-example-ci.release.xcconfig */;
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				CLANG_ENABLE_MODULES = YES;
@@ -646,7 +654,10 @@
 					"-DFOLLY_CFG_NO_COROUTINES=1",
 					"-DFOLLY_HAVE_CLOCK_GETTIME=1",
 				);
-				OTHER_LDFLAGS = "$(inherited)  ";
+				OTHER_LDFLAGS = (
+					"$(inherited)",
+					" ",
+				);
 				REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
 				SDKROOT = iphoneos;
 				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG";
@@ -715,7 +726,10 @@
 					"-DFOLLY_CFG_NO_COROUTINES=1",
 					"-DFOLLY_HAVE_CLOCK_GETTIME=1",
 				);
-				OTHER_LDFLAGS = "$(inherited)  ";
+				OTHER_LDFLAGS = (
+					"$(inherited)",
+					" ",
+				);
 				REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
 				SDKROOT = iphoneos;
 				USE_HERMES = true;

From bcea8cdc4c71f25ae2de9f75a0900f434fc619b2 Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Tue, 17 Dec 2024 09:22:27 +0200
Subject: [PATCH 24/51] test(ios): update binary path to the non-detox-linked
 app (example-ci).

---
 detox/test/e2e/detox.config.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/detox/test/e2e/detox.config.js b/detox/test/e2e/detox.config.js
index da4ee2381a..aa105e2969 100644
--- a/detox/test/e2e/detox.config.js
+++ b/detox/test/e2e/detox.config.js
@@ -52,7 +52,7 @@ const config = {
     'ios.debug': {
       type: 'ios.app',
       name: 'example',
-      binaryPath: 'ios/build/Build/Products/Debug-iphonesimulator/example.app',
+      binaryPath: 'ios/build/Build/Products/Debug-iphonesimulator/example-ci.app',
       build: 'set -o pipefail && xcodebuild -workspace ios/example.xcworkspace -scheme example-ci -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build -quiet',
       start: 'react-native start',
       bundleId: 'com.wix.detox-example',
@@ -61,7 +61,7 @@ const config = {
     'ios.release': {
       type: 'ios.app',
       name: 'example',
-      binaryPath: 'ios/build/Build/Products/Release-iphonesimulator/example.app',
+      binaryPath: 'ios/build/Build/Products/Release-iphonesimulator/example-ci.app',
       build: 'set -o pipefail && export CODE_SIGNING_REQUIRED=NO && export RCT_NO_LAUNCH_PACKAGER=true && xcodebuild -workspace ios/example.xcworkspace -scheme example-ci -configuration Release -sdk iphonesimulator -derivedDataPath ios/build -quiet',
     },
 

From abca5b943764c3b085f07dc2a0d88a1c19c71ee3 Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Tue, 17 Dec 2024 12:04:08 +0200
Subject: [PATCH 25/51] fix(ios): temporary remove text fix for predicate.

---
 detox/ios/Detox/Invocation/Predicate.swift    |  8 +-
 .../ios/Detox/Utilities/NSObject+DontCrash.m  | 97 +++++--------------
 2 files changed, 28 insertions(+), 77 deletions(-)

diff --git a/detox/ios/Detox/Invocation/Predicate.swift b/detox/ios/Detox/Invocation/Predicate.swift
index ffd19d873c..cd264f5194 100644
--- a/detox/ios/Detox/Invocation/Predicate.swift
+++ b/detox/ios/Detox/Invocation/Predicate.swift
@@ -66,9 +66,7 @@ class Predicate : CustomStringConvertible, CustomDebugStringConvertible {
           return ValuePredicate(kind: kind, modifiers: modifiers, value: label, requiresAccessibilityElement: true, isRegex: isRegex)
         } else {
           //Will crash if RN app and neither class exists
-          let RCTTextViewClass : AnyClass =
-            NSClassFromString("RCTParagraphComponentView") ??
-            NSClassFromString("RCTText") ?? NSClassFromString("RCTTextView")!
+          let RCTTextViewClass : AnyClass = NSClassFromString("RCTText") ?? NSClassFromString("RCTTextView")!
 
           let descendantPredicate = DescendantPredicate(predicate: AndCompoundPredicate(predicates: [
             try KindOfPredicate(kind: Kind.type, modifiers: [], className: NSStringFromClass(RCTTextViewClass)),
@@ -91,9 +89,7 @@ class Predicate : CustomStringConvertible, CustomDebugStringConvertible {
 
         if ReactNativeSupport.isReactNativeApp == true {
           //Will crash if RN app and neither class exists
-          let RCTTextViewClass : AnyClass =
-            NSClassFromString("RCTParagraphComponentView") ??
-            NSClassFromString("RCTText") ?? NSClassFromString("RCTTextView")!
+          let RCTTextViewClass : AnyClass = NSClassFromString("RCTText") ?? NSClassFromString("RCTTextView")!
           orPredicates.append(try KindOfPredicate(kind: Kind.type, modifiers: [], className: NSStringFromClass(RCTTextViewClass)))
         }
 
diff --git a/detox/ios/Detox/Utilities/NSObject+DontCrash.m b/detox/ios/Detox/Utilities/NSObject+DontCrash.m
index f880071c2d..eb72d4169c 100644
--- a/detox/ios/Detox/Utilities/NSObject+DontCrash.m
+++ b/detox/ios/Detox/Utilities/NSObject+DontCrash.m
@@ -7,81 +7,36 @@
 
 #import "NSObject+DontCrash.h"
 
-@interface NSObject (DontCrashPrivate)
-+ (Class)dtx_classForName:(NSString *)className;
-- (nullable NSString *)dtx_extractTextFromRCTComponent;
-@end
-
 @implementation NSObject (DontCrash)
 
-#pragma mark - Public Methods
-
-- (id)_dtx_text {
-    if ([self respondsToSelector:@selector(text)]) {
-        return [(UITextView *)self text];
-    }
-
-    NSString *reactText = [self dtx_extractTextFromRCTComponent];
-    if (reactText) {
-        return reactText;
-    }
-
-    return nil;
-}
-
-- (id)_dtx_placeholder {
-    if ([self respondsToSelector:@selector(placeholder)]) {
-        return [(UITextField *)self placeholder];
-    }
-    return nil;
-}
-
-@end
-
-@implementation NSObject (DontCrashPrivate)
-
-#pragma mark - Private Methods
-
-+ (Class)dtx_classForName:(NSString *)className {
-    static NSMutableDictionary<NSString *, Class> *classCache;
-    static dispatch_once_t onceToken;
-
-    dispatch_once(&onceToken, ^{
-        classCache = [NSMutableDictionary dictionary];
-    });
-
-    Class cachedClass = classCache[className];
-    if (!cachedClass) {
-        cachedClass = NSClassFromString(className);
-        if (cachedClass) {
-            classCache[className] = cachedClass;
-        }
-    }
-
-    return cachedClass;
+- (id)_dtx_text
+{
+	if([self respondsToSelector:@selector(text)])
+	{
+		return [(UITextView*)self text];
+	}
+	
+	static Class RCTTextView;
+	static dispatch_once_t onceToken;
+	dispatch_once(&onceToken, ^{
+		RCTTextView = NSClassFromString(@"RCTTextView");
+	});
+	if(RCTTextView != nil && [self isKindOfClass:RCTTextView])
+	{
+		return [(NSTextStorage*)[self valueForKey:@"textStorage"] string];
+	}
+	
+	return nil;
 }
 
-- (nullable NSString *)dtx_extractTextFromRCTComponent {
-    static Class RCTTextViewClass;
-    static Class RCTParagraphComponentViewClass;
-    static dispatch_once_t onceToken;
-
-    dispatch_once(&onceToken, ^{
-        RCTTextViewClass = [self.class dtx_classForName:@"RCTTextView"];
-        RCTParagraphComponentViewClass = [self.class dtx_classForName:@"RCTParagraphComponentView"];
-    });
-
-    if (RCTTextViewClass && [self isKindOfClass:RCTTextViewClass]) {
-        NSTextStorage *textStorage = [self valueForKey:@"textStorage"];
-        return [textStorage string];
-    }
-
-    if (RCTParagraphComponentViewClass && [self isKindOfClass:RCTParagraphComponentViewClass]) {
-        NSAttributedString *attributedText = [self valueForKey:@"attributedText"];
-        return [attributedText string];
-    }
-
-    return nil;
+- (id)_dtx_placeholder
+{
+	if([self respondsToSelector:@selector(placeholder)])
+	{
+		return [(UITextField*)self placeholder];
+	}
+	
+	return nil;
 }
 
 @end

From 2fd21b06975912d0c8d08da251456107ee884883 Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Wed, 18 Dec 2024 09:00:10 +0200
Subject: [PATCH 26/51] fix(ios): support new `RCTParagraphComponentView`
 component.

---
 detox/ios/Detox/Invocation/Predicate.swift    | 56 ++++++++++++-----
 .../ios/Detox/Utilities/NSObject+DontCrash.m  | 60 ++++++++++++-------
 2 files changed, 78 insertions(+), 38 deletions(-)

diff --git a/detox/ios/Detox/Invocation/Predicate.swift b/detox/ios/Detox/Invocation/Predicate.swift
index cd264f5194..3dd18f7bd9 100644
--- a/detox/ios/Detox/Invocation/Predicate.swift
+++ b/detox/ios/Detox/Invocation/Predicate.swift
@@ -65,20 +65,32 @@ class Predicate : CustomStringConvertible, CustomDebugStringConvertible {
         if ReactNativeSupport.isReactNativeApp == false {
           return ValuePredicate(kind: kind, modifiers: modifiers, value: label, requiresAccessibilityElement: true, isRegex: isRegex)
         } else {
-          //Will crash if RN app and neither class exists
-          let RCTTextViewClass : AnyClass = NSClassFromString("RCTText") ?? NSClassFromString("RCTTextView")!
-
-          let descendantPredicate = DescendantPredicate(predicate: AndCompoundPredicate(predicates: [
-            try KindOfPredicate(kind: Kind.type, modifiers: [], className: NSStringFromClass(RCTTextViewClass)),
-            ValuePredicate(kind: kind, modifiers: modifiers, value: label, requiresAccessibilityElement: true, isRegex: isRegex)
-          ], modifiers: []), modifiers: [Modifier.not])
-          descendantPredicate.hidden = true
-
-          return AndCompoundPredicate(predicates: [
-            ValuePredicate(kind: kind, modifiers: modifiers, value: label, requiresAccessibilityElement: true, isRegex: isRegex),
-            descendantPredicate
-          ], modifiers: [])
+            let possibleRNClasses: [AnyClass] = [
+                NSClassFromString("RCTParagraphComponentView"),
+                NSClassFromString("RCTText"),
+                NSClassFromString("RCTTextView")
+            ].compactMap { $0 }
+
+            guard !possibleRNClasses.isEmpty else {
+                fatalError("No React Native text component classes found")
+            }
+
+            let typePredicates = possibleRNClasses.map { rnClass in
+                try! KindOfPredicate(kind: Kind.type, modifiers: [], className: NSStringFromClass(rnClass))
+            }
+
+            let descendantPredicate = DescendantPredicate(predicate: AndCompoundPredicate(predicates: [
+                OrCompoundPredicate(predicates: typePredicates, modifiers: []),
+                ValuePredicate(kind: kind, modifiers: modifiers, value: label, requiresAccessibilityElement: true, isRegex: isRegex)
+            ], modifiers: []), modifiers: [Modifier.not])
+            descendantPredicate.hidden = true
+
+            return AndCompoundPredicate(predicates: [
+                ValuePredicate(kind: kind, modifiers: modifiers, value: label, requiresAccessibilityElement: true, isRegex: isRegex),
+                descendantPredicate
+            ], modifiers: [])
         }
+
       case Kind.text:
         let text = dictionaryRepresentation[Keys.value] as! String
         var orPredicates = [
@@ -88,9 +100,21 @@ class Predicate : CustomStringConvertible, CustomDebugStringConvertible {
         ]
 
         if ReactNativeSupport.isReactNativeApp == true {
-          //Will crash if RN app and neither class exists
-          let RCTTextViewClass : AnyClass = NSClassFromString("RCTText") ?? NSClassFromString("RCTTextView")!
-          orPredicates.append(try KindOfPredicate(kind: Kind.type, modifiers: [], className: NSStringFromClass(RCTTextViewClass)))
+            let possibleRNClasses: [AnyClass] = [
+                NSClassFromString("RCTParagraphComponentView"),
+                NSClassFromString("RCTText"),
+                NSClassFromString("RCTTextView")
+            ].compactMap { $0 }
+
+            guard !possibleRNClasses.isEmpty else {
+                fatalError("No React Native text component classes found")
+            }
+
+            possibleRNClasses.forEach { rnClass in
+                let predicate = try! KindOfPredicate(kind: Kind.type, modifiers: [], className: NSStringFromClass(rnClass))
+
+                orPredicates.append(predicate)
+            }
         }
 
         let orCompoundPredicate = OrCompoundPredicate(predicates: orPredicates, modifiers: [])
diff --git a/detox/ios/Detox/Utilities/NSObject+DontCrash.m b/detox/ios/Detox/Utilities/NSObject+DontCrash.m
index eb72d4169c..d78f254cfc 100644
--- a/detox/ios/Detox/Utilities/NSObject+DontCrash.m
+++ b/detox/ios/Detox/Utilities/NSObject+DontCrash.m
@@ -11,32 +11,48 @@ @implementation NSObject (DontCrash)
 
 - (id)_dtx_text
 {
-	if([self respondsToSelector:@selector(text)])
-	{
-		return [(UITextView*)self text];
-	}
-	
-	static Class RCTTextView;
-	static dispatch_once_t onceToken;
-	dispatch_once(&onceToken, ^{
-		RCTTextView = NSClassFromString(@"RCTTextView");
-	});
-	if(RCTTextView != nil && [self isKindOfClass:RCTTextView])
-	{
-		return [(NSTextStorage*)[self valueForKey:@"textStorage"] string];
-	}
-	
-	return nil;
+    if([self respondsToSelector:@selector(text)])
+    {
+        return [(UITextView*)self text];
+    }
+
+    static Class RCTParagraphComponentViewClass;
+    static Class RCTTextClass;
+    static Class RCTTextViewClass;
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+        RCTParagraphComponentViewClass = NSClassFromString(@"RCTParagraphComponentView");
+        RCTTextClass = NSClassFromString(@"RCTText");
+        RCTTextViewClass = NSClassFromString(@"RCTTextView");
+    });
+
+    if(RCTParagraphComponentViewClass != nil && [self isKindOfClass:RCTParagraphComponentViewClass])
+    {
+        NSAttributedString *attributedText = [self valueForKey:@"attributedText"];
+        return [attributedText string];
+    }
+
+    if(RCTTextClass != nil && [self isKindOfClass:RCTTextClass])
+    {
+        return [(NSTextStorage*)[self valueForKey:@"textStorage"] string];
+    }
+
+    if(RCTTextViewClass != nil && [self isKindOfClass:RCTTextViewClass])
+    {
+        return [(NSTextStorage*)[self valueForKey:@"textStorage"] string];
+    }
+
+    return nil;
 }
 
 - (id)_dtx_placeholder
 {
-	if([self respondsToSelector:@selector(placeholder)])
-	{
-		return [(UITextField*)self placeholder];
-	}
-	
-	return nil;
+    if([self respondsToSelector:@selector(placeholder)])
+    {
+        return [(UITextField*)self placeholder];
+    }
+
+    return nil;
 }
 
 @end

From 824c053febb68b5f419123d9b1d932d8cd7bf363 Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Sun, 22 Dec 2024 17:42:13 +0200
Subject: [PATCH 27/51] test: enable new arch from the Podfile.

---
 detox/test/ios/Podfile                           |  2 +-
 detox/test/ios/example.xcodeproj/project.pbxproj | 14 ++++----------
 2 files changed, 5 insertions(+), 11 deletions(-)

diff --git a/detox/test/ios/Podfile b/detox/test/ios/Podfile
index cacd6701d5..bb5256f319 100644
--- a/detox/test/ios/Podfile
+++ b/detox/test/ios/Podfile
@@ -1,4 +1,4 @@
-ENV['RCT_NEW_ARCH_ENABLED'] = '0'
+ENV['RCT_NEW_ARCH_ENABLED'] = ENV['RCT_NEW_ARCH_ENABLED'] || 0
 
 if ENV["REACT_NATIVE_VERSION"] && ENV["REACT_NATIVE_VERSION"].match(/0.(70|71).*/)
     require_relative '../node_modules/react-native/scripts/react_native_pods'
diff --git a/detox/test/ios/example.xcodeproj/project.pbxproj b/detox/test/ios/example.xcodeproj/project.pbxproj
index 856f9965fe..01f8a263ec 100644
--- a/detox/test/ios/example.xcodeproj/project.pbxproj
+++ b/detox/test/ios/example.xcodeproj/project.pbxproj
@@ -7,7 +7,7 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
-		0C80B921A6F3F58F76C31292 /* BuildFile in Frameworks */ = {isa = PBXBuildFile; };
+		0C80B921A6F3F58F76C31292 /* (null) in Frameworks */ = {isa = PBXBuildFile; };
 		13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; };
 		13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
 		13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
@@ -74,7 +74,7 @@
 			buildActionMask = 2147483647;
 			files = (
 				609DDB892D10C21800028574 /* Detox.framework in Frameworks */,
-				0C80B921A6F3F58F76C31292 /* BuildFile in Frameworks */,
+				0C80B921A6F3F58F76C31292 /* (null) in Frameworks */,
 				213E1077F464B28612297B3E /* libPods-example.a in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -654,10 +654,7 @@
 					"-DFOLLY_CFG_NO_COROUTINES=1",
 					"-DFOLLY_HAVE_CLOCK_GETTIME=1",
 				);
-				OTHER_LDFLAGS = (
-					"$(inherited)",
-					" ",
-				);
+				OTHER_LDFLAGS = "$(inherited)  ";
 				REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
 				SDKROOT = iphoneos;
 				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG";
@@ -726,10 +723,7 @@
 					"-DFOLLY_CFG_NO_COROUTINES=1",
 					"-DFOLLY_HAVE_CLOCK_GETTIME=1",
 				);
-				OTHER_LDFLAGS = (
-					"$(inherited)",
-					" ",
-				);
+				OTHER_LDFLAGS = "$(inherited)  ";
 				REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
 				SDKROOT = iphoneos;
 				USE_HERMES = true;

From e5f012734e13e8039e124e90e3bf4f9412d3d97b Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Sun, 22 Dec 2024 17:47:46 +0200
Subject: [PATCH 28/51] test(RN .76): update view-hierarchy snapshot tests.

---
 .../assets/view-hierarchy-web-view.76.ios.txt | 65 +++++++++++++++++++
 ...ierarchy-with-test-id-injection.76.ios.txt | 24 +++++++
 ...archy-without-test-id-injection.76.ios.txt | 24 +++++++
 3 files changed, 113 insertions(+)
 create mode 100644 detox/test/e2e/assets/view-hierarchy-web-view.76.ios.txt
 create mode 100644 detox/test/e2e/assets/view-hierarchy-with-test-id-injection.76.ios.txt
 create mode 100644 detox/test/e2e/assets/view-hierarchy-without-test-id-injection.76.ios.txt

diff --git a/detox/test/e2e/assets/view-hierarchy-web-view.76.ios.txt b/detox/test/e2e/assets/view-hierarchy-web-view.76.ios.txt
new file mode 100644
index 0000000000..135ffe0a28
--- /dev/null
+++ b/detox/test/e2e/assets/view-hierarchy-web-view.76.ios.txt
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ViewHierarchy>
+ <UIWindow alpha="1.0" class="UIWindow" focused="false" height="<number>" id="detox_temp_" visibility="visible" width="<number>">
+  <UITransitionView alpha="1.0" class="UITransitionView" focused="false" height="<number>" id="detox_temp_0" visibility="visible" width="<number>" x="<number>" y="<number>">
+   <UIDropShadowView alpha="1.0" class="UIDropShadowView" focused="false" height="<number>" id="detox_temp_0_0" visibility="visible" width="<number>" x="<number>" y="<number>">
+    <RCTRootView alpha="1.0" class="RCTRootView" focused="false" height="<number>" id="detox_temp_0_0_0" visibility="visible" width="<number>" x="<number>" y="<number>">
+     <RCTRootContentView alpha="1.0" class="RCTRootContentView" focused="false" height="<number>" label="Show 2nd webview Show 3rd webview Vertical scroll bar, 4 pages Horizontal scroll bar, 1 page" visibility="visible" width="<number>" x="<number>" y="<number>">
+      <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" label="Show 2nd webview Show 3rd webview Vertical scroll bar, 4 pages Horizontal scroll bar, 1 page" visibility="visible" width="<number>" x="<number>" y="<number>">
+       <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" label="Show 2nd webview Show 3rd webview Vertical scroll bar, 4 pages Horizontal scroll bar, 1 page" visibility="visible" width="<number>" x="<number>" y="<number>">
+        <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" label="Show 2nd webview Show 3rd webview" visibility="visible" width="<number>" x="<number>" y="<number>">
+         <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" label="Show 2nd webview" visibility="visible" width="<number>" x="<number>" y="<number>">
+          <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" id="toggle2ndWebviewButton" label="Show 2nd webview" visibility="visible" width="<number>" x="<number>" y="<number>">
+           <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" label="Show 2nd webview" visibility="visible" width="<number>" x="<number>" y="<number>">
+            <RCTTextView alpha="1.0" class="RCTTextView" focused="false" height="<number>" label="Show 2nd webview" visibility="visible" width="<number>" x="<number>" y="<number>" />
+           </RCTView>
+          </RCTView>
+         </RCTView>
+         <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" label="Show 3rd webview" visibility="visible" width="<number>" x="<number>" y="<number>">
+          <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" id="toggle3rdWebviewButton" label="Show 3rd webview" visibility="visible" width="<number>" x="<number>" y="<number>">
+           <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" label="Show 3rd webview" visibility="visible" width="<number>" x="<number>" y="<number>">
+            <RCTTextView alpha="1.0" class="RCTTextView" focused="false" height="<number>" label="Show 3rd webview" visibility="visible" width="<number>" x="<number>" y="<number>" />
+           </RCTView>
+          </RCTView>
+         </RCTView>
+        </RCTView>
+        <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" label="Vertical scroll bar, 4 pages Horizontal scroll bar, 1 page" visibility="visible" width="<number>" x="<number>" y="<number>">
+         <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" label="Vertical scroll bar, 4 pages Horizontal scroll bar, 1 page" visibility="visible" width="<number>" x="<number>" y="<number>">
+          <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" label="Vertical scroll bar, 4 pages Horizontal scroll bar, 1 page" visibility="visible" width="<number>" x="<number>" y="<number>">
+           <RNCWebViewImpl alpha="1.0" class="RNCWebViewImpl" focused="false" height="<number>" id="webViewFormWithScrolling" label="Vertical scroll bar, 4 pages Horizontal scroll bar, 1 page" visibility="visible" width="<number>" x="<number>" y="<number>">
+            <RNCWKWebView alpha="1.0" class="RNCWKWebView" focused="false" height="<number>" visibility="visible" width="<number>" x="<number>" y="<number>">
+            	<![CDATA[<html xmlns="http://www.w3.org/1999/xhtml">
+    <body>
+        <h1 id="pageHeadline" aria-label="first-webview">First Webview</h1>
+        <h2>Form</h2>
+        <form>
+            <label for="fname">Your name:</label><br />
+            <input type="text" id="fname" name="fname" maxlength="<number>" /><br />
+            <input type="submit" id="submit" value="Submit" onclick="document.getElementById('resultFname').innerHTML = document.getElementById('fname').value; return false;" />
+        </form>
+
+        <h2>Form Results</h2>
+        <p>Your first name is: <span id="resultFname">No input yet</span></p>
+
+        <h2>Content Editable</h2>
+        <div id="contentEditable" class="contentEditable" contenteditable="true">Name: </div>
+
+        <h2>Text and link</h2>
+        <p>Some text and a <a id="w3link" href="https://www.w3schools.com">link</a>.</p>
+        <p id="bottomParagraph" class="specialParagraph">This is a bottom paragraph with class.</p>
+    
+
+</body></html>]]>
+            </RNCWKWebView>
+           </RNCWebViewImpl>
+          </RCTView>
+         </RCTView>
+        </RCTView>
+       </RCTView>
+      </RCTView>
+     </RCTRootContentView>
+    </RCTRootView>
+   </UIDropShadowView>
+  </UITransitionView>
+ </UIWindow>
+</ViewHierarchy>
\ No newline at end of file
diff --git a/detox/test/e2e/assets/view-hierarchy-with-test-id-injection.76.ios.txt b/detox/test/e2e/assets/view-hierarchy-with-test-id-injection.76.ios.txt
new file mode 100644
index 0000000000..678cc758d9
--- /dev/null
+++ b/detox/test/e2e/assets/view-hierarchy-with-test-id-injection.76.ios.txt
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ViewHierarchy>
+ <UIWindow alpha="1.0" class="UIWindow" focused="false" height="<number>" id="detox_temp_" visibility="visible" width="<number>">
+  <UITransitionView alpha="1.0" class="UITransitionView" focused="false" height="<number>" id="detox_temp_0" visibility="visible" width="<number>" x="<number>" y="<number>">
+   <UIDropShadowView alpha="1.0" class="UIDropShadowView" focused="false" height="<number>" id="detox_temp_0_0" visibility="visible" width="<number>" x="<number>" y="<number>">
+    <RCTRootView alpha="1.0" class="RCTRootView" focused="false" height="<number>" id="detox_temp_0_0_0" visibility="visible" width="<number>" x="<number>" y="<number>">
+     <RCTRootContentView alpha="1.0" class="RCTRootContentView" focused="false" height="<number>" id="detox_temp_0_0_0_0" label="Welcome Say Hello Say World" visibility="visible" width="<number>" x="<number>" y="<number>">
+      <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" id="detox_temp_0_0_0_0_0" label="Welcome Say Hello Say World" visibility="visible" width="<number>" x="<number>" y="<number>">
+       <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" id="detox_temp_0_0_0_0_0_0" label="Welcome Say Hello Say World" visibility="visible" width="<number>" x="<number>" y="<number>">
+        <RCTTextView alpha="1.0" class="RCTTextView" focused="false" height="<number>" id="detox_temp_0_0_0_0_0_0_0" label="Welcome" visibility="visible" width="<number>" x="<number>" y="<number>" />
+        <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" id="detox_temp_0_0_0_0_0_0_1" label="Say Hello" visibility="visible" width="<number>" x="<number>" y="<number>">
+         <RCTTextView alpha="1.0" class="RCTTextView" focused="false" height="<number>" id="detox_temp_0_0_0_0_0_0_1_0" label="Say Hello" visibility="visible" width="<number>" x="<number>" y="<number>" />
+        </RCTView>
+        <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" id="detox_temp_0_0_0_0_0_0_2" label="Say World" visibility="visible" width="<number>" x="<number>" y="<number>">
+         <RCTTextView alpha="1.0" class="RCTTextView" focused="false" height="<number>" id="detox_temp_0_0_0_0_0_0_2_0" label="Say World" visibility="visible" width="<number>" x="<number>" y="<number>" />
+        </RCTView>
+       </RCTView>
+      </RCTView>
+     </RCTRootContentView>
+    </RCTRootView>
+   </UIDropShadowView>
+  </UITransitionView>
+ </UIWindow>
+</ViewHierarchy>
\ No newline at end of file
diff --git a/detox/test/e2e/assets/view-hierarchy-without-test-id-injection.76.ios.txt b/detox/test/e2e/assets/view-hierarchy-without-test-id-injection.76.ios.txt
new file mode 100644
index 0000000000..03777012f2
--- /dev/null
+++ b/detox/test/e2e/assets/view-hierarchy-without-test-id-injection.76.ios.txt
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ViewHierarchy>
+ <UIWindow alpha="1.0" class="UIWindow" focused="false" height="<number>" visibility="visible" width="<number>">
+  <UITransitionView alpha="1.0" class="UITransitionView" focused="false" height="<number>" visibility="visible" width="<number>" x="<number>" y="<number>">
+   <UIDropShadowView alpha="1.0" class="UIDropShadowView" focused="false" height="<number>" visibility="visible" width="<number>" x="<number>" y="<number>">
+    <RCTRootView alpha="1.0" class="RCTRootView" focused="false" height="<number>" visibility="visible" width="<number>" x="<number>" y="<number>">
+     <RCTRootContentView alpha="1.0" class="RCTRootContentView" focused="false" height="<number>" label="Welcome Say Hello Say World" visibility="visible" width="<number>" x="<number>" y="<number>">
+      <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" label="Welcome Say Hello Say World" visibility="visible" width="<number>" x="<number>" y="<number>">
+       <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" label="Welcome Say Hello Say World" visibility="visible" width="<number>" x="<number>" y="<number>">
+        <RCTTextView alpha="1.0" class="RCTTextView" focused="false" height="<number>" label="Welcome" visibility="visible" width="<number>" x="<number>" y="<number>" />
+        <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" label="Say Hello" visibility="visible" width="<number>" x="<number>" y="<number>">
+         <RCTTextView alpha="1.0" class="RCTTextView" focused="false" height="<number>" label="Say Hello" visibility="visible" width="<number>" x="<number>" y="<number>" />
+        </RCTView>
+        <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" label="Say World" visibility="visible" width="<number>" x="<number>" y="<number>">
+         <RCTTextView alpha="1.0" class="RCTTextView" focused="false" height="<number>" label="Say World" visibility="visible" width="<number>" x="<number>" y="<number>" />
+        </RCTView>
+       </RCTView>
+      </RCTView>
+     </RCTRootContentView>
+    </RCTRootView>
+   </UIDropShadowView>
+  </UITransitionView>
+ </UIWindow>
+</ViewHierarchy>
\ No newline at end of file

From fc625fdf062e6adc7c0fe2b04f2cab0979991fed Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Mon, 23 Dec 2024 16:49:51 +0200
Subject: [PATCH 29/51] fix(iOS): fix implicit conversion of Integer in
 Podfile.

---
 detox/test/ios/Podfile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/detox/test/ios/Podfile b/detox/test/ios/Podfile
index bb5256f319..87c22bc8e3 100644
--- a/detox/test/ios/Podfile
+++ b/detox/test/ios/Podfile
@@ -1,4 +1,4 @@
-ENV['RCT_NEW_ARCH_ENABLED'] = ENV['RCT_NEW_ARCH_ENABLED'] || 0
+ENV['RCT_NEW_ARCH_ENABLED'] = ENV['RCT_NEW_ARCH_ENABLED'] || '0'
 
 if ENV["REACT_NATIVE_VERSION"] && ENV["REACT_NATIVE_VERSION"].match(/0.(70|71).*/)
     require_relative '../node_modules/react-native/scripts/react_native_pods'

From 263a85fd227859f221809c7d1c8ff2efbb8f7240 Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Mon, 23 Dec 2024 21:12:33 +0200
Subject: [PATCH 30/51] fix(ios): remove `RCT_NEW_ARCH_ENABLED` assignment from
 Podfile.

not needed as can be empty for no-new-arch.
---
 detox/test/ios/Podfile | 2 --
 1 file changed, 2 deletions(-)

diff --git a/detox/test/ios/Podfile b/detox/test/ios/Podfile
index 87c22bc8e3..6bf92b7c5e 100644
--- a/detox/test/ios/Podfile
+++ b/detox/test/ios/Podfile
@@ -1,5 +1,3 @@
-ENV['RCT_NEW_ARCH_ENABLED'] = ENV['RCT_NEW_ARCH_ENABLED'] || '0'
-
 if ENV["REACT_NATIVE_VERSION"] && ENV["REACT_NATIVE_VERSION"].match(/0.(70|71).*/)
     require_relative '../node_modules/react-native/scripts/react_native_pods'
     require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'

From b5bd5b4dec7ecfa728d9eb2e8184af338970ae42 Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Wed, 25 Dec 2024 15:44:35 +0200
Subject: [PATCH 31/51] fix: make keyboard tests pass on legacy arch.

---
 detox/test/ios/AppDelegate.swift              | 127 ++++++++++++
 detox/test/ios/ReactModules/NativeModule.h    |   6 -
 detox/test/ios/ReactModules/NativeModule.mm   | 168 ---------------
 .../test/ios/ReactModules/NativeModule.swift  | 196 ++++++++++++++++++
 .../ios/ReactModules/ReactModulesBridge.m     |  36 ++++
 .../ios/ReactModules/ShakeEventEmitter.swift  |  28 +++
 .../test/ios/UI/CustomKeyboardDelegate.swift  | 110 ++++++++++
 detox/test/ios/UI/NativeScreenManager.swift   |  49 +++++
 detox/test/ios/example-Bridging-Header.h      |   4 +
 detox/test/ios/example-ci-Bridging-Header.h   |   4 +
 .../ios/example.xcodeproj/project.pbxproj     |  95 ++++++---
 detox/test/ios/example/AppDelegate.h          |   6 -
 detox/test/ios/example/AppDelegate.mm         | 108 ----------
 detox/test/ios/example/main.m                 |  10 -
 14 files changed, 617 insertions(+), 330 deletions(-)
 create mode 100644 detox/test/ios/AppDelegate.swift
 delete mode 100644 detox/test/ios/ReactModules/NativeModule.h
 delete mode 100644 detox/test/ios/ReactModules/NativeModule.mm
 create mode 100644 detox/test/ios/ReactModules/NativeModule.swift
 create mode 100644 detox/test/ios/ReactModules/ReactModulesBridge.m
 create mode 100644 detox/test/ios/ReactModules/ShakeEventEmitter.swift
 create mode 100644 detox/test/ios/UI/CustomKeyboardDelegate.swift
 create mode 100644 detox/test/ios/UI/NativeScreenManager.swift
 create mode 100644 detox/test/ios/example-Bridging-Header.h
 create mode 100644 detox/test/ios/example-ci-Bridging-Header.h
 delete mode 100644 detox/test/ios/example/AppDelegate.h
 delete mode 100644 detox/test/ios/example/AppDelegate.mm
 delete mode 100644 detox/test/ios/example/main.m

diff --git a/detox/test/ios/AppDelegate.swift b/detox/test/ios/AppDelegate.swift
new file mode 100644
index 0000000000..026c6c77c6
--- /dev/null
+++ b/detox/test/ios/AppDelegate.swift
@@ -0,0 +1,127 @@
+import UIKit
+import React
+import UserNotifications
+import CoreSpotlight
+
+// MARK: - App Delegate
+
+@UIApplicationMain
+@objc(AppDelegate)
+class AppDelegate: UIResponder, UIApplicationDelegate {
+
+    var window: UIWindow?
+    var moduleName: String = "example"
+    var initialProps: [String: Any] = [:]
+    private var screenManager: NativeScreenManaging?
+
+    // MARK: - UIApplicationDelegate Methods
+
+    func application(_ application: UIApplication,
+                     didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
+
+        setupReactNative(with: launchOptions)
+        setupNotifications()
+        setupScreenManager()
+
+        return true
+    }
+
+    // MARK: - Setup Methods
+
+    private func setupReactNative(with launchOptions: [UIApplication.LaunchOptionsKey: Any]?) {
+        let bridge = RCTBridge(delegate: self, launchOptions: launchOptions)
+        let rootView = RCTRootView(bridge: bridge!,
+                                   moduleName: moduleName,
+                                   initialProperties: initialProps)
+        rootView.backgroundColor = .white
+
+        let rootViewController = UIViewController()
+        rootViewController.view = rootView
+
+        window = UIWindow(frame: UIScreen.main.bounds)
+        window?.rootViewController = rootViewController
+        window?.makeKeyAndVisible()
+    }
+
+    private func setupNotifications() {
+        UNUserNotificationCenter.current().delegate = self
+
+        NotificationCenter.default.addObserver(
+            forName: Notification.Name("ChangeScreen"),
+            object: nil,
+            queue: nil
+        ) { [weak self] notification in
+            self?.screenManager?.handle(notification)
+        }
+    }
+
+    private func setupScreenManager() {
+        screenManager = NativeScreenManager(window: window)
+    }
+}
+
+// MARK: - Shake Gesture Handling
+
+extension AppDelegate {
+    override func motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
+        if motion == .motionShake {
+            if let rootView = window?.rootViewController?.view as? RCTRootView {
+                let bridge = rootView.bridge
+                let shakeModule = bridge.module(for: ShakeEventEmitter.self) as! ShakeEventEmitter
+                shakeModule.handleShake()
+            }
+        } else {
+            super.motionEnded(motion, with: event)
+        }
+    }
+}
+
+// MARK: - URL and Universal Links Handling
+
+extension AppDelegate {
+    func application(_ app: UIApplication,
+                     open url: URL,
+                     options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
+        return RCTLinkingManager.application(app, open: url, options: options)
+    }
+
+    func application(_ application: UIApplication,
+                     continue userActivity: NSUserActivity,
+                     restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
+        return RCTLinkingManager.application(application,
+                                             continue: userActivity,
+                                             restorationHandler: restorationHandler)
+    }
+}
+
+// MARK: - UNUserNotificationCenterDelegate
+extension AppDelegate: UNUserNotificationCenterDelegate {
+    func userNotificationCenter(_ center: UNUserNotificationCenter,
+                                willPresent notification: UNNotification,
+                                withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
+        completionHandler([.list, .banner, .badge, .sound])
+    }
+
+    func userNotificationCenter(_ center: UNUserNotificationCenter,
+                                didReceive response: UNNotificationResponse,
+                                withCompletionHandler completionHandler: @escaping () -> Void) {
+        completionHandler()
+    }
+}
+
+// MARK: - RCTBridgeDelegate
+
+extension AppDelegate: RCTBridgeDelegate {
+    func sourceURL(for bridge: RCTBridge) -> URL? {
+        return bundleURL()
+    }
+
+    private func bundleURL() -> URL {
+#if DEBUG
+        return RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index",
+                                                                 fallbackExtension: nil)!
+#else
+        return Bundle.main.url(forResource: "main", withExtension: "jsbundle")!
+#endif
+    }
+}
diff --git a/detox/test/ios/ReactModules/NativeModule.h b/detox/test/ios/ReactModules/NativeModule.h
deleted file mode 100644
index 7bde08a0f8..0000000000
--- a/detox/test/ios/ReactModules/NativeModule.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#import <React/RCTBridgeModule.h>
-#import <Foundation/Foundation.h>
-
-@interface NativeModule : NSObject <RCTBridgeModule>
-
-@end
diff --git a/detox/test/ios/ReactModules/NativeModule.mm b/detox/test/ios/ReactModules/NativeModule.mm
deleted file mode 100644
index bd80781919..0000000000
--- a/detox/test/ios/ReactModules/NativeModule.mm
+++ /dev/null
@@ -1,168 +0,0 @@
-#import "NativeModule.h"
-#import <UIKit/UIKit.h>
-#import <React/RCTRootView.h>
-
-@interface NativeModule ()
-@property (nonatomic, strong) UIWindow *overlayWindow;
-@property (nonatomic, strong) UIView *overlayView;
-@property (nonatomic, assign) NSInteger callCounter;
-@end
-
-@implementation NativeModule
-
-RCT_EXPORT_MODULE();
-
-#pragma mark - Lifecycle Methods
-
-- (instancetype)init {
-    self = [super init];
-    if (self) {
-        _callCounter = 0;
-    }
-    return self;
-}
-
-#pragma mark - Echo Methods
-
-RCT_EXPORT_METHOD(echoWithoutResponse:(NSString *)str) {
-    self.callCounter++;
-}
-
-RCT_EXPORT_METHOD(echoWithResponse:(NSString *)str
-                  resolver:(RCTPromiseResolveBlock)resolve
-                  rejecter:(RCTPromiseRejectBlock)reject) {
-    self.callCounter++;
-    resolve(str);
-}
-
-#pragma mark - Timing Methods
-
-RCT_EXPORT_METHOD(nativeSetTimeout:(NSTimeInterval)delay
-                  block:(RCTResponseSenderBlock)block) {
-    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)),
-                   dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
-        [self executeOnMainThread:^{
-            block(@[]);
-        }];
-    });
-}
-
-#pragma mark - Navigation Methods
-
-RCT_EXPORT_METHOD(switchToNativeRoot) {
-    [self executeOnMainThread:^{
-        UIViewController *newRoot = [self createNativeRootViewController];
-        [self updateRootViewController:newRoot];
-    }];
-}
-
-RCT_EXPORT_METHOD(switchToMultipleReactRoots) {
-    [self executeOnMainThread:^{
-        UITabBarController *tabController = [self createTabBarControllerWithBridge];
-        [self updateRootViewController:tabController];
-    }];
-}
-
-#pragma mark - Notification Methods
-
-RCT_EXPORT_METHOD(sendNotification:(NSString*)notification
-                  name:(NSString*)name) {
-    [self executeOnMainThread:^{
-        [NSNotificationCenter.defaultCenter postNotificationName:notification
-                                                          object:nil
-                                                        userInfo:@{@"name": name}];
-    }];
-}
-
-#pragma mark - Overlay Methods
-
-RCT_EXPORT_METHOD(presentOverlayWindow) {
-    [self executeOnMainThread:^{
-        [self setupAndShowOverlayWindow];
-    }];
-}
-
-RCT_EXPORT_METHOD(presentOverlayView) {
-    [self executeOnMainThread:^{
-        [self setupAndShowOverlayView];
-    }];
-}
-
-#pragma mark - Private Helper Methods
-
-- (void)executeOnMainThread:(void (^)(void))block {
-    if ([NSThread isMainThread]) {
-        block();
-    } else {
-        dispatch_async(dispatch_get_main_queue(), block);
-    }
-}
-
-- (UIViewController *)createNativeRootViewController {
-    UIViewController *newRoot = [UIViewController new];
-    newRoot.view.backgroundColor = UIColor.whiteColor;
-
-    UILabel *label = [UILabel new];
-    label.text = @"this is a new native root";
-    [label sizeToFit];
-    [newRoot.view addSubview:label];
-    label.center = newRoot.view.center;
-
-    return newRoot;
-}
-
-- (UITabBarController *)createTabBarControllerWithBridge {
-    RCTBridge *bridge = [self getCurrentBridge];
-    NSArray *viewControllers = @[
-        [self createReactRootViewController:bridge title:@"1"],
-        [self createReactRootViewController:bridge title:@"2"],
-        [self createReactRootViewController:bridge title:@"3"],
-        [self createReactRootViewController:bridge title:@"4"]
-    ];
-
-    UITabBarController *tabController = [UITabBarController new];
-    tabController.viewControllers = viewControllers;
-    return tabController;
-}
-
-- (UIViewController *)createReactRootViewController:(RCTBridge *)bridge
-                                              title:(NSString *)title {
-    UIViewController *viewController = [UIViewController new];
-    viewController.view = [[RCTRootView alloc] initWithBridge:bridge
-                                                   moduleName:@"example"
-                                            initialProperties:nil];
-    viewController.tabBarItem.title = title;
-    return viewController;
-}
-
-- (RCTBridge *)getCurrentBridge {
-    id<UIApplicationDelegate> delegate = UIApplication.sharedApplication.delegate;
-    return ((RCTRootView *)delegate.window.rootViewController.view).bridge;
-}
-
-- (void)updateRootViewController:(UIViewController *)viewController {
-    id<UIApplicationDelegate> delegate = UIApplication.sharedApplication.delegate;
-    [delegate.window setRootViewController:viewController];
-    [delegate.window makeKeyAndVisible];
-}
-
-- (void)setupAndShowOverlayWindow {
-    CGRect screenBounds = UIScreen.mainScreen.bounds;
-    self.overlayWindow = [[UIWindow alloc] initWithFrame:screenBounds];
-    self.overlayWindow.accessibilityIdentifier = @"OverlayWindow";
-    [self.overlayWindow setWindowLevel:UIWindowLevelStatusBar];
-    [self.overlayWindow setHidden:NO];
-    [self.overlayWindow makeKeyAndVisible];
-}
-
-- (void)setupAndShowOverlayView {
-    CGRect screenBounds = UIScreen.mainScreen.bounds;
-    self.overlayView = [[UIView alloc] initWithFrame:screenBounds];
-    self.overlayView.userInteractionEnabled = YES;
-    self.overlayView.accessibilityIdentifier = @"OverlayView";
-
-    UIWindow *keyWindow = UIApplication.sharedApplication.keyWindow;
-    [keyWindow addSubview:self.overlayView];
-}
-
-@end
diff --git a/detox/test/ios/ReactModules/NativeModule.swift b/detox/test/ios/ReactModules/NativeModule.swift
new file mode 100644
index 0000000000..9fd6856ef4
--- /dev/null
+++ b/detox/test/ios/ReactModules/NativeModule.swift
@@ -0,0 +1,196 @@
+//
+//  NativeModule.swift (example)
+//  Created by Asaf Korem (Wix.com) on 2024.
+//
+
+import Foundation
+import React
+import UIKit
+
+@objc(NativeModule)
+class NativeModule: NSObject, RCTBridgeModule {
+    
+    // MARK: - Properties
+    
+    var overlayWindow: UIWindow?
+    var overlayView: UIView?
+    var callCounter: Int = 0
+    
+    // MARK: - RCTBridgeModule
+    
+    static func moduleName() -> String! {
+        return "NativeModule"
+    }
+    
+    static func requiresMainQueueSetup() -> Bool {
+        // Indicates that the module must be initialized on the main thread
+        return true
+    }
+    
+    // MARK: - Lifecycle Methods
+    
+    override init() {
+        super.init()
+        self.callCounter = 0
+    }
+    
+    // MARK: - Echo Methods
+    
+    @objc
+    func echoWithoutResponse(_ str: String) {
+        self.callCounter += 1
+    }
+    
+    @objc
+    func echoWithResponse(_ str: String,
+                          resolver resolve: @escaping RCTPromiseResolveBlock,
+                          rejecter reject: @escaping RCTPromiseRejectBlock) {
+        self.callCounter += 1
+        resolve(str)
+    }
+    
+    // MARK: - Timing Methods
+    
+    @objc
+    func nativeSetTimeout(_ delay: TimeInterval,
+                          block: @escaping RCTResponseSenderBlock) {
+        let dispatchTime = DispatchTime.now() + delay
+        DispatchQueue.global(qos: .default).asyncAfter(deadline: dispatchTime) { [weak self] in
+            self?.executeOnMainThread {
+                block([])
+            }
+        }
+    }
+    
+    // MARK: - Navigation Methods
+    
+    @objc
+    func switchToNativeRoot() {
+        executeOnMainThread { [weak self] in
+            guard let self = self else { return }
+            let newRoot = self.createNativeRootViewController()
+            self.updateRootViewController(newRoot)
+        }
+    }
+    
+    @objc
+    func switchToMultipleReactRoots() {
+        executeOnMainThread { [weak self] in
+            guard let self = self else { return }
+            let tabController = self.createTabBarControllerWithBridge()
+            self.updateRootViewController(tabController)
+        }
+    }
+    
+    // MARK: - Notification Methods
+    
+    @objc
+    func sendNotification(_ notification: String, name: String) {
+        executeOnMainThread {
+            NotificationCenter.default.post(name: Notification.Name(notification),
+                                            object: nil,
+                                            userInfo: ["name": name])
+        }
+    }
+    
+    // MARK: - Overlay Methods
+    
+    @objc
+    func presentOverlayWindow() {
+        executeOnMainThread { [weak self] in
+            self?.setupAndShowOverlayWindow()
+        }
+    }
+    
+    @objc
+    func presentOverlayView() {
+        executeOnMainThread { [weak self] in
+            self?.setupAndShowOverlayView()
+        }
+    }
+    
+    // MARK: - Private Helper Methods
+    
+    private func executeOnMainThread(_ block: @escaping () -> Void) {
+        if Thread.isMainThread {
+            block()
+        } else {
+            DispatchQueue.main.async {
+                block()
+            }
+        }
+    }
+    
+    private func createNativeRootViewController() -> UIViewController {
+        let newRoot = UIViewController()
+        newRoot.view.backgroundColor = .white
+        
+        let label = UILabel()
+        label.text = "This is a new native root"
+        label.sizeToFit()
+        label.center = newRoot.view.center
+        newRoot.view.addSubview(label)
+        
+        return newRoot
+    }
+    
+    private func createTabBarControllerWithBridge() -> UITabBarController {
+        guard let bridge = getCurrentBridge() else {
+            fatalError("RCTBridge is not available")
+        }
+        
+        let viewControllers = [
+            createReactRootViewController(bridge: bridge, title: "1"),
+            createReactRootViewController(bridge: bridge, title: "2"),
+            createReactRootViewController(bridge: bridge, title: "3"),
+            createReactRootViewController(bridge: bridge, title: "4")
+        ]
+        
+        let tabController = UITabBarController()
+        tabController.viewControllers = viewControllers
+        return tabController
+    }
+    
+    private func createReactRootViewController(bridge: RCTBridge, title: String) -> UIViewController {
+        let viewController = UIViewController()
+        viewController.view = RCTRootView(bridge: bridge, moduleName: "example", initialProperties: nil)
+        viewController.tabBarItem.title = title
+        return viewController
+    }
+    
+    private func getCurrentBridge() -> RCTBridge? {
+        guard let delegate = UIApplication.shared.delegate as? AppDelegate,
+              let window = delegate.window,
+              let rootView = window.rootViewController?.view as? RCTRootView else {
+            return nil
+        }
+        return rootView.bridge
+    }
+    
+    private func updateRootViewController(_ viewController: UIViewController) {
+        guard let delegate = UIApplication.shared.delegate as? AppDelegate,
+              let window = delegate.window else {
+            return
+        }
+        window.rootViewController = viewController
+        window.makeKeyAndVisible()
+    }
+    
+    private func setupAndShowOverlayWindow() {
+        let screenBounds = UIScreen.main.bounds
+        overlayWindow = UIWindow(frame: screenBounds)
+        overlayWindow?.accessibilityIdentifier = "OverlayWindow"
+        overlayWindow?.windowLevel = UIWindow.Level.statusBar
+        overlayWindow?.isHidden = false
+        overlayWindow?.makeKeyAndVisible()
+    }
+    
+    private func setupAndShowOverlayView() {
+        guard let keyWindow = UIApplication.shared.keyWindow else { return }
+        let screenBounds = UIScreen.main.bounds
+        overlayView = UIView(frame: screenBounds)
+        overlayView?.isUserInteractionEnabled = true
+        overlayView?.accessibilityIdentifier = "OverlayView"
+        keyWindow.addSubview(overlayView!)
+    }
+}
diff --git a/detox/test/ios/ReactModules/ReactModulesBridge.m b/detox/test/ios/ReactModules/ReactModulesBridge.m
new file mode 100644
index 0000000000..8cd211819a
--- /dev/null
+++ b/detox/test/ios/ReactModules/ReactModulesBridge.m
@@ -0,0 +1,36 @@
+//
+//  ReactModulesBridge.m (example)
+//  Created by Asaf Korem (Wix.com) on 2024.
+//
+
+#import "React/RCTBridgeModule.h"
+#import "React/RCTEventEmitter.h"
+#import "React/RCTViewManager.h"
+
+@interface RCT_EXTERN_MODULE(ShakeEventEmitter, RCTEventEmitter)
+
+@end
+
+@interface RCT_EXTERN_MODULE(NativeModule, NSObject)
+
+RCT_EXTERN_METHOD(echoWithoutResponse:(NSString *)str)
+
+RCT_EXTERN_METHOD(echoWithResponse:(NSString *)str
+                  resolver:(RCTPromiseResolveBlock)resolve
+                  rejecter:(RCTPromiseRejectBlock)reject)
+
+RCT_EXTERN_METHOD(nativeSetTimeout:(double)delay
+                  block:(RCTResponseSenderBlock)block)
+
+RCT_EXTERN_METHOD(switchToNativeRoot)
+
+RCT_EXTERN_METHOD(switchToMultipleReactRoots)
+
+RCT_EXTERN_METHOD(sendNotification:(NSString *)notification
+                  name:(NSString *)name)
+
+RCT_EXTERN_METHOD(presentOverlayWindow)
+
+RCT_EXTERN_METHOD(presentOverlayView)
+
+@end
diff --git a/detox/test/ios/ReactModules/ShakeEventEmitter.swift b/detox/test/ios/ReactModules/ShakeEventEmitter.swift
new file mode 100644
index 0000000000..400488cdcc
--- /dev/null
+++ b/detox/test/ios/ReactModules/ShakeEventEmitter.swift
@@ -0,0 +1,28 @@
+//
+//  ShakeEventEmitter.swift (example)
+//  Created by Asaf Korem (Wix.com) on 2024.
+//
+
+import Foundation
+import React
+
+@objc(ShakeEventEmitter)
+class ShakeEventEmitter: RCTEventEmitter {
+
+  // MARK: - RCTEventEmitter Overrides
+  
+  override static func requiresMainQueueSetup() -> Bool {
+    return true
+  }
+  
+  override func supportedEvents() -> [String]! {
+    return ["ShakeEvent"]
+  }
+  
+  // MARK: - Public Methods
+  
+  @objc
+  func handleShake() {
+    sendEvent(withName: "ShakeEvent", body: nil)
+  }
+}
diff --git a/detox/test/ios/UI/CustomKeyboardDelegate.swift b/detox/test/ios/UI/CustomKeyboardDelegate.swift
new file mode 100644
index 0000000000..8a9a4d548d
--- /dev/null
+++ b/detox/test/ios/UI/CustomKeyboardDelegate.swift
@@ -0,0 +1,110 @@
+//
+//  CustomKeyboardDelegate.swift (example)
+//  Created by Asaf Korem (Wix.com) on 2024.
+//
+
+
+import UIKit
+
+protocol CustomKeyboardDelegate: AnyObject {
+    func customKeyboardTappedButton(_ sender: CustomKeyboardView)
+}
+
+class CustomKeyboardView: UIView {
+    weak var delegate: CustomKeyboardDelegate?
+    
+    override init(frame: CGRect) {
+        super.init(frame: frame)
+        loadView()
+    }
+    
+    required init?(coder: NSCoder) {
+        super.init(coder: coder)
+        loadView()
+    }
+    
+    func loadView() {
+        let kbButton = UIButton(type: .custom)
+        kbButton.translatesAutoresizingMaskIntoConstraints = false
+        kbButton.setTitle("Hello", for: .normal)
+        kbButton.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
+        kbButton.accessibilityIdentifier = "keyboardHelloButton"
+        
+        addSubview(kbButton)
+        
+        NSLayoutConstraint.activate([
+            kbButton.widthAnchor.constraint(greaterThanOrEqualToConstant: 44),
+            kbButton.heightAnchor.constraint(equalToConstant: 44),
+            kbButton.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 20),
+            kbButton.topAnchor.constraint(equalTo: topAnchor, constant: 20)
+        ])
+    }
+    
+    @objc private func buttonTapped(_ sender: Any) {
+        delegate?.customKeyboardTappedButton(self)
+    }
+}
+
+class CustomKeyboardViewController: UIViewController {
+    private var textField: UITextField!
+    
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        
+        view.backgroundColor = .systemBackground
+        
+        let closeButton = UIButton(type: .system)
+        closeButton.setImage(UIImage(systemName: "xmark.circle.fill"), for: .normal)
+        closeButton.translatesAutoresizingMaskIntoConstraints = false
+        closeButton.accessibilityIdentifier = "closeButton"
+        closeButton.addTarget(self, action: #selector(close), for: .primaryActionTriggered)
+        
+        let inputView = CustomKeyboardView()
+        inputView.translatesAutoresizingMaskIntoConstraints = false
+        inputView.delegate = self
+        inputView.backgroundColor = .lightGray
+        
+        let text = UITextField()
+        text.translatesAutoresizingMaskIntoConstraints = false
+        text.inputView = inputView
+        text.borderStyle = .roundedRect
+        text.accessibilityIdentifier = "textWithCustomInput"
+        
+        let obscuredLabel = UILabel()
+        obscuredLabel.translatesAutoresizingMaskIntoConstraints = false
+        obscuredLabel.text = "Obscured by keyboard"
+        
+        textField = text
+        
+        view.addSubview(closeButton)
+        view.addSubview(text)
+        view.addSubview(obscuredLabel)
+        
+        NSLayoutConstraint.activate([
+            text.heightAnchor.constraint(equalToConstant: 50),
+            text.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 20),
+            view.safeAreaLayoutGuide.trailingAnchor.constraint(equalTo: text.trailingAnchor, constant: 20),
+            text.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 50),
+            
+            inputView.widthAnchor.constraint(equalToConstant: view.frame.size.width),
+            
+            view.layoutMarginsGuide.trailingAnchor.constraint(equalTo: closeButton.trailingAnchor),
+            view.layoutMarginsGuide.topAnchor.constraint(equalTo: closeButton.topAnchor),
+            
+            obscuredLabel.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 20),
+            view.safeAreaLayoutGuide.trailingAnchor.constraint(greaterThanOrEqualTo: obscuredLabel.trailingAnchor, constant: 20),
+            view.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: obscuredLabel.bottomAnchor, constant: 50)
+        ])
+    }
+    
+    @objc private func close() {
+        presentingViewController?.dismiss(animated: true)
+    }
+}
+
+// MARK: - CustomKeyboardDelegate
+extension CustomKeyboardViewController: CustomKeyboardDelegate {
+    func customKeyboardTappedButton(_ sender: CustomKeyboardView) {
+        textField.text = "World!"
+    }
+}
diff --git a/detox/test/ios/UI/NativeScreenManager.swift b/detox/test/ios/UI/NativeScreenManager.swift
new file mode 100644
index 0000000000..cda456a9c7
--- /dev/null
+++ b/detox/test/ios/UI/NativeScreenManager.swift
@@ -0,0 +1,49 @@
+//
+//  NativeScreenManager.swift (example)
+//  Created by Asaf Korem (Wix.com) on 2024.
+//
+
+import UIKit
+
+enum NativeScreen {
+    case customKeyboard
+
+    var viewController: UIViewController {
+        switch self {
+            case .customKeyboard:
+                let vc = CustomKeyboardViewController()
+                vc.modalPresentationStyle = .fullScreen
+                return vc
+        }
+    }
+}
+
+protocol NativeScreenManaging {
+    func present(_ screen: NativeScreen, from: UIViewController?, animated: Bool)
+    func handle(_ notification: Notification)
+}
+
+class NativeScreenManager: NativeScreenManaging {
+    weak var window: UIWindow?
+
+    init(window: UIWindow?) {
+        self.window = window
+    }
+
+    func present(_ screen: NativeScreen, from: UIViewController?, animated: Bool) {
+        let presentingVC = from ?? window?.rootViewController
+        let viewController = screen.viewController
+        presentingVC?.present(viewController, animated: animated)
+    }
+
+    func handle(_ notification: Notification) {
+        guard let name = notification.userInfo?["name"] as? String else { return }
+
+        switch name {
+            case "customKeyboard":
+                present(.customKeyboard, from: nil, animated: true)
+            default:
+                print("Unknown screen: \(name)")
+        }
+    }
+}
diff --git a/detox/test/ios/example-Bridging-Header.h b/detox/test/ios/example-Bridging-Header.h
new file mode 100644
index 0000000000..1b2cb5d6d0
--- /dev/null
+++ b/detox/test/ios/example-Bridging-Header.h
@@ -0,0 +1,4 @@
+//
+//  Use this file to import your target's public headers that you would like to expose to Swift.
+//
+
diff --git a/detox/test/ios/example-ci-Bridging-Header.h b/detox/test/ios/example-ci-Bridging-Header.h
new file mode 100644
index 0000000000..1b2cb5d6d0
--- /dev/null
+++ b/detox/test/ios/example-ci-Bridging-Header.h
@@ -0,0 +1,4 @@
+//
+//  Use this file to import your target's public headers that you would like to expose to Swift.
+//
+
diff --git a/detox/test/ios/example.xcodeproj/project.pbxproj b/detox/test/ios/example.xcodeproj/project.pbxproj
index 01f8a263ec..fcf919e2c3 100644
--- a/detox/test/ios/example.xcodeproj/project.pbxproj
+++ b/detox/test/ios/example.xcodeproj/project.pbxproj
@@ -7,19 +7,24 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
-		0C80B921A6F3F58F76C31292 /* (null) in Frameworks */ = {isa = PBXBuildFile; };
-		13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; };
 		13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
-		13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
 		213E1077F464B28612297B3E /* libPods-example.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 467D00885FA51E1E9B0E8063 /* libPods-example.a */; };
-		60493BDE2D10E7E4002853A0 /* NativeModule.mm in Sources */ = {isa = PBXBuildFile; fileRef = 609DDBE32D10D45500028574 /* NativeModule.mm */; };
-		60493BDF2D10E7E4002853A0 /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; };
-		60493BE02D10E7E4002853A0 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
 		60493BE52D10E7E4002853A0 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
 		60493BE62D10E7E4002853A0 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
 		60493BE72D10E7E4002853A0 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */; };
+		608868A02D1A9F070070D199 /* NativeModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6088689D2D1A9F070070D199 /* NativeModule.swift */; };
+		608868A12D1A9F070070D199 /* ShakeEventEmitter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6088689E2D1A9F070070D199 /* ShakeEventEmitter.swift */; };
+		608868A22D1A9F070070D199 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6088689A2D1A9F070070D199 /* AppDelegate.swift */; };
+		608868A32D1A9F070070D199 /* NativeModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6088689D2D1A9F070070D199 /* NativeModule.swift */; };
+		608868A42D1A9F070070D199 /* ShakeEventEmitter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6088689E2D1A9F070070D199 /* ShakeEventEmitter.swift */; };
+		608868A52D1A9F070070D199 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6088689A2D1A9F070070D199 /* AppDelegate.swift */; };
+		608868AB2D1AA19B0070D199 /* NativeScreenManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 608868AA2D1AA19B0070D199 /* NativeScreenManager.swift */; };
+		608868AC2D1AA19B0070D199 /* NativeScreenManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 608868AA2D1AA19B0070D199 /* NativeScreenManager.swift */; };
+		608868B22D1AA1FB0070D199 /* CustomKeyboardDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 608868B02D1AA1FB0070D199 /* CustomKeyboardDelegate.swift */; };
+		608868B32D1AA1FB0070D199 /* CustomKeyboardDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 608868B02D1AA1FB0070D199 /* CustomKeyboardDelegate.swift */; };
+		608868C52D1C3D130070D199 /* ReactModulesBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 608868C42D1C3D0E0070D199 /* ReactModulesBridge.m */; };
+		608868C62D1C3D130070D199 /* ReactModulesBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 608868C42D1C3D0E0070D199 /* ReactModulesBridge.m */; };
 		609DDB892D10C21800028574 /* Detox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 609DDB852D10C20800028574 /* Detox.framework */; };
-		609DDBE42D10D45500028574 /* NativeModule.mm in Sources */ = {isa = PBXBuildFile; fileRef = 609DDBE32D10D45500028574 /* NativeModule.mm */; };
 		81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
 		90CCD0BA1322566EB1285DC2 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */; };
 		CA25A6405AF58BA742F7FD47 /* libPods-example-ci.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1CB0FE045763B5363B2E7054 /* libPods-example-ci.a */; };
@@ -44,11 +49,8 @@
 
 /* Begin PBXFileReference section */
 		13B07F961A680F5B00A75B9A /* example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = example.app; sourceTree = BUILT_PRODUCTS_DIR; };
-		13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = example/AppDelegate.h; sourceTree = "<group>"; };
-		13B07FB01A68108700A75B9A /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = example/AppDelegate.mm; sourceTree = "<group>"; };
 		13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = example/Images.xcassets; sourceTree = "<group>"; };
 		13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = example/Info.plist; sourceTree = "<group>"; };
-		13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = example/main.m; sourceTree = "<group>"; };
 		13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = PrivacyInfo.xcprivacy; path = example/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
 		19F6CBCC0A4E27FBF8BF4A61 /* libPods-example-exampleTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-example-exampleTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
 		1CB0FE045763B5363B2E7054 /* libPods-example-ci.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-example-ci.a"; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -59,9 +61,15 @@
 		5B7EB9410499542E8C5724F5 /* Pods-example-exampleTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example-exampleTests.debug.xcconfig"; path = "Target Support Files/Pods-example-exampleTests/Pods-example-exampleTests.debug.xcconfig"; sourceTree = "<group>"; };
 		60493BD72D10D967002853A0 /* example.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = example.entitlements; path = example/example.entitlements; sourceTree = "<group>"; };
 		60493BEE2D10E7E4002853A0 /* example-ci.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "example-ci.app"; sourceTree = BUILT_PRODUCTS_DIR; };
+		6088689A2D1A9F070070D199 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
+		6088689B2D1A9F070070D199 /* example-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "example-Bridging-Header.h"; sourceTree = "<group>"; };
+		6088689C2D1A9F070070D199 /* example-ci-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "example-ci-Bridging-Header.h"; sourceTree = "<group>"; };
+		6088689D2D1A9F070070D199 /* NativeModule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NativeModule.swift; sourceTree = "<group>"; };
+		6088689E2D1A9F070070D199 /* ShakeEventEmitter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShakeEventEmitter.swift; sourceTree = "<group>"; };
+		608868AA2D1AA19B0070D199 /* NativeScreenManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NativeScreenManager.swift; sourceTree = "<group>"; };
+		608868B02D1AA1FB0070D199 /* CustomKeyboardDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomKeyboardDelegate.swift; sourceTree = "<group>"; };
+		608868C42D1C3D0E0070D199 /* ReactModulesBridge.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ReactModulesBridge.m; sourceTree = "<group>"; };
 		609DDB772D10C20700028574 /* Detox.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Detox.xcodeproj; path = /Users/asafk/Development/Detox/detox/ios/Detox.xcodeproj; sourceTree = "<absolute>"; };
-		609DDBE22D10D45500028574 /* NativeModule.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NativeModule.h; sourceTree = "<group>"; };
-		609DDBE32D10D45500028574 /* NativeModule.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = NativeModule.mm; sourceTree = "<group>"; };
 		80C930B7D5D6C25DA27372A5 /* Pods-example-ci.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example-ci.release.xcconfig"; path = "Target Support Files/Pods-example-ci/Pods-example-ci.release.xcconfig"; sourceTree = "<group>"; };
 		81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = example/LaunchScreen.storyboard; sourceTree = "<group>"; };
 		89C6BE57DB24E9ADA2F236DE /* Pods-example-exampleTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example-exampleTests.release.xcconfig"; path = "Target Support Files/Pods-example-exampleTests/Pods-example-exampleTests.release.xcconfig"; sourceTree = "<group>"; };
@@ -74,7 +82,6 @@
 			buildActionMask = 2147483647;
 			files = (
 				609DDB892D10C21800028574 /* Detox.framework in Frameworks */,
-				0C80B921A6F3F58F76C31292 /* (null) in Frameworks */,
 				213E1077F464B28612297B3E /* libPods-example.a in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -93,15 +100,16 @@
 		13B07FAE1A68108700A75B9A /* example */ = {
 			isa = PBXGroup;
 			children = (
+				6088689A2D1A9F070070D199 /* AppDelegate.swift */,
 				60493BD72D10D967002853A0 /* example.entitlements */,
-				13B07FAF1A68108700A75B9A /* AppDelegate.h */,
-				13B07FB01A68108700A75B9A /* AppDelegate.mm */,
+				6088689B2D1A9F070070D199 /* example-Bridging-Header.h */,
+				6088689C2D1A9F070070D199 /* example-ci-Bridging-Header.h */,
 				13B07FB51A68108700A75B9A /* Images.xcassets */,
 				13B07FB61A68108700A75B9A /* Info.plist */,
 				81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */,
-				13B07FB71A68108700A75B9A /* main.m */,
 				13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */,
-				609DDBE12D10D44F00028574 /* ReactModules */,
+				6088689F2D1A9F070070D199 /* ReactModules */,
+				608868B12D1AA1FB0070D199 /* UI */,
 			);
 			name = example;
 			sourceTree = "<group>";
@@ -117,22 +125,32 @@
 			name = Frameworks;
 			sourceTree = "<group>";
 		};
-		609DDB802D10C20800028574 /* Products */ = {
+		6088689F2D1A9F070070D199 /* ReactModules */ = {
 			isa = PBXGroup;
 			children = (
-				609DDB852D10C20800028574 /* Detox.framework */,
-				609DDB872D10C20800028574 /* DetoxUserNotificationTests.xctest */,
+				608868C42D1C3D0E0070D199 /* ReactModulesBridge.m */,
+				6088689D2D1A9F070070D199 /* NativeModule.swift */,
+				6088689E2D1A9F070070D199 /* ShakeEventEmitter.swift */,
 			);
-			name = Products;
+			path = ReactModules;
 			sourceTree = "<group>";
 		};
-		609DDBE12D10D44F00028574 /* ReactModules */ = {
+		608868B12D1AA1FB0070D199 /* UI */ = {
 			isa = PBXGroup;
 			children = (
-				609DDBE22D10D45500028574 /* NativeModule.h */,
-				609DDBE32D10D45500028574 /* NativeModule.mm */,
+				608868B02D1AA1FB0070D199 /* CustomKeyboardDelegate.swift */,
+				608868AA2D1AA19B0070D199 /* NativeScreenManager.swift */,
 			);
-			path = ReactModules;
+			path = UI;
+			sourceTree = "<group>";
+		};
+		609DDB802D10C20800028574 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				609DDB852D10C20800028574 /* Detox.framework */,
+				609DDB872D10C20800028574 /* DetoxUserNotificationTests.xctest */,
+			);
+			name = Products;
 			sourceTree = "<group>";
 		};
 		832341AE1AAA6A7D00B99B32 /* Libraries */ = {
@@ -233,7 +251,10 @@
 				LastUpgradeCheck = 1210;
 				TargetAttributes = {
 					13B07F861A680F5B00A75B9A = {
-						LastSwiftMigration = 1120;
+						LastSwiftMigration = 1600;
+					};
+					60493BDB2D10E7E4002853A0 = {
+						LastSwiftMigration = 1600;
 					};
 				};
 			};
@@ -454,9 +475,12 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				609DDBE42D10D45500028574 /* NativeModule.mm in Sources */,
-				13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */,
-				13B07FC11A68108700A75B9A /* main.m in Sources */,
+				608868A32D1A9F070070D199 /* NativeModule.swift in Sources */,
+				608868A42D1A9F070070D199 /* ShakeEventEmitter.swift in Sources */,
+				608868AB2D1AA19B0070D199 /* NativeScreenManager.swift in Sources */,
+				608868C52D1C3D130070D199 /* ReactModulesBridge.m in Sources */,
+				608868A52D1A9F070070D199 /* AppDelegate.swift in Sources */,
+				608868B22D1AA1FB0070D199 /* CustomKeyboardDelegate.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -464,9 +488,12 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				60493BDE2D10E7E4002853A0 /* NativeModule.mm in Sources */,
-				60493BDF2D10E7E4002853A0 /* AppDelegate.mm in Sources */,
-				60493BE02D10E7E4002853A0 /* main.m in Sources */,
+				608868A02D1A9F070070D199 /* NativeModule.swift in Sources */,
+				608868A12D1A9F070070D199 /* ShakeEventEmitter.swift in Sources */,
+				608868AC2D1AA19B0070D199 /* NativeScreenManager.swift in Sources */,
+				608868C62D1C3D130070D199 /* ReactModulesBridge.m in Sources */,
+				608868A22D1A9F070070D199 /* AppDelegate.swift in Sources */,
+				608868B32D1AA1FB0070D199 /* CustomKeyboardDelegate.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -496,6 +523,7 @@
 				);
 				PRODUCT_BUNDLE_IDENTIFIER = "com.wix.detox-example";
 				PRODUCT_NAME = example;
+				SWIFT_OBJC_BRIDGING_HEADER = "example-Bridging-Header.h";
 				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
 				SWIFT_VERSION = 5.0;
 				VERSIONING_SYSTEM = "apple-generic";
@@ -524,6 +552,7 @@
 				);
 				PRODUCT_BUNDLE_IDENTIFIER = "com.wix.detox-example";
 				PRODUCT_NAME = example;
+				SWIFT_OBJC_BRIDGING_HEADER = "example-Bridging-Header.h";
 				SWIFT_VERSION = 5.0;
 				VERSIONING_SYSTEM = "apple-generic";
 			};
@@ -552,6 +581,7 @@
 				);
 				PRODUCT_BUNDLE_IDENTIFIER = "com.wix.detox-example";
 				PRODUCT_NAME = "$(TARGET_NAME)";
+				SWIFT_OBJC_BRIDGING_HEADER = "example-ci-Bridging-Header.h";
 				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
 				SWIFT_VERSION = 5.0;
 				VERSIONING_SYSTEM = "apple-generic";
@@ -580,6 +610,7 @@
 				);
 				PRODUCT_BUNDLE_IDENTIFIER = "com.wix.detox-example";
 				PRODUCT_NAME = "$(TARGET_NAME)";
+				SWIFT_OBJC_BRIDGING_HEADER = "example-ci-Bridging-Header.h";
 				SWIFT_VERSION = 5.0;
 				VERSIONING_SYSTEM = "apple-generic";
 			};
diff --git a/detox/test/ios/example/AppDelegate.h b/detox/test/ios/example/AppDelegate.h
deleted file mode 100644
index 5d2808256c..0000000000
--- a/detox/test/ios/example/AppDelegate.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#import <RCTAppDelegate.h>
-#import <UIKit/UIKit.h>
-
-@interface AppDelegate : RCTAppDelegate
-
-@end
diff --git a/detox/test/ios/example/AppDelegate.mm b/detox/test/ios/example/AppDelegate.mm
deleted file mode 100644
index fbb3aee217..0000000000
--- a/detox/test/ios/example/AppDelegate.mm
+++ /dev/null
@@ -1,108 +0,0 @@
-#import "AppDelegate.h"
-#import <React/RCTBundleURLProvider.h>
-#import <React/RCTLinkingManager.h>
-#import <UserNotifications/UserNotifications.h>
-#import <CoreSpotlight/CoreSpotlight.h>
-
-// Shake event handling
-@interface ShakeEventEmitter : RCTEventEmitter
-@end
-
-static ShakeEventEmitter* _shakeInstance;
-
-@implementation ShakeEventEmitter
-RCT_EXPORT_MODULE();
-
-- (instancetype)init {
-    self = [super init];
-    _shakeInstance = self;
-    return self;
-}
-
-- (NSArray<NSString *> *)supportedEvents {
-    return @[@"ShakeEvent"];
-}
-
-- (void)sendShakeEvent {
-    [self sendEventWithName:@"ShakeEvent" body:nil];
-}
-
-+ (BOOL)requiresMainQueueSetup {
-    return YES;
-}
-@end
-
-// Custom ViewController for shake detection
-@interface ShakeDetectViewController : UIViewController
-@property (nonatomic, weak) RCTBridge* bridge;
-@end
-
-@implementation ShakeDetectViewController
-- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event {
-    if(event.subtype == UIEventSubtypeMotionShake) {
-        [_shakeInstance sendShakeEvent];
-    }
-}
-@end
-
-@interface AppDelegate () <UNUserNotificationCenterDelegate>
-@end
-
-@implementation AppDelegate
-
-- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
-{
-    self.moduleName = @"example";
-    self.initialProps = @{};
-
-    // Setup notification delegate
-    [UNUserNotificationCenter currentNotificationCenter].delegate = self;
-
-    return [super application:application didFinishLaunchingWithOptions:launchOptions];
-}
-
-// URL scheme handling
-- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options
-{
-    return [RCTLinkingManager application:application openURL:url options:options];
-}
-
-// Universal links and Spotlight search handling
-- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void(^)(NSArray<id<UIUserActivityRestoring>> *))restorationHandler
-{
-    return [RCTLinkingManager application:application continueUserActivity:userActivity restorationHandler:restorationHandler];
-}
-
-// Push notification handling
-- (void)userNotificationCenter:(UNUserNotificationCenter *)center
-       willPresentNotification:(UNNotification *)notification
-         withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler
-{
-    completionHandler(UNNotificationPresentationOptionList |
-                      UNNotificationPresentationOptionBanner |
-                      UNNotificationPresentationOptionBadge |
-                      UNNotificationPresentationOptionSound);
-}
-
-- (void)userNotificationCenter:(UNUserNotificationCenter *)center
-didReceiveNotificationResponse:(UNNotificationResponse *)response
-         withCompletionHandler:(void (^)(void))completionHandler
-{
-    completionHandler();
-}
-
-- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
-{
-    return [self bundleURL];
-}
-
-- (NSURL *)bundleURL
-{
-#if DEBUG
-    return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
-#else
-    return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
-#endif
-}
-
-@end
diff --git a/detox/test/ios/example/main.m b/detox/test/ios/example/main.m
deleted file mode 100644
index d645c7246c..0000000000
--- a/detox/test/ios/example/main.m
+++ /dev/null
@@ -1,10 +0,0 @@
-#import <UIKit/UIKit.h>
-
-#import "AppDelegate.h"
-
-int main(int argc, char *argv[])
-{
-  @autoreleasepool {
-    return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
-  }
-}

From 28358fbcd569c0668e3a525cfdfda433edf7c92b Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Thu, 26 Dec 2024 14:13:31 +0200
Subject: [PATCH 32/51] refactor(iOS): `AppDelegate` extensions.

---
 .../AppDelegate+Notifications.swift           | 59 ++++++++++++++++++
 .../AppDelegate+Shake.swift                   | 21 +++++++
 detox/test/ios/AppDelegate.swift              | 58 +++++-------------
 detox/test/ios/UI/InAppNotificationView.swift | 60 +++++++++++++++++++
 .../ios/example.xcodeproj/project.pbxproj     | 17 ++++++
 5 files changed, 172 insertions(+), 43 deletions(-)
 create mode 100644 detox/test/ios/AppDelegate Extensions/AppDelegate+Notifications.swift
 create mode 100644 detox/test/ios/AppDelegate Extensions/AppDelegate+Shake.swift
 create mode 100644 detox/test/ios/UI/InAppNotificationView.swift

diff --git a/detox/test/ios/AppDelegate Extensions/AppDelegate+Notifications.swift b/detox/test/ios/AppDelegate Extensions/AppDelegate+Notifications.swift
new file mode 100644
index 0000000000..885673dce0
--- /dev/null
+++ b/detox/test/ios/AppDelegate Extensions/AppDelegate+Notifications.swift	
@@ -0,0 +1,59 @@
+//
+//  AppDelegate+Notifications.swift
+//  Created by Asaf Korem (Wix.com) on 2024.
+//
+
+import UserNotifications
+import UIKit
+import React
+
+extension AppDelegate: UNUserNotificationCenterDelegate {
+    func userNotificationCenter(_ center: UNUserNotificationCenter,
+                                willPresent notification: UNNotification,
+                                withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
+
+        completionHandler([.list, .banner, .badge, .sound])
+
+        let title = notification.request.content.title
+        showInAppNotification(withTitle: title)
+    }
+
+    func userNotificationCenter(_ center: UNUserNotificationCenter,
+                                didReceive response: UNNotificationResponse,
+                                withCompletionHandler completionHandler: @escaping () -> Void) {
+
+        let title = response.notification.request.content.title
+        showInAppNotification(withTitle: title)
+
+        completionHandler()
+    }
+}
+
+// MARK: - Private Helpers
+
+extension AppDelegate {
+
+    /// Displays the custom in-app notification banner on top of the React Native content view
+    private func showInAppNotification(withTitle title: String) {
+
+        let bannerView = InAppNotificationView(title: title)
+
+        guard
+            let rootView = window?.rootViewController?.view as? RCTRootView,
+            let contentView = rootView.value(forKey: "contentView") as? UIView
+        else {
+            return
+        }
+
+        contentView.addSubview(bannerView)
+
+        NSLayoutConstraint.activate([
+            bannerView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
+            bannerView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
+            bannerView.topAnchor.constraint(equalTo: contentView.safeAreaLayoutGuide.topAnchor),
+            bannerView.heightAnchor.constraint(equalToConstant: 60)
+        ])
+
+        contentView.bringSubviewToFront(bannerView)
+    }
+}
diff --git a/detox/test/ios/AppDelegate Extensions/AppDelegate+Shake.swift b/detox/test/ios/AppDelegate Extensions/AppDelegate+Shake.swift
new file mode 100644
index 0000000000..d8c1eec128
--- /dev/null
+++ b/detox/test/ios/AppDelegate Extensions/AppDelegate+Shake.swift	
@@ -0,0 +1,21 @@
+//
+//  AppDelegate+Shake.swift (example)
+//  Created by Asaf Korem (Wix.com) on 2024.
+//
+
+import UIKit
+import React
+
+extension AppDelegate {
+    override func motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
+        if motion == .motionShake {
+            if let rootView = window?.rootViewController?.view as? RCTRootView {
+                let bridge = rootView.bridge
+                let shakeModule = bridge.module(for: ShakeEventEmitter.self) as! ShakeEventEmitter
+                shakeModule.handleShake()
+            }
+        } else {
+            super.motionEnded(motion, with: event)
+        }
+    }
+}
diff --git a/detox/test/ios/AppDelegate.swift b/detox/test/ios/AppDelegate.swift
index 026c6c77c6..0461a7d0ee 100644
--- a/detox/test/ios/AppDelegate.swift
+++ b/detox/test/ios/AppDelegate.swift
@@ -1,10 +1,8 @@
 import UIKit
 import React
-import UserNotifications
 import CoreSpotlight
 
 // MARK: - App Delegate
-
 @UIApplicationMain
 @objc(AppDelegate)
 class AppDelegate: UIResponder, UIApplicationDelegate {
@@ -16,9 +14,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
 
     // MARK: - UIApplicationDelegate Methods
 
-    func application(_ application: UIApplication,
-                     didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
-
+    func application(
+        _ application: UIApplication,
+        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
+    ) -> Bool {
         setupReactNative(with: launchOptions)
         setupNotifications()
         setupScreenManager()
@@ -30,9 +29,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
 
     private func setupReactNative(with launchOptions: [UIApplication.LaunchOptionsKey: Any]?) {
         let bridge = RCTBridge(delegate: self, launchOptions: launchOptions)
-        let rootView = RCTRootView(bridge: bridge!,
-                                   moduleName: moduleName,
-                                   initialProperties: initialProps)
+        let rootView = RCTRootView(
+            bridge: bridge!,
+            moduleName: moduleName,
+            initialProperties: initialProps
+        )
         rootView.backgroundColor = .white
 
         let rootViewController = UIViewController()
@@ -44,8 +45,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
     }
 
     private func setupNotifications() {
+        // Set ourselves as the UNUserNotificationCenter delegate
         UNUserNotificationCenter.current().delegate = self
 
+        // Example: Listen for a custom "ChangeScreen" event
         NotificationCenter.default.addObserver(
             forName: Notification.Name("ChangeScreen"),
             object: nil,
@@ -60,24 +63,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
     }
 }
 
-// MARK: - Shake Gesture Handling
-
-extension AppDelegate {
-    override func motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
-        if motion == .motionShake {
-            if let rootView = window?.rootViewController?.view as? RCTRootView {
-                let bridge = rootView.bridge
-                let shakeModule = bridge.module(for: ShakeEventEmitter.self) as! ShakeEventEmitter
-                shakeModule.handleShake()
-            }
-        } else {
-            super.motionEnded(motion, with: event)
-        }
-    }
-}
-
 // MARK: - URL and Universal Links Handling
-
 extension AppDelegate {
     func application(_ app: UIApplication,
                      open url: URL,
@@ -94,23 +80,7 @@ extension AppDelegate {
     }
 }
 
-// MARK: - UNUserNotificationCenterDelegate
-extension AppDelegate: UNUserNotificationCenterDelegate {
-    func userNotificationCenter(_ center: UNUserNotificationCenter,
-                                willPresent notification: UNNotification,
-                                withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
-        completionHandler([.list, .banner, .badge, .sound])
-    }
-
-    func userNotificationCenter(_ center: UNUserNotificationCenter,
-                                didReceive response: UNNotificationResponse,
-                                withCompletionHandler completionHandler: @escaping () -> Void) {
-        completionHandler()
-    }
-}
-
 // MARK: - RCTBridgeDelegate
-
 extension AppDelegate: RCTBridgeDelegate {
     func sourceURL(for bridge: RCTBridge) -> URL? {
         return bundleURL()
@@ -118,8 +88,10 @@ extension AppDelegate: RCTBridgeDelegate {
 
     private func bundleURL() -> URL {
 #if DEBUG
-        return RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index",
-                                                                 fallbackExtension: nil)!
+        return RCTBundleURLProvider.sharedSettings().jsBundleURL(
+            forBundleRoot: "index",
+            fallbackExtension: nil
+        )!
 #else
         return Bundle.main.url(forResource: "main", withExtension: "jsbundle")!
 #endif
diff --git a/detox/test/ios/UI/InAppNotificationView.swift b/detox/test/ios/UI/InAppNotificationView.swift
new file mode 100644
index 0000000000..ee84661807
--- /dev/null
+++ b/detox/test/ios/UI/InAppNotificationView.swift
@@ -0,0 +1,60 @@
+//
+//  InAppNotificationView.swift (example)
+//  Created by Asaf Korem (Wix.com) on 2024.
+//
+
+
+import UIKit
+
+class InAppNotificationView: UIView {
+    
+    private let titleLabel: UILabel = {
+        let label = UILabel()
+        label.translatesAutoresizingMaskIntoConstraints = false
+        label.numberOfLines = 2
+        label.textAlignment = .center
+        label.textColor = .white
+        label.font = UIFont.boldSystemFont(ofSize: 16)
+        return label
+    }()
+    
+    private let closeButton: UIButton = {
+        let button = UIButton(type: .system)
+        button.translatesAutoresizingMaskIntoConstraints = false
+        button.setTitle("×", for: .normal)
+        button.titleLabel?.font = UIFont.systemFont(ofSize: 24)
+        button.setTitleColor(.white, for: .normal)
+        return button
+    }()
+    
+    // MARK: - Init
+    
+    init(title: String) {
+        super.init(frame: .zero)
+        translatesAutoresizingMaskIntoConstraints = false
+        backgroundColor = UIColor.black.withAlphaComponent(0.7)
+        
+        titleLabel.text = title
+        
+        addSubview(titleLabel)
+        addSubview(closeButton)
+        
+        NSLayoutConstraint.activate([
+            titleLabel.centerYAnchor.constraint(equalTo: centerYAnchor),
+            titleLabel.centerXAnchor.constraint(equalTo: centerXAnchor),
+            
+            closeButton.topAnchor.constraint(equalTo: topAnchor, constant: 5),
+            closeButton.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -10),
+        ])
+        
+        closeButton.addTarget(self, action: #selector(didTapClose), for: .touchUpInside)
+    }
+    
+    @objc private func didTapClose() {
+        removeFromSuperview()
+    }
+    
+    required init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+}
diff --git a/detox/test/ios/example.xcodeproj/project.pbxproj b/detox/test/ios/example.xcodeproj/project.pbxproj
index fcf919e2c3..407b2bb788 100644
--- a/detox/test/ios/example.xcodeproj/project.pbxproj
+++ b/detox/test/ios/example.xcodeproj/project.pbxproj
@@ -24,6 +24,8 @@
 		608868B32D1AA1FB0070D199 /* CustomKeyboardDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 608868B02D1AA1FB0070D199 /* CustomKeyboardDelegate.swift */; };
 		608868C52D1C3D130070D199 /* ReactModulesBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 608868C42D1C3D0E0070D199 /* ReactModulesBridge.m */; };
 		608868C62D1C3D130070D199 /* ReactModulesBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 608868C42D1C3D0E0070D199 /* ReactModulesBridge.m */; };
+		608868D22D1D696E0070D199 /* InAppNotificationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 608868D12D1D696E0070D199 /* InAppNotificationView.swift */; };
+		608868D32D1D696E0070D199 /* InAppNotificationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 608868D12D1D696E0070D199 /* InAppNotificationView.swift */; };
 		609DDB892D10C21800028574 /* Detox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 609DDB852D10C20800028574 /* Detox.framework */; };
 		81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
 		90CCD0BA1322566EB1285DC2 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */; };
@@ -69,6 +71,7 @@
 		608868AA2D1AA19B0070D199 /* NativeScreenManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NativeScreenManager.swift; sourceTree = "<group>"; };
 		608868B02D1AA1FB0070D199 /* CustomKeyboardDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomKeyboardDelegate.swift; sourceTree = "<group>"; };
 		608868C42D1C3D0E0070D199 /* ReactModulesBridge.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ReactModulesBridge.m; sourceTree = "<group>"; };
+		608868D12D1D696E0070D199 /* InAppNotificationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InAppNotificationView.swift; sourceTree = "<group>"; };
 		609DDB772D10C20700028574 /* Detox.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Detox.xcodeproj; path = /Users/asafk/Development/Detox/detox/ios/Detox.xcodeproj; sourceTree = "<absolute>"; };
 		80C930B7D5D6C25DA27372A5 /* Pods-example-ci.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example-ci.release.xcconfig"; path = "Target Support Files/Pods-example-ci/Pods-example-ci.release.xcconfig"; sourceTree = "<group>"; };
 		81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = example/LaunchScreen.storyboard; sourceTree = "<group>"; };
@@ -76,6 +79,10 @@
 		ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
 /* End PBXFileReference section */
 
+/* Begin PBXFileSystemSynchronizedRootGroup section */
+		608868CB2D1D67DA0070D199 /* AppDelegate Extensions */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = "AppDelegate Extensions"; sourceTree = "<group>"; };
+/* End PBXFileSystemSynchronizedRootGroup section */
+
 /* Begin PBXFrameworksBuildPhase section */
 		13B07F8C1A680F5B00A75B9A /* Frameworks */ = {
 			isa = PBXFrameworksBuildPhase;
@@ -101,6 +108,7 @@
 			isa = PBXGroup;
 			children = (
 				6088689A2D1A9F070070D199 /* AppDelegate.swift */,
+				608868CB2D1D67DA0070D199 /* AppDelegate Extensions */,
 				60493BD72D10D967002853A0 /* example.entitlements */,
 				6088689B2D1A9F070070D199 /* example-Bridging-Header.h */,
 				6088689C2D1A9F070070D199 /* example-ci-Bridging-Header.h */,
@@ -138,6 +146,7 @@
 		608868B12D1AA1FB0070D199 /* UI */ = {
 			isa = PBXGroup;
 			children = (
+				608868D12D1D696E0070D199 /* InAppNotificationView.swift */,
 				608868B02D1AA1FB0070D199 /* CustomKeyboardDelegate.swift */,
 				608868AA2D1AA19B0070D199 /* NativeScreenManager.swift */,
 			);
@@ -216,6 +225,9 @@
 			);
 			dependencies = (
 			);
+			fileSystemSynchronizedGroups = (
+				608868CB2D1D67DA0070D199 /* AppDelegate Extensions */,
+			);
 			name = example;
 			productName = example;
 			productReference = 13B07F961A680F5B00A75B9A /* example.app */;
@@ -237,6 +249,9 @@
 			);
 			dependencies = (
 			);
+			fileSystemSynchronizedGroups = (
+				608868CB2D1D67DA0070D199 /* AppDelegate Extensions */,
+			);
 			name = "example-ci";
 			productName = example;
 			productReference = 60493BEE2D10E7E4002853A0 /* example-ci.app */;
@@ -479,6 +494,7 @@
 				608868A42D1A9F070070D199 /* ShakeEventEmitter.swift in Sources */,
 				608868AB2D1AA19B0070D199 /* NativeScreenManager.swift in Sources */,
 				608868C52D1C3D130070D199 /* ReactModulesBridge.m in Sources */,
+				608868D32D1D696E0070D199 /* InAppNotificationView.swift in Sources */,
 				608868A52D1A9F070070D199 /* AppDelegate.swift in Sources */,
 				608868B22D1AA1FB0070D199 /* CustomKeyboardDelegate.swift in Sources */,
 			);
@@ -492,6 +508,7 @@
 				608868A12D1A9F070070D199 /* ShakeEventEmitter.swift in Sources */,
 				608868AC2D1AA19B0070D199 /* NativeScreenManager.swift in Sources */,
 				608868C62D1C3D130070D199 /* ReactModulesBridge.m in Sources */,
+				608868D22D1D696E0070D199 /* InAppNotificationView.swift in Sources */,
 				608868A22D1A9F070070D199 /* AppDelegate.swift in Sources */,
 				608868B32D1AA1FB0070D199 /* CustomKeyboardDelegate.swift in Sources */,
 			);

From 4dbe3c403e72f3028477d7774bbe81c8d9dee3d0 Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Sun, 29 Dec 2024 18:57:39 +0200
Subject: [PATCH 33/51] fix: support background searchable items.

---
 .../AppDelegate+ApplicationState.swift        | 43 +++++++++++++
 .../AppDelegate+Linking.swift                 | 42 +++++++++++++
 .../AppDelegate+Notifications.swift           | 33 +---------
 .../AppDelegate+OverlayView.swift             | 32 ++++++++++
 detox/test/ios/AppDelegate.swift              | 19 +-----
 ...ionView.swift => OverlayMessageView.swift} | 57 +++++++++--------
 .../ios/example.xcodeproj/project.pbxproj     | 61 +++++++++++++------
 7 files changed, 197 insertions(+), 90 deletions(-)
 create mode 100644 detox/test/ios/AppDelegate Extensions/AppDelegate+ApplicationState.swift
 create mode 100644 detox/test/ios/AppDelegate Extensions/AppDelegate+Linking.swift
 create mode 100644 detox/test/ios/AppDelegate Extensions/AppDelegate+OverlayView.swift
 rename detox/test/ios/UI/{InAppNotificationView.swift => OverlayMessageView.swift} (59%)

diff --git a/detox/test/ios/AppDelegate Extensions/AppDelegate+ApplicationState.swift b/detox/test/ios/AppDelegate Extensions/AppDelegate+ApplicationState.swift
new file mode 100644
index 0000000000..205c368c05
--- /dev/null
+++ b/detox/test/ios/AppDelegate Extensions/AppDelegate+ApplicationState.swift	
@@ -0,0 +1,43 @@
+//
+//  AppDelegate+ApplicationState.swift (example)
+//  Created by Asaf Korem (Wix.com) on 2024.
+//
+
+import UIKit
+
+extension AppDelegate {
+    func setupApplicationStateObservers() {
+        NotificationCenter.default.addObserver(
+            self,
+            selector: #selector(applicationDidBecomeActive),
+            name: UIApplication.didBecomeActiveNotification,
+            object: nil
+        )
+
+        NotificationCenter.default.addObserver(
+            self,
+            selector: #selector(applicationWillResignActive),
+            name: UIApplication.willResignActiveNotification,
+            object: nil
+        )
+
+        NotificationCenter.default.addObserver(
+            self,
+            selector: #selector(applicationDidEnterBackground),
+            name: UIApplication.didEnterBackgroundNotification,
+            object: nil
+        )
+    }
+
+    @objc private func applicationDidBecomeActive() {
+        showOverlayMessage(withMessage: "Active")
+    }
+
+    @objc private func applicationWillResignActive() {
+        showOverlayMessage(withMessage: "Inactive")
+    }
+
+    @objc private func applicationDidEnterBackground() {
+        showOverlayMessage(withMessage: "Background")
+    }
+}
diff --git a/detox/test/ios/AppDelegate Extensions/AppDelegate+Linking.swift b/detox/test/ios/AppDelegate Extensions/AppDelegate+Linking.swift
new file mode 100644
index 0000000000..11de67b62b
--- /dev/null
+++ b/detox/test/ios/AppDelegate Extensions/AppDelegate+Linking.swift	
@@ -0,0 +1,42 @@
+//
+//  AppDelegate+Linking.swift (example)
+//  Created by Asaf Korem (Wix.com) on 2024.
+//
+
+import UIKit
+import React
+import CoreSpotlight
+
+// MARK: - URL and Universal Links Handling
+extension AppDelegate {
+    func application(
+        _ app: UIApplication,
+        open url: URL,
+        options: [UIApplication.OpenURLOptionsKey : Any] = [:]
+    ) -> Bool {
+        return RCTLinkingManager.application(app, open: url, options: options)
+    }
+
+    func application(
+        _ application: UIApplication,
+        continue userActivity: NSUserActivity,
+        restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void
+    ) -> Bool {
+        if userActivity.activityType == CSSearchableItemActionType {
+            if let identifier = userActivity.userInfo?[CSSearchableItemActivityIdentifier] as? String,
+               let url = URL(string: "\(identifier)") {
+
+                let customOptions: [UIApplication.OpenURLOptionsKey: Any] = [
+                    .sourceApplication: "",
+                    .annotation: [:]
+                ]
+
+                return RCTLinkingManager.application(application, open: url, options: customOptions)
+            } else {
+                return false
+            }
+        }
+
+        return RCTLinkingManager.application(application, continue: userActivity, restorationHandler: restorationHandler)
+    }
+}
diff --git a/detox/test/ios/AppDelegate Extensions/AppDelegate+Notifications.swift b/detox/test/ios/AppDelegate Extensions/AppDelegate+Notifications.swift
index 885673dce0..b4d7740c79 100644
--- a/detox/test/ios/AppDelegate Extensions/AppDelegate+Notifications.swift	
+++ b/detox/test/ios/AppDelegate Extensions/AppDelegate+Notifications.swift	
@@ -15,7 +15,7 @@ extension AppDelegate: UNUserNotificationCenterDelegate {
         completionHandler([.list, .banner, .badge, .sound])
 
         let title = notification.request.content.title
-        showInAppNotification(withTitle: title)
+        showOverlayMessage(withMessage: title)
     }
 
     func userNotificationCenter(_ center: UNUserNotificationCenter,
@@ -23,37 +23,8 @@ extension AppDelegate: UNUserNotificationCenterDelegate {
                                 withCompletionHandler completionHandler: @escaping () -> Void) {
 
         let title = response.notification.request.content.title
-        showInAppNotification(withTitle: title)
+        showOverlayMessage(withMessage: title)
 
         completionHandler()
     }
 }
-
-// MARK: - Private Helpers
-
-extension AppDelegate {
-
-    /// Displays the custom in-app notification banner on top of the React Native content view
-    private func showInAppNotification(withTitle title: String) {
-
-        let bannerView = InAppNotificationView(title: title)
-
-        guard
-            let rootView = window?.rootViewController?.view as? RCTRootView,
-            let contentView = rootView.value(forKey: "contentView") as? UIView
-        else {
-            return
-        }
-
-        contentView.addSubview(bannerView)
-
-        NSLayoutConstraint.activate([
-            bannerView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
-            bannerView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
-            bannerView.topAnchor.constraint(equalTo: contentView.safeAreaLayoutGuide.topAnchor),
-            bannerView.heightAnchor.constraint(equalToConstant: 60)
-        ])
-
-        contentView.bringSubviewToFront(bannerView)
-    }
-}
diff --git a/detox/test/ios/AppDelegate Extensions/AppDelegate+OverlayView.swift b/detox/test/ios/AppDelegate Extensions/AppDelegate+OverlayView.swift
new file mode 100644
index 0000000000..49c19e1707
--- /dev/null
+++ b/detox/test/ios/AppDelegate Extensions/AppDelegate+OverlayView.swift	
@@ -0,0 +1,32 @@
+//
+//  AppDelegate+OverlayView.swift (example)
+//  Created by Asaf Korem (Wix.com) on 2024.
+//
+
+
+import UIKit
+import React
+
+extension AppDelegate {
+    func showOverlayMessage(withMessage message: String) {
+        guard
+            let rootView = window?.rootViewController?.view as? RCTRootView,
+            let contentView = rootView.value(forKey: "contentView") as? UIView
+        else {
+            return
+        }
+
+        let messageView = OverlayMessageView(message: message)
+        contentView.addSubview(messageView)
+
+        NSLayoutConstraint.activate([
+            messageView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
+            messageView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
+            messageView.topAnchor.constraint(equalTo: contentView.safeAreaLayoutGuide.topAnchor),
+            messageView.heightAnchor.constraint(equalToConstant: 60)
+        ])
+
+        contentView.bringSubviewToFront(messageView)
+    }
+}
+
diff --git a/detox/test/ios/AppDelegate.swift b/detox/test/ios/AppDelegate.swift
index 0461a7d0ee..e78726e852 100644
--- a/detox/test/ios/AppDelegate.swift
+++ b/detox/test/ios/AppDelegate.swift
@@ -1,6 +1,5 @@
 import UIKit
 import React
-import CoreSpotlight
 
 // MARK: - App Delegate
 @UIApplicationMain
@@ -21,6 +20,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
         setupReactNative(with: launchOptions)
         setupNotifications()
         setupScreenManager()
+        setupApplicationStateObservers()
 
         return true
     }
@@ -63,23 +63,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
     }
 }
 
-// MARK: - URL and Universal Links Handling
-extension AppDelegate {
-    func application(_ app: UIApplication,
-                     open url: URL,
-                     options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
-        return RCTLinkingManager.application(app, open: url, options: options)
-    }
-
-    func application(_ application: UIApplication,
-                     continue userActivity: NSUserActivity,
-                     restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
-        return RCTLinkingManager.application(application,
-                                             continue: userActivity,
-                                             restorationHandler: restorationHandler)
-    }
-}
-
 // MARK: - RCTBridgeDelegate
 extension AppDelegate: RCTBridgeDelegate {
     func sourceURL(for bridge: RCTBridge) -> URL? {
diff --git a/detox/test/ios/UI/InAppNotificationView.swift b/detox/test/ios/UI/OverlayMessageView.swift
similarity index 59%
rename from detox/test/ios/UI/InAppNotificationView.swift
rename to detox/test/ios/UI/OverlayMessageView.swift
index ee84661807..c20b4448b6 100644
--- a/detox/test/ios/UI/InAppNotificationView.swift
+++ b/detox/test/ios/UI/OverlayMessageView.swift
@@ -1,14 +1,13 @@
 //
-//  InAppNotificationView.swift (example)
+//  OverlayMessageView.swift (example)
 //  Created by Asaf Korem (Wix.com) on 2024.
 //
 
-
 import UIKit
 
-class InAppNotificationView: UIView {
-    
-    private let titleLabel: UILabel = {
+class OverlayMessageView: UIView {
+
+    private let messageLabel: UILabel = {
         let label = UILabel()
         label.translatesAutoresizingMaskIntoConstraints = false
         label.numberOfLines = 2
@@ -17,7 +16,7 @@ class InAppNotificationView: UIView {
         label.font = UIFont.boldSystemFont(ofSize: 16)
         return label
     }()
-    
+
     private let closeButton: UIButton = {
         let button = UIButton(type: .system)
         button.translatesAutoresizingMaskIntoConstraints = false
@@ -26,35 +25,45 @@ class InAppNotificationView: UIView {
         button.setTitleColor(.white, for: .normal)
         return button
     }()
-    
-    // MARK: - Init
-    
-    init(title: String) {
+
+    init(message: String) {
         super.init(frame: .zero)
+        setup(with: message)
+    }
+
+    required init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+
+    private func setup(with message: String) {
         translatesAutoresizingMaskIntoConstraints = false
         backgroundColor = UIColor.black.withAlphaComponent(0.7)
-        
-        titleLabel.text = title
-        
-        addSubview(titleLabel)
+
+        messageLabel.text = message
+
+        addSubview(messageLabel)
         addSubview(closeButton)
-        
+
         NSLayoutConstraint.activate([
-            titleLabel.centerYAnchor.constraint(equalTo: centerYAnchor),
-            titleLabel.centerXAnchor.constraint(equalTo: centerXAnchor),
-            
+            messageLabel.centerYAnchor.constraint(equalTo: centerYAnchor),
+            messageLabel.centerXAnchor.constraint(equalTo: centerXAnchor),
+            messageLabel.leadingAnchor.constraint(greaterThanOrEqualTo: leadingAnchor, constant: 40),
+            messageLabel.trailingAnchor.constraint(lessThanOrEqualTo: trailingAnchor, constant: -40),
+
             closeButton.topAnchor.constraint(equalTo: topAnchor, constant: 5),
             closeButton.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -10),
+            closeButton.widthAnchor.constraint(equalToConstant: 30),
+            closeButton.heightAnchor.constraint(equalToConstant: 30)
         ])
-        
+
         closeButton.addTarget(self, action: #selector(didTapClose), for: .touchUpInside)
+
+        Timer.scheduledTimer(withTimeInterval: 1.0, repeats: false) { [weak self] _ in
+            self?.removeFromSuperview()
+        }
     }
-    
+
     @objc private func didTapClose() {
         removeFromSuperview()
     }
-    
-    required init?(coder: NSCoder) {
-        fatalError("init(coder:) has not been implemented")
-    }
 }
diff --git a/detox/test/ios/example.xcodeproj/project.pbxproj b/detox/test/ios/example.xcodeproj/project.pbxproj
index 407b2bb788..7a4fe3d392 100644
--- a/detox/test/ios/example.xcodeproj/project.pbxproj
+++ b/detox/test/ios/example.xcodeproj/project.pbxproj
@@ -24,9 +24,19 @@
 		608868B32D1AA1FB0070D199 /* CustomKeyboardDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 608868B02D1AA1FB0070D199 /* CustomKeyboardDelegate.swift */; };
 		608868C52D1C3D130070D199 /* ReactModulesBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 608868C42D1C3D0E0070D199 /* ReactModulesBridge.m */; };
 		608868C62D1C3D130070D199 /* ReactModulesBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 608868C42D1C3D0E0070D199 /* ReactModulesBridge.m */; };
-		608868D22D1D696E0070D199 /* InAppNotificationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 608868D12D1D696E0070D199 /* InAppNotificationView.swift */; };
-		608868D32D1D696E0070D199 /* InAppNotificationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 608868D12D1D696E0070D199 /* InAppNotificationView.swift */; };
+		608868D22D1D696E0070D199 /* OverlayMessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 608868D12D1D696E0070D199 /* OverlayMessageView.swift */; };
+		608868D32D1D696E0070D199 /* OverlayMessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 608868D12D1D696E0070D199 /* OverlayMessageView.swift */; };
 		609DDB892D10C21800028574 /* Detox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 609DDB852D10C20800028574 /* Detox.framework */; };
+		60E207962D21B0B400E6DBD2 /* AppDelegate+ApplicationState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60E207902D21B0B400E6DBD2 /* AppDelegate+ApplicationState.swift */; };
+		60E207972D21B0B400E6DBD2 /* AppDelegate+Linking.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60E207912D21B0B400E6DBD2 /* AppDelegate+Linking.swift */; };
+		60E207982D21B0B400E6DBD2 /* AppDelegate+Notifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60E207922D21B0B400E6DBD2 /* AppDelegate+Notifications.swift */; };
+		60E207992D21B0B400E6DBD2 /* AppDelegate+OverlayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60E207932D21B0B400E6DBD2 /* AppDelegate+OverlayView.swift */; };
+		60E2079A2D21B0B400E6DBD2 /* AppDelegate+Shake.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60E207942D21B0B400E6DBD2 /* AppDelegate+Shake.swift */; };
+		60E2079B2D21B0B400E6DBD2 /* AppDelegate+ApplicationState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60E207902D21B0B400E6DBD2 /* AppDelegate+ApplicationState.swift */; };
+		60E2079C2D21B0B400E6DBD2 /* AppDelegate+Linking.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60E207912D21B0B400E6DBD2 /* AppDelegate+Linking.swift */; };
+		60E2079D2D21B0B400E6DBD2 /* AppDelegate+Notifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60E207922D21B0B400E6DBD2 /* AppDelegate+Notifications.swift */; };
+		60E2079E2D21B0B400E6DBD2 /* AppDelegate+OverlayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60E207932D21B0B400E6DBD2 /* AppDelegate+OverlayView.swift */; };
+		60E2079F2D21B0B400E6DBD2 /* AppDelegate+Shake.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60E207942D21B0B400E6DBD2 /* AppDelegate+Shake.swift */; };
 		81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
 		90CCD0BA1322566EB1285DC2 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */; };
 		CA25A6405AF58BA742F7FD47 /* libPods-example-ci.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1CB0FE045763B5363B2E7054 /* libPods-example-ci.a */; };
@@ -71,18 +81,19 @@
 		608868AA2D1AA19B0070D199 /* NativeScreenManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NativeScreenManager.swift; sourceTree = "<group>"; };
 		608868B02D1AA1FB0070D199 /* CustomKeyboardDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomKeyboardDelegate.swift; sourceTree = "<group>"; };
 		608868C42D1C3D0E0070D199 /* ReactModulesBridge.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ReactModulesBridge.m; sourceTree = "<group>"; };
-		608868D12D1D696E0070D199 /* InAppNotificationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InAppNotificationView.swift; sourceTree = "<group>"; };
+		608868D12D1D696E0070D199 /* OverlayMessageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverlayMessageView.swift; sourceTree = "<group>"; };
 		609DDB772D10C20700028574 /* Detox.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Detox.xcodeproj; path = /Users/asafk/Development/Detox/detox/ios/Detox.xcodeproj; sourceTree = "<absolute>"; };
+		60E207902D21B0B400E6DBD2 /* AppDelegate+ApplicationState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppDelegate+ApplicationState.swift"; sourceTree = "<group>"; };
+		60E207912D21B0B400E6DBD2 /* AppDelegate+Linking.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppDelegate+Linking.swift"; sourceTree = "<group>"; };
+		60E207922D21B0B400E6DBD2 /* AppDelegate+Notifications.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppDelegate+Notifications.swift"; sourceTree = "<group>"; };
+		60E207932D21B0B400E6DBD2 /* AppDelegate+OverlayView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppDelegate+OverlayView.swift"; sourceTree = "<group>"; };
+		60E207942D21B0B400E6DBD2 /* AppDelegate+Shake.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppDelegate+Shake.swift"; sourceTree = "<group>"; };
 		80C930B7D5D6C25DA27372A5 /* Pods-example-ci.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example-ci.release.xcconfig"; path = "Target Support Files/Pods-example-ci/Pods-example-ci.release.xcconfig"; sourceTree = "<group>"; };
 		81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = example/LaunchScreen.storyboard; sourceTree = "<group>"; };
 		89C6BE57DB24E9ADA2F236DE /* Pods-example-exampleTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example-exampleTests.release.xcconfig"; path = "Target Support Files/Pods-example-exampleTests/Pods-example-exampleTests.release.xcconfig"; sourceTree = "<group>"; };
 		ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
 /* End PBXFileReference section */
 
-/* Begin PBXFileSystemSynchronizedRootGroup section */
-		608868CB2D1D67DA0070D199 /* AppDelegate Extensions */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = "AppDelegate Extensions"; sourceTree = "<group>"; };
-/* End PBXFileSystemSynchronizedRootGroup section */
-
 /* Begin PBXFrameworksBuildPhase section */
 		13B07F8C1A680F5B00A75B9A /* Frameworks */ = {
 			isa = PBXFrameworksBuildPhase;
@@ -108,7 +119,7 @@
 			isa = PBXGroup;
 			children = (
 				6088689A2D1A9F070070D199 /* AppDelegate.swift */,
-				608868CB2D1D67DA0070D199 /* AppDelegate Extensions */,
+				60E207952D21B0B400E6DBD2 /* AppDelegate Extensions */,
 				60493BD72D10D967002853A0 /* example.entitlements */,
 				6088689B2D1A9F070070D199 /* example-Bridging-Header.h */,
 				6088689C2D1A9F070070D199 /* example-ci-Bridging-Header.h */,
@@ -146,9 +157,9 @@
 		608868B12D1AA1FB0070D199 /* UI */ = {
 			isa = PBXGroup;
 			children = (
-				608868D12D1D696E0070D199 /* InAppNotificationView.swift */,
 				608868B02D1AA1FB0070D199 /* CustomKeyboardDelegate.swift */,
 				608868AA2D1AA19B0070D199 /* NativeScreenManager.swift */,
+				608868D12D1D696E0070D199 /* OverlayMessageView.swift */,
 			);
 			path = UI;
 			sourceTree = "<group>";
@@ -162,6 +173,18 @@
 			name = Products;
 			sourceTree = "<group>";
 		};
+		60E207952D21B0B400E6DBD2 /* AppDelegate Extensions */ = {
+			isa = PBXGroup;
+			children = (
+				60E207902D21B0B400E6DBD2 /* AppDelegate+ApplicationState.swift */,
+				60E207912D21B0B400E6DBD2 /* AppDelegate+Linking.swift */,
+				60E207922D21B0B400E6DBD2 /* AppDelegate+Notifications.swift */,
+				60E207932D21B0B400E6DBD2 /* AppDelegate+OverlayView.swift */,
+				60E207942D21B0B400E6DBD2 /* AppDelegate+Shake.swift */,
+			);
+			path = "AppDelegate Extensions";
+			sourceTree = "<group>";
+		};
 		832341AE1AAA6A7D00B99B32 /* Libraries */ = {
 			isa = PBXGroup;
 			children = (
@@ -225,9 +248,6 @@
 			);
 			dependencies = (
 			);
-			fileSystemSynchronizedGroups = (
-				608868CB2D1D67DA0070D199 /* AppDelegate Extensions */,
-			);
 			name = example;
 			productName = example;
 			productReference = 13B07F961A680F5B00A75B9A /* example.app */;
@@ -249,9 +269,6 @@
 			);
 			dependencies = (
 			);
-			fileSystemSynchronizedGroups = (
-				608868CB2D1D67DA0070D199 /* AppDelegate Extensions */,
-			);
 			name = "example-ci";
 			productName = example;
 			productReference = 60493BEE2D10E7E4002853A0 /* example-ci.app */;
@@ -490,11 +507,16 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				60E207962D21B0B400E6DBD2 /* AppDelegate+ApplicationState.swift in Sources */,
+				60E207972D21B0B400E6DBD2 /* AppDelegate+Linking.swift in Sources */,
+				60E207982D21B0B400E6DBD2 /* AppDelegate+Notifications.swift in Sources */,
+				60E207992D21B0B400E6DBD2 /* AppDelegate+OverlayView.swift in Sources */,
+				60E2079A2D21B0B400E6DBD2 /* AppDelegate+Shake.swift in Sources */,
 				608868A32D1A9F070070D199 /* NativeModule.swift in Sources */,
 				608868A42D1A9F070070D199 /* ShakeEventEmitter.swift in Sources */,
 				608868AB2D1AA19B0070D199 /* NativeScreenManager.swift in Sources */,
 				608868C52D1C3D130070D199 /* ReactModulesBridge.m in Sources */,
-				608868D32D1D696E0070D199 /* InAppNotificationView.swift in Sources */,
+				608868D32D1D696E0070D199 /* OverlayMessageView.swift in Sources */,
 				608868A52D1A9F070070D199 /* AppDelegate.swift in Sources */,
 				608868B22D1AA1FB0070D199 /* CustomKeyboardDelegate.swift in Sources */,
 			);
@@ -504,11 +526,16 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				60E2079B2D21B0B400E6DBD2 /* AppDelegate+ApplicationState.swift in Sources */,
+				60E2079C2D21B0B400E6DBD2 /* AppDelegate+Linking.swift in Sources */,
+				60E2079D2D21B0B400E6DBD2 /* AppDelegate+Notifications.swift in Sources */,
+				60E2079E2D21B0B400E6DBD2 /* AppDelegate+OverlayView.swift in Sources */,
+				60E2079F2D21B0B400E6DBD2 /* AppDelegate+Shake.swift in Sources */,
 				608868A02D1A9F070070D199 /* NativeModule.swift in Sources */,
 				608868A12D1A9F070070D199 /* ShakeEventEmitter.swift in Sources */,
 				608868AC2D1AA19B0070D199 /* NativeScreenManager.swift in Sources */,
 				608868C62D1C3D130070D199 /* ReactModulesBridge.m in Sources */,
-				608868D22D1D696E0070D199 /* InAppNotificationView.swift in Sources */,
+				608868D22D1D696E0070D199 /* OverlayMessageView.swift in Sources */,
 				608868A22D1A9F070070D199 /* AppDelegate.swift in Sources */,
 				608868B32D1AA1FB0070D199 /* CustomKeyboardDelegate.swift in Sources */,
 			);

From 35ba68ab714324c26f1bab3201c46f452ba1be32 Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Sun, 29 Dec 2024 19:23:59 +0200
Subject: [PATCH 34/51] chore: update detox-copilot cache.

---
 detox/test/detox_copilot_cache.json | 41 ++++++++++++++++++++++++++++-
 1 file changed, 40 insertions(+), 1 deletion(-)

diff --git a/detox/test/detox_copilot_cache.json b/detox/test/detox_copilot_cache.json
index 531ac66dfb..8bb236eae7 100644
--- a/detox/test/detox_copilot_cache.json
+++ b/detox/test/detox_copilot_cache.json
@@ -66,5 +66,44 @@
   "{\"step\":\"Enable the second WebView\",\"previous\":[{\"step\":\"Restart the React Native state\",\"code\":\"await device.reloadReactNative();\"},{\"step\":\"Navigate to the WebView screen\",\"code\":\"await element(by.text('WebView')).tap();\"}],\"viewHierarchyHash\":\"b8835bc4182c98f0bb33470103592e88\"}": "await element(by.id('toggle2ndWebviewButton')).tap();",
   "{\"step\":\"In the second WebView, verify the headline has the message \\\"This is a dummy webview.\\\"\",\"previous\":[{\"step\":\"Restart the React Native state\",\"code\":\"await device.reloadReactNative();\"},{\"step\":\"Navigate to the WebView screen\",\"code\":\"await element(by.text('WebView')).tap();\"},{\"step\":\"Enable the second WebView\",\"code\":\"await element(by.id('toggle2ndWebviewButton')).tap();\"}],\"viewHierarchyHash\":\"32e8fc9416dc1fc3aee3dbb0d1ce2e32\"}": "await expect(web.element(by.web.id('message'))).toHaveText('This is a dummy webview.');",
   "{\"step\":\"In the second WebView, verify the headline has the message \\\"This is a dummy webview.\\\"\",\"previous\":[{\"step\":\"Restart the React Native state\",\"code\":\"await device.reloadReactNative();\"},{\"step\":\"Navigate to the WebView screen\",\"code\":\"await element(by.text('WebView')).tap();\"},{\"step\":\"Enable the second WebView\",\"code\":\"await element(by.id('toggle2ndWebviewButton')).tap();\"},{\"step\":\"In the second WebView, verify the headline has the message \\\"This is a dummy webview.\\\"\",\"code\":\"await expect(web.element(by.web.id('message'))).toHaveText('This is a dummy webview.');\",\"result\":\"Caught an error while evaluating \\\"In the second WebView, verify the headline has the message \\\"This is a dummy webview.\\\"\\\", tried with generated code: \\\"await expect(web.element(by.web.id('message'))).toHaveText('This is a dummy webview.');\\\". Validate the code against the APIs and hierarchy and continue with a different approach. If can't, return a code that throws a descriptive error.\"}],\"viewHierarchyHash\":\"32e8fc9416dc1fc3aee3dbb0d1ce2e32\"}": "`await expect(web.element(by.web.id('message'))).toHaveText('This is a dummy webview.');`",
-  "{\"step\":\"Hide the second WebView\",\"previous\":[{\"step\":\"Restart the React Native state\",\"code\":\"await device.reloadReactNative();\"},{\"step\":\"Navigate to the WebView screen\",\"code\":\"await element(by.text('WebView')).tap();\"},{\"step\":\"Enable the second WebView\",\"code\":\"await element(by.id('toggle2ndWebviewButton')).tap();\"},{\"step\":\"In the second WebView, verify the headline has the message \\\"This is a dummy webview.\\\"\",\"code\":\"`await expect(web.element(by.web.id('message'))).toHaveText('This is a dummy webview.');`\"}],\"viewHierarchyHash\":\"32e8fc9416dc1fc3aee3dbb0d1ce2e32\"}": "await element(by.id('toggle2ndWebviewButton')).tap();"
+  "{\"step\":\"Hide the second WebView\",\"previous\":[{\"step\":\"Restart the React Native state\",\"code\":\"await device.reloadReactNative();\"},{\"step\":\"Navigate to the WebView screen\",\"code\":\"await element(by.text('WebView')).tap();\"},{\"step\":\"Enable the second WebView\",\"code\":\"await element(by.id('toggle2ndWebviewButton')).tap();\"},{\"step\":\"In the second WebView, verify the headline has the message \\\"This is a dummy webview.\\\"\",\"code\":\"`await expect(web.element(by.web.id('message'))).toHaveText('This is a dummy webview.');`\"}],\"viewHierarchyHash\":\"32e8fc9416dc1fc3aee3dbb0d1ce2e32\"}": "await element(by.id('toggle2ndWebviewButton')).tap();",
+  "{\"step\":\"Restart the React Native environment\",\"previous\":[],\"viewHierarchyHash\":\"7f840438086fdf188cb1ec5f909a8cfa\"}": "await device.reloadReactNative();",
+  "{\"step\":\"Go to the Actions screen\",\"previous\":[{\"step\":\"Restart the React Native environment\",\"code\":\"await device.reloadReactNative();\"}],\"viewHierarchyHash\":\"74f6292e255463a732384a5649407ee5\"}": "await element(by.text('Actions')).tap();",
+  "{\"step\":\"Tap the return key on the keyboard for the text input\",\"previous\":[{\"step\":\"Restart the React Native environment\",\"code\":\"await device.reloadReactNative();\"},{\"step\":\"Go to the Actions screen\",\"code\":\"await element(by.text('Actions')).tap();\"}],\"viewHierarchyHash\":\"bb425e9320101560c151b2d020ce77b7\"}": "throw new Error(\"Multiple text inputs found in view hierarchy. Please specify which text input should receive the return key tap action.\");",
+  "{\"step\":\"Tap the return key on the keyboard for the text input\",\"previous\":[{\"step\":\"Restart the React Native environment\",\"code\":\"await device.reloadReactNative();\"},{\"step\":\"Go to the Actions screen\",\"code\":\"await element(by.text('Actions')).tap();\"},{\"step\":\"Tap the return key on the keyboard for the text input\",\"code\":\"throw new Error(\\\"Multiple text inputs found in view hierarchy. Please specify which text input should receive the return key tap action.\\\");\",\"result\":\"Caught an error while evaluating \\\"Tap the return key on the keyboard for the text input\\\", tried with generated code: \\\"throw new Error(\\\"Multiple text inputs found in view hierarchy. Please specify which text input should receive the return key tap action.\\\");\\\". Validate the code against the APIs and hierarchy and continue with a different approach. If can't, return a code that throws a descriptive error.\"}],\"viewHierarchyHash\":\"bb425e9320101560c151b2d020ce77b7\"}": "throw new Error(\"Multiple text inputs found in the view hierarchy. Please specify which text input should receive the return key tap action.\");",
+  "{\"step\":\"Restart the React Native environment\",\"previous\":[],\"viewHierarchyHash\":\"70ca2d5c905bc2b6a32e3cda69a7aa33\"}": "await device.reloadReactNative();",
+  "{\"step\":\"The element with text \\\"Text1\\\" can be seen\",\"previous\":[{\"step\":\"Restart the React Native environment\",\"code\":\"await device.reloadReactNative();\"},{\"step\":\"Go to the Actions screen\",\"code\":\"await element(by.text('Actions')).tap();\"}],\"viewHierarchyHash\":\"bb425e9320101560c151b2d020ce77b7\"}": "await expect(element(by.text('Text1'))).toBeVisible();",
+  "{\"step\":\"Swipe the view \\\"ScrollView161\\\" upwards\",\"previous\":[{\"step\":\"Restart the React Native environment\",\"code\":\"await device.reloadReactNative();\"},{\"step\":\"Go to the Actions screen\",\"code\":\"await element(by.text('Actions')).tap();\"},{\"step\":\"The element with text \\\"Text1\\\" can be seen\",\"code\":\"await expect(element(by.text('Text1'))).toBeVisible();\"}],\"viewHierarchyHash\":\"bb425e9320101560c151b2d020ce77b7\"}": "throw new Error(\"Cannot find scroll view with ID 'ScrollView161' in the current view hierarchy.\");",
+  "{\"step\":\"Swipe the view \\\"ScrollView161\\\" upwards\",\"previous\":[{\"step\":\"Restart the React Native environment\",\"code\":\"await device.reloadReactNative();\"},{\"step\":\"Go to the Actions screen\",\"code\":\"await element(by.text('Actions')).tap();\"},{\"step\":\"The element with text \\\"Text1\\\" can be seen\",\"code\":\"await expect(element(by.text('Text1'))).toBeVisible();\"},{\"step\":\"Swipe the view \\\"ScrollView161\\\" upwards\",\"code\":\"throw new Error(\\\"Cannot find scroll view with ID 'ScrollView161' in the current view hierarchy.\\\");\",\"result\":\"Caught an error while evaluating \\\"Swipe the view \\\"ScrollView161\\\" upwards\\\", tried with generated code: \\\"throw new Error(\\\"Cannot find scroll view with ID 'ScrollView161' in the current view hierarchy.\\\");\\\". Validate the code against the APIs and hierarchy and continue with a different approach. If can't, return a code that throws a descriptive error.\"}],\"viewHierarchyHash\":\"bb425e9320101560c151b2d020ce77b7\"}": "await element(by.id('ScrollView161')).swipe('up');",
+  "{\"step\":\"The Text1 element is no longer in view\",\"previous\":[{\"step\":\"Restart the React Native environment\",\"code\":\"await device.reloadReactNative();\"},{\"step\":\"Go to the Actions screen\",\"code\":\"await element(by.text('Actions')).tap();\"},{\"step\":\"The element with text \\\"Text1\\\" can be seen\",\"code\":\"await expect(element(by.text('Text1'))).toBeVisible();\"},{\"step\":\"Swipe the view \\\"ScrollView161\\\" upwards\",\"code\":\"await element(by.id('ScrollView161')).swipe('up');\"}],\"viewHierarchyHash\":\"7a647a35084f285172ba19cacdfa312b\"}": "await expect(element(by.text('Text1'))).not.toBeVisible();",
+  "{\"step\":\"Swipe the element back up until the \\\"Text1\\\" element is visible\",\"previous\":[{\"step\":\"Restart the React Native environment\",\"code\":\"await device.reloadReactNative();\"},{\"step\":\"Go to the Actions screen\",\"code\":\"await element(by.text('Actions')).tap();\"},{\"step\":\"The element with text \\\"Text1\\\" can be seen\",\"code\":\"await expect(element(by.text('Text1'))).toBeVisible();\"},{\"step\":\"Swipe the view \\\"ScrollView161\\\" upwards\",\"code\":\"await element(by.id('ScrollView161')).swipe('up');\"},{\"step\":\"The Text1 element is no longer in view\",\"code\":\"await expect(element(by.text('Text1'))).not.toBeVisible();\"}],\"viewHierarchyHash\":\"7a647a35084f285172ba19cacdfa312b\"}": "await waitFor(element(by.text('Text1')))\n  .toBeVisible()\n  .whileElement(by.id('ScrollView161'))\n  .scroll(100, 'down');",
+  "{\"step\":\"Swipe the element back up until the \\\"Text1\\\" element is visible\",\"previous\":[{\"step\":\"Restart the React Native environment\",\"code\":\"await device.reloadReactNative();\"},{\"step\":\"Go to the Actions screen\",\"code\":\"await element(by.text('Actions')).tap();\"},{\"step\":\"The element with text \\\"Text1\\\" can be seen\",\"code\":\"await expect(element(by.text('Text1'))).toBeVisible();\"},{\"step\":\"Swipe the view \\\"ScrollView161\\\" upwards\",\"code\":\"await element(by.id('ScrollView161')).swipe('up');\"},{\"step\":\"The Text1 element is no longer in view\",\"code\":\"await expect(element(by.text('Text1'))).not.toBeVisible();\"},{\"step\":\"Swipe the element back up until the \\\"Text1\\\" element is visible\",\"code\":\"await waitFor(element(by.text('Text1')))\\n  .toBeVisible()\\n  .whileElement(by.id('ScrollView161'))\\n  .scroll(100, 'down');\",\"result\":\"Caught an error while evaluating \\\"Swipe the element back up until the \\\"Text1\\\" element is visible\\\", tried with generated code: \\\"await waitFor(element(by.text('Text1')))\\n  .toBeVisible()\\n  .whileElement(by.id('ScrollView161'))\\n  .scroll(100, 'down');\\\". Validate the code against the APIs and hierarchy and continue with a different approach. If can't, return a code that throws a descriptive error.\"}],\"viewHierarchyHash\":\"7a647a35084f285172ba19cacdfa312b\"}": "await waitFor(element(by.text('Text1')))\n  .toBeVisible()\n  .whileElement(by.id('ScrollView161'))\n  .scroll(100, 'down');",
+  "{\"step\":\"Remove the app and start a fresh instance\",\"previous\":[],\"viewHierarchyHash\":\"b16ef5d51f0f64d6a63d434b26d81efc\"}": "await device.launchApp({ newInstance: true, delete: true });",
+  "{\"step\":\"Navigate to the System Dialogs screen\",\"previous\":[{\"step\":\"Remove the app and start a fresh instance\",\"code\":\"await device.launchApp({ newInstance: true, delete: true });\"}],\"viewHierarchyHash\":\"b16ef5d51f0f64d6a63d434b26d81efc\"}": "```await element(by.text('System Dialogs')).tap();```",
+  "{\"step\":\"Navigate to the System Dialogs screen\",\"previous\":[{\"step\":\"Remove the app and start a fresh instance\",\"code\":\"await device.launchApp({ newInstance: true, delete: true });\"},{\"step\":\"Navigate to the System Dialogs screen\",\"code\":\"```await element(by.text('System Dialogs')).tap();```\",\"result\":\"Caught an error while evaluating \\\"Navigate to the System Dialogs screen\\\", tried with generated code: \\\"```await element(by.text('System Dialogs')).tap();```\\\". Validate the code against the APIs and hierarchy and continue with a different approach. If can't, return a code that throws a descriptive error.\"}],\"viewHierarchyHash\":\"b16ef5d51f0f64d6a63d434b26d81efc\"}": "```await element(by.text('System Dialogs')).tap();```",
+  "{\"step\":\"Restart the React Native state\",\"previous\":[],\"viewHierarchyHash\":\"0ca2c9cbebc7ab6248e6b4db4a70160d\"}": "await device.reloadReactNative();",
+  "{\"step\":\"Navigate to the DatePicker screen\",\"previous\":[{\"step\":\"Restart the React Native state\",\"code\":\"await device.reloadReactNative();\"}],\"viewHierarchyHash\":\"b16ef5d51f0f64d6a63d434b26d81efc\"}": "await element(by.label('DatePicker')).tap();",
+  "{\"step\":\"Verify there is an element with the text \\\"Compact Date Picker\\\"\",\"previous\":[{\"step\":\"Restart the React Native state\",\"code\":\"await device.reloadReactNative();\"},{\"step\":\"Navigate to the DatePicker screen\",\"code\":\"await element(by.label('DatePicker')).tap();\"}],\"viewHierarchyHash\":\"338d7b478bd28a5a1c110d54da1748a7\"}": "await expect(element(by.text('Compact Date Picker'))).toExist();",
+  "{\"step\":\"Tap the element with the text \\\"Compact Date Picker\\\"\",\"previous\":[{\"step\":\"Restart the React Native state\",\"code\":\"await device.reloadReactNative();\"},{\"step\":\"Navigate to the DatePicker screen\",\"code\":\"await element(by.label('DatePicker')).tap();\"},{\"step\":\"Verify there is an element with the text \\\"Compact Date Picker\\\"\",\"code\":\"await expect(element(by.text('Compact Date Picker'))).toExist();\"}],\"viewHierarchyHash\":\"338d7b478bd28a5a1c110d54da1748a7\"}": "await element(by.text('Compact Date Picker')).tap();",
+  "{\"step\":\"Verify there is an element with the text \\\"Inline Date Picker\\\"\",\"previous\":[{\"step\":\"Restart the React Native state\",\"code\":\"await device.reloadReactNative();\"},{\"step\":\"Navigate to the DatePicker screen\",\"code\":\"await element(by.label('DatePicker')).tap();\"},{\"step\":\"Verify there is an element with the text \\\"Compact Date Picker\\\"\",\"code\":\"await expect(element(by.text('Compact Date Picker'))).toExist();\"},{\"step\":\"Tap the element with the text \\\"Compact Date Picker\\\"\",\"code\":\"await element(by.text('Compact Date Picker')).tap();\"}],\"viewHierarchyHash\":\"a6430970141975bb65460afdcfe68f60\"}": "await expect(element(by.text('Inline Date Picker'))).toExist();",
+  "{\"step\":\"Verify there is an element with today`s date at the bottom of the screen\",\"previous\":[{\"step\":\"Restart the React Native state\",\"code\":\"await device.reloadReactNative();\"},{\"step\":\"Navigate to the DatePicker screen\",\"code\":\"await element(by.label('DatePicker')).tap();\"},{\"step\":\"Verify there is an element with the text \\\"Compact Date Picker\\\"\",\"code\":\"await expect(element(by.text('Compact Date Picker'))).toExist();\"},{\"step\":\"Tap the element with the text \\\"Compact Date Picker\\\"\",\"code\":\"await element(by.text('Compact Date Picker')).tap();\"},{\"step\":\"Verify there is an element with the text \\\"Inline Date Picker\\\"\",\"code\":\"await expect(element(by.text('Inline Date Picker'))).toExist();\"}],\"viewHierarchyHash\":\"a6430970141975bb65460afdcfe68f60\"}": "await expect(element(by.id('datePicker'))).toExist();\nawait expect(element(by.label('July 2023'))).toBeVisible();\nawait expect(element(by.label('Monday, 31 July'))).toBeVisible(); // Verifies date at bottom of calendar",
+  "{\"step\":\"Verify there is an element with today`s date at the bottom of the screen\",\"previous\":[{\"step\":\"Restart the React Native state\",\"code\":\"await device.reloadReactNative();\"},{\"step\":\"Navigate to the DatePicker screen\",\"code\":\"await element(by.label('DatePicker')).tap();\"},{\"step\":\"Verify there is an element with the text \\\"Compact Date Picker\\\"\",\"code\":\"await expect(element(by.text('Compact Date Picker'))).toExist();\"},{\"step\":\"Tap the element with the text \\\"Compact Date Picker\\\"\",\"code\":\"await element(by.text('Compact Date Picker')).tap();\"},{\"step\":\"Verify there is an element with the text \\\"Inline Date Picker\\\"\",\"code\":\"await expect(element(by.text('Inline Date Picker'))).toExist();\"},{\"step\":\"Verify there is an element with today`s date at the bottom of the screen\",\"code\":\"await expect(element(by.id('datePicker'))).toExist();\\nawait expect(element(by.label('July 2023'))).toBeVisible();\\nawait expect(element(by.label('Monday, 31 July'))).toBeVisible(); // Verifies date at bottom of calendar\",\"result\":\"Caught an error while evaluating \\\"Verify there is an element with today`s date at the bottom of the screen\\\", tried with generated code: \\\"await expect(element(by.id('datePicker'))).toExist();\\nawait expect(element(by.label('July 2023'))).toBeVisible();\\nawait expect(element(by.label('Monday, 31 July'))).toBeVisible(); // Verifies date at bottom of calendar\\\". Validate the code against the APIs and hierarchy and continue with a different approach. If can't, return a code that throws a descriptive error.\"}],\"viewHierarchyHash\":\"a6430970141975bb65460afdcfe68f60\"}": "await expect(element(by.label('July 2023'))).toBeVisible();\nawait expect(element(by.label('31'))).toBeVisible();",
+  "{\"step\":\"Restart the React Native state\",\"previous\":[],\"viewHierarchyHash\":\"a6430970141975bb65460afdcfe68f60\"}": "await device.reloadReactNative();",
+  "{\"step\":\"Tap the element with the text \\\"Inline Date Picker\\\"\",\"previous\":[{\"step\":\"Restart the React Native state\",\"code\":\"await device.reloadReactNative();\"},{\"step\":\"Navigate to the DatePicker screen\",\"code\":\"await element(by.label('DatePicker')).tap();\"},{\"step\":\"Verify there is an element with the text \\\"Compact Date Picker\\\"\",\"code\":\"await expect(element(by.text('Compact Date Picker'))).toExist();\"},{\"step\":\"Tap the element with the text \\\"Compact Date Picker\\\"\",\"code\":\"await element(by.text('Compact Date Picker')).tap();\"},{\"step\":\"Verify there is an element with the text \\\"Inline Date Picker\\\"\",\"code\":\"await expect(element(by.text('Inline Date Picker'))).toExist();\"}],\"viewHierarchyHash\":\"a6430970141975bb65460afdcfe68f60\"}": "await element(by.text('Inline Date Picker')).tap();",
+  "{\"step\":\"Verify that there is slider element at the bottom of the screen\",\"previous\":[{\"step\":\"Restart the React Native state\",\"code\":\"await device.reloadReactNative();\"},{\"step\":\"Navigate to the DatePicker screen\",\"code\":\"await element(by.label('DatePicker')).tap();\"},{\"step\":\"Verify there is an element with the text \\\"Compact Date Picker\\\"\",\"code\":\"await expect(element(by.text('Compact Date Picker'))).toExist();\"},{\"step\":\"Tap the element with the text \\\"Compact Date Picker\\\"\",\"code\":\"await element(by.text('Compact Date Picker')).tap();\"},{\"step\":\"Verify there is an element with the text \\\"Inline Date Picker\\\"\",\"code\":\"await expect(element(by.text('Inline Date Picker'))).toExist();\"},{\"step\":\"Tap the element with the text \\\"Inline Date Picker\\\"\",\"code\":\"await element(by.text('Inline Date Picker')).tap();\"}],\"viewHierarchyHash\":\"dd6b04249fe6f709c315b5de2b08ec23\"}": "await expect(element(by.id('datePicker'))).toExist();\nconst attributes = await element(by.id('datePicker')).getAttributes();\njestExpect(attributes.y).toBeGreaterThan(500);",
+  "{\"step\":\"Verify that there is slider element at the bottom of the screen\",\"previous\":[{\"step\":\"Restart the React Native state\",\"code\":\"await device.reloadReactNative();\"},{\"step\":\"Navigate to the DatePicker screen\",\"code\":\"await element(by.label('DatePicker')).tap();\"},{\"step\":\"Verify there is an element with the text \\\"Compact Date Picker\\\"\",\"code\":\"await expect(element(by.text('Compact Date Picker'))).toExist();\"},{\"step\":\"Tap the element with the text \\\"Compact Date Picker\\\"\",\"code\":\"await element(by.text('Compact Date Picker')).tap();\"},{\"step\":\"Verify there is an element with the text \\\"Inline Date Picker\\\"\",\"code\":\"await expect(element(by.text('Inline Date Picker'))).toExist();\"},{\"step\":\"Tap the element with the text \\\"Inline Date Picker\\\"\",\"code\":\"await element(by.text('Inline Date Picker')).tap();\"},{\"step\":\"Verify that there is slider element at the bottom of the screen\",\"code\":\"await expect(element(by.id('datePicker'))).toExist();\\nconst attributes = await element(by.id('datePicker')).getAttributes();\\njestExpect(attributes.y).toBeGreaterThan(500);\",\"result\":\"Caught an error while evaluating \\\"Verify that there is slider element at the bottom of the screen\\\", tried with generated code: \\\"await expect(element(by.id('datePicker'))).toExist();\\nconst attributes = await element(by.id('datePicker')).getAttributes();\\njestExpect(attributes.y).toBeGreaterThan(500);\\\". Validate the code against the APIs and hierarchy and continue with a different approach. If can't, return a code that throws a descriptive error.\"}],\"viewHierarchyHash\":\"dd6b04249fe6f709c315b5de2b08ec23\"}": "await expect(element(by.id('datePicker'))).toExist();\nconst attributes = await element(by.id('datePicker')).getAttributes();\njestExpect(attributes.y).toBeGreaterThan(500);",
+  "{\"step\":\"Reset react native state\",\"previous\":[],\"viewHierarchyHash\":\"b16ef5d51f0f64d6a63d434b26d81efc\"}": "await element(by.label('Switch Root')).tap();",
+  "{\"step\":\"Enter the \\\"Shape Matching\\\" game screen\",\"previous\":[{\"step\":\"Reset react native state\",\"code\":\"await element(by.label('Switch Root')).tap();\"}],\"viewHierarchyHash\":\"5d4d366cd4d5e8e92dff8bfcfc171e3a\"}": "throw new Error(\"Unable to find any elements related to 'Shape Matching' game screen in the current view hierarchy. The only visible elements are 'Switch to a new native root' and 'Switch to multiple react roots'.\");",
+  "{\"step\":\"Enter the \\\"Shape Matching\\\" game screen\",\"previous\":[{\"step\":\"Reset react native state\",\"code\":\"await element(by.label('Switch Root')).tap();\"},{\"step\":\"Enter the \\\"Shape Matching\\\" game screen\",\"code\":\"throw new Error(\\\"Unable to find any elements related to 'Shape Matching' game screen in the current view hierarchy. The only visible elements are 'Switch to a new native root' and 'Switch to multiple react roots'.\\\");\",\"result\":\"Caught an error while evaluating \\\"Enter the \\\"Shape Matching\\\" game screen\\\", tried with generated code: \\\"throw new Error(\\\"Unable to find any elements related to 'Shape Matching' game screen in the current view hierarchy. The only visible elements are 'Switch to a new native root' and 'Switch to multiple react roots'.\\\");\\\". Validate the code against the APIs and hierarchy and continue with a different approach. If can't, return a code that throws a descriptive error.\"}],\"viewHierarchyHash\":\"5d4d366cd4d5e8e92dff8bfcfc171e3a\"}": "throw new Error(\"Unable to find elements related to 'Shape Matching' game screen in the current view hierarchy. The only visible elements are 'Switch to a new native root' and 'Switch to multiple react roots'.\");",
+  "{\"step\":\"Restart the React Native state\",\"previous\":[],\"viewHierarchyHash\":\"b16ef5d51f0f64d6a63d434b26d81efc\"}": "await device.reloadReactNative();",
+  "{\"step\":\"Navigate to the Location screen\",\"previous\":[{\"step\":\"Restart the React Native state\",\"code\":\"await device.reloadReactNative();\"}],\"viewHierarchyHash\":\"b16ef5d51f0f64d6a63d434b26d81efc\"}": "await element(by.label('Location')).tap();",
+  "{\"step\":\"Launch the app with location permission denied\",\"previous\":[{\"step\":\"Restart the React Native state\",\"code\":\"await device.reloadReactNative();\"},{\"step\":\"Navigate to the Location screen\",\"code\":\"await element(by.label('Location')).tap();\"}],\"viewHierarchyHash\":\"e79b58a41e3e4e6b49202372b5c1cc79\"}": "await device.launchApp({\n  newInstance: true,\n  permissions: { \n    location: \"never\"\n  }\n});",
+  "{\"step\":\"Verify there is an element with the text \\\"Get location\\\"\",\"previous\":[{\"step\":\"Restart the React Native state\",\"code\":\"await device.reloadReactNative();\"},{\"step\":\"Navigate to the Location screen\",\"code\":\"await element(by.label('Location')).tap();\"},{\"step\":\"Launch the app with location permission denied\",\"code\":\"await device.launchApp({\\n  newInstance: true,\\n  permissions: { \\n    location: \\\"never\\\"\\n  }\\n});\"}],\"viewHierarchyHash\":\"b16ef5d51f0f64d6a63d434b26d81efc\"}": "await expect(element(by.text('Get location'))).toExist();",
+  "{\"step\":\"Verify there is an element with the text \\\"Get location\\\"\",\"previous\":[{\"step\":\"Restart the React Native state\",\"code\":\"await device.reloadReactNative();\"},{\"step\":\"Navigate to the Location screen\",\"code\":\"await element(by.label('Location')).tap();\"},{\"step\":\"Launch the app with location permission denied\",\"code\":\"await device.launchApp({\\n  newInstance: true,\\n  permissions: { \\n    location: \\\"never\\\"\\n  }\\n});\"},{\"step\":\"Verify there is an element with the text \\\"Get location\\\"\",\"code\":\"await expect(element(by.text('Get location'))).toExist();\",\"result\":\"Caught an error while evaluating \\\"Verify there is an element with the text \\\"Get location\\\"\\\", tried with generated code: \\\"await expect(element(by.text('Get location'))).toExist();\\\". Validate the code against the APIs and hierarchy and continue with a different approach. If can't, return a code that throws a descriptive error.\"}],\"viewHierarchyHash\":\"b16ef5d51f0f64d6a63d434b26d81efc\"}": "throw new Error(\"The text 'Get location' is not visible in the current view hierarchy or snapshot image\");",
+  "{\"step\":\"Launch the app with location permission always\",\"previous\":[{\"step\":\"Restart the React Native state\",\"code\":\"await device.reloadReactNative();\"},{\"step\":\"Navigate to the Location screen\",\"code\":\"await element(by.label('Location')).tap();\"}],\"viewHierarchyHash\":\"e79b58a41e3e4e6b49202372b5c1cc79\"}": "await device.launchApp({ \n  newInstance: true,\n  permissions: { location: 'always' }\n});",
+  "{\"step\":\"Verify there is an element with the text \\\"Get location\\\"\",\"previous\":[{\"step\":\"Restart the React Native state\",\"code\":\"await device.reloadReactNative();\"},{\"step\":\"Navigate to the Location screen\",\"code\":\"await element(by.label('Location')).tap();\"},{\"step\":\"Launch the app with location permission always\",\"code\":\"await device.launchApp({ \\n  newInstance: true,\\n  permissions: { location: 'always' }\\n});\"}],\"viewHierarchyHash\":\"b16ef5d51f0f64d6a63d434b26d81efc\"}": "throw new Error(\"No element with text 'Get location' found in the view hierarchy. Found 'Location' instead.\");",
+  "{\"step\":\"Verify there is an element with the text \\\"Get location\\\"\",\"previous\":[{\"step\":\"Restart the React Native state\",\"code\":\"await device.reloadReactNative();\"},{\"step\":\"Navigate to the Location screen\",\"code\":\"await element(by.label('Location')).tap();\"},{\"step\":\"Launch the app with location permission always\",\"code\":\"await device.launchApp({ \\n  newInstance: true,\\n  permissions: { location: 'always' }\\n});\"},{\"step\":\"Verify there is an element with the text \\\"Get location\\\"\",\"code\":\"throw new Error(\\\"No element with text 'Get location' found in the view hierarchy. Found 'Location' instead.\\\");\",\"result\":\"Caught an error while evaluating \\\"Verify there is an element with the text \\\"Get location\\\"\\\", tried with generated code: \\\"throw new Error(\\\"No element with text 'Get location' found in the view hierarchy. Found 'Location' instead.\\\");\\\". Validate the code against the APIs and hierarchy and continue with a different approach. If can't, return a code that throws a descriptive error.\"}],\"viewHierarchyHash\":\"b16ef5d51f0f64d6a63d434b26d81efc\"}": "throw new Error(\"No element with text 'Get location' found in the view hierarchy. Found 'Location' instead.\");",
+  "{\"step\":\"Launch the app with location permission just once\",\"previous\":[{\"step\":\"Restart the React Native state\",\"code\":\"await device.reloadReactNative();\"},{\"step\":\"Navigate to the Location screen\",\"code\":\"await element(by.label('Location')).tap();\"}],\"viewHierarchyHash\":\"e79b58a41e3e4e6b49202372b5c1cc79\"}": "await device.launchApp({\n  newInstance: true,\n  permissions: { location: 'inuse' }\n});",
+  "{\"step\":\"Verify there is an element with the text \\\"Get location\\\"\",\"previous\":[{\"step\":\"Restart the React Native state\",\"code\":\"await device.reloadReactNative();\"},{\"step\":\"Navigate to the Location screen\",\"code\":\"await element(by.label('Location')).tap();\"},{\"step\":\"Launch the app with location permission just once\",\"code\":\"await device.launchApp({\\n  newInstance: true,\\n  permissions: { location: 'inuse' }\\n});\"}],\"viewHierarchyHash\":\"b16ef5d51f0f64d6a63d434b26d81efc\"}": "await expect(element(by.text('Get location'))).toExist();",
+  "{\"step\":\"Verify there is an element with the text \\\"Get location\\\"\",\"previous\":[{\"step\":\"Restart the React Native state\",\"code\":\"await device.reloadReactNative();\"},{\"step\":\"Navigate to the Location screen\",\"code\":\"await element(by.label('Location')).tap();\"},{\"step\":\"Launch the app with location permission just once\",\"code\":\"await device.launchApp({\\n  newInstance: true,\\n  permissions: { location: 'inuse' }\\n});\"},{\"step\":\"Verify there is an element with the text \\\"Get location\\\"\",\"code\":\"await expect(element(by.text('Get location'))).toExist();\",\"result\":\"Caught an error while evaluating \\\"Verify there is an element with the text \\\"Get location\\\"\\\", tried with generated code: \\\"await expect(element(by.text('Get location'))).toExist();\\\". Validate the code against the APIs and hierarchy and continue with a different approach. If can't, return a code that throws a descriptive error.\"}],\"viewHierarchyHash\":\"b16ef5d51f0f64d6a63d434b26d81efc\"}": "throw new Error(\"Element with text 'Get location' is not found in the current view hierarchy\")"
 }
\ No newline at end of file

From 594c66c30ec896ac0b03bb48df11e91b767e8b0b Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Sun, 29 Dec 2024 22:10:36 +0200
Subject: [PATCH 35/51] test: update image snapshot tests.

---
 ...os.horiz.png => elementScreenshot.horiz.ios.png} | Bin
 ....ios.vert.png => elementScreenshot.vert.ios.png} | Bin
 2 files changed, 0 insertions(+), 0 deletions(-)
 rename detox/test/e2e/assets/{elementScreenshot.ios.horiz.png => elementScreenshot.horiz.ios.png} (100%)
 rename detox/test/e2e/assets/{elementScreenshot.ios.vert.png => elementScreenshot.vert.ios.png} (100%)

diff --git a/detox/test/e2e/assets/elementScreenshot.ios.horiz.png b/detox/test/e2e/assets/elementScreenshot.horiz.ios.png
similarity index 100%
rename from detox/test/e2e/assets/elementScreenshot.ios.horiz.png
rename to detox/test/e2e/assets/elementScreenshot.horiz.ios.png
diff --git a/detox/test/e2e/assets/elementScreenshot.ios.vert.png b/detox/test/e2e/assets/elementScreenshot.vert.ios.png
similarity index 100%
rename from detox/test/e2e/assets/elementScreenshot.ios.vert.png
rename to detox/test/e2e/assets/elementScreenshot.vert.ios.png

From 9c7b542974a9b462f4027a4bfebb9e7265d3a9af Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Sun, 29 Dec 2024 23:07:09 +0200
Subject: [PATCH 36/51] test(ios): support shake events from test-app.

---
 .../AppDelegate+Shake.swift                   | 21 ----------
 detox/test/ios/AppDelegate.swift              |  7 +++-
 .../ios/ReactModules/ShakeEventEmitter.swift  | 39 +++++++++++--------
 .../test/ios/UI/UIViewController+Shake.swift  | 37 ++++++++++++++++++
 .../ios/example.xcodeproj/project.pbxproj     | 12 +++---
 5 files changed, 71 insertions(+), 45 deletions(-)
 delete mode 100644 detox/test/ios/AppDelegate Extensions/AppDelegate+Shake.swift
 create mode 100644 detox/test/ios/UI/UIViewController+Shake.swift

diff --git a/detox/test/ios/AppDelegate Extensions/AppDelegate+Shake.swift b/detox/test/ios/AppDelegate Extensions/AppDelegate+Shake.swift
deleted file mode 100644
index d8c1eec128..0000000000
--- a/detox/test/ios/AppDelegate Extensions/AppDelegate+Shake.swift	
+++ /dev/null
@@ -1,21 +0,0 @@
-//
-//  AppDelegate+Shake.swift (example)
-//  Created by Asaf Korem (Wix.com) on 2024.
-//
-
-import UIKit
-import React
-
-extension AppDelegate {
-    override func motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
-        if motion == .motionShake {
-            if let rootView = window?.rootViewController?.view as? RCTRootView {
-                let bridge = rootView.bridge
-                let shakeModule = bridge.module(for: ShakeEventEmitter.self) as! ShakeEventEmitter
-                shakeModule.handleShake()
-            }
-        } else {
-            super.motionEnded(motion, with: event)
-        }
-    }
-}
diff --git a/detox/test/ios/AppDelegate.swift b/detox/test/ios/AppDelegate.swift
index e78726e852..34a9fcea7a 100644
--- a/detox/test/ios/AppDelegate.swift
+++ b/detox/test/ios/AppDelegate.swift
@@ -21,6 +21,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
         setupNotifications()
         setupScreenManager()
         setupApplicationStateObservers()
+        setupShakeDetection()
 
         return true
     }
@@ -45,10 +46,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
     }
 
     private func setupNotifications() {
-        // Set ourselves as the UNUserNotificationCenter delegate
         UNUserNotificationCenter.current().delegate = self
 
-        // Example: Listen for a custom "ChangeScreen" event
         NotificationCenter.default.addObserver(
             forName: Notification.Name("ChangeScreen"),
             object: nil,
@@ -61,6 +60,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
     private func setupScreenManager() {
         screenManager = NativeScreenManager(window: window)
     }
+
+    private func setupShakeDetection() {
+        UIViewController.swizzleMotionEnded()
+    }
 }
 
 // MARK: - RCTBridgeDelegate
diff --git a/detox/test/ios/ReactModules/ShakeEventEmitter.swift b/detox/test/ios/ReactModules/ShakeEventEmitter.swift
index 400488cdcc..012ee712f4 100644
--- a/detox/test/ios/ReactModules/ShakeEventEmitter.swift
+++ b/detox/test/ios/ReactModules/ShakeEventEmitter.swift
@@ -9,20 +9,27 @@ import React
 @objc(ShakeEventEmitter)
 class ShakeEventEmitter: RCTEventEmitter {
 
-  // MARK: - RCTEventEmitter Overrides
-  
-  override static func requiresMainQueueSetup() -> Bool {
-    return true
-  }
-  
-  override func supportedEvents() -> [String]! {
-    return ["ShakeEvent"]
-  }
-  
-  // MARK: - Public Methods
-  
-  @objc
-  func handleShake() {
-    sendEvent(withName: "ShakeEvent", body: nil)
-  }
+    static var reactInstance: ShakeEventEmitter? = nil
+
+    override init() {
+        super.init()
+        ShakeEventEmitter.reactInstance = self
+    }
+
+    // MARK: - RCTEventEmitter Overrides
+
+    override static func requiresMainQueueSetup() -> Bool {
+        return true
+    }
+
+    override func supportedEvents() -> [String]! {
+        return ["ShakeEvent"]
+    }
+
+    // MARK: - Public Methods
+
+    @objc
+    func handleShake() {
+        sendEvent(withName: "ShakeEvent", body: nil)
+    }
 }
diff --git a/detox/test/ios/UI/UIViewController+Shake.swift b/detox/test/ios/UI/UIViewController+Shake.swift
new file mode 100644
index 0000000000..db464fcd70
--- /dev/null
+++ b/detox/test/ios/UI/UIViewController+Shake.swift
@@ -0,0 +1,37 @@
+//
+//  UIViewController+Shake.swift (example)
+//  Created by Asaf Korem (Wix.com) on 2024.
+//
+
+import UIKit
+import React
+
+extension UIViewController {
+
+    static func swizzleMotionEnded() {
+        guard let originalMethod = class_getInstanceMethod(UIViewController.self, #selector(motionEnded(_:with:))),
+              let swizzledMethod = class_getInstanceMethod(UIViewController.self, #selector(swizzled_motionEnded(_:with:))
+              ) else { return }
+
+        method_exchangeImplementations(originalMethod, swizzledMethod)
+    }
+
+    @objc private func swizzled_motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
+        if motion == .motionShake {
+            handleGlobalShakeGesture()
+        }
+
+        if self.responds(to: #selector(swizzled_motionEnded(_:with:))) {
+            self.swizzled_motionEnded(motion, with: event)
+        }
+    }
+
+
+    private func handleGlobalShakeGesture() {
+        guard let shakeModule = ShakeEventEmitter.reactInstance else {
+            return
+        }
+
+        shakeModule.handleShake()
+    }
+}
diff --git a/detox/test/ios/example.xcodeproj/project.pbxproj b/detox/test/ios/example.xcodeproj/project.pbxproj
index 7a4fe3d392..8c779b3a1c 100644
--- a/detox/test/ios/example.xcodeproj/project.pbxproj
+++ b/detox/test/ios/example.xcodeproj/project.pbxproj
@@ -27,16 +27,16 @@
 		608868D22D1D696E0070D199 /* OverlayMessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 608868D12D1D696E0070D199 /* OverlayMessageView.swift */; };
 		608868D32D1D696E0070D199 /* OverlayMessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 608868D12D1D696E0070D199 /* OverlayMessageView.swift */; };
 		609DDB892D10C21800028574 /* Detox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 609DDB852D10C20800028574 /* Detox.framework */; };
+		60A403A92D21EAE3004344C3 /* UIViewController+Shake.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60A403A82D21EADE004344C3 /* UIViewController+Shake.swift */; };
+		60A403AA2D21EAE3004344C3 /* UIViewController+Shake.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60A403A82D21EADE004344C3 /* UIViewController+Shake.swift */; };
 		60E207962D21B0B400E6DBD2 /* AppDelegate+ApplicationState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60E207902D21B0B400E6DBD2 /* AppDelegate+ApplicationState.swift */; };
 		60E207972D21B0B400E6DBD2 /* AppDelegate+Linking.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60E207912D21B0B400E6DBD2 /* AppDelegate+Linking.swift */; };
 		60E207982D21B0B400E6DBD2 /* AppDelegate+Notifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60E207922D21B0B400E6DBD2 /* AppDelegate+Notifications.swift */; };
 		60E207992D21B0B400E6DBD2 /* AppDelegate+OverlayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60E207932D21B0B400E6DBD2 /* AppDelegate+OverlayView.swift */; };
-		60E2079A2D21B0B400E6DBD2 /* AppDelegate+Shake.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60E207942D21B0B400E6DBD2 /* AppDelegate+Shake.swift */; };
 		60E2079B2D21B0B400E6DBD2 /* AppDelegate+ApplicationState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60E207902D21B0B400E6DBD2 /* AppDelegate+ApplicationState.swift */; };
 		60E2079C2D21B0B400E6DBD2 /* AppDelegate+Linking.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60E207912D21B0B400E6DBD2 /* AppDelegate+Linking.swift */; };
 		60E2079D2D21B0B400E6DBD2 /* AppDelegate+Notifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60E207922D21B0B400E6DBD2 /* AppDelegate+Notifications.swift */; };
 		60E2079E2D21B0B400E6DBD2 /* AppDelegate+OverlayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60E207932D21B0B400E6DBD2 /* AppDelegate+OverlayView.swift */; };
-		60E2079F2D21B0B400E6DBD2 /* AppDelegate+Shake.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60E207942D21B0B400E6DBD2 /* AppDelegate+Shake.swift */; };
 		81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
 		90CCD0BA1322566EB1285DC2 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */; };
 		CA25A6405AF58BA742F7FD47 /* libPods-example-ci.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1CB0FE045763B5363B2E7054 /* libPods-example-ci.a */; };
@@ -83,11 +83,11 @@
 		608868C42D1C3D0E0070D199 /* ReactModulesBridge.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ReactModulesBridge.m; sourceTree = "<group>"; };
 		608868D12D1D696E0070D199 /* OverlayMessageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverlayMessageView.swift; sourceTree = "<group>"; };
 		609DDB772D10C20700028574 /* Detox.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Detox.xcodeproj; path = /Users/asafk/Development/Detox/detox/ios/Detox.xcodeproj; sourceTree = "<absolute>"; };
+		60A403A82D21EADE004344C3 /* UIViewController+Shake.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Shake.swift"; sourceTree = "<group>"; };
 		60E207902D21B0B400E6DBD2 /* AppDelegate+ApplicationState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppDelegate+ApplicationState.swift"; sourceTree = "<group>"; };
 		60E207912D21B0B400E6DBD2 /* AppDelegate+Linking.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppDelegate+Linking.swift"; sourceTree = "<group>"; };
 		60E207922D21B0B400E6DBD2 /* AppDelegate+Notifications.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppDelegate+Notifications.swift"; sourceTree = "<group>"; };
 		60E207932D21B0B400E6DBD2 /* AppDelegate+OverlayView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppDelegate+OverlayView.swift"; sourceTree = "<group>"; };
-		60E207942D21B0B400E6DBD2 /* AppDelegate+Shake.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppDelegate+Shake.swift"; sourceTree = "<group>"; };
 		80C930B7D5D6C25DA27372A5 /* Pods-example-ci.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example-ci.release.xcconfig"; path = "Target Support Files/Pods-example-ci/Pods-example-ci.release.xcconfig"; sourceTree = "<group>"; };
 		81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = example/LaunchScreen.storyboard; sourceTree = "<group>"; };
 		89C6BE57DB24E9ADA2F236DE /* Pods-example-exampleTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example-exampleTests.release.xcconfig"; path = "Target Support Files/Pods-example-exampleTests/Pods-example-exampleTests.release.xcconfig"; sourceTree = "<group>"; };
@@ -157,6 +157,7 @@
 		608868B12D1AA1FB0070D199 /* UI */ = {
 			isa = PBXGroup;
 			children = (
+				60A403A82D21EADE004344C3 /* UIViewController+Shake.swift */,
 				608868B02D1AA1FB0070D199 /* CustomKeyboardDelegate.swift */,
 				608868AA2D1AA19B0070D199 /* NativeScreenManager.swift */,
 				608868D12D1D696E0070D199 /* OverlayMessageView.swift */,
@@ -180,7 +181,6 @@
 				60E207912D21B0B400E6DBD2 /* AppDelegate+Linking.swift */,
 				60E207922D21B0B400E6DBD2 /* AppDelegate+Notifications.swift */,
 				60E207932D21B0B400E6DBD2 /* AppDelegate+OverlayView.swift */,
-				60E207942D21B0B400E6DBD2 /* AppDelegate+Shake.swift */,
 			);
 			path = "AppDelegate Extensions";
 			sourceTree = "<group>";
@@ -508,10 +508,10 @@
 			buildActionMask = 2147483647;
 			files = (
 				60E207962D21B0B400E6DBD2 /* AppDelegate+ApplicationState.swift in Sources */,
+				60A403AA2D21EAE3004344C3 /* UIViewController+Shake.swift in Sources */,
 				60E207972D21B0B400E6DBD2 /* AppDelegate+Linking.swift in Sources */,
 				60E207982D21B0B400E6DBD2 /* AppDelegate+Notifications.swift in Sources */,
 				60E207992D21B0B400E6DBD2 /* AppDelegate+OverlayView.swift in Sources */,
-				60E2079A2D21B0B400E6DBD2 /* AppDelegate+Shake.swift in Sources */,
 				608868A32D1A9F070070D199 /* NativeModule.swift in Sources */,
 				608868A42D1A9F070070D199 /* ShakeEventEmitter.swift in Sources */,
 				608868AB2D1AA19B0070D199 /* NativeScreenManager.swift in Sources */,
@@ -527,10 +527,10 @@
 			buildActionMask = 2147483647;
 			files = (
 				60E2079B2D21B0B400E6DBD2 /* AppDelegate+ApplicationState.swift in Sources */,
+				60A403A92D21EAE3004344C3 /* UIViewController+Shake.swift in Sources */,
 				60E2079C2D21B0B400E6DBD2 /* AppDelegate+Linking.swift in Sources */,
 				60E2079D2D21B0B400E6DBD2 /* AppDelegate+Notifications.swift in Sources */,
 				60E2079E2D21B0B400E6DBD2 /* AppDelegate+OverlayView.swift in Sources */,
-				60E2079F2D21B0B400E6DBD2 /* AppDelegate+Shake.swift in Sources */,
 				608868A02D1A9F070070D199 /* NativeModule.swift in Sources */,
 				608868A12D1A9F070070D199 /* ShakeEventEmitter.swift in Sources */,
 				608868AC2D1AA19B0070D199 /* NativeScreenManager.swift in Sources */,

From d4fe2ad250841128d83f816a14751487e7b1abdf Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Tue, 31 Dec 2024 17:39:32 +0200
Subject: [PATCH 37/51] test(app): support stack view for toasts.

---
 .../AppDelegate+OverlayView.swift             | 46 ++++++++++++++-----
 detox/test/ios/UI/OverlayMessageView.swift    |  4 +-
 2 files changed, 38 insertions(+), 12 deletions(-)

diff --git a/detox/test/ios/AppDelegate Extensions/AppDelegate+OverlayView.swift b/detox/test/ios/AppDelegate Extensions/AppDelegate+OverlayView.swift
index 49c19e1707..fdd58fb886 100644
--- a/detox/test/ios/AppDelegate Extensions/AppDelegate+OverlayView.swift	
+++ b/detox/test/ios/AppDelegate Extensions/AppDelegate+OverlayView.swift	
@@ -3,30 +3,54 @@
 //  Created by Asaf Korem (Wix.com) on 2024.
 //
 
-
 import UIKit
 import React
 
 extension AppDelegate {
-    func showOverlayMessage(withMessage message: String) {
+    private var overlayStackView: UIStackView? {
         guard
             let rootView = window?.rootViewController?.view as? RCTRootView,
             let contentView = rootView.value(forKey: "contentView") as? UIView
         else {
-            return
+            return nil
         }
 
-        let messageView = OverlayMessageView(message: message)
-        contentView.addSubview(messageView)
+        return contentView.subviews.compactMap { $0 as? UIStackView }
+            .first { $0.accessibilityIdentifier == "overlayStackView" }
+    }
+
+    private func createOverlayStackView(in contentView: UIView) -> UIStackView {
+        let stackView = UIStackView()
+        stackView.axis = .vertical
+        stackView.distribution = .equalSpacing
+        stackView.spacing = 8
+        stackView.translatesAutoresizingMaskIntoConstraints = false
+
+        stackView.accessibilityIdentifier = "overlayStackView"
+
+        contentView.addSubview(stackView)
 
         NSLayoutConstraint.activate([
-            messageView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
-            messageView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
-            messageView.topAnchor.constraint(equalTo: contentView.safeAreaLayoutGuide.topAnchor),
-            messageView.heightAnchor.constraint(equalToConstant: 60)
+            stackView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
+            stackView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
+            stackView.topAnchor.constraint(equalTo: contentView.safeAreaLayoutGuide.topAnchor)
         ])
 
-        contentView.bringSubviewToFront(messageView)
+        return stackView
     }
-}
 
+    func showOverlayMessage(withMessage message: String) {
+        guard
+            let rootView = window?.rootViewController?.view as? RCTRootView,
+            let contentView = rootView.value(forKey: "contentView") as? UIView
+        else {
+            return
+        }
+
+        let stackView = overlayStackView ?? createOverlayStackView(in: contentView)
+        let messageView = OverlayMessageView(message: message)
+
+        stackView.addArrangedSubview(messageView)
+        contentView.bringSubviewToFront(stackView)
+    }
+}
diff --git a/detox/test/ios/UI/OverlayMessageView.swift b/detox/test/ios/UI/OverlayMessageView.swift
index c20b4448b6..0b1298c3a8 100644
--- a/detox/test/ios/UI/OverlayMessageView.swift
+++ b/detox/test/ios/UI/OverlayMessageView.swift
@@ -45,6 +45,8 @@ class OverlayMessageView: UIView {
         addSubview(closeButton)
 
         NSLayoutConstraint.activate([
+            heightAnchor.constraint(equalToConstant: 60),
+
             messageLabel.centerYAnchor.constraint(equalTo: centerYAnchor),
             messageLabel.centerXAnchor.constraint(equalTo: centerXAnchor),
             messageLabel.leadingAnchor.constraint(greaterThanOrEqualTo: leadingAnchor, constant: 40),
@@ -58,7 +60,7 @@ class OverlayMessageView: UIView {
 
         closeButton.addTarget(self, action: #selector(didTapClose), for: .touchUpInside)
 
-        Timer.scheduledTimer(withTimeInterval: 1.0, repeats: false) { [weak self] _ in
+        Timer.scheduledTimer(withTimeInterval: 2.0, repeats: false) { [weak self] _ in
             self?.removeFromSuperview()
         }
     }

From c27a0032352b2cf37643ba5cf9c83ff863c8dcb5 Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Tue, 31 Dec 2024 19:20:24 +0200
Subject: [PATCH 38/51] test: fix test text matcher.

---
 detox/test/e2e/08.stress-root.test.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/detox/test/e2e/08.stress-root.test.js b/detox/test/e2e/08.stress-root.test.js
index 8e5113922c..277da273b2 100644
--- a/detox/test/e2e/08.stress-root.test.js
+++ b/detox/test/e2e/08.stress-root.test.js
@@ -10,7 +10,7 @@ describe('StressRoot', () => {
 
   it('should switch root view controller from RN to native', async () => {
     await element(by.text('Switch to a new native root')).tap();
-    await expect(element(by.text('this is a new native root'))).toBeVisible();
+    await expect(element(by.text('This is a new native root'))).toBeVisible();
   });
 
   it(':ios: should switch root view controller from RN to RN', async () => {

From 88f22ff7ccab4fad193125322fd98d20b74a4c9a Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Wed, 1 Jan 2025 13:40:27 +0200
Subject: [PATCH 39/51] test(app): remove old iOS code.

---
 detox/test/ios-old/.xcode.env                 |  11 -
 detox/test/ios-old/Podfile                    | 122 ---
 .../ios-old/example.xcodeproj/project.pbxproj | 930 ------------------
 .../xcshareddata/xcschemes/example.xcscheme   | 184 ----
 .../xcschemes/example_ci.xcscheme             |  91 --
 detox/test/ios-old/example/AppDelegate.h      |  17 -
 detox/test/ios-old/example/AppDelegate.m      | 370 -------
 .../example/Base.lproj/LaunchScreen.xib       |  42 -
 .../example/CustomKeyboardViewController.h    |  17 -
 .../example/CustomKeyboardViewController.m    | 117 ---
 .../AppIcon.appiconset/Contents.json          |  53 -
 detox/test/ios-old/example/Info.plist         | 108 --
 detox/test/ios-old/example/NativeModule.h     |   6 -
 detox/test/ios-old/example/NativeModule.m     | 119 ---
 .../ios-old/example/PrivacyInfo.xcprivacy     |  37 -
 .../test/ios-old/example/example.entitlements |   8 -
 detox/test/ios-old/example/main.m             |   9 -
 detox/test/ios-old/exampleUITests/Info.plist  |  22 -
 .../ios-old/exampleUITests/exampleUITests.m   |  42 -
 detox/test/ios-old/example_ci.entitlements    |   8 -
 20 files changed, 2313 deletions(-)
 delete mode 100644 detox/test/ios-old/.xcode.env
 delete mode 100644 detox/test/ios-old/Podfile
 delete mode 100644 detox/test/ios-old/example.xcodeproj/project.pbxproj
 delete mode 100644 detox/test/ios-old/example.xcodeproj/xcshareddata/xcschemes/example.xcscheme
 delete mode 100644 detox/test/ios-old/example.xcodeproj/xcshareddata/xcschemes/example_ci.xcscheme
 delete mode 100644 detox/test/ios-old/example/AppDelegate.h
 delete mode 100644 detox/test/ios-old/example/AppDelegate.m
 delete mode 100644 detox/test/ios-old/example/Base.lproj/LaunchScreen.xib
 delete mode 100644 detox/test/ios-old/example/CustomKeyboardViewController.h
 delete mode 100644 detox/test/ios-old/example/CustomKeyboardViewController.m
 delete mode 100644 detox/test/ios-old/example/Images.xcassets/AppIcon.appiconset/Contents.json
 delete mode 100644 detox/test/ios-old/example/Info.plist
 delete mode 100644 detox/test/ios-old/example/NativeModule.h
 delete mode 100644 detox/test/ios-old/example/NativeModule.m
 delete mode 100644 detox/test/ios-old/example/PrivacyInfo.xcprivacy
 delete mode 100644 detox/test/ios-old/example/example.entitlements
 delete mode 100644 detox/test/ios-old/example/main.m
 delete mode 100644 detox/test/ios-old/exampleUITests/Info.plist
 delete mode 100644 detox/test/ios-old/exampleUITests/exampleUITests.m
 delete mode 100644 detox/test/ios-old/example_ci.entitlements

diff --git a/detox/test/ios-old/.xcode.env b/detox/test/ios-old/.xcode.env
deleted file mode 100644
index ce9964f6b7..0000000000
--- a/detox/test/ios-old/.xcode.env
+++ /dev/null
@@ -1,11 +0,0 @@
-# This `.xcode.env` file is versioned and is used to source the environment
-2	# used when running script phases inside Xcode.
-3	# To customize your local environment, you can create an `.xcode.env.local`
-4	# file that is not versioned.
-5
-6	# NODE_BINARY variable contains the PATH to the node executable.
-7	#
-8	# Customize the NODE_BINARY variable here.
-9	# For example, to use nvm with brew, add the following line
-10	# . "$(brew --prefix nvm)/nvm.sh" --no-use
-11	export NODE_BINARY=$(command -v node)
diff --git a/detox/test/ios-old/Podfile b/detox/test/ios-old/Podfile
deleted file mode 100644
index 030471de41..0000000000
--- a/detox/test/ios-old/Podfile
+++ /dev/null
@@ -1,122 +0,0 @@
-ENV['RCT_NEW_ARCH_ENABLED'] = '0'
-
-if ENV["REACT_NATIVE_VERSION"] && ENV["REACT_NATIVE_VERSION"].match(/0.(70|71).*/)
-    require_relative '../node_modules/react-native/scripts/react_native_pods'
-    require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
-    require_relative '../node_modules/react-native-permissions/scripts/setup'
-else
-    # Resolve react_native_pods.rb with node to allow for hoisting
-    def node_require(script)
-      # Resolve script with node to allow for hoisting
-      require Pod::Executable.execute_command('node', ['-p',
-        "require.resolve(
-          '#{script}',
-          {paths: [process.argv[1]]},
-        )", __dir__]).strip
-    end
-
-    node_require('react-native/scripts/react_native_pods.rb')
-    node_require('react-native-permissions/scripts/setup.rb')
-end
-platform :ios, min_ios_version_supported
-
-install! 'cocoapods', :deterministic_uuids => false
-
-# Comment unwanted permissions
-setup_permissions([
-  'AppTrackingTransparency',
-  'Bluetooth',
-  'Calendars',
-  'Camera',
-  'Contacts',
-  'FaceID',
-  'LocationAccuracy',
-  'LocationAlways',
-  'LocationWhenInUse',
-  'MediaLibrary',
-  'Microphone',
-  'Motion',
-  'Notifications',
-  'PhotoLibrary',
-  'PhotoLibraryAddOnly',
-  'Reminders',
-  'Siri',
-  'SpeechRecognition',
-  'StoreKit',
-])
-
-def shared_pods
-    config = use_native_modules!
-
-    if ENV["REACT_NATIVE_VERSION"] && ENV["REACT_NATIVE_VERSION"].match(/0.(70).*/)
-      # Flags change depending on the env values.
-      flags = get_default_flags()
-
-      use_react_native!(
-        :path => config[:reactNativePath],
-        :hermes_enabled => flags[:hermes_enabled],
-        :fabric_enabled => flags[:fabric_enabled],
-        # :flipper_configuration => FlipperConfiguration.enabled,
-        # An absolute path to your application root.
-        :app_path => "#{Pod::Config.instance.installation_root}/.."
-      )
-    else
-      use_react_native!(
-        # To enable hermes on iOS, change `false` to `true` and then install pods
-        :hermes_enabled => false,
-      )
-    end
-end
-
-target 'example' do
-  shared_pods
-  pod 'react-native-slider', :path => '../node_modules/@react-native-community/slider'
-end
-
-target 'example_ci' do
-  shared_pods
-end
-
-def __apply_update_deployment_target_workaround(installer)
-  # This is a workaround for updating the deployment target of pod targets to the minimal supported version.
-  # See StackOverflow: https://stackoverflow.com/questions/72729591/fbreactnativespec-h-error-after-upgrading-from-0-68-x-to-0-69-0/75915794#75915794
-  puts "Applying update deployment target workaround"
-  installer.pods_project.targets.each do |target|
-      target.build_configurations.each do |config|
-        config.build_settings['SWIFT_VERSION'] = '5.0'
-        if config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] < '12.4'
-          config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.4'
-        end
-      end
-    end
-end
-
-def __apply_Xcode_15_post_install_workaround(installer)
-  # This is a workaround for Xcode 15, see: https://github.com/facebook/react-native/issues/37748.
-  puts "Applying Xcode 15 post install workaround"
-  installer.pods_project.targets.each do |target|
-    target.build_configurations.each do |config|
-      config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)', '_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION']
-    end
-  end
-end
-
-post_install do |installer|
-  __apply_update_deployment_target_workaround(installer)
-  __apply_Xcode_15_post_install_workaround(installer)
-
-  config = use_native_modules!
-
-  react_native_post_install(
-    installer,
-      config[:reactNativePath],
-      # Set `mac_catalyst_enabled` to `true` in order to apply patches
-      # necessary for Mac Catalyst builds
-      :mac_catalyst_enabled => false
-  )
-
-  # See https://github.com/wix/Detox/pull/3035#discussion_r774747705
-  if ENV["REACT_NATIVE_VERSION"] && ENV["REACT_NATIVE_VERSION"].match(/0.(70|72).*/)
-    __apply_Xcode_12_5_M1_post_install_workaround(installer)
-  end
-end
diff --git a/detox/test/ios-old/example.xcodeproj/project.pbxproj b/detox/test/ios-old/example.xcodeproj/project.pbxproj
deleted file mode 100644
index 95434ed05e..0000000000
--- a/detox/test/ios-old/example.xcodeproj/project.pbxproj
+++ /dev/null
@@ -1,930 +0,0 @@
-// !$*UTF8*$!
-{
-	archiveVersion = 1;
-	classes = {
-	};
-	objectVersion = 51;
-	objects = {
-
-/* Begin PBXBuildFile section */
-		03815B1566F43B2C8ACBCCBB /* libPods-example_ci.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6CEAF92A5314EC6824AB3DE3 /* libPods-example_ci.a */; };
-		13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
-		13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
-		13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
-		13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
-		3953CC0D229AA78F005DD98C /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 39ED920022916437005EDB56 /* JavaScriptCore.framework */; };
-		399B4DEC1ED587120098D2AC /* NativeModule.m in Sources */ = {isa = PBXBuildFile; fileRef = CC17D3311D60A24300267B0C /* NativeModule.m */; };
-		399B4DED1ED587120098D2AC /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
-		399B4DEE1ED587120098D2AC /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
-		399B4DFE1ED587120098D2AC /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
-		399B4DFF1ED587120098D2AC /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
-		39A34C791E30F3A000BEBB59 /* Detox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 39B044621DAED76400431EC5 /* Detox.framework */; };
-		39B044651DAED76E00431EC5 /* Detox.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 39B044621DAED76400431EC5 /* Detox.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
-		39B71FCC24643AEA00CC9A88 /* exampleUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 39B71FCB24643AEA00CC9A88 /* exampleUITests.m */; };
-		39ED92302291643E005EDB56 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 39ED920022916437005EDB56 /* JavaScriptCore.framework */; };
-		4FB97BDF2636490900B7B57C /* CustomKeyboardViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4FB97BDE2636490800B7B57C /* CustomKeyboardViewController.m */; };
-		4FB97BE02636490900B7B57C /* CustomKeyboardViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4FB97BDE2636490800B7B57C /* CustomKeyboardViewController.m */; };
-		89F67C3B2D0E9AF9FCED18F6 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 18AB08AE5A45E52755A8055D /* PrivacyInfo.xcprivacy */; };
-		A6246A8AF2D035D89BA61CA6 /* libPods-example.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 86172A40F266BB07F101EB18 /* libPods-example.a */; };
-		CC17D3321D60A24300267B0C /* NativeModule.m in Sources */ = {isa = PBXBuildFile; fileRef = CC17D3311D60A24300267B0C /* NativeModule.m */; };
-		F7E0527E5F2860339654E3EF /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 75C5679B8378704E8D3D9C66 /* PrivacyInfo.xcprivacy */; };
-/* End PBXBuildFile section */
-
-/* Begin PBXContainerItemProxy section */
-		39A0778B1E5450E700A53A07 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 39B0445B1DAED76400431EC5 /* Detox.xcodeproj */;
-			proxyType = 2;
-			remoteGlobalIDString = 3928EFA51E47404900C19B6E;
-			remoteInfo = DetoxUserNotificationTests;
-		};
-		39B044611DAED76400431EC5 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 39B0445B1DAED76400431EC5 /* Detox.xcodeproj */;
-			proxyType = 2;
-			remoteGlobalIDString = CCE6D4371D11A76500F81E39;
-			remoteInfo = Detox;
-		};
-		39B044631DAED76800431EC5 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 39B0445B1DAED76400431EC5 /* Detox.xcodeproj */;
-			proxyType = 1;
-			remoteGlobalIDString = 394767961DBF985400D72256;
-			remoteInfo = Detox;
-		};
-		39B71FCE24643AEA00CC9A88 /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
-			proxyType = 1;
-			remoteGlobalIDString = 13B07F861A680F5B00A75B9A;
-			remoteInfo = example;
-		};
-/* End PBXContainerItemProxy section */
-
-/* Begin PBXCopyFilesBuildPhase section */
-		399B4E011ED587120098D2AC /* Embed Frameworks */ = {
-			isa = PBXCopyFilesBuildPhase;
-			buildActionMask = 2147483647;
-			dstPath = "";
-			dstSubfolderSpec = 10;
-			files = (
-			);
-			name = "Embed Frameworks";
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		CC0F353E1D461097008BB94F /* Embed Frameworks */ = {
-			isa = PBXCopyFilesBuildPhase;
-			buildActionMask = 2147483647;
-			dstPath = "";
-			dstSubfolderSpec = 10;
-			files = (
-				39B044651DAED76E00431EC5 /* Detox.framework in Embed Frameworks */,
-			);
-			name = "Embed Frameworks";
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-/* End PBXCopyFilesBuildPhase section */
-
-/* Begin PBXFileReference section */
-		008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = main.jsbundle; sourceTree = "<group>"; };
-		13B07F961A680F5B00A75B9A /* example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = example.app; sourceTree = BUILT_PRODUCTS_DIR; };
-		13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = example/AppDelegate.h; sourceTree = "<group>"; tabWidth = 4; };
-		13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = example/AppDelegate.m; sourceTree = "<group>"; tabWidth = 4; usesTabs = 1; };
-		13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = "<group>"; };
-		13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = example/Images.xcassets; sourceTree = "<group>"; };
-		13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = example/Info.plist; sourceTree = "<group>"; };
-		13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = example/main.m; sourceTree = "<group>"; };
-		18AB08AE5A45E52755A8055D /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xml; name = PrivacyInfo.xcprivacy; path = example/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
-		399B4E061ED587120098D2AC /* example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = example.app; sourceTree = BUILT_PRODUCTS_DIR; };
-		39B0445B1DAED76400431EC5 /* Detox.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Detox.xcodeproj; path = ../../ios/Detox.xcodeproj; sourceTree = "<group>"; };
-		39B71FC924643AEA00CC9A88 /* exampleUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = exampleUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
-		39B71FCB24643AEA00CC9A88 /* exampleUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = exampleUITests.m; sourceTree = "<group>"; };
-		39B71FCD24643AEA00CC9A88 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
-		39ED920022916437005EDB56 /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
-		39FC9D23202899F90033C11A /* e2e */ = {isa = PBXFileReference; lastKnownFileType = folder; name = e2e; path = ../e2e; sourceTree = "<group>"; };
-		39FC9D24202899F90033C11A /* src */ = {isa = PBXFileReference; lastKnownFileType = folder; name = src; path = ../src; sourceTree = "<group>"; };
-		4FB97BDD2636490800B7B57C /* CustomKeyboardViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CustomKeyboardViewController.h; path = example/CustomKeyboardViewController.h; sourceTree = "<group>"; };
-		4FB97BDE2636490800B7B57C /* CustomKeyboardViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = CustomKeyboardViewController.m; path = example/CustomKeyboardViewController.m; sourceTree = "<group>"; usesTabs = 1; };
-		6027065D2B1DF4DD00CD52CF /* example.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = example.entitlements; path = example/example.entitlements; sourceTree = "<group>"; };
-		6027065F2B1DF82400CD52CF /* example_ci.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = example_ci.entitlements; sourceTree = "<group>"; };
-		6CEAF92A5314EC6824AB3DE3 /* libPods-example_ci.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-example_ci.a"; sourceTree = BUILT_PRODUCTS_DIR; };
-		75C5679B8378704E8D3D9C66 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xml; name = PrivacyInfo.xcprivacy; path = example/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
-		86172A40F266BB07F101EB18 /* libPods-example.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-example.a"; sourceTree = BUILT_PRODUCTS_DIR; };
-		A112C2B84196BF64AE1EFFA3 /* Pods-example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example.debug.xcconfig"; path = "Target Support Files/Pods-example/Pods-example.debug.xcconfig"; sourceTree = "<group>"; };
-		A398C1445E8C769F5903CD2D /* Pods-example_ci.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example_ci.debug.xcconfig"; path = "Target Support Files/Pods-example_ci/Pods-example_ci.debug.xcconfig"; sourceTree = "<group>"; };
-		CC17D3301D60A24300267B0C /* NativeModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NativeModule.h; path = example/NativeModule.h; sourceTree = "<group>"; };
-		CC17D3311D60A24300267B0C /* NativeModule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NativeModule.m; path = example/NativeModule.m; sourceTree = "<group>"; };
-		CC2D09EF9818766C1EE13DEE /* Pods-example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example.release.xcconfig"; path = "Target Support Files/Pods-example/Pods-example.release.xcconfig"; sourceTree = "<group>"; };
-		F08DEFD1BF85073C69F1A95E /* Pods-example_ci.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example_ci.release.xcconfig"; path = "Target Support Files/Pods-example_ci/Pods-example_ci.release.xcconfig"; sourceTree = "<group>"; };
-/* End PBXFileReference section */
-
-/* Begin PBXFrameworksBuildPhase section */
-		13B07F8C1A680F5B00A75B9A /* Frameworks */ = {
-			isa = PBXFrameworksBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				3953CC0D229AA78F005DD98C /* JavaScriptCore.framework in Frameworks */,
-				39A34C791E30F3A000BEBB59 /* Detox.framework in Frameworks */,
-				A6246A8AF2D035D89BA61CA6 /* libPods-example.a in Frameworks */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		399B4DEF1ED587120098D2AC /* Frameworks */ = {
-			isa = PBXFrameworksBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				39ED92302291643E005EDB56 /* JavaScriptCore.framework in Frameworks */,
-				03815B1566F43B2C8ACBCCBB /* libPods-example_ci.a in Frameworks */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		39B71FC624643AEA00CC9A88 /* Frameworks */ = {
-			isa = PBXFrameworksBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-/* End PBXFrameworksBuildPhase section */
-
-/* Begin PBXGroup section */
-		13B07FAE1A68108700A75B9A /* example */ = {
-			isa = PBXGroup;
-			children = (
-				6027065D2B1DF4DD00CD52CF /* example.entitlements */,
-				008F07F21AC5B25A0029DE68 /* main.jsbundle */,
-				13B07FAF1A68108700A75B9A /* AppDelegate.h */,
-				13B07FB01A68108700A75B9A /* AppDelegate.m */,
-				13B07FB51A68108700A75B9A /* Images.xcassets */,
-				13B07FB61A68108700A75B9A /* Info.plist */,
-				13B07FB11A68108700A75B9A /* LaunchScreen.xib */,
-				13B07FB71A68108700A75B9A /* main.m */,
-				ADB9A7A225C82082005236EE /* ReactModules */,
-				ADB9A79F25C81FF7005236EE /* UI */,
-				75C5679B8378704E8D3D9C66 /* PrivacyInfo.xcprivacy */,
-			);
-			name = example;
-			sourceTree = "<group>";
-		};
-		160A423EA1148BC845CDF95E /* Pods */ = {
-			isa = PBXGroup;
-			children = (
-				A112C2B84196BF64AE1EFFA3 /* Pods-example.debug.xcconfig */,
-				CC2D09EF9818766C1EE13DEE /* Pods-example.release.xcconfig */,
-				A398C1445E8C769F5903CD2D /* Pods-example_ci.debug.xcconfig */,
-				F08DEFD1BF85073C69F1A95E /* Pods-example_ci.release.xcconfig */,
-			);
-			path = Pods;
-			sourceTree = "<group>";
-		};
-		39B0445C1DAED76400431EC5 /* Products */ = {
-			isa = PBXGroup;
-			children = (
-				39B044621DAED76400431EC5 /* Detox.framework */,
-				39A0778C1E5450E700A53A07 /* DetoxUserNotificationTests.xctest */,
-			);
-			name = Products;
-			sourceTree = "<group>";
-		};
-		39B71FCA24643AEA00CC9A88 /* exampleUITests */ = {
-			isa = PBXGroup;
-			children = (
-				39B71FCB24643AEA00CC9A88 /* exampleUITests.m */,
-				39B71FCD24643AEA00CC9A88 /* Info.plist */,
-			);
-			path = exampleUITests;
-			sourceTree = "<group>";
-		};
-		39FC9CFD202899D10033C11A /* JS */ = {
-			isa = PBXGroup;
-			children = (
-				39FC9D23202899F90033C11A /* e2e */,
-				39FC9D24202899F90033C11A /* src */,
-			);
-			name = JS;
-			sourceTree = "<group>";
-		};
-		83CBB9F61A601CBA00E9B192 = {
-			isa = PBXGroup;
-			children = (
-				6027065F2B1DF82400CD52CF /* example_ci.entitlements */,
-				39B0445B1DAED76400431EC5 /* Detox.xcodeproj */,
-				13B07FAE1A68108700A75B9A /* example */,
-				39FC9CFD202899D10033C11A /* JS */,
-				39B71FCA24643AEA00CC9A88 /* exampleUITests */,
-				CCFA7DE41D11D22600E15EDF /* Frameworks */,
-				83CBBA001A601CBA00E9B192 /* Products */,
-				160A423EA1148BC845CDF95E /* Pods */,
-				18AB08AE5A45E52755A8055D /* PrivacyInfo.xcprivacy */,
-			);
-			indentWidth = 4;
-			sourceTree = "<group>";
-			tabWidth = 4;
-		};
-		83CBBA001A601CBA00E9B192 /* Products */ = {
-			isa = PBXGroup;
-			children = (
-				13B07F961A680F5B00A75B9A /* example.app */,
-				399B4E061ED587120098D2AC /* example.app */,
-				39B71FC924643AEA00CC9A88 /* exampleUITests.xctest */,
-			);
-			name = Products;
-			sourceTree = "<group>";
-		};
-		ADB9A79F25C81FF7005236EE /* UI */ = {
-			isa = PBXGroup;
-			children = (
-				ADB9A7A125C82033005236EE /* ViewControllers */,
-			);
-			name = UI;
-			sourceTree = "<group>";
-		};
-		ADB9A7A125C82033005236EE /* ViewControllers */ = {
-			isa = PBXGroup;
-			children = (
-				4FB97BDD2636490800B7B57C /* CustomKeyboardViewController.h */,
-				4FB97BDE2636490800B7B57C /* CustomKeyboardViewController.m */,
-			);
-			name = ViewControllers;
-			sourceTree = "<group>";
-		};
-		ADB9A7A225C82082005236EE /* ReactModules */ = {
-			isa = PBXGroup;
-			children = (
-				CC17D3301D60A24300267B0C /* NativeModule.h */,
-				CC17D3311D60A24300267B0C /* NativeModule.m */,
-			);
-			name = ReactModules;
-			sourceTree = "<group>";
-		};
-		CCFA7DE41D11D22600E15EDF /* Frameworks */ = {
-			isa = PBXGroup;
-			children = (
-				39ED920022916437005EDB56 /* JavaScriptCore.framework */,
-				86172A40F266BB07F101EB18 /* libPods-example.a */,
-				6CEAF92A5314EC6824AB3DE3 /* libPods-example_ci.a */,
-			);
-			name = Frameworks;
-			sourceTree = "<group>";
-		};
-/* End PBXGroup section */
-
-/* Begin PBXNativeTarget section */
-		13B07F861A680F5B00A75B9A /* example */ = {
-			isa = PBXNativeTarget;
-			buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "example" */;
-			buildPhases = (
-				DC59FF1BA0BA7FA633F256AA /* [CP] Check Pods Manifest.lock */,
-				13B07F871A680F5B00A75B9A /* Sources */,
-				13B07F8C1A680F5B00A75B9A /* Frameworks */,
-				13B07F8E1A680F5B00A75B9A /* Resources */,
-				00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
-				CC0F353E1D461097008BB94F /* Embed Frameworks */,
-				7E5379D0D68561A29BC0458B /* [CP] Copy Pods Resources */,
-			);
-			buildRules = (
-			);
-			dependencies = (
-				39B044641DAED76800431EC5 /* PBXTargetDependency */,
-			);
-			name = example;
-			productName = "Hello World";
-			productReference = 13B07F961A680F5B00A75B9A /* example.app */;
-			productType = "com.apple.product-type.application";
-		};
-		399B4DE81ED587120098D2AC /* example_ci */ = {
-			isa = PBXNativeTarget;
-			buildConfigurationList = 399B4E031ED587120098D2AC /* Build configuration list for PBXNativeTarget "example_ci" */;
-			buildPhases = (
-				5D18F0A8E13DBF942B818AE3 /* [CP] Check Pods Manifest.lock */,
-				399B4DEB1ED587120098D2AC /* Sources */,
-				399B4DEF1ED587120098D2AC /* Frameworks */,
-				399B4DFD1ED587120098D2AC /* Resources */,
-				399B4E001ED587120098D2AC /* Bundle React Native code and images */,
-				399B4E011ED587120098D2AC /* Embed Frameworks */,
-				9C024938B44AFDD355A0B654 /* [CP] Copy Pods Resources */,
-			);
-			buildRules = (
-			);
-			dependencies = (
-			);
-			name = example_ci;
-			productName = "Hello World";
-			productReference = 399B4E061ED587120098D2AC /* example.app */;
-			productType = "com.apple.product-type.application";
-		};
-		39B71FC824643AEA00CC9A88 /* exampleUITests */ = {
-			isa = PBXNativeTarget;
-			buildConfigurationList = 39B71FD324643AEA00CC9A88 /* Build configuration list for PBXNativeTarget "exampleUITests" */;
-			buildPhases = (
-				39B71FC524643AEA00CC9A88 /* Sources */,
-				39B71FC624643AEA00CC9A88 /* Frameworks */,
-				39B71FC724643AEA00CC9A88 /* Resources */,
-			);
-			buildRules = (
-			);
-			dependencies = (
-				39B71FCF24643AEA00CC9A88 /* PBXTargetDependency */,
-			);
-			name = exampleUITests;
-			productName = exampleUITests;
-			productReference = 39B71FC924643AEA00CC9A88 /* exampleUITests.xctest */;
-			productType = "com.apple.product-type.bundle.ui-testing";
-		};
-/* End PBXNativeTarget section */
-
-/* Begin PBXProject section */
-		83CBB9F71A601CBA00E9B192 /* Project object */ = {
-			isa = PBXProject;
-			attributes = {
-				LastUpgradeCheck = 1220;
-				ORGANIZATIONNAME = Wix;
-				TargetAttributes = {
-					39B71FC824643AEA00CC9A88 = {
-						CreatedOnToolsVersion = 11.5;
-						TestTargetID = 13B07F861A680F5B00A75B9A;
-					};
-				};
-			};
-			buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "example" */;
-			compatibilityVersion = "Xcode 10.0";
-			developmentRegion = en;
-			hasScannedForEncodings = 0;
-			knownRegions = (
-				en,
-				Base,
-			);
-			mainGroup = 83CBB9F61A601CBA00E9B192;
-			productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
-			projectDirPath = "";
-			projectReferences = (
-				{
-					ProductGroup = 39B0445C1DAED76400431EC5 /* Products */;
-					ProjectRef = 39B0445B1DAED76400431EC5 /* Detox.xcodeproj */;
-				},
-			);
-			projectRoot = "";
-			targets = (
-				13B07F861A680F5B00A75B9A /* example */,
-				399B4DE81ED587120098D2AC /* example_ci */,
-				39B71FC824643AEA00CC9A88 /* exampleUITests */,
-			);
-		};
-/* End PBXProject section */
-
-/* Begin PBXReferenceProxy section */
-		39A0778C1E5450E700A53A07 /* DetoxUserNotificationTests.xctest */ = {
-			isa = PBXReferenceProxy;
-			fileType = wrapper.cfbundle;
-			path = DetoxUserNotificationTests.xctest;
-			remoteRef = 39A0778B1E5450E700A53A07 /* PBXContainerItemProxy */;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
-		39B044621DAED76400431EC5 /* Detox.framework */ = {
-			isa = PBXReferenceProxy;
-			fileType = wrapper.framework;
-			path = Detox.framework;
-			remoteRef = 39B044611DAED76400431EC5 /* PBXContainerItemProxy */;
-			sourceTree = BUILT_PRODUCTS_DIR;
-		};
-/* End PBXReferenceProxy section */
-
-/* Begin PBXResourcesBuildPhase section */
-		13B07F8E1A680F5B00A75B9A /* Resources */ = {
-			isa = PBXResourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
-				13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */,
-				F7E0527E5F2860339654E3EF /* PrivacyInfo.xcprivacy in Resources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		399B4DFD1ED587120098D2AC /* Resources */ = {
-			isa = PBXResourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				399B4DFE1ED587120098D2AC /* Images.xcassets in Resources */,
-				399B4DFF1ED587120098D2AC /* LaunchScreen.xib in Resources */,
-				89F67C3B2D0E9AF9FCED18F6 /* PrivacyInfo.xcprivacy in Resources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		39B71FC724643AEA00CC9A88 /* Resources */ = {
-			isa = PBXResourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-/* End PBXResourcesBuildPhase section */
-
-/* Begin PBXShellScriptBuildPhase section */
-		00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = {
-			isa = PBXShellScriptBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			inputPaths = (
-			);
-			name = "Bundle React Native code and images";
-			outputPaths = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-			shellPath = /bin/sh;
-			shellScript = "export NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh";
-		};
-		399B4E001ED587120098D2AC /* Bundle React Native code and images */ = {
-			isa = PBXShellScriptBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			inputPaths = (
-			);
-			name = "Bundle React Native code and images";
-			outputPaths = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-			shellPath = /bin/sh;
-			shellScript = "../node_modules/react-native/scripts/react-native-xcode.sh\n";
-		};
-		5D18F0A8E13DBF942B818AE3 /* [CP] Check Pods Manifest.lock */ = {
-			isa = PBXShellScriptBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			inputFileListPaths = (
-			);
-			inputPaths = (
-				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
-				"${PODS_ROOT}/Manifest.lock",
-			);
-			name = "[CP] Check Pods Manifest.lock";
-			outputFileListPaths = (
-			);
-			outputPaths = (
-				"$(DERIVED_FILE_DIR)/Pods-example_ci-checkManifestLockResult.txt",
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-			shellPath = /bin/sh;
-			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
-			showEnvVarsInLog = 0;
-		};
-		7E5379D0D68561A29BC0458B /* [CP] Copy Pods Resources */ = {
-			isa = PBXShellScriptBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			inputFileListPaths = (
-				"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-resources-${CONFIGURATION}-input-files.xcfilelist",
-			);
-			name = "[CP] Copy Pods Resources";
-			outputFileListPaths = (
-				"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-resources-${CONFIGURATION}-output-files.xcfilelist",
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-			shellPath = /bin/sh;
-			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-resources.sh\"\n";
-			showEnvVarsInLog = 0;
-		};
-		9C024938B44AFDD355A0B654 /* [CP] Copy Pods Resources */ = {
-			isa = PBXShellScriptBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			inputFileListPaths = (
-				"${PODS_ROOT}/Target Support Files/Pods-example_ci/Pods-example_ci-resources-${CONFIGURATION}-input-files.xcfilelist",
-			);
-			name = "[CP] Copy Pods Resources";
-			outputFileListPaths = (
-				"${PODS_ROOT}/Target Support Files/Pods-example_ci/Pods-example_ci-resources-${CONFIGURATION}-output-files.xcfilelist",
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-			shellPath = /bin/sh;
-			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-example_ci/Pods-example_ci-resources.sh\"\n";
-			showEnvVarsInLog = 0;
-		};
-		DC59FF1BA0BA7FA633F256AA /* [CP] Check Pods Manifest.lock */ = {
-			isa = PBXShellScriptBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			inputFileListPaths = (
-			);
-			inputPaths = (
-				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
-				"${PODS_ROOT}/Manifest.lock",
-			);
-			name = "[CP] Check Pods Manifest.lock";
-			outputFileListPaths = (
-			);
-			outputPaths = (
-				"$(DERIVED_FILE_DIR)/Pods-example-checkManifestLockResult.txt",
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-			shellPath = /bin/sh;
-			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
-			showEnvVarsInLog = 0;
-		};
-/* End PBXShellScriptBuildPhase section */
-
-/* Begin PBXSourcesBuildPhase section */
-		13B07F871A680F5B00A75B9A /* Sources */ = {
-			isa = PBXSourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				CC17D3321D60A24300267B0C /* NativeModule.m in Sources */,
-				13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */,
-				4FB97BDF2636490900B7B57C /* CustomKeyboardViewController.m in Sources */,
-				13B07FC11A68108700A75B9A /* main.m in Sources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		399B4DEB1ED587120098D2AC /* Sources */ = {
-			isa = PBXSourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				399B4DEC1ED587120098D2AC /* NativeModule.m in Sources */,
-				399B4DED1ED587120098D2AC /* AppDelegate.m in Sources */,
-				4FB97BE02636490900B7B57C /* CustomKeyboardViewController.m in Sources */,
-				399B4DEE1ED587120098D2AC /* main.m in Sources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		39B71FC524643AEA00CC9A88 /* Sources */ = {
-			isa = PBXSourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				39B71FCC24643AEA00CC9A88 /* exampleUITests.m in Sources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-/* End PBXSourcesBuildPhase section */
-
-/* Begin PBXTargetDependency section */
-		39B044641DAED76800431EC5 /* PBXTargetDependency */ = {
-			isa = PBXTargetDependency;
-			name = Detox;
-			targetProxy = 39B044631DAED76800431EC5 /* PBXContainerItemProxy */;
-		};
-		39B71FCF24643AEA00CC9A88 /* PBXTargetDependency */ = {
-			isa = PBXTargetDependency;
-			target = 13B07F861A680F5B00A75B9A /* example */;
-			targetProxy = 39B71FCE24643AEA00CC9A88 /* PBXContainerItemProxy */;
-		};
-/* End PBXTargetDependency section */
-
-/* Begin PBXVariantGroup section */
-		13B07FB11A68108700A75B9A /* LaunchScreen.xib */ = {
-			isa = PBXVariantGroup;
-			children = (
-				13B07FB21A68108700A75B9A /* Base */,
-			);
-			name = LaunchScreen.xib;
-			path = example;
-			sourceTree = "<group>";
-		};
-/* End PBXVariantGroup section */
-
-/* Begin XCBuildConfiguration section */
-		13B07F941A680F5B00A75B9A /* Debug */ = {
-			isa = XCBuildConfiguration;
-			baseConfigurationReference = A112C2B84196BF64AE1EFFA3 /* Pods-example.debug.xcconfig */;
-			buildSettings = {
-				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
-				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = NO;
-				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO;
-				CODE_SIGN_ENTITLEMENTS = example/example.entitlements;
-				DEAD_CODE_STRIPPING = NO;
-				DEVELOPMENT_TEAM = "";
-				GCC_PREPROCESSOR_DEFINITIONS = (
-					"EXTERNAL_LOGGER=1",
-					"$(inherited)",
-				);
-				INFOPLIST_FILE = example/Info.plist;
-				IPHONEOS_DEPLOYMENT_TARGET = 13.0;
-				LD_RUNPATH_SEARCH_PATHS = (
-					"$(inherited)",
-					"@executable_path/Frameworks",
-				);
-				OTHER_LDFLAGS = (
-					"$(inherited)",
-					"-ObjC",
-					"-lc++",
-				);
-				PRODUCT_BUNDLE_IDENTIFIER = "com.wix.detox-example";
-				PRODUCT_NAME = example;
-				TARGETED_DEVICE_FAMILY = "1,2";
-			};
-			name = Debug;
-		};
-		13B07F951A680F5B00A75B9A /* Release */ = {
-			isa = XCBuildConfiguration;
-			baseConfigurationReference = CC2D09EF9818766C1EE13DEE /* Pods-example.release.xcconfig */;
-			buildSettings = {
-				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
-				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = NO;
-				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO;
-				CODE_SIGN_ENTITLEMENTS = example/example.entitlements;
-				DEVELOPMENT_TEAM = "";
-				GCC_PREPROCESSOR_DEFINITIONS = (
-					"EXTERNAL_LOGGER=1",
-					"$(inherited)",
-				);
-				INFOPLIST_FILE = example/Info.plist;
-				IPHONEOS_DEPLOYMENT_TARGET = 13.0;
-				LD_RUNPATH_SEARCH_PATHS = (
-					"$(inherited)",
-					"@executable_path/Frameworks",
-				);
-				OTHER_LDFLAGS = (
-					"$(inherited)",
-					"-ObjC",
-					"-lc++",
-				);
-				PRODUCT_BUNDLE_IDENTIFIER = "com.wix.detox-example";
-				PRODUCT_NAME = example;
-				TARGETED_DEVICE_FAMILY = "1,2";
-			};
-			name = Release;
-		};
-		399B4E041ED587120098D2AC /* Debug */ = {
-			isa = XCBuildConfiguration;
-			baseConfigurationReference = A398C1445E8C769F5903CD2D /* Pods-example_ci.debug.xcconfig */;
-			buildSettings = {
-				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
-				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = NO;
-				CODE_SIGN_ENTITLEMENTS = example_ci.entitlements;
-				DEAD_CODE_STRIPPING = NO;
-				DEVELOPMENT_TEAM = "";
-				INFOPLIST_FILE = "$(SRCROOT)/example/Info.plist";
-				IPHONEOS_DEPLOYMENT_TARGET = 13.0;
-				LD_RUNPATH_SEARCH_PATHS = (
-					"$(inherited)",
-					"@executable_path/Frameworks",
-				);
-				OTHER_LDFLAGS = (
-					"-ObjC",
-					"-lc++",
-					"-Wl,-U,___dtx_send_external_log",
-					"$(inherited)",
-				);
-				PRODUCT_BUNDLE_IDENTIFIER = "com.wix.detox-example";
-				PRODUCT_NAME = example;
-			};
-			name = Debug;
-		};
-		399B4E051ED587120098D2AC /* Release */ = {
-			isa = XCBuildConfiguration;
-			baseConfigurationReference = F08DEFD1BF85073C69F1A95E /* Pods-example_ci.release.xcconfig */;
-			buildSettings = {
-				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
-				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = NO;
-				CODE_SIGN_ENTITLEMENTS = example_ci.entitlements;
-				DEVELOPMENT_TEAM = "";
-				INFOPLIST_FILE = "$(SRCROOT)/example/Info.plist";
-				IPHONEOS_DEPLOYMENT_TARGET = 13.0;
-				LD_RUNPATH_SEARCH_PATHS = (
-					"$(inherited)",
-					"@executable_path/Frameworks",
-				);
-				OTHER_LDFLAGS = (
-					"-ObjC",
-					"-lc++",
-					"-Wl,-U,___dtx_send_external_log",
-					"$(inherited)",
-				);
-				PRODUCT_BUNDLE_IDENTIFIER = "com.wix.detox-example";
-				PRODUCT_NAME = example;
-			};
-			name = Release;
-		};
-		39B71FD024643AEA00CC9A88 /* Debug */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				CLANG_ANALYZER_NONNULL = YES;
-				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
-				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
-				CLANG_ENABLE_OBJC_WEAK = YES;
-				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
-				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
-				CODE_SIGN_STYLE = Automatic;
-				DEBUG_INFORMATION_FORMAT = dwarf;
-				GCC_C_LANGUAGE_STANDARD = gnu11;
-				INFOPLIST_FILE = exampleUITests/Info.plist;
-				IPHONEOS_DEPLOYMENT_TARGET = 13.5;
-				LD_RUNPATH_SEARCH_PATHS = (
-					"$(inherited)",
-					"@executable_path/Frameworks",
-					"@loader_path/Frameworks",
-				);
-				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
-				MTL_FAST_MATH = YES;
-				PRODUCT_BUNDLE_IDENTIFIER = com.wix.exampleUITests;
-				PRODUCT_NAME = "$(TARGET_NAME)";
-				TARGETED_DEVICE_FAMILY = "1,2";
-				TEST_TARGET_NAME = example;
-			};
-			name = Debug;
-		};
-		39B71FD124643AEA00CC9A88 /* Release */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				CLANG_ANALYZER_NONNULL = YES;
-				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
-				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
-				CLANG_ENABLE_OBJC_WEAK = YES;
-				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
-				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
-				CODE_SIGN_STYLE = Automatic;
-				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
-				GCC_C_LANGUAGE_STANDARD = gnu11;
-				INFOPLIST_FILE = exampleUITests/Info.plist;
-				IPHONEOS_DEPLOYMENT_TARGET = 13.5;
-				LD_RUNPATH_SEARCH_PATHS = (
-					"$(inherited)",
-					"@executable_path/Frameworks",
-					"@loader_path/Frameworks",
-				);
-				MTL_FAST_MATH = YES;
-				PRODUCT_BUNDLE_IDENTIFIER = com.wix.exampleUITests;
-				PRODUCT_NAME = "$(TARGET_NAME)";
-				TARGETED_DEVICE_FAMILY = "1,2";
-				TEST_TARGET_NAME = example;
-			};
-			name = Release;
-		};
-		83CBBA201A601CBA00E9B192 /* Debug */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				ALWAYS_SEARCH_USER_PATHS = NO;
-				CC = "";
-				CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
-				CLANG_CXX_LANGUAGE_STANDARD = "c++20";
-				CLANG_CXX_LIBRARY = "libc++";
-				CLANG_ENABLE_MODULES = YES;
-				CLANG_ENABLE_OBJC_ARC = YES;
-				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
-				CLANG_WARN_BOOL_CONVERSION = YES;
-				CLANG_WARN_COMMA = YES;
-				CLANG_WARN_CONSTANT_CONVERSION = YES;
-				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
-				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
-				CLANG_WARN_EMPTY_BODY = YES;
-				CLANG_WARN_ENUM_CONVERSION = YES;
-				CLANG_WARN_INFINITE_RECURSION = YES;
-				CLANG_WARN_INT_CONVERSION = YES;
-				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
-				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
-				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
-				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
-				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
-				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
-				CLANG_WARN_STRICT_PROTOTYPES = YES;
-				CLANG_WARN_SUSPICIOUS_MOVE = YES;
-				CLANG_WARN_UNREACHABLE_CODE = YES;
-				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
-				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
-				COPY_PHASE_STRIP = NO;
-				CXX = "";
-				ENABLE_BITCODE = NO;
-				ENABLE_STRICT_OBJC_MSGSEND = YES;
-				ENABLE_TESTABILITY = YES;
-				"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
-				GCC_C_LANGUAGE_STANDARD = gnu99;
-				GCC_DYNAMIC_NO_PIC = NO;
-				GCC_NO_COMMON_BLOCKS = YES;
-				GCC_OPTIMIZATION_LEVEL = 0;
-				GCC_PREPROCESSOR_DEFINITIONS = (
-					"DEBUG=1",
-					"$(inherited)",
-					_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION,
-				);
-				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
-				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
-				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
-				GCC_WARN_UNDECLARED_SELECTOR = YES;
-				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
-				GCC_WARN_UNUSED_FUNCTION = YES;
-				GCC_WARN_UNUSED_VARIABLE = YES;
-				IPHONEOS_DEPLOYMENT_TARGET = 13.0;
-				LD = "";
-				LDPLUSPLUS = "";
-				MTL_ENABLE_DEBUG_INFO = YES;
-				ONLY_ACTIVE_ARCH = YES;
-				OTHER_CFLAGS = "$(inherited)";
-				OTHER_CPLUSPLUSFLAGS = "$(inherited)";
-				OTHER_LDFLAGS = "$(inherited)";
-				REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
-				SDKROOT = iphoneos;
-				SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG";
-				USE_HERMES = false;
-			};
-			name = Debug;
-		};
-		83CBBA211A601CBA00E9B192 /* Release */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				ALWAYS_SEARCH_USER_PATHS = NO;
-				CC = "";
-				CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
-				CLANG_CXX_LANGUAGE_STANDARD = "c++20";
-				CLANG_CXX_LIBRARY = "libc++";
-				CLANG_ENABLE_MODULES = YES;
-				CLANG_ENABLE_OBJC_ARC = YES;
-				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
-				CLANG_WARN_BOOL_CONVERSION = YES;
-				CLANG_WARN_COMMA = YES;
-				CLANG_WARN_CONSTANT_CONVERSION = YES;
-				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
-				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
-				CLANG_WARN_EMPTY_BODY = YES;
-				CLANG_WARN_ENUM_CONVERSION = YES;
-				CLANG_WARN_INFINITE_RECURSION = YES;
-				CLANG_WARN_INT_CONVERSION = YES;
-				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
-				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
-				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
-				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
-				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
-				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
-				CLANG_WARN_STRICT_PROTOTYPES = YES;
-				CLANG_WARN_SUSPICIOUS_MOVE = YES;
-				CLANG_WARN_UNREACHABLE_CODE = YES;
-				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
-				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
-				COPY_PHASE_STRIP = NO;
-				CXX = "";
-				ENABLE_BITCODE = NO;
-				ENABLE_NS_ASSERTIONS = NO;
-				ENABLE_STRICT_OBJC_MSGSEND = YES;
-				"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
-				GCC_C_LANGUAGE_STANDARD = gnu99;
-				GCC_NO_COMMON_BLOCKS = YES;
-				GCC_PREPROCESSOR_DEFINITIONS = (
-					"$(inherited)",
-					_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION,
-				);
-				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
-				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
-				GCC_WARN_UNDECLARED_SELECTOR = YES;
-				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
-				GCC_WARN_UNUSED_FUNCTION = YES;
-				GCC_WARN_UNUSED_VARIABLE = YES;
-				IPHONEOS_DEPLOYMENT_TARGET = 13.0;
-				LD = "";
-				LDPLUSPLUS = "";
-				MTL_ENABLE_DEBUG_INFO = NO;
-				OTHER_CFLAGS = "$(inherited)";
-				OTHER_CPLUSPLUSFLAGS = "$(inherited)";
-				OTHER_LDFLAGS = "$(inherited)";
-				REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
-				SDKROOT = iphoneos;
-				USE_HERMES = false;
-				VALIDATE_PRODUCT = YES;
-			};
-			name = Release;
-		};
-/* End XCBuildConfiguration section */
-
-/* Begin XCConfigurationList section */
-		13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "example" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				13B07F941A680F5B00A75B9A /* Debug */,
-				13B07F951A680F5B00A75B9A /* Release */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Release;
-		};
-		399B4E031ED587120098D2AC /* Build configuration list for PBXNativeTarget "example_ci" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				399B4E041ED587120098D2AC /* Debug */,
-				399B4E051ED587120098D2AC /* Release */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Release;
-		};
-		39B71FD324643AEA00CC9A88 /* Build configuration list for PBXNativeTarget "exampleUITests" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				39B71FD024643AEA00CC9A88 /* Debug */,
-				39B71FD124643AEA00CC9A88 /* Release */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Release;
-		};
-		83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "example" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				83CBBA201A601CBA00E9B192 /* Debug */,
-				83CBBA211A601CBA00E9B192 /* Release */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Release;
-		};
-/* End XCConfigurationList section */
-	};
-	rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */;
-}
diff --git a/detox/test/ios-old/example.xcodeproj/xcshareddata/xcschemes/example.xcscheme b/detox/test/ios-old/example.xcodeproj/xcshareddata/xcschemes/example.xcscheme
deleted file mode 100644
index 996c109aef..0000000000
--- a/detox/test/ios-old/example.xcodeproj/xcshareddata/xcschemes/example.xcscheme
+++ /dev/null
@@ -1,184 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<Scheme
-   LastUpgradeVersion = "1220"
-   version = "1.3">
-   <BuildAction
-      parallelizeBuildables = "NO"
-      buildImplicitDependencies = "YES">
-      <BuildActionEntries>
-         <BuildActionEntry
-            buildForTesting = "YES"
-            buildForRunning = "YES"
-            buildForProfiling = "YES"
-            buildForArchiving = "YES"
-            buildForAnalyzing = "YES">
-            <BuildableReference
-               BuildableIdentifier = "primary"
-               BlueprintIdentifier = "83CBBA2D1A601D0E00E9B192"
-               BuildableName = "libReact.a"
-               BlueprintName = "React"
-               ReferencedContainer = "container:../node_modules/react-native/React/React.xcodeproj">
-            </BuildableReference>
-         </BuildActionEntry>
-         <BuildActionEntry
-            buildForTesting = "YES"
-            buildForRunning = "YES"
-            buildForProfiling = "YES"
-            buildForArchiving = "YES"
-            buildForAnalyzing = "YES">
-            <BuildableReference
-               BuildableIdentifier = "primary"
-               BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
-               BuildableName = "example.app"
-               BlueprintName = "example"
-               ReferencedContainer = "container:example.xcodeproj">
-            </BuildableReference>
-         </BuildActionEntry>
-      </BuildActionEntries>
-   </BuildAction>
-   <TestAction
-      buildConfiguration = "Debug"
-      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
-      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      shouldUseLaunchSchemeArgsEnv = "YES">
-      <Testables>
-         <TestableReference
-            skipped = "NO">
-            <BuildableReference
-               BuildableIdentifier = "primary"
-               BlueprintIdentifier = "39B71FC824643AEA00CC9A88"
-               BuildableName = "exampleUITests.xctest"
-               BlueprintName = "exampleUITests"
-               ReferencedContainer = "container:example.xcodeproj">
-            </BuildableReference>
-         </TestableReference>
-      </Testables>
-   </TestAction>
-   <LaunchAction
-      buildConfiguration = "Debug"
-      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
-      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      disableMainThreadChecker = "YES"
-      launchStyle = "0"
-      useCustomWorkingDirectory = "NO"
-      ignoresPersistentStateOnLaunch = "NO"
-      debugDocumentVersioning = "YES"
-      debugServiceExtension = "internal"
-      allowLocationSimulation = "YES">
-      <BuildableProductRunnable
-         runnableDebuggingMode = "0">
-         <BuildableReference
-            BuildableIdentifier = "primary"
-            BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
-            BuildableName = "example.app"
-            BlueprintName = "example"
-            ReferencedContainer = "container:example.xcodeproj">
-         </BuildableReference>
-      </BuildableProductRunnable>
-      <CommandLineArguments>
-         <CommandLineArgument
-            argument = "-detoxURLOverride test://ttt"
-            isEnabled = "NO">
-         </CommandLineArgument>
-         <CommandLineArgument
-            argument = "-detoxDebugVisibility YES"
-            isEnabled = "YES">
-         </CommandLineArgument>
-         <CommandLineArgument
-            argument = "-detoxSourceAppOverride com.apple.mobilesafari"
-            isEnabled = "NO">
-         </CommandLineArgument>
-         <CommandLineArgument
-            argument = "-detoxUserNotificationDataURL /Users/lnatan/Desktop/Code/Detox/detox/ios/DetoxUserNotificationTests/user_notification_push_trigger.json"
-            isEnabled = "NO">
-         </CommandLineArgument>
-         <CommandLineArgument
-            argument = "-detoxWaitForDebugger 9000"
-            isEnabled = "NO">
-         </CommandLineArgument>
-         <CommandLineArgument
-            argument = "-recordingPath /Users/lnatan/Desktop/from_detox.dtxrec"
-            isEnabled = "NO">
-         </CommandLineArgument>
-         <CommandLineArgument
-            argument = "-detoxPrintBusyIdleResources YES"
-            isEnabled = "NO">
-         </CommandLineArgument>
-         <CommandLineArgument
-            argument = "-detoxUserActivityDataURL /Users/lnatan/Desktop/user-activity.json"
-            isEnabled = "NO">
-         </CommandLineArgument>
-         <CommandLineArgument
-            argument = "-enableAppDelegateVerboseLogging YES"
-            isEnabled = "NO">
-         </CommandLineArgument>
-         <CommandLineArgument
-            argument = "-recordingPath /Users/lnatan/Desktop/test"
-            isEnabled = "NO">
-         </CommandLineArgument>
-         <CommandLineArgument
-            argument = "-samplingInterval 0.1"
-            isEnabled = "NO">
-         </CommandLineArgument>
-         <CommandLineArgument
-            argument = "-detoxURLBlacklistRegex &apos;(&quot;.*localhost.*&quot;, &quot;http://192.168.1.253:19001/onchange&quot;,&quot;https://e.crashlytics.com/spi/v2/events&quot;)&apos;"
-            isEnabled = "NO">
-         </CommandLineArgument>
-         <CommandLineArgument
-            argument = "-detoxEnableSynchronization NO"
-            isEnabled = "NO">
-         </CommandLineArgument>
-         <CommandLineArgument
-            argument = "-DTXEnableVerboseSyncSystem YES"
-            isEnabled = "NO">
-         </CommandLineArgument>
-         <CommandLineArgument
-            argument = "-DTXEnableVerboseSyncResources YES"
-            isEnabled = "NO">
-         </CommandLineArgument>
-         <CommandLineArgument
-            argument = "-detoxEnableSyncDebug YES"
-            isEnabled = "NO">
-         </CommandLineArgument>
-         <CommandLineArgument
-            argument = "-detoxDisableTouchIndicators YES"
-            isEnabled = "NO">
-         </CommandLineArgument>
-         <CommandLineArgument
-            argument = "-detoxDisableAnimationSpeedup YES"
-            isEnabled = "NO">
-         </CommandLineArgument>
-      </CommandLineArguments>
-      <AdditionalOptions>
-         <AdditionalOption
-            key = "NSZombieEnabled"
-            value = "YES"
-            isEnabled = "YES">
-         </AdditionalOption>
-      </AdditionalOptions>
-   </LaunchAction>
-   <ProfileAction
-      buildConfiguration = "Debug"
-      shouldUseLaunchSchemeArgsEnv = "YES"
-      savedToolIdentifier = ""
-      useCustomWorkingDirectory = "NO"
-      debugDocumentVersioning = "YES">
-      <BuildableProductRunnable
-         runnableDebuggingMode = "0">
-         <BuildableReference
-            BuildableIdentifier = "primary"
-            BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
-            BuildableName = "example.app"
-            BlueprintName = "example"
-            ReferencedContainer = "container:example.xcodeproj">
-         </BuildableReference>
-      </BuildableProductRunnable>
-   </ProfileAction>
-   <AnalyzeAction
-      buildConfiguration = "Debug">
-   </AnalyzeAction>
-   <ArchiveAction
-      buildConfiguration = "Release"
-      revealArchiveInOrganizer = "YES">
-   </ArchiveAction>
-</Scheme>
diff --git a/detox/test/ios-old/example.xcodeproj/xcshareddata/xcschemes/example_ci.xcscheme b/detox/test/ios-old/example.xcodeproj/xcshareddata/xcschemes/example_ci.xcscheme
deleted file mode 100644
index ac388e69f6..0000000000
--- a/detox/test/ios-old/example.xcodeproj/xcshareddata/xcschemes/example_ci.xcscheme
+++ /dev/null
@@ -1,91 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<Scheme
-   LastUpgradeVersion = "1220"
-   version = "1.3">
-   <BuildAction
-      parallelizeBuildables = "NO"
-      buildImplicitDependencies = "YES">
-      <BuildActionEntries>
-         <BuildActionEntry
-            buildForTesting = "YES"
-            buildForRunning = "YES"
-            buildForProfiling = "YES"
-            buildForArchiving = "YES"
-            buildForAnalyzing = "YES">
-            <BuildableReference
-               BuildableIdentifier = "primary"
-               BlueprintIdentifier = "83CBBA2D1A601D0E00E9B192"
-               BuildableName = "libReact.a"
-               BlueprintName = "React"
-               ReferencedContainer = "container:../node_modules/react-native/React/React.xcodeproj">
-            </BuildableReference>
-         </BuildActionEntry>
-         <BuildActionEntry
-            buildForTesting = "YES"
-            buildForRunning = "YES"
-            buildForProfiling = "YES"
-            buildForArchiving = "YES"
-            buildForAnalyzing = "YES">
-            <BuildableReference
-               BuildableIdentifier = "primary"
-               BlueprintIdentifier = "399B4DE81ED587120098D2AC"
-               BuildableName = "example.app"
-               BlueprintName = "example_ci"
-               ReferencedContainer = "container:example.xcodeproj">
-            </BuildableReference>
-         </BuildActionEntry>
-      </BuildActionEntries>
-   </BuildAction>
-   <TestAction
-      buildConfiguration = "Debug"
-      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
-      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      shouldUseLaunchSchemeArgsEnv = "YES">
-      <Testables>
-      </Testables>
-   </TestAction>
-   <LaunchAction
-      buildConfiguration = "Debug"
-      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
-      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      launchStyle = "0"
-      useCustomWorkingDirectory = "NO"
-      ignoresPersistentStateOnLaunch = "NO"
-      debugDocumentVersioning = "YES"
-      debugServiceExtension = "internal"
-      allowLocationSimulation = "YES">
-      <BuildableProductRunnable
-         runnableDebuggingMode = "0">
-         <BuildableReference
-            BuildableIdentifier = "primary"
-            BlueprintIdentifier = "399B4DE81ED587120098D2AC"
-            BuildableName = "example.app"
-            BlueprintName = "example_ci"
-            ReferencedContainer = "container:example.xcodeproj">
-         </BuildableReference>
-      </BuildableProductRunnable>
-   </LaunchAction>
-   <ProfileAction
-      buildConfiguration = "Release"
-      shouldUseLaunchSchemeArgsEnv = "YES"
-      savedToolIdentifier = ""
-      useCustomWorkingDirectory = "NO"
-      debugDocumentVersioning = "YES">
-      <MacroExpansion>
-         <BuildableReference
-            BuildableIdentifier = "primary"
-            BlueprintIdentifier = "83CBBA2D1A601D0E00E9B192"
-            BuildableName = "libReact.a"
-            BlueprintName = "React"
-            ReferencedContainer = "container:../node_modules/react-native/React/React.xcodeproj">
-         </BuildableReference>
-      </MacroExpansion>
-   </ProfileAction>
-   <AnalyzeAction
-      buildConfiguration = "Debug">
-   </AnalyzeAction>
-   <ArchiveAction
-      buildConfiguration = "Release"
-      revealArchiveInOrganizer = "YES">
-   </ArchiveAction>
-</Scheme>
diff --git a/detox/test/ios-old/example/AppDelegate.h b/detox/test/ios-old/example/AppDelegate.h
deleted file mode 100644
index 9231535b24..0000000000
--- a/detox/test/ios-old/example/AppDelegate.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#import <UIKit/UIKit.h>
-
-@interface SomeMiddleman : UIWindow @end
-
-@interface AnnoyingWindow : SomeMiddleman
-
-@property (nonatomic, strong) UILabel* annoyingLabel;
-
-@end
-
-@interface DetoxApp : UIApplication @end
-
-@interface AppDelegate : UIResponder <UIApplicationDelegate>
-
-@property (nonatomic, strong) AnnoyingWindow *window;
-
-@end
diff --git a/detox/test/ios-old/example/AppDelegate.m b/detox/test/ios-old/example/AppDelegate.m
deleted file mode 100644
index b4bc4f1de0..0000000000
--- a/detox/test/ios-old/example/AppDelegate.m
+++ /dev/null
@@ -1,370 +0,0 @@
-#import "AppDelegate.h"
-#import <React/RCTRootView.h>
-#import <React/RCTLinkingManager.h>
-
-#if RCT_NEW_ARCH_ENABLED
-#import <React/CoreModulesPlugins.h>
-#import <React/RCTCxxBridgeDelegate.h>
-#import <React/RCTFabricSurfaceHostingProxyRootView.h>
-#import <React/RCTSurfacePresenter.h>
-#import <React/RCTSurfacePresenterBridgeAdapter.h>
-#import <ReactCommon/RCTTurboModuleManager.h>
-#import <React/config/ReactNativeConfig.h>
-#endif
-
-#import "CustomKeyboardViewController.h"
-@import CoreSpotlight;
-
-@import UserNotifications;
-
-#if EXTERNAL_LOGGER
-extern void __dtx_send_external_log(const char* log) __attribute__((weak));
-#define __dtx_external_logger(log) __dtx_send_external_log(log);
-#else
-#define __dtx_external_logger(log)
-#endif
-
-@implementation SomeMiddleman @end
-
-@implementation AnnoyingWindow
-
-- (instancetype)initWithFrame:(CGRect)frame
-{
-	self = [super initWithFrame:frame];
-	
-	if(self)
-	{
-		_annoyingLabel = [UILabel new];
-		_annoyingLabel.translatesAutoresizingMaskIntoConstraints = NO;
-		
-		[self addSubview:_annoyingLabel];
-		
-		NSLayoutYAxisAnchor* topAnchor = self.safeAreaLayoutGuide.topAnchor;;
-		NSLayoutConstraint* topConstraint = [_annoyingLabel.topAnchor constraintEqualToAnchor:topAnchor constant:-14];
-		topConstraint.priority = UILayoutPriorityRequired - 1;
-		[NSLayoutConstraint activateConstraints:@[
-			[_annoyingLabel.centerXAnchor constraintEqualToAnchor:self.centerXAnchor],
-			topConstraint,
-			[_annoyingLabel.topAnchor constraintGreaterThanOrEqualToAnchor:self.topAnchor],
-		]];
-	}
-	
-	return self;
-}
-
-- (void)setHidden:(BOOL)hidden
-{
-	[super setHidden:hidden];
-}
-
-- (void)layoutSubviews
-{
-	[super layoutSubviews];
-	
-	[self bringSubviewToFront:_annoyingLabel];
-}
-
-@end
-
-@interface ShakeEventEmitter : RCTEventEmitter @end
-static ShakeEventEmitter* _instance;
-@implementation ShakeEventEmitter
-
-RCT_EXPORT_MODULE();
-
-- (instancetype)init
-{
-	self = [super init];
-	_instance = self;
-	return self;
-}
-
-- (NSArray<NSString *> *)supportedEvents
-{
-	return @[@"ShakeEvent"];
-}
-
-- (void)sendShakeEvent
-{
-	[self sendEventWithName:@"ShakeEvent" body:nil];
-}
-
-+ (BOOL)requiresMainQueueSetup
-{
-	return YES;
-}
-
-@end
-
-@interface ShakeDetectViewController : UIViewController
-@property (nonatomic, weak) RCTBridge* bridge;
-@end
-@implementation ShakeDetectViewController
-
-- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
-{
-	if(event.subtype == UIEventSubtypeMotionShake)
-	{
-		[_instance sendShakeEvent];
-	}
-	else
-	{
-		//This will disable RN dev menu even in debug as shake events are not passed further in responder chain.
-		[super motionEnded:motion withEvent:event];
-	}
-}
-
-@end
-
-@implementation DetoxApp @end
-
-#if RCT_NEW_ARCH_ENABLED
-@interface AppDelegate () <UNUserNotificationCenterDelegate, RCTCxxBridgeDelegate, RCTTurboModuleManagerDelegate> {
-	RCTTurboModuleManager *_turboModuleManager;
-	RCTSurfacePresenterBridgeAdapter *_bridgeAdapter;
-	std::shared_ptr<const facebook::react::ReactNativeConfig> _reactNativeConfig;
-	facebook::react::ContextContainer::Shared _contextContainer;
-}
-@end
-#else
-@interface AppDelegate () <UNUserNotificationCenterDelegate>
-
-@end
-#endif
-
-@implementation AppDelegate
-{
-	UILabel* _resignActive;
-}
-
-- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
-{
-	// this conditional init loads Detox only when command line arguments are given
-	// in normal execution, Detox is not loaded and there's zero impact on the app
-	
-	NSURL *jsCodeLocation;
-	
-	// this is a simple variant over the default React Native starter project which loads the bundle
-	// in Debug from the packager (OPTION 1) and in Release from a local resource (OPTION 2)
-#ifdef DEBUG
-	jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle?platform=ios&dev=true"];
-#else
-	jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
-#endif
-	
-	//RN 🤦‍♂️
-	NSMutableDictionary* opts = launchOptions.mutableCopy;
-	opts[UIApplicationLaunchOptionsRemoteNotificationKey] = nil;
-	
-	RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
-														moduleName:@"example"
-												 initialProperties:nil
-													 launchOptions:opts];
-
-#if RCT_NEW_ARCH_ENABLED
-	_contextContainer = std::make_shared<facebook::react::ContextContainer const>();
-	_reactNativeConfig = std::make_shared<facebook::react::EmptyReactNativeConfig const>();
-	_contextContainer->insert("ReactNativeConfig", _reactNativeConfig);
-	_bridgeAdapter = [[RCTSurfacePresenterBridgeAdapter alloc] initWithBridge:bridge contextContainer:_contextContainer];
-	rootView.bridge.surfacePresenter = _bridgeAdapter.surfacePresenter;
-#endif
-
-	rootView.backgroundColor = UIColor.whiteColor;
-	
-	self.window = [[AnnoyingWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
-
-	[self.window setIsAccessibilityElement:NO];
-	[self.window setAccessibilityElementsHidden:NO];
-
-	ShakeDetectViewController *rootViewController = [ShakeDetectViewController new];
-	rootViewController.bridge = rootView.bridge;
-
-	rootViewController.view = rootView;
-	self.window.rootViewController = rootViewController;
-	[self.window makeKeyAndVisible];
-	
-	[UNUserNotificationCenter currentNotificationCenter].delegate = self;
-	
-	self.window.annoyingLabel.text = @"App is inactive";
-	self.window.annoyingLabel.backgroundColor = UIColor.redColor;
-	self.window.annoyingLabel.textColor = UIColor.whiteColor;
-	self.window.annoyingLabel.font = [UIFont systemFontOfSize:30];
-	[self.window.annoyingLabel sizeToFit];
-	
-	[NSNotificationCenter.defaultCenter addObserverForName:@"ChangeScreen" object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) {
-		NSString* name = note.userInfo[@"name"];
-
-		if ([name isEqualToString:@"customKeyboard"])
-		{
-			CustomKeyboardViewController *vc = [[CustomKeyboardViewController alloc] init];
-			vc.modalPresentationStyle = UIModalPresentationFullScreen;
-			[self.window.rootViewController presentViewController:vc animated:YES completion:nil];
-		}
-	}];
-	
-	return YES;
-}
-
-- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options
-{
-	__dtx_external_logger("Got openURL:");
-	
-	BOOL rv = [RCTLinkingManager application:application
-									 openURL:url
-						   sourceApplication:options[UIApplicationOpenURLOptionsSourceApplicationKey]
-								  annotation:options[UIApplicationOpenURLOptionsAnnotationKey]];
-	
-	__dtx_external_logger("Finished openURL:");
-	
-	return rv;
-}
-
-- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler
-{
-	completionHandler(UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionBadge | UNNotificationPresentationOptionSound);
-}
-
-- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler
-{
-	UILabel* someLabel = [UILabel new];
-	someLabel.translatesAutoresizingMaskIntoConstraints = NO;
-	
-	someLabel.text = response.notification.request.content.title;
-	someLabel.backgroundColor = UIColor.blackColor;
-	someLabel.textColor = UIColor.whiteColor;
-	someLabel.font = [UIFont systemFontOfSize:40];
-	
-	RCTRootView* rv = (id)self.window.rootViewController.view;
-	//Add to the content view so that reloadReactNative() removes this label.
-	[[rv valueForKey:@"contentView"] addSubview:someLabel];
-	
-	[NSLayoutConstraint activateConstraints:@[
-		[someLabel.centerXAnchor constraintEqualToAnchor:self.window.centerXAnchor],
-		[someLabel.topAnchor constraintEqualToAnchor:self.window.annoyingLabel.bottomAnchor],
-	]];
-	
-	[someLabel.superview bringSubviewToFront:someLabel];
-	
-	static id __prevObserver = nil;
-	
-	//Cleanup the previous observer
-	if(__prevObserver != nil)
-	{
-		[NSNotificationCenter.defaultCenter removeObserver:__prevObserver];
-		__prevObserver = nil;
-	}
-	
-	__prevObserver = [NSNotificationCenter.defaultCenter addObserverForName:RCTContentDidAppearNotification object:self.window.rootViewController.view queue:nil usingBlock:^(NSNotification * _Nonnull note) {
-		if(someLabel.window == nil)
-		{
-			[NSNotificationCenter.defaultCenter removeObserver:__prevObserver];
-			__prevObserver = nil;
-			return;
-		}
-		
-		[someLabel.superview bringSubviewToFront:someLabel];
-	}];
-}
-
-- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void(^)(NSArray<id<UIUserActivityRestoring>> * __nullable restorableObjects))restorationHandler
-{
-	if([userActivity.activityType isEqualToString:CSSearchableItemActionType])
-	{
-		NSString* identifier = userActivity.userInfo[CSSearchableItemActivityIdentifier];
-		
-		//Fake it here as if it is a URL, but actually it's a searchable item identifier.
-		return [RCTLinkingManager application:application
-									  openURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@", identifier]]
-							sourceApplication:@""
-								   annotation:@{}];
-	}
-	
-	return [RCTLinkingManager application:application continueUserActivity:userActivity restorationHandler:restorationHandler];
-}
-
-- (NSString*)_stringFromAppState
-{
-	switch (UIApplication.sharedApplication.applicationState) {
-		case UIApplicationStateActive:
-			return @"Active";
-		case UIApplicationStateInactive:
-			return @"Inactive";
-		case UIApplicationStateBackground:
-			return @"Background";
-	}
-}
-
-- (void)applicationDidEnterBackground:(UIApplication *)application
-{
-	self.window.annoyingLabel.text = [self _stringFromAppState];
-	self.window.annoyingLabel.backgroundColor = UIColor.redColor;
-	[self.window.annoyingLabel sizeToFit];
-	
-	__dtx_external_logger("DidEnterBackground");
-}
-
-- (void)applicationWillEnterForeground:(UIApplication *)application
-{
-	self.window.annoyingLabel.text = [self _stringFromAppState];
-	self.window.annoyingLabel.backgroundColor = UIColor.redColor;
-	[self.window.annoyingLabel sizeToFit];
-	
-	__dtx_external_logger("WillEnterForeground");
-}
-
-- (void)applicationWillResignActive:(UIApplication *)application
-{
-	self.window.annoyingLabel.text = [self _stringFromAppState];
-	self.window.annoyingLabel.backgroundColor = UIColor.redColor;
-	[self.window.annoyingLabel sizeToFit];
-	
-	__dtx_external_logger("WillResignActive");
-}
-
-- (void)applicationDidBecomeActive:(UIApplication *)application
-{
-	self.window.annoyingLabel.text = [self _stringFromAppState];
-	self.window.annoyingLabel.backgroundColor = UIColor.greenColor;
-	[self.window.annoyingLabel sizeToFit];
-	
-	__dtx_external_logger("DidBecomeActive");
-}
-
-#if RCT_NEW_ARCH_ENABLED
-
-#pragma mark -
-#pragma mark - RCTCxxBridgeDelegate
-#pragma mark -
-
-- (std::unique_ptr<facebook::react::JSExecutorFactory>)jsExecutorFactoryForBridge:(RCTBridge *)bridge {
-	_turboModuleManager = [[RCTTurboModuleManager alloc] initWithBridge:bridge
-															   delegate:self
-															  jsInvoker:bridge.jsCallInvoker];
-  return RCTAppSetupDefaultJsExecutorFactory(bridge, _turboModuleManager);
-}
-
-#pragma mark -
-#pragma mark RCTTurboModuleManagerDelegate
-#pragma mark -
-
-- (Class)getModuleClassFromName:(const char *)name {
-  return RCTCoreModulesClassProvider(name);
-}
-
-- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const std::string &)name
-    jsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker {
-  return nullptr;
-}
-
-- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const std::string &)name
-    initParams:(const facebook::react::ObjCTurboModule::InitParams &)params {
-  return nullptr;
-}
-
-- (id<RCTTurboModule>)getModuleInstanceFromClass:(Class)moduleClass {
-  return RCTAppSetupDefaultModuleFromClass(moduleClass);
-}
-
-#endif
-
-@end
diff --git a/detox/test/ios-old/example/Base.lproj/LaunchScreen.xib b/detox/test/ios-old/example/Base.lproj/LaunchScreen.xib
deleted file mode 100644
index 9e04807a83..0000000000
--- a/detox/test/ios-old/example/Base.lproj/LaunchScreen.xib
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7702" systemVersion="14D136" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
-    <dependencies>
-        <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7701"/>
-        <capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
-    </dependencies>
-    <objects>
-        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
-        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
-        <view contentMode="scaleToFill" id="iN0-l3-epB">
-            <rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
-            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
-            <subviews>
-                <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Powered by React Native" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="8ie-xW-0ye">
-                    <rect key="frame" x="20" y="439" width="441" height="21"/>
-                    <fontDescription key="fontDescription" type="system" pointSize="17"/>
-                    <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
-                    <nil key="highlightedColor"/>
-                </label>
-                <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="example" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
-                    <rect key="frame" x="20" y="140" width="441" height="43"/>
-                    <fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
-                    <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
-                    <nil key="highlightedColor"/>
-                </label>
-            </subviews>
-            <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
-            <constraints>
-                <constraint firstItem="kId-c2-rCX" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="bottom" multiplier="1/3" constant="1" id="5cJ-9S-tgC"/>
-                <constraint firstAttribute="centerX" secondItem="kId-c2-rCX" secondAttribute="centerX" id="Koa-jz-hwk"/>
-                <constraint firstAttribute="bottom" secondItem="8ie-xW-0ye" secondAttribute="bottom" constant="20" id="Kzo-t9-V3l"/>
-                <constraint firstItem="8ie-xW-0ye" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="MfP-vx-nX0"/>
-                <constraint firstAttribute="centerX" secondItem="8ie-xW-0ye" secondAttribute="centerX" id="ZEH-qu-HZ9"/>
-                <constraint firstItem="kId-c2-rCX" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="fvb-Df-36g"/>
-            </constraints>
-            <nil key="simulatedStatusBarMetrics"/>
-            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
-            <point key="canvasLocation" x="548" y="455"/>
-        </view>
-    </objects>
-</document>
diff --git a/detox/test/ios-old/example/CustomKeyboardViewController.h b/detox/test/ios-old/example/CustomKeyboardViewController.h
deleted file mode 100644
index 8ee742fb12..0000000000
--- a/detox/test/ios-old/example/CustomKeyboardViewController.h
+++ /dev/null
@@ -1,17 +0,0 @@
-//
-//  CustomKeyboardViewController.h
-//  example
-//
-//  Created by Tyrone Trevorrow on 26/4/21.
-//  Copyright © 2021 Wix. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-
-NS_ASSUME_NONNULL_BEGIN
-
-@interface CustomKeyboardViewController : UIViewController
-
-@end
-
-NS_ASSUME_NONNULL_END
diff --git a/detox/test/ios-old/example/CustomKeyboardViewController.m b/detox/test/ios-old/example/CustomKeyboardViewController.m
deleted file mode 100644
index 4dc90129f3..0000000000
--- a/detox/test/ios-old/example/CustomKeyboardViewController.m
+++ /dev/null
@@ -1,117 +0,0 @@
-//
-//  CustomKeyboardViewController.m
-//  example
-//
-//  Created by Tyrone Trevorrow on 26/4/21.
-//  Copyright © 2021 Wix. All rights reserved.
-//
-
-#import "CustomKeyboardViewController.h"
-
-@class CustomKeyboardView;
-@protocol CustomKeyboardDelegate
-- (void) customKeyboardTappedButton: (CustomKeyboardView*) sender;
-@end
-
-@interface CustomKeyboardView : UIView
-@property (nonatomic, weak) id<CustomKeyboardDelegate> delegate;
-- (void) loadView;
-@end
-
-@implementation CustomKeyboardView
-
-- (void) loadView
-{
-	UIButton* kbButton = [UIButton buttonWithType: UIButtonTypeCustom];
-	kbButton.translatesAutoresizingMaskIntoConstraints = NO;
-	[kbButton setTitle: @"Hello" forState: UIControlStateNormal];
-	[kbButton addTarget: self action: @selector(buttonTapped:) forControlEvents: UIControlEventTouchUpInside];
-	kbButton.accessibilityIdentifier = @"keyboardHelloButton";
-	
-	[self addSubview: kbButton];
-	
-	[NSLayoutConstraint activateConstraints: @[
-		[kbButton.widthAnchor constraintGreaterThanOrEqualToConstant:44],
-		[kbButton.heightAnchor constraintEqualToConstant:44],
-		[kbButton.leadingAnchor constraintEqualToAnchor:self.leadingAnchor constant:20],
-		[kbButton.topAnchor constraintEqualToAnchor:self.topAnchor constant:20]
-	]];
-}
-
-- (void) buttonTapped: (id) sender
-{
-	if (self.delegate) {
-		[self.delegate customKeyboardTappedButton: self];
-	}
-}
-
-@end
-
-@interface CustomKeyboardViewController () <CustomKeyboardDelegate>
-@property (nonatomic, strong) UITextField* textField;
-@end
-
-@implementation CustomKeyboardViewController
-
-- (void)viewDidLoad
-{
-	[super viewDidLoad];
-	
-	self.view.backgroundColor = UIColor.systemBackgroundColor;
-	
-	UIButton* closeButton = [UIButton buttonWithType:UIButtonTypeSystem];
-	[closeButton setImage:[UIImage systemImageNamed:@"xmark.circle.fill"] forState:UIControlStateNormal];
-	closeButton.translatesAutoresizingMaskIntoConstraints = NO;
-	closeButton.accessibilityIdentifier = @"closeButton";
-	[closeButton addTarget:self action:@selector(_close) forControlEvents:UIControlEventPrimaryActionTriggered];
-	
-	CustomKeyboardView* inputView = [[CustomKeyboardView alloc] init];
-	inputView.translatesAutoresizingMaskIntoConstraints = NO;
-	inputView.delegate = self;
-	[inputView setBackgroundColor: [UIColor lightGrayColor]];
-	[inputView loadView];
-	
-	UITextField* text = [[UITextField alloc] init];
-	text.translatesAutoresizingMaskIntoConstraints = NO;
-	text.inputView = inputView;
-	text.borderStyle = UITextBorderStyleRoundedRect;
-	text.accessibilityIdentifier = @"textWithCustomInput";
-	
-	UILabel* obscuredLabel = [[UILabel alloc] init];
-	obscuredLabel.translatesAutoresizingMaskIntoConstraints = NO;
-	obscuredLabel.text = @"Obscured by keyboard";
-	
-	self.textField = text;
-	
-	[self.view addSubview:closeButton];
-	[self.view addSubview:text];
-	[self.view addSubview:obscuredLabel];
-	
-	[NSLayoutConstraint activateConstraints:@[
-		[text.heightAnchor constraintEqualToConstant:50],
-		[text.leadingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.leadingAnchor constant:20],
-		[self.view.safeAreaLayoutGuide.trailingAnchor constraintEqualToAnchor:text.trailingAnchor constant:20],
-		[text.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor constant:50],
-		
-		[inputView.widthAnchor constraintEqualToConstant:self.view.frame.size.width],
-		
-		[self.view.layoutMarginsGuide.trailingAnchor constraintEqualToAnchor:closeButton.trailingAnchor],
-		[self.view.layoutMarginsGuide.topAnchor constraintEqualToAnchor:closeButton.topAnchor],
-		
-		[obscuredLabel.leadingAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.leadingAnchor constant:20],
-		[self.view.safeAreaLayoutGuide.trailingAnchor constraintGreaterThanOrEqualToAnchor:obscuredLabel.trailingAnchor constant:20],
-		[self.view.safeAreaLayoutGuide.bottomAnchor constraintEqualToAnchor:obscuredLabel.bottomAnchor constant:50],
-	]];
-}
-
-- (void)customKeyboardTappedButton:(CustomKeyboardView *)sender
-{
-	[self.textField setText:@"World!"];
-}
-
-- (void)_close
-{
-	[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
-}
-
-@end
diff --git a/detox/test/ios-old/example/Images.xcassets/AppIcon.appiconset/Contents.json b/detox/test/ios-old/example/Images.xcassets/AppIcon.appiconset/Contents.json
deleted file mode 100644
index 19882d568a..0000000000
--- a/detox/test/ios-old/example/Images.xcassets/AppIcon.appiconset/Contents.json
+++ /dev/null
@@ -1,53 +0,0 @@
-{
-  "images" : [
-    {
-      "idiom" : "iphone",
-      "size" : "20x20",
-      "scale" : "2x"
-    },
-    {
-      "idiom" : "iphone",
-      "size" : "20x20",
-      "scale" : "3x"
-    },
-    {
-      "idiom" : "iphone",
-      "size" : "29x29",
-      "scale" : "2x"
-    },
-    {
-      "idiom" : "iphone",
-      "size" : "29x29",
-      "scale" : "3x"
-    },
-    {
-      "idiom" : "iphone",
-      "size" : "40x40",
-      "scale" : "2x"
-    },
-    {
-      "idiom" : "iphone",
-      "size" : "40x40",
-      "scale" : "3x"
-    },
-    {
-      "idiom" : "iphone",
-      "size" : "60x60",
-      "scale" : "2x"
-    },
-    {
-      "idiom" : "iphone",
-      "size" : "60x60",
-      "scale" : "3x"
-    },
-    {
-      "idiom" : "ios-marketing",
-      "size" : "1024x1024",
-      "scale" : "1x"
-    }
-  ],
-  "info" : {
-    "version" : 1,
-    "author" : "xcode"
-  }
-}
\ No newline at end of file
diff --git a/detox/test/ios-old/example/Info.plist b/detox/test/ios-old/example/Info.plist
deleted file mode 100644
index 45242fcbe7..0000000000
--- a/detox/test/ios-old/example/Info.plist
+++ /dev/null
@@ -1,108 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>CFBundleDevelopmentRegion</key>
-	<string>en</string>
-	<key>CFBundleExecutable</key>
-	<string>$(EXECUTABLE_NAME)</string>
-	<key>CFBundleIdentifier</key>
-	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
-	<key>CFBundleInfoDictionaryVersion</key>
-	<string>6.0</string>
-	<key>CFBundleName</key>
-	<string>$(PRODUCT_NAME)</string>
-	<key>CFBundlePackageType</key>
-	<string>APPL</string>
-	<key>CFBundleShortVersionString</key>
-	<string>1.0</string>
-	<key>CFBundleSignature</key>
-	<string>????</string>
-	<key>CFBundleURLTypes</key>
-	<array>
-		<dict>
-			<key>CFBundleTypeRole</key>
-			<string>Editor</string>
-			<key>CFBundleURLName</key>
-			<string>detoxtesturlscheme.test.app</string>
-			<key>CFBundleURLSchemes</key>
-			<array>
-				<string>detoxtesturlscheme</string>
-			</array>
-		</dict>
-	</array>
-	<key>CFBundleVersion</key>
-	<string>1</string>
-	<key>LSRequiresIPhoneOS</key>
-	<true/>
-	<key>NSAppTransportSecurity</key>
-	<dict>
-		<key>NSAllowsArbitraryLoads</key>
-		<false/>
-		<key>NSAllowsLocalNetworking</key>
-		<true/>
-	</dict>
-	<key>NSAppleMusicUsageDescription</key>
-	<string></string>
-	<key>NSBluetoothAlwaysUsageDescription</key>
-	<string></string>
-	<key>NSBluetoothPeripheralUsageDescription</key>
-	<string></string>
-	<key>NSCalendarsUsageDescription</key>
-	<string></string>
-	<key>NSCameraUsageDescription</key>
-	<string></string>
-	<key>NSContactsUsageDescription</key>
-	<string></string>
-	<key>NSFaceIDUsageDescription</key>
-	<string></string>
-	<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
-	<string></string>
-	<key>NSLocationTemporaryUsageDescriptionDictionary</key>
-	<dict/>
-	<key>NSLocationWhenInUseUsageDescription</key>
-	<string></string>
-	<key>NSMicrophoneUsageDescription</key>
-	<string></string>
-	<key>NSMotionUsageDescription</key>
-	<string></string>
-	<key>NSPhotoLibraryAddUsageDescription</key>
-	<string></string>
-	<key>NSPhotoLibraryUsageDescription</key>
-	<string></string>
-	<key>NSRemindersUsageDescription</key>
-	<string></string>
-	<key>NSSiriUsageDescription</key>
-	<string></string>
-	<key>NSSpeechRecognitionUsageDescription</key>
-	<string></string>
-	<key>NSUserTrackingUsageDescription</key>
-	<string></string>
-	<key>UIBackgroundModes</key>
-	<array>
-		<string>fetch</string>
-		<string>remote-notification</string>
-	</array>
-	<key>UILaunchStoryboardName</key>
-	<string>LaunchScreen</string>
-	<key>UIRequiredDeviceCapabilities</key>
-	<array>
-		<string>armv7</string>
-	</array>
-	<key>UIRequiresFullScreen</key>
-	<true/>
-	<key>UISupportedInterfaceOrientations</key>
-	<array>
-		<string>UIInterfaceOrientationPortrait</string>
-		<string>UIInterfaceOrientationLandscapeLeft</string>
-		<string>UIInterfaceOrientationLandscapeRight</string>
-		<string>UIInterfaceOrientationPortraitUpsideDown</string>
-	</array>
-	<key>UIViewControllerBasedStatusBarAppearance</key>
-	<true/>
-	<key>WKBackgroundModes</key>
-	<array>
-		<string>remote-notification</string>
-	</array>
-</dict>
-</plist>
diff --git a/detox/test/ios-old/example/NativeModule.h b/detox/test/ios-old/example/NativeModule.h
deleted file mode 100644
index 7bde08a0f8..0000000000
--- a/detox/test/ios-old/example/NativeModule.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#import <React/RCTBridgeModule.h>
-#import <Foundation/Foundation.h>
-
-@interface NativeModule : NSObject <RCTBridgeModule>
-
-@end
diff --git a/detox/test/ios-old/example/NativeModule.m b/detox/test/ios-old/example/NativeModule.m
deleted file mode 100644
index 08f07b45fc..0000000000
--- a/detox/test/ios-old/example/NativeModule.m
+++ /dev/null
@@ -1,119 +0,0 @@
-#import "NativeModule.h"
-#import <UIKit/UIKit.h>
-#import <React/RCTRootView.h>
-
-static int CALL_COUNTER = 0;
-
-@implementation NativeModule
-
-RCT_EXPORT_MODULE();
-
-RCT_EXPORT_METHOD(echoWithoutResponse:(NSString *)str)
-{
-  // NSLog(@"NativeModule echoWithoutResponse called");
-  CALL_COUNTER++;
-}
-
-RCT_EXPORT_METHOD(echoWithResponse:(NSString *)str
-                          resolver:(RCTPromiseResolveBlock)resolve
-                          rejecter:(RCTPromiseRejectBlock)reject)
-{
-  CALL_COUNTER++;
-  resolve(str);
-  // NSLog(@"NativeModule echoWithResponse called");
-}
-
-RCT_EXPORT_METHOD(nativeSetTimeout:(NSTimeInterval)delay block:(RCTResponseSenderBlock)block)
-{
-	dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
-		dispatch_async(dispatch_get_main_queue(), ^{
-			block(@[]);
-		});
-	});
-}
-
-RCT_EXPORT_METHOD(switchToNativeRoot)
-{
-  dispatch_async(dispatch_get_main_queue(), ^{
-    UIViewController* newRoot = [UIViewController new];
-    newRoot.view.backgroundColor = [UIColor whiteColor];
-    UILabel* label = [UILabel new];
-    label.text = @"this is a new native root";
-    [label sizeToFit];
-    [[newRoot view] addSubview:label];
-    label.center = newRoot.view.center;
-
-    id<UIApplicationDelegate> delegate = [[UIApplication sharedApplication] delegate];
-    [[delegate window]setRootViewController:newRoot];
-    [[delegate window] makeKeyAndVisible];
-  });
-}
-
-RCT_EXPORT_METHOD(switchToMultipleReactRoots)
-{
-  dispatch_async(dispatch_get_main_queue(), ^{
-    id<UIApplicationDelegate> delegate = [[UIApplication sharedApplication] delegate];
-    RCTBridge* bridge = ((RCTRootView*)delegate.window.rootViewController.view).bridge;
-
-    UIViewController* newRoot = [UIViewController new];
-    newRoot.view = [[RCTRootView alloc]initWithBridge:bridge moduleName:@"example" initialProperties:nil];
-    newRoot.tabBarItem.title = @"1";
-
-
-    UIViewController* newRoot2 = [UIViewController new];
-    newRoot2.view = [[RCTRootView alloc]initWithBridge:bridge moduleName:@"example" initialProperties:nil];
-    newRoot2.tabBarItem.title = @"2";
-
-    UIViewController* newRoot3 = [UIViewController new];
-    newRoot3.view = [[RCTRootView alloc]initWithBridge:bridge moduleName:@"example" initialProperties:nil];
-    newRoot3.tabBarItem.title = @"3";
-
-    UIViewController* newRoot4 = [UIViewController new];
-    newRoot4.view = [[RCTRootView alloc]initWithBridge:bridge moduleName:@"example" initialProperties:nil];
-    newRoot4.tabBarItem.title = @"4";
-
-    UITabBarController* tbc = [UITabBarController new];
-    tbc.viewControllers = @[newRoot, newRoot2, newRoot3, newRoot4];
-
-    [[delegate window]setRootViewController:tbc];
-    [[delegate window] makeKeyAndVisible];
-  });
-}
-
-RCT_EXPORT_METHOD(sendNotification:(NSString*)notification name:(NSString*)name)
-{
-	dispatch_async(dispatch_get_main_queue(), ^{
-		[NSNotificationCenter.defaultCenter postNotificationName:notification object:nil userInfo:@{@"name": name}];
-	});
-}
-
-RCT_EXPORT_METHOD(presentOverlayWindow) {
-    static UIWindow *overlayWindow;
-
-    dispatch_async(dispatch_get_main_queue(), ^{
-        CGRect screenBounds = UIScreen.mainScreen.bounds;
-        overlayWindow = [[UIWindow alloc] initWithFrame:screenBounds];
-        overlayWindow.accessibilityIdentifier = @"OverlayWindow";
-
-        [overlayWindow setWindowLevel:UIWindowLevelStatusBar];
-        [overlayWindow setHidden:NO];
-
-        [overlayWindow makeKeyAndVisible];
-    });
-}
-
-RCT_EXPORT_METHOD(presentOverlayView) {
-    static UIView *overlayView;
-
-    dispatch_async(dispatch_get_main_queue(), ^{
-        CGRect screenBounds = UIScreen.mainScreen.bounds;
-        overlayView = [[UIView alloc] initWithFrame:screenBounds];
-        overlayView.userInteractionEnabled = YES;
-        overlayView.accessibilityIdentifier = @"OverlayView";
-
-        UIWindow *keyWindow = UIApplication.sharedApplication.keyWindow;
-        [keyWindow addSubview:overlayView];
-    });
-}
-
-@end
diff --git a/detox/test/ios-old/example/PrivacyInfo.xcprivacy b/detox/test/ios-old/example/PrivacyInfo.xcprivacy
deleted file mode 100644
index 41b8317f06..0000000000
--- a/detox/test/ios-old/example/PrivacyInfo.xcprivacy
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>NSPrivacyAccessedAPITypes</key>
-	<array>
-		<dict>
-			<key>NSPrivacyAccessedAPIType</key>
-			<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
-			<key>NSPrivacyAccessedAPITypeReasons</key>
-			<array>
-				<string>C617.1</string>
-			</array>
-		</dict>
-		<dict>
-			<key>NSPrivacyAccessedAPIType</key>
-			<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
-			<key>NSPrivacyAccessedAPITypeReasons</key>
-			<array>
-				<string>CA92.1</string>
-			</array>
-		</dict>
-		<dict>
-			<key>NSPrivacyAccessedAPIType</key>
-			<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
-			<key>NSPrivacyAccessedAPITypeReasons</key>
-			<array>
-				<string>35F9.1</string>
-			</array>
-		</dict>
-	</array>
-	<key>NSPrivacyCollectedDataTypes</key>
-	<array/>
-	<key>NSPrivacyTracking</key>
-	<false/>
-</dict>
-</plist>
diff --git a/detox/test/ios-old/example/example.entitlements b/detox/test/ios-old/example/example.entitlements
deleted file mode 100644
index 21d95c45f3..0000000000
--- a/detox/test/ios-old/example/example.entitlements
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>com.apple.developer.siri</key>
-	<true/>
-</dict>
-</plist>
diff --git a/detox/test/ios-old/example/main.m b/detox/test/ios-old/example/main.m
deleted file mode 100644
index 389f54704d..0000000000
--- a/detox/test/ios-old/example/main.m
+++ /dev/null
@@ -1,9 +0,0 @@
-#import <UIKit/UIKit.h>
-
-#import "AppDelegate.h"
-
-int main(int argc, char *argv[]) {
-  @autoreleasepool {
-    return UIApplicationMain(argc, argv, NSStringFromClass(DetoxApp.class), NSStringFromClass(AppDelegate.class));
-  }
-}
diff --git a/detox/test/ios-old/exampleUITests/Info.plist b/detox/test/ios-old/exampleUITests/Info.plist
deleted file mode 100644
index 64d65ca495..0000000000
--- a/detox/test/ios-old/exampleUITests/Info.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>CFBundleDevelopmentRegion</key>
-	<string>$(DEVELOPMENT_LANGUAGE)</string>
-	<key>CFBundleExecutable</key>
-	<string>$(EXECUTABLE_NAME)</string>
-	<key>CFBundleIdentifier</key>
-	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
-	<key>CFBundleInfoDictionaryVersion</key>
-	<string>6.0</string>
-	<key>CFBundleName</key>
-	<string>$(PRODUCT_NAME)</string>
-	<key>CFBundlePackageType</key>
-	<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
-	<key>CFBundleShortVersionString</key>
-	<string>1.0</string>
-	<key>CFBundleVersion</key>
-	<string>1</string>
-</dict>
-</plist>
diff --git a/detox/test/ios-old/exampleUITests/exampleUITests.m b/detox/test/ios-old/exampleUITests/exampleUITests.m
deleted file mode 100644
index 28f9790cc4..0000000000
--- a/detox/test/ios-old/exampleUITests/exampleUITests.m
+++ /dev/null
@@ -1,42 +0,0 @@
-//
-//  exampleUITests.m
-//  exampleUITests
-//
-//  Created by Leo Natan (Wix) on 5/7/20.
-//  Copyright © 2020 Facebook. All rights reserved.
-//
-
-#import <XCTest/XCTest.h>
-
-@interface exampleUITests : XCTestCase
-
-@end
-
-@implementation exampleUITests
-
-- (void)setUp {
-    // Put setup code here. This method is called before the invocation of each test method in the class.
-
-    // In UI tests it is usually best to stop immediately when a failure occurs.
-    self.continueAfterFailure = NO;
-
-    // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
-}
-
-- (void)tearDown {
-    // Put teardown code here. This method is called after the invocation of each test method in the class.
-}
-
-- (void)testExample {
-    // UI tests must launch the application that they test.
-    XCUIApplication *app = [[XCUIApplication alloc] init];
-    [app launch];
-
-	[NSThread sleepForTimeInterval:1];
-	
-	[app.otherElements[@"Matchers"] tap];
-	
-	[NSThread sleepUntilDate:NSDate.distantFuture];
-}
-
-@end
diff --git a/detox/test/ios-old/example_ci.entitlements b/detox/test/ios-old/example_ci.entitlements
deleted file mode 100644
index 21d95c45f3..0000000000
--- a/detox/test/ios-old/example_ci.entitlements
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>com.apple.developer.siri</key>
-	<true/>
-</dict>
-</plist>

From d8ec159a9e9c97d1924ac8cafe562169ca6c60da Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Wed, 1 Jan 2025 13:40:58 +0200
Subject: [PATCH 40/51] test(podfile): remove old RN versions check.

---
 detox/test/ios/Podfile | 27 ++++++++++-----------------
 1 file changed, 10 insertions(+), 17 deletions(-)

diff --git a/detox/test/ios/Podfile b/detox/test/ios/Podfile
index 6bf92b7c5e..4aabdff2ed 100644
--- a/detox/test/ios/Podfile
+++ b/detox/test/ios/Podfile
@@ -1,22 +1,15 @@
-if ENV["REACT_NATIVE_VERSION"] && ENV["REACT_NATIVE_VERSION"].match(/0.(70|71).*/)
-    require_relative '../node_modules/react-native/scripts/react_native_pods'
-    require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
-    require_relative '../node_modules/react-native-permissions/scripts/setup'
-else
-    # Resolve react_native_pods.rb with node to allow for hoisting
-    def node_require(script)
-      # Resolve script with node to allow for hoisting
-      require Pod::Executable.execute_command('node', ['-p',
-        "require.resolve(
-          '#{script}',
-          {paths: [process.argv[1]]},
-        )", __dir__]).strip
-    end
-
-    node_require('react-native/scripts/react_native_pods.rb')
-    node_require('react-native-permissions/scripts/setup.rb')
+def node_require(script)
+  # Resolve script with node to allow for hoisting
+  require Pod::Executable.execute_command('node', ['-p',
+    "require.resolve(
+      '#{script}',
+      {paths: [process.argv[1]]},
+    )", __dir__]).strip
 end
 
+node_require('react-native/scripts/react_native_pods.rb')
+node_require('react-native-permissions/scripts/setup.rb')
+
 platform :ios, min_ios_version_supported
 
 install! 'cocoapods', :deterministic_uuids => false

From 865645d7ee79811def8deb31ceb94d83a6c09da2 Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Wed, 1 Jan 2025 14:05:10 +0200
Subject: [PATCH 41/51] chore: clean old snapshot test artifacts.

---
 .../view-hierarchy-web-view.71.android.txt    | 62 ------------------
 .../assets/view-hierarchy-web-view.71.ios.txt | 64 -------------------
 ...rchy-with-test-id-injection.71.android.txt | 32 ----------
 ...ierarchy-with-test-id-injection.71.ios.txt | 27 --------
 ...y-without-test-id-injection.71.android.txt | 32 ----------
 ...archy-without-test-id-injection.71.ios.txt | 27 --------
 6 files changed, 244 deletions(-)
 delete mode 100644 detox/test/e2e/assets/view-hierarchy-web-view.71.android.txt
 delete mode 100644 detox/test/e2e/assets/view-hierarchy-web-view.71.ios.txt
 delete mode 100644 detox/test/e2e/assets/view-hierarchy-with-test-id-injection.71.android.txt
 delete mode 100644 detox/test/e2e/assets/view-hierarchy-with-test-id-injection.71.ios.txt
 delete mode 100644 detox/test/e2e/assets/view-hierarchy-without-test-id-injection.71.android.txt
 delete mode 100644 detox/test/e2e/assets/view-hierarchy-without-test-id-injection.71.ios.txt

diff --git a/detox/test/e2e/assets/view-hierarchy-web-view.71.android.txt b/detox/test/e2e/assets/view-hierarchy-web-view.71.android.txt
deleted file mode 100644
index 3020bb4e38..0000000000
--- a/detox/test/e2e/assets/view-hierarchy-web-view.71.android.txt
+++ /dev/null
@@ -1,62 +0,0 @@
-<?xml version='1.0' encoding='UTF_8' standalone='yes' ?>
-<ViewHierarchy>
-  <DecorView class="com.android.internal.policy.DecorView" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" x="<number>" y="<number>" id="detox_temp_">
-    <LinearLayout class="android.widget.LinearLayout" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" x="<number>" y="<number>" id="detox_temp_0">
-      <ViewStub class="android.view.ViewStub" width="<number>" height="<number>" visibility="gone" alpha="1.0" focused="false" x="<number>" y="<number>" id="detox_temp_0_0" />
-      <FrameLayout class="android.widget.FrameLayout" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" x="<number>" y="<number>" id="detox_temp_0_1">
-        <FitWindowsLinearLayout class="androidx.appcompat.widget.FitWindowsLinearLayout" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" x="<number>" y="<number>" id="detox_temp_0_1_0">
-          <ViewStubCompat class="androidx.appcompat.widget.ViewStubCompat" width="<number>" height="<number>" visibility="gone" alpha="1.0" focused="false" x="<number>" y="<number>" id="detox_temp_0_1_0_0" />
-          <ContentFrameLayout class="androidx.appcompat.widget.ContentFrameLayout" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" x="<number>" y="<number>" id="detox_temp_0_1_0_1">
-            <ReactRootView class="com.facebook.react.ReactRootView" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" label="SHOW 2ND WEBVIEW SHOW 3RD WEBVIEW" x="<number>" y="<number>" id="detox_temp_0_1_0_1_0">
-              <ReactViewGroup class="com.facebook.react.views.view.ReactViewGroup" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" label="SHOW 2ND WEBVIEW SHOW 3RD WEBVIEW" x="<number>" y="<number>">
-                <ReactViewGroup class="com.facebook.react.views.view.ReactViewGroup" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" label="SHOW 2ND WEBVIEW SHOW 3RD WEBVIEW" x="<number>" y="<number>">
-                  <ReactViewGroup class="com.facebook.react.views.view.ReactViewGroup" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" label="SHOW 2ND WEBVIEW SHOW 3RD WEBVIEW" x="<number>" y="<number>">
-                    <ReactViewGroup class="com.facebook.react.views.view.ReactViewGroup" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" label="SHOW 2ND WEBVIEW SHOW 3RD WEBVIEW" x="<number>" y="<number>">
-                      <ReactViewGroup class="com.facebook.react.views.view.ReactViewGroup" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" label="SHOW 2ND WEBVIEW" x="<number>" y="<number>">
-                        <ReactViewGroup class="com.facebook.react.views.view.ReactViewGroup" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" label="SHOW 2ND WEBVIEW" x="<number>" y="<number>" id="toggle2ndWebviewButton">
-                          <ReactTextView class="com.facebook.react.views.text.ReactTextView" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" label="SHOW 2ND WEBVIEW" x="<number>" y="<number>" text="SHOW 2ND WEBVIEW" />
-                        </ReactViewGroup>
-                      </ReactViewGroup>
-                      <ReactViewGroup class="com.facebook.react.views.view.ReactViewGroup" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" label="SHOW 3RD WEBVIEW" x="<number>" y="<number>">
-                        <ReactViewGroup class="com.facebook.react.views.view.ReactViewGroup" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" label="SHOW 3RD WEBVIEW" x="<number>" y="<number>" id="toggle3rdWebviewButton">
-                          <ReactTextView class="com.facebook.react.views.text.ReactTextView" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" label="SHOW 3RD WEBVIEW" x="<number>" y="<number>" text="SHOW 3RD WEBVIEW" />
-                        </ReactViewGroup>
-                      </ReactViewGroup>
-                    </ReactViewGroup>
-                    <ReactViewGroup class="com.facebook.react.views.view.ReactViewGroup" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" x="<number>" y="<number>">
-                      <ReactViewGroup class="com.facebook.react.views.view.ReactViewGroup" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" x="<number>" y="<number>">
-                        <ReactViewGroup class="com.facebook.react.views.view.ReactViewGroup" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" x="<number>" y="<number>">
-                          <RNCWebView class="com.reactnativecommunity.webview.RNCWebViewManager$RNCWebView" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" x="<number>" y="<number>" id="webViewFormWithScrolling"><![CDATA["<html xmlns=\"http://www.w3.org/1999/xhtml\">
-    <body>
-        <h1 id=\"pageHeadline\" aria-label=\"first-webview\">First Webview</h1>
-        <h2>Form</h2>
-        <form>
-            <label for=\"fname\">Your name:</label><br />
-            <input type=\"text\" id=\"fname\" name=\"fname\" maxlength=\"10\" /><br />
-            <input type=\"submit\" id=\"submit\" value=\"Submit\" onclick=\"document.getElementById('resultFname').innerHTML = document.getElementById('fname').value; return false;\" />
-        </form>
-        <h2>Form Results</h2>
-        <p>Your first name is: <span id=\"resultFname\">No input yet</span></p>
-        <h2>Content Editable</h2>
-        <div id=\"contentEditable\" class=\"contentEditable\" contenteditable=\"true\">Name: </div>
-        <h2>Text and link</h2>
-        <p>Some text and a <a id=\"w3link\" href=\"https://www.w3schools.com\">link</a>.</p>
-        <p id=\"bottomParagraph\" class=\"specialParagraph\">This is a bottom paragraph with class.</p>
-
-</body></html>"]]>
-                          </RNCWebView>
-                        </ReactViewGroup>
-                      </ReactViewGroup>
-                    </ReactViewGroup>
-                  </ReactViewGroup>
-                </ReactViewGroup>
-              </ReactViewGroup>
-            </ReactRootView>
-          </ContentFrameLayout>
-        </FitWindowsLinearLayout>
-      </FrameLayout>
-    </LinearLayout>
-    <View class="android.view.View" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" x="<number>" y="<number>" />
-    <View class="android.view.View" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" x="<number>" y="<number>" />
-  </DecorView>
-</ViewHierarchy>
diff --git a/detox/test/e2e/assets/view-hierarchy-web-view.71.ios.txt b/detox/test/e2e/assets/view-hierarchy-web-view.71.ios.txt
deleted file mode 100644
index cdf809ae6d..0000000000
--- a/detox/test/e2e/assets/view-hierarchy-web-view.71.ios.txt
+++ /dev/null
@@ -1,64 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<ViewHierarchy>
- <AnnoyingWindow alpha="1.0" class="AnnoyingWindow" focused="false" height="<number>" id="detox_temp_" visibility="visible" width="<number>">
-  <UITransitionView alpha="1.0" class="UITransitionView" focused="false" height="<number>" id="detox_temp_0" visibility="visible" width="<number>" x="<number>" y="<number>">
-   <UIDropShadowView alpha="1.0" class="UIDropShadowView" focused="false" height="<number>" id="detox_temp_0_0" visibility="visible" width="<number>" x="<number>" y="<number>">
-    <RCTRootView alpha="1.0" class="RCTRootView" focused="false" height="<number>" id="detox_temp_0_0_0" visibility="visible" width="<number>" x="<number>" y="<number>">
-     <RCTRootContentView alpha="1.0" class="RCTRootContentView" focused="false" height="<number>" label="Show 2nd webview Show 3rd webview Vertical scroll bar, 4 pages Horizontal scroll bar, 1 page" visibility="visible" width="<number>" x="<number>" y="<number>">
-      <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" label="Show 2nd webview Show 3rd webview Vertical scroll bar, 4 pages Horizontal scroll bar, 1 page" visibility="visible" width="<number>" x="<number>" y="<number>">
-       <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" label="Show 2nd webview Show 3rd webview Vertical scroll bar, 4 pages Horizontal scroll bar, 1 page" visibility="visible" width="<number>" x="<number>" y="<number>">
-        <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" label="Show 2nd webview Show 3rd webview Vertical scroll bar, 4 pages Horizontal scroll bar, 1 page" visibility="visible" width="<number>" x="<number>" y="<number>">
-         <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" label="Show 2nd webview Show 3rd webview" visibility="visible" width="<number>" x="<number>" y="<number>">
-          <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" label="Show 2nd webview" visibility="visible" width="<number>" x="<number>" y="<number>">
-           <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" id="toggle2ndWebviewButton" label="Show 2nd webview" visibility="visible" width="<number>" x="<number>" y="<number>">
-            <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" label="Show 2nd webview" visibility="visible" width="<number>" x="<number>" y="<number>">
-             <RCTTextView alpha="1.0" class="RCTTextView" focused="false" height="<number>" label="Show 2nd webview" visibility="visible" width="<number>" x="<number>" y="<number>" />
-            </RCTView>
-           </RCTView>
-          </RCTView>
-          <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" label="Show 3rd webview" visibility="visible" width="<number>" x="<number>" y="<number>">
-           <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" id="toggle3rdWebviewButton" label="Show 3rd webview" visibility="visible" width="<number>" x="<number>" y="<number>">
-            <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" label="Show 3rd webview" visibility="visible" width="<number>" x="<number>" y="<number>">
-             <RCTTextView alpha="1.0" class="RCTTextView" focused="false" height="<number>" label="Show 3rd webview" visibility="visible" width="<number>" x="<number>" y="<number>" />
-            </RCTView>
-           </RCTView>
-          </RCTView>
-         </RCTView>
-         <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" label="Vertical scroll bar, 4 pages Horizontal scroll bar, 1 page" visibility="visible" width="<number>" x="<number>" y="<number>">
-          <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" label="Vertical scroll bar, 4 pages Horizontal scroll bar, 1 page" visibility="visible" width="<number>" x="<number>" y="<number>">
-           <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" label="Vertical scroll bar, 4 pages Horizontal scroll bar, 1 page" visibility="visible" width="<number>" x="<number>" y="<number>">
-            <RNCWebView alpha="1.0" class="RNCWebView" focused="false" height="<number>" id="webViewFormWithScrolling" label="Vertical scroll bar, 4 pages Horizontal scroll bar, 1 page" visibility="visible" width="<number>" x="<number>" y="<number>">
-             <WKWebView alpha="1.0" class="WKWebView" focused="false" height="<number>" visibility="visible" width="<number>" x="<number>" y="<number>">
-             	<![CDATA[<html xmlns="http://www.w3.org/1999/xhtml">
-    <body>
-        <h1 id="pageHeadline" aria-label="first-webview">First Webview</h1>
-        <h2>Form</h2>
-        <form>
-            <label for="fname">Your name:</label><br />
-            <input type="text" id="fname" name="fname" maxlength="<number>" /><br />
-            <input type="submit" id="submit" value="Submit" onclick="document.getElementById('resultFname').innerHTML = document.getElementById('fname').value; return false;" />
-        </form>
-        <h2>Form Results</h2>
-        <p>Your first name is: <span id="resultFname">No input yet</span></p>
-        <h2>Content Editable</h2>
-        <div id="contentEditable" class="contentEditable" contenteditable="true">Name: </div>
-        <h2>Text and link</h2>
-        <p>Some text and a <a id="w3link" href="https://www.w3schools.com">link</a>.</p>
-        <p id="bottomParagraph" class="specialParagraph">This is a bottom paragraph with class.</p>
-
-</body></html>]]>
-             </WKWebView>
-            </RNCWebView>
-           </RCTView>
-          </RCTView>
-         </RCTView>
-        </RCTView>
-       </RCTView>
-      </RCTView>
-     </RCTRootContentView>
-    </RCTRootView>
-   </UIDropShadowView>
-  </UITransitionView>
-  <UILabel alpha="1.0" class="UILabel" focused="false" height="<number>" id="detox_temp_1" label="Active" text="Active" visibility="visible" width="<number>" x="<number>" y="<number>" />
- </AnnoyingWindow>
-</ViewHierarchy>
diff --git a/detox/test/e2e/assets/view-hierarchy-with-test-id-injection.71.android.txt b/detox/test/e2e/assets/view-hierarchy-with-test-id-injection.71.android.txt
deleted file mode 100644
index 9613748ce4..0000000000
--- a/detox/test/e2e/assets/view-hierarchy-with-test-id-injection.71.android.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version='1.0' encoding='UTF_8' standalone='yes' ?>
-<ViewHierarchy>
-  <DecorView class="com.android.internal.policy.DecorView" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" x="<number>" y="<number>" id="detox_temp_">
-    <LinearLayout class="android.widget.LinearLayout" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" x="<number>" y="<number>" id="detox_temp_0">
-      <ViewStub class="android.view.ViewStub" width="<number>" height="<number>" visibility="gone" alpha="1.0" focused="false" x="<number>" y="<number>" id="detox_temp_0_0" />
-      <FrameLayout class="android.widget.FrameLayout" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" x="<number>" y="<number>" id="detox_temp_0_1">
-        <FitWindowsLinearLayout class="androidx.appcompat.widget.FitWindowsLinearLayout" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" x="<number>" y="<number>" id="detox_temp_0_1_0">
-          <ViewStubCompat class="androidx.appcompat.widget.ViewStubCompat" width="<number>" height="<number>" visibility="gone" alpha="1.0" focused="false" x="<number>" y="<number>" id="detox_temp_0_1_0_0" />
-          <ContentFrameLayout class="androidx.appcompat.widget.ContentFrameLayout" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" x="<number>" y="<number>" id="detox_temp_0_1_0_1">
-            <ReactRootView class="com.facebook.react.ReactRootView" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" label="Welcome Say Hello Say World" x="<number>" y="<number>" id="detox_temp_0_1_0_1_0">
-              <ReactViewGroup class="com.facebook.react.views.view.ReactViewGroup" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" label="Welcome Say Hello Say World" x="<number>" y="<number>" id="detox_temp_0_1_0_1_0_0">
-                <ReactViewGroup class="com.facebook.react.views.view.ReactViewGroup" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" label="Welcome Say Hello Say World" x="<number>" y="<number>" id="detox_temp_0_1_0_1_0_0_0">
-                  <ReactViewGroup class="com.facebook.react.views.view.ReactViewGroup" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" label="Welcome Say Hello Say World" x="<number>" y="<number>" id="detox_temp_0_1_0_1_0_0_0_0">
-                    <ReactTextView class="com.facebook.react.views.text.ReactTextView" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" label="Welcome" x="<number>" y="<number>" text="Welcome" id="detox_temp_0_1_0_1_0_0_0_0_0" />
-                    <ReactViewGroup class="com.facebook.react.views.view.ReactViewGroup" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" label="Say Hello" x="<number>" y="<number>" id="detox_temp_0_1_0_1_0_0_0_0_1">
-                      <ReactTextView class="com.facebook.react.views.text.ReactTextView" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" label="Say Hello" x="<number>" y="<number>" text="Say Hello" id="detox_temp_0_1_0_1_0_0_0_0_1_0" />
-                    </ReactViewGroup>
-                    <ReactViewGroup class="com.facebook.react.views.view.ReactViewGroup" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" label="Say World" x="<number>" y="<number>" id="detox_temp_0_1_0_1_0_0_0_0_2">
-                      <ReactTextView class="com.facebook.react.views.text.ReactTextView" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" label="Say World" x="<number>" y="<number>" text="Say World" id="detox_temp_0_1_0_1_0_0_0_0_2_0" />
-                    </ReactViewGroup>
-                  </ReactViewGroup>
-                </ReactViewGroup>
-              </ReactViewGroup>
-            </ReactRootView>
-          </ContentFrameLayout>
-        </FitWindowsLinearLayout>
-      </FrameLayout>
-    </LinearLayout>
-    <View class="android.view.View" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" x="<number>" y="<number>" id="detox_temp_1" />
-    <View class="android.view.View" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" x="<number>" y="<number>" id="detox_temp_2" />
-  </DecorView>
-</ViewHierarchy>
diff --git a/detox/test/e2e/assets/view-hierarchy-with-test-id-injection.71.ios.txt b/detox/test/e2e/assets/view-hierarchy-with-test-id-injection.71.ios.txt
deleted file mode 100644
index c88d7f37c6..0000000000
--- a/detox/test/e2e/assets/view-hierarchy-with-test-id-injection.71.ios.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<ViewHierarchy>
- <AnnoyingWindow alpha="1.0" class="AnnoyingWindow" focused="false" height="<number>" id="detox_temp_" visibility="visible" width="<number>">
-  <UITransitionView alpha="1.0" class="UITransitionView" focused="false" height="<number>" id="detox_temp_0" visibility="visible" width="<number>" x="<number>" y="<number>">
-   <UIDropShadowView alpha="1.0" class="UIDropShadowView" focused="false" height="<number>" id="detox_temp_0_0" visibility="visible" width="<number>" x="<number>" y="<number>">
-    <RCTRootView alpha="1.0" class="RCTRootView" focused="false" height="<number>" id="detox_temp_0_0_0" visibility="visible" width="<number>" x="<number>" y="<number>">
-     <RCTRootContentView alpha="1.0" class="RCTRootContentView" focused="false" height="<number>" id="detox_temp_0_0_0_0" label="Welcome Say Hello Say World" visibility="visible" width="<number>" x="<number>" y="<number>">
-      <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" id="detox_temp_0_0_0_0_0" label="Welcome Say Hello Say World" visibility="visible" width="<number>" x="<number>" y="<number>">
-       <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" id="detox_temp_0_0_0_0_0_0" label="Welcome Say Hello Say World" visibility="visible" width="<number>" x="<number>" y="<number>">
-        <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" id="detox_temp_0_0_0_0_0_0_0" label="Welcome Say Hello Say World" visibility="visible" width="<number>" x="<number>" y="<number>">
-         <RCTTextView alpha="1.0" class="RCTTextView" focused="false" height="<number>" id="detox_temp_0_0_0_0_0_0_0_0" label="Welcome" visibility="visible" width="<number>" x="<number>" y="<number>" />
-         <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" id="detox_temp_0_0_0_0_0_0_0_1" label="Say Hello" visibility="visible" width="<number>" x="<number>" y="<number>">
-          <RCTTextView alpha="1.0" class="RCTTextView" focused="false" height="<number>" id="detox_temp_0_0_0_0_0_0_0_1_0" label="Say Hello" visibility="visible" width="<number>" x="<number>" y="<number>" />
-         </RCTView>
-         <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" id="detox_temp_0_0_0_0_0_0_0_2" label="Say World" visibility="visible" width="<number>" x="<number>" y="<number>">
-          <RCTTextView alpha="1.0" class="RCTTextView" focused="false" height="<number>" id="detox_temp_0_0_0_0_0_0_0_2_0" label="Say World" visibility="visible" width="<number>" x="<number>" y="<number>" />
-         </RCTView>
-        </RCTView>
-       </RCTView>
-      </RCTView>
-     </RCTRootContentView>
-    </RCTRootView>
-   </UIDropShadowView>
-  </UITransitionView>
-  <UILabel alpha="1.0" class="UILabel" focused="false" height="<number>" id="detox_temp_1" label="Active" text="Active" visibility="visible" width="<number>" x="<number>" y="<number>" />
- </AnnoyingWindow>
-</ViewHierarchy>
diff --git a/detox/test/e2e/assets/view-hierarchy-without-test-id-injection.71.android.txt b/detox/test/e2e/assets/view-hierarchy-without-test-id-injection.71.android.txt
deleted file mode 100644
index f73e77f8ea..0000000000
--- a/detox/test/e2e/assets/view-hierarchy-without-test-id-injection.71.android.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version='1.0' encoding='UTF_8' standalone='yes' ?>
-<ViewHierarchy>
-  <DecorView class="com.android.internal.policy.DecorView" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" x="<number>" y="<number>">
-    <LinearLayout class="android.widget.LinearLayout" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" x="<number>" y="<number>">
-      <ViewStub class="android.view.ViewStub" width="<number>" height="<number>" visibility="gone" alpha="1.0" focused="false" x="<number>" y="<number>" />
-      <FrameLayout class="android.widget.FrameLayout" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" x="<number>" y="<number>">
-        <FitWindowsLinearLayout class="androidx.appcompat.widget.FitWindowsLinearLayout" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" x="<number>" y="<number>">
-          <ViewStubCompat class="androidx.appcompat.widget.ViewStubCompat" width="<number>" height="<number>" visibility="gone" alpha="1.0" focused="false" x="<number>" y="<number>" />
-          <ContentFrameLayout class="androidx.appcompat.widget.ContentFrameLayout" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" x="<number>" y="<number>">
-            <ReactRootView class="com.facebook.react.ReactRootView" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" label="Welcome Say Hello Say World" x="<number>" y="<number>">
-              <ReactViewGroup class="com.facebook.react.views.view.ReactViewGroup" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" label="Welcome Say Hello Say World" x="<number>" y="<number>">
-                <ReactViewGroup class="com.facebook.react.views.view.ReactViewGroup" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" label="Welcome Say Hello Say World" x="<number>" y="<number>">
-                  <ReactViewGroup class="com.facebook.react.views.view.ReactViewGroup" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" label="Welcome Say Hello Say World" x="<number>" y="<number>">
-                    <ReactTextView class="com.facebook.react.views.text.ReactTextView" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" label="Welcome" x="<number>" y="<number>" text="Welcome" />
-                    <ReactViewGroup class="com.facebook.react.views.view.ReactViewGroup" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" label="Say Hello" x="<number>" y="<number>">
-                      <ReactTextView class="com.facebook.react.views.text.ReactTextView" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" label="Say Hello" x="<number>" y="<number>" text="Say Hello" />
-                    </ReactViewGroup>
-                    <ReactViewGroup class="com.facebook.react.views.view.ReactViewGroup" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" label="Say World" x="<number>" y="<number>">
-                      <ReactTextView class="com.facebook.react.views.text.ReactTextView" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" label="Say World" x="<number>" y="<number>" text="Say World" />
-                    </ReactViewGroup>
-                  </ReactViewGroup>
-                </ReactViewGroup>
-              </ReactViewGroup>
-            </ReactRootView>
-          </ContentFrameLayout>
-        </FitWindowsLinearLayout>
-      </FrameLayout>
-    </LinearLayout>
-    <View class="android.view.View" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" x="<number>" y="<number>" />
-    <View class="android.view.View" width="<number>" height="<number>" visibility="visible" alpha="1.0" focused="false" x="<number>" y="<number>" />
-  </DecorView>
-</ViewHierarchy>
diff --git a/detox/test/e2e/assets/view-hierarchy-without-test-id-injection.71.ios.txt b/detox/test/e2e/assets/view-hierarchy-without-test-id-injection.71.ios.txt
deleted file mode 100644
index 47f5778eaa..0000000000
--- a/detox/test/e2e/assets/view-hierarchy-without-test-id-injection.71.ios.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<ViewHierarchy>
- <AnnoyingWindow alpha="1.0" class="AnnoyingWindow" focused="false" height="<number>" visibility="visible" width="<number>">
-  <UITransitionView alpha="1.0" class="UITransitionView" focused="false" height="<number>" visibility="visible" width="<number>" x="<number>" y="<number>">
-   <UIDropShadowView alpha="1.0" class="UIDropShadowView" focused="false" height="<number>" visibility="visible" width="<number>" x="<number>" y="<number>">
-    <RCTRootView alpha="1.0" class="RCTRootView" focused="false" height="<number>" visibility="visible" width="<number>" x="<number>" y="<number>">
-     <RCTRootContentView alpha="1.0" class="RCTRootContentView" focused="false" height="<number>" label="Welcome Say Hello Say World" visibility="visible" width="<number>" x="<number>" y="<number>">
-      <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" label="Welcome Say Hello Say World" visibility="visible" width="<number>" x="<number>" y="<number>">
-       <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" label="Welcome Say Hello Say World" visibility="visible" width="<number>" x="<number>" y="<number>">
-        <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" label="Welcome Say Hello Say World" visibility="visible" width="<number>" x="<number>" y="<number>">
-         <RCTTextView alpha="1.0" class="RCTTextView" focused="false" height="<number>" label="Welcome" visibility="visible" width="<number>" x="<number>" y="<number>" />
-         <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" label="Say Hello" visibility="visible" width="<number>" x="<number>" y="<number>">
-          <RCTTextView alpha="1.0" class="RCTTextView" focused="false" height="<number>" label="Say Hello" visibility="visible" width="<number>" x="<number>" y="<number>" />
-         </RCTView>
-         <RCTView alpha="1.0" class="RCTView" focused="false" height="<number>" label="Say World" visibility="visible" width="<number>" x="<number>" y="<number>">
-          <RCTTextView alpha="1.0" class="RCTTextView" focused="false" height="<number>" label="Say World" visibility="visible" width="<number>" x="<number>" y="<number>" />
-         </RCTView>
-        </RCTView>
-       </RCTView>
-      </RCTView>
-     </RCTRootContentView>
-    </RCTRootView>
-   </UIDropShadowView>
-  </UITransitionView>
-  <UILabel alpha="1.0" class="UILabel" focused="false" height="<number>" label="Active" text="Active" visibility="visible" width="<number>" x="<number>" y="<number>" />
- </AnnoyingWindow>
-</ViewHierarchy>

From c469c8b9d9f6cad433f89ec49e17fb6335da9c29 Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Wed, 1 Jan 2025 17:17:41 +0200
Subject: [PATCH 42/51] revert(test): use old string for native root native
 module.

---
 detox/test/e2e/08.stress-root.test.js         |  2 +-
 .../test/ios/ReactModules/NativeModule.swift  | 68 +++++++++----------
 2 files changed, 35 insertions(+), 35 deletions(-)

diff --git a/detox/test/e2e/08.stress-root.test.js b/detox/test/e2e/08.stress-root.test.js
index 277da273b2..8e5113922c 100644
--- a/detox/test/e2e/08.stress-root.test.js
+++ b/detox/test/e2e/08.stress-root.test.js
@@ -10,7 +10,7 @@ describe('StressRoot', () => {
 
   it('should switch root view controller from RN to native', async () => {
     await element(by.text('Switch to a new native root')).tap();
-    await expect(element(by.text('This is a new native root'))).toBeVisible();
+    await expect(element(by.text('this is a new native root'))).toBeVisible();
   });
 
   it(':ios: should switch root view controller from RN to RN', async () => {
diff --git a/detox/test/ios/ReactModules/NativeModule.swift b/detox/test/ios/ReactModules/NativeModule.swift
index 9fd6856ef4..40e2d8543b 100644
--- a/detox/test/ios/ReactModules/NativeModule.swift
+++ b/detox/test/ios/ReactModules/NativeModule.swift
@@ -9,38 +9,38 @@ import UIKit
 
 @objc(NativeModule)
 class NativeModule: NSObject, RCTBridgeModule {
-    
+
     // MARK: - Properties
-    
+
     var overlayWindow: UIWindow?
     var overlayView: UIView?
     var callCounter: Int = 0
-    
+
     // MARK: - RCTBridgeModule
-    
+
     static func moduleName() -> String! {
         return "NativeModule"
     }
-    
+
     static func requiresMainQueueSetup() -> Bool {
         // Indicates that the module must be initialized on the main thread
         return true
     }
-    
+
     // MARK: - Lifecycle Methods
-    
+
     override init() {
         super.init()
         self.callCounter = 0
     }
-    
+
     // MARK: - Echo Methods
-    
+
     @objc
     func echoWithoutResponse(_ str: String) {
         self.callCounter += 1
     }
-    
+
     @objc
     func echoWithResponse(_ str: String,
                           resolver resolve: @escaping RCTPromiseResolveBlock,
@@ -48,9 +48,9 @@ class NativeModule: NSObject, RCTBridgeModule {
         self.callCounter += 1
         resolve(str)
     }
-    
+
     // MARK: - Timing Methods
-    
+
     @objc
     func nativeSetTimeout(_ delay: TimeInterval,
                           block: @escaping RCTResponseSenderBlock) {
@@ -61,9 +61,9 @@ class NativeModule: NSObject, RCTBridgeModule {
             }
         }
     }
-    
+
     // MARK: - Navigation Methods
-    
+
     @objc
     func switchToNativeRoot() {
         executeOnMainThread { [weak self] in
@@ -72,7 +72,7 @@ class NativeModule: NSObject, RCTBridgeModule {
             self.updateRootViewController(newRoot)
         }
     }
-    
+
     @objc
     func switchToMultipleReactRoots() {
         executeOnMainThread { [weak self] in
@@ -81,9 +81,9 @@ class NativeModule: NSObject, RCTBridgeModule {
             self.updateRootViewController(tabController)
         }
     }
-    
+
     // MARK: - Notification Methods
-    
+
     @objc
     func sendNotification(_ notification: String, name: String) {
         executeOnMainThread {
@@ -92,25 +92,25 @@ class NativeModule: NSObject, RCTBridgeModule {
                                             userInfo: ["name": name])
         }
     }
-    
+
     // MARK: - Overlay Methods
-    
+
     @objc
     func presentOverlayWindow() {
         executeOnMainThread { [weak self] in
             self?.setupAndShowOverlayWindow()
         }
     }
-    
+
     @objc
     func presentOverlayView() {
         executeOnMainThread { [weak self] in
             self?.setupAndShowOverlayView()
         }
     }
-    
+
     // MARK: - Private Helper Methods
-    
+
     private func executeOnMainThread(_ block: @escaping () -> Void) {
         if Thread.isMainThread {
             block()
@@ -120,44 +120,44 @@ class NativeModule: NSObject, RCTBridgeModule {
             }
         }
     }
-    
+
     private func createNativeRootViewController() -> UIViewController {
         let newRoot = UIViewController()
         newRoot.view.backgroundColor = .white
-        
+
         let label = UILabel()
-        label.text = "This is a new native root"
+        label.text = "this is a new native root"
         label.sizeToFit()
         label.center = newRoot.view.center
         newRoot.view.addSubview(label)
-        
+
         return newRoot
     }
-    
+
     private func createTabBarControllerWithBridge() -> UITabBarController {
         guard let bridge = getCurrentBridge() else {
             fatalError("RCTBridge is not available")
         }
-        
+
         let viewControllers = [
             createReactRootViewController(bridge: bridge, title: "1"),
             createReactRootViewController(bridge: bridge, title: "2"),
             createReactRootViewController(bridge: bridge, title: "3"),
             createReactRootViewController(bridge: bridge, title: "4")
         ]
-        
+
         let tabController = UITabBarController()
         tabController.viewControllers = viewControllers
         return tabController
     }
-    
+
     private func createReactRootViewController(bridge: RCTBridge, title: String) -> UIViewController {
         let viewController = UIViewController()
         viewController.view = RCTRootView(bridge: bridge, moduleName: "example", initialProperties: nil)
         viewController.tabBarItem.title = title
         return viewController
     }
-    
+
     private func getCurrentBridge() -> RCTBridge? {
         guard let delegate = UIApplication.shared.delegate as? AppDelegate,
               let window = delegate.window,
@@ -166,7 +166,7 @@ class NativeModule: NSObject, RCTBridgeModule {
         }
         return rootView.bridge
     }
-    
+
     private func updateRootViewController(_ viewController: UIViewController) {
         guard let delegate = UIApplication.shared.delegate as? AppDelegate,
               let window = delegate.window else {
@@ -175,7 +175,7 @@ class NativeModule: NSObject, RCTBridgeModule {
         window.rootViewController = viewController
         window.makeKeyAndVisible()
     }
-    
+
     private func setupAndShowOverlayWindow() {
         let screenBounds = UIScreen.main.bounds
         overlayWindow = UIWindow(frame: screenBounds)
@@ -184,7 +184,7 @@ class NativeModule: NSObject, RCTBridgeModule {
         overlayWindow?.isHidden = false
         overlayWindow?.makeKeyAndVisible()
     }
-    
+
     private func setupAndShowOverlayView() {
         guard let keyWindow = UIApplication.shared.keyWindow else { return }
         let screenBounds = UIScreen.main.bounds

From 58e775773a0a77a03b203556c5e51edacbbc7908 Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Wed, 1 Jan 2025 17:25:10 +0200
Subject: [PATCH 43/51] test: remove old RN workarounds from podfile.

---
 examples/demo-react-native/ios/Podfile      | 21 +++++----------------
 scripts/change_all_react_native_versions.sh |  0
 2 files changed, 5 insertions(+), 16 deletions(-)
 mode change 100644 => 100755 scripts/change_all_react_native_versions.sh

diff --git a/examples/demo-react-native/ios/Podfile b/examples/demo-react-native/ios/Podfile
index f165377191..fd8c4dc722 100644
--- a/examples/demo-react-native/ios/Podfile
+++ b/examples/demo-react-native/ios/Podfile
@@ -1,14 +1,8 @@
-if ENV["REACT_NATIVE_VERSION"] && ENV["REACT_NATIVE_VERSION"].match(/0.(70|71).*/)
-    require_relative '../node_modules/react-native/scripts/react_native_pods'
-    require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
-else
-    # Resolve react_native_pods.rb with node to allow for hoisting
-    require Pod::Executable.execute_command('node', ['-p',
-      'require.resolve(
-        "react-native/scripts/react_native_pods.rb",
-        {paths: [process.argv[1]]},
-      )', __dir__]).strip
-end
+require Pod::Executable.execute_command('node', ['-p',
+  'require.resolve(
+    "react-native/scripts/react_native_pods.rb",
+    {paths: [process.argv[1]]},
+  )', __dir__]).strip
 
 platform :ios, min_ios_version_supported
 
@@ -33,11 +27,6 @@ target 'example' do
        # necessary for Mac Catalyst builds
        :mac_catalyst_enabled => false
      )
-
-    # See https://github.com/wix/Detox/pull/3035#discussion_r774747705
-    if ENV["REACT_NATIVE_VERSION"] && ENV["REACT_NATIVE_VERSION"].match(/0.(70|72).*/)
-     __apply_Xcode_12_5_M1_post_install_workaround(installer)
-    end
   end
 end
 
diff --git a/scripts/change_all_react_native_versions.sh b/scripts/change_all_react_native_versions.sh
old mode 100644
new mode 100755

From 207673c22905e13bb557e1fd7612e0b33d644a18 Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Wed, 1 Jan 2025 18:48:36 +0200
Subject: [PATCH 44/51] test: update snapshots.

---
 detox/test/e2e/assets/view-hierarchy-web-view.73.ios.txt | 9 ++++-----
 detox/test/e2e/assets/view-hierarchy-web-view.75.ios.txt | 9 ++++-----
 .../view-hierarchy-with-test-id-injection.73.ios.txt     | 5 ++---
 .../view-hierarchy-with-test-id-injection.75.ios.txt     | 7 +++----
 .../view-hierarchy-without-test-id-injection.73.ios.txt  | 5 ++---
 .../view-hierarchy-without-test-id-injection.75.ios.txt  | 7 +++----
 6 files changed, 18 insertions(+), 24 deletions(-)

diff --git a/detox/test/e2e/assets/view-hierarchy-web-view.73.ios.txt b/detox/test/e2e/assets/view-hierarchy-web-view.73.ios.txt
index 22552e8c06..7f119af50e 100644
--- a/detox/test/e2e/assets/view-hierarchy-web-view.73.ios.txt
+++ b/detox/test/e2e/assets/view-hierarchy-web-view.73.ios.txt
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <ViewHierarchy>
- <AnnoyingWindow alpha="1.0" class="AnnoyingWindow" focused="false" height="<number>" id="detox_temp_" visibility="visible" width="<number>">
+ <UIWindow alpha="1.0" class="UIWindow" focused="false" height="<number>" id="detox_temp_" visibility="visible" width="<number>">
   <UITransitionView alpha="1.0" class="UITransitionView" focused="false" height="<number>" id="detox_temp_0" visibility="visible" width="<number>" x="<number>" y="<number>">
    <UIDropShadowView alpha="1.0" class="UIDropShadowView" focused="false" height="<number>" id="detox_temp_0_0" visibility="visible" width="<number>" x="<number>" y="<number>">
     <RCTRootView alpha="1.0" class="RCTRootView" focused="false" height="<number>" id="detox_temp_0_0_0" visibility="visible" width="<number>" x="<number>" y="<number>">
@@ -48,7 +48,7 @@
         <h2>Text and link</h2>
         <p>Some text and a <a id="w3link" href="https://www.w3schools.com">link</a>.</p>
         <p id="bottomParagraph" class="specialParagraph">This is a bottom paragraph with class.</p>
-    
+
 
 </body></html>]]>
              </RNCWKWebView>
@@ -63,6 +63,5 @@
     </RCTRootView>
    </UIDropShadowView>
   </UITransitionView>
-  <UILabel alpha="1.0" class="UILabel" focused="false" height="<number>" id="detox_temp_1" label="Active" text="Active" visibility="visible" width="<number>" x="<number>" y="<number>" />
- </AnnoyingWindow>
-</ViewHierarchy>
\ No newline at end of file
+ </UIWindow>
+</ViewHierarchy>
diff --git a/detox/test/e2e/assets/view-hierarchy-web-view.75.ios.txt b/detox/test/e2e/assets/view-hierarchy-web-view.75.ios.txt
index 8e020b72e1..3a9af9cda7 100644
--- a/detox/test/e2e/assets/view-hierarchy-web-view.75.ios.txt
+++ b/detox/test/e2e/assets/view-hierarchy-web-view.75.ios.txt
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <ViewHierarchy>
- <AnnoyingWindow alpha="1.0" class="AnnoyingWindow" focused="false" height="<number>" id="detox_temp_" visibility="visible" width="<number>">
+ <UIWindow alpha="1.0" class="UIWindow" focused="false" height="<number>" id="detox_temp_" visibility="visible" width="<number>">
   <UITransitionView alpha="1.0" class="UITransitionView" focused="false" height="<number>" id="detox_temp_0" visibility="visible" width="<number>" x="<number>" y="<number>">
    <UIDropShadowView alpha="1.0" class="UIDropShadowView" focused="false" height="<number>" id="detox_temp_0_0" visibility="visible" width="<number>" x="<number>" y="<number>">
     <RCTRootView alpha="1.0" class="RCTRootView" focused="false" height="<number>" id="detox_temp_0_0_0" visibility="visible" width="<number>" x="<number>" y="<number>">
@@ -47,7 +47,7 @@
         <h2>Text and link</h2>
         <p>Some text and a <a id="w3link" href="https://www.w3schools.com">link</a>.</p>
         <p id="bottomParagraph" class="specialParagraph">This is a bottom paragraph with class.</p>
-    
+
 
 </body></html>]]>
             </RNCWKWebView>
@@ -61,6 +61,5 @@
     </RCTRootView>
    </UIDropShadowView>
   </UITransitionView>
-  <UILabel alpha="1.0" class="UILabel" focused="false" height="<number>" id="detox_temp_1" label="Active" text="Active" visibility="visible" width="<number>" x="<number>" y="<number>" />
- </AnnoyingWindow>
-</ViewHierarchy>
\ No newline at end of file
+ </UIWindow>
+</ViewHierarchy>
diff --git a/detox/test/e2e/assets/view-hierarchy-with-test-id-injection.73.ios.txt b/detox/test/e2e/assets/view-hierarchy-with-test-id-injection.73.ios.txt
index c88d7f37c6..c13d85a1bb 100644
--- a/detox/test/e2e/assets/view-hierarchy-with-test-id-injection.73.ios.txt
+++ b/detox/test/e2e/assets/view-hierarchy-with-test-id-injection.73.ios.txt
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <ViewHierarchy>
- <AnnoyingWindow alpha="1.0" class="AnnoyingWindow" focused="false" height="<number>" id="detox_temp_" visibility="visible" width="<number>">
+ <UIWindow alpha="1.0" class="UIWindow" focused="false" height="<number>" id="detox_temp_" visibility="visible" width="<number>">
   <UITransitionView alpha="1.0" class="UITransitionView" focused="false" height="<number>" id="detox_temp_0" visibility="visible" width="<number>" x="<number>" y="<number>">
    <UIDropShadowView alpha="1.0" class="UIDropShadowView" focused="false" height="<number>" id="detox_temp_0_0" visibility="visible" width="<number>" x="<number>" y="<number>">
     <RCTRootView alpha="1.0" class="RCTRootView" focused="false" height="<number>" id="detox_temp_0_0_0" visibility="visible" width="<number>" x="<number>" y="<number>">
@@ -22,6 +22,5 @@
     </RCTRootView>
    </UIDropShadowView>
   </UITransitionView>
-  <UILabel alpha="1.0" class="UILabel" focused="false" height="<number>" id="detox_temp_1" label="Active" text="Active" visibility="visible" width="<number>" x="<number>" y="<number>" />
- </AnnoyingWindow>
+ </UIWindow>
 </ViewHierarchy>
diff --git a/detox/test/e2e/assets/view-hierarchy-with-test-id-injection.75.ios.txt b/detox/test/e2e/assets/view-hierarchy-with-test-id-injection.75.ios.txt
index fba29973c5..88f9d7e59f 100644
--- a/detox/test/e2e/assets/view-hierarchy-with-test-id-injection.75.ios.txt
+++ b/detox/test/e2e/assets/view-hierarchy-with-test-id-injection.75.ios.txt
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <ViewHierarchy>
- <AnnoyingWindow alpha="1.0" class="AnnoyingWindow" focused="false" height="<number>" id="detox_temp_" visibility="visible" width="<number>">
+ <UIWindow alpha="1.0" class="UIWindow" focused="false" height="<number>" id="detox_temp_" visibility="visible" width="<number>">
   <UITransitionView alpha="1.0" class="UITransitionView" focused="false" height="<number>" id="detox_temp_0" visibility="visible" width="<number>" x="<number>" y="<number>">
    <UIDropShadowView alpha="1.0" class="UIDropShadowView" focused="false" height="<number>" id="detox_temp_0_0" visibility="visible" width="<number>" x="<number>" y="<number>">
     <RCTRootView alpha="1.0" class="RCTRootView" focused="false" height="<number>" id="detox_temp_0_0_0" visibility="visible" width="<number>" x="<number>" y="<number>">
@@ -20,6 +20,5 @@
     </RCTRootView>
    </UIDropShadowView>
   </UITransitionView>
-  <UILabel alpha="1.0" class="UILabel" focused="false" height="<number>" id="detox_temp_1" label="Active" text="Active" visibility="visible" width="<number>" x="<number>" y="<number>" />
- </AnnoyingWindow>
-</ViewHierarchy>
\ No newline at end of file
+ </UIWindow>
+</ViewHierarchy>
diff --git a/detox/test/e2e/assets/view-hierarchy-without-test-id-injection.73.ios.txt b/detox/test/e2e/assets/view-hierarchy-without-test-id-injection.73.ios.txt
index 47f5778eaa..6cf7b869f9 100644
--- a/detox/test/e2e/assets/view-hierarchy-without-test-id-injection.73.ios.txt
+++ b/detox/test/e2e/assets/view-hierarchy-without-test-id-injection.73.ios.txt
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <ViewHierarchy>
- <AnnoyingWindow alpha="1.0" class="AnnoyingWindow" focused="false" height="<number>" visibility="visible" width="<number>">
+ <UIWindow alpha="1.0" class="UIWindow" focused="false" height="<number>" visibility="visible" width="<number>">
   <UITransitionView alpha="1.0" class="UITransitionView" focused="false" height="<number>" visibility="visible" width="<number>" x="<number>" y="<number>">
    <UIDropShadowView alpha="1.0" class="UIDropShadowView" focused="false" height="<number>" visibility="visible" width="<number>" x="<number>" y="<number>">
     <RCTRootView alpha="1.0" class="RCTRootView" focused="false" height="<number>" visibility="visible" width="<number>" x="<number>" y="<number>">
@@ -22,6 +22,5 @@
     </RCTRootView>
    </UIDropShadowView>
   </UITransitionView>
-  <UILabel alpha="1.0" class="UILabel" focused="false" height="<number>" label="Active" text="Active" visibility="visible" width="<number>" x="<number>" y="<number>" />
- </AnnoyingWindow>
+ </UIWindow>
 </ViewHierarchy>
diff --git a/detox/test/e2e/assets/view-hierarchy-without-test-id-injection.75.ios.txt b/detox/test/e2e/assets/view-hierarchy-without-test-id-injection.75.ios.txt
index fd1fc31bac..7379b47549 100644
--- a/detox/test/e2e/assets/view-hierarchy-without-test-id-injection.75.ios.txt
+++ b/detox/test/e2e/assets/view-hierarchy-without-test-id-injection.75.ios.txt
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <ViewHierarchy>
- <AnnoyingWindow alpha="1.0" class="AnnoyingWindow" focused="false" height="<number>" visibility="visible" width="<number>">
+ <UIWindow alpha="1.0" class="UIWindow" focused="false" height="<number>" visibility="visible" width="<number>">
   <UITransitionView alpha="1.0" class="UITransitionView" focused="false" height="<number>" visibility="visible" width="<number>" x="<number>" y="<number>">
    <UIDropShadowView alpha="1.0" class="UIDropShadowView" focused="false" height="<number>" visibility="visible" width="<number>" x="<number>" y="<number>">
     <RCTRootView alpha="1.0" class="RCTRootView" focused="false" height="<number>" visibility="visible" width="<number>" x="<number>" y="<number>">
@@ -20,6 +20,5 @@
     </RCTRootView>
    </UIDropShadowView>
   </UITransitionView>
-  <UILabel alpha="1.0" class="UILabel" focused="false" height="<number>" label="Active" text="Active" visibility="visible" width="<number>" x="<number>" y="<number>" />
- </AnnoyingWindow>
-</ViewHierarchy>
\ No newline at end of file
+ </UIWindow>
+</ViewHierarchy>

From b1889a63992cc715f26a9a82a545240612e5610f Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Thu, 2 Jan 2025 10:47:02 +0200
Subject: [PATCH 45/51] ci: add new arch pipeline step for RN 76 + new arch +
 iOS.

---
 .buildkite/jobs/pipeline.ios_demo_app_rn_76.yml       |  1 +
 .../jobs/pipeline.ios_demo_app_rn_76_new_arch.yml     | 10 ++++++++++
 .buildkite/jobs/pipeline.ios_rn_76.yml                |  1 +
 .buildkite/jobs/pipeline.ios_rn_76_new_arch.yml       | 11 +++++++++++
 .buildkite/pipeline_common.sh                         |  2 ++
 5 files changed, 25 insertions(+)
 create mode 100644 .buildkite/jobs/pipeline.ios_demo_app_rn_76_new_arch.yml
 create mode 100644 .buildkite/jobs/pipeline.ios_rn_76_new_arch.yml

diff --git a/.buildkite/jobs/pipeline.ios_demo_app_rn_76.yml b/.buildkite/jobs/pipeline.ios_demo_app_rn_76.yml
index aff5caf84a..ad359422c9 100644
--- a/.buildkite/jobs/pipeline.ios_demo_app_rn_76.yml
+++ b/.buildkite/jobs/pipeline.ios_demo_app_rn_76.yml
@@ -4,6 +4,7 @@
       - "./scripts/demo-projects.ios.sh"
     env:
       REACT_NATIVE_VERSION: 0.76.3
+      RCT_NEW_ARCH_ENABLED: 0
     artifact_paths:
       - "/Users/builder/uibuilder/work/coverage/**/*.lcov"
       - "/Users/builder/uibuilder/work/artifacts*.tar.gz"
diff --git a/.buildkite/jobs/pipeline.ios_demo_app_rn_76_new_arch.yml b/.buildkite/jobs/pipeline.ios_demo_app_rn_76_new_arch.yml
new file mode 100644
index 0000000000..0a3b3d6f98
--- /dev/null
+++ b/.buildkite/jobs/pipeline.ios_demo_app_rn_76_new_arch.yml
@@ -0,0 +1,10 @@
+  - label: ":new::ios::react: RN .76 + iOS: Demo app"
+    command:
+      - "nvm install"
+      - "./scripts/demo-projects.ios.sh"
+    env:
+      REACT_NATIVE_VERSION: 0.76.3
+      RCT_NEW_ARCH_ENABLED: 1
+    artifact_paths:
+      - "/Users/builder/uibuilder/work/coverage/**/*.lcov"
+      - "/Users/builder/uibuilder/work/artifacts*.tar.gz"
diff --git a/.buildkite/jobs/pipeline.ios_rn_76.yml b/.buildkite/jobs/pipeline.ios_rn_76.yml
index b31ba4e00a..3b20cde7a5 100644
--- a/.buildkite/jobs/pipeline.ios_rn_76.yml
+++ b/.buildkite/jobs/pipeline.ios_rn_76.yml
@@ -4,6 +4,7 @@
       - "./scripts/ci.ios.sh"
     env:
       REACT_NATIVE_VERSION: 0.76.3
+      RCT_NEW_ARCH_ENABLED: 0
     artifact_paths:
       - "/Users/builder/uibuilder/work/coverage/**/*.lcov"
       - "/Users/builder/uibuilder/work/**/allure-report-*.html"
diff --git a/.buildkite/jobs/pipeline.ios_rn_76_new_arch.yml b/.buildkite/jobs/pipeline.ios_rn_76_new_arch.yml
new file mode 100644
index 0000000000..5ff264ed17
--- /dev/null
+++ b/.buildkite/jobs/pipeline.ios_rn_76_new_arch.yml
@@ -0,0 +1,11 @@
+  - label: ":new::ios::detox: RN .76 + New Arch + iOS: Tests app"
+    command:
+      - "nvm install"
+      - "./scripts/ci.ios.sh"
+    env:
+      REACT_NATIVE_VERSION: 0.76.3
+      RCT_NEW_ARCH_ENABLED: 1
+    artifact_paths:
+      - "/Users/builder/uibuilder/work/coverage/**/*.lcov"
+      - "/Users/builder/uibuilder/work/**/allure-report-*.html"
+      - "/Users/builder/uibuilder/work/artifacts*.tar.gz"
diff --git a/.buildkite/pipeline_common.sh b/.buildkite/pipeline_common.sh
index 4afa7835b7..54a62690cd 100755
--- a/.buildkite/pipeline_common.sh
+++ b/.buildkite/pipeline_common.sh
@@ -2,9 +2,11 @@
 
 echo "steps:"
 
+cat .buildkite/jobs/pipeline.ios_rn_76_new_arch.yml
 cat .buildkite/jobs/pipeline.ios_rn_76.yml
 cat .buildkite/jobs/pipeline.ios_rn_75.yml
 cat .buildkite/jobs/pipeline.ios_rn_73.yml
+cat .buildkite/jobs/pipeline.ios_demo_app_rn_76_new_arch.yml
 cat .buildkite/jobs/pipeline.ios_demo_app_rn_76.yml
 cat .buildkite/jobs/pipeline.android_rn_76.yml
 cat .buildkite/jobs/pipeline.android_rn_75.yml

From 24d519833c99581b99794c0847f78d8dab3634a8 Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Thu, 2 Jan 2025 12:15:02 +0200
Subject: [PATCH 46/51] test: update copilot cache.

---
 detox/test/detox_copilot_cache.json | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/detox/test/detox_copilot_cache.json b/detox/test/detox_copilot_cache.json
index 8bb236eae7..18461248f4 100644
--- a/detox/test/detox_copilot_cache.json
+++ b/detox/test/detox_copilot_cache.json
@@ -105,5 +105,17 @@
   "{\"step\":\"Verify there is an element with the text \\\"Get location\\\"\",\"previous\":[{\"step\":\"Restart the React Native state\",\"code\":\"await device.reloadReactNative();\"},{\"step\":\"Navigate to the Location screen\",\"code\":\"await element(by.label('Location')).tap();\"},{\"step\":\"Launch the app with location permission always\",\"code\":\"await device.launchApp({ \\n  newInstance: true,\\n  permissions: { location: 'always' }\\n});\"},{\"step\":\"Verify there is an element with the text \\\"Get location\\\"\",\"code\":\"throw new Error(\\\"No element with text 'Get location' found in the view hierarchy. Found 'Location' instead.\\\");\",\"result\":\"Caught an error while evaluating \\\"Verify there is an element with the text \\\"Get location\\\"\\\", tried with generated code: \\\"throw new Error(\\\"No element with text 'Get location' found in the view hierarchy. Found 'Location' instead.\\\");\\\". Validate the code against the APIs and hierarchy and continue with a different approach. If can't, return a code that throws a descriptive error.\"}],\"viewHierarchyHash\":\"b16ef5d51f0f64d6a63d434b26d81efc\"}": "throw new Error(\"No element with text 'Get location' found in the view hierarchy. Found 'Location' instead.\");",
   "{\"step\":\"Launch the app with location permission just once\",\"previous\":[{\"step\":\"Restart the React Native state\",\"code\":\"await device.reloadReactNative();\"},{\"step\":\"Navigate to the Location screen\",\"code\":\"await element(by.label('Location')).tap();\"}],\"viewHierarchyHash\":\"e79b58a41e3e4e6b49202372b5c1cc79\"}": "await device.launchApp({\n  newInstance: true,\n  permissions: { location: 'inuse' }\n});",
   "{\"step\":\"Verify there is an element with the text \\\"Get location\\\"\",\"previous\":[{\"step\":\"Restart the React Native state\",\"code\":\"await device.reloadReactNative();\"},{\"step\":\"Navigate to the Location screen\",\"code\":\"await element(by.label('Location')).tap();\"},{\"step\":\"Launch the app with location permission just once\",\"code\":\"await device.launchApp({\\n  newInstance: true,\\n  permissions: { location: 'inuse' }\\n});\"}],\"viewHierarchyHash\":\"b16ef5d51f0f64d6a63d434b26d81efc\"}": "await expect(element(by.text('Get location'))).toExist();",
-  "{\"step\":\"Verify there is an element with the text \\\"Get location\\\"\",\"previous\":[{\"step\":\"Restart the React Native state\",\"code\":\"await device.reloadReactNative();\"},{\"step\":\"Navigate to the Location screen\",\"code\":\"await element(by.label('Location')).tap();\"},{\"step\":\"Launch the app with location permission just once\",\"code\":\"await device.launchApp({\\n  newInstance: true,\\n  permissions: { location: 'inuse' }\\n});\"},{\"step\":\"Verify there is an element with the text \\\"Get location\\\"\",\"code\":\"await expect(element(by.text('Get location'))).toExist();\",\"result\":\"Caught an error while evaluating \\\"Verify there is an element with the text \\\"Get location\\\"\\\", tried with generated code: \\\"await expect(element(by.text('Get location'))).toExist();\\\". Validate the code against the APIs and hierarchy and continue with a different approach. If can't, return a code that throws a descriptive error.\"}],\"viewHierarchyHash\":\"b16ef5d51f0f64d6a63d434b26d81efc\"}": "throw new Error(\"Element with text 'Get location' is not found in the current view hierarchy\")"
+  "{\"step\":\"Verify there is an element with the text \\\"Get location\\\"\",\"previous\":[{\"step\":\"Restart the React Native state\",\"code\":\"await device.reloadReactNative();\"},{\"step\":\"Navigate to the Location screen\",\"code\":\"await element(by.label('Location')).tap();\"},{\"step\":\"Launch the app with location permission just once\",\"code\":\"await device.launchApp({\\n  newInstance: true,\\n  permissions: { location: 'inuse' }\\n});\"},{\"step\":\"Verify there is an element with the text \\\"Get location\\\"\",\"code\":\"await expect(element(by.text('Get location'))).toExist();\",\"result\":\"Caught an error while evaluating \\\"Verify there is an element with the text \\\"Get location\\\"\\\", tried with generated code: \\\"await expect(element(by.text('Get location'))).toExist();\\\". Validate the code against the APIs and hierarchy and continue with a different approach. If can't, return a code that throws a descriptive error.\"}],\"viewHierarchyHash\":\"b16ef5d51f0f64d6a63d434b26d81efc\"}": "throw new Error(\"Element with text 'Get location' is not found in the current view hierarchy\")",
+  "{\"step\":\"Remove the app and start a fresh instance\",\"previous\":[],\"viewHierarchyHash\":\"a14a74aaf07d6f92a7030643e4ac6895\"}": "await device.launchApp({\n  delete: true,\n  newInstance: true\n});",
+  "{\"step\":\"Navigate to the System Dialogs screen\",\"previous\":[{\"step\":\"Remove the app and start a fresh instance\",\"code\":\"await device.launchApp({\\n  delete: true,\\n  newInstance: true\\n});\"}],\"viewHierarchyHash\":\"a14a74aaf07d6f92a7030643e4ac6895\"}": "await element(by.text('System Dialogs')).tap();",
+  "{\"step\":\"Check that the initial permission status is \\\"denied\\\"\",\"previous\":[{\"step\":\"Remove the app and start a fresh instance\",\"code\":\"await device.launchApp({\\n  delete: true,\\n  newInstance: true\\n});\"},{\"step\":\"Navigate to the System Dialogs screen\",\"code\":\"await element(by.text('System Dialogs')).tap();\"}],\"viewHierarchyHash\":\"31263c8ad60867de323197ea33be2402\"}": "await expect(element(by.id('permissionStatus'))).toHaveText('denied');",
+  "{\"step\":\"Tap the button to request permission\",\"previous\":[{\"step\":\"Remove the app and start a fresh instance\",\"code\":\"await device.launchApp({\\n  delete: true,\\n  newInstance: true\\n});\"},{\"step\":\"Navigate to the System Dialogs screen\",\"code\":\"await element(by.text('System Dialogs')).tap();\"},{\"step\":\"Check that the initial permission status is \\\"denied\\\"\",\"code\":\"await expect(element(by.id('permissionStatus'))).toHaveText('denied');\"}],\"viewHierarchyHash\":\"31263c8ad60867de323197ea33be2402\"}": "await element(by.id('requestPermissionButton')).tap();",
+  "{\"step\":\"A system dialog appears asking for permission\",\"previous\":[{\"step\":\"Remove the app and start a fresh instance\",\"code\":\"await device.launchApp({\\n  delete: true,\\n  newInstance: true\\n});\"},{\"step\":\"Navigate to the System Dialogs screen\",\"code\":\"await element(by.text('System Dialogs')).tap();\"},{\"step\":\"Check that the initial permission status is \\\"denied\\\"\",\"code\":\"await expect(element(by.id('permissionStatus'))).toHaveText('denied');\"},{\"step\":\"Tap the button to request permission\",\"code\":\"await element(by.id('requestPermissionButton')).tap();\"}],\"viewHierarchyHash\":\"227afc5a25375e77c25cfdfc6a1c7fe6\"}": "await expect(system.element(by.system.label('Allow \"example-ci\" to track your activity across other companies' apps and websites?'))).toExist();",
+  "{\"step\":\"A system dialog appears asking for permission\",\"previous\":[{\"step\":\"Remove the app and start a fresh instance\",\"code\":\"await device.launchApp({\\n  delete: true,\\n  newInstance: true\\n});\"},{\"step\":\"Navigate to the System Dialogs screen\",\"code\":\"await element(by.text('System Dialogs')).tap();\"},{\"step\":\"Check that the initial permission status is \\\"denied\\\"\",\"code\":\"await expect(element(by.id('permissionStatus'))).toHaveText('denied');\"},{\"step\":\"Tap the button to request permission\",\"code\":\"await element(by.id('requestPermissionButton')).tap();\"},{\"step\":\"A system dialog appears asking for permission\",\"code\":\"await expect(system.element(by.system.label('Allow \\\"example-ci\\\" to track your activity across other companies' apps and websites?'))).toExist();\",\"result\":\"Caught an error while evaluating \\\"A system dialog appears asking for permission\\\", tried with generated code: \\\"await expect(system.element(by.system.label('Allow \\\"example-ci\\\" to track your activity across other companies' apps and websites?'))).toExist();\\\". Validate the code against the APIs and hierarchy and continue with a different approach. If can't, return a code that throws a descriptive error.\"}],\"viewHierarchyHash\":\"b85ab02e88af10d34333cce30397498f\"}": "await expect(system.element(by.system.label('Allow \"example-ci\" to track your activity across other companies' apps and websites?'))).toExist();",
+  "{\"step\":\"Remove the app and start a fresh instance\",\"previous\":[],\"viewHierarchyHash\":\"b85ab02e88af10d34333cce30397498f\"}": "await device.launchApp({\n  newInstance: true,\n  delete: true\n});",
+  "{\"step\":\"Restart the React Native state\",\"previous\":[],\"viewHierarchyHash\":\"66b21c68b8b89f4e8d7c1a733d789ea6\"}": "await device.reloadReactNative();",
+  "{\"step\":\"Navigate to the Assertions screen\",\"previous\":[{\"step\":\"Restart the React Native state\",\"code\":\"await device.reloadReactNative();\"}],\"viewHierarchyHash\":\"b16ef5d51f0f64d6a63d434b26d81efc\"}": "await element(by.text('Assertions')).tap();",
+  "{\"step\":\"Find an element with ID \\\"RandomJunk959\\\" in the screen\",\"previous\":[{\"step\":\"Restart the React Native state\",\"code\":\"await device.reloadReactNative();\"},{\"step\":\"Navigate to the Assertions screen\",\"code\":\"await element(by.text('Assertions')).tap();\"}],\"viewHierarchyHash\":\"66b21c68b8b89f4e8d7c1a733d789ea6\"}": "throw new Error(\"Element with ID 'RandomJunk959' not found in view hierarchy.\")",
+  "{\"step\":\"Verify there is a green text element\",\"previous\":[{\"step\":\"Restart the React Native state\",\"code\":\"await device.reloadReactNative();\"},{\"step\":\"Navigate to the Assertions screen\",\"code\":\"await element(by.text('Assertions')).tap();\"}],\"viewHierarchyHash\":\"66b21c68b8b89f4e8d7c1a733d789ea6\"}": "throw new Error(\"Cannot verify if text is green - color information is not available in the view hierarchy and cannot be visually confirmed from the snapshot.\");",
+  "{\"step\":\"Verify there is a green text element\",\"previous\":[{\"step\":\"Restart the React Native state\",\"code\":\"await device.reloadReactNative();\"},{\"step\":\"Navigate to the Assertions screen\",\"code\":\"await element(by.text('Assertions')).tap();\"},{\"step\":\"Verify there is a green text element\",\"code\":\"throw new Error(\\\"Cannot verify if text is green - color information is not available in the view hierarchy and cannot be visually confirmed from the snapshot.\\\");\",\"result\":\"Caught an error while evaluating \\\"Verify there is a green text element\\\", tried with generated code: \\\"throw new Error(\\\"Cannot verify if text is green - color information is not available in the view hierarchy and cannot be visually confirmed from the snapshot.\\\");\\\". Validate the code against the APIs and hierarchy and continue with a different approach. If can't, return a code that throws a descriptive error.\"}],\"viewHierarchyHash\":\"66b21c68b8b89f4e8d7c1a733d789ea6\"}": "throw new Error(\"Cannot verify if text is green - color attributes are not available through the testing framework APIs for verification\");"
 }
\ No newline at end of file

From abb9ae441bf1fbce675ad945d1127e6cedb4157c Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Thu, 2 Jan 2025 14:45:33 +0200
Subject: [PATCH 47/51] test: print if react native new arch is enabled.

---
 detox/test/ios/Podfile | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/detox/test/ios/Podfile b/detox/test/ios/Podfile
index 4aabdff2ed..ceeda69c06 100644
--- a/detox/test/ios/Podfile
+++ b/detox/test/ios/Podfile
@@ -1,3 +1,7 @@
+if ENV['RCT_NEW_ARCH_ENABLED'] == '1'
+  puts 'React Native new arch enabled (RCT_NEW_ARCH_ENABLED = 1)'
+end
+
 def node_require(script)
   # Resolve script with node to allow for hoisting
   require Pod::Executable.execute_command('node', ['-p',

From 6902b2337261a2bb194f4ddf9f62aeaafc68735a Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Thu, 2 Jan 2025 15:37:09 +0200
Subject: [PATCH 48/51] test: skip picker tests on new arch.

---
 detox/test/e2e/17.datePicker.test.js          |  3 +-
 detox/test/e2e/17.picker.test.js              |  4 +-
 .../e2e/copilot/09.copilot.datepicker.test.js | 94 ++++++++++---------
 detox/test/e2e/utils/custom-describes.js      | 29 ++++--
 4 files changed, 76 insertions(+), 54 deletions(-)

diff --git a/detox/test/e2e/17.datePicker.test.js b/detox/test/e2e/17.datePicker.test.js
index f664941e67..131065b053 100644
--- a/detox/test/e2e/17.datePicker.test.js
+++ b/detox/test/e2e/17.datePicker.test.js
@@ -1,6 +1,7 @@
+const { describeNewArchNotSupported } = require('./utils/custom-describes');
 const jestExpect = require('expect').default;
 
-describe('DatePicker', () => {
+describeNewArchNotSupported('DatePicker', () => {
   describe.each([
     ['ios', 'compact', 0],
     ['ios', 'inline', 1],
diff --git a/detox/test/e2e/17.picker.test.js b/detox/test/e2e/17.picker.test.js
index 14e0f3a852..a6be677257 100644
--- a/detox/test/e2e/17.picker.test.js
+++ b/detox/test/e2e/17.picker.test.js
@@ -1,4 +1,6 @@
-describe(":ios: Picker", () => {
+const { describeNewArchNotSupported } = require('./utils/custom-describes');
+
+describeNewArchNotSupported(":ios: Picker", () => {
     beforeEach(async () => {
       await device.reloadReactNative();
       await element(by.text("Picker")).tap();
diff --git a/detox/test/e2e/copilot/09.copilot.datepicker.test.js b/detox/test/e2e/copilot/09.copilot.datepicker.test.js
index ad35350efd..d894508fa1 100644
--- a/detox/test/e2e/copilot/09.copilot.datepicker.test.js
+++ b/detox/test/e2e/copilot/09.copilot.datepicker.test.js
@@ -1,58 +1,60 @@
-const { describeForCopilotEnv } = require('../utils/custom-describes');
+const { describeForCopilotEnv, describeNewArchNotSupported } = require('../utils/custom-describes');
 const { default: jestExpect } = require('expect');
 
-describeForCopilotEnv('DatePicker', () => {
-  beforeEach(async () => {
-    await copilot.perform(
-      'Restart the React Native state',
-      'Navigate to the DatePicker screen'
-    );
-  });
-
-  describe('DatePicker Tests', () => {
-
-    // Note: when writing "Date (UTC):" instead of "Date (UTC): " copilot failed the test
-    it('correct date and time', async () => {
+describeNewArchNotSupported('DatePicker', () => {
+  describeForCopilotEnv('Copilot', () => {
+    beforeEach(async () => {
       await copilot.perform(
-        'Verify there is element with the text "Date (UTC): "',
-        'Verify the element value of current date UTC July 1st 2023',
-        'Verify there is element with the text "Time (UTC): "',
-        'Verify there is element with the text "Time Local: "',
-        'Verify "Time Local: " value is 7:30 pm'
+        'Restart the React Native state',
+        'Navigate to the DatePicker screen'
       );
     });
 
-    it('compact date picker', async () => {
-      await copilot.perform(
-        'Verify there is an element with the text "Compact Date Picker"',
-        'Verify there is an element with today`s date at the bottom of the screen',
-        'Set the date picker to September 9th, 2023'
-      );
-    });
+    describe('DatePicker Tests', () => {
 
-    it('inline date picker', async () => {
-      await copilot.perform(
-        'Verify there is an element with the text "Compact Date Picker"',
-        'Tap the element with the text "Compact Date Picker"',
-        'Verify there is an element with the text "Inline Date Picker"',
-        'Verify there is an element with today`s date at the bottom of the screen',
-        'Set the date picker to September 9th, 2023'
-      );
-    });
+      // Note: when writing "Date (UTC):" instead of "Date (UTC): " copilot failed the test
+      it('correct date and time', async () => {
+        await copilot.perform(
+          'Verify there is element with the text "Date (UTC): "',
+          'Verify the element value of current date UTC July 1st 2023',
+          'Verify there is element with the text "Time (UTC): "',
+          'Verify there is element with the text "Time Local: "',
+          'Verify "Time Local: " value is 7:30 pm'
+        );
+      });
 
-    it('switch to spinner date picker', async () => {
-      await copilot.perform(
-        'Verify there is an element with the text "Compact Date Picker"',
-        'Tap the element with the text "Compact Date Picker"',
-        'Verify there is an element with the text "Inline Date Picker"',
-        'Tap the element with the text "Inline Date Picker"',
-        'Verify that there is slider element at the bottom of the screen',
-        'Set the date picker to September 9th, 2023'
-      );
+      it('compact date picker', async () => {
+        await copilot.perform(
+          'Verify there is an element with the text "Compact Date Picker"',
+          'Verify there is an element with today`s date at the bottom of the screen',
+          'Set the date picker to September 9th, 2023'
+        );
+      });
+
+      it('inline date picker', async () => {
+        await copilot.perform(
+          'Verify there is an element with the text "Compact Date Picker"',
+          'Tap the element with the text "Compact Date Picker"',
+          'Verify there is an element with the text "Inline Date Picker"',
+          'Verify there is an element with today`s date at the bottom of the screen',
+          'Set the date picker to September 9th, 2023'
+        );
+      });
+
+      it('switch to spinner date picker', async () => {
+        await copilot.perform(
+          'Verify there is an element with the text "Compact Date Picker"',
+          'Tap the element with the text "Compact Date Picker"',
+          'Verify there is an element with the text "Inline Date Picker"',
+          'Tap the element with the text "Inline Date Picker"',
+          'Verify that there is slider element at the bottom of the screen',
+          'Set the date picker to September 9th, 2023'
+        );
 
-      await jestExpect(async () =>
-        await copilot.perform('Set the date picker`s first column to 10th, so the date will be September 10th, 2023')
-      ).rejects.toThrowError();
+        await jestExpect(async () =>
+          await copilot.perform('Set the date picker`s first column to 10th, so the date will be September 10th, 2023')
+        ).rejects.toThrowError();
+      });
     });
   });
 });
diff --git a/detox/test/e2e/utils/custom-describes.js b/detox/test/e2e/utils/custom-describes.js
index d44f4872a4..f66cb3f168 100644
--- a/detox/test/e2e/utils/custom-describes.js
+++ b/detox/test/e2e/utils/custom-describes.js
@@ -1,13 +1,14 @@
 const axios = require('axios');
 const PromptHandler = require("./PromptHandler");
 
-const describeOrDescribeSkip = process.env.CI === 'true' ? describe.skip : describe;
-
 describeForCopilotEnv = (description, fn) => {
-  describeOrDescribeSkip(':ios: Copilot', () => {
+  const isCI = process.env.CI === 'true';
+  const describeOrDescribeSkipIfCI = isCI ? describe.skip : describe;
+
+  describeOrDescribeSkipIfCI(':ios: Copilot', () => {
     describe(description, () => {
       beforeAll(async () => {
-        if (!await checkVpnStatus()) {
+        if (!await _checkVpnStatus()) {
           console.warn('Cannot access the LLM service without Wix BO environment. Relying on cached responses only.');
         }
         try {
@@ -25,7 +26,7 @@ describeForCopilotEnv = (description, fn) => {
   });
 };
 
-checkVpnStatus = async () => {
+_checkVpnStatus = async () => {
   try {
     const response = await axios.get('https://bo.wix.com/_serverless/expert-toolkit/checkVpn');
     return response.data.enabled === true;
@@ -35,6 +36,22 @@ checkVpnStatus = async () => {
   }
 };
 
+describeNewArchNotSupported = (description, fn) => {
+  const isNewArch = process.env.RCT_NEW_ARCH_ENABLED === '1';
+  const describeOrDescribeSkipIfNewArch = isNewArch ? describe.skip : describe;
+
+  if (isNewArch) {
+    console.warn('Skipping tests for new architecture, as there are issues related to the new architecture.');
+  }
+
+  describeOrDescribeSkipIfNewArch('Legacy Arch (Paper)', () => {
+    describe(description, () => {
+      fn();
+    });
+  });
+}
+
 module.exports = {
-  describeForCopilotEnv
+  describeForCopilotEnv,
+  describeNewArchNotSupported
 };

From e017d396dbb19c03e22b8e453bbd6c44ae68cca0 Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Mon, 6 Jan 2025 15:41:37 +0200
Subject: [PATCH 49/51] test(custom-describe): change to skip methods.

---
 detox/test/e2e/17.datePicker.test.js          |  3 +-
 detox/test/e2e/17.picker.test.js              |  4 +-
 .../e2e/copilot/01.copilot.sanity.test.js     |  4 +-
 .../e2e/copilot/02.copilot.actions.test.js    |  3 +-
 .../copilot/03.copilot.shape-match.test.js    |  4 +-
 detox/test/e2e/copilot/04.webview.test.js     |  4 +-
 detox/test/e2e/copilot/05.system.test.js      |  3 +-
 detox/test/e2e/copilot/06.waitfor.test.js     |  3 +-
 .../e2e/copilot/07.copilot.assertions.test.js |  3 +-
 .../e2e/copilot/08.copilot.location.test.js   |  3 +-
 .../e2e/copilot/09.copilot.datepicker.test.js |  5 +--
 .../e2e/copilot/10.copilot.visibility.test.js |  3 +-
 detox/test/e2e/setup.js                       |  1 +
 detox/test/e2e/utils/custom-describes.js      | 40 ++++++++-----------
 14 files changed, 30 insertions(+), 53 deletions(-)

diff --git a/detox/test/e2e/17.datePicker.test.js b/detox/test/e2e/17.datePicker.test.js
index 131065b053..f8bab7608a 100644
--- a/detox/test/e2e/17.datePicker.test.js
+++ b/detox/test/e2e/17.datePicker.test.js
@@ -1,7 +1,6 @@
-const { describeNewArchNotSupported } = require('./utils/custom-describes');
 const jestExpect = require('expect').default;
 
-describeNewArchNotSupported('DatePicker', () => {
+describe.skipIfNewArch('DatePicker', () => {
   describe.each([
     ['ios', 'compact', 0],
     ['ios', 'inline', 1],
diff --git a/detox/test/e2e/17.picker.test.js b/detox/test/e2e/17.picker.test.js
index a6be677257..a2cd329b39 100644
--- a/detox/test/e2e/17.picker.test.js
+++ b/detox/test/e2e/17.picker.test.js
@@ -1,6 +1,4 @@
-const { describeNewArchNotSupported } = require('./utils/custom-describes');
-
-describeNewArchNotSupported(":ios: Picker", () => {
+describe.skipIfNewArch(":ios: Picker", () => {
     beforeEach(async () => {
       await device.reloadReactNative();
       await element(by.text("Picker")).tap();
diff --git a/detox/test/e2e/copilot/01.copilot.sanity.test.js b/detox/test/e2e/copilot/01.copilot.sanity.test.js
index 56b5995a6f..9de6e4dac1 100644
--- a/detox/test/e2e/copilot/01.copilot.sanity.test.js
+++ b/detox/test/e2e/copilot/01.copilot.sanity.test.js
@@ -1,6 +1,4 @@
-const {describeForCopilotEnv} = require("../utils/custom-describes");
-
-describeForCopilotEnv('Copilot Sanity', () => {
+describe.forCopilot('Copilot Sanity', () => {
   beforeEach(async () => {
     await copilot.perform(
       'Restart the React Native state',
diff --git a/detox/test/e2e/copilot/02.copilot.actions.test.js b/detox/test/e2e/copilot/02.copilot.actions.test.js
index bee228e8e8..f18e213505 100644
--- a/detox/test/e2e/copilot/02.copilot.actions.test.js
+++ b/detox/test/e2e/copilot/02.copilot.actions.test.js
@@ -1,7 +1,6 @@
-const {describeForCopilotEnv} = require("../utils/custom-describes");
 const jestExpect = require('expect').default;
 
-describeForCopilotEnv('Copilot Actions', () => {
+describe.forCopilot('Copilot Actions', () => {
   beforeEach(async () => {
     await copilot.perform(
       'Restart the React Native environment',
diff --git a/detox/test/e2e/copilot/03.copilot.shape-match.test.js b/detox/test/e2e/copilot/03.copilot.shape-match.test.js
index a9aab84752..50e3c3dad1 100644
--- a/detox/test/e2e/copilot/03.copilot.shape-match.test.js
+++ b/detox/test/e2e/copilot/03.copilot.shape-match.test.js
@@ -1,6 +1,4 @@
-const {describeForCopilotEnv} = require("../utils/custom-describes");
-
-describeForCopilotEnv('Shape Match Game Screen', () => {
+describe.forCopilot('Shape Match Game Screen', () => {
   beforeEach(async () => {
     await copilot.perform(
       'Reset react native state',
diff --git a/detox/test/e2e/copilot/04.webview.test.js b/detox/test/e2e/copilot/04.webview.test.js
index c66c4c57ef..1e6a7346be 100644
--- a/detox/test/e2e/copilot/04.webview.test.js
+++ b/detox/test/e2e/copilot/04.webview.test.js
@@ -1,6 +1,4 @@
-const {describeForCopilotEnv} = require("../utils/custom-describes");
-
-describeForCopilotEnv('WebView Interactions', () => {
+describe.forCopilot('WebView Interactions', () => {
   beforeEach(async () => {
     await copilot.perform(
       'Restart the React Native state',
diff --git a/detox/test/e2e/copilot/05.system.test.js b/detox/test/e2e/copilot/05.system.test.js
index ef6f5ad3df..3dbcc5a68a 100644
--- a/detox/test/e2e/copilot/05.system.test.js
+++ b/detox/test/e2e/copilot/05.system.test.js
@@ -1,7 +1,6 @@
-const {describeForCopilotEnv} = require("../utils/custom-describes");
 const {expectToThrow} = require("../utils/custom-expects");
 
-describeForCopilotEnv(':ios: iOS Permission Dialogs', () => {
+describe.forCopilot(':ios: iOS Permission Dialogs', () => {
   beforeEach(async () => {
     await copilot.perform(
       'Remove the app and start a fresh instance',
diff --git a/detox/test/e2e/copilot/06.waitfor.test.js b/detox/test/e2e/copilot/06.waitfor.test.js
index 675397351a..ed9c7c0663 100644
--- a/detox/test/e2e/copilot/06.waitfor.test.js
+++ b/detox/test/e2e/copilot/06.waitfor.test.js
@@ -1,7 +1,6 @@
-const {describeForCopilotEnv} = require("../utils/custom-describes");
 const {expectToThrow} = require("../utils/custom-expects");
 
-describeForCopilotEnv('WaitFor Functionality', () => {
+describe.forCopilot('WaitFor Functionality', () => {
   beforeEach(async () => {
     await copilot.perform(
       'Restart the React Native environment',
diff --git a/detox/test/e2e/copilot/07.copilot.assertions.test.js b/detox/test/e2e/copilot/07.copilot.assertions.test.js
index 1a9932031d..ef44b46007 100644
--- a/detox/test/e2e/copilot/07.copilot.assertions.test.js
+++ b/detox/test/e2e/copilot/07.copilot.assertions.test.js
@@ -1,7 +1,6 @@
-const { describeForCopilotEnv } = require('../utils/custom-describes');
 const jestExpect = require('expect').default;
 
-describeForCopilotEnv('Assertions', () => {
+describe.forCopilot('Assertions', () => {
   beforeEach(async () => {
     await copilot.perform(
       'Restart the React Native state',
diff --git a/detox/test/e2e/copilot/08.copilot.location.test.js b/detox/test/e2e/copilot/08.copilot.location.test.js
index ea7a1600cf..c03a1d8b67 100644
--- a/detox/test/e2e/copilot/08.copilot.location.test.js
+++ b/detox/test/e2e/copilot/08.copilot.location.test.js
@@ -1,10 +1,9 @@
-const { describeForCopilotEnv } = require('../utils/custom-describes');
 const DUMMY_COORDINATE1_LONGITUDE = '66.5';
 const DUMMY_COORDINATE1_LATITUDE = '-80.125';
 const DUMMY_COORDINATE2_LONGITUDE = '-80.125';
 const DUMMY_COORDINATE2_LATITUDE = '66.5';
 
-describeForCopilotEnv('Location', () => {
+describe.forCopilot('Location', () => {
   beforeEach(async () => {
     await copilot.perform(
       'Restart the React Native state',
diff --git a/detox/test/e2e/copilot/09.copilot.datepicker.test.js b/detox/test/e2e/copilot/09.copilot.datepicker.test.js
index d894508fa1..6d12f16d05 100644
--- a/detox/test/e2e/copilot/09.copilot.datepicker.test.js
+++ b/detox/test/e2e/copilot/09.copilot.datepicker.test.js
@@ -1,8 +1,7 @@
-const { describeForCopilotEnv, describeNewArchNotSupported } = require('../utils/custom-describes');
 const { default: jestExpect } = require('expect');
 
-describeNewArchNotSupported('DatePicker', () => {
-  describeForCopilotEnv('Copilot', () => {
+describe.skipIfNewArch('DatePicker', () => {
+  describe.forCopilot('Copilot', () => {
     beforeEach(async () => {
       await copilot.perform(
         'Restart the React Native state',
diff --git a/detox/test/e2e/copilot/10.copilot.visibility.test.js b/detox/test/e2e/copilot/10.copilot.visibility.test.js
index 0d96e27bdc..3fedddf908 100644
--- a/detox/test/e2e/copilot/10.copilot.visibility.test.js
+++ b/detox/test/e2e/copilot/10.copilot.visibility.test.js
@@ -1,7 +1,6 @@
-const {describeForCopilotEnv} = require("../utils/custom-describes");
 const { default: jestExpect } = require('expect');
 
-describeForCopilotEnv('Visibility', () => {
+describe.forCopilot('Visibility', () => {
   describe('Visibility Expectation', () => {
     beforeEach(async () => {
       await copilot.perform(
diff --git a/detox/test/e2e/setup.js b/detox/test/e2e/setup.js
index a2bc5ea2a7..deda7dd184 100644
--- a/detox/test/e2e/setup.js
+++ b/detox/test/e2e/setup.js
@@ -1,4 +1,5 @@
 const { device } = require('detox');
+require('./utils/custom-describes');
 
 beforeAll(async () => {
   await device.selectApp('example');
diff --git a/detox/test/e2e/utils/custom-describes.js b/detox/test/e2e/utils/custom-describes.js
index f66cb3f168..a42898101b 100644
--- a/detox/test/e2e/utils/custom-describes.js
+++ b/detox/test/e2e/utils/custom-describes.js
@@ -1,11 +1,22 @@
 const axios = require('axios');
 const PromptHandler = require("./PromptHandler");
 
-describeForCopilotEnv = (description, fn) => {
+describe.skipIfCI = (title, fn) => {
   const isCI = process.env.CI === 'true';
-  const describeOrDescribeSkipIfCI = isCI ? describe.skip : describe;
+  return isCI ? describe.skip(title, fn) : describe(title, fn);
+};
+
+describe.skipIfNewArch = (title, fn) => {
+  const isNewArch = process.env.RCT_NEW_ARCH_ENABLED === '1';
+  if (isNewArch) {
+    console.warn('Skipping tests for new architecture, as there are issues related to the new architecture.');
+    return describe.skip(title, fn);
+  }
+  return describe(title, fn);
+};
 
-  describeOrDescribeSkipIfCI(':ios: Copilot', () => {
+describe.forCopilot = (description, fn) => {
+  return describe.skipIfCI(':ios: Copilot', () => {
     describe(description, () => {
       beforeAll(async () => {
         if (!await _checkVpnStatus()) {
@@ -15,6 +26,7 @@ describeForCopilotEnv = (description, fn) => {
           await copilot.init(new PromptHandler());
         } catch (error) {
           if (error.message.includes('Copilot has already been initialized')) {
+            // Ignore already initialized error
           } else {
             throw error;
           }
@@ -26,7 +38,7 @@ describeForCopilotEnv = (description, fn) => {
   });
 };
 
-_checkVpnStatus = async () => {
+const _checkVpnStatus = async () => {
   try {
     const response = await axios.get('https://bo.wix.com/_serverless/expert-toolkit/checkVpn');
     return response.data.enabled === true;
@@ -35,23 +47,3 @@ _checkVpnStatus = async () => {
     return false;
   }
 };
-
-describeNewArchNotSupported = (description, fn) => {
-  const isNewArch = process.env.RCT_NEW_ARCH_ENABLED === '1';
-  const describeOrDescribeSkipIfNewArch = isNewArch ? describe.skip : describe;
-
-  if (isNewArch) {
-    console.warn('Skipping tests for new architecture, as there are issues related to the new architecture.');
-  }
-
-  describeOrDescribeSkipIfNewArch('Legacy Arch (Paper)', () => {
-    describe(description, () => {
-      fn();
-    });
-  });
-}
-
-module.exports = {
-  describeForCopilotEnv,
-  describeNewArchNotSupported
-};

From 30b0dacdf9bc21fae19d2fbbfe0e04f1c8faa69c Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Mon, 6 Jan 2025 15:50:46 +0200
Subject: [PATCH 50/51] ci: remove common & redundant steps from pipelines.

---
 .buildkite/jobs/pipeline.ios_demo_app_rn_76.yml | 10 ----------
 .buildkite/jobs/pipeline.ios_rn_75.yml          | 10 ----------
 .buildkite/pipeline_common.sh                   |  2 --
 3 files changed, 22 deletions(-)
 delete mode 100644 .buildkite/jobs/pipeline.ios_demo_app_rn_76.yml
 delete mode 100644 .buildkite/jobs/pipeline.ios_rn_75.yml

diff --git a/.buildkite/jobs/pipeline.ios_demo_app_rn_76.yml b/.buildkite/jobs/pipeline.ios_demo_app_rn_76.yml
deleted file mode 100644
index ad359422c9..0000000000
--- a/.buildkite/jobs/pipeline.ios_demo_app_rn_76.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-  - label: ":ios::react: RN .76 + iOS: Demo app"
-    command:
-      - "nvm install"
-      - "./scripts/demo-projects.ios.sh"
-    env:
-      REACT_NATIVE_VERSION: 0.76.3
-      RCT_NEW_ARCH_ENABLED: 0
-    artifact_paths:
-      - "/Users/builder/uibuilder/work/coverage/**/*.lcov"
-      - "/Users/builder/uibuilder/work/artifacts*.tar.gz"
diff --git a/.buildkite/jobs/pipeline.ios_rn_75.yml b/.buildkite/jobs/pipeline.ios_rn_75.yml
deleted file mode 100644
index 71332023d9..0000000000
--- a/.buildkite/jobs/pipeline.ios_rn_75.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-  - label: ":ios::detox: RN .75 + iOS: Tests app"
-    command:
-      - "nvm install"
-      - "./scripts/ci.ios.sh"
-    env:
-      REACT_NATIVE_VERSION: 0.75.4
-    artifact_paths:
-      - "/Users/builder/uibuilder/work/coverage/**/*.lcov"
-      - "/Users/builder/uibuilder/work/**/allure-report-*.html"
-      - "/Users/builder/uibuilder/work/artifacts*.tar.gz"
diff --git a/.buildkite/pipeline_common.sh b/.buildkite/pipeline_common.sh
index 54a62690cd..907bfad145 100755
--- a/.buildkite/pipeline_common.sh
+++ b/.buildkite/pipeline_common.sh
@@ -4,10 +4,8 @@ echo "steps:"
 
 cat .buildkite/jobs/pipeline.ios_rn_76_new_arch.yml
 cat .buildkite/jobs/pipeline.ios_rn_76.yml
-cat .buildkite/jobs/pipeline.ios_rn_75.yml
 cat .buildkite/jobs/pipeline.ios_rn_73.yml
 cat .buildkite/jobs/pipeline.ios_demo_app_rn_76_new_arch.yml
-cat .buildkite/jobs/pipeline.ios_demo_app_rn_76.yml
 cat .buildkite/jobs/pipeline.android_rn_76.yml
 cat .buildkite/jobs/pipeline.android_rn_75.yml
 cat .buildkite/jobs/pipeline.android_rn_73.yml

From 0b9b92f281bcfbe0efa4eacaf746457389202161 Mon Sep 17 00:00:00 2001
From: Asaf Korem <asaf.korem@gmail.com>
Date: Mon, 6 Jan 2025 16:06:03 +0200
Subject: [PATCH 51/51] test: change skip method to skip only on iOS.

---
 detox/test/e2e/17.datePicker.test.js                 | 2 +-
 detox/test/e2e/17.picker.test.js                     | 2 +-
 detox/test/e2e/copilot/09.copilot.datepicker.test.js | 2 +-
 detox/test/e2e/utils/custom-describes.js             | 4 ++--
 4 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/detox/test/e2e/17.datePicker.test.js b/detox/test/e2e/17.datePicker.test.js
index f8bab7608a..2f59ae6097 100644
--- a/detox/test/e2e/17.datePicker.test.js
+++ b/detox/test/e2e/17.datePicker.test.js
@@ -1,6 +1,6 @@
 const jestExpect = require('expect').default;
 
-describe.skipIfNewArch('DatePicker', () => {
+describe.skipIfNewArchOnIOS('DatePicker', () => {
   describe.each([
     ['ios', 'compact', 0],
     ['ios', 'inline', 1],
diff --git a/detox/test/e2e/17.picker.test.js b/detox/test/e2e/17.picker.test.js
index a2cd329b39..258d448ebf 100644
--- a/detox/test/e2e/17.picker.test.js
+++ b/detox/test/e2e/17.picker.test.js
@@ -1,4 +1,4 @@
-describe.skipIfNewArch(":ios: Picker", () => {
+describe.skipIfNewArchOnIOS(":ios: Picker", () => {
     beforeEach(async () => {
       await device.reloadReactNative();
       await element(by.text("Picker")).tap();
diff --git a/detox/test/e2e/copilot/09.copilot.datepicker.test.js b/detox/test/e2e/copilot/09.copilot.datepicker.test.js
index 6d12f16d05..afba3912e0 100644
--- a/detox/test/e2e/copilot/09.copilot.datepicker.test.js
+++ b/detox/test/e2e/copilot/09.copilot.datepicker.test.js
@@ -1,6 +1,6 @@
 const { default: jestExpect } = require('expect');
 
-describe.skipIfNewArch('DatePicker', () => {
+describe.skipIfNewArchOnIOS('DatePicker', () => {
   describe.forCopilot('Copilot', () => {
     beforeEach(async () => {
       await copilot.perform(
diff --git a/detox/test/e2e/utils/custom-describes.js b/detox/test/e2e/utils/custom-describes.js
index a42898101b..ee0013e348 100644
--- a/detox/test/e2e/utils/custom-describes.js
+++ b/detox/test/e2e/utils/custom-describes.js
@@ -6,9 +6,9 @@ describe.skipIfCI = (title, fn) => {
   return isCI ? describe.skip(title, fn) : describe(title, fn);
 };
 
-describe.skipIfNewArch = (title, fn) => {
+describe.skipIfNewArchOnIOS = (title, fn) => {
   const isNewArch = process.env.RCT_NEW_ARCH_ENABLED === '1';
-  if (isNewArch) {
+  if (isNewArch && device.getPlatform() === 'ios') {
     console.warn('Skipping tests for new architecture, as there are issues related to the new architecture.');
     return describe.skip(title, fn);
   }