Skip to content

Comments

chore: Refactors visual tests setup#393

Merged
pan-kot merged 1 commit intomainfrom
refactor-visual-tests
Feb 11, 2026
Merged

chore: Refactors visual tests setup#393
pan-kot merged 1 commit intomainfrom
refactor-visual-tests

Conversation

@pan-kot
Copy link
Member

@pan-kot pan-kot commented Feb 10, 2026

Description

The visual tests are refactored for more code reuse between different scenarios so that optimisations for less flakiness can be applied to all tests.

Rel: D383236509

Similar: cloudscape-design/chart-components#163

How has this been tested?

I tested that by running visual refresh tests locally (npm run test:visual). The first run generates screenshots - the second one generates new screenshots and compares them to ones generated previously.

Note: the Visual Regressions action is expected to fail in this PR. I expect it to work and produce less flakiness in future PRs to charts. I will experiment with that more once this PR is merged.

Review checklist

The following items are to be evaluated by the author(s) and the reviewer(s).

Correctness

  • Changes include appropriate documentation updates.
  • Changes are backward-compatible if not indicated, see CONTRIBUTING.md.
  • Changes do not include unsupported browser features, see CONTRIBUTING.md.
  • Changes were manually tested for accessibility, see accessibility guidelines.

Security

Testing

  • Changes are covered with new/existing unit tests?
  • Changes are covered with new/existing integration tests?

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@codecov
Copy link

codecov bot commented Feb 10, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.11%. Comparing base (6cae59e) to head (1ec355a).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #393      +/-   ##
==========================================
- Coverage   95.54%   95.11%   -0.43%     
==========================================
  Files          67       67              
  Lines        3278     3278              
  Branches      706      702       -4     
==========================================
- Hits         3132     3118      -14     
- Misses        146      160      +14     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

await page.keys(["Enter"]);
await page.keys(["ArrowLeft"]);
expect(await page.fullPageScreenshot()).toMatchImageSnapshot();
for (let i = 1; i <= 3; i++) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before my changes, we could call toMatchImageSnapshot() within the same test multiple times. The snapshots would then be stored with a suffix like -2 and -3 for the subsequent calls.

However, the counter is also added when the tests are retried with vitest retry configuration - which contradicts the idea of the retries. To mitigate that, I updated the generated snapshot names and removed the counter from there. Now, there must be a single snapshot taken per test.

return `/#${page}?${urlParams.toString()}`;
}

const ignoredPages = new Set([
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before my change, we run tests on all pages with .screenshot-area - which actually missed some useful pages, as the screenshot area is not really a requirement for the full-page screenshots. The updated config captures all pages except those where it does not make sense.

.map((page) => "/" + path.relative("../../pages/", page))
.filter((page) => !ignoredPages.has(page));

const rtlStaticPages = ["/dnd/engine-a2h-test", "/with-app-layout/integ"];
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is new. Previously only lrt direction was covered.


const toMatchImageSnapshot = configureToMatchImageSnapshot({
customSnapshotsDir: snapshotDir,
customSnapshotIdentifier: ({ currentTestName }) => currentTestName.replace("/#/", "").replace(/[\s]/g, "-"),
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this makes generated snapshots better organised (with folders) and removes the counter from the name, which is affected by retries config.

@pan-kot pan-kot marked this pull request as ready for review February 10, 2026 12:37
@pan-kot pan-kot requested a review from a team as a code owner February 10, 2026 12:37
@pan-kot pan-kot requested review from Who-is-PS and removed request for a team February 10, 2026 12:37
Copy link
Member

@Who-is-PS Who-is-PS left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor suggestion: Consider extracting the timing values into named constants for better readability and easier tuning. What do you think about this?

await this.browser.execute((target) => {
(document.querySelector(target) as HTMLButtonElement)!.focus();
}, selector);
await this.browser.keys(["ArrowDown"]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was ArrowDown added to focus()? Is this intentional or a mistake?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there was a bug with that focus outline that got fixed but w/o updating the tests. The focus outline is expected to be shown only when the last user interaction was keyboard-based. Calling the ".focus()" is artificial and it does not satisfy the criteria (the focus outline would be shown if we focus the handles with Tab navigation, for instance).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, makes sense, triggers :focus-visible styling. Thanks for the clarification!

"dev": true,
"license": "MIT"
},
"node_modules/react-keyed-flatten-children": {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

react-keyed-flatten-children was added but doesn't appear used in these changes. Could be unrelated or needed elsewhere? Could you please explain.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This came from installing dependencies (npm install) - and is likely due to changes in the components dependency.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, transitive dependency. Thanks!

await browser.url(url);
const page = new DndPageObject(browser);
await page.waitForVisible("main");
await page.waitForJsTimers(500);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you test it with a lower number? This could cause more delay per test

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I selected a rather large number in an attempt to make the flakiness minimal. It does affect the completion time of the visual regression CI action - but this time is still lower than the other actions, so it is fine to have it like that. It is also easily reversible if the visual regression tests running time will ever be a problem.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough, makes sense prioritizing stability over speed. Thanks for the explanation!


async fullPageScreenshot() {
// Necessary for animations to complete.
await this.pause(200);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The original value was 100ms, is the increase to 200ms necessary? With many screenshots, this doubles the wait time per test.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doubles the waiting time before interactions but it is still a small increase to the total execution time of each test, where the largest portion is setting up the test session. I am not sure if this particular increase makes a real difference, but it might have some effect since the most of flakiness is now observed in the dynamic tests (those where we trigger some actions before taking a screenshot).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, thanks.

@pan-kot
Copy link
Member Author

pan-kot commented Feb 11, 2026

Minor suggestion: Consider extracting the timing values into named constants for better readability and easier tuning. What do you think about this?

TBH, I think this is not very practical here, as there is no need to reuse them and there is no added benefit of giving these values names: the values are based on practical experiments rather than explicit constraints (such as matching certain timeouts present in the feature implementation).

@pan-kot pan-kot added this pull request to the merge queue Feb 11, 2026
Merged via the queue into main with commit a1466f0 Feb 11, 2026
81 of 83 checks passed
@pan-kot pan-kot deleted the refactor-visual-tests branch February 11, 2026 17:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants