Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ If you have `bitkit-e2e-tests`, `bitkit-android`, and `bitkit-ios` checked out i
# Android (builds ../bitkit-android and copies APK to ./aut/bitkit_e2e.apk)
./scripts/build-android-apk.sh

# Legacy RN Android (builds ../bitkit and copies APK to ./aut/bitkit_rn_regtest.apk)
./scripts/build-rn-android-apk.sh

# iOS (builds ../bitkit-ios and copies IPA to ./aut/bitkit_e2e.ipa)
./scripts/build-ios-sim.sh
```
Expand All @@ -67,6 +70,9 @@ Optional backend selection (`BACKEND=local` is default and can be omitted):
BACKEND=local ./scripts/build-android-apk.sh
BACKEND=regtest ./scripts/build-android-apk.sh

# Legacy RN Android
BACKEND=regtest ./scripts/build-rn-android-apk.sh

# iOS
BACKEND=local ./scripts/build-ios-sim.sh
BACKEND=regtest ./scripts/build-ios-sim.sh
Expand Down
71 changes: 71 additions & 0 deletions scripts/build-rn-android-apk.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#!/usr/bin/env bash
# Build the legacy Bitkit RN Android APK from ../bitkit and copy into aut/
#
# Inputs/roots:
# - E2E root: this repo (bitkit-e2e-tests)
# - RN root: ../bitkit (resolved relative to this script)
#
# Output:
# - Copies APK -> aut/bitkit_rn_<backend>.apk
#
# Usage:
# ./scripts/build-rn-android-apk.sh [debug|release]
# BACKEND=regtest ./scripts/build-rn-android-apk.sh
# ENV_FILE=.env.test.template ./scripts/build-rn-android-apk.sh
set -euo pipefail

E2E_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
RN_ROOT="$(cd "$E2E_ROOT/../bitkit" && pwd)"

BUILD_TYPE="${1:-debug}"
BACKEND="${BACKEND:-regtest}"

if [[ "$BUILD_TYPE" != "debug" && "$BUILD_TYPE" != "release" ]]; then
echo "ERROR: Unsupported build type: $BUILD_TYPE (expected debug|release)" >&2
exit 1
fi

if [[ -z "${ENV_FILE:-}" ]]; then
if [[ "$BACKEND" == "regtest" ]]; then
ENV_FILE=".env.test.template"
else
ENV_FILE=".env.development"
fi
fi

if [[ ! -f "$RN_ROOT/$ENV_FILE" ]]; then
echo "ERROR: Env file not found: $RN_ROOT/$ENV_FILE" >&2
exit 1
fi

echo "Building RN Android APK (BACKEND=$BACKEND, ENV_FILE=$ENV_FILE, BUILD_TYPE=$BUILD_TYPE)..."

pushd "$RN_ROOT" >/dev/null
if [[ -f .env ]]; then
cp .env .env.bak
fi
cp "$ENV_FILE" .env
E2E_TESTS=true yarn "e2e:build:android-$BUILD_TYPE"
if [[ -f .env.bak ]]; then
mv .env.bak .env
else
rm -f .env
fi
popd >/dev/null

APK_PATH="$RN_ROOT/android/app/build/outputs/apk/$BUILD_TYPE/app-universal-$BUILD_TYPE.apk"
if [[ ! -f "$APK_PATH" ]]; then
ALT_APK_PATH="$RN_ROOT/android/app/build/outputs/apk/$BUILD_TYPE/app-$BUILD_TYPE.apk"
if [[ -f "$ALT_APK_PATH" ]]; then
APK_PATH="$ALT_APK_PATH"
else
echo "ERROR: APK not found at: $APK_PATH" >&2
exit 1
fi
fi

OUT="$E2E_ROOT/aut"
mkdir -p "$OUT"
OUT_APK="$OUT/bitkit_rn_${BACKEND}.apk"
cp -f "$APK_PATH" "$OUT_APK"
echo "RN APK copied to: $OUT_APK (from $(basename "$APK_PATH"))"
4 changes: 3 additions & 1 deletion test/helpers/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,9 @@ export async function restoreWallet(
const getStarted = await elementById('GetStartedButton');
await getStarted.waitForDisplayed();
await tap('GetStartedButton');

await sleep(1000);
await handleAndroidAlert();

if (expectQuickPayTimedSheet) {
await dismissQuickPayIntro();
}
Expand Down
32 changes: 32 additions & 0 deletions test/helpers/setup.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { execSync } from 'node:child_process';
import fs from 'node:fs';
import path from 'node:path';
import { sleep } from './actions';
import { getAppId, getAppPath } from './constants';

Expand All @@ -24,6 +26,36 @@ export async function reinstallApp() {
await driver.activateApp(appId);
}

export function getRnAppPath(): string {
const fallback = path.join(__dirname, '..', '..', 'aut', 'bitkit_rn_regtest.apk');
const appPath = process.env.RN_APK_PATH ?? fallback;
if (!fs.existsSync(appPath)) {
throw new Error(
`RN APK not found at: ${appPath}. Set RN_APK_PATH or place it at ${fallback}`
);
}
return appPath;
}

export function getNativeAppPath(): string {
const fallback = path.join(__dirname, '..', '..', 'aut', 'bitkit_e2e.apk');
const appPath = process.env.NATIVE_APK_PATH ?? fallback;
if (!fs.existsSync(appPath)) {
throw new Error(
`Native APK not found at: ${appPath}. Set NATIVE_APK_PATH or place it at ${fallback}`
);
}
return appPath;
}

export async function reinstallAppFromPath(appPath: string, appId: string = getAppId()) {
console.info(`→ Reinstalling app from: ${appPath}`);
await driver.removeApp(appId);
resetBootedIOSKeychain();
await driver.installApp(appPath);
await driver.activateApp(appId);
}

/**
* Resets iOS simulator to remove stored data between app reinstall cycles.
* (Wallet data is stored in iOS Keychain and persists even after app uninstall
Expand Down
47 changes: 47 additions & 0 deletions test/specs/migration.e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { elementById, restoreWallet, sleep, tap, typeText, waitForSetupWalletScreenFinish } from '../helpers/actions';
import { ciIt } from '../helpers/suite';
import { getNativeAppPath, getRnAppPath, reinstallAppFromPath } from '../helpers/setup';

const MIGRATION_MNEMONIC =
process.env.MIGRATION_MNEMONIC ??
'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about';

describe('@migration - Legacy RN migration', () => {
ciIt('@migration_1 - Can restore legacy RN wallet from mnemonic', async () => {
await installLegacyRnApp();
await restoreLegacyRnWallet(MIGRATION_MNEMONIC);

// Restore into native app
// await installNativeApp();
await restoreWallet(MIGRATION_MNEMONIC);
});
});

async function installNativeApp() {
await reinstallAppFromPath(getNativeAppPath());
}
async function installLegacyRnApp() {
await reinstallAppFromPath(getRnAppPath());
}

async function restoreLegacyRnWallet(seed: string) {
await elementById('Continue').waitForDisplayed();
await tap('Check1');
await tap('Check2');
await tap('Continue');

await tap('SkipIntro');

await tap('RestoreWallet');
await tap('MultipleDevices-button');

await typeText('Word-0', seed);
await sleep(1500);
await tap('RestoreButton');
await waitForSetupWalletScreenFinish();

const getStarted = await elementById('GetStartedButton');
await getStarted.waitForDisplayed( { timeout: 120000 });
await tap('GetStartedButton');
await sleep(1000);
}