Skip to content

Commit

Permalink
[B2CQA-2056] Various E2E Mobile tests improvements (#5390)
Browse files Browse the repository at this point in the history
* test: upgrade android emulator to Pixel 6 Pro SDK 32 and cache it
* test: fix market test
* ci: use s3 caching for avd
* test: update detox to latest version
* fix: sending mock message only after ws client is connected
* chore: update pnpm-lock file
  • Loading branch information
abdurrahman-ledger authored and lvndry committed Nov 14, 2023
1 parent 9cce54e commit 1bac929
Show file tree
Hide file tree
Showing 9 changed files with 115 additions and 51 deletions.
44 changes: 36 additions & 8 deletions .github/workflows/test-mobile-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -210,25 +210,53 @@ jobs:
- name: Build Android app for Detox test run
run: |
pnpm mobile e2e:build -c android.emu.release
- name: cache android emulator
uses: tespkg/actions-cache@v1
id: detox-avd
with:
path: |
~/.android/avd/*
~/.android/adb*
key: ${{ runner.os }}-detox-avd-${{ hashFiles('~/.android/avd/*/config.ini') }}
restore-keys: |
${{ runner.os }}-detox-avd-
accessKey: ${{ secrets.AWS_S3_CACHE_ACCESS_KEY }}
secretKey: ${{ secrets.AWS_S3_CACHE_SECRET_KEY }}
bucket: ll-gha-s3-cache
region: eu-west-1
use-fallback: false
- name: create AVD and generate snapshot for caching
if: steps.detox-avd.outputs.cache-hit != 'true'
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 32
arch: x86_64
profile: pixel_6_pro
target: google_apis
avd-name: "Pixel_6_Pro_API_32"
force-avd-creation: true
cores: 4
ram-size: 8192M
disable-linux-hw-accel: false
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
script: ./tools/scripts/wait_emulator_idle.sh
- name: Start Emulator and Run Android Tests
id: detox
uses: reactivecircus/android-emulator-runner@v2
timeout-minutes: 60
env:
DETOX_INSTALL_TIMEOUT: 120000
with:
api-level: 31
api-level: 32
arch: x86_64
profile: pixel_5
profile: pixel_6_pro
target: google_apis
avd-name: "Pixel_5_API_31"
force-avd-creation: true
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
avd-name: "Pixel_6_Pro_API_32"
force-avd-creation: false
cores: 4
ram-size: 4096M
heap-size: 512M
disk-size: 4096M
ram-size: 8192M
disable-linux-hw-accel: false
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
script: pnpm mobile e2e:test -c android.emu.release --loglevel error --record-logs all --take-screenshots all --forceExit --detectOpenHandles --headless --retries 1
- name: Upload test artifacts
if: always()
Expand Down
2 changes: 1 addition & 1 deletion apps/ledger-live-mobile/detox.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ module.exports = {
emulator: {
type: "android.emulator",
device: {
avdName: "Pixel_5_API_31",
avdName: "Pixel_6_Pro_API_32",
},
gpuMode: "swiftshader_indirect",
headless: process.env.CI ? true : false,
Expand Down
30 changes: 19 additions & 11 deletions apps/ledger-live-mobile/e2e/bridge/server.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Server } from "ws";
import { Server, WebSocket } from "ws";
import path from "path";
import fs from "fs";
import { toAccountRaw } from "@ledgerhq/live-common/account/index";
Expand All @@ -16,17 +16,22 @@ type ServerData = {
export const e2eBridgeServer = new Subject<ServerData>();

let wss: Server;
let onConnectionPromise: Promise<WebSocket> | null = null;

// eslint-disable-next-line @typescript-eslint/no-empty-function
export function init(port = 8099, onConnection = () => {}) {
wss = new Server({ port });
log(`Start listening on localhost:${port}`);

wss.on("connection", ws => {
log(`Connection`);
onConnection();
ws.on("message", onMessage);
export function init(port = 8099, onConnection = () => {}): Promise<WebSocket> {
onConnectionPromise = new Promise(resolve => {
wss = new Server({ port });
log(`Start listening on localhost:${port}`);

wss.on("connection", ws => {
log(`Client connected`);
onConnection();
resolve(ws); // Resolve the promise when a client connects
ws.on("message", onMessage);
});
});
return onConnectionPromise;
}

export function close() {
Expand Down Expand Up @@ -136,8 +141,11 @@ function acceptTerms() {
postMessage({ type: "acceptTerms" });
}

function postMessage(message: MessageData) {
for (const ws of wss.clients.values()) {
async function postMessage(message: MessageData) {
const ws = await onConnectionPromise; // Wait until a client is connected and get the WebSocket instance
if (ws) {
ws.send(JSON.stringify(message));
} else {
log("WebSocket connection is not open. Message not sent.");
}
}
6 changes: 2 additions & 4 deletions apps/ledger-live-mobile/e2e/specs/market.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,12 @@ describe("Market page for user with no device", () => {
await expect(getElementByText("Bitcoin (BTC)")).toBeVisible();
});

// FIXME Javascript error on webview
it.skip("should redirect to the buy a nano marketplace page", async () => {
it("should redirect to the buy a nano marketplace page", async () => {
await marketPage.openAssetPage("Bitcoin (BTC)");
await marketPage.buyNano();
await marketPage.openMarketPlace();

if (isAndroid()) {
const url = await web.element(by.web.id("main")).getCurrentUrl();
const url = await web.element(by.web.id("__next")).getCurrentUrl();
const expectedUrl = "https://shop.ledger.com/";

jestExpect(url).toContain(expectedUrl);
Expand Down
2 changes: 1 addition & 1 deletion apps/ledger-live-mobile/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@
"@types/ws": "^8.5.3",
"allure-js-commons": "1.3.2",
"babel-jest": "^29.7.0",
"detox": "^20.13.1",
"detox": "^20.13.5",
"eslint-import-resolver-typescript": "^3.6.1",
"eslint-plugin-detox": "^1.0.0",
"eslint-plugin-i18next": "^6.0.3",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@
"react-native-image-crop-tools@1.6.4": "patches/react-native-image-crop-tools@1.6.4.patch",
"react-native-webview@11.26.1": "patches/react-native-webview@11.26.1.patch",
"asyncstorage-down@4.2.0": "patches/asyncstorage-down@4.2.0.patch",
"detox@20.13.1": "patches/detox@20.13.1.patch",
"detox@20.13.5": "patches/detox@20.13.5.patch",
"usb@2.9.0": "patches/usb@2.9.0.patch"
},
"packageExtensions": {
Expand Down
File renamed without changes.
37 changes: 12 additions & 25 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

43 changes: 43 additions & 0 deletions tools/scripts/wait_emulator_idle.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/bin/bash

# Wait until the device is considered idle

start_time=$(date +%s)
load_threshold=0.9
echo "Start waiting until the device is idle ($(date))"
end_time=$((start_time + 1800))

while true; do
load=$(adb shell uptime | cut -d , -f 3 | cut -f 2 -d :)

if (( $(echo "$load > $load_threshold" | bc -l) )); then
if (( $(echo "$load < 4" | bc -l) )); then
anr_package=$(adb shell dumpsys window | grep -E "mCurrentFocus.*Application Not Responding" | cut -f 2 -d : | sed -e "s/}//" -e "s/^ *//" | tr -d '\r\n')

if [ -n "$anr_package" ]; then
echo "ANR on screen for: $anr_package. Restarting it."

# Some suggest that restarting the service with 'am startservice' should restart it,
# but it doesn't seem to work. So using killall.
# We additionally restart it, but with killall, the system UI is restarted automatically
adb shell su 0 killall $anr_package

if [ "$anr_package" == "com.android.systemui" ]; then
adb shell am start-service -n com.android.systemui/.SystemUIService || true
fi
fi
fi

sleep 15
else
break
fi

if [ $(date +%s) -ge $end_time ]; then
echo "Reached the timeout before the device is idle."
break
fi
done

echo "Waited until the device is idle for $(( $(date +%s) - start_time )) seconds."

0 comments on commit 1bac929

Please sign in to comment.