---
title: "Comparing web pages and htmlwidgets"
output: rmarkdown::html_vignette
vignette: >
%\VignetteIndexEntry{Comparing web pages and htmlwidgets}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---
```{r, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>",
eval = FALSE
)
```
odiffr compares images; it does not open web pages or drive a browser. To
test how a web page, an R Markdown/Quarto report or an htmlwidget looks,
take a screenshot with a headless browser first, for example with
[webshot2](https://rstudio.github.io/webshot2/) or
[chromote](https://rstudio.github.io/chromote/) (both use Chrome or
Chromium), and then compare the PNG files with odiff. For Shiny apps, see
`vignette("shinytest2")`.
## Screenshot a page
```{r, eval = FALSE}
webshot2::webshot(
"https://example.com",
file = "current/home.png",
vwidth = 1280, vheight = 800,
delay = 0.5 # let the page settle
)
```
Local HTML files work too, e.g. a rendered report:
`webshot2::webshot("report.html", "current/report.png")`.
## Screenshot an htmlwidget
Save the widget as an HTML file, then take a screenshot of it:
```{r, eval = FALSE}
widget <- DT::datatable(head(iris)) # any htmlwidget
html <- tempfile(fileext = ".html")
htmlwidgets::saveWidget(widget, html, selfcontained = TRUE)
webshot2::webshot(html, file = "current/table.png",
vwidth = 800, vheight = 600, delay = 1)
```
Keep everything deterministic that you can: a fixed viewport size, a fixed
zoom level, a fixed seed for random data, and no animations (many widgets
have an option to disable them). Map tiles and other content loaded from the
internet can change at any time; avoid them in tests or hide them with
`ignore_regions`.
## Compare with a baseline
Browser screenshots contain anti-aliasing noise around rounded corners,
borders and text. The `"screenshot"` preset ignores anti-aliased pixels while
keeping the colour threshold low (see `?odiff_preset`):
```{r, eval = FALSE}
library(odiffr)
result <- do.call(compare_images, c(
list("baseline/home.png", "current/home.png", diff_output = "home-diff.png"),
odiff_preset("screenshot")
))
result$match
```
For many pages at once, use `compare_image_dirs()` and `batch_report()`:
```{r, eval = FALSE}
results <- do.call(compare_image_dirs, c(
list("baseline/", "current/", diff_dir = "diffs/"),
odiff_preset("screenshot")
))
batch_report(results, output_file = "report.html", images = "all",
embed = TRUE)
```
## As a testthat snapshot
`expect_snapshot_image()` stores the screenshot as a testthat snapshot and
compares it with odiff on later runs. On failure a diff image is written to
`tests/testthat/_odiffr/`.
```{r, eval = FALSE}
test_that("report looks the same", {
skip_if_not_installed("webshot2")
path <- tempfile(fileext = ".png")
webshot2::webshot("report.html", file = path,
vwidth = 1024, vheight = 768)
expect_snapshot_image(
path,
name = "report",
preset = "screenshot",
variant = Sys.info()[["sysname"]] # fonts differ between systems
)
})
```
Review changes with `testthat::snapshot_review()`, and on CI write a report
of all changed snapshots with `snapshot_report()`.