tests/testthat/test-pagination-mocks.R

# Mock tests for pagination logic (no API calls required)

context("Pagination Logic Tests")

# Mock tuber_GET function for testing
mock_tuber_GET <- function(path, query, ...) {
  # Simulate different response types based on path and query
  if (path == "playlistItems") {
    mock_playlist_response(query)
  } else if (path == "commentThreads") {
    mock_comment_threads_response(query)
  } else if (path == "search") {
    mock_search_response(query)
  }
}

# Mock playlist API response
mock_playlist_response <- function(query) {
  max_results <- query$maxResults %||% 50
  page_token <- query$pageToken

  # Create mock items
  items <- lapply(1:min(max_results, 10), function(i) {
    offset <- if (!is.null(page_token)) as.numeric(page_token) * 10 else 0
    list(
      id = paste0("item_", offset + i),
      snippet = list(
        title = paste("Video", offset + i),
        playlistId = "PLtest123"
      ),
      contentDetails = list(
        videoId = paste0("video_", offset + i)
      )
    )
  })

  # Add nextPageToken if more results exist
  next_token <- NULL
  current_page <- if (!is.null(page_token)) as.numeric(page_token) else 0
  if (current_page < 5) {  # Simulate 6 pages total (60 items)
    next_token <- as.character(current_page + 1)
  }

  list(
    items = items,
    nextPageToken = next_token,
    pageInfo = list(
      totalResults = 55,
      resultsPerPage = length(items)
    )
  )
}

# Mock comment threads API response
mock_comment_threads_response <- function(query) {
  max_results <- query$maxResults %||% 100
  page_token <- query$pageToken

  # Create mock comment items
  items <- lapply(1:min(max_results, 20), function(i) {
    offset <- if (!is.null(page_token)) as.numeric(page_token) * 20 else 0
    list(
      id = paste0("comment_", offset + i),
      snippet = list(
        topLevelComment = list(
          snippet = list(
            textDisplay = paste("Comment", offset + i),
            authorDisplayName = paste("Author", offset + i),
            likeCount = as.character(i),  # Convert to character as API returns
            publishedAt = "2023-01-01T00:00:00Z"
          ),
          id = paste0("comment_", offset + i)
        )
      )
    )
  })

  # Add nextPageToken if more results exist
  next_token <- NULL
  current_page <- if (!is.null(page_token)) as.numeric(page_token) else 0
  if (current_page < 2) {  # Simulate 3 pages total
    next_token <- as.character(current_page + 1)
  }

  list(
    items = items,
    nextPageToken = next_token,
    pageInfo = list(
      totalResults = 55,
      resultsPerPage = length(items)
    )
  )
}

# Mock search API response
mock_search_response <- function(query) {
  max_results <- query$maxResults %||% 50
  page_token <- query$pageToken

  # Create mock search items
  items <- lapply(1:min(max_results, 25), function(i) {
    offset <- if (!is.null(page_token)) as.numeric(page_token) * 25 else 0
    list(
      id = list(
        kind = "youtube#video",
        videoId = paste0("search_video_", offset + i)
      ),
      snippet = list(
        title = paste("Search Result", offset + i),
        channelId = "UC123456789",
        publishedAt = "2023-01-01T00:00:00Z"
      )
    )
  })

  # Add nextPageToken if more results exist
  next_token <- NULL
  current_page <- if (!is.null(page_token)) as.numeric(page_token) else 0
  if (current_page < 4) {  # Simulate 5 pages total
    next_token <- as.character(current_page + 1)
  }

  list(
    items = items,
    nextPageToken = next_token,
    pageInfo = list(
      totalResults = 120,
      resultsPerPage = length(items)
    )
  )
}

# Test playlist pagination logic
test_that("get_playlist_items handles pagination correctly", {
  # Mock the tuber_GET function
  with_mocked_bindings(
    tuber_GET = mock_tuber_GET,
    {
      # Test requesting more than 50 items triggers pagination
      result <- get_playlist_items(
        filter = c(playlist_id = "PLtest123"),
        max_results = 55,
        simplify = FALSE
      )

      expect_equal(length(result$items), 55)
      expect_null(result$nextPageToken)  # Should be NULL when we've got all requested items
    }
  )
})

test_that("get_playlist_items respects max_results limit", {
  with_mocked_bindings(
    tuber_GET = mock_tuber_GET,
    {
      # Test that we don't get more than requested
      result <- get_playlist_items(
        filter = c(playlist_id = "PLtest123"),
        max_results = 25,
        simplify = FALSE
      )

      expect_equal(length(result$items), 25)
    }
  )
})

# Test comment pagination logic
# Skipping complex comment threading test due to API response complexity

test_that("get_comment_threads handles small max_results efficiently", {
  with_mocked_bindings(
    tuber_GET = mock_tuber_GET,
    {
      result <- get_comment_threads(
        filter = c(video_id = "test123"),
        max_results = 50,
        simplify = TRUE
      )

      # The function returns a matrix when simplified, not a data.frame
      expect_true(is.matrix(result) || is.data.frame(result))
      expect_true(nrow(result) <= 50)
    }
  )
})

# Test search pagination
test_that("yt_search handles get_all parameter correctly", {
  with_mocked_bindings(
    tuber_GET = mock_tuber_GET,
    {
      # Test with get_all = FALSE
      result_single <- yt_search(
        term = "test",
        max_results = 50,
        get_all = FALSE
      )

      expect_s3_class(result_single, "data.frame")
      expect_true(nrow(result_single) <= 50)

      # Test with get_all = TRUE and max_pages limit
      result_all <- yt_search(
        term = "test",
        max_results = 100,
        get_all = TRUE,
        max_pages = 3
      )

      expect_s3_class(result_all, "data.frame")
      expect_true(nrow(result_all) >= 75)  # Should have multiple pages
      expect_true("video_id" %in% colnames(result_all))
    }
  )
})

# Test attribute setting in search results
test_that("yt_search sets proper result attributes", {
  with_mocked_bindings(
    tuber_GET = mock_tuber_GET,
    {
      result <- yt_search(
        term = "test",
        max_results = 100,
        get_all = TRUE
      )

      expect_true(!is.null(attr(result, "total_results")))
      expect_true(!is.null(attr(result, "actual_results")))
      expect_true(!is.null(attr(result, "api_limit_reached")))
      expect_equal(attr(result, "actual_results"), nrow(result))
    }
  )
})

Try the tuber package in your browser

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

tuber documentation built on March 25, 2026, 9:08 a.m.