From 97bc1be7c18dfaff267e489021e4ad51c88dc9e2 Mon Sep 17 00:00:00 2001 From: Siyuan Miao Date: Thu, 20 Nov 2025 00:15:43 +0100 Subject: [PATCH] add script to automate pushing --- scripts/e2e.sh | 78 ++++++++++++++++++++++++++++++++++++++++++++ ui/tests/ota.spec.ts | 32 ++++++++---------- 2 files changed, 92 insertions(+), 18 deletions(-) create mode 100755 scripts/e2e.sh diff --git a/scripts/e2e.sh b/scripts/e2e.sh new file mode 100755 index 00000000..529d0105 --- /dev/null +++ b/scripts/e2e.sh @@ -0,0 +1,78 @@ +#!/usr/bin/env bash +# +# Exit immediately if a command exits with a non-zero status +set -e + +SCRIPT_PATH=$(realpath "$(dirname $(realpath "${BASH_SOURCE[0]}"))") +source ${SCRIPT_PATH}/build_utils.sh + +# Function to display help message +show_help() { + echo "Usage: $0 [options] -r " + echo + echo "Required:" + echo " -r, --remote Remote host IP address" + echo + echo "Example:" + echo " $0 -r 192.168.0.17" +} + +REMOTE_HOST="" +PAUSE_AFTER_PUSH=0 + +# Parse command line arguments +while [[ $# -gt 0 ]]; do + case $1 in + -r|--remote) + REMOTE_HOST="$2" + shift 2 + ;; + --help) + show_help + exit 0 + ;; + --pause) + PAUSE_AFTER_PUSH=1 + shift + ;; + *) + echo "Unknown option: $1" + show_help + exit 1 + ;; + esac +done + +# Verify required parameters +if [ -z "$REMOTE_HOST" ]; then + msg_err "Error: Remote IP is a required parameter" + show_help + exit 1 +fi + +function sshrun() { + ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "root@${REMOTE_HOST}" "$@" +} + +msg_info "▶ Pushing baseline version to remote host" +gzip -9c bin/jetkvm_app | pv | sshrun "gzip -d > /userdata/jetkvm/jetkvm_app.update" + +msg_info "▶ Rebooting device" +sshrun ash << EOF +set -e +sync +echo 1 > /proc/sys/vm/drop_caches +reboot -d 5 -f & +exit 0 +EOF + +if [ $PAUSE_AFTER_PUSH -eq 1 ]; then + read -p "Press Enter to continue" +fi + +sleep 5 + +pushd ui > /dev/null +# npx playwright test --headed -g 'standard upgrade process' +npx playwright test --headed -g 'custom upgrade process: upgrade app only' +popd > /dev/null \ No newline at end of file diff --git a/ui/tests/ota.spec.ts b/ui/tests/ota.spec.ts index 27defc35..d4fd0c5a 100644 --- a/ui/tests/ota.spec.ts +++ b/ui/tests/ota.spec.ts @@ -149,12 +149,12 @@ const doStandardUpdate = async (page: Page) => { app: '', } - const systemUpdateAvailable = updateAvailableContainer.locator('.text-sm', { hasText: m.general_update_system_type()+":" }).first(); + const systemUpdateAvailable = updateAvailableContainer.locator('.text-sm', { hasText: m.general_update_system_type() + ":" }).first(); if (await systemUpdateAvailable.isVisible()) { versionInfo.sys = await systemUpdateAvailable.textContent() ?? ''; } - const appUpdateAvailable = updateAvailableContainer.locator('.text-sm', { hasText: m.general_update_application_type()+":" }).first(); + const appUpdateAvailable = updateAvailableContainer.locator('.text-sm', { hasText: m.general_update_application_type() + ":" }).first(); if (await appUpdateAvailable.isVisible()) { versionInfo.app = await appUpdateAvailable.textContent() ?? ''; } @@ -194,21 +194,18 @@ const runUpdateTest = ({ sys, app }: CustomUpgradeProcessOptions) => async ({ pa } // Except ICE gathering completed or JetKVM device connected + // await expect( + // getByText(page, 'ice_gathering_completed'). + // or(getByText(page, 'video_overlay_loading_stream')). + // or(getByText(page, 'video_overlay_no_hdmi_signal')) + // , + // 'Wait until the WebRTC connection is established', + // ).toBeVisible(); await expect( - getByText(page, 'ice_gathering_completed'). - or(getByText(page, 'peer_connection_connected').first()). - or(getByText(page, 'video_overlay_loading_stream')) - , + getByText(page, 'video_overlay_no_hdmi_signal'), 'Wait until the WebRTC connection is established', ).toBeVisible(); - // Except No HDMI signal detected, as the device is not connected to the HDMI port - // await expect( - // getByText(page, 'video_overlay_no_hdmi_signal'), - // 'should be visible when no HDMI signal is detected', - // ).toBeVisible(); - - await sleep(); // Emulate upgrade process @@ -250,9 +247,7 @@ const runUpdateTest = ({ sys, app }: CustomUpgradeProcessOptions) => async ({ pa await expect( getByText(page, 'general_update_status_awaiting_reboot') .or(getByText(page, 'general_update_rebooting')) - // older version uses "..." instead of "…" for the ellipsis - .or(page.getByText('Rebooting to complete the update')), - 'UpdatingDeviceState: awaiting reboot or rebooting', + , 'UpdatingDeviceState: awaiting reboot or rebooting', ).toBeVisible({ timeout }); }; @@ -265,7 +260,8 @@ const runUpdateTest = ({ sys, app }: CustomUpgradeProcessOptions) => async ({ pa // Rebooting or different IP message await expect( - getByText(page, 'video_overlay_reboot_device_is_rebooting') + getByText(page, 'general_update_rebooting') + .or(getByText(page, 'video_overlay_reboot_unable_to_reconnect')) .or(getByText(page, 'video_overlay_reboot_different_ip_message')) , 'VideoOverlay should show either reboot device is rebooting or different ip message' ).toBeVisible({ timeout }); @@ -307,7 +303,7 @@ test('custom upgrade process: upgrade system only', runUpdateTest({ })); test('custom upgrade process: upgrade app only', runUpdateTest({ - app: '0.4.5', + app: '0.4.8', })); test('custom upgrade process: upgrade both', runUpdateTest({