From b784e1c28a3762155f250c71456cebf70798b35f Mon Sep 17 00:00:00 2001 From: Martin Frigaard Date: Mon, 6 Nov 2023 14:11:32 -0800 Subject: [PATCH] Built site for gh-pages --- .nojekyll | 2 +- app_packages.html | 2 +- debugging.html | 42 +++++------ development.html | 6 +- document.html | 2 +- external.html | 38 +++++----- golem.html | 34 ++++----- launch.html | 30 ++++---- leprechaun.html | 183 +++++++++++++++++++++++++--------------------- packages.html | 4 +- rhino.html | 24 +++--- search.json | 39 +++------- shiny.html | 50 ++++++------- sitemap.xml | 70 +++++++++--------- test_modules.html | 18 ++--- test_specs.html | 15 ++-- test_suite.html | 51 +++++++++++-- test_tools.html | 50 ++++++------- whole_game.html | 2 +- 19 files changed, 348 insertions(+), 314 deletions(-) diff --git a/.nojekyll b/.nojekyll index ee177c4..467e97b 100644 --- a/.nojekyll +++ b/.nojekyll @@ -1 +1 @@ -a592afa8 \ No newline at end of file +06cd5fb0 \ No newline at end of file diff --git a/app_packages.html b/app_packages.html index bca1c42..b58cd02 100644 --- a/app_packages.html +++ b/app_packages.html @@ -567,7 +567,7 @@

