tests/testthat/test-rmd_modify.R

test_that("rmd_modify works with rmd_ast", {
  # Create simple test AST
  original_ast = rmd_ast(
    nodes = list(
      rmd_heading(name = "Test", level = 1L),
      rmd_chunk(engine = "r", label = "test", code = "1 + 1"),
      rmd_markdown(lines = "Some text")
    )
  )
  
  # Test basic modification of heading name
  modified = rmd_modify(original_ast, .f = function(x) {
    if (inherits(x, "rmd_heading")) {
      x@name = "Modified Test"
    }
    x
  })
  
  expected_ast = rmd_ast(
    nodes = list(
      rmd_heading(name = "Modified Test", level = 1L),
      rmd_chunk(engine = "r", label = "test", code = "1 + 1"),
      rmd_markdown(lines = "Some text")
    )
  )
  
  expect_equal(modified, expected_ast)
})

test_that("rmd_modify works with selection", {
  # Create simple test AST
  original_ast = rmd_ast(
    nodes = list(
      rmd_heading(name = "Test", level = 1L),
      rmd_chunk(engine = "r", label = "test", code = "1 + 1"),
      rmd_markdown(lines = "Some text")
    )
  )
  
  # Test modification of selected chunk only
  modified = rmd_modify(original_ast, .f = function(x) {
    if (inherits(x, "rmd_chunk")) {
      x@code = "2 + 2"
    }
    x
  }, has_type("rmd_chunk"))
  
  expected_ast = rmd_ast(
    nodes = list(
      rmd_heading(name = "Test", level = 1L),
      rmd_chunk(engine = "r", label = "test", code = "2 + 2"),
      rmd_markdown(lines = "Some text")
    )
  )
  
  expect_equal(modified, expected_ast)
})

test_that("rmd_modify passes named arguments to function", {
  # Create simple test AST
  original_ast = rmd_ast(
    nodes = list(
      rmd_chunk(engine = "r", label = "test1", code = "1 + 1"),
      rmd_chunk(engine = "r", label = "test2", code = "2 + 2")
    )
  )
  
  # Test passing named arguments
  modified = rmd_modify(original_ast, .f = function(x, new_engine) {
    if (inherits(x, "rmd_chunk")) {
      x@engine = new_engine
    }
    x
  }, has_type("rmd_chunk"), new_engine = "python")
  
  expected_ast = rmd_ast(
    nodes = list(
      rmd_chunk(engine = "python", label = "test1", code = "1 + 1"),
      rmd_chunk(engine = "python", label = "test2", code = "2 + 2")
    )
  )
  
  expect_equal(modified, expected_ast)
})

test_that("rmd_modify works with multiple selection criteria", {
  # Create simple test AST
  original_ast = rmd_ast(
    nodes = list(
      rmd_heading(name = "Test", level = 1L),
      rmd_chunk(engine = "r", label = "test", code = "1 + 1"),
      rmd_markdown(lines = "Some text"),
      rmd_heading(name = "Another", level = 2L)
    )
  )
  
  # Test multiple selection arguments - modify both chunks and headings
  modified = rmd_modify(original_ast, .f = function(x) {
    if (inherits(x, "rmd_chunk")) {
      x@code = "modified"
    } else if (inherits(x, "rmd_heading")) {
      x@name = paste("Modified", x@name)
    }
    x
  }, has_type("rmd_chunk"), has_type("rmd_heading"))
  
  expected_ast = rmd_ast(
    nodes = list(
      rmd_heading(name = "Modified Test", level = 1L),
      rmd_chunk(engine = "r", label = "test", code = "modified"),
      rmd_markdown(lines = "Some text"),
      rmd_heading(name = "Modified Another", level = 2L)
    )
  )
  
  expect_equal(modified, expected_ast)
})

test_that("rmd_modify handles empty selection", {
  # Create simple test AST
  original_ast = rmd_ast(
    nodes = list(
      rmd_heading(name = "Test", level = 1L),
      rmd_markdown(lines = "Some text")
    )
  )
  
  # Test with selection that matches nothing
  modified = rmd_modify(original_ast, .f = function(x) {
    if (inherits(x, "rmd_chunk")) {
      x@code = "should not happen"
    }
    x
  }, has_type("rmd_chunk"))
  
  # Should be unchanged since no chunks exist
  expect_equal(modified, original_ast)
})

test_that("rmd_modify handles label-based selection", {
  # Create simple test AST
  original_ast = rmd_ast(
    nodes = list(
      rmd_chunk(engine = "r", label = "setup", code = "1 + 1"),
      rmd_chunk(engine = "r", label = "analysis", code = "2 + 2")
    )
  )
  
  # Test selection by chunk label
  modified = rmd_modify(original_ast, .f = function(x) {
    if (inherits(x, "rmd_chunk")) {
      x@code = "modified setup"
    }
    x
  }, "setup")
  
  expected_ast = rmd_ast(
    nodes = list(
      rmd_chunk(engine = "r", label = "setup", code = "modified setup"),
      rmd_chunk(engine = "r", label = "analysis", code = "2 + 2")
    )
  )
  
  expect_equal(modified, expected_ast)
})

test_that("rmd_modify validates .f argument", {
  original_ast = rmd_ast(
    nodes = list(
      rmd_heading(name = "Test", level = 1L)
    )
  )
  
  expect_snapshot_error(
    rmd_modify(original_ast, .f = "not_a_function")
  )
  
  expect_snapshot_error(
    rmd_modify(original_ast, .f = 123)
  )
})

