Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 12 additions & 36 deletions .github/workflows/e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,19 @@ jobs:
timeout-minutes: 60
runs-on: ubuntu-latest
container:
image: docker://doronbancor/playwright-imagemagick:latest # Updated to use your Docker image
image: docker://doronbancor/playwright-imagemagick:1.43.1 # Updated to use your Docker image
options: --platform linux/amd64 # Specify platform
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2 # Fetch the last 2 commits for comparison

- uses: actions/setup-node@v4
with:
node-version: 20

- name: Install build-essential
run: apt-get update && apt-get install -y build-essential

- name: Install dependencies
run: yarn

- name: Install Playwright browsers and run Playwright tests
- name: Run e2e tests
run: yarn e2e
env:
TENDERLY_ACCOUNT: bancor
Expand All @@ -41,37 +36,19 @@ jobs:
path: playwright-report/
retention-days: 3

- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: screenshots
path: e2e/screenshots
retention-days: 3

commit-screenshots:
name: 'Commit Screenshots'
needs: e2e
runs-on: ubuntu-latest
if: github.event.pull_request.draft == false && github.base_ref == 'main' && !startsWith(github.event.head_commit.message, '[CI]')
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2 # Ensure the last 2 commits are fetched for diff

- uses: actions/download-artifact@master
with:
name: screenshots
path: e2e/screenshots
- name: Configure safe directory
run: |
git config --global --add safe.directory "${GITHUB_WORKSPACE}"

- name: Compare Modified Screenshots
if: github.event.pull_request.draft == false && github.base_ref == 'main' && !startsWith(github.event.head_commit.message, '[CI]')
id: compare-screenshots
run: |
chmod +x $GITHUB_WORKSPACE/scripts/compare_screenshots.sh # Add execute permissions
$GITHUB_WORKSPACE/scripts/compare_screenshots.sh # Execute the script

- name: Import GPG key
if: github.event.pull_request.draft == false && github.base_ref == 'main' && !startsWith(github.event.head_commit.message, '[CI]')
id: import-gpg
uses: crazy-max/ghaction-import-gpg@v6
with:
Expand All @@ -81,12 +58,11 @@ jobs:
git_commit_gpgsign: true

- name: Commit changes
if: github.event.pull_request.draft == false && github.base_ref == 'main' && !startsWith(github.event.head_commit.message, '[CI]')
uses: stefanzweifel/git-auto-commit-action@v5
with:
commit_message: '[CI] Update Screenshots'
commit_user_name: ${{ steps.import-gpg.outputs.name }}
commit_user_email: ${{ steps.import-gpg.outputs.email }}

- uses: geekyeggo/delete-artifact@v5
with:
name: screenshots
skip_fetch: true
skip_checkout: true
19 changes: 12 additions & 7 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
# Use the official Playwright Docker image as a base
FROM mcr.microsoft.com/playwright:v1.43.0-jammy
FROM mcr.microsoft.com/playwright:v1.43.1-jammy

