Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

To run BackstopJS visual tests in GitLab CI, install the project’s locked BackstopJS dependency, make the app reachable from the runner, run backstop test, and publish its JUnit XML with artifacts:reports:junit. Keep approved reference screenshots under version control or otherwise available to the job. The JUnit report gives GitLab test visibility, but it does not fail a job by itself: the test command must return a non-zero exit status when comparisons fail.

How the pipeline fits together

BackstopJS captures pages defined by scenarios, then compares them with an approved reference set. A GitLab job needs to provide four things: the pinned tool and its browser environment, the app URL the runner can reach, the approved references, and an exit status that reflects the test result. JUnit XML is an additional reporting channel, not a replacement for the test command.

  1. Install: commit BackstopJS as a project dependency and commit the lockfile so local and CI installations select the same version.
  2. Configure: define at least one viewport and one or more scenarios, each with a label and URL.
  3. Prepare: provide the app and approved reference images before the test runs.
  4. Test and report: run backstop test and upload the generated JUnit XML.

Check the Node.js and BackstopJS versions

The package metadata snapshot for BackstopJS 6.3.25 specifies Node.js 16 or later and npm 8 or later. This is a version-specific requirement, not a promise about every BackstopJS release. Check the version selected by your lockfile and its installed package documentation before choosing the CI image; the project README is on a moving branch, so defaults can change. See the BackstopJS 6.3.25 package metadata and BackstopJS project README.

Configure scenarios and establish references

Initialize the project

Install BackstopJS locally in the project, then initialize its configuration:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
#1 Best Overall
Elebase USB to USB C Adapter for iPhone 18 Pro Max,USBC Car Charger Adapter
  • Read Before You Buy — No Video Output: These adapters support charging and USB 2.0 data transfer, but cannot transmit video signals. Except for standard USB webcams (which use USB data only), they are not compatible with HDMI/DisplayPort cables, video-capable USB-C hubs, or docking stations with video output.
  • Convert USB-A Ports to USB-C: Designed to connect USB-C earphones, cables, flash drives, card readers, and other USB-C accessories to standard USB-A ports. Plug-and-play with no drivers or software required.
  • Aluminum Alloy Housing: Built with a sturdy aluminum alloy shell that aids in heat dissipation and protects against daily wear and scratches. Designed to maintain a stable and secure connection.
  • Compact & Travel-Friendly: The ultra-compact design allows the adapter to stay plugged into your device without blocking adjacent ports or adding bulk, reducing wear and tear on your original USB ports.
  • 12-Month Warranty: Backed by a 12-month manufacturer warranty for peace of mind. Designed to meet strict quality control standards for reliable everyday performance.
npm install --save-dev backstopjs
npx backstop init

Commit the resulting configuration and lockfile. A basic setup defines viewports and scenarios. Each scenario needs a label and a URL; the URL can be absolute or project-local, but in CI it must resolve from the runner’s network context. The app is not necessarily reachable at the same hostname inside a container as it is on a developer’s machine.

Create and review the baseline

BackstopJS’s workflow uses init, test, and approve. Run the tests against the intended app state and review the captured results before approving them. backstop approve promotes the latest test captures into the reference set, changing the baseline used by future tests. Do not automatically approve every failing run: doing so can turn a real regression into the new expected appearance.

Make the approved references available to the GitLab job, commonly by committing them to the repository. If your pipeline generates or retrieves them another way, ensure that happens before testing and that the resulting files match the intended baseline.

Rank #2
Anker USB-C Hub, 5-in-1 USB Hub for Laptops, 4K HDMI Multiport Adapter
  • 5-in-1 USB-C Hub: Experience comprehensive connectivity featuring a Power Delivery input, two USB-A 2.0 ports, a USB-A 3.0 port, and an HDMI port. (Note: The USB-C power delivery input port is only for connecting an external wall charger to power your laptop and cannot power peripheral devices.)
  • 90W Pass-Through Charging: Achieve optimal charging with 90W pass-through power to your laptop, supported by a total input of 100W, with the hub reserving 10W for operational efficiency. (Note: Wall charger not included.)
  • Quick Data Transfers: Accelerate your productivity with rapid data transfers using a high-speed 5Gbps USB 3.0 port and two 480Mbps USB 2.0 ports.
  • 4K HDMI Display: Enhance your visual experience with a hub capable of delivering 4K resolution at 30Hz in both mirror and extend modes. Please note that this hub is compatible with MacBook (macOS 12 and newer), Windows 10 and 11, ChromeOS, and laptops equipped with DP Alt Mode and Power Delivery. Note: This device is not compatible with Linux.
  • What You Get: Anker USB-C Hub (5-in-1, 4K HDMI), welcome guide, 18-month warranty, and our friendly customer service.

Enable BackstopJS CI reporting

