tests/testthat/test-resource_route.R

test_that('resource_route validates inputs', {
  # Check arguments
  expect_snapshot(
    resource_route(continue = "not_logical"),
    error = TRUE
  )

  expect_snapshot(
    resource_route(finalize = "not_function"),
    error = TRUE
  )

  expect_snapshot(
    resource_route(finalize = function(request, response) {}),
    error = TRUE
  )

  expect_snapshot(
    resource_route(default_file = 1),
    error = TRUE
  )

  expect_snapshot(
    resource_route(default_ext = 1),
    error = TRUE
  )

  # Check that named mappings are required
  expect_snapshot(
    resource_route("path/to/dir"),
    error = TRUE
  )
})

test_that('resource_route creates a route with expected properties', {
  # Create route
  route <- resource_route(
    '/files/' = "fixtures/test_files/",
    default_file = 'index.html',
    default_ext = 'html'
  )

  # Check the type
  expect_s3_class(route, "Route")

  # Check that it has a handler for the mapped path
  expect_true(!is.null(route$get_handler("all", "/files/*")))
})

test_that('resource_route supports complete_paths function', {
  # Create route with various path formats
  route <- resource_route(
    '/complete/' = "fixtures/test_files/",  # with leading and trailing slash
    'incomplete' = "fixtures/test_files"    # without leading and trailing slash
  )

  # Check handlers exist for both paths
  expect_true(!is.null(route$get_handler("all", "/complete/*")))
  expect_true(!is.null(route$get_handler("all", "/incomplete/*")))
})

test_that('resource_route handles requests for existing files', {
  # Create route
  route <- resource_route(
    '/files/' = "fixtures/test_files/"
  )

  # Test request to an existing file
  rook <- fiery::fake_request('www.example.com/files/test.txt')
  req <- reqres::Request$new(rook)
  res <- req$respond()

  # Dispatch the request
  result <- route$dispatch(req)

  # Check the result
  expect_false(result)
  expect_equal(res$status, 200L)
  expect_equal(basename(res$body), "test.txt")
  expect_equal(res$type, "text/plain")
})

test_that('resource_route adds default extension when needed', {
  # Create route
  route <- resource_route(
    '/files/' = "fixtures/test_files/",
    default_ext = 'html'
  )

  # Test request to a file without extension
  rook <- fiery::fake_request('www.example.com/files/sample')
  req <- reqres::Request$new(rook)
  res <- req$respond()

  # Dispatch the request
  result <- route$dispatch(req)

  # Check the result
  expect_false(result)
  expect_equal(res$status, 200L)
  expect_equal(basename(res$body), "sample.html")
  expect_equal(res$type, "text/html")
})

test_that('resource_route adds default file when needed', {
  # Create route
  route <- resource_route(
    '/files/' = "fixtures/test_files/",
    default_file = 'index.html'
  )

  # Test request to a directory
  rook <- fiery::fake_request('www.example.com/files/')
  req <- reqres::Request$new(rook)
  res <- req$respond()

  # Dispatch the request
  result <- route$dispatch(req)

  # Check the result
  expect_false(result)
  expect_equal(res$status, 200L)
  expect_equal(basename(res$body), "index.html")
  expect_equal(res$type, "text/html")
})

test_that('resource_route handles subdirectory default files', {
  # Create route
  route <- resource_route(
    '/files/' = "fixtures/test_files/"
  )

  # Test request to a subdirectory
  rook <- fiery::fake_request('www.example.com/files/subdir/')
  req <- reqres::Request$new(rook)
  res <- req$respond()

  # Dispatch the request
  result <- route$dispatch(req)

  # Check the result
  expect_false(result)
  expect_equal(res$status, 200L)
  expect_true(grepl("subdir/index.html$", res$body))
  expect_equal(res$type, "text/html")
})

test_that('resource_route returns TRUE for non-existent files', {
  # Create route
  route <- resource_route(
    '/files/' = "fixtures/test_files/"
  )

  # Test request to a non-existent file
  rook <- fiery::fake_request('www.example.com/files/nonexistent.txt')
  req <- reqres::Request$new(rook)
  res <- req$respond()

  # Dispatch the request
  result <- route$dispatch(req)

  # Check the result - should return TRUE to continue to next route
  expect_true(result)
})

test_that('resource_route handles HTTP methods correctly', {
  # Create route
  route <- resource_route(
    '/files/' = "fixtures/test_files/"
  )

  # Test with GET method
  rook_get <- fiery::fake_request('www.example.com/files/test.txt', 'get')
  req_get <- reqres::Request$new(rook_get)
  res_get <- req_get$respond()

  result_get <- route$dispatch(req_get)
  expect_false(result_get)
  expect_equal(res_get$status, 200L)

  # Test with HEAD method
  rook_head <- fiery::fake_request('www.example.com/files/test.txt', 'head')
  req_head <- reqres::Request$new(rook_head)
  res_head <- req_head$respond()

  result_head <- route$dispatch(req_head)
  expect_false(result_head)
  expect_equal(res_head$status, 200L)
  expect_equal(res_head$body, "")  # HEAD should not have body

  # Test with POST method - should not be handled
  rook_post <- fiery::fake_request('www.example.com/files/test.txt', 'post')
  req_post <- reqres::Request$new(rook_post)
  res_post <- req_post$respond()

  result_post <- route$dispatch(req_post)
  expect_true(result_post)  # Should return TRUE to continue to next route
})

