Skip to content

Commit

Permalink
Init commit for view_image_diffs()
Browse files Browse the repository at this point in the history
  • Loading branch information
schloerke committed Jul 24, 2023
1 parent bbab360 commit bb09c61
Show file tree
Hide file tree
Showing 6 changed files with 479 additions and 0 deletions.
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export(trigger_results)
export(trigger_tests)
export(use_manual_app)
export(use_shinyjster)
export(view_image_diffs)
export(view_test_images)
export(write_sysinfo)
importFrom(stats,setNames)
151 changes: 151 additions & 0 deletions R/view-image-diffs.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
# TODO
# - Make method to check all images in git status?
# * No. This requires too many permissions. Skipping for now.


setup_gha_image_diffs <- function(
...,
min_diff = 3,
repo_dir = ".",
# location to save images
out_dir = tempfile(),
sha = git_sha(repo_dir)
# # location of repo for comparisons
# vanilla_repo_dir = "../z-shinycoreci.nosync"
) {
ellipsis::check_dots_empty()
repo_dir <- normalizePath(repo_dir)
# vanilla_repo_dir <- normalizePath(vanilla_repo_dir)
force(sha)
withr::local_dir(repo_dir)

out_dir <- "inst/img-diff-app"
dir.create(out_dir, recursive = TRUE, showWarnings = FALSE)


proc_locs <- as.list(Sys.which(c("git", "gm")))
if (proc_locs$git == "") stop("Please install git")
if (proc_locs$gm == "") stop("Please install graphicsmagick via `brew install graphicsmagick` or `apt-get install graphicsmagick`")

all_files <- system("git diff --name-only", intern = TRUE)
png_files <- all_files[fs::path_ext(all_files) == "png" & grepl("^inst/apps/", all_files)]

tmp_img_path <- file.path(out_dir, "tmp_original_image.png")
# Extract original image so that two files can be compared
get_original_file <- function(png_file) {
system(paste0("git show HEAD:", png_file, " > ", tmp_img_path))
tmp_img_path
}
on.exit(if (file.exists(tmp_img_path)) unlink(tmp_img_path))

message("\nFinding images...")
p <- progress::progress_bar$new(
format = "[:current/:total;:eta] :name",
total = length(png_files),
show_after = 0,
clear = FALSE
)
diffs <- lapply(png_files, function(png_file) {
p$tick(tokens = list(name = png_file))
# Compare images
shinytest2::screenshot_max_difference(png_file, get_original_file(png_file))
})
# diffs <- as.list(seq_along(png_files))

diffs <- setNames(diffs, png_files)
# hist(unlist(diffs))

diff_folder <- file.path(out_dir, "image_diffs")
if (dir.exists(diff_folder)) unlink(diff_folder, recursive = TRUE)
dir.create(diff_folder, showWarnings = FALSE, recursive = TRUE)

bad_pngs <- names(diffs[diffs > min_diff])
bad_diff_count <- unname(unlist(diffs[bad_pngs]))

message("\nDiff images")
p <- progress::progress_bar$new(
format = "[:current;:total;:eta] :name",
total = length(bad_pngs),
show_after = 0,
clear = FALSE
)
img_dt <-
lapply(bad_pngs, function(bad_png) {
p$tick(tokens = list(name = bad_png))
san_path <- fs::path_sanitize(bad_png, "_")
new_png <- fs::file_copy(
bad_png,
file.path(diff_folder, fs::path_ext_set(san_path, ".new.png")),
overwrite = TRUE
)
orig_png <- fs::file_copy(
get_original_file(bad_png),
file.path(diff_folder, fs::path_ext_set(san_path, ".old.png")),
overwrite = TRUE
)
diff_png <- file.path(diff_folder, san_path)
system(paste0(
"gm compare ", new_png, " ", orig_png, " -highlight-style assign -file ", diff_png
))

dplyr::tibble(
diff_png = diff_png,
orig_png = orig_png,
new_png = new_png
)
}) %>%
dplyr::bind_rows()

png_dt <- dplyr::tibble(
file = bad_pngs,
diff_png = img_dt$diff_png,
orig_png = img_dt$orig_png,
new_png = img_dt$new_png,
diff_count = bad_diff_count
) %>%
dplyr::mutate(
# inst/apps/041-dynamic-ui/tests/testthat/_snaps/linux-4.0/mytest/022.png
base = gsub("^inst/apps/", "", file),
app = gsub("/.*$", "", base),
snap = file.path(basename(dirname(base)), basename(base)),
platform_combo = basename(dirname(dirname(base))),
anchor = fs::path_sanitize(file, "_"),
) %>%
dplyr::select(-base) %>%
tidyr::separate_wider_delim(cols = "platform_combo", names = c("platform", "Rver"), delim = "-", cols_remove = FALSE)

data_path <- file.path(out_dir, "data.json")
writeLines(
jsonlite::serializeJSON(png_dt, pretty = TRUE),
data_path,
useBytes = TRUE
)

data_path
}



