knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  eval = FALSE
)

Reactor and Golem

Reactor is built to run regular Shiny Applications and ones that are packaged using the golem package.

In this example we are using package called puzzlemath.

Puzzlemath

This application is made for creating simple arithmetic questions for the user and given a correct answer a piece of the "puzzle" is revealed to the user.

The user can control the application using the following inputs:

The application has the following outputs:

whereami observers

whereami observers are placed in the reactive part of the application to log when chunks are being triggered by shiny.

We use this in order to track reactivity while the application is running and test expected reactivity against it.

The observers placed in puzzlemath are placed in the following places in order to test the reactivity of the plotting and when new questions are drawn.

Testing Reactivity with Reactor

Intialize reactor

reactor starts with initialization of the reactor object and populating the application and the webdriver fields. In this example we are using a golem based application and a chrome webdriver.

RSelenium will run more consistently with an explicit assignment of the web driver version. For this reactor comes with it a function that returns the version of chrome that is installed on the system chrome_version().

library(reactor)
obj <- init_reactor()%>%
  set_golem_args(
    package_name = 'puzzlemath'
  )%>%
  set_chrome_driver(
    chromever = chrome_version()
  )

Starting reactor

Once the reactor fields are populated reactor can be started. This step will create two child processes one for hosting the application and the other for hosting the webdriver to interact with the application.

obj <- obj%>%
  start_reactor()

Testing reactivity at application startup

Usually there are reactive components being invalidated at application startup. For this app the inputs plot and draw are both expected to be invalidated once.

obj%>%
  expect_reactivity('plot',1)%>%
  expect_reactivity('draw',1)

Sending Commands to the Application

We now want to do something in the application, click the draw button. Once it is clicked we are expecting a new question to be drawn, but not rerendering the plot.

obj%>%
  click_id('draw')%>%
  expect_reactivity('plot',1)
  expect_reactivity('draw',2)

The application has a sliderInput object with the id 'range' which controls the range of values that can be used in each question. Once it is clicked a new game is created and a question is drawn. We test that following expectation.

obj%>%
  set_id_value('range',c(10,20))%>%
  expect_reactivity('plot',2)%>%
  expect_reactivity('draw',3)

Querying the Application

Now we are interested in querying the value of a question in order to send correct value to the appropriate textInput with an id 'ans' using set_id_value().

We can do this with query_output_id() using the 'ques' id, the result is in the form of a question, e.g. '3 + 1 ?'

obj%>%
  query_output_id('ques')%>%
  gsub('\\?','',.)%>%
  parse(text = .)%>%
  eval()%>%
  set_id_value(
    obj = obj, 
    id = 'ans'
  )

Given the correct answer the app is supposed to change the border of the div surrounding the textInput with the color green.

We can send a query to the app using query_style_id() that queries the style of an element by element id and return the value to R. The argument flatten is used to unlist the result and return the character.

We can test this expectation using testthat expectations.

obj%>%
  query_style_id(
    id = 'anspanel',
    style = 'borderColor',
    flatten = TRUE
  )%>%
  testthat::expect_equal(
    expected = "green"
  )

Closing Reactor

To cleanly close reactor we run the following.

obj%>%
  kill_app()


yonicd/reactor documentation built on Jan. 20, 2021, 4:40 a.m.