dynamic content Archives - AI-Powered End-to-End Testing | Applitools https://app14743.cloudwayssites.com/blog/tag/dynamic-content/ Applitools delivers full end-to-end test automation with AI infused at every step. Wed, 11 Mar 2026 19:00:25 +0000 en-US hourly 1 https://wordpress.org/?v=6.5.8 Handling Animations and Loading Artifacts in Visual Testing https://app14743.cloudwayssites.com/blog/handling-animations-and-loading-artifacts-in-visual-testing/ Mon, 21 Jul 2025 18:12:29 +0000 https://app14743.cloudwayssites.com/?p=61002 Master dynamic content visual testing with our hands-on tutorial. Learn to capture rich UI experiences effectively.

The post Handling Animations and Loading Artifacts in Visual Testing appeared first on AI-Powered End-to-End Testing | Applitools.

]]>
Stylized screenshot with half greyed out and other half colorized to highlight dynamic content

Have you ever encountered a situation where you try to take a screenshot, but instead of the beautifully well-crafted UI, all you’ve got is an image of a spinner/skeleton/loading screen? Handling animations and loading artifacts in visual testing can be daunting.

Don’t worry – it can happen to anyone, and we’re not here to judge you 😉

One of the SDK engineers here at Applitools, Noam, breaks this down into a hands-on tutorial, hoping it will help you get a better understanding of the industry’s best practices around visual testing of rich and dynamic UI experiences.

Let’s dive right in!

Framework Native Solutions

Most frameworks already have different mechanisms to handle animations and loading artifacts. Keeping things simple is often the best way to achieve code stability and maintainability. Using your framework’s built-in tools would most often be the best approach.

For example:

Playwright JS

// Playwright: wait for spinner to be removed
await page.waitForSelector('.spinner', { state: 'detached' });
await eyes.check()

Cypress

// Cypress: wait for spinner to not exist
cy.get('.spinner').should('not.exist'); 
cy.eyesCheck()

Selenium JS

// Selenium: wait for spinner to be invisible
const spinnerElements = await driver.findElements(By.css('.spinner'));
if (spinnerElements.length) {
  await driver.wait(until.elementIsNotVisible(spinnerElements[0]), 5000);
}
await eyes.check()

A Common Pitfall

Even if the UI appears visually unchanged, frontend frameworks like React, Vue, and Angular may re-render elements under the hood. This can lead to stale element references, especially when capturing regions right after a DOM change.

Consider the following example:

cy.get('.main').then($el => {
  cy.get('.spinner').should('not.exist'); // spinner disappears after main was located

  cy.eyesCheckWindow({
    tag: 'main',
    target: 'region',
    element: $el, // stale reference if .main was replaced
  });
});
  1. First, Cypress locates .main
  2. Then, Cypress waits for the spinner to disappear
  3. This example would fail (even if the new element has the exact same properties) if the main element is replaced by another element

How to avoid that?

When possible (e.g., Playwright), it’s preferred that you use locators instead of selectors. If you can’t, it’s better if you use selectors instead of DOM references (element: ‘.main’).

Videos, CSS Animations, GIFs

There are many techniques to eliminate other types of dynamic behaviour in web pages. Playwright, for example, provides a Clock API that allows pausing JavaScript time-related events (including JS-driven animations). It’s also possible to install custom CSS snippets to pause and reset CSS-related animations. Other JS specialized crafted snippets would be required for resetting GIFs, videos, and so on – you get the idea.

This never-ending cat-and-mouse game can be prevented by using Applitools Ultrafast Grid (UFG). Instead of rendering web pages on locally executed browsers, the UFG team maintains specialized logics and fine-tuned commands that ensure a stable and consistent rendering experience. While UFG offers more than just rendering stability, it’s worth noting that classic screenshots can still achieve stable results. UFG just makes it easier!

Algo-Based Solutions

If you intentionally want to capture dynamic content (e.g., animations, changes), a smarter strategy is to embrace that variability and use smart matching algorithms to compare just what you need, like those found in Applitools Eyes.

Any match level can be used for the entire screenshot or specific regions of the screen. Read more in the Match Level Best Practices tutorial. For example, algorithms like the Layout match level can drastically improve your experience with localization testing.

