From 1648d038183fa1f4484cd35b53b0f4055b6d8431 Mon Sep 17 00:00:00 2001 From: Jakub Stepniak Date: Sat, 9 Sep 2023 13:02:02 +0200 Subject: [PATCH 01/10] bun support added --- DESCRIPTION | 2 +- R/config.R | 5 +++++ R/node.R | 31 +++++++++++++++++--------- R/tools.R | 20 ++++++++--------- inst/templates/app_structure/rhino.yml | 1 + vignettes/explanation/rhino-yml.Rmd | 5 +++++ 6 files changed, 43 insertions(+), 21 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 6708609a..07015650 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: rhino Title: A Framework for Enterprise Shiny Applications -Version: 1.5.0.9003 +Version: 1.5.0.9004 Authors@R: c( person("Kamil", "Żyła", role = c("aut", "cre"), email = "opensource+kamil@appsilon.com"), diff --git a/R/config.R b/R/config.R index 7ac65222..c4e53310 100644 --- a/R/config.R +++ b/R/config.R @@ -37,6 +37,11 @@ rhino_config_definition <- list( validator = option_validator("app_dir", "source", "box_top_level"), required = FALSE ), + list( + name = "js_package_manager", + validator = option_validator("npm", "bun"), + required = FALSE + ), list( name = "legacy_max_lint_r_errors", validator = positive_integer_validator, diff --git a/R/node.R b/R/node.R index 2263eb64..d7724534 100644 --- a/R/node.R +++ b/R/node.R @@ -9,26 +9,37 @@ add_node <- function(clean = FALSE) { copy_template("node", node_path()) } -# Run `npm` command (assume node directory already exists in the project). -npm_raw <- function(..., status_ok = 0) { +# Run `npm`/`bun` command (assume node directory already exists in the project). +js_package_manager_raw <- function(..., status_ok = 0) { + command <- read_config()$js_package_manager withr::with_dir(node_path(), { - status <- system2(command = "npm", args = c(...)) + status <- system2(command = command, args = c(...)) }) if (status != status_ok) { - cli::cli_abort("System command 'npm' exited with status {status}.") + cli::cli_abort("System command '{command}' exited with status {status}.") } } -# Run `npm` command (create node directory in the project if needed). -npm <- function(...) { +# Run `npm`/`bun` command (create node directory in the project if needed). +js_package_manager <- function(...) { + command <- read_config()$js_package_manager + command <- ifelse( + is.null(command), + "npm", + command + ) + display_names <- list( + npm = "Node.js", + bun = "Bun" + ) check_system_dependency( - cmd = "node", - dependency_name = "Node.js", + cmd = command, + dependency_name = display_names[[command]], documentation_url = "https://go.appsilon.com/rhino-system-dependencies" ) if (!fs::dir_exists(node_path())) { add_node() - npm_raw("install", "--no-audit", "--no-fund") + js_package_manager_raw("install", "--no-audit", "--no-fund") } - npm_raw(...) + js_package_manager_raw(...) } diff --git a/R/tools.R b/R/tools.R index 859c2ca2..4fef5111 100644 --- a/R/tools.R +++ b/R/tools.R @@ -185,9 +185,9 @@ format_r <- function(paths) { #' @export build_js <- function(watch = FALSE) { if (watch) { - npm("run", "build-js", "--", "--watch", status_ok = 2) + js_package_manager("run", "build-js", "--", "--watch", status_ok = 2) } else { - npm("run", "build-js") + js_package_manager("run", "build-js") } } @@ -224,9 +224,9 @@ build_js <- function(watch = FALSE) { # nolint end lint_js <- function(fix = FALSE) { if (fix) { - npm("run", "lint-js", "--", "--fix") + js_package_manager("run", "lint-js", "--", "--fix") } else { - npm("run", "lint-js") + js_package_manager("run", "lint-js") } } @@ -277,9 +277,9 @@ build_sass <- function(watch = FALSE) { build_sass_node <- function(watch = FALSE) { if (watch) { - npm("run", "build-sass", "--", "--watch", status_ok = 2) + js_package_manager("run", "build-sass", "--", "--watch", status_ok = 2) } else { - npm("run", "build-sass") + js_package_manager("run", "build-sass") } } @@ -310,9 +310,9 @@ build_sass_r <- function() { #' @export lint_sass <- function(fix = FALSE) { if (fix) { - npm("run", "lint-sass", "--", "--fix") + js_package_manager("run", "lint-sass", "--", "--fix") } else { - npm("run", "lint-sass") + js_package_manager("run", "lint-sass") } } @@ -343,8 +343,8 @@ lint_sass <- function(fix = FALSE) { #' @export test_e2e <- function(interactive = FALSE) { if (interactive) { - npm("run", "test-e2e-interactive") + js_package_manager("run", "test-e2e-interactive") } else { - npm("run", "test-e2e") + js_package_manager("run", "test-e2e") } } diff --git a/inst/templates/app_structure/rhino.yml b/inst/templates/app_structure/rhino.yml index fea13278..d554e4fc 100644 --- a/inst/templates/app_structure/rhino.yml +++ b/inst/templates/app_structure/rhino.yml @@ -1 +1,2 @@ sass: node +js_package_manager: "npm" \ No newline at end of file diff --git a/vignettes/explanation/rhino-yml.Rmd b/vignettes/explanation/rhino-yml.Rmd index f43b223a..0f9ce56b 100644 --- a/vignettes/explanation/rhino-yml.Rmd +++ b/vignettes/explanation/rhino-yml.Rmd @@ -19,6 +19,7 @@ options are described below. ```yaml sass: string # required | one of: "node", "r" legacy_entrypoint: string # optional | one of: "app_dir", "source", "box_top_level" +js_package_manager: string # optional | one of: "npm", "bun" ``` ### `sass` @@ -30,3 +31,7 @@ Read more in [Explanation: Node.js - JavaScript and Sass tools](https://appsilon ### `legacy_entrypoint` This setting is useful when migrating an existing Shiny application to Rhino. For more details see [`rhino::app()` details section](https://appsilon.github.io/rhino/reference/app.html#details-1). + +### `js_package_manager` +Configures whether [JavaScript packages](https://www.npmjs.com/) should be installed using [npm](https://www.npmjs.com/) or [bun](https://bun.sh/). +It allows to avoid installation of Node.js, and using Bun Javascript runtime. From 258cf91ab831beac2472e668e8192529dc850e0f Mon Sep 17 00:00:00 2001 From: Jakub Stepniak Date: Sat, 9 Sep 2023 13:13:14 +0200 Subject: [PATCH 02/10] improved format of default rhino.js --- inst/templates/app_structure/rhino.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inst/templates/app_structure/rhino.yml b/inst/templates/app_structure/rhino.yml index d554e4fc..f3e28992 100644 --- a/inst/templates/app_structure/rhino.yml +++ b/inst/templates/app_structure/rhino.yml @@ -1,2 +1,2 @@ sass: node -js_package_manager: "npm" \ No newline at end of file +js_package_manager: npm From f29a306eecb1f4b2a8ca7be95adc9439ae74eec9 Mon Sep 17 00:00:00 2001 From: Jakub Stepniak Date: Sat, 9 Sep 2023 13:21:58 +0200 Subject: [PATCH 03/10] fix for fresh apps --- R/node.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/node.R b/R/node.R index d7724534..5446f9be 100644 --- a/R/node.R +++ b/R/node.R @@ -39,7 +39,7 @@ js_package_manager <- function(...) { ) if (!fs::dir_exists(node_path())) { add_node() - js_package_manager_raw("install", "--no-audit", "--no-fund") + js_package_manager_raw(command, "install", "--no-audit", "--no-fund") } js_package_manager_raw(...) } From 3a374a0c0b78b82f134a7459b3177e85466ec379 Mon Sep 17 00:00:00 2001 From: Jakub Stepniak Date: Sat, 9 Sep 2023 13:31:33 +0200 Subject: [PATCH 04/10] restructure of setting npm as default --- R/config.R | 6 ++++++ R/node.R | 5 ----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/R/config.R b/R/config.R index c4e53310..ed91ba76 100644 --- a/R/config.R +++ b/R/config.R @@ -83,5 +83,11 @@ validate_config <- function(definition, config) { read_config <- function() { config <- read_yaml("rhino") validate_config(rhino_config_definition, config) + # using npm by default + config$js_package_manager <- ifelse( + is.null(config$js_package_manager), + "npm", + config$js_package_manager + ) config } diff --git a/R/node.R b/R/node.R index 5446f9be..623dfc9a 100644 --- a/R/node.R +++ b/R/node.R @@ -23,11 +23,6 @@ js_package_manager_raw <- function(..., status_ok = 0) { # Run `npm`/`bun` command (create node directory in the project if needed). js_package_manager <- function(...) { command <- read_config()$js_package_manager - command <- ifelse( - is.null(command), - "npm", - command - ) display_names <- list( npm = "Node.js", bun = "Bun" From 635583476d68849d8bf0974c7f7d2bd3ba42449f Mon Sep 17 00:00:00 2001 From: Jakub Stepniak Date: Sat, 9 Sep 2023 14:10:58 +0200 Subject: [PATCH 05/10] installation of js package manager fixed --- R/node.R | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/R/node.R b/R/node.R index 623dfc9a..5c1c639a 100644 --- a/R/node.R +++ b/R/node.R @@ -32,9 +32,16 @@ js_package_manager <- function(...) { dependency_name = display_names[[command]], documentation_url = "https://go.appsilon.com/rhino-system-dependencies" ) + init_js_package_manager() + js_package_manager_raw(...) +} + +init_js_package_manager <- function() { + command <- read_config()$js_package_manager if (!fs::dir_exists(node_path())) { add_node() + } + if (!fs::dir_exists(node_path("node_modules"))) { js_package_manager_raw(command, "install", "--no-audit", "--no-fund") } - js_package_manager_raw(...) } From 8527b5cb06837476b4844eb7e767cde144689f41 Mon Sep 17 00:00:00 2001 From: Jakub Stepniak Date: Sat, 9 Sep 2023 14:20:46 +0200 Subject: [PATCH 06/10] better js package installation --- R/node.R | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/R/node.R b/R/node.R index 5c1c639a..a63a245c 100644 --- a/R/node.R +++ b/R/node.R @@ -39,9 +39,11 @@ js_package_manager <- function(...) { init_js_package_manager <- function() { command <- read_config()$js_package_manager if (!fs::dir_exists(node_path())) { + message("Initializing Javascript packages…") add_node() } if (!fs::dir_exists(node_path("node_modules"))) { - js_package_manager_raw(command, "install", "--no-audit", "--no-fund") + message("Installing dependencies by ", command, "…") + js_package_manager_raw("install", "--no-audit", "--no-fund") } } From 55d4ba91a7c614a287e9d757c4b120f98d190ef1 Mon Sep 17 00:00:00 2001 From: Jakub Stepniak Date: Sun, 14 Jan 2024 19:26:20 +0000 Subject: [PATCH 07/10] using RHINO_NPM env var to control used package manager --- R/config.R | 11 ------- R/node.R | 29 +++++++------------ inst/templates/app_structure/rhino.yml | 1 - .../node-js-javascript-and-sass-tools.Rmd | 8 ++++- vignettes/explanation/rhino-yml.Rmd | 5 ---- 5 files changed, 18 insertions(+), 36 deletions(-) diff --git a/R/config.R b/R/config.R index ed91ba76..7ac65222 100644 --- a/R/config.R +++ b/R/config.R @@ -37,11 +37,6 @@ rhino_config_definition <- list( validator = option_validator("app_dir", "source", "box_top_level"), required = FALSE ), - list( - name = "js_package_manager", - validator = option_validator("npm", "bun"), - required = FALSE - ), list( name = "legacy_max_lint_r_errors", validator = positive_integer_validator, @@ -83,11 +78,5 @@ validate_config <- function(definition, config) { read_config <- function() { config <- read_yaml("rhino") validate_config(rhino_config_definition, config) - # using npm by default - config$js_package_manager <- ifelse( - is.null(config$js_package_manager), - "npm", - config$js_package_manager - ) config } diff --git a/R/node.R b/R/node.R index a63a245c..866cded1 100644 --- a/R/node.R +++ b/R/node.R @@ -2,16 +2,9 @@ node_path <- function(...) { fs::path(".rhino", ...) } -add_node <- function(clean = FALSE) { - if (clean && fs::dir_exists(node_path())) { - fs::dir_delete(node_path()) - } - copy_template("node", node_path()) -} - # Run `npm`/`bun` command (assume node directory already exists in the project). js_package_manager_raw <- function(..., status_ok = 0) { - command <- read_config()$js_package_manager + command <- Sys.getenv("RHINO_NPM", "npm") withr::with_dir(node_path(), { status <- system2(command = command, args = c(...)) }) @@ -22,14 +15,11 @@ js_package_manager_raw <- function(..., status_ok = 0) { # Run `npm`/`bun` command (create node directory in the project if needed). js_package_manager <- function(...) { - command <- read_config()$js_package_manager - display_names <- list( - npm = "Node.js", - bun = "Bun" - ) + command <- Sys.getenv("RHINO_NPM", "npm") + display_name <- ifelse(command == "npm", "Node.js", command) check_system_dependency( cmd = command, - dependency_name = display_names[[command]], + dependency_name = display_name, documentation_url = "https://go.appsilon.com/rhino-system-dependencies" ) init_js_package_manager() @@ -37,13 +27,16 @@ js_package_manager <- function(...) { } init_js_package_manager <- function() { - command <- read_config()$js_package_manager + command <- Sys.getenv("RHINO_NPM", "npm") if (!fs::dir_exists(node_path())) { - message("Initializing Javascript packages…") - add_node() + message("Initializing Javascript configs\u2026") + copy_template("node", node_path()) } + + # existing .rhino and missing node_modules folder + # indicate that packages were not installed but rhino project initialized if (!fs::dir_exists(node_path("node_modules"))) { - message("Installing dependencies by ", command, "…") + message("Installing dependencies by ", command, "\u2026") js_package_manager_raw("install", "--no-audit", "--no-fund") } } diff --git a/inst/templates/app_structure/rhino.yml b/inst/templates/app_structure/rhino.yml index f3e28992..fea13278 100644 --- a/inst/templates/app_structure/rhino.yml +++ b/inst/templates/app_structure/rhino.yml @@ -1,2 +1 @@ sass: node -js_package_manager: npm diff --git a/vignettes/explanation/node-js-javascript-and-sass-tools.Rmd b/vignettes/explanation/node-js-javascript-and-sass-tools.Rmd index e9044fd9..1adeed9e 100644 --- a/vignettes/explanation/node-js-javascript-and-sass-tools.Rmd +++ b/vignettes/explanation/node-js-javascript-and-sass-tools.Rmd @@ -13,7 +13,13 @@ vignette: > can execute JavaScript code outside a web browser. It is used widely for web development. Its package manager, [npm](https://docs.npmjs.com/about-npm), makes it easy to install -virtually any JavaScript library. +virtually any JavaScript library. You can use other package managers such as +[bun](https://bun.sh) and [pnpm](https://pnpm.io/) that are compatible with +`npm`. + +To switch from the default npm usage, set a global environment variable named +`RHINO_NPM`. For instance, if you want to use `bun` instead of `npm`, enter +`RHINO_NPM=bun`. Rhino uses Node.js to provide state of the art tools for working with JavaScript and Sass. The following functions require Node.js to work: diff --git a/vignettes/explanation/rhino-yml.Rmd b/vignettes/explanation/rhino-yml.Rmd index 0f9ce56b..f43b223a 100644 --- a/vignettes/explanation/rhino-yml.Rmd +++ b/vignettes/explanation/rhino-yml.Rmd @@ -19,7 +19,6 @@ options are described below. ```yaml sass: string # required | one of: "node", "r" legacy_entrypoint: string # optional | one of: "app_dir", "source", "box_top_level" -js_package_manager: string # optional | one of: "npm", "bun" ``` ### `sass` @@ -31,7 +30,3 @@ Read more in [Explanation: Node.js - JavaScript and Sass tools](https://appsilon ### `legacy_entrypoint` This setting is useful when migrating an existing Shiny application to Rhino. For more details see [`rhino::app()` details section](https://appsilon.github.io/rhino/reference/app.html#details-1). - -### `js_package_manager` -Configures whether [JavaScript packages](https://www.npmjs.com/) should be installed using [npm](https://www.npmjs.com/) or [bun](https://bun.sh/). -It allows to avoid installation of Node.js, and using Bun Javascript runtime. From 514a762bde3773c242041f8e4fd2ee61a8624361 Mon Sep 17 00:00:00 2001 From: Kamil Zyla Date: Wed, 17 Jan 2024 15:40:20 +0100 Subject: [PATCH 08/10] refactor: Apply review suggestions --- R/node.R | 49 +++++++++---------- R/tools.R | 20 ++++---- inst/WORDLIST | 7 ++- .../node-js-javascript-and-sass-tools.Rmd | 6 +-- 4 files changed, 40 insertions(+), 42 deletions(-) diff --git a/R/node.R b/R/node.R index 866cded1..7f0fbae9 100644 --- a/R/node.R +++ b/R/node.R @@ -2,41 +2,36 @@ node_path <- function(...) { fs::path(".rhino", ...) } -# Run `npm`/`bun` command (assume node directory already exists in the project). -js_package_manager_raw <- function(..., status_ok = 0) { - command <- Sys.getenv("RHINO_NPM", "npm") - withr::with_dir(node_path(), { - status <- system2(command = command, args = c(...)) - }) - if (status != status_ok) { - cli::cli_abort("System command '{command}' exited with status {status}.") - } -} - -# Run `npm`/`bun` command (create node directory in the project if needed). -js_package_manager <- function(...) { - command <- Sys.getenv("RHINO_NPM", "npm") - display_name <- ifelse(command == "npm", "Node.js", command) +# Run `npm` or an alternative command specified by `RHINO_NPM`. +# If needed, copy over Node.js template and install dependencies. +npm <- function(...) { + npm_command <- Sys.getenv("RHINO_NPM", "npm") check_system_dependency( - cmd = command, - dependency_name = display_name, + cmd = npm_command, + dependency_name = ifelse(npm_command == "npm", "Node.js", npm_command), documentation_url = "https://go.appsilon.com/rhino-system-dependencies" ) - init_js_package_manager() - js_package_manager_raw(...) + node_init(npm_command) + node_run(npm_command, ...) } -init_js_package_manager <- function() { - command <- Sys.getenv("RHINO_NPM", "npm") +node_init <- function(npm_command) { if (!fs::dir_exists(node_path())) { - message("Initializing Javascript configs\u2026") + cli::cli_alert_info("Initializing Node.js directory...") copy_template("node", node_path()) } - - # existing .rhino and missing node_modules folder - # indicate that packages were not installed but rhino project initialized if (!fs::dir_exists(node_path("node_modules"))) { - message("Installing dependencies by ", command, "\u2026") - js_package_manager_raw("install", "--no-audit", "--no-fund") + cli::cli_alert_info("Installing Node.js packages with {npm_command}...") + node_run(npm_command, "install", "--no-audit", "--no-fund") + } +} + +# Run the specified command in Node.js directory (assume it already exists). +node_run <- function(command, ..., status_ok = 0) { + withr::with_dir(node_path(), { + status <- system2(command = command, args = c(...)) + }) + if (status != status_ok) { + cli::cli_abort("System command '{command}' exited with status {status}.") } } diff --git a/R/tools.R b/R/tools.R index 4fef5111..859c2ca2 100644 --- a/R/tools.R +++ b/R/tools.R @@ -185,9 +185,9 @@ format_r <- function(paths) { #' @export build_js <- function(watch = FALSE) { if (watch) { - js_package_manager("run", "build-js", "--", "--watch", status_ok = 2) + npm("run", "build-js", "--", "--watch", status_ok = 2) } else { - js_package_manager("run", "build-js") + npm("run", "build-js") } } @@ -224,9 +224,9 @@ build_js <- function(watch = FALSE) { # nolint end lint_js <- function(fix = FALSE) { if (fix) { - js_package_manager("run", "lint-js", "--", "--fix") + npm("run", "lint-js", "--", "--fix") } else { - js_package_manager("run", "lint-js") + npm("run", "lint-js") } } @@ -277,9 +277,9 @@ build_sass <- function(watch = FALSE) { build_sass_node <- function(watch = FALSE) { if (watch) { - js_package_manager("run", "build-sass", "--", "--watch", status_ok = 2) + npm("run", "build-sass", "--", "--watch", status_ok = 2) } else { - js_package_manager("run", "build-sass") + npm("run", "build-sass") } } @@ -310,9 +310,9 @@ build_sass_r <- function() { #' @export lint_sass <- function(fix = FALSE) { if (fix) { - js_package_manager("run", "lint-sass", "--", "--fix") + npm("run", "lint-sass", "--", "--fix") } else { - js_package_manager("run", "lint-sass") + npm("run", "lint-sass") } } @@ -343,8 +343,8 @@ lint_sass <- function(fix = FALSE) { #' @export test_e2e <- function(interactive = FALSE) { if (interactive) { - js_package_manager("run", "test-e2e-interactive") + npm("run", "test-e2e-interactive") } else { - js_package_manager("run", "test-e2e") + npm("run", "test-e2e") } } diff --git a/inst/WORDLIST b/inst/WORDLIST index 70df777b..c89b7b65 100644 --- a/inst/WORDLIST +++ b/inst/WORDLIST @@ -1,3 +1,5 @@ +Addin +Addins Appsilon Boxifying ESLint @@ -13,9 +15,11 @@ Renv Renviron Rhinoverse Rprofile +Rstudio SDK Stylelint UI +Webpack blogpost conf config @@ -41,6 +45,7 @@ nodejs npm nvm overridable +pnpm preconfigured renv roxygen @@ -54,5 +59,3 @@ unintuitive usethis webpack yml -Addin -Addins diff --git a/vignettes/explanation/node-js-javascript-and-sass-tools.Rmd b/vignettes/explanation/node-js-javascript-and-sass-tools.Rmd index 1adeed9e..b896e43d 100644 --- a/vignettes/explanation/node-js-javascript-and-sass-tools.Rmd +++ b/vignettes/explanation/node-js-javascript-and-sass-tools.Rmd @@ -18,8 +18,8 @@ virtually any JavaScript library. You can use other package managers such as `npm`. To switch from the default npm usage, set a global environment variable named -`RHINO_NPM`. For instance, if you want to use `bun` instead of `npm`, enter -`RHINO_NPM=bun`. +`RHINO_NPM`. For instance, if you want to use `bun` instead of `npm`, +add `export RHINO_NPM=bun` to your shell startup file (e.g. `.bashrc`). Rhino uses Node.js to provide state of the art tools for working with JavaScript and Sass. The following functions require Node.js to work: @@ -32,7 +32,7 @@ JavaScript and Sass. The following functions require Node.js to work: ### Node directory -Under the hood Rhino will create a `.rhino/node` directory in your +Under the hood Rhino will create a `.rhino` directory in your project to store the specific libraries needed by these tools. This directory is git-ignored by default and safe to remove. From bf594c410d2722d4db6debb62f88a461f50e4965 Mon Sep 17 00:00:00 2001 From: Kamil Zyla Date: Thu, 18 Jan 2024 11:19:35 +0100 Subject: [PATCH 09/10] docs: Add RHINO_NPM to NEWS.md --- NEWS.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS.md b/NEWS.md index 4d26de0d..1076f588 100644 --- a/NEWS.md +++ b/NEWS.md @@ -10,6 +10,8 @@ * `lint_sass()` now uses `stylelint` 14.16 (the last major version supporting stylistic rules) * Upgrade all remaining Node.js dependencies to latest versions and fix vulnerabilities. * The minimum supported Node.js version is now 16. +4. Introduce `RHINO_NPM` environment variable +to allow using `npm` alternatives like `bun` and `pnpm`. # [rhino 1.5.0](https://github.com/Appsilon/rhino/releases/tag/v1.5.0) From 6b0684de90be4b065bac797daf42afda2976f6de Mon Sep 17 00:00:00 2001 From: Kamil Zyla Date: Thu, 18 Jan 2024 17:11:24 +0100 Subject: [PATCH 10/10] test: Add E2E test for RHINO_NPM env var --- .github/workflows/e2e-test.yml | 7 +++++++ tests/e2e/test-custom-npm.R | 22 ++++++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 tests/e2e/test-custom-npm.R diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index 9ff2ecdf..2be0b0f1 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -65,6 +65,13 @@ jobs: cd RhinoApp Rscript ../test-dependencies.R + - name: Node.js commands should respect RHINO_NPM + # Skip this test on Windows because it requires a Unix shell. + if: runner.os != 'Windows' + run: | + cd RhinoApp + Rscript ../test-custom-npm.R + - name: lint_r() should detect lint errors in R scripts if: always() run: | diff --git a/tests/e2e/test-custom-npm.R b/tests/e2e/test-custom-npm.R new file mode 100644 index 00000000..91f43a44 --- /dev/null +++ b/tests/e2e/test-custom-npm.R @@ -0,0 +1,22 @@ +local({ + tmp <- withr::local_tempdir() + wrapper_path <- fs::path(tmp, "wrapper") + touch_path <- fs::path(tmp, "it_works") + + # Prepare a wrapper script which creates an "it_works" file and runs npm. + fs::file_create(wrapper_path, mode = "u=rwx") + writeLines( + c( + "#!/bin/sh", + paste("touch", touch_path), + 'exec npm "$@"' + ), + wrapper_path + ) + + # Use the wrapper script instead of npm. + withr::local_envvar(RHINO_NPM = wrapper_path) + rhino:::npm("--version") + + testthat::expect_true(fs::file_exists(touch_path)) +})