chore: migrate `@rocket.chat/visual-regression` from Fuselage (#42759) · RocketChat/Rocket.Chat@bec3ea0 · GitHub
Skip to content

Commit bec3ea0

Browse files
authored
chore: migrate @rocket.chat/visual-regression from Fuselage (#42759)
1 parent 16badb0 commit bec3ea0

7 files changed

Lines changed: 236 additions & 0 deletions

File tree

Lines changed: 55 additions & 0 deletions
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"name": "@rocket.chat/visual-regression",
3+
"version": "0.0.1",
4+
"private": true,
5+
"type": "module",
6+
"bin": "./bin/index.js",
7+
"scripts": {
8+
"lint": "eslint .",
9+
"lint:fix": "eslint --fix .",
10+
"typecheck": "tsc --noEmit"
11+
},
12+
"dependencies": {
13+
"@playwright/test": "~1.52.0"
14+
},
15+
"devDependencies": {
16+
"@rocket.chat/tsconfig": "workspace:*",
17+
"@types/node": "~24.13.6",
18+
"eslint": "~10.12.0",
19+
"typescript": "~5.9.3"
20+
},
21+
"volta": {
22+
"extends": "../../package.json"
23+
}
24+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import path from 'path';
2+
import { fileURLToPath } from 'url';
3+
4+
import { defineConfig, devices } from '@playwright/test';
5+
6+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
7+
8+
// The directory of the consuming package (i.e. where playwright is invoked from)
9+
const packageDir = process.env.PACKAGE_DIR ?? process.cwd();
10+
11+
const BASE_URL = process.env.TEST_BASE_URL || 'http://localhost:6006';
12+
13+
export default defineConfig({
14+
testDir: path.join(__dirname, 'test'),
15+
fullyParallel: true,
16+
workers: process.env.CI ? 2 : 4,
17+
snapshotPathTemplate: path.join(packageDir, 'test/snapshots/{arg}-{projectName}.png'),
18+
outputDir: path.join(packageDir, 'test-results'),
19+
reporter: process.env.CI ? 'html' : 'dot',
20+
use: {
21+
baseURL: BASE_URL,
22+
},
23+
projects: [
24+
{
25+
name: 'desktop',
26+
use: {
27+
...devices['Desktop Chrome'],
28+
launchOptions: {
29+
args: [
30+
'--disable-lcd-text',
31+
'--font-render-hinting=none',
32+
'--disable-skia-runtime-opts',
33+
'--disable-font-subpixel-positioning',
34+
'--disable-accelerated-2d-canvas',
35+
'--disable-gpu',
36+
],
37+
},
38+
},
39+
},
40+
],
41+
});
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#!/bin/bash
2+
set -e
3+
4+
# Script to run Playwright visual regression tests in Docker.
5+
# Storybook should be running on the host system at port 6006.
6+
#
7+
# Environment variables (set by bin/index.js):
8+
# PACKAGE_DIR - absolute path to the consuming package (e.g. /repo/packages/fuselage)
9+
10+
PACKAGE_DIR="${PACKAGE_DIR:-$(pwd)}"
11+
12+
# Derive monorepo root from git
13+
MONOREPO_ROOT="$(git -C "${PACKAGE_DIR}" rev-parse --show-toplevel)"
14+
15+
# Relative path of consuming package inside the monorepo (e.g. packages/fuselage)
16+
REL_PACKAGE_PATH="$(node -e 'console.log(require("path").relative(process.argv[1], process.argv[2]))' "${MONOREPO_ROOT}" "${PACKAGE_DIR}")"
17+
18+
TOOL_DIR="$(cd "$(dirname "$0")/.." && pwd)"
19+
REL_TOOL_PATH="$(node -e 'console.log(require("path").relative(process.argv[1], process.argv[2]))' "${MONOREPO_ROOT}" "${TOOL_DIR}")"
20+
21+
BASE_URL="http://host.docker.internal:6006"
22+
23+
# Check if update-snapshots flag is passed
24+
UPDATE_SNAPSHOTS=""
25+
case "$*" in
26+
*--update-snapshots*) UPDATE_SNAPSHOTS="--update-snapshots" ;;
27+
esac
28+
29+
# Read the Playwright version from this tool's package.json.
30+
PLAYWRIGHT_VERSION="$(node -e 'console.log(require(process.argv[1]).dependencies["@playwright/test"].replace(/^[^0-9]*/, ""))' "${TOOL_DIR}/package.json")"
31+
32+
DOCKER_PW_IMAGE="mcr.microsoft.com/playwright:v${PLAYWRIGHT_VERSION}-noble"
33+
34+
echo "Running Playwright tests in Docker container for ${REL_PACKAGE_PATH} with env:"
35+
echo "PACKAGE_DIR: ${PACKAGE_DIR}"
36+
echo "MONOREPO_ROOT: ${MONOREPO_ROOT}"
37+
echo "REL_PACKAGE_PATH: ${REL_PACKAGE_PATH}"
38+
echo "TEST_BASE_URL: ${BASE_URL}"
39+
echo "CI: ${CI:-false}"
40+
echo "UPDATE_SNAPSHOTS: ${UPDATE_SNAPSHOTS}"
41+
echo "DOCKER_PW_IMAGE: ${DOCKER_PW_IMAGE}"
42+
43+
docker run --rm \
44+
--init \
45+
--ipc=host \
46+
--add-host=host.docker.internal:host-gateway \
47+
-e TEST_BASE_URL="${BASE_URL}" \
48+
-e CI \
49+
-e PACKAGE_DIR="/app/${REL_PACKAGE_PATH}" \
50+
-v "${MONOREPO_ROOT}:/app" \
51+
-w "/app/${REL_PACKAGE_PATH}" \
52+
"${DOCKER_PW_IMAGE}" \
53+
npx -y playwright@${PLAYWRIGHT_VERSION} test --config="/app/${REL_TOOL_PATH}/playwright.config.ts" ${UPDATE_SNAPSHOTS}
54+
55+
echo "Playwright tests completed!"
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import fs from 'fs';
2+
import path from 'path';
3+
4+
import { expect, test } from '@playwright/test';
5+
6+
const packageDir = process.env.PACKAGE_DIR ?? process.cwd();
7+
8+
const storybookStaticDir = path.join(packageDir, 'storybook-static') ?? path.join(process.cwd(), 'storybook-static');
9+
10+
const storybook = JSON.parse(fs.readFileSync(path.join(storybookStaticDir, 'index.json'), 'utf-8'));
11+
12+
// Only run tests on stories, not other documentation pages.
13+
const stories = Object.values(storybook.entries).filter((e: any) => e.type === 'story');
14+
15+
for (const story of stories as any[]) {
16+
test(`${story.title} ${story.name} should not have visual regressions`, async ({ page }) => {
17+
const params = new URLSearchParams({
18+
id: story.id,
19+
viewMode: 'story',
20+
});
21+
22+
await page.goto(`/iframe.html?${params.toString()}`, {
23+
waitUntil: 'domcontentloaded',
24+
});
25+
26+
await page.evaluate(() => document.fonts.ready);
27+
28+
const storybookRoot = page.locator('#storybook-root');
29+
await storybookRoot.waitFor({ state: 'visible' });
30+
31+
await expect(page).toHaveScreenshot(`${story.id}.png`, {
32+
fullPage: true,
33+
animations: 'disabled',
34+
});
35+
});
36+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"extends": "@rocket.chat/tsconfig/base.json",
3+
"compilerOptions": {
4+
"target": "ES2024",
5+
"module": "nodenext",
6+
"moduleResolution": "nodenext",
7+
"noEmit": true
8+
},
9+
"include": ["playwright.config.ts", "test"],
10+
"exclude": ["node_modules"]
11+
}

‎yarn.lock‎

Lines changed: 14 additions & 0 deletions

0 commit comments

Comments
 (0)