test_that("inputs are concatenated, interpolated variables recycled", {
  expect_equal(
    glue("test", "a", "string", "{1:2}"),
    c("testastring1", "testastring2")
  )
})
test_that("glue errors if the expression fails", {
  expect_snapshot(glue("{NoTfOuNd}"), error = TRUE)
})

test_that("glue ignores trailing empty argument", {
  expect_equal(glue("x", ), glue("x"))
})

test_that("glue errors if invalid format", {
  expect_snapshot(glue("x={x"), error = TRUE)
})

test_that("glue returns length 1 string from length 1 input", {
  expect_equal(glue(""), "")
})

test_that("glue works with single expressions", {
  foo <- "foo"
  expect_equal(glue("{foo}"), foo)

  foo <- 1L
  expect_identical(glue("{foo}"), as_glue(foo))

  foo <- as.raw(1)
  expect_identical(glue("{foo}"), as_glue(foo))

  foo <- TRUE
  expect_identical(glue("{foo}"), as_glue(foo))

  foo <- as.Date("2016-01-01")
  expect_identical(glue("{foo}"), as_glue(foo))
})

test_that("glue works with repeated expressions", {
  foo <- "foo"
  expect_equal(glue("{foo} {foo}"), paste(foo, foo))

  foo <- 1L
  expect_equal(glue("{foo} {foo}"), paste(as.character(foo), as.character(foo)))

  foo <- as.raw(1)
  expect_equal(glue("{foo} {foo}"), paste(as.character(foo), as.character(foo)))

  foo <- TRUE
  expect_equal(glue("{foo} {foo}"), paste(as.character(foo), as.character(foo)))

  foo <- as.Date("2016-01-01")
  expect_equal(glue("{foo} {foo}"), paste(as.character(foo), as.character(foo)))
})

test_that("glue works with multiple expressions", {
  foo <- "foo"
  bar <- "bar"
  expect_equal(glue("{foo} {bar}"), paste(foo, bar))

  foo <- 1L
  bar <- 2L
  expect_equal(glue("{foo} {bar}"), paste(as.character(foo), as.character(bar)))

  foo <- as.raw(1)
  bar <- as.raw(2)
  expect_equal(glue("{foo} {bar}"), paste(as.character(foo), as.character(bar)))

  foo <- TRUE
  bar <- FALSE
  expect_equal(glue("{foo} {bar}"), paste(as.character(foo), as.character(bar)))

  foo <- as.Date("2016-01-01")
  bar <- as.Date("2016-01-02")
  expect_equal(glue("{foo} {bar}"), paste(as.character(foo), as.character(bar)))
})

test_that("glue with doubled braces are converted glue single braces", {
  expect_equal(glue("{{foo}}"), "{foo}")
})

