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

Introduce integration testing framework #2682

Merged
merged 13 commits into from
Oct 30, 2019
Merged

Introduce integration testing framework #2682

merged 13 commits into from
Oct 30, 2019

Conversation

trestletech
Copy link
Contributor

@trestletech trestletech commented Oct 24, 2019

This PR introduces an integration testing framework that facilitates the testing of reactives inside of a Shiny server function or a Shiny module. The two entry-points are testModule and testServer which take a module or a shiny application object, respectively.

The vignette included in this PR best captures the functionality and how to use this. The initial version is published here: https://beta.rstudioconnect.com/content/6874/integration-testing.html

Intentionally omitted from this PR is any inline documentation on these new functions or their associated objects. I'm still debating whether this would be best served by an article in the dev center, something roxygenized, more vignettes, or some combination. I'll start work on how to document and expose this stuff next. (Preview)

Validation

This PR finally surfaces some of the internal work that we've been doing for a few weeks now. So there's a little more surface area that we could test here. However, any edge cases that we've discovered around weird reactivity or timing issues are already covered in unit tests, so I don't think there will be too much exploring required.

Take a look at testServer and testModule and pass in a few applications or modules as discussed in the vignette (linked above). If everything there works, I think we may be good for now. Once the documentation for all this lands, I'll want to get more feedback on usability and approachability, but that's intentionally omitted right now.

@trestletech trestletech requested a review from wch October 24, 2019 17:02
.gitignore Outdated Show resolved Hide resolved
R/test-module.R Outdated Show resolved Hide resolved
R/test-module.R Outdated Show resolved Hide resolved
R/test-module.R Outdated Show resolved Hide resolved
@@ -89,7 +90,9 @@ Suggests:
ggplot2,
reactlog (>= 1.0.0),
magrittr,
yaml
yaml,
future,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These packages aren't needed anymore, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They're still used in test-test-module, actually.

Copy link
Collaborator

@wch wch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just one thing with the Suggested packages; otherwise looks good!

@trestletech trestletech merged commit 67a66fd into master Oct 30, 2019
@trestletech trestletech deleted the jeff/int-test branch October 30, 2019 18:36
netbsd-srcmastr pushed a commit to NetBSD/pkgsrc that referenced this pull request Jun 5, 2021
shiny 1.6.0
================

This release focuses on improvements in three main areas:

