Description: avoid not-in-Debian crate mockito
Author: Jonas Smedegaard <dr@jones.dk>
Forwarded: not-needed
Last-Update: 2024-09-14
---
This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
--- a/library/Cargo.toml
+++ b/library/Cargo.toml
@@ -53,7 +53,6 @@
 reqwest_middleware = ["dep:reqwest-middleware", "reqwest"]
 
 [dev-dependencies]
-mockito = "1.5"
 env_logger = "0.11"
 assert-json-diff = "2.0"
 tokio = { version = "1.40", features = ["test-util", "full"] }
--- a/library/src/standards/webmention/mod.rs
+++ b/library/src/standards/webmention/mod.rs
@@ -64,7 +64,7 @@
 ///
 /// # Examples
 /// This is what it looks like sending a Webmention that processes it synchronously.
-/// ```
+/// ```ignore
 /// use indieweb::standards::webmention::{Request, Response, send, Status};
 /// use indieweb::http::{Client, reqwest::Client as HttpClient};
 /// use url::Url;
@@ -95,7 +95,7 @@
 /// ```
 ///
 /// This is how it'd look when it's processed asynchronously pointing to a status page.
-/// ```
+/// ```ignore
 /// use indieweb::standards::webmention::{Request, Response, send, Status};
 /// use indieweb::http::{Client, reqwest::Client as HttpClient};
 /// use url::Url;
@@ -438,5 +438,3 @@
             }
         })
 }
-
-mod test;
--- a/library/src/test.rs
+++ /dev/null
@@ -1,100 +0,0 @@
-#![cfg(test)]
-
-use std::str::FromStr;
-
-use async_trait::async_trait;
-use http::header::CONNECTION;
-use reqwest::{NoProxy, Proxy};
-
-static USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "-test/", env!("CARGO_PKG_VERSION"),);
-
-pub struct Client {
-    pub mock_server: mockito::ServerGuard,
-    pub http_client: reqwest::Client,
-}
-
-impl Default for Client {
-    fn default() -> Self {
-        let mut b = reqwest::Client::builder();
-
-        if let Ok(proxy) = std::env::var("http_proxy") {
-            b = b.proxy(Proxy::http(proxy).unwrap().no_proxy(NoProxy::from_env()));
-        }
-
-        let http_client = b.user_agent(USER_AGENT).build().unwrap();
-        Self {
-            mock_server: mockito::Server::new(),
-            http_client,
-        }
-    }
-}
-
-impl Client {
-    pub fn merge_into_url(&self, path: &str) -> url::Url {
-        self.mock_server
-            .url()
-            .parse::<url::Url>()
-            .expect("failed to make http URL")
-            .join(path)
-            .expect("failed to join URL")
-    }
-
-    pub(crate) async fn new() -> Self {
-        Self {
-            http_client: reqwest::Client::new(),
-            mock_server: mockito::Server::new_async().await,
-        }
-    }
-}
-
-#[async_trait]
-impl crate::http::Client for Client {
-    #[tracing::instrument(skip(self))]
-    async fn send_request(
-        &self,
-        request: http::Request<crate::http::Body>,
-    ) -> Result<http::Response<crate::http::Body>, crate::Error> {
-        let method = reqwest::Method::from_str(request.method().as_ref()).unwrap();
-        let mut req = reqwest::Request::new(
-            method,
-            request
-                .uri()
-                .to_string()
-                .parse()
-                .map_err(crate::Error::Url)?,
-        );
-        let it = request
-            .headers()
-            .iter()
-            .filter(|(h, _)| h != &CONNECTION)
-            .map(move |(header_name, header_value)| {
-                (
-                    reqwest::header::HeaderName::from_str(header_name.as_str()).unwrap(),
-                    reqwest::header::HeaderValue::from_bytes(header_value.as_bytes()).unwrap(),
-                )
-            });
-        req.headers_mut().extend(it);
-        *req.body_mut() = Some(reqwest::Body::from(request.body().as_bytes().to_vec()));
-
-        let resp = self
-            .http_client
-            .execute(req)
-            .await
-            .map_err(crate::Error::Reqwest)?;
-
-        let status = resp.status().as_u16();
-        let mut whole_resp = http::Response::builder().status(status);
-        for (name, value) in resp.headers() {
-            whole_resp = whole_resp.header(name.as_str(), value.as_bytes());
-        }
-        let body = resp
-            .bytes()
-            .await
-            .map_err(crate::Error::Reqwest)?
-            .into_iter()
-            .collect::<Vec<_>>()
-            .into();
-
-        whole_resp.body(body).map_err(crate::Error::Http)
-    }
-}
--- a/library/src/algorithms/representative_hcard/test.rs
+++ /dev/null
@@ -1,123 +0,0 @@
-use microformats::types::PropertyValue;
-
-use crate::algorithms::representative_hcard::for_url;
-
-#[tokio::test]
-async fn directly_on_page() {
-    let mut client = crate::test::Client::new().await;
-    let page_mock = client
-        .mock_server
-        .mock("GET", "/rep-hcard/on-page")
-        .expect(1)
-        .match_header(
-            "accept",
-            mockito::Matcher::Regex("(.*)text/html(.*)".into()),
-        )
-        .with_header("content-type", "text/html")
-        .with_body(
-            r#"<html>
-    <body class="h-card">
-        <a href="" class="u-uid u-url"></a>
-    </body>
-</html>"#,
-        )
-        .create_async()
-        .await;
-
-    let item_result = for_url(
-        &client,
-        &format!("{}/rep-hcard/on-page", client.mock_server.url())
-            .parse()
-            .unwrap(),
-    )
-    .await;
-    assert_eq!(
-        item_result.as_ref().err(),
-        None,
-        "no errors when parsing rep h-card"
-    );
-    page_mock.assert_async().await;
-}
-
-#[tokio::test]
-async fn rel_me_association_on_page() {
-    let mut client = crate::test::Client::new().await;
-    let page_mock = client
-        .mock_server
-        .mock("GET", "/rep-hcard/via-relme")
-        .expect(1)
-        .match_header(
-            "accept",
-            mockito::Matcher::Regex("(.*)text/html(.*)".into()),
-        )
-        .with_header("content-type", "text/html")
-        .with_body(
-            r#"<html>
-    <head>
-        <link rel="me" href="/foo-bar" />
-    </head>
-    <body class="h-card">
-        <a href="/foo-bar" class="u-url"></a>
-    </body>
-</html>"#,
-        )
-        .create_async()
-        .await;
-
-    let r = for_url(
-        &client,
-        &format!("{}/rep-hcard/via-relme", client.mock_server.url())
-            .parse()
-            .unwrap(),
-    )
-    .await;
-    assert_eq!(r.as_ref().err(), None, "no errors when parsing rep h-card");
-    page_mock.assert_async().await;
-}
-
-#[tracing_test::traced_test]
-#[tokio::test]
-async fn solo_card() {
-    let mut client = crate::test::Client::new().await;
-    let page_mock = client
-        .mock_server
-        .mock("GET", "/rep-hcard/only-one")
-        .expect(1)
-        .match_header(
-            "accept",
-            mockito::Matcher::Regex("(.*)text/html(.*)".into()),
-        )
-        .with_header("content-type", "text/html")
-        .with_body(
-            r#"<html>
-    <head>
-    </head>
-    <body class="h-card">
-        <a href="/solo-dolo" class="u-url"></a>
-    </body>
-</html>"#,
-        )
-        .create_async()
-        .await;
-
-    let r = for_url(
-        &client,
-        &format!("{}/rep-hcard/only-one", client.mock_server.url())
-            .parse()
-            .unwrap(),
-    )
-    .await;
-    assert_eq!(r.as_ref().err(), None, "no errors when parsing rep h-card");
-    page_mock.assert_async().await;
-    assert_eq!(
-        r.map(|i| i.get_property("url"))
-            .ok()
-            .flatten()
-            .and_then(|v| v.first().cloned()),
-        format!("{}/solo-dolo", client.mock_server.url())
-            .parse()
-            .ok()
-            .map(PropertyValue::Url),
-        "gave expected URL"
-    );
-}
--- a/library/src/lib.rs
+++ b/library/src/lib.rs
@@ -27,8 +27,6 @@
 /// Traits to extend everyday functionality with IndieWeb-adjacent tooling.
 pub mod traits;
 