Development (Chapter
1
-Always leave an empty line in the DESCRIPTION +Always leave an empty line in the DESCRIPTION
diff --git a/debugging.html b/debugging.html index c67dc18..9e9c8e4 100644 --- a/debugging.html +++ b/debugging.html @@ -490,12 +490,12 @@

<
1
-observe() function scope
+observe() function scope
2
-Call to browser() (called at the top of the observe() scope) +Call to browser() (called at the top of the observe() scope)
@@ -603,12 +603,12 @@

Debugging app func
1
-Observer scope
+Observer scope
2
-Activate debugger +Activate debugger
@@ -670,7 +670,7 @@

Module communication<
1
-Reactive values returned from variable input module +Reactive values returned from variable input module
@@ -684,11 +684,11 @@

Module communication<
1
-Reactive values returned from variable input module +Reactive values returned from variable input module
2
-Variable inputs passed to scatter plot display module +Variable inputs passed to scatter plot display module
@@ -799,7 +799,7 @@

Debugging modules

1
-Wrap browser() in observe() and place after the call to moduleServer() +Wrap browser() in observe() and place after the call to moduleServer()
@@ -873,12 +873,12 @@

Verify variable inp
1
-Variable inputs (from selected_vars)
+Variable inputs (from selected_vars)
2
-inputs() for scatter_plot() +inputs() for scatter_plot()
@@ -947,12 +947,12 @@

Verify graph

1
-Observe scope
+Observe scope
2
-Call to browser() +Call to browser()
@@ -1035,7 +1035,7 @@
1
-Location of debugger in utility function +Location of debugger in utility function
@@ -1093,17 +1093,17 @@

Exploring code

1
-Observer scope
+Observer scope
2
-Call to browser()
+Call to browser()
3
-Additional module code omitted +Additional module code omitted
@@ -1300,12 +1300,12 @@

Debugging apps

1
-Optional label
+Optional label
2
-Include the ns() for the inputId +Include the ns() for the inputId
@@ -1326,17 +1326,17 @@

Debugging apps

1
-Collect reactive values in module
+Collect reactive values in module
2
-Print these values to the UI
+Print these values to the UI
3
-Include all reactive objects +Include all reactive objects
diff --git a/development.html b/development.html index 4290c5a..03ac643 100644 --- a/development.html +++ b/development.html @@ -597,7 +597,7 @@

1
-Leave an empty final line in the DESCRIPTION +Leave an empty final line in the DESCRIPTION
@@ -755,12 +755,12 @@
1
-The Encoding value shouldn’t include quotes like the warning message above (i.e., UTF-8)
+The Encoding value shouldn’t include quotes like the warning message above (i.e., UTF-8)
2
-Always leave an empty final line in the DESCRIPTION +Always leave an empty final line in the DESCRIPTION
diff --git a/document.html b/document.html index 8fe4e9c..4caced3 100644 --- a/document.html +++ b/document.html @@ -577,7 +577,7 @@

1
-Always leave at least one empty final line in your DESCRIPTION file. +Always leave at least one empty final line in your DESCRIPTION file.
diff --git a/external.html b/external.html index 1fc1536..da40368 100644 --- a/external.html +++ b/external.html @@ -533,7 +533,7 @@

Our app-package file
1
-This is the location of the installed version of moviesApp +This is the location of the installed version of moviesApp
@@ -722,17 +722,17 @@

1
-Prefix (or folder name) of installed location
+Prefix (or folder name) of installed location
2
-Path to installed package files
+Path to installed package files
3
-Reference to installed package image file +Reference to installed package image file
@@ -878,22 +878,22 @@

1
-Include inst/www resources
+Include inst/www resources
2
-Standard fluidPage()
+Standard fluidPage()
3
-bslib layout
+bslib layout
4
-Reference to alternate image (bootstrap.png) +Reference to alternate image (bootstrap.png)
@@ -1099,12 +1099,12 @@
Modules
1
-Alternate help text for ggplot2movies data
+Alternate help text for ggplot2movies data
2
-Check-box to remove missing values +Check-box to remove missing values
@@ -1169,17 +1169,17 @@
Modules
1
-Build reactive data based on missing checkbox input
+Build reactive data based on missing checkbox input
2
-Bind missing input to update when UI changes
+Bind missing input to update when UI changes
3
-Bind plot output to update with variable inputs and ‘missing’ checkbox output +Bind plot output to update with variable inputs and ‘missing’ checkbox output
@@ -1239,21 +1239,21 @@
UI and server
1
-Add alternate path to include image file +Add alternate path to include image file
2
-Development variable input module (UI)
+Development variable input module (UI)
3
-Refer to alternate image
+Refer to alternate image
4
-Development scatter-plot display module (UI) +Development scatter-plot display module (UI)
@@ -1273,11 +1273,11 @@
UI and server
1
-mod_var_input_server() exported from moviesApp’s R/ folder +mod_var_input_server() exported from moviesApp’s R/ folder
2
-Defined in dev/inst/app.R +Defined in dev/inst/app.R
diff --git a/golem.html b/golem.html index 6530d0f..6e57ffa 100644 --- a/golem.html +++ b/golem.html @@ -566,41 +566,41 @@

Development

1
-Turn off loadSupport()
+Turn off loadSupport()
2
-Configure app functions +Configure app functions
3
-App UI and server functions
+App UI and server functions
4
-Data documentation
+Data documentation
5
-golem utility functions
+golem utility functions
6
-Scatter plot module
+Scatter plot module
7
-Variable input module
+Variable input module
8
-Standalone app function +Standalone app function
@@ -676,20 +676,20 @@

Development

1
-These come ‘pre-packaged’ in golem apps +These come ‘pre-packaged’ in golem apps
2
-Module and utility functions
+Module and utility functions
3
-Data documentation +Data documentation
4
-The ‘pre-packaged’ standalone app function is the only export from golem apps. +The ‘pre-packaged’ standalone app function is the only export from golem apps.
@@ -730,23 +730,23 @@

Development

1
-Created with: golem::use_recommended_tests() +Created with: golem::use_recommended_tests()
2
-Created with: golem::use_utils_ui(with_test = TRUE) +Created with: golem::use_utils_ui(with_test = TRUE)
3
-Created with: golem::use_utils_server(with_test = TRUE) +Created with: golem::use_utils_server(with_test = TRUE)
4
-Created with: golem::add_module(name = 'plot', with_test = TRUE, export = TRUE, utils = 'server') +Created with: golem::add_module(name = 'plot', with_test = TRUE, export = TRUE, utils = 'server')
5
-Created with: golem::add_module(name = 'var_input', with_test = TRUE, export = TRUE) +Created with: golem::add_module(name = 'var_input', with_test = TRUE, export = TRUE)
diff --git a/launch.html b/launch.html index 79c1502..6f0a4ae 100644 --- a/launch.html +++ b/launch.html @@ -534,17 +534,17 @@

1
-Install packages (if needed)
+Install packages (if needed)
2
-Load package
+Load package
3
-Call standalone app function +Call standalone app function
@@ -605,7 +605,7 @@

1
-The movies_app() standalone function +The movies_app() standalone function
@@ -744,12 +744,12 @@

<
1
-appDir is the first argument of runApp()
+appDir is the first argument of runApp()
2
-A shiny app object +A shiny app object
@@ -925,12 +925,12 @@

1
-Build the shiny app object with movies_ui and movies_server
+Build the shiny app object with movies_ui and movies_server
2
-Include options list +Include options list
@@ -1027,17 +1027,17 @@

Updated
1
-Check if interactive (Workbench) launch
+Check if interactive (Workbench) launch
2
-Set shinyViewerType option with display_type()
+Set shinyViewerType option with display_type()
3
-Launch app +Launch app
@@ -1208,22 +1208,22 @@

1
-Turn off loadSupport()
+Turn off loadSupport()
2
-Define non-interactive behaviors
+Define non-interactive behaviors
3
-Define interactive behaviors
+Define interactive behaviors
4
-Launch app (with options) +Launch app (with options)
diff --git a/leprechaun.html b/leprechaun.html index 96977d8..98f9934 100644 --- a/leprechaun.html +++ b/leprechaun.html @@ -371,15 +371,16 @@

Contents

  • lap (a leprechaun app-package)
  • Set up
  • -
  • App code
  • -
  • App files
  • +
  • Development +
  • Tests
  • lap dependencies
  • Recap
  • @@ -439,10 +440,10 @@

    leprechaun


      -
    • leprechaun helps keep your app-package dependencies low (think golem à la carte)

    • +
    • leprechaun has many of the same features found in the golem framework, but without the added dependencies (think golem à la carte)

    • Helper functions for creating modules, app.R files, JavaScript, CSS, SCSS, HTML, etc.

    • leprechaun apps come ‘pre-packaged’ with UI, server, and standalone app functions

    • -
    • Add functionality with a variety of use_* functions that are ‘bundled’ into the inst/ folder:

      +
    • Additional features and functionality are added with a variety of use_* functions ‘bundle’ resources in the inst/ folder:

      • use_sass(), use_config(), use_packer() (with use_js_utils()), etc.
    • @@ -502,7 +503,24 @@

      lap

      Set up

      -

      Create new leprechaun app-packages with usethis::create_package('lap'). After the package is created, leprechaun::scaffold() 1 builds the core app files:2

      +

      Creating a new leprechaun app-package can be done with usethis::create_package() (covered in Packages).1

      +

      After your app-package is created, leprechaun::scaffold() builds the core app files: 2

      +
        +
      • Code files: the code files in new leprechaun apps include the following:

        +
          +
        • _disable_autoload.R: Disables shiny::loadSupport() (covered in Launch)

        • +
        • assets.R: includes serveAssets() for serving JavaScript files, remove_modules() and get_modules() for adding/removing modules, and the collapse_files() helper function for collapsing files.3

        • +
        • input-handlers.R: leprechaun_handler_df() and leprechaun_handler_list() are helper functions for including data and lists “from Websocket”.4

        • +
        • leprechaun-utils.R: includes a make_send_message() function for “send custom messages to the front-end” with the “namespace carried along”. Read below for demonstration of how this is used.5

        • +
        • run.R: the standalone app function for your leprechaun app (covered in Launch).

        • +
        • server.R & ui.R are applications primary UI and server functions.

          +
            +
          • ui: contains the application UI and the assets() function (which calls serveAssets() covered above).6

          • +
          • server.R: creates send_message from make_send_message(session) (covered below).7

          • +
        • +
        • zzz.R is a utility function file that holds the .onLoad() function for adding external resources (using methods covered in External files).8
        • +
      • +
      R
       ├── _disable_autoload.R
      @@ -557,7 +575,9 @@ 

      Set up

      -

      shiny, bslib, htmltools and pkgload are added to the DESCRIPTION.

      +
        +
      • Adding dependencies: shiny, bslib, htmltools and pkgload should be added to the DESCRIPTION with usethis::use_package() (covered in the Dependencies chapter).
      • +
      Imports: 
           bslib,
      @@ -566,72 +586,67 @@ 

      Set up

      Suggests: pkgload
      -

      The lap folder structure should look familiar if you’ve been following along with the previous chapters. The standard R package files and folders (DESCRIPTION, NAMESPACE, R/, and .Rproj) are accompanied by inst/ sub-folders (recall that inst/ contents are available when the package is installed) and a .leprechaun lock file.

      +

      The lap folder structure should look familiar if you’ve been following along with the previous chapters. The standard R package files (DESCRIPTION, NAMESPACE, and .Rproj) are accompanied by a .leprechaun lock file.

      lap/
       ├── .leprechaun
       ├── DESCRIPTION
       ├── NAMESPACE
      -├── inst/
      -   ├── assets
      -   ├── dev
      -   ├── img
      -   └── run
      -       └── app.R
      -└── moviesApp.Rproj
      +└── moviesApp.Rproj
      +

      The initial call to leprechaun::scaffold() creates the following folders in the inst/ folder (recall that inst/ contents are available when the package is installed).

      +
      +
      inst/
      +├── assets
      +├── dev
      +├── img
      +└── run
      +    └── app.R
      +
      +5 directories, 1 file
      +
      +

      inst/run/app.R contains a call to leprechaun::build(), pkgload::load_all(), then a call to the standalone app function, run().9

      -
      -

      App code

      +
      +

      Development

        -
      • Code files: new code files in leprechaun apps can be created with usethis::use_r() or with leprechaun’s helper functions.

        +
      • Code files: new code files in leprechaun apps can be created with usethis::use_r() or with a helper function:

          -
        • Modules: Add modules with leprechaun::add_module("name") 3

          +
        • Create modules with add_module(). Modules created with add_module("name") will have:10
            -
          • Module files created with add_module() have a module_ prefix.

          • +
          • A module file with a module_name prefix (R/module_name.R)
          • +
          • A module UI function: nameUI()
          • +
          • A module server function: name_server()
            +
          • +
        • +
        • Create an app.R file with add_app_file(). This includes a call to pkgload::load_all() and run().11

      • -
      • Run: R/run.R contains functions for running the app.4

      • -
      • UI and server: Add the modules to R/ui.R and R/server.R.

        +
      • App files: R/run.R contains functions for running the app.12

        +
          +
        • Add the modules to R/ui.R and R/server.R.

            -
          • R/server.R includes the send_message and make_send_message(session) functions by default.5

          • -
          • R/ui.R holds the ui() and assets() functions.6

          • +
          • R/server.R includes a call to send_message by default.13

          • +
          • R/ui.R holds the ui() and assets() functions.14

        • -
        • Utility function: R/utils_scatter_plot.R holds the scatter_plot() utility function.7

        • -
        • Adding external files: The R/zzz.R file contains the .onLoad() function 8

        • -
        • app.R file: include an app.R in the root directory using add_app_file() 9
        • +
        • Utility function: R/utils_scatter_plot.R holds the scatter_plot() utility function.15

        • +
        • Adding files: The R/zzz.R file contains the .onLoad() function, which wraps system.file('img', package = 'lap') and addResourcePath() for including external resources.

      -
      R
      -├── module_plot_display.R
      -├── module_var_input.R
      -├── run.R
      -├── server.R
      -├── ui.R
      -└── utils_scatter_plot.R
      -
      -1 directory, 6 files
      -
      -
      -
      -

      App files

      -

      The initial call to leprechaun::scaffold() creates the following folders in the inst/ folder

      -
      -
      inst
      -├── assets
      -├── dev
      -├── img
      -└── run
      -    └── app.R
      -
      -5 directories, 1 file
      -
      -

      The inst/run/app.R looks like a standard app.R file, but it’s not.10

      -
      -
      -

      Data files

      +
      R
      +├── module_plot_display.R
      +├── module_var_input.R
      +├── run.R
      +├── server.R
      +├── ui.R
      +└── utils_scatter_plot.R
      +
      +1 directory, 6 files
      + +
      +

      Data files

        -
      • Including data files: the movies.RData data was moved into inst/extdata, then loaded into data/ with the script created with usethis::use_data_raw('movies'):
      • +
      • Including data files: the movies.RData data was moved into inst/extdata, then loaded into data/ with the script created with usethis::use_data_raw('movies') (similar to methods covered in the Data chapter):
      data-raw/
      @@ -651,11 +666,11 @@ 

      Data files

      1 directory, 1 file
      -
      -

      leprechaun features

      +
      +

      Adding features

      The leprechaun workflow involves a combination of use_ functions that are combined with leprechaun::build() to add various functionality to your application. I’ll demonstrate three options in the sections below:

      -
      -

      Use packer

      +
      +

      Use packer

      I’ll demo using the make_send_message() from the JavaScript example on the package website:

      • Run packer::scaffold_leprechaun()

        @@ -665,7 +680,7 @@

        Use packer

      • Run leprechaun::use_packer()

      • Run leprechaun::build()
      -

      This creates inst/dev/packer.R and inst/assets/index.js.11

      +

      This creates inst/dev/packer.R and inst/assets/index.js.16

      inst
       ├── assets
      @@ -740,9 +755,9 @@ 
      -
      -

      Add images

      -

      I’ll demonstrate adding an image file (leprechaun.jpg) to the UI function.

      +
      +

      Add images

      +

      Adding images is simplified with the .onLoad() function, which I’ll demonstrate by adding the leprechaun.jpg image file to the UI function.

      • Place the leprechaun.jpg file in inst/img/

      • Add the img/ path to the code to UI:
      • @@ -787,8 +802,8 @@
      -
      -

      Use Sass

      +
      +

      Use Sass

      To add Sass styling, I can use leprechaun’s use_sass() function

      +

      Tests

      leprechaun doesn’t any specific support for testing (like the golem framework), but we can create tests using any combination of testthat, testServer(), and shinytest2.

      @@ -886,9 +902,7 @@

      Recap

      “it generates code and does not make itself a dependency of the application you build; this means applications are leaner, and smaller”

      -

      leprechaun is similar to golem in that it ‘bundles’ various app-package development functions into helper/utility functions. For example, the .onLoad() function is a wrapper for:

      -
      shiny::addResourcePath("img", system.file("img", package = "lap"))
      -

      .onLoad() saves some time because you won’t have to add the code above to the UI (at the cost of making your app code less clear and explicit).

      +

      leprechaun is similar to golem in that it ‘bundles’ various app-package development functions into helper/utility functions. For example, the .onLoad() function saves some time (at the cost of making your app code less clear and explicit).

      leprechaun also relies on external packages like packer to integrate and bundle external code files, so becoming more familiar with these packages will extend what you can build with leprechaun.

      @@ -896,18 +910,23 @@

      Recap


        -
      1. leprechaun::scaffold() has arguments for ui (fluidPage or navbarPage) bs_version (bootstrap version) and overwrite (if you need to start over).↩︎

      2. -
      3. Remember to provide a list of fields to usethis::create_package() for the DESCRIPTION file (or edit this manually).↩︎

      4. -
      5. leprechaun modules created with add_module() have the following naming convention: leprechaun::add_module("name") creates var_inputUI() and var_input_server().↩︎

      6. -
      7. R/run.R includes functions for running the production (run()) and development (run_dev()) version of the application.↩︎

      8. -
      9. make_send_message() is in R/leprechaun-utils.R.↩︎

      10. -
      11. assets() loads the resources called in the R/assets.R file with the serveAssets() function.↩︎

      12. -
      13. The same scatter_plot() function from moviesApp (i.e, imports .data from rlang)↩︎

      14. -
      15. .onLoad() is a wrapper for shiny::addResourcePath('img', system.file('img', package = 'lap'))↩︎

      16. -
      17. the app.R file includes a call to pkgload::load_all().↩︎

      18. -
      19. inst/run/app.R contains a call to leprechaun::build(), then pkgload::load_all().↩︎

      20. -
      21. Using packer will download multiple folders into your leprechaun app package root folder (srcjs/, node_modules/, package-lock.json, package.json, webpack.common.js, webpack.dev.js, webpack.prod.js). These are not necessary and can be removed (but do not remove inst/dev/packer.R and inst/assets/index.js).↩︎

      22. -
      23. The scss folder is added to the root directory, but after running leprechaun::build() and creating inst/dev/sass.R, this folder can be removed.↩︎

      24. +
      25. Remember to provide a list of fields to usethis::create_package() for the DESCRIPTION file (or edit this manually).↩︎

      26. +
      27. leprechaun::scaffold() has arguments for ui (fluidPage or navbarPage) bs_version (bootstrap version) and overwrite (if you need to start over).↩︎

      28. +
      29. Link to R/assets.R file.↩︎

      30. +
      31. Link to R/input-handlers.R file.↩︎

      32. +
      33. Link to R/leprechaun-utils.R file.↩︎

      34. +
      35. Link to R/ui.R file.↩︎

      36. +
      37. Link to R/server.R file.↩︎

      38. +
      39. Link to R/zzz.R file.↩︎

      40. +
      41. Link to inst/run/app.R file.↩︎

      42. +
      43. leprechaun modules do not have the same naming conventions as golem (or that I’ve recommended throughout this book).↩︎

      44. +
      45. pkgload::load_all() has reset set to TRUE and helpers set to FALSE.↩︎

      46. +
      47. R/run.R includes functions for running the production (run()) and development (run_dev()) version of the application.↩︎

      48. +
      49. make_send_message() is in R/leprechaun-utils.R.↩︎

      50. +
      51. assets() loads the resources called in the R/assets.R file with the serveAssets() function.↩︎

      52. +
      53. The same scatter_plot() function from moviesApp (i.e, imports .data from rlang)↩︎

      54. +
      55. Using packer will download multiple folders into your leprechaun app package root folder (srcjs/, node_modules/, package-lock.json, package.json, webpack.common.js, webpack.dev.js, webpack.prod.js). These are not necessary and can be removed (but do not remove inst/dev/packer.R and inst/assets/index.js).↩︎

      56. +
      57. The scss folder is added to the root directory, but after running leprechaun::build() and creating inst/dev/sass.R, this folder can be removed.↩︎

      diff --git a/packages.html b/packages.html index e4ab52e..365f8d3 100644 --- a/packages.html +++ b/packages.html @@ -675,7 +675,7 @@

      1
      -Leave an empty final line in the DESCRIPTION +Leave an empty final line in the DESCRIPTION
      @@ -1124,7 +1124,7 @@

      IDE arguments

      1
      -Leave an empty final line in the DESCRIPTION +Leave an empty final line in the DESCRIPTION
      diff --git a/rhino.html b/rhino.html index c98432a..365df85 100644 --- a/rhino.html +++ b/rhino.html @@ -528,30 +528,30 @@

      rap (a
      1
      -Activates the renv package +Activates the renv package
      2
      -CI/CD via GitHub actions
      +CI/CD via GitHub actions
      3
      -Lintr (from lintr package)
      +Lintr (from lintr package)
      4
      -renv ignore (works like .gitignore)
      +renv ignore (works like .gitignore)
      5
      -rhino app dependencies +rhino app dependencies
      6
      -renv library of packages in app project +renv library of packages in app project
      @@ -583,12 +583,12 @@

      box modules

      1
      -Non-shiny code
      +Non-shiny code
      2
      -Shiny modules and app code +Shiny modules and app code
      @@ -667,12 +667,12 @@

      Tests

      1
      -Cypress test infrastructure
      +Cypress test infrastructure
      2
      -testthat test infrastructure +testthat test infrastructure
      @@ -697,11 +697,11 @@

      Tests

      1
      -box module importing test package functions +box module importing test package functions
      2
      -Using shiny::testServer() and testthat::test_that() functions in test. +Using shiny::testServer() and testthat::test_that() functions in test.
      diff --git a/search.json b/search.json index c45ab28..7f70fb4 100644 --- a/search.json +++ b/search.json @@ -655,7 +655,7 @@ "href": "test_suite.html#creating-unit-tests", "title": "Test suite", "section": "Creating unit tests", - "text": "Creating unit tests\nThe standard workflow for writing testthat unit tests consists of the following:\n\nNew tests are created with usethis::use_test():\n\n\nusethis::use_test(\"scatter_plot\") \n\n\ntestthat recommends having a corresponding test file in tests/testthat/ (with the test- prefix) for the files in R/.\n\n\ntest- files\n\nTest files: the IDE will automatically create and open the new test file:\n\n✔ Writing 'tests/testthat/test-scatter_plot.R'\n• Modify 'tests/testthat/test-scatter_plot.R'\n\n\ntest_that() tests\n\nEach new test file contains a boilerplate test_that() test:\n\n\n1test_that(desc = \"multiplication works\", code = {\n \n})\n\n\n1\n\ndesc is the test context (supplied in \"quotes\"), and code is the test code (supplied in {curly brackets}).\n\n\n\n\n\n\nexpect_ations\n\nExpectation typically have two parts: an observed object, and an expected object:\n\n\n1expect_equal(\n2 object = 2 * 2,\n3 expected = 4\n ) \n\n\n1\n\nA testthat expectation function\n\n\n2\n\nThe output or behavior being tested\n\n\n3\n\nA predefined output or behavior\n\n\n\n\n\nThe observed object is an artifact of some code we’ve written, and it’s being compared against an expected result.\n\n\n\nRunning tests\n\nAnother devtools habit to adopt is regularly writing and running tests. If you’re using Posit Workbench and have devtools installed, you can test your app-package using the Build pane or the keyboard shortcut: Ctrl/Cmd + Shift + T\n\n\n\n\n\n\nRun all tests\n\n\n\n\nKeyboard shortcuts\nR Packages, 2ed also suggests binding test_active_file() and test_coverage_active_file() to keyboard shortcuts. I highly recommend using a shortcut while developing tests because it will improve your ability to iterate quickly.\n\n\n\ndevtools function\ntest()\n\n\n \n\n\nKeyboard shortcut\nCtrl/Cmd + Shift + T\n\n\n\n\n\n\ntest_active_file()\n\n\n \n\n\nCtrl/Cmd + T\n\n\n\n\n\n\ntest_coverage_active_file()\n\n\n \n\n\nCtrl/Cmd + Shift + R\n\n\n\nWhen the test is run, we’ll see feedback on whether it passes or fails (and occasionally some encouragement):\n\ntest_that(\"multiplication works\", { \n expect_equal( \n object = 2 * 2, \n expected = 4 \n ) \n})\n## Test passed 🥇" + "text": "Creating unit tests\nThe standard workflow for writing testthat unit tests consists of the following:\n\nNew tests are created with usethis::use_test():\n\n\nusethis::use_test(\"scatter_plot\") \n\n\ntestthat recommends having a corresponding test file in tests/testthat/ (with the test- prefix) for the files in R/.\n\n\ntest- files\n\nTest files: the IDE will automatically create and open the new test file:\n\n✔ Writing 'tests/testthat/test-scatter_plot.R'\n• Modify 'tests/testthat/test-scatter_plot.R'\n\n\ntest_that() tests\n\nEach new test file contains a boilerplate test_that() test:\n\n\n1test_that(desc = \"multiplication works\", code = {\n \n})\n\n\n1\n\ndesc is the test context (supplied in \"quotes\"), and code is the test code (supplied in {curly brackets}).\n\n\n\n\n\n\nexpect_ations\n\nExpectation typically have two parts: an observed object, and an expected object:\n\n\n1expect_equal(\n2 object = 2 * 2,\n3 expected = 4\n ) \n\n\n1\n\nA testthat expectation function\n\n\n2\n\nThe output or behavior being tested\n\n\n3\n\nA predefined output or behavior\n\n\n\n\n\nThe observed object is an artifact of some code we’ve written, and it’s being compared against an expected result.\n\n\n\nBDD test functions\ntestthat also has two behavior-driven development (BDD) functions for performing tests: describe() and it().\n\n“Use describe() to verify that you implement the right things and use [it()] to ensure you do the things right.” - testthat documentation\n\n\n1describe(\"Description of feature or specification\",\n code = { \n2 it(\"Functionality under test\",\n3 code = {\n expect_equal( \n object = 2 * 2, \n expected = 4 \n )\n })\n })\n\n\n1\n\ndescribe() the feature or specification\n\n\n2\n\nCapture it() in a test\n\n\n3\n\nWrite expectations\n\n\n\n\nWe’ll cover BDD more in the next chapter, but for now just know that each call to it() behaves like test_that().\n\n\nRunning tests\n\nAnother devtools habit to adopt is regularly writing and running tests. If you’re using Posit Workbench and have devtools installed, you can test your app-package using the Build pane or the keyboard shortcut: Ctrl/Cmd + Shift + T\n\n\n\n\n\n\nRun all tests\n\n\n\n\nKeyboard shortcuts\nR Packages, 2ed also suggests binding test_active_file() and test_coverage_active_file() to keyboard shortcuts. I highly recommend using a shortcut while developing tests because it will improve your ability to iterate quickly.\n\n\n\ndevtools function\ntest()\n\n\n \n\n\nKeyboard shortcut\nCtrl/Cmd + Shift + T\n\n\n\n\n\n\ntest_active_file()\n\n\n \n\n\nCtrl/Cmd + T\n\n\n\n\n\n\ntest_coverage_active_file()\n\n\n \n\n\nCtrl/Cmd + Shift + R\n\n\n\nWhen the test is run, we’ll see feedback on whether it passes or fails (and occasionally some encouragement):\n\ntest_that(\"multiplication works\", { \n expect_equal( \n object = 2 * 2, \n expected = 4 \n ) \n})\n## Test passed 🎉" }, { "objectID": "test_suite.html#recap", @@ -683,7 +683,7 @@ "href": "test_specs.html#application-developemnt", "title": "Specifications", "section": "Application developemnt", - "text": "Application developemnt\nThe Shiny application development process follows something like the figure below:\n\n\n\nGeneral application development process\n\n\nThe figure above is an oversimplification, but it highlights a common separation (or ‘hand-off’) between users/stakeholders and developers. In the sections below, we’ll look at two common development processes: test-driven and behavior-driven development.\n\nTest-driven development\nIf moviesApp was built using test-driven development (TDD), the process might look something like this:\n\nGather user needs and translate into application features:\n\nDocument the application’s capabilities for exploring movie review variables from IMDB and Rotten Tomatoes.\nInclude feature descriptions for displaying continuous variables (i.e., ‘critics score’ and ‘audience score’) categorical variables (i.e., ‘MPAA’ ), graph visual attributes (size, color, opacity), and an optional plot title.\n\nWrite Tests:\n\nWrite tests to ensure the graph displays relationships between a set of continuous and categorical variables when the app launches.\n\nRun Tests:\n\nBefore writing any code, these tests will fail.\n\nDevelop Features:\n\nWrite UI, server, module, and utility functions for user inputs and graph outputs.\n\nRerun Tests:\n\nIf the graph has been correctly implemented in the application, the tests should pass.\n\nWrite more Tests:\n\nAdd more tests for additional functionalities (e.g., an option to remove missing values from graph).\n\n\nStarting with tests and writing just enough code to get them to pass often results in developing less (but better) code. The drawback to this approach is a strict focus on the function being tested and not the overall objective of the application.\n\n\nBehavior-driven development\nIn behavior-driven development (BDD) (or behavior-driven testing), users and developers work together to understand, define and express application behaviors in non-technical language, 7\n\n“Using conversation and examples to specify how you expect a system to behave is a core part of BDD” - BDD in Action, 2ed\n\nPlacing an emphasis on writing human-readable expectations for the application’s behaviors makes it easier to develop tests that can focus on verifying each user need exists (and is functioning properly). In BDD, the application’s expected capabilities are captured in Features and illustrated with concrete examples, or Scenarios.\n\nFeature\nIn BDD, a Feature describes an implemented behavior or capability in the application, from a user’s perspective. Typically, these are written in the Gherkin format using specific keywords:8\n\nAs a ...\n\nI want ...\n\nSo that ...\n\nBelow is an example Gherkin Feature for the graph in movies_app():\nFeature: Visualization\n As a user\n I want to see the changes in the plot\n So that I can visualize the impact of my customizations\nAs you can see, the feature uses plain language and the wording is user-centric, so it remains accessible to both developers and users (or other non-technical stakeholders).\n\n\nScenario\nA Gherkin Scenario provides a concrete example of how the Feature works and has the following general format:\n\nGiven ...\n\nWhen ...\n\nThen ...\n\nAn example Scenario for movies_app() might be:\n Scenario: Viewing the Data Visualization\n Given I have launched the application\n And it contains movie review data from IMDB and Rotten Tomatoes\n And the data contains variables like 'Critics Score' and 'MPAA'\n When I interact with the controls in the sidebar panel\n Then the graph should update with the selected options\n\n\nBackground\nInstead of repeating any pre-conditions in each Scenario (i.e., the steps contained in the “Given” and first “And” statement), we can establish the context with a Background:\n Background: Launching the application\n Given I have launched the application\n And it loads with movie review data from IMDB and Rotten Tomatoes\n \n Scenario: Viewing the Data Visualization\n Given the data contains variables like 'Critics Score' and 'MPAA'\n When I interact with the controls in the sidebar panel\n Then the graph should update with the selected options\nAdopting the Gherkin format (or something similar) provides a common language to express an application’s behavior:\n\nAs developers, we can work with users and shareholders to write specifications that describe the expected behavior of each Feature\nWhen developing tests, we can group the tests by their Feature and Scenarios\nEach test can execute a step (i.e., the Then statements).\n\nIn the next section we’ll cover how to map test code for each Scenario step with testthat.\n\n\n\nBDD and testthat\n\n“Use describe() to verify that you implement the right things and use [it()] to ensure you do the things right.” - testthat documentation\n\ntestthat’s BDD functions (describe() and it()) allow us add Gherkin-style features and scenarios to our test files, ensuring the application remains user-centric while meeting the technical specifications.9\n\ndescribe() a feature\nWe can use the language from our Feature, Background, and Scenario to in the description in the argument of describe():\n\ntestthat::describe(\n description = \"Feature: Visualization\n As a user\n I want to see the changes in the plot\n So that I can visualize the impact of my customizations\",\n code = {\n \n})\n\nWe can also nest describe() calls, which means we can include the Background (or other relevant information):\n\n1describe(\n \"Feature: Visualization\n As a user\n I want to see the changes in the graph\n So that I can visualize the impact of my customizations.\", \n code = {\n \n2 describe(\n \"Background: Launching the application\n Given I have launched the application\n And it loads with movie review data from IMDB and Rotten Tomatoes\", \n code = { \n \n })\n \n })\n\n\n1\n\nBDD Feature (title and description)\n\n\n2\n\nBackground (preexisting conditions before each scenario)\n\n\n\n\n\n\nConfirm it() with a test\nInside describe(), we can include multiple it() blocks which “functions as a test and is evaluated in its own environment.”\nIn the example below, we’ll use an it() block to test the example scenario from above:10\n\n1testthat::describe(\n \"Feature: Visualization\n As a user\n I want to see the changes in the graph\n So that I can visualize the impact of my customizations.\", \n code = {\n \n2 testthat::describe(\n \"Background: Launching the application\n Given I have launched the application\n And it loads with movie review data from IMDB and Rotten Tomatoes\",\n code = {\n \n3 testthat::it(\n \"Scenario: Viewing the Data Visualization\n Given the data contains variables like 'Critics Score' and 'MPAA'\n When I interact with the controls in the sidebar panel\n Then the graph should update with the selected options\",\n code = {\n4 # test code\n })\n \n })\n \n})\n\n\n1\n\nBDD Feature (title and description)\n\n\n2\n\nBackground (preexisting conditions before each scenario)\n\n3\n\nScenario (a concrete examples that illustrates a feature)\n\n4\n\nTest code\n\n\n\n\nIn the scenario above, Then contains the information required for the testthat expectation. This could be expect_snapshot_file() or vdiffr::expect_doppelganger()–whichever makes sense from the user’s perspective.\nThis is an generic example, but hopefully the example tests in the upcoming chapters convey how helpful and expressive the BDD functions can be (or they inspire you to properly implement what I’m attempting to do in your own app-packages).11" + "text": "Application developemnt\nThe Shiny application development process follows something like the figure below:\n\n\n\nGeneral application development process\n\n\nThe figure above is an oversimplification, but it highlights a common separation (or ‘hand-off’) between users/stakeholders and developers. In the sections below, we’ll look at two common development processes: test-driven and behavior-driven development.\n\nTest-driven development\nIf moviesApp was built using test-driven development (TDD), the process might look something like this:\n\nGather user needs and translate into application features:\n\nDocument the application’s capabilities for exploring movie review variables from IMDB and Rotten Tomatoes.\nInclude feature descriptions for displaying continuous variables (i.e., ‘critics score’ and ‘audience score’) categorical variables (i.e., ‘MPAA’ ), graph visual attributes (size, color, opacity), and an optional plot title.\n\nWrite Tests:\n\nWrite tests to ensure the graph displays relationships between a set of continuous and categorical variables when the app launches.\n\nRun Tests:\n\nBefore writing any code, these tests will fail.\n\nDevelop Features:\n\nWrite UI, server, module, and utility functions for user inputs and graph outputs.\n\nRerun Tests:\n\nIf the graph has been correctly implemented in the application, the tests should pass.\n\nWrite more Tests:\n\nAdd more tests for additional functionalities (e.g., an option to remove missing values from graph).\n\n\nStarting with tests and writing just enough code to get them to pass often results in developing less (but better) code. The drawback to this approach is a strict focus on the function being tested and not the overall objective of the application.\n\n\nBehavior-driven development\nIn behavior-driven development (BDD) (or behavior-driven testing), users and developers work together to understand, define and express application behaviors in non-technical language, 7\n\n“Using conversation and examples to specify how you expect a system to behave is a core part of BDD” - BDD in Action, 2ed\n\nPlacing an emphasis on writing human-readable expectations for the application’s behaviors makes it easier to develop tests that can focus on verifying each user need exists (and is functioning properly). In BDD, the application’s expected capabilities are captured in Features and illustrated with concrete examples, or Scenarios.\n\nFeature\nIn BDD, a Feature describes an implemented behavior or capability in the application, from a user’s perspective. Typically, these are written in the Gherkin format using specific keywords:8\n\nAs a ...\n\nI want ...\n\nSo that ...\n\nBelow is an example Gherkin Feature for the graph in movies_app():\nFeature: Visualization\n As a user\n I want to see the changes in the plot\n So that I can visualize the impact of my customizations\nAs you can see, the feature uses plain language and the wording is user-centric, so it remains accessible to both developers and users (or other non-technical stakeholders).\n\n\nScenario\nA Gherkin Scenario provides a concrete example of how the Feature works and has the following general format:\n\nGiven ...\n\nWhen ...\n\nThen ...\n\nAn example Scenario for movies_app() might be:\n Scenario: Viewing the Data Visualization\n Given I have launched the application\n And it contains movie review data from IMDB and Rotten Tomatoes\n And the data contains variables like 'Critics Score' and 'MPAA'\n When I interact with the controls in the sidebar panel\n Then the graph should update with the selected options\n\n\nBackground\nInstead of repeating any pre-conditions in each Scenario (i.e., the steps contained in the “Given” and first “And” statement), we can establish the context with a Background:\n Background: Launching the application\n Given I have launched the application\n And it loads with movie review data from IMDB and Rotten Tomatoes\n \n Scenario: Viewing the Data Visualization\n Given the data contains variables like 'Critics Score' and 'MPAA'\n When I interact with the controls in the sidebar panel\n Then the graph should update with the selected options\nAdopting the Gherkin format (or something similar) provides a common language to express an application’s behavior:\n\nAs developers, we can work with users and shareholders to write specifications that describe the expected behavior of each Feature\nWhen developing tests, we can group the tests by their Feature and Scenarios\nEach test can execute a step (i.e., the Then statements).\n\nIn the next section we’ll cover how to map test code for each Scenario step with testthat.\n\n\n\nBDD and testthat\ntestthat’s BDD functions (describe() and it()) allow us add Gherkin-style features and scenarios to our test files, ensuring the application remains user-centric while meeting the technical specifications.9\n\ndescribe() a feature\nWe can use the language from our Feature, Background, and Scenario to in the description in the argument of describe():\n\ntestthat::describe(\n description = \"Feature: Visualization\n As a user\n I want to see the changes in the plot\n So that I can visualize the impact of my customizations\",\n code = {\n \n})\n\nWe can also nest describe() calls, which means we can include the Background (or other relevant information):\n\n1describe(\n \"Feature: Visualization\n As a user\n I want to see the changes in the graph\n So that I can visualize the impact of my customizations.\", \n code = {\n \n2 describe(\n \"Background: Launching the application\n Given I have launched the application\n And it loads with movie review data from IMDB and Rotten Tomatoes\", \n code = { \n \n })\n \n })\n\n\n1\n\nBDD Feature (title and description)\n\n\n2\n\nBackground (preexisting conditions before each scenario)\n\n\n\n\n\n\nConfirm it() with a test\nInside describe(), we can include multiple it() blocks which “functions as a test and is evaluated in its own environment.”\nIn the example below, we’ll use an it() block to test the example scenario from above:10\n\n1testthat::describe(\n \"Feature: Visualization\n As a user\n I want to see the changes in the graph\n So that I can visualize the impact of my customizations.\", \n code = {\n \n2 testthat::describe(\n \"Background: Launching the application\n Given I have launched the application\n And it loads with movie review data from IMDB and Rotten Tomatoes\",\n code = {\n \n3 testthat::it(\n \"Scenario: Viewing the Data Visualization\n Given the data contains variables like 'Critics Score' and 'MPAA'\n When I interact with the controls in the sidebar panel\n Then the graph should update with the selected options\",\n code = {\n4 # test code\n })\n \n })\n \n})\n\n\n1\n\nBDD Feature (title and description)\n\n\n2\n\nBackground (preexisting conditions before each scenario)\n\n3\n\nScenario (a concrete examples that illustrates a feature)\n\n4\n\nTest code\n\n\n\n\nIn the scenario above, Then contains the information required for the testthat expectation. This could be expect_snapshot_file() or vdiffr::expect_doppelganger()–whichever makes sense from the user’s perspective.\nThis is an generic example, but hopefully the example tests in the upcoming chapters convey how helpful and expressive the BDD functions can be (or they inspire you to properly implement what I’m attempting to do in your own app-packages).11" }, { "objectID": "test_specs.html#traceability-matrix", @@ -858,35 +858,14 @@ "href": "leprechaun.html#set-up", "title": "leprechaun", "section": "Set up", - "text": "Set up\nCreate new leprechaun app-packages with usethis::create_package('lap'). After the package is created, leprechaun::scaffold() 1 builds the core app files:2\n\nR\n1├── _disable_autoload.R\n2├── assets.R\n3├── input-handlers.R\n4├── leprechaun-utils.R\n5├── run.R\n6├── server.R\n7├── ui.R\n8└── zzz.R\n\n1 directory, 8 files\n\n\n1\n\nDisables shiny::loadSupport()\n\n\n2\n\nIncludes functions for serving JavaScript files, adding/removing modules, and collapsing files.\n\n3\n\nUtility functions for handling lists and data.frames\n\n\n4\n\nContains the make_send_message() function for ‘send[ing] custom messages to the front-end’\n\n5\n\nStandalone app function\n\n\n6\n\nApp primary server function\n\n\n7\n\nApp primary ui function\n\n\n8\n\nIncludes wrapper for adding external files\n\n\n\n\nshiny, bslib, htmltools and pkgload are added to the DESCRIPTION.\n\nImports: \n bslib,\n htmltools,\n shiny\nSuggests: \n pkgload\n\nThe lap folder structure should look familiar if you’ve been following along with the previous chapters. The standard R package files and folders (DESCRIPTION, NAMESPACE, R/, and .Rproj) are accompanied by inst/ sub-folders (recall that inst/ contents are available when the package is installed) and a .leprechaun lock file.\n\nlap/\n├── .leprechaun\n├── DESCRIPTION\n├── NAMESPACE\n├── inst/\n│ ├── assets\n│ ├── dev\n│ ├── img\n│ └── run\n│ └── app.R\n└── moviesApp.Rproj" + "text": "Set up\nCreating a new leprechaun app-package can be done with usethis::create_package() (covered in Packages).1\nAfter your app-package is created, leprechaun::scaffold() builds the core app files: 2\n\nCode files: the code files in new leprechaun apps include the following: \n\n_disable_autoload.R: Disables shiny::loadSupport() (covered in Launch) \nassets.R: includes serveAssets() for serving JavaScript files, remove_modules() and get_modules() for adding/removing modules, and the collapse_files() helper function for collapsing files.3 \ninput-handlers.R: leprechaun_handler_df() and leprechaun_handler_list() are helper functions for including data and lists “from Websocket”.4 \nleprechaun-utils.R: includes a make_send_message() function for “send custom messages to the front-end” with the “namespace carried along”. Read below for demonstration of how this is used.5 \nrun.R: the standalone app function for your leprechaun app (covered in Launch). \nserver.R & ui.R are applications primary UI and server functions. \n\nui: contains the application UI and the assets() function (which calls serveAssets() covered above).6 \nserver.R: creates send_message from make_send_message(session) (covered below).7 \n\nzzz.R is a utility function file that holds the .onLoad() function for adding external resources (using methods covered in External files).8\n\n\n\nR\n1├── _disable_autoload.R\n2├── assets.R\n3├── input-handlers.R\n4├── leprechaun-utils.R\n5├── run.R\n6├── server.R\n7├── ui.R\n8└── zzz.R\n\n1 directory, 8 files\n\n\n1\n\nDisables shiny::loadSupport()\n\n\n2\n\nIncludes functions for serving JavaScript files, adding/removing modules, and collapsing files.\n\n3\n\nUtility functions for handling lists and data.frames\n\n\n4\n\nContains the make_send_message() function for ‘send[ing] custom messages to the front-end’\n\n5\n\nStandalone app function\n\n\n6\n\nApp primary server function\n\n\n7\n\nApp primary ui function\n\n\n8\n\nIncludes wrapper for adding external files\n\n\n\n\n\nAdding dependencies: shiny, bslib, htmltools and pkgload should be added to the DESCRIPTION with usethis::use_package() (covered in the Dependencies chapter).\n\n\nImports: \n bslib,\n htmltools,\n shiny\nSuggests: \n pkgload\n\nThe lap folder structure should look familiar if you’ve been following along with the previous chapters. The standard R package files (DESCRIPTION, NAMESPACE, and .Rproj) are accompanied by a .leprechaun lock file.\n\nlap/\n├── .leprechaun\n├── DESCRIPTION\n├── NAMESPACE\n└── moviesApp.Rproj\n\nThe initial call to leprechaun::scaffold() creates the following folders in the inst/ folder (recall that inst/ contents are available when the package is installed).\n\ninst/\n├── assets\n├── dev\n├── img\n└── run\n └── app.R\n\n5 directories, 1 file\n\ninst/run/app.R contains a call to leprechaun::build(), pkgload::load_all(), then a call to the standalone app function, run().9" }, { - "objectID": "leprechaun.html#app-code", - "href": "leprechaun.html#app-code", + "objectID": "leprechaun.html#development", + "href": "leprechaun.html#development", "title": "leprechaun", - "section": "App code", - "text": "App code\n\nCode files: new code files in leprechaun apps can be created with usethis::use_r() or with leprechaun’s helper functions. \n\nModules: Add modules with leprechaun::add_module(\"name\") 3 \n\nModule files created with add_module() have a module_ prefix. \n\nRun: R/run.R contains functions for running the app.4 \nUI and server: Add the modules to R/ui.R and R/server.R. \n\nR/server.R includes the send_message and make_send_message(session) functions by default.5 \nR/ui.R holds the ui() and assets() functions.6 \n\nUtility function: R/utils_scatter_plot.R holds the scatter_plot() utility function.7 \nAdding external files: The R/zzz.R file contains the .onLoad() function 8 \napp.R file: include an app.R in the root directory using add_app_file() 9\n\n\n\nR\n├── module_plot_display.R\n├── module_var_input.R\n├── run.R\n├── server.R\n├── ui.R\n└── utils_scatter_plot.R\n\n1 directory, 6 files" - }, - { - "objectID": "leprechaun.html#app-files", - "href": "leprechaun.html#app-files", - "title": "leprechaun", - "section": "App files", - "text": "App files\nThe initial call to leprechaun::scaffold() creates the following folders in the inst/ folder\n\ninst\n├── assets\n├── dev\n├── img\n└── run\n └── app.R\n\n5 directories, 1 file\n\nThe inst/run/app.R looks like a standard app.R file, but it’s not.10" - }, - { - "objectID": "leprechaun.html#data-files", - "href": "leprechaun.html#data-files", - "title": "leprechaun", - "section": "Data files", - "text": "Data files\n\nIncluding data files: the movies.RData data was moved into inst/extdata, then loaded into data/ with the script created with usethis::use_data_raw('movies'):\n\n\ndata-raw/\n└── movies.R\n\n1 directory, 1 file\n\n\n└── extdata\n └── movies.RData\n1 directory, 1 file\n\n\ndata\n└── movies.rda\n\n1 directory, 1 file" - }, - { - "objectID": "leprechaun.html#leprechaun-features", - "href": "leprechaun.html#leprechaun-features", - "title": "leprechaun", - "section": "leprechaun features", - "text": "leprechaun features\nThe leprechaun workflow involves a combination of use_ functions that are combined with leprechaun::build() to add various functionality to your application. I’ll demonstrate three options in the sections below:\n\nUse packer\nI’ll demo using the make_send_message() from the JavaScript example on the package website:\n\nRun packer::scaffold_leprechaun() \n\nInitializes npm, adds npm scripts, creates srcjs, srcjs/config, webpack, webpack-cli, and webpack-merge \n\nRun leprechaun::use_packer() \nRun leprechaun::build()\n\nThis creates inst/dev/packer.R and inst/assets/index.js.11\n\ninst\n├── assets\n│ └── index.js\n├── dev\n│ └── packer.R\n├── extdata\n│ └── movies.RData\n├── img\n└── run\n └── app.R\n\nAssign the output from make_send_message() to send_message() in R/server.R, then pass the msgId and text of the message:\n\nserver <- function(input, output, session){\n ## New code -->\n1 send_message <- make_send_message(session)\n \n2 send_message(\"show-packer\",\n text = \"this message is from your R/server.R file\")\n \n selected_vars <- var_input_server(\"vars\")\n\n plot_display_server(\"plot\", var_inputs = selected_vars)\n ## New code <--\n\n}\n\n\n1\n\nCreate send_message()\n\n\n2\n\nUse send_message() to send message the UI.\n\n\n\n\nAfter loading, documenting, and installing your app-package:\n\n\n\n\n\n\n\n\nCtrl/Cmd + Shift + L / D / B\n\n\n\n\n\n\n\nRun the application:\n\nlap::run()\n\n\n\n\n\n\n(a) send_message() in lap::run()\n\n\nFigure 16.2: Adding the make_send_message() functionality to R/server.R\n\n\n\n\nAdd images\nI’ll demonstrate adding an image file (leprechaun.jpg) to the UI function.\n\nPlace the leprechaun.jpg file in inst/img/ \nAdd the img/ path to the code to UI:\n\n\ntags$img(\n src = \"img/leprechaun.jpg\", \n height = \"25%\", \n width = \"25%\")\n\n\nrun devtools::load_all(), devtools::document(), and devtools::install(), then run the application with run():\n\n\n\n\n\n\n\n\n\nCtrl/Cmd + Shift + L / D / B\n\n\n\n\n\n\n\n\nlap::run()\n\n\n\n\n\n\n(a) leprechaun.jpg in R/ui.R\n\n\nFigure 16.3: Adding images to inst/img/\n\n\n\n\nUse Sass\nTo add Sass styling, I can use leprechaun’s use_sass() function\n\nRun leprechaun::use_sass() \n\na scss/ folder will be created that contains _core.scss and main.scss\n\n\n\nscss\n├── _core.scss\n└── main.scss\n\n1 directory, 2 files\n\n\nThe original _core.scss file is below\n\nhtml{\n .error {\n color: red\n }\n}\n\nChange the color: from red to green (#38B44A) using $accent: #38B44A;\n\n$accent: #38B44A;\n\nhtml{\n h1 {\n color: $accent;\n }\n}\n\nSave this file and run leprechaun::build():12\n\n\nleprechaun::build()\n\n\n✔ Running packer.R\n✔ Bundled \n✔ Running sass.R\n\n\nOnce again, run devtools::load_all(), devtools::document(), and devtools::install(), then run the application with run():\n\n\n\n\n\n\n\n\n\nCtrl/Cmd + Shift + L / D / B\n\n\n\n\n\n\n\n\nlap::run()\n\n\n\n\n\n\n(a)\n\n\nFigure 16.4: Running lap with new Sass" + "section": "Development", + "text": "Development\n\nCode files: new code files in leprechaun apps can be created with usethis::use_r() or with a helper function: \n\nCreate modules with add_module(). Modules created with add_module(\"name\") will have:10 \n\nA module file with a module_name prefix (R/module_name.R)\nA module UI function: nameUI()\nA module server function: name_server()\n\n\nCreate an app.R file with add_app_file(). This includes a call to pkgload::load_all() and run().11 \n\nApp files: R/run.R contains functions for running the app.12 \n\nAdd the modules to R/ui.R and R/server.R. \n\nR/server.R includes a call to send_message by default.13 \nR/ui.R holds the ui() and assets() functions.14 \n\nUtility function: R/utils_scatter_plot.R holds the scatter_plot() utility function.15 \nAdding files: The R/zzz.R file contains the .onLoad() function, which wraps system.file('img', package = 'lap') and addResourcePath() for including external resources. \n\n\n\nR\n├── module_plot_display.R\n├── module_var_input.R\n├── run.R\n├── server.R\n├── ui.R\n└── utils_scatter_plot.R\n\n1 directory, 6 files\n\n\nData files\n\nIncluding data files: the movies.RData data was moved into inst/extdata, then loaded into data/ with the script created with usethis::use_data_raw('movies') (similar to methods covered in the Data chapter):\n\n\ndata-raw/\n└── movies.R\n\n1 directory, 1 file\n\n\n└── extdata\n └── movies.RData\n1 directory, 1 file\n\n\ndata\n└── movies.rda\n\n1 directory, 1 file\n\n\n\nAdding features\nThe leprechaun workflow involves a combination of use_ functions that are combined with leprechaun::build() to add various functionality to your application. I’ll demonstrate three options in the sections below:\n\nUse packer\nI’ll demo using the make_send_message() from the JavaScript example on the package website:\n\nRun packer::scaffold_leprechaun() \n\nInitializes npm, adds npm scripts, creates srcjs, srcjs/config, webpack, webpack-cli, and webpack-merge \n\nRun leprechaun::use_packer() \nRun leprechaun::build()\n\nThis creates inst/dev/packer.R and inst/assets/index.js.16\n\ninst\n├── assets\n│ └── index.js\n├── dev\n│ └── packer.R\n├── extdata\n│ └── movies.RData\n├── img\n└── run\n └── app.R\n\nAssign the output from make_send_message() to send_message() in R/server.R, then pass the msgId and text of the message:\n\nserver <- function(input, output, session){\n ## New code -->\n1 send_message <- make_send_message(session)\n \n2 send_message(\"show-packer\",\n text = \"this message is from your R/server.R file\")\n \n selected_vars <- var_input_server(\"vars\")\n\n plot_display_server(\"plot\", var_inputs = selected_vars)\n ## New code <--\n\n}\n\n\n1\n\nCreate send_message()\n\n\n2\n\nUse send_message() to send message the UI.\n\n\n\n\nAfter loading, documenting, and installing your app-package:\n\n\n\n\n\n\n\n\nCtrl/Cmd + Shift + L / D / B\n\n\n\n\n\n\n\nRun the application:\n\nlap::run()\n\n\n\n\n\n\n(a) send_message() in lap::run()\n\n\nFigure 16.2: Adding the make_send_message() functionality to R/server.R\n\n\n\n\nAdd images\nAdding images is simplified with the .onLoad() function, which I’ll demonstrate by adding the leprechaun.jpg image file to the UI function.\n\nPlace the leprechaun.jpg file in inst/img/ \nAdd the img/ path to the code to UI:\n\n\ntags$img(\n src = \"img/leprechaun.jpg\", \n height = \"25%\", \n width = \"25%\")\n\n\nrun devtools::load_all(), devtools::document(), and devtools::install(), then run the application with run():\n\n\n\n\n\n\n\n\n\nCtrl/Cmd + Shift + L / D / B\n\n\n\n\n\n\n\n\nlap::run()\n\n\n\n\n\n\n(a) leprechaun.jpg in R/ui.R\n\n\nFigure 16.3: Adding images to inst/img/\n\n\n\n\nUse Sass\nTo add Sass styling, I can use leprechaun’s use_sass() function\n\nRun leprechaun::use_sass() \n\na scss/ folder will be created that contains _core.scss and main.scss\n\n\n\nscss\n├── _core.scss\n└── main.scss\n\n1 directory, 2 files\n\n\nThe original _core.scss file is below\n\nhtml{\n .error {\n color: red\n }\n}\n\nChange the color: from red to green (#38B44A) using $accent: #38B44A;\n\n$accent: #38B44A;\n\nhtml{\n h1 {\n color: $accent;\n }\n}\n\nSave this file and run leprechaun::build():17\n\n\nleprechaun::build()\n\n\n✔ Running packer.R\n✔ Bundled \n✔ Running sass.R\n\n\nOnce again, run devtools::load_all(), devtools::document(), and devtools::install(), then run the application with run():\n\n\n\n\n\n\n\n\n\nCtrl/Cmd + Shift + L / D / B\n\n\n\n\n\n\n\n\nlap::run()\n\n\n\n\n\n\n(a)\n\n\nFigure 16.4: Running lap with new Sass" }, { "objectID": "leprechaun.html#tests", @@ -907,14 +886,14 @@ "href": "leprechaun.html#recap", "title": "leprechaun", "section": "Recap", - "text": "Recap\nleprechaun apps are built using the same methods as app-packages (devtools and usethis), and are intended to be a ‘leaner and smaller’ version of golem.\n\n“it generates code and does not make itself a dependency of the application you build; this means applications are leaner, and smaller”\n\nleprechaun is similar to golem in that it ‘bundles’ various app-package development functions into helper/utility functions. For example, the .onLoad() function is a wrapper for:\nshiny::addResourcePath(\"img\", system.file(\"img\", package = \"lap\"))\n.onLoad() saves some time because you won’t have to add the code above to the UI (at the cost of making your app code less clear and explicit).\nleprechaun also relies on external packages like packer to integrate and bundle external code files, so becoming more familiar with these packages will extend what you can build with leprechaun." + "text": "Recap\nleprechaun apps are built using the same methods as app-packages (devtools and usethis), and are intended to be a ‘leaner and smaller’ version of golem.\n\n“it generates code and does not make itself a dependency of the application you build; this means applications are leaner, and smaller”\n\nleprechaun is similar to golem in that it ‘bundles’ various app-package development functions into helper/utility functions. For example, the .onLoad() function saves some time (at the cost of making your app code less clear and explicit).\nleprechaun also relies on external packages like packer to integrate and bundle external code files, so becoming more familiar with these packages will extend what you can build with leprechaun." }, { "objectID": "leprechaun.html#footnotes", "href": "leprechaun.html#footnotes", "title": "leprechaun", "section": "", - "text": "leprechaun::scaffold() has arguments for ui (fluidPage or navbarPage) bs_version (bootstrap version) and overwrite (if you need to start over).↩︎\nRemember to provide a list of fields to usethis::create_package() for the DESCRIPTION file (or edit this manually).↩︎\nleprechaun modules created with add_module() have the following naming convention: leprechaun::add_module(\"name\") creates var_inputUI() and var_input_server().↩︎\nR/run.R includes functions for running the production (run()) and development (run_dev()) version of the application.↩︎\nmake_send_message() is in R/leprechaun-utils.R.↩︎\nassets() loads the resources called in the R/assets.R file with the serveAssets() function.↩︎\nThe same scatter_plot() function from moviesApp (i.e, imports .data from rlang)↩︎\n.onLoad() is a wrapper for shiny::addResourcePath('img', system.file('img', package = 'lap'))↩︎\nthe app.R file includes a call to pkgload::load_all().↩︎\ninst/run/app.R contains a call to leprechaun::build(), then pkgload::load_all().↩︎\nUsing packer will download multiple folders into your leprechaun app package root folder (srcjs/, node_modules/, package-lock.json, package.json, webpack.common.js, webpack.dev.js, webpack.prod.js). These are not necessary and can be removed (but do not remove inst/dev/packer.R and inst/assets/index.js).↩︎\nThe scss folder is added to the root directory, but after running leprechaun::build() and creating inst/dev/sass.R, this folder can be removed.↩︎" + "text": "Remember to provide a list of fields to usethis::create_package() for the DESCRIPTION file (or edit this manually).↩︎\nleprechaun::scaffold() has arguments for ui (fluidPage or navbarPage) bs_version (bootstrap version) and overwrite (if you need to start over).↩︎\nLink to R/assets.R file.↩︎\nLink to R/input-handlers.R file.↩︎\nLink to R/leprechaun-utils.R file.↩︎\nLink to R/ui.R file.↩︎\nLink to R/server.R file.↩︎\nLink to R/zzz.R file.↩︎\nLink to inst/run/app.R file.↩︎\nleprechaun modules do not have the same naming conventions as golem (or that I’ve recommended throughout this book).↩︎\npkgload::load_all() has reset set to TRUE and helpers set to FALSE.↩︎\nR/run.R includes functions for running the production (run()) and development (run_dev()) version of the application.↩︎\nmake_send_message() is in R/leprechaun-utils.R.↩︎\nassets() loads the resources called in the R/assets.R file with the serveAssets() function.↩︎\nThe same scatter_plot() function from moviesApp (i.e, imports .data from rlang)↩︎\nUsing packer will download multiple folders into your leprechaun app package root folder (srcjs/, node_modules/, package-lock.json, package.json, webpack.common.js, webpack.dev.js, webpack.prod.js). These are not necessary and can be removed (but do not remove inst/dev/packer.R and inst/assets/index.js).↩︎\nThe scss folder is added to the root directory, but after running leprechaun::build() and creating inst/dev/sass.R, this folder can be removed.↩︎" }, { "objectID": "rhino.html#rap-a-rhino-app", diff --git a/shiny.html b/shiny.html index 5b9ecf7..633a666 100644 --- a/shiny.html +++ b/shiny.html @@ -826,7 +826,7 @@

      Update
      1
      -Comment out these lines after installing pkgs +Comment out these lines after installing pkgs
      @@ -1058,30 +1058,30 @@

      1
      -y axis numeric variable +y axis numeric variable
      2
      -x axis numeric variable +x axis numeric variable
      3
      -z axis categorical variable
      +z axis categorical variable
      4
      -alpha numeric value for points
      +alpha numeric value for points
      5
      -size numeric value for size
      +size numeric value for size
      6
      -plot_title text +plot_title text
      @@ -1112,30 +1112,30 @@
      1
      -y axis numeric variable +y axis numeric variable
      2
      -x axis numeric variable +x axis numeric variable
      3
      -z axis categorical variable
      +z axis categorical variable
      4
      -alpha numeric value for points
      +alpha numeric value for points
      5
      -size numeric value for size
      +size numeric value for size
      6
      -plot_title text +plot_title text
      @@ -1169,7 +1169,7 @@
      1
      -Namespaced module id for plot in UI +Namespaced module id for plot in UI
      @@ -1226,23 +1226,23 @@
      1
      -loading the movies data +loading the movies data
      2
      -assembling the returned values from mod_var_input_server(), and creating the input() reactive +assembling the returned values from mod_var_input_server(), and creating the input() reactive
      3
      -scatter_plot() utility function creates the plot object +scatter_plot() utility function creates the plot object
      4
      -adds the plot_title() +adds the plot_title()
      5
      -add theme to layers +add theme to layers
      @@ -1315,28 +1315,28 @@
      app.R
      1
      -Header (comment this out after the packages are installed) +Header (comment this out after the packages are installed)
      2
      -Load packages
      +Load packages
      3
      -Variable input UI module +Variable input UI module
      4
      -Graph display UI module +Graph display UI module
      5
      -Variable input server module +Variable input server module
      6
      -Graph display server module +Graph display server module
      diff --git a/sitemap.xml b/sitemap.xml index f995b07..481c18e 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -2,142 +2,142 @@ https://mjfrigaard.github.io/shinyap/index.html - 2023-11-06T10:37:07.202Z + 2023-11-06T22:11:29.138Z https://mjfrigaard.github.io/shinyap/intro.html - 2023-11-06T10:37:07.217Z + 2023-11-06T22:11:29.153Z https://mjfrigaard.github.io/shinyap/whole_game.html - 2023-11-06T10:37:07.258Z + 2023-11-06T22:11:29.200Z https://mjfrigaard.github.io/shinyap/shiny.html - 2023-11-06T10:37:07.341Z + 2023-11-06T22:11:29.294Z https://mjfrigaard.github.io/shinyap/packages.html - 2023-11-06T10:37:07.394Z + 2023-11-06T22:11:29.354Z https://mjfrigaard.github.io/shinyap/development.html - 2023-11-06T10:37:07.427Z + 2023-11-06T22:11:29.390Z https://mjfrigaard.github.io/shinyap/app_packages.html - 2023-11-06T10:37:07.449Z + 2023-11-06T22:11:29.409Z https://mjfrigaard.github.io/shinyap/document.html - 2023-11-06T10:37:07.524Z + 2023-11-06T22:11:29.466Z https://mjfrigaard.github.io/shinyap/dependencies.html - 2023-11-06T10:37:07.581Z + 2023-11-06T22:11:29.527Z https://mjfrigaard.github.io/shinyap/data.html - 2023-11-06T10:37:07.628Z + 2023-11-06T22:11:29.574Z https://mjfrigaard.github.io/shinyap/launch.html - 2023-11-06T10:37:07.686Z + 2023-11-06T22:11:29.629Z https://mjfrigaard.github.io/shinyap/external.html - 2023-11-06T10:37:07.776Z + 2023-11-06T22:11:29.744Z https://mjfrigaard.github.io/shinyap/tests.html - 2023-11-06T10:37:07.784Z + 2023-11-06T22:11:29.753Z https://mjfrigaard.github.io/shinyap/test_suite.html - 2023-11-06T10:37:07.805Z + 2023-11-06T22:11:29.774Z https://mjfrigaard.github.io/shinyap/test_specs.html - 2023-11-06T10:37:07.832Z + 2023-11-06T22:11:29.808Z https://mjfrigaard.github.io/shinyap/test_tools.html - 2023-11-06T10:37:07.883Z + 2023-11-06T22:11:29.860Z https://mjfrigaard.github.io/shinyap/test_modules.html - 2023-11-06T10:37:07.913Z + 2023-11-06T22:11:29.887Z https://mjfrigaard.github.io/shinyap/test_system.html - 2023-11-06T10:37:07.953Z + 2023-11-06T22:11:29.927Z https://mjfrigaard.github.io/shinyap/frameworks.html - 2023-11-06T10:37:07.961Z + 2023-11-06T22:11:29.935Z https://mjfrigaard.github.io/shinyap/golem.html - 2023-11-06T10:37:07.994Z + 2023-11-06T22:11:29.972Z https://mjfrigaard.github.io/shinyap/leprechaun.html - 2023-11-06T10:37:08.068Z + 2023-11-06T22:11:30.006Z https://mjfrigaard.github.io/shinyap/rhino.html - 2023-11-06T10:37:08.094Z + 2023-11-06T22:11:30.036Z https://mjfrigaard.github.io/shinyap/special_topics.html - 2023-11-06T10:37:08.102Z + 2023-11-06T22:11:30.044Z https://mjfrigaard.github.io/shinyap/debugging.html - 2023-11-06T10:37:08.162Z + 2023-11-06T22:11:30.103Z https://mjfrigaard.github.io/shinyap/test_mocks.html - 2023-11-06T10:37:08.188Z + 2023-11-06T22:11:30.127Z https://mjfrigaard.github.io/shinyap/code_tools.html - 2023-11-06T10:37:08.197Z + 2023-11-06T22:11:30.136Z https://mjfrigaard.github.io/shinyap/cicd.html - 2023-11-06T10:37:08.205Z + 2023-11-06T22:11:30.144Z https://mjfrigaard.github.io/shinyap/css.html - 2023-11-06T10:37:08.213Z + 2023-11-06T22:11:30.152Z https://mjfrigaard.github.io/shinyap/js.html - 2023-11-06T10:37:08.222Z + 2023-11-06T22:11:30.160Z https://mjfrigaard.github.io/shinyap/github.html - 2023-11-06T10:37:08.240Z + 2023-11-06T22:11:30.178Z https://mjfrigaard.github.io/shinyap/dependency_trees.html - 2023-11-06T10:37:08.257Z + 2023-11-06T22:11:30.195Z https://mjfrigaard.github.io/shinyap/create.html - 2023-11-06T10:37:08.269Z + 2023-11-06T22:11:30.207Z https://mjfrigaard.github.io/shinyap/comparisons.html - 2023-11-06T10:37:08.285Z + 2023-11-06T22:11:30.223Z https://mjfrigaard.github.io/shinyap/bdd.html - 2023-11-06T10:37:08.300Z + 2023-11-06T22:11:30.238Z https://mjfrigaard.github.io/shinyap/glossary.html - 2023-11-06T10:37:08.310Z + 2023-11-06T22:11:30.247Z diff --git a/test_modules.html b/test_modules.html index e132425..1b08ede 100644 --- a/test_modules.html +++ b/test_modules.html @@ -478,22 +478,22 @@

      1
      -Call to testServer()
      +Call to testServer()
      2
      -Create output values for comparison
      +Create output values for comparison
      3
      -Set each input using setInputs(input = )
      +Set each input using setInputs(input = )
      4
      -Confirm returned values against test_vals +Confirm returned values against test_vals
      @@ -517,7 +517,7 @@

      1
      -Calls return(reactive(list(...))) +Calls return(reactive(list(...)))
      @@ -599,12 +599,12 @@

      1
      -List of reactive variable inputs
      +List of reactive variable inputs
      2
      -Compare inputs() to initial values +Compare inputs() to initial values
      @@ -676,12 +676,12 @@

      Testing
      1
      -Build graph (same code from module function)
      +Build graph (same code from module function)
      2
      -Confirm ggplot2 object is built +Confirm ggplot2 object is built
      diff --git a/test_specs.html b/test_specs.html index ee90300..0ff06f1 100644 --- a/test_specs.html +++ b/test_specs.html @@ -611,9 +611,6 @@

      BDD and testthat

      -
      -

      Use describe() to verify that you implement the right things and use [it()] to ensure you do the things right.” - testthat documentation

      -

      testthat’s BDD functions (describe() and it()) allow us add Gherkin-style features and scenarios to our test files, ensuring the application remains user-centric while meeting the technical specifications.9

      describe() a feature

      @@ -650,12 +647,12 @@

      1
      -BDD Feature (title and description)
      +BDD Feature (title and description)
      2
      -Background (preexisting conditions before each scenario) +Background (preexisting conditions before each scenario)
      @@ -695,20 +692,20 @@

      Confirm
      1
      -BDD Feature (title and description)
      +BDD Feature (title and description)
      2
      -Background (preexisting conditions before each scenario) +Background (preexisting conditions before each scenario)
      3
      -Scenario (a concrete examples that illustrates a feature) +Scenario (a concrete examples that illustrates a feature)
      4
      -Test code +Test code
      diff --git a/test_suite.html b/test_suite.html index 2809e97..c983e20 100644 --- a/test_suite.html +++ b/test_suite.html @@ -376,6 +376,7 @@

      Contents

    • test- files
    • test_that() tests
    • expect_ations
    • +
    • BDD test functions
    • Running tests
    • Keyboard shortcuts
    @@ -487,7 +488,7 @@

    1
    -Referred to as the ‘test runner,’ because it runs all our tests (do not edit this file). +Referred to as the ‘test runner,’ because it runs all our tests (do not edit this file).
    @@ -526,7 +527,7 @@

    1
    -desc is the test context (supplied in "quotes"), and code is the test code (supplied in {curly brackets}). +desc is the test context (supplied in "quotes"), and code is the test code (supplied in {curly brackets}).
    @@ -546,17 +547,17 @@

    1
    -A testthat expectation function
    +A testthat expectation function
    2
    -The output or behavior being tested
    +The output or behavior being tested
    3
    -A predefined output or behavior +A predefined output or behavior
    @@ -565,6 +566,44 @@

    +

    BDD test functions

    +

    testthat also has two behavior-driven development (BDD) functions for performing tests: describe() and it().

    +
    +

    Use describe() to verify that you implement the right things and use [it()] to ensure you do the things right.” - testthat documentation

    +
    +
    +
    describe("Description of feature or specification",
    +      code = { 
    +    it("Functionality under test",
    +        code = {
    +            expect_equal( 
    +            object = 2 * 2, 
    +            expected = 4 
    +            )
    +        })
    +    })
    +
    +
    +
    1
    +
    +describe() the feature or specification
    +
    +
    +
    2
    +
    +Capture it() in a test
    +
    +
    +
    3
    +
    +Write expectations +
    +
    +
    +
    +

    We’ll cover BDD more in the next chapter, but for now just know that each call to it() behaves like test_that().

    +

    Running tests

      @@ -631,7 +670,7 @@

      Keyboard shortcut

      expected = 4 ) }) -## Test passed 🥇
      +## Test passed 🎉
    diff --git a/test_tools.html b/test_tools.html index 3e3d6c4..e43f71a 100644 --- a/test_tools.html +++ b/test_tools.html @@ -492,11 +492,11 @@

    Test data

    1
    -The code used to create the test data (make-make_tidy_ggp2_movies.R) +The code used to create the test data (make-make_tidy_ggp2_movies.R)
    2
    -The test data file (i.e., tidy_ggp2_movies.rds): +The test data file (i.e., tidy_ggp2_movies.rds):
    @@ -533,37 +533,37 @@

    Example: test fixture
    1
    -High-level description (title and description)
    +High-level description (title and description)
    2
    -Steps or conditions that exist before each scenario
    +Steps or conditions that exist before each scenario
    3
    -Used to describe the initial context or preconditions for the scenario
    +Used to describe the initial context or preconditions for the scenario
    4
    -A series of steps outlining a concrete examples that illustrates a feature
    +A series of steps outlining a concrete examples that illustrates a feature
    5
    -Used to describe an event, or an action
    +Used to describe an event, or an action
    6
    -Use to combine Given, When, or Then
    +Use to combine Given, When, or Then
    7
    -Use to verify expected outcomes that are observable by a user +Use to verify expected outcomes that are observable by a user
    @@ -623,32 +623,32 @@

    Example: test fixture
    1
    -Feature
    +Feature
    2
    -Scenario
    +Scenario
    3
    -Test inputs
    +Test inputs
    4
    -Test fixture
    +Test fixture
    5
    -Create observed object
    +Create observed object
    6
    -Expectation +Expectation
    @@ -676,17 +676,17 @@

    Helpers

    1
    -Test fixture scripts and .rds files
    +Test fixture scripts and .rds files
    2
    -Helper functions
    +Helper functions
    3
    -Test file +Test file
    @@ -755,12 +755,12 @@

    Helpers

    1
    -Load test fixture
    +Load test fixture
    2
    -Identical to the code in mod_scatter_display_server() +Identical to the code in mod_scatter_display_server()
    @@ -996,27 +996,27 @@

    Example: snapshots

    1
    -Test scope (T2)
    +Test scope (T2)
    2
    -Log start (T2)
    +Log start (T2)
    3
    -Initial movies variable inputs for x, y, and z from UI
    +Initial movies variable inputs for x, y, and z from UI
    4
    -Snapshot with initial values
    +Snapshot with initial values
    5
    -Log end (T2)
    +Log end (T2)
    diff --git a/whole_game.html b/whole_game.html index 535ca29..d058a2a 100644 --- a/whole_game.html +++ b/whole_game.html @@ -497,7 +497,7 @@

    1
    -Always leave an empty final line in the DESCRIPTION +Always leave an empty final line in the DESCRIPTION