1. Better theming (and Bootstrap 4) support:

  * The `theme` argument of `fluidPage()`, `navbarPage()`, and
    `bootstrapPage()` all now understand `bslib::bs_theme()` objects,
    which can be used to opt-into Bootstrap 4, use any Bootswatch
    theme, and/or implement custom themes without writing any CSS.

  * The `session` object now includes `$setCurrentTheme()` and
    `$getCurrentTheme()` methods to dynamically update (or obtain) the
    page's `theme` after initial load, which is useful for things such
    as [adding a dark mode switch to an
    app](https://rstudio.github.io/bslib/articles/theming.html#dynamic-shiny)
    or some other "real-time" theming tool like `bslib::bs_themer()`.

  * For more details, see [`{bslib}`'s
    website](https://rstudio.github.io/bslib/)

2. Caching of `reactive()` and `render*()` (e.g. `renderText()`,
   `renderTable()`, etc) expressions.

   * Such expressions automatically cache their _most recent value_,
     which helps to avoid redund ant computation within a single "flush" of
     reactivity. The new `bindCache()` function can be used to cache _all
     previous values_ (as long as they fit in the cache). This cache may be
     optionally scoped within and/or across user sessions, possibly leading
     to huge performance gains, especially when deployed at scale across
     user sessions.

  * For more details, see `help(bindCache, package = "shiny")`

3. Various improvements to accessibility for screen-reader and keyboard users.
  * For more details, see the accessibility section below.

## Full changelog

### Breaking changes

* Closed #3074: Shiny no longer supports file uploads for Internet Explorer 8 or 9. (#3075)

* Subtle changes, and some soft-deprecations, have come to
  `freezeReactiveValue` and `freezeReactiveVal` (#3055). These functions
  have been fragile at best in previous releases (issues #1791, #2463,
  #2946). In this release, we've solved all the problems we know about with
  `freezeReactiveValue(input, "x")`, by 1) invalidating `input$x` and set
  it to `NULL` whenever we freeze, and 2) ensuring that, after a freeze,
  even if the effect of `renderUI` or `updateXXXInput` is to set `input$x`
  to the same value it already has, this will result in an invalidation
  (whereas by default, Shiny filters out such spurious assignments).

  Similar problems may exist when using `freezeReactiveVal`, and when using
  `freezeReactiveValue` with non-`input` reactive values objects. But
  support for those was added mostly for symmetry with
  `freezeReactiveValue(input)`, and given the above issues, it's not clear
  to us how you could have used these successfully in the past, or why you
  would even want to. For this release, we're soft-deprecating both of
  those uses, but we're more than willing to un-deprecate if it turns out
  people are using these; if that includes you, please join the
  conversation at rstudio/shiny#3063. In the
  meantime, you can squelch the deprecation messages for these functions
  specifically, by setting `options(shiny.deprecation.messages.freeze =
  FALSE)`.

### Accessibility

* Added [bootstrap accessibility
  plugin](https://github.com/paypal/bootstrap-accessibility-plugin) under
  the hood to improve accessibility of shiny apps for screen-reader and
  keyboard users: the enhancements include better navigations for alert,
  tooltip, popover, modal dialog, dropdown, tab Panel, collapse, and
  carousel elements. (#2911)

* Closed #2987: Improved accessibility of "live regions" -- namely,
  `*Output()` bindings and `update*Input()`. (#3042)

* Added appropriate labels to `icon()` element to provide screen-reader
  users with alternative descriptions for the `fontawesome` and
  `glyphicon`: `aria-label` is automatically applied based on the
  fontawesome name. For example, `icon("calendar")` will be announced as
  "calendar icon" to screen readers. "presentation" aria role has also been
  attached to `icon()` to remove redundant semantic info for screen
  readers. (#2917)

* Closed #2929: Fixed keyboard accessibility for file picker button:
  keyboard users can now tab to focus on `fileInput()` widget. (#2937)

* Fixed #2951: screen readers correctly announce labels and date formats
  for `dateInput()` and `dateRangeInput()` widgets. (#2978)

* Closed #2847: `selectInput()` is reasonably accessible for screen readers
  even when `selectize` option is set to TRUE. To improve `selectize.js`
  accessibility, we have added
  [selectize-plugin-a11y](https://github.com/SLMNBJ/selectize-plugin-a11y)
  by default. (#2993)

* Closed #612: Added `alt` argument to `renderPlot()` and
  `renderCachedPlot()` to specify descriptive texts for `plotOutput()`
  objects, which is essential for screen readers. By default, alt text is
  set to the static text, "Plot object," but even dynamic text can be made
  with reactive function. (#3006, thanks @trafficonese and @leonawicz for
  the original PR and discussion via #2494)

* Added semantic landmarks for `mainPanel()` and `sidebarPanel()` so that
  assistive technologies can recognize them as "main" and "complementary"
  region respectively. (#3009)

* Closed #2844: Added `lang` argument to ui `*Page()` functions (e.g.,
  `fluidPage`, `bootstrapPage`) that specifies document-level language
  within the app for the accessibility of screen readers and search-engine
  parsers. By default, it is set to empty string which is commonly
  recognized as a browser's default locale. (#2920)

* Improved accessibility for `radioButtons()` and `checkboxGroupInput()`:
  All options are now grouped together semantically for assistive
  technologies. (thanks @jooyoungseo, #3187).

### Minor new features and improvements

* Added support for Shiny Developer Mode. Developer Mode enables a number
  of `options()` to make a developer's life easier, like enabling
  non-minified JS and printing messages about deprecated functions and
  options. See `?devmode()` for more details. (#3174)

* New `reactiveConsole()` makes it easier to interactively experiment with
  reactivity at the console (#2518).

* When UI is specified as a function (e.g. `ui <- function(req) { ... }`),
  the response can now be an HTTP response as returned from the (newly
  exported) `httpResponse()` function. (#2970)

* `selectInput` and `selectizeInput` now warn about performance
  implications when thousands of choices are used, and recommend
  [server-side
  selectize](https://shiny.rstudio.com/articles/selectize.html) be used
  instead. (#2959)

* Closed #2980: `addResourcePath()` now allows paths with a leading `.`
  (thanks to @ColinFay). (#2981)

* Closed #2972: `runExample()` now supports the `shiny.port` option (thanks
  to @ColinFay). (#2982)

* Closed #2692: `downloadButton()` icon can now be changed via the `icon`
  parameter (thanks to @ColinFay). (#3010)

* Closed #2984: improved documentation for `renderCachedPlot()` (thanks to
  @aalucaci). (#3016)

* `reactiveValuesToList()` will save its `reactlog` label as
  `reactiveValuesToList(<ID>)` vs `as.list(<ID>)` (#3017)

* Removed unused (and non-exported) `cacheContext` class.

* `testServer()` can accept a single server function as input (#2965).

* `shinyOptions()` now has session-level scoping, in addition to global and
  application-level scoping. (#3080)

* `runApp()` now warns when running an application in an R package
  directory. (#3114)

* Shiny now uses `cache_mem` from the cachem package, instead of
  `memoryCache` and `diskCache`. (#3118)

* Closed #3140: Added support for `...` argument in `icon()`. (#3143)

* Closed #629: All `update*` functions now have a default value for
  `session`, and issue an informative warning if it is missing. (#3195,
  #3199)

* Improved error messages when reading reactive values outside of a
  reactive domain (e.g., `reactiveVal()()`). (#3007)

### Bug fixes

* Fixed #1942: Calling `runApp("app.R")` no longer ignores options passed
  into `shinyApp()`. This makes it possible for Shiny apps to specify what
  port/host should be used by default. (#2969)

* Fixed #3033: When a `DiskCache` was created with both `max_n` and
  `max_size`, too many items could get pruned when `prune()` was
  called. (#3034)

* Fixed #2703: Fixed numerous issues with some combinations of
  `min`/`value`/`max` causing issues with `date[Range]Input()` and
  `updateDate[Range]Input()`. (#3038, #3201)

* Fixed #2936: `dateYMD` was giving a warning when passed a vector of dates
  from `dateInput` which was greater than length 1. The length check was
  removed because it was not needed. (#3061)

* Fixed #2266, #2688: `radioButtons` and `updateRadioButtons` now accept
  `character(0)` to indicate that none of the options should be selected
  (thanks to @ColinFay). (#3043)

* Fixed a bug that `textAreaInput()` doesn't work as expected for relative
  `width` (thanks to @shrektan). (#2049)

* Fixed #2859: `renderPlot()` wasn't correctly setting
  `showtext::showtext_opts()`'s `dpi` setting with the correct resolution
  on high resolution displays; which means, if the font was rendered by
  showtext, font sizes would look smaller than they should on such
  displays. (#2941)

* Closed #2910, #2909, #1552: `sliderInput()` warns if the `value` is
  outside of `min` and `max`, and errors if `value` is `NULL` or
  `NA`. (#3194)

### Library updates

* Removed html5shiv and respond.js, which were used for IE 8 and IE 9
  compatibility. (#2973)

* Removed es5-shim library, which was internally used within
  `selectInput()` for ECMAScript 5 compatibility. (#2993)


shiny 1.5.0
===========

## Full changelog

### Breaking changes

* Fixed #2869: Until this release, `renderImage()` had a dangerous default
  of `deleteFile = TRUE`. (Sorry!) Going forward, calls to `renderImage()`
  will need an explicit `deleteFile` argument; for now, failing to provide
  one will result in a warning message, and the file will be deleted if it
  appears to be within the `tempdir()`. (#2881)

### New features

* The new `shinyAppTemplate()` function creates a new template Shiny
  application, where components are optional, such as helper files in an R/
  subdirectory, a module, and various kinds of tests. (#2704)

* `runTests()` is a new function that behaves much like R CMD
  check. `runTests()` invokes all of the top-level R files in the tests/
  directory inside an application, in that application's
  environment. (#2585)

* `testServer()` is a new function for testing reactive behavior inside
  server functions and
  modules. ([#2682](rstudio/shiny#2682),
  [#2764](rstudio/shiny#2764),
  [#2807](rstudio/shiny#2807))

* The new `moduleServer` function provides a simpler interface for creating
  and using modules. (#2773)

* Resolved #2732: `markdown()` is a new function for writing Markdown with
  Github extensions directly in Shiny UIs. Markdown rendering is performed
  by the [commonmark](https://github.com/jeroen/commonmark)
  package. (#2737)

* The `getCurrentOutputInfo()` function can now return the background color
  (`bg`), foreground color (`fg`), `accent` (i.e., hyperlink) color, and
  `font` information of the output's HTML container. This information is
  reported by `plotOutput()`, `imageOutput()`, and any other output
  bindings containing a class of `.shiny-report-theme`. This feature allows
  developers to style an output's contents based on the container's CSS
  styling.  (#2740)

### Minor new features and improvements

* Fixed #2042, #2628: In a `dateInput` and `dateRangeInput`, disabled
  months and years are now a lighter gray, to make it easier to see that
  they are disabled. (#2690)

* `getCurrentOutputInfo()` previously threw an error when called from
  outside of an output; now it returns `NULL`. (#2707 and #2858)

* Added a label to observer that auto-reloads `R/` directory to avoid
  confusion when using `reactlog`. (#58)

* `getDefaultReactiveDomain()` can now be called inside a
  `session$onSessionEnded` callback and will return the calling `session`
  information. (#2757)

* Added a `'function'` class to `reactive()` and `reactiveVal()`
  objects. (#2793)

* Added a new option (`type = "hidden"`) to `tabsetPanel()`, making it
  easier to set the active tab via other input controls (e.g.,
  `radioButtons()`) rather than tabs or pills. Use this option in
  conjunction with `updateTabsetPanel()` and the new `tabsetPanelBody()`
  function (see `help(tabsetPanel)` for an example and more details).
  (#2814)

* Added function `updateActionLink()` to update an `actionLink()` label
  and/or icon value. (#2811)

* Fixed #2856: Bumped jQuery 3 from 3.4.1 to 3.5.1. (#2857)

### Bug fixes

* Fixed #2606: `debounce()` would not work properly if the code in the
  reactive expression threw an error on the first run. (#2652)

* Fixed #2653: The `dataTableOutput()` could have incorrect output if
  certain characters were in the column names. (#2658)

### Documentation Updates

### Library updates

* Updated from Font-Awesome 5.3.1 to 5.13.0, which includes icons related
  to COVID-19. For upgrade notes, see
  https://github.com/FortAwesome/Font-Awesome/blob/master/UPGRADING.md. (#2891)


shiny 1.4.0.2
===========

Minor patch release: fixed some timing-dependent tests failed
intermittently on CRAN build machines.


shiny 1.4.0.1
===========

Minor patch release to account for changes to the grid package that will be
upcoming in the R 4.0 release (#2776).


shiny 1.4.0
===========

## Full changelog

### Breaking changes

* Resolved #2554: Upgraded jQuery from v.1.12.4 to v3.4.1 and bootstrap
  from v3.3.7 to v3.4.1. (#2557). Since the jQuery upgrade may introduce
  breaking changes to user code, there is an option to switch back to the
  old version by setting `options(shiny.jquery.version = 1)`. If you've
  hard-coded `shared/jquery[.min].js` in the HTML of your Shiny app, in
  order to downgrade, you'll have to change that filepath to
  `shared/legacy/jquery[.min].js`.

### Improvements

* Resolved #1433: `plotOutput()`'s coordmap info now includes discrete axis
  limits for **ggplot2** plots. As a result, any **shinytest** tests that
  contain **ggplot2** plots with discrete axes (that were recorded before
  this change) will now report differences that can safely be updated. This
  new coordmap info was added to correctly infer what data points are
  within an input brush and/or near input click/hover in scenarios where a
  non-trivial discrete axis scale is involved (e.g., whenever
  `scale_[x/y]_discrete(limits = ...)` and/or free scales across multiple
  discrete axes are used). (#2410)

* Resolved #2402: An informative warning is now thrown for mis-specified
  (date) strings in `dateInput()`, `updateDateInput()`, `dateRangeInput()`,
  and `updateDateRangeInput()`. (#2403)

* If the `shiny.autoload.r` option is set to `TRUE`, all files ending in
  `.r` or `.R` contained in a directory named `R/` adjacent to your
  application are sourced when your app is started. This will become the
  default Shiny behavior in a future release (#2547)

* Resolved #2442: The `shiny:inputchanged` JavaScript event now triggers on
  the related input element instead of `document`. Existing event listeners
  bound to `document` will still detect the event due to event
  bubbling. (#2446)

* Fixed #1393, #2223: For plots with any interactions enabled, the image is
  no longer draggable. (#2460)

* Resolved #2469: `renderText` now takes a `sep` argument that is passed to `cat`. (#2497)

* Added `resourcePaths()` and `removeResourcePaths()` functions. (#2459)

* Resolved #2433: An informative warning is now thrown if subdirectories of
  the app's `www/` directory are masked by other resource prefixes and/or
  the same resource prefix is mapped to different local file paths. (#2434)

* Resolved #2478: `cmd + shift + f3` and `ctrl + shift + f3` can now be
  used to add a reactlog mark. If reactlog keybindings are used and the
  reactlog is not enabled, an error page is displayed showing how to enable
  reactlog recordings. (#2560)

### Bug fixes

* Partially resolved #2423: Reactivity in Shiny leaked some memory, because
  R can leak memory whenever a new symbols is interned, which happens
  whenever a new name/key is used in an environment. R now uses the fastmap
  package, which avoids this problem. (#2429)

* Fixed #2267: Fixed a memory leak with `invalidateLater`. (#2555)

* Fixed #1548: The `reactivePoll` function leaked an observer; that is the
  observer would continue to exist even if the `reactivePoll` object was no
  longer accessible. #2522

* Fixed #2116: Fixed an issue where dynamic tabs could not be added when on
  a hosted platform. (#2545)

* Resolved #2515: `selectInput()` and `selectizeInput()` now deal
  appropriately with named factors. Note that `updateSelectInput()` and
  `updateSelectizeInput()` **do not** yet handle factors; their behavior is
  unchanged. (#2524, #2540, #2625)

* Resolved #2471: Large file uploads to a Windows computer were
  slow. (#2579)

* Fixed #2387: Updating a `sliderInput()`'s type from numeric to date no
  longer changes the rate policy from debounced to immediate. More
  generally, updating an input binding with a new type should (no longer)
  incorrectly alter the input rate policy. (#2404)

* Fixed #868: If an input is initialized with a `NULL` label, it can now be
  updated with a string. Moreover, if an input label is initialized with a
  string, it can now be removed by updating with `label=character(0)`
  (similar to how `choices` and `selected` can be cleared in
  `updateSelectInput()`). (#2406)

* Fixed #2250: `updateSliderInput()` now works with un-specified (or
  zero-length) `min`, `max`, and `value`. (#2416)

* Fixed #2396: `selectInput("myID", ...)` resulting in an extra
  `myID-selectized` input (introduced in v1.2.0). (#2418)

* Fixed #2233: `verbatimTextOutput()` produced wrapped text on Safari, but
  the text should not be wrapped. (#2353)

* Fixed #2335: When `dateInput()`'s `value` was unspecified, and `max`
  and/or `min` was set to `Sys.Date()`, the value was not being set
  properly. (#2526)

* Fixed #2591: Providing malformed date-strings to `min` or `max` no longer
  results in JS errors for `dateInput()` and `dateRangeInput()`. (#2592)

* Fixed
  [rstudio/reactlog#36](rstudio/reactlog#36):
  Changes to reactive values not displaying accurately in reactlog. (#2424)

* Fixed #2598: Showcase files don't appear with a wide window. (#2582)

* Fixed #2329, #1817: These bugs were reported as fixed in Shiny 1.3.0 but
  were not actually fixed because some JavaScript changes were accidentally
  not included in the release. The fix resolves issues that occur when
  `withProgressBar()` or bookmarking are combined with the
  [networkD3](https://christophergandrud.github.io/networkD3/) package's
  Sankey plot.
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

Successfully merging this pull request may close these issues.

2 participants