test_that("generating R code from original data works", {
  set.seed(5653)
  data <- data.frame(x = rnorm(100),
                     y = rnorm(100),
                     z = rnorm(100),
                     w = rnorm(100),
                     q = rnorm(100))
  # Generate R code for the data.
  code <- semproducible(data,
                        covmat_variable = "tmp_var",
                        formula = "y ~ x + z + w")
  # Make sure the output type is correct.
  expect_true(is_semproducible(code))
  # Run the generate code.
  eval(parse(text = code))
  # Make sure the data type is correct.
  expect_equal(class(tmp_var)[[1]], "matrix")
  # All values should be the same (digits will be different on different
  # systems so we need to use rounding to get the same number of digits).
  total_true <- sum(
    round(as.data.frame(cov(data)), 5) == round(as.data.frame(tmp_var), 5))
  # There should be 25 identical values.
  expect_equal(25, total_true)
})
test_that("different vars_per_line work", {
  set.seed(5653)
  data <- data.frame(x = rnorm(100),
                     y = rnorm(100),
                     z = rnorm(100),
                     w = rnorm(100),
                     q = rnorm(100))
  # Test different vars_per_line (from -1 to 30) and run the code.
  for (i in -1:30) {
    eval(parse(text = semproducible(data,
                                    covmat_variable = "tmp_var_test",
                                    formula = "y ~ x + z + w",
                                    vars_per_line = i)))
    # Variable should be a matrix if code successfully ran.
    expect_equal(class(tmp_var_test)[[1]], "matrix")
    expect_type(tmp_var_test, "double")
    # Variable should be lavaan object.
    expect_equal(class(fit)[1], "lavaan")
    # Clean up so we don't accidentally test old variables.
    rm(tmp_var_test)
    rm(fit)
  }
})
test_that("no comments in generated code works", {
  set.seed(5653)
  data <- data.frame(x = rnorm(100),
                     y = rnorm(100),
                     z = rnorm(100),
                     w = rnorm(100),
                     q = rnorm(100))
  code <- semproducible(data, covmat_variable="tmp_var_test", comments=TRUE,
                        formula = "y ~ x + z + w")
  eval(parse(text = code))
  expect_true(stringi::stri_detect_fixed(code, "#"))
  code <- semproducible(data, covmat_variable="tmp_var_test", comments=FALSE,
                        formula = "y ~ x + z + w")
  eval(parse(text = code))
  expect_false(stringi::stri_detect_fixed(code, "#"))
  expect_equal(class(fit)[1], "lavaan")
  rm(tmp_var_test)
  rm(fit)
})
test_that("covariance matrix as input works", {
  set.seed(5653)
  data <- data.frame(x = rnorm(100),
                     y = rnorm(100),
                     z = rnorm(100),
                     w = rnorm(100),
                     q = rnorm(100))
  # Same thing again, but with covariance matrix input instead.
  cov_mat <- cov(data)
  code <- semproducible(cov_mat, covmat_variable="tmp_var2",
                        formula = "y ~ x + z + w",
                        vars_per_line = 1)
  # Make sure the output type is correct.
  expect_true(is_semproducible(code))
  # Run the generated code.
  eval(parse(text = code))
  # Make sure the data type is correct.
  expect_equal(class(tmp_var2)[[1]], "matrix")
  # All values should be the same (digits will be different on different
  # systems so we need to use rounding to get the same number of digits).
  total_true <- sum(
    round(as.data.frame(cov(data)), 5) == round(as.data.frame(tmp_var2), 5))
  # There should be 25 identical values.
  expect_equal(25, total_true)
})
test_that("non-numeric input parameters works", {
  set.seed(5653)
  data <- data.frame(x = rnorm(100),
                     y = rnorm(100),
                     z = rnorm(100),
                     w = rnorm(100),
                     q = rnorm(100),
                     chr = rep("a", 100))
  # Should throw an error about non-numeric columns.
  expect_error(semproducible(data,
                             covmat_variable="tmp_var3",
                             formula = "y ~ x + z + w"))
  # Should work: drop_non_numeric = TRUE.
  expect_message(code <- semproducible(data,
                        covmat_variable="tmp_var3",
                        formula = "y ~ x + z + w",
                        drop_non_numeric = TRUE))
  # Make sure the output type is correct.
  expect_true(is_semproducible(code))
  # Run the generated code.
  eval(parse(text = code))
  # Make sure the data type is correct.
  expect_equal(class(tmp_var3)[[1]], "matrix")
  # All values should be the same (digits will be different on different
  # systems so we need to use rounding to get the same number of digits).
  data_no_numeric <- data[, c("x", "y", "z", "w", "q")]
  total_true <- sum(
    round(as.data.frame(cov(data_no_numeric)), 5) == round(
      as.data.frame(tmp_var3), 5))
  # There should be 25 identical values.
  expect_equal(25, total_true)
})
test_that("wrong input parameters fails", {
  wrong <- list()
  expect_error(semproducible(wrong, formula = character(0)))
  data <- data.frame(x=rnorm(100), y=rnorm(100))
  expect_error(semproducible(data, covmat_variable=""))
  expect_error(semproducible(data, covmat_variable=NULL))
  expect_error(semproducible(data, covmat_variable=NULL))
  expect_error(semproducible(data, template=NULL))
})
get_any_working_lavaan_model <- function() {
  formula <- "visual  =~ x1 + x2 + x3
              textual =~ x4 + x5 + x6
              speed   =~ x7 + x8 + x9"
  fit <- lavaan::sem(model=formula, data=lavaan::HolzingerSwineford1939)
  list(fit=fit, formula=formula)
}
test_that("empty formula works", {
  model <- get_any_working_lavaan_model()
  fit <- model$fit
  formula <- model$formula
  code1 <- semproducible(fit, formula=NULL)
  code2 <- semproducible(fit, formula=NULL, eval=TRUE)
  code3 <- semproducible(fit, formula=formula, eval=TRUE)
  expect_gte(nchar(code1), 2000)
  expect_gte(nchar(code2), 2000)
  expect_gte(nchar(code3), 2000)
})
test_that("switching input arguments fails", {
  model <- get_any_working_lavaan_model()
  fit <- model$fit
  formula <- model$formula
  expect_error(semproducible(formula, fit))
})
test_that("evaluate code with invalid input arguments fails", {
  expect_error(run_and_evaluate_code(NULL, NULL))
  expect_error(run_and_evaluate_code(NULL, ""))
  expect_error(run_and_evaluate_code("", NULL))
})
test_that("saving code files work", {
  data <- data.frame(x = rnorm(100), y = rnorm(100))
  code <- semproducible(data, covmat_variable="tmp_var4",
                        formula = "y ~ x",
                        vars_per_line = 4)
  tmp_file <- tempfile(fileext = ".r")
  save_code(code, file = tmp_file)
  # This should give a warning that file already exists.
  expect_error(save_code(code, file = tmp_file))
  # This should work.
  save_code(code, file = tmp_file, overwrite = TRUE)
  # Cleanup test file.
  file.remove(tmp_file)
})
test_that("evaluating code works", {
  data <- data.frame(x = rnorm(100), y = rnorm(100))
  # This should work
  code <- semproducible(data, covmat_variable="tmp_var5", formula = "y ~ x",
                        vars_per_line = 4, digits = 3, eval = TRUE)
  # Use wrong variable names, should cause complaints by lavaan.
  expect_error(code <- semproducible(data, covmat_variable="tmp_var5",
                        formula = "y ~ VAR_DOES_NOT_EXIST",
                        vars_per_line = 4,
                        eval = TRUE))
})
test_that("using fitted lavaan object works", {
  data <- data.frame(x = rnorm(100), y = rnorm(100))
  fit <- lavaan::sem(model = "y ~ x", data = data)
  # This should work
  code <- semproducible(fit, covmat_variable="tmp_var6",
                        formula = "y ~ x",
                        vars_per_line = 3,
                        digits = 6)
  # Run the generated code.
  eval(parse(text = code))
  # Generated covariance matrix should be identical to original.
  expect_equal(tmp_var6[c("x", "y"), c("x", "y")],
               cov(data)[c("x", "y"), c("x", "y")], tolerance = 0.05)
})
test_that("more complex fitted lavaan object works", {
  model <- get_any_working_lavaan_model()
  fit <- model$fit
  formula <- model$formula
  # This should work
  code <- semproducible(fit, covmat_variable="tmp_var7",
                        formula = formula,
                        vars_per_line = 3,
                        digits = NULL)
  # Run the generated code.
  eval(parse(text = code))
  # Generated covariance matrix should be identical to original.
  data <- lavaan::HolzingerSwineford1939[c("x1", "x2", "x3",
                                           "x4", "x5", "x6",
                                           "x7", "x8", "x9")]
  expect_equal(tmp_var7, cov(data), tolerance = 0.005)
})
test_that("compare lavaan covariance with semproducible covariances works", {
  set.seed(8324)
  # Compare random covariance matrices.
  for (i in 1:10) {
    data <- data.frame(x = rnorm(1000),
                       y = rnorm(1000),
                       z = rnorm(1000),
                       w = rnorm(1000),
                       q = rnorm(1000))
    # Make lavaan model.
    formula = "y ~ x + z + w + q"
    lavaan_model <- lavaan::sem(formula, data)
    # Reproduce model with semproducible.
    code <- semproducible(data, covmat_variable = "tmp_var8",
                          formula = formula, digits = 10)
    eval(parse(text = code))
    # Compare lavaan + semproducible output.
    lavaan_cov <- lavaan::lavInspect(lavaan_model, what="sampstat")$cov
    expect_equal(lavaan_cov["y", "y"], tmp_var8["y", "y"], tolerance=0.01)
    expect_equal(lavaan_cov["x", "y"], tmp_var8["x", "y"], tolerance=0.01)
    expect_equal(lavaan_cov["z", "y"], tmp_var8["z", "y"], tolerance=0.01)
    expect_equal(lavaan_cov["w", "y"], tmp_var8["w", "y"], tolerance=0.01)
    expect_equal(lavaan_cov["q", "y"], tmp_var8["q", "y"], tolerance=0.01)
    expect_equal(lavaan_cov["q", "q"], tmp_var8["q", "q"], tolerance=0.01)
  }
})
test_that("growth model with data as input works", {
  set.seed(273)
  # Example from bottom of page: https://lavaan.ugent.be/tutorial/growth.html
  # a linear growth model with a time-varying covariate
  formula <- "
  # intercept and slope with fixed coefficients
    i =~ 1*t1 + 1*t2 + 1*t3 + 1*t4
    s =~ 0*t1 + 1*t2 + 2*t3 + 3*t4
  # regressions
    i ~ x1 + x2
    s ~ x1 + x2
  # time-varying covariates
    t1 ~ c1
    t2 ~ c2
    t3 ~ c3
    t4 ~ c4"
  lavaan_model <- lavaan::growth(formula, data=lavaan::Demo.growth)
  code <- semproducible(lavaan::Demo.growth, formula=formula, covmat_variable="tmp_var9")
  eval(parse(text = code))
  # Compare lavaan + semproducible output.
  lavaan_cov <- lavaan::lavInspect(lavaan_model, what="sampstat")$cov
  expect_equal(lavaan_cov["t1", "t2"], tmp_var9["t1", "t2"], tolerance=0.01)
  expect_equal(lavaan_cov["t3", "c3"], tmp_var9["t3", "c3"], tolerance=0.01)
})
test_that("growth model with model as input works", {
  set.seed(1234)
  # Example from bottom of page: https://lavaan.ugent.be/tutorial/growth.html
  # a linear growth model with a time-varying covariate
  formula <- "
  # intercept and slope with fixed coefficients
    i =~ 1*t1 + 1*t2 + 1*t3 + 1*t4
    s =~ 0*t1 + 1*t2 + 2*t3 + 3*t4
  # regressions
    i ~ x1 + x2
    s ~ x1 + x2
  # time-varying covariates
    t1 ~ c1
    t2 ~ c2
    t3 ~ c3
    t4 ~ c4"
  lavaan_model <- lavaan::growth(formula, data=lavaan::Demo.growth)
  code <- semproducible(lavaan_model, formula=formula, covmat_variable="tmp_var10")
  eval(parse(text = code))
  # Compare lavaan + semproducible output.
  lavaan_cov <- lavaan::lavInspect(lavaan_model, what="sampstat")$cov
  expect_equal(lavaan_cov["t1", "t2"], tmp_var10["t1", "t2"], tolerance=0.01)
  expect_equal(lavaan_cov["t3", "c3"], tmp_var10["t3", "c3"], tolerance=0.01)
  expect_equal(anova(fit)$Df[2], anova(lavaan_model)$Df[2], tolerance=0)
  expect_equal(anova(fit)$Pr[2], anova(lavaan_model)$Pr[2], tolerance=0.3) # here's some larger differences
})
test_that("example model #1 works", {
  # https://stats.stackexchange.com/questions/523678/lavaan-sem-through-time
  set.seed(1234)
  n <- 100
  ### T1
  X_t1 <- rnorm(n)
  x1_t1 <- X_t1 + rnorm(n)
  x2_t1 <- X_t1 + rnorm(n)
  x3_t1 <- X_t1 + rnorm(n)
  M_t1 <- 0.5*X_t1 + rnorm(n)
  Y_t1 <- 0.7*M_t1 + rnorm(n)
  DF1 <- data.frame(x1_t1, x2_t1, x3_t1, Y_t1, M_t1)
  ### T2
  X_t2 <- rnorm(n)
  x1_t2 <- X_t2 + rnorm(n)
  x2_t2 <- X_t2 + rnorm(n)
  x3_t2 <- X_t2 + rnorm(n)
  M_t2 <- 0.5*X_t2 + rnorm(n)
  Y_t2 <- 0.7*M_t2 + rnorm(n)
  DF2 <- data.frame(x1_t2, x2_t2, x3_t2, Y_t2, M_t2)
  # Dataframe
  DF <- cbind(DF1, DF2)
  model_free <- '
            #Time 1
            # latent variable
              X_t1 =~ x1_t1 + x2_t1 + x3_t1
            # direct effect
              Y_t1 ~ c*X_t1
            # mediator
              M_t1 ~ a*X_t1
              Y_t1 ~ b*M_t1
            # indirect effect (a*b)
              ab := a*b
            # total effect
              total_t1 := c + (a*b)
             # Time 2
            # latent variable
              X_t2 =~ x1_t2 + x2_t2 + x3_t2
            # direct effect
              Y_t2 ~ d*X_t2
            # mediator
              M_t2 ~ e*X_t2
              Y_t2 ~ f*M_t2
            # indirect effect (e*f)
              ef := e*f
            # total effect
              total_t2 := d + (e*f)'
  model_constrained <- '
            #Time 1
            # latent variable
              X_t1 =~ x1_t1 + x2_t1 + x3_t1
            # direct effect
              Y_t1 ~ c*X_t1
            # mediator
              M_t1 ~ a*X_t1
              Y_t1 ~ b*M_t1
            # indirect effect (a*b)
              ab := a*b
            # total effect
              total_t1 := c + (a*b)
            # Time 2
            # latent variable
              X_t2 =~ x1_t2 + x2_t2 + x3_t2
            # direct effect
              Y_t2 ~ c*X_t2
            # mediator
              M_t2 ~ a*X_t2
              Y_t2 ~ b*M_t2
            # indirect effect (a*b)
              ab := a*b
            # total effect
              total_t2 := c + (a*b)'
  # Original
  fit_free <- lavaan::sem(model_free, data = DF)
  fit_constrained <- lavaan::sem(model_constrained, data = DF)
  comparison1 <- lavaan::lavTestLRT(fit_free, fit_constrained)
  # Reproduce
  code_free <- semproducible(fit_free, model_free,
                             covmat_variable="covmat_free",
                             fit_variable="rep_free")
  code_constrained <- semproducible(fit_constrained, model_constrained,
                                    covmat_variable="covmat_constrained",
                                    fit_variable="rep_constrained")
  eval(parse(text = code_free))
  eval(parse(text = code_constrained))
  comparison2 <- lavaan::lavTestLRT(rep_free, rep_constrained)
  # Assert
  expect_equal(comparison1$Df, comparison2$Df)
  expect_equal(comparison1$Chisq, comparison2$Chisq)
})
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.