Skip to content

Commit 2f613d1

Browse files
kyle-ssgclaude
andauthored
refactor: Remove unused scss (#7194)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent bb24248 commit 2f613d1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+154
-1405
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Visual Regression Test Runner
2+
3+
Run local visual regression tests by capturing baselines from main on this machine, then comparing against the current branch. Both runs use the same OS and browser, so diffs reflect actual style changes rather than platform rendering differences.
4+
5+
## Prerequisites
6+
7+
- Docker running with Flagsmith services on localhost:8000
8+
9+
## Workflow
10+
11+
1. Capture local baselines from main (stashes changes, checks out main, runs E2E, switches back):
12+
13+
```bash
14+
npm run test:visual:baselines
15+
```
16+
17+
2. Run E2E tests on the current branch with visual regression screenshot capture:
18+
19+
```bash
20+
VISUAL_REGRESSION=1 npm run test
21+
```
22+
23+
3. Compare captured screenshots against local baselines:
24+
25+
```bash
26+
npm run test:visual:compare
27+
```
28+
29+
4. If there are failures, open the HTML report for visual diff inspection:
30+
31+
```bash
32+
npm run test:visual:report
33+
```
34+
35+
5. Report results: how many comparisons passed/failed, and whether failures are style/layout regressions or data differences.

frontend/README.md

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -149,20 +149,26 @@ E2E_RETRIES=0 SKIP_BUNDLE=1 E2E_CONCURRENCY=1 npm run test -- tests/flag-tests.p
149149

150150
Visual regression screenshots are captured during E2E tests via `visualSnapshot()` calls. They are a no-op unless `VISUAL_REGRESSION=1` is set. Comparison runs as a separate step after all E2E retries complete, so flaky tests don't affect the report.
151151

152+
##### Local development
153+
154+
To check for visual regressions locally, capture baselines from main on your machine then compare against your branch. Both runs use the same OS and browser, so diffs reflect actual style changes.
155+
152156
```bash
153-
# 1. Run E2E tests with screenshot capture (with retries)
154-
VISUAL_REGRESSION=1 npm run test
157+
# 1. Capture baselines from main (stashes changes, checks out main, runs E2E, switches back)
158+
npm run test:visual:baselines
155159
156-
# 2a. Generate/update baselines from captured screenshots
157-
npm run test:visual:compare -- --update-snapshots
160+
# 2. Run E2E tests on your branch with screenshot capture
161+
VISUAL_REGRESSION=1 npm run test
158162
159-
# 2b. Compare screenshots against baselines (generates Playwright report with diffs)
163+
# 3. Compare screenshots against baselines (generates Playwright report with diffs)
160164
npm run test:visual:compare
161165
162-
# 3. Open the report
166+
# 4. Open the report
163167
npm run test:visual:report
164168
```
165169

170+
##### CI
171+
166172
Visual diffs never fail CI — they are reported via PR comment and the Playwright HTML report.
167173

168174
Screenshots are saved to `e2e/visual-regression-screenshots/`, baselines to `e2e/visual-regression-snapshots/` (both git-ignored). In CI, the main branch uploads screenshots as baseline artifacts, and PRs download them for comparison.
@@ -181,3 +187,5 @@ When using Claude Code, these commands are available for e2e testing:
181187
- `/e2e-create [description]` - Create a new test following existing patterns
182188

183189
The optional `[N]` argument sets `E2E_REPEAT` to run tests N additional times after passing (defaults to 0). E.g., `/e2e 5` runs tests, then repeats 5 more times to detect flakiness.
190+
191+
- `/visual-regression` - Download CI baselines, run E2E with screenshot capture, compare and report

frontend/e2e/capture-baselines.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { execSync } from 'child_process'
2+
import * as fs from 'fs'
3+
import * as path from 'path'
4+
5+
const SNAPSHOTS_DIR = path.resolve(__dirname, 'visual-regression-snapshots')
6+
const SCREENSHOTS_DIR = path.resolve(__dirname, 'visual-regression-screenshots')
7+
8+
function run(cmd: string) {
9+
execSync(cmd, { stdio: 'inherit' })
10+
}
11+
12+
function runQuiet(cmd: string) {
13+
execSync(cmd, { stdio: 'pipe' })
14+
}
15+
16+
const branch = execSync('git rev-parse --abbrev-ref HEAD', { encoding: 'utf-8' }).trim()
17+
18+
console.log(`Current branch: ${branch}`)
19+
console.log('Checking out main source code (keeping branch e2e tests)...')
20+
21+
// Only checkout main's source code, not e2e/ test files.
22+
// This ensures both baseline and branch runs use the same test code.
23+
runQuiet('git checkout main -- web/ common/')
24+
25+
try {
26+
console.log('Running E2E on main source with VISUAL_REGRESSION=1...')
27+
if (fs.existsSync(SCREENSHOTS_DIR)) {
28+
fs.rmSync(SCREENSHOTS_DIR, { recursive: true })
29+
}
30+
run('cross-env VISUAL_REGRESSION=1 npm run test')
31+
32+
console.log('Copying screenshots to baselines...')
33+
if (fs.existsSync(SNAPSHOTS_DIR)) {
34+
fs.rmSync(SNAPSHOTS_DIR, { recursive: true })
35+
}
36+
fs.cpSync(SCREENSHOTS_DIR, SNAPSHOTS_DIR, { recursive: true })
37+
38+
const count = fs.readdirSync(SNAPSHOTS_DIR).filter((f) => f.endsWith('.png')).length
39+
console.log(`Captured ${count} baseline snapshots`)
40+
} finally {
41+
// Restore branch's source code
42+
console.log('Restoring branch source code...')
43+
runQuiet('git checkout -- web/ common/')
44+
}
45+
46+
console.log('Baselines ready. Now run: VISUAL_REGRESSION=1 npm run test && npm run test:visual:compare')

frontend/e2e/tests/roles-test.pw.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@ test.describe('Roles Tests', () => {
1919
login,
2020
logout,
2121
waitForElementVisible,
22+
waitForToastsToClear,
2223
} = createHelpers(page);
2324

2425
const rolesProject = 'project-my-test-project-7-role'
2526
log('Login')
2627
await login(E2E_USER, PASSWORD)
2728
await click(byId(rolesProject))
2829
await createFeature({ name: 'test_feature', value: false })
30+
await waitForToastsToClear()
2931
log('Go to Roles')
3032
await click(byId('organisation-link'))
3133
await click(byId('users-and-permissions'))

frontend/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"test:unit:watch": "jest --watch",
1919
"test:unit:coverage": "jest --coverage",
2020
"test:visual": "cross-env VISUAL_REGRESSION=1 npx playwright test",
21+
"test:visual:baselines": "npx tsx e2e/capture-baselines.ts",
2122
"test:visual:compare": "npx tsx e2e/compare-visual-regression.ts && npx playwright test -c playwright.visual.config.ts",
2223
"test:visual:report": "npx playwright show-report e2e/visual-regression-report",
2324
"test:report": "npx playwright show-report e2e/playwright-report",

frontend/web/components/ActionButton.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ const ActionButton: FC<ActionButtonType> = ({
2424
onClick()
2525
}}
2626
>
27-
<div className='pointer-events-none'>
27+
<div className='pe-none'>
2828
<Icon name='more-vertical' width={16} fill='#656D7B' />
2929
</div>
3030
</Button>

frontend/web/components/DateSelect.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const DateSelect: FC<DateSelectProps> = ({
2727
const [isOpen, setIsOpen] = useState(false)
2828

2929
return (
30-
<Flex style={{ position: 'relative' }}>
30+
<Flex className='position-relative'>
3131
<DatePicker
3232
className={`${className} ${!isValid && touched ? 'invalid' : ''}`}
3333
dateFormat={dateFormat}

frontend/web/components/ExternalResourcesTable.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ const ExternalResourceRow: FC<ExternalResourceRowType> = ({
4141
}, [isDeleted])
4242
return (
4343
<Row className='list-item' key={externalResource?.id}>
44-
<div className='table-column text-left' style={{ width: '100px' }}>
44+
<div className='table-column text-start' style={{ width: '100px' }}>
4545
<div className='font-weight-medium mb-1'>
4646
{
4747
Constants.resourceTypes[

frontend/web/components/IdentitySelect.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ const IdentitySelect: FC<IdentitySelectType> = ({
4949
.slice(0, 10)
5050
}, [ignoreIds, data])
5151
return (
52-
<Flex className='text-left'>
52+
<Flex className='text-start'>
5353
<Select
5454
onInputChange={(e: InputEvent) => {
5555
searchItems(Utils.safeParseEventValue(e))

frontend/web/components/InlineModal.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ const InlineModal: FC<InlineModalProps> = ({
5151
})
5252

5353
return (
54-
<div className={relativeToParent ? '' : 'relative'}>
54+
<div className={relativeToParent ? '' : 'position-relative'}>
5555
{isOpen && (
5656
<div ref={modalRef} className={classNames('inline-modal', className)}>
5757
<div className='d-flex py-2 d-lg-none justify-content-end px-4'>

0 commit comments

Comments
 (0)