--- 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()`.