Nothing
# ==============================================================================
# Tests for YouTube Channel Functions
# ==============================================================================
# This file tests all channel-related functions including:
# - get_all_channel_video_stats() - Get statistics for all videos in a channel
# - list_channel_resources() - Get channel information and playlists
# - get_playlist_items() - Used internally by channel stats functions
#
# Tests use accurate YouTube API v3 mocks that reflect current API behavior:
# - dislikeCount is private since December 2021
# - Proper response structure with kind, etag, pageInfo fields
# ==============================================================================
test_that("get_all_channel_video_stats handles video details correctly", {
# Mock the required functions
with_mocked_bindings(
# Mock list_channel_resources
list_channel_resources = function(...) {
list(
kind = "youtube#channelListResponse",
etag = "test-etag",
pageInfo = list(
totalResults = 1,
resultsPerPage = 1
),
items = list(
list(
kind = "youtube#channel",
etag = "channel-etag",
id = "UCad-_hTvV-yBPcpy9jwQWeA",
contentDetails = list(
relatedPlaylists = list(
uploads = "UUad-_hTvV-yBPcpy9jwQWeA",
likes = "",
watchHistory = "HL",
watchLater = "WL"
)
)
)
)
)
},
# Mock get_playlist_items to return 2 video IDs
get_playlist_items = function(...) {
list(
kind = "youtube#playlistItemListResponse",
etag = "test-etag",
pageInfo = list(
totalResults = 2,
resultsPerPage = 2
),
items = list(
list(
kind = "youtube#playlistItem",
etag = "item1-etag",
contentDetails = list(
videoId = "video1",
videoPublishedAt = "2024-01-01T00:00:00Z"
)
),
list(
kind = "youtube#playlistItem",
etag = "item2-etag",
contentDetails = list(
videoId = "video2",
videoPublishedAt = "2024-01-02T00:00:00Z"
)
)
),
nextPageToken = NULL
)
},
# Mock tuber_GET for video stats and details
tuber_GET = function(path, query, ...) {
# Handle combined snippet,statistics call (what get_video_details does)
if (grepl("statistics", query$part) && grepl("snippet", query$part)) {
# Return both stats and snippet for videos
list(
kind = "youtube#videoListResponse",
etag = "test-etag",
pageInfo = list(
totalResults = 2,
resultsPerPage = 2
),
items = list(
list(
kind = "youtube#video",
etag = "video1-etag",
id = "video1",
snippet = list(
publishedAt = "2024-01-01T00:00:00Z",
channelId = "UCad-_hTvV-yBPcpy9jwQWeA",
title = "Test Video 1",
description = "Test description 1",
channelTitle = "Test Channel"
),
statistics = list(
viewCount = "1000",
likeCount = "100",
# dislikeCount removed - private since Dec 2021
commentCount = "50"
)
),
list(
kind = "youtube#video",
etag = "video2-etag",
id = "video2",
snippet = list(
publishedAt = "2024-01-02T00:00:00Z",
channelId = "UCad-_hTvV-yBPcpy9jwQWeA",
title = "Test Video 2",
description = "Test description 2",
channelTitle = "Test Channel"
),
statistics = list(
viewCount = "2000",
likeCount = "200",
# dislikeCount removed - private since Dec 2021
commentCount = "100"
)
)
)
)
} else if (grepl("statistics", query$part)) {
# Return stats for videos (fallback for individual calls)
list(
kind = "youtube#videoListResponse",
etag = "test-etag",
pageInfo = list(
totalResults = 2,
resultsPerPage = 2
),
items = list(
list(
kind = "youtube#video",
etag = "video1-etag",
id = "video1",
statistics = list(
viewCount = "1000",
likeCount = "100",
# dislikeCount removed - private since Dec 2021
commentCount = "50"
)
),
list(
kind = "youtube#video",
etag = "video2-etag",
id = "video2",
statistics = list(
viewCount = "2000",
likeCount = "200",
# dislikeCount removed - private since Dec 2021
commentCount = "100"
)
)
)
)
} else if (grepl("snippet", query$part)) {
# Return details for videos (fallback for individual calls)
list(
kind = "youtube#videoListResponse",
etag = "test-etag",
pageInfo = list(
totalResults = 2,
resultsPerPage = 2
),
items = list(
list(
kind = "youtube#video",
etag = "video1-etag",
id = "video1",
snippet = list(
publishedAt = "2024-01-01T00:00:00Z",
channelId = "UCad-_hTvV-yBPcpy9jwQWeA",
title = "Test Video 1",
description = "Test description 1",
channelTitle = "Test Channel"
)
),
list(
kind = "youtube#video",
etag = "video2-etag",
id = "video2",
snippet = list(
publishedAt = "2024-01-02T00:00:00Z",
channelId = "UCad-_hTvV-yBPcpy9jwQWeA",
title = "Test Video 2",
description = "Test description 2",
channelTitle = "Test Channel"
)
)
)
)
}
},
{
# Test the function
result <- get_all_channel_video_stats(channel_id = "UCad-_hTvV-yBPcpy9jwQWeA")
# Verify the result structure
expect_true(is.data.frame(result))
expect_equal(nrow(result), 2)
# Check column names (note: dislike_count may be present but NA)
expected_cols <- c("id", "title", "publication_date", "description",
"channel_id", "channel_title", "view_count",
"like_count", "comment_count", "url")
expect_true(all(expected_cols %in% names(result)))
# dislike_count column may exist but should be NA (private since Dec 2021)
if ("dislike_count" %in% names(result)) {
expect_true(all(is.na(result$dislike_count)))
}
# Verify data integrity
expect_equal(result$id[1], "video1")
expect_equal(result$id[2], "video2")
expect_equal(result$title[1], "Test Video 1")
expect_equal(result$title[2], "Test Video 2")
expect_equal(result$publication_date[1], "2024-01-01T00:00:00Z")
expect_equal(result$publication_date[2], "2024-01-02T00:00:00Z")
expect_equal(result$view_count[1], "1000")
expect_equal(result$view_count[2], "2000")
# Check URL generation
expect_equal(result$url[1], "https://www.youtube.com/watch?v=video1")
expect_equal(result$url[2], "https://www.youtube.com/watch?v=video2")
}
)
})
test_that("get_all_channel_video_stats handles missing publishedAt field", {
# Mock setup with video missing publishedAt
with_mocked_bindings(
list_channel_resources = function(...) {
list(
kind = "youtube#channelListResponse",
etag = "test-etag",
pageInfo = list(
totalResults = 1,
resultsPerPage = 1
),
items = list(
list(
kind = "youtube#channel",
etag = "channel-etag",
id = "UCtest",
contentDetails = list(
relatedPlaylists = list(
uploads = "UUtest",
likes = "",
watchHistory = "HL",
watchLater = "WL"
)
)
)
)
)
},
get_playlist_items = function(...) {
list(
kind = "youtube#playlistItemListResponse",
etag = "test-etag",
pageInfo = list(
totalResults = 1,
resultsPerPage = 1
),
items = list(
list(
kind = "youtube#playlistItem",
etag = "item1-etag",
contentDetails = list(
videoId = "video1",
videoPublishedAt = "2024-01-01T00:00:00Z"
)
)
),
nextPageToken = NULL
)
},
tuber_GET = function(path, query, ...) {
# Handle combined snippet,statistics call (what get_video_details does)
if (grepl("statistics", query$part) && grepl("snippet", query$part)) {
list(
kind = "youtube#videoListResponse",
etag = "test-etag",
pageInfo = list(
totalResults = 1,
resultsPerPage = 1
),
items = list(
list(
kind = "youtube#video",
etag = "video1-etag",
id = "video1",
snippet = list(
# publishedAt is intentionally missing for this test
channelId = "UCtest",
title = "Test Video",
description = "Test",
channelTitle = "Test"
),
statistics = list(
viewCount = "1000",
likeCount = "100",
# dislikeCount removed - private since Dec 2021
commentCount = "25"
)
)
)
)
} else if (grepl("statistics", query$part)) {
list(
kind = "youtube#videoListResponse",
etag = "test-etag",
pageInfo = list(
totalResults = 1,
resultsPerPage = 1
),
items = list(
list(
kind = "youtube#video",
etag = "video1-etag",
id = "video1",
statistics = list(
viewCount = "1000",
likeCount = "100",
# dislikeCount removed - private since Dec 2021
commentCount = "25"
)
)
)
)
} else if (grepl("snippet", query$part)) {
list(
kind = "youtube#videoListResponse",
etag = "test-etag",
pageInfo = list(
totalResults = 1,
resultsPerPage = 1
),
items = list(
list(
kind = "youtube#video",
etag = "video1-etag",
id = "video1",
snippet = list(
# publishedAt is intentionally missing for this test
channelId = "UCtest",
title = "Test Video",
description = "Test",
channelTitle = "Test"
)
)
)
)
}
},
{
result <- get_all_channel_video_stats(channel_id = "UCtest")
# Should handle missing publishedAt gracefully with NA
expect_true(is.data.frame(result))
expect_equal(nrow(result), 1)
expect_true(is.na(result$publication_date[1]))
}
)
})
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.