tests: add tests for YT internal channels, remove RSS default feature
This commit is contained in:
parent
de118c59c4
commit
62853d50bf
6 changed files with 90 additions and 60 deletions
|
|
@ -13,7 +13,7 @@ include = ["/src", "README.md", "LICENSE", "!snapshots"]
|
||||||
members = [".", "codegen", "cli"]
|
members = [".", "codegen", "cli"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["default-tls", "rss"]
|
default = ["default-tls"]
|
||||||
all = ["rss", "html"]
|
all = ["rss", "html"]
|
||||||
|
|
||||||
rss = ["quick-xml"]
|
rss = ["quick-xml"]
|
||||||
|
|
|
||||||
|
|
@ -383,11 +383,13 @@ fn map_channel<T>(
|
||||||
id: &str,
|
id: &str,
|
||||||
lang: Language,
|
lang: Language,
|
||||||
) -> Result<Channel<T>, ExtractionError> {
|
) -> Result<Channel<T>, ExtractionError> {
|
||||||
let header = header.ok_or(ExtractionError::NoData)?;
|
let header =
|
||||||
|
header.ok_or_else(|| ExtractionError::ContentUnavailable("channel not found".into()))?;
|
||||||
let metadata = metadata
|
let metadata = metadata
|
||||||
.ok_or(ExtractionError::NoData)?
|
.ok_or_else(|| ExtractionError::ContentUnavailable("channel not found".into()))?
|
||||||
.channel_metadata_renderer;
|
.channel_metadata_renderer;
|
||||||
let microformat = microformat.ok_or(ExtractionError::NoData)?;
|
let microformat = microformat
|
||||||
|
.ok_or_else(|| ExtractionError::ContentUnavailable("channel not found".into()))?;
|
||||||
|
|
||||||
if metadata.external_id != id {
|
if metadata.external_id != id {
|
||||||
return Err(ExtractionError::WrongResult(format!(
|
return Err(ExtractionError::WrongResult(format!(
|
||||||
|
|
@ -463,7 +465,9 @@ fn map_channel_content(
|
||||||
Some(contents) => {
|
Some(contents) => {
|
||||||
let tabs = contents.two_column_browse_results_renderer.tabs;
|
let tabs = contents.two_column_browse_results_renderer.tabs;
|
||||||
if tabs.is_empty() {
|
if tabs.is_empty() {
|
||||||
return Err(ExtractionError::NoData);
|
return Err(ExtractionError::ContentUnavailable(
|
||||||
|
"channel not found".into(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let (channel_content, target_id) = tabs
|
let (channel_content, target_id) = tabs
|
||||||
|
|
|
||||||
|
|
@ -1095,7 +1095,6 @@ impl RustyPipeQuery {
|
||||||
ExtractionError::VideoUnavailable(_, _)
|
ExtractionError::VideoUnavailable(_, _)
|
||||||
| ExtractionError::VideoAgeRestricted
|
| ExtractionError::VideoAgeRestricted
|
||||||
| ExtractionError::ContentUnavailable(_)
|
| ExtractionError::ContentUnavailable(_)
|
||||||
| ExtractionError::NoData
|
|
||||||
| ExtractionError::Retry => (),
|
| ExtractionError::Retry => (),
|
||||||
_ => create_report(Level::ERR, Some(e.to_string()), Vec::new()),
|
_ => create_report(Level::ERR, Some(e.to_string()), Vec::new()),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -506,9 +506,10 @@ pub fn alerts_to_err(alerts: Option<Vec<Alert>>) -> ExtractionError {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|a| a.alert_renderer.text)
|
.map(|a| a.alert_renderer.text)
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(" "),
|
.join(" ")
|
||||||
|
.into(),
|
||||||
),
|
),
|
||||||
None => ExtractionError::InvalidData("no contents".into()),
|
None => ExtractionError::ContentUnavailable("content not found".into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -75,10 +75,8 @@ pub enum ExtractionError {
|
||||||
VideoUnavailable(&'static str, String),
|
VideoUnavailable(&'static str, String),
|
||||||
#[error("Video is age restricted")]
|
#[error("Video is age restricted")]
|
||||||
VideoAgeRestricted,
|
VideoAgeRestricted,
|
||||||
#[error("Content is not available. Reason (from YT): {0}")]
|
#[error("Content is not available. Reason: {0}")]
|
||||||
ContentUnavailable(String),
|
ContentUnavailable(Cow<'static, str>),
|
||||||
#[error("Got no data from YouTube")]
|
|
||||||
NoData,
|
|
||||||
#[error("deserialization error: {0}")]
|
#[error("deserialization error: {0}")]
|
||||||
Deserialization(#[from] serde_json::Error),
|
Deserialization(#[from] serde_json::Error),
|
||||||
#[error("got invalid data from YT: {0}")]
|
#[error("got invalid data from YT: {0}")]
|
||||||
|
|
|
||||||
124
tests/youtube.rs
124
tests/youtube.rs
|
|
@ -1,4 +1,4 @@
|
||||||
use chrono::{Datelike, Timelike};
|
use chrono::Datelike;
|
||||||
use rstest::rstest;
|
use rstest::rstest;
|
||||||
|
|
||||||
use rustypipe::client::{ClientType, RustyPipe};
|
use rustypipe::client::{ClientType, RustyPipe};
|
||||||
|
|
@ -218,10 +218,14 @@ async fn playlist_not_found() {
|
||||||
.await
|
.await
|
||||||
.unwrap_err();
|
.unwrap_err();
|
||||||
|
|
||||||
assert!(matches!(
|
assert!(
|
||||||
err,
|
matches!(
|
||||||
Error::Extraction(ExtractionError::ContentUnavailable(_))
|
err,
|
||||||
));
|
Error::Extraction(ExtractionError::ContentUnavailable(_))
|
||||||
|
),
|
||||||
|
"got: {}",
|
||||||
|
err
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
//#VIDEO DETAILS
|
//#VIDEO DETAILS
|
||||||
|
|
@ -324,6 +328,7 @@ async fn get_video_details_music() {
|
||||||
assert!(!details.is_live);
|
assert!(!details.is_live);
|
||||||
assert!(!details.is_ccommons);
|
assert!(!details.is_ccommons);
|
||||||
|
|
||||||
|
assert!(!details.recommended.items.is_empty());
|
||||||
assert!(!details.recommended.is_exhausted());
|
assert!(!details.recommended.is_exhausted());
|
||||||
|
|
||||||
// Comments are disabled for this video
|
// Comments are disabled for this video
|
||||||
|
|
@ -381,6 +386,7 @@ async fn get_video_details_ccommons() {
|
||||||
assert!(!details.is_live);
|
assert!(!details.is_live);
|
||||||
assert!(details.is_ccommons);
|
assert!(details.is_ccommons);
|
||||||
|
|
||||||
|
assert!(!details.recommended.items.is_empty());
|
||||||
assert!(!details.recommended.is_exhausted());
|
assert!(!details.recommended.is_exhausted());
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
|
|
@ -520,6 +526,7 @@ async fn get_video_details_chapters() {
|
||||||
"###);
|
"###);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert!(!details.recommended.items.is_empty());
|
||||||
assert!(!details.recommended.is_exhausted());
|
assert!(!details.recommended.is_exhausted());
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
|
|
@ -579,6 +586,7 @@ async fn get_video_details_live() {
|
||||||
assert!(details.is_live);
|
assert!(details.is_live);
|
||||||
assert!(!details.is_ccommons);
|
assert!(!details.is_ccommons);
|
||||||
|
|
||||||
|
assert!(!details.recommended.items.is_empty());
|
||||||
assert!(!details.recommended.is_exhausted());
|
assert!(!details.recommended.is_exhausted());
|
||||||
|
|
||||||
// No comments because livestream
|
// No comments because livestream
|
||||||
|
|
@ -637,10 +645,14 @@ async fn get_video_details_not_found() {
|
||||||
let rp = RustyPipe::builder().strict().build();
|
let rp = RustyPipe::builder().strict().build();
|
||||||
let err = rp.query().video_details("abcdefgLi5X").await.unwrap_err();
|
let err = rp.query().video_details("abcdefgLi5X").await.unwrap_err();
|
||||||
|
|
||||||
assert!(matches!(
|
assert!(
|
||||||
err,
|
matches!(
|
||||||
Error::Extraction(ExtractionError::ContentUnavailable(_))
|
err,
|
||||||
))
|
Error::Extraction(ExtractionError::ContentUnavailable(_))
|
||||||
|
),
|
||||||
|
"got: {}",
|
||||||
|
err
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
|
@ -837,13 +849,15 @@ fn assert_channel_eevblog<T>(channel: &Channel<T>) {
|
||||||
#[rstest]
|
#[rstest]
|
||||||
#[case::artist("UC_vmjW5e1xEHhYjY2a0kK1A", "Oonagh - Topic", false, false)]
|
#[case::artist("UC_vmjW5e1xEHhYjY2a0kK1A", "Oonagh - Topic", false, false)]
|
||||||
#[case::shorts("UCh8gHdtzO2tXd593_bjErWg", "Doobydobap", true, true)]
|
#[case::shorts("UCh8gHdtzO2tXd593_bjErWg", "Doobydobap", true, true)]
|
||||||
#[case::live(
|
#[case::livestream(
|
||||||
"UChs0pSaEoNLV4mevBFGaoKA",
|
"UChs0pSaEoNLV4mevBFGaoKA",
|
||||||
"The Good Life Radio x Sensual Musique",
|
"The Good Life Radio x Sensual Musique",
|
||||||
true,
|
true,
|
||||||
true
|
true
|
||||||
)]
|
)]
|
||||||
#[case::music("UC-9-kyTW8ZkZNDHQJ6FgpwQ", "Music", false, false)]
|
#[case::music("UC-9-kyTW8ZkZNDHQJ6FgpwQ", "Music", false, false)]
|
||||||
|
#[case::live("UC4R8DWoMoI7CAwX8_LjQHig", "Live", false, false)]
|
||||||
|
#[case::news("UCYfdidRxbB8Qhf0Nx7ioOYw", "News", false, false)]
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn channel_more(
|
async fn channel_more(
|
||||||
#[case] id: &str,
|
#[case] id: &str,
|
||||||
|
|
@ -882,58 +896,72 @@ async fn channel_more(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
#[case::gaming("UCOpNcN46UbXVtpKMrmU4Abg", false)]
|
#[case::not_exist("UCOpNcN46UbXVtpKMrmU4Abx")]
|
||||||
#[case::not_found("UCOpNcN46UbXVtpKMrmU4Abx", true)]
|
#[case::gaming("UCOpNcN46UbXVtpKMrmU4Abg")]
|
||||||
|
#[case::movies("UCuJcl0Ju-gPDoksRjK1ya-w")]
|
||||||
|
#[case::sports("UCEgdi0XIXXZ-qJOFPf4JSKw")]
|
||||||
|
#[case::learning("UCtFRv9O2AHqOZjjynzrv-xg")]
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn channel_error(#[case] id: &str, #[case] not_found: bool) {
|
async fn channel_not_found(#[case] id: &str) {
|
||||||
let rp = RustyPipe::builder().strict().build();
|
let rp = RustyPipe::builder().strict().build();
|
||||||
let err = rp.query().channel_videos(&id).await.unwrap_err();
|
let err = rp.query().channel_videos(&id).await.unwrap_err();
|
||||||
|
|
||||||
if not_found {
|
assert!(
|
||||||
assert!(matches!(
|
matches!(
|
||||||
err,
|
err,
|
||||||
Error::Extraction(ExtractionError::ContentUnavailable(_))
|
Error::Extraction(ExtractionError::ContentUnavailable(_))
|
||||||
));
|
),
|
||||||
} else {
|
"got: {}",
|
||||||
assert!(matches!(err, Error::Extraction(ExtractionError::NoData)));
|
err
|
||||||
}
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
//#CHANNEL_RSS
|
//#CHANNEL_RSS
|
||||||
|
|
||||||
#[tokio::test]
|
#[cfg(feature = "rss")]
|
||||||
async fn get_channel_rss() {
|
mod channel_rss {
|
||||||
let rp = RustyPipe::builder().strict().build();
|
use super::*;
|
||||||
let channel = rp
|
|
||||||
.query()
|
|
||||||
.channel_rss("UCHnyfMqiRRG1u-2MsSQLbXA")
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
assert_eq!(channel.id, "UCHnyfMqiRRG1u-2MsSQLbXA");
|
use chrono::Timelike;
|
||||||
assert_eq!(channel.name, "Veritasium");
|
|
||||||
assert_eq!(channel.create_date.year(), 2010);
|
|
||||||
assert_eq!(channel.create_date.month(), 7);
|
|
||||||
assert_eq!(channel.create_date.day(), 21);
|
|
||||||
assert_eq!(channel.create_date.hour(), 7);
|
|
||||||
assert_eq!(channel.create_date.minute(), 18);
|
|
||||||
|
|
||||||
assert!(!channel.videos.is_empty());
|
#[tokio::test]
|
||||||
}
|
async fn get_channel_rss() {
|
||||||
|
let rp = RustyPipe::builder().strict().build();
|
||||||
|
let channel = rp
|
||||||
|
.query()
|
||||||
|
.channel_rss("UCHnyfMqiRRG1u-2MsSQLbXA")
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
#[tokio::test]
|
assert_eq!(channel.id, "UCHnyfMqiRRG1u-2MsSQLbXA");
|
||||||
async fn get_channel_rss_not_found() {
|
assert_eq!(channel.name, "Veritasium");
|
||||||
let rp = RustyPipe::builder().strict().build();
|
assert_eq!(channel.create_date.year(), 2010);
|
||||||
let err = rp
|
assert_eq!(channel.create_date.month(), 7);
|
||||||
.query()
|
assert_eq!(channel.create_date.day(), 21);
|
||||||
.channel_rss("UCHnyfMqiRRG1u-2MsSQLbXZ")
|
assert_eq!(channel.create_date.hour(), 7);
|
||||||
.await
|
assert_eq!(channel.create_date.minute(), 18);
|
||||||
.unwrap_err();
|
|
||||||
|
|
||||||
assert!(matches!(
|
assert!(!channel.videos.is_empty());
|
||||||
err,
|
}
|
||||||
Error::Extraction(ExtractionError::ContentUnavailable(_))
|
|
||||||
));
|
#[tokio::test]
|
||||||
|
async fn get_channel_rss_not_found() {
|
||||||
|
let rp = RustyPipe::builder().strict().build();
|
||||||
|
let err = rp
|
||||||
|
.query()
|
||||||
|
.channel_rss("UCHnyfMqiRRG1u-2MsSQLbXZ")
|
||||||
|
.await
|
||||||
|
.unwrap_err();
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
matches!(
|
||||||
|
err,
|
||||||
|
Error::Extraction(ExtractionError::ContentUnavailable(_))
|
||||||
|
),
|
||||||
|
"got: {}",
|
||||||
|
err
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//#SEARCH
|
//#SEARCH
|
||||||
|
|
|
||||||
Reference in a new issue