-mod test;
-
 #[doc(inline)]
 pub use error::Error;
 
--- a/library/src/algorithms/representative_hcard/mod.rs
+++ b/library/src/algorithms/representative_hcard/mod.rs
@@ -106,6 +106,3 @@
         Err(crate::Error::NoRepresentativeHCardFound(url.clone()))
     }
 }
-
-#[cfg(test)]
-mod test;
--- a/library/src/standards/indieauth/test.rs
+++ b/library/src/standards/indieauth/test.rs
@@ -10,160 +10,6 @@
 
 use super::{ClientId, CodeChallenge};
 
-#[tokio::test]
-async fn obtain_metadata_none_found() -> miette::Result<()> {
-    let mut server = mockito::Server::new_async().await;
-    let html_remote_page_mock = server
-        .mock("GET", "/profile")
-        .expect_at_most(1)
-        .create_async()
-        .await;
-
-    let headers_remote_page_mock = server
-        .mock("HEAD", "/profile")
-        .expect_at_most(1)
-        .create_async()
-        .await;
-
-    let client = super::Client::new(
-        "http://example.com",
-        crate::http::reqwest::Client::default(),
-    )?;
-
-    let remote_url = format!("{}/profile", server.url()).parse().unwrap();
-    let resp = client.obtain_metadata(&remote_url).await;
-
-    assert_eq!(
-        resp,
-        Err(super::Error::NoMetadataEndpoint.into()),
-        "expected no metadata anywhere due to lack of an endpoint"
-    );
-
-    headers_remote_page_mock.assert_async().await;
-    html_remote_page_mock.assert_async().await;
-    Ok(())
-}
-
-#[tokio::test]
-async fn obtain_metadata_via_endpoint_html() -> miette::Result<()> {
-    let mut server = mockito::Server::new_async().await;
-    let server_url = server.url();
-    let metadata = ServerMetadata {
-        issuer: server.url().parse().unwrap(),
-        authorization_endpoint: format!("{server_url}/endpoints/auth").parse().unwrap(),
-        token_endpoint: format!("{server_url}/endpoints/token").parse().unwrap(),
-        introspection_endpoint: None,
-        code_challenge_methods_supported: ServerMetadata::recommended_code_challenge_methods(),
-        scopes_supported: Scopes::minimal(),
-    };
-
-    let html_remote_page_mock = server
-        .mock("GET", "/profile")
-        .expect_at_most(1)
-        .with_body(format!(
-            r#"
-<html>
-    <head>
-        <link rel="indieauth-metadata" href="{server_url}/metadata" />
-    </head>
-</html>
-            "#
-        ))
-        .create_async()
-        .await;
-
-    let headers_remote_page_mock = server
-        .mock("HEAD", "/profile")
-        .expect_at_most(1)
-        .create_async()
-        .await;
-
-    let metadata_endpoint_mock = server
-        .mock("GET", "/metadata")
-        .with_header(CONTENT_TYPE, CONTENT_TYPE_JSON)
-        .with_body(serde_json::json!(metadata).to_string())
-        .expect_at_most(1)
-        .create_async()
-        .await;
-
-    let client = super::Client::new(
-        "http://example.com",
-        crate::http::reqwest::Client::default(),
-    )?;
-
-    let remote_url = format!("{}/profile", server.url()).parse().unwrap();
-    let resp = client.obtain_metadata(&remote_url).await;
-
-    headers_remote_page_mock.assert_async().await;
-    metadata_endpoint_mock.assert_async().await;
-    html_remote_page_mock.assert_async().await;
-
-    assert_eq!(resp, Ok(metadata));
-
-    Ok(())
-}
-
-#[tokio::test]
-async fn obtain_metadata_via_endpoint_headers() -> miette::Result<()> {
-    let mut server = mockito::Server::new_async().await;
-    let server_url = server.url();
-    let var_name = ServerMetadata {
-        issuer: server.url().parse().unwrap(),
-        authorization_endpoint: format!("{server_url}/endpoints/auth").parse().unwrap(),
-        token_endpoint: format!("{server_url}/endpoints/token").parse().unwrap(),
-        introspection_endpoint: format!("{server_url}/endpoints/token").parse().ok(),
-        code_challenge_methods_supported: ServerMetadata::recommended_code_challenge_methods(),
-        scopes_supported: Scopes::minimal(),
-    };
-    let metadata = var_name;
-    let html_remote_page_mock = server
-        .mock("GET", "/profile")
-        .expect_at_most(0)
-        .create_async()
-        .await;
-
-    let headers_remote_page_mock = server
-        .mock("HEAD", "/profile")
-        .with_header(
-            LINK,
-            &format!(
-                r#"<{}/metadata>; rel="{}""#,
-                server.url(),
-                super::Client::<crate::http::reqwest::Client>::LINK_REL
-            ),
-        )
-        .expect_at_most(1)
-        .create_async()
-        .await;
-
-    let metadata_endpoint_mock = server
-        .mock("GET", "/metadata")
-        .with_header(CONTENT_TYPE, CONTENT_TYPE_JSON)
-        .with_body(serde_json::json!(metadata).to_string())
-        .expect_at_most(1)
-        .create_async()
-        .await;
-
-    let client = super::Client::new(
-        "http://example.com",
-        crate::http::reqwest::Client::default(),
-    )?;
-
-    let remote_url = format!("{}/profile", server.url()).parse().unwrap();
-    let resp = client.obtain_metadata(&remote_url).await;
-
-    headers_remote_page_mock.assert_async().await;
-    html_remote_page_mock.assert_async().await;
-    metadata_endpoint_mock.assert_async().await;
-    assert_eq!(
-        resp,
-        Ok(metadata),
-        "expected no metadata anywhere due to lack of an endpoint"
-    );
-
-    Ok(())
-}
-
 #[test]
 fn server_metadata_new_authorization_request_url() -> miette::Result<()> {
     let issuer: Url = "https://example.com".parse().unwrap();
--- a/library/src/standards/micropub/action/mod.rs
+++ b/library/src/standards/micropub/action/mod.rs
@@ -568,145 +568,6 @@
     );
 }
 