test_that("rmd_modify works with range selection", {
  # Create simple test AST
  original_ast = rmd_ast(
    nodes = list(
      rmd_chunk(engine = "r", label = "chunk1", code = "1 + 1"),
      rmd_chunk(engine = "r", label = "chunk2", code = "2 + 2"),
      rmd_chunk(engine = "r", label = "chunk3", code = "3 + 3")
    )
  )
  
  # Test range selection
  modified = rmd_modify(original_ast, .f = function(x) {
    if (inherits(x, "rmd_chunk")) {
      x@code = "range modified"
    }
    x
  }, "chunk1":"chunk3")
  
  expected_ast = rmd_ast(
    nodes = list(
      rmd_chunk(engine = "r", label = "chunk1", code = "range modified"),
      rmd_chunk(engine = "r", label = "chunk2", code = "range modified"),
      rmd_chunk(engine = "r", label = "chunk3", code = "range modified")
    )
  )
  
  expect_equal(modified, expected_ast)
})

test_that("rmd_modify preserves original object structure", {
  # Create simple test AST
  original_ast = rmd_ast(
    nodes = list(
      rmd_heading(name = "Test", level = 1L),
      rmd_chunk(engine = "r", label = "test", code = "1 + 1"),
      rmd_markdown(lines = "Some text")
    )
  )
  
  # Make small modification to chunk code
  modified = rmd_modify(original_ast, .f = function(x) {
    if (inherits(x, "rmd_chunk")) {
      x@code = "modified"
    }
    x
  }, has_type("rmd_chunk"))
  
  # Structure should be preserved
  expect_equal(length(modified), length(original_ast))
  expect_equal(rmd_node_type(modified), rmd_node_type(original_ast))
  expect_equal(rmd_node_label(modified), rmd_node_label(original_ast))
})

test_that("rmd_modify error handling", {
  # Test unsupported type
  expect_snapshot_error(
    rmd_modify("not_rmd_object", .f = identity)
  )
})

test_that("rmd_modify validates function results", {
  original_ast = rmd_ast(
    nodes = list(
      rmd_heading(name = "Test", level = 1L)
    )
  )
  
  # Test function that returns invalid object
  expect_snapshot_error(
    rmd_modify(original_ast, .f = function(x) "not_an_rmd_node")
  )
  
  # Test function that returns NULL
  expect_snapshot_error(
    rmd_modify(original_ast, .f = function(x) NULL)
  )
  
  # Test function that returns list without proper class
  expect_snapshot_error(
    rmd_modify(original_ast, .f = function(x) list(content = "test"))
  )
  
  # Test function that returns object with wrong class
  expect_snapshot_error(
    rmd_modify(original_ast, .f = function(x) structure(list(), class = "wrong_class"))
  )
})

test_that("rmd_modify validates chunk structure", {
  original_ast = rmd_ast(
    nodes = list(
      rmd_chunk(engine = "r", label = "test", code = "1 + 1")
    )
  )
  
  # Test function that returns invalid chunk
  expect_snapshot_error(
    rmd_modify(original_ast, .f = function(x) {
      if (inherits(x, "rmd_chunk")) {
        # Return chunk with invalid engine type
        x@engine = 123
      }
      x
    }, has_type("rmd_chunk"))
  )
})

test_that("rmd_modify validates heading structure", {
  original_ast = rmd_ast(
    nodes = list(
      rmd_heading(name = "Test", level = 1L)
    )
  )
  
  # Test function that returns invalid heading
  expect_snapshot_error(
    rmd_modify(original_ast, .f = function(x) {
      if (inherits(x, "rmd_heading")) {
        # Return heading with invalid level
        x@level = 10L  # should be 1-6
      }
      x
    }, has_type("rmd_heading"))
  )
})

test_that("rmd_modify with yaml modifications", {
  original_ast = rmd_ast(
    nodes = list(
      rmd_yaml(yaml = list(title = "Original", output = "html_document")),
      rmd_heading(name = "Test", level = 1L)
    )
  )
  
  # Test modification of yaml properties
  modified = rmd_modify(original_ast, .f = function(x) {
    if (inherits(x, "rmd_yaml")) {
      x@yaml$title = "Modified Title"
    }
    x
  }, has_type("rmd_yaml"))
  
  expected_ast = rmd_ast(
    nodes = list(
      rmd_yaml(yaml = list(title = "Modified Title", output = "html_document")),
      rmd_heading(name = "Test", level = 1L)
    )
  )
  
  expect_equal(modified, expected_ast)
})

test_that("rmd_modify with markdown modifications", {
  original_ast = rmd_ast(
    nodes = list(
      rmd_markdown(lines = "Original text"),
      rmd_markdown(lines = "Another paragraph")
    )
  )
  
  # Test modification of markdown content
  modified = rmd_modify(original_ast, .f = function(x) {
    if (inherits(x, "rmd_markdown")) {
      x@lines = paste("Modified:", x@lines)
    }
    x
  }, has_type("rmd_markdown"))
  
  expected_ast = rmd_ast(
    nodes = list(
      rmd_markdown(lines = "Modified: Original text"),
      rmd_markdown(lines = "Modified: Another paragraph")
    )
  )
  
  expect_equal(modified, expected_ast)
})

Try the parsermd package in your browser

Any scripts or data that you put into this service are public.

parsermd documentation built on Aug. 21, 2025, 5:27 p.m.