Files
rust_browser/crates/net/tests/http_tests.rs
2026-01-30 23:10:27 -05:00

231 lines
7.0 KiB
Rust

//! Integration tests for HTTP loader using a local test server.
mod test_server;
use net::{HttpLoader, Loader, NetworkStack};
use shared::BrowserUrl;
use std::sync::mpsc;
use std::thread;
use std::time::Duration;
use test_server::{serve_background, TestResponse, TestServer};
/// Start a simple test server that responds to specific paths.
fn start_test_server() -> (String, u16, mpsc::Sender<()>) {
let (test_server, server) = TestServer::new();
let base_url = test_server.url();
let port = test_server.port();
let (_handle, stop_tx) = serve_background(server, move |path: &str| match path {
"/" | "/index.html" => TestResponse::ok(
"text/html; charset=utf-8",
b"<html><body><h1>Hello World</h1></body></html>".to_vec(),
),
"/basic.html" => TestResponse::ok(
"text/html",
b"<html><body>Basic Page</body></html>".to_vec(),
),
"/redirect-301" => {
TestResponse::redirect(301, format!("http://127.0.0.1:{}/basic.html", port))
}
"/redirect-302" => TestResponse::redirect(302, "/basic.html".to_string()),
"/redirect-chain" => TestResponse::redirect(302, "/redirect-302".to_string()),
"/infinite-redirect" => TestResponse::redirect(302, "/infinite-redirect".to_string()),
"/404" => TestResponse::error(404, b"Not Found".to_vec()),
"/500" => TestResponse::error(500, b"Internal Server Error".to_vec()),
"/json" => TestResponse::ok("application/json", br#"{"message": "hello"}"#.to_vec()),
"/plain" => TestResponse::ok("text/plain", b"Plain text content".to_vec()),
_ => TestResponse::error(404, b"Not Found".to_vec()),
});
// Give the server a moment to start
thread::sleep(Duration::from_millis(50));
(base_url, port, stop_tx)
}
#[test]
fn test_http_basic_get() {
let (base_url, _port, stop_tx) = start_test_server();
let loader = HttpLoader::new();
let url = BrowserUrl::parse(&format!("{}/basic.html", base_url)).unwrap();
let result = loader.load(&url);
stop_tx.send(()).ok();
assert!(result.is_ok(), "Expected OK, got: {:?}", result);
let response = result.unwrap();
assert!(response.is_success());
assert!(response.content_type.is_html());
assert!(response.body_as_string().unwrap().contains("Basic Page"));
}
#[test]
fn test_http_redirect_301() {
let (base_url, _port, stop_tx) = start_test_server();
let loader = HttpLoader::new();
let url = BrowserUrl::parse(&format!("{}/redirect-301", base_url)).unwrap();
let result = loader.load(&url);
stop_tx.send(()).ok();
assert!(result.is_ok());
let response = result.unwrap();
assert!(response.is_success());
// Should have followed redirect to basic.html
assert!(response.body_as_string().unwrap().contains("Basic Page"));
}
#[test]
fn test_http_redirect_302() {
let (base_url, _port, stop_tx) = start_test_server();
let loader = HttpLoader::new();
let url = BrowserUrl::parse(&format!("{}/redirect-302", base_url)).unwrap();
let result = loader.load(&url);
stop_tx.send(()).ok();
assert!(result.is_ok());
let response = result.unwrap();
assert!(response.is_success());
assert!(response.body_as_string().unwrap().contains("Basic Page"));
}
#[test]
fn test_http_redirect_chain() {
let (base_url, _port, stop_tx) = start_test_server();
let loader = HttpLoader::new();
let url = BrowserUrl::parse(&format!("{}/redirect-chain", base_url)).unwrap();
let result = loader.load(&url);
stop_tx.send(()).ok();
assert!(result.is_ok());
let response = result.unwrap();
assert!(response.is_success());
// Should have followed the chain: redirect-chain -> redirect-302 -> basic.html
assert!(response.body_as_string().unwrap().contains("Basic Page"));
}
#[test]
fn test_http_too_many_redirects() {
let (base_url, _port, stop_tx) = start_test_server();
// Use a loader with a low redirect limit
let loader = HttpLoader::new().with_max_redirects(2);
let url = BrowserUrl::parse(&format!("{}/infinite-redirect", base_url)).unwrap();
let result = loader.load(&url);
stop_tx.send(()).ok();
assert!(result.is_err());
let err = result.unwrap_err();
assert!(matches!(
err,
shared::NavigationError::TooManyRedirects { max: 2 }
));
}
#[test]
fn test_http_404_error() {
let (base_url, _port, stop_tx) = start_test_server();
let loader = HttpLoader::new();
let url = BrowserUrl::parse(&format!("{}/404", base_url)).unwrap();
let result = loader.load(&url);
stop_tx.send(()).ok();
// 404 returns a Response (not an Err), with error status
assert!(result.is_ok());
let response = result.unwrap();
assert!(!response.is_success());
assert_eq!(response.status.code(), 404);
}
#[test]
fn test_http_500_error() {
let (base_url, _port, stop_tx) = start_test_server();
let loader = HttpLoader::new();
let url = BrowserUrl::parse(&format!("{}/500", base_url)).unwrap();
let result = loader.load(&url);
stop_tx.send(()).ok();
assert!(result.is_ok());
let response = result.unwrap();
assert!(!response.is_success());
assert_eq!(response.status.code(), 500);
assert!(response.status.is_server_error());
}
#[test]
fn test_http_content_type_json() {
let (base_url, _port, stop_tx) = start_test_server();
let loader = HttpLoader::new();
let url = BrowserUrl::parse(&format!("{}/json", base_url)).unwrap();
let result = loader.load(&url);
stop_tx.send(()).ok();
assert!(result.is_ok());
let response = result.unwrap();
assert!(response.is_success());
assert_eq!(response.content_type.mime_type(), "application/json");
}
#[test]
fn test_http_content_type_plain() {
let (base_url, _port, stop_tx) = start_test_server();
let loader = HttpLoader::new();
let url = BrowserUrl::parse(&format!("{}/plain", base_url)).unwrap();
let result = loader.load(&url);
stop_tx.send(()).ok();
assert!(result.is_ok());
let response = result.unwrap();
assert!(response.is_success());
assert!(response.content_type.is_text());
assert_eq!(response.body_as_string().unwrap(), "Plain text content");
}
#[test]
fn test_network_stack_http() {
let (base_url, _port, stop_tx) = start_test_server();
let stack = NetworkStack::new();
let url = BrowserUrl::parse(&format!("{}/basic.html", base_url)).unwrap();
let result = stack.load_sync(&url);
stop_tx.send(()).ok();
assert!(result.is_ok());
let response = result.unwrap();
assert!(response.is_success());
assert!(response.is_html());
}
#[test]
fn test_http_connection_refused() {
// Try to connect to a port that's not listening
let loader = HttpLoader::new().with_connect_timeout(1);
let url = BrowserUrl::parse("http://127.0.0.1:59999/test").unwrap();
let result = loader.load(&url);
assert!(result.is_err());
let err = result.unwrap_err();
assert!(
err.is_network_error(),
"Expected network error, got: {:?}",
err
);
}