<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: VINIT RAJ</title>
    <description>The latest articles on DEV Community by VINIT RAJ (@vinitraj10).</description>
    <link>https://dev.to/vinitraj10</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2793065%2F562f4957-7c4b-4ce0-90a7-5b495bdff649.jpg</url>
      <title>DEV Community: VINIT RAJ</title>
      <link>https://dev.to/vinitraj10</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vinitraj10"/>
    <language>en</language>
    <item>
      <title>Maestro + CircleCI for React Native: The Practical Setup</title>
      <dc:creator>VINIT RAJ</dc:creator>
      <pubDate>Mon, 12 May 2025 23:13:29 +0000</pubDate>
      <link>https://dev.to/vinitraj10/maestro-circleci-for-react-native-the-practical-setup-5b64</link>
      <guid>https://dev.to/vinitraj10/maestro-circleci-for-react-native-the-practical-setup-5b64</guid>
      <description>&lt;p&gt;Alright, if you’re building a React Native app without &lt;strong&gt;&lt;a href="https://docs.expo.dev/eas/workflows/reference/e2e-tests/" rel="noopener noreferrer"&gt;Expo EAS&lt;/a&gt;&lt;/strong&gt;, or if you prefer the flexibility of your own custom setup rather than relying on managed services like &lt;strong&gt;&lt;a href="https://www.maestro.dev/pricing" rel="noopener noreferrer"&gt;Maestro Cloud&lt;/a&gt;&lt;/strong&gt; for test orchestration, setting up proper end-to-end (E2E) testing on &lt;strong&gt;&lt;a href="https://circleci.com/" rel="noopener noreferrer"&gt;CircleCI&lt;/a&gt;&lt;/strong&gt; can be challenging. While many apps are moving towards the full Expo ecosystem. Given that it’s the officially &lt;a href="https://reactnative.dev/blog/2024/06/25/use-a-framework-to-build-react-native-apps" rel="noopener noreferrer"&gt;recommended framework&lt;/a&gt; from the React Native team, there are still plenty of projects using custom build systems and standalone frameworks, where having fine-grained control over your CI/CD pipeline is crucial.&lt;/p&gt;

&lt;p&gt;I’ve often found myself building custom setups for E2E testing because I like keeping things under my control – without relying too much on managed services. This approach keeps things flexible, scalable, and cost-effective, but it also means you need to get the details right. If you’re in the same boat, this guide is for you.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Gist of It
&lt;/h3&gt;

