#![allow(clippy::unwrap_used, clippy::expect_used)]
use liburlx::protocol::http::multipart::MultipartForm;
#[test]
fn single_text_field() {
let mut form = MultipartForm::with_boundary("testboundary");
form.field("name", "value");
let encoded = form.encode();
let body = String::from_utf8(encoded).unwrap();
assert!(body.contains("--testboundary\r\n"));
assert!(body.contains("Content-Disposition: form-data; name=\"name\""));
assert!(body.contains("\r\n\r\nvalue\r\n"));
assert!(body.contains("--testboundary--\r\n"));
}
#[test]
fn multiple_text_fields() {
let mut form = MultipartForm::with_boundary("bound");
form.field("first", "one");
form.field("second", "two");
form.field("third", "three");
let encoded = form.encode();
let body = String::from_utf8(encoded).unwrap();
assert!(body.contains("name=\"first\""));
assert!(body.contains("\r\n\r\none\r\n"));
assert!(body.contains("name=\"second\""));
assert!(body.contains("\r\n\r\ntwo\r\n"));
assert!(body.contains("name=\"third\""));
assert!(body.contains("\r\n\r\nthree\r\n"));
}
#[test]
fn content_type_includes_boundary() {
let form = MultipartForm::with_boundary("myboundary");
let ct = form.content_type();
assert_eq!(ct, "multipart/form-data; boundary=myboundary");
}
#[test]
fn default_boundary_in_content_type() {
let form = MultipartForm::new();
let ct = form.content_type();
assert!(ct.starts_with("multipart/form-data; boundary="));
assert!(ct.len() > "multipart/form-data; boundary=".len());
}
#[test]
fn different_forms_get_different_boundaries() {
let form1 = MultipartForm::new();
let form2 = MultipartForm::new();
let ct1 = form1.content_type();
let ct2 = form2.content_type();
assert!(ct1.starts_with("multipart/form-data; boundary="));
assert!(ct2.starts_with("multipart/form-data; boundary="));
}
#[test]
fn file_data_with_filename() {
let mut form = MultipartForm::with_boundary("fileboundary");
form.file_data("upload", "test.txt", b"file contents here");
let encoded = form.encode();
let body = String::from_utf8(encoded).unwrap();
assert!(body.contains("name=\"upload\""));
assert!(body.contains("filename=\"test.txt\""));
assert!(body.contains("Content-Type: text/plain"));
assert!(body.contains("file contents here"));
}
#[test]
fn file_data_json_content_type() {
let mut form = MultipartForm::with_boundary("jsonbound");
form.file_data("data", "payload.json", b"{\"key\": \"value\"}");
let encoded = form.encode();
let body = String::from_utf8(encoded).unwrap();
assert!(body.contains("filename=\"payload.json\""));
assert!(body.contains("Content-Type: application/json"));
}
#[test]
fn file_data_png_content_type() {
let mut form = MultipartForm::with_boundary("imgbound");
form.file_data("image", "photo.png", &[0x89, 0x50, 0x4E, 0x47]);
let encoded = form.encode();
let body = String::from_utf8_lossy(&encoded);
assert!(body.contains("filename=\"photo.png\""));
assert!(body.contains("Content-Type: image/png"));
}
#[test]
fn file_data_unknown_extension_uses_octet_stream() {
let mut form = MultipartForm::with_boundary("unknownbound");
form.file_data("file", "data.xyz", b"some data");
let encoded = form.encode();
let body = String::from_utf8(encoded).unwrap();
assert!(body.contains("Content-Type: application/octet-stream"));
}
#[test]
fn mixed_fields_and_files() {
let mut form = MultipartForm::with_boundary("mixedbound");
form.field("description", "My upload");
form.file_data("file", "doc.pdf", b"PDF data");
form.field("tag", "important");
let encoded = form.encode();
let body = String::from_utf8(encoded).unwrap();
assert!(body.contains("name=\"description\""));
assert!(body.contains("My upload"));
assert!(body.contains("name=\"file\""));
assert!(body.contains("filename=\"doc.pdf\""));
assert!(body.contains("Content-Type: application/pdf"));
assert!(body.contains("name=\"tag\""));
assert!(body.contains("important"));
}
#[test]
fn empty_form_has_closing_boundary() {
let form = MultipartForm::with_boundary("emptybound");
let encoded = form.encode();
let body = String::from_utf8(encoded).unwrap();
assert!(body.contains("--emptybound--"));
}
#[test]
fn field_with_newlines() {
let mut form = MultipartForm::with_boundary("nlbound");
form.field("text", "line1\nline2\nline3");
let encoded = form.encode();
let body = String::from_utf8(encoded).unwrap();
assert!(body.contains("line1\nline2\nline3"));
}
#[test]
fn field_with_unicode() {
let mut form = MultipartForm::with_boundary("unicodebound");
form.field("name", "Hello world");
let encoded = form.encode();
let body = String::from_utf8(encoded).unwrap();
assert!(body.contains("Hello world"));
}
#[test]
fn binary_file_data_preserved() {
let binary_data: Vec<u8> = (0..=255).collect();
let mut form = MultipartForm::with_boundary("binbound");
form.file_data("binary", "data.bin", &binary_data);
let encoded = form.encode();
let header_end = b"\r\n\r\n";
let mut pos = 0;
for window in encoded.windows(header_end.len()) {
if window == header_end {
pos += header_end.len();
break;
}
pos += 1;
}
assert!(encoded[pos..].windows(256).any(|w| w == binary_data.as_slice()));
}
#[test]
fn large_field_value() {
let large_value = "x".repeat(100_000);
let mut form = MultipartForm::with_boundary("largebound");
form.field("big", &large_value);
let encoded = form.encode();
let body = String::from_utf8(encoded).unwrap();
assert!(body.contains(&large_value));
}
#[test]
fn content_type_detection_html() {
let mut form = MultipartForm::with_boundary("b");
form.file_data("f", "page.html", b"<html>");
let body = String::from_utf8(form.encode()).unwrap();
assert!(body.contains("Content-Type: text/html"));
}
#[test]
fn content_type_detection_css() {
let mut form = MultipartForm::with_boundary("b");
form.file_data("f", "style.css", b"body{}");
let body = String::from_utf8(form.encode()).unwrap();
assert!(body.contains("Content-Type: text/css"));
}
#[test]
fn content_type_detection_js() {
let mut form = MultipartForm::with_boundary("b");
form.file_data("f", "app.js", b"console.log()");
let body = String::from_utf8(form.encode()).unwrap();
assert!(body.contains("Content-Type: application/javascript"));
}
#[test]
fn content_type_detection_xml() {
let mut form = MultipartForm::with_boundary("b");
form.file_data("f", "data.xml", b"<root/>");
let body = String::from_utf8(form.encode()).unwrap();
assert!(body.contains("Content-Type: application/xml"));
}
#[test]
fn content_type_detection_jpeg() {
let mut form = MultipartForm::with_boundary("b");
form.file_data("f", "photo.jpg", b"\xff\xd8");
let encoded = form.encode();
let body = String::from_utf8_lossy(&encoded);
assert!(body.contains("Content-Type: image/jpeg"));
}
#[test]
fn content_type_detection_gif() {
let mut form = MultipartForm::with_boundary("b");
form.file_data("f", "anim.gif", b"GIF89a");
let body = String::from_utf8(form.encode()).unwrap();
assert!(body.contains("Content-Type: image/gif"));
}
#[test]
fn content_type_detection_svg() {
let mut form = MultipartForm::with_boundary("b");
form.file_data("f", "icon.svg", b"<svg/>");
let body = String::from_utf8(form.encode()).unwrap();
assert!(body.contains("Content-Type: image/svg+xml"));
}
#[test]
fn content_type_detection_zip() {
let mut form = MultipartForm::with_boundary("b");
form.file_data("f", "archive.zip", b"PK");
let body = String::from_utf8(form.encode()).unwrap();
assert!(body.contains("Content-Type: application/zip"));
}
#[test]
fn content_type_detection_gzip() {
let mut form = MultipartForm::with_boundary("b");
form.file_data("f", "data.gz", b"\x1f\x8b");
let encoded = form.encode();
let body = String::from_utf8_lossy(&encoded);
assert!(body.contains("Content-Type: application/gzip"));
}