test_that("simple expressions left as is", {
  lf <- lazy_frame(x = 1:10, y = 1:10)

  expect_equal(capture_dot(lf, NULL), NULL)
  expect_equal(capture_dot(lf, 10), 10)
  expect_equal(capture_dot(lf, x), sym("x"))
  expect_equal(capture_dot(lf, x + y), expr(x + y))
  expect_equal(capture_dot(lf, x[[1]]), expr(x[[1]]))

  # logicals
  expect_equal(eval(capture_dot(lf, T), globalenv()), TRUE)
  expect_equal(eval(capture_dot(lf, F), globalenv()), FALSE)
  expect_equal(capture_dot(lf, TRUE), TRUE)
  expect_equal(capture_dot(lf, FALSE), FALSE)
})

test_that("existing atomic non-variables get inlined", {
  lf <- lazy_frame(x = 1:10, y = 1:10)

  n <- 10
  expect_equal(capture_dot(lf, x + n), expr(x + 10))
})

test_that("names are stripped", {
  lf <- lazy_frame(x = "a")
  y <- c(x = "a", "b")

  expect_equal(partial_eval(quote(x %in% y), lf), expr(x %in% !!c("a", "b")))
})

test_that("using environment of inlined quosures", {
  lf <- lazy_frame(x = 1:10, y = 1:10)

  n <- 10
  quo <- new_quosure(quote(x + n), env(n = 20))

  expect_equal(capture_dot(lf, f(!!quo)), quote(f(x + 20)))
})

test_that("use quosure environment for unevaluted formulas", {
  lf <- lazy_frame(x = 1, y = 2)

  z <- 1
  expect_equal(partial_eval(expr(~z), lf), quote(~1))
})

test_that("can look up inlined function", {
  lf <- lazy_frame(x = 1, y = 2)

  expect_equal(
    partial_eval(expr((!!mean)(x)), data = lf),
    expr(mean(x))
  )
})

test_that("respects tidy evaluation pronouns", {
  lf <- lazy_frame(x = 1, y = 2)

  x <- "X"
  X <- "XX"

  expect_equal(partial_eval(expr(.data$x), lf), expr(x))
  expect_equal(partial_eval(expr(.data[["x"]]), lf), expr(x))
  expect_equal(partial_eval(expr(.data[[x]]), lf), expr(X))

  expect_equal(partial_eval(expr(.env$x), lf), "X")
  expect_equal(partial_eval(expr(.env[["x"]]), lf), "X")
  expect_equal(partial_eval(expr(.env[[x]]), lf), "XX")
})

test_that("respects .sql pronoun", {
  lf <- lazy_frame(x = 1)

  expect_equal(partial_eval(expr(.sql$foo), lf), expr(foo))
  expect_equal(partial_eval(expr(.sql$foo(x, "y")), lf), expr(foo(x, "y")))
})

test_that("sql() is inlined", {
  lf <- lazy_frame(x = 1)

  foo <- "x"
  expect_equal(partial_eval(expr(sql(foo)), lf), sql("x"))
})

test_that("fails with multi-classes", {
  lf <- lazy_frame(x = 1, y = 2)
  x <- structure(list(), class = c('a', 'b'))
  expect_error(partial_eval(x, lf), "Unknown input type", fixed = TRUE)
})

# replace_sym1 -----------------------------------------------------------------

test_that("replace_sym1() replaces matching symbols", {
  expect_equal(replace_sym1(sym("x"), "x", sym("y")), sym("y"))
  expect_equal(replace_sym1(sym("z"), "x", sym("y")), sym("z"))
  expect_equal(replace_sym1(expr(x + z), "x", sym("y")), expr(y + z))
  expect_equal(replace_sym1(1, "x", sym("y")), 1)
})

test_that("replace_sym1() supports list of replacements", {
  expect_equal(
    replace_sym1(expr(x + y), c("x", "y"), list(sym("a"), sym("b"))),
    expr(a + b)
  )
})

test_that("replace_sym1() does not rewrite field names of `$` and `@` (#1812)", {
  expect_equal(replace_sym1(expr(ltr$x), "x", sym("y")), expr(ltr$x))
  expect_equal(replace_sym1(expr(ltr@x), "x", sym("y")), expr(ltr@x))

  # but still recurses into the object
  expect_equal(replace_sym1(expr(x$foo), "x", sym("y")), expr(y$foo))
  expect_equal(replace_sym1(expr(x@foo), "x", sym("y")), expr(y@foo))
})
