Skip to content

Commit

Permalink
Allow vector values in fields
Browse files Browse the repository at this point in the history
Closes #130. Fixes #127.
  • Loading branch information
hadley committed Dec 19, 2020
1 parent 1914cdc commit 9ba664b
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 20 deletions.
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# rvest (development version)

* `form_set()` can now accept character vectors allowing you to select
multiple checkboxes in a set or select multiple values from a multi-`<select>`
(#127, with help from @juba).

* Objects within a `html_form()` now have class `rvest_field`, instead of a
variety of classes that were lacking the `rvest_` prefix.

Expand Down
26 changes: 15 additions & 11 deletions R/form-submit.R
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
#' @param form An [html_form()].
#' @param ... <[`dynamic-dots`][rlang::dyn-dots]> Name-value pairs giving
#' fields to modify.
#'
#' Provide a character vector to set multiple checkboxes in a set or
#' select multiple values from a multi-select.
#' @return `set_values()` returns an updated form object;
#' `submit_form()` returns the parsed HTML response (or an error if the
#' HTTP request fails).
Expand Down Expand Up @@ -70,13 +73,13 @@ form_submit <- function(form, session, submit = NULL, ...) {
if (request$method == "POST") {
request_POST(session,
url = request$url,
body = as.list(request$values),
body = request$values,
encode = request$enctype
)
} else {
request_GET(session,
url = request$url,
query = as.list(request$values)
query = request$values
)
}
}
Expand Down Expand Up @@ -120,11 +123,17 @@ submission_build_values <- function(form, submit = NULL) {
fields <- form$fields
submit <- submission_find_submit(fields, submit)
entry_list <- c(Filter(Negate(is_button), fields), list(submit))
entry_list <- Filter(is_entry, entry_list)
entry_list <- Filter(function(x) !is.null(x$name), entry_list)

if (length(entry_list) == 0) {
return(list())
}

values <- map_chr(entry_list, "[[", "value")
names(values) <- map_chr(entry_list, "[[", "name")
values
values <- lapply(entry_list, function(x) as.character(x$value))
names <- map_chr(entry_list, "[[", "name")

out <- set_names(unlist(values, use.names = FALSE), rep(names, lengths(values)))
as.list(out)
}

submission_find_submit <- function(fields, idx) {
Expand Down Expand Up @@ -157,11 +166,6 @@ submission_find_submit <- function(fields, idx) {
}
}

# https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#constructing-the-form-data-set
is_entry <- function(x) {
length(x$value) == 1 && !is.null(x$name)
}

is_button <- function(x) {
tolower(x$type) %in% c("submit", "image", "button")
}
Expand Down
4 changes: 2 additions & 2 deletions R/utils.R
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ pluck <- function(x, i, type) {
}

map_chr <- function(.x, .f, ...) {
vapply(.x, .f, ..., FUN.VALUE = character(1))
vapply(.x, .f, ..., FUN.VALUE = character(1), USE.NAMES = FALSE)
}
map_lgl <- function(.x, .f, ...) {
vapply(.x, .f, ..., FUN.VALUE = logical(1))
vapply(.x, .f, ..., FUN.VALUE = logical(1), USE.NAMES = FALSE)
}

str_trunc <- function(x, width) {
Expand Down
5 changes: 4 additions & 1 deletion man/form_set.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 22 additions & 6 deletions tests/testthat/test-form-submit.R
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,10 @@ test_that("works as expected in simple case", {
sub <- submission_build(form, "clickMe", "http://here.com")
expect_equal(sub$method, "POST")
expect_equal(sub$url, "http://here.com/test-path")
expect_equal(sub$values, c(x = "1"))
expect_equal(sub$values, list(x = "1"))
})


test_that("useful feedback on invalid forms", {
html <- minimal_html("test", "<form></form>")
form <- html_form(html)[[1]]
Expand All @@ -64,6 +65,22 @@ test_that("useful feedback on invalid forms", {
expect_snapshot(x <- submission_build(form, NULL, base_url = "http://"))
})

test_that("can handle multiple values", {
html <- minimal_html("test", '
<form method="post" action="/">
<input type="text" name="x">
<input type="text" name="y">
</form>
')
form <- html_form(html)[[1]]
form <- form_set(form, x = c("1", "2", "3"), y = character())

expect_equal(
submission_build_values(form),
list(x = "1", x = "2", x = "3")
)
})

test_that("handles multiple buttons", {
html <- minimal_html("test", '
<form action="/">
Expand All @@ -75,10 +92,10 @@ test_that("handles multiple buttons", {

# Messages when picking automatically
expect_snapshot(vals <- submission_build_values(form, NULL))
expect_equal(vals, c(one = "1"))
expect_equal(vals, list(one = "1"))

expect_equal(submission_build_values(form, "two"), c(two = "2"))
expect_equal(submission_build_values(form, 2L), c(two = "2"))
expect_equal(submission_build_values(form, "two"), list(two = "2"))
expect_equal(submission_build_values(form, 2L), list(two = "2"))

# Useful failure messages
expect_snapshot(submission_build_values(form, 3L), error = TRUE)
Expand All @@ -96,7 +113,7 @@ test_that("handles no buttons", {

expect_equal(
submission_build_values(form),
c(x = "1")
list(x = "1")
)
})

Expand Down Expand Up @@ -129,4 +146,3 @@ test_that("can submit using three primary techniques", {
show_response(form_submit(form, session))
})
})

0 comments on commit 9ba664b

Please sign in to comment.