# Install ImageMagick
RUN apt-get update && apt-get install -y imagemagick
# Install extra packages
RUN apt-get update && apt-get install -y \
imagemagick \
build-essential \
# Add more if you need them
&& rm -rf /var/lib/apt/lists/*

# Clean up
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
# (Optional) Install Node 20 if needed
# RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
# && apt-get install -y nodejs

# Display installed versions
RUN identify -version
# Debug: confirm versions
RUN node --version && npx playwright --version && identify -version
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
"@ethersproject/bytes": "^5.0.0",
"@ethersproject/providers": "^5.7.1",
"@floating-ui/react": "^0.25.4",
"@playwright/test": "^1.43.1",
"@sentry/react": "^8.17.0",
"@sentry/vite-plugin": "^2.21.1",
"@tanstack/react-query": "^5.40.1",
Expand Down Expand Up @@ -101,8 +100,8 @@
"pretest": "yarn compile-abis",
"test": "vitest run --mode production",
"coverage": "yarn test --coverage",
"pree2e": "yarn playwright install --with-deps chromium",
"e2e": "playwright test",
"e2e:local": "yarn playwright install --with-deps chromium && yarn e2e",
"lint": "eslint --ext .tsx,.ts .",
"pre-commit": "yarn lint-staged",
"e2e:report": "npx playwright show-report e2e/playwright-report",
Expand All @@ -127,6 +126,7 @@
]
},
"devDependencies": {
"@playwright/test": "1.43.1",
"@types/d3": "^7.4.3",
"vite-bundle-analyzer": "^0.15.2"
},
Expand Down
111 changes: 92 additions & 19 deletions scripts/compare_screenshots.sh
Original file line number Diff line number Diff line change
@@ -1,26 +1,91 @@
#!/bin/bash
#
# This script compares modified screenshots to their baseline versions and reverts
# the file if the visual difference is negligible. We now ignore isolated single-pixel
# differences by using a morphological operation on the difference mask.

set -e
set -o pipefail

# Function to compare images
# Function to compare images while ignoring single-pixel isolated differences.
# Returns 0 (success) if differences are within acceptable threshold, 1 (failure) otherwise.
compare_images() {
local img1="$1"
local img2="$2"
local diff_img="$3"

# Use ImageMagick compare with AE metric to count different pixels
local diff_pixels
diff_pixels=$(compare -metric AE "$img1" "$img2" "$diff_img" 2>&1 >/dev/null)
# This file will be our initial black/white difference mask (white = difference).
local diff_mask_raw="${diff_img%.png}.rawmask.png"

# This file will be the mask after morphological "open" (which removes isolated pixels).
local diff_mask_clean="${diff_img%.png}.cleanmask.png"

echo "[DEBUG] Comparing '$img1' vs '$img2' and ignoring isolated diffs."

# -----------------------------------------------------------
# 1. Create a black/white difference mask:
# -highlight-color White => areas that differ become white
# -lowlight-color Black => areas that match remain black
# -----------------------------------------------------------
echo "[DEBUG] Generating raw difference mask '$diff_mask_raw'..."
compare -quiet \
-fuzz 0% \
-highlight-color White \
-lowlight-color Black \
"$img1" "$img2" \
"$diff_mask_raw" || true
# '|| true' so that 'compare' doesn't break the script if images differ.

# -----------------------------------------------------------
# 2. Remove single-pixel noise using morphological 'Open':
# This will eliminate any isolated white pixel (i.e., an
# isolated difference) in the mask.
# -----------------------------------------------------------
echo "[DEBUG] Applying morphological open to remove isolated white pixels..."
convert "$diff_mask_raw" -morphology Open Diamond "$diff_mask_clean"

echo "diff pixels for $img1, $img2: $diff_pixels"
# -----------------------------------------------------------
# 3. Count the number of white pixels in the cleaned mask.
# - %[fx:mean] gives the average brightness of the image
# in the range [0..1].
# - Multiply by w*h to get total white pixels (float).
# - Convert that float to an integer.
# -----------------------------------------------------------
local pixel_diff_float
pixel_diff_float=$(convert "$diff_mask_clean" -format "%[fx:mean*w*h]" info:)

# Check if the number of different pixels is less than 11
if [ "$diff_pixels" -lt 11 ]; then
return 0 # Images are considered identical
# Convert floating-point value to integer (rounded to nearest whole number).
local pixel_diff_count
pixel_diff_count=$(printf "%.0f" "$pixel_diff_float")

echo "[DEBUG] Number of differing pixels after cleaning: $pixel_diff_count"

# -----------------------------------------------------------
# 4. Decide if the difference is acceptable.
# You can change the threshold (10) as needed.
# -----------------------------------------------------------
local threshold=10
if [ "$pixel_diff_count" -lt "$threshold" ]; then
echo "[DEBUG] Differences ($pixel_diff_count) are under threshold ($threshold)."
# Save the final cleaned mask as the "diff image" for reference.
mv "$diff_mask_clean" "$diff_img"
# Remove intermediate file
rm -f "$diff_mask_raw"
return 0 # Images are considered "identical enough".
else
return 1 # Images are different
echo "[DEBUG] Differences ($pixel_diff_count) exceed threshold ($threshold)."
# Keep the final cleaned mask as the "diff image".
mv "$diff_mask_clean" "$diff_img"
# Remove intermediate file
rm -f "$diff_mask_raw"
return 1 # Images are considered different.
fi
}

# ------------------------------------------------------------------------------
# Main script
# ------------------------------------------------------------------------------

# Check if GITHUB_WORKSPACE is set
if [ -z "$GITHUB_WORKSPACE" ]; then
echo "Error: GITHUB_WORKSPACE is not set."
Expand All @@ -30,8 +95,8 @@ fi
# Directory where screenshots are stored
SCREENSHOT_DIR="${GITHUB_WORKSPACE}/e2e/screenshots"

# Get a list of modified screenshots
modified_files=$(git diff --name-only | grep '.png$' || true)
# Get a list of modified screenshots (relative to the last commit)
modified_files=$(git -C "${GITHUB_WORKSPACE}" diff --name-only | grep '.png$' || true)

# Check if any modified files are found
if [[ -z "$modified_files" ]]; then
Expand All @@ -45,32 +110,40 @@ for screenshot in $modified_files; do
current_screenshot="${GITHUB_WORKSPACE}/${screenshot}"

# Retrieve the original version of the file from the previous commit
git show HEAD~1:"$screenshot" > original_screenshot.png
git show HEAD~1:"$screenshot" > original_screenshot.png 2>/dev/null || true
baseline_screenshot="original_screenshot.png"

# Check if the baseline screenshot exists
# Check if the baseline screenshot exists (i.e., wasn't newly added)
if [[ ! -s "$baseline_screenshot" ]]; then
echo "No baseline image for $screenshot. Assuming this is a new screenshot."
rm -f "$baseline_screenshot" # Clean up the non-existent baseline file
rm -f "$baseline_screenshot" # Clean up
continue # Skip to the next iteration
fi

# Compare with the baseline version
diff_file="${current_screenshot}.diff.png"
# Temporarily disable 'set -e' to handle non-zero exit status

echo ""
echo "----------------------------------------------------------"
echo "Comparing screenshot: $screenshot"
echo "Baseline: $baseline_screenshot"
echo "Current: $current_screenshot"
echo "----------------------------------------------------------"

# Temporarily disable 'set -e' so we can capture the compare_images return code
set +e
compare_images "$baseline_screenshot" "$current_screenshot" "$diff_file"
comparison_result=$?
set -e

# If images are identical, revert the screenshot
# If images are "identical enough," revert the screenshot
if [ $comparison_result -eq 0 ]; then
echo "No visual difference for $screenshot. Reverting changes."
echo "[INFO] $screenshot: No significant visual difference. Reverting changes."
git restore "$screenshot"
else
echo "Visual difference detected for $screenshot. Keeping changes."
echo "[INFO] $screenshot: Visual difference detected above threshold. Keeping changes."
fi

# Clean up temporary files
rm -f "$diff_file" "$baseline_screenshot"
rm -f "$baseline_screenshot" "$diff_file"
done
2 changes: 1 addition & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2853,7 +2853,7 @@
resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==

"@playwright/test@^1.43.1":
"@playwright/test@1.43.1":
version "1.43.1"
resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.43.1.tgz#16728a59eb8ce0f60472f98d8886d6cab0fa3e42"
integrity sha512-HgtQzFgNEEo4TE22K/X7sYTYNqEMMTZmFS8kTq6m8hXj+m1D8TgwgIbumHddJa9h4yl4GkKb8/bgAl2+g7eDgA==
Expand Down