diff --git a/.github/workflows/desktop-linux.yml b/.github/workflows/desktop-linux.yml index f826ccbbfc..40ad0f164c 100644 --- a/.github/workflows/desktop-linux.yml +++ b/.github/workflows/desktop-linux.yml @@ -274,6 +274,15 @@ jobs: timeout-minutes: 30 run: scripts/ci/desktop-linux/backend.sh start ~/backend/${{ env.BACKEND_PKG }} "$RUNNER_TEMP/backend" + - name: Point the app at the test directory + id: link + if: steps.backend.outcome == 'success' + run: | + link=$(cat "$RUNNER_TEMP/backend/directory-link") + file=apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/DirectorySearch.kt + sed -i "s|^const val DIRECTORY_SERVICE_LINK = \".*\"$|const val DIRECTORY_SERVICE_LINK = \"$link\"|" "$file" + grep -F "const val DIRECTORY_SERVICE_LINK = \"$link\"" "$file" + # the app and its tests are still built when the backend fails - name: Setup Java if: ${{ !cancelled() && steps.core.outcome == 'success' }} @@ -304,13 +313,13 @@ jobs: run: scripts/ci/desktop-linux/test-summary.py apps/multiplatform/common/build/test-results/desktopTest - name: Run smoke test - if: ${{ !cancelled() && steps.build.outcome == 'success' && steps.backend.outcome != 'failure' }} + if: ${{ !cancelled() && steps.build.outcome == 'success' && steps.backend.outcome != 'failure' && steps.link.outcome != 'failure' }} env: BACKEND: ${{ steps.backend.outcome }} run: | if [ "$BACKEND" = success ]; then export NAMES_SERVER=$(cat "$RUNNER_TEMP/backend/names-server") - cases=backend + cases=search fi scripts/ci/desktop-linux/smoke-test.sh apps/multiplatform/release/main/app/simplex "$RUNNER_TEMP/smoke-test" ${cases:-} diff --git a/scripts/ci/desktop-linux/smoke-test.sh b/scripts/ci/desktop-linux/smoke-test.sh index a3561865d9..e26539e291 100755 --- a/scripts/ci/desktop-linux/smoke-test.sh +++ b/scripts/ci/desktop-linux/smoke-test.sh @@ -2,11 +2,13 @@ # Starts the desktop app on a virtual display and runs the scripted UI cases with the ui helper: onboarding to the # chat list, a local group, then the chat list with the toolbar at the bottom (the default) and at the top. -# Usage: scripts/ci/desktop-linux/smoke-test.sh [start|onboarding|layouts|setup|backend] +# Usage: scripts/ci/desktop-linux/smoke-test.sh [start|onboarding|layouts|setup|backend|search] # With "start" it stops at the first screen, for an agent to go on from; with "onboarding", at the chat list. # "setup" creates the group, makes the test SMP server (backend.sh) the one that resolves SimpleX names, and stops; # "backend" does the same, connects to the name that backend.sh registered, and goes on to both layouts. -# Both need NAMES_SERVER, the test SMP server's address. +# "search" also searches in both layouts: the test directory with "Search in Directory", and the full search with +# Enter, which also resolves a SimpleX name; with the toolbar at the bottom, also the full search in the New chat sheet. +# These three need NAMES_SERVER, the test SMP server's address. # Each step saves a numbered screenshot and the text read from it to the output dir, prints the text to the log, # and adds a line to steps.log there. What the screens show is checked without stopping: every check is listed in # checks.txt and the job summary, and the test fails at the end if any failed. The app keeps running for later @@ -18,17 +20,21 @@ app_dir=$1 export UI_OUT=$2 cases=${3:-layouts} case "$cases" in - start | onboarding | layouts | setup | backend) ;; + start | onboarding | layouts | setup | backend | search) ;; *) - echo "error: unknown case \"$cases\": start, onboarding, layouts (the default), setup or backend" + echo "error: unknown case \"$cases\": start, onboarding, layouts (the default), setup, backend or search" exit 1 ;; esac -# backend.sh registered seeded.testing for ci_contact +search_text="ci seed" +# backend.sh registered seeded.testing for ci_contact; as a SimpleX name candidate, Enter also searches the directory, +# whose entries are "CI seeded ..." name_label=seeded local_chat="seeded notes" ui=$(dirname "$0")/ui checks=$UI_OUT/checks.txt +# the Wefunder banner, the reachable toolbars card and the connect cards, which the chat list hides while it shows online results +cards=("Invest in SimpleX Chat" "Top bar" "New 1-time link") # switches are at the right of the left pane, where Settings open switch_x=335 mkdir -p "$UI_OUT" @@ -131,6 +137,24 @@ above() { [ "$a" -lt "$b" ] } +# each text is above the next +in_order() { + local text y previous=-1 + for text in "$@"; do + y=$(y_of "$text") || return 1 + [ "$y" -gt "$previous" ] || return 1 + previous=$y + done +} + +# the label is in the row headed by the name: below the name, by less than a row's height +in_row_of() { + local label name + label=$(y_of "$1") || return 1 + name=$(y_of "$2") || return 1 + [ "$label" -ge "$name" ] && [ $((label - name)) -lt 45 ] +} + # the value is on the same line as its setting's title in_line_with() { local value title @@ -151,6 +175,187 @@ scroll_to() { return 1 } +# the count's text is smaller than the description's above it: both have capitals and ascenders, no descenders +count_text_smaller() { + local count description + count=$("$ui" ink "1 subscriber") || return 1 + description=$("$ui" ink "CI seeded channel") || return 1 + echo "NOTE ink heights: \"1 subscriber\" $count px, \"CI seeded channel\" $description px" | tee -a "$checks" + [ "$count" -lt "$description" ] +} + +# the phrases in the chat list pane, left of x 390, one per line, normalised; the right pane can show a banner too +left_pane_text() { + local line + "$ui" text | while IFS= read -r line; do + if [ "${line%%,*}" -lt 390 ]; then + normalise "${line#* }" + echo + fi + done +} + +not_in() { + ! grep -qF "$(normalise "$2")" <<< "$1" +} + +is_in() { + grep -qF "$(normalise "$2")" <<< "$1" +} + +# Records which of the cards the chat list shows while the typed text only filters it, in shown_cards. +cards_while_typing() { + local layout=$1 screen card + screen=$(left_pane_text) + shown_cards=() + for card in "${cards[@]}"; do + if is_in "$screen" "$card"; then + shown_cards+=("$card") + fi + done + echo "NOTE $layout: while typing, the chat list shows: ${shown_cards[*]:-none of the cards}" | tee -a "$checks" + check "$layout: banner or cards shown while typing" [ ${#shown_cards[@]} -gt 0 ] +} + +cards_hidden() { + local what=$1 screen card + screen=$(left_pane_text) + for card in "${shown_cards[@]}"; do + check "$what: \"$card\" hidden" not_in "$screen" "$card" + done +} + +# Escape clears the search field +clear_search_and_check_cards() { + local what=$1 screen card + "$ui" key Escape + "$ui" wait "Search or paste SimpleX link" 10 || true + "$ui" shot "$(tr -cd 'a-z-' <<< "${what// /-}")-cleared" + screen=$(left_pane_text) + for card in "${shown_cards[@]}"; do + check "$what: \"$card\" back after clearing the search" is_in "$screen" "$card" + done +} + +# Shows more results until both seeded entries are listed: their avatars make each response hold one of them. +# Sets pages and retries. +show_all_results() { + local layout=$1 missing + pages=1 + retries=0 + while :; do + "$ui" wait "Join" 60 || true + missing="" + on_screen "#ci_channel" || missing="#ci_channel" + on_screen "#ci_group" || missing="#ci_group" + "$ui" shot "$layout-page-$pages" + [ -n "$missing" ] || break + if on_screen "Search failed, tap to retry"; then + retries=$((retries + 1)) + [ "$retries" -le 2 ] || fail "$layout: the search failed $retries times" + "$ui" click-text "Search failed, tap to retry" + else + [ "$pages" -lt 5 ] || fail "$layout: $missing is not in $pages pages of results" + "$ui" click-text "Show more" 10 || fail "$layout: $missing is not in the results, and there is no Show more" + pages=$((pages + 1)) + "$ui" wait "$missing" 60 || true + fi + done + echo "NOTE $layout: the results came in $pages pages, after $retries retries" | tee -a "$checks" +} + +check_directory_rows() { + local layout=$1 + check "$layout: the first page held one result, \"Show more\" loaded the other" [ "$pages" -eq 2 ] + check "$layout: no more results offered" not_on_screen "Show more" + check "$layout: \"Directory\" header above #ci_group" above "Directory" "#ci_group" + check "$layout: \"Directory\" header above #ci_channel" above "Directory" "#ci_channel" + check "$layout: #ci_group shows its red avatar" "$ui" avatar "#ci_group" red + check "$layout: #ci_channel shows its green avatar" "$ui" avatar "#ci_channel" green + check "$layout: #ci_group row has \"CI seeded group\"" in_row_of "CI seeded group" "#ci_group" + check "$layout: #ci_channel row has \"CI seeded channel\"" in_row_of "CI seeded channel" "#ci_channel" + check "$layout: #ci_group row has \"Join group\"" in_row_of "Join group" "#ci_group" + check "$layout: #ci_channel row has \"Join channel\"" in_row_of "Join channel" "#ci_channel" + check "$layout: member count shown" on_screen "2 members" + check "$layout: subscriber count shown" on_screen "1 subscriber" +} + +# Searches the directory for the text in the search field with the "Search in Directory" row. +search_directory() { + local layout=$1 consent=$2 + "$ui" click-text "Search in Directory" + "$ui" wait "Search and don't show again" 10 + "$ui" shot "$layout-search-consent" + "$ui" click-text "$consent" + show_all_results "$layout-directory" + check_directory_rows "$layout" + check "$layout: the count's text is smaller than the description's" count_text_smaller + cards_hidden "$layout, directory results" + clear_search_and_check_cards "$layout directory search" +} + +# Types a SimpleX name and presses Enter, the desktop's Search key: the local chat that matches, then the Names part +# with the name's contact, then the Directory part, in the list's order outward from the search field. +full_search() { + local layout=$1 consent=$2 + "$ui" click-text "Search or paste SimpleX link" + "$ui" type "$name_label" + "$ui" wait "Connect to $name_label.testing" 15 + "$ui" shot "$layout-name-typed" + "$ui" key Return + if [ -n "$consent" ]; then + "$ui" wait "Search and don't show again" 10 + "$ui" click-text "$consent" + fi + "$ui" wait "ci_contact" 60 || true + show_all_results "$layout-full" + check_directory_rows "$layout full search" + check "$layout full search: \"$local_chat\" listed" on_screen "$local_chat" + check "$layout full search: \"Names\" header shown" on_screen "Names" + check "$layout full search: ci_contact found by its name" in_row_of "@$name_label.testing" "ci_contact" + check "$layout full search: ci_contact row has \"CI seeded contact\"" in_row_of "CI seeded contact" "ci_contact" + check "$layout full search: ci_contact shows its blue avatar" "$ui" avatar "ci_contact" blue + check "$layout full search: \"Connect to $name_label.testing\" gone once the name is found" not_on_screen "Connect to $name_label.testing" + check "$layout full search: \"Names\" header above ci_contact" above "Names" "ci_contact" + if [ "$layout" = top ]; then + check "$layout full search: local chat, Names, Directory, from the search field down" \ + in_order "Search in Directory" "$local_chat" "Names" "ci_contact" "Directory" "#ci_channel" + else + check "$layout full search: local chat, Names, Directory, from the search field up" \ + in_order "Directory" "#ci_channel" "Names" "ci_contact" "$local_chat" "Search in Directory" + fi + cards_hidden "$layout, full search results" + clear_search_and_check_cards "$layout full search" +} + +# The same full search from the New chat sheet, whose list is reversed too with the toolbar at the bottom. +new_chat_sheet_search() { + local consent=$1 + # the pencil at the right of the bottom toolbar opens New chat; the chat list behind it has the same search field + "$ui" click 363 730 + "$ui" wait "Create group" 10 + "$ui" click-text "Search or paste SimpleX link" + "$ui" type "$name_label" + "$ui" wait "Connect to $name_label.testing" 15 + "$ui" key Return + "$ui" wait "Search and don't show again" 10 + "$ui" click-text "$consent" + "$ui" wait "ci_contact" 60 || true + show_all_results new-chat + check "New chat: the first page held one result, \"Show more\" loaded the other" [ "$pages" -eq 2 ] + check "New chat: no more results offered" not_on_screen "Show more" + check "New chat: \"Names\" header above ci_contact" above "Names" "ci_contact" + check "New chat: \"Directory\" header above #ci_group" above "Directory" "#ci_group" + check "New chat: \"Directory\" header above #ci_channel" above "Directory" "#ci_channel" + check "New chat: Names, then Directory, from the search field up" \ + in_order "Directory" "#ci_channel" "Names" "ci_contact" "Search in Directory" + # with the toolbar at the bottom Escape only clears the sheet's search; its back arrow closes it + "$ui" key Escape + "$ui" wait "Create group" 10 + "$ui" click 27 730 + back_to_chat_list || fail "no chat list after the New chat sheet" +} + # Escape closes one screen at a time, and clears the search field back_to_chat_list() { for _ in 1 2 3 4 5 6; do @@ -354,7 +559,7 @@ if [ "$cases" = onboarding ]; then fi create_local_chat -if [ "$cases" = setup ] || [ "$cases" = backend ]; then +if [ "$cases" = setup ] || [ "$cases" = backend ] || [ "$cases" = search ]; then : "${NAMES_SERVER:?NAMES_SERVER must be the test SMP server address}" use_names_server if [ "$cases" = setup ]; then @@ -365,8 +570,31 @@ if [ "$cases" = setup ] || [ "$cases" = backend ]; then fi check_layout bottom +# typed text that is not a SimpleX link offers the directory +if [ "$cases" = search ]; then + "$ui" click-text "Search or paste SimpleX link" + "$ui" type "$search_text" + "$ui" wait "$search_text" 15 + "$ui" wait "Search in Directory" 15 + "$ui" shot bottom-search-typed + cards_while_typing bottom + search_directory bottom "Search" + full_search bottom "Search" + new_chat_sheet_search "Search" +fi use_top_toolbar check_layout top +# the alert was answered with "Search" both times, so it asks again +if [ "$cases" = search ]; then + "$ui" click-text "Search or paste SimpleX link" + "$ui" type "$search_text" + "$ui" wait "$search_text" 15 + "$ui" wait "Search in Directory" 15 + "$ui" shot top-search-typed + cards_while_typing top + search_directory top "Search and don't show again" + full_search top "" +fi if grep -q '^FAIL' "$checks"; then fail "the smoke test failed checks: $(grep -c '^FAIL' "$checks") of $(grep -cE '^(PASS|FAIL)' "$checks")"