tests/testthat/test-metareactive.R

test_that("doesn't break metaprogramming with quosures", {
  isolate({

    my_quo <- local({
      local_x <- 123L
      rlang::quo({
        "# A comment in a quosure"
        local_x
      })
    })

    outer_quo <- rlang::quo({
      if (!!my_quo == 123L) {
        "ok"
      }
    })

    # Reactive expressions

    r1 <- rlang::inject(metaReactive(!!my_quo, varname = "r1"))
    r2 <- rlang::inject(metaReactive(!!my_quo * -1L, varname = "r2"))

    expect_identical(r1(), 123L)
    expect_identical(r2(), -123L)

    expect_snapshot_output(withMetaMode(r1()))
    expect_snapshot_output(withMetaMode(r2()))

    # Observers

    result1 <- NULL
    o1 <- rlang::inject(metaObserve({
      result1 <<- !!outer_quo
    }))

    shiny:::flushReact()

    expect_identical(result1, "ok")

    expect_snapshot_output(withMetaMode(o1()))
  })

  # Outputs
  testthat::skip_if_not_installed("shiny", "1.6.0.9000")
  isolate({
    out1 <- rlang::inject(metaRender(shiny::renderText, !!outer_quo))
    expect_identical(out1(), "ok")
  })
})

describe("metaAction", {
  it("basically works", {
    a <- 1
    metaAction({
      a <- 2
    })
    expect_identical(a, 2)

    metaAction(quote({
      a <- 3
    }), quoted = TRUE)
    expect_identical(a, 3)

    env <- new.env()
    metaAction({
      a <- 4
    }, env = env)
    expect_identical(a, 3)
    expect_identical(env[["a"]], 4)

    metaAction(quote({
      a <- 5
    }), env = env, quoted = TRUE)
    expect_identical(a, 3)
    expect_identical(env[["a"]], 5)
  })

  it("unquotes properly", {
    b <- TRUE
    act <- metaAction(x <- ..(b))
    expect_identical(x, TRUE)
    expect_snapshot_output(withMetaMode(act()))

    mr <- metaReactive({
      FALSE
    })
    isolate({
      act <- metaAction(y <- ..(mr()))
    })
    expect_identical(y, FALSE)
    expect_snapshot_output(expandChain(act()))
  })

  it("errors on non-meta usage", {
    ma <- metaAction({})
    expect_error(ma())
  })

  it("can contain code that uses !!", {
    ma <- metaAction({
      foo <- 1
      x <- rlang::expr(!!foo)
    })
    expect_identical(x, 1)
    if (getRversion() < "3.5") {
      skip("Quoted !! isn't printed properly in R3.4 and lower.")
    } else {
      expect_snapshot_output(withMetaMode(ma()))
    }
  })

  it("obeys scoping rules", {
    # introduces scopes
    outer <- environment()
    i <- 0

    mr <- metaReactive({
      inner <- environment()
      expect_false(identical(inner, outer))

      i <<- i + 1
    })
    isolate(mr())

    expect_identical(i, 1)

    mr2 <- metaReactive2({
      inner <- environment()
      expect_false(identical(inner, outer))
      i <<- i + 1
      metaExpr({
        innermost <- environment()
        expect_true(identical(innermost, inner))
        i <<- i + 1
      })
    })
    isolate(mr2())

    expect_identical(i, 3)

    # In meta mode, the `metaExpr()` part of the reactive is quoted and
    # returned, not executed, so `i` only increments by 1.
    withMetaMode(mr2())
    expect_identical(i, 4)
  })
})
rstudio/shinymeta documentation built on April 26, 2024, 1:12 a.m.