In the BackstopJS configuration, enable the CI reporter, for example with "report": ["CI"]. The README says this reporter produces JUnit XML by default and allows the report directory and filename to be customized. Its documented default filename is xunit.xml; configure paths.ci_report if you want the report in a particular directory. GitLab’s report path must match the file BackstopJS actually writes.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Add the GitLab CI job

This is a starting pattern, not a tested, universal pipeline. Select a Node image compatible with the pinned BackstopJS version and your app. Replace the build and app-start steps with commands that suit the project, and make the app reachable from the test process.

visual_regression:
  stage: test
  script:
    - npm ci
    - npm run build
    # Start or connect to the application here; it must be reachable by the runner.
    - npx backstop test
  artifacts:
    when: always
    paths:
      - backstop_data/ci_report/
    reports:
      junit: backstop_data/ci_report/xunit.xml

The sample assumes the CI report is configured to write to backstop_data/ci_report/. If you change the BackstopJS report directory or filename, update both GitLab artifact entries accordingly. GitLab accepts a JUnit filename, glob pattern, or array of XML report paths; it does not accept a directory alone as the JUnit report path.

Rank #3
Sale
Anker USB C Hub, 7in1 Multi-Port USB Adapter, 4K@60Hz USBC to HDMI Splitter
  • Sleek 7-in-1 USB-C Hub: Features an HDMI port, two USB-A 3.0 ports, and a USB-C data port, each providing 5Gbps transfer speeds. It also includes a USB-C PD input port for charging up to 100W and dual SD and TF card slots, all in a compact design.
  • Flawless 4K@60Hz Video with HDMI: Delivers exceptional clarity and smoothness with its 4K@60Hz HDMI port, making it ideal for high-definition presentations and entertainment. (Note: Only the HDMI port supports video projection; the USB-C port is for data transfer only.)
  • Double Up on Efficiency: The two USB-A 3.0 ports and a USB-C port support a fast 5Gbps data rate, significantly boosting your transfer speeds and improving productivity.
  • Fast and Reliable 85W Charging: Offers high-capacity, speedy charging for laptops up to 85W, so you spend less time tethered to an outlet and more time being productive.
  • What You Get: Anker USB-C Hub (7-in-1), welcome guide, 18-month warranty, and our friendly customer service.

Make the app available to the test job

If the app is built or served in another job, arrange the pipeline dependency and network route so the visual-test job can access it. The correct hostname and routing depend on the runner executor, container setup, and deployment design. A scenario URL that works on a developer’s laptop may not work from a GitLab runner.

Make failed comparisons fail the pipeline

GitLab’s unit test report documentation states: “Unit test reports require the JUnit XML format and do not affect job status. To make a job fail when tests fail, your job’s script must exit with a non-zero status.” In other words, publishing the XML is not a merge gate by itself. The shell command’s exit status controls whether the job fails.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Check the behavior of npx backstop test using the exact BackstopJS version pinned by your project. Confirm in a pipeline that a known visual mismatch causes a non-zero exit and fails the job. If it does not, investigate the installed version’s behavior and the script wrapper rather than assuming GitLab will infer failure from the report.

Rank #4
Sale
UGREEN USB to USB C Adapter Combo 4-Pack, 10Gbps USB C Converter Space Gray
  • Dual Converters, Infinite Potential:Includes 2× USB C male to USB A female adapters and 2× USB A male to USB C female adapters. Perfect for a wide range of uses—tablets with Bluetooth keyboards, expand USB ports on macbook, and more. Two different converters for all your daily needs
  • Next-Level 10Gbps & 3A Charging: No more slow 480Mbps, this usb to usb c adapter has a transfer speed of up to 10Gbps, allowing you to do more transferring in less time. This usb adapter fits both USB A and USB C charger, supporting up to 3A fast charging
  • Upgraded Exquisite Craftsmanship: With an aluminum alloy housing and metal connector, the usbc to usb adapter is extremely durable and sturdy. Rigorously tested to withstand more than 10,000 times of plugging and unplugging, ensuring long-lasting performance
  • Broad Compatible: The usb c to usb adapter widely supports all USB C/ USB A devices like laptops, tablets, cellphones, car chargers, and phone chargers. Such as compatible with MacBook Pro/Air 2023/2022, Thunderbolt 4/3 Devices,Apple MagSafe Watch 9/8/7/SE/Ultra, iPad Pro 2022/2021, Samsung Galaxy S23/S20/S10, and iPhone 17/16/15 Pro. Plug and play
  • Please Note: To reach 10Gbps speed, keep the cable under 3.3 ft. For USB A Male to USB C adapters, try flipping the USB C connector. USB C Male to USB A adapters support bidirectional 10Gbps transfer within 3.3 ft

Choose a rendering approach