-#[test]
-fn action_representation_create() {
-    crate::test::Client::default();
-    let creation_properties = CreationProperties {
-        parameters: Parameters {
-            category: vec!["foo".into(), "bar".into()],
-            ..Default::default()
-        },
-        extra_fields: Properties::try_from(serde_json::json!({
-            "content": ["hello world"],
-            "photo": ["https://photos.example.com/592829482876343254.jpg"]
-        }))
-        .expect("failed to build extra fields of creation properties"),
-        r#type: microformats::types::Class::Known(microformats::types::KnownClass::Entry),
-    };
-
-    assert_eq!(
-        serde_json::from_value(serde_json::json!({
-          "type": ["h-entry"],
-          "properties": {
-            "content": ["hello world"],
-            "category": ["foo","bar"],
-            "photo": ["https://photos.example.com/592829482876343254.jpg"]
-          }
-        }))
-        .map_err(|e| e.to_string()),
-        Ok(Action::Create {
-            properties: creation_properties.clone(),
-            files: Default::default()
-        }),
-        "converts create payload from JSON"
-    );
-
-    assert_eq!(
-        serde_qs::from_str("h=entry&content=hello+world&category[]=foo&category[]=bar&photo=https://photos.example.com/592829482876343254.jpg")
-            .map_err(|e| e.to_string()),
-        Ok(Action::Create {
-            properties: creation_properties.clone(),
-            files: Default::default()
-        }),
-        "converts create payload from form encoded payload"
-    );
-}
-
-#[test]
-fn action_representation_delete() {
-    crate::test::Client::default();
-    assert_eq!(
-        serde_json::from_value(
-            serde_json::json!({"action": "delete", "url": "http://example.com"})
-        )
-        .map_err(|e| e.to_string()),
-        Ok(Action::Delete("http://example.com".parse().unwrap())),
-        "converts delete payload from JSON"
-    );
-    assert_eq!(
-        serde_json::from_value(
-            serde_json::json!({"action": "undelete", "url": "http://example.com"})
-        )
-        .map_err(|e| e.to_string()),
-        Ok(Action::Undelete("http://example.com".parse().unwrap())),
-        "converts undelete payload from JSON"
-    )
-}
-
-#[test]
-fn action_representation_update_replace() {
-    crate::test::Client::default();
-
-    assert_eq!(
-        serde_json::from_value(serde_json::json!({
-            "action": "update",
-            "url": "http://example.com",
-            "replace": {
-                "category": ["tag1", "tag2"]
-            }
-        }))
-        .map_err(|e| e.to_string()),
-        Ok(Action::Update {
-            url: "http://example.com".parse().unwrap(),
-            operation: (
-                UpdateOperation::Replace,
-                serde_json::from_value(serde_json::json!({
-                    "category": ["tag1", "tag2"]
-                }))
-                .unwrap()
-            )
-        }),
-        "converts upload payload for replace from JSON"
-    );
-}
-
-#[test]
-fn action_representation_update_delete() {
-    crate::test::Client::default();
-    assert_eq!(
-        serde_json::from_value(serde_json::json!({
-            "action": "update",
-            "url": "http://example.com",
-            "delete": {
-                "category": ["tag1", "tag2"]
-            }
-        }))
-        .map_err(|e| e.to_string()),
-        Ok(Action::Update {
-            url: "http://example.com".parse().unwrap(),
-            operation: (
-                UpdateOperation::Delete,
-                serde_json::from_value(serde_json::json!({
-                    "category": ["tag1", "tag2"]
-                }))
-                .unwrap()
-            )
-        }),
-        "converts upload payload from delete from JSON"
-    );
-}
-
-#[test]
-fn action_representation_update_replace_whole() {
-    crate::test::Client::default();
-    assert_eq!(
-        serde_json::from_value(serde_json::json!({
-            "action": "update",
-            "url": "http://example.com",
-            "add": ["category"]
-        }))
-        .map_err(|e| e.to_string()),
-        Ok(Action::Update {
-            url: "http://example.com".parse().unwrap(),
-            operation: (
-                UpdateOperation::Add,
-                serde_json::from_value(serde_json::json!(["category"])).unwrap()
-            )
-        }),
-        "converts upload payload from add from JSON"
-    );
-}
-
 /// Represents a collection of the known response sttes of a Micropub server.
 #[derive(Clone, Debug, PartialEq, Eq)]
 pub enum ActionResponse {
@@ -736,5 +597,3 @@
         changes: Option<serde_json::Value>,
     },
 }
