test_that("canonical b64url roundtrips raw and is URL-safe", { set.seed(123) bytes <- as.raw(sample.int(256, size = 64, replace = TRUE) - 1L) enc <- shinyOAuth:::b64url_encode(bytes) dec <- shinyOAuth:::b64url_decode(enc) # round-trip expect_true(is.character(enc) && length(enc) == 1L) expect_true(is.raw(dec)) expect_identical(dec, bytes) # URL-safe alphabet and no padding expect_false(grepl("[+/=]", enc)) }) test_that("wrappers mirror canonical helpers", { # Use bytes that will need padding in standard base64 to test both paths bytes1 <- charToRaw("f") # 'Zg==' -> 'Zg' bytes2 <- charToRaw("fo") # 'Zm8=' -> 'Zm8' bytes3 <- charToRaw("foobar") # multiples of 3, no padding for (b in list(bytes1, bytes2, bytes3)) { enc_canon <- shinyOAuth:::b64url_encode(b) enc_wrap <- shinyOAuth:::base64url_encode(b) expect_identical(enc_wrap, enc_canon) # Raw decode dec_raw_wrap <- shinyOAuth:::base64url_decode_raw(enc_canon) dec_raw_canon <- shinyOAuth:::b64url_decode(enc_canon) expect_identical(dec_raw_wrap, dec_raw_canon) # Text decode (for JSON parts); ensure it matches original text when valid UTF-8 txt <- rawToChar(b) dec_txt_wrap <- shinyOAuth:::base64url_decode(enc_canon) expect_identical(dec_txt_wrap, txt) } }) test_that("decode accepts missing or present padding equivalently", { # Choose input that requires padding in base64 to ensure stripped form is shorter b <- charToRaw("fo") enc <- shinyOAuth:::b64url_encode(b) # e.g., 'Zm8' # Manually add required '=' padding to create a padded variant missing <- (4 - (nchar(enc) %% 4)) %% 4 enc_padded <- if (missing > 0) paste0(enc, strrep("=", missing)) else enc dec1 <- shinyOAuth:::b64url_decode(enc) dec2 <- shinyOAuth:::b64url_decode(enc_padded) expect_identical(dec1, dec2) }) test_that("unicode text roundtrips via wrappers", { txt <- "héllø 🌍" raw <- charToRaw(txt) # UTF-8 enc <- shinyOAuth:::base64url_encode(raw) out <- shinyOAuth:::base64url_decode(enc) expect_identical(out, txt) }) test_that("invalid input yields empty decode without error", { r1 <- shinyOAuth:::b64url_decode("!@#") expect_true(is.raw(r1)) expect_length(r1, 0) t1 <- shinyOAuth:::base64url_decode("!@#") expect_identical(t1, "") r2 <- shinyOAuth:::base64url_decode_raw("!@#") expect_true(is.raw(r2)) expect_length(r2, 0) })