diff --git a/.github/workflows/ui-automated-tests.yml b/.github/workflows/ui-automated-tests.yml index 41f78292a0..53bab6e1a7 100644 --- a/.github/workflows/ui-automated-tests.yml +++ b/.github/workflows/ui-automated-tests.yml @@ -1,4 +1,4 @@ -name: UI Tests on Windows and MacOS ๐Ÿงช +name: UI Tests on MacOS ๐Ÿงช on: schedule: @@ -71,64 +71,6 @@ jobs: Failed Automated Test type: add - build-windows: - runs-on: - labels: windows-latest - - steps: - - name: Checkout testing directory ๐Ÿ”– - uses: actions/checkout@v3 - with: - repository: Satellite-im/Uplink - - - name: Install Rust ๐Ÿ’ฟ - uses: actions-rs/toolchain@v1 - with: - toolchain: 1.73.0 - override: true - components: rustfmt, clippy - - - name: Build executable ๐Ÿ–ฅ๏ธ - run: cargo build --release -F production_mode - continue-on-error: true - - - name: Create ZIP archive on Windows ๐Ÿ—ณ๏ธ - run: Compress-Archive -Path target/release/uplink.exe -Destination uplinkWindows.zip - - - name: Copy Extensions ๐Ÿ—ณ๏ธ - run: | - mkdir ./ui/extra/extensions - cp -r ./target/release/emoji_selector.d ./ui/extra/extensions/ - cp -r ./target/release/emoji_selector.dll ./ui/extra/extensions/ - cp -r ./target/release/emoji_selector.dll.exp ./ui/extra/extensions/ - cp -r ./target/release/emoji_selector.dll.lib ./ui/extra/extensions/ - cp -r ./target/release/emoji_selector.pdb ./ui/extra/extensions/ - - - name: Upload Executable โฌ†๏ธ - uses: actions/upload-artifact@v3 - with: - name: Uplink-windows-latest - path: uplinkWindows.zip - - - name: Upload Windows Assets - uses: actions/upload-artifact@v3 - with: - name: uplink-windows-assets - path: | - ui/extra/images/ - ui/extra/prism_langs/ - ui/extra/themes/ - ui/extra/extensions/ - - - name: Add label if any of build jobs failed - if: failure() - uses: buildsville/add-remove-label@v2.0.0 - with: - token: ${{ secrets.GITHUB_TOKEN }} - labels: | - Failed Automated Test - type: add - test-mac: needs: build-mac runs-on: macos-13 @@ -223,124 +165,22 @@ jobs: name: appium-log-macos path: ./appium.log - - name: Add label if any of test jobs failed - if: failure() - uses: buildsville/add-remove-label@v2.0.0 - with: - token: ${{ secrets.GITHUB_TOKEN }} - labels: | - Failed Automated Test - type: add - - test-windows-chats: - needs: build-windows - runs-on: windows-latest - - steps: - - name: Checkout testing directory ๐Ÿ”– - uses: actions/checkout@v3 - - - name: Change resolution on Windows Runner - run: Set-DisplayResolution -Width 1920 -Height 1080 -Force - shell: powershell - - - name: Download the Windows app ๐Ÿ—ณ๏ธ - uses: actions/download-artifact@v3 - with: - name: Uplink-windows-latest - path: ./apps - - - name: Extract .zip into apps Directory ๐Ÿ—ณ๏ธ - run: Expand-Archive -Path ./apps/uplinkWindows.zip -DestinationPath ./apps - - - name: Download the Windows app assets - uses: actions/download-artifact@v3 - with: - name: uplink-windows-assets - path: ./apps - - - name: Copy app to have two instances ๐Ÿ’ฟ - working-directory: ./apps - run: | - cp -r ./uplink.exe ./uplink2.exe - - - name: Move Windows assets to correct locations ๐Ÿ’ฟ - working-directory: ./apps - run: | - mkdir ./bin/extra - mkdir ./extra - mv ./uplink.exe ./bin/ - mv ./uplink2.exe ./bin/ - mv ./images/ ./bin/extra/ - mv ./prism_langs/ ./bin/extra/ - mv ./themes/ ./extra/ - - - name: Setup Node.js ๐Ÿ”จ - uses: actions/setup-node@v3 - with: - node-version: 18 - cache: "npm" - - - name: Cache NPM dependencies ๐Ÿ”จ - uses: actions/cache@v3 - id: cache-windows-chats - with: - path: node_modules - key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }} - - - name: Install NPM dependencies ๐Ÿ“ฆ - if: steps.cache-windows-chats.outputs.cache-hit != 'true' - run: npm ci - - - name: Install Appium Server ๐Ÿ’ป - run: | - npm install -g appium@next - appium -v - - - name: Install Appium Driver ๐Ÿ’ป - run: | - appium driver install --source=npm appium-windows-driver - appium driver list - - - name: Setup FFMPEG to record screen - uses: FedericoCarboni/setup-ffmpeg@v2 - id: setup-ffmpeg - - - name: Delete Cache Folder if exists - Windows - run: If (Test-Path $home/.uplink/.user) {Remove-Item -Recurse -Force $home/.uplink/.user} Else { Break } - shell: powershell + - name: Run Tests on to Create First Account ๐Ÿงช + run: npm run mac.createAccountA - - name: Run Chat Tests on Windows ๐Ÿงช - run: npm run windows.multiremote + - name: Run Tests on to Create Second Account ๐Ÿงช + run: npm run mac.createAccountB - - name: Upload Test Report - Windows Chats - if: always() + - name: Upload test accounts for Chat Users uses: actions/upload-artifact@v3 - with: - name: test-report-windows-chats - path: ./test-report/*.xml - - - name: Upload Allure Test Results if: always() - uses: actions/upload-artifact@v3 - with: - name: test-allure-windows-chats - path: ./allure-results/ - - - name: Upload Screenshots for Windows - Chats ๐Ÿ“ท - uses: actions/upload-artifact@v3 - if: failure() - with: - name: appium-screenshots-windows-chats - path: ./test-results - - - name: Upload Appium Log for Windows - Chats ๐Ÿ“ท - uses: actions/upload-artifact@v3 - if: failure() with: - name: appium-log-windows-chats + name: appium-test-accounts path: | - ./appium.log + ./tests/fixtures/users/mac2/ChatUserA/ + ./tests/fixtures/users/mac2/ChatUserB/ + ./tests/fixtures/users/mac2/ChatUserA.json + ./tests/fixtures/users/mac2/ChatUserB.json - name: Add label if any of test jobs failed if: failure() @@ -351,42 +191,45 @@ jobs: Failed Automated Test type: add - test-windows: - needs: build-windows - runs-on: windows-latest + test-mac-chats: + strategy: + fail-fast: false + max-parallel: 2 + matrix: + job: ["chatA", "chatB"] + include: + - job: "chatA" + username: "ChatUserA" + - job: "chatB" + username: "ChatUserB" + needs: test-mac + runs-on: macos-13 steps: - name: Checkout testing directory ๐Ÿ”– uses: actions/checkout@v3 - - name: Change resolution on Windows Runner - run: Set-DisplayResolution -Width 1920 -Height 1080 -Force - shell: powershell - - - name: Download the Windows app ๐Ÿ—ณ๏ธ + - name: Download the MacOS app ๐Ÿ—ณ๏ธ uses: actions/download-artifact@v3 with: - name: Uplink-windows-latest + name: Uplink-macos-latest path: ./apps - - name: Extract .zip into apps Directory ๐Ÿ—ณ๏ธ - run: Expand-Archive -Path ./apps/uplinkWindows.zip -DestinationPath ./apps - - - name: Download the Windows app assets + - name: Download Test User Accounts ๐Ÿ—ณ๏ธ uses: actions/download-artifact@v3 with: - name: uplink-windows-assets - path: ./apps + name: appium-test-accounts + path: ./tests/fixtures/users/mac2 - - name: Move Windows assets to correct locations ๐Ÿ’ฟ + - name: Enable opening app not codesigned ๐Ÿ–ฅ๏ธ + run: sudo spctl --master-disable + + - name: Copy DMG to Appium Apps Directory ๐Ÿ’ฟ working-directory: ./apps run: | - mkdir ./bin/extra - mkdir ./extra - mv ./uplink.exe ./bin/ - mv ./images/ ./bin/extra/ - mv ./prism_langs/ ./bin/extra/ - mv ./themes/ ./extra/ + unzip Uplink-Mac-Universal.zip + cp -r ./Uplink.app /Applications/ + sudo xattr -r -d com.apple.quarantine /Applications/Uplink.app - name: Setup Node.js ๐Ÿ”จ uses: actions/setup-node@v3 @@ -396,63 +239,66 @@ jobs: - name: Cache NPM dependencies ๐Ÿ”จ uses: actions/cache@v3 - id: cache-windows + id: cache-mac with: path: node_modules key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }} - name: Install NPM dependencies ๐Ÿ“ฆ - if: steps.cache-windows.outputs.cache-hit != 'true' + if: steps.cache-mac.outputs.cache-hit != 'true' run: npm ci - - name: Install and Run Appium Server ๐Ÿ’ป + - name: Install Appium Server ๐Ÿ’ป run: | npm install -g appium@next appium -v - name: Install Appium Driver ๐Ÿ’ป run: | - appium driver install --source=npm appium-windows-driver + appium driver install mac2 appium driver list - - name: Setup FFMPEG to record screen - uses: FedericoCarboni/setup-ffmpeg@v2 - id: setup-ffmpeg + - name: Update MacOS runner to not autocorrect text + run: | + defaults write -g NSAutomaticCapitalizationEnabled -bool false + defaults write -g NSAutomaticPeriodSubstitutionEnabled -bool false + defaults write -g NSAutomaticSpellingCorrectionEnabled -bool false - - name: Delete Cache Folder if exists - Windows - run: If (Test-Path $home/.uplink/.user) {Remove-Item -Recurse -Force $home/.uplink/.user} Else { Break } - shell: powershell + - if: ${{ matrix.username }} + name: Delete Cache Folder and copy reusable data for ${{ matrix.username }} + run: | + rm -rf ~/.uplink + cp -r ./tests/fixtures/users/mac2/${{ matrix.username }}/ ~/.uplink - - name: Run Tests on Windows ๐Ÿงช - id: test-execution-windows - run: npm run windows.ci + - name: Run Tests on MacOS ๐Ÿงช + run: npm run mac.${{ matrix.job }} - - name: Upload Test Report - Windows CI + - name: Upload Test Report - MacOS CI if: always() uses: actions/upload-artifact@v3 with: - name: test-report-windows-ci + name: test-report-macos-${{ matrix.job }} path: ./test-report/*.xml - name: Upload Allure Test Results if: always() uses: actions/upload-artifact@v3 with: - name: test-allure-windows-ci + name: test-allure-mac-${{ matrix.job }} path: ./allure-results/ - - name: Upload Screenshots for Windows ๐Ÿ“ท + - name: Upload Screenshots for MacOS ๐Ÿ“ท uses: actions/upload-artifact@v3 if: failure() with: - name: appium-screenshots-windows + name: appium-screenshots-macos-${{ matrix.job }} path: ./test-results - - name: Upload Appium Log for Windows ๐Ÿ“ท + - name: Upload Appium Log for MacOS ๐Ÿ“ท uses: actions/upload-artifact@v3 if: failure() with: - name: appium-log-windows + name: appium-log-macos-${{ matrix.job }} path: ./appium.log - name: Add label if any of test jobs failed @@ -464,108 +310,8 @@ jobs: Failed Automated Test type: add - publish-test-results: - if: always() - needs: - [build-mac, build-windows, test-mac, test-windows-chats, test-windows] - runs-on: ubuntu-latest - permissions: - checks: write - pull-requests: write - contents: write - issues: read - - steps: - - name: Download Test Report for MacOS CI - uses: actions/download-artifact@v3 - with: - name: test-report-macos-ci - path: artifacts - - - name: Download Test Report for Windows Chats - uses: actions/download-artifact@v3 - with: - name: test-report-windows-chats - path: artifacts - - - name: Download Test Report for Windows CI - uses: actions/download-artifact@v3 - with: - name: test-report-windows-ci - path: artifacts - - - name: Download Allure Results for MacOS CI - uses: actions/download-artifact@v3 - with: - name: test-allure-mac-ci - path: allure - - - name: Download Allure Results for Windows CI - uses: actions/download-artifact@v3 - with: - name: test-allure-windows-ci - path: allure - - - name: Download Allure Results for Windows Chats - uses: actions/download-artifact@v3 - with: - name: test-allure-windows-chats - path: allure - - - name: Publish Test Results for Tests - uses: EnricoMi/publish-unit-test-result-action/composite@v2 - if: success() - with: - junit_files: "artifacts/**/*.xml" - ignore_runs: true - job_summary: false - compare_to_earlier_commit: false - check_name: "UI Automated Test Results Summary for MacOS/Windows" - - - name: Get Allure history - uses: actions/checkout@v3 - if: success() - continue-on-error: true - with: - ref: gh-pages - path: gh-pages - - - name: Allure Report action from marketplace - uses: simple-elf/allure-report-action@master - if: success() - id: allure-report - with: - gh_pages: gh-pages - allure_results: allure - allure_report: allure-report - allure_history: allure-history - keep_reports: 20 - - - name: Deploy report to Github Pages - if: success() - uses: peaceiris/actions-gh-pages@v3 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_branch: gh-pages - publish_dir: allure-history - - - name: Comment PR with the Test Results - if: success() - uses: mshick/add-pr-comment@v2 - with: - message: | - UI Automated Tests execution is complete! You can find the test results report [here](https://satellite-im.github.io/testing-uplink/${{ github.run_number }}) - remove-artifacts: - needs: - [ - build-mac, - build-windows, - test-mac, - test-windows-chats, - test-windows, - publish-test-results, - ] + needs: [build-mac, test-mac, test-mac-chats] runs-on: ubuntu-latest steps: @@ -584,12 +330,11 @@ jobs: uses: geekyeggo/delete-artifact@v2 with: name: | - Uplink-windows-latest - uplink-windows-assets Uplink-macos-latest test-report-macos-ci - test-report-windows-ci - test-report-windows-chats + test-report-macos-chatA + test-report-macos-chatB test-allure-mac-ci - test-allure-windows-ci - test-allure-windows-chats + test-allure-mac-chatA + test-allure-mac-chatB + appium-test-accounts diff --git a/.github/workflows/ui-automated-windows.yml b/.github/workflows/ui-automated-windows.yml new file mode 100644 index 0000000000..d5c489ec4b --- /dev/null +++ b/.github/workflows/ui-automated-windows.yml @@ -0,0 +1,451 @@ +name: UI Tests on Windows ๐Ÿงช + +on: + schedule: + - cron: "0 0/6 * * 1-5" + pull_request: + types: [opened, synchronize, reopened, edited] + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + CARGO_TERM_COLOR: always + +jobs: + build-windows: + runs-on: + labels: windows-latest + + steps: + - name: Checkout testing directory ๐Ÿ”– + uses: actions/checkout@v3 + with: + repository: Satellite-im/Uplink + + - name: Install Rust ๐Ÿ’ฟ + uses: actions-rs/toolchain@v1 + with: + toolchain: 1.73.0 + override: true + components: rustfmt, clippy + + - name: Build executable ๐Ÿ–ฅ๏ธ + run: cargo build --release -F production_mode + continue-on-error: true + + - name: Create ZIP archive on Windows ๐Ÿ—ณ๏ธ + run: Compress-Archive -Path target/release/uplink.exe -Destination uplinkWindows.zip + + - name: Copy Extensions ๐Ÿ—ณ๏ธ + run: | + mkdir ./ui/extra/extensions + cp -r ./target/release/emoji_selector.d ./ui/extra/extensions/ + cp -r ./target/release/emoji_selector.dll ./ui/extra/extensions/ + cp -r ./target/release/emoji_selector.dll.exp ./ui/extra/extensions/ + cp -r ./target/release/emoji_selector.dll.lib ./ui/extra/extensions/ + cp -r ./target/release/emoji_selector.pdb ./ui/extra/extensions/ + + - name: Upload Executable โฌ†๏ธ + uses: actions/upload-artifact@v3 + with: + name: Uplink-windows-latest + path: uplinkWindows.zip + + - name: Upload Windows Assets + uses: actions/upload-artifact@v3 + with: + name: uplink-windows-assets + path: | + ui/extra/images/ + ui/extra/prism_langs/ + ui/extra/themes/ + ui/extra/extensions/ + + - name: Add label if any of build jobs failed + if: failure() + uses: buildsville/add-remove-label@v2.0.0 + with: + token: ${{ secrets.GITHUB_TOKEN }} + labels: | + Failed Automated Test + type: add + + test-windows-chats: + needs: build-windows + runs-on: windows-latest + + steps: + - name: Checkout testing directory ๐Ÿ”– + uses: actions/checkout@v3 + + - name: Change resolution on Windows Runner + run: Set-DisplayResolution -Width 1920 -Height 1080 -Force + shell: powershell + + - name: Download the Windows app ๐Ÿ—ณ๏ธ + uses: actions/download-artifact@v3 + with: + name: Uplink-windows-latest + path: ./apps + + - name: Extract .zip into apps Directory ๐Ÿ—ณ๏ธ + run: Expand-Archive -Path ./apps/uplinkWindows.zip -DestinationPath ./apps + + - name: Download the Windows app assets + uses: actions/download-artifact@v3 + with: + name: uplink-windows-assets + path: ./apps + + - name: Copy app to have two instances ๐Ÿ’ฟ + working-directory: ./apps + run: | + cp -r ./uplink.exe ./uplink2.exe + + - name: Move Windows assets to correct locations ๐Ÿ’ฟ + working-directory: ./apps + run: | + mkdir ./bin/extra + mkdir ./extra + mv ./uplink.exe ./bin/ + mv ./uplink2.exe ./bin/ + mv ./images/ ./bin/extra/ + mv ./prism_langs/ ./bin/extra/ + mv ./themes/ ./extra/ + + - name: Setup Node.js ๐Ÿ”จ + uses: actions/setup-node@v3 + with: + node-version: 18 + cache: "npm" + + - name: Cache NPM dependencies ๐Ÿ”จ + uses: actions/cache@v3 + id: cache-windows-chats + with: + path: node_modules + key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }} + + - name: Install NPM dependencies ๐Ÿ“ฆ + if: steps.cache-windows-chats.outputs.cache-hit != 'true' + run: npm ci + + - name: Install Appium Server ๐Ÿ’ป + run: | + npm install -g appium@next + appium -v + + - name: Install Appium Driver ๐Ÿ’ป + run: | + appium driver install --source=npm appium-windows-driver + appium driver list + + - name: Setup FFMPEG to record screen + uses: FedericoCarboni/setup-ffmpeg@v2 + id: setup-ffmpeg + + - name: Delete Cache Folder if exists - Windows + run: If (Test-Path $home/.uplink/.user) {Remove-Item -Recurse -Force $home/.uplink/.user} Else { Break } + shell: powershell + + - name: Run Chat Tests on Windows ๐Ÿงช + run: npm run windows.multiremote + + - name: Upload Test Report - Windows Chats + if: always() + uses: actions/upload-artifact@v3 + with: + name: test-report-windows-chats + path: ./test-report/*.xml + + - name: Upload Allure Test Results + if: always() + uses: actions/upload-artifact@v3 + with: + name: test-allure-windows-chats + path: ./allure-results/ + + - name: Upload Screenshots for Windows - Chats ๐Ÿ“ท + uses: actions/upload-artifact@v3 + if: failure() + with: + name: appium-screenshots-windows-chats + path: ./test-results + + - name: Upload Appium Log for Windows - Chats ๐Ÿ“ท + uses: actions/upload-artifact@v3 + if: failure() + with: + name: appium-log-windows-chats + path: | + ./appium.log + + - name: Add label if any of test jobs failed + if: failure() + uses: buildsville/add-remove-label@v2.0.0 + with: + token: ${{ secrets.GITHUB_TOKEN }} + labels: | + Failed Automated Test + type: add + + test-windows: + needs: build-windows + runs-on: windows-latest + + steps: + - name: Checkout testing directory ๐Ÿ”– + uses: actions/checkout@v3 + + - name: Change resolution on Windows Runner + run: Set-DisplayResolution -Width 1920 -Height 1080 -Force + shell: powershell + + - name: Download the Windows app ๐Ÿ—ณ๏ธ + uses: actions/download-artifact@v3 + with: + name: Uplink-windows-latest + path: ./apps + + - name: Extract .zip into apps Directory ๐Ÿ—ณ๏ธ + run: Expand-Archive -Path ./apps/uplinkWindows.zip -DestinationPath ./apps + + - name: Download the Windows app assets + uses: actions/download-artifact@v3 + with: + name: uplink-windows-assets + path: ./apps + + - name: Move Windows assets to correct locations ๐Ÿ’ฟ + working-directory: ./apps + run: | + mkdir ./bin/extra + mkdir ./extra + mv ./uplink.exe ./bin/ + mv ./images/ ./bin/extra/ + mv ./prism_langs/ ./bin/extra/ + mv ./themes/ ./extra/ + + - name: Setup Node.js ๐Ÿ”จ + uses: actions/setup-node@v3 + with: + node-version: 18 + cache: "npm" + + - name: Cache NPM dependencies ๐Ÿ”จ + uses: actions/cache@v3 + id: cache-windows + with: + path: node_modules + key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }} + + - name: Install NPM dependencies ๐Ÿ“ฆ + if: steps.cache-windows.outputs.cache-hit != 'true' + run: npm ci + + - name: Install and Run Appium Server ๐Ÿ’ป + run: | + npm install -g appium@next + appium -v + + - name: Install Appium Driver ๐Ÿ’ป + run: | + appium driver install --source=npm appium-windows-driver + appium driver list + + - name: Setup FFMPEG to record screen + uses: FedericoCarboni/setup-ffmpeg@v2 + id: setup-ffmpeg + + - name: Delete Cache Folder if exists - Windows + run: If (Test-Path $home/.uplink/.user) {Remove-Item -Recurse -Force $home/.uplink/.user} Else { Break } + shell: powershell + + - name: Run Tests on Windows ๐Ÿงช + id: test-execution-windows + run: npm run windows.ci + + - name: Upload Test Report - Windows CI + if: always() + uses: actions/upload-artifact@v3 + with: + name: test-report-windows-ci + path: ./test-report/*.xml + + - name: Upload Allure Test Results + if: always() + uses: actions/upload-artifact@v3 + with: + name: test-allure-windows-ci + path: ./allure-results/ + + - name: Upload Screenshots for Windows ๐Ÿ“ท + uses: actions/upload-artifact@v3 + if: failure() + with: + name: appium-screenshots-windows + path: ./test-results + + - name: Upload Appium Log for Windows ๐Ÿ“ท + uses: actions/upload-artifact@v3 + if: failure() + with: + name: appium-log-windows + path: ./appium.log + + - name: Add label if any of test jobs failed + if: failure() + uses: buildsville/add-remove-label@v2.0.0 + with: + token: ${{ secrets.GITHUB_TOKEN }} + labels: | + Failed Automated Test + type: add + + publish-test-results: + if: always() + needs: + #[build-mac, build-windows, test-mac, test-mac-chats, test-windows-chats, test-windows] + [build-windows, test-windows-chats, test-windows] + runs-on: ubuntu-latest + permissions: + checks: write + pull-requests: write + contents: write + issues: read + + steps: + #- name: Download Test Report for MacOS CI + # uses: actions/download-artifact@v3 + # with: + # name: test-report-macos-ci + # path: artifacts + + #- name: Download Test Report for MacOS Chat A + # uses: actions/download-artifact@v3 + # with: + # name: test-report-macos-chatA + # path: artifacts + + #- name: Download Test Report for MacOS Chat B + # uses: actions/download-artifact@v3 + # with: + # name: test-report-macos-chatB + # path: artifacts + + - name: Download Test Report for Windows Chats + uses: actions/download-artifact@v3 + with: + name: test-report-windows-chats + path: artifacts + + - name: Download Test Report for Windows CI + uses: actions/download-artifact@v3 + with: + name: test-report-windows-ci + path: artifacts + + #- name: Download Allure Results for MacOS CI + # uses: actions/download-artifact@v3 + # with: + # name: test-allure-mac-ci + # path: allure + + #- name: Download Allure Results for MacOS Chat A + # uses: actions/download-artifact@v3 + # with: + # name: test-allure-mac-chatA + # path: allure + + #- name: Download Allure Results for MacOS Chat B + # uses: actions/download-artifact@v3 + # with: + # name: test-allure-mac-chatB + # path: allure + + - name: Download Allure Results for Windows CI + uses: actions/download-artifact@v3 + with: + name: test-allure-windows-ci + path: allure + + - name: Download Allure Results for Windows Chats + uses: actions/download-artifact@v3 + with: + name: test-allure-windows-chats + path: allure + + - name: Publish Test Results for Tests + uses: EnricoMi/publish-unit-test-result-action/composite@v2 + if: success() + with: + junit_files: "artifacts/**/*.xml" + ignore_runs: true + job_summary: false + compare_to_earlier_commit: false + check_name: "UI Automated Test Results Summary for MacOS/Windows" + + - name: Get Allure history + uses: actions/checkout@v3 + if: success() + continue-on-error: true + with: + ref: gh-pages + path: gh-pages + + - name: Allure Report action from marketplace + uses: simple-elf/allure-report-action@master + if: success() + id: allure-report + with: + gh_pages: gh-pages + allure_results: allure + allure_report: allure-report + allure_history: allure-history + keep_reports: 20 + + - name: Deploy report to Github Pages + if: success() + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_branch: gh-pages + publish_dir: allure-history + + - name: Comment PR with the Test Results + if: success() + uses: mshick/add-pr-comment@v2 + with: + message: | + UI Automated Tests execution is complete! You can find the test results report [here](https://satellite-im.github.io/testing-uplink/${{ github.run_number }}) + + remove-artifacts: + needs: + [build-windows, test-windows-chats, test-windows, publish-test-results] + runs-on: ubuntu-latest + + steps: + - name: Checkout testing directory ๐Ÿ”– + uses: actions/checkout@v3 + + - name: Remove label if all test jobs succeeded + uses: buildsville/add-remove-label@v2.0.0 + with: + token: ${{ secrets.GITHUB_TOKEN }} + labels: | + Failed Automated Test + type: remove + + - name: Delete artifacts + uses: geekyeggo/delete-artifact@v2 + with: + name: | + Uplink-windows-latest + test-report-windows-chats + test-report-windows-ci + test-allure-windows-chats + test-allure-windows-ci diff --git a/config/macos-chats/wdio.mac.chatA.conf.ts b/config/macos-chats/wdio.mac.chatA.conf.ts new file mode 100644 index 0000000000..46654d33e6 --- /dev/null +++ b/config/macos-chats/wdio.mac.chatA.conf.ts @@ -0,0 +1,143 @@ +import "module-alias/register"; +import allureReporter from '@wdio/allure-reporter' +import { config as sharedConfig } from '@config/wdio.shared.conf'; +import { join } from "path"; +import { MACOS_BUNDLE_ID, MACOS_DRIVER } from "@helpers/constants"; +const fsp = require("fs").promises; +const { readFileSync, rmSync } = require("fs"); + +// @ts-expect-error +export const config: WebdriverIO.Config = { + ...sharedConfig, + ...{ + // + // ================== + // Specify Test Files + // ================== + // Define which test specs should run. The pattern is relative to the directory + // from which `wdio` was called. + // + // The specs are defined as an array of spec files (optionally using wildcards + // that will be expanded). The test for each spec file will be run in a separate + // worker process. In order to have a group of spec files run in the same worker + // process simply enclose them in an array within the specs array. + // + // If you are calling `wdio` from an NPM script (see https://docs.npmjs.com/cli/run-script), + // then the current working directory is where your `package.json` resides, so `wdio` + // will be called from there. + // + specs: [join(process.cwd(), "./tests/suites/Chats/02-ChatsUserA.suite.ts")], + // Patterns to exclude. + exclude: [ + // 'path/to/excluded/files' + ], + specFileRetries: 0, + // Options to be passed to Mocha. + mochaOpts: { + ui: "bdd", + /** + * NOTE: This has been increased for more stable Appium Native app + * tests because they can take a bit longer. + */ + timeout: 300000, // 5min + bail: true, + }, + // + // ============ + // Capabilities + // ============ + // Define your capabilities here. WebdriverIO can run multiple capabilities at the same + // time. Depending on the number of capabilities, WebdriverIO launches several test + // sessions. Within your capabilities you can overwrite the spec and exclude options in + // order to group specific specs to a specific capability. + // + // + // If you have trouble getting all important capabilities together, check out the + // Sauce Labs platform configurator - a great tool to configure your capabilities: + // https://docs.saucelabs.com/reference/platforms-configurator + // + port: 4723, + path: '/', + capabilities: { + userA: { + capabilities: { + platformName: "mac", + "appium:automationName": MACOS_DRIVER, + "appium:bundleId": MACOS_BUNDLE_ID, + "appium:systemPort": 4724, + } + }, + } + , + // + // =================== + // Test Configurations + // =================== + // Define all options that are relevant for the WebdriverIO instance here + // + reporters: [ + ["spec", + { + showPreface: false, + }, + ], + ['allure', + { + outputDir: './allure-results', + disableWebdriverStepsReporting: true, + disableWebdriverScreenshotsReporting: false, + } + ], + ['junit', + { + outputDir: './test-report/', + outputFileFormat: function (options) { + return `test-results-macos-chatA-${options.cid}.xml`; + } + } + ], + ], + // + // ===== + // Hooks + // ===== + // WebdriverIO provides several hooks you can use to interfere with the test process in order to enhance + // it and to build services around it. You can either apply a single function or an array of + // methods to it. If one of them returns with a promise, WebdriverIO will wait until that promise got + // resolved to continue. + onPrepare: async function() { + const allureResultsFolder = join(process.cwd(), "./allure-results"); + const testReportFolder = join(process.cwd(), "./test-report"); + const testResultsFolder = join(process.cwd(), "./test-results"); + try { + await rmSync(allureResultsFolder, { recursive: true, force: true }); + await rmSync(testReportFolder, { recursive: true, force: true }); + await rmSync(testResultsFolder, { recursive: true, force: true }); + console.log("Deleted Artifacts Folders Successfully!"); + } catch (error) { + console.error( + `Got an error trying to delete artifacts folders: ${error.message}` + ); + } + }, + + afterTest: async function (test, describe, { error }) { + if (error) { + let imageFile = await driver.takeScreenshot(); + const imageFolder = join(process.cwd(), "./test-results/macos-chatA", test.parent); + const imageTitle = test.title + " - Failed.png" + await fsp.mkdir(imageFolder, {recursive: true}); + await fsp.writeFile( + imageFolder + "/" + imageTitle, + imageFile, + "base64" + ); + + // Add to Screenshot to Allure Reporter + const data = await readFileSync(`${imageFolder}/${imageTitle}`); + allureReporter.addAttachment(imageTitle, data, 'image/png') + } + }, + } + +} \ No newline at end of file diff --git a/config/macos-chats/wdio.mac.chatB.conf.ts b/config/macos-chats/wdio.mac.chatB.conf.ts new file mode 100644 index 0000000000..a4c628fbc4 --- /dev/null +++ b/config/macos-chats/wdio.mac.chatB.conf.ts @@ -0,0 +1,144 @@ +import "module-alias/register"; +import allureReporter from '@wdio/allure-reporter' +import { config as sharedConfig } from '@config/wdio.shared.conf'; +import { homedir } from "os"; +import { join } from "path"; +import { MACOS_BUNDLE_ID, MACOS_DRIVER } from "@helpers/constants"; +const fsp = require("fs").promises; +const { readFileSync, rmSync } = require("fs"); + +// @ts-expect-error +export const config: WebdriverIO.Config = { + ...sharedConfig, + ...{ + // + // ================== + // Specify Test Files + // ================== + // Define which test specs should run. The pattern is relative to the directory + // from which `wdio` was called. + // + // The specs are defined as an array of spec files (optionally using wildcards + // that will be expanded). The test for each spec file will be run in a separate + // worker process. In order to have a group of spec files run in the same worker + // process simply enclose them in an array within the specs array. + // + // If you are calling `wdio` from an NPM script (see https://docs.npmjs.com/cli/run-script), + // then the current working directory is where your `package.json` resides, so `wdio` + // will be called from there. + // + specs: [join(process.cwd(), "./tests/suites/Chats/03-ChatsUserB.suite.ts")], + // Patterns to exclude. + exclude: [ + // 'path/to/excluded/files' + ], + specFileRetries: 0, + // Options to be passed to Mocha. + mochaOpts: { + ui: "bdd", + /** + * NOTE: This has been increased for more stable Appium Native app + * tests because they can take a bit longer. + */ + timeout: 300000, // 5min + bail: true, + }, + // + // ============ + // Capabilities + // ============ + // Define your capabilities here. WebdriverIO can run multiple capabilities at the same + // time. Depending on the number of capabilities, WebdriverIO launches several test + // sessions. Within your capabilities you can overwrite the spec and exclude options in + // order to group specific specs to a specific capability. + // + // + // If you have trouble getting all important capabilities together, check out the + // Sauce Labs platform configurator - a great tool to configure your capabilities: + // https://docs.saucelabs.com/reference/platforms-configurator + // + port: 4723, + path: '/', + capabilities: { + userA: { + capabilities: { + platformName: "mac", + "appium:automationName": MACOS_DRIVER, + "appium:bundleId": MACOS_BUNDLE_ID, + "appium:systemPort": 4724, + } + }, + } + , + // + // =================== + // Test Configurations + // =================== + // Define all options that are relevant for the WebdriverIO instance here + // + reporters: [ + ["spec", + { + showPreface: false, + }, + ], + ['allure', + { + outputDir: './allure-results', + disableWebdriverStepsReporting: true, + disableWebdriverScreenshotsReporting: false, + } + ], + ['junit', + { + outputDir: './test-report/', + outputFileFormat: function (options) { + return `test-results-macos-chatB-${options.cid}.xml`; + } + } + ], + ], + // + // ===== + // Hooks + // ===== + // WebdriverIO provides several hooks you can use to interfere with the test process in order to enhance + // it and to build services around it. You can either apply a single function or an array of + // methods to it. If one of them returns with a promise, WebdriverIO will wait until that promise got + // resolved to continue. + onPrepare: async function() { + const allureResultsFolder = join(process.cwd(), "./allure-results"); + const testReportFolder = join(process.cwd(), "./test-report"); + const testResultsFolder = join(process.cwd(), "./test-results"); + try { + await rmSync(allureResultsFolder, { recursive: true, force: true }); + await rmSync(testReportFolder, { recursive: true, force: true }); + await rmSync(testResultsFolder, { recursive: true, force: true }); + console.log("Deleted Artifacts Folders Successfully!"); + } catch (error) { + console.error( + `Got an error trying to delete artifacts folders: ${error.message}` + ); + } + }, + + afterTest: async function (test, describe, { error }) { + if (error) { + let imageFile = await driver.takeScreenshot(); + const imageFolder = join(process.cwd(), "./test-results/macos-chatB", test.parent); + const imageTitle = test.title + " - Failed.png" + await fsp.mkdir(imageFolder, {recursive: true}); + await fsp.writeFile( + imageFolder + "/" + imageTitle, + imageFile, + "base64" + ); + + // Add to Screenshot to Allure Reporter + const data = await readFileSync(`${imageFolder}/${imageTitle}`); + allureReporter.addAttachment(imageTitle, data, 'image/png') + } + }, + } + +} \ No newline at end of file diff --git a/config/macos-chats/wdio.mac.createAccountA.conf.ts b/config/macos-chats/wdio.mac.createAccountA.conf.ts new file mode 100644 index 0000000000..368ff02c6a --- /dev/null +++ b/config/macos-chats/wdio.mac.createAccountA.conf.ts @@ -0,0 +1,149 @@ +import "module-alias/register"; +import allureReporter from '@wdio/allure-reporter' +import { config as sharedConfig } from '@config/wdio.shared.conf'; +import { homedir } from "os"; +import { join } from "path"; +import { MACOS_BUNDLE_ID, MACOS_DRIVER } from "@helpers/constants"; +const fsp = require("fs").promises; +const { readFileSync, rmSync } = require("fs"); + +// @ts-expect-error +export const config: WebdriverIO.Config = { + ...sharedConfig, + ...{ + // + // ================== + // Specify Test Files + // ================== + // Define which test specs should run. The pattern is relative to the directory + // from which `wdio` was called. + // + // The specs are defined as an array of spec files (optionally using wildcards + // that will be expanded). The test for each spec file will be run in a separate + // worker process. In order to have a group of spec files run in the same worker + // process simply enclose them in an array within the specs array. + // + // If you are calling `wdio` from an NPM script (see https://docs.npmjs.com/cli/run-script), + // then the current working directory is where your `package.json` resides, so `wdio` + // will be called from there. + // + maxInstances: 1, + specs: [ + join(process.cwd(), "./tests/suites/MainTests/03-CreateAccountA.suite.ts") + ], + // Patterns to exclude. + exclude: [ + // 'path/to/excluded/files' + ], + // + // ============ + // Capabilities + // ============ + // Define your capabilities here. WebdriverIO can run multiple capabilities at the same + // time. Depending on the number of capabilities, WebdriverIO launches several test + // sessions. Within your capabilities you can overwrite the spec and exclude options in + // order to group specific specs to a specific capability. + // + // + // If you have trouble getting all important capabilities together, check out the + // Sauce Labs platform configurator - a great tool to configure your capabilities: + // https://docs.saucelabs.com/reference/platforms-configurator + // + port: 4723, + path: '/', + capabilities: { + userA: { + capabilities: { + platformName: "mac", + "appium:automationName": MACOS_DRIVER, + "appium:bundleId": MACOS_BUNDLE_ID, + "appium:arguments": ["--path", homedir() + "/.uplink"], + "appium:systemPort": 4724, + "appium:prerun": { + command: 'do shell script "rm -rf ~/.uplink"', + }, + } + }, + } + , + // + // =================== + // Test Configurations + // =================== + // Define all options that are relevant for the WebdriverIO instance here + // + reporters: [ + ["spec", + { + showPreface: false, + }, + ], + ['allure', + { + outputDir: './allure-results', + disableWebdriverStepsReporting: true, + disableWebdriverScreenshotsReporting: false, + } + ], + ['junit', + { + outputDir: './test-report/', + outputFileFormat: function (options) { + return `test-results-macos-app-${options.cid}.xml`; + } + } + ], + ], + // + // ===== + // Hooks + // ===== + // WebdriverIO provides several hooks you can use to interfere with the test process in order to enhance + // it and to build services around it. You can either apply a single function or an array of + // methods to it. If one of them returns with a promise, WebdriverIO will wait until that promise got + // resolved to continue. + onPrepare: async function() { + const cacheFolder = homedir() + "/.uplink/.user"; + const allureResultsFolder = join(process.cwd(), "./allure-results"); + const testReportFolder = join(process.cwd(), "./test-report"); + const testResultsFolder = join(process.cwd(), "./test-results"); + try { + await rmSync(allureResultsFolder, { recursive: true, force: true }); + await rmSync(testReportFolder, { recursive: true, force: true }); + await rmSync(testResultsFolder, { recursive: true, force: true }); + console.log("Deleted Artifacts Folders Successfully!"); + } catch (error) { + console.error( + `Got an error trying to delete artifacts folders: ${error.message}` + ); + } + try { + await rmSync(cacheFolder, { recursive: true, force: true }); + console.log("Deleted Cache Folder Successfully!"); + } catch (error) { + console.error( + `Got an error trying to delete Cache Folder: ${error.message}` + ); + } + }, + + afterTest: async function (test, describe, { error }) { + if (error) { + let imageFile = await driver.takeScreenshot(); + const imageFolder = join(process.cwd(), "./test-results/macos-app", test.parent); + const imageTitle = test.title + " - Failed.png" + await fsp.mkdir(imageFolder, {recursive: true}); + await fsp.writeFile( + imageFolder + "/" + imageTitle, + imageFile, + "base64" + ); + + // Add to Screenshot to Allure Reporter + const data = await readFileSync(`${imageFolder}/${imageTitle}`); + allureReporter.addAttachment(imageTitle, data, 'image/png') + } + }, + } + +} \ No newline at end of file diff --git a/config/macos-chats/wdio.mac.createAccountB.conf.ts b/config/macos-chats/wdio.mac.createAccountB.conf.ts new file mode 100644 index 0000000000..42b4b93293 --- /dev/null +++ b/config/macos-chats/wdio.mac.createAccountB.conf.ts @@ -0,0 +1,149 @@ +import "module-alias/register"; +import allureReporter from '@wdio/allure-reporter' +import { config as sharedConfig } from '@config/wdio.shared.conf'; +import { homedir } from "os"; +import { join } from "path"; +import { MACOS_BUNDLE_ID, MACOS_DRIVER } from "@helpers/constants"; +const fsp = require("fs").promises; +const { readFileSync, rmSync } = require("fs"); + +// @ts-expect-error +export const config: WebdriverIO.Config = { + ...sharedConfig, + ...{ + // + // ================== + // Specify Test Files + // ================== + // Define which test specs should run. The pattern is relative to the directory + // from which `wdio` was called. + // + // The specs are defined as an array of spec files (optionally using wildcards + // that will be expanded). The test for each spec file will be run in a separate + // worker process. In order to have a group of spec files run in the same worker + // process simply enclose them in an array within the specs array. + // + // If you are calling `wdio` from an NPM script (see https://docs.npmjs.com/cli/run-script), + // then the current working directory is where your `package.json` resides, so `wdio` + // will be called from there. + // + maxInstances: 1, + specs: [ + join(process.cwd(), "./tests/suites/MainTests/04-CreateAccountB.suite.ts") + ], + // Patterns to exclude. + exclude: [ + // 'path/to/excluded/files' + ], + // + // ============ + // Capabilities + // ============ + // Define your capabilities here. WebdriverIO can run multiple capabilities at the same + // time. Depending on the number of capabilities, WebdriverIO launches several test + // sessions. Within your capabilities you can overwrite the spec and exclude options in + // order to group specific specs to a specific capability. + // + // + // If you have trouble getting all important capabilities together, check out the + // Sauce Labs platform configurator - a great tool to configure your capabilities: + // https://docs.saucelabs.com/reference/platforms-configurator + // + port: 4723, + path: '/', + capabilities: { + userA: { + capabilities: { + platformName: "mac", + "appium:automationName": MACOS_DRIVER, + "appium:bundleId": MACOS_BUNDLE_ID, + "appium:arguments": ["--path", homedir() + "/.uplink"], + "appium:systemPort": 4724, + "appium:prerun": { + command: 'do shell script "rm -rf ~/.uplink"', + }, + } + }, + } + , + // + // =================== + // Test Configurations + // =================== + // Define all options that are relevant for the WebdriverIO instance here + // + reporters: [ + ["spec", + { + showPreface: false, + }, + ], + ['allure', + { + outputDir: './allure-results', + disableWebdriverStepsReporting: true, + disableWebdriverScreenshotsReporting: false, + } + ], + ['junit', + { + outputDir: './test-report/', + outputFileFormat: function (options) { + return `test-results-macos-app-${options.cid}.xml`; + } + } + ], + ], + // + // ===== + // Hooks + // ===== + // WebdriverIO provides several hooks you can use to interfere with the test process in order to enhance + // it and to build services around it. You can either apply a single function or an array of + // methods to it. If one of them returns with a promise, WebdriverIO will wait until that promise got + // resolved to continue. + onPrepare: async function() { + const cacheFolder = homedir() + "/.uplink/.user"; + const allureResultsFolder = join(process.cwd(), "./allure-results"); + const testReportFolder = join(process.cwd(), "./test-report"); + const testResultsFolder = join(process.cwd(), "./test-results"); + try { + await rmSync(allureResultsFolder, { recursive: true, force: true }); + await rmSync(testReportFolder, { recursive: true, force: true }); + await rmSync(testResultsFolder, { recursive: true, force: true }); + console.log("Deleted Artifacts Folders Successfully!"); + } catch (error) { + console.error( + `Got an error trying to delete artifacts folders: ${error.message}` + ); + } + try { + await rmSync(cacheFolder, { recursive: true, force: true }); + console.log("Deleted Cache Folder Successfully!"); + } catch (error) { + console.error( + `Got an error trying to delete Cache Folder: ${error.message}` + ); + } + }, + + afterTest: async function (test, describe, { error }) { + if (error) { + let imageFile = await driver.takeScreenshot(); + const imageFolder = join(process.cwd(), "./test-results/macos-app", test.parent); + const imageTitle = test.title + " - Failed.png" + await fsp.mkdir(imageFolder, {recursive: true}); + await fsp.writeFile( + imageFolder + "/" + imageTitle, + imageFile, + "base64" + ); + + // Add to Screenshot to Allure Reporter + const data = await readFileSync(`${imageFolder}/${imageTitle}`); + allureReporter.addAttachment(imageTitle, data, 'image/png') + } + }, + } + +} \ No newline at end of file diff --git a/config/wdio.mac.app.conf.ts b/config/wdio.mac.app.conf.ts index 8a77ab9591..c2275f3c72 100644 --- a/config/wdio.mac.app.conf.ts +++ b/config/wdio.mac.app.conf.ts @@ -27,7 +27,10 @@ export const config: WebdriverIO.Config = { // then the current working directory is where your `package.json` resides, so `wdio` // will be called from there. // - specs: [join(process.cwd(), "./tests/suites/MainTests/01-UplinkTests.suite.ts")], + maxInstances: 1, + specs: [ + join(process.cwd(), "./tests/suites/MainTests/01-UplinkTests.suite.ts") + ], // Patterns to exclude. exclude: [ // 'path/to/excluded/files' diff --git a/config/wdio.mac.ci.conf.ts b/config/wdio.mac.ci.conf.ts index d2e98987e2..a19be70ae9 100644 --- a/config/wdio.mac.ci.conf.ts +++ b/config/wdio.mac.ci.conf.ts @@ -26,8 +26,10 @@ export const config: WebdriverIO.Config = { // If you are calling `wdio` from an NPM script (see https://docs.npmjs.com/cli/run-script), // then the current working directory is where your `package.json` resides, so `wdio` // will be called from there. - // - specs: [join(process.cwd(), "./tests/suites/MainTests/01-UplinkTests.suite.ts")], + maxInstances: 1, + specs: [ + join(process.cwd(), "./tests/suites/MainTests/01-UplinkTests.suite.ts") + ], // Patterns to exclude. exclude: [ // 'path/to/excluded/files' diff --git a/package.json b/package.json index 6e15558eb1..f718733302 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,10 @@ "description": "An automation testing framework built with WebdriverIO and Appium to test Uplink Desktop app", "scripts": { "mac.app": "wdio config/wdio.mac.app.conf.ts", + "mac.chatA": "wdio config/macos-chats/wdio.mac.chatA.conf.ts", + "mac.chatB": "wdio config/macos-chats/wdio.mac.chatB.conf.ts", + "mac.createAccountA": "wdio config/macos-chats/wdio.mac.createAccountA.conf.ts", + "mac.createAccountB": "wdio config/macos-chats/wdio.mac.createAccountB.conf.ts", "mac.ci": "wdio config/wdio.mac.ci.conf.ts", "mac.multiremote": "wdio config/wdio.mac.multiremote.conf.ts", "windows.app": "wdio config/wdio.windows.app.conf.ts", diff --git a/tests/helpers/commands.ts b/tests/helpers/commands.ts index 3886ed660d..53da8dcdd3 100644 --- a/tests/helpers/commands.ts +++ b/tests/helpers/commands.ts @@ -16,7 +16,7 @@ import { const { readFileSync, rmSync, writeFileSync } = require("fs"); const { execSync } = require("child_process"); const fsp = require("fs").promises; -const { mouse, Button } = require("@nut-tree/nut-js") +const { mouse, Button } = require("@nut-tree/nut-js"); let createPinFirstUser = new CreatePinScreen(USER_A_INSTANCE); let createPinSecondUser = new CreatePinScreen(USER_B_INSTANCE); let createUserFirstUser = new CreateUserScreen(USER_A_INSTANCE); @@ -35,7 +35,7 @@ export async function deleteCache() { console.log("Deleted user cache successfully"); } catch (error) { console.error( - `Got an error trying to delete the user cache files: ${error.message}` + `Got an error trying to delete the user cache files: ${error.message}`, ); } } @@ -50,7 +50,7 @@ export async function grabCacheFolder(username: string, instance: string) { console.log("Copied user cache successfully"); } catch (error) { console.error( - `Got an error trying to copy the user cache files: ${error.message}` + `Got an error trying to copy the user cache files: ${error.message}`, ); } } @@ -67,7 +67,7 @@ export async function loadTestUserData(user: string, instance: string) { console.log("Copied user cache successfully"); } catch (error) { console.error( - `Got an error trying to copy the user cache files: ${error.message}` + `Got an error trying to copy the user cache files: ${error.message}`, ); } } @@ -88,7 +88,7 @@ export async function getUserKey(username: string, instance: string) { export async function saveTestKeys( username: string, didkey: string, - instance: string + instance: string, ) { // Save JSON file with keys const currentDriver = await driver[instance].capabilities.automationName; @@ -263,7 +263,7 @@ export async function maximizeWindow(instance: string) { export async function clickOnSwitchMacOS( element: WebdriverIO.Element, - instance: string + instance: string, ) { const currentInstance = await browser.getInstance(instance); const elementLocator = await currentInstance.$(element); @@ -288,7 +288,7 @@ export async function getClipboardMacOS() { export async function hoverOnMacOS( locator: WebdriverIO.Element, - instance: string + instance: string, ) { // Hover on X and Y coordinates previously retrieved await driver[instance].executeScript("macos: hover", [ @@ -323,7 +323,7 @@ export async function saveFileOnMacOS(filename: string, instance: string) { export async function selectFileOnMacos( relativePath: string, - instance: string + instance: string, ) { const currentInstance = await browser.getInstance(instance); @@ -366,7 +366,7 @@ export async function selectFileOnMacos( export async function rightClickOnMacOS( locator: WebdriverIO.Element, - instance: string + instance: string, ) { await driver[instance].executeScript("macos: rightClick", [ { @@ -379,14 +379,14 @@ export async function rightClickOnMacOS( export async function hoverOnWindows( locator: WebdriverIO.Element, - instance: string + instance: string, ) { await driver[instance].moveToElement(locator.elementId); } export async function rightClickOnWindows( locator: WebdriverIO.Element, - instance: string + instance: string, ) { await driver[instance].moveToElement(locator.elementId); await mouse.click(Button.RIGHT); @@ -395,7 +395,7 @@ export async function rightClickOnWindows( export async function saveFileOnWindows( filename: string, uplinkContext: string, - instance: string + instance: string, ) { // Get the filepath to select on browser const filepath = join(process.cwd(), "\\tests\\fixtures\\", filename); @@ -415,7 +415,7 @@ export async function saveFileOnWindows( // Type file location and hit enter const editInput = await driver[instance].$( - "/Window/Pane[1]/ComboBox[1]/Edit" + "/Window/Pane[1]/ComboBox[1]/Edit", ); await editInput.clearValue(); await editInput.setValue(filename + "\uE007"); @@ -429,7 +429,7 @@ export async function saveFileOnWindows( export async function selectFileOnWindows( relativePath: string, uplinkContext: string, - instance: string + instance: string, ) { // Get the filepath to select on browser const filepath = join(process.cwd(), relativePath); diff --git a/tests/screenobjects/UplinkMainScreen.ts b/tests/screenobjects/UplinkMainScreen.ts index efe0d6e079..9b53079ed5 100644 --- a/tests/screenobjects/UplinkMainScreen.ts +++ b/tests/screenobjects/UplinkMainScreen.ts @@ -318,9 +318,9 @@ export default class UplinkMainScreen extends AppScreen { await this.instance.switchToWindow(currentInstance); } - async showUplinkWindow() { + async showUplinkWindow(timeout: number = 15000) { const window = await this.instance.window; await window.click(); - await window.waitForExist(); + await window.waitForExist({ timeout: timeout }); } } diff --git a/tests/screenobjects/chats/ChatsLayout.ts b/tests/screenobjects/chats/ChatsLayout.ts index 881a104a63..8a9d9e98f8 100644 --- a/tests/screenobjects/chats/ChatsLayout.ts +++ b/tests/screenobjects/chats/ChatsLayout.ts @@ -22,8 +22,7 @@ const SELECTORS_WINDOWS = { const SELECTORS_MACOS = { ENCRYPTED_MESSAGES: "~messages-secured-alert", - ENCRYPTED_MESSAGES_TEXT: - "-ios class chain:**/XCUIElementTypeGroup/XCUIElementTypeStaticText", + ENCRYPTED_MESSAGES_TEXT: "-ios class chain:**/XCUIElementTypeStaticText", TYPING_INDICATOR: "~message-typing-indicator", TYPING_INDICATOR_TEXT: "~typing-message", TYPING_INDICATOR_TEXT_VALUE: "-ios class chain:**/XCUIElementTypeStaticText", @@ -70,15 +69,15 @@ export default class ChatsLayout extends UplinkMainScreen { .$(SELECTORS.TYPING_INDICATOR_TEXT_VALUE); } - async validateChatLayoutIsShown() { + async validateChatLayoutIsShown(timeout: number = 15000) { await driver[this.executor].waitUntil( async () => { - return await this.chatLayout; + return await this.chatLayout.waitForExist({ timeout: timeout }); }, { timeout: 15000, timeoutMsg: "Expected chat layout was never displayed after 15 seconds", - } + }, ); } } diff --git a/tests/screenobjects/chats/ChatsSidebar.ts b/tests/screenobjects/chats/ChatsSidebar.ts index cee9c2e581..5719cb2c6d 100644 --- a/tests/screenobjects/chats/ChatsSidebar.ts +++ b/tests/screenobjects/chats/ChatsSidebar.ts @@ -326,17 +326,17 @@ export default class ChatsSidebar extends UplinkMainScreen { return (await sidebarStatusValue.getText()) === message; }, { - timeout: 15000, + timeout: 60000, timeoutMsg: - "Expected sidebar status value never include the message after 15 seconds", - } + "Expected sidebar status value never include the message after 60 seconds", + }, ); } async validateLastMessageTimeAgo() { const timeAgo = await this.sidebarChatsUserBadgeTimeAgoValue; await expect(timeAgo).toHaveTextContaining( - /(?:\d{1,2}\s+(?:second|minute)s?\s+ago|now)$/ + /(?:\d{1,2}\s+(?:second|minute)s?\s+ago|now)$/, ); } @@ -346,10 +346,10 @@ export default class ChatsSidebar extends UplinkMainScreen { return await this.sidebarChatsUserBadge.waitForExist({ reverse: true }); }, { - timeout: 15000, + timeout: 60000, timeoutMsg: - "Expected badge number of unread messages is still displayed after 15 seconds", - } + "Expected badge number of unread messages is still displayed after 60 seconds", + }, ); } @@ -361,9 +361,9 @@ export default class ChatsSidebar extends UplinkMainScreen { }); }, { - timeout: 15000, - timeoutMsg: "Sidebar chats are still displayed after 15 seconds", - } + timeout: 60000, + timeoutMsg: "Sidebar chats are still displayed after 60 seconds", + }, ); } @@ -377,9 +377,9 @@ export default class ChatsSidebar extends UplinkMainScreen { .waitForExist({ reverse: true }); }, { - timeout: 15000, - timeoutMsg: "Sidebar chats are still displayed after 15 seconds", - } + timeout: 60000, + timeoutMsg: "Sidebar chats are still displayed after 60 seconds", + }, ); } @@ -389,9 +389,9 @@ export default class ChatsSidebar extends UplinkMainScreen { return await this.sidebarGroupChatImage.waitForExist({ reverse: true }); }, { - timeout: 15000, - timeoutMsg: "Sidebar group chats are still displayed after 15 seconds", - } + timeout: 60000, + timeoutMsg: "Sidebar group chats are still displayed after 60 seconds", + }, ); } @@ -405,29 +405,34 @@ export default class ChatsSidebar extends UplinkMainScreen { await expect(usernameDisplayed).toHaveTextContaining(username); } - async validateSidebarChatsIsShown() { + async validateSidebarChatsIsShown(timeout: number = 15000) { const sidebarChats = await this.sidebarChatsUser; - await sidebarChats.waitForExist(); + await sidebarChats.waitForExist({ timeout: timeout }); } // Waiting methods - async waitForReceivingMessageOnSidebar() { + async waitForReceivingMessageOnSidebar(timeout: number = 15000) { await driver[this.executor].waitUntil( async () => { - return await this.sidebarChatsUserStatusValue; + return await this.sidebarChatsUserStatusValue.waitForExist({ + timeout: timeout, + }); }, { - timeout: 15000, + timeout: 60000, timeoutMsg: - "Sidebar never displayed received messages after 15 seconds", - } + "Sidebar never displayed received messages after 60 seconds", + }, ); } // Get Sidebar Group elements - async getExistingElementByAriaLabel(username: string) { + async getExistingElementByAriaLabel( + username: string, + timeout: number = 15000, + ) { const currentDriver = await this.getCurrentDriver(); let locator; if (currentDriver === macDriver) { @@ -437,7 +442,7 @@ export default class ChatsSidebar extends UplinkMainScreen { .$(SELECTORS.SIDEBAR) .$('[name="' + username + '"]'); } - await locator.waitForExist(); + await locator.waitForExist({ timeout: timeout }); return locator; } @@ -452,17 +457,20 @@ export default class ChatsSidebar extends UplinkMainScreen { return locator; } - async waitForGroupToBeCreated(groupname: string) { + async waitForGroupToBeCreated(groupname: string, timeout: number = 15000) { const element = await this.getExistingElementByAriaLabel(groupname); await driver[this.executor].waitUntil( async () => { - return await this.instance.$(SELECTORS.SIDEBAR).$(element); + return await this.instance + .$(SELECTORS.SIDEBAR) + .$(element) + .waitForExist({ timeout: timeout }); }, { - timeout: 15000, + timeout: 60000, timeoutMsg: - "Expected chat group was never displayed on Sidebar after 15 seconds", - } + "Expected chat group was never displayed on Sidebar after 60 seconds", + }, ); } @@ -476,85 +484,92 @@ export default class ChatsSidebar extends UplinkMainScreen { .waitForExist({ reverse: true }); }, { - timeout: 15000, - timeoutMsg: "Sidebar group was never deleted after 15 seconds", - } + timeout: 60000, + timeoutMsg: "Sidebar group was never deleted after 60 seconds", + }, ); } - async getSidebarGroupPlusSome(groupname: string) { + async getSidebarGroupPlusSome(groupname: string, timeout: number = 15000) { const groupLocator = await this.getExistingElementByAriaLabel(groupname); const plusSomeLocator = await groupLocator.$( - SELECTORS.SIDEBAR_GROUP_CHAT_PLUS_SOME + SELECTORS.SIDEBAR_GROUP_CHAT_PLUS_SOME, ); - await plusSomeLocator.waitForExist(); + await plusSomeLocator.waitForExist({ timeout: timeout }); return plusSomeLocator; } - async getSidebarGroupStatus(groupname: string) { + async getSidebarGroupStatus(groupname: string, timeout: number = 15000) { const groupLocator = await this.getExistingElementByAriaLabel(groupname); const statusLocator = await groupLocator .$(SELECTORS.SIDEBAR_CHATS_USER_STATUS) .$(SELECTORS.SIDEBAR_CHATS_USER_STATUS_VALUE); - await statusLocator.waitForExist(); + await statusLocator.waitForExist({ timeout: timeout }); return statusLocator; } // Get Sidebar User elements - async getSidebarUserImage(username: string) { + async getSidebarUserImage(username: string, timeout: number = 15000) { const userLocator = await this.getExistingElementByAriaLabel(username); const imageLocator = await userLocator .$(SELECTORS.SIDEBAR_CHATS_USER_IMAGE_WRAP) .$(SELECTORS.SIDEBAR_CHATS_USER_IMAGE); - await imageLocator.waitForExist(); + await imageLocator.waitForExist({ timeout: timeout }); return imageLocator; } - async getSidebarUserStatus(username: string) { + async getSidebarUserStatus(username: string, timeout: number = 15000) { const userLocator = await this.getExistingElementByAriaLabel(username); const statusLocator = await userLocator .$(SELECTORS.SIDEBAR_CHATS_USER_INFO) .$(SELECTORS.SIDEBAR_CHATS_USER_STATUS) .$(SELECTORS.SIDEBAR_CHATS_USER_STATUS_VALUE); - await statusLocator.waitForExist(); + await statusLocator.waitForExist({ timeout: timeout }); return statusLocator; } - async getSidebarUserIndicator(username: string) { + async getSidebarUserIndicator(username: string, timeout: number = 15000) { const userLocator = await this.getExistingElementByAriaLabel(username); const indicatorLocator = await userLocator .$(SELECTORS.SIDEBAR_CHATS_USER_IMAGE_WRAP) .$(SELECTORS.SIDEBAR_CHATS_USER_IMAGE) .$(SELECTORS.SIDEBAR_CHATS_USER_INDICATOR); - await indicatorLocator.waitForExist(); + await indicatorLocator.waitForExist({ timeout: timeout }); return indicatorLocator; } - async getSidebarUserIndicatorOffline(username: string) { + async getSidebarUserIndicatorOffline( + username: string, + timeout: number = 15000, + ) { const userLocator = await this.getExistingElementByAriaLabel(username); const offlineLocator = await userLocator .$(SELECTORS.SIDEBAR_CHATS_USER_IMAGE_WRAP) .$(SELECTORS.SIDEBAR_CHATS_USER_IMAGE) .$(SELECTORS.SIDEBAR_CHATS_USER_OFFLINE_INDICATOR); - await offlineLocator.waitForExist(); + await offlineLocator.waitForExist({ timeout: timeout }); return offlineLocator; } - async getSidebarUserIndicatorOnline(username: string) { + async getSidebarUserIndicatorOnline( + username: string, + timeout: number = 15000, + ) { const userLocator = await this.getExistingElementByAriaLabel(username); await driver[this.executor].waitUntil( async () => { return await userLocator .$(SELECTORS.SIDEBAR_CHATS_USER_IMAGE_WRAP) .$(SELECTORS.SIDEBAR_CHATS_USER_IMAGE) - .$(SELECTORS.SIDEBAR_CHATS_USER_ONLINE_INDICATOR); + .$(SELECTORS.SIDEBAR_CHATS_USER_ONLINE_INDICATOR) + .waitForExist({ timeout: timeout }); }, { - timeout: 15000, + timeout: 60000, timeoutMsg: - "Expected indicator online was never displayed on Chats Sidebar after 15 seconds", - } + "Expected indicator online was never displayed on Chats Sidebar after 60 seconds", + }, ); const onlineLocator = await userLocator @@ -564,13 +579,13 @@ export default class ChatsSidebar extends UplinkMainScreen { return onlineLocator; } - async getSidebarUserProfileTyping(username: string) { + async getSidebarUserProfileTyping(username: string, timeout: number = 15000) { const userLocator = await this.getExistingElementByAriaLabel(username); const profileTyping = await userLocator .$(SELECTORS.SIDEBAR_CHATS_USER_IMAGE_WRAP) .$(SELECTORS.SIDEBAR_CHATS_USER_IMAGE) .$(SELECTORS.SIDEBAR_CHATS_USER_PROFILE_TYPING); - await profileTyping.waitForExist(); + await profileTyping.waitForExist({ timeout: timeout }); return profileTyping; } @@ -599,9 +614,8 @@ export default class ChatsSidebar extends UplinkMainScreen { } async openContextMenuOnGroupChat(groupName: string) { - const imageToRightClick = await this.getExistingElementByAriaLabel( - groupName - ); + const imageToRightClick = + await this.getExistingElementByAriaLabel(groupName); await this.hoverOnElement(imageToRightClick); const currentDriver = await this.getCurrentDriver(); if (currentDriver === macDriver) { diff --git a/tests/screenobjects/chats/ComposeAttachment.ts b/tests/screenobjects/chats/ComposeAttachment.ts index 871c200463..18ec6a31da 100644 --- a/tests/screenobjects/chats/ComposeAttachment.ts +++ b/tests/screenobjects/chats/ComposeAttachment.ts @@ -58,25 +58,25 @@ export default class ComposeAttachments extends UplinkMainScreen { get composeAttachmentsFileIcon() { return this.composeAttachmentsFileEmbed.$( - SELECTORS.COMPOSE_ATTACHMENTS_FILE_ICON + SELECTORS.COMPOSE_ATTACHMENTS_FILE_ICON, ); } get composeAttachmentsFileInfo() { return this.composeAttachmentsFileEmbed.$( - SELECTORS.COMPOSE_ATTACHMENTS_FILE_INFO + SELECTORS.COMPOSE_ATTACHMENTS_FILE_INFO, ); } get composeAttachmentsFileMeta() { return this.composeAttachmentsFileEmbed.$( - SELECTORS.COMPOSE_ATTACHMENTS_FILE_META + SELECTORS.COMPOSE_ATTACHMENTS_FILE_META, ); } get composeAttachmentsFileName() { return this.composeAttachmentsFileEmbed.$( - SELECTORS.COMPOSE_ATTACHMENTS_FILE_NAME + SELECTORS.COMPOSE_ATTACHMENTS_FILE_NAME, ); } @@ -92,17 +92,17 @@ export default class ComposeAttachments extends UplinkMainScreen { get composeAttachmentsInputErrorText() { return this.composeAttachmentsInputError.$( - SELECTORS.COMPOSE_ATTACHMENTS_INPUT_ERROR_TEXT + SELECTORS.COMPOSE_ATTACHMENTS_INPUT_ERROR_TEXT, ); } async clickOnDeleteAttachment(attachment: number) { // Get the locator of attachment to delete by passing the index const attachmentToDelete = await this.instance.$$( - SELECTORS.COMPOSE_ATTACHMENTS_FILE_EMBED + SELECTORS.COMPOSE_ATTACHMENTS_FILE_EMBED, )[attachment]; const deleteAttachmentButton = await attachmentToDelete.$( - SELECTORS.COMPOSE_ATTACHMENTS_BUTTON + SELECTORS.COMPOSE_ATTACHMENTS_BUTTON, ); await deleteAttachmentButton.click(); } @@ -112,11 +112,11 @@ export default class ComposeAttachments extends UplinkMainScreen { await composeAttachmentsButton.click(); } - async getListOfAttachmentsEmbed() { + async getListOfAttachmentsEmbed(timeout: number = 15000) { const composeAttachments = await this.composeAttachments; - await composeAttachments.waitForExist(); + await composeAttachments.waitForExist({ timeout: timeout }); const filesAttached = await this.instance.$$( - SELECTORS.COMPOSE_ATTACHMENTS_FILE_EMBED + SELECTORS.COMPOSE_ATTACHMENTS_FILE_EMBED, ); let results = []; for (let fileAttached of filesAttached) { @@ -130,30 +130,32 @@ export default class ComposeAttachments extends UplinkMainScreen { return results; } - async validateAttachmentIsAdded() { + async validateAttachmentIsAdded(timeout: number = 15000) { const composeAttachmentsFileEmbed = await this.composeAttachmentsFileEmbed; await driver[this.executor].waitUntil( async () => { - return await composeAttachmentsFileEmbed; + return await composeAttachmentsFileEmbed.waitForExist({ + timeout: timeout, + }); }, { timeout: 15000, timeoutMsg: "Attachment file was not added after 15 seconds", - } + }, ); } async validateAttachmentWithFileNameIsAdded( fileName: string, - expectedAssertion: boolean + expectedAssertion: boolean, ) { const attachmentsList = await this.getListOfAttachmentsEmbed(); const includesAttachment = await attachmentsList.includes(fileName); await expect(includesAttachment).toEqual(expectedAssertion); } - async validateComposeAttachmentsIsShown() { + async validateComposeAttachmentsIsShown(timeout: number = 15000) { const composeAttachments = await this.composeAttachments; - await composeAttachments.waitForExist(); + await composeAttachments.waitForExist({ timeout: timeout }); } } diff --git a/tests/screenobjects/chats/ContextMenu.ts b/tests/screenobjects/chats/ContextMenu.ts index f586f70349..e6f9dcbae4 100644 --- a/tests/screenobjects/chats/ContextMenu.ts +++ b/tests/screenobjects/chats/ContextMenu.ts @@ -152,11 +152,11 @@ export default class ContextMenu extends UplinkMainScreen { locator = await this.instance.$( '//XCUIElementTypeGroup[@label="Context Menu"]/XCUIElementTypeButton[@Value="' + reaction + - '"]' + '"]', ); } else if (currentDriver === WINDOWS_DRIVER) { locator = await this.instance.$( - '//Group[@Name="Context Menu"]/Button[@Name="' + reaction + '"]' + '//Group[@Name="Context Menu"]/Button[@Name="' + reaction + '"]', ); } await locator.click(); @@ -203,8 +203,8 @@ export default class ContextMenu extends UplinkMainScreen { await contextMessagesReply.click(); } - async validateContextMenuIsOpen() { + async validateContextMenuIsOpen(timeout: number = 15000) { const contextMenu = await this.contextMenu; - await contextMenu.waitForExist(); + await contextMenu.waitForExist({ timeout: timeout }); } } diff --git a/tests/screenobjects/chats/ContextMenuSidebar.ts b/tests/screenobjects/chats/ContextMenuSidebar.ts index e803ea8015..429ac24c70 100644 --- a/tests/screenobjects/chats/ContextMenuSidebar.ts +++ b/tests/screenobjects/chats/ContextMenuSidebar.ts @@ -84,8 +84,8 @@ export default class ContextMenuSidebar extends UplinkMainScreen { await leaveGroup.click(); } - async validateContextMenuIsOpen() { + async validateContextMenuIsOpen(timeout: number = 15000) { const contextMenu = await this.contextMenu; - await contextMenu.waitForExist(); + await contextMenu.waitForExist({ timeout: timeout }); } } diff --git a/tests/screenobjects/chats/CreateGroupChat.ts b/tests/screenobjects/chats/CreateGroupChat.ts index 0ad4f578df..310cb06f0d 100644 --- a/tests/screenobjects/chats/CreateGroupChat.ts +++ b/tests/screenobjects/chats/CreateGroupChat.ts @@ -1,4 +1,4 @@ -const {keyboard, Key} = require("@nut-tree/nut-js"); +const { keyboard, Key } = require("@nut-tree/nut-js"); import "module-alias/register"; import { getClipboardMacOS } from "@helpers/commands"; import { @@ -177,47 +177,58 @@ export default class CreateGroupChat extends UplinkMainScreen { await createGroupChatButton.click(); } - async getFriendFromListIndicator(username: string) { + async getFriendFromListIndicator(username: string, timeout: number = 15000) { const friendLocator = await this.getFriendFromListLocator(username); const indicator = await friendLocator.$(SELECTORS.FRIEND_INDICATOR); - await indicator.waitForExist(); + await indicator.waitForExist({ timeout: timeout }); return indicator; } - async getFriendFromListIndicatorOffline(username: string) { + async getFriendFromListIndicatorOffline( + username: string, + timeout: number = 15000, + ) { const friendLocator = await this.getFriendFromListLocator(username); const indicatorOffline = await friendLocator.$( - SELECTORS.FRIEND_INDICATOR_OFFLINE + SELECTORS.FRIEND_INDICATOR_OFFLINE, ); - await indicatorOffline.waitForExist(); + await indicatorOffline.waitForExist({ timeout: timeout }); return indicatorOffline; } - async getFriendFromListIndicatorOnline(username: string) { + async getFriendFromListIndicatorOnline( + username: string, + timeout: number = 15000, + ) { const friendLocator = await this.getFriendFromListLocator(username); await driver[this.executor].waitUntil( async () => { - return await friendLocator.$(SELECTORS.FRIEND_INDICATOR_ONLINE); + return await friendLocator + .$(SELECTORS.FRIEND_INDICATOR_ONLINE) + .waitForExist({ timeout: timeout }); }, { timeout: 15000, timeoutMsg: "Expected indicator online was never displayed on Create Group Users List after 15 seconds", - } + }, ); const indicatorOnline = await friendLocator.$( - SELECTORS.FRIEND_INDICATOR_ONLINE + SELECTORS.FRIEND_INDICATOR_ONLINE, ); return indicatorOnline; } - async getFriendFromListUserImageProfile(username: string) { + async getFriendFromListUserImageProfile( + username: string, + timeout: number = 15000, + ) { const friendLocator = await this.getFriendFromListLocator(username); const userImageProfile = await friendLocator.$( - SELECTORS.FRIEND_USER_IMAGE_PROFILE + SELECTORS.FRIEND_USER_IMAGE_PROFILE, ); - await userImageProfile.waitForExist(); + await userImageProfile.waitForExist({ timeout: timeout }); return userImageProfile; } @@ -231,7 +242,7 @@ export default class CreateGroupChat extends UplinkMainScreen { .$( '//XCUIElementTypeGroup[@label="friend-name"]/XCUIElementTypeStaticText[contains(@value, "' + username + - '")]/../..' + '")]/../..', ); } else if (currentDriver === WINDOWS_DRIVER) { friendLocator = await this.instance @@ -240,25 +251,28 @@ export default class CreateGroupChat extends UplinkMainScreen { .$( '//Group[@Name="friend-name"]/Text[contains(@Name, "' + username + - '")]/../..' + '")]/../..', ); } return friendLocator; } - async getFriendFromListUserImage(username: string) { + async getFriendFromListUserImage(username: string, timeout: number = 15000) { const friendLocator = await this.getFriendFromListLocator(username); const userImage = await friendLocator.$(SELECTORS.FRIEND_USER_IMAGE); - await userImage.waitForExist(); + await userImage.waitForExist({ timeout: timeout }); return userImage; } - async getFriendFromListUserImageWrap(username: string) { + async getFriendFromListUserImageWrap( + username: string, + timeout: number = 15000, + ) { const friendLocator = await this.getFriendFromListLocator(username); const userImageWrap = await friendLocator.$( - SELECTORS.FRIEND_USER_IMAGE_WRAP + SELECTORS.FRIEND_USER_IMAGE_WRAP, ); - await userImageWrap.waitForExist(); + await userImageWrap.waitForExist({ timeout: timeout }); return userImageWrap; } @@ -267,7 +281,7 @@ export default class CreateGroupChat extends UplinkMainScreen { const usernameLocator = await friendLocator .$(SELECTORS.FRIEND_USER_NAME) .$(SELECTORS.FRIEND_USER_NAME_TEXT); - await usernameLocator.waitForExist(); + await usernameLocator.waitForExist({ timeout: timeout }); return usernameLocator; } @@ -345,8 +359,8 @@ export default class CreateGroupChat extends UplinkMainScreen { return result.toString(); } - async validateCreateGroupChatsIsShown() { + async validateCreateGroupChatsIsShown(timeout: number = 15000) { const createGroupChatSection = await this.createGroupChatSection; - await createGroupChatSection.waitForExist(); + await createGroupChatSection.waitForExist({ timeout: timeout }); } } diff --git a/tests/screenobjects/chats/EditGroup.ts b/tests/screenobjects/chats/EditGroup.ts index e2d43cf1a2..13404228dc 100644 --- a/tests/screenobjects/chats/EditGroup.ts +++ b/tests/screenobjects/chats/EditGroup.ts @@ -245,36 +245,36 @@ export default class EditGroup extends UplinkMainScreen { await currentMembers.click(); } - async clickOnFirstAddButton() { + async clickOnFirstAddButton(timeout: number = 15000) { const firstAddButton = await this.instance.$$( - SELECTORS.ADD_PARTICIPANT_BUTTON + SELECTORS.ADD_PARTICIPANT_BUTTON, )[0]; await driver[this.executor].waitUntil( async () => { - return await firstAddButton; + return await firstAddButton.waitForExist({ timeout: timeout }); }, { timeout: 15000, timeoutMsg: "Add friend button from Edit Group was never displayed after 15 seconds", - } + }, ); await firstAddButton.click(); } - async clickOnFirstRemoveButton() { + async clickOnFirstRemoveButton(timeout: number = 15000) { const removeParticipantButton = await this.instance.$$( - SELECTORS.REMOVE_PARTICIPANT_BUTTON + SELECTORS.REMOVE_PARTICIPANT_BUTTON, )[0]; await driver[this.executor].waitUntil( async () => { - return await removeParticipantButton; + return await removeParticipantButton.waitForExist({ timeout: timeout }); }, { timeout: 15000, timeoutMsg: "Remove friend button from Edit Group was never displayed after 15 seconds", - } + }, ); await removeParticipantButton.click(); } @@ -314,7 +314,7 @@ export default class EditGroup extends UplinkMainScreen { .$( '//XCUIElementTypeGroup[@label="Friend Container"]/XCUIElementTypeGroup/XCUIElementTypeStaticText[contains(@value, "' + participant + - '")]/../..' + '")]/../..', ); } else if (currentDriver === WINDOWS_DRIVER) { locator = await this.instance @@ -322,87 +322,107 @@ export default class EditGroup extends UplinkMainScreen { .$( '//Group[@Name="Friend Container"]/Group/Text[contains(@Name, "' + participant + - '")]/../..' + '")]/../..', ); } return locator; } - async getParticipantIndicator(participant: string) { + async getParticipantIndicator(participant: string, timeout: number = 15000) { const userLocator = await this.getParticipantContainerLocator(participant); const indicator = await userLocator.$(SELECTORS.PARTICIPANT_USER_INDICATOR); - await indicator.waitForExist(); + await indicator.waitForExist({ timeout: timeout }); return indicator; } - async getParticipantIndicatorOffline(participant: string) { + async getParticipantIndicatorOffline( + participant: string, + timeout: number = 15000, + ) { const userLocator = await this.getParticipantContainerLocator(participant); const indicatorOffline = await userLocator.$( - SELECTORS.PARTICIPANT_USER_INDICATOR_OFFLINE + SELECTORS.PARTICIPANT_USER_INDICATOR_OFFLINE, ); - await indicatorOffline.waitForExist(); + await indicatorOffline.waitForExist({ timeout: timeout }); return indicatorOffline; } - async getParticipantIndicatorOnline(participant: string) { + async getParticipantIndicatorOnline( + participant: string, + timeout: number = 15000, + ) { const userLocator = await this.getParticipantContainerLocator(participant); await driver[this.executor].waitUntil( async () => { - return await userLocator.$(SELECTORS.PARTICIPANT_USER_INDICATOR_ONLINE); + return await userLocator + .$(SELECTORS.PARTICIPANT_USER_INDICATOR_ONLINE) + .waitForExist({ timeout: timeout }); }, { - timeout: 15000, + timeout: 60000, timeoutMsg: - "Expected indicator online was never displayed on Edit Group Users List after 15 seconds", - } + "Expected indicator online was never displayed on Edit Group Users List after 60 seconds", + }, ); const indicatorOnline = await userLocator.$( - SELECTORS.PARTICIPANT_USER_INDICATOR_ONLINE + SELECTORS.PARTICIPANT_USER_INDICATOR_ONLINE, ); return indicatorOnline; } - async getParticipantUserCreatorBadgeImage(participant: string) { + async getParticipantUserCreatorBadgeImage( + participant: string, + timeout: number = 15000, + ) { const userLocator = await this.getParticipantContainerLocator(participant); const badgeImage = await userLocator.$( - SELECTORS.PARTICIPANT_USER_CREATOR_BADGE_IMAGE + SELECTORS.PARTICIPANT_USER_CREATOR_BADGE_IMAGE, ); - await badgeImage.waitForExist(); + await badgeImage.waitForExist({ timeout: timeout }); return badgeImage; } - async getParticipantUserCreatorBadgeText(participant: string) { + async getParticipantUserCreatorBadgeText( + participant: string, + timeout: number = 15000, + ) { const userLocator = await this.getParticipantContainerLocator(participant); const badgeText = await userLocator.$( - SELECTORS.PARTICIPANT_USER_CREATOR_BADGE_TEXT + SELECTORS.PARTICIPANT_USER_CREATOR_BADGE_TEXT, ); - await badgeText.waitForExist(); + await badgeText.waitForExist({ timeout: timeout }); return badgeText; } - async getParticipantUserImage(participant: string) { + async getParticipantUserImage(participant: string, timeout: number = 15000) { const userLocator = await this.getParticipantContainerLocator(participant); const userImage = await userLocator.$(SELECTORS.PARTICIPANT_USER_IMAGE); - await userImage.waitForExist(); + await userImage.waitForExist({ timeout: timeout }); return userImage; } - async getParticipantUserImageProfile(participant: string) { + async getParticipantUserImageProfile( + participant: string, + timeout: number = 15000, + ) { const userLocator = await this.getParticipantContainerLocator(participant); const userImageProfile = await userLocator.$( - SELECTORS.PARTICIPANT_USER_IMAGE_PROFILE + SELECTORS.PARTICIPANT_USER_IMAGE_PROFILE, ); - await userImageProfile.waitForExist(); + await userImageProfile.waitForExist({ timeout: timeout }); return userImageProfile; } - async getParticipantUserImageWrap(participant: string) { + async getParticipantUserImageWrap( + participant: string, + timeout: number = 15000, + ) { const userLocator = await this.getParticipantContainerLocator(participant); const userImageWrap = await userLocator.$( - SELECTORS.PARTICIPANT_USER_IMAGE_WRAP + SELECTORS.PARTICIPANT_USER_IMAGE_WRAP, ); - await userImageWrap.waitForExist(); + await userImageWrap.waitForExist({ timeout: timeout }); return userImageWrap; } @@ -427,25 +447,30 @@ export default class EditGroup extends UplinkMainScreen { } } - async validateEditGroupIsShown() { + async validateEditGroupIsShown(timeout: number = 15000) { const editGroupSection = await this.editGroupSection; - await editGroupSection.waitForExist(); + await editGroupSection.waitForExist({ timeout: timeout }); } - async validateNothingHereIsDisplayed() { + async validateNothingHereIsDisplayed(timeout: number = 15000) { const nothingHereText = await this.nothingHereText; - await nothingHereText.waitForExist(); + await nothingHereText.waitForExist({ timeout: timeout }); } - async validateParticipantIndicatorOnline(username: string) { + async validateParticipantIndicatorOnline( + username: string, + timeout: number = 15000, + ) { await driver[this.executor].waitUntil( async () => { - return await this.getParticipantIndicatorOnline(username); + return await this.getParticipantIndicatorOnline(username).waitForExist({ + timeout: timeout, + }); }, { - timeout: 15000, - timeoutMsg: "Expected chat layout was never displayed after 15 seconds", - } + timeout: timeout, + timeoutMsg: "Expected chat layout was never displayed", + }, ); } } diff --git a/tests/screenobjects/chats/EmojiSelector.ts b/tests/screenobjects/chats/EmojiSelector.ts index 730f1892a3..678592bb23 100644 --- a/tests/screenobjects/chats/EmojiSelector.ts +++ b/tests/screenobjects/chats/EmojiSelector.ts @@ -5,6 +5,7 @@ import { USER_A_INSTANCE, } from "@helpers/constants"; import UplinkMainScreen from "@screenobjects/UplinkMainScreen"; +const { mouse, Button } = require("@nut-tree/nut-js"); const currentOS = driver[USER_A_INSTANCE].capabilities.automationName; let SELECTORS = {}; @@ -72,6 +73,6 @@ export default class EmojiSelector extends UplinkMainScreen { .$(emojiLocator); } await this.hoverOnElement(emojiElement); - await emojiElement.click(); + await mouse.click(Button.LEFT); } } diff --git a/tests/screenobjects/chats/FavoritesSidebar.ts b/tests/screenobjects/chats/FavoritesSidebar.ts index cca99435ed..639e7bef89 100644 --- a/tests/screenobjects/chats/FavoritesSidebar.ts +++ b/tests/screenobjects/chats/FavoritesSidebar.ts @@ -175,7 +175,7 @@ export default class FavoritesSidebar extends UplinkMainScreen { await favoritesRemove.click(); } - async getFavoritesUserByAriaLabel(username: string) { + async getFavoritesUserByAriaLabel(username: string, timeout: number = 15000) { const currentDriver = await this.getCurrentDriver(); let favoritesLocator: string = ""; if (currentDriver === MACOS_DRIVER) { @@ -185,13 +185,16 @@ export default class FavoritesSidebar extends UplinkMainScreen { } await driver[this.executor].waitUntil( async () => { - return await this.instance.$(SELECTORS.SLIMBAR).$(favoritesLocator); + return await this.instance + .$(SELECTORS.SLIMBAR) + .$(favoritesLocator) + .waitForExist({ timeout: timeout }); }, { timeout: 15000, timeoutMsg: "Expected Favorite User was never displayed after 15 seconds", - } + }, ); const favoritesElement = await this.instance .$(SELECTORS.SLIMBAR) @@ -199,96 +202,110 @@ export default class FavoritesSidebar extends UplinkMainScreen { return favoritesElement; } - async getFavoritesUserImage(username: string) { + async getFavoritesUserImage(username: string, timeout: number = 15000) { const favoriteLocator = await this.getFavoritesUserByAriaLabel(username); await driver[this.executor].waitUntil( async () => { - return await favoriteLocator.$(SELECTORS.FAVORITES_USER_IMAGE); + return await favoriteLocator + .$(SELECTORS.FAVORITES_USER_IMAGE) + .waitForExist({ timeout: timeout }); }, { timeout: 15000, timeoutMsg: "Expected user image was never displayed on Favorites Sidebar after 15 seconds", - } + }, ); const userImage = await favoriteLocator.$(SELECTORS.FAVORITES_USER_IMAGE); return userImage; } - async getFavoritesUserImageGroupWrap(username: string) { + async getFavoritesUserImageGroupWrap( + username: string, + timeout: number = 15000, + ) { const favoriteLocator = await this.getFavoritesUserByAriaLabel(username); await driver[this.executor].waitUntil( async () => { - return await favoriteLocator.$( - SELECTORS.FAVORITES_USER_IMAGE_GROUP_WRAP - ); + return await favoriteLocator + .$(SELECTORS.FAVORITES_USER_IMAGE_GROUP_WRAP) + .waitForExist({ timeout: timeout }); }, { timeout: 15000, timeoutMsg: "Expected user image group wrap was never displayed on Favorites Sidebar after 15 seconds", - } + }, ); const userImageGroupWrap = await favoriteLocator.$( - SELECTORS.FAVORITES_USER_IMAGE_GROUP_WRAP + SELECTORS.FAVORITES_USER_IMAGE_GROUP_WRAP, ); return userImageGroupWrap; } - async getFavoritesUserImageProfile(username: string) { + async getFavoritesUserImageProfile( + username: string, + timeout: number = 15000, + ) { const favoriteLocator = await this.getFavoritesUserByAriaLabel(username); const imageProfile = await favoriteLocator.$( - SELECTORS.FAVORITES_USER_IMAGE_PROFILE + SELECTORS.FAVORITES_USER_IMAGE_PROFILE, ); - await imageProfile.waitForExist(); + await imageProfile.waitForExist({ timeout: timeout }); return imageProfile; } - async getFavoritesUserImageWrap(username: string) { + async getFavoritesUserImageWrap(username: string, timeout: number = 15000) { const favoriteLocator = await this.getFavoritesUserByAriaLabel(username); const userImageWrap = await favoriteLocator.$( - SELECTORS.FAVORITES_USER_IMAGE_WRAP + SELECTORS.FAVORITES_USER_IMAGE_WRAP, ); - await userImageWrap.waitForExist(); + await userImageWrap.waitForExist({ timeout: timeout }); return userImageWrap; } - async getFavoritesUserIndicator(username: string) { + async getFavoritesUserIndicator(username: string, timeout: number = 15000) { const favoriteLocator = await this.getFavoritesUserByAriaLabel(username); const indicator = await favoriteLocator.$( - SELECTORS.FAVORITES_USER_INDICATOR + SELECTORS.FAVORITES_USER_INDICATOR, ); - await indicator.waitForExist(); + await indicator.waitForExist({ timeout: timeout }); return indicator; } - async getFavoritesUserIndicatorOffline(username: string) { + async getFavoritesUserIndicatorOffline( + username: string, + timeout: number = 15000, + ) { const favoriteLocator = await this.getFavoritesUserByAriaLabel(username); const indicatorOffline = await favoriteLocator.$( - SELECTORS.FAVORITES_USER_INDICATOR_OFFLINE + SELECTORS.FAVORITES_USER_INDICATOR_OFFLINE, ); - await indicatorOffline.waitForExist(); + await indicatorOffline.waitForExist({ timeout: timeout }); return indicatorOffline; } - async getFavoritesUserIndicatorOnline(username: string) { + async getFavoritesUserIndicatorOnline( + username: string, + timeout: number = 15000, + ) { const favoriteLocator = await this.getFavoritesUserByAriaLabel(username); await driver[this.executor].waitUntil( async () => { - return await favoriteLocator.$( - SELECTORS.FAVORITES_USER_INDICATOR_ONLINE - ); + return await favoriteLocator + .$(SELECTORS.FAVORITES_USER_INDICATOR_ONLINE) + .waitForExist({ timeout: timeout }); }, { - timeout: 15000, + timeout: 60000, timeoutMsg: - "Expected indicator online was never displayed on Favorite User after 15 seconds", - } + "Expected indicator online was never displayed on Favorite User after 60 seconds", + }, ); const indicatorOnline = await favoriteLocator.$( - SELECTORS.FAVORITES_USER_INDICATOR_ONLINE + SELECTORS.FAVORITES_USER_INDICATOR_ONLINE, ); return indicatorOnline; } @@ -298,7 +315,7 @@ export default class FavoritesSidebar extends UplinkMainScreen { await this.hoverOnElement(favoritesBubble); } - async openContextMenuOnFavoritesUser(name: string) { + async openContextMenuOnFavoritesUser(name: string, timeout: number = 15000) { const userImageProfile = await this.getFavoritesUserImageProfile(name); const currentDriver = await this.getCurrentDriver(); if (currentDriver === MACOS_DRIVER) { @@ -308,13 +325,13 @@ export default class FavoritesSidebar extends UplinkMainScreen { } await driver[this.executor].waitUntil( async () => { - return await this.contextMenu; + return await this.contextMenu.waitForExist({ timeout: timeout }); }, { timeout: 15000, timeoutMsg: "Expected Context Menu was never displayed after 15 seconds", - } + }, ); } @@ -362,15 +379,15 @@ export default class FavoritesSidebar extends UplinkMainScreen { await this.hoverOnElement(slimbarSettingsButton); } - async validateFavoritesAreShown() { + async validateFavoritesAreShown(timeout: number = 15000) { await driver[this.executor].waitUntil( async () => { - return await this.favorites; + return await this.favorites.waitForExist({ timeout: timeout }); }, { timeout: 15000, timeoutMsg: "Expected Favorites were never displayed after 15 seconds", - } + }, ); } @@ -380,9 +397,8 @@ export default class FavoritesSidebar extends UplinkMainScreen { } async validateFavoritesIndicatorOnline(username: string) { - const indicatorOnline = await this.getFavoritesUserIndicatorOnline( - username - ); + const indicatorOnline = + await this.getFavoritesUserIndicatorOnline(username); await indicatorOnline.waitForDisplayed(); } } diff --git a/tests/screenobjects/chats/InputBar.ts b/tests/screenobjects/chats/InputBar.ts index 72bdca3cea..75f3cb1f02 100644 --- a/tests/screenobjects/chats/InputBar.ts +++ b/tests/screenobjects/chats/InputBar.ts @@ -11,7 +11,7 @@ import { selectFileOnWindows, } from "@helpers/commands"; import UplinkMainScreen from "@screenobjects/UplinkMainScreen"; -const {keyboard, Key} = require("@nut-tree/nut-js"); +const { keyboard, Key } = require("@nut-tree/nut-js"); const currentOS = driver[USER_A_INSTANCE].capabilities.automationName; let SELECTORS = {}; @@ -38,7 +38,7 @@ const SELECTORS_WINDOWS = { const SELECTORS_MACOS = { EDIT_MESSAGE_INPUT: "~edit-message-input", EMOJI_BUTTON: - '-ios class chain:**/XCUIElementTypeGroup[`label == "chat-layout"`]/XCUIElementTypeButton[2]', + '-ios class chain:**/XCUIElementTypeGroup[`label == "chat-layout"`]/XCUIElementTypeGroup[8]/XCUIElementTypeButton', INPUT_CHAR_COUNTER: "~input-char-counter", INPUT_CHAR_COUNTER_TEXT: "-ios class chain:**/XCUIElementTypeStaticText", INPUT_CHAR_MAX_TEXT: diff --git a/tests/screenobjects/chats/MessageGroup.ts b/tests/screenobjects/chats/MessageGroup.ts index 9dff4a914e..8f53899b59 100644 --- a/tests/screenobjects/chats/MessageGroup.ts +++ b/tests/screenobjects/chats/MessageGroup.ts @@ -78,7 +78,7 @@ export default class MessageGroup extends UplinkMainScreen { constructor(executor: string) { super( executor, - SELECTORS.MESSAGE_GROUP_WRAP_REMOTE || SELECTORS.MESSAGE_GROUP_WRAP_SENT + SELECTORS.MESSAGE_GROUP_WRAP_REMOTE || SELECTORS.MESSAGE_GROUP_WRAP_SENT, ); } @@ -228,28 +228,28 @@ export default class MessageGroup extends UplinkMainScreen { return lastGroupWrap; } - async getLastGroupWrapReceivedImage() { + async getLastGroupWrapReceivedImage(timeout: number = 15000) { const groupWrap = await this.getLastGroupWrapReceived(); const userImage = await groupWrap .$(SELECTORS.MESSAGE_GROUP_USER_IMAGE_WRAP) .$(SELECTORS.MESSAGE_GROUP_USER_IMAGE); - await userImage.waitForExist(); + await userImage.waitForExist({ timeout: timeout }); return userImage; } - async getLastGroupWrapReceivedIndicator() { + async getLastGroupWrapReceivedIndicator(timeout: number = 15000) { const groupWrap = await this.getLastGroupWrapReceived(); const indicator = await groupWrap.$(SELECTORS.MESSAGE_GROUP_USER_INDICATOR); - await indicator.waitForExist(); + await indicator.waitForExist({ timeout: timeout }); return indicator; } - async getLastGroupWrapReceivedOnline() { + async getLastGroupWrapReceivedOnline(timeout: number = 15000) { const groupWrap = await this.getLastGroupWrapReceived(); const onlineStatus = await groupWrap.$( - SELECTORS.MESSAGE_GROUP_USER_INDICATOR_ONLINE + SELECTORS.MESSAGE_GROUP_USER_INDICATOR_ONLINE, ); - await onlineStatus.waitForExist(); + await onlineStatus.waitForExist({ timeout: timeout }); return onlineStatus; } @@ -262,28 +262,28 @@ export default class MessageGroup extends UplinkMainScreen { return lastGroupWrap; } - async getLastGroupWrapSentImage() { + async getLastGroupWrapSentImage(timeout: number = 15000) { const groupWrap = await this.getLastGroupWrapSent(); const userImage = await groupWrap .$(SELECTORS.MESSAGE_GROUP_USER_IMAGE_WRAP) .$(SELECTORS.MESSAGE_GROUP_USER_IMAGE); - await userImage.waitForExist(); + await userImage.waitForExist({ timeout: timeout }); return userImage; } - async getLastGroupWrapSentIndicator() { + async getLastGroupWrapSentIndicator(timeout: number = 15000) { const groupWrap = await this.getLastGroupWrapSent(); const indicator = await groupWrap.$(SELECTORS.MESSAGE_GROUP_USER_INDICATOR); - await indicator.waitForExist(); + await indicator.waitForExist({ timeout: timeout }); return indicator; } - async getLastGroupWrapSentOnline() { + async getLastGroupWrapSentOnline(timeout: number = 15000) { const groupWrap = await this.getLastGroupWrapSent(); const onlineStatus = await groupWrap.$( - SELECTORS.MESSAGE_GROUP_USER_INDICATOR_ONLINE + SELECTORS.MESSAGE_GROUP_USER_INDICATOR_ONLINE, ); - await onlineStatus.waitForExist(); + await onlineStatus.waitForExist({ timeout: timeout }); return onlineStatus; } @@ -296,29 +296,31 @@ export default class MessageGroup extends UplinkMainScreen { return lastGroupLocator; } - async getLastMessageReceivedPinIndicator() { + async getLastMessageReceivedPinIndicator(timeout: number = 15000) { const lastGroupReceived = await this.getLastReceivedGroup(); await driver[this.executor].waitUntil( async () => { - return await lastGroupReceived.$(SELECTORS.PIN_INDICATOR); + return await lastGroupReceived + .$(SELECTORS.PIN_INDICATOR) + .waitForExist({ timeout: timeout }); }, { timeout: 15000, timeoutMsg: "Expected pin indicator was never added to received message after 15 seconds", - } + }, ); const pinIndicator = await lastGroupReceived.$(SELECTORS.PIN_INDICATOR); return pinIndicator; } - async getLastMessageReceivedTimeAgo() { + async getLastMessageReceivedTimeAgo(timeout: number = 15000) { const lastGroupReceived = await this.getLastReceivedGroup(); const timeAgoText = await lastGroupReceived .$(SELECTORS.MESSAGE_GROUP_TIME_AGO) .$(SELECTORS.MESSAGE_GROUP_TIME_AGO_TEXT); - await timeAgoText.waitForExist(); + await timeAgoText.waitForExist({ timeout: timeout }); return timeAgoText; } @@ -330,29 +332,31 @@ export default class MessageGroup extends UplinkMainScreen { return lastGroupLocator; } - async getLastMessageSentPinIndicator() { + async getLastMessageSentPinIndicator(timeout: number = 15000) { const lastGroupSent = await this.getLastSentGroup(); await driver[this.executor].waitUntil( async () => { - return await lastGroupSent.$(SELECTORS.PIN_INDICATOR); + return await lastGroupSent + .$(SELECTORS.PIN_INDICATOR) + .waitForExist({ timeout: timeout }); }, { timeout: 15000, timeoutMsg: "Expected pin indicator was never added to sent message after 15 seconds", - } + }, ); const pinIndicator = await lastGroupSent.$(SELECTORS.PIN_INDICATOR); return pinIndicator; } - async getLastMessageSentTimeAgo() { + async getLastMessageSentTimeAgo(timeout: number = 15000) { const lastGroupSent = await this.getLastSentGroup(); const timeAgoText = await lastGroupSent .$(SELECTORS.MESSAGE_GROUP_TIME_AGO) .$(SELECTORS.MESSAGE_GROUP_TIME_AGO_TEXT); - await timeAgoText.waitForExist(); + await timeAgoText.waitForExist({ timeout: timeout }); return timeAgoText; } @@ -375,7 +379,7 @@ export default class MessageGroup extends UplinkMainScreen { async getLastMessageReceivedReactionsContainer() { const lastGroupReceived = await this.getLastReceivedGroup(); const reactionContainers = await lastGroupReceived.$$( - SELECTORS.MESSAGE_REACTION_CONTAINER + SELECTORS.MESSAGE_REACTION_CONTAINER, ); const lastContainerIndex = (await reactionContainers.length) - 1; const lastContainerLocator = await reactionContainers[lastContainerIndex]; @@ -386,7 +390,7 @@ export default class MessageGroup extends UplinkMainScreen { const reactionsContainer = await this.getLastMessageReceivedReactionsContainer(); const remoteReactions = await reactionsContainer.$$( - SELECTORS.EMOJI_REACTION_REMOTE + SELECTORS.EMOJI_REACTION_REMOTE, ); let results = []; for (let reaction of remoteReactions) { @@ -401,7 +405,7 @@ export default class MessageGroup extends UplinkMainScreen { const reactionsContainer = await this.getLastMessageReceivedReactionsContainer(); const selfReactions = await reactionsContainer.$$( - SELECTORS.EMOJI_REACTION_SELF + SELECTORS.EMOJI_REACTION_SELF, ); let results = []; for (let reaction of selfReactions) { @@ -415,7 +419,7 @@ export default class MessageGroup extends UplinkMainScreen { async getLastMessageSentReactionsContainer() { const lastGroupSent = await this.getLastSentGroup(); const reactionContainers = await lastGroupSent.$$( - SELECTORS.MESSAGE_REACTION_CONTAINER + SELECTORS.MESSAGE_REACTION_CONTAINER, ); const lastContainerIndex = (await reactionContainers.length) - 1; const lastContainerLocator = await reactionContainers[lastContainerIndex]; @@ -426,7 +430,7 @@ export default class MessageGroup extends UplinkMainScreen { const reactionsContainer = await this.getLastMessageSentReactionsContainer(); const remoteReactions = await reactionsContainer.$$( - SELECTORS.EMOJI_REACTION_REMOTE + SELECTORS.EMOJI_REACTION_REMOTE, ); let results = []; for (let reaction of remoteReactions) { @@ -441,7 +445,7 @@ export default class MessageGroup extends UplinkMainScreen { const reactionsContainer = await this.getLastMessageSentReactionsContainer(); const selfReactions = await reactionsContainer.$$( - SELECTORS.EMOJI_REACTION_SELF + SELECTORS.EMOJI_REACTION_SELF, ); let results = []; for (let reaction of selfReactions) { @@ -452,7 +456,10 @@ export default class MessageGroup extends UplinkMainScreen { return results; } - async waitUntilEmojiReactionRemoteExists(expectedReaction: string) { + async waitUntilEmojiReactionRemoteExists( + expectedReaction: string, + timeout: number = 15000, + ) { const currentDriver = await this.getCurrentDriver(); let emojiReactionLocator: string = ""; if (currentDriver === MACOS_DRIVER) { @@ -468,17 +475,22 @@ export default class MessageGroup extends UplinkMainScreen { } await driver[this.executor].waitUntil( async () => { - return await this.instance.$(emojiReactionLocator); + return await this.instance + .$(emojiReactionLocator) + .waitForExist({ timeout: timeout }); }, { - timeout: 15000, + timeout: 60000, timeoutMsg: - "Expected remote emoji reaction is still not displayed after 15 seconds", - } + "Expected remote emoji reaction is still not displayed after 60 seconds", + }, ); } - async waitUntilEmojiReactionSelfExists(expectedReaction: string) { + async waitUntilEmojiReactionSelfExists( + expectedReaction: string, + timeout: number = 15000, + ) { const currentDriver = await this.getCurrentDriver(); let emojiReactionLocator: string = ""; if (currentDriver === MACOS_DRIVER) { @@ -494,13 +506,15 @@ export default class MessageGroup extends UplinkMainScreen { } await driver[this.executor].waitUntil( async () => { - return await this.instance.$(emojiReactionLocator); + return await this.instance + .$(emojiReactionLocator) + .waitForExist({ timeout: timeout }); }, { timeout: 15000, timeoutMsg: "Expected self emoji reaction is still not displayed after 15 seconds", - } + }, ); } @@ -509,7 +523,7 @@ export default class MessageGroup extends UplinkMainScreen { async getFirstMessageInLastGroupReceived() { const lastGroupSent = await this.getLastReceivedGroup(); const firstMessage = await lastGroupSent.$( - SELECTORS.CHAT_MESSAGE_LOCAL_FIRST + SELECTORS.CHAT_MESSAGE_LOCAL_FIRST, ); return firstMessage; } @@ -517,7 +531,7 @@ export default class MessageGroup extends UplinkMainScreen { async getLastMessageInLastGroupReceived() { const lastGroupSent = await this.getLastReceivedGroup(); const lastMessage = await lastGroupSent.$( - SELECTORS.CHAT_MESSAGE_LOCAL_LAST + SELECTORS.CHAT_MESSAGE_LOCAL_LAST, ); return lastMessage; } @@ -525,19 +539,19 @@ export default class MessageGroup extends UplinkMainScreen { async getMiddleMessageInLastGroupReceived(index: number) { const lastGroupSent = await this.getLastReceivedGroup(); const middleMessage = await lastGroupSent.$$( - SELECTORS.CHAT_MESSAGE_LOCAL_MIDDLE + SELECTORS.CHAT_MESSAGE_LOCAL_MIDDLE, )[index]; return middleMessage; } // Pin Indicator validations - async validateLastMessageReceivedHasPinIndicator() { + async validateLastMessageReceivedHasPinIndicator(timeout: number = 15000) { const pinIndicator = await this.getLastMessageReceivedPinIndicator(); - await pinIndicator.waitForExist(); + await pinIndicator.waitForExist({ timeout: timeout }); } - async validateLastMessageSentHasPinIndicator() { + async validateLastMessageSentHasPinIndicator(timeout: number = 15000) { const pinIndicator = await this.getLastMessageSentPinIndicator(); - await pinIndicator.waitForExist(); + await pinIndicator.waitForExist({ timeout: timeout }); } } diff --git a/tests/screenobjects/chats/Messages.ts b/tests/screenobjects/chats/Messages.ts index 1445bc474d..e4ba55a37a 100644 --- a/tests/screenobjects/chats/Messages.ts +++ b/tests/screenobjects/chats/Messages.ts @@ -95,7 +95,7 @@ export default class Messages extends UplinkMainScreen { constructor(executor: string) { super( executor, - SELECTORS.CHAT_MESSAGE_LOCAL || SELECTORS.CHAT_MESSAGE_REMOTE + SELECTORS.CHAT_MESSAGE_LOCAL || SELECTORS.CHAT_MESSAGE_REMOTE, ); } @@ -309,17 +309,17 @@ export default class Messages extends UplinkMainScreen { const message = await this.getLastMessageReceivedLocator(); const messageText = await message.$(SELECTORS.CHAT_MESSAGE_TEXT_GROUP); const messageCodeLanguage = await messageText.$( - SELECTORS.CHAT_MESSAGE_CODE_LANGUAGE + SELECTORS.CHAT_MESSAGE_CODE_LANGUAGE, ); return messageCodeLanguage; } - async getLastMessageReceivedCodePane() { + async getLastMessageReceivedCodePane(timeout: number = 15000) { const message = await this.getLastMessageReceivedLocator(); const messageCodePane = await message .$(SELECTORS.CHAT_MESSAGE_TEXT_GROUP) .$(SELECTORS.CHAT_MESSAGE_CODE_PANE); - await messageCodePane.waitForExist(); + await messageCodePane.waitForExist({ timeout: timeout }); return messageCodePane; } @@ -327,7 +327,7 @@ export default class Messages extends UplinkMainScreen { const messageCodePane = await this.getLastMessageReceivedCodePane(); let messageResult = ""; const messageResultElements = await messageCodePane.$$( - SELECTORS.CHAT_MESSAGE_CODE_MESSAGES + SELECTORS.CHAT_MESSAGE_CODE_MESSAGES, ); for (let element of messageResultElements) { const codeMessageText = await element.getText(); @@ -336,7 +336,10 @@ export default class Messages extends UplinkMainScreen { return messageResult; } - async getMessageReceivedLocator(expectedMessage: string) { + async getMessageReceivedLocator( + expectedMessage: string, + timeout: number = 60000, + ) { const currentDriver = await this.getCurrentDriver(); let locator: string = ""; if (currentDriver === MACOS_DRIVER) { @@ -352,12 +355,14 @@ export default class Messages extends UplinkMainScreen { } await driver[this.executor].waitUntil( async () => { - return await this.instance.$(locator); + return await this.instance + .$(locator) + .waitForExist({ timeout: timeout }); }, { - timeout: 15000, - timeoutMsg: "Expected message was never received after 15 seconds", - } + timeout: timeout, + timeoutMsg: "Expected message was never received", + }, ); const element = await this.instance.$(locator); return element; @@ -370,12 +375,12 @@ export default class Messages extends UplinkMainScreen { return lastMessage; } - async getLastMessageReceivedText() { + async getLastMessageReceivedText(timeout: number = 15000) { const message = await this.getLastMessageReceivedLocator(); const messageText = await message .$(SELECTORS.CHAT_MESSAGE_TEXT_GROUP) .$(SELECTORS.CHAT_MESSAGE_TEXT_VALUE); - await messageText.waitForExist(); + await messageText.waitForExist({ timeout: timeout }); return messageText; } @@ -385,18 +390,18 @@ export default class Messages extends UplinkMainScreen { return firstMessage; } - async getFirstMessageReceivedText() { + async getFirstMessageReceivedText(timeout: number = 15000) { const message = await this.getFirstMessageReceivedLocator(); const messageText = await message .$(SELECTORS.CHAT_MESSAGE_TEXT_GROUP) .$(SELECTORS.CHAT_MESSAGE_TEXT_VALUE); - await messageText.waitForExist(); + await messageText.waitForExist({ timeout: timeout }); return messageText; } async waitForCodeMessageSentToExist( expectedLanguage: string, - timeoutMsg: number = 30000 + timeout: number = 15000, ) { const currentDriver = await this.getCurrentDriver(); let codeMessageLocator: string = ""; @@ -413,12 +418,14 @@ export default class Messages extends UplinkMainScreen { } await driver[this.executor].waitUntil( async () => { - return await this.instance.$(codeMessageLocator); + return await this.instance + .$(codeMessageLocator) + .waitForExist({ timeout: timeout }); }, { - timeout: 15000, - timeoutMsg: "Expected code message was never sent after 15 seconds", - } + timeout: timeout, + timeoutMsg: "Expected code message was never sent after waiting", + }, ); } @@ -431,7 +438,7 @@ export default class Messages extends UplinkMainScreen { .$( '//XCUIElementTypeGroup[@label="message-text"]//XCUIElementTypeStaticText[contains(@value, "' + expectedMessage + - '")]' + '")]', ) .waitForExist({ reverse: true }); } else if (currentDriver === WINDOWS_DRIVER) { @@ -439,7 +446,7 @@ export default class Messages extends UplinkMainScreen { .$( '//Group[@Name="message-text"]//Text[contains(@Name, "' + expectedMessage + - '")]' + '")]', ) .waitForExist({ reverse: true }); } @@ -447,11 +454,14 @@ export default class Messages extends UplinkMainScreen { { timeout: 15000, timeoutMsg: "Expected message was not deleted after 15 seconds", - } + }, ); } - async waitForLinkSentToExist(expectedMessage: string) { + async waitForLinkSentToExist( + expectedMessage: string, + timeout: number = 15000, + ) { const currentDriver = await this.getCurrentDriver(); let linkSentLocator: string = ""; if (currentDriver === MACOS_DRIVER) { @@ -467,17 +477,22 @@ export default class Messages extends UplinkMainScreen { } await driver[this.executor].waitUntil( async () => { - return await this.instance.$(linkSentLocator); + return await this.instance + .$(linkSentLocator) + .waitForExist({ timeout: timeout }); }, { - timeout: 15000, + timeout: timeout, timeoutMsg: - "Expected chat message with link was not sent after 15 seconds", - } + "Expected chat message with link was not sent after waiting", + }, ); } - async waitForMessageSentToExist(expectedMessage: string) { + async waitForMessageSentToExist( + expectedMessage: string, + timeout: number = 15000, + ) { const currentDriver = await this.getCurrentDriver(); let messageSentLocator: string = ""; if (currentDriver === MACOS_DRIVER) { @@ -493,16 +508,21 @@ export default class Messages extends UplinkMainScreen { } await driver[this.executor].waitUntil( async () => { - return await this.instance.$(messageSentLocator); + return await this.instance + .$(messageSentLocator) + .waitForExist({ timeout: timeout }); }, { - timeout: 15000, - timeoutMsg: "Expected chat message was not sent after 15 seconds", - } + timeout: timeout, + timeoutMsg: "Expected chat message was not sent", + }, ); } - async waitForReceivingCodeMessage(expectedLanguage: string) { + async waitForReceivingCodeMessage( + expectedLanguage: string, + timeout: number = 60000, + ) { const currentDriver = await this.getCurrentDriver(); let codeMessageReceivedLocator: string = ""; if (currentDriver === MACOS_DRIVER) { @@ -519,16 +539,18 @@ export default class Messages extends UplinkMainScreen { await driver[this.executor].waitUntil( async () => { - return await this.instance.$(codeMessageReceivedLocator); + return await this.instance + .$(codeMessageReceivedLocator) + .waitForExist({ timeout: timeout }); }, { - timeout: 15000, - timeoutMsg: "Expected code message was not received after 15 seconds", - } + timeout: timeout, + timeoutMsg: "Expected code message was not received", + }, ); } - async waitForReceivingLink(expectedMessage: string) { + async waitForReceivingLink(expectedMessage: string, timeout: number = 60000) { const currentDriver = await this.getCurrentDriver(); let linkReceivedLocator: string = ""; if (currentDriver === MACOS_DRIVER) { @@ -545,16 +567,21 @@ export default class Messages extends UplinkMainScreen { await driver[this.executor].waitUntil( async () => { - return await this.instance.$(linkReceivedLocator); + return await this.instance + .$(linkReceivedLocator) + .waitForExist({ timeout: timeout }); }, { - timeout: 15000, - timeoutMsg: "Expected link message was not received after 15 seconds", - } + timeout: timeout, + timeoutMsg: "Expected link message was not received", + }, ); } - async waitForReceivingMessage(expectedMessage: string) { + async waitForReceivingMessage( + expectedMessage: string, + timeout: number = 60000, + ) { const currentDriver = await this.getCurrentDriver(); let receivedMessageLocator: string = ""; if (currentDriver === MACOS_DRIVER) { @@ -571,12 +598,14 @@ export default class Messages extends UplinkMainScreen { await driver[this.executor].waitUntil( async () => { - return await this.instance.$(receivedMessageLocator); + return await this.instance + .$(receivedMessageLocator) + .waitForExist({ timeout: timeout }); }, { - timeout: 15000, - timeoutMsg: "Expected chat message was not received after 15 seconds", - } + timeout: timeout, + timeoutMsg: "Expected chat message was not received", + }, ); } @@ -588,31 +617,31 @@ export default class Messages extends UplinkMainScreen { await copyButton.click(); } - async getLastMessageSentCodeCopyButton() { + async getLastMessageSentCodeCopyButton(timeout: number = 15000) { const message = await this.getLastMessageSentLocator(); const messageCodeCopyButton = await message .$(SELECTORS.CHAT_MESSAGE_TEXT_GROUP) .$(SELECTORS.CHAT_MESSAGE_CODE_COPY_BUTTON); - await messageCodeCopyButton.waitForExist(); + await messageCodeCopyButton.waitForExist({ timeout: timeout }); return messageCodeCopyButton; } - async getLastMessageSentCodeLanguage() { + async getLastMessageSentCodeLanguage(timeout: number = 15000) { const message = await this.getLastMessageSentLocator(); const messageText = await message.$(SELECTORS.CHAT_MESSAGE_TEXT_GROUP); const messageCodeLanguage = await messageText.$( - SELECTORS.CHAT_MESSAGE_CODE_LANGUAGE + SELECTORS.CHAT_MESSAGE_CODE_LANGUAGE, ); - await messageCodeLanguage.waitForExist(); + await messageCodeLanguage.waitForExist({ timeout: timeout }); return messageCodeLanguage; } - async getLastMessageSentCodePane() { + async getLastMessageSentCodePane(timeout: number = 15000) { const message = await this.getLastMessageSentLocator(); const messageCodePane = await message .$(SELECTORS.CHAT_MESSAGE_TEXT_GROUP) .$(SELECTORS.CHAT_MESSAGE_CODE_PANE); - await messageCodePane.waitForExist(); + await messageCodePane.waitForExist({ timeout: timeout }); return messageCodePane; } @@ -620,7 +649,7 @@ export default class Messages extends UplinkMainScreen { const messageCodePane = await this.getLastMessageSentCodePane(); let messageResult = ""; const messageResultElements = await messageCodePane.$$( - SELECTORS.CHAT_MESSAGE_CODE_MESSAGES + SELECTORS.CHAT_MESSAGE_CODE_MESSAGES, ); for (let element of messageResultElements) { const codeMessageText = await element.getText(); @@ -629,7 +658,10 @@ export default class Messages extends UplinkMainScreen { return messageResult; } - async getMessageSentLocator(expectedMessage: string) { + async getMessageSentLocator( + expectedMessage: string, + timeout: number = 15000, + ) { const currentDriver = await this.getCurrentDriver(); let messageSentLocator: string = ""; if (currentDriver === MACOS_DRIVER) { @@ -646,12 +678,14 @@ export default class Messages extends UplinkMainScreen { await driver[this.executor].waitUntil( async () => { - return await this.instance.$(messageSentLocator); + return await this.instance + .$(messageSentLocator) + .waitForExist({ timeout: timeout }); }, { - timeout: 15000, - timeoutMsg: "Expected chat message was not sent after 15 seconds", - } + timeout: timeout, + timeoutMsg: "Expected chat message was not sent", + }, ); } @@ -662,12 +696,12 @@ export default class Messages extends UplinkMainScreen { return lastMessage; } - async getLastMessageSentText() { + async getLastMessageSentText(timeout: number = 15000) { const message = await this.getLastMessageSentLocator(); const messageText = await message .$(SELECTORS.CHAT_MESSAGE_TEXT_GROUP) .$(SELECTORS.CHAT_MESSAGE_TEXT_VALUE); - await messageText.waitForExist(); + await messageText.waitForExist({ timeout: timeout }); return messageText; } @@ -677,27 +711,27 @@ export default class Messages extends UplinkMainScreen { return firstMessage; } - async getFirstMessageSentText() { + async getFirstMessageSentText(timeout: number = 15000) { const message = await this.getFirstMessageSentLocator(); const messageText = await message .$(SELECTORS.CHAT_MESSAGE_TEXT_GROUP) .$(SELECTORS.CHAT_MESSAGE_TEXT_VALUE); - await messageText.waitForExist(); + await messageText.waitForExist({ timeout: timeout }); return messageText; } // Replies Methods - async getLastReply() { + async getLastReply(timeout: number = 15000) { const lastReply = await this.chatMessageReply; - await lastReply.waitForExist(); + await lastReply.waitForExist({ timeout: timeout }); return lastReply; } - async getLastReplyText() { + async getLastReplyText(timeout: number = 15000) { const lastGroup = await this.chatMessageReply; const lastReplyText = await lastGroup.$(SELECTORS.CHAT_MESSAGE_REPLY_TEXT); - await lastReplyText.waitForExist(); + await lastReplyText.waitForExist({ timeout: timeout }); return lastReplyText; } @@ -763,93 +797,93 @@ export default class Messages extends UplinkMainScreen { // Messages With Files Methods - async getLastMessageReceivedDownloadButton() { + async getLastMessageReceivedDownloadButton(timeout: number = 15000) { const lastMessage = await this.getLastMessageReceivedLocator(); const getLastMessageDownloadButton = await lastMessage.$( - SELECTORS.CHAT_MESSAGE_FILE_BUTTON + SELECTORS.CHAT_MESSAGE_FILE_BUTTON, ); - await getLastMessageDownloadButton.waitForExist(); + await getLastMessageDownloadButton.waitForExist({ timeout: timeout }); return getLastMessageDownloadButton; } - async getLastMessageReceivedFileEmbed() { + async getLastMessageReceivedFileEmbed(timeout: number = 15000) { const lastMessage = await this.getLastMessageReceivedLocator(); const lastMessageFileEmbed = await lastMessage.$( - SELECTORS.CHAT_MESSAGE_FILE_EMBED_REMOTE + SELECTORS.CHAT_MESSAGE_FILE_EMBED_REMOTE, ); - await lastMessageFileEmbed.waitForExist(); + await lastMessageFileEmbed.waitForExist({ timeout: timeout }); return lastMessageFileEmbed; } - async getLastMessageReceivedFileIcon() { + async getLastMessageReceivedFileIcon(timeout: number = 15000) { const lastMessage = await this.getLastMessageReceivedLocator(); const lastMessageFileIcon = await lastMessage.$( - SELECTORS.CHAT_MESSAGE_FILE_ICON + SELECTORS.CHAT_MESSAGE_FILE_ICON, ); - await lastMessageFileIcon.waitForExist(); + await lastMessageFileIcon.waitForExist({ timeout: timeout }); return lastMessageFileIcon; } - async getLastMessageReceivedFileMeta() { + async getLastMessageReceivedFileMeta(timeout: number = 15000) { const lastMessage = await this.getLastMessageReceivedLocator(); const lastMessageFileMeta = await lastMessage .$(SELECTORS.CHAT_MESSAGE_FILE_META) .$(SELECTORS.CHAT_MESSAGE_FILE_META_TEXT); - await lastMessageFileMeta.waitForExist(); + await lastMessageFileMeta.waitForExist({ timeout: timeout }); return lastMessageFileMeta; } - async getLastMessageReceivedFileName() { + async getLastMessageReceivedFileName(timeout: number = 15000) { const lastMessage = await this.getLastMessageReceivedLocator(); const lastMessageFileName = await lastMessage .$(SELECTORS.CHAT_MESSAGE_FILE_NAME) .$(SELECTORS.CHAT_MESSAGE_FILE_NAME_TEXT); - await lastMessageFileName.waitForExist(); + await lastMessageFileName.waitForExist({ timeout: timeout }); return lastMessageFileName; } - async getLastMessageSentDownloadButton() { + async getLastMessageSentDownloadButton(timeout: number = 15000) { const lastMessage = await this.getLastMessageSentLocator(); const getLastMessageSentDownloadButton = await lastMessage.$( - SELECTORS.CHAT_MESSAGE_FILE_BUTTON + SELECTORS.CHAT_MESSAGE_FILE_BUTTON, ); - await getLastMessageSentDownloadButton.waitForExist(); + await getLastMessageSentDownloadButton.waitForExist({ timeout: timeout }); return getLastMessageSentDownloadButton; } - async getLastMessageSentFileEmbed() { + async getLastMessageSentFileEmbed(timeout: number = 15000) { const lastMessage = await this.getLastMessageSentLocator(); const lastMessageFileEmbed = await lastMessage.$( - SELECTORS.CHAT_MESSAGE_FILE_EMBED + SELECTORS.CHAT_MESSAGE_FILE_EMBED, ); - await lastMessageFileEmbed.waitForExist(); + await lastMessageFileEmbed.waitForExist({ timeout: timeout }); return lastMessageFileEmbed; } - async getLastMessageSentFileIcon() { + async getLastMessageSentFileIcon(timeout: number = 15000) { const lastMessage = await this.getLastMessageSentLocator(); const lastMessageFileIcon = await lastMessage.$( - SELECTORS.CHAT_MESSAGE_FILE_ICON + SELECTORS.CHAT_MESSAGE_FILE_ICON, ); - await lastMessageFileIcon.waitForExist(); + await lastMessageFileIcon.waitForExist({ timeout: timeout }); return lastMessageFileIcon; } - async getLastMessageSentFileMeta() { + async getLastMessageSentFileMeta(timeout: number = 15000) { const lastMessage = await this.getLastMessageSentLocator(); const lastMessageFileMeta = await lastMessage .$(SELECTORS.CHAT_MESSAGE_FILE_META) .$(SELECTORS.CHAT_MESSAGE_FILE_META_TEXT); - await lastMessageFileMeta.waitForExist(); + await lastMessageFileMeta.waitForExist({ timeout: timeout }); return lastMessageFileMeta; } - async getLastMessageSentFileName() { + async getLastMessageSentFileName(timeout: number = 15000) { const lastMessage = await this.getLastMessageSentLocator(); const lastMessageFileName = await lastMessage .$(SELECTORS.CHAT_MESSAGE_FILE_NAME) .$(SELECTORS.CHAT_MESSAGE_FILE_NAME_TEXT); - await lastMessageFileName.waitForExist(); + await lastMessageFileName.waitForExist({ timeout: timeout }); return lastMessageFileName; } @@ -857,74 +891,74 @@ export default class Messages extends UplinkMainScreen { async getLastMessageReceivedLinkEmbed() { const lastMessage = await this.getLastMessageReceivedLocator(); const lastMessageLinkEmbed = await lastMessage.$( - SELECTORS.CHAT_MESSAGE_LINK_EMBED + SELECTORS.CHAT_MESSAGE_LINK_EMBED, ); await lastMessageLinkEmbed.waitForExist({ timeout: 30000 }); return lastMessageLinkEmbed; } - async getLastMessageReceivedLinkEmbedDetailsText() { + async getLastMessageReceivedLinkEmbedDetailsText(timeout: number = 15000) { const linkEmbedLastMessage = await this.getLastMessageReceivedLinkEmbed(); const linkEmbedDetailsText = await linkEmbedLastMessage .$(SELECTORS.CHAT_MESSAGE_LINK_EMBED_DETAILS) .$(SELECTORS.CHAT_MESSAGE_LINK_EMBED_DETAILS_TEXT); - await linkEmbedDetailsText.waitForExist(); + await linkEmbedDetailsText.waitForExist({ timeout: timeout }); return linkEmbedDetailsText; } - async getLastMessageReceivedLinkEmbedIcon() { + async getLastMessageReceivedLinkEmbedIcon(timeout: number = 15000) { const linkEmbedLastMessage = await this.getLastMessageReceivedLinkEmbed(); const linkEmbedIcon = await linkEmbedLastMessage.$( - SELECTORS.CHAT_MESSAGE_LINK_EMBED_ICON + SELECTORS.CHAT_MESSAGE_LINK_EMBED_ICON, ); - await linkEmbedIcon.waitForExist(); + await linkEmbedIcon.waitForExist({ timeout: timeout }); return linkEmbedIcon; } - async getLastMessageReceivedLinkEmbedIconTitle() { + async getLastMessageReceivedLinkEmbedIconTitle(timeout: number = 15000) { const linkEmbedIconLastMessage = await this.getLastMessageReceivedLinkEmbedIcon(); const iconTitle = await linkEmbedIconLastMessage.$( - SELECTORS.CHAT_MESSAGE_LINK_EMBED_TITLE + SELECTORS.CHAT_MESSAGE_LINK_EMBED_TITLE, ); - await iconTitle.waitForExist(); + await iconTitle.waitForExist({ timeout: timeout }); return iconTitle; } async getLastMessageSentLinkEmbed() { const lastMessage = await this.getLastMessageSentLocator(); const lastMessageLinkEmbed = await lastMessage.$( - SELECTORS.CHAT_MESSAGE_LINK_EMBED + SELECTORS.CHAT_MESSAGE_LINK_EMBED, ); await lastMessageLinkEmbed.waitForExist({ timeout: 30000 }); return lastMessageLinkEmbed; } - async getLastMessageSentLinkEmbedDetailsText() { + async getLastMessageSentLinkEmbedDetailsText(timeout: number = 15000) { const linkEmbedLastMessage = await this.getLastMessageSentLinkEmbed(); const linkEmbedDetailsText = await linkEmbedLastMessage .$(SELECTORS.CHAT_MESSAGE_LINK_EMBED_DETAILS) .$(SELECTORS.CHAT_MESSAGE_LINK_EMBED_DETAILS_TEXT); - await linkEmbedDetailsText.waitForExist(); + await linkEmbedDetailsText.waitForExist({ timeout: timeout }); return linkEmbedDetailsText; } - async getLastMessageSentLinkEmbedIcon() { + async getLastMessageSentLinkEmbedIcon(timeout: number = 15000) { const linkEmbedLastMessage = await this.getLastMessageSentLinkEmbed(); const linkEmbedIcon = await linkEmbedLastMessage.$( - SELECTORS.CHAT_MESSAGE_LINK_EMBED_ICON + SELECTORS.CHAT_MESSAGE_LINK_EMBED_ICON, ); - await linkEmbedIcon.waitForExist(); + await linkEmbedIcon.waitForExist({ timeout: timeout }); return linkEmbedIcon; } - async getLastMessageSentLinkEmbedIconTitle() { + async getLastMessageSentLinkEmbedIconTitle(timeout: number = 15000) { const linkEmbedIconLastMessage = await this.getLastMessageSentLinkEmbedIcon(); const iconTitle = await linkEmbedIconLastMessage.$( - SELECTORS.CHAT_MESSAGE_LINK_EMBED_TITLE + SELECTORS.CHAT_MESSAGE_LINK_EMBED_TITLE, ); - await iconTitle.waitForExist(); + await iconTitle.waitForExist({ timeout: timeout }); return iconTitle; } diff --git a/tests/screenobjects/chats/PinnedMessages.ts b/tests/screenobjects/chats/PinnedMessages.ts index 2b35c139be..e461de2a98 100644 --- a/tests/screenobjects/chats/PinnedMessages.ts +++ b/tests/screenobjects/chats/PinnedMessages.ts @@ -88,49 +88,49 @@ export default class PinnedMessages extends UplinkMainScreen { get pinnedMessageAttachmentsFileEmbed() { return this.pinnedMessageAttachments.$( - SELECTORS.PINNED_MESSAGE_ATTACHMENTS_FILE_EMBED + SELECTORS.PINNED_MESSAGE_ATTACHMENTS_FILE_EMBED, ); } get pinnedMessageAttachmentsFileIcon() { return this.pinnedMessageAttachmentsFileEmbed.$( - SELECTORS.PINNED_MESSAGE_ATTACHMENTS_FILE_ICON + SELECTORS.PINNED_MESSAGE_ATTACHMENTS_FILE_ICON, ); } get pinnedMessageAttachmentsFileIconExtension() { return this.pinnedMessageAttachmentsFileIcon.$( - SELECTORS.PINNED_MESSAGE_ATTACHMENTS_FILE_ICON_EXTENSION + SELECTORS.PINNED_MESSAGE_ATTACHMENTS_FILE_ICON_EXTENSION, ); } get pinnedMessageAttachmentsFileInfo() { return this.pinnedMessageAttachmentsFileEmbed.$( - SELECTORS.PINNED_MESSAGE_ATTACHMENTS_FILE_INFO + SELECTORS.PINNED_MESSAGE_ATTACHMENTS_FILE_INFO, ); } get pinnedMessageAttachmentsFileMeta() { return this.pinnedMessageAttachmentsFileInfo.$( - SELECTORS.PINNED_MESSAGE_ATTACHMENTS_FILE_META + SELECTORS.PINNED_MESSAGE_ATTACHMENTS_FILE_META, ); } get pinnedMessageAttachmentsFileMetaText() { return this.pinnedMessageAttachmentsFileMeta.$( - SELECTORS.PINNED_MESSAGE_ATTACHMENTS_FILE_META_TEXT + SELECTORS.PINNED_MESSAGE_ATTACHMENTS_FILE_META_TEXT, ); } get pinnedMessageAttachmentsFileName() { return this.pinnedMessageAttachmentsFileInfo.$( - SELECTORS.PINNED_MESSAGE_ATTACHMENTS_FILE_NAME + SELECTORS.PINNED_MESSAGE_ATTACHMENTS_FILE_NAME, ); } get pinnedMessageAttachmentsFileNameText() { return this.pinnedMessageAttachmentsFileName.$( - SELECTORS.PINNED_MESSAGE_ATTACHMENTS_FILE_NAME_TEXT + SELECTORS.PINNED_MESSAGE_ATTACHMENTS_FILE_NAME_TEXT, ); } @@ -164,19 +164,19 @@ export default class PinnedMessages extends UplinkMainScreen { get pinnedMessageTimestampText() { return this.pinnedMessageTimestamp.$( - SELECTORS.PINNED_MESSAGE_TIMESTAMP_TEXT + SELECTORS.PINNED_MESSAGE_TIMESTAMP_TEXT, ); } get pinnedMessageUserImage() { return this.pinnedMessageUserImageWrap.$( - SELECTORS.PINNED_MESSAGE_USER_IMAGE + SELECTORS.PINNED_MESSAGE_USER_IMAGE, ); } get pinnedMessageUserImageProfile() { return this.pinnedMessageUserImage.$( - SELECTORS.PINNED_MESSAGE_USER_IMAGE_PROFILE + SELECTORS.PINNED_MESSAGE_USER_IMAGE_PROFILE, ); } @@ -243,80 +243,80 @@ export default class PinnedMessages extends UplinkMainScreen { async getPinnedMessageAttachment( orderPinned: number, - attachmentNumber: number + attachmentNumber: number, ) { const pinnedContainerByIndex = await this.getPinnedMessageLocatorByAdditionOrder(orderPinned); const attachmentOnPinnedMessage = await pinnedContainerByIndex.$$( - SELECTORS.PINNED_MESSAGE_ATTACHMENTS + SELECTORS.PINNED_MESSAGE_ATTACHMENTS, )[attachmentNumber]; return attachmentOnPinnedMessage; } async getPinnedMessageAttachmentFileEmbed( orderPinned: number, - attachmentNumber: number + attachmentNumber: number, ) { const attachmentOnPinnedMessage = await this.getPinnedMessageAttachment( orderPinned, - attachmentNumber + attachmentNumber, ); const attachmentFileEmbed = await attachmentOnPinnedMessage.$( - SELECTORS.PINNED_MESSAGE_ATTACHMENTS_FILE_EMBED + SELECTORS.PINNED_MESSAGE_ATTACHMENTS_FILE_EMBED, ); return attachmentFileEmbed; } async getPinnedMessageAttachmentFileIcon( orderPinned: number, - attachmentNumber: number + attachmentNumber: number, ) { const attachmentOnPinnedFileEmbed = await this.getPinnedMessageAttachmentFileEmbed( orderPinned, - attachmentNumber + attachmentNumber, ); const attachmentFileIcon = await attachmentOnPinnedFileEmbed.$( - SELECTORS.PINNED_MESSAGE_ATTACHMENTS_FILE_ICON + SELECTORS.PINNED_MESSAGE_ATTACHMENTS_FILE_ICON, ); return attachmentFileIcon; } async getPinnedMessageAttachmentFileIconExtension( orderPinned: number, - attachmentNumber: number + attachmentNumber: number, ) { const attachmentFileIcon = await this.getPinnedMessageAttachmentFileIcon( orderPinned, - attachmentNumber + attachmentNumber, ); const attachmentFileIconExtension = await attachmentFileIcon.$( - SELECTORS.PINNED_MESSAGE_ATTACHMENTS_FILE_ICON_EXTENSION + SELECTORS.PINNED_MESSAGE_ATTACHMENTS_FILE_ICON_EXTENSION, ); return attachmentFileIconExtension; } async getPinnedMessageAttachmentFileInfo( orderPinned: number, - attachmentNumber: number + attachmentNumber: number, ) { const attachmentFileEmbed = await this.getPinnedMessageAttachmentFileEmbed( orderPinned, - attachmentNumber + attachmentNumber, ); const attachmentFileInfo = await attachmentFileEmbed.$( - SELECTORS.PINNED_MESSAGE_ATTACHMENTS_FILE_INFO + SELECTORS.PINNED_MESSAGE_ATTACHMENTS_FILE_INFO, ); return attachmentFileInfo; } async getPinnedMessageAttachmentFileMetaText( orderPinned: number, - attachmentNumber: number + attachmentNumber: number, ) { const attachmentFileInfo = await this.getPinnedMessageAttachmentFileInfo( orderPinned, - attachmentNumber + attachmentNumber, ); const fileMetaText = await attachmentFileInfo .$(SELECTORS.PINNED_MESSAGE_ATTACHMENTS_FILE_META) @@ -326,11 +326,11 @@ export default class PinnedMessages extends UplinkMainScreen { async getPinnedMessageAttachmentFileNameText( orderPinned: number, - attachmentNumber: number + attachmentNumber: number, ) { const attachmentFileInfo = await this.getPinnedMessageAttachmentFileInfo( orderPinned, - attachmentNumber + attachmentNumber, ); const fileNameText = await attachmentFileInfo .$(SELECTORS.PINNED_MESSAGE_ATTACHMENTS_FILE_NAME) @@ -342,7 +342,7 @@ export default class PinnedMessages extends UplinkMainScreen { const pinnedContainerByIndex = await this.getPinnedMessageLocatorByAdditionOrder(orderPinned); const goToButton = await pinnedContainerByIndex.$( - SELECTORS.PINNED_MESSAGE_BUTTON_GO_TO + SELECTORS.PINNED_MESSAGE_BUTTON_GO_TO, ); return goToButton; } @@ -351,7 +351,7 @@ export default class PinnedMessages extends UplinkMainScreen { const pinnedContainerByIndex = await this.getPinnedMessageLocatorByAdditionOrder(orderPinned); const unpinButton = await pinnedContainerByIndex.$( - SELECTORS.PINNED_MESSAGE_BUTTON_UNPIN + SELECTORS.PINNED_MESSAGE_BUTTON_UNPIN, ); return unpinButton; } @@ -378,7 +378,7 @@ export default class PinnedMessages extends UplinkMainScreen { const pinnedWrapByIndex = await this.getPinnedMessageWrapLocatorByAdditionOrder(orderPinned); const userImage = await pinnedWrapByIndex.$( - SELECTORS.PINNED_MESSAGE_USER_IMAGE + SELECTORS.PINNED_MESSAGE_USER_IMAGE, ); return userImage; } @@ -387,7 +387,7 @@ export default class PinnedMessages extends UplinkMainScreen { const pinnedWrapByIndex = await this.getPinnedMessageWrapLocatorByAdditionOrder(orderPinned); const userImageProfile = await pinnedWrapByIndex.$( - SELECTORS.PINNED_MESSAGE_USER_IMAGE_PROFILE + SELECTORS.PINNED_MESSAGE_USER_IMAGE_PROFILE, ); return userImageProfile; } @@ -411,13 +411,13 @@ export default class PinnedMessages extends UplinkMainScreen { return await pinnedMessagesMain.waitForDisplayed(); } - async validateFirstPinnedMessageAttachmentFileIcon() { + async validateFirstPinnedMessageAttachmentFileIcon(timeout: number = 15000) { const attachmentIcon = await this.getPinnedMessageAttachmentFileIcon(0, 0); - await attachmentIcon.waitForExist(); + await attachmentIcon.waitForExist({ timeout: timeout }); } async validateFirstPinnedMessageAttachmentFileIconExtension( - extension: string + extension: string, ) { const attachmentExtension = await this.getPinnedMessageAttachmentFileIconExtension(0, 0); @@ -434,9 +434,9 @@ export default class PinnedMessages extends UplinkMainScreen { await expect(currentName).toHaveTextContaining(expectedName); } - async validateFirstPinnedMessageImageProfileIsShown() { + async validateFirstPinnedMessageImageProfileIsShown(timeout: number = 15000) { const imageProfile = await this.getPinnedMessageUserImageProfile(0); - await imageProfile.waitForExist(); + await imageProfile.waitForExist({ timeout: timeout }); } async validateFirstPinnedMessageSender(username: string) { @@ -452,7 +452,7 @@ export default class PinnedMessages extends UplinkMainScreen { async validateFirstPinnedMessageTimestampIsShown() { const timestamp = await this.getPinnedMessageTimestampText(0); await expect(timestamp).toHaveTextContaining( - /^(0[1-9]|[12][0-9]|3[01])\/(0[1-9]|1[0-2])\/\d{4}\s+(0[1-9]|1[0-2]):([0-5][0-9])\s+(AM|PM)$/ + /^(0[1-9]|[12][0-9]|3[01])\/(0[1-9]|1[0-2])\/\d{4}\s+(0[1-9]|1[0-2]):([0-5][0-9])\s+(AM|PM)$/, ); } } diff --git a/tests/screenobjects/chats/ReplyPrompt.ts b/tests/screenobjects/chats/ReplyPrompt.ts index 2c32bf7741..59058d4b95 100644 --- a/tests/screenobjects/chats/ReplyPrompt.ts +++ b/tests/screenobjects/chats/ReplyPrompt.ts @@ -142,25 +142,27 @@ export default class ReplyPrompt extends UplinkMainScreen { await replyPopUpCloseButton.click(); } - async validateReplyPromptElementsShown(message: string) { + async validateReplyPromptElementsShown( + message: string, + timeout: number = 15000, + ) { const replyPopUp = await this.replyPopUp; const replyPopUpCloseButton = await this.replyPopUpCloseButton; const replyPopUpUserImage = await this.replyPopUpUserImage; const replyPopUpIndicator = await this.replyPopUpIndicator; - await replyPopUp.waitForExist(); - await replyPopUpCloseButton.waitForExist(); - await replyPopUpUserImage.waitForExist(); - await replyPopUpIndicator.waitForExist(); + await replyPopUp.waitForExist({ timeout: timeout }); + await replyPopUpCloseButton.waitForExist({ timeout: timeout }); + await replyPopUpUserImage.waitForExist({ timeout: timeout }); + await replyPopUpIndicator.waitForExist({ timeout: timeout }); await driver[this.executor].waitUntil( async () => { return (await this.replyPopUpHeader.getText()) === "REPLYING TO:"; }, { - timeout: 15000, - timeoutMsg: - "Expected reply prompt header was incorrect after 15 seconds", - } + timeout: timeout, + timeoutMsg: "Expected reply prompt header was incorrect", + }, ); await driver[this.executor].waitUntil( @@ -170,10 +172,9 @@ export default class ReplyPrompt extends UplinkMainScreen { ); }, { - timeout: 15000, - timeoutMsg: - "Expected reply prompt header text to reply was incorrect after 15 seconds", - } + timeout: timeout, + timeoutMsg: "Expected reply prompt header text to reply was incorrect", + }, ); } @@ -185,7 +186,7 @@ export default class ReplyPrompt extends UplinkMainScreen { { timeout: 15000, timeoutMsg: "Expected reply modal is still visible after 15 seconds", - } + }, ); } } diff --git a/tests/screenobjects/chats/SendFiles.ts b/tests/screenobjects/chats/SendFiles.ts index 0fb3cd1805..d701f4265a 100644 --- a/tests/screenobjects/chats/SendFiles.ts +++ b/tests/screenobjects/chats/SendFiles.ts @@ -218,15 +218,15 @@ export default class SendFiles extends UplinkMainScreen { return result.toString(); } - async typeOnFileNameInput(name: string) { + async typeOnFileNameInput(name: string, timeout: number = 15000) { const inputFileName = await this.inputFileName; - await inputFileName.waitForExist(); + await inputFileName.waitForExist({ timeout: timeout }); await inputFileName.setValue(name); } - async typeOnFolderNameInput(name: string) { + async typeOnFolderNameInput(name: string, timeout: number = 15000) { const inputFolderName = await this.inputFolderName; - await inputFolderName.waitForExist(); + await inputFolderName.waitForExist({ timeout: timeout }); await inputFolderName.setValue(name); } @@ -234,7 +234,7 @@ export default class SendFiles extends UplinkMainScreen { const folders = await this.filesCrumb; const treeLength = folders.length - 1; const currentFolderName = await folders[treeLength].$( - SELECTORS.FILES_CRUMB_TEXT + SELECTORS.FILES_CRUMB_TEXT, ); const currentFolderNameText = await currentFolderName.getText(); return currentFolderNameText; @@ -270,28 +270,32 @@ export default class SendFiles extends UplinkMainScreen { return locator; } - async updateNameFile(newName: string, extension: string = "") { + async updateNameFile( + newName: string, + extension: string = "", + timeout: number = 15000, + ) { const inputFileName = await this.inputFileName; - await inputFileName.waitForExist(); + await inputFileName.waitForExist({ timeout: timeout }); await inputFileName.setValue(newName); const newFile = await this.getLocatorOfFolderFile(newName + extension); const newFileElement = await this.instance.$(newFile); - await newFileElement.waitForExist(); + await newFileElement.waitForExist({ timeout: timeout }); } - async updateNameFolder(newName: string) { + async updateNameFolder(newName: string, timeout: number = 15000) { const inputFolderName = await this.inputFolderName; - await inputFolderName.waitForExist(); + await inputFolderName.waitForExist({ timeout: timeout }); await inputFolderName.setValue(newName); const newFolder = await this.getLocatorOfFolderFile(newName); const newFolderElement = await this.instance.$(newFolder); - await newFolderElement.waitForExist(); + await newFolderElement.waitForExist({ timeout: timeout }); } - async validateFileOrFolderExist(locator: string) { + async validateFileOrFolderExist(locator: string, timeout: number = 15000) { const fileFolderElementLocator = await this.getLocatorOfFolderFile(locator); const fileFolderElement = await this.instance.$(fileFolderElementLocator); - await fileFolderElement.waitForExist(); + await fileFolderElement.waitForExist({ timeout: timeout }); } async validateFileOrFolderNotExist(locator: string) { @@ -299,9 +303,9 @@ export default class SendFiles extends UplinkMainScreen { await this.instance.$(fileFolderLocator).waitForExist({ reverse: true }); } - async validateNoFilesAvailableIsShown() { + async validateNoFilesAvailableIsShown(timeout: number = 15000) { const noFilesAvailable = await this.noFilesAvailable; - await noFilesAvailable.waitForExist(); + await noFilesAvailable.waitForExist({ timeout: timeout }); await expect(noFilesAvailable).toHaveTextContaining("NO FILES AVAILABLE."); } @@ -311,21 +315,21 @@ export default class SendFiles extends UplinkMainScreen { }); } - async validateSendFilesModalIsShown() { + async validateSendFilesModalIsShown(timeout: number = 15000) { const filesBody = await this.sendFilesLayout; - await filesBody.waitForExist(); + await filesBody.waitForExist({ timeout: timeout }); } - async validateThumbnailIsShown(name: string) { + async validateThumbnailIsShown(name: string, timeout: number = 15000) { const fileElementLocator = await this.getLocatorOfFolderFile(name); const fileElement = await this.instance.$(fileElementLocator); const fileThumbnail = await fileElement.$(SELECTORS.FILE_THUMBNAIL); - await fileThumbnail.waitForExist(); + await fileThumbnail.waitForExist({ timeout: timeout }); } // Context Menu methods - async openFilesContextMenu(name: string) { + async openFilesContextMenu(name: string, timeout: number = 15000) { const elementLocator = await this.getLocatorOfFolderFile(name); const fileFolderToRightClick = await this.instance .$(elementLocator) @@ -336,7 +340,7 @@ export default class SendFiles extends UplinkMainScreen { } else if (currentDriver === WINDOWS_DRIVER) { await rightClickOnWindows(fileFolderToRightClick, this.executor); } - await this.contextMenu.waitForExist(); + await this.contextMenu.waitForExist({ timeout: timeout }); } async clickOnFilesRename() { diff --git a/tests/screenobjects/chats/Topbar.ts b/tests/screenobjects/chats/Topbar.ts index 7599e9049b..ff60a1c094 100644 --- a/tests/screenobjects/chats/Topbar.ts +++ b/tests/screenobjects/chats/Topbar.ts @@ -223,19 +223,20 @@ export default class Topbar extends UplinkMainScreen { // Top Bar Methods - async addToFavorites() { + async addToFavorites(timeout: number = 15000) { const topbarAddToFavorites = await this.topbarAddToFavorites; await this.hoverOnElement(topbarAddToFavorites); await topbarAddToFavorites.click(); await driver[this.executor].waitUntil( async () => { - return await this.topbarRemoveFromFavorites; + return await this.topbarRemoveFromFavorites.waitForExist({ + timeout: timeout, + }); }, { - timeout: 15000, - timeoutMsg: - "Remove from favorites button was not displayed after passing 15 seconds from adding the same user of favorites", - } + timeout: timeout, + timeoutMsg: "Remove from favorites button was not displayed again", + }, ); } @@ -292,16 +293,18 @@ export default class Topbar extends UplinkMainScreen { await topbarRemoveFromFavorites.click(); } - async validateTopbarIndicatorOnline() { + async validateTopbarIndicatorOnline(timeout: number = 15000) { await driver[this.executor].waitUntil( async () => { - return await this.topbarIndicatorOnline; + return await this.topbarIndicatorOnline.waitForExist({ + timeout: timeout, + }); }, { - timeout: 15000, + timeout: timeout, timeoutMsg: - "Expected indicator online was never displayed on Chat Screen topbar after 15 seconds", - } + "Expected indicator online was never displayed on Chat Screen topbar", + }, ); } @@ -314,44 +317,46 @@ export default class Topbar extends UplinkMainScreen { timeout: 15000, timeoutMsg: "Expected username was never displayed on Chat Screen topbar after 15 seconds", - } + }, ); } - async validateTopbarUserImage() { + async validateTopbarUserImage(timeout: number = 15000) { await driver[this.executor].waitUntil( async () => { - return await this.topbarUserImage; + return await this.topbarUserImage.waitForExist({ timeout: timeout }); }, { timeout: 15000, timeoutMsg: "Expected user image was never displayed on Chat Screen topbar after 15 seconds", - } + }, ); } - async validateTopbarExists() { + async validateTopbarExists(timeout: number = 15000) { await driver[this.executor].waitUntil( async () => { - return await this.topbar; + return await this.topbar.waitForExist({ timeout: timeout }); }, { timeout: 15000, timeoutMsg: "Chats Topbar was never shown after 15 seconds", - } + }, ); } - async waitUntilRemoteUserIsOnline() { + async waitUntilRemoteUserIsOnline(timeout: number = 60000) { await driver[this.executor].waitUntil( async () => { - return await this.topbarIndicatorOnline; + return await this.topbarIndicatorOnline.waitForExist({ + timeout: timeout, + }); }, { - timeout: 15000, - timeoutMsg: "Remote user never shown as online after 15 seconds", - } + timeout: timeout, + timeoutMsg: "Remote user never shown as online", + }, ); } } diff --git a/tests/screenobjects/files/FilesScreen.ts b/tests/screenobjects/files/FilesScreen.ts index a72ee7601f..45e741a706 100644 --- a/tests/screenobjects/files/FilesScreen.ts +++ b/tests/screenobjects/files/FilesScreen.ts @@ -372,7 +372,7 @@ export default class FilesScreen extends UplinkMainScreen { } } - async createFolder(name: string) { + async createFolder(name: string, timeout: number = 15000) { await this.clickOnCreateFolder(); const inputFolderName = await this.inputFolderName; const filesInfoCurrentSizeLabel = await this.filesInfoCurrentSizeLabel; @@ -386,7 +386,7 @@ export default class FilesScreen extends UplinkMainScreen { await filesInfoCurrentSizeLabel.click(); const newFolder = await this.getLocatorOfFolderFile(name); const newFolderElement = await this.instance.$(newFolder); - await newFolderElement.waitForExist(); + await newFolderElement.waitForExist({ timeout: timeout }); } async typeOnFileNameInput(name: string) { @@ -489,26 +489,30 @@ export default class FilesScreen extends UplinkMainScreen { return progressText; } - async updateNameFile(newName: string, extension: string = "") { + async updateNameFile( + newName: string, + extension: string = "", + timeout: number = 15000, + ) { const inputFileName = await this.inputFileName; - await inputFileName.waitForExist(); + await inputFileName.waitForExist({ timeout: timeout }); await inputFileName.setValue(newName); const filesInfoCurrentSizeLabel = await this.filesInfoCurrentSizeLabel; await filesInfoCurrentSizeLabel.click(); const newFile = await this.getLocatorOfFolderFile(newName + extension); const newFileElement = await this.instance.$(newFile); - await newFileElement.waitForExist(); + await newFileElement.waitForExist({ timeout: timeout }); } - async updateNameFolder(newName: string) { + async updateNameFolder(newName: string, timeout: number = 15000) { const inputFolderName = await this.inputFolderName; - await inputFolderName.waitForExist(); + await inputFolderName.waitForExist({ timeout: timeout }); await inputFolderName.setValue(newName); const filesInfoCurrentSizeLabel = await this.filesInfoCurrentSizeLabel; await filesInfoCurrentSizeLabel.click(); const newFolder = await this.getLocatorOfFolderFile(newName); const newFolderElement = await this.instance.$(newFolder); - await newFolderElement.waitForExist(); + await newFolderElement.waitForExist({ timeout: timeout }); } async uploadFile(relativePath: string) { @@ -535,9 +539,9 @@ export default class FilesScreen extends UplinkMainScreen { await this.instance.$(fileFolderLocator).waitForExist({ reverse: true }); } - async validateFilesScreenIsShown() { + async validateFilesScreenIsShown(timeout: number = 15000) { const filesBody = await this.filesBody; - await filesBody.waitForExist(); + await filesBody.waitForExist({ timeout: timeout }); } // Hovering methods @@ -554,7 +558,7 @@ export default class FilesScreen extends UplinkMainScreen { // Context Menu methods - async openFilesContextMenu(name: string) { + async openFilesContextMenu(name: string, timeout: number = 15000) { const elementLocator = await this.getLocatorOfFolderFile(name); const fileFolderToRightClick = await this.instance .$(elementLocator) @@ -565,7 +569,7 @@ export default class FilesScreen extends UplinkMainScreen { } else if (currentDriver === WINDOWS_DRIVER) { await rightClickOnWindows(fileFolderToRightClick, this.executor); } - await this.contextMenu.waitForExist(); + await this.contextMenu.waitForExist({ timeout: timeout }); } async clickOnFilesDelete() { diff --git a/tests/screenobjects/friends/FriendsScreen.ts b/tests/screenobjects/friends/FriendsScreen.ts index 1a66f36321..11faa51e36 100644 --- a/tests/screenobjects/friends/FriendsScreen.ts +++ b/tests/screenobjects/friends/FriendsScreen.ts @@ -13,7 +13,7 @@ import { } from "@helpers/commands"; const currentOS = driver[USER_A_INSTANCE].capabilities.automationName; -const {keyboard, Key} = require("@nut-tree/nut-js"); +const { keyboard, Key } = require("@nut-tree/nut-js"); let SELECTORS = {}; @@ -368,7 +368,7 @@ export default class FriendsScreen extends UplinkMainScreen { async acceptIncomingRequest(name: string) { const friendToClick = await this.getExistingFriendByAriaLabel(name); const acceptButton = await friendToClick.$( - SELECTORS.ACCEPT_FRIEND_REQUEST_BUTTON + SELECTORS.ACCEPT_FRIEND_REQUEST_BUTTON, ); await acceptButton.click(); } @@ -407,9 +407,12 @@ export default class FriendsScreen extends UplinkMainScreen { async enterFriendDidKey(didkey: string) { const addSomeoneInput = await this.addSomeoneInput; - await addSomeoneInput.click(); await addSomeoneInput.clearValue(); await addSomeoneInput.setValue(didkey); + const addSomeoneInputText = await addSomeoneInput.getText(); + if (addSomeoneInputText !== didkey) { + await this.enterFriendDidKey(didkey); + } } async enterCopiedID() { @@ -439,9 +442,9 @@ export default class FriendsScreen extends UplinkMainScreen { return abbreviated; } - async getAllFriendsList() { + async getAllFriendsList(timeout: number = 15000) { const friendsList = await this.friendsList; - await friendsList.waitForExist(); + await friendsList.waitForExist({ timeout: timeout }); const friends = await this.instance.$$(SELECTORS.FRIEND_INFO_USERNAME); let results = []; for (let friend of friends) { @@ -452,9 +455,9 @@ export default class FriendsScreen extends UplinkMainScreen { return results; } - async getBlockedList() { + async getBlockedList(timeout: number = 15000) { const blockedList = await this.blockedList; - await blockedList.waitForExist(); + await blockedList.waitForExist({ timeout: timeout }); const friends = await this.instance.$$(SELECTORS.FRIEND_INFO_USERNAME); let results = []; for (let friend of friends) { @@ -465,7 +468,10 @@ export default class FriendsScreen extends UplinkMainScreen { return results; } - async getExistingFriendByAriaLabel(username: string) { + async getExistingFriendByAriaLabel( + username: string, + timeout: number = 15000, + ) { const currentDriver = await this.getCurrentDriver(); let locator; if (currentDriver === MACOS_DRIVER) { @@ -475,7 +481,7 @@ export default class FriendsScreen extends UplinkMainScreen { .$(SELECTORS.FRIENDS_BODY) .$('[name="' + username + '"]'); } - await locator.waitForExist(); + await locator.waitForExist({ timeout: timeout }); return locator; } @@ -490,9 +496,9 @@ export default class FriendsScreen extends UplinkMainScreen { return locator; } - async getIncomingList() { + async getIncomingList(timeout: number = 15000) { const incomingList = await this.incomingRequestsList; - await incomingList.waitForExist(); + await incomingList.waitForExist({ timeout: timeout }); const friends = await this.instance .$(SELECTORS.INCOMING_REQUESTS_LIST) .$$(SELECTORS.FRIEND_INFO_USERNAME); @@ -511,9 +517,9 @@ export default class FriendsScreen extends UplinkMainScreen { return errorText; } - async getOutgoingList() { + async getOutgoingList(timeout: number = 15000) { const outgoingList = await this.outgoingRequestsList; - await outgoingList.waitForExist(); + await outgoingList.waitForExist({ timeout: timeout }); const friends = await this.instance .$(SELECTORS.OUTGOING_REQUESTS_LIST) .$$(SELECTORS.FRIEND_INFO_USERNAME); @@ -526,9 +532,9 @@ export default class FriendsScreen extends UplinkMainScreen { return results; } - async getUserFromAllFriendsList() { + async getUserFromAllFriendsList(timeout: number = 15000) { const friendsList = await this.friendsList; - await friendsList.waitForExist(); + await friendsList.waitForExist({ timeout: timeout }); const firstUserFromList = await this.instance .$$(SELECTORS.FRIEND_INFO_USERNAME)[0] .$(SELECTORS.FRIEND_INFO_USERNAME_NAME); @@ -536,9 +542,9 @@ export default class FriendsScreen extends UplinkMainScreen { return firstUserFromListText; } - async getUserFromIncomingList() { + async getUserFromIncomingList(timeout: number = 15000) { const incomingList = await this.incomingRequestsList; - await incomingList.waitForExist(); + await incomingList.waitForExist({ timeout: timeout }); const firstUserFromList = await this.instance .$(SELECTORS.INCOMING_REQUESTS_LIST) .$$(SELECTORS.FRIEND_INFO_USERNAME)[0] @@ -547,9 +553,9 @@ export default class FriendsScreen extends UplinkMainScreen { return firstUserFromListText; } - async getUserFromOutgoingList() { + async getUserFromOutgoingList(timeout: number = 15000) { const outgoingList = await this.outgoingRequestsList; - await outgoingList.waitForExist(); + await outgoingList.waitForExist({ timeout: timeout }); const firstUserFromList = await this.instance .$(SELECTORS.OUTGOING_REQUESTS_LIST) .$$(SELECTORS.FRIEND_INFO_USERNAME)[0] @@ -558,9 +564,9 @@ export default class FriendsScreen extends UplinkMainScreen { return firstUserFromListText; } - async getUserFromBlockedList() { + async getUserFromBlockedList(timeout: number = 15000) { const blockedList = await this.blockedList; - await blockedList.waitForExist(); + await blockedList.waitForExist({ timeout: timeout }); const firstUserFromList = await this.instance .$$(SELECTORS.FRIEND_INFO_USERNAME)[0] .$(SELECTORS.FRIEND_INFO_USERNAME_NAME); @@ -568,59 +574,61 @@ export default class FriendsScreen extends UplinkMainScreen { return firstUserFromListText; } - async getUserImage(username: string) { + async getUserImage(username: string, timeout: number = 15000) { const userLocator = await this.getExistingFriendByAriaLabel(username); const userImage = await userLocator.$(SELECTORS.FRIEND_USER_IMAGE); - await userImage.waitForExist(); + await userImage.waitForExist({ timeout: timeout }); return userImage; } - async getUserImageProfile(username: string) { + async getUserImageProfile(username: string, timeout: number = 15000) { const userLocator = await this.getExistingFriendByAriaLabel(username); const userImageProfile = await userLocator.$( - SELECTORS.FRIEND_USER_IMAGE_PROFILE + SELECTORS.FRIEND_USER_IMAGE_PROFILE, ); - await userImageProfile.waitForExist(); + await userImageProfile.waitForExist({ timeout: timeout }); return userImageProfile; } - async getUserImageWrap(username: string) { + async getUserImageWrap(username: string, timeout: number = 15000) { const userLocator = await this.getExistingFriendByAriaLabel(username); const userImageWrap = await userLocator.$(SELECTORS.FRIEND_USER_IMAGE_WRAP); - await userImageWrap.waitForExist(); + await userImageWrap.waitForExist({ timeout: timeout }); return userImageWrap; } - async getUserIndicator(username: string) { + async getUserIndicator(username: string, timeout: number = 15000) { const userLocator = await this.getExistingFriendByAriaLabel(username); const indicator = await userLocator.$(SELECTORS.FRIEND_USER_INDICATOR); - await indicator.waitForExist(); + await indicator.waitForExist({ timeout: timeout }); return indicator; } - async getUserIndicatorOffline(username: string) { + async getUserIndicatorOffline(username: string, timeout: number = 15000) { const userLocator = await this.getExistingFriendByAriaLabel(username); const indicatorOffline = await userLocator.$( - SELECTORS.FRIEND_USER_INDICATOR_OFFLINE + SELECTORS.FRIEND_USER_INDICATOR_OFFLINE, ); - await indicatorOffline.waitForExist(); + await indicatorOffline.waitForExist({ timeout: timeout }); return indicatorOffline; } - async getUserIndicatorOnline(username: string) { + async getUserIndicatorOnline(username: string, timeout: number = 15000) { const userLocator = await this.getExistingFriendByAriaLabel(username); await driver[this.executor].waitUntil( async () => { - return await userLocator.$(SELECTORS.FRIEND_USER_INDICATOR_ONLINE); + return await userLocator + .$(SELECTORS.FRIEND_USER_INDICATOR_ONLINE) + .waitForExist({ timeout: timeout }); }, { - timeout: 15000, + timeout: timeout, timeoutMsg: - "Expected indicator online was never displayed on Friends Screen User after 15 seconds", - } + "Expected indicator online was never displayed on Friends Screen User", + }, ); const indicatorOnline = await userLocator.$( - SELECTORS.FRIEND_USER_INDICATOR_ONLINE + SELECTORS.FRIEND_USER_INDICATOR_ONLINE, ); return indicatorOnline; } @@ -631,12 +639,12 @@ export default class FriendsScreen extends UplinkMainScreen { return userTooltip; } - async getUserTooltipText(username: string) { + async getUserTooltipText(username: string, timeout: number = 15000) { const userLocator = await this.getExistingFriendByAriaLabel(username); const userTooltipText = await userLocator .$(SELECTORS.TOOLTIP) .$(SELECTORS.TOOLTIP_TEXT); - await userTooltipText.waitForExist(); + await userTooltipText.waitForExist({ timeout: timeout }); return userTooltipText; } @@ -664,7 +672,7 @@ export default class FriendsScreen extends UplinkMainScreen { async hoverOnBlockButton(username: string) { const userLocator = await this.getExistingFriendByAriaLabel(username); const secondButtonLocator = await userLocator.$( - SELECTORS.BLOCK_FRIEND_BUTTON + SELECTORS.BLOCK_FRIEND_BUTTON, ); await this.hoverOnElement(secondButtonLocator); } @@ -677,7 +685,7 @@ export default class FriendsScreen extends UplinkMainScreen { async hoverOnChatWithFriendButton(username: string) { const userLocator = await this.getExistingFriendByAriaLabel(username); const buttonLocator = await userLocator.$( - SELECTORS.CHAT_WITH_FRIEND_BUTTON + SELECTORS.CHAT_WITH_FRIEND_BUTTON, ); await this.hoverOnElement(buttonLocator); } @@ -690,7 +698,7 @@ export default class FriendsScreen extends UplinkMainScreen { async hoverOnUnfriendDenyUnblockButton(username: string) { const userLocator = await this.getExistingFriendByAriaLabel(username); const firstButtonLocator = await userLocator.$( - SELECTORS.REMOVE_OR_DENY_FRIEND_BUTTON + SELECTORS.REMOVE_OR_DENY_FRIEND_BUTTON, ); await this.hoverOnElement(firstButtonLocator); } @@ -714,80 +722,96 @@ export default class FriendsScreen extends UplinkMainScreen { async removeOrCancelUser(name: string) { const friendToClick = await this.getExistingFriendByAriaLabel(name); const removeOrDenyButton = await friendToClick.$( - SELECTORS.REMOVE_OR_DENY_FRIEND_BUTTON + SELECTORS.REMOVE_OR_DENY_FRIEND_BUTTON, ); await removeOrDenyButton.click(); } - async validateAllFriendsListIsNotEmpty() { + async validateAllFriendsListIsNotEmpty(timeout: number = 60000) { // Wait until friends list is not empty await driver[this.executor].waitUntil( async () => { return await this.instance .$(SELECTORS.FRIENDS_LIST) - .$(SELECTORS.FRIEND_INFO_USERNAME); + .$(SELECTORS.FRIEND_INFO_USERNAME) + .waitForExist({ timeout: timeout }); }, { - timeout: 15000, - timeoutMsg: "All friends list never shown any records after 15 seconds", - } + timeout: timeout, + timeoutMsg: "All friends list never shown any records", + }, ); } - async validateAllFriendsListIsShown() { + async validateAllFriendsListIsShown(timeout: number = 15000) { const allFriendsList = await this.friendsList; - await allFriendsList.waitForExist(); + await allFriendsList.waitForExist({ timeout: timeout }); } - async validateBlockedListIsNotEmpty() { + async validateBlockedListIsNotEmpty(timeout: number = 60000) { // Wait until blocked list is not empty await driver[this.executor].waitUntil( async () => { return await this.instance .$(SELECTORS.BLOCKED_LIST) - .$(SELECTORS.FRIEND_INFO_USERNAME); + .$(SELECTORS.FRIEND_INFO_USERNAME) + .waitForExist({ timeout: timeout }); }, { - timeout: 15000, - timeoutMsg: - "Blocked friends list never shown any records after 15 seconds", - } + timeout: timeout, + timeoutMsg: "Blocked friends list never shown any records", + }, ); } - async validateBlockedListIsShown() { + async validateBlockedListIsShown(timeout: number = 15000) { const blockedList = await this.blockedList; - await blockedList.waitForExist(); + await blockedList.waitForExist({ timeout: timeout }); } - async validateChatWithFriendButtonIsShown() { + async validateChatWithFriendButtonIsShown(timeout: number = 15000) { const chatWithFriend = await this.chatWithFriendButton; - await chatWithFriend.waitForExist(); + await chatWithFriend.waitForExist({ timeout: timeout }); } - async validateFriendsButtonBadgeIsShown() { + async validateChatWithFriendButtonExists(timeout: number = 60000) { + // Wait until incoming list is not empty + await driver[this.executor].waitUntil( + async () => { + return await this.chatWithFriendButton.waitForExist({ + timeout: timeout, + }); + }, + { + timeout: timeout, + timeoutMsg: "Chat with friend button does not exist", + }, + ); + } + + async validateFriendsButtonBadgeIsShown(timeout: number = 15000) { const friendsButtonBadge = await this.friendsButtonBadge; - await friendsButtonBadge.waitForExist(); + await friendsButtonBadge.waitForExist({ timeout: timeout }); } - async validateFriendsScreenIsShown() { + async validateFriendsScreenIsShown(timeout: number = 15000) { const friendsScreen = await this.friendsBody; - await friendsScreen.waitForExist(); + await friendsScreen.waitForExist({ timeout: timeout }); } - async validateIncomingListIsNotEmpty() { + async validateIncomingListIsNotEmpty(timeout: number = 60000) { // Wait until incoming list is not empty await driver[this.executor].waitUntil( async () => { return await this.instance .$(SELECTORS.INCOMING_REQUESTS_LIST) - .$(SELECTORS.FRIEND_INFO_USERNAME); + .$(SELECTORS.FRIEND_INFO_USERNAME) + .waitForExist({ timeout: timeout }); }, { - timeout: 15000, - timeoutMsg: - "Incoming friends list never shown any records after 15 seconds", - } + timeout: timeout, + timeoutMsg: "Incoming friends list never shown any records", + }, ); } @@ -797,92 +821,99 @@ export default class FriendsScreen extends UplinkMainScreen { }); } - async validateIncomingListIsShown() { + async validateIncomingListIsShown(timeout: number = 15000) { const incomingList = await this.incomingRequestsList; - await incomingList.waitForExist(); + await incomingList.waitForExist({ timeout: timeout }); } - async validateNoRequestsIsShown() { + async validateNoRequestsIsShown(timeout: number = 15000) { // Ensure no requests message is displayed const noRequests = await this.noRequests; - await noRequests.waitForExist(); + await noRequests.waitForExist({ timeout: timeout }); } - async validateOutgoingListIsNotEmpty() { + async validateOutgoingListIsNotEmpty(timeout: number = 60000) { await driver[this.executor].waitUntil( async () => { return await this.instance .$(SELECTORS.OUTGOING_REQUESTS_LIST) - .$(SELECTORS.FRIEND_INFO_USERNAME); + .$(SELECTORS.FRIEND_INFO_USERNAME) + .waitForExist({ timeout: timeout }); }, { - timeout: 15000, - timeoutMsg: - "Expected friend list never shown any records after 15 seconds", - } + timeout: timeout, + timeoutMsg: "Expected friend list never shown any records", + }, ); } - async validateOutgoingListIsShown() { + async validateOutgoingListIsShown(timeout: number = 15000) { const outgoingList = await this.outgoingRequestsList; - await outgoingList.waitForExist(); + await outgoingList.waitForExist({ timeout: timeout }); } - async validateRemoveOrDenyButtonIsShown() { + async validateRemoveOrDenyButtonIsShown(timeout: number = 15000) { const removeOrDenyButton = await this.removeOrDenyFriendButton; - await removeOrDenyButton.waitForExist(); + await removeOrDenyButton.waitForExist({ timeout: timeout }); } async waitUntilFriendIsRemoved( username: string, - timeoutUser: number = 30000 + timeoutUser: number = 30000, ) { - const nonExistingFriend = await this.getNonExistingFriendByAriaLabel( - username - ); + const nonExistingFriend = + await this.getNonExistingFriendByAriaLabel(username); await this.instance .$(SELECTORS.FRIENDS_BODY) .$(nonExistingFriend) .waitForExist({ timeout: timeoutUser, reverse: true }); } - async waitUntilFriendRequestIsReceived() { + async waitUntilFriendRequestIsReceived(timeout: number = 180000) { await driver[this.executor].waitUntil( async () => { - return await this.acceptFriendRequestButton; + return await this.acceptFriendRequestButton.waitForExist({ + timeout: timeout, + }); }, { - timeout: 15000, + timeout: timeout, timeoutMsg: - "Expected Accept Friend Request button was never displayed on Friends Screen after 15 seconds", - } + "Expected Accept Friend Request button was never displayed on Friends Screen", + }, ); } - async waitUntilUserAcceptedFriendRequest() { + async waitUntilUserAcceptedFriendRequest(timeout: number = 180000) { await driver[this.executor].waitUntil( async () => { - return await this.chatWithFriendButton; + return await this.chatWithFriendButton.waitForExist({ + timeout: timeout, + }); }, { - timeout: 15000, + timeout: timeout, timeoutMsg: - "Expected Chat With Friend button was never displayed on Friends Screen after 15 seconds", - } + "Expected Chat With Friend button was never displayed on Friends Screen", + }, ); } - async waitUntilUserIsInCurrentList(username: string) { + async waitUntilUserIsInCurrentList( + username: string, + timeout: number = 15000, + ) { const user = await this.getExistingFriendByAriaLabel(username); await driver[this.executor].waitUntil( async () => { - return await user.$(SELECTORS.FRIEND_INFO_USERNAME); + return await user + .$(SELECTORS.FRIEND_INFO_USERNAME) + .waitForExist({ timeout: timeout }); }, { - timeout: 15000, - timeoutMsg: - "Expected Username was never displayed on Friends Screen after 15 seconds", - } + timeout: timeout, + timeoutMsg: "Expected Username was never displayed on Friends Screen", + }, ); } @@ -933,7 +964,7 @@ export default class FriendsScreen extends UplinkMainScreen { await contextMenuUnblock.click(); } - async openFriendContextMenu(name: string) { + async openFriendContextMenu(name: string, timeout: number = 15000) { const friendElement = await this.getExistingFriendByAriaLabel(name); const currentDriver = await this.getCurrentDriver(); if (currentDriver === MACOS_DRIVER) { @@ -942,6 +973,6 @@ export default class FriendsScreen extends UplinkMainScreen { await rightClickOnWindows(friendElement, this.executor); } const contextMenu = await this.contextMenu; - await contextMenu.waitForExist(); + await contextMenu.waitForExist({ timeout: timeout }); } } diff --git a/tests/screenobjects/settings/SettingsGeneralScreen.ts b/tests/screenobjects/settings/SettingsGeneralScreen.ts index 746b8075c6..7cf1baae77 100644 --- a/tests/screenobjects/settings/SettingsGeneralScreen.ts +++ b/tests/screenobjects/settings/SettingsGeneralScreen.ts @@ -432,8 +432,8 @@ export default class SettingsGeneralScreen extends SettingsBaseScreen { await this.hoverOnElement(openThemesButton); } - async validateSettingsGeneralIsShown() { + async validateSettingsGeneralIsShown(timeout: number = 15000) { const settingsGeneral = await this.settingsGeneral; - await settingsGeneral.waitForExist(); + await settingsGeneral.waitForExist({ timeout: timeout }); } } diff --git a/tests/screenobjects/settings/SettingsMessagesScreen.ts b/tests/screenobjects/settings/SettingsMessagesScreen.ts index 7f80253312..2ed2cc0933 100644 --- a/tests/screenobjects/settings/SettingsMessagesScreen.ts +++ b/tests/screenobjects/settings/SettingsMessagesScreen.ts @@ -122,8 +122,8 @@ export default class SettingsMessagesScreen extends SettingsBaseScreen { } } - async validateSettingsMessagesIsShown() { + async validateSettingsMessagesIsShown(timeout: number = 15000) { const settingsMessages = await this.settingsMessages; - await settingsMessages.waitForExist(); + await settingsMessages.waitForExist({ timeout: timeout }); } } diff --git a/tests/screenobjects/settings/SettingsNotificationsScreen.ts b/tests/screenobjects/settings/SettingsNotificationsScreen.ts index 80974e5a9e..a67ff76164 100644 --- a/tests/screenobjects/settings/SettingsNotificationsScreen.ts +++ b/tests/screenobjects/settings/SettingsNotificationsScreen.ts @@ -166,8 +166,8 @@ export default class SettingsNotificationsScreen extends SettingsBaseScreen { async clickOnFriendsNotifications() { const currentDriver = await this.getCurrentDriver(); if (currentDriver === WINDOWS_DRIVER) { - const friendsNotificationsCheckbox = await this - .friendsNotificationsCheckbox; + const friendsNotificationsCheckbox = + await this.friendsNotificationsCheckbox; await friendsNotificationsCheckbox.click(); } else if (currentDriver === MACOS_DRIVER) { const locator = await this.friendsNotificationsCheckbox; @@ -178,8 +178,8 @@ export default class SettingsNotificationsScreen extends SettingsBaseScreen { async clickOnMessagesNotifications() { const currentDriver = await this.getCurrentDriver(); if (currentDriver === WINDOWS_DRIVER) { - const messagesNotificationsCheckbox = await this - .messagesNotificationsCheckbox; + const messagesNotificationsCheckbox = + await this.messagesNotificationsCheckbox; await messagesNotificationsCheckbox.click(); } else if (currentDriver === MACOS_DRIVER) { const locator = await this.messagesNotificationsCheckbox; @@ -190,8 +190,8 @@ export default class SettingsNotificationsScreen extends SettingsBaseScreen { async clickOnSettingsNotifications() { const currentDriver = await this.getCurrentDriver(); if (currentDriver === WINDOWS_DRIVER) { - const settingsNotificationsCheckbox = await this - .settingsNotificationsCheckbox; + const settingsNotificationsCheckbox = + await this.settingsNotificationsCheckbox; await settingsNotificationsCheckbox.click(); } else if (currentDriver === MACOS_DRIVER) { const locator = await this.settingsNotificationsCheckbox; @@ -199,8 +199,8 @@ export default class SettingsNotificationsScreen extends SettingsBaseScreen { } } - async validateSettingsNotificationsIsShown() { + async validateSettingsNotificationsIsShown(timeout: number = 15000) { const settingsNotifications = await this.settingsNotifications; - await settingsNotifications.waitForExist(); + await settingsNotifications.waitForExist({ timeout: timeout }); } } diff --git a/tests/screenobjects/settings/SettingsProfileScreen.ts b/tests/screenobjects/settings/SettingsProfileScreen.ts index 6b259081a8..f2cc5bacbb 100644 --- a/tests/screenobjects/settings/SettingsProfileScreen.ts +++ b/tests/screenobjects/settings/SettingsProfileScreen.ts @@ -15,7 +15,7 @@ import { import SettingsBaseScreen from "@screenobjects/settings/SettingsBaseScreen"; const currentOS = driver[USER_A_INSTANCE].capabilities.automationName; -const {keyboard, Key} = require("@nut-tree/nut-js"); +const { keyboard, Key } = require("@nut-tree/nut-js"); let SELECTORS = {}; const SELECTORS_COMMON = { @@ -333,7 +333,7 @@ export default class SettingsProfileScreen extends SettingsBaseScreen { { timeout: 5000, timeoutMsg: "Expected status input to contain did:key after 5 seconds", - } + }, ); } @@ -371,20 +371,20 @@ export default class SettingsProfileScreen extends SettingsBaseScreen { } } - async validateBannerPictureIsShown() { + async validateBannerPictureIsShown(timeout: number = 15000) { // Validate that profile banner is displayed on screen const bannerImage = await this.profileBanner; - await bannerImage.waitForExist(); + await bannerImage.waitForExist({ timeout: timeout }); } - async validateProfilePictureIsShown() { + async validateProfilePictureIsShown(timeout: number = 15000) { // Validate that profile picture is displayed on screen const profilePictureImage = await this.profilePicture; - await profilePictureImage.waitForExist(); + await profilePictureImage.waitForExist({ timeout: timeout }); } - async validateSettingsProfileIsShown() { + async validateSettingsProfileIsShown(timeout: number = 15000) { const settingsProfile = await this.settingsProfile; - await settingsProfile.waitForExist(); + await settingsProfile.waitForExist({ timeout: timeout }); } } diff --git a/tests/screenobjects/welcome-screen/WelcomeScreen.ts b/tests/screenobjects/welcome-screen/WelcomeScreen.ts index 40cea7eebb..a1bec38873 100644 --- a/tests/screenobjects/welcome-screen/WelcomeScreen.ts +++ b/tests/screenobjects/welcome-screen/WelcomeScreen.ts @@ -53,8 +53,8 @@ export default class WelcomeScreen extends UplinkMainScreen { await addSomeoneButton.click(); } - async validateWelcomeScreenIsShown() { + async validateWelcomeScreenIsShown(timeout: number = 15000) { const welcomeLayout = await this.welcomeLayout; - await welcomeLayout.waitForExist(); + await welcomeLayout.waitForExist({ timeout: timeout }); } } diff --git a/tests/specs/01-create-account.spec.ts b/tests/specs/01-create-account.spec.ts index e18974fa5b..0d7ba28097 100644 --- a/tests/specs/01-create-account.spec.ts +++ b/tests/specs/01-create-account.spec.ts @@ -192,7 +192,7 @@ export default async function createAccount() { }); it("Enter valid username to continue", async () => { - await createUserFirstUser.enterUsername("Test123"); + await createUserFirstUser.enterUsername("ChatUserA"); const statusOfButton = await createPinFirstUser.getStatusOfCreateAccountButton(); await expect(statusOfButton).toEqual("true"); diff --git a/tests/specs/05-settings-profile.spec.ts b/tests/specs/05-settings-profile.spec.ts index 4e7bc0320b..2c47f23c5b 100644 --- a/tests/specs/05-settings-profile.spec.ts +++ b/tests/specs/05-settings-profile.spec.ts @@ -2,6 +2,7 @@ import "module-alias/register"; import CropImageProfileModal from "@screenobjects/settings/CropToolProfileModal"; import FilesScreen from "@screenobjects/files/FilesScreen"; import SettingsProfileScreen from "@screenobjects/settings/SettingsProfileScreen"; +import { grabCacheFolder, saveTestKeys } from "@helpers/commands"; import { USER_A_INSTANCE } from "@helpers/constants"; let cropProfileFirstUser = new CropImageProfileModal(USER_A_INSTANCE); let filesScreenFirstUser = new FilesScreen(USER_A_INSTANCE); @@ -66,7 +67,7 @@ export default async function settingsProfile() { // Assert username and status placeholder values are displayed const usernameInput = await settingsProfileFirstUser.usernameInput; - await expect(usernameInput).toHaveTextContaining("Test123"); + await expect(usernameInput).toHaveTextContaining("ChatUserA"); const statusInput = await settingsProfileFirstUser.statusInput; await expect(statusInput).toHaveTextContaining(""); @@ -228,8 +229,7 @@ export default async function settingsProfile() { await settingsProfileFirstUser.waitUntilNotificationIsClosed(); }); - // Skipping test - requires adding validation to ensure clipboard is not empty before pasting - xit("Settings Profile - Copied ID can be placed on any text field", async () => { + it("Settings Profile - Copied ID can be placed on any text field", async () => { // Paste copied DID Key into Status Input await settingsProfileFirstUser.pasteUserKeyInStatus(); @@ -238,6 +238,14 @@ export default async function settingsProfile() { await settingsProfileFirstUser.getStatusInputElement(); await expect(statusInputText).toHaveTextContaining("did:key:"); + const didkey = await settingsProfileFirstUser.getCopiedDidFromStatusInput(); + const username = "ChatUserA"; + // Grab cache folder and restart + await saveTestKeys(username, didkey, USER_A_INSTANCE); + + // Update banner picture from user A + await grabCacheFolder(username, USER_A_INSTANCE); + // Clear value from status input await settingsProfileFirstUser.deleteStatus(); }); @@ -277,7 +285,7 @@ export default async function settingsProfile() { ); // Clear value from username input, then enter a valid value again - await settingsProfileFirstUser.enterUsername("Test123"); + await settingsProfileFirstUser.enterUsername("ChatUserA"); }); it("Settings Profile - Username - Spaces are not allowed", async () => { @@ -294,7 +302,7 @@ export default async function settingsProfile() { ); // Clear value from username input, then enter a valid value again - await settingsProfileFirstUser.enterUsername("Test123"); + await settingsProfileFirstUser.enterUsername("ChatUserA"); }); it("Settings Profile - Username with non-alphanumeric characters", async () => { @@ -312,7 +320,7 @@ export default async function settingsProfile() { ); // Clear value from username input, then enter a valid value again - await settingsProfileFirstUser.enterUsername("Test123"); + await settingsProfileFirstUser.enterUsername("ChatUserA"); }); it("Settings Profile - Username with more than 32 characters", async () => { @@ -331,7 +339,7 @@ export default async function settingsProfile() { ); // Clear value from username input, then enter a valid value again - await settingsProfileFirstUser.enterUsername("Test123"); + await settingsProfileFirstUser.enterUsername("ChatUserA"); // Wait for toast notification to be closed before starting next tests await settingsProfileFirstUser.waitUntilNotificationIsClosed(); diff --git a/tests/specs/14-create-reusable-accounts.spec.ts b/tests/specs/14-create-reusable-accounts.spec.ts deleted file mode 100644 index 052a1fb1d4..0000000000 --- a/tests/specs/14-create-reusable-accounts.spec.ts +++ /dev/null @@ -1,116 +0,0 @@ -import "module-alias/register"; -import { - createNewUser, - grabCacheFolder, - resetApp, - saveTestKeys, -} from "@helpers/commands"; -import { USER_A_INSTANCE } from "@helpers/constants"; -import CropImageProfileModal from "@screenobjects/settings/CropToolProfileModal"; -import SettingsProfileScreen from "@screenobjects/settings/SettingsProfileScreen"; -import WelcomeScreen from "@screenobjects/welcome-screen/WelcomeScreen"; -let cropProfileFirstUser = new CropImageProfileModal(USER_A_INSTANCE); -let settingsProfileFirstUser = new SettingsProfileScreen(USER_A_INSTANCE); -let welcomeScreenFirstUser = new WelcomeScreen(USER_A_INSTANCE); - -export default async function createReusableAccounts() { - it("Create reusable account - Chat User A", async () => { - await resetApp(USER_A_INSTANCE); - // Create New User and go to Settings Profile Screen - const username = "ChatUserA"; - await createNewUser(username); - await welcomeScreenFirstUser.goToSettings(); - await settingsProfileFirstUser.waitForIsShown(true); - }); - - it("Add profile picture - Chat User A", async () => { - await settingsProfileFirstUser.selectProfilePicture( - "./tests/fixtures/logo.jpg" - ); - - // Validate Crop Tool Modal is displayed - await cropProfileFirstUser.validateCropToolModalIsShown(); - - // Do not change the size of picture and just confirm on crop modal - await cropProfileFirstUser.clickOnConfirmButton(); - - // Validate new profile picture is displayed - await settingsProfileFirstUser.validateProfilePictureIsShown(); - }); - - it("Add banner picture - Chat User A", async () => { - await settingsProfileFirstUser.selectBannerPicture( - "./tests/fixtures/banner.jpg" - ); - }); - - it("Save test account - Chat User A", async () => { - // Click on Copy ID button and assert Toast Notification is displayed - const username = "ChatUserA"; - await settingsProfileFirstUser.clickOnCopyIDButton(); - - // Wait for toast notification to be closed - await settingsProfileFirstUser.waitUntilNotificationIsClosed(); - - // Paste copied DID Key into Status Input - await settingsProfileFirstUser.pasteUserKeyInStatus(); - const didkey = await settingsProfileFirstUser.getCopiedDidFromStatusInput(); - - // Grab cache folder and restart - await saveTestKeys(username, didkey, USER_A_INSTANCE); - - // Update profile picture from user A - - // Update banner picture from user A - await grabCacheFolder(username, USER_A_INSTANCE); - await resetApp(USER_A_INSTANCE); - }); - - it("Create reusable account - Chat User B", async () => { - // Create New User and go to Settings Profile Screen - const username = "ChatUserB"; - await createNewUser(username); - await welcomeScreenFirstUser.goToSettings(); - await settingsProfileFirstUser.waitForIsShown(true); - }); - - it("Add profile picture - Chat User B", async () => { - await settingsProfileFirstUser.selectProfilePicture( - "./tests/fixtures/second-profile.png" - ); - - // Validate Crop Tool Modal is displayed - await cropProfileFirstUser.validateCropToolModalIsShown(); - - // Do not change the size of picture and just confirm on crop modal - await cropProfileFirstUser.clickOnConfirmButton(); - - // Validate new profile picture is displayed - await settingsProfileFirstUser.validateProfilePictureIsShown(); - }); - - it("Add banner picture - Chat User B", async () => { - it("Settings Profile - Change banner picture", async () => { - await settingsProfileFirstUser.selectBannerPicture( - "./tests/fixtures/second-banner.jpg" - ); - }); - }); - - it("Save test account - Chat User B", async () => { - const username = "ChatUserB"; - // Click on Copy ID button and assert Toast Notification is displayed - await settingsProfileFirstUser.clickOnCopyIDButton(); - - // Wait for toast notification to be closed - await settingsProfileFirstUser.waitUntilNotificationIsClosed(); - - // Paste copied DID Key into Status Input - await settingsProfileFirstUser.pasteUserKeyInStatus(); - const didkey = await settingsProfileFirstUser.getCopiedDidFromStatusInput(); - - // Grab cache folder and restart - await saveTestKeys(username, didkey, USER_A_INSTANCE); - await grabCacheFolder(username, USER_A_INSTANCE); - }); -} diff --git a/tests/specs/15-settings-messages.spec.ts b/tests/specs/14-settings-messages.spec.ts similarity index 100% rename from tests/specs/15-settings-messages.spec.ts rename to tests/specs/14-settings-messages.spec.ts diff --git a/tests/specs/15-create-first-account.spec.ts b/tests/specs/15-create-first-account.spec.ts new file mode 100644 index 0000000000..b99536dd41 --- /dev/null +++ b/tests/specs/15-create-first-account.spec.ts @@ -0,0 +1,96 @@ +import "module-alias/register"; +import { grabCacheFolder, maximizeWindow, saveTestKeys } from "@helpers/commands"; +import { USER_A_INSTANCE } from "@helpers/constants"; +import CreatePinScreen from "@screenobjects/account-creation/CreatePinScreen"; +import CreateUserScreen from "@screenobjects/account-creation/CreateUserScreen"; +import SettingsProfileScreen from "@screenobjects/settings/SettingsProfileScreen"; +import WelcomeScreen from "@screenobjects/welcome-screen/WelcomeScreen"; +let createPinFirstUser = new CreatePinScreen(USER_A_INSTANCE); +let createUserFirstUser = new CreateUserScreen(USER_A_INSTANCE); +let settingsProfileFirstUser = new SettingsProfileScreen(USER_A_INSTANCE); +let welcomeScreenFirstUser = new WelcomeScreen(USER_A_INSTANCE); + +export default async function createFirstAccount() { + it("Validate warning texts are displayed on screen", async () => { + const unlockWarningHeader = await createPinFirstUser.unlockWarningHeader; + await unlockWarningHeader.waitForExist(); + await expect(unlockWarningHeader).toHaveTextContaining([ + "LET'S CHOOSE YOUR PASSWORD", + "WELCOME BACK,", + ]); + + const unlockWarningParagraph = + await createPinFirstUser.unlockWarningParagraph; + await unlockWarningParagraph.waitForExist(); + await expect(unlockWarningParagraph).toHaveTextContaining( + "(this is used to encrypt all of the data Uplink stores on your computer when you're not using it so nobody can read your data.)" + ); + }); + + it("Unlock Screen - Reset Account is shown after right clicking on Help Button", async () => { + // Right click on Help Button to show the help menu + await createPinFirstUser.openHelpButtonMenu(); + + // Right click again on Help Button to hide the help menu + await createPinFirstUser.openHelpButtonMenu(); + }); + + it("Enter a valid pin and continue creating a username", async () => { + await createPinFirstUser.enterPin("1234"); + const statusOfButton = + await createPinFirstUser.getStatusOfCreateAccountButton(); + await expect(statusOfButton).toEqual("true"); + await createPinFirstUser.clickOnCreateAccount(); + await createUserFirstUser.waitForIsShown(true); + }); + + it("Enter valid username to continue", async () => { + await createUserFirstUser.enterUsername("ChatUserA"); + const statusOfButton = + await createPinFirstUser.getStatusOfCreateAccountButton(); + await expect(statusOfButton).toEqual("true"); + await createUserFirstUser.clickOnCreateAccount(); + await welcomeScreenFirstUser.waitForIsShown(true); + + // Maximize Window on Execution + await maximizeWindow(USER_A_INSTANCE); + }); + + it("Go to Settings with Chat User B", async () => { + // Go to Settings Screen and select the Settings Screen to validate + await welcomeScreenFirstUser.goToSettings(); + await settingsProfileFirstUser.waitForIsShown(true); + }); + + it("Settings Profile - Click On Copy ID Button", async () => { + // Wait for toast notification to be closed before starting test + await settingsProfileFirstUser.waitUntilNotificationIsClosed(); + + // Click on Copy ID button and assert Toast Notification is displayed + await settingsProfileFirstUser.clickOnCopyIDButton(); + + // Wait for toast notification to be closed + await settingsProfileFirstUser.waitUntilNotificationIsClosed(); + }); + + it("Settings Profile - Copied ID can be placed on any text field", async () => { + // Paste copied DID Key into Status Input + await settingsProfileFirstUser.pasteUserKeyInStatus(); + + // Ensure that value placed in Status is the did key from the user + const statusInputText = + await settingsProfileFirstUser.getStatusInputElement(); + await expect(statusInputText).toHaveTextContaining("did:key:"); + + const didkey = await settingsProfileFirstUser.getCopiedDidFromStatusInput(); + const username = "ChatUserA"; + // Grab cache folder and restart + await saveTestKeys(username, didkey, USER_A_INSTANCE); + + // Update banner picture from user A + await grabCacheFolder(username, USER_A_INSTANCE); + + // Clear value from status input + await settingsProfileFirstUser.deleteStatus(); + }); +} diff --git a/tests/specs/16-create-second-account.spec.ts b/tests/specs/16-create-second-account.spec.ts new file mode 100644 index 0000000000..ed71236ad2 --- /dev/null +++ b/tests/specs/16-create-second-account.spec.ts @@ -0,0 +1,96 @@ +import "module-alias/register"; +import { grabCacheFolder, maximizeWindow, saveTestKeys } from "@helpers/commands"; +import { USER_A_INSTANCE } from "@helpers/constants"; +import CreatePinScreen from "@screenobjects/account-creation/CreatePinScreen"; +import CreateUserScreen from "@screenobjects/account-creation/CreateUserScreen"; +import SettingsProfileScreen from "@screenobjects/settings/SettingsProfileScreen"; +import WelcomeScreen from "@screenobjects/welcome-screen/WelcomeScreen"; +let createPinFirstUser = new CreatePinScreen(USER_A_INSTANCE); +let createUserFirstUser = new CreateUserScreen(USER_A_INSTANCE); +let settingsProfileFirstUser = new SettingsProfileScreen(USER_A_INSTANCE); +let welcomeScreenFirstUser = new WelcomeScreen(USER_A_INSTANCE); + +export default async function createSecondAccount() { + it("Validate warning texts are displayed on screen", async () => { + const unlockWarningHeader = await createPinFirstUser.unlockWarningHeader; + await unlockWarningHeader.waitForExist(); + await expect(unlockWarningHeader).toHaveTextContaining([ + "LET'S CHOOSE YOUR PASSWORD", + "WELCOME BACK,", + ]); + + const unlockWarningParagraph = + await createPinFirstUser.unlockWarningParagraph; + await unlockWarningParagraph.waitForExist(); + await expect(unlockWarningParagraph).toHaveTextContaining( + "(this is used to encrypt all of the data Uplink stores on your computer when you're not using it so nobody can read your data.)" + ); + }); + + it("Unlock Screen - Reset Account is shown after right clicking on Help Button", async () => { + // Right click on Help Button to show the help menu + await createPinFirstUser.openHelpButtonMenu(); + + // Right click again on Help Button to hide the help menu + await createPinFirstUser.openHelpButtonMenu(); + }); + + it("Enter a valid pin and continue creating a username", async () => { + await createPinFirstUser.enterPin("1234"); + const statusOfButton = + await createPinFirstUser.getStatusOfCreateAccountButton(); + await expect(statusOfButton).toEqual("true"); + await createPinFirstUser.clickOnCreateAccount(); + await createUserFirstUser.waitForIsShown(true); + }); + + it("Enter valid username to continue", async () => { + await createUserFirstUser.enterUsername("ChatUserB"); + const statusOfButton = + await createPinFirstUser.getStatusOfCreateAccountButton(); + await expect(statusOfButton).toEqual("true"); + await createUserFirstUser.clickOnCreateAccount(); + await welcomeScreenFirstUser.waitForIsShown(true); + + // Maximize Window on Execution + await maximizeWindow(USER_A_INSTANCE); + }); + + it("Go to Settings with Chat User B", async () => { + // Go to Settings Screen and select the Settings Screen to validate + await welcomeScreenFirstUser.goToSettings(); + await settingsProfileFirstUser.waitForIsShown(true); + }); + + it("Settings Profile - Click On Copy ID Button", async () => { + // Wait for toast notification to be closed before starting test + await settingsProfileFirstUser.waitUntilNotificationIsClosed(); + + // Click on Copy ID button and assert Toast Notification is displayed + await settingsProfileFirstUser.clickOnCopyIDButton(); + + // Wait for toast notification to be closed + await settingsProfileFirstUser.waitUntilNotificationIsClosed(); + }); + + it("Settings Profile - Copied ID can be placed on any text field", async () => { + // Paste copied DID Key into Status Input + await settingsProfileFirstUser.pasteUserKeyInStatus(); + + // Ensure that value placed in Status is the did key from the user + const statusInputText = + await settingsProfileFirstUser.getStatusInputElement(); + await expect(statusInputText).toHaveTextContaining("did:key:"); + + const didkey = await settingsProfileFirstUser.getCopiedDidFromStatusInput(); + const username = "ChatUserB"; + // Grab cache folder and restart + await saveTestKeys(username, didkey, USER_A_INSTANCE); + + // Update banner picture from user A + await grabCacheFolder(username, USER_A_INSTANCE); + + // Clear value from status input + await settingsProfileFirstUser.deleteStatus(); + }); +} diff --git a/tests/specs/reusable-accounts/ChatUserA/01-main-chats-userA.spec.ts b/tests/specs/reusable-accounts/ChatUserA/01-main-chats-userA.spec.ts new file mode 100644 index 0000000000..c050f990ba --- /dev/null +++ b/tests/specs/reusable-accounts/ChatUserA/01-main-chats-userA.spec.ts @@ -0,0 +1,149 @@ +import "module-alias/register"; +import { loginWithTestUser } from "@helpers/commands"; +import { USER_A_INSTANCE } from "@helpers/constants"; +import ChatsLayout from "@screenobjects/chats/ChatsLayout"; +import EmojiSelector from "@screenobjects/chats/EmojiSelector"; +import FavoritesSidebar from "@screenobjects/chats/FavoritesSidebar"; +import FriendsScreen from "@screenobjects/friends/FriendsScreen"; +import InputBar from "@screenobjects/chats/InputBar"; +import Messages from "@screenobjects/chats/Messages"; +import MessageGroup from "@screenobjects/chats/MessageGroup"; +import Topbar from "@screenobjects/chats/Topbar"; +import WelcomeScreen from "@screenobjects/welcome-screen/WelcomeScreen"; +let chatsMessagesFirstUser = new Messages(USER_A_INSTANCE); +let chatsMessageGroupsFirstUser = new MessageGroup(USER_A_INSTANCE); +let chatsInputFirstUser = new InputBar(USER_A_INSTANCE); +let chatsLayoutFirstUser = new ChatsLayout(USER_A_INSTANCE); +let chatsTopbarFirstUser = new Topbar(USER_A_INSTANCE); +let emojiSelectorFirstUser = new EmojiSelector(USER_A_INSTANCE); +let favoritesSidebarFirstUser = new FavoritesSidebar(USER_A_INSTANCE); +let friendsScreenFirstUser = new FriendsScreen(USER_A_INSTANCE); +let welcomeScreenFirstUser = new WelcomeScreen(USER_A_INSTANCE); + +export default async function mainChatsTestsUserA() { + it("Chat User A - Login with account previously created", async () => { + // Login with account previously created + await loginWithTestUser(); + await welcomeScreenFirstUser.validateWelcomeScreenIsShown(); + await welcomeScreenFirstUser.goToFriends(); + await friendsScreenFirstUser.validateFriendsScreenIsShown(); + }); + + it("Chat User A - Accept friend request from User A and go to chat button", async () => { + // With User A - Go to pending requests list, wait for receiving the friend request and accept it + await friendsScreenFirstUser.hoverOnPendingListButton(); + await friendsScreenFirstUser.goToPendingFriendsList(); + await friendsScreenFirstUser.waitUntilFriendRequestIsReceived(); + await friendsScreenFirstUser.acceptIncomingRequest("ChatUserB"); + + // Validate friend is now on all friends list + await friendsScreenFirstUser.goToAllFriendsList(); + await friendsScreenFirstUser.validateAllFriendsListIsShown(); + await friendsScreenFirstUser.validateAllFriendsListIsNotEmpty(); + + // Go to Chat with User B + await friendsScreenFirstUser.chatWithFriendButton.click(); + }); + + it("Chat User A - Chat screen displays Messages secured text displayed on top of conversation", async () => { + await chatsTopbarFirstUser.validateTopbarExists(); + + // Validate E2E message is displayed on top of chat + const encryptedMessagesText = + await chatsLayoutFirstUser.encryptedMessagesText; + await encryptedMessagesText.waitForExist(); + await expect(encryptedMessagesText).toHaveTextContaining( + "Messages are secured by end-to-end encryption and sent over a peer-to-peer network.", + ); + }); + + it("Input Bar - Chars Counter on Input Bar displays 0/1024 before typing a text", async () => { + // Validate Char counter is displayed on Input Bar and it displays 0/1024 + const inputCharCounter = await chatsInputFirstUser.inputCharCounterText; + const inputCharMaxText = await chatsInputFirstUser.inputCharMaxText; + await expect(inputCharCounter).toHaveTextContaining("0"); + await expect(inputCharMaxText).toHaveTextContaining("/1024"); + }); + + it("Input Bar - Chars Counter on Input Bar displays the number of chars of text entered", async () => { + // Validate Char counter increases after typing a text + const inputCharCounter = await chatsInputFirstUser.inputCharCounterText; + const inputCharMaxText = await chatsInputFirstUser.inputCharMaxText; + await chatsInputFirstUser.typeMessageOnInput("Testing..."); + await expect(inputCharCounter).toHaveTextContaining("10"); + await expect(inputCharMaxText).toHaveTextContaining("/1024"); + }); + + it("Input Bar - Add emoji to the message to be sent", async () => { + // Add emoji to the message to be sent + await chatsInputFirstUser.clickOnEmojiButton(); + await emojiSelectorFirstUser.clickOnEmoji("๐Ÿ˜€"); + + // Validate Char counter increases after adding an emoji to input bar + const inputCharCounter = await chatsInputFirstUser.inputCharCounterText; + const inputCharMaxText = await chatsInputFirstUser.inputCharMaxText; + await expect(inputCharCounter).toHaveTextContaining("11"); + await expect(inputCharMaxText).toHaveTextContaining("/1024"); + }); + + it("Input Bar - Click on send button will send the message to the other user", async () => { + // Send message to the other user + await chatsInputFirstUser.clickOnSendMessage(); + await chatsMessagesFirstUser.waitForMessageSentToExist("Testing...๐Ÿ˜€"); + + const textFromMessage = + await chatsMessagesFirstUser.getFirstMessageSentText(); + await expect(textFromMessage).toHaveTextContaining("Testing...๐Ÿ˜€"); + }); + + it("Input Bar - Chars Counter on Input Bar displays 0/1024 after sending a message", async () => { + // Validate Char counter is displayed on Input Bar and it displays 0/1024 + const inputCharCounter = await chatsInputFirstUser.inputCharCounterText; + const inputCharMaxText = await chatsInputFirstUser.inputCharMaxText; + await expect(inputCharCounter).toHaveTextContaining("0"); + await expect(inputCharMaxText).toHaveTextContaining("/1024"); + }); + + it("Chat User A - Validate Chat Message displays timestamp and user who sent it", async () => { + //Timestamp from last message sent should be displayed + const timeAgo = + await chatsMessageGroupsFirstUser.getLastMessageSentTimeAgo(); + await expect(timeAgo).toHaveTextContaining( + /- (?:\d{1,2}\s+(?:second|minute)s?\s+ago|now)$/, + ); + await expect(timeAgo).toHaveTextContaining("ChatUserA"); + }); + + it("Chat User A - Validate Chat Message sent contents", async () => { + //Any message you sent yourself should appear within a colored message bubble + const messageText = await chatsMessagesFirstUser.getFirstMessageSentText(); + await expect(messageText).toHaveTextContaining("Testing...๐Ÿ˜€"); + }); + + it("Chat User A - Validate Chat Message Group displays username picture", async () => { + //Your user image should be displayed next to the message + const userImage = + await chatsMessageGroupsFirstUser.getLastGroupWrapSentImage(); + await userImage.waitForExist(); + }); + + it("Chat User A - Topbar information", async () => { + // Validate user image, username is displayed on Chat Topbar + await chatsTopbarFirstUser.validateTopbarUserImage(); + await chatsTopbarFirstUser.validateTopbarUserName("ChatUserB"); + }); + + it("Chat User A - Add user with active chat to Favorites", async () => { + // Add user to favorites + await chatsTopbarFirstUser.addToFavorites(); + await favoritesSidebarFirstUser.validateFavoritesAreShown(); + + // Favorites Sidebar User bubble should be displayed with image + await favoritesSidebarFirstUser.validateFavoritesUserImage("ChatUserB"); + }); + + it("Chat User A - Remove user with active chat from Favorites", async () => { + // Remove user from favorites + await chatsTopbarFirstUser.removeFromFavorites(); + }); +} diff --git a/tests/specs/reusable-accounts/ChatUserA/02-chat-replies-userA.spec.ts b/tests/specs/reusable-accounts/ChatUserA/02-chat-replies-userA.spec.ts new file mode 100644 index 0000000000..850b739adb --- /dev/null +++ b/tests/specs/reusable-accounts/ChatUserA/02-chat-replies-userA.spec.ts @@ -0,0 +1,70 @@ +import "module-alias/register"; +import { USER_A_INSTANCE } from "@helpers/constants"; +import ContextMenu from "@screenobjects/chats/ContextMenu"; +import InputBar from "@screenobjects/chats/InputBar"; +import MessageGroup from "@screenobjects/chats/MessageGroup"; +import Messages from "@screenobjects/chats/Messages"; +import ReplyPrompt from "@screenobjects/chats/ReplyPrompt"; +let chatsContextMenuFirstUser = new ContextMenu(USER_A_INSTANCE); +let chatsInputFirstUser = new InputBar(USER_A_INSTANCE); +let chatsMessageGroupsFirstUser = new MessageGroup(USER_A_INSTANCE); +let chatsMessagesFirstUser = new Messages(USER_A_INSTANCE); +let chatsReplyPromptFirstUser = new ReplyPrompt(USER_A_INSTANCE); + +export default async function repliesTestsUserA() { + it("Chat User A - Validate reply message contents", async () => { + // With User A - Validate that reply message is received + await chatsMessagesFirstUser.chatMessageReply.waitForExist(); + + // Validate message replied appears smaller above your reply + const replyReceived = await chatsMessagesFirstUser.getLastReply(); + const replyReceivedText = await chatsMessagesFirstUser.getLastReplyText(); + await replyReceived.waitForExist(); + await expect(replyReceivedText).toHaveTextContaining("Testing...๐Ÿ˜€"); + + // Validate reply message sent appears as last message + const textFromMessage = + await chatsMessagesFirstUser.getLastMessageReceivedText(); + await expect(textFromMessage).toHaveTextContaining("Reply"); + }); + + it("Chat User A - Validate reply message group contains timestamp", async () => { + //Timestamp from last message sent should be displayed + const timeAgo = + await chatsMessageGroupsFirstUser.getLastMessageReceivedTimeAgo(); + await expect(timeAgo).toHaveTextContaining( + /- (?:\d{1,2}\s+(?:second|minute)s?\s+ago|now)$/, + ); + await expect(timeAgo).toHaveTextContaining("ChatUserB"); + }); + + it("Chat User A - Validate reply message group contains user image", async () => { + //Your user image should be displayed next to the message + const userImage = + await chatsMessageGroupsFirstUser.getLastGroupWrapReceivedImage(); + await userImage.waitForExist(); + }); + + it("Chat User A - Reply to yourself", async () => { + // Open Context Menu on Last Message Sent + await chatsMessagesFirstUser.openContextMenuOnLastSent(); + await chatsContextMenuFirstUser.validateContextMenuIsOpen(); + await chatsContextMenuFirstUser.selectContextOptionReply(); + + // Type a reply and sent it + await chatsReplyPromptFirstUser.replyPopUp.waitForExist(); + await chatsInputFirstUser.typeMessageOnInput("SelfReply"); + await chatsInputFirstUser.clickOnSendMessage(); + await chatsReplyPromptFirstUser.waitForReplyModalToNotExist(); + + // Validate reply to self message is displayed on Chat Conversation + const repliedMessage = await chatsMessagesFirstUser.getLastReply(); + const repliedMessageText = await chatsMessagesFirstUser.getLastReplyText(); + await repliedMessage.waitForExist(); + await expect(repliedMessageText).toHaveTextContaining("Testing...๐Ÿ˜€"); + + // Validate reply message sent appears as last message + const message = await chatsMessagesFirstUser.getLastMessageSentText(); + await expect(message).toHaveTextContaining("SelfReply"); + }); +} diff --git a/tests/specs/reusable-accounts/ChatUserA/03-message-context-menu-userA.spec.ts b/tests/specs/reusable-accounts/ChatUserA/03-message-context-menu-userA.spec.ts new file mode 100644 index 0000000000..de8a9ca0dd --- /dev/null +++ b/tests/specs/reusable-accounts/ChatUserA/03-message-context-menu-userA.spec.ts @@ -0,0 +1,71 @@ +import "module-alias/register"; +import { USER_A_INSTANCE } from "@helpers/constants"; +import ContextMenu from "@screenobjects/chats/ContextMenu"; +import InputBar from "@screenobjects/chats/InputBar"; +import MessageGroup from "@screenobjects/chats/MessageGroup"; +import Messages from "@screenobjects/chats/Messages"; +let chatsContextMenuFirstUser = new ContextMenu(USER_A_INSTANCE); +let chatsInputFirstUser = new InputBar(USER_A_INSTANCE); +let chatsMessagesFirstUser = new Messages(USER_A_INSTANCE); +let chatsMessageGroupsFirstUser = new MessageGroup(USER_A_INSTANCE); + +export default async function messageContextMenuTestsUserA() { + it("Chat User A - Send two messages to Chat User B", async () => { + // Send a message to Chat User B + await chatsInputFirstUser.typeMessageOnInput("Two..."); + await chatsInputFirstUser.clickOnSendMessage(); + await chatsMessagesFirstUser.waitForMessageSentToExist("Two..."); + + // Send a message to Chat User B + await chatsInputFirstUser.typeMessageOnInput("Three..."); + await chatsInputFirstUser.clickOnSendMessage(); + await chatsMessagesFirstUser.waitForMessageSentToExist("Three..."); + }); + + it("Chat User A - Context Menu - Delete Message", async () => { + // Open context menu on last message sent and select option for deleting + await chatsMessagesFirstUser.openContextMenuOnLastSent(); + await chatsContextMenuFirstUser.validateContextMenuIsOpen(); + await chatsContextMenuFirstUser.selectContextOptionDelete(); + + // Validate that last message was deleted and therefore the last message displayed is "two..." + const textMessage = await chatsMessagesFirstUser.getLastMessageSentText(); + await expect(textMessage).toHaveTextContaining("Two..."); + }); + + it("Chat User A - React to sent message and multiple reactions in a message", async () => { + // React with ๐Ÿ˜‚ emoji + await chatsMessagesFirstUser.openContextMenuOnLastSent(); + await chatsContextMenuFirstUser.validateContextMenuIsOpen(); + await chatsContextMenuFirstUser.clickOnFirstReaction(); + await chatsMessageGroupsFirstUser.waitUntilEmojiReactionSelfExists("๐Ÿ˜‚"); + + // React with ๐Ÿ–– emoji + await chatsMessagesFirstUser.openContextMenuOnLastSent(); + await chatsContextMenuFirstUser.validateContextMenuIsOpen(); + await chatsContextMenuFirstUser.clickOnSecondReaction(); + await chatsMessageGroupsFirstUser.waitUntilEmojiReactionSelfExists("๐Ÿ––"); + + // Validate reactions are displayed correctly + const reactions = + await chatsMessageGroupsFirstUser.getLastMessageSentSelfReactions(); + await expect(reactions.includes("๐Ÿ–– 1")).toEqual(true); + await expect(reactions.includes("๐Ÿ˜‚ 1")).toEqual(true); + }); + + it("Chat User A - React to received message", async () => { + // Validate message received from Chat User A + await chatsMessagesFirstUser.waitForReceivingMessage("Reply"); + + // React with ๐Ÿ‘Ž emoji + await chatsMessagesFirstUser.openContextMenuOnLastReceived(); + await chatsContextMenuFirstUser.validateContextMenuIsOpen(); + await chatsContextMenuFirstUser.clickOnThirdReaction(); + await chatsMessageGroupsFirstUser.waitUntilEmojiReactionSelfExists("๐Ÿ‘Ž"); + + // Validate reaction is displayed correctly + const reaction = + await chatsMessageGroupsFirstUser.getLastMessageReceivedSelfReactions(); + await expect(reaction.includes("๐Ÿ‘Ž 1")).toEqual(true); + }); +} diff --git a/tests/specs/reusable-accounts/ChatUserA/04-message-input-userA.spec.ts b/tests/specs/reusable-accounts/ChatUserA/04-message-input-userA.spec.ts new file mode 100644 index 0000000000..4205dcd658 --- /dev/null +++ b/tests/specs/reusable-accounts/ChatUserA/04-message-input-userA.spec.ts @@ -0,0 +1,131 @@ +import "module-alias/register"; +import { USER_A_INSTANCE, USER_B_INSTANCE } from "@helpers/constants"; +import InputBar from "@screenobjects/chats/InputBar"; +import Messages from "@screenobjects/chats/Messages"; +let chatsInputFirstUser = new InputBar(USER_A_INSTANCE); +let chatsMessagesFirstUser = new Messages(USER_A_INSTANCE); + +export default async function messageInputTestsUserA() { + it("Chat User A - Message Input - User cannot send empty messages", async () => { + // Ensure that input bar is empty and click on send message button + await chatsInputFirstUser.clearInputBar(); + await chatsInputFirstUser.clickOnInputBar(); + await chatsInputFirstUser.clickOnSendMessage(); + + // Ensure that input bar is empty and press Enter Key + await chatsInputFirstUser.clearInputBar(); + await chatsInputFirstUser.clickOnInputBar(); + await chatsInputFirstUser.pressEnterKeyOnInputBar(); + + // Validate latest message sent displayed on Chat Conversation is still "Two..." + const textMessage = await chatsMessagesFirstUser.getLastMessageSentText(); + await expect(textMessage).toHaveTextContaining("Two..."); + }); + + // Skipping test failing on CI due to slowness on driver typing 1024 characters + xit("Chat User A - Message Input - User can type up to 1024 chars on input bar", async () => { + // Generate a random text with 1024 chars + const longText = await chatsInputFirstUser.generateRandomText(); + // Type long text with 1024 chars on input bar and attempt to add 4 more chars (efgh) + await chatsInputFirstUser.typeMessageOnInput(longText + "efgh"); + + // Ensure that latest chars were not added to input bar, since the max number of chars has been reached + // Input bar text should be equal to long text with 1024 chars + await expect(chatsInputFirstUser.inputText).toHaveText(longText); + + // Clear input bar to finish test + await chatsInputFirstUser.clearInputBar(); + }); + + it("Chat Input Text - Validate texts with ** markdown are sent in bolds", async () => { + // With Chat User A, send a message with ** markdown + await chatsInputFirstUser.clearInputBar(); + await chatsInputFirstUser.typeMessageOnInput("**Bolds1**"); + await chatsInputFirstUser.clickOnSendMessage(); + await chatsMessagesFirstUser.waitForMessageSentToExist("Bolds1"); + }); + + it("Chat Input Text - Validate texts with __ markdown are sent in bolds", async () => { + // With Chat User A, send a message with __ markdown + await chatsInputFirstUser.typeMessageOnInput("__Bolds2__"); + await chatsInputFirstUser.clickOnSendMessage(); + await chatsMessagesFirstUser.waitForMessageSentToExist("Bolds2"); + }); + + it("Chat Input Text - Validate users can send messages using the code language markdown", async () => { + // With Chat User A, send a code snippet with JavaScript language + await chatsInputFirstUser.typeCodeOnInputBar("JavaScript", "let a = 1;"); + await chatsInputFirstUser.clickOnSendMessage(); + + // With Chat User A, validate code message was sent and is displayed correctly + await chatsMessagesFirstUser.waitForCodeMessageSentToExist("JavaScript"); + const codeMessageTextSent = + await chatsMessagesFirstUser.getLastMessageSentCodeMessage(); + await expect(codeMessageTextSent).toEqual("let a = 1;"); + }); + + // Skipping test that is failing often on CI - Requires investigation to improve execution + xit("Chat Input Text - Code Markdown - User can copy the message from the code block", async () => { + // With Chat User A, click on the copy button from code block of last chat message sent + await chatsMessagesFirstUser.clickOnCopyCodeOfLastMessageSent(); + + // Then, paste it into the input bar and assert the text contents on input bar + await chatsInputFirstUser.pasteClipboardOnInputBar(); + await expect(chatsInputFirstUser.inputText).toHaveText("let a = 1;"); + + // Finally, clear the input bar for next tests + await chatsInputFirstUser.clearInputBar(); + }); + + it("Chat Input Text - Validate text starting with https:// is sent as link", async () => { + // With Chat User A + await chatsInputFirstUser.typeMessageOnInput("https://www.google.com"); + await chatsInputFirstUser.clickOnSendMessage(); + await chatsMessagesFirstUser.waitForLinkSentToExist( + "https://www.google.com", + ); + }); + + it("Chat Input Text - Validate text starting with www. is sent as link", async () => { + // With Chat User A + await chatsInputFirstUser.typeMessageOnInput("www.apple.com"); + await chatsInputFirstUser.clickOnSendMessage(); + await chatsMessagesFirstUser.waitForLinkSentToExist("www.apple.com"); + }); + + it("Chat Input Text - Validate text starting with http:// is sent as link", async () => { + // With Chat User A + await chatsInputFirstUser.typeMessageOnInput("http://www.satellite.im"); + await chatsInputFirstUser.clickOnSendMessage(); + await chatsMessagesFirstUser.waitForLinkSentToExist( + "http://www.satellite.im", + ); + }); + + it("Chat User - Chat Messages containing links contents on local side", async () => { + // Validate link embed contents on chat message + const linkEmbedSent = + await chatsMessagesFirstUser.getLastMessageSentLinkEmbed(); + const linkEmbedSentDetailsText = + await chatsMessagesFirstUser.getLastMessageSentLinkEmbedDetailsText(); + const linkEmbedSentIcon = + await chatsMessagesFirstUser.getLastMessageSentLinkEmbedIcon(); + const linkEmbedSentIconTitle = + await chatsMessagesFirstUser.getLastMessageSentLinkEmbedIconTitle(); + + await linkEmbedSent.waitForExist(); + await expect(linkEmbedSentDetailsText).toHaveTextContaining( + "P2P Chat, Voice & Video Open-source, stored on IPFS. End to end encryption... trackers not included.", + ); + await linkEmbedSentIcon.waitForExist(); + await linkEmbedSentIconTitle.waitForExist(); + }); + + // Skipping test failing on because the typing indicator is gone before the test can validate it + xit("Typing Indicator - Send a long message to trigger typing indicator on remote side", async () => { + // Generate a random text with 100 chars + const shortText = await chatsInputFirstUser.generateShortRandomText(); + // Type the text with 90 chars on input bar + await chatsInputFirstUser.typeMessageOnInput(shortText + "efgh"); + }); +} diff --git a/tests/specs/reusable-accounts/ChatUserA/05-message-attachments-userA.spec.ts b/tests/specs/reusable-accounts/ChatUserA/05-message-attachments-userA.spec.ts new file mode 100644 index 0000000000..9940788b24 --- /dev/null +++ b/tests/specs/reusable-accounts/ChatUserA/05-message-attachments-userA.spec.ts @@ -0,0 +1,79 @@ +import "module-alias/register"; +import { USER_A_INSTANCE } from "@helpers/constants"; +import ComposeAttachment from "@screenobjects/chats/ComposeAttachment"; +import InputBar from "@screenobjects/chats/InputBar"; +import Messages from "@screenobjects/chats/Messages"; +let chatsAttachmentFirstUser = new ComposeAttachment(USER_A_INSTANCE); +let chatsInputFirstUser = new InputBar(USER_A_INSTANCE); +let chatsMessagesFirstUser = new Messages(USER_A_INSTANCE); + +export default async function messageAttachmentsTestsUserA() { + it("Send files from Browse Files - Message sent with attachments is shown on remote side", async () => { + // Ensure that message sent with attached file is displayed on remote side + // With User A- Validate that message with attachment was received + await chatsInputFirstUser.clickOnInputBar(); + await chatsMessagesFirstUser.chatMessageFileEmbedRemote.waitForExist(); + + // Validate text from message containing attachment + const message = await chatsMessagesFirstUser.getLastMessageReceivedText(); + await expect(message).toHaveTextContaining("Attached"); + }); + + it("Send Files on Chats - Validate compose attachments contents", async () => { + // Continue with test execution and clear input bar + await chatsInputFirstUser.clearInputBar(); + + // Click on upload button and attach a file to compose attachment + await chatsInputFirstUser.uploadFileFromLocalDisk( + "./tests/fixtures/testfile.txt", + ); + + // Validate contents on Compose Attachments are displayed + await chatsAttachmentFirstUser.composeAttachmentsFileEmbed.waitForExist(); + await chatsAttachmentFirstUser.composeAttachmentsFileIcon.waitForExist(); + await chatsAttachmentFirstUser.composeAttachmentsFileNameText.waitForExist(); + }); + + it("Send Files on Chats - Delete attachment before sending the message", async () => { + // Click on upload button and attach a file to compose attachment + await chatsAttachmentFirstUser.deleteFileOnComposeAttachment(); + }); + + it("Receive Files on Chats - Received Message with Attachment - Text Message contents", async () => { + // With User B - Validate that message with attachment was received + await chatsInputFirstUser.clickOnInputBar(); + await chatsMessagesFirstUser.chatMessageFileEmbedRemote.waitForExist(); + + // Validate text from message containing attachment + const message = await chatsMessagesFirstUser.getLastMessageReceivedText(); + await expect(message).toHaveTextContaining("Attached2"); + }); + + it("Receive Files on Chats - Attachment File Contents", async () => { + // Validate file metadata is displayed correctly on last chat message sent + const fileMeta = + await chatsMessagesFirstUser.getLastMessageReceivedFileMeta(); + await expect(fileMeta).toHaveTextContaining("47 B"); + + // Validate filename is displayed correctly on last chat message sent + const fileName = + await chatsMessagesFirstUser.getLastMessageReceivedFileName(); + await expect(fileName).toHaveTextContaining("testfile.txt"); + + // Validate file icon is displayed correctly on last chat message sent + const fileIcon = + await chatsMessagesFirstUser.getLastMessageReceivedFileIcon(); + await fileIcon.waitForExist(); + + // Validate file download button is displayed correctly on last chat message sent + await chatsMessagesFirstUser.hoverOnLastFileReceived(); + const fileDownloadButton = + await chatsMessagesFirstUser.getLastMessageReceivedDownloadButton(); + await fileDownloadButton.waitForExist(); + }); + + it("Chat Messages with Files - Remote user can download file received", async () => { + // Download latest image file received + await chatsMessagesFirstUser.downloadLastReceivedFile(".txt"); + }); +} diff --git a/tests/specs/reusable-accounts/ChatUserA/06-chat-topbar-userA.spec.ts b/tests/specs/reusable-accounts/ChatUserA/06-chat-topbar-userA.spec.ts new file mode 100644 index 0000000000..94bdd65a22 --- /dev/null +++ b/tests/specs/reusable-accounts/ChatUserA/06-chat-topbar-userA.spec.ts @@ -0,0 +1,123 @@ +import "module-alias/register"; +import InputBar from "@screenobjects/chats/InputBar"; +import ContextMenu from "@screenobjects/chats/ContextMenu"; +import Messages from "@screenobjects/chats/Messages"; +import MessageGroup from "@screenobjects/chats/MessageGroup"; +import PinnedMessages from "@screenobjects/chats/PinnedMessages"; +import Topbar from "@screenobjects/chats/Topbar"; +import { USER_A_INSTANCE } from "@helpers/constants"; +let chatsContextMenuFirstUser = new ContextMenu(USER_A_INSTANCE); +let chatsInputFirstUser = new InputBar(USER_A_INSTANCE); +let chatsMessagesFirstUser = new Messages(USER_A_INSTANCE); +let chatsMessageGroupsFirstUser = new MessageGroup(USER_A_INSTANCE); +let chatsTopbarFirstUser = new Topbar(USER_A_INSTANCE); +let pinnedMessagesFirstUser = new PinnedMessages(USER_A_INSTANCE); + +export default async function chatTopbarTestsUserA() { + it("Chat User A - Validate Chat Screen tooltips are displayed", async () => { + // Validate Favorites button tooltip + await chatsTopbarFirstUser.hoverOnFavoritesButton(); + const favoritesAddTooltipText = + await chatsTopbarFirstUser.topbarAddToFavoritesTooltipText; + await expect(favoritesAddTooltipText).toHaveTextContaining( + "Add to Favorites", + ); + + // Validate Pinned Messages button tooltip + await chatsTopbarFirstUser.hoverOnPinnedMessagesButton(); + const pinnedMessagesTooltipText = + await chatsTopbarFirstUser.topbarPinnedMessagesTooltipText; + await expect(pinnedMessagesTooltipText).toHaveTextContaining( + "Pinned Messages", + ); + + // Validate Upload button tooltip + await chatsInputFirstUser.hoverOnUploadButton(); + const uploadTooltipText = await chatsInputFirstUser.uploadTooltipText; + await expect(uploadTooltipText).toHaveTextContaining("Upload"); + + // Validate Send button tooltip + await chatsInputFirstUser.hoverOnSendButton(); + const sendMessageTooltipText = + await chatsInputFirstUser.sendMessageTooltipText; + await expect(sendMessageTooltipText).toHaveTextContaining("Send"); + }); + + it("Chat User A - Validate Chat Screen tooltips for Call and Videocall display Coming soon", async () => { + // Validate Call button tooltip contains "Coming soon" + await chatsTopbarFirstUser.hoverOnCallButton(); + const callTooltipText = await chatsTopbarFirstUser.topbarCallTooltipText; + await expect(callTooltipText).toHaveTextContaining("Coming soon"); + + // Validate Videocall button tooltip contains "Coming soon" + await chatsTopbarFirstUser.hoverOnVideocallButton(); + const videoCallTooltipText = + await chatsTopbarFirstUser.topbarVideocallTooltipText; + await expect(videoCallTooltipText).toHaveTextContaining("Coming soon"); + }); + + it("Pinned Messages - Container is empty when no pinned messages have been added", async () => { + // Go to Pinned Messages and validate container is empty + await chatsTopbarFirstUser.clickOnPinnedMessages(); + await pinnedMessagesFirstUser.validatePinnedMessagesIsDisplayed(); + await pinnedMessagesFirstUser.validateEmptyPinnedMessagesIsDisplayed(); + + // Exit from Pinned Messages + await chatsTopbarFirstUser.clickOnPinnedMessages(); + }); + + it("Pinned Messages - Pin a message with attachments", async () => { + // Look for the latest message received by User A, open context menu and pin message + await chatsMessagesFirstUser.openContextMenuOnLastReceived(); + await chatsContextMenuFirstUser.validateContextMenuIsOpen(); + await chatsContextMenuFirstUser.selectContextOptionPin(); + + // Ensure that message shows a pin indicator + await chatsMessageGroupsFirstUser.validateLastMessageReceivedHasPinIndicator(); + }); + + it("Pinned Messages - Pinned message shows timestamp, sender and message", async () => { + // Go to Pinned Messages and validate container shows message + await chatsTopbarFirstUser.clickOnPinnedMessages(); + await pinnedMessagesFirstUser.validatePinnedMessagesIsDisplayed(); + + // Validate pinned message shows timestamp, sender and message + await pinnedMessagesFirstUser.validateFirstPinnedMessageImageProfileIsShown(); + await pinnedMessagesFirstUser.validateFirstPinnedMessageTimestampIsShown(); + await pinnedMessagesFirstUser.validateFirstPinnedMessageSender("ChatUserB"); + await pinnedMessagesFirstUser.validateFirstPinnedMessageText("Attached2"); + }); + + it("Pinned Messages - Pinned message with attachment shows icon, extension, filename and metadata", async () => { + // Validate attachment elements are shown in pinned message + await pinnedMessagesFirstUser.validateFirstPinnedMessageAttachmentFileIcon(); + await pinnedMessagesFirstUser.validateFirstPinnedMessageAttachmentFileIconExtension( + "txt", + ); + await pinnedMessagesFirstUser.validateFirstPinnedMessageAttachmentFileMeta( + "47 B", + ); + await pinnedMessagesFirstUser.validateFirstPinnedMessageAttachmentFileName( + "testfile.txt", + ); + }); + + it("Pinned Messages - User can be redirected to the message when clicking on Go to message", async () => { + // Click on Go to Message + await pinnedMessagesFirstUser.clickOnGoToMessage(0); + + // Open pinned messages + await chatsTopbarFirstUser.clickOnPinnedMessages(); + }); + + it("Pinned Messages - Remove a pinned message", async () => { + // Click on Unpin button to remove message from pinned messages + await pinnedMessagesFirstUser.clickOnUnpinMessage(0); + + // Validate that no posts are pinned + await pinnedMessagesFirstUser.validateEmptyPinnedMessagesIsDisplayed(); + + // Close pinned messages + await chatsTopbarFirstUser.clickOnPinnedMessages(); + }); +} diff --git a/tests/specs/reusable-accounts/ChatUserA/07-quick-profile-userA.spec.ts b/tests/specs/reusable-accounts/ChatUserA/07-quick-profile-userA.spec.ts new file mode 100644 index 0000000000..7945249d73 --- /dev/null +++ b/tests/specs/reusable-accounts/ChatUserA/07-quick-profile-userA.spec.ts @@ -0,0 +1,147 @@ +import "module-alias/register"; +import { getUserKey } from "@helpers/commands"; +import { USER_A_INSTANCE } from "@helpers/constants"; +import FriendsScreen from "@screenobjects/friends/FriendsScreen"; +import InputBar from "@screenobjects/chats/InputBar"; +import MessageGroup from "@screenobjects/chats/MessageGroup"; +import Messages from "@screenobjects/chats/Messages"; +import QuickProfile from "@screenobjects/chats/QuickProfile"; +import Topbar from "@screenobjects/chats/Topbar"; +import SettingsProfileScreen from "@screenobjects/settings/SettingsProfileScreen"; +import WelcomeScreen from "@screenobjects/welcome-screen/WelcomeScreen"; + +let chatsInputFirstUser = new InputBar(USER_A_INSTANCE); +let chatsMessageGroupsFirstUser = new MessageGroup(USER_A_INSTANCE); +let chatsMessagesFirstUser = new Messages(USER_A_INSTANCE); +let chatsQuickProfileFirstUser = new QuickProfile(USER_A_INSTANCE); +let chatsTopbarFirstUser = new Topbar(USER_A_INSTANCE); +let friendsScreenFirstUser = new FriendsScreen(USER_A_INSTANCE); +let settingsProfileFirstUser = new SettingsProfileScreen(USER_A_INSTANCE); +let welcomeScreenFirstUser = new WelcomeScreen(USER_A_INSTANCE); + +export default async function quickProfileTestsUserA() { + it("Chat User A - Validate contents from local quick profile", async () => { + // Open quick profile from remote user + await chatsMessageGroupsFirstUser.openLocalQuickProfile(); + await chatsQuickProfileFirstUser.quickProfile.waitForExist(); + + // Validate contents from quick profile + await chatsQuickProfileFirstUser.quickProfileUserImage.waitForExist(); + await chatsQuickProfileFirstUser.quickProfileBannerImage.waitForExist(); + await chatsQuickProfileFirstUser.quickProfileEditProfile.waitForExist(); + const quickProfileUsername = + await chatsQuickProfileFirstUser.quickProfileUserNameValueText; + await expect(quickProfileUsername).toHaveTextContaining("ChatUserA"); + }); + + it("Chat User A - Click on Edit Profile", async () => { + // Click on Edit Profile from Quick Profile + await chatsQuickProfileFirstUser.clickOnEditProfile(); + await settingsProfileFirstUser.validateSettingsProfileIsShown(); + await settingsProfileFirstUser.goToMainScreen(); + }); + + it("Chat User A - Validate contents from remote quick profile", async () => { + // With User A - Validate that message was received + await chatsInputFirstUser.clickOnInputBar(); + await chatsMessagesFirstUser.waitForReceivingMessage("click..."); + + // Open quick profile from remote user + await chatsMessageGroupsFirstUser.openRemoteQuickProfile(); + + // Validate quick profile is displayed + await chatsQuickProfileFirstUser.quickProfile.waitForExist(); + + // Validate contents from quick profile + await chatsQuickProfileFirstUser.quickProfileUserImage.waitForExist(); + await chatsQuickProfileFirstUser.quickProfileBannerImage.waitForExist(); + await chatsQuickProfileFirstUser.quickProfileRemoveFriend.waitForExist(); + await chatsQuickProfileFirstUser.quickProfileBlockUser.waitForExist(); + + // Validate username from quick profile + const quickProfileUsername = + await chatsQuickProfileFirstUser.quickProfileUserNameValueText; + await expect(quickProfileUsername).toHaveTextContaining("ChatUserB"); + + // Click outside to close quick profile + await chatsInputFirstUser.clickOnInputBar(); + }); + + it("Chat User A - Remove Friend", async () => { + // Open quick profile from remote user + await chatsMessageGroupsFirstUser.openRemoteQuickProfile(); + await chatsQuickProfileFirstUser.quickProfile.waitForExist(); + + // Click on Remove Friend from Quick Profile + await chatsQuickProfileFirstUser.clickOnRemoveUser(); + + // Welcome Screen should be displayed + await welcomeScreenFirstUser.skeletalUser.waitForExist(); + }); + + it("Chat User A - Ensure that Chat User B is not in friends list now", async () => { + // Get current list of All friends and ensure that it does not include the removed user + await welcomeScreenFirstUser.goToFriends(); + const allFriendsList = await friendsScreenFirstUser.getAllFriendsList(); + const includesFriend = await allFriendsList.includes("ChatUserB"); + await expect(includesFriend).toEqual(false); + }); + + it("Chat User A - Send friend request again to User B", async () => { + // Obtain did key from Chat User B + const friendDidKey = await getUserKey("ChatUserB", USER_A_INSTANCE); + await friendsScreenFirstUser.enterFriendDidKey(friendDidKey); + await friendsScreenFirstUser.clickOnAddSomeoneButton(); + + // Wait for toast notification to be closed + await friendsScreenFirstUser.waitUntilNotificationIsClosed(); + + // Validate friend request appears on pending list + await friendsScreenFirstUser.hoverOnPendingListButton(); + await friendsScreenFirstUser.goToPendingFriendsList(); + await friendsScreenFirstUser.validateOutgoingListIsShown(); + await friendsScreenFirstUser.validateOutgoingListIsNotEmpty(); + }); + + it("Chat User A - Wait until friend request is accepted again", async () => { + // Validate friend is now on all friends list + await friendsScreenFirstUser.goToAllFriendsList(); + await friendsScreenFirstUser.validateAllFriendsListIsShown(); + await friendsScreenFirstUser.validateAllFriendsListIsNotEmpty(); + + // Go to chat with User B + await friendsScreenFirstUser.validateChatWithFriendButtonIsShown(); + await friendsScreenFirstUser.hoverOnChatWithFriendButton("ChatUserB"); + await friendsScreenFirstUser.clickOnChatWithFriend(); + + // Validate that Topbar is displayed + await chatsTopbarFirstUser.validateTopbarExists(); + }); + + it("Chat User A - Block Friend", async () => { + // With User A - Validate that message was received + await chatsMessagesFirstUser.waitForReceivingMessage("Accepted..."); + + // Open quick profile from remote user + await chatsMessageGroupsFirstUser.openRemoteQuickProfile(); + await chatsQuickProfileFirstUser.quickProfile.waitForExist(); + + // Click on Block Friend from Quick Profile + await chatsQuickProfileFirstUser.clickOnBlockUser(); + + // Welcome Screen should be displayed + await welcomeScreenFirstUser.validateWelcomeScreenIsShown(); + }); + + it("Chat User A - Ensure that Chat User B is in blocked list now", async () => { + // Get current list of Blocked friends and ensure that it includes the blocked user + await welcomeScreenFirstUser.goToFriends(); + await friendsScreenFirstUser.goToBlockedList(); + await friendsScreenFirstUser.validateBlockedListIsShown(); + await friendsScreenFirstUser.validateBlockedListIsNotEmpty(); + + // Validate that blocked user is on blocked list + await friendsScreenFirstUser.goToAllFriendsList(); + await friendsScreenFirstUser.validateAllFriendsListIsShown(); + }); +} diff --git a/tests/specs/reusable-accounts/ChatUserA/08-sidebar-chats-userA.spec.ts b/tests/specs/reusable-accounts/ChatUserA/08-sidebar-chats-userA.spec.ts new file mode 100644 index 0000000000..c0fc5c2561 --- /dev/null +++ b/tests/specs/reusable-accounts/ChatUserA/08-sidebar-chats-userA.spec.ts @@ -0,0 +1,210 @@ +import "module-alias/register"; +import { getUserKey } from "@helpers/commands"; +import { USER_A_INSTANCE } from "@helpers/constants"; +import ChatsLayout from "@screenobjects/chats/ChatsLayout"; +import ChatsSidebar from "@screenobjects/chats/ChatsSidebar"; +import ContextMenuSidebar from "@screenobjects/chats/ContextMenuSidebar"; +import FavoritesSidebar from "@screenobjects/chats/FavoritesSidebar"; +import InputBar from "@screenobjects/chats/InputBar"; +import Messages from "@screenobjects/chats/Messages"; +import Topbar from "@screenobjects/chats/Topbar"; +import FilesScreen from "@screenobjects/files/FilesScreen"; +import FriendsScreen from "@screenobjects/friends/FriendsScreen"; +import SettingsProfileScreen from "@screenobjects/settings/SettingsProfileScreen"; +import WelcomeScreen from "@screenobjects/welcome-screen/WelcomeScreen"; +let chatsInputFirstUser = new InputBar(USER_A_INSTANCE); +let chatsLayoutFirstUser = new ChatsLayout(USER_A_INSTANCE); +let chatsMessagesFirstUser = new Messages(USER_A_INSTANCE); +let chatsSidebarFirstUser = new ChatsSidebar(USER_A_INSTANCE); +let chatsTopbarFirstUser = new Topbar(USER_A_INSTANCE); +let contextMenuSidebarFirstUser = new ContextMenuSidebar(USER_A_INSTANCE); +let favoritesSidebarFirstUser = new FavoritesSidebar(USER_A_INSTANCE); +let filesScreenFirstUser = new FilesScreen(USER_A_INSTANCE); +let friendsScreenFirstUser = new FriendsScreen(USER_A_INSTANCE); +let settingsProfileFirstUser = new SettingsProfileScreen(USER_A_INSTANCE); +let welcomeScreenFirstUser = new WelcomeScreen(USER_A_INSTANCE); + +export default async function sidebarChatsTestsUserA() { + it("Chat User A - Unblock the other Chat User", async () => { + // Unblock Chat User B and go to Friends List to send a new friend request + await friendsScreenFirstUser.validateFriendsScreenIsShown(); + await friendsScreenFirstUser.hoverOnBlockedListButton(); + await friendsScreenFirstUser.goToBlockedList(); + await friendsScreenFirstUser.validateBlockedListIsShown(); + await friendsScreenFirstUser.validateBlockedListIsNotEmpty(); + await friendsScreenFirstUser.removeOrCancelUser("ChatUserB"); + await friendsScreenFirstUser.removeOrDenyFriendButton.waitForExist({ + reverse: true, + }); + await friendsScreenFirstUser.goToAllFriendsList(); + await friendsScreenFirstUser.validateAllFriendsListIsShown(); + }); + + it("Chat User A - Send friend request again to Chat User B", async () => { + // Obtain did key from Chat User B + const friendDidKey = await getUserKey("ChatUserB", USER_A_INSTANCE); + await friendsScreenFirstUser.enterFriendDidKey(friendDidKey); + await friendsScreenFirstUser.clickOnAddSomeoneButton(); + + // Wait for toast notification to be closed + await friendsScreenFirstUser.waitUntilNotificationIsClosed(); + + // Validate that friend request was sent + await friendsScreenFirstUser.hoverOnPendingListButton(); + await friendsScreenFirstUser.goToPendingFriendsList(); + await friendsScreenFirstUser.validateOutgoingListIsShown(); + await friendsScreenFirstUser.validateRemoveOrDenyButtonIsShown(); + }); + + it("Chat User A - Wait until Chat User B accepts friend request and sends a message", async () => { + // Validate last message contents on Sidebar displays hello on bolds and not __hello__ + await chatsSidebarFirstUser.validateLastMessageDisplayed("hello"); + + // With User A - Wait until user B accepts the friend request + await friendsScreenFirstUser.goToAllFriendsList(); + await friendsScreenFirstUser.validateAllFriendsListIsShown(); + await friendsScreenFirstUser.validateAllFriendsListIsShown(); + await friendsScreenFirstUser.waitUntilUserAcceptedFriendRequest(); + + // Go to another part of the app + await friendsScreenFirstUser.goToMainScreen(); + + // Wait until message is received + await chatsSidebarFirstUser.waitForReceivingMessageOnSidebar(); + }); + + it("Chat User A - Sidebar - Any active chats user has created should appear in Sidebar", async () => { + // Validate Sidebar shows Username + await chatsSidebarFirstUser.validateUsernameDisplayed("ChatUserB"); + + // Validate number of unread messages is displayed on sidebar + await chatsSidebarFirstUser.validateNumberOfUnreadMessages("1"); + + // Validate time ago displayed on sidebar + await chatsSidebarFirstUser.validateLastMessageTimeAgo(); + }); + + it("Sidebar - Message preview on Sidebar should display the message without the markdown characters", async () => { + // Validate last message contents on Sidebar displays hello on bolds and not __hello__ + await chatsSidebarFirstUser.validateLastMessageDisplayed("hello"); + }); + + it("Chat User A - Sidebar - Context Menu - Clear Unreads", async () => { + // Open context menu and right click on Clear Unreads + await chatsSidebarFirstUser.openContextMenuOnSidebar("ChatUserB"); + await contextMenuSidebarFirstUser.selectChatsClearUnreads(); + await chatsSidebarFirstUser.validateNoUnreadMessages(); + }); + + it("Chat User A - Sidebar - Context Menu - Hide chat", async () => { + // Open context menu and right click on Hide chat + await chatsSidebarFirstUser.openContextMenuOnSidebar("ChatUserB"); + await contextMenuSidebarFirstUser.selectChatsHideChat(); + await chatsSidebarFirstUser.validateSidebarChatIsNotDisplayed("ChatUserB"); + }); + + it("Chat User A - Sidebar - Send a message to User B", async () => { + // Go to the current list of All friends and then open a Chat conversation with ChatUserA + await welcomeScreenFirstUser.goToFriends(); + await friendsScreenFirstUser.validateChatWithFriendButtonIsShown(); + await friendsScreenFirstUser.hoverOnChatWithFriendButton("ChatUserB"); + await friendsScreenFirstUser.clickOnChatWithFriend(); + await chatsLayoutFirstUser.validateChatLayoutIsShown(); + + // Send message to Chat User B + await chatsInputFirstUser.typeMessageOnInput("Hi..."); + await chatsInputFirstUser.clickOnSendMessage(); + await chatsMessagesFirstUser.waitForMessageSentToExist("Hi..."); + }); + + it("Chat User A - Sidebar - Persists between different sections of the app - Files Screen", async () => { + // Validate on Files Screen that sidebar is displayed + await chatsLayoutFirstUser.goToFiles(); + await filesScreenFirstUser.validateFilesScreenIsShown(); + await chatsSidebarFirstUser.validateSidebarChatsIsShown(); + }); + + it("Chat User A - Chats Sidebar is hidden when entering to Settings Screen", async () => { + // Go to Settings Profile Screen + await filesScreenFirstUser.goToSettings(); + await settingsProfileFirstUser.validateSettingsProfileIsShown(); + + // Validate that Chats Sidebar is not displayed on Settings Screen + await chatsSidebarFirstUser.sidebarChatsSection.waitForExist({ + reverse: true, + }); + }); + + it("Chat User A - Chats Sidebar is displayed again when opening Friends Screen", async () => { + // Validate on Friends Screen that sidebar is displayed + await settingsProfileFirstUser.goToFriends(); + await friendsScreenFirstUser.validateFriendsScreenIsShown(); + await chatsSidebarFirstUser.validateSidebarChatsIsShown(); + + // Return to chat + await chatsSidebarFirstUser.goToSidebarFirstChat(); + }); + + it("Chat User A - Sidebar - Validate Hamburger button and back buttons can hide or display the sidebar", async () => { + // Click on hamburger button and validate that Sidebar is hidden + await chatsLayoutFirstUser.clickOnHamburgerButton(); + + // Click on back button and validate that Sidebar is displayed again + await chatsLayoutFirstUser.clickOnBackButton(); + await chatsSidebarFirstUser.validateSidebarChatsIsShown(); + }); + + it("Chat User A - Sidebar - Context Menu - Delete chat", async () => { + // Open context menu and right click on Delete chat + await chatsSidebarFirstUser.openContextMenuOnSidebar("ChatUserB"); + await contextMenuSidebarFirstUser.selectChatsDeleteConversation(); + await chatsSidebarFirstUser.skeletalUser.waitForExist(); + }); + + it("Chat User A - Sidebar without messages sent displays No messages yet, sent one", async () => { + // Go to the current list of All friends and then open a Chat conversation with ChatUserA + await welcomeScreenFirstUser.goToFriends(); + await friendsScreenFirstUser.validateChatWithFriendButtonIsShown(); + await friendsScreenFirstUser.hoverOnChatWithFriendButton("ChatUserB"); + await friendsScreenFirstUser.clickOnChatWithFriend(); + await chatsLayoutFirstUser.validateChatLayoutIsShown(); + + // Validate that sidebar record is displayed with correct username and status + const sidebarChatUsername = + await chatsSidebarFirstUser.sidebarChatsUserNameValue; + await expect(sidebarChatUsername).toHaveTextContaining("ChatUserB"); + + const sidebarChatStatus = + await chatsSidebarFirstUser.sidebarChatsUserStatusValue; + await expect(sidebarChatStatus).toHaveTextContaining( + "No messages sent yet, send one!", + ); + }); + + it("Sidebar - Favorites - Add user to Favorites", async () => { + // Add user to favorites + await chatsTopbarFirstUser.addToFavorites(); + await favoritesSidebarFirstUser.validateFavoritesAreShown(); + + // Favorites Sidebar User bubble should be displayed with image + await favoritesSidebarFirstUser.validateFavoritesUserImage("ChatUserB"); + }); + + // Skipping test failing - needs research + xit("Sidebar - Favorites - Context Menu - Chat with user", async () => { + // Open context menu and right click on Chat with user + await favoritesSidebarFirstUser.goToFiles(); + await filesScreenFirstUser.validateFilesScreenIsShown(); + await favoritesSidebarFirstUser.openContextMenuOnFavoritesUser("ChatUserB"); + await favoritesSidebarFirstUser.clickOnContextMenuFavoritesChat(); + await chatsLayoutFirstUser.validateChatLayoutIsShown(); + await chatsInputFirstUser.typeMessageOnInput("Hi..."); + await chatsInputFirstUser.clearInputBar(); + }); + + it("Sidebar - Favorites - Context Menu - Remove user from Favorites", async () => { + // Open context menu and right click on Remove user from Favorites + await favoritesSidebarFirstUser.openContextMenuOnFavoritesUser("ChatUserB"); + await favoritesSidebarFirstUser.clickOnContextMenuFavoriteRemove(); + }); +} diff --git a/tests/specs/reusable-accounts/ChatUserA/09-group-chats-userA.spec.ts b/tests/specs/reusable-accounts/ChatUserA/09-group-chats-userA.spec.ts new file mode 100644 index 0000000000..0a573d553c --- /dev/null +++ b/tests/specs/reusable-accounts/ChatUserA/09-group-chats-userA.spec.ts @@ -0,0 +1,155 @@ +import "module-alias/register"; +import ChatsSidebar from "@screenobjects/chats/ChatsSidebar"; +import CreateGroupChat from "@screenobjects/chats/CreateGroupChat"; +import FilesScreen from "@screenobjects/files/FilesScreen"; +import InputBar from "@screenobjects/chats/InputBar"; +import Messages from "@screenobjects/chats/Messages"; +import SidebarSearch from "@screenobjects/chats/SidebarSearch"; +import Topbar from "@screenobjects/chats/Topbar"; +import { USER_A_INSTANCE } from "@helpers/constants"; +let chatsInputFirstUser = new InputBar(USER_A_INSTANCE); +let chatsMessagesFirstUser = new Messages(USER_A_INSTANCE); +let chatsSidebarFirstUser = new ChatsSidebar(USER_A_INSTANCE); +let chatsTopbarFirstUser = new Topbar(USER_A_INSTANCE); +let createGroupFirstUser = new CreateGroupChat(USER_A_INSTANCE); +let filesScreenFirstUser = new FilesScreen(USER_A_INSTANCE); +let sidebarSearchFirstUser = new SidebarSearch(USER_A_INSTANCE); + +export default async function groupChatTestsUserA() { + it("Chat User A - Create Group Chat button tooltip", async () => { + // Hover on create group chat button and validate tooltip is shown + await chatsSidebarFirstUser.hoverOnCreateGroupButton(); + }); + + it("Chat User A - Click on Create Group Chat and close modal", async () => { + // Open modal to create group chat + await chatsSidebarFirstUser.clickOnCreateGroupChat(); + await createGroupFirstUser.validateCreateGroupChatsIsShown(); + + // Click again on create group chat and modal will be closed + await chatsTopbarFirstUser.clickOnTopbar(); + await createGroupFirstUser.createGroupChatSection.waitForExist({ + reverse: true, + }); + }); + + it("Chat User A - Create Group Chat Modal contents", async () => { + // Open modal to create group chat + await chatsSidebarFirstUser.clickOnCreateGroupChat(); + await createGroupFirstUser.validateCreateGroupChatsIsShown(); + + // Validate contents + await createGroupFirstUser.createGroupChatButton.waitForExist(); + await createGroupFirstUser.friendsList.waitForExist(); + await createGroupFirstUser.groupNameInput.waitForExist(); + await createGroupFirstUser.userSearchInput.waitForExist(); + }); + + it("Chat User A - Attempt to create group chat with alphanumeric chars in name", async () => { + // Open modal to create group chat and type alphanumeric chars in name + await createGroupFirstUser.typeOnGroupName("@"); + await createGroupFirstUser.createGroupInputError.waitForExist(); + const inputErrorText = await createGroupFirstUser.createGroupInputErrorText; + await expect(inputErrorText).toHaveTextContaining( + "Not allowed character(s): @", + ); + await createGroupFirstUser.clearGroupNameInput(); + }); + + // Skipping test that sometimes fail in CI because Appium randomly jumps when typing into a different input field + xit("Chat User A - Attempt to create group chat with more than 64 chars in name", async () => { + // Open modal to create group chat and type more than 64 chars in name + await createGroupFirstUser.typeLongerTextInGroupName(); + await createGroupFirstUser.createGroupInputError.waitForExist(); + const inputErrorText = await createGroupFirstUser.createGroupInputErrorText; + await expect(inputErrorText).toHaveTextContaining( + "Maximum of 64 characters exceeded.", + ); + await createGroupFirstUser.clearGroupNameInput(); + }); + + it("Chat User A - Search bar - Look for non existing user", async () => { + // Open modal to create group chat and type non existing user + await createGroupFirstUser.typeOnUsersSearchInput("z"); + const numberOfUsersInList = + await createGroupFirstUser.getNumberOfUsersInListFromCreateGroup(); + await expect(numberOfUsersInList).toEqual(0); + await createGroupFirstUser.clearUserSearchInput(); + }); + + it("Chat User A - Create group chat with a valid participant", async () => { + // Open modal to create group chat and type valid participant and then create group chat + await createGroupFirstUser.typeOnGroupName("Test"); + await createGroupFirstUser.typeOnUsersSearchInput("Ch"); + await createGroupFirstUser.selectUserFromList("ChatUserB"); + await createGroupFirstUser.clickOnCreateGroupChat(); + await chatsSidebarFirstUser.waitForGroupToBeCreated("Test"); + }); + + it("Chat User A - Group Chat is displayed on local user sidebar", async () => { + // Validate group chat is displayed on local user sidebar and then go to group chat + const statusFromGroup = + await chatsSidebarFirstUser.getSidebarGroupStatus("Test"); + await expect(statusFromGroup).toHaveTextContaining( + "No messages sent yet, send one!", + ); + await chatsSidebarFirstUser.goToSidebarGroupChat("Test"); + await chatsTopbarFirstUser.validateTopbarExists(); + + // Validate topbar contents has correct name + const topbarUserName = chatsTopbarFirstUser.topbarUserNameValue; + await expect(topbarUserName).toHaveTextContaining("Test"); + + // Validate topbar contents has correct number of participants + const topbarUserStatus = chatsTopbarFirstUser.topbarUserStatusValue; + await expect(topbarUserStatus).toHaveTextContaining("Members (2)"); + }); + + it("Group Chat - User A sends a message in group chat", async () => { + // Send a message in group chat + await chatsInputFirstUser.typeMessageOnInput("Sup"); + await chatsInputFirstUser.clickOnSendMessage(); + await chatsMessagesFirstUser.waitForMessageSentToExist("Sup"); + await chatsInputFirstUser.typeMessageOnInput("test"); + await chatsInputFirstUser.clearInputBar(); + + // Validate text from message sent to the group + const textMessage = await chatsMessagesFirstUser.getLastMessageSentText(); + await expect(textMessage).toHaveTextContaining("Sup"); + }); + + it("Sidebar - Search string matching username and group and go to first result", async () => { + // Validate search results for a string matching a single user and a single group + await chatsTopbarFirstUser.goToFiles(); + await filesScreenFirstUser.validateFilesScreenIsShown(); + await chatsSidebarFirstUser.typeOnSidebarSearchInput("Ch"); + const searchResultsUsers = + await sidebarSearchFirstUser.getSidebarSearchResultsUsers(); + const searchResultsGroupsNotMatchingName = + await sidebarSearchFirstUser.getSidebarSearchResultsGroupsNotMatchingName(); + const searchResultsParticipantsInGroups = + await sidebarSearchFirstUser.getSidebarSearchResultsParticipantsInGroups(); + await expect(searchResultsUsers).toEqual(["ChatUserB"]); + await expect(searchResultsGroupsNotMatchingName).toEqual(["Test"]); + await expect(searchResultsParticipantsInGroups).toEqual(["ChatUserB"]); + await chatsSidebarFirstUser.clearSidebarSearchInput(); + }); + + it("Sidebar - Search Bar - Search for a string matching a single group chat", async () => { + // Validate search results for a string matching a single group chat + await chatsTopbarFirstUser.goToFiles(); + await filesScreenFirstUser.validateFilesScreenIsShown(); + await chatsSidebarFirstUser.typeOnSidebarSearchInput("Te"); + const searchResults = + await sidebarSearchFirstUser.getSidebarSearchResultsGroupsMatchingName(); + await expect(searchResults).toEqual(["Test"]); + await chatsSidebarFirstUser.clearSidebarSearchInput(); + }); + + it("Sidebar - Search Bar - Not matching results and then go to the group", async () => { + // Validate search results for a string not matching any group chat or user + await chatsSidebarFirstUser.typeOnSidebarSearchInput("z"); + await chatsSidebarFirstUser.clearSidebarSearchInput(); + await chatsSidebarFirstUser.goToSidebarGroupChat("Test"); + }); +} diff --git a/tests/specs/reusable-accounts/ChatUserA/10-group-chat-edit-userA.spec.ts b/tests/specs/reusable-accounts/ChatUserA/10-group-chat-edit-userA.spec.ts new file mode 100644 index 0000000000..17283b8549 --- /dev/null +++ b/tests/specs/reusable-accounts/ChatUserA/10-group-chat-edit-userA.spec.ts @@ -0,0 +1,140 @@ +import "module-alias/register"; +import EditGroup from "@screenobjects/chats/EditGroup"; +import ChatsSidebar from "@screenobjects/chats/ChatsSidebar"; +import Topbar from "@screenobjects/chats/Topbar"; +import { USER_A_INSTANCE } from "@helpers/constants"; +let chatsSidebarFirstUser = new ChatsSidebar(USER_A_INSTANCE); +let chatsTopbarFirstUser = new Topbar(USER_A_INSTANCE); +let editGroupFirstUser = new EditGroup(USER_A_INSTANCE); + +export default async function groupChatEditTestsUserA() { + it("Chat User A - Edit Group Chat button tooltip", async () => { + // Hover on edit group chat button and validate tooltip is shown + await chatsTopbarFirstUser.hoverOnEditGroupButton(); + + const tooltipText = await chatsTopbarFirstUser.topbarEditGroupTooltipText; + await expect(tooltipText).toHaveTextContaining("Edit Group"); + }); + + it("Chat User A - Click on Edit Group Chat and close modal", async () => { + // Open modal to edit group chat + await chatsTopbarFirstUser.editGroup(); + await editGroupFirstUser.validateEditGroupIsShown(); + await chatsTopbarFirstUser.editGroup(); + }); + + it("Edit Group - Group Name Edit - Contents displayed", async () => { + // Open edit group modal. Validate contents displayed + await chatsTopbarFirstUser.editGroup(); + await editGroupFirstUser.validateEditGroupIsShown(); + + await editGroupFirstUser.groupNameInput.waitForExist(); + await editGroupFirstUser.userInput.waitForExist(); + }); + + it("Edit Group - Attempt to change Group Name for a name containing non-alphanumeric characters", async () => { + // Type on group name input an invalid name and validate error message + await editGroupFirstUser.typeOnGroupNameInput("@"); + await editGroupFirstUser.groupNameInputError.waitForExist(); + + const inputErrorText = await editGroupFirstUser.groupNameInputErrorText; + await expect(inputErrorText).toHaveTextContaining( + "Not allowed character(s): @", + ); + + await editGroupFirstUser.clearGroupNameInput(); + }); + + // Skipping test due to input issue changing the cursor to a different input field + xit("Edit Group - Attempt to change Group Name for a name with more than 64 characters", async () => { + // Type on group name input a name with more than 64 characters and validate error message + await editGroupFirstUser.clickOnGroupNameInput(); + await editGroupFirstUser.typeOnGroupNameInput( + "12345678901234567890123456789012345678901234567890123456789012345678", + ); + + // Validate error message + await editGroupFirstUser.groupNameInputError.waitForExist(); + const inputErrorText = await editGroupFirstUser.groupNameInputErrorText; + await expect(inputErrorText).toHaveTextContaining( + "Maximum of 64 characters exceeded.", + ); + await editGroupFirstUser.clearGroupNameInput(); + }); + + it("Edit Group - Change Group Name for a valid name", async () => { + // Type on group name input a valid name and validate group name is changed correctly + await editGroupFirstUser.typeOnGroupNameInput("X"); + await chatsTopbarFirstUser.editGroup(); + await chatsSidebarFirstUser.waitForGroupToBeCreated("X"); + + // Validate group name was changed correctly on local side + const topbarFirstUserName = await chatsTopbarFirstUser.topbarUserNameValue; + await expect(topbarFirstUserName).toHaveTextContaining("X"); + await chatsSidebarFirstUser.waitForGroupToBeCreated("X"); + }); + + it("Edit Group - Contents displayed in add list are correct", async () => { + // Open edit group modal. Validate contents displayed in add list are correct + await chatsTopbarFirstUser.editGroup(); + await editGroupFirstUser.validateEditGroupIsShown(); + await editGroupFirstUser.clickOnAddMembers(); + await editGroupFirstUser.validateNothingHereIsDisplayed(); + }); + + it("Edit Group - Contents displayed in remove list are correct", async () => { + // Validate contents displayed in remove list are correct + await editGroupFirstUser.clickOnCurrentMembers(); + const currentList = await editGroupFirstUser.getParticipantsList(); + const expectedList = ["ChatUserB"]; + await expect(currentList).toEqual(expectedList); + }); + + it("Edit Group - Look for non existing user in Remove Users List", async () => { + // Type on search user input a non existing user and validate nothing here is displayed + await editGroupFirstUser.typeOnSearchUserInput("z"); + await editGroupFirstUser.validateNothingHereIsDisplayed(); + await editGroupFirstUser.clearSearchUserInput(); + }); + + it("Edit Group - Remove someone from the group", async () => { + // Type on search user input a valid user and then remove it from the group + await editGroupFirstUser.typeOnSearchUserInput("ChatUserB"); + await editGroupFirstUser.clickOnFirstRemoveButton(); + await editGroupFirstUser.validateNothingHereIsDisplayed(); + await chatsTopbarFirstUser.editGroup(); + await chatsTopbarFirstUser.validateTopbarExists(); + + const topbarUserStatus = chatsTopbarFirstUser.topbarUserStatusValue; + await expect(topbarUserStatus).toHaveTextContaining("Members (1)"); + }); + + it("Edit Group - Add Users List - Chat User B appears now in list", async () => { + // Open edit group modal. Validate contents displayed in add list are correct + await chatsTopbarFirstUser.editGroup(); + await editGroupFirstUser.validateEditGroupIsShown(); + await editGroupFirstUser.clickOnAddMembers(); + const currentList = await editGroupFirstUser.getParticipantsList(); + await expect(currentList).toEqual(["ChatUserB"]); + }); + + it("Edit Group - Look for non existing user in Add Users List", async () => { + // Type on search user input a non existing user and validate nothing here is displayed + await editGroupFirstUser.typeOnSearchUserInput("z"); + await editGroupFirstUser.validateNothingHereIsDisplayed(); + await editGroupFirstUser.clearSearchUserInput(); + }); + + it("Edit Group - Add someone to the group - Add Chat User B again", async () => { + // Type on search user input a valid user and then add it to the group + await editGroupFirstUser.typeOnSearchUserInput("ChatUserB"); + await editGroupFirstUser.clickOnFirstAddButton(); + await editGroupFirstUser.validateNothingHereIsDisplayed(); + await chatsTopbarFirstUser.editGroup(); + await chatsTopbarFirstUser.validateTopbarExists(); + + // Validate topbar contents has correct number of participants + const topbarUserStatus = await chatsTopbarFirstUser.topbarUserStatusValue; + await expect(topbarUserStatus).toHaveTextContaining("Members (2)"); + }); +} diff --git a/tests/specs/reusable-accounts/ChatUserA/11-group-chats-sidebar-userA.spec.ts b/tests/specs/reusable-accounts/ChatUserA/11-group-chats-sidebar-userA.spec.ts new file mode 100644 index 0000000000..178bbee48c --- /dev/null +++ b/tests/specs/reusable-accounts/ChatUserA/11-group-chats-sidebar-userA.spec.ts @@ -0,0 +1,119 @@ +import "module-alias/register"; +import ChatsSidebar from "@screenobjects/chats/ChatsSidebar"; +import ContextMenuSidebar from "@screenobjects/chats/ContextMenuSidebar"; +import EditGroup from "@screenobjects/chats/EditGroup"; +import FavoritesSidebar from "@screenobjects/chats/FavoritesSidebar"; +import FriendsScreen from "@screenobjects/friends/FriendsScreen"; +import Topbar from "@screenobjects/chats/Topbar"; +import { USER_A_INSTANCE } from "@helpers/constants"; +let chatsSidebarFirstUser = new ChatsSidebar(USER_A_INSTANCE); +let chatsTopbarFirstUser = new Topbar(USER_A_INSTANCE); +let contextMenuSidebarFirstUser = new ContextMenuSidebar(USER_A_INSTANCE); +let editGroupFirstUser = new EditGroup(USER_A_INSTANCE); +let favoritesSidebarFirstUser = new FavoritesSidebar(USER_A_INSTANCE); +let friendsScreenFirstUser = new FriendsScreen(USER_A_INSTANCE); + +export default async function groupChatSidebarTestsUserA() { + it("Group Chat - Add group to favorites", async () => { + // Leave Participants List screen + await chatsTopbarFirstUser.clickOnTopbar(); + + // Click on Favorites button for Group Chat + await chatsTopbarFirstUser.addToFavorites(); + await favoritesSidebarFirstUser.validateFavoritesAreShown(); + + // Favorites Sidebar should be displayed and showing the name of the group added to Favorites + // Favorites Sidebar User bubble should be displayed + await favoritesSidebarFirstUser.validateFavoritesUserImage("X"); + }); + + it("Group Chat - Remove group from favorites", async () => { + // Remove user from favorites and ensure that Favorites bar is hidden now + await chatsTopbarFirstUser.removeFromFavorites(); + }); + + it("Group Chats Testing - Go to another chat conversation", async () => { + // Go to another chat conversation + await chatsTopbarFirstUser.goToFriends(); + await friendsScreenFirstUser.validateFriendsScreenIsShown(); + await friendsScreenFirstUser.validateChatWithFriendButtonIsShown(); + await friendsScreenFirstUser.hoverOnChatWithFriendButton("ChatUserB"); + await friendsScreenFirstUser.clickOnChatWithFriend(); + await chatsTopbarFirstUser.validateTopbarExists(); + }); + + it("Group Chat - Sidebar - Any new messages received in group should appear in Sidebar", async () => { + // Validate Sidebar shows Group Name + await chatsSidebarFirstUser.validateUsernameDisplayed("X"); + + // Validate last message content from group is displayed on sidebar + await chatsSidebarFirstUser.validateLastMessageDisplayed("HelloGroup"); + + // Validate number of unread messages from the group is displayed on sidebar + await chatsSidebarFirstUser.validateNumberOfUnreadMessages("1"); + + // Validate time ago is displayed on sidebar for group chat + await chatsSidebarFirstUser.validateLastMessageTimeAgo(); + }); + + it("Group Chat - Sidebar - Context Menu - Clear Unreads", async () => { + // Open context menu on group chat and select Clear Unreads + await chatsSidebarFirstUser.openContextMenuOnGroupChat("X"); + await contextMenuSidebarFirstUser.selectChatsClearUnreads(); + await chatsSidebarFirstUser.validateNoUnreadMessages(); + }); + + it("Group Chat - Sidebar - Context Menu - Hide chat", async () => { + // Open context menu on group chat and select Hide Chat + await chatsSidebarFirstUser.openContextMenuOnGroupChat("X"); + await contextMenuSidebarFirstUser.selectChatsHideChat(); + await chatsSidebarFirstUser.validateSidebarChatIsNotDisplayed("X"); + }); + + it("Group Chat - Validate remote user received the message", async () => { + // Validate that message was received + await chatsSidebarFirstUser.waitForGroupToBeCreated("X"); + await chatsSidebarFirstUser.goToSidebarGroupChat("X"); + await chatsTopbarFirstUser.validateTopbarExists(); + }); + + it("Group Chat - Sidebar - If a user leaves a group, remote user will see the number of group members decreased", async () => { + // Now, go to the Group Chat and validate that User B is not part of it anymore + await chatsTopbarFirstUser.validateTopbarExists(); + + // Validate topbar contents has correct name + const topbarUserName = await chatsTopbarFirstUser.topbarUserNameValue; + await expect(topbarUserName).toHaveTextContaining("X"); + + // Validate topbar contents has correct number of participants + const topbarUserStatus = await chatsTopbarFirstUser.topbarUserStatusValue; + await expect(topbarUserStatus).toHaveTextContaining("Members (1)"); + }); + + it("Group Chat - Add Chat User B again to the group", async () => { + // Go to Edit Group and then add again Chat User B to the group + await chatsTopbarFirstUser.editGroup(); + await editGroupFirstUser.validateEditGroupIsShown(); + await editGroupFirstUser.clickOnAddMembers(); + await editGroupFirstUser.typeOnSearchUserInput("ChatUserB"); + await editGroupFirstUser.clickOnFirstAddButton(); + await editGroupFirstUser.validateNothingHereIsDisplayed(); + + // Validate topbar contents has correct number of participants + await chatsTopbarFirstUser.editGroup(); + await chatsTopbarFirstUser.validateTopbarExists(); + + // Validate topbar contents has correct number of participants + const topbarUserStatus = await chatsTopbarFirstUser.topbarUserStatusValue; + await expect(topbarUserStatus).toHaveTextContaining("Members (2)"); + }); + + it("Group Chat - Sidebar - Delete group", async () => { + // Delete the group + await chatsSidebarFirstUser.openContextMenuOnGroupChat("X"); + await contextMenuSidebarFirstUser.selectChatsDeleteGroup(); + + // Ensure that group was removed on local side + await chatsSidebarFirstUser.validateSidebarChatIsNotDisplayed("X"); + }); +} diff --git a/tests/specs/reusable-accounts/ChatUserB/01-main-chats-userB.spec.ts b/tests/specs/reusable-accounts/ChatUserB/01-main-chats-userB.spec.ts new file mode 100644 index 0000000000..e4b205854a --- /dev/null +++ b/tests/specs/reusable-accounts/ChatUserB/01-main-chats-userB.spec.ts @@ -0,0 +1,83 @@ +import "module-alias/register"; +import { getUserKey, loginWithTestUser } from "@helpers/commands"; +import { USER_A_INSTANCE } from "@helpers/constants"; +import FriendsScreen from "@screenobjects/friends/FriendsScreen"; +import Messages from "@screenobjects/chats/Messages"; +import MessageGroup from "@screenobjects/chats/MessageGroup"; +import Topbar from "@screenobjects/chats/Topbar"; +import WelcomeScreen from "@screenobjects/welcome-screen/WelcomeScreen"; +let chatsMessagesFirstUser = new Messages(USER_A_INSTANCE); +let chatsMessageGroupsFirstUser = new MessageGroup(USER_A_INSTANCE); +let chatsTopbarFirstUser = new Topbar(USER_A_INSTANCE); +let friendsScreenFirstUser = new FriendsScreen(USER_A_INSTANCE); +let welcomeScreenFirstUser = new WelcomeScreen(USER_A_INSTANCE); + +export default async function mainChatsTestsUserB() { + it("Chat User B - Login with account previously created", async () => { + // Login with account previously created + await loginWithTestUser(); + await welcomeScreenFirstUser.validateWelcomeScreenIsShown(); + await welcomeScreenFirstUser.goToFriends(); + await friendsScreenFirstUser.validateFriendsScreenIsShown(); + }); + + it("Chat User B - Send friend request to User A", async () => { + // Obtain did key from Chat User B + const friendDidKey = await getUserKey("ChatUserA", USER_A_INSTANCE); + await friendsScreenFirstUser.enterFriendDidKey(friendDidKey); + const addSomeoneInput = await friendsScreenFirstUser.addSomeoneInput; + await expect(addSomeoneInput).toHaveTextContaining(friendDidKey); + await friendsScreenFirstUser.clickOnAddSomeoneButton(); + + // Wait for toast notification to be closed + await friendsScreenFirstUser.waitUntilNotificationIsClosed(); + + // Validate friend request appears on pending list + await friendsScreenFirstUser.hoverOnPendingListButton(); + await friendsScreenFirstUser.goToPendingFriendsList(); + }); + + it("Chat User B - Validate friend request was accepted", async () => { + // With User A - Go to pending requests list, wait for receiving the friend request and accept it + await friendsScreenFirstUser.goToAllFriendsList(); + await friendsScreenFirstUser.waitUntilUserAcceptedFriendRequest(); + + // Validate friend is now on all friends list + await friendsScreenFirstUser.validateAllFriendsListIsShown(); + await friendsScreenFirstUser.validateAllFriendsListIsNotEmpty(); + }); + + it("Chat User B - Wait until the other user is connected", async () => { + // Go to the current list of All friends and then open a Chat conversation with ChatUserA + await friendsScreenFirstUser.validateChatWithFriendButtonExists(); + await friendsScreenFirstUser.chatWithFriendButton.click(); + await chatsTopbarFirstUser.validateTopbarExists(); + }); + + it("Chat User B - Assert message received from Chat User A", async () => { + // Validate message received from Chat User A + await chatsMessagesFirstUser.waitForReceivingMessage("Testing...๐Ÿ˜€"); + + //Any message you sent yourself should appear within a colored message bubble + const textFromMessage = + await chatsMessagesFirstUser.getLastMessageReceivedText(); + await expect(textFromMessage).toHaveTextContaining("Testing...๐Ÿ˜€"); + }); + + it("Chat User B - Validate Chat Message Group from remote user displays username picture", async () => { + //Your user image should be displayed next to the message + const userImage = + await chatsMessageGroupsFirstUser.getLastGroupWrapReceivedImage(); + await userImage.waitForExist(); + }); + + it("Chat User B - Validate Chat Message received displays timestamp and user who sent it", async () => { + //Timestamp should be displayed when you send a message + const timeAgo = + await chatsMessageGroupsFirstUser.getLastMessageReceivedTimeAgo(); + await expect(timeAgo).toHaveTextContaining( + /- (?:\d{1,2}\s+(?:second|minute)s?\s+ago|now)$/, + ); + await expect(timeAgo).toHaveTextContaining("ChatUserA"); + }); +} diff --git a/tests/specs/reusable-accounts/ChatUserB/02-chat-replies-userB.spec.ts b/tests/specs/reusable-accounts/ChatUserB/02-chat-replies-userB.spec.ts new file mode 100644 index 0000000000..82f5cca059 --- /dev/null +++ b/tests/specs/reusable-accounts/ChatUserB/02-chat-replies-userB.spec.ts @@ -0,0 +1,68 @@ +import "module-alias/register"; +import { USER_A_INSTANCE } from "@helpers/constants"; +import ContextMenu from "@screenobjects/chats/ContextMenu"; +import InputBar from "@screenobjects/chats/InputBar"; +import MessageGroup from "@screenobjects/chats/MessageGroup"; +import Messages from "@screenobjects/chats/Messages"; +import ReplyPrompt from "@screenobjects/chats/ReplyPrompt"; +let chatsContextMenuFirstUser = new ContextMenu(USER_A_INSTANCE); +let chatsInputFirstUser = new InputBar(USER_A_INSTANCE); +let chatsMessageGroupsFirstUser = new MessageGroup(USER_A_INSTANCE); +let chatsMessagesFirstUser = new Messages(USER_A_INSTANCE); +let chatsReplyPromptFirstUser = new ReplyPrompt(USER_A_INSTANCE); + +export default async function repliesTestsUserB() { + it("Chat User B - Reply popup - Validate contents and close it", async () => { + // Open Context Menu on Last Message Received and select Reply + await chatsMessagesFirstUser.openContextMenuOnLastReceived(); + await chatsContextMenuFirstUser.validateContextMenuIsOpen(); + await chatsContextMenuFirstUser.selectContextOptionReply(); + + // Validate contents of Reply Pop Up and close it + await chatsReplyPromptFirstUser.validateReplyPromptElementsShown( + "Testing...๐Ÿ˜€", + ); + await chatsReplyPromptFirstUser.closeReplyModal(); + await chatsReplyPromptFirstUser.waitForReplyModalToNotExist(); + }); + + it("Chat User B - Reply to a message", async () => { + // Open Context Menu on Last Message Received and select Reply + await chatsMessagesFirstUser.openContextMenuOnLastReceived(); + await chatsContextMenuFirstUser.validateContextMenuIsOpen(); + await chatsContextMenuFirstUser.selectContextOptionReply(); + + // Type a reply and sent it + await chatsReplyPromptFirstUser.replyPopUp.waitForExist(); + await chatsInputFirstUser.typeMessageOnInput("Reply"); + await chatsInputFirstUser.clickOnSendMessage(); + await chatsReplyPromptFirstUser.waitForReplyModalToNotExist(); + }); + + it("Chat User B - Validate reply message group reply and message replied", async () => { + // Validate message replied appears smaller above your reply + const replySent = await chatsMessagesFirstUser.getLastReply(); + const replySentText = await chatsMessagesFirstUser.getLastReplyText(); + await replySent.waitForExist(); + await expect(replySentText).toHaveTextContaining("Testing...๐Ÿ˜€"); + + // Validate reply message sent appears as last message + const message = await chatsMessagesFirstUser.getLastMessageSentText(); + await expect(message).toHaveTextContaining("Reply"); + }); + + it("Chat User B - Validate reply message group contains timestamp and user image", async () => { + //Timestamp from last message sent should be displayed + const timeAgo = + await chatsMessageGroupsFirstUser.getLastMessageSentTimeAgo(); + await expect(timeAgo).toHaveTextContaining( + /- (?:\d{1,2}\s+(?:second|minute)s?\s+ago|now)$/, + ); + await expect(timeAgo).toHaveTextContaining("ChatUserB"); + + //Your user image should be displayed next to the message + const userImage = + await chatsMessageGroupsFirstUser.getLastGroupWrapSentImage(); + await userImage.waitForExist(); + }); +} diff --git a/tests/specs/reusable-accounts/ChatUserB/03-message-context-menu-userB.spec.ts b/tests/specs/reusable-accounts/ChatUserB/03-message-context-menu-userB.spec.ts new file mode 100644 index 0000000000..dcd369ac2f --- /dev/null +++ b/tests/specs/reusable-accounts/ChatUserB/03-message-context-menu-userB.spec.ts @@ -0,0 +1,74 @@ +import "module-alias/register"; +import { USER_A_INSTANCE } from "@helpers/constants"; +import ContextMenu from "@screenobjects/chats/ContextMenu"; +import InputBar from "@screenobjects/chats/InputBar"; +import MessageGroup from "@screenobjects/chats/MessageGroup"; +import Messages from "@screenobjects/chats/Messages"; +let chatsContextMenuFirstUser = new ContextMenu(USER_A_INSTANCE); +let chatsInputFirstUser = new InputBar(USER_A_INSTANCE); +let chatsMessagesFirstUser = new Messages(USER_A_INSTANCE); +let chatsMessageGroupsFirstUser = new MessageGroup(USER_A_INSTANCE); + +export default async function messageContextMenuTestsUserB() { + it("Chat User B - Receive two messages from Chat User B", async () => { + // Assert messages received from Chat User B + await chatsMessagesFirstUser.waitForReceivingMessage("Two..."); + await chatsMessagesFirstUser.waitForReceivingMessage("Three..."); + }); + + it("Chat User B - Validate Message was deleted and is no longer visible in remote chat", async () => { + // With User B - Validate that last message is "Two..." + await chatsMessagesFirstUser.waitForReceivingMessage("Two..."); + + // With User B - Ensure that message "three.." was deleted + await chatsMessagesFirstUser.waitForMessageToBeDeleted("Three..."); + }); + + it("Chat User B - Receive reaction in sent message", async () => { + await chatsInputFirstUser.clickOnInputBar(); + await chatsInputFirstUser.typeMessageOnInput("Hello"); + await chatsInputFirstUser.clearInputBar(); + + // Validate reactions received on sent message + await chatsMessageGroupsFirstUser.waitUntilEmojiReactionRemoteExists("๐Ÿ‘Ž"); + const reaction = + await chatsMessageGroupsFirstUser.getLastMessageSentRemoteReactions(); + await expect(reaction.includes("๐Ÿ‘Ž 1")).toEqual(true); + }); + + it("Chat User B - Receive reaction in received message", async () => { + // Validate reactions received on sent message + await chatsMessageGroupsFirstUser.waitUntilEmojiReactionRemoteExists("๐Ÿ––"); + const reactions = + await chatsMessageGroupsFirstUser.getLastMessageReceivedRemoteReactions(); + await expect(reactions.includes("๐Ÿ–– 1")).toEqual(true); + await expect(reactions.includes("๐Ÿ˜‚ 1")).toEqual(true); + }); + + it("Chat User B - Both users can react with the same emoji to a message", async () => { + // React with ๐Ÿ‘Ž emoji + await chatsMessagesFirstUser.openContextMenuOnLastSent(); + await chatsContextMenuFirstUser.validateContextMenuIsOpen(); + await chatsContextMenuFirstUser.clickOnThirdReaction(); + + // Validate reaction is displayed correctly + await chatsMessageGroupsFirstUser.waitUntilEmojiReactionSelfExists("๐Ÿ‘Ž"); + const reaction = + await chatsMessageGroupsFirstUser.getLastMessageSentSelfReactions(); + await expect(reaction.includes("๐Ÿ‘Ž 2")).toEqual(true); + }); + + it("Chat User B - Users can add a new reaction to a message already containing reactions", async () => { + // React with ๐Ÿ‘ emoji + await chatsMessagesFirstUser.openContextMenuOnLastSent(); + await chatsContextMenuFirstUser.validateContextMenuIsOpen(); + await chatsContextMenuFirstUser.clickOnFourthReaction(); + + // Validate reaction is displayed correctly + await chatsMessageGroupsFirstUser.waitUntilEmojiReactionSelfExists("๐Ÿ‘"); + const reaction = + await chatsMessageGroupsFirstUser.getLastMessageSentSelfReactions(); + await expect(reaction.includes("๐Ÿ‘Ž 2")).toEqual(true); + await expect(reaction.includes("๐Ÿ‘ 1")).toEqual(true); + }); +} diff --git a/tests/specs/reusable-accounts/ChatUserB/04-message-input-userB.spec.ts b/tests/specs/reusable-accounts/ChatUserB/04-message-input-userB.spec.ts new file mode 100644 index 0000000000..7f5510208a --- /dev/null +++ b/tests/specs/reusable-accounts/ChatUserB/04-message-input-userB.spec.ts @@ -0,0 +1,68 @@ +import "module-alias/register"; +import { USER_A_INSTANCE } from "@helpers/constants"; +import ChatsLayout from "@screenobjects/chats/ChatsLayout"; +import Messages from "@screenobjects/chats/Messages"; +let chatsMessagesFirstUser = new Messages(USER_A_INSTANCE); +let chatsLayoutFirstUser = new ChatsLayout(USER_A_INSTANCE); + +export default async function messageInputTestsUserB() { + it("Chat Input Text - Validate messages with bold markdowns were received in expected format", async () => { + // With Chat User B, validate message with with ** markdown was received in bolds + await chatsMessagesFirstUser.waitForReceivingMessage("Bolds1"); + + // With Chat User B, validate message with with __ markdown was received in bolds + await chatsMessagesFirstUser.waitForReceivingMessage("Bolds2"); + }); + + // Skipping test that is failing often on CI - Requires investigation to improve execution + xit("Chat Input Text - Validate message with code markdown is received in expected format", async () => { + // With Chat User B, validate code message was received and is displayed correctly + await chatsMessagesFirstUser.waitForReceivingCodeMessage("JavaScript"); + const codeMessageTextReceived = + await chatsMessagesFirstUser.getLastMessageReceivedCodeMessage(); + await expect(codeMessageTextReceived).toEqual("let a = 1;"); + }); + + it("Chat Input Text - Validate messages with links were received correctly", async () => { + // With Chat User B, validate message with URL starting with https:// was received as link + await chatsMessagesFirstUser.waitForReceivingLink("https://www.google.com"); + + // With Chat User B, validate message with URL starting with www. was received as link + await chatsMessagesFirstUser.waitForReceivingLink("www.apple.com"); + + // With Chat User B, validate message with URL starting with http:// was received as link + await chatsMessagesFirstUser.waitForReceivingLink( + "http://www.satellite.im", + ); + }); + + it("Chat User - Chat Messages containing links contents on remote side", async () => { + // Validate link embed contents on chat message + const linkEmbedReceived = + await chatsMessagesFirstUser.getLastMessageReceivedLinkEmbed(); + const linkEmbedReceivedDetailsText = + await chatsMessagesFirstUser.getLastMessageReceivedLinkEmbedDetailsText(); + const linkEmbedReceivedIcon = + await chatsMessagesFirstUser.getLastMessageReceivedLinkEmbedIcon(); + const linkEmbedReceivedIconTitle = + await chatsMessagesFirstUser.getLastMessageReceivedLinkEmbedIconTitle(); + + await linkEmbedReceived.waitForExist(); + await expect(linkEmbedReceivedDetailsText).toHaveTextContaining( + "P2P Chat, Voice & Video Open-source, stored on IPFS. End to end encryption... trackers not included.", + ); + await linkEmbedReceivedIcon.waitForExist(); + await linkEmbedReceivedIconTitle.waitForExist(); + }); + + // Skipping test failing on because the typing indicator is gone before the test can validate it + xit("Validate Typing Indicator is displayed if remote user is typing", async () => { + // Switch to second user and validate that Typing Indicator is displayed + await chatsLayoutFirstUser.typingIndicator.waitForExist({ + timeout: 30000, + }); + await expect( + chatsLayoutFirstUser.typingIndicatorTextValue, + ).toHaveTextContaining("ChatUserA is typing"); + }); +} diff --git a/tests/specs/reusable-accounts/ChatUserB/05-message-attachments-userB.spec.ts b/tests/specs/reusable-accounts/ChatUserB/05-message-attachments-userB.spec.ts new file mode 100644 index 0000000000..693866dc80 --- /dev/null +++ b/tests/specs/reusable-accounts/ChatUserB/05-message-attachments-userB.spec.ts @@ -0,0 +1,176 @@ +import "module-alias/register"; +import { USER_A_INSTANCE } from "@helpers/constants"; +import ComposeAttachment from "@screenobjects/chats/ComposeAttachment"; +import FilesScreen from "@screenobjects/files/FilesScreen"; +import InputBar from "@screenobjects/chats/InputBar"; +import Messages from "@screenobjects/chats/Messages"; +import SendFiles from "@screenobjects/chats/SendFiles"; +let chatsAttachmentFirstUser = new ComposeAttachment(USER_A_INSTANCE); +let chatsInputFirstUser = new InputBar(USER_A_INSTANCE); +let chatsMessagesFirstUser = new Messages(USER_A_INSTANCE); +let filesScreenFirstUser = new FilesScreen(USER_A_INSTANCE); +let sendFilesFirstUser = new SendFiles(USER_A_INSTANCE); + +export default async function messageAttachmentsTestsUserB() { + it("Send files from Browse Files - No files are displayed on modal and user can close modal", async () => { + // Go to upload button and then select Browser Files (from Uplink storage) + await chatsInputFirstUser.openUploadFilesFromStorage(); + await sendFilesFirstUser.validateSendFilesModalIsShown(); + await sendFilesFirstUser.validateNoFilesAvailableIsShown(); + + // Click outside of the modal to close it, in this case on the send message button + await sendFilesFirstUser.clickOnCloseModal(); + }); + + it("Send files from Browse Files - Upload an image on Files to run tests", async () => { + // Go to Files Screen andand upload an image file before starting + await chatsInputFirstUser.goToFiles(); + await filesScreenFirstUser.validateFilesScreenIsShown(); + await filesScreenFirstUser.uploadFile("./tests/fixtures/banner.jpg"); + await filesScreenFirstUser.validateFileOrFolderExist("banner.jpg"); + }); + + it("Send files from Browse Files - Upload a txt file in a different folder", async () => { + // Create a new folder and enter on it + await filesScreenFirstUser.createFolder("testfolder01"); + await filesScreenFirstUser.validateFileOrFolderExist("testfolder01"); + await filesScreenFirstUser.clickOnFileOrFolder("testfolder01"); + + // Upload one time the testfile.txt file + await filesScreenFirstUser.uploadFile("./tests/fixtures/testfile.txt"); + await filesScreenFirstUser.validateFileOrFolderExist("testfile.txt"); + + // Return to chat screen + await filesScreenFirstUser.goToMainScreen(); + }); + + it("Send files from Browse Files - Thumbnails are displayed on modal", async () => { + // Open modal to send files from storage + await chatsInputFirstUser.openUploadFilesFromStorage(); + await sendFilesFirstUser.validateSendFilesModalIsShown(); + + // Go to Home Folder and validate thumbnail for file is shown + await sendFilesFirstUser.clickOnHomeFolderCrumb(); + await filesScreenFirstUser.validateFileOrFolderExist("banner.jpg"); + await sendFilesFirstUser.validateThumbnailIsShown("banner.jpg"); + }); + + // Skipping test because it takes too much time for execution + xit("Send files from Browse Files - User can navigate through folders and to home", async () => { + // Navigate to testfolder01 and ensure thumbnail from testfile.txt is shown + await sendFilesFirstUser.clickOnFileOrFolder("testfolder01"); + await filesScreenFirstUser.validateFileOrFolderExist("testfile.txt"); + await sendFilesFirstUser.validateThumbnailIsShown("testfile.txt"); + + // Navigate to home folder and ensure thumbnail from banner.jpg is shown + await sendFilesFirstUser.clickOnHomeFolderCrumb(); + await filesScreenFirstUser.validateFileOrFolderExist("banner.jpg"); + await sendFilesFirstUser.validateThumbnailIsShown("banner.jpg"); + }); + + it("Send files from Browse Files - Go to files button redirects to Files", async () => { + // Click on Go To Files button and validate User is redirected to Files Screen + await sendFilesFirstUser.clickOnGoToFiles(); + await filesScreenFirstUser.validateFilesScreenIsShown(); + + // Return to Chat Screen and open again the Send Files from Storage modal + await filesScreenFirstUser.goToMainScreen(); + await chatsInputFirstUser.openUploadFilesFromStorage(); + await sendFilesFirstUser.validateSendFilesModalIsShown(); + }); + + it("Send files from Browse Files - Send files button shows 0/8 files if no files are selected", async () => { + // When no files are selected, Send Files button should display 0/8 File(s) + await sendFilesFirstUser.validateSendFilesButtonText("Send 0/8 File(s)"); + }); + + it("Send files from Browse Files - User cannot click on send files if no files are selected", async () => { + // Click on Send files button without any files selected + await sendFilesFirstUser.clickOnSendFilesButton(); + + // Ensure that Send Files Modal is still displayed + await sendFilesFirstUser.validateSendFilesModalIsShown(); + }); + + it("Send files from Browse Files - Send files counter is updated", async () => { + // Select one file from root folder and ensure Send Files button displays 1/8 File(s) + await sendFilesFirstUser.clickOnFileOrFolder("banner.jpg"); + await sendFilesFirstUser.validateSendFilesButtonText("Send 1/8 File(s)"); + }); + + it("Send files from Browse Files - Files selected will be displayed on Compose Attachment", async () => { + // Send the only image file previously selected + await sendFilesFirstUser.clickOnSendFilesButton(); + + // Validate file is displayed on Compose Attachment + // Validate compose attachments displays the files to be uploaded before sending the message + await chatsAttachmentFirstUser.validateComposeAttachmentsIsShown(); + + // Obtain the list of attachments added to Compose Attachment + await chatsAttachmentFirstUser.validateAttachmentWithFileNameIsAdded( + "banner.jpg", + true, + ); + }); + + it("Send files from Browse Files - Message sent with attachments is shown on local side", async () => { + // Type a text message and send it + await chatsInputFirstUser.typeMessageOnInput("Attached"); + await chatsInputFirstUser.pressEnterKeyOnInputBar(); + + // Ensure that message sent with attached file is displayed on local side + await chatsMessagesFirstUser.waitForMessageSentToExist("Attached"); + + await chatsMessagesFirstUser.chatMessageFileEmbedLocal.waitForExist(); + + // Validate text from message containing attachment + const textMessage = await chatsMessagesFirstUser.getLastMessageSentText(); + await expect(textMessage).toHaveTextContaining("Attached"); + }); + + it("Send File from Add Files - Select a file and send message with attachment", async () => { + // Click on upload button and attach a file to compose attachment + await chatsInputFirstUser.uploadFileFromLocalDisk( + "./tests/fixtures/testfile.txt", + ); + + // Validate contents on Compose Attachments are displayed + await chatsAttachmentFirstUser.composeAttachmentsFileEmbed.waitForExist(); + + // Type a text message and send it + await chatsInputFirstUser.typeMessageOnInput("Attached2"); + await chatsInputFirstUser.pressEnterKeyOnInputBar(); + await chatsMessagesFirstUser.waitForMessageSentToExist("Attached2"); + }); + + it("Send Files on Chats - Message Sent With Attachment - Attachment Contents", async () => { + await chatsMessagesFirstUser.chatMessageFileEmbedLocal.waitForExist(); + + // Validate text from message containing attachment + const textMessage = await chatsMessagesFirstUser.getLastMessageSentText(); + await expect(textMessage).toHaveTextContaining("Attached2"); + + // Validate file metadata is displayed correctly on last chat message sent + const fileMeta = await chatsMessagesFirstUser.getLastMessageSentFileMeta(); + await expect(fileMeta).toHaveTextContaining("47 B"); + + // Validate filename is displayed correctly on last chat message sent + const fileName = await chatsMessagesFirstUser.getLastMessageSentFileName(); + await expect(fileName).toHaveTextContaining("testfile.txt"); + + // Validate file icon is displayed correctly on last chat message sent + const fileIcon = await chatsMessagesFirstUser.getLastMessageSentFileIcon(); + await fileIcon.waitForExist(); + + // Validate file download button is displayed correctly on last chat message sent + await chatsMessagesFirstUser.hoverOnLastFileSent(); + const fileDownloadButton = + await chatsMessagesFirstUser.getLastMessageSentDownloadButton(); + await fileDownloadButton.waitForExist(); + }); + + it("Chat Messages with Files - Local user can download file sent", async () => { + // Download latest image file received + await chatsMessagesFirstUser.downloadLastSentFile(".txt"); + }); +} diff --git a/tests/specs/reusable-accounts/ChatUserB/06-quick-profile-userB.spec.ts b/tests/specs/reusable-accounts/ChatUserB/06-quick-profile-userB.spec.ts new file mode 100644 index 0000000000..0c595aef05 --- /dev/null +++ b/tests/specs/reusable-accounts/ChatUserB/06-quick-profile-userB.spec.ts @@ -0,0 +1,68 @@ +import "module-alias/register"; +import { USER_A_INSTANCE } from "@helpers/constants"; +import FriendsScreen from "@screenobjects/friends/FriendsScreen"; +import InputBar from "@screenobjects/chats/InputBar"; +import Messages from "@screenobjects/chats/Messages"; +import Topbar from "@screenobjects/chats/Topbar"; +import WelcomeScreen from "@screenobjects/welcome-screen/WelcomeScreen"; + +let chatsInputFirstUser = new InputBar(USER_A_INSTANCE); +let chatsMessagesFirstUser = new Messages(USER_A_INSTANCE); +let chatsTopbarFirstUser = new Topbar(USER_A_INSTANCE); +let friendsScreenFirstUser = new FriendsScreen(USER_A_INSTANCE); +let welcomeScreenFirstUser = new WelcomeScreen(USER_A_INSTANCE); + +export default async function quickProfileTestsUserB() { + it("Chat User B - Send message to User A", async () => { + await chatsInputFirstUser.clickOnInputBar(); + await chatsInputFirstUser.typeMessageOnInput("click..."); + await chatsInputFirstUser.clickOnSendMessage(); + await chatsMessagesFirstUser.waitForMessageSentToExist("click..."); + }); + + it("Chat User B - Validate friendship was removed", async () => { + // With User B - Go to Friends and wait for User A to remove friendship with User B + await welcomeScreenFirstUser.goToFriends(); + await friendsScreenFirstUser.validateFriendsScreenIsShown(); + }); + + it("Chat User B - Validate that User A is now a friend", async () => { + // With User B - Go to pending requests list, wait for receiving the friend request and accept it + await friendsScreenFirstUser.hoverOnFriendsButton(); + await friendsScreenFirstUser.goToFriends(); + await friendsScreenFirstUser.validateFriendsScreenIsShown(); + await friendsScreenFirstUser.hoverOnPendingListButton(); + await friendsScreenFirstUser.goToPendingFriendsList(); + await friendsScreenFirstUser.validateIncomingListIsShown(); + await friendsScreenFirstUser.acceptIncomingRequest("ChatUserA"); + + // Return to Friends List + await friendsScreenFirstUser.goToAllFriendsList(); + await friendsScreenFirstUser.validateAllFriendsListIsShown(); + + // Validate friend is now on all friends list + await friendsScreenFirstUser.validateAllFriendsListIsNotEmpty(); + }); + + it("Chat User B - Send message to User B", async () => { + // Go to the current list of All friends and then open a Chat conversation with ChatUserA + await friendsScreenFirstUser.validateChatWithFriendButtonIsShown(); + await friendsScreenFirstUser.hoverOnChatWithFriendButton("ChatUserA"); + await friendsScreenFirstUser.clickOnChatWithFriend(); + + // Validate that Topbar is displayed + await chatsTopbarFirstUser.validateTopbarExists(); + + // Send message to Chat User B + await chatsInputFirstUser.typeMessageOnInput("Accepted..."); + await chatsInputFirstUser.clickOnSendMessage(); + await chatsMessagesFirstUser.waitForMessageSentToExist("Accepted..."); + }); + + it("Chat User B - Validate that User A blocked User B", async () => { + // With User B - Go to Friends and wait for User A to remove friendship with User B + await chatsInputFirstUser.goToFriends(); + await friendsScreenFirstUser.validateFriendsScreenIsShown(); + await friendsScreenFirstUser.waitUntilFriendIsRemoved("ChatUserA"); + }); +} diff --git a/tests/specs/reusable-accounts/ChatUserB/07-sidebar-chats-userB.spec.ts b/tests/specs/reusable-accounts/ChatUserB/07-sidebar-chats-userB.spec.ts new file mode 100644 index 0000000000..423631c6d0 --- /dev/null +++ b/tests/specs/reusable-accounts/ChatUserB/07-sidebar-chats-userB.spec.ts @@ -0,0 +1,73 @@ +import "module-alias/register"; +import { USER_A_INSTANCE } from "@helpers/constants"; +import ChatsLayout from "@screenobjects/chats/ChatsLayout"; +import InputBar from "@screenobjects/chats/InputBar"; +import Messages from "@screenobjects/chats/Messages"; +import FriendsScreen from "@screenobjects/friends/FriendsScreen"; +import WelcomeScreen from "@screenobjects/welcome-screen/WelcomeScreen"; +let chatsInputFirstUser = new InputBar(USER_A_INSTANCE); +let chatsLayoutFirstUser = new ChatsLayout(USER_A_INSTANCE); +let chatsMessagesFirstUser = new Messages(USER_A_INSTANCE); +let friendsScreenFirstUser = new FriendsScreen(USER_A_INSTANCE); +let welcomeScreenFirstUser = new WelcomeScreen(USER_A_INSTANCE); + +export default async function sidebarChatsTestsUserB() { + it("Chat User B - Validate button badge displays the number of incoming requests", async () => { + // Go to pending requests list, wait for receiving the friend request and accept it + await friendsScreenFirstUser.goToFriends(); + await friendsScreenFirstUser.validateFriendsScreenIsShown(); + await friendsScreenFirstUser.hoverOnPendingListButton(); + await friendsScreenFirstUser.goToPendingFriendsList(); + await friendsScreenFirstUser.validateIncomingListIsShown(); + await friendsScreenFirstUser.waitUntilFriendRequestIsReceived(); + + // Validate that button badge displays the number of incoming requests + await friendsScreenFirstUser.validateFriendsButtonBadgeIsShown; + const friendsButtonBadgeText = + await friendsScreenFirstUser.getValueFromFriendsButtonBadge(); + await expect(friendsButtonBadgeText).toEqual("1"); + }); + + it("Chat User B - Accept incoming request", async () => { + // Accept incoming request + await friendsScreenFirstUser.acceptIncomingRequest("ChatUserA"); + await friendsScreenFirstUser.acceptFriendRequestButton.waitForExist({ + reverse: true, + }); + + // Return to Friends List + await friendsScreenFirstUser.goToAllFriendsList(); + await friendsScreenFirstUser.validateAllFriendsListIsShown(); + }); + + it("Chat User B - Send message to User A", async () => { + // Go to the current list of All friends and then open a Chat conversation with ChatUserA + await friendsScreenFirstUser.validateChatWithFriendButtonIsShown(); + await friendsScreenFirstUser.hoverOnChatWithFriendButton("ChatUserA"); + await friendsScreenFirstUser.clickOnChatWithFriend(); + await chatsLayoutFirstUser.validateChatLayoutIsShown(); + + // Send message with markdown to Chat User B + await chatsInputFirstUser.typeMessageOnInput("__hello__"); + await chatsInputFirstUser.clickOnSendMessage(); + await chatsMessagesFirstUser.waitForMessageSentToExist("hello"); + }); + + it("Chat User B - Validate message was received", async () => { + // With User B - Wait until message is received + await chatsMessagesFirstUser.waitForReceivingMessage("Hi..."); + }); + + it("Chat User B - Sidebar - Wait for receiving a a new message", async () => { + // With User B - Wait until message is received + await chatsMessagesFirstUser.waitForReceivingMessage("Hi..."); + const latestMessage = + await chatsMessagesFirstUser.getLastMessageReceivedText(); + await expect(latestMessage).toHaveTextContaining("Hi..."); + }); + + it("Chat User B - Sidebar - If user deletes chat on remote side, it will be removed on local side as well", async () => { + // After user deletes chat conversation on remote side, chat is deleted on local side and Welcome Image displayed again + await welcomeScreenFirstUser.skeletalUser.waitForExist(); + }); +} diff --git a/tests/specs/reusable-accounts/ChatUserB/08-group-chats-userB.spec.ts b/tests/specs/reusable-accounts/ChatUserB/08-group-chats-userB.spec.ts new file mode 100644 index 0000000000..31f5b7be7e --- /dev/null +++ b/tests/specs/reusable-accounts/ChatUserB/08-group-chats-userB.spec.ts @@ -0,0 +1,46 @@ +import "module-alias/register"; +import ChatsSidebar from "@screenobjects/chats/ChatsSidebar"; +import Messages from "@screenobjects/chats/Messages"; +import Topbar from "@screenobjects/chats/Topbar"; +import { USER_A_INSTANCE } from "@helpers/constants"; +let chatsMessagesFirstUser = new Messages(USER_A_INSTANCE); +let chatsSidebarFirstUser = new ChatsSidebar(USER_A_INSTANCE); +let chatsTopbarFirstUser = new Topbar(USER_A_INSTANCE); + +export default async function groupChatTestsUserB() { + it("User B - Group Chat is displayed on remote participant users sidebar", async () => { + // Validate group chat is displayed on remote participant users sidebar and then go to group chat + await chatsSidebarFirstUser.waitForGroupToBeCreated("Test"); + const statusFromGroupOnUserB = + await chatsSidebarFirstUser.getSidebarGroupStatus("Test"); + await expect(statusFromGroupOnUserB).toHaveTextContaining( + "No messages sent yet, send one!", + ); + await chatsSidebarFirstUser.goToSidebarGroupChat("Test"); + + await chatsTopbarFirstUser.validateTopbarExists(); + + const topbarUserName = await chatsTopbarFirstUser.topbarUserNameValue; + await expect(topbarUserName).toHaveTextContaining("Test"); + + const topbarUserStatus = await chatsTopbarFirstUser.topbarUserStatusValue; + await expect(topbarUserStatus).toHaveTextContaining("Members (2)"); + await chatsSidebarFirstUser.goToSidebarChat("ChatUserA"); + + await chatsTopbarFirstUser.validateTopbarExists(); + }); + + it("Group Chat - User B receives the message in group chat", async () => { + // Validate message is received in group chat + await chatsSidebarFirstUser.goToSidebarGroupChat("Test"); + await chatsMessagesFirstUser.waitForReceivingMessage("Sup"); + }); + + it("Group Chat - User B - Group is displayed", async () => { + // Validate search results for a string not matching any group chat or user + await chatsTopbarFirstUser.validateTopbarExists(); + + const topbarUserName = await chatsTopbarFirstUser.topbarUserNameValue; + await expect(topbarUserName).toHaveTextContaining("Test"); + }); +} diff --git a/tests/specs/reusable-accounts/ChatUserB/09-group-chat-edit-userB.spec.ts b/tests/specs/reusable-accounts/ChatUserB/09-group-chat-edit-userB.spec.ts new file mode 100644 index 0000000000..e09f6d0f72 --- /dev/null +++ b/tests/specs/reusable-accounts/ChatUserB/09-group-chat-edit-userB.spec.ts @@ -0,0 +1,48 @@ +import "module-alias/register"; +import ChatsSidebar from "@screenobjects/chats/ChatsSidebar"; +import FilesScreen from "@screenobjects/files/FilesScreen"; +import Topbar from "@screenobjects/chats/Topbar"; +import WelcomeScreen from "@screenobjects/welcome-screen/WelcomeScreen"; +import { USER_A_INSTANCE } from "@helpers/constants"; +let chatsSidebarFirstUser = new ChatsSidebar(USER_A_INSTANCE); +let chatsTopbarFirstUser = new Topbar(USER_A_INSTANCE); +let filesScreenFirstUser = new FilesScreen(USER_A_INSTANCE); +let welcomeScreenFirstUser = new WelcomeScreen(USER_A_INSTANCE); + +export default async function groupChatEditTestsUserB() { + it("Chat User B - You are not the group creator tooltip is displayed", async () => { + // Validate tooltip is shown + await chatsTopbarFirstUser.hoverOnEditGroupButton(); + + const tooltipText = await chatsTopbarFirstUser.viewGroupTooltipText; + await expect(tooltipText).toHaveTextContaining("View Group"); + }); + + it("Edit Group - Validate group name was changed correctly on remote side", async () => { + // Validate group name was changed correctly on remote side + await chatsSidebarFirstUser.waitForGroupToBeCreated("X"); + const topbarSecondUserName = await chatsTopbarFirstUser.topbarUserNameValue; + await expect(topbarSecondUserName).toHaveTextContaining("X"); + }); + + it("Edit Group - Validate remote user was correctly removed from the group chat", async () => { + // Validate that remote user was removed from the group correctly + await chatsSidebarFirstUser.waitForGroupToBeDeleted("X"); + await welcomeScreenFirstUser.validateWelcomeScreenIsShown(); + }); + + it("Edit Group - Ensure that Chat User B was added back to the group", async () => { + // Validate that User B was added back to the group chat + await chatsSidebarFirstUser.goToFiles(); + await filesScreenFirstUser.validateFilesScreenIsShown(); + await filesScreenFirstUser.goToMainScreen(); + await chatsSidebarFirstUser.validateSidebarChatsIsShown(); + await chatsSidebarFirstUser.waitForGroupToBeCreated("X"); + await chatsSidebarFirstUser.goToSidebarGroupChat("X"); + await chatsTopbarFirstUser.validateTopbarExists(); + + // Validate topbar contents has correct name + const topbarUserStatus = await chatsTopbarFirstUser.topbarUserStatusValue; + await expect(topbarUserStatus).toHaveTextContaining("Members (2)"); + }); +} diff --git a/tests/specs/reusable-accounts/ChatUserB/10-group-chats-sidebar-userB.spec.ts b/tests/specs/reusable-accounts/ChatUserB/10-group-chats-sidebar-userB.spec.ts new file mode 100644 index 0000000000..12760b99fc --- /dev/null +++ b/tests/specs/reusable-accounts/ChatUserB/10-group-chats-sidebar-userB.spec.ts @@ -0,0 +1,57 @@ +import "module-alias/register"; +import ChatsSidebar from "@screenobjects/chats/ChatsSidebar"; +import ContextMenuSidebar from "@screenobjects/chats/ContextMenuSidebar"; +import FilesScreen from "@screenobjects/files/FilesScreen"; +import InputBar from "@screenobjects/chats/InputBar"; +import Messages from "@screenobjects/chats/Messages"; +import Topbar from "@screenobjects/chats/Topbar"; +import { USER_A_INSTANCE } from "@helpers/constants"; +let chatsInputFirstUser = new InputBar(USER_A_INSTANCE); +let chatsMessagesFirstUser = new Messages(USER_A_INSTANCE); +let chatsSidebarFirstUser = new ChatsSidebar(USER_A_INSTANCE); +let chatsTopbarFirstUser = new Topbar(USER_A_INSTANCE); +let contextMenuSidebarFirstUser = new ContextMenuSidebar(USER_A_INSTANCE); +let filesScreenFirstUser = new FilesScreen(USER_A_INSTANCE); + +export default async function groupChatSidebarTestsUserB() { + it("Group Chat - Send message to the group with User B", async () => { + // Send message to the group + await chatsInputFirstUser.typeMessageOnInput("HelloGroup"); + await chatsInputFirstUser.clickOnSendMessage(); + await chatsMessagesFirstUser.waitForMessageSentToExist("HelloGroup"); + }); + + it("Group Chat - Send another message to show again the group chat", async () => { + // Send message to the group + await chatsInputFirstUser.typeMessageOnInput("Hey!"); + await chatsInputFirstUser.clickOnSendMessage(); + await chatsMessagesFirstUser.waitForMessageSentToExist("Hey!"); + }); + + it("Group Chat - Sidebar - Leave group", async () => { + // Leave group chat + await chatsSidebarFirstUser.openContextMenuOnGroupChat("X"); + await contextMenuSidebarFirstUser.selectChatsLeaveGroup(); + await chatsSidebarFirstUser.validateSidebarChatIsNotDisplayed("X"); + }); + + it("Group Chat - Ensure in remote side that user was added again to the group", async () => { + // Ensure that user was added again to the group + await chatsSidebarFirstUser.goToFiles(); + await filesScreenFirstUser.validateFilesScreenIsShown(); + await filesScreenFirstUser.goToMainScreen(); + await chatsSidebarFirstUser.validateSidebarChatsIsShown(); + await chatsSidebarFirstUser.waitForGroupToBeCreated("X"); + await chatsSidebarFirstUser.goToSidebarGroupChat("X"); + await chatsTopbarFirstUser.validateTopbarExists(); + + // Validate topbar contents has correct name + const topbarUserName = await chatsTopbarFirstUser.topbarUserNameValue; + await expect(topbarUserName).toHaveTextContaining("X"); + }); + + it("Group Chat - Sidebar - Deleted group is not shown on remote side", async () => { + // Ensure that group was removed on this side too + await chatsSidebarFirstUser.validateSidebarChatIsNotDisplayed("X"); + }); +} diff --git a/tests/suites/Chats/02-ChatsUserA.suite.ts b/tests/suites/Chats/02-ChatsUserA.suite.ts new file mode 100644 index 0000000000..a7d7703b70 --- /dev/null +++ b/tests/suites/Chats/02-ChatsUserA.suite.ts @@ -0,0 +1,26 @@ +import "module-alias/register"; +import mainChatsTestsUserA from "@specs/reusable-accounts/ChatUserA/01-main-chats-userA.spec"; +import repliesTestsUserA from "@specs/reusable-accounts/ChatUserA/02-chat-replies-userA.spec"; +import messageContextMenuTestsUserA from "@specs/reusable-accounts/ChatUserA/03-message-context-menu-userA.spec"; +import messageInputTestsUserA from "@specs/reusable-accounts/ChatUserA/04-message-input-userA.spec"; +import messageAttachmentsTestsUserA from "@specs/reusable-accounts/ChatUserA/05-message-attachments-userA.spec"; +import chatTopbarTestsUserA from "@specs/reusable-accounts/ChatUserA/06-chat-topbar-userA.spec"; +import quickProfileTestsUserA from "@specs/reusable-accounts/ChatUserA/07-quick-profile-userA.spec"; +import sidebarChatsTestsUserA from "@specs/reusable-accounts/ChatUserA/08-sidebar-chats-userA.spec"; +import groupChatTestsUserA from "@specs/reusable-accounts/ChatUserA/09-group-chats-userA.spec"; +import groupChatEditTestsUserA from "@specs/reusable-accounts/ChatUserA/10-group-chat-edit-userA.spec"; +import groupChatSidebarTestsUserA from "@specs/reusable-accounts/ChatUserA/11-group-chats-sidebar-userA.spec"; + +describe("MacOS Chats Tests - User A", async () => { + describe("Accept friend request and Chat", mainChatsTestsUserA.bind(this)); + xdescribe("Chat Replies", repliesTestsUserA.bind(this)); + xdescribe("Message Context Menu", messageContextMenuTestsUserA.bind(this)); + xdescribe("Message Input", messageInputTestsUserA.bind(this)); + xdescribe("Message Attachments", messageAttachmentsTestsUserA.bind(this)); + xdescribe("Chat Topbar", chatTopbarTestsUserA.bind(this)); + xdescribe("Quick Profile", quickProfileTestsUserA.bind(this)); + xdescribe("Sidebar Chats", sidebarChatsTestsUserA.bind(this)); + xdescribe("Group Chats Main", groupChatTestsUserA.bind(this)); + xdescribe("Group Chats Edit", groupChatEditTestsUserA.bind(this)); + xdescribe("Group Chats Sidebar", groupChatSidebarTestsUserA.bind(this)); +}); diff --git a/tests/suites/Chats/03-ChatsUserB.suite.ts b/tests/suites/Chats/03-ChatsUserB.suite.ts new file mode 100644 index 0000000000..2428d32ef2 --- /dev/null +++ b/tests/suites/Chats/03-ChatsUserB.suite.ts @@ -0,0 +1,24 @@ +import "module-alias/register"; +import mainChatsTestsUserB from "@specs/reusable-accounts/ChatUserB/01-main-chats-userB.spec"; +import repliesTestsUserB from "@specs/reusable-accounts/ChatUserB/02-chat-replies-userB.spec"; +import messageContextMenuTestsUserB from "@specs/reusable-accounts/ChatUserB/03-message-context-menu-userB.spec"; +import messageInputTestsUserB from "@specs/reusable-accounts/ChatUserB/04-message-input-userB.spec"; +import messageAttachmentsTestsUserB from "@specs/reusable-accounts/ChatUserB/05-message-attachments-userB.spec"; +import quickProfileTestsUserB from "@specs/reusable-accounts/ChatUserB/06-quick-profile-userB.spec"; +import sidebarChatsTestsUserB from "@specs/reusable-accounts/ChatUserB/07-sidebar-chats-userB.spec"; +import groupChatTestsUserB from "@specs/reusable-accounts/ChatUserB/08-group-chats-userB.spec"; +import groupChatEditTestsUserB from "@specs/reusable-accounts/ChatUserB/09-group-chat-edit-userB.spec"; +import groupChatSidebarTestsUserB from "@specs/reusable-accounts/ChatUserB/10-group-chats-sidebar-userB.spec"; + +describe("MacOS Chats Tests - User B", async () => { + describe("Send friend request and Chat", mainChatsTestsUserB.bind(this)); + xdescribe("Chat Replies", repliesTestsUserB.bind(this)); + xdescribe("Message Context Menu", messageContextMenuTestsUserB.bind(this)); + xdescribe("Message Input", messageInputTestsUserB.bind(this)); + xdescribe("Message Attachments", messageAttachmentsTestsUserB.bind(this)); + xdescribe("Quick Profile", quickProfileTestsUserB.bind(this)); + xdescribe("Sidebar Chats", sidebarChatsTestsUserB.bind(this)); + xdescribe("Group Chats Main", groupChatTestsUserB.bind(this)); + xdescribe("Group Chats Edit", groupChatEditTestsUserB.bind(this)); + xdescribe("Group Chats Sidebar", groupChatSidebarTestsUserB.bind(this)); +}); diff --git a/tests/suites/MainTests/01-UplinkTests.suite.ts b/tests/suites/MainTests/01-UplinkTests.suite.ts index a0c3211f06..3551f1fcdc 100644 --- a/tests/suites/MainTests/01-UplinkTests.suite.ts +++ b/tests/suites/MainTests/01-UplinkTests.suite.ts @@ -4,7 +4,7 @@ import chats from "@specs/02-chats.spec"; import files from "@specs/03-files.spec"; import settingsProfile from "@specs/05-settings-profile.spec"; import settingsGeneral from "@specs/06-settings-general.spec"; -import settingsMessages from "@specs/15-settings-messages.spec"; +import settingsMessages from "@specs/14-settings-messages.spec"; import settingsAudio from "@specs/07-settings-audio.spec"; import settingsExtensions from "@specs/08-settings-extensions.spec"; import settingsNotifications from "@specs/09-settings-notifications.spec"; diff --git a/tests/suites/MainTests/02-UplinkWindows.suite.ts b/tests/suites/MainTests/02-UplinkWindows.suite.ts index 2e2fbe372c..f6221cd143 100644 --- a/tests/suites/MainTests/02-UplinkWindows.suite.ts +++ b/tests/suites/MainTests/02-UplinkWindows.suite.ts @@ -4,7 +4,7 @@ import chats from "@specs/02-chats.spec"; import files from "@specs/03-files.spec"; import settingsProfile from "@specs/05-settings-profile.spec"; import settingsGeneral from "@specs/06-settings-general.spec"; -import settingsMessages from "@specs/15-settings-messages.spec"; +import settingsMessages from "@specs/14-settings-messages.spec"; import settingsAudio from "@specs/07-settings-audio.spec"; import settingsExtensions from "@specs/08-settings-extensions.spec"; import settingsNotifications from "@specs/09-settings-notifications.spec"; diff --git a/tests/suites/MainTests/03-CreateAccountA.suite.ts b/tests/suites/MainTests/03-CreateAccountA.suite.ts new file mode 100644 index 0000000000..693ca9df40 --- /dev/null +++ b/tests/suites/MainTests/03-CreateAccountA.suite.ts @@ -0,0 +1,6 @@ +import "module-alias/register"; +import createFirstAccount from "@specs/15-create-first-account.spec"; + +describe("MacOS Tests - Create First Account", function () { + describe("Create and Save First Account", createFirstAccount.bind(this)); +}) \ No newline at end of file diff --git a/tests/suites/MainTests/04-CreateAccountB.suite.ts b/tests/suites/MainTests/04-CreateAccountB.suite.ts new file mode 100644 index 0000000000..aae56d8c8b --- /dev/null +++ b/tests/suites/MainTests/04-CreateAccountB.suite.ts @@ -0,0 +1,6 @@ +import "module-alias/register"; +import createSecondAccount from "@specs/16-create-second-account.spec"; + +describe("MacOS Tests - Create Second Account", function () { + describe("Create and Save Second Account", createSecondAccount.bind(this)); +}) \ No newline at end of file