1#!/bin/bash
2# Copyright (c) Meta Platforms, Inc. and affiliates.
3#
4# This source code is licensed under the MIT license found in the
5# LICENSE file in the root directory of this source tree.
6
7RED="\033[0;31m"
8GREEN="\033[0;32m"
9BLUE="\033[0;35m"
10ENDCOLOR="\033[0m"
11
12error() {
13    echo -e "$RED""$*""$ENDCOLOR"
14    popd >/dev/null || exit
15    exit 1
16}
17
18success() {
19    echo -e "$GREEN""$*""$ENDCOLOR"
20}
21
22info() {
23    echo -e "$BLUE""$*""$ENDCOLOR"
24}
25
26# Ensures commands are executed from the repo root folder
27dir_absolute_path=$( cd "$(dirname "${BASH_SOURCE[0]}")" || exit ; pwd -P )
28pushd "$dir_absolute_path/../" >/dev/null || exit
29
30repo_root=$(pwd)
31selected_platform=""
32selected_vm=""
33PACKAGE_VERSION=""
34
35test_android(){
36    if [ "$1" == "1" ]; then
37        test_android_hermes
38    elif [ "$1" == "2" ]; then
39        test_android_jsc
40    fi
41}
42
43generate_maven_artifacts(){
44    rm -rf android
45    ./gradlew :ReactAndroid:installArchives || error "Couldn't generate React Native Maven artifacts"
46    ./gradlew :ReactAndroid:hermes-engine:installArchives || error "Couldn't generate Hermes Engine Maven artifacts"
47
48    success "Generated artifacts for Maven"
49}
50
51test_android_hermes(){
52    ./gradlew :packages:rn-tester:android:app:installHermesDebug || error "Couldn't build RNTester Android"
53
54    info "Press any key to run RNTester on Android with Hermes enabled"
55    info ""
56    read -r -n 1
57    adb shell am start -n com.facebook.react.uiapp/.RNTesterActivity
58}
59
60test_android_jsc(){
61    ./gradlew :packages:rn-tester:android:app:installJscDebug || error "Couldn't build RNTester Android"
62
63    info "Press any key to run RNTester in an already running Android emulator/device"
64    info ""
65    read -r -n 1
66    adb shell am start -n com.facebook.react.uiapp/.RNTesterActivity
67}
68
69test_ios(){
70    if [ "$1" == "1" ]; then
71        test_ios_hermes
72    elif [ "$1" == "2" ]; then
73        test_ios_jsc
74    fi
75}
76
77test_ios_hermes(){
78    success "About to test iOS Hermes... "
79    success "Installing CocoaPods dependencies..."
80    rm -rf packages/rn-tester/Pods
81    (cd packages/rn-tester && USE_HERMES=1 bundle exec pod install)
82
83    info "Press any key to open the workspace in Xcode, then build and test manually."
84    info ""
85    read -r -n 1
86
87    open "packages/rn-tester/RNTesterPods.xcworkspace"
88}
89
90test_ios_jsc(){
91    success "About to test iOS JSC... "
92    success "Installing CocoaPods dependencies..."
93    rm -rf packages/rn-tester/Pods
94    (cd packages/rn-tester && USE_HERMES=0 bundle exec pod install)
95
96    info "Press any key to open the workspace in Xcode, then build and test manually."
97    info ""
98    read -r -n 1
99
100    open "packages/rn-tester/RNTesterPods.xcworkspace"
101}
102
103kill_packagers(){
104    success "Killing any running packagers"
105    lsof -i :8081 | grep LISTEN
106    lsof -i :8081 | grep LISTEN | /usr/bin/awk '{print $2}' | xargs kill
107}
108
109init_template_app(){
110    kill_packagers
111
112    if [ "$selected_platform" == "1" ]; then
113        generate_maven_artifacts
114    fi
115
116    PACKAGE_VERSION=$(cat package.json \
117    | grep version \
118    | head -1 \
119    | awk -F: '{ print $2 }' \
120    | sed 's/[",]//g' \
121    | tr -d '[[:space:]]')
122
123    success "Preparing version $PACKAGE_VERSION"
124
125    npm pack
126
127    TIMESTAMP=$(date +%s)
128    PACKAGE=$(pwd)/react-native-$PACKAGE_VERSION-$TIMESTAMP.tgz
129    success "Package bundled ($PACKAGE)"
130
131    mv "$(pwd)/react-native-$PACKAGE_VERSION.tgz" "$PACKAGE"
132
133    node scripts/set-rn-template-version.js "file:$PACKAGE"
134    success "React Native version changed in the template"
135
136    project_name="RNTestProject"
137
138    pushd /tmp/ >/dev/null || exit
139    rm -rf "$project_name"
140    node "$repo_root/cli.js" init "$project_name" --template "$repo_root"
141
142    info "Double checking the versions in package.json are correct:"
143    grep "\"react-native\": \".*react-native-$PACKAGE_VERSION-$TIMESTAMP.tgz\"" "/tmp/${project_name}/package.json" || error "Incorrect version number in /tmp/${project_name}/package.json"
144
145    success "New sample project generated at /tmp/${project_name}"
146    popd >/dev/null || exit
147}
148
149test_template_app(){
150    if [ "$PACKAGE_VERSION" == "" ]; then
151        init_template_app
152    fi
153
154    pushd "/tmp/${project_name}" >/dev/null || exit
155    if [ "$selected_platform" == "1" ]; then
156        info "Test the following on Android:"
157        info "   - Disable Fast Refresh. It might be enabled from last time (the setting is stored on the device)"
158        info "   - Verify 'Reload JS' works"
159        info ""
160        info "Press any key to run the sample in Android emulator/device"
161        info ""
162        read -r -n 1
163        npx react-native run-android
164    elif [ "$selected_platform" == "2" ]; then
165        info "Test the following on iOS:"
166        info "   - Disable Fast Refresh. It might be enabled from last time (the setting is stored on the device)"
167        info "   - Verify 'Reload JS' works"
168        info "   - Test Chrome debugger by adding breakpoints and reloading JS. We don't have tests for Chrome debugging."
169        info "   - Disable Chrome debugging."
170        info "   - Enable Fast Refresh, change a file (index.js) and save. The UI should refresh."
171        info "   - Disable Fast Refresh."
172        info ""
173        info "Press any key to open the project in Xcode"
174        info ""
175        read -r -n 1
176        open "ios/${project_name}.xcworkspace"
177    fi
178    popd >/dev/null || exit
179}
180
181
182show_menu(){
183    echo "Which app do you want to test?
184  1 - RNTester
185  2 - A new RN app using the template"
186    read -p "> " selected_app
187
188    echo "What platform do you want to test?
189  1 - Android
190  2 - iOS"
191    read -p "> " selected_platform
192
193    if [ "$selected_app" == "1" ]; then
194        echo "What VM are you testing?
195  1 - Hermes
196  2 - JSC"
197        read -p "> " selected_vm
198    fi
199
200}
201
202handle_menu_input(){
203    if [ "$selected_app" == "1" ]; then
204        info "Start the packager in another terminal by running 'npm start' from the root"
205        info "and then press any key."
206        info ""
207        read -r -n 1
208
209        if [ "$selected_platform" == "1" ]; then
210            test_android "$selected_vm"
211        elif [ "$selected_platform" == "2" ]; then
212            test_ios "$selected_vm"
213        fi
214    elif [ "$selected_app" == "2" ]; then
215        test_template_app
216    fi
217
218    read -p "Would you like to test something else? (Y/N)" confirm
219    if [ "$confirm" == "${confirm#[Yy]}" ]; then
220        info "Next steps:"
221        info "https://reactnative.dev/contributing/release-candidate-minor"
222        popd >/dev/null || exit
223        exit 1
224    else
225        show_menu
226        handle_menu_input
227    fi
228}
229
230init(){
231    show_menu
232    yarn
233    kill_packagers
234    handle_menu_input
235}
236
237init
238