The waitBeforeCapture Setting

Performing wait operations can become more complicated when:

  1. Testing with no-code visual testing SDKs (e.g eyes-storybook)
  2. Testing with advanced Eyes features like lazyLoading and layoutBreakpoints

The waitBeforeCapture setting was invented for these types of use cases (and a few others).

This setting can receive three types of arguments:

  1. Milliseconds – the simplest approach. While it’s not always the most innovative or sophisticated pattern, in many cases, it “does the trick.” In general, waiting for explicit timeouts during tests is not recommended. However, when compared to clock manipulations and code injections, sometimes the simplicity and stability is worth the longer run-time.
  2. Selector – when we’re waiting for something to appear, most SDKs support passing a selector, and Applitools Eyes will automatically wait for an element that matches this selector to appear in the web page.
  3. Custom function – see code example
// eyes-storybook
  waitBeforeCapture: async () => {
    while (document.querySelector('.spinner')) {
      await new Promise((resolve) => setTimeout(resolve, 100))
    }
    return true;
  }

// eyes-playwright
await eyes.check({
  name: 'my-step',
  async waitBeforeCapture() {
    await page.locator('.spinner').waitFor({state: 'hidden'})
  },
})

The waitBeforeCapture setting can be defined in your applitools.config file, in your eyes.check settings, using the Target settings builder, and in other similar places. Please refer to the documentation of the specific SDK you’re using for concrete examples.

Storybook Play Functions

A nice eyes-storybook-specific trick to achieve a desired rendering state would be a Storybook Play Function.

Applitools Eyes will run your play functions and wait for them to finish before capturing anything on the screen. Use Play Functions to navigate the story to an interesting state and wait for the story to be stable inside the play function to help Eyes understand what the best time is to capture the screenshot.

Applitools is Here to Help

We hope you’ve found this article interesting, and maybe it solved some of the most common visual testing issues you may have encountered. Go ahead and try these examples out for free with Applitools Eyes.

However, if something isn’t clear or if you’d like advice regarding the best way to incorporate visual testing into your organization, please don’t hesitate to reach out to our experts! Testing is our passion, and we’re here to help.

Quick Answers

What are “loading artifacts” in visual testing, and how do I avoid flaky tests?

Loading artifacts are transient UI elements, like spinners, skeleton cards, GIFs, that appear while data is fetched. If a screenshot is captured before they disappear, your baseline image won’t match future renders, causing false failures (flaky tests).

Why do I get “stale element reference” errors after a React/Vue/Angular re‑render?

Modern frameworks often replace DOM nodes even when the UI looks identical. If you save a DOM reference (e.g., cy.get('.main')) before waiting for the spinner to vanish, that reference may point to a removed element, causing stale errors. Capture by selector or locator, not by saved element handles, to avoid this.

What is the waitBeforeCapture setting in Applitools, and what values can it accept?

waitBeforeCapture delays the screenshot after the DOM is stable. It accepts:
Milliseconds (e.g., 500)
CSS selector to wait for element presence/absence
Custom async function for complex logic (e.g., loop until .spinner hidden)

Can I use Storybook Play Functions to control the render state before visual testing?

Yes. In eyes‑storybook, Applitools runs each story’s Play Function and waits for it to finish—perfect for clicking buttons, filling forms, or pausing animations before the snapshot.


Is it better to fast-forward the JavaScript clock or add explicit waits for CSS animations?

Fast-forwarding the JS clock (e.g., page.clock.fastForward(1000) in Playwright) is usually more reliable and efficient than using hard timeouts. It advances timers without waiting in real time, making tests faster. However, it won’t affect CSS-driven animations since those still require CSS overrides to pause or skip transitions. For full stability, combine clock control with style injections or use Applitools Ultrafast Grid, which auto-handles CSS animations under the hood.

The post Handling Animations and Loading Artifacts in Visual Testing appeared first on AI-Powered End-to-End Testing | Applitools.

]]>
Think You Have Full Test Coverage? Here Are 5 Gaps Most Teams Miss https://app14743.cloudwayssites.com/blog/expand-test-coverage-beyond-code-coverage/ Fri, 20 Jun 2025 16:44:46 +0000 https://app14743.cloudwayssites.com/?p=60839 Even with 100% code coverage, critical bugs still slip through. In this post, we explore five common gaps in software test coverage—from missed visual defects to untested browser variations—and how modern teams are using visual AI and no-code test automation to close them.