-
-mod test;
--- a/library/src/standards/micropub/action/test.rs
+++ /dev/null
@@ -1,66 +0,0 @@
-#![cfg(test)]
-use microformats::types::{Class, KnownClass};
-
-use super::Action;
-use crate::standards::{
-    indieauth::AccessToken,
-    micropub::action::{ActionResponse, CreationProperties},
-};
-
-async fn mock_micropub_request(
-    client: impl crate::http::Client,
-    endpoint: &url::Url,
-    token: &AccessToken,
-    action: &Action,
-    response: &ActionResponse,
-    message: impl ToString,
-) {
-    assert_eq!(
-        action.send(&client, endpoint, token).await,
-        Ok(response.to_owned()),
-        "crafts expected response for {}",
-        message.to_string()
-    );
-}
-
-#[tracing_test::traced_test]
-#[tokio::test]
-async fn action_send_request() {
-    let mut client = crate::test::Client::new().await;
-    let token = AccessToken::new("a-bad-token");
-
-    client
-        .mock_server
-        .mock("POST", "/action-create-sync")
-        .with_header(http::header::CONTENT_TYPE.to_string(), "application/json")
-        .with_header(http::header::LOCATION.to_string(), "http://example.com/new")
-        .with_status(http::StatusCode::CREATED.as_u16().into())
-        .expect(1)
-        .create_async()
-        .await;
-
-    let u = format!("{}/action-create-sync", client.mock_server.url())
-        .parse()
-        .unwrap();
-
-    mock_micropub_request(
-        client,
-        &u,
-        &token,
-        &Action::Create {
-            properties: CreationProperties {
-                r#type: Class::Known(KnownClass::Entry),
-                parameters: Default::default(),
-                extra_fields: Default::default(),
-            },
-            files: Default::default(),
-        },
-        &ActionResponse::Created {
-            sync: true,
-            location: "http://example.com/new".parse().unwrap(),
-            rel: Default::default(),
-        },
-        "create sync",
-    )
-    .await;
-}
--- a/library/src/standards/micropub/query/test.rs
+++ b/library/src/standards/micropub/query/test.rs
@@ -17,152 +17,6 @@
     standards::micropub::{query::QueryKind, Error},
 };
 
