Skip to content

Commit 540d68e

Browse files
authored
Update the _inputs_ and _values_ regular expr to support a trailing = (#3648)
1 parent 1ad49b1 commit 540d68e

File tree

4 files changed

+47
-29
lines changed

4 files changed

+47
-29
lines changed

R/bookmark-state.R

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -321,34 +321,38 @@ RestoreContext <- R6Class("RestoreContext",
321321
if (substr(queryString, 1, 1) == '?')
322322
queryString <- substr(queryString, 2, nchar(queryString))
323323

324+
# The "=" after "_inputs_" is optional. Shiny doesn't generate URLs with
325+
# "=", but httr always adds "=".
326+
inputs_reg <- "(^|&)_inputs_=?(&|$)"
327+
values_reg <- "(^|&)_values_=?(&|$)"
324328

325329
# Error if multiple '_inputs_' or '_values_'. This is needed because
326330
# strsplit won't add an entry if the search pattern is at the end of a
327331
# string.
328-
if (length(gregexpr("(^|&)_inputs_(&|$)", queryString)[[1]]) > 1)
332+
if (length(gregexpr(inputs_reg, queryString)[[1]]) > 1)
329333
stop("Invalid state string: more than one '_inputs_' found")
330-
if (length(gregexpr("(^|&)_values_(&|$)", queryString)[[1]]) > 1)
334+
if (length(gregexpr(values_reg, queryString)[[1]]) > 1)
331335
stop("Invalid state string: more than one '_values_' found")
332336

333337
# Look for _inputs_ and store following content in inputStr
334-
splitStr <- strsplit(queryString, "(^|&)_inputs_(&|$)")[[1]]
338+
splitStr <- strsplit(queryString, inputs_reg)[[1]]
335339
if (length(splitStr) == 2) {
336340
inputStr <- splitStr[2]
337341
# Remove any _values_ (and content after _values_) that may come after
338342
# _inputs_
339-
inputStr <- strsplit(inputStr, "(^|&)_values_(&|$)")[[1]][1]
343+
inputStr <- strsplit(inputStr, values_reg)[[1]][1]
340344

341345
} else {
342346
inputStr <- ""
343347
}
344348

345349
# Look for _values_ and store following content in valueStr
346-
splitStr <- strsplit(queryString, "(^|&)_values_(&|$)")[[1]]
350+
splitStr <- strsplit(queryString, values_reg)[[1]]
347351
if (length(splitStr) == 2) {
348352
valueStr <- splitStr[2]
349353
# Remove any _inputs_ (and content after _inputs_) that may come after
350354
# _values_
351-
valueStr <- strsplit(valueStr, "(^|&)_inputs_(&|$)")[[1]][1]
355+
valueStr <- strsplit(valueStr, inputs_reg)[[1]][1]
352356

353357
} else {
354358
valueStr <- ""

man/downloadHandler.Rd

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/fileInput.Rd

Lines changed: 5 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/test-bookmarking.R

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,33 @@
11
test_that("Inputs and values in query string", {
2-
# Normal format
3-
vals <- RestoreContext$new("?_inputs_&a=1&b=2&_values_&x=3")$asList()
4-
expect_true(contents_identical(vals$input, list(a=1L, b=2L)))
5-
expect_identical(as.list(vals$values), list(x=3L))
6-
7-
# No leading '?', trailing '&', and values before inputs
8-
vals <- RestoreContext$new("_values_&x=3&_inputs_&a=1&b=2&")$asList()
9-
expect_true(contents_identical(vals$input, list(a=1L, b=2L)))
10-
expect_identical(as.list(vals$values), list(x=3L))
11-
12-
# Just inputs, no values, and leading '&'
13-
vals <- RestoreContext$new("&_inputs_&a=1&b=2")$asList()
14-
expect_true(contents_identical(vals$input, list(a=1L, b=2L)))
15-
expect_identical(as.list(vals$values), list())
162

17-
# No inputs, just values
18-
vals <- RestoreContext$new("?_values_&x=3")$asList()
19-
expect_identical(vals$input, list())
20-
expect_identical(as.list(vals$values), list(x=3L))
3+
restore_context <- function(...) {
4+
RestoreContext$new(paste0(...))$asList()
5+
}
6+
7+
for (input_str in c("_inputs_", "_inputs_=")) {
8+
for (value_str in c("_values_", "_values_=")) {
9+
10+
# Normal format
11+
vals <- restore_context("?", input_str, "&a=1&b=2&", value_str, "&x=3")
12+
expect_true(contents_identical(vals$input, list(a=1L, b=2L)))
13+
expect_identical(as.list(vals$values), list(x=3L))
14+
15+
# No leading '?', trailing '&', and values before inputs
16+
vals <- restore_context(value_str, "&x=3&", input_str, "&a=1&b=2&")
17+
expect_true(contents_identical(vals$input, list(a=1L, b=2L)))
18+
expect_identical(as.list(vals$values), list(x=3L))
19+
20+
# Just inputs, no values, and leading '&'
21+
vals <- restore_context("&", input_str, "&a=1&b=2")
22+
expect_true(contents_identical(vals$input, list(a=1L, b=2L)))
23+
expect_identical(as.list(vals$values), list())
24+
25+
# No inputs, just values
26+
vals <- restore_context("?", value_str, "&x=3")
27+
expect_identical(vals$input, list())
28+
expect_identical(as.list(vals$values), list(x=3L))
29+
}
30+
}
2131

2232
# Empty query string
2333
vals <- RestoreContext$new("")$asList()

0 commit comments

Comments
 (0)