Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Forward shiny app options from snapshot_review #1928

Open
stefanedwards opened this issue Feb 6, 2024 · 0 comments
Open

Forward shiny app options from snapshot_review #1928

stefanedwards opened this issue Feb 6, 2024 · 0 comments

Comments

@stefanedwards
Copy link

I am unit testing a package using expect_doppelganger, but doing so from a Docker container on a remote server.

Short story, something failed and testthat suggests running testthat::snapshot_review('facet/') to review changes. Alas, it doesn't quite work as expected:

Starting Shiny app for snapshot review
ℹ Use Ctrl + C to quit
/usr/bin/xdg-open: 882: www-browser: not found
/usr/bin/xdg-open: 882: links2: not found
/usr/bin/xdg-open: 882: elinks: not found
/usr/bin/xdg-open: 882: links: not found
/usr/bin/xdg-open: 882: lynx: not found
/usr/bin/xdg-open: 882: w3m: not found
xdg-open: no method available for opening 'http://127.0.0.1:6299'

Mainly, the host and port cannot be specified from snapshot_review. That would be nice.

I suggest adding an ellipsis to snapshot_review, which gets passed on to the non-exported method review_app. Here, the arguments in ... are used in either shiny::runApp, as such,

shiny::runApp(shiny::shinyApp(ui, server), quiet = TRUE, launch.browser = shiny::paneViewer(), ...)

or in shiny::shinyApp, as such:

shiny::runApp(shiny::shinyApp(ui, server, options = list(...)), quiet = TRUE, launch.browser = shiny::paneViewer())

Or even let shapshot_review accept an explicit argument for shinyApp.

Workaround for now is to overload the two functions locally:

snapshot_review <- function (files = NULL, path = "tests/testthat", ...) {
    rlang::check_installed(c("shiny", "diffviewer"), "to use snapshot_review()")
    changed <- testthat:::snapshot_meta(files, path)
    if (nrow(changed) == 0) {
        rlang::inform("No snapshots to update")
        return(invisible())
    }
    review_app(changed$name, changed$cur, changed$new, ...)
    testthat:::rstudio_tickle()
    invisible()
}

review_app <- function (name, old_path, new_path, ...) {
    stopifnot(length(name) == length(old_path), length(old_path) ==
        length(new_path))
    n <- length(name)
    case_index <- stats::setNames(seq_along(name), name)
    handled <- rep(FALSE, n)
    ui <- shiny::fluidPage(style = "margin: 0.5em", shiny::fluidRow(style = "display: flex",
        shiny::div(style = "flex: 1 1", shiny::selectInput("cases",
            NULL, case_index, width = "100%")), shiny::div(class = "btn-group",
            style = "margin-left: 1em; flex: 0 0 auto", shiny::actionButton("skip",
                "Skip"), shiny::actionButton("accept", "Accept",
                class = "btn-success"), )), shiny::fluidRow(diffviewer::visual_diff_output("diff")))
    server <- function(input, output, session) {
        i <- shiny::reactive(as.numeric(input$cases))
        output$diff <- diffviewer::visual_diff_render({
            diffviewer::visual_diff(old_path[[i()]], new_path[[i()]])
        })
        shiny::observeEvent(input$reject, {
            rlang::inform(paste0("Rejecting snapshot: '", new_path[[i()]],
                "'"))
            unlink(new_path[[i()]])
            update_cases()
        })
        shiny::observeEvent(input$accept, {
            rlang::inform(paste0("Accepting snapshot: '", old_path[[i()]],
                "'"))
            file.rename(new_path[[i()]], old_path[[i()]])
            update_cases()
        })
        shiny::observeEvent(input$skip, {
            i <- next_case()
            shiny::updateSelectInput(session, "cases", selected = i)
        })
        update_cases <- function() {
            handled[[i()]] <<- TRUE
            i <- next_case()
            shiny::updateSelectInput(session, "cases", choices = case_index[!handled],
                selected = i)
        }
        next_case <- function() {
            if (all(handled)) {
                rlang::inform("Review complete")
                shiny::stopApp()
                return()
            }
            remaining <- case_index[!handled]
            next_cases <- which(remaining > i())
            if (length(next_cases) == 0)
                remaining[[1]]
            else remaining[[next_cases[[1]]]]
        }
    }
    rlang::inform(c("Starting Shiny app for snapshot review", i = "Use Ctrl + C to quit"))
    shiny::runApp(shiny::shinyApp(ui, server), quiet = TRUE,
        launch.browser = shiny::paneViewer(), ...)
    invisible()
}

snapshot_review('facet/', port = 8001, host="0.0.0.0")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant