diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 86f92a38fd..59029c28e2 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -59,6 +59,35 @@ jobs:
- name: Start UI and Test
run: yarn start-server-and-test 'start' http://127.0.0.1:3000 'yarn test:ci'
+ test-visual-regression:
+ name: "Visual Regression Test"
+ runs-on: ubuntu-latest
+ needs: [build, check-files]
+ if: needs.check-files.outputs.run_tests == 'true' && github.event.pull_request.draft == false
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Install node_modules
+ uses: OffchainLabs/actions/node-modules/install@main
+
+ - name: Restore build artifacts
+ uses: ./.github/actions/restore-build-artifacts
+
+ - name: Install Playwright browsers
+ run: yarn workspace arb-token-bridge-ui playwright install --with-deps
+
+ - name: Run visual regression tests
+ run: yarn start-server-and-test "yarn workspace arb-token-bridge-ui start" http://127.0.0.1:3000 "yarn workspace arb-token-bridge-ui test:widget-snapshot"
+
+ - name: Upload Playwright report in case of failure
+ if: failure()
+ uses: actions/upload-artifact@v4
+ with:
+ name: playwright-report
+ path: packages/arb-token-bridge-ui/playwright-report/
+ retention-days: 5
+
audit:
name: "Audit"
runs-on: ubuntu-latest
diff --git a/package.json b/package.json
index f627f40830..7ba52f5088 100644
--- a/package.json
+++ b/package.json
@@ -11,6 +11,7 @@
"start": "yarn workspace arb-token-bridge-ui start",
"audit:ci": "audit-ci --config ./audit-ci.jsonc",
"test:ci": "yarn workspace arb-token-bridge-ui test:ci",
+ "test:widget-snapshot": "yarn workspace arb-token-bridge-ui test:widget-snapshot",
"prettier:check": "./node_modules/.bin/prettier --check .",
"prettier:format": "./node_modules/.bin/prettier --write .",
"lint": "yarn workspace arb-token-bridge-ui lint",
diff --git a/packages/arb-token-bridge-ui/.gitignore b/packages/arb-token-bridge-ui/.gitignore
index c11e5a25db..242fc60f19 100644
--- a/packages/arb-token-bridge-ui/.gitignore
+++ b/packages/arb-token-bridge-ui/.gitignore
@@ -40,3 +40,7 @@ yarn-error.log*
# Next.js
.next
next-env.d.ts
+
+# Test results
+/test-results/
+/playwright-report/
\ No newline at end of file
diff --git a/packages/arb-token-bridge-ui/package.json b/packages/arb-token-bridge-ui/package.json
index 4957500790..af625255cf 100644
--- a/packages/arb-token-bridge-ui/package.json
+++ b/packages/arb-token-bridge-ui/package.json
@@ -62,6 +62,7 @@
"start": "next start",
"test": "vitest --config vitest.config.ts --watch",
"test:ci": "vitest --config vitest.config.ts --run",
+ "test:widget-snapshot": "yarn playwright test src/components/Widget/__tests__/widget-visual-regression.spec.ts",
"lint": "tsc && eslint",
"lint:fix": "tsc && eslint --quiet --fix",
"prettier:format": "prettier --config-precedence file-override --write \"src/**/*.{tsx,ts,scss,md,json}\"",
@@ -91,6 +92,7 @@
"@eslint/eslintrc": "^3.3.1",
"@eslint/js": "^9.26.0",
"@next/eslint-plugin-next": "^15.3.2",
+ "@playwright/test": "^1.45.3",
"@synthetixio/synpress": "3.7.3",
"@testing-library/react": "^16.3.0",
"@types/lodash-es": "^4.17.12",
@@ -128,6 +130,7 @@
"typescript": "^5.2.2",
"typescript-eslint": "^8.32.1",
"vitest": "^3.1.1",
+ "wait-on": "^7.2.0",
"yargs": "^18.0.0"
}
}
diff --git a/packages/arb-token-bridge-ui/src/components/Widget/WidgetTransferPanel.tsx b/packages/arb-token-bridge-ui/src/components/Widget/WidgetTransferPanel.tsx
index 971e5f3e85..8116545704 100644
--- a/packages/arb-token-bridge-ui/src/components/Widget/WidgetTransferPanel.tsx
+++ b/packages/arb-token-bridge-ui/src/components/Widget/WidgetTransferPanel.tsx
@@ -43,7 +43,7 @@ export function WidgetTransferPanel({
<>