Approach When it helps Trade-offs to check
Run BackstopJS directly in the CI job A simpler runner setup when the job environment already has the browser dependencies BackstopJS needs. Rendering can vary with the browser and system libraries available in that environment. Verify that generated artifacts are writable and that the app URL is reachable.
Use BackstopJS’s --docker rendering option When you want a versioned BackstopJS rendering image to reduce differences between environments. The runner must be able to invoke Docker and have the required permissions. Check container networking and filesystem ownership for reports and screenshots.

BackstopJS documents --docker as an option that invokes Docker and uses a versioned BackstopJS image by default. For CI-like output where the command is piped, its README advises removing -t from the default Docker command template. Container access, permissions, and whether Docker is available depend on the GitLab runner configuration.

The README’s host.docker.internal suggestion applies to the cited Mac/Windows setup for reaching a host from its Docker rendering environment. Do not assume that hostname works on a GitLab runner: test the route and use a hostname that resolves in the actual runner’s network context.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Keep test results and screenshots available

Setting artifacts:when: always asks GitLab to upload configured artifacts even when the job fails. Include the report and any diagnostic screenshots you need under artifacts:paths. GitLab’s documentation describes JUnit system-out attachment tags for screenshots, along with uploading the image files as artifacts; the report’s attachment references and artifact paths must correspond to the files your job produces.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Best Value
Anker USB C Hub, 5-in-1 USBC to HDMI Splitter with 4K Display
  • 5-in-1 Connectivity: Equipped with a 4K HDMI port, a 5 Gbps USB-C data port, two 5 Gbps USB-A ports, and a USB C 100W PD-IN port. Note: The USB C 100W PD-IN port supports only charging and does not support data transfer devices such as headphones or speakers.
  • Powerful Pass-Through Charging: Supports up to 85W pass-through charging so you can power up your laptop while you use the hub. Note: Pass-through charging requires a charger (not included). Note: To achieve full power for iPad, we recommend using a 45W wall charger.
  • Transfer Files in Seconds: Move files to and from your laptop at speeds of up to 5 Gbps via the USB-C and USB-A data ports. Note: The USB C 5Gbps Data port does not support video output.
  • HD Display: Connect to the HDMI port to stream or mirror content to an external monitor in resolutions of up to 4K@30Hz. Note: The USB-C ports do not support video output.
  • What You Get: Anker 332 USB-C Hub (5-in-1), welcome guide, our worry-free 18-month warranty, and friendly customer service.

GitLab documents JUnit XML requirements including an .xml extension, a limit of less than 30 MB per file and less than 100 MB total per job, and that duplicate test names are ignored after the first occurrence. If a report does not appear, check the XML format, exact path, extension, artifact upload behavior, and size.

Troubleshoot common failures

Symptom Likely cause What to check or change
Scenario cannot load its URL The hostname or route is only valid on the developer’s machine, or the app has not started yet. Confirm the service is running before backstop test and test the URL from the same runner/container network context as the browser.
GitLab shows no test report CI reporting is not enabled, or GitLab points at a different path or filename than BackstopJS produced. Enable "report": ["CI"], inspect the generated output, configure paths.ci_report if needed, and use the exact XML path under reports:junit.
The job passes despite a failed visual comparison JUnit ingestion does not set job status, or the command/wrapper is not returning a failing exit code. Verify the pinned version’s exit behavior with a known mismatch and ensure the script does not suppress or overwrite the command’s status.
Docker rendering cannot reach the app The browser container uses a different network context from the host or service. Verify the runner’s container networking and use a hostname routable from that container; do not copy the Mac/Windows-only hostname advice without testing.
Artifacts are missing after a failure Artifacts are configured to upload only on success, paths do not match output, or container ownership prevents writing. Set when: always, verify output locations, and inspect file permissions and runner configuration.
GitLab rejects or omits JUnit results The XML extension, format, path, or size is not accepted, or duplicate names are being collapsed. Use valid JUnit XML with an .xml extension, a file or glob rather than a directory for the report path, stay within GitLab’s documented report limits, and ensure test names are unique where distinct results matter.

Or skip the browser setup

For a one-off screenshot or an automated capture outside a BackstopJS baseline comparison, ScreenshotNeo provides a screenshot API and MCP server. A single GET request can return an image or PDF; see the API documentation for options and response details.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
  • It accepts cookie and consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off.
  • Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed; response headers indicate the page verdict and billing status.
  • Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for AI agents and MCP clients.
  • The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots.

Sign up free for 1,000 screenshots a month with no card.

Frequently Asked Questions

Does GitLab CI need to run BackstopJS inside Docker?

No. BackstopJS documents Docker rendering as an option, not a requirement; choose based on the runner environment and verify browser consistency and network access.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Can I use a JUnit report as the only merge-blocking check?

No. GitLab displays report results, but the job must exit non-zero to fail.

Is ScreenshotNeo a replacement for BackstopJS baselines?

No. ScreenshotNeo captures pages, while BackstopJS provides the reference-image comparison and approval workflow described here.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.