The post Think You Have Full Test Coverage? Here Are 5 Gaps Most Teams Miss appeared first on AI-Powered End-to-End Testing | Applitools.

]]>

You’ve got your unit tests. Your end-to-end flows. Maybe even 100% code coverage. But bugs still slip through.

That’s because full code coverage doesn’t guarantee full test coverage. Visual glitches, browser inconsistencies, and content drift often escape traditional automation — and they’re exactly the kinds of issues your users notice first.

In The Coverage Overlook, the kickoff session of our Testing Your Way: Code & No-Code Journeys webinar series, we explored five critical coverage gaps most teams miss — and how to close them with AI-powered visual testing and no-code tools.

1. Visual and Layout Bugs

Code-based assertions won’t catch when an element shifts, disappears, or overlaps. That’s where Visual AI steps in.

By analyzing the rendered UI — not just the DOM — Visual AI identifies layout issues, missing images, overlapping text, and subtle visual defects with a single line of code (or none at all).

“Visual AI can instantly catch layout shifts, missing elements, and new text that coded assertions would miss — all without the maintenance burden of custom locators.”
Tim Hinds, Applitools

2. Cross-Browser and Device Inconsistencies

Most test suites default to Chrome. But real users span dozens of devices and browsers.

Visual AI tools like Applitools Eyes can validate your app across multiple browsers and screen sizes in parallel — using a single test run. No custom scripting required.

3. Dynamic Content Variations

Personalized content, A/B tests, and location-based content are tough to verify with scripted tests alone.

Visual AI combined with flexible match algorithms can confirm layout structure while ignoring safe visual differences — helping your team catch what matters, without writing exceptions for every variant.

4. Lower-Priority Flows and Pages

Teams tend to focus their test coverage on critical flows — like checkout or login — and leave lower-traffic pages untested.

No-code tools like Applitools Autonomous make it easy to cover the rest. A built-in crawler can scan your site and establish visual baselines across dozens (or hundreds) of pages — all without writing a single test script.

5. Accessibility Gaps

Code coverage can’t catch color contrast failures, missing labels, or overlapping elements that make your UI inaccessible.

Visual AI can. And with upcoming enforcement of the European Accessibility Act, now is the time to start catching these issues early.

Watch the Full Session On-Demand: Code & No-Code Journeys: The Coverage Overlook

Closing the Gap

Code coverage still has value — but modern teams are shifting toward user-centered test coverage.

As shared in the session, teams like Eversana are combining code-based, no-code, and visual testing strategies to expand coverage, accelerate feedback, and reduce risk. With this blended approach, they’ve achieved:

  • 65% reduction in regression testing time
  • 750+ hours saved per month
  • 90% test stability
  • A unified testing culture across manual testers, developers, and QA

What’s Next in the Series?

The journey continues with The Maintenance Shortcut, where we explore how teams are reducing flaky tests, eliminating brittle locators, and cutting test maintenance with Visual AI and Autonomous.


Quick Answers

Why isn’t 100% code coverage enough?

Code coverage measures lines executed, not what users see—visual defects, layout shifts, and browser differences can slip through.

Which testing gaps are most commonly missed?

Visual regressions, cross-browser/device inconsistencies, dynamic/personalized content, untested journeys, and accessibility issues.

How do modern teams close these gaps?

Use Visual AI (https://app14743.cloudwayssites.com/visual-ai) to validate pixels and Ultrafast Grid (https://app14743.cloudwayssites.com/ultrafast-grid) to scale UI checks across browsers/devices; add no-code flows with Autonomous to broaden coverage (https://app14743.cloudwayssites.com/platform/autonomous/).

What’s a practical first step in expanding test coverage?

Start by visual-validating your highest-traffic pages and critical journeys, then expand to your full cross-browser matrix.

The post Think You Have Full Test Coverage? Here Are 5 Gaps Most Teams Miss appeared first on AI-Powered End-to-End Testing | Applitools.

]]>