test_that('resource_route handles finalize function correctly', {
  # Create finalize function to track calls
  finalize_called <- FALSE
  test_finalize <- function(request, response, ...) {
    finalize_called <<- TRUE
    response$set_header("X-Test", "finalized")
  }

  # Create route with finalize function
  route <- resource_route(
    '/files/' = "fixtures/test_files/",
    finalize = test_finalize
  )

  # Test request
  rook <- fiery::fake_request('www.example.com/files/test.txt')
  req <- reqres::Request$new(rook)
  res <- req$respond()

  # Dispatch the request
  result <- route$dispatch(req)

  # Check the result
  expect_false(result)
  expect_true(finalize_called)
  expect_equal(res$get_header("X-Test"), "finalized")
})

test_that('resource_route handles encodings correctly', {
  # Create route
  route <- resource_route(
    '/files/' = "fixtures/test_files/"
  )

  # Test request with Accept-Encoding header
  rook <- fiery::fake_request('www.example.com/files/sample.html')
  rook$HTTP_ACCEPT_ENCODING <- "gzip, deflate, br"
  req <- reqres::Request$new(rook)
  res <- req$respond()

  # Dispatch the request
  result <- route$dispatch(req)

  # Check the result
  expect_false(result)
  expect_equal(res$status, 200L)
  expect_equal(res$get_header("Content-Encoding"), "gzip")
})

test_that('resource_route handles If-Modified-Since correctly', {
  # Create route
  route <- resource_route(
    '/files/' = "fixtures/test_files/"
  )

  # Get file info to set future modification time
  file_path <- "fixtures/test_files/test.txt"
  file_info <- fs::file_info(file_path)
  future_time <- file_info$modification_time + 3600 #one hour into the future

  # Test request with If-Modified-Since header in the future
  rook <- fiery::fake_request('www.example.com/files/test.txt')
  rook$HTTP_IF_MODIFIED_SINCE <- reqres::to_http_date(future_time)
  req <- reqres::Request$new(rook)
  res <- req$respond()

  # Dispatch the request
  result <- route$dispatch(req)

  # Check the result
  expect_false(result)
  expect_equal(res$status, 304L)
})

test_that('resource_route handles ETag correctly', {
  # Create route
  route <- resource_route(
    '/files/' = "fixtures/test_files/"
  )

  # Get file info to calculate ETag
  file_path <- "fixtures/test_files/test.txt"
  file_info <- fs::file_info(file_path)
  etag <- rlang::hash(file_info$modification_time)

  # Test request with If-None-Match header matching ETag
  rook <- fiery::fake_request('www.example.com/files/test.txt')
  rook$HTTP_IF_NONE_MATCH <- etag
  req <- reqres::Request$new(rook)
  res <- req$respond()

  # Dispatch the request
  result <- route$dispatch(req)

  # Check the result
  expect_false(result)
  expect_equal(res$status, 304L)
})

test_that('resource_route sets correct headers', {
  # Create route
  route <- resource_route(
    '/files/' = "fixtures/test_files/"
  )

  # Test request
  rook <- fiery::fake_request('www.example.com/files/test.txt')
  req <- reqres::Request$new(rook)
  res <- req$respond()

  # Dispatch the request
  result <- route$dispatch(req)

  # Check headers
  expect_false(result)
  expect_equal(res$type, "text/plain")
  expect_equal(res$get_header("Content-Encoding"), "identity")
  expect_false(is.null(res$get_header("ETag")))
  expect_equal(res$get_header("Cache-Control"), "max-age=3600")
  expect_false(is.null(res$get_header("Last-Modified")))
  expect_equal(res$get_header("Content-Location"), "/files/test.txt")
})

test_that('resource_route respects continue parameter', {
  # Create route with continue=TRUE
  route_continue <- resource_route(
    '/files/' = "fixtures/test_files/",
    continue = TRUE
  )

  # Test request
  rook <- fiery::fake_request('www.example.com/files/test.txt')
  req <- reqres::Request$new(rook)
  res <- req$respond()

  # Dispatch the request
  result <- route_continue$dispatch(req)

  # Check the result
  expect_true(result)  # Should return TRUE to continue
  expect_equal(res$status, 200L)
})

Try the routr package in your browser

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

routr documentation built on Aug. 21, 2025, 5:47 p.m.