Skip to content

Commit

Permalink
e2e-test: convert to playwright runner (#5234)
Browse files Browse the repository at this point in the history
### Summary

This PR introduces a significant update to our e2e testing framework by
migrating from Mocha to Playwright as our test runner. The new setup not
only achieves feature parity with the existing Mocha runner but also
adds enhanced capabilities, offering an improved developer experience
and streamlined debugging. For an in-depth explanation of the changes
and rationale, please refer to the [POC
Document](https://positpbc.atlassian.net/wiki/spaces/POSITRON/pages/1224999131/Proof+of+Concept+Playwright).

**Key notes:**
* Replaced Mocha with Playwright for e2e test execution.
* All existing Positron tests have been converted to Playwright syntax
and are fully operational.
* Updated all CI workflows and added publishing of HTML reports to S3
bucket

### QA Notes
Example Workflow Runs:
* [Full Test
Suite](https://github.com/posit-dev/positron/actions/runs/11933152185)
* [Windows Test
Suite](https://github.com/posit-dev/positron/actions/runs/11933795345)
* [Tests against Latest
Build](https://github.com/posit-dev/positron/actions/runs/11933100000)

### Screenshots
<img width="362" alt="Screenshot 2024-11-18 at 11 37 22 AM"
src="https://github.com/user-attachments/assets/1483e0f1-664b-4de9-98b9-0638a169d881">
  • Loading branch information
midleman authored Nov 21, 2024
1 parent 59b5b0c commit 4003c9d
Show file tree
Hide file tree
Showing 113 changed files with 4,510 additions and 4,957 deletions.
117 changes: 117 additions & 0 deletions .github/actions/e2e-report/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
name: "E2E Report"
description: "Generate and upload E2E reports, and notify stakeholders"
inputs:
aws-s3-bucket:
description: "AWS S3 bucket name"
required: true
aws-role:
description: "AWS role to assume"
required: true
junit-pattern:
description: "Pattern to match JUnit reports"
default: "junit-report-*"
blob-pattern:
description: "Pattern to match blob reports"
default: "blob-report-*"
slack-token:
description: "Slack token for notifications"
required: true
slack-channel:
description: "Slack channel for notifications"
required: true
slack-title:
description: "Slack title for the test suite"
default: "Test Suite Results"
testrail-api-key:
description: "TestRail API Key"
required: true
github-token:
description: "GitHub token for API calls"
required: true
testrail-project:
description: "TestRail project name"
default: "Positron"
testrail-title:
description: "Title for TestRail runs"
default: "E2E Test Run"

runs:
using: "composite"
steps:
- name: Checkout Repository
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: .nvmrc

- name: Install AWS CLI
shell: bash
run: |
apt-get update && apt-get install -y unzip python3-pip
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o /tmp/awscliv2.zip
unzip -q /tmp/awscliv2.zip -d /tmp
/tmp/aws/install -i $HOME/aws-cli -b $HOME/bin
rm -rf /tmp/aws /tmp/awscliv2.zip
- name: Add AWS CLI to PATH
shell: bash
run: echo "$HOME/bin" >> $GITHUB_PATH

- name: Verify AWS CLI installation
shell: bash
run: aws --version

- name: Download Blob Reports
uses: actions/download-artifact@v4
with:
path: all-blob-reports
pattern: ${{ inputs.blob-pattern }}
merge-multiple: true

- name: Merge Blobs into HTML Report
shell: bash
run: npx playwright merge-reports --reporter html ./all-blob-reports

- name: Upload Playwright Report to S3
uses: ./.github/actions/upload-report-to-s3
with:
role-to-assume: ${{ inputs.aws-role }}

- name: Send HTML Report URL to GitHub Summary
shell: bash
run: |
REPORT_URL="https://d38p2avprg8il3.cloudfront.net/${{ env.REPORT_DIR }}/index.html"
echo "Report URL: $REPORT_URL"
echo "📄 [Playwright Report]($REPORT_URL) <br>" > $GITHUB_STEP_SUMMARY
- name: Download JUnit Reports
uses: actions/download-artifact@v4
with:
path: all-junit-reports
pattern: ${{ inputs.junit-pattern }}
merge-multiple: true

- name: Merge JUnit Reports
shell: bash
run: npm install -g junit-report-merger && npx jrm junit.xml "all-junit-reports/*.xml"

- name: Install trcli
shell: bash
run: apt-get update && apt-get install -y python3-pip && pip3 install trcli

- name: Upload Test Results to TestRail
shell: bash
run: |
TESTRAIL_TITLE="$(date +'%Y-%m-%d') ${{ inputs.testrail-title }} - $GITHUB_REF_NAME"
echo "TESTRAIL_TITLE=$TESTRAIL_TITLE" >> $GITHUB_ENV
trcli --host "https://posit.testrail.io/" --project "${{ inputs.testrail-project }}" --username testrailautomation@posit.co --key "${{ inputs.testrail-api-key }}" parse_junit --file "./junit.xml" --case-matcher name --title "$TESTRAIL_TITLE" --close-run
- name: Send Slack Notification
uses: testlabauto/action-test-results-to-slack@v0.0.6
with:
github_token: ${{ inputs.github-token }}
slack_token: ${{ inputs.slack-token }}
slack_channel: ${{ inputs.slack-channel }}
suite_name: ${{ inputs.slack-title }}
4 changes: 4 additions & 0 deletions .github/actions/setup-test-env/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ inputs:
runs:
using: "composite"
steps:
- name: Compile E2E Tests
shell: bash
run: yarn --cwd test/automation compile && yarn --cwd test/smoke compile

- name: Setup AWS S3 Access
uses: aws-actions/configure-aws-credentials@v4
with:
Expand Down
22 changes: 22 additions & 0 deletions .github/actions/upload-report-to-s3/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: "Upload Playwright Report to S3"
description: "Configures AWS credentials and uploads the Playwright report to S3"
inputs:
role-to-assume:
description: "The AWS role to assume"
required: true

runs:
using: "composite"
steps:
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
if: ${{ !cancelled() }}
with:
role-to-assume: ${{ inputs.role-to-assume }}
aws-region: "us-east-1"

- name: Upload Playwright Report to S3 Bucket
if: ${{ !cancelled() }}
shell: bash
run: |
aws s3 cp playwright-report/. s3://positron-test-reports/playwright-report-${{ github.run_id }} --recursive
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,21 @@ name: "Latest Release: E2E Electron Tests"

on:
workflow_dispatch:
inputs:
e2e_grep:
required: false
description: "Grep filter to apply to the e2e tests: @pr, @win, etc."
default: ""
type: string

permissions:
id-token: write
contents: read

env:
E2E_GREP: ${{ inputs.e2e_grep || '' }}
REPORT_DIR: playwright-report-${{ github.run_id }}

jobs:
linux:
name: e2e-electron-tests
Expand Down Expand Up @@ -66,36 +76,26 @@ jobs:
sudo update-rc.d xvfb defaults
sudo service xvfb start
- name: Send HTML report URL to GitHub Summary
if: ${{ !cancelled() }}
run: |
REPORT_URL="https://d38p2avprg8il3.cloudfront.net/${{ env.REPORT_DIR }}/index.html"
echo "Report URL: $REPORT_URL"
echo "📄 [Playwright Report]($REPORT_URL) <br>" > $GITHUB_STEP_SUMMARY
- name: Run Tests (Electron)
if: ${{ !cancelled() }}
env:
POSITRON_PY_VER_SEL: 3.10.12
POSITRON_R_VER_SEL: 4.4.0
id: electron-smoke-tests
run: |
cd test/smoke
export BUILD_ARTIFACTSTAGINGDIRECTORY=../../.build/logs/smoke-tests-electron
export DISPLAY=:10
node run-tests.js --tracing --parallel --jobs 2 --skip-cleanup --build /usr/share/positron
BUILD=/usr/share/positron npx playwright test --project e2e-electron --workers 2 --grep="${{ env.E2E_GREP }}"
- name: Convert XUnit to JUnit
id: xunit-to-junit
if: success() || failure()
run: |
sudo apt-get update
sudo apt-get install -y libxml2-utils
yarn xunit-to-junit smoke-tests-electron
- name: Publish Electron Test Report
uses: mikepenz/action-junit-report@v4
if: success() || failure()
- name: Upload Playwright Report to S3
if: ${{ !cancelled() }}
uses: ./.github/actions/upload-report-to-s3
with:
report_paths: "**/.build/logs/smoke-tests-electron/test-results/xunit-results.xml"
check_name: "Electron Test Results"
token: ${{ secrets.GITHUB_TOKEN }}
role-to-assume: ${{ secrets.AWS_TEST_REPORTS_ROLE }}

- name: Upload Artifacts - Electron
if: always()
uses: actions/upload-artifact@v4
with:
name: run-artifacts-electron
path: .build/logs/smoke-tests-electron/
125 changes: 53 additions & 72 deletions .github/workflows/positron-full-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,12 @@ jobs:

e2e-electron-tests:
runs-on: ubuntu-latest-8x
timeout-minutes: 80
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
shardIndex: [1, 2]
shardTotal: [2]
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
POSITRON_BUILD_NUMBER: 0 # CI skips building releases
Expand Down Expand Up @@ -126,45 +131,27 @@ jobs:
env:
POSITRON_PY_VER_SEL: 3.10.12
POSITRON_R_VER_SEL: 4.4.0
id: electron-smoke-tests
run: DISPLAY=:10 yarn smoketest-all --tracing --skip-cleanup

- name: Convert XUnit to JUnit
id: xunit-to-junit
if: success() || failure()
run: |
sudo apt-get update
sudo apt-get install -y libxml2-utils
yarn xunit-to-junit smoke-tests-electron
- name: Publish Electron Test Report
uses: mikepenz/action-junit-report@v4
if: success() || failure()
with:
report_paths: "**/.build/logs/smoke-tests-electron/test-results/xunit-results.xml"
check_name: "Electron Test Results"
token: ${{ secrets.GITHUB_TOKEN }}

- name: Set TestRail Run Title
id: set-testrail-run-title
if: steps.xunit-to-junit == 'success'
run: echo "TESTRAIL_TITLE=$(date +'%Y-%m-%d') Nightly Smoke Tests - $GITHUB_REF_NAME" >> $GITHUB_ENV
id: electron-tests
run: DISPLAY=:10 npx playwright test --project e2e-electron --workers 1 --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}

- name: Upload Test Results to TestRail (Electron ONLY)
id: testrail-upload
if: steps.xunit-to-junit == 'success'
run: trcli --host "https://posit.testrail.io/" --project Positron --username testrailautomation@posit.co --key ${{ secrets.TESTRAIL_API_KEY}} parse_junit --file ".build/logs/smoke-tests-electron/test-results/xunit-results.xml" --case-matcher name --title "$TESTRAIL_TITLE" --close-run
- name: Upload blob report
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v4
with:
name: blob-report-electron-${{ matrix.shardIndex }}
path: blob-report
retention-days: 14

- name: Upload Artifacts - Electron
if: always()
- name: Upload junit report
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v4
with:
name: run-artifacts-electron
path: .build/logs/smoke-tests-electron/
name: junit-report-electron-${{ matrix.shardIndex }}
path: test-results/junit.xml

e2e-browser-tests:
runs-on: ubuntu-latest-4x
timeout-minutes: 40
timeout-minutes: 50
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
POSITRON_BUILD_NUMBER: 0 # CI skips building releases
Expand Down Expand Up @@ -197,56 +184,50 @@ jobs:
aws-region: ${{ secrets.QA_AWS_REGION }}
github-token: ${{ secrets.GITHUB_TOKEN }}

- name: Run Web Smoke Tests
- name: Run Tests (Browser)
env:
POSITRON_PY_VER_SEL: 3.10.12
POSITRON_R_VER_SEL: 4.4.0
id: electron-web-smoke-tests
run: DISPLAY=:10 yarn smoketest-web --tracing

- name: Convert XUnit to JUnit
id: xunit-to-junit
if: success() || failure()
run: |
sudo apt-get update
sudo apt-get install -y libxml2-utils
yarn xunit-to-junit smoke-tests-browser
- name: Publish Web Test Report
uses: mikepenz/action-junit-report@v4
if: success() || failure()
with:
report_paths: "**/.build/logs/smoke-tests-browser/test-results/xunit-results.xml"
check_name: "Web Test Results"
token: ${{ secrets.GITHUB_TOKEN }}
id: browser-tests
run: DISPLAY=:10 npx playwright test --project e2e-browser --workers 1

- name: Upload Artifacts - Browser
if: always()
- name: Upload blob report
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v4
with:
name: run-artifacts-browser
path: .build/logs/smoke-tests-browser/
name: blob-report-browser
path: blob-report
retention-days: 14

- name: Clean up license files
if: always()
run: cd .. && rm -rf positron-license

slack-notification:
name: "slack-notification"
e2e-report:
if: always()
runs-on: ubuntu-latest
needs:
[
"unit-tests",
"integration-tests",
"e2e-electron-tests",
"e2e-browser-tests",
]
if: failure()
container:
image: mcr.microsoft.com/playwright:v1.48.0-jammy
needs: [e2e-electron-tests, e2e-browser-tests, unit-tests, integration-tests]
env:
REPORT_DIR: playwright-report-${{ github.run_id }}

steps:
- name: "Send Slack notification"
uses: testlabauto/action-test-results-to-slack@v0.0.6
- uses: actions/checkout@v4

- name: Setup Node
uses: actions/setup-node@v4
with:
github_token: ${{ secrets.POSITRON_GITHUB_PAT }}
slack_token: ${{ secrets.SMOKE_TESTS_SLACK_TOKEN }}
slack_channel: C07FR1JNZNJ #positron-test-results channel
suite_name: Positron Full Test Suite
node-version-file: .nvmrc

- name: Run E2E Report
uses: ./.github/actions/e2e-report
with:
aws-s3-bucket: positron-test-reports
aws-role: ${{ secrets.AWS_TEST_REPORTS_ROLE }}
slack-token: ${{ secrets.SMOKE_TESTS_SLACK_TOKEN }}
slack-channel: C07FR1JNZNJ
slack-title: "Full Test Suite (Electron)"
testrail-api-key: ${{ secrets.TESTRAIL_API_KEY }}
testrail-title: "E2E Electron Test Run"
github-token: ${{ secrets.POSITRON_GITHUB_PAT }}
Loading

0 comments on commit 4003c9d

Please sign in to comment.