diff --git a/.gitignore b/.gitignore index 57ddef5d..c859f2d5 100644 --- a/.gitignore +++ b/.gitignore @@ -24,7 +24,6 @@ pnpm-debug.log* # Playwright /test-results/ -/ortoni-report/ /playwright-report/ /blob-report/ /playwright/.cache/ diff --git a/Dockerfile.playwright b/Dockerfile.playwright index 46a2114a..6271a937 100644 --- a/Dockerfile.playwright +++ b/Dockerfile.playwright @@ -1,4 +1,4 @@ -FROM node:20 +FROM node:16 FROM mcr.microsoft.com/playwright:v1.48.0-noble @@ -12,10 +12,10 @@ COPY package*.json ./ RUN npm install # Install Playwright browsers -RUN npx playwright install chromium --with-deps - -# Install jq -RUN apt-get install -y jq +RUN npx playwright install --with-deps # Copy the rest of the application code COPY . . + +# Run Playwright tests +CMD ["npx", "playwright", "test"] diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 6bddeece..cedebb5b 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -90,6 +90,7 @@ stages: "npx wait-on http://localhost:8080 && npm run test:playwright -- --shard=$(shardNumber)/$(totalShards) --reporter=list,blob --grep \"@smoke | @Advanced\"") # Start container and stream logs + echo "Starting tests for shard $(shardNumber)..." docker start -a $container_id @@ -126,60 +127,26 @@ stages: condition: always() - job: download_and_merge_reports + container: + image: mcr.microsoft.com/playwright:v1.48.0-noble dependsOn: playwright_tests steps: - - task: DownloadPipelineArtifact@2 - inputs: - targetPath: '$(System.DefaultWorkingDirectory)/playwright-reports' - - task: Docker@2 - displayName: 'Build Docker Image' - inputs: - command: build - dockerfile: Dockerfile.playwright - repository: $(dockerImageName) - tags: $(imageTag) - arguments: '--no-cache --pull' - - bash: | - # Create container for jira writeback - container_id=$(docker create \ - --ipc=host \ - -e JIRA_SERVER=$(JIRA_SERVER) \ - -e JIRA_USERNAME=$(JIRA_USERNAME) \ - -e JIRA_API_KEY=$(JIRA_API_KEY) \ - $(dockerImageName):$(imageTag) \ - bash -c "echo \"Moving Playwright reports out of subfolders...\" && - find ./playwright-reports/ -mindepth 2 -type f -exec mv {} ./playwright-reports/ \; && - echo \"Merging reports...\" && - npx playwright merge-reports --reporter=ortoni-report ./playwright-reports - # npx playwright merge-reports --config=playwright-tests/playwright.config.ts ./playwright-reports - # num_failures=$(sed -n 's/.*failures="\([^"]*\)".*/\1/p' /app/test-results/junit_results.xml | head -n 1) - # echo \"Number of test failures: '$num_failures'\" - # (($num_failures -eq 0)) && jira_message='Playwright tests passed!' || jira_message=\"$num_failures Playwright tests failed.\" - # TODO: Update to include test status message later - echo \"Contents of ortoni-report:\" && ls ./ortoni-report && - echo \"Writing report to Jira card '$(Build.SourceBranchName)'...\" && - ./devops/scripts/jira_writeback.sh add_comment \"$(Build.SourceBranchName)\" /app/ortoni-report/ortoni-report.html \"AUTOMATED TEST RUN: $(date)\" ") - - # Start container and stream logs - echo "Starting merge" - docker start -a $container_id - - # Create directory for test results - echo "Creating test results directory..." - mkdir -p $(System.DefaultWorkingDirectory)/ortoni-report - - # Copy test results from container - echo "Copying test results..." - docker cp $container_id:/app/ortoni-report/. $(System.DefaultWorkingDirectory)/ortoni-report - # docker cp $container_id:/app/test-results/junit_results.xml $(System.DefaultWorkingDirectory) - # TODO: Update to include junit results if necessary - - # Remove container - echo "Cleaning up container..." - docker rm $container_id - env: - JIRA_API_KEY: $(JIRA_API_KEY) - displayName: merge_and_publish_results_to_jira + - task: DownloadPipelineArtifact@2 + inputs: + targetPath: '$(System.DefaultWorkingDirectory)/playwright-reports' + - script: | + npm i ortoni-report && + for dir in $(System.DefaultWorkingDirectory)/playwright-reports/*/; do + if [ -d "$dir" ]; then + mv "$dir"* $(System.DefaultWorkingDirectory)/playwright-reports/ + rmdir "$dir" + fi + done + npx playwright merge-reports --reporter=ortoni-report,junit $(System.DefaultWorkingDirectory)/playwright-reports + ls + displayName: merge_reports + env: + PLAYWRIGHT_JUNIT_OUTPUT_FILE: "test-results/results.xml" # TODO: Enable later when working on PR gate # - task: PublishTestResults@2 @@ -187,23 +154,19 @@ stages: # inputs: # searchFolder: 'test-results' # testResultsFormat: 'JUnit' - # testResultsFiles: 'junit_results.xml' + # testResultsFiles: 'results.xml' # mergeTestResults: true # failTaskOnFailedTests: false # testRunTitle: 'Playwright Tests' # condition: succeededOrFailed() - - task: PublishPipelineArtifact@1 - displayName: 'Publish Merged Report' - condition: always() - inputs: - targetPath: '$(System.DefaultWorkingDirectory)/ortoni-report' - artifact: 'playwright-merged-report' - publishLocation: 'pipeline' - - script: | - docker rmi $(dockerImageName):$(imageTag) -f - displayName: 'Cleanup Docker Image' - condition: always() + - task: PublishPipelineArtifact@1 + displayName: 'Publish Merged Report' + condition: always() + inputs: + targetPath: '$(System.DefaultWorkingDirectory)/ortoni-report' + artifact: 'playwright-merged-report' + publishLocation: 'pipeline' - ${{ else }}: # Dev Build/Deploy diff --git a/devops/scripts/jira_writeback.sh b/devops/scripts/jira_writeback.sh deleted file mode 100755 index 1d605072..00000000 --- a/devops/scripts/jira_writeback.sh +++ /dev/null @@ -1,149 +0,0 @@ -#!/bin/bash -create_issue() { - local title="$1" - local project_key="$2" - local issue_type="$3" - local parent_issue_key="$4" - - AUTH=$(echo -ne "$JIRA_USERNAME:$JIRA_API_KEY" | base64 --wrap 0) - - local parent_issue=$(curl -s -H "Authorization: Basic $AUTH" \ - "$JIRA_SERVER/rest/api/3/issue/$parent_issue_key") - - local parent_fix_versions=$(echo $parent_issue | jq -r '.fields.fixVersions') - - local created_issue=$(curl -X POST -H "Content-Type: application/json" \ - -H "Authorization: Basic $AUTH" \ - -d '{ - "fields": { - "summary": "'"$title"'", - "project": { - "key": "'"$project_key"'" - }, - "issuetype": { - "name": "'"$issue_type"'" - }, - "parent": { - "key": "'"$parent_issue_key"'" - }, - "fixVersions": '"$parent_fix_versions"' - } - }' \ - "$JIRA_SERVER/rest/api/3/issue") - - local created_issue_id=$(echo $created_issue | jq -r '.id') - - curl -X PUT -H "Content-Type: application/json" \ - -H "Authorization: Basic $AUTH" \ - -d '{ - "fields": { - "fixVersions": '"$parent_fix_versions"' - } - }' \ - "$JIRA_SERVER/rest/api/3/issue/$created_issue_id" -} - -extract_uuid() { - local url="$1" - local uuid_regex='[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}' - if [[ "$url" =~ $uuid_regex ]]; then - echo "${BASH_REMATCH}" - else - echo "No UUID found in the URL." - fi -} - -update_issue_status() { - local issue_key="$1" - local status_name="$2" - - AUTH=$(echo -ne "$JIRA_USERNAME:$JIRA_API_KEY" | base64 --wrap 0) - - local transitions=$(curl -s -H "Authorization: Basic $AUTH" \ - "$JIRA_SERVER/rest/api/3/issue/$issue_key/transitions") - - local transition_id=$(echo "$transitions" | jq -r --arg status_name "$status_name" ' - .transitions[] | select(.isAvailable == true and .to.name == $status_name) | .id - ') - - if [ -z "$transition_id" ]; then - echo "BadRequestError" - exit 1 - else - curl -X POST -H "Content-Type: application/json" \ - -H "Authorization: Basic $AUTH" \ - -d '{ - "transition": { - "id": "'"$transition_id"'" - } - }' \ - "$JIRA_SERVER/rest/api/3/issue/$issue_key/transitions" - fi -} - -add_attachments() { - AUTH=$(echo -ne "$JIRA_USERNAME:$JIRA_API_KEY" | base64 --wrap 0) - - local issue_key="$1" - shift - local attachments=("$@") - - echo $issue_key - echo $attachments - - local form_data="" - for attachment in "${attachments[@]}"; do - form_data+="--form file=@$attachment " - done - - echo $form_data - - echo $(curl -X POST $form_data \ - -H "X-Atlassian-Token: no-check" \ - -H "Authorization: Basic $AUTH" \ - "$JIRA_SERVER/rest/api/3/issue/$issue_key/attachments") -} - -add_comment() { - AUTH=$(echo -ne "$JIRA_USERNAME:$JIRA_API_KEY" | base64 --wrap 0) - local issue_key="$1" - shift - local comment_items_input=("$@") - local comment_json="[]" - - for item in "${comment_items_input[@]}"; do - if [ -e "$item" ]; then - # If it's a file path - local attachment=$(add_attachments "$issue_key" "$item") - local id=$(echo $attachment | grep -oP '"id":\s*"\K[^"]+') - - local attachment_content=$(curl -s -I -L -H "Authorization: Basic $AUTH" "$JIRA_SERVER/rest/api/3/attachment/content/$id" \ - | grep -i "Location:" | tail -1 | awk '{print $2}' | tr -d '\r') - echo "$JIRA_SERVER/rest/api/3/attachment/content/$id" - echo "$attachment_content" - - local uuid=$(extract_uuid "$attachment_content") - echo "$uuid" - - json_object=$(jq -n --arg uuid "$uuid" '{ type: "mediaSingle", attrs: { layout: "align-start" }, content: [{ type: "media", attrs: { type: "file", id: $uuid, width: 200, height: 200, collection: "", alt: "" } }]}') - - comment_json=$(echo "$comment_json" | jq --argjson obj "$json_object" '. += [$obj]') - else - # If it's a string - json_object=$(jq -n --arg text "$item" '{ type: "paragraph", content: [{ type: "text", text: $text }]}') - - comment_json=$(echo "$comment_json" | jq --argjson obj "$json_object" '. += [$obj]') - fi - done - - request=$(jq -n --argjson content "$comment_json" '{body: { type: "doc", version: 1, content: $content }}') - - curl -X POST -H "Content-Type: application/json" \ - -H "Authorization: Basic $AUTH" \ - -d "$request" \ - "$JIRA_SERVER/rest/api/3/issue/$issue_key/comment" -} - -if [[ $# -gt 0 ]]; then # IF function call passed in - "$@" # Call function -fi \ No newline at end of file diff --git a/playwright-tests/playwright.config.ts b/playwright-tests/playwright.config.ts index 0e7eaecb..20bf301e 100644 --- a/playwright-tests/playwright.config.ts +++ b/playwright-tests/playwright.config.ts @@ -28,7 +28,7 @@ if (!process.env.CI) { const reportConfig: OrtoniReportConfig = { port: 1994, open: "never", - folderPath: "ortoni-report", + folderPath: "test-results", filename: "index.html", logo: "../business-logic/data/logo.png", title: "Test Report", @@ -55,7 +55,7 @@ export default defineConfig({ /* Reporter to use. See https://playwright.dev/docs/test-reporters */ reporter: [ ['ortoni-report', reportConfig], - ['junit', {outputFile: '../test-results/junit_results.xml'}], + ['junit'], ['list'] ], timeout: 120_000,