use rust_scraper::{
crawl_site, discover_urls_for_tui, is_allowed, is_excluded, is_internal_link, matches_pattern,
CrawlerConfig,
};
use url::Url;
#[test]
fn test_matches_pattern_wildcard() {
assert!(matches_pattern("https://example.com/page", "*"));
assert!(matches_pattern("https://any.domain/any/path", "*"));
}
#[test]
fn test_matches_pattern_domain_wildcard() {
assert!(matches_pattern(
"https://blog.example.com/post",
"*.example.com/*"
));
assert!(matches_pattern(
"https://sub.example.com/page",
"*.example.com"
));
assert!(!matches_pattern("https://other.com/page", "*.example.com"));
}
#[test]
fn test_matches_pattern_prefix_wildcard() {
assert!(matches_pattern(
"https://blog.example.com/post",
"*.example.com/*"
));
assert!(matches_pattern(
"https://admin.example.com/users",
"*.example.com/*"
));
assert!(!matches_pattern(
"https://other.com/page",
"*.example.com/*"
));
assert!(!matches_pattern(
"https://example.com/admin/users",
"*.example.com/*"
));
}
#[test]
fn test_is_excluded() {
let patterns = vec![
"*.admin.com".to_string(),
"*.private.com".to_string(),
"*.example.com".to_string(), ];
assert!(is_excluded("https://admin.admin.com/page", &patterns));
assert!(is_excluded("https://private.private.com/data", &patterns));
assert!(is_excluded("https://blog.example.com/login", &patterns));
assert!(!is_excluded("https://public.com/page", &patterns));
assert!(!is_excluded("https://example.com/admin/users", &patterns));
}
#[test]
fn test_is_internal_link() {
assert!(is_internal_link("https://example.com/page", "example.com"));
assert!(is_internal_link(
"https://www.example.com/page",
"example.com"
));
assert!(is_internal_link(
"https://blog.example.com/post",
"example.com"
));
assert!(!is_internal_link("https://other.com/page", "example.com"));
}
#[tokio::test]
#[ignore]
async fn test_crawl_site_small() {
let seed = Url::parse("https://example.com").unwrap();
let config = CrawlerConfig::builder(seed)
.max_depth(1)
.max_pages(5)
.delay_ms(500)
.build();
let result = crawl_site(config).await.unwrap();
assert!(result.total_pages >= 1);
assert!(!result.urls.is_empty());
println!("Crawled {} pages", result.total_pages);
}
#[tokio::test]
#[ignore]
async fn test_discover_urls() {
let seed = Url::parse("https://example.com").unwrap();
let config = CrawlerConfig::new(seed);
let urls: Vec<_> = discover_urls_for_tui("https://example.com", &config)
.await
.unwrap();
assert!(!urls.is_empty());
println!("Discovered {} URLs", urls.len());
}
#[tokio::test]
#[ignore]
async fn test_crawl_with_sitemap() {
use rust_scraper::crawl_with_sitemap;
let seed = Url::parse("https://example.com").unwrap();
let config = CrawlerConfig::new(seed);
let urls: Vec<_> = crawl_with_sitemap("https://example.com", None, &config)
.await
.unwrap();
println!("Found {} URLs from sitemap", urls.len());
}
#[test]
fn test_is_allowed_complex() {
let seed = Url::parse("https://example.com").unwrap();
let config = CrawlerConfig::builder(seed)
.include_pattern("blog.example.com".to_string())
.include_pattern("*.blog.example.com".to_string())
.include_pattern("docs.example.com".to_string())
.include_pattern("*.docs.example.com".to_string())
.exclude_pattern("draft.example.com".to_string())
.exclude_pattern("*.draft.example.com".to_string())
.build();
assert!(is_allowed("https://blog.example.com/post", &config));
assert!(is_allowed("https://news.blog.example.com/article", &config));
assert!(is_allowed("https://docs.example.com/guide", &config));
assert!(!is_allowed("https://draft.example.com/post", &config));
assert!(!is_allowed("https://test.draft.example.com/guide", &config));
assert!(!is_allowed("https://example.com/shop/products", &config));
assert!(!is_allowed("https://admin.example.com/users", &config));
}
#[test]
fn test_crawler_config_builder() {
let seed = Url::parse("https://example.com").unwrap();
let config = CrawlerConfig::builder(seed)
.max_depth(5)
.max_pages(500)
.concurrency(5)
.delay_ms(1000)
.include_pattern("*.example.com/*".to_string())
.exclude_pattern("*/admin/*".to_string())
.user_agent("test-crawler/1.0")
.timeout_secs(60)
.build();
assert_eq!(config.max_depth, 5);
assert_eq!(config.max_pages, 500);
assert_eq!(config.concurrency, 5);
assert_eq!(config.delay_ms, 1000);
assert_eq!(config.include_patterns.len(), 1);
assert_eq!(config.exclude_patterns.len(), 1);
assert_eq!(config.user_agent, "test-crawler/1.0");
assert_eq!(config.timeout_secs, 60);
}
#[test]
fn test_crawler_config_defaults() {
let seed = Url::parse("https://example.com").unwrap();
let config = CrawlerConfig::new(seed);
assert_eq!(config.max_depth, 3);
assert_eq!(config.max_pages, 100);
assert_eq!(config.concurrency, 3); assert_eq!(config.delay_ms, 500); }