Sets up the core infrastructure for Playwright-based automated testing, including: - Docker support for consistent environments - Azure Pipelines configuration for CI/CD - Page Object Model structure for maintainable tests - Test data, validation, and rule engine implementation - Test configuration for alerts and other scenarios
336 lines
No EOL
14 KiB
YAML
336 lines
No EOL
14 KiB
YAML
pool: 'Default'
|
|
|
|
variables:
|
|
# - group: Digital-Infrastructure
|
|
# - group: FMG-BuildBranches
|
|
- name: dockerImageName
|
|
value: 'playwright-tests'
|
|
- name: imageTag
|
|
value: '$(Build.BuildId)'
|
|
- name: totalShards
|
|
value: 4
|
|
|
|
stages:
|
|
- stage: TestPr
|
|
displayName: Run Playwright Test
|
|
jobs:
|
|
- job: playwright_tests
|
|
continueOnError: true
|
|
strategy:
|
|
matrix:
|
|
shard1:
|
|
shardNumber: 1
|
|
shard2:
|
|
shardNumber: 2
|
|
shard3:
|
|
shardNumber: 3
|
|
shard4:
|
|
shardNumber: 4
|
|
|
|
steps:
|
|
- task: Docker@2
|
|
displayName: 'Build Docker Image'
|
|
inputs:
|
|
command: build
|
|
dockerfile: Dockerfile.playwright
|
|
repository: $(dockerImageName)
|
|
tags: $(imageTag)
|
|
arguments: '--no-cache --pull'
|
|
|
|
- script: |
|
|
# Create container and run tests
|
|
container_id=$(docker create \
|
|
--ipc=host \
|
|
-e CCIS_API_AUTH=$(CCIS_API_AUTH) \
|
|
-e BASE_URL="$(BASE_URL)" \
|
|
-e CCIS_API_URL=$(CCIS_API_URL) \
|
|
-e ADMIN_SERVICE_API_URL=$(ADMIN_SERVICE_API_URL) \
|
|
-e SKIP_CONTENT_SITE=$(SKIP_CONTENT_SITE) \
|
|
-e CI=true \
|
|
-e NODE_ENV=$(NODE_ENV) \
|
|
$(dockerImageName):$(imageTag) \
|
|
npm run test:playwright -- --shard=$(shardNumber)/$(totalShards) --reporter=list,blob --grep '@(Alert|CASH)')
|
|
|
|
# Start container and stream logs
|
|
echo "Starting tests for shard $(shardNumber)..."
|
|
docker start -a $container_id
|
|
|
|
# Create directory for test results
|
|
echo "Creating test results directory..."
|
|
mkdir -p $(System.DefaultWorkingDirectory)/blob-reports/shard-$(shardNumber)
|
|
|
|
# Copy test results from container
|
|
echo "Copying test results..."
|
|
docker cp $container_id:/app/blob-report/. $(System.DefaultWorkingDirectory)/blob-reports/shard-$(shardNumber)/
|
|
|
|
# Remove container
|
|
echo "Cleaning up container..."
|
|
docker rm $container_id
|
|
|
|
# Check if tests failed
|
|
if [ $? -ne 0 ]; then
|
|
echo "Tests failed in shard $(shardNumber) or tests don't exist for this shard number!"
|
|
exit 0 # Suppress error. It will be visible in report.
|
|
fi
|
|
displayName: 'Run Playwright Tests - Shard $(shardNumber)'
|
|
|
|
- task: PublishPipelineArtifact@1
|
|
displayName: 'Publish Test Reports - Shard $(shardNumber)'
|
|
condition: always()
|
|
inputs:
|
|
targetPath: '$(System.DefaultWorkingDirectory)/blob-reports/shard-$(shardNumber)'
|
|
artifact: 'playwright-report-shard-$(shardNumber)'
|
|
publishLocation: 'pipeline'
|
|
|
|
- script: |
|
|
docker rmi $(dockerImageName):$(imageTag) -f
|
|
displayName: 'Cleanup Docker Image'
|
|
condition: always()
|
|
|
|
- job: download_and_merge_reports
|
|
dependsOn: playwright_tests
|
|
timeoutInMinutes: 8
|
|
cancelTimeoutInMinutes: 10
|
|
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: |
|
|
# Jira credentials and server
|
|
jira_server=$(JIRA_SERVER)
|
|
jira_username=$(JIRA_USERNAME)
|
|
jira_api_key=$(JIRA_API_KEY)
|
|
|
|
echo "Using Jira server: $jira_server"
|
|
echo "Using Jira username: $jira_username"
|
|
|
|
# Jira card details
|
|
jira_key="CASH"
|
|
jira_card_summary="AUTOMATED REGRESSION RUN RESULTS"
|
|
jira_card_description="This card contains the results of automated regression runs."
|
|
jira_parent_key="CASH-208"
|
|
jira_uat_tester_id="557058:a314fc5b-aed9-4472-90f8-00f106e06207"
|
|
|
|
# Get active sprint with CASH in the name
|
|
echo "Getting active sprint with CASH in the name..."
|
|
sprint_response=$(curl -s -u "$jira_username:$jira_api_key" -X GET "$jira_server/rest/agile/1.0/board/845/sprint?state=active")
|
|
|
|
# Check if response contains an error
|
|
if echo "$sprint_response" | grep -q "\"errorMessages\""; then
|
|
echo "Error retrieving sprints: $(echo $sprint_response | jq -r '.errorMessages[0]')"
|
|
exit 1
|
|
fi
|
|
|
|
active_sprint=$(echo "$sprint_response" | jq -r '.values[] | select(.name | test("CASH"; "i")) | .id')
|
|
|
|
if [ -z "$active_sprint" ]; then
|
|
echo "No active sprint with CASH in the name found. Response was:"
|
|
echo "$sprint_response" | jq '.'
|
|
# Fallback to getting any active sprint
|
|
active_sprint=$(echo "$sprint_response" | jq -r '.values[0].id')
|
|
if [ -z "$active_sprint" ]; then
|
|
echo "No active sprints found at all."
|
|
exit 1
|
|
else
|
|
echo "Using fallback active sprint: $active_sprint"
|
|
fi
|
|
else
|
|
echo "Found active CASH sprint with ID: $active_sprint"
|
|
fi
|
|
|
|
# Check if the card exists in the active sprint with detailed error handling
|
|
echo "Checking for existing card in sprint $active_sprint..."
|
|
|
|
sprint_issues_response=$(curl -s -u "$jira_username:$jira_api_key" -X GET "$jira_server/rest/agile/1.0/sprint/$active_sprint/issue")
|
|
|
|
if echo "$sprint_issues_response" | grep -q "\"errorMessages\""; then
|
|
echo "Error retrieving sprint issues: $(echo $sprint_issues_response | jq -r '.errorMessages[0]')"
|
|
# Fall back to searching for the issue directly
|
|
echo "Falling back to direct issue search..."
|
|
search_response=$(curl -s -u "$jira_username:$jira_api_key" -X GET "$jira_server/rest/api/2/search?jql=project=$jira_key%20AND%20summary~%22$jira_card_summary%22")
|
|
existing_card=$(echo "$search_response" | jq -r '.issues[0].key')
|
|
else
|
|
existing_card=$(echo "$sprint_issues_response" | jq -r ".issues[] | select(.fields.summary == \"$jira_card_summary\") | .key")
|
|
fi
|
|
|
|
echo "Existing card on current sprint: $existing_card"
|
|
|
|
if [ -z "$existing_card" ]; then
|
|
echo "No existing card found. Creating new card..."
|
|
# Create JSON payload for issue creation
|
|
creation_payload='{
|
|
"fields": {
|
|
"project": {
|
|
"key": "'$jira_key'"
|
|
},
|
|
"summary": "'$jira_card_summary'",
|
|
"description": "'$jira_card_description'",
|
|
"issuetype": {
|
|
"name": "Task"
|
|
},
|
|
"parent": {
|
|
"key": "'$jira_parent_key'"
|
|
},
|
|
"customfield_13100": {
|
|
"id": "'$jira_uat_tester_id'"
|
|
}
|
|
}
|
|
}'
|
|
echo "Creation payload: $creation_payload"
|
|
|
|
response=$(curl -s -u "$jira_username:$jira_api_key" \
|
|
-X POST \
|
|
-H "Content-Type: application/json" \
|
|
-d "$creation_payload" \
|
|
"$jira_server/rest/api/2/issue")
|
|
|
|
echo "Card creation response: $response"
|
|
|
|
# Check for errors in the response
|
|
if echo "$response" | grep -q "\"errorMessages\""; then
|
|
echo "Error creating card: $(echo $response | jq -r '.errorMessages[0]')"
|
|
exit 1
|
|
fi
|
|
|
|
new_card=$(echo $response | jq -r '.key')
|
|
|
|
if [ -z "$new_card" ] || [ "$new_card" == "null" ]; then
|
|
echo "Failed to create new card. Response: $response"
|
|
exit 1
|
|
fi
|
|
|
|
card_key=$new_card
|
|
echo "Created new card with key: $card_key"
|
|
|
|
# Move the new card to the active sprint with better error handling
|
|
echo "Moving card to sprint $active_sprint..."
|
|
sprint_move_payload="{\"fields\": {\"customfield_10007\": $active_sprint}}"
|
|
sprint_move_response=$(curl -s -u "$jira_username:$jira_api_key" \
|
|
-X PUT \
|
|
-H "Content-Type: application/json" \
|
|
-d "$sprint_move_payload" \
|
|
"$jira_server/rest/api/2/issue/$card_key")
|
|
|
|
# Check for errors in sprint move response (will be empty if successful)
|
|
if [ ! -z "$sprint_move_response" ] && echo "$sprint_move_response" | grep -q "\"errorMessages\""; then
|
|
echo "Warning: Error moving card to sprint: $(echo $sprint_move_response | jq -r '.errorMessages[0]')"
|
|
echo "Continuing anyway..."
|
|
else
|
|
echo "Card moved to sprint successfully"
|
|
fi
|
|
|
|
# Move the new card to In Test Status with better error handling
|
|
echo "Moving card to In Test status..."
|
|
transition_id="271"
|
|
transition_payload="{\"transition\": {\"id\": $transition_id}}"
|
|
transition_response=$(curl -s -u "$jira_username:$jira_api_key" \
|
|
-X POST \
|
|
-H "Content-Type: application/json" \
|
|
-d "$transition_payload" \
|
|
"$jira_server/rest/api/2/issue/$card_key/transitions")
|
|
|
|
# Check for errors in transition response
|
|
if [ ! -z "$transition_response" ] && echo "$transition_response" | grep -q "\"errorMessages\""; then
|
|
echo "Warning: Error transitioning card: $(echo $transition_response | jq -r '.errorMessages[0]')"
|
|
# Try to get available transitions for debugging
|
|
available_transitions=$(curl -s -u "$jira_username:$jira_api_key" -X GET "$jira_server/rest/api/2/issue/$card_key/transitions")
|
|
echo "Available transitions: $available_transitions"
|
|
echo "Continuing anyway..."
|
|
else
|
|
echo "Card status changed successfully"
|
|
fi
|
|
|
|
else
|
|
card_key=$existing_card
|
|
echo "Using existing card with key: $card_key"
|
|
fi
|
|
|
|
# Get current day of week and numeric date for report name
|
|
current_day=$(date +%A)
|
|
numeric_date=$(date +%m-%d-%Y)
|
|
report_name="ortoni-report-${NODE_ENV}-${current_day}-${numeric_date}.html"
|
|
|
|
# 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) \
|
|
-e REPORT_NAME="$report_name" \
|
|
-e CURRENT_DAY="$current_day" \
|
|
-e NUMERIC_DATE="$numeric_date" \
|
|
-e NODE_ENV=$(NODE_ENV) \
|
|
-e CARD_KEY="$card_key" \
|
|
$(dockerImageName):$(imageTag) \
|
|
bash -c "chmod +x devops/scripts/jira_writeback.sh
|
|
echo \"Moving Playwright reports out of subfolders...\"
|
|
find ./playwright-reports/ -mindepth 2 -type f -exec mv {} ./playwright-reports/ \;
|
|
echo \"Merging reports...\"
|
|
PLAYWRIGHT_JUNIT_OUTPUT_DIR='/app/playwright-tests/artifacts/test-results' PLAYWRIGHT_JUNIT_OUTPUT_NAME='junit_results.xml' npx playwright merge-reports --reporter=ortoni-report,junit ./playwright-reports
|
|
echo \"Contents of ortoni-report:\" && ls ./ortoni-report
|
|
echo 'Current dir: ' && pwd
|
|
echo 'Contents of current dir: ' && ls
|
|
echo 'Contents of /app/playwright-tests/artifacts/test-results' && ls /app/playwright-tests/artifacts/test-results
|
|
|
|
# Rename the report file to include the day and date
|
|
if [ -f /app/ortoni-report/ortoni-report.html ]; then
|
|
mv /app/ortoni-report/ortoni-report.html /app/ortoni-report/\${REPORT_NAME}
|
|
echo \"Renamed report to \${REPORT_NAME}\"
|
|
else
|
|
echo \"ortoni-report.html not found!\"
|
|
fi
|
|
|
|
echo \"Writing report to Jira card '\${CARD_KEY}'...\"
|
|
/app/devops/scripts/jira_writeback.sh add_comment \"\${CARD_KEY}\" /app/ortoni-report/\${REPORT_NAME} \"AUTOMATED TEST RUN: $(date) - \${CURRENT_DAY} (\${NUMERIC_DATE}) - Environment: \${NODE_ENV}\" ")
|
|
|
|
# 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
|
|
mkdir -p $(System.DefaultWorkingDirectory)/test-results
|
|
|
|
# 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/playwright-tests/artifacts/test-results/junit_results.xml $(System.DefaultWorkingDirectory)/test-results
|
|
|
|
# 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: PublishTestResults@2
|
|
displayName: 'Publish test results'
|
|
inputs:
|
|
searchFolder: 'test-results'
|
|
testResultsFormat: 'JUnit'
|
|
testResultsFiles: 'junit_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() |