context("query strings") test_that("query strings are properly parsed", { expect_equal(parseQS("?a=1"), list(a="1")) expect_equal(parseQS("b=2"), list(b="2")) expect_equal(parseQS("a=1&b=2&c=url%20encoded"), list(a="1", b="2", c="url encoded")) }) test_that("path parameters do not convert + to space", { r <- pr(test_path("files/path-params.R")) expect_equal(r$route(make_req("GET", "/car/a+b"), PlumberResponse$new()), "a+b") }) test_that("special characters in query strings are handled properly", { expect_equal(parseQS("?a=1+.#"), list(a="1 .#")) expect_equal(parseQS("?a=a%20b"), list(a="a b")) expect_equal(parseQS('?a=%2C%2B%2F%3F%25%26'), list(a=",+/?%&")) }) test_that("null an empty strings return empty list", { expect_equal(parseQS(NULL), list()) expect_equal(parseQS(""), list()) }) test_that("incomplete query strings are ignored", { expect_equivalent(parseQS("a="), list()) # It's technically a named list() expect_equal(parseQS("a=1&b=&c&d=1"), list(a="1", d="1")) }) test_that("query strings with duplicates are made into vectors", { expect_equal(parseQS("a=1&a=2&a=3&a=4"), list(a=c("1", "2", "3", "4"))) }) test_that("parseQS() will mark UTF-8 explicitly", { expect_warning( { out <- parseQS("%E5%8F%82%E6%95%B01=%E4%B8%AD%E6%96%87") }, "received in non-ASCII encoding" ) expect_equal(Encoding(names(out)), "UTF-8") expect_identical( charToRaw(names(out)), as.raw(c(0xe5, 0x8f, 0x82, 0xe6, 0x95, 0xb0, 0x31)) ) expect_identical( charToRaw(out[[1L]]), as.raw(c(0xe4, 0xb8, 0xad, 0xe6, 0x96, 0x87)) ) expect_equal(Encoding(out[[1L]]), "UTF-8") }) test_that("different lengths of query string return same shape", { for (n in c(5, 50, 500, 1000)) { keys <- sample(letters, n, replace = TRUE) vals <- as.list(sample(letters, n, replace = TRUE)) expect_equal( parseQS( paste0("?", paste0(keys, "=", vals, collapse = "&")) ), stats::setNames( lapply(unique(keys), function(key) { unname(unlist(vals[keys == key])) }), unique(keys) ) ) } })