-#[tracing_test::traced_test]
-#[tokio::test]
-async fn query_send() {
-    let mut client = crate::test::Client::new().await;
-    let token = AccessToken::new("a-bad-token");
-    let query = crate::standards::micropub::query::Query {
-        pagination: Default::default(),
-        kind: QueryKind::Configuration,
-    };
-    let endpoint_mock = client
-        .mock_server
-        .mock("get", "/micropub/auth-failure")
-        .match_query("q=config")
-        .with_status(400)
-        .with_header(CONTENT_TYPE.as_str(), CONTENT_TYPE_JSON)
-        .with_body(
-            serde_json::to_string(&serde_json::json!({
-                "error": "invalid_request",
-                "error_description": "This was a bad, bad request."
-            }))
-            .unwrap(),
-        )
-        .expect(1)
-        .create_async()
-        .await;
-
-    let endpoint = format!("{}/micropub/auth-failure", client.mock_server.url())
-        .parse()
-        .unwrap();
-
-    let query_result = query.send(&client, &endpoint, &token).await;
-
-    endpoint_mock.assert_async().await;
-
-    assert_eq!(
-        query_result,
-        Err(Error::bad_request("This was a bad, bad request").into()),
-        "reports an authorization failure"
-    );
-}
-
-#[test]
-fn query_from_qs_str() {
-    crate::test::Client::default();
-    assert_eq!(
-        Ok(vec![Type::Note, Type::Read]),
-        serde_qs::from_str::<Query>(
-            "q=source&post-type[]=note&post-type[]=read&channel=jump&limit=5"
-        )
-        .map_err(|e| e.to_string())
-        .map(|q| q.kind)
-        .map(|k| match k {
-            QueryKind::Source(query) => query.post_type,
-            _ => vec![],
-        }),
-        "provides deserialization of the source query with multiple post type asked for"
-    );
-    assert_eq!(
-        Ok(vec![Type::Video, Type::Read]),
-        serde_qs::Config::new(1, false)
-            .deserialize_str::<Query>(
-                "q=source&post-type%5B0%5D=video&post-type%5B1%5D=read&limit=5"
-            )
-            .map_err(|e| e.to_string())
-            .map(|q| q.kind)
-            .map(|k| match k {
-                QueryKind::Source(query) => query.post_type,
-                _ => vec![],
-            }),
-        "provides deserialization of the source query with multiple post type asked for"
-    );
-
-    assert_eq!(
-        None,
-        serde_qs::from_str::<Query>("q=source&post-type=")
-            .err()
-            .map(|e| e.to_string()),
-        "ignores if the post type value is 'empty'"
-    );
-
-    assert_eq!(
-        None,
-        serde_qs::from_str::<Query>("q=source&syndicate-to=3")
-            .err()
-            .map(|e| e.to_string()),
-        "supports filtering by syndication targets"
-    );
-    assert_eq!(
-        None,
-        serde_qs::from_str::<Query>("q=config")
-            .err()
-            .map(|e| e.to_string()),
-        "provides deserialization of the config query"
-    );
-}
-
-#[test]
-fn query_from_qs_str_with_property_filtering() {
-    crate::test::Client::default();
-    assert_eq!(
-        Ok(QueryKind::Source(Box::new(SourceQuery {
-            exists: vec!["in-reply-to".to_string()],
-            not_exists: vec!["like-of".to_string()],
-            matching_properties: MatchingPropertyValuesMap::from_iter(vec![
-                ("byline".into(), vec!["today".into()]),
-                ("range".into(), vec!["3".into(), "10".into()])
-            ]),
-            ..Default::default()
-        }))),
-        serde_qs::from_str::<Query>("q=source&not-exists=like-of&exists=in-reply-to&property-byline=today&property-range[]=3&property-range[]=10")
-            .map(|q| q.kind)
-            .map_err(|e| e.to_string()),
-        "provides deserialization of the config query"
-    );
-}
-
-#[test]
-fn query_to_str() {
-    crate::test::Client::default();
-    let result1 = serde_qs::to_string(&QueryKind::Source(Box::new(SourceQuery {
-        post_type: vec![Type::Article],
-        ..Default::default()
-    })));
-
-    assert_eq!(
-        result1.as_ref().err().map(|s| s.to_string()),
-        None,
-        "can query a list of articles"
-    );
-    assert_eq!(
-        Some("q=source&post-type=article".to_string()),
-        result1.ok(),
-        "can query a list of articles"
-    );
-
-    let result2 = serde_qs::to_string(&QueryKind::Source(Box::new(SourceQuery {
-        post_type: vec![Type::Article, Type::Note],
-        ..Default::default()
-    })));
-    assert_eq!(
-        Some("q=source&post-type[0]=article&post-type[1]=note".to_string()),
-        result2.ok(),
-        "can query a list of articles and notes"
-    );
-}
-
 #[test]
 #[cfg(feature = "experimental_channels")]
 fn query_response_for_channels() {
@@ -303,69 +157,3 @@
         "works with paging"
     )
 }
