feat: project init
This commit is contained in:
parent
992b17d25a
commit
92675ed37c
232
.github/workflows/e2e_android.yml
vendored
Normal file
232
.github/workflows/e2e_android.yml
vendored
Normal file
@ -0,0 +1,232 @@
|
||||
name: Testing E2E Android
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
clearCaches:
|
||||
description: "Clear workflow caches where possible"
|
||||
required: false
|
||||
type: string
|
||||
|
||||
pull_request:
|
||||
branches:
|
||||
- '**'
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- 'website/**'
|
||||
- '.spellcheck.dict.txt'
|
||||
# - '**/*.md'
|
||||
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- v14-release
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- 'website/**'
|
||||
- '.spellcheck.dict.txt'
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
android:
|
||||
name: Android
|
||||
runs-on: macos-12
|
||||
timeout-minutes: 90
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
# Refactor to make these dynamic with a low/high bracket only on schedule, not push
|
||||
# For now this is just the fastest combo (api/arch/target/snapshot-warm-time) based on testing
|
||||
api-level: [30]
|
||||
arch: [x86_64]
|
||||
target: [google_apis]
|
||||
first-boot-delay: [600]
|
||||
# This is useful for benchmarking, do 0, 1, 2, etc (up to 256 max job-per-matrix limit) for averages
|
||||
iteration: [0]
|
||||
env:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
EMULATOR_COMMAND: "-avd TestingAVD -noaudio -gpu swiftshader_indirect -camera-back none -no-snapshot -no-window -no-boot-anim -nojni -memory 2048 -timezone 'Europe/London' -cores 2"
|
||||
EMULATOR_EXECUTABLE: qemu-system-x86_64-headless
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 50
|
||||
|
||||
# Set up tool versions
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
|
||||
- name: Configure JDK 1.11
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '11'
|
||||
|
||||
# Set path variables needed for caches
|
||||
- name: Set workflow variables
|
||||
id: workflow-variables
|
||||
run: |
|
||||
echo "metro-cache=$HOME/.metro" >> $GITHUB_OUTPUT
|
||||
echo "yarn-cache-dir=$(yarn cache dir)" >> $GITHUB_OUTPUT
|
||||
echo "tempdir=$TMPDIR" >> $GITHUB_OUTPUT
|
||||
|
||||
- uses: actions/cache@v3
|
||||
name: Yarn Cache
|
||||
id: yarn-cache
|
||||
with:
|
||||
path: ${{ steps.workflow-variables.outputs.yarn-cache-dir }}
|
||||
key: ${{ runner.os }}-yarn-v1-${{ hashFiles('yarn.lock') }}
|
||||
restore-keys: ${{ runner.os }}-yarn-v1
|
||||
|
||||
- name: Yarn Install
|
||||
uses: nick-invision/retry@v2
|
||||
with:
|
||||
timeout_minutes: 10
|
||||
retry_wait_seconds: 60
|
||||
max_attempts: 3
|
||||
command: DETOX_DISABLE_POSTINSTALL=1 yarn --no-audit --prefer-offline
|
||||
|
||||
- name: Cache pushy Emulator
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.cache/pushy/emulators
|
||||
key: pushy-emulators-v1-${{ github.run_id }}
|
||||
restore-keys: pushy-emulators-v1
|
||||
|
||||
- name: Start pushy Emulator
|
||||
run: yarn tests:emulator:start-ci
|
||||
|
||||
- uses: actions/cache@v3
|
||||
name: Gradle Cache
|
||||
with:
|
||||
path: ~/.gradle/caches
|
||||
key: ${{ runner.os }}-gradle-v1-${{ hashFiles('**/*.gradle*') }}
|
||||
restore-keys: ${{ runner.os }}-gradle-v1
|
||||
|
||||
# This appears to be 'Cache Size: ~1230 MB (1290026823 B)' based on watching action logs
|
||||
# Repo limit is 10GB; branch caches are independent; branches may read default branch cache.
|
||||
# We don't want branches to evict main branch snapshot, so save on main, read-only all else
|
||||
- name: AVD cache
|
||||
uses: actions/cache@v3
|
||||
id: avd-cache
|
||||
with:
|
||||
path: |
|
||||
~/.android/avd/*
|
||||
~/.android/adb*
|
||||
key: avd-${{ matrix.api-level }}-${{ matrix.arch }}-${{matrix.target}}-v1-${{ github.event.inputs.clearCaches }}
|
||||
restore-keys: |
|
||||
avd-${{ matrix.api-level }}-${{ matrix.arch }}-${{matrix.target}}-v1
|
||||
|
||||
- name: Clear Caches Optionally
|
||||
if: "${{ github.event.inputs.clearCaches != '' }}"
|
||||
shell: bash
|
||||
run: |
|
||||
du -sk ~/.gradle
|
||||
du -sk ~/.android
|
||||
rm -fr ~/.gradle
|
||||
rm -fr ~/.android
|
||||
du -sk ~/.gradle || echo ~/.gradle is gone
|
||||
du -sk ~/.android || echo ~/.android is gone
|
||||
|
||||
- name: Build Android App
|
||||
uses: nick-invision/retry@v2
|
||||
with:
|
||||
timeout_minutes: 25
|
||||
retry_wait_seconds: 60
|
||||
max_attempts: 3
|
||||
command: yarn build:android-release
|
||||
|
||||
- name: Metro Bundler Cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ steps.workflow-variables.outputs.metro-cache }}
|
||||
key: ${{ runner.os }}-metro-v1-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}-metro-v1
|
||||
|
||||
- name: Pre-fetch Javascript bundle
|
||||
# Prebuild the bundle so that's fast when the app starts.
|
||||
run: |
|
||||
nohup yarn tests:packager:jet-ci &
|
||||
printf 'Waiting for packager to come online'
|
||||
until curl --output /dev/null --silent --head --fail http://localhost:8081/status; do
|
||||
printf '.'
|
||||
sleep 2
|
||||
done
|
||||
echo "Packager is online! Preparing javascript bundle..."
|
||||
curl --output /dev/null --silent --head --fail "http://localhost:8081/index.bundle?platform=android&dev=true&minify=false&inlineSourceMap=true"
|
||||
echo "...javascript bundle ready."
|
||||
|
||||
- name: AVD Boot and Snapshot Creation
|
||||
# Only generate a snapshot with a cache miss
|
||||
# Comment the if out to generate snapshots on branch for performance testing
|
||||
if: "${{ github.event.inputs.clearCaches != '' || (steps.avd-cache.outputs.cache-hit != 'true' && github.ref == 'refs/heads/main') }}"
|
||||
uses: reactivecircus/android-emulator-runner@v2
|
||||
with:
|
||||
api-level: ${{ matrix.api-level }}
|
||||
avd-name: TestingAVD
|
||||
force-avd-creation: false
|
||||
target: ${{ matrix.target }}
|
||||
arch: ${{ matrix.arch }}
|
||||
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
||||
sdcard-path-or-size: 100M
|
||||
disable-animations: true
|
||||
# Give the emulator a little time to run and do first boot stuff before taking snapshot
|
||||
script: |
|
||||
$ANDROID_HOME/platform-tools/adb logcat '*:D' -d > adb-snapshot-log.txt
|
||||
$ANDROID_HOME/platform-tools/adb logcat --clear
|
||||
echo "Generated AVD snapshot for caching."
|
||||
|
||||
# This step is separate so pure install time may be calculated as a step
|
||||
- name: Emulator Snapshot After Firstboot Warmup
|
||||
# Only generate a snapshot for saving with a cache miss
|
||||
# Switch the if statements via comment if generating snapshots for performance testing
|
||||
# if: matrix.first-boot-delay != '0'
|
||||
if: "${{ github.event.inputs.clearCaches != '' || (steps.avd-cache.outputs.cache-hit != 'true' && github.ref == 'refs/heads/main') }}"
|
||||
env:
|
||||
FIRST_BOOT_DELAY: ${{ matrix.first-boot-delay }}
|
||||
uses: reactivecircus/android-emulator-runner@v2
|
||||
with:
|
||||
api-level: ${{ matrix.api-level }}
|
||||
avd-name: TestingAVD
|
||||
force-avd-creation: false
|
||||
target: ${{ matrix.target }}
|
||||
arch: ${{ matrix.arch }}
|
||||
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
||||
sdcard-path-or-size: 100M
|
||||
disable-animations: true
|
||||
# Give the emulator a little time to run and do first boot stuff before taking snapshot
|
||||
# The zygote restart makes sure zygote has correct heap size as a workaround for android emulator init bug
|
||||
script: |
|
||||
$ANDROID_HOME/platform-tools/adb shell su root "setprop ctl.restart zygote"
|
||||
sleep $FIRST_BOOT_DELAY
|
||||
$ANDROID_HOME/platform-tools/adb logcat '*:D' -d > adb-warmup-log.txt
|
||||
$ANDROID_HOME/platform-tools/adb logcat --clear
|
||||
echo "First boot warmup completed."
|
||||
|
||||
- name: Test Tapper
|
||||
# Run this outside the emulator runner so the emulator runner does not wait on it for cleanup
|
||||
run: |
|
||||
nohup sh -c "until false; do $ANDROID_HOME/platform-tools/adb shell input tap 100 800; sleep 0.2; done" &
|
||||
shell: bash
|
||||
|
||||
- name: Detox Tests
|
||||
uses: reactivecircus/android-emulator-runner@v2
|
||||
timeout-minutes: 40
|
||||
with:
|
||||
api-level: ${{ matrix.api-level }}
|
||||
avd-name: TestingAVD
|
||||
force-avd-creation: false
|
||||
target: ${{ matrix.target }}
|
||||
arch: ${{ matrix.arch }}
|
||||
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
||||
sdcard-path-or-size: 100M
|
||||
disable-animations: true
|
||||
# Detox uses Espresso to choreograph steps in reaction to UI events, so we need to send a stream of taps.
|
||||
script: |
|
||||
$ANDROID_HOME/platform-tools/adb devices
|
||||
nohup sh -c "$ANDROID_HOME/platform-tools/adb logcat '*:D' > adb-log.txt" &
|
||||
yarn test:android-release
|
183
.github/workflows/e2e_ios.yml
vendored
Normal file
183
.github/workflows/e2e_ios.yml
vendored
Normal file
@ -0,0 +1,183 @@
|
||||
name: Testing E2E iOS
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- '**'
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- 'website/**'
|
||||
- '.spellcheck.dict.txt'
|
||||
- '**/*.md'
|
||||
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- v14-release
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- 'website/**'
|
||||
- '.spellcheck.dict.txt'
|
||||
# - '**/*.md'
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
ios:
|
||||
name: iOS
|
||||
runs-on: macos-12
|
||||
# TODO matrix across APIs, at least 11 and 15 (lowest to highest)
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
steps:
|
||||
# Set up tool versions
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
|
||||
- name: Configure JDK 1.11
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '11'
|
||||
|
||||
- uses: maxim-lobanov/setup-xcode@v1
|
||||
with:
|
||||
xcode-version: 'latest-stable'
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 50
|
||||
|
||||
# Set path variables needed for caches
|
||||
- name: Set workflow variables
|
||||
id: workflow-variables
|
||||
run: |
|
||||
echo "metro-cache=$HOME/.metro" >> $GITHUB_OUTPUT
|
||||
echo "xcode-version=$(xcodebuild -version|tail -1|cut -f3 -d' ')" >> $GITHUB_OUTPUT
|
||||
echo "yarn-cache-dir=$(yarn cache dir)" >> $GITHUB_OUTPUT
|
||||
|
||||
- uses: actions/cache@v3
|
||||
name: Yarn Cache
|
||||
id: yarn-cache
|
||||
with:
|
||||
path: ${{ steps.workflow-variables.outputs.yarn-cache-dir }}
|
||||
key: ${{ runner.os }}-yarn-v1-${{ hashFiles('yarn.lock') }}
|
||||
restore-keys: ${{ runner.os }}-yarn-v1
|
||||
|
||||
- uses: actions/cache@v3
|
||||
name: Detox Framework Cache
|
||||
id: detox-cache
|
||||
with:
|
||||
path: ~/Library/Detox/ios
|
||||
key: ${{ runner.os }}-detox-framework-cache-${{ steps.workflow-variables.outputs.xcode-version }}
|
||||
|
||||
# Detox is compiled during yarn install, using Xcode, set up cache first
|
||||
- uses: hendrikmuhs/ccache-action@v1.2
|
||||
name: Xcode Compile Cache
|
||||
with:
|
||||
key: ${{ runner.os }}-v2 # makes a unique key w/related restore key internally
|
||||
max-size: 1500M
|
||||
|
||||
- name: Yarn Install
|
||||
uses: nick-invision/retry@v2
|
||||
with:
|
||||
timeout_minutes: 10
|
||||
retry_wait_seconds: 60
|
||||
max_attempts: 3
|
||||
command: yarn --no-audit --prefer-offline
|
||||
|
||||
- name: Setup Ruby
|
||||
uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: 3
|
||||
|
||||
- name: Update Ruby build tools
|
||||
uses: nick-invision/retry@v2
|
||||
with:
|
||||
timeout_minutes: 2
|
||||
retry_wait_seconds: 60
|
||||
max_attempts: 3
|
||||
command: gem update cocoapods xcodeproj
|
||||
|
||||
- uses: actions/cache@v3
|
||||
name: Cache Pods
|
||||
id: pods-cache
|
||||
with:
|
||||
path: tests/ios/Pods
|
||||
key: ${{ runner.os }}-pods-v2-${{ hashFiles('tests/ios/Podfile.lock') }}
|
||||
restore-keys: ${{ runner.os }}-pods-v2
|
||||
|
||||
- name: Pod Install
|
||||
uses: nick-invision/retry@v2
|
||||
with:
|
||||
timeout_minutes: 10
|
||||
retry_wait_seconds: 30
|
||||
max_attempts: 3
|
||||
command: yarn tests:ios:pod:install
|
||||
|
||||
- name: Cache Firestore Emulator
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.cache/pushy/emulators
|
||||
key: pushy-emulators-v1-${{ github.run_id }}
|
||||
restore-keys: pushy-emulators-v1
|
||||
|
||||
- name: Start Firestore Emulator
|
||||
run: yarn tests:emulator:start-ci
|
||||
|
||||
- name: Install brew utilities
|
||||
uses: nick-invision/retry@v2
|
||||
with:
|
||||
timeout_minutes: 5
|
||||
retry_wait_seconds: 60
|
||||
max_attempts: 3
|
||||
command: HOMEBREW_NO_AUTO_UPDATE=1 brew tap wix/brew && HOMEBREW_NO_AUTO_UPDATE=1 brew install applesimutils xcbeautify && applesimutils --list
|
||||
|
||||
- name: Build iOS App
|
||||
run: |
|
||||
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
|
||||
export CCACHE_SLOPPINESS=clang_index_store,file_stat_matches,include_file_ctime,include_file_mtime,ivfsoverlay,pch_defines,modules,system_headers,time_macros
|
||||
export CCACHE_FILECLONE=true
|
||||
export CCACHE_DEPEND=true
|
||||
export CCACHE_INODECACHE=true
|
||||
export CCACHE_LIMIT_MULTIPLE=0.95
|
||||
ccache -s
|
||||
export SKIP_BUNDLING=1
|
||||
export RCT_NO_LAUNCH_PACKAGER=1
|
||||
set -o pipefail
|
||||
yarn build:ios-release
|
||||
ccache -s
|
||||
shell: bash
|
||||
|
||||
- name: Metro Bundler Cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ steps.workflow-variables.outputs.metro-cache }}
|
||||
key: ${{ runner.os }}-metro-v1-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}-metro-v1
|
||||
|
||||
- name: Pre-fetch Javascript bundle
|
||||
run: |
|
||||
nohup yarn tests:packager:jet-ci &
|
||||
printf 'Waiting for packager to come online'
|
||||
until curl --output /dev/null --silent --head --fail http://localhost:8081/status; do
|
||||
printf '.'
|
||||
sleep 2
|
||||
done
|
||||
echo "Packager is online! Preparing bundle..."
|
||||
curl --output /dev/null --silent --head --fail "http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false&inlineSourceMap=true"
|
||||
echo "...javascript bundle ready"
|
||||
|
||||
- name: Create Simulator Log
|
||||
# With a little delay so the detox test below has time to spawn it, missing the first part of boot is fine
|
||||
# If you boot the simulator separately from detox, some other race fails and detox testee never sends ready to proxy
|
||||
continue-on-error: true
|
||||
run: nohup sh -c "sleep 30 && xcrun simctl spawn booted log stream --level debug --style compact > simulator.log 2>&1 &"
|
||||
|
||||
- name: Detox Test
|
||||
timeout-minutes: 30
|
||||
run: yarn test:ios-release
|
10
.github/workflows/scripts/adb_all_emulators.sh
vendored
Executable file
10
.github/workflows/scripts/adb_all_emulators.sh
vendored
Executable file
@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
echo "Running $1 on all running emulators..."
|
||||
devices=`adb devices`
|
||||
|
||||
for device in $devices; do
|
||||
if [[ "$device" =~ "emulator-" ]]; then
|
||||
adb -s $device $1
|
||||
fi
|
||||
done
|
||||
echo "All Done."
|
13
.github/workflows/scripts/database.rules
vendored
Normal file
13
.github/workflows/scripts/database.rules
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"rules": {
|
||||
// Database in general is closed. Read/Write to anything but "tests/" will fail.
|
||||
".read": false,
|
||||
".write": false,
|
||||
|
||||
// ..."tests" node will succeed
|
||||
"tests": {
|
||||
".read": true,
|
||||
".write": true,
|
||||
}
|
||||
}
|
||||
}
|
39
.github/workflows/scripts/firebase.json
vendored
Normal file
39
.github/workflows/scripts/firebase.json
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
{
|
||||
"firestore": {
|
||||
"rules": "firestore.rules",
|
||||
"indexes": "firestore.indexes.json"
|
||||
},
|
||||
"functions": {
|
||||
"predeploy": [
|
||||
"yarn",
|
||||
"yarn --prefix \"$RESOURCE_DIR\" build"
|
||||
],
|
||||
"source": "functions"
|
||||
},
|
||||
"database": {
|
||||
"rules": "database.rules"
|
||||
},
|
||||
"storage": {
|
||||
"rules": "storage.rules"
|
||||
},
|
||||
"emulators": {
|
||||
"auth": {
|
||||
"port": 9099
|
||||
},
|
||||
"database": {
|
||||
"port": 9000
|
||||
},
|
||||
"firestore": {
|
||||
"port": 8080
|
||||
},
|
||||
"functions": {
|
||||
"port": 5001
|
||||
},
|
||||
"storage": {
|
||||
"port": 9199
|
||||
},
|
||||
"ui": {
|
||||
"enabled": true
|
||||
}
|
||||
}
|
||||
}
|
72
.github/workflows/scripts/firestore.indexes.json
vendored
Normal file
72
.github/workflows/scripts/firestore.indexes.json
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
{
|
||||
"indexes": [
|
||||
{
|
||||
"collectionGroup": "firestore",
|
||||
"queryScope": "COLLECTION",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "a",
|
||||
"order": "ASCENDING"
|
||||
},
|
||||
{
|
||||
"fieldPath": "b",
|
||||
"order": "ASCENDING"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"fieldOverrides": [
|
||||
{
|
||||
"collectionGroup": "collectionGroup",
|
||||
"fieldPath": "value",
|
||||
"indexes": [
|
||||
{
|
||||
"order": "ASCENDING",
|
||||
"queryScope": "COLLECTION"
|
||||
},
|
||||
{
|
||||
"order": "DESCENDING",
|
||||
"queryScope": "COLLECTION"
|
||||
},
|
||||
{
|
||||
"arrayConfig": "CONTAINS",
|
||||
"queryScope": "COLLECTION"
|
||||
},
|
||||
{
|
||||
"order": "ASCENDING",
|
||||
"queryScope": "COLLECTION_GROUP"
|
||||
},
|
||||
{
|
||||
"order": "DESCENDING",
|
||||
"queryScope": "COLLECTION_GROUP"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"collectionGroup": "collectionGroup",
|
||||
"fieldPath": "number",
|
||||
"indexes": [
|
||||
{
|
||||
"order": "ASCENDING",
|
||||
"queryScope": "COLLECTION"
|
||||
},
|
||||
{
|
||||
"order": "DESCENDING",
|
||||
"queryScope": "COLLECTION"
|
||||
},
|
||||
{
|
||||
"arrayConfig": "CONTAINS",
|
||||
"queryScope": "COLLECTION"
|
||||
},
|
||||
{
|
||||
"order": "ASCENDING",
|
||||
"queryScope": "COLLECTION_GROUP"
|
||||
},
|
||||
{
|
||||
"order": "DESCENDING",
|
||||
"queryScope": "COLLECTION_GROUP"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
17
.github/workflows/scripts/firestore.rules
vendored
Normal file
17
.github/workflows/scripts/firestore.rules
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
rules_version = '2';
|
||||
service cloud.firestore {
|
||||
match /databases/{database}/documents {
|
||||
match /{document=**} {
|
||||
allow read, write: if false;
|
||||
}
|
||||
match /firestore-bundle-tests/{document=**} {
|
||||
allow read, write: if true;
|
||||
}
|
||||
match /firestore/{document=**} {
|
||||
allow read, write: if true;
|
||||
}
|
||||
match /{path=**}/collectionGroup/{documentId} {
|
||||
allow read, write: if true;
|
||||
}
|
||||
}
|
||||
}
|
10
.github/workflows/scripts/functions/.gitignore
vendored
Normal file
10
.github/workflows/scripts/functions/.gitignore
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
# Compiled JavaScript files
|
||||
lib/**/*.js
|
||||
lib/**/*.js.map
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# Node.js dependency directory
|
||||
node_modules/
|
||||
yarn.lock
|
24
.github/workflows/scripts/functions/package.json
vendored
Normal file
24
.github/workflows/scripts/functions/package.json
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "functions",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"serve": "npm run build && firebase emulators:start --only functions",
|
||||
"shell": "npm run build && firebase functions:shell",
|
||||
"start": "npm run shell",
|
||||
"deploy": "firebase deploy --only functions",
|
||||
"logs": "firebase functions:log"
|
||||
},
|
||||
"engines": {
|
||||
"node": "16"
|
||||
},
|
||||
"main": "lib/index.js",
|
||||
"dependencies": {
|
||||
"firebase-admin": "^11.3.0",
|
||||
"firebase-functions": "^4.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"firebase-functions-test": "^3.0.0",
|
||||
"typescript": "^4.9.5"
|
||||
},
|
||||
"private": true
|
||||
}
|
13
.github/workflows/scripts/functions/src/exports.ts
vendored
Normal file
13
.github/workflows/scripts/functions/src/exports.ts
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
/*
|
||||
*
|
||||
* Testing tools for invertase/react-native-firebase use only.
|
||||
*
|
||||
* Copyright (C) 2018-present Invertase Limited <oss@invertase.io>
|
||||
*
|
||||
* See License file for more information.
|
||||
*/
|
||||
|
||||
/* eslint-disable global-require */
|
||||
module.exports = {
|
||||
SAMPLE_DATA: require('./functions/sample-data'),
|
||||
};
|
12
.github/workflows/scripts/functions/src/index.ts
vendored
Normal file
12
.github/workflows/scripts/functions/src/index.ts
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
import * as functions from 'firebase-functions';
|
||||
|
||||
// // Start writing Firebase Functions
|
||||
// // https://firebase.google.com/docs/functions/typescript
|
||||
//
|
||||
export const helloWorld = functions.https.onRequest((request, response) => {
|
||||
functions.logger.info('Hello logs!', { structuredData: true });
|
||||
response.send('{ "data": "Hello from Firebase!" }');
|
||||
});
|
||||
|
||||
export { testFunctionCustomRegion } from './testFunctionCustomRegion';
|
||||
export { testFunctionDefaultRegion } from './testFunctionDefaultRegion';
|
80
.github/workflows/scripts/functions/src/sample-data.ts
vendored
Normal file
80
.github/workflows/scripts/functions/src/sample-data.ts
vendored
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Testing tools for invertase/react-native-firebase use only.
|
||||
*
|
||||
* Copyright (C) 2018-present Invertase Limited <oss@invertase.io>
|
||||
*
|
||||
* See License file for more information.
|
||||
*/
|
||||
|
||||
const SAMPLE_DATA: { [key: string]: any } = {
|
||||
number: 1234,
|
||||
string: 'acde',
|
||||
boolean: true,
|
||||
null: null,
|
||||
object: {
|
||||
number: 1234,
|
||||
string: 'acde',
|
||||
boolean: true,
|
||||
null: null,
|
||||
},
|
||||
array: [1234, 'acde', true, null],
|
||||
deepObject: {
|
||||
array: [1234, 'acde', false, null],
|
||||
object: {
|
||||
number: 1234,
|
||||
string: 'acde',
|
||||
boolean: true,
|
||||
null: null,
|
||||
array: [1234, 'acde', true, null],
|
||||
},
|
||||
number: 1234,
|
||||
string: 'acde',
|
||||
boolean: true,
|
||||
null: null,
|
||||
},
|
||||
deepArray: [
|
||||
1234,
|
||||
'acde',
|
||||
true,
|
||||
null,
|
||||
[1234, 'acde', true, null],
|
||||
{
|
||||
number: 1234,
|
||||
string: 'acde',
|
||||
boolean: true,
|
||||
null: null,
|
||||
array: [1234, 'acde', true, null],
|
||||
},
|
||||
],
|
||||
deepMap: {
|
||||
number: 123,
|
||||
string: 'foo',
|
||||
booleanTrue: true,
|
||||
booleanFalse: false,
|
||||
null: null,
|
||||
list: ['1', 2, true, false],
|
||||
map: {
|
||||
number: 123,
|
||||
string: 'foo',
|
||||
booleanTrue: true,
|
||||
booleanFalse: false,
|
||||
null: null,
|
||||
},
|
||||
},
|
||||
deepList: [
|
||||
'1',
|
||||
2,
|
||||
true,
|
||||
false,
|
||||
['1', 2, true, false],
|
||||
{
|
||||
number: 123,
|
||||
string: 'foo',
|
||||
booleanTrue: true,
|
||||
booleanFalse: false,
|
||||
null: null,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default SAMPLE_DATA;
|
14
.github/workflows/scripts/functions/src/testFunctionCustomRegion.ts
vendored
Normal file
14
.github/workflows/scripts/functions/src/testFunctionCustomRegion.ts
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
*
|
||||
* Testing tools for invertase/react-native-firebase use only.
|
||||
*
|
||||
* Copyright (C) 2018-present Invertase Limited <oss@invertase.io>
|
||||
*
|
||||
* See License file for more information.
|
||||
*/
|
||||
|
||||
import * as functions from 'firebase-functions';
|
||||
|
||||
export const testFunctionCustomRegion = functions
|
||||
.region('europe-west1')
|
||||
.https.onCall(() => 'europe-west1');
|
70
.github/workflows/scripts/functions/src/testFunctionDefaultRegion.ts
vendored
Normal file
70
.github/workflows/scripts/functions/src/testFunctionDefaultRegion.ts
vendored
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
*
|
||||
* Testing tools for invertase/react-native-firebase use only.
|
||||
*
|
||||
* Copyright (C) 2018-present Invertase Limited <oss@invertase.io>
|
||||
*
|
||||
* See License file for more information.
|
||||
*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { FirebaseError } from 'firebase-admin';
|
||||
import * as functions from 'firebase-functions';
|
||||
import SAMPLE_DATA from './sample-data';
|
||||
|
||||
export const testFunctionDefaultRegion = functions.https.onCall(data => {
|
||||
console.log(Date.now(), data);
|
||||
|
||||
if (typeof data === 'undefined') {
|
||||
return 'undefined';
|
||||
}
|
||||
|
||||
if (typeof data === 'string') {
|
||||
return 'string';
|
||||
}
|
||||
|
||||
if (typeof data === 'number') {
|
||||
return 'number';
|
||||
}
|
||||
|
||||
if (typeof data === 'boolean') {
|
||||
return 'boolean';
|
||||
}
|
||||
|
||||
if (data === null) {
|
||||
return 'null';
|
||||
}
|
||||
|
||||
if (Array.isArray(data)) {
|
||||
return 'array';
|
||||
}
|
||||
|
||||
const { type, asError, inputData } = data;
|
||||
if (!Object.hasOwnProperty.call(SAMPLE_DATA, type)) {
|
||||
throw new functions.https.HttpsError('invalid-argument', 'Invalid test requested.');
|
||||
}
|
||||
|
||||
const outputData = SAMPLE_DATA[type];
|
||||
|
||||
try {
|
||||
assert.deepEqual(outputData, inputData);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
throw new functions.https.HttpsError(
|
||||
'invalid-argument',
|
||||
'Input and Output types did not match.',
|
||||
(e as FirebaseError).message,
|
||||
);
|
||||
}
|
||||
|
||||
// all good
|
||||
if (asError) {
|
||||
throw new functions.https.HttpsError(
|
||||
'cancelled',
|
||||
'Response data was requested to be sent as part of an Error payload, so here we are!',
|
||||
outputData,
|
||||
);
|
||||
}
|
||||
|
||||
return outputData;
|
||||
});
|
16
.github/workflows/scripts/functions/tsconfig.json
vendored
Normal file
16
.github/workflows/scripts/functions/tsconfig.json
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"noImplicitReturns": true,
|
||||
"noUnusedLocals": true,
|
||||
"outDir": "lib",
|
||||
"sourceMap": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"target": "es2017"
|
||||
},
|
||||
"compileOnSave": true,
|
||||
"include": [
|
||||
"src"
|
||||
]
|
||||
}
|
6
.github/workflows/scripts/start-firebase-emulator.bat
vendored
Normal file
6
.github/workflows/scripts/start-firebase-emulator.bat
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
@REM this pushd is likely not needed, but just in case
|
||||
pushd "%~dp0"
|
||||
@REM this is just to see what our current directory is. Should be .github/workflow/scripts
|
||||
echo %cd%
|
||||
@REM strangely, unless you specify the config file as being right in the current directory, it won't find it, and everything fails
|
||||
yarn firebase emulators:start --config %cd%\firebase.json --only auth,database,firestore,functions,storage --project react-native-firebase-testing
|
44
.github/workflows/scripts/start-firebase-emulator.sh
vendored
Executable file
44
.github/workflows/scripts/start-firebase-emulator.sh
vendored
Executable file
@ -0,0 +1,44 @@
|
||||
#!/bin/bash
|
||||
if ! [ -x "$(command -v firebase)" ]; then
|
||||
echo "❌ Firebase-tools CLI is missing. Run 'npm i -g firebase-tools' or the equivalent"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
EMU_START_COMMAND="firebase emulators:start --only auth,database,firestore,functions,storage --project react-native-firebase-testing"
|
||||
#EMU_START_COMMAND="sleep 120"
|
||||
MAX_RETRIES=3
|
||||
MAX_CHECKATTEMPTS=60
|
||||
CHECKATTEMPTS_WAIT=1
|
||||
|
||||
# Make sure functions are ready to go
|
||||
pushd "$(dirname "$0")/functions" && yarn && yarn build && popd
|
||||
|
||||
|
||||
RETRIES=1
|
||||
while [ $RETRIES -le $MAX_RETRIES ]; do
|
||||
|
||||
if [ "$1" == "--no-daemon" ]; then
|
||||
echo "Starting Firebase Emulator Suite in foreground."
|
||||
$EMU_START_COMMAND
|
||||
exit 0
|
||||
else
|
||||
echo "Starting Firebase Emulator Suite in background."
|
||||
$EMU_START_COMMAND &
|
||||
CHECKATTEMPTS=1
|
||||
while [ $CHECKATTEMPTS -le $MAX_CHECKATTEMPTS ]; do
|
||||
sleep $CHECKATTEMPTS_WAIT
|
||||
if curl --output /dev/null --silent --fail http://localhost:8080; then
|
||||
echo "Firebase Emulator Suite is online!"
|
||||
exit 0;
|
||||
fi
|
||||
echo "Waiting for Firebase Emulator Suite to come online, check $CHECKATTEMPTS of $MAX_CHECKATTEMPTS..."
|
||||
((CHECKATTEMPTS = CHECKATTEMPTS + 1))
|
||||
done
|
||||
fi
|
||||
|
||||
echo "Firebase Emulator Suite did not come online in $MAX_CHECKATTEMPTS checks. Try $RETRIES of $MAX_RETRIES."
|
||||
((RETRIES = RETRIES + 1))
|
||||
|
||||
done
|
||||
echo "Firebase Emulator Suite did not come online after $MAX_RETRIES attempts."
|
||||
exit 1
|
21
.github/workflows/scripts/storage.rules
vendored
Normal file
21
.github/workflows/scripts/storage.rules
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
rules_version = '2';
|
||||
service firebase.storage {
|
||||
match /b/{bucket}/o {
|
||||
match /{document=**} {
|
||||
allow read, write: if false;
|
||||
}
|
||||
|
||||
match /writeOnly.jpeg {
|
||||
allow read: if false;
|
||||
allow write: if true;
|
||||
}
|
||||
|
||||
match /playground/{document=**} {
|
||||
allow read, write: if true;
|
||||
}
|
||||
|
||||
match /react-native-firebase-testing/{document=**} {
|
||||
allow read, write: if true;
|
||||
}
|
||||
}
|
||||
}
|
BIN
Example/testHotUpdate/cache/test-butler-app.apk
vendored
Normal file
BIN
Example/testHotUpdate/cache/test-butler-app.apk
vendored
Normal file
Binary file not shown.
111
Example/testHotUpdate/detox.config.js
Normal file
111
Example/testHotUpdate/detox.config.js
Normal file
@ -0,0 +1,111 @@
|
||||
/** @type {Detox.DetoxConfig} */
|
||||
module.exports = {
|
||||
logger: {
|
||||
level: process.env.CI ? 'debug' : undefined,
|
||||
},
|
||||
testRunner: {
|
||||
args: {
|
||||
config: 'e2e/jest.config.js',
|
||||
maxWorkers: process.env.CI ? 2 : undefined,
|
||||
_: ['e2e'],
|
||||
},
|
||||
},
|
||||
artifacts: {
|
||||
plugins: {
|
||||
log: process.env.CI ? 'failing' : undefined,
|
||||
screenshot: process.env.CI ? 'failing' : undefined,
|
||||
},
|
||||
},
|
||||
apps: {
|
||||
'ios.release': {
|
||||
type: 'ios.app',
|
||||
binaryPath:
|
||||
'ios/build/Build/Products/Release-iphonesimulator/testHotUpdate.app',
|
||||
build:
|
||||
'export RCT_NO_LAUNCH_PACKAGER=true && xcodebuild -workspace ios/testHotUpdate.xcworkspace -UseNewBuildSystem=NO -scheme testHotUpdate -configuration Release -sdk iphonesimulator -derivedDataPath ios/build -quiet',
|
||||
},
|
||||
'ios.debug': {
|
||||
type: 'ios.app',
|
||||
binaryPath:
|
||||
'ios/build/Build/Products/Debug-iphonesimulator/testHotUpdate.app',
|
||||
build:
|
||||
'xcodebuild -workspace ios/testHotUpdate.xcworkspace -UseNewBuildSystem=NO -scheme testHotUpdate -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build',
|
||||
start: 'scripts/start-rn.sh ios',
|
||||
},
|
||||
'android.debug': {
|
||||
type: 'android.apk',
|
||||
binaryPath: 'android/app/build/outputs/apk/debug/app-debug.apk',
|
||||
build:
|
||||
'cd android ; ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug ; cd -',
|
||||
start: 'scripts/start-rn.sh android',
|
||||
},
|
||||
'android.release': {
|
||||
type: 'android.apk',
|
||||
binaryPath: 'android/app/build/outputs/apk/release/app-release.apk',
|
||||
build:
|
||||
'cd android ; ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release ; cd -',
|
||||
},
|
||||
},
|
||||
devices: {
|
||||
simulator: {
|
||||
type: 'ios.simulator',
|
||||
headless: Boolean(process.env.CI),
|
||||
device: {
|
||||
type: 'iPhone 14',
|
||||
},
|
||||
},
|
||||
emulator: {
|
||||
type: 'android.emulator',
|
||||
headless: Boolean(process.env.CI),
|
||||
gpuMode: process.env.CI ? 'off' : undefined,
|
||||
device: {
|
||||
avdName: 'Pixel_3a_API_33_arm64-v8a',
|
||||
},
|
||||
utilBinaryPaths: ['./cache/test-butler-app.apk'],
|
||||
},
|
||||
'genymotion.emulator.uuid': {
|
||||
type: 'android.genycloud',
|
||||
device: {
|
||||
recipeUUID: 'a50a71d6-da90-4c67-bdfa-5b602b0bbd15',
|
||||
},
|
||||
utilBinaryPaths: ['./cache/test-butler-app.apk'],
|
||||
},
|
||||
'genymotion.emulator.name': {
|
||||
type: 'android.genycloud',
|
||||
device: {
|
||||
recipeName: 'Pixel_3a_API_33_arm64-v8a',
|
||||
},
|
||||
utilBinaryPaths: ['./cache/test-butler-app.apk'],
|
||||
},
|
||||
},
|
||||
configurations: {
|
||||
'ios.sim.release': {
|
||||
device: 'simulator',
|
||||
app: 'ios.release',
|
||||
},
|
||||
'ios.sim.debug': {
|
||||
device: 'simulator',
|
||||
app: 'ios.debug',
|
||||
},
|
||||
'ios.manual': {
|
||||
type: 'ios.manual',
|
||||
behavior: {
|
||||
launchApp: 'manual',
|
||||
},
|
||||
artifacts: false,
|
||||
session: {
|
||||
autoStart: true,
|
||||
server: 'ws://localhost:8099',
|
||||
sessionId: 'com.wix.demo.react.native',
|
||||
},
|
||||
},
|
||||
'android.emu.debug': {
|
||||
device: 'emulator',
|
||||
app: 'android.debug',
|
||||
},
|
||||
'android.emu.release': {
|
||||
device: 'emulator',
|
||||
app: 'android.release',
|
||||
},
|
||||
},
|
||||
};
|
89
Example/testHotUpdate/e2e/NativeModule.test.ts
Normal file
89
Example/testHotUpdate/e2e/NativeModule.test.ts
Normal file
@ -0,0 +1,89 @@
|
||||
import {by, device, element, expect} from 'detox';
|
||||
|
||||
describe('测试Native模块的方法', () => {
|
||||
beforeAll(async () => {
|
||||
await device.launchApp();
|
||||
});
|
||||
|
||||
it('setLocalHashInfo', async () => {
|
||||
await element(by.id('testcase')).longPress();
|
||||
await element(by.id('setLocalHashInfo')).tap();
|
||||
await element(by.id('submit')).tap();
|
||||
await expect(element(by.text('done'))).toBeVisible();
|
||||
await element(by.text('OK')).tap();
|
||||
});
|
||||
|
||||
it('getLocalHashInfo', async () => {
|
||||
await element(by.id('getLocalHashInfo')).tap();
|
||||
await element(by.id('submit')).tap();
|
||||
await expect(element(by.text('done'))).toBeVisible();
|
||||
await element(by.text('OK')).tap();
|
||||
});
|
||||
|
||||
it('setUuid', async () => {
|
||||
await element(by.id('setUuid')).tap();
|
||||
await element(by.id('submit')).tap();
|
||||
await expect(element(by.text('done'))).toBeVisible();
|
||||
await element(by.text('OK')).tap();
|
||||
});
|
||||
|
||||
it('setBlockUpdate', async () => {
|
||||
await element(by.id('setBlockUpdate')).tap();
|
||||
await element(by.id('submit')).tap();
|
||||
await expect(element(by.text('done'))).toBeVisible();
|
||||
await element(by.text('OK')).tap();
|
||||
});
|
||||
|
||||
it('reloadUpdate', async () => {
|
||||
await element(by.id('reloadUpdate')).tap();
|
||||
await element(by.id('submit')).tap();
|
||||
await expect(element(by.text('刚刚更新失败了,版本被回滚.'))).toBeVisible();
|
||||
await element(by.text('OK')).tap();
|
||||
});
|
||||
|
||||
it('setNeedUpdate', async () => {
|
||||
await element(by.id('testcase')).longPress();
|
||||
await element(by.id('setNeedUpdate')).tap();
|
||||
await element(by.id('submit')).tap();
|
||||
await expect(element(by.text('done'))).toBeVisible();
|
||||
await element(by.text('OK')).tap();
|
||||
});
|
||||
|
||||
it('markSuccess', async () => {
|
||||
await element(by.id('markSuccess')).tap();
|
||||
await element(by.id('submit')).tap();
|
||||
await expect(element(by.text('done'))).toBeVisible();
|
||||
await element(by.text('OK')).tap();
|
||||
});
|
||||
|
||||
it('downloadPatchFromPpk', async () => {
|
||||
await element(by.id('downloadPatchFromPpk')).tap();
|
||||
await element(by.id('submit')).tap();
|
||||
await expect(element(by.text('failed to open zip file'))).toBeVisible();
|
||||
await element(by.text('OK')).tap();
|
||||
});
|
||||
|
||||
it('downloadPatchFromPackage', async () => {
|
||||
await element(by.id('downloadPatchFromPackage')).tap();
|
||||
await element(by.id('submit')).tap();
|
||||
await expect(element(by.text('failed to open zip file'))).toBeVisible();
|
||||
await element(by.text('OK')).tap();
|
||||
});
|
||||
|
||||
it('downloadFullUpdate', async () => {
|
||||
await element(by.id('downloadFullUpdate')).tap();
|
||||
await element(by.id('submit')).tap();
|
||||
await expect(element(by.text('failed to open zip file'))).toBeVisible();
|
||||
await element(by.text('OK')).tap();
|
||||
});
|
||||
|
||||
if (device.getPlatform() === 'android') {
|
||||
it('downloadAndInstallApk', async () => {
|
||||
await element(by.id('testcase')).longPress();
|
||||
await element(by.id('downloadAndInstallApk')).tap();
|
||||
await element(by.id('submit')).tap();
|
||||
await expect(element(by.text('failed to open zip file'))).toBeVisible();
|
||||
await element(by.text('OK')).tap();
|
||||
});
|
||||
}
|
||||
});
|
29
Example/testHotUpdate/e2e/globalSetup.ts
Normal file
29
Example/testHotUpdate/e2e/globalSetup.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import { execSync } from 'child_process';
|
||||
|
||||
import { pathExists, ensureDir } from 'fs-extra';
|
||||
|
||||
import { resolveConfig } from 'detox/internals';
|
||||
import { globalSetup } from 'detox/runners/jest';
|
||||
|
||||
export default async function customGlobalSetup() {
|
||||
const config = await resolveConfig();
|
||||
if (config.device.type === 'android.emulator') {
|
||||
await downloadTestButlerAPK();
|
||||
}
|
||||
|
||||
await globalSetup();
|
||||
}
|
||||
|
||||
async function downloadTestButlerAPK() {
|
||||
const version = '2.2.1';
|
||||
const artifactUrl = `https://repo1.maven.org/maven2/com/linkedin/testbutler/test-butler-app/${version}/test-butler-app-${version}.apk`;
|
||||
const filePath = `cache/test-butler-app.apk`;
|
||||
|
||||
await ensureDir('cache');
|
||||
if (!(await pathExists(filePath))) {
|
||||
console.log(`\nDownloading Test-Butler APK v${version}...`);
|
||||
execSync(`curl -f -o ${filePath} ${artifactUrl}`);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = customGlobalSetup;
|
16
Example/testHotUpdate/e2e/jest.config.js
Normal file
16
Example/testHotUpdate/e2e/jest.config.js
Normal file
@ -0,0 +1,16 @@
|
||||
/** @type {import('jest').Config} */
|
||||
module.exports = {
|
||||
maxWorkers: 1,
|
||||
globalSetup: './globalSetup.ts',
|
||||
globalTeardown: 'detox/runners/jest/globalTeardown',
|
||||
testEnvironment: 'detox/runners/jest/testEnvironment',
|
||||
setupFilesAfterEnv: ['./setup.ts'],
|
||||
testRunner: 'jest-circus/runner',
|
||||
testTimeout: 120000,
|
||||
testMatch: ['**/*.test.ts'],
|
||||
transform: {
|
||||
'\\.tsx?$': 'ts-jest',
|
||||
},
|
||||
reporters: ['detox/runners/jest/reporter'],
|
||||
verbose: true,
|
||||
};
|
5
Example/testHotUpdate/e2e/setup.ts
Normal file
5
Example/testHotUpdate/e2e/setup.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import { device } from 'detox';
|
||||
|
||||
beforeAll(async () => {
|
||||
await device.launchApp();
|
||||
});
|
@ -89,11 +89,6 @@ PODS:
|
||||
- DoubleConversion
|
||||
- fmt (~> 6.2.1)
|
||||
- glog
|
||||
- RCT-Folly/Fabric (2021.07.22.00):
|
||||
- boost
|
||||
- DoubleConversion
|
||||
- fmt (~> 6.2.1)
|
||||
- glog
|
||||
- RCT-Folly/Futures (2021.07.22.00):
|
||||
- boost
|
||||
- DoubleConversion
|
||||
@ -126,10 +121,8 @@ PODS:
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
- React-Core
|
||||
- React-graphics
|
||||
- React-jsi
|
||||
- React-jsiexecutor
|
||||
- React-rncore
|
||||
- ReactCommon/turbomodule/bridging
|
||||
- ReactCommon/turbomodule/core
|
||||
- React-Core (0.71.1):
|
||||
@ -278,326 +271,6 @@ PODS:
|
||||
- React-logger (= 0.71.1)
|
||||
- React-perflogger (= 0.71.1)
|
||||
- React-runtimeexecutor (= 0.71.1)
|
||||
- React-Fabric (0.71.1):
|
||||
- RCT-Folly/Fabric (= 2021.07.22.00)
|
||||
- RCTRequired (= 0.71.1)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-Fabric/animations (= 0.71.1)
|
||||
- React-Fabric/attributedstring (= 0.71.1)
|
||||
- React-Fabric/butter (= 0.71.1)
|
||||
- React-Fabric/componentregistry (= 0.71.1)
|
||||
- React-Fabric/componentregistrynative (= 0.71.1)
|
||||
- React-Fabric/components (= 0.71.1)
|
||||
- React-Fabric/config (= 0.71.1)
|
||||
- React-Fabric/core (= 0.71.1)
|
||||
- React-Fabric/debug_core (= 0.71.1)
|
||||
- React-Fabric/debug_renderer (= 0.71.1)
|
||||
- React-Fabric/imagemanager (= 0.71.1)
|
||||
- React-Fabric/leakchecker (= 0.71.1)
|
||||
- React-Fabric/mapbuffer (= 0.71.1)
|
||||
- React-Fabric/mounting (= 0.71.1)
|
||||
- React-Fabric/runtimescheduler (= 0.71.1)
|
||||
- React-Fabric/scheduler (= 0.71.1)
|
||||
- React-Fabric/telemetry (= 0.71.1)
|
||||
- React-Fabric/templateprocessor (= 0.71.1)
|
||||
- React-Fabric/textlayoutmanager (= 0.71.1)
|
||||
- React-Fabric/uimanager (= 0.71.1)
|
||||
- React-Fabric/utils (= 0.71.1)
|
||||
- React-graphics (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-Fabric/animations (0.71.1):
|
||||
- RCT-Folly/Fabric (= 2021.07.22.00)
|
||||
- RCTRequired (= 0.71.1)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-graphics (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-Fabric/attributedstring (0.71.1):
|
||||
- RCT-Folly/Fabric (= 2021.07.22.00)
|
||||
- RCTRequired (= 0.71.1)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-graphics (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-Fabric/butter (0.71.1):
|
||||
- RCT-Folly/Fabric (= 2021.07.22.00)
|
||||
- RCTRequired (= 0.71.1)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-graphics (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-Fabric/componentregistry (0.71.1):
|
||||
- RCT-Folly/Fabric (= 2021.07.22.00)
|
||||
- RCTRequired (= 0.71.1)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-graphics (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-Fabric/componentregistrynative (0.71.1):
|
||||
- RCT-Folly/Fabric (= 2021.07.22.00)
|
||||
- RCTRequired (= 0.71.1)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-graphics (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-Fabric/components (0.71.1):
|
||||
- RCT-Folly/Fabric (= 2021.07.22.00)
|
||||
- RCTRequired (= 0.71.1)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-Fabric/components/activityindicator (= 0.71.1)
|
||||
- React-Fabric/components/image (= 0.71.1)
|
||||
- React-Fabric/components/inputaccessory (= 0.71.1)
|
||||
- React-Fabric/components/legacyviewmanagerinterop (= 0.71.1)
|
||||
- React-Fabric/components/modal (= 0.71.1)
|
||||
- React-Fabric/components/root (= 0.71.1)
|
||||
- React-Fabric/components/safeareaview (= 0.71.1)
|
||||
- React-Fabric/components/scrollview (= 0.71.1)
|
||||
- React-Fabric/components/slider (= 0.71.1)
|
||||
- React-Fabric/components/text (= 0.71.1)
|
||||
- React-Fabric/components/textinput (= 0.71.1)
|
||||
- React-Fabric/components/unimplementedview (= 0.71.1)
|
||||
- React-Fabric/components/view (= 0.71.1)
|
||||
- React-graphics (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-Fabric/components/activityindicator (0.71.1):
|
||||
- RCT-Folly/Fabric (= 2021.07.22.00)
|
||||
- RCTRequired (= 0.71.1)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-graphics (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-Fabric/components/image (0.71.1):
|
||||
- RCT-Folly/Fabric (= 2021.07.22.00)
|
||||
- RCTRequired (= 0.71.1)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-graphics (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-Fabric/components/inputaccessory (0.71.1):
|
||||
- RCT-Folly/Fabric (= 2021.07.22.00)
|
||||
- RCTRequired (= 0.71.1)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-graphics (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-Fabric/components/legacyviewmanagerinterop (0.71.1):
|
||||
- RCT-Folly/Fabric (= 2021.07.22.00)
|
||||
- RCTRequired (= 0.71.1)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-graphics (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-Fabric/components/modal (0.71.1):
|
||||
- RCT-Folly/Fabric (= 2021.07.22.00)
|
||||
- RCTRequired (= 0.71.1)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-graphics (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-Fabric/components/root (0.71.1):
|
||||
- RCT-Folly/Fabric (= 2021.07.22.00)
|
||||
- RCTRequired (= 0.71.1)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-graphics (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-Fabric/components/safeareaview (0.71.1):
|
||||
- RCT-Folly/Fabric (= 2021.07.22.00)
|
||||
- RCTRequired (= 0.71.1)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-graphics (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-Fabric/components/scrollview (0.71.1):
|
||||
- RCT-Folly/Fabric (= 2021.07.22.00)
|
||||
- RCTRequired (= 0.71.1)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-graphics (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-Fabric/components/slider (0.71.1):
|
||||
- RCT-Folly/Fabric (= 2021.07.22.00)
|
||||
- RCTRequired (= 0.71.1)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-graphics (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-Fabric/components/text (0.71.1):
|
||||
- RCT-Folly/Fabric (= 2021.07.22.00)
|
||||
- RCTRequired (= 0.71.1)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-graphics (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-Fabric/components/textinput (0.71.1):
|
||||
- RCT-Folly/Fabric (= 2021.07.22.00)
|
||||
- RCTRequired (= 0.71.1)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-graphics (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-Fabric/components/unimplementedview (0.71.1):
|
||||
- RCT-Folly/Fabric (= 2021.07.22.00)
|
||||
- RCTRequired (= 0.71.1)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-graphics (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-Fabric/components/view (0.71.1):
|
||||
- RCT-Folly/Fabric (= 2021.07.22.00)
|
||||
- RCTRequired (= 0.71.1)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-graphics (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- Yoga
|
||||
- React-Fabric/config (0.71.1):
|
||||
- RCT-Folly/Fabric (= 2021.07.22.00)
|
||||
- RCTRequired (= 0.71.1)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-graphics (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-Fabric/core (0.71.1):
|
||||
- RCT-Folly/Fabric (= 2021.07.22.00)
|
||||
- RCTRequired (= 0.71.1)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-graphics (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-Fabric/debug_core (0.71.1):
|
||||
- RCT-Folly/Fabric (= 2021.07.22.00)
|
||||
- RCTRequired (= 0.71.1)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-graphics (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-Fabric/debug_renderer (0.71.1):
|
||||
- RCT-Folly/Fabric (= 2021.07.22.00)
|
||||
- RCTRequired (= 0.71.1)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-graphics (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-Fabric/imagemanager (0.71.1):
|
||||
- RCT-Folly/Fabric (= 2021.07.22.00)
|
||||
- RCTRequired (= 0.71.1)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-graphics (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- React-RCTImage (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-Fabric/leakchecker (0.71.1):
|
||||
- RCT-Folly/Fabric (= 2021.07.22.00)
|
||||
- RCTRequired (= 0.71.1)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-graphics (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-Fabric/mapbuffer (0.71.1):
|
||||
- RCT-Folly/Fabric (= 2021.07.22.00)
|
||||
- RCTRequired (= 0.71.1)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-graphics (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-Fabric/mounting (0.71.1):
|
||||
- RCT-Folly/Fabric (= 2021.07.22.00)
|
||||
- RCTRequired (= 0.71.1)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-graphics (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-Fabric/runtimescheduler (0.71.1):
|
||||
- RCT-Folly/Fabric (= 2021.07.22.00)
|
||||
- RCTRequired (= 0.71.1)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-graphics (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-Fabric/scheduler (0.71.1):
|
||||
- RCT-Folly/Fabric (= 2021.07.22.00)
|
||||
- RCTRequired (= 0.71.1)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-graphics (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-Fabric/telemetry (0.71.1):
|
||||
- RCT-Folly/Fabric (= 2021.07.22.00)
|
||||
- RCTRequired (= 0.71.1)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-graphics (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-Fabric/templateprocessor (0.71.1):
|
||||
- RCT-Folly/Fabric (= 2021.07.22.00)
|
||||
- RCTRequired (= 0.71.1)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-graphics (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-Fabric/textlayoutmanager (0.71.1):
|
||||
- RCT-Folly/Fabric (= 2021.07.22.00)
|
||||
- RCTRequired (= 0.71.1)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-Fabric/uimanager
|
||||
- React-graphics (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-Fabric/uimanager (0.71.1):
|
||||
- RCT-Folly/Fabric (= 2021.07.22.00)
|
||||
- RCTRequired (= 0.71.1)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-graphics (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-Fabric/utils (0.71.1):
|
||||
- RCT-Folly/Fabric (= 2021.07.22.00)
|
||||
- RCTRequired (= 0.71.1)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
- React-graphics (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-jsiexecutor (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-graphics (0.71.1):
|
||||
- RCT-Folly/Fabric (= 2021.07.22.00)
|
||||
- React-Core/Default (= 0.71.1)
|
||||
- React-hermes (0.71.1):
|
||||
- DoubleConversion
|
||||
- glog
|
||||
@ -624,34 +297,19 @@ PODS:
|
||||
- React-jsinspector (0.71.1)
|
||||
- React-logger (0.71.1):
|
||||
- glog
|
||||
- react-native-update (9.1.0):
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
- react-native-update (9.0.0):
|
||||
- React
|
||||
- React-Codegen
|
||||
- React-Core
|
||||
- react-native-update/HDiffPatch (= 9.1.0)
|
||||
- react-native-update/RCTPushy (= 9.1.0)
|
||||
- ReactCommon/turbomodule/core
|
||||
- react-native-update/HDiffPatch (= 9.0.0)
|
||||
- react-native-update/RCTPushy (= 9.0.0)
|
||||
- SSZipArchive
|
||||
- react-native-update/HDiffPatch (9.1.0):
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
- react-native-update/HDiffPatch (9.0.0):
|
||||
- React
|
||||
- React-Codegen
|
||||
- React-Core
|
||||
- ReactCommon/turbomodule/core
|
||||
- SSZipArchive
|
||||
- react-native-update/RCTPushy (9.1.0):
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
- react-native-update/RCTPushy (9.0.0):
|
||||
- React
|
||||
- React-Codegen
|
||||
- React-Core
|
||||
- ReactCommon/turbomodule/core
|
||||
- SSZipArchive
|
||||
- React-perflogger (0.71.1)
|
||||
- React-RCTActionSheet (0.71.1):
|
||||
@ -668,8 +326,6 @@ PODS:
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
- React-Core
|
||||
- React-graphics
|
||||
- React-RCTFabric
|
||||
- ReactCommon/turbomodule/core
|
||||
- React-RCTBlob (0.71.1):
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
@ -679,11 +335,6 @@ PODS:
|
||||
- React-jsi (= 0.71.1)
|
||||
- React-RCTNetwork (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-RCTFabric (0.71.1):
|
||||
- RCT-Folly/Fabric (= 2021.07.22.00)
|
||||
- React-Core (= 0.71.1)
|
||||
- React-Fabric (= 0.71.1)
|
||||
- React-RCTImage (= 0.71.1)
|
||||
- React-RCTImage (0.71.1):
|
||||
- RCT-Folly (= 2021.07.22.00)
|
||||
- RCTTypeSafety (= 0.71.1)
|
||||
@ -719,7 +370,6 @@ PODS:
|
||||
- React-Core/RCTVibrationHeaders (= 0.71.1)
|
||||
- React-jsi (= 0.71.1)
|
||||
- ReactCommon/turbomodule/core (= 0.71.1)
|
||||
- React-rncore (0.71.1)
|
||||
- React-runtimeexecutor (0.71.1):
|
||||
- React-jsi (= 0.71.1)
|
||||
- ReactCommon/turbomodule/bridging (0.71.1):
|
||||
@ -779,7 +429,6 @@ DEPENDENCIES:
|
||||
- libevent (~> 2.1.12)
|
||||
- OpenSSL-Universal (= 1.1.1100)
|
||||
- RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`)
|
||||
- RCT-Folly/Fabric (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`)
|
||||
- RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired`)
|
||||
- RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`)
|
||||
- React (from `../node_modules/react-native/`)
|
||||
@ -790,8 +439,6 @@ DEPENDENCIES:
|
||||
- React-Core/RCTWebSocket (from `../node_modules/react-native/`)
|
||||
- React-CoreModules (from `../node_modules/react-native/React/CoreModules`)
|
||||
- React-cxxreact (from `../node_modules/react-native/ReactCommon/cxxreact`)
|
||||
- React-Fabric (from `../node_modules/react-native/ReactCommon`)
|
||||
- React-graphics (from `../node_modules/react-native/ReactCommon/react/renderer/graphics`)
|
||||
- React-hermes (from `../node_modules/react-native/ReactCommon/hermes`)
|
||||
- React-jsi (from `../node_modules/react-native/ReactCommon/jsi`)
|
||||
- React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`)
|
||||
@ -803,14 +450,12 @@ DEPENDENCIES:
|
||||
- React-RCTAnimation (from `../node_modules/react-native/Libraries/NativeAnimation`)
|
||||
- React-RCTAppDelegate (from `../node_modules/react-native/Libraries/AppDelegate`)
|
||||
- React-RCTBlob (from `../node_modules/react-native/Libraries/Blob`)
|
||||
- React-RCTFabric (from `../node_modules/react-native/React`)
|
||||
- React-RCTImage (from `../node_modules/react-native/Libraries/Image`)
|
||||
- React-RCTLinking (from `../node_modules/react-native/Libraries/LinkingIOS`)
|
||||
- React-RCTNetwork (from `../node_modules/react-native/Libraries/Network`)
|
||||
- React-RCTSettings (from `../node_modules/react-native/Libraries/Settings`)
|
||||
- React-RCTText (from `../node_modules/react-native/Libraries/Text`)
|
||||
- React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`)
|
||||
- React-rncore (from `../node_modules/react-native/ReactCommon`)
|
||||
- React-runtimeexecutor (from `../node_modules/react-native/ReactCommon/runtimeexecutor`)
|
||||
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
|
||||
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
|
||||
@ -865,10 +510,6 @@ EXTERNAL SOURCES:
|
||||
:path: "../node_modules/react-native/React/CoreModules"
|
||||
React-cxxreact:
|
||||
:path: "../node_modules/react-native/ReactCommon/cxxreact"
|
||||
React-Fabric:
|
||||
:path: "../node_modules/react-native/ReactCommon"
|
||||
React-graphics:
|
||||
:path: "../node_modules/react-native/ReactCommon/react/renderer/graphics"
|
||||
React-hermes:
|
||||
:path: "../node_modules/react-native/ReactCommon/hermes"
|
||||
React-jsi:
|
||||
@ -891,8 +532,6 @@ EXTERNAL SOURCES:
|
||||
:path: "../node_modules/react-native/Libraries/AppDelegate"
|
||||
React-RCTBlob:
|
||||
:path: "../node_modules/react-native/Libraries/Blob"
|
||||
React-RCTFabric:
|
||||
:path: "../node_modules/react-native/React"
|
||||
React-RCTImage:
|
||||
:path: "../node_modules/react-native/Libraries/Image"
|
||||
React-RCTLinking:
|
||||
@ -905,8 +544,6 @@ EXTERNAL SOURCES:
|
||||
:path: "../node_modules/react-native/Libraries/Text"
|
||||
React-RCTVibration:
|
||||
:path: "../node_modules/react-native/Libraries/Vibration"
|
||||
React-rncore:
|
||||
:path: "../node_modules/react-native/ReactCommon"
|
||||
React-runtimeexecutor:
|
||||
:path: "../node_modules/react-native/ReactCommon/runtimeexecutor"
|
||||
ReactCommon:
|
||||
@ -919,7 +556,7 @@ SPEC CHECKSUMS:
|
||||
CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99
|
||||
DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54
|
||||
FBLazyVector: ad72713385db5289b19f1ead07e8e4aa26dcb01d
|
||||
FBReactNativeSpec: 06fc2a521838dc240b499699d43467b071c66908
|
||||
FBReactNativeSpec: df2602c11e33d310433496e28a48b4b2be652a61
|
||||
Flipper: 26fc4b7382499f1281eb8cb921e5c3ad6de91fe0
|
||||
Flipper-Boost-iOSX: fd1e2b8cbef7e662a122412d7ac5f5bea715403c
|
||||
Flipper-DoubleConversion: 2dc99b02f658daf147069aad9dbd29d8feb06d30
|
||||
@ -939,31 +576,27 @@ SPEC CHECKSUMS:
|
||||
RCTTypeSafety: c276d85975bde3d8448907235c70bf0da257adfd
|
||||
React: e481a67971af1ce9639c9f746b753dd0e84ca108
|
||||
React-callinvoker: 1051c04a94fa9d243786b86380606bad701a3b31
|
||||
React-Codegen: d4bc58865453b6a797405aa99f9fa1da3c9e58c6
|
||||
React-Codegen: 14b1e716d361d5ad95e0ce1a338f3fa0733a98b5
|
||||
React-Core: 698fc3baecb80d511d987475a16d036cec6d287f
|
||||
React-CoreModules: 59245305f41ff0adfeac334acc0594dea4585a7c
|
||||
React-cxxreact: 49accd2954b0f532805dbcd1918fa6962f32f247
|
||||
React-Fabric: 30982dc19c7511bedf1751b0a0c21a5b816e2a3e
|
||||
React-graphics: beabc29b026e7472ced1482557effedd15a09cf1
|
||||
React-hermes: d068733294581a085e95b6024e8d951b005e26d3
|
||||
React-jsi: 122b9bce14f4c6c7cb58f28f87912cfe091885fa
|
||||
React-jsiexecutor: 60cf272aababc5212410e4249d17cea14fc36caa
|
||||
React-jsinspector: ff56004b0c974b688a6548c156d5830ad751ae07
|
||||
React-logger: 60a0b5f8bed667ecf9e24fecca1f30d125de6d75
|
||||
react-native-update: b9d44d250953e61f1b42c22fa4d585a6bb5dd4d6
|
||||
react-native-update: 2b5ef06bfeaa668614c8deb7ec4d20dcf56f9278
|
||||
React-perflogger: ec8eef2a8f03ecfa6361c2c5fb9197ef4a29cc85
|
||||
React-RCTActionSheet: a0c023b86cf4c862fa9c4eb0f6f91fbe878fb2de
|
||||
React-RCTAnimation: 168d53718c74153947c0109f55900faa64d79439
|
||||
React-RCTAppDelegate: 5f34addd2f9d8c542c129b562b7f3db0cc599a3d
|
||||
React-RCTAppDelegate: a8efbab128b34aa07a9491c85a41401210b1bec5
|
||||
React-RCTBlob: 9bcbfc893bfda9f6b2eb016329d38c0f6366d31a
|
||||
React-RCTFabric: cec4e89720e8778aa132e5515be1af251d2e9b6a
|
||||
React-RCTImage: 3fcd4570b4b0f1ac2f4b4b6308dba33ce66c5b50
|
||||
React-RCTLinking: 1edb8e1bb3fc39bf9e13c63d6aaaa3f0c3d18683
|
||||
React-RCTNetwork: 500a79e0e0f67678077df727fabba87a55c043e1
|
||||
React-RCTSettings: cc4414eb84ad756d619076c3999fecbf12896d6f
|
||||
React-RCTText: 2a34261f3da6e34f47a62154def657546ebfa5e1
|
||||
React-RCTVibration: 49d531ec8498e0afa2c9b22c2205784372e3d4f3
|
||||
React-rncore: b802bc9f6985c482127b066c869999a09d25edeb
|
||||
React-runtimeexecutor: 311feb67600774723fe10eb8801d3138cae9ad67
|
||||
ReactCommon: 03be76588338a27a88d103b35c3c44a3fd43d136
|
||||
SocketRocket: fccef3f9c5cedea1353a9ef6ada904fde10d6608
|
||||
|
@ -211,7 +211,7 @@
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "testHotupdate" */;
|
||||
buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "testHotUpdate" */;
|
||||
compatibilityVersion = "Xcode 12.0";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
@ -689,7 +689,7 @@
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "testHotupdate" */ = {
|
||||
83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "testHotUpdate" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
83CBBA201A601CBA00E9B192 /* Debug */,
|
||||
|
@ -7,4 +7,7 @@
|
||||
<FileRef
|
||||
location = "group:Pods/Pods.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:testHotUpdate.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
|
@ -24,17 +24,6 @@
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSExceptionDomains</key>
|
||||
<dict>
|
||||
<key>localhost</key>
|
||||
<dict>
|
||||
<key>NSExceptionAllowsInsecureHTTPLoads</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>NSLocationWhenInUseUsageDescription</key>
|
||||
<string></string>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
@ -51,5 +40,18 @@
|
||||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
<true/>
|
||||
<key>NSExceptionDomains</key>
|
||||
<dict>
|
||||
<key>localhost</key>
|
||||
<dict>
|
||||
<key>NSExceptionAllowsInsecureHTTPLoads</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
|
@ -25,11 +25,15 @@
|
||||
"@types/react": "^18.0.24",
|
||||
"@types/react-test-renderer": "^18.0.0",
|
||||
"babel-jest": "^29.2.1",
|
||||
"detox": "^20.5.0",
|
||||
"eslint": "^8.19.0",
|
||||
"fs-extra": "^11.1.0",
|
||||
"jest": "^29.2.1",
|
||||
"metro-react-native-babel-preset": "0.73.7",
|
||||
"prettier": "^2.4.1",
|
||||
"react-test-renderer": "18.2.0"
|
||||
"react-test-renderer": "18.2.0",
|
||||
"ts-jest": "^29.0.5",
|
||||
"typescript": "^4.9.5"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "react-native"
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* eslint-disable react-native/no-inline-styles */
|
||||
/* eslint-disable react/react-in-jsx-scope */
|
||||
import {useState} from 'react';
|
||||
import {useCallback, useMemo, useState} from 'react';
|
||||
import {
|
||||
ActivityIndicator,
|
||||
Alert,
|
||||
@ -10,14 +10,117 @@ import {
|
||||
StyleSheet,
|
||||
SafeAreaView,
|
||||
Text,
|
||||
ScrollView,
|
||||
View,
|
||||
TouchableOpacity,
|
||||
} from 'react-native';
|
||||
|
||||
import {PushyModule} from 'react-native-update';
|
||||
|
||||
const Hash = '9D5CE6EBA420717BE7E7D308B11F8207681B066C951D68F3994D19828F342474';
|
||||
const UUID = '00000000-0000-0000-0000-000000000000';
|
||||
const DownloadUrl =
|
||||
'http://cos.pgyer.com/697913e94d7441f20c686e2b0996a1aa.apk?sign=363b035b7ef52c199c268abfacee3712&t=1678603669&response-content-disposition=attachment%3Bfilename%3DtestHotupdate_1.0.apk';
|
||||
export default function TestConsole({visible}) {
|
||||
const [text, setText] = useState('');
|
||||
const [running, setRunning] = useState(false);
|
||||
const [options, setOptions] = useState();
|
||||
const NativeTestMethod = useMemo(() => {
|
||||
return [
|
||||
{
|
||||
name: 'setLocalHashInfo',
|
||||
invoke: () => {
|
||||
setText(
|
||||
`setLocalHashInfo\n${Hash}\n{\"version\":\"1.0.0\",\"size\":\"19M\"}`,
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'getLocalHashInfo',
|
||||
invoke: () => {
|
||||
setText(`getLocalHashInfo\n${Hash}`);
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'setUuid',
|
||||
invoke: () => {
|
||||
setText(`setUuid\n${UUID}`);
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'setBlockUpdate',
|
||||
invoke: () => {
|
||||
setText('setBlockUpdate');
|
||||
setOptions({reason: 'application has been block', until: 1673082950});
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'reloadUpdate',
|
||||
invoke: () => {
|
||||
setText('reloadUpdate');
|
||||
setOptions({hash: Hash});
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'setNeedUpdate',
|
||||
invoke: () => {
|
||||
setText('setNeedUpdate');
|
||||
setOptions({hash: Hash});
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'markSuccess',
|
||||
invoke: () => {
|
||||
setText('markSuccess');
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'downloadPatchFromPpk',
|
||||
invoke: () => {
|
||||
setText('downloadPatchFromPpk');
|
||||
setOptions({updateUrl: DownloadUrl, hash: Hash, originHash: Hash});
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'downloadPatchFromPackage',
|
||||
invoke: () => {
|
||||
setText('downloadPatchFromPackage');
|
||||
setOptions({updateUrl: DownloadUrl, hash: Hash});
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'downloadFullUpdate',
|
||||
invoke: () => {
|
||||
setText('downloadFullUpdate');
|
||||
setOptions({updateUrl: DownloadUrl, hash: Hash});
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'downloadAndInstallApk',
|
||||
invoke: () => {
|
||||
setText('downloadAndInstallApk');
|
||||
setOptions({url: DownloadUrl, target: Hash, hash: Hash});
|
||||
},
|
||||
},
|
||||
];
|
||||
}, []);
|
||||
|
||||
const renderTestView = useCallback(() => {
|
||||
const views = [];
|
||||
for (let i = 0; i < NativeTestMethod.length; i++) {
|
||||
views.push(
|
||||
<TouchableOpacity
|
||||
key={i}
|
||||
testID={NativeTestMethod[i].name}
|
||||
onPress={() => {
|
||||
NativeTestMethod[i].invoke();
|
||||
}}
|
||||
style={{width: 10, height: 10, backgroundColor: 'red'}}
|
||||
/>,
|
||||
);
|
||||
}
|
||||
return <View>{views}</View>;
|
||||
}, [NativeTestMethod]);
|
||||
|
||||
return (
|
||||
<Modal visible={visible}>
|
||||
<SafeAreaView style={{flex: 1, padding: 10}}>
|
||||
@ -42,25 +145,27 @@ export default function TestConsole({visible}) {
|
||||
{running && <ActivityIndicator />}
|
||||
<Button
|
||||
title="执行"
|
||||
testID="submit"
|
||||
onPress={async () => {
|
||||
setRunning(true);
|
||||
try {
|
||||
const inputs = text.split('\n');
|
||||
const methodName = inputs[0];
|
||||
let params;
|
||||
let params = [];
|
||||
if (inputs.length === 1) {
|
||||
await PushyModule[methodName]();
|
||||
if (options) {
|
||||
await PushyModule[methodName](options);
|
||||
} else {
|
||||
await PushyModule[methodName]();
|
||||
}
|
||||
} else {
|
||||
if (inputs.length === 2) {
|
||||
params = inputs[1];
|
||||
params = [inputs[1]];
|
||||
} else {
|
||||
params = {};
|
||||
for (let i = 1; i < inputs.length; i += 2) {
|
||||
params[inputs[i]] = inputs[i + 1];
|
||||
}
|
||||
params = [inputs[1], inputs[2]];
|
||||
console.log({inputs, params});
|
||||
}
|
||||
await PushyModule[methodName](params);
|
||||
await PushyModule[methodName](...params);
|
||||
}
|
||||
Alert.alert('done');
|
||||
} catch (e) {
|
||||
@ -69,9 +174,11 @@ export default function TestConsole({visible}) {
|
||||
setRunning(false);
|
||||
}}
|
||||
/>
|
||||
<View style={{marginTop: 15}}>
|
||||
<ScrollView style={{marginTop: 15}}>
|
||||
<Button title="重置" onPress={() => setText('')} />
|
||||
</View>
|
||||
|
||||
{renderTestView()}
|
||||
</ScrollView>
|
||||
</SafeAreaView>
|
||||
</Modal>
|
||||
);
|
||||
|
@ -170,6 +170,7 @@ export default class App extends Component {
|
||||
</TouchableOpacity>
|
||||
|
||||
<TouchableOpacity
|
||||
testID="testcase"
|
||||
style={{marginTop: 15}}
|
||||
onLongPress={() => {
|
||||
this.setState({showTestConsole: true});
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -58,6 +58,7 @@ repositories {
|
||||
|
||||
dependencies {
|
||||
implementation 'com.facebook.react:react-native:+'
|
||||
implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.0'
|
||||
}
|
||||
if (isNewArchitectureEnabled()) {
|
||||
react {
|
||||
|
@ -10,8 +10,19 @@ import com.facebook.react.bridge.Promise;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.bridge.UiThreadUtil;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class UpdateModuleImpl {
|
||||
|
||||
public static final String NAME = "Pushy";
|
||||
@ -72,27 +83,35 @@ public class UpdateModuleImpl {
|
||||
}
|
||||
|
||||
public static void downloadPatchFromPpk(UpdateContext updateContext, ReadableMap options, Promise promise) {
|
||||
String url = options.getString("updateUrl");
|
||||
String hash = options.getString("hash");
|
||||
try {
|
||||
String url = options.getString("updateUrl");
|
||||
String hash = options.getString("hash");
|
||||
|
||||
String originHash = options.getString("originHash");
|
||||
String originHash = options.getString("originHash");
|
||||
|
||||
updateContext.downloadPatchFromPpk(url, hash, originHash, new UpdateContext.DownloadFileListener() {
|
||||
@Override
|
||||
public void onDownloadCompleted(DownloadTaskParams params) {
|
||||
promise.resolve(null);
|
||||
}
|
||||
updateContext.downloadPatchFromPpk(url, hash, originHash, new UpdateContext.DownloadFileListener() {
|
||||
@Override
|
||||
public void onDownloadCompleted(DownloadTaskParams params) {
|
||||
promise.resolve(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDownloadFailed(Throwable error) {
|
||||
promise.reject(error);
|
||||
}
|
||||
});
|
||||
@Override
|
||||
public void onDownloadFailed(Throwable error) {
|
||||
promise.reject(error);
|
||||
}
|
||||
});
|
||||
}catch (Exception e){
|
||||
promise.reject("执行报错:"+e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public static void reloadUpdate(UpdateContext updateContext, ReactApplicationContext mContext, ReadableMap options) {
|
||||
public static void reloadUpdate(UpdateContext updateContext, ReactApplicationContext mContext, ReadableMap options,Promise promise) {
|
||||
final String hash = options.getString("hash");
|
||||
|
||||
if(hash==null || hash.isEmpty()){
|
||||
promise.reject("hash不能为空");
|
||||
return;
|
||||
}
|
||||
UiThreadUtil.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -112,6 +131,7 @@ public class UpdateModuleImpl {
|
||||
loadField.setAccessible(true);
|
||||
loadField.set(instanceManager, loader);
|
||||
} catch (Throwable err) {
|
||||
promise.reject("pushy:"+err.getMessage());
|
||||
Field jsBundleField = instanceManager.getClass().getDeclaredField("mJSBundleFile");
|
||||
jsBundleField.setAccessible(true);
|
||||
jsBundleField.set(instanceManager, UpdateContext.getBundleUrl(application));
|
||||
@ -119,11 +139,14 @@ public class UpdateModuleImpl {
|
||||
|
||||
try {
|
||||
instanceManager.recreateReactContextInBackground();
|
||||
promise.resolve(true);
|
||||
} catch (Throwable err) {
|
||||
promise.reject("pushy:"+err.getMessage());
|
||||
activity.recreate();
|
||||
}
|
||||
|
||||
} catch (Throwable err) {
|
||||
promise.reject("pushy:switchVersion failed"+err.getMessage());
|
||||
Log.e("pushy", "switchVersion failed", err);
|
||||
}
|
||||
}
|
||||
@ -131,61 +154,112 @@ public class UpdateModuleImpl {
|
||||
}
|
||||
|
||||
|
||||
public static void setNeedUpdate(UpdateContext updateContext, ReadableMap options) {
|
||||
final String hash = options.getString("hash");
|
||||
public static void setNeedUpdate(UpdateContext updateContext, ReadableMap options,Promise promise) {
|
||||
try {
|
||||
final String hash = options.getString("hash");
|
||||
if(hash==null || hash.isEmpty()){
|
||||
promise.reject("hash不能为空");
|
||||
return;
|
||||
}
|
||||
UiThreadUtil.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
updateContext.switchVersion(hash);
|
||||
promise.resolve(true);
|
||||
} catch (Throwable err) {
|
||||
promise.reject("switchVersionLater failed:"+err.getMessage());
|
||||
Log.e("pushy", "switchVersionLater failed", err);
|
||||
}
|
||||
}
|
||||
});
|
||||
}catch (Exception e){
|
||||
promise.reject("执行报错:"+e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public static void markSuccess(UpdateContext updateContext,Promise promise) {
|
||||
try {
|
||||
UiThreadUtil.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateContext.markSuccess();
|
||||
promise.resolve(true);
|
||||
}
|
||||
});
|
||||
}catch (Exception e){
|
||||
promise.reject("执行报错:"+e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public static void setBlockUpdate(UpdateContext updateContext, ReadableMap options,Promise promise) {
|
||||
try {
|
||||
final int until = options.getInt("until");
|
||||
final String reason = options.getString("reason");
|
||||
UiThreadUtil.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateContext.setBlockUpdate(until, reason);
|
||||
}
|
||||
});
|
||||
promise.resolve(true);
|
||||
}catch (Exception e){
|
||||
promise.reject("执行报错:"+e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void setUuid(UpdateContext updateContext, String uuid, Promise promise) {
|
||||
try {
|
||||
UiThreadUtil.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateContext.setKv("uuid", uuid);
|
||||
promise.resolve(true);
|
||||
}
|
||||
});
|
||||
}catch (Exception e){
|
||||
promise.reject("执行报错:"+e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static boolean check(String json) {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
try {
|
||||
mapper.readValue(json, Map.class);
|
||||
System.out.println("String can be converted to Map");
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
System.out.println("String cannot be converted to Map");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void setLocalHashInfo(UpdateContext updateContext, final String hash, final String info, Promise promise) {
|
||||
UiThreadUtil.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
updateContext.switchVersion(hash);
|
||||
} catch (Throwable err) {
|
||||
Log.e("pushy", "switchVersionLater failed", err);
|
||||
if(!check(info)){
|
||||
updateContext.setKv("hash_" + hash, info);
|
||||
promise.reject("校验报错:json字符串格式错误");
|
||||
}else {
|
||||
updateContext.setKv("hash_" + hash, info);
|
||||
promise.resolve(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void markSuccess(UpdateContext updateContext) {
|
||||
UiThreadUtil.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateContext.markSuccess();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void setBlockUpdate(UpdateContext updateContext, ReadableMap options) {
|
||||
final int until = options.getInt("until");
|
||||
final String reason = options.getString("reason");
|
||||
UiThreadUtil.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateContext.setBlockUpdate(until, reason);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void setUuid(UpdateContext updateContext, String uuid) {
|
||||
UiThreadUtil.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateContext.setKv("uuid", uuid);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void setLocalHashInfo(UpdateContext updateContext, final String hash, final String info) {
|
||||
UiThreadUtil.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateContext.setKv("hash_" + hash, info);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void getLocalHashInfo(UpdateContext updateContext, final String hash, Promise promise) {
|
||||
promise.resolve(updateContext.getKv("hash_" + hash));
|
||||
String value = updateContext.getKv("hash_" + hash);
|
||||
if(check(value)){
|
||||
promise.resolve(value);
|
||||
}else {
|
||||
promise.reject("校验报错:json字符串格式错误");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -94,33 +94,33 @@ public class UpdateModule extends NativeUpdateSpec {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reloadUpdate(ReadableMap options) {
|
||||
UpdateModuleImpl.reloadUpdate(updateContext, mContext, options);
|
||||
public void reloadUpdate(ReadableMap options,Promise promise) {
|
||||
UpdateModuleImpl.reloadUpdate(updateContext, mContext, options,promise);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNeedUpdate(ReadableMap options) {
|
||||
UpdateModuleImpl.setNeedUpdate(updateContext, options);
|
||||
public void setNeedUpdate(ReadableMap options,Promise promise) {
|
||||
UpdateModuleImpl.setNeedUpdate(updateContext, options,promise);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markSuccess() {
|
||||
UpdateModuleImpl.markSuccess(updateContext);
|
||||
public void markSuccess(Promise promise) {
|
||||
UpdateModuleImpl.markSuccess(updateContext,promise);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlockUpdate(ReadableMap options) {
|
||||
UpdateModuleImpl.setBlockUpdate(updateContext,options);
|
||||
public void setBlockUpdate(ReadableMap options,Promise promise) {
|
||||
UpdateModuleImpl.setBlockUpdate(updateContext,options,promise);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUuid(final String uuid) {
|
||||
UpdateModuleImpl.setUuid(updateContext,uuid);
|
||||
public void setUuid(final String uuid, Promise promise) {
|
||||
UpdateModuleImpl.setUuid(updateContext,uuid,promise);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLocalHashInfo(final String hash, final String info) {
|
||||
UpdateModuleImpl.setLocalHashInfo(updateContext,hash,info);
|
||||
public void setLocalHashInfo(final String hash, final String info, final Promise promise) {
|
||||
UpdateModuleImpl.setLocalHashInfo(updateContext,hash,info,promise);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -192,29 +192,53 @@ RCT_EXPORT_MODULE(RCTPushy);
|
||||
return self;
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(setBlockUpdate:(NSDictionary *)options)
|
||||
RCT_EXPORT_METHOD(setBlockUpdate:(NSDictionary *)options
|
||||
resolver:(RCTPromiseResolveBlock)resolve
|
||||
rejecter:(RCTPromiseRejectBlock)reject)
|
||||
{
|
||||
// NSMutableDictionary *blockUpdateInfo = [NSMutableDictionary new];
|
||||
// blockUpdateInfo[@"reason"] = options[@"reason"];
|
||||
// blockUpdateInfo[@"until"] = options[@"until"];
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
[defaults setObject:options forKey:keyBlockUpdate];
|
||||
[defaults synchronize];
|
||||
@try {
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
[defaults setObject:options forKey:keyBlockUpdate];
|
||||
[defaults synchronize];
|
||||
resolve(@true);
|
||||
}
|
||||
@catch (NSException *exception) {
|
||||
reject(@"执行报错", nil, nil);
|
||||
}
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(setUuid:(NSString *)uuid)
|
||||
RCT_EXPORT_METHOD(setUuid:(NSString *)uuid resolver:(RCTPromiseResolveBlock)resolve
|
||||
rejecter:(RCTPromiseRejectBlock)reject)
|
||||
{
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
[defaults setObject:uuid forKey:keyUuid];
|
||||
[defaults synchronize];
|
||||
@try {
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
[defaults setObject:uuid forKey:keyUuid];
|
||||
[defaults synchronize];
|
||||
resolve(@true);
|
||||
}
|
||||
@catch (NSException *exception) {
|
||||
reject(@"json格式校验报错", nil, nil);
|
||||
}
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(setLocalHashInfo:(NSString *)hash
|
||||
value:(NSString *)value)
|
||||
value:(NSString *)value resolver:(RCTPromiseResolveBlock)resolve
|
||||
rejecter:(RCTPromiseRejectBlock)reject)
|
||||
{
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
[defaults setObject:value forKey:[keyHashInfo stringByAppendingString:hash]];
|
||||
[defaults synchronize];
|
||||
NSData *data = [value dataUsingEncoding:NSUTF8StringEncoding];
|
||||
NSError *error = nil;
|
||||
id object = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
|
||||
if (object && [object isKindOfClass:[NSDictionary class]]) {
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
[defaults setObject:value forKey:[keyHashInfo stringByAppendingString:hash]];
|
||||
[defaults synchronize];
|
||||
resolve(@true);
|
||||
} else {
|
||||
reject(@"json格式校验报错", nil, nil);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -269,7 +293,9 @@ RCT_EXPORT_METHOD(downloadPatchFromPpk:(NSDictionary *)options
|
||||
}];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(setNeedUpdate:(NSDictionary *)options)
|
||||
RCT_EXPORT_METHOD(setNeedUpdate:(NSDictionary *)options
|
||||
resolver:(RCTPromiseResolveBlock)resolve
|
||||
rejecter:(RCTPromiseRejectBlock)reject)
|
||||
{
|
||||
NSString *hash = options[@"hash"];
|
||||
|
||||
@ -290,45 +316,66 @@ RCT_EXPORT_METHOD(setNeedUpdate:(NSDictionary *)options)
|
||||
[defaults setObject:newInfo forKey:keyPushyInfo];
|
||||
|
||||
[defaults synchronize];
|
||||
resolve(@true);
|
||||
}else{
|
||||
reject(@"执行报错", nil, nil);
|
||||
}
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(reloadUpdate:(NSDictionary *)options)
|
||||
RCT_EXPORT_METHOD(reloadUpdate:(NSDictionary *)options
|
||||
resolver:(RCTPromiseResolveBlock)resolve
|
||||
rejecter:(RCTPromiseRejectBlock)reject)
|
||||
{
|
||||
NSString *hash = options[@"hash"];
|
||||
|
||||
if (hash.length) {
|
||||
[self setNeedUpdate:options];
|
||||
|
||||
// reload 0.62+
|
||||
// RCTReloadCommandSetBundleURL([[self class] bundleURL]);
|
||||
// RCTTriggerReloadCommandListeners(@"pushy reload");
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self.bridge setValue:[[self class] bundleURL] forKey:@"bundleURL"];
|
||||
[self.bridge reload];
|
||||
});
|
||||
@try {
|
||||
NSString *hash = options[@"hash"];
|
||||
if (hash.length) {
|
||||
[self setNeedUpdate:options resolver:resolve rejecter:reject];
|
||||
|
||||
// reload 0.62+
|
||||
// RCTReloadCommandSetBundleURL([[self class] bundleURL]);
|
||||
// RCTTriggerReloadCommandListeners(@"pushy reload");
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self.bridge setValue:[[self class] bundleURL] forKey:@"bundleURL"];
|
||||
[self.bridge reload];
|
||||
});
|
||||
resolve(@true);
|
||||
}else{
|
||||
reject(@"执行报错", nil, nil);
|
||||
}
|
||||
}
|
||||
@catch (NSException *exception) {
|
||||
reject(@"执行报错", nil, nil);
|
||||
}
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(markSuccess)
|
||||
RCT_EXPORT_METHOD(markSuccess:
|
||||
resolver:(RCTPromiseResolveBlock)resolve
|
||||
rejecter:(RCTPromiseRejectBlock)reject)
|
||||
{
|
||||
// up package info
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
NSMutableDictionary *pushyInfo = [[NSMutableDictionary alloc] initWithDictionary:[defaults objectForKey:keyPushyInfo]];
|
||||
[pushyInfo setObject:@(NO) forKey:paramIsFirstTime];
|
||||
[pushyInfo setObject:@(YES) forKey:paramIsFirstLoadOk];
|
||||
|
||||
NSString *lastVersion = pushyInfo[paramLastVersion];
|
||||
NSString *curVersion = pushyInfo[paramCurrentVersion];
|
||||
if (lastVersion != nil && ![lastVersion isEqualToString:curVersion]) {
|
||||
[pushyInfo removeObjectForKey:[keyHashInfo stringByAppendingString:lastVersion]];
|
||||
@try {
|
||||
// up package info
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
NSMutableDictionary *pushyInfo = [[NSMutableDictionary alloc] initWithDictionary:[defaults objectForKey:keyPushyInfo]];
|
||||
[pushyInfo setObject:@(NO) forKey:paramIsFirstTime];
|
||||
[pushyInfo setObject:@(YES) forKey:paramIsFirstLoadOk];
|
||||
|
||||
NSString *lastVersion = pushyInfo[paramLastVersion];
|
||||
NSString *curVersion = pushyInfo[paramCurrentVersion];
|
||||
if (lastVersion != nil && ![lastVersion isEqualToString:curVersion]) {
|
||||
[pushyInfo removeObjectForKey:[keyHashInfo stringByAppendingString:lastVersion]];
|
||||
}
|
||||
[defaults setObject:pushyInfo forKey:keyPushyInfo];
|
||||
[defaults synchronize];
|
||||
|
||||
// clear other package dir
|
||||
[self clearInvalidFiles];
|
||||
resolve(@true);
|
||||
}
|
||||
@catch (NSException *exception) {
|
||||
reject(@"执行报错", nil, nil);
|
||||
}
|
||||
[defaults setObject:pushyInfo forKey:keyPushyInfo];
|
||||
[defaults synchronize];
|
||||
|
||||
// clear other package dir
|
||||
[self clearInvalidFiles];
|
||||
}
|
||||
|
||||
|
||||
@ -354,6 +401,19 @@ RCT_EXPORT_METHOD(markSuccess)
|
||||
// Remove upstream listeners, stop unnecessary background tasks
|
||||
}
|
||||
|
||||
- (BOOL) isBlankString:(NSString *)string {
|
||||
if (string == nil || string == NULL) {
|
||||
return YES;
|
||||
}
|
||||
if ([string isKindOfClass:[NSNull class]]) {
|
||||
return YES;
|
||||
}
|
||||
if ([[string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] length]==0) {
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
- (void)doPushy:(PushyType)type options:(NSDictionary *)options callback:(void (^)(NSError *error))callback
|
||||
{
|
||||
@ -365,7 +425,7 @@ RCT_EXPORT_METHOD(markSuccess)
|
||||
return;
|
||||
}
|
||||
NSString *originHash = [RCTConvert NSString:options[@"originHash"]];
|
||||
if (type == PushyTypePatchFromPpk && originHash <= 0) {
|
||||
if (type == PushyTypePatchFromPpk && [self isBlankString:originHash]) {
|
||||
callback([self errorWithMessage:ERROR_OPTIONS]);
|
||||
return;
|
||||
}
|
||||
@ -570,7 +630,7 @@ RCT_EXPORT_METHOD(markSuccess)
|
||||
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
|
||||
(const facebook::react::ObjCTurboModule::InitParams &)params
|
||||
{
|
||||
return std::make_shared<facebook::react::NativeCalculatorSpecJSI>(params);
|
||||
return std::make_shared<facebook::react::NativeUpdateSpecJSI>(params);
|
||||
}
|
||||
#endif
|
||||
|
@ -1 +1 @@
|
||||
1676798137
|
||||
1678849794
|
||||
|
@ -19,10 +19,13 @@ export interface Spec extends TurboModule {
|
||||
uuid: string,
|
||||
isUsingBundleUrl: boolean,
|
||||
};
|
||||
setLocalHashInfo(hash: string, info: string): void;
|
||||
setLocalHashInfo(hash: string, info: string): Promise<void>;
|
||||
getLocalHashInfo(hash: string): Promise<string>;
|
||||
setUuid(uuid: string): void;
|
||||
setBlockUpdate(options: { reason: string, until: number }): void;
|
||||
setUuid(uuid: string): Promise<void>;
|
||||
setBlockUpdate(options: { reason: string, until: number }): Promise<void>;
|
||||
reloadUpdate(options: { hash: string }): Promise<void>;
|
||||
setNeedUpdate(options: { hash: string }): Promise<void>;
|
||||
markSuccess(): Promise<void>;
|
||||
downloadPatchFromPpk(options: {
|
||||
updateUrl: string,
|
||||
hash: string,
|
||||
@ -36,9 +39,6 @@ export interface Spec extends TurboModule {
|
||||
updateUrl: string,
|
||||
hash: string,
|
||||
}): Promise<void>;
|
||||
reloadUpdate(options: { hash: string }): void;
|
||||
setNeedUpdate(options: { hash: string }): void;
|
||||
markSuccess(): void;
|
||||
downloadAndInstallApk(options: {
|
||||
url: string,
|
||||
target: string,
|
||||
|
27
package.json
27
package.json
@ -7,7 +7,23 @@
|
||||
"prepublish": "yarn submodule",
|
||||
"submodule": "git submodule update --init --recursive",
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"build-lib": "yarn submodule && $ANDROID_HOME/ndk/20.1.5948944/ndk-build NDK_PROJECT_PATH=android APP_BUILD_SCRIPT=android/jni/Android.mk NDK_APPLICATION_MK=android/jni/Application.mk NDK_LIBS_OUT=android/lib"
|
||||
"build-lib": "yarn submodule && $ANDROID_HOME/ndk/20.1.5948944/ndk-build NDK_PROJECT_PATH=android APP_BUILD_SCRIPT=android/jni/Android.mk NDK_APPLICATION_MK=android/jni/Application.mk NDK_LIBS_OUT=android/lib",
|
||||
"build:ios": "cd Example/testHotUpdate && detox build --configuration ios.sim.debug",
|
||||
"build:ios-debug": "cd Example/testHotUpdate && detox build --configuration ios.sim.debug",
|
||||
"build:ios-release": "cd Example/testHotUpdate && detox build --configuration ios.sim.release",
|
||||
"build:android-debug": "cd Example/testHotUpdate && detox build --configuration android.emu.debug",
|
||||
"build:android-release": "cd Example/testHotUpdate && detox build --configuration android.emu.release",
|
||||
"test:ios": "cd Example/testHotUpdate && detox test --configuration ios.sim.debug",
|
||||
"test:ios-debug": "cd Example/testHotUpdate && detox test --configuration ios.sim.debug",
|
||||
"test:ios-release": "cd Example/testHotUpdate && detox test --configuration ios.sim.release",
|
||||
"test:android-debug": "cd Example/testHotUpdate && detox test --configuration android.emu.debug",
|
||||
"test:android-release": "cd Example/testHotUpdate && ./node_modules/.bin/nyc yarn detox test --configuration android.emu.debug",
|
||||
"e2e:ios": "npm run build:ios-release && npm run test:ios-release",
|
||||
"e2e:android": "npm run build:android-release && npm run test:android-release",
|
||||
"tests:emulator:prepare": "cd .github/workflows/scripts/functions && yarn && yarn build",
|
||||
"tests:emulator:start-ci": "yarn tests:emulator:prepare && cd ./.github/workflows/scripts && ./start-firebase-emulator.sh",
|
||||
"tests:packager:jet-ci": "cd Example/testHotUpdate && cross-env TMPDIR=$HOME/.metro REACT_DEBUGGER=\"echo nope\" node_modules/.bin/react-native start --no-interactive",
|
||||
"tests:ios:pod:install": "rm -rf ios/RCTPushy.xcworkspace && yarn pod-install"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -33,11 +49,14 @@
|
||||
},
|
||||
"codegenConfig": {
|
||||
"libraries": [
|
||||
{
|
||||
{
|
||||
"name": "RCTPushySpec",
|
||||
"type": "modules",
|
||||
"jsSrcsDir": "lib"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"firebase-tools": "^11.24.1"
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user