anki/rslib/tests/links.rs
Damien Elmes d73852f272 use separate integration test for links
If we run into issues with unreliable network connections in the future,
we'll be able to mark the test as flaky so Bazel can retry it multiple
times.
2021-07-24 10:12:25 +10:00

88 lines
2.6 KiB
Rust

// Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
use anki::links::HelpPage;
#[cfg(test)]
mod test {
use std::iter;
use futures::StreamExt;
use itertools::Itertools;
use linkcheck::{
validation::{check_web, Context, Reason},
BasicContext,
};
use reqwest::Url;
use strum::IntoEnumIterator;
use super::*;
/// Aggregates [`Outcome`]s by collecting the error messages of the invalid ones.
#[derive(Default)]
struct Outcomes(Vec<String>);
enum Outcome {
Valid,
Invalid(String),
}
#[tokio::test]
async fn check_links() {
let ctx = BasicContext::default();
let result = futures::stream::iter(HelpPage::iter())
.map(|page| check_page(page, &ctx))
.buffer_unordered(ctx.concurrency())
.collect::<Outcomes>()
.await;
if !result.0.is_empty() {
panic!("{}", result.message());
}
}
async fn check_page(page: HelpPage, ctx: &BasicContext) -> Outcome {
let link = page.to_link();
match Url::parse(&link) {
Ok(url) => {
if url.as_str() == link {
match check_web(&url, ctx).await {
Ok(()) => Outcome::Valid,
Err(Reason::Dom) => Outcome::Invalid(format!(
"'#{}' not found on '{}{}'",
url.fragment().unwrap(),
url.domain().unwrap(),
url.path(),
)),
Err(Reason::Web(err)) => Outcome::Invalid(err.to_string()),
_ => unreachable!(),
}
} else {
Outcome::Invalid(format!(
"'{}' is not a valid URL part",
page.to_link_suffix(),
))
}
}
Err(err) => Outcome::Invalid(err.to_string()),
}
}
impl Extend<Outcome> for Outcomes {
fn extend<T: IntoIterator<Item = Outcome>>(&mut self, items: T) {
for outcome in items {
match outcome {
Outcome::Valid => (),
Outcome::Invalid(err) => self.0.push(err),
}
}
}
}
impl Outcomes {
fn message(&self) -> String {
iter::once("invalid links found:")
.chain(self.0.iter().map(String::as_str))
.join("\n - ")
}
}
}