-
-#[test]
-fn query_response_for_source() {
-    crate::test::Client::default();
-    let item = microformats::types::Item {
-        r#type: vec![Class::Known(KnownClass::Entry)],
-        ..Default::default()
-    };
-    assert_eq!(
-        Ok(Response::Source(SourceResponse {
-            post_type: vec![],
-            item
-        })),
-        serde_json::from_value(serde_json::json!({
-            "type": ["h-entry"],
-            "properties": {}
-        }))
-        .map_err(|e| e.to_string())
-    );
-
-    assert_eq!(
-        serde_json::from_value::<Response>(serde_json::json!(
-        {
-            "post-type": [
-                "article"
-            ],
-            "properties": {
-                "audience": [],
-                "category": [],
-                "channel": [
-                    "all"
-                ],
-                "content": {
-                    "html": "<p>well-here-we-go</p>"
-                },
-                "name": "magic-omg",
-                "post-status": [
-                    "published"
-                ],
-                "published": [
-                    "2022-02-12T23:22:27+00:00"
-                ],
-                "slug": [
-                    "Gzg043ii"
-                ],
-                "syndication": [],
-                "updated": [
-                    "2022-02-12T23:22:27+00:00"
-                ],
-                "url": [
-                    "http://localhost:3112/Gzg043ii"
-                ],
-                "visibility": [
-                    "public"
-                ]
-            },
-            "type": [
-                "h-entry"
-            ]
-        }
-                ))
-        .map_err(|e| e.to_string())
-        .err(),
-        None,
-    )
-}
--- a/library/src/standards/webmention/test.rs
+++ /dev/null
@@ -1,576 +0,0 @@
-#![cfg(test)]
-use crate::test::Client;
-
-use super::endpoint_for;
-use url::Url;
-
-#[macro_export]
-macro_rules! run_stock_webmention_test {
-    ($slug: expr, $mock_page: expr, $resulting_url: expr) => {
-        run_webmention_test_with_client!(
-            $crate::test::Client::new().await,
-            $slug,
-            $mock_page,
-            $resulting_url
-        )
-    };
-}
-
-#[macro_export]
-macro_rules! run_webmention_test_with_client {
-    ($client: expr, $slug: expr, $mock_page: expr, $resulting_url: expr) => {
-        let lpath = format!("/page-{}", $slug);
-        let resource_url = $client.merge_into_url(&lpath);
-
-        let mut resource_mock = $client
-            .mock_server
-            .mock("GET", lpath.as_str())
-            .with_status($mock_page.status().as_u16().into());
-
-        for (name, value) in $mock_page.headers().into_iter() {
-            resource_mock = resource_mock.with_header(name.as_str(), value.to_str().unwrap());
-        }
-
-        resource_mock
-            .with_body($mock_page.into_body().as_bytes())
-            .create();
-
-        let result = endpoint_for(&$client, &resource_url).await;
-
-        let compared_url = if $resulting_url.starts_with("/") {
-            Ok($client.merge_into_url(&$resulting_url))
-        } else {
-            Ok($resulting_url.parse::<url::Url>().unwrap())
-        };
-
-        assert_eq!(
-            result.map(|u| u.to_string()),
-            compared_url.map(|u| u.to_string()),
-            "resolution found the URL {resource_url}",
-        );
-    };
-}
-
-#[tokio::test]
-// Implements <https://webmention.rocks/test/1>
-async fn http_link_header_unquoted_rel_relative_url() {
-    run_stock_webmention_test!(
-        "1",
-        ::http::Response::builder()
-            .status(::http::StatusCode::OK)
-            .header(::http::header::LINK, "</test/1/webmention>; rel=webmention")
-            .body(crate::http::Body::Empty)
-            .unwrap_or_default(),
-        "/test/1/webmention"
-    );
-}
-
-#[tokio::test]
-// Implments <https://webmention.rocks/test/2>
-async fn http_link_header_unquoted_rel_absolute_url() {
-    run_stock_webmention_test!(
-        "2",
-        ::http::Response::builder()
-            .status(::http::StatusCode::OK)
-            .header(::http::header::LINK, "</test/2/webmention>; rel=webmention",)
-            .body(crate::http::Body::Empty)
-            .unwrap_or_default(),
-        "/test/2/webmention"
-    );
-}
-
-#[tokio::test]
-// Implements <https://webmention.rocks/test/3>
-async fn http_link_tag_relative_url() {
-    let whole_url = "/test/3/webmention";
-    run_stock_webmention_test!(
-        "3",
-        ::http::Response::builder()
-            .status(::http::StatusCode::OK)
-            .header("content-type", "text/html")
-            .body(crate::http::Body::from(format!(
-                r#"
-          <html>
-            <head>
-                <link rel="webmention" href="{}" />
-            </head>
-          </html>
-            "#,
-                whole_url
-            )))
-            .unwrap(),
-        whole_url
-    );
-}
-
-#[tokio::test]
-// Implements <https://webmention.rocks/test/4>
-async fn http_link_tag_absolute_url() {
-    let mut client = Client::new().await;
-    let whole_url = format!("{}/test/4/webmention", client.mock_server.url());
-    run_webmention_test_with_client!(
-        client,
-        "4",
-        ::http::Response::builder()
-            .status(::http::StatusCode::OK)
-            .body(crate::http::Body::from(format!(
-                r#"
-          <html>
-            <head>
-                <link rel="webmention" href="{}" />
-            </head>
-          </html>
-            "#,
-                whole_url
-            )))
-            .unwrap_or_default(),
-        whole_url
-    );
-}
-
-#[tokio::test]
-// Implements <https://webmention.rocks/test/5>
-async fn http_a_tag_relative_url() {
-    let whole_url = "/test/5/webmention";
-    run_stock_webmention_test!(
-        "5",
-        ::http::Response::builder()
-            .status(::http::StatusCode::OK)
-            .body(crate::http::Body::from(format!(
-                r#"
-          <html>
-            <head>
-                <link rel="webmention" href="{}" />
-            </head>
-          </html>
-            "#,
-                whole_url
-            )))
-            .unwrap_or_default(),
-        whole_url
-    );
-}
-
-#[tokio::test]
-// Implements <https://webmention.rocks/test/6>
-async fn http_a_tag_absolute_url() {
-    let mut client = Client::new().await;
-    let whole_url: Url = format!("{}/test/6/webmention", client.mock_server.url())
-        .parse()
-        .unwrap();
-    run_webmention_test_with_client!(
-        client,
-        "6",
-        ::http::Response::builder()
-            .status(::http::StatusCode::OK)
-            .body(crate::http::Body::from(format!(
-                r#"
-          <html>
-            <body>
-                <a rel="webmention" href="{}" />
-            </body>
-          </html>
-            "#,
-                whole_url
-            )))
-            .unwrap_or_default(),
-        whole_url.as_str()
-    );
-}
-
-#[tokio::test]
-// Implements <https://webmention.rocks/test/7>
-async fn http_link_header_strange_casing() {
-    let mut client = Client::new().await;
-    let whole_url: Url = format!("{}/test/7/webmention", client.mock_server.url())
-        .parse()
-        .unwrap();
-    let resp = ::http::Response::builder()
-        .header("Link", format!("<{}>; rel=webmention", whole_url).as_str())
-        .body(crate::http::Body::Empty)
-        .unwrap_or_default();
-    run_webmention_test_with_client!(client, "7", resp, whole_url.as_str());
-}
-
-// Implements <https://webmention.rocks/test/8>
-#[tracing_test::traced_test]
-#[tokio::test]
-async fn http_link_header_quoted_rel() {
-    let mut client = Client::new().await;
-    let whole_url: Url = format!("{}/test/8/webmention", client.mock_server.url())
-        .parse()
-        .unwrap();
-    let resp = ::http::Response::builder()
-        .header(
-            "Link",
-            format!("<{}>; rel=\"webmention\"", whole_url).as_str(),
-        )
-        .body(crate::http::Body::Empty)
-        .unwrap_or_default();
-    run_webmention_test_with_client!(client, "8", resp, whole_url.as_str());
-}
-
-// Implements <https://webmention.rocks/test/9>
-#[tracing_test::traced_test]
-#[tokio::test]
-async fn http_multiple_rel_values_on_link_tag() {
-    let mut client = Client::new().await;
-    let whole_url = client.merge_into_url("/test/9/webmention");
-    let resp = ::http::Response::builder()
-        .body(crate::http::Body::Bytes(
-            format!(
-                r#"
-          <html>
-            <head>
-                <link rel="webmention something-else" href="{}" />
-            </head>
-          </html>
-            "#,
-                whole_url
-            )
-            .into(),
-        ))
-        .unwrap_or_default();
-    run_webmention_test_with_client!(client, "9", resp, whole_url.path());
-}
-
-// Implements <https://webmention.rocks/test/10>
-#[tracing_test::traced_test]
-#[tokio::test]
-async fn http_rel_values_on_rel_headers() {
-    let mut client = Client::new().await;
-    let whole_url: Url = format!("{}/test/10/webmention", client.mock_server.url())
-        .parse()
-        .unwrap();
-    let resp = ::http::Response::builder()
-        .header(
-            "LinK",
-            format!("<{}>; rel=\"webmention somethingelse\"", whole_url).as_str(),
-        )
-        .body(crate::http::Body::Empty)
-        .unwrap_or_default();
-    run_webmention_test_with_client!(client, "10", resp, whole_url.path());
-}
-
-#[tokio::test]
-// Implements <https://webmention.rocks/test/11>
-async fn http_rel_multiple_webmention_endpoints_advertised() {
-    let mut client = Client::new().await;
-    let resp = ::http::Response::builder()
-        .header(
-            "LinK",
-            format!(
-                "<{}/test/11/webmention/header>; rel=\"webmention somethingelse\"",
-                client.mock_server.url()
-            )
-            .as_str(),
-        )
-        .body(crate::http::Body::from(format!(
-            r#"
-            <html>
-                <head>
-                    <link rel="webmention" href="{0}/test/11/webmention/link-tag" />
-                </head>
-                <body>
-                    <a rel="webmention" href="{0}/test/11/webmention/a-tag" />
-                </body>
-            </html>
-                "#,
-            client.mock_server.url()
-        )))
-        .unwrap_or_default();
-    run_webmention_test_with_client!(
-        client,
-        "11",
-        resp,
-        format!("{}/test/11/webmention/header", client.mock_server.url())
-    );
-}
-
-#[tokio::test]
-// Implements <https://webmention.rocks/test/12>
-async fn http_rel_checking_for_exact_match_of_rel_webmention() {
-    let mut client = Client::new().await;
-    let resp = ::http::Response::builder()
-        .body(crate::http::Body::from(format!(
-            r#"
-            <html>
-                <head>
-                    <link rel="webmention" href="{0}/test/12/webmention/right" />
-                    <link rel="not-webmention" href="{0}/test/12/webmention/wrong" />
-                </head>
-            </html>
-                "#,
-            client.mock_server.url()
-        )))
-        .unwrap_or_default();
-    run_webmention_test_with_client!(
-        client,
-        "12",
-        resp,
-        format!("{}/test/12/webmention/right", client.mock_server.url())
-    );
-}
-
-#[tokio::test]
-// Implements <https://webmention.rocks/test/13>
-async fn http_rel_false_endpoint_inside_html_element() {
-    let mut client = Client::new().await;
-    let resp = ::http::Response::builder()
-        .body(crate::http::Body::from(format!(
-            r#"
-            <html>
-                <body>
-                <!--
-                    <a rel="webmention" href="{0}/test/13/webmention/wrong" />
-                -->
-
-                    <a rel="webmention" href="{0}/test/13/webmention/right" />
-                </body>
-            </html>
-                "#,
-            client.mock_server.url()
-        )))
-        .unwrap_or_default();
-    run_webmention_test_with_client!(
-        client,
-        "13",
-        resp,
-        format!("{}/test/13/webmention/right", client.mock_server.url())
-    );
-}
-
-#[tokio::test]
-// Implements <https://webmention.rocks/test/14>
-async fn http_rel_false_endpoint_inside_escaped_html() {
-    let mut client = Client::new().await;
-    let resp = ::http::Response::builder()
-    .body(crate::http::Body::from(
-        r#"
-            <html>
-                <body>
-                    This post contains sample code with escaped HTML which should not
-                    be discovered by the Webmention client.
-                    <code>&lt;a href="/test/14/webmention/error" rel="webmention"&gt;&lt;/a&gt;</code>
-                    There is also a <a href="/test/14/webmention/right" rel="webmention">correct endpoint</a>
-                    defined, so if your comment appears below, it means you successfully ignored the false endpoint.
-                </body>
-            </html>
-                "#
-    .to_string()))
-    .unwrap_or_default();
-    run_webmention_test_with_client!(
-        client,
-        "14",
-        resp,
-        format!("{}/test/14/webmention/right", client.mock_server.url())
-    );
-}
-
-#[tokio::test]
-// Implements <https://webmention.rocks/test/15>
-async fn http_rel_webmention_href_empty_string() {
-    let mut client = Client::new().await;
-    let resp = ::http::Response::builder()
-        .body(crate::http::Body::from(
-            r#"
-            <html>
-                <head>
-                    <link rel="webmention" href="" />
-                </head>
-            </html>
-
-                "#
-            .to_string(),
-        ))
-        .unwrap_or_default();
-    run_webmention_test_with_client!(
-        client,
-        "15",
-        resp,
-        format!("{}/page-15", client.mock_server.url())
-    );
-}
-
-// Implements <https://webmention.rocks/test/16>
-#[tracing_test::traced_test]
-#[tokio::test]
-async fn http_rel_multiple_webmention_endpoints_advertised_link_a() {
-    let resp = ::http::Response::builder()
-    .body(crate::http::Body::from(
-        r#"
-            <html>
-                <body>
-                    This post advertises its Webmention endpoint in an HTML
-                    <a href="https://webmention.rocks/test/16/webmention"
-                    rel="webmention">&lt;a&gt; tag</a>, followed by a later
-                    definition in a &lt;link&gt; tag. Your Webmention client
-                    must only send a Webmention to the one in the &lt;a&gt;
-                    tag since it appears first in the document.
-                    <link rel="webmention" href="https://webmention.rocks/test/16/webmention/error" />
-                </body>
-            </html>
-
-                "#
-        .to_string(),
-    ))
-    .expect("yeup");
-    run_stock_webmention_test!("16", resp, "https://webmention.rocks/test/16/webmention");
-}
-
-#[tokio::test]
-// Implements <https://webmention.rocks/test/17>
-async fn http_rel_multiple_webmention_endpoints_advertised_a_link() {
-    let mut client = Client::new().await;
-    let resp = ::http::Response::builder()
-        .body(crate::http::Body::from(
-            r#"
-            <html>
-                <body>
-                    This post advertises its Webmention endpoint in an
-                    HTML &lt;link&gt; tag <link rel="webmention" href="/test/17/webmention">
-                    followed by a later definition in an <a href="/test/17/webmention/error"
-                    rel="webmention">&lt;a&gt; tag</a>. Your Webmention client must only send
-                    a Webmention to the one in the &lt;link&gt; tag since it appears first in
-                    the document
-                </body>
-            </html>
-
-                "#
-            .to_string(),
-        ))
-        .unwrap_or_default();
-    run_webmention_test_with_client!(
-        client,
-        "17",
-        resp,
-        format!("{}/test/17/webmention", client.mock_server.url())
-    );
-}
-
-#[tokio::test]
-// Implements <https://webmention.rocks/test/18>
-async fn http_rel_multiple_link_http_headers() {
-    let mut client = Client::new().await;
-    let resp = ::http::Response::builder()
-        .header(
-            "LinK",
-            format!(
-                r#"<{0}/test/18/webmention>; rel="webmention""#,
-                client.mock_server.url()
-            )
-            .as_str(),
-        )
-        .header(
-            ::http::header::LINK,
-            format!(
-                r#"<{0}/test/18/webmention/error>; rel="other""#,
-                client.mock_server.url()
-            )
-            .as_str(),
-        )
-        .body(crate::http::Body::Empty)
-        .unwrap_or_default();
-    run_webmention_test_with_client!(
-        client,
-        "18",
-        resp,
-        format!("{}/test/18/webmention", client.mock_server.url())
-    );
-}
-
-#[tokio::test]
-// Implements <https://webmention.rocks/test/19>
-async fn http_rel_single_link_header_multiple_values() {
-    let mut client = Client::new().await;
-    let resp = ::http::Response::builder()
-        .header(
-            "LinK",
-            format!(
-                r#"<{0}/test/19/webmention/error>; rel="other", <{0}/test/19/webmention>; rel="webmention""#,
-                client.mock_server.url()
-            )
-            .as_str(),
-        )
-    .body(crate::http::Body::Empty)
-    .unwrap_or_default();
-    run_webmention_test_with_client!(
-        client,
-        "18",
-        resp,
-        format!("{}/test/19/webmention", client.mock_server.url())
-    );
-}
-
-#[tracing_test::traced_test]
-#[tokio::test]
-// Implements <https://webmention.rocks/test/20>
-async fn link_tag_with_no_href_attribute() {
-    let mut client = Client::new().await;
-    let resp = ::http::Response::builder()
-        .body(crate::http::Body::from(
-            r#"
-            <html>
-                <body>
-                    This post has a &lt;link&gt; tag <link rel="webmention"> which
-                    has no href attribute. Your Webmention client should not find
-                    this link tag, and should send the webmention to
-                    <a href="/test/20/webmention" rel="webmention">this endpoint</a>
-                    instead.
-                </body>
-            </html>
-                "#
-            .to_string(),
-        ))
-        .unwrap_or_default();
-    run_webmention_test_with_client!(
-        client,
-        "20",
-        resp,
-        format!("{}/test/20/webmention", client.mock_server.url())
-    );
-}
-
-#[tokio::test]
-// Implements <https://webmention.rocks/test/21>
-async fn webmention_endpoint_with_query_params() {
-    let mut client = Client::new().await;
-    let resp = ::http::Response::builder()
-        .body(crate::http::Body::from(
-            r#"
-            <html>
-                <link rel="webmention" href="/test/21/webmention?query=yes">
-            </html>
-                "#
-            .to_string(),
-        ))
-        .unwrap_or_default();
-    run_webmention_test_with_client!(
-        client,
-        "21",
-        resp,
-        format!("{}/test/21/webmention?query=yes", client.mock_server.url())
-    );
-}
-
-#[tokio::test]
-// Implements <https://webmention.rocks/test/22>
-async fn webmention_endpoint_relative_to_path() {
-    let mut client = Client::new().await;
-    let resp = ::http::Response::builder()
-        .body(crate::http::Body::from(
-            r#"
-            <html>
-                <link rel="webmention" href="22/webmention">
-            </html>
-                "#
-            .to_string(),
-        ))
-        .unwrap_or_default();
-    run_webmention_test_with_client!(
-        client,
-        "22",
-        resp,
-        format!("{}/22/webmention", client.mock_server.url())
-    );
-}
--- a/library/src/traits/mod.rs
+++ b/library/src/traits/mod.rs
@@ -154,5 +154,3 @@
         }
     }
 }
-
-mod test;
--- a/library/src/traits/test.rs
+++ /dev/null
@@ -1,37 +0,0 @@
-#![cfg(test)]
-
-use url::Url;
-
-use crate::traits::FetchMF2FromExt;
-
-#[tracing_test::traced_test]
-#[tokio::test]
-async fn fetch_mf2_from_ext_url() {
-    let mut client = crate::test::Client::new().await;
-    let u: Url = format!("{}/test-endpoint-fetch", client.mock_server.url())
-        .parse()
-        .unwrap();
-    let _ = client
-        .mock_server
-        .mock("GET", u.path())
-        .with_status(200)
-        .with_header("content-type", "text/html")
-        .with_body(
-            r#"
-            <html>
-                <body>
-                    <main class="h-entry">
-                        <a href="" class="u-url u-uid"></a>
-                    </main>
-                </body>
-            </html>
-            "#,
-        )
-        .expect_at_most(1)
-        .create_async()
-        .await;
-    let result = u.fetch_mf2_from(client).await;
-
-    assert!(result.is_ok());
-    assert_eq!(result.map(|doc| doc.items.len()), Ok(1));
-}