&lt;p&gt;If you’re ready to jump right into the code, check out the &lt;a href="https://gist.github.com/vinitraj10/424561861419fe6e986b9f2cd070a860/" rel="noopener noreferrer"&gt;&lt;strong&gt;Gist on GitHub&lt;/strong&gt;&lt;/a&gt; – a complete, ready-to-run &lt;code&gt;config.yml&lt;/code&gt; for running Maestro tests on CircleCI. It includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reusable test command (&lt;code&gt;run-maestro-tests&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;iOS and Android job configurations&lt;/li&gt;
&lt;li&gt;Best practices for stable test runs on virtualized CI environments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fork it, tweak it, and drop a star if it saves you some headaches.&lt;/p&gt;




&lt;h3&gt;
  
  
  Breaking Down the &lt;code&gt;config.yml&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Here’s a quick breakdown of the key sections:&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Orbs
&lt;/h4&gt;

&lt;p&gt;I have used the CircleCI Android orb to simplify emulator setup and build:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;orbs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;android&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;circleci/android@3.1.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. Execution Environment
&lt;/h4&gt;

&lt;p&gt;Using the macOS execution environment for iOS, which you can read more about &lt;a href="https://circleci.com/docs/using-macos/" rel="noopener noreferrer"&gt;here&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;macos&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;xcode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;16.0.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  3. The &lt;code&gt;run-maestro-tests&lt;/code&gt; Command
&lt;/h4&gt;

&lt;p&gt;I kept this command reusable so you don’t have to rewrite it for iOS and Android:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;run-maestro-tests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Run&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Maestro&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Tests'&lt;/span&gt;
    &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;platform&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;enum&lt;/span&gt;
        &lt;span class="na"&gt;enum&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;android&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;ios&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
        &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Platform&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;run&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;tests&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;for'&lt;/span&gt;
      &lt;span class="na"&gt;maestro_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
        &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Path&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Maestro&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;test&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;file'&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run Maestro Tests for &amp;lt;&amp;lt; parameters.platform &amp;gt;&amp;gt;&lt;/span&gt;
          &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
              &lt;span class="s"&gt;maestro test &amp;lt;&amp;lt; parameters.maestro_file &amp;gt;&amp;gt;&lt;/span&gt;
              &lt;span class="s"&gt;if [ $? -eq 0 ]; then&lt;/span&gt;
                  &lt;span class="s"&gt;echo "✅ Tests Passed"&lt;/span&gt;
              &lt;span class="s"&gt;else&lt;/span&gt;
                  &lt;span class="s"&gt;echo "❌ Tests Failed"&lt;/span&gt;
              &lt;span class="s"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  4. Android Job
&lt;/h4&gt;

&lt;p&gt;Choosing the right &lt;code&gt;resource_class&lt;/code&gt; is critical. You don’t want your builds timing out or failing because you ran out of memory. Check out the &lt;a href="https://circleci.com/docs/using-linuxvm/#available-linuxvm-resource-classes" rel="noopener noreferrer"&gt;CircleCI resource classes&lt;/a&gt; for a good overview.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;run_maestro_android&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;executor&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;android/android_machine&lt;/span&gt;
    &lt;span class="na"&gt;resource_class&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;xlarge&lt;/span&gt; &lt;span class="c1"&gt;# 8GB / 16GB for better stability&lt;/span&gt;
  &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;checkout&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;install_node_modules&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;install_gems&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;install_maestro_cli&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;android/create_avd&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;avd_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test&lt;/span&gt;
        &lt;span class="na"&gt;system_image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;system-images;android-34;google_apis;x86_64'&lt;/span&gt;
        &lt;span class="na"&gt;install&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
        &lt;span class="na"&gt;additional_args&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;--device&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;pixel_4'&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build Android App&lt;/span&gt;
        &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
            &lt;span class="s"&gt;cd android&lt;/span&gt;
            &lt;span class="s"&gt;./gradlew assembleRelease --no-daemon --console=plain&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;store_artifacts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./android/app/build/outputs/apk/release/app-release.apk&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run-maestro-tests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;platform&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;android&lt;/span&gt;
        &lt;span class="na"&gt;maestro_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;e2e/main.yml'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Commands like &lt;code&gt;install_gems&lt;/code&gt;, &lt;code&gt;install_maestro_cli&lt;/code&gt;, and &lt;code&gt;install_node_modules&lt;/code&gt; are &lt;strong&gt;implicit&lt;/strong&gt; in the &lt;a href="https://gist.github.com/vinitraj10/424561861419fe6e986b9f2cd070a860" rel="noopener noreferrer"&gt;full config.yml&lt;/a&gt; – mostly boilerplate, so I’ve kept the focus here on the more interesting bits.&lt;/p&gt;

&lt;h4&gt;
  
  
  5. iOS Job
&lt;/h4&gt;

&lt;p&gt;Setting up the iOS build can be a bit more finicky, but here’s a working approach:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;run_maestro_ios&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;macos&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;xcode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;16.0.0&lt;/span&gt;
  &lt;span class="na"&gt;resource_class&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;m2pro.medium&lt;/span&gt;
  &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;node/install&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;20.10.0'&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;checkout&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;install_node_modules&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;install_gems&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install Pods&lt;/span&gt;
        &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
            &lt;span class="s"&gt;cd ios&lt;/span&gt;
            &lt;span class="s"&gt;bundle install&lt;/span&gt;
            &lt;span class="s"&gt;bundle exec pod install&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;install_maestro_cli&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Boot iPhone Simulator&lt;/span&gt;
        &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
            &lt;span class="s"&gt;xcrun simctl boot "iPhone 15"&lt;/span&gt;
            &lt;span class="s"&gt;xcrun simctl list devices booted&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build iOS App for Simulator&lt;/span&gt;
        &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
            &lt;span class="s"&gt;cd ios&lt;/span&gt;
            &lt;span class="s"&gt;xcodebuild clean build \&lt;/span&gt;
                &lt;span class="s"&gt;-workspace MyApp.xcworkspace \&lt;/span&gt;
                &lt;span class="s"&gt;-scheme MyApp-Dev \&lt;/span&gt;
                &lt;span class="s"&gt;-configuration Release \&lt;/span&gt;
                &lt;span class="s"&gt;-sdk iphonesimulator \&lt;/span&gt;
                &lt;span class="s"&gt;-derivedDataPath ./build&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;store_artifacts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./ios/build/Build/Products/Release-iphonesimulator/MyApp-Dev.app&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run-maestro-tests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;platform&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ios&lt;/span&gt;
        &lt;span class="na"&gt;maestro_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;e2e/main.yml'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Debugging Like a Pro (with Caution)
&lt;/h3&gt;

&lt;p&gt;E2E tests can be tricky – they work fine locally, but suddenly fail on CircleCI. This is often due to environment mismatches, network issues, or emulator quirks. Here’s a reliable way to debug these problems in real-time, but be mindful of the security implications.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;SSH into the CI Machine&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;First, gain access to your CircleCI machine using SSH. This lets you poke around the live environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-p&lt;/span&gt; &amp;lt;ci_machine_ip_address&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Start Maestro Studio&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run Maestro Studio to get a live view of what the emulator is doing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;maestro studio
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Expose the Maestro Studio Network with ngrok&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use ngrok to create a secure tunnel to your CI machine so you can access Maestro Studio remotely:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ngrok authtoken &amp;lt;YOUR_NGROK_AUTH_TOKEN&amp;gt;
ngrok http 9999
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;⚠️ Security Disclaimer:&lt;/strong&gt;&lt;br&gt;
  Be careful with this approach. Exposing your CI machine to the public internet, even through a secure tunnel like ngrok, can introduce security risks. Make sure you’re not leaking sensitive environment variables or allowing unauthorized access. Use ngrok’s IP whitelisting or basic authentication for an extra layer of security if needed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Inspect and Debug in Real-Time&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Open the ngrok URL and you should be able to interact with the emulator live, inspect flows, and catch any UI issues or environment mismatches that might be causing your tests to fail.&lt;/p&gt;




&lt;h3&gt;
  
  
  Final Thoughts
&lt;/h3&gt;

&lt;p&gt;With a bit of upfront setup, you can have reliable, automated E2E tests that keep your React Native app rock solid – without shelling out for expensive testing services. If this guide saved you some late-night headaches, drop a star on the Gist or share your setup in the comments. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The current &lt;code&gt;config.yml&lt;/code&gt; sets up a cron job to run these E2E tests every midnight. This was just my project choice to keep a consistent test cycle, but feel free to adjust or remove this schedule based on your team’s workflow and testing frequency.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Happy testing! 🚀&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>maestro</category>
      <category>android</category>
      <category>mobile</category>
    </item>
  </channel>
</rss>