test_that("glue works with complex expressions", {
  `foo}\`` <- "foo"

  expect_equal(
    glue(
      "{
      {
        '}\\'' # { and } in comments, single quotes
        \"}\\\"\" # or double quotes are ignored
        `foo}\\`` # as are { in backticks
      }
  }"
    ),
    `foo}\``
  )
})

test_that("glue works with large outputs", {
  # initial buffer allocates input string length + 1024, 40 * 26 = 1040
  foo <- paste(rep(letters, 40), collapse = "")

  # re-allocation on result
  expect_equal(glue("{foo}"), foo)

  # re-allocation on input
  bar <- paste(rep(letters, 40), collapse = "")
  additional <- " some more text that requires an allocation"
  expect_equal(glue("{bar}", additional), paste0(bar, additional))
})

test_that("glue works with named arguments", {
  name <- "Fred"
  res <- glue(
    'My name is {name},',
    ' my age next year is {age + 1},',
    ' a dot is a {.}',
    name = "Joe",
    age = 40,
    . = "'.'"
  )

  expect_equal(
    res,
    "My name is Joe, my age next year is 41, a dot is a '.'"
  )

  expect_identical(name, "Fred")
})

test_that("glue evaluates arguments in the expected environment", {
  x <- 2
  fun <- function() {
    x <- 1
    glue("x: {x}, x+1: {y}", y = x + 1, .envir = parent.frame())
  }

  expect_equal(fun(), "x: 2, x+1: 3")
})

test_that("glue assigns arguments in the environment", {
  expect_equal(glue("{b}", a = 1, b = a), "1")
})

test_that("error if non length 1 inputs", {
  expect_snapshot(glue(1:2, "{1:2}"), error = TRUE)
})

test_that("error if not simple recycling", {
  expect_snapshot(glue("{1:2}{1:10}"), error = TRUE)
})

test_that("recycle_columns returns if zero length input", {
  expect_identical(recycle_columns(list()), list())
  expect_identical(recycle_columns(list(character())), character())
})

test_that("glue_data evaluates in the object first, then enclosure, then parent", {
  x <- 1
  y <- 1
  z <- 1
  fun <- function(env = environment()) {
    y <- 2
    glue_data(list(x = 3), "{x} {y} {z}", .envir = env)
  }

  # The function environment
  expect_equal(fun(), "3 2 1")

  # This environment
  env <- environment()
  expect_equal(fun(env), "3 1 1")

  # A new environment
  env2 <- new.env(parent = emptyenv())
  env2$x <- 3
  env2$y <- 3
  env2$z <- 3

  expect_equal(glue_data(env2, "{x} {y} {z}"), "3 3 3")
})

test_that("glue_data lazily evaluates named interpolation variables, in order", {
  # Decoy 'x', which should not be evaluated
  delayedAssign("x", stop("This 'x' shouldn't have been referenced"))

  env <- new.env()
  env$x <- "blah"

  expect_equal(
    glue_data(.x = env, "{x}{z}", y = stop("!"), z = x),
    "blahblah"
  )
  expect_equal(
    glue_data(.x = env, "{x}{z}", z = x, y = stop("!")),
    "blahblah"
  )
  expect_equal(
    glue_data(.x = list(x = "blah"), "{x}{z}", y = stop("!"), z = x),
    "blahblah"
  )
  expect_equal(
    glue_data(.x = list(x = "blah"), "{x}{z}", z = x, y = stop("!")),
    "blahblah"
  )
  expect_equal(
    glue_data(.x = NULL, "{x}{z}", x = "blah", y = stop("!"), z = x),
    "blahblah"
  )
  expect_equal(
    glue_data(.x = NULL, "blahblah", y = stop("!"), z = x),
    "blahblah"
  )
  expect_equal(
    glue_data(.x = NULL, "blahblah", x = x, y = stop("!"), z = x),
    "blahblah"
  )
})

test_that("converting glue to character", {
  expect_identical(as.character(glue("foo bar")), "foo bar")
})

test_that("converting glue to glue", {
  expect_equal(glue("foo bar"), "foo bar")
})

test_that("printing glue identical to cat()", {
  expect_output(print(glue("foo\nbar")), "foo\nbar")
})

test_that("length 0 inputs produce length 0 outputs", {
  expect_equal(glue("foo", character(0)), character(0))
  expect_equal(glue("foo", NULL), character(0))
  expect_equal(glue("foo", NULL, "bar"), character(0))

  expect_equal(glue("foo", "{character(0)}"), character(0))
  expect_equal(glue("foo {character(0)}"), character(0))
})

test_that("values are trimmed before evaluation", {
  x <- " a1\n b2\n c3"

  expect_equal(
    glue(
      "
  A
  {x}
  B
  "
    ),
    "A
 a1
 b2
 c3
B"
  )
})

test_that("glue works with alternative delimiters", {
  expect_equal(glue("{1}", .open = "", .close = ""), "{1}")
  expect_equal(glue("{{}}", .open = "", .close = ""), "{{}}")

  expect_equal(glue("<<1>>", .open = "<<", .close = ">>"), "1")
  expect_equal(glue("<<<<>>>>", .open = "<<", .close = ">>"), "<<>>")

  expect_equal(glue("{{1}}", .open = "{{", .close = "}}"), "1")
  expect_equal(glue("{{ {{1}} }}", .open = "{{", .close = "}}"), "1")
  expect_equal(glue("{{ {{{1}}} }}", .open = "{{", .close = "}}"), "1")
  expect_equal(glue("{{ {{{{1}}}} }}", .open = "{{", .close = "}}"), "1")

  expect_equal(glue("[letters[[1]]]", .open = "[", .close = "]"), "a")

  expect_equal(glue("[[ letters[[1]] ]]", .open = "[[", .close = "]]"), "a")
})

test_that("you can disable trimming in glue and glue_data", {
  expect_equal(glue("\nfoo\n"), "foo")
  expect_equal(glue("\nfoo\n", .trim = FALSE), "\nfoo\n")

  expect_equal(glue_data(list(), "\nfoo\n"), "foo")
  expect_equal(glue_data(list(), "\nfoo\n", .trim = FALSE), "\nfoo\n")
})

test_that("glue always returns UTF-8 encoded strings regardless of input encodings", {
  x <- "fa\xE7ile"
  Encoding(x) <- "latin1"

  x_out <- as_glue(enc2utf8(x))

  expect_identical(glue(x), x_out)
  expect_identical(glue("{x}"), x_out)
  expect_equal(Encoding(glue(x)), "UTF-8")
  expect_equal(Encoding(glue("{x}")), "UTF-8")

  y <- "p\u00E4o"
  Encoding(y) <- "UTF-8"

  y_out <- as_glue(enc2utf8(y))

  expect_identical(glue(y), y_out)
  expect_identical(glue("{y}"), y_out)
  expect_equal(Encoding(glue(y)), "UTF-8")
  expect_equal(Encoding(glue("{y}")), "UTF-8")

  xy_out <- as_glue(paste0(x_out, y_out))

  expect_identical(glue(x, y), xy_out)
  expect_identical(glue("{x}{y}"), xy_out)
  expect_equal(Encoding(glue(x, y)), "UTF-8")
  expect_equal(Encoding(glue("{x}{y}")), "UTF-8")

  expect_equal(Encoding(glue_collapse(x)), "UTF-8")

  skip_on_os(c("mac", "linux", "solaris"))
  withr::with_locale(c(LC_CTYPE = "Chinese (Simplified)_China.936"), {
    z <- "{format(as.Date(\"2018-01-04\"), \"%Y\U5E74\")}"
    z_out <- glue(z)
    expect_equal(Encoding(z_out), "UTF-8")
    expect_equal(z_out, "2018\U5E74")
  })
})

test_that("glue always returns NA_character_ if given any NA input and `.na` == NULL", {
  expect_equal(
    glue("{NA}", .na = NULL),
    NA_character_
  )

  expect_equal(
    glue(NA, .na = NULL),
    NA_character_
  )

  expect_equal(
    glue(NA, 1, .na = NULL),
    NA_character_
  )

  expect_equal(
    glue(1, NA, 2, .na = NULL),
    NA_character_
  )

  x <- c("foo", NA_character_, "bar")
  expect_equal(
    glue("{x}", .na = NULL),
    c("foo", NA_character_, "bar")
  )

  expect_equal(
    glue("{1:3} - {x}", .na = NULL),
    c("1 - foo", NA_character_, "3 - bar")
  )
})

test_that("glue always returns .na if given any NA input and `.na` != NULL", {
  expect_equal(
    glue("{NA}", .na = "foo"),
    "foo"
  )

  expect_equal(
    glue("{NA}", .na = "foo"),
    "foo"
  )

  expect_equal(
    glue(NA, .na = "foo"),
    "foo"
  )

  expect_equal(
    glue(NA, 1, .na = "foo"),
    "foo1"
  )

  expect_equal(
    glue(1, NA, 2, .na = "foo"),
    "1foo2"
  )

  x <- c("foo", NA_character_, "bar")
  expect_equal(
    glue("{x}", .na = "baz"),
    c("foo", "baz", "bar")
  )

  expect_equal(
    glue("{1:3} - {x}", .na = "baz"),
    c("1 - foo", "2 - baz", "3 - bar")
  )
})

test_that("glue always returns character() if given any NULL input if `.null` == character()", {
  expect_equal(
    glue("{NULL}", .null = character()),
    character()
  )

  expect_equal(
    glue("{}", .null = character()),
    character()
  )

  expect_equal(
    glue(NULL, .null = character()),
    character()
  )

  expect_equal(
    glue(NULL, 1, .null = character()),
    character()
  )

  expect_equal(
    glue(1, NULL, 2, .null = character()),
    character()
  )

  expect_equal(
    glue("x: ", if (FALSE) "positive", .null = character()),
    character()
  )

  expect_equal(
    glue("x: {NULL}", .null = character()),
    character()
  )
})

test_that("glue drops any NULL input if `.null` == NULL", {
  # This should work like `paste0()`
  expect_equal(
    glue("{NULL}", .null = NULL),
    character()
  )

  expect_equal(
    glue("{}", .null = NULL),
    character()
  )

  expect_equal(
    glue(NULL, .null = NULL),
    character()
  )

  expect_equal(
    glue(NULL, 1, .null = NULL),
    "1"
  )

  expect_equal(
    glue(1, NULL, 2, .null = NULL),
    "12"
  )

  expect_equal(
    glue("x: ", if (FALSE) "positive", .null = NULL),
    "x: "
  )

  expect_equal(
    glue("x: {NULL}", .null = NULL),
    "x: "
  )
})

test_that("glue replaces NULL input if `.null` is not NULL or character()", {
  expect_equal(
    glue("{NULL}", .null = "foo"),
    "foo"
  )

  expect_equal(
    glue("{}", .null = "foo"),
    "foo"
  )

  expect_equal(
    glue(NULL, .null = "foo"),
    "foo"
  )

  expect_equal(
    glue(NULL, 1, .null = "foo"),
    "foo1"
  )

  expect_equal(
    glue(1, NULL, 2, .null = "foo"),
    "1foo2"
  )

  expect_equal(
    glue("x: ", if (FALSE) "positive", .null = "foo"),
    "x: foo"
  )

  expect_equal(
    glue("x: {NULL}", .null = "foo"),
    "x: foo"
  )
})

test_that("glue works within functions", {
  x <- 1
  f <- function(msg) glue(msg, .envir = parent.frame())

  expect_equal(f("{x}"), "1")
})

test_that("scoping works within lapply (#42)", {
  f <- function(msg) {
    glue(msg, .envir = parent.frame())
  }
  expect_identical(
    lapply(1:2, function(x) f("{x * 2}")),
    list(as_glue("2"), as_glue("4"))
  )
})

test_that("glue works with lots of arguments", {
  expect_equal(
    glue(
      "a",
      "very",
      "long",
      "test",
      "of",
      "how",
      "many",
      "unnamed",
      "arguments",
      "you",
      "can",
      "have"
    ),
    "averylongtestofhowmanyunnamedargumentsyoucanhave"
  )
})

test_that("glue does not drop it's class when subsetting", {
  expect_equal(glue("foo")[1], "foo")

  expect_equal(glue("foo")[[1]], "foo")

  expect_equal(glue("{1:2}")[2], "2")
})

test_that("interpolation variables can have same names as their values (#89)", {
  x <- 1
  expect_equal(
    glue("{x}", x = x + 1),
    "2"
  )
})

test_that("as_glue works", {
  expect_identical(as_glue(as_glue("x")), as_glue("x"))
})

test_that("throws informative error if interpolating a function", {
  expect_snapshot(glue("{cat}"), error = TRUE)

  # some crayon functions are OK, make sure this still works
  if (require("crayon", quietly = TRUE)) {
    expect_s3_class(glue("{red}red{reset}"), "glue")
  }
})

test_that("`+` method for glue works", {
  expect_identical(glue("foo") + "bar", "foobar")
  expect_identical("foo" + glue("bar"), "foobar")
})

test_that("`+` method requires character vectors", {
  expect_snapshot(error = TRUE, {
    as_glue("a") + 1
    1 + as_glue("a")
  })
})

test_that("`+` method does not interpolate twice", {
  expect_identical(glue("{x}", x = "{wut}") + "y", "{wut}y")
})

test_that("`+` method returns length-0 if there is a length-0 input", {
  expect_identical(as_glue("hello") + character(), character())
})

test_that("`+` method returns length-0 if there is a `NULL` input", {
  expect_identical(as_glue("hello") + NULL, character())
})

test_that("`+` recycles", {
  x <- c("a", "b", "c")
  expect_identical("(" + as_glue(x) + ")", paste0("(", x, ")"))
  y <- as.character(1:3)
  expect_identical(as_glue(x) + y, c("a1", "b2", "c3"))
})

test_that("`+` method errors for inputs of incompatible size", {
  expect_snapshot(error = TRUE, {
    as_glue(letters[1:2]) + letters[1:3]
  })
})

test_that("unterminated quotes are error", {
  expect_snapshot(glue("{this doesn\"t work}"), error = TRUE)
  expect_snapshot(glue("{this doesn't work}"), error = TRUE)
  expect_snapshot(glue("{this doesn`t work}"), error = TRUE)
})

test_that("unterminated comment", {
  expect_snapshot(
    error = TRUE,
    glue("pre {1 + 5 # comment} post")
  )
  expect_snapshot(
    error = TRUE,
    glue("pre {1 + 5 # comment")
  )

  expect_equal(glue("pre {1 + 5 + #comment\n 4} post"), "pre 10 post")
})

test_that("empty glue produces no output", {
  expect_equal(capture.output(print(glue())), character())
})

test_that("glue objects can be compared to regular strings", {
  expect_equal(capture.output(print(glue())), character())
})

test_that("glue can use different comment characters (#193)", {
  expect_equal(
    glue(.comment = "", "{foo#}", .transformer = function(x, ...) x),
    "foo#"
  )
})

test_that("`.literal` treats quotes and `#` as regular characters", {
  expect_snapshot(
    error = TRUE,
    glue("{'fo`o\"#}", .transformer = function(x, ...) x)
  )
  expect_equal(
    glue("{'fo`o\"#}", .literal = TRUE, .transformer = function(x, ...) x),
    "'fo`o\"#"
  )
})

test_that("`.literal` is not about (preventing) evaluation", {
  x <- "world"
  expect_equal(glue("hello {x}!"), glue("hello {x}!", .literal = TRUE))
})

# glue_collapse ----------------------------------------------------------

test_that("glue_collapse works like paste(glue_collapse=)", {
  # Always return 0 length outputs for 0 length inputs.
  #expect_identical(paste(glue_collapse = "", character(0)), glue_collapse(character(0)))

  expect_identical(as_glue(paste(collapse = "", "")), glue_collapse(""))

  expect_identical(as_glue(paste(collapse = "", 1:10)), glue_collapse(1:10))

  expect_identical(
    as_glue(paste(collapse = " ", 1:10)),
    glue_collapse(1:10, sep = " ")
  )
})

test_that("glue_collapse truncates", {
  expect_identical(as_glue("12345678910"), glue_collapse(1:10, width = 11))
  expect_identical(as_glue("12345678910"), glue_collapse(1:10, width = 100))
  expect_identical(as_glue("1234567..."), glue_collapse(1:10, width = 10))
  expect_identical(as_glue("123..."), glue_collapse(1:10, width = 6))
  expect_identical(as_glue("1..."), glue_collapse(1:10, width = 4))
  expect_identical(as_glue("..."), glue_collapse(1:10, width = 0))
})

test_that("last argument to glue_collapse", {
  expect_equal(glue_collapse(character(), last = " and "), as_glue(""))
  expect_equal(glue_collapse("", last = " and "), as_glue(""))
  expect_equal(glue_collapse(1, last = " and "), as_glue("1"))
  expect_equal(glue_collapse(1:2, last = " and "), as_glue("1 and 2"))
  expect_equal(
    glue_collapse(1:4, ", ", last = " and "),
    as_glue("1, 2, 3 and 4")
  )

  expect_equal(
    glue_collapse(1:4, ", ", last = " and ", width = 5),
    as_glue("1,...")
  )

  expect_equal(
    glue_collapse(1:4, ", ", last = " and ", width = 10),
    as_glue("1, 2, 3...")
  )
})

test_that("glue_collapse returns empty string for 0 length input", {
  expect_identical(glue_collapse(character()), as_glue(""))
})

test_that("glue_collapse returns NA_character_ if any inputs are NA", {
  expect_identical(glue_collapse(NA_character_), as_glue(NA_character_))

  expect_identical(
    glue_collapse(c(1, 2, 3, NA_character_)),
    as_glue(NA_character_)
  )

  expect_identical(
    glue_collapse(c("foo", NA_character_, "bar")),
    as_glue(NA_character_)
  )
})

# trim -------------------------------------------------------------------

test_that("trim works", {
  expect_identical("", trim(""))
  expect_identical(character(), trim(character()))
  expect_identical(" ", trim(" "))
  expect_identical("test", trim("test"))
  expect_identical(" test", trim(" test"))
  expect_identical("test ", trim("test "))
  expect_identical("test", trim("test"))
  expect_identical(c("foo", "bar"), trim(c("foo", "bar")))
  expect_identical(c("foo", "bar"), trim(c("\nfoo", "bar\n")))
  expect_identical(
    "test",
    trim(
      "test"
    )
  )
  expect_identical(
    "test",
    x <- trim(
      "test
    "
    )
  )
  expect_identical(
    "test",
    trim(
      "\x20\x20\x20\x20\x20\x20
      test
      "
    )
  )
  expect_identical(
    "test",
    trim(
      "test"
    )
  )
  expect_identical(
    "test\n  test2",
    trim(
      "
      test
        test2
      "
    )
  )
  expect_identical(
    "test\n  test2\n    test3",
    trim(
      "
      test
        test2
          test3
      "
    )
  )

  expect_identical(
    "\ntest\n",
    trim(
      "

      test

      "
    )
  )
})

test_that("trim strips escaped newlines", {
  expect_identical(
    "foo bar baz",
    trim("foo bar \\\nbaz")
  )

  expect_identical(
    trim(
      "
      foo bar \\
      baz"
    ),
    "foo bar baz"
  )

  expect_identical(
    trim(
      "
      foo bar \\
      baz
      "
    ),
    "foo bar baz"
  )

  expect_identical(
    "foo bar baz\n",
    trim("foo bar baz\n\n")
  )

  expect_identical(
    "\nfoo bar baz",
    trim("\n\nfoo bar baz")
  )
})

test_that("issue#44", {
  expect_identical(
    trim(
      "12345678
            foo
           bar
          baz
           bar
            baz"
    ),
    "12345678\n  foo\n bar\nbaz\n bar\n  baz"
  )
})

test_that("issue#47", {
  expect_identical(
    trim(
      "
      Hello,
      World.
    "
    ),
    "  Hello,\n  World."
  )

  expect_identical(
    trim(
      "
      foo
              bar
        123456789"
    ),
    "foo\n        bar\n  123456789"
  )

  expected <- "The stuff before the bullet list\n  * one bullet"

  expect_identical(
    trim(
      "The stuff before the bullet list
            * one bullet
          "
    ),
    expected
  )

  expect_identical(
    trim(
      "
      The stuff before the bullet list
        * one bullet"
    ),
    expected
  )

  expect_identical(
    trim(
      "
         The stuff before the bullet list
           * one bullet
         "
    ),
    expected
  )
})

test_that("lines containing only indentation are handled properly", {
  # Tabs and spaces are considered indentation. The following examples look
  # funny because I'm using a tab escape as the last indentation character to
  # prevent RStudio from removing trailing whitespace on save.
  expect_identical(
    trim(
      "
         \ta
         \tb
         \t
         \tc"
    ),
    "a\nb\n\nc"
  )
  expect_identical(
    trim(
      "
         \ta
       \tb
         \t
         \tc"
    ),
    " \ta\nb\n \t\n \tc"
  )
  # A line shorter than min_indent that contains only indentation should not be
  # trimmed, removed, or prepended to the next line.
  expect_identical(
    trim(
      "
       \ta
       \tb
      \t
       \tc"
    ),
    "a\nb\n      \t\nc"
  )
  # Ensure empty intermedite lines are handled properly
  expect_identical(
    trim(
      "
       \ta
       \tb

       \tc"
    ),
    "a\nb\n\nc"
  )
})

# https://github.com/tidyverse/glue/issues/238
test_that("indent counter resets at newline", {
  # whitespace-only line has 1 space < min_indent (which is 2)
  # comment in trim_() says:
  # "if the line consists only of tabs and spaces, and if the line is
  #  shorter than min_indent, copy the entire line"
  expect_identical(trim("\n \n  abcd"), " \nabcd")

  # whitespace-only line has n spaces, n >= min_indent
  expect_identical(trim("\n  \n  abcd"), "\nabcd")
  expect_identical(trim("\n   \n  abcd"), " \nabcd")
})

# https://github.com/tidyverse/glue/issues/247
test_that("trailing whitespace-only line doesn't goof up indentation", {
  expect_identical(trim("\n  A\n\n"), "A\n")
  # comment in trim_() says:
  # "if the line consists only of tabs and spaces, and if the line is
  #  shorter than min_indent, copy the entire line"
  expect_identical(trim("\n  A\n \n"), "A\n ")
  expect_identical(trim("\n  A\n  \n"), "A\n")
  expect_identical(trim("\n  A\n   \n"), "A\n ")
})
