test_that("format_yaml round-trips basic R lists", { obj <- list( foo = "bar", baz = list(TRUE, 123L), qux = list(sub = list("nested", NULL)) ) encoded <- format_yaml(obj) expect_type(encoded, "character") expected <- list( foo = "bar", baz = list(TRUE, 123L), qux = list(sub = c("nested", NA)) ) reparsed <- parse_yaml(encoded) expect_identical(reparsed, expected) expect_identical(parse_yaml(encoded, simplify = FALSE), obj) }) test_that("format_yaml preserves yaml_tag attribute", { obj <- structure( list( scalar = structure("bar", yaml_tag = "!expr"), seq = structure(list(1L, 2L), yaml_tag = "!seq") ), yaml_tag = "!custom" ) encoded <- format_yaml(obj) expect_true(grepl("!custom", encoded, fixed = TRUE)) expect_true(grepl("!expr", encoded, fixed = TRUE)) expect_true(grepl("!seq", encoded, fixed = TRUE)) reparsed <- parse_yaml(encoded) expect_identical(attr(reparsed, "yaml_tag"), "!custom") expect_identical(attr(reparsed$scalar, "yaml_tag"), "!expr") expect_identical(attr(reparsed$seq, "yaml_tag"), "!seq") }) test_that("format_yaml preserves yaml_tag attributes using core schema handle", { obj <- structure( list( seq = structure(list(1L, 2L), yaml_tag = "!!seq"), map = structure(list(foo = "bar"), yaml_tag = "!!map") ), yaml_tag = "!custom" ) encoded <- format_yaml(obj) expect_true(grepl("!!seq", encoded, fixed = TRUE)) expect_true(grepl("!!map", encoded, fixed = TRUE)) expect_true(grepl("!custom", encoded, fixed = TRUE)) reparsed <- parse_yaml(encoded, simplify = FALSE) expect_identical(attr(reparsed, "yaml_tag", exact = TRUE), "!custom") expect_null(attr(reparsed$seq, "yaml_tag", exact = TRUE)) expect_null(attr(reparsed$map, "yaml_tag", exact = TRUE)) }) test_that("format_yaml keeps fully-qualified yaml_tag strings intact", { obj <- structure("bar", yaml_tag = "!") encoded <- format_yaml(obj) expect_true(grepl("!", encoded, fixed = TRUE)) reparsed <- parse_yaml(encoded) expect_identical(reparsed, "bar") expect_null(attr(reparsed, "yaml_tag", exact = TRUE)) }) test_that("format_yaml round-trips multi-document streams", { docs <- list(list(foo = 1L), list(bar = list(2L, NULL))) encoded <- format_yaml(docs, multi = TRUE) expect_true(startsWith(encoded, "---")) expect_true(grepl("\n---\n", encoded, fixed = TRUE)) expect_true(grepl("\n$", encoded)) parsed <- parse_yaml(encoded, multi = TRUE) docs[[2]]$bar <- c(2L, NA) expect_identical(parsed, docs) }) test_that("format_yaml with multi = TRUE rejects named lists", { docs <- list(a = list(foo = 1L), b = list(bar = 2L)) expect_error( format_yaml(docs, multi = TRUE), "`value` must be an unnamed list when `multi = TRUE` (names must be NULL)", fixed = TRUE ) }) test_that("format_yaml single-document output has no header or trailing newline", { obj <- list(foo = 1L) encoded <- format_yaml(obj) expect_false(startsWith(encoded, "---")) expect_false(grepl("\n$", encoded)) expect_identical(parse_yaml(encoded), obj) }) test_that("format_yaml validates yaml_tag attribute shape", { tagged <- structure("value", yaml_tag = c("!a", "!b")) expect_error( format_yaml(tagged), "Invalid `yaml_tag` attribute: expected a single, non-missing string" ) bad_type <- structure("value", yaml_tag = 1L) expect_error( format_yaml(bad_type), "Invalid `yaml_tag` attribute: expected a single, non-missing string" ) }) test_that("format_yaml errors clearly when multi = TRUE without a list", { expect_error( format_yaml(1L, multi = TRUE), "`value` must be a list when `multi = TRUE`", fixed = TRUE ) }) test_that("format_yaml preserves binary tags", { # b64::encode("hello world") tagged <- structure("aGVsbG8gd29ybGQ=", yaml_tag = "!!binary") out <- format_yaml(tagged) expect_true(startsWith(out, "!!binary ")) expect_true(grepl("!!binary", out, fixed = TRUE)) reparsed <- parse_yaml(out) expect_identical(as.character(reparsed), "aGVsbG8gd29ybGQ=") expect_identical( attr(reparsed, "yaml_tag", exact = TRUE), "tag:yaml.org,2002:binary" ) }) test_that("format_yaml respects yaml_keys attribute", { parsed <- parse_yaml( r"--( 1: a true: b null: c 3.5: d )--" ) encoded <- format_yaml(parsed) reparsed <- parse_yaml(encoded) expect_identical(reparsed, parsed) }) test_that("format_yaml returns visibly", { obj <- list(answer = 42L) expect_visible(format_yaml(obj)) out <- format_yaml(obj) expect_true(is.character(out) && length(out) == 1) expect_identical(parse_yaml(out), obj) }) test_that("format_yaml preserves single-length collections", { seq_out <- format_yaml(list(list(1L))) reparsed_seq <- parse_yaml(seq_out) expect_identical(reparsed_seq, list(1L)) map_out <- format_yaml(list(list(key = 1L))) reparsed_map <- parse_yaml(map_out) expect_identical(reparsed_map, list(list(key = 1L))) }) test_that("format_yaml retains partial names as mapping keys", { obj <- list(a = 1L, 2L) encoded <- format_yaml(obj) reparsed <- parse_yaml(encoded) expect_named(reparsed, c("a", "")) expect_identical(reparsed[[1]], 1L) expect_identical(reparsed[[2]], 2L) }) test_that("format_yaml converts NA names to null YAML keys", { obj <- list(a = 1L, b = 2L) names(obj)[2] <- NA_character_ encoded <- format_yaml(obj) reparsed <- parse_yaml(encoded) expect_named(reparsed, c("a", "")) yaml_keys <- attr(reparsed, "yaml_keys", exact = TRUE) expect_identical(yaml_keys[[1]], "a") expect_null(yaml_keys[[2]]) }) test_that("format_yaml errors clearly on invalid yaml_tag", { missing <- structure("value", yaml_tag = NA_character_) expect_error( format_yaml(missing), "non-missing string.*Must not be NA" ) malformed <- structure("value", yaml_tag = "!!") expect_error( format_yaml(malformed), "Invalid YAML tag `!!`", fixed = TRUE ) }) test_that("format_yaml round-trips bare local tag handle", { tagged <- structure(1, yaml_tag = "!") encoded <- format_yaml(tagged) expect_identical(encoded, "! 1") reparsed <- parse_yaml(encoded) expect_identical(reparsed, structure("1", yaml_tag = "!")) }) if (FALSE) { test_that("format_yaml tags Date and POSIXct objects as timestamps", { posix_val <- as.POSIXct("2024-01-02 03:04:05", tz = "UTC") posix_yaml <- format_yaml(posix_val) expect_true(grepl("timestamp", posix_yaml, fixed = TRUE)) parsed_posix <- parse_yaml(posix_yaml) expect_s3_class(parsed_posix, "POSIXct") expect_identical(attr(parsed_posix, "tzone"), "UTC") expect_equal(as.numeric(parsed_posix), as.numeric(posix_val)) date_val <- as.Date("2024-01-02") date_yaml <- format_yaml(date_val) expect_true(grepl("timestamp", date_yaml, fixed = TRUE)) parsed_date <- parse_yaml(date_yaml) expect_s3_class(parsed_date, "Date") expect_identical(parsed_date, date_val) }) test_that("POSIXct values round-trip with format_yaml/parse_yaml", { utc_time <- as.POSIXct("2024-02-03 01:02:03", tz = "UTC") expect_identical(utc_time, parse_yaml(format_yaml(utc_time))) local_time <- as.POSIXct("2024-02-03 01:02:03", tz = "") round_tripped <- parse_yaml(format_yaml(local_time)) expect_s3_class(round_tripped, "POSIXct") expect_identical(as.numeric(round_tripped), as.numeric(local_time)) expect_null(attr(round_tripped, "tzone", exact = TRUE)) now_time <- Sys.time() expect_identical(now_time, parse_yaml(format_yaml(now_time))) naive_time <- structure(1763834102.3786, class = c("POSIXct", "POSIXt")) expect_identical(naive_time, parse_yaml(format_yaml(naive_time))) offset_time <- as.POSIXct("2024-02-03 01:02:03", tz = "Etc/GMT-3") offset_round_tripped <- parse_yaml(format_yaml(offset_time)) expect_s3_class(offset_round_tripped, "POSIXct") expect_identical(as.numeric(offset_round_tripped), as.numeric(offset_time)) expect_identical( attr(offset_round_tripped, "tzone", exact = TRUE), "Etc/GMT-3" ) }) test_that("Date sequences round-trip with format_yaml/parse_yaml", { dates <- seq.Date(as.Date("1000-01-01"), as.Date("3000-01-01"), by = "day") expect_equal(parse_yaml(format_yaml(dates)), dates) }) test_that("POSIXct round-trips with format_yaml/parse_yaml", { x <- .POSIXct(runif(10000, ISOdate(1000, 1, 1), ISOdate(3000, 1, 1))) expect_equal(x, parse_yaml(format_yaml(x))) x <- .POSIXct(runif(10000, ISOdate(1900, 1, 1), ISOdate(2100, 1, 1))) expect_equal(x, parse_yaml(format_yaml(x))) x <- .POSIXct(runif(10000, ISOdate(1960, 1, 1), ISOdate(2025, 1, 1))) expect_equal(x, parse_yaml(format_yaml(x))) }) }