scrape_core/query/
error.rs

1//! Error types for query operations.
2
3use thiserror::Error;
4
5/// Result type alias for query operations.
6pub type QueryResult<T> = std::result::Result<T, QueryError>;
7
8/// Error type for query operations.
9///
10/// This error type distinguishes between invalid selectors and other query failures,
11/// enabling `Result<Option<Tag>, QueryError>` to differentiate "not found" from
12/// "invalid query".
13#[derive(Debug, Error, Clone, PartialEq, Eq)]
14pub enum QueryError {
15    /// Invalid CSS selector syntax.
16    #[error("invalid selector: {0}")]
17    InvalidSelector(String),
18}
19
20impl QueryError {
21    /// Creates a new invalid selector error.
22    #[must_use]
23    pub fn invalid_selector(message: impl Into<String>) -> Self {
24        Self::InvalidSelector(message.into())
25    }
26}
27
28#[cfg(test)]
29mod tests {
30    use super::*;
31
32    #[test]
33    fn test_query_error_display() {
34        let err = QueryError::invalid_selector("unexpected token at position 5");
35        assert_eq!(err.to_string(), "invalid selector: unexpected token at position 5");
36    }
37
38    #[test]
39    fn test_query_error_equality() {
40        let err1 = QueryError::invalid_selector("foo");
41        let err2 = QueryError::invalid_selector("foo");
42        let err3 = QueryError::invalid_selector("bar");
43        assert_eq!(err1, err2);
44        assert_ne!(err1, err3);
45    }
46
47    #[test]
48    fn test_query_result_type() {
49        let ok: QueryResult<i32> = Ok(42);
50        let err: QueryResult<i32> = Err(QueryError::invalid_selector("test"));
51
52        assert!(ok.is_ok());
53        assert!(err.is_err());
54    }
55}