#' @export
view_image_diffs <- function(
...,
run_fix_snaps = TRUE,
run_setup = TRUE,
open_viewer = TRUE,
repo_dir = ".",
sha = git_sha(repo_dir)
) {
ellipsis::check_dots_empty()
if (run_fix_snaps) {
fix_snaps(ask_apps = FALSE, ask_branches = FALSE, repo_dir = repo_dir, sha = sha)
}
if (run_setup) {
setup_gha_image_diffs(repo_dir = repo_dir, sha = sha)
}

withr::local_dir(repo_dir)
rmarkdown::render("inst/img-diff-app/diff.Rmd")
if (open_viewer) {
system("open inst/img-diff-app/diff.html")
}
}
2 changes: 2 additions & 0 deletions R/zzz.R
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
`%>%` <- NULL

.onLoad <- function(...) {
`%>%` <<- dplyr::`%>%`

apps_on_load()
}
4 changes: 4 additions & 0 deletions inst/img-diff-app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
image_diffs
tmp_original_image.png
data.json
diff.html
87 changes: 87 additions & 0 deletions inst/img-diff-app/app.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
library(bslib)
library(shiny)

print(getwd())
png_dt <- jsonlite::unserializeJSON(paste0(readLines("data.json"), collapse = "\n"))

ui <- bslib::page_sidebar(
shiny::uiOutput("title"),
"Diff: ", shiny::verbatimTextOutput("diff_count"),
shiny::imageOutput("diff_image"),
sidebar = bslib::sidebar(
style="white-space: nowrap;",
Map(
seq_len(nrow(png_dt)),
png_dt$app,
png_dt$snap,
png_dt$platform_combo,
f = function(i, app, snap, platform_combo) {
shiny::actionLink(
paste0("link_", i),
# paste0(app, " ", snap, " on ", platform_combo)
paste0(app, "/", platform_combo, "/", snap)
)
}
)
)
)

server <- function(input, output, session) {
bad_row <- reactiveVal(1)

lapply(seq_len(nrow(png_dt)), function(i) {
diff_image <- png_dt$diff_file[i]

observe({
req(input[[paste0("link_", i)]]) # Force reactivity
bad_row(i)
})
})

output$title <- shiny::renderUI({
req(bad_row())
info <- as.list(png_dt[bad_row(), ])
shiny::tagList(
shiny::h1(
shiny::a(
target="_blank",
href=paste0("https://github.com/rstudio/shinycoreci/tree/main/inst/apps/", info$app),
info$app
)
),
shiny::p(
"Snap: ",
shiny::a(
target="_blank",
href=paste0("https://github.com/rstudio/shinycoreci/tree/main/", info$file),
paste0(tail(strsplit(info$file, "/")[[1]], 3), collapse = "/")
)
),
shiny::p(
"App: ",
shiny::a(
target="_blank",
href=paste0("https://testing-apps.shinyapps.io/", info$app),
"shinyapps.io"
)
),

shiny::p(
"Diff: ",
shiny::code(info$diff_count)
),
)
})

output$diff_image <- shiny::renderImage({
req(bad_row())
list(
src = file.path("image_diffs", basename(png_dt$diff_file[bad_row()])),
contentType = "image/png",
width = "100%",
style="border: 1px solid black;"
)
}, deleteFile = FALSE)
}

shiny::shinyApp(ui, server)
Loading

0 comments on commit bb09c61

Please sign in to comment.