use base64::Engine;
use multiavatar::*;
const PNG_MAGIC: [u8; 8] = [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A];
const JPG_MAGIC: [u8; 3] = [0xFF, 0xD8, 0xFF];
const GIF_MAGIC: &[u8] = b"GIF8";
#[test]
fn svg_smoke() {
let svg = multiavatar("Binx Bond");
assert!(svg.starts_with(
"<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"256\" height=\"256\" viewBox=\"0 0 231 231\">"
));
assert!(svg.ends_with("</svg>"));
assert!(svg.contains("<path"), "缺少 path 元素");
}
#[test]
fn empty_input() {
assert_eq!(multiavatar(""), "");
assert!(to_png("").is_empty());
assert!(to_jpg("").is_empty());
assert!(to_gif("").is_empty());
assert_eq!(to_data_uri(""), "");
assert!(to_image("").is_none());
}
#[test]
fn png_bytes_and_dimension() {
let png = to_png("demon1110");
assert_eq!(&png[..8], &PNG_MAGIC[..]);
let decoder = png::Decoder::new(std::io::Cursor::new(&png));
let reader = decoder.read_info().expect("PNG 头解析失败");
assert_eq!((reader.info().width, reader.info().height), (256, 256));
}
#[test]
fn png_custom_size() {
let png = to_png_sized("demon1110", 512);
let decoder = png::Decoder::new(std::io::Cursor::new(&png));
let reader = decoder.read_info().expect("PNG 头解析失败");
assert_eq!((reader.info().width, reader.info().height), (512, 512));
}
#[test]
fn jpg_bytes() {
let jpg = to_jpg("demon1110");
assert_eq!(&jpg[..3], &JPG_MAGIC[..]);
assert!(jpg.len() > 1000, "JPG 过小: {}", jpg.len());
}
#[test]
fn gif_bytes() {
let gif = to_gif("demon1110");
assert!(gif.len() > 6);
assert_eq!(&gif[..4], GIF_MAGIC);
let mut decoder = gif::DecodeOptions::new();
decoder.set_color_output(gif::ColorOutput::RGBA);
let mut reader = decoder.read_info(std::io::Cursor::new(&gif)).expect("GIF 解析失败");
let first = reader.read_next_frame().expect("首帧缺失").unwrap();
let has_opaque = first.buffer.chunks_exact(4).any(|px| px[3] > 0);
assert!(has_opaque, "GIF 首帧不可见(无有效像素)");
}
#[test]
fn data_uri_prefix() {
let uri = to_data_uri("Binx Bond");
assert!(uri.starts_with("data:image/png;base64,"));
let b64 = uri.trim_start_matches("data:image/png;base64,");
let decoded = base64::engine::general_purpose::STANDARD
.decode(b64)
.expect("data URI base64 解码失败");
assert_eq!(&decoded[..8], &PNG_MAGIC[..]);
}
#[test]
fn favicon_zip_entries() {
let zip = to_favicon_zip("Binx Bond");
let mut reader = zip::ZipArchive::new(std::io::Cursor::new(zip)).expect("zip 解析失败");
let names: Vec<String> = (0..reader.len())
.map(|i| reader.by_index(i).unwrap().name().unwrap().to_string())
.collect();
assert_eq!(names.len(), 6);
assert_eq!(names[0], "avatar-16.png");
assert!(names.contains(&"avatar-256.png".to_string()));
}
#[test]
fn favicon_ico_structure() {
let ico = to_favicon_ico("Binx Bond");
assert_eq!(&ico[0..2], &[0, 0]);
assert_eq!(&ico[2..4], &[1, 0]);
assert_eq!(&ico[4..6], &[6, 0]);
assert_eq!(ico[6], 16);
assert_eq!(ico[7], 16);
assert!(ico.len() > 102, "ICO 过小: {}", ico.len());
}
#[test]
fn forced_part_and_theme() {
let a = multiavatar_full("aaa", false, Some("05"), Some("B"));
let b = multiavatar_full("zzz", false, Some("05"), Some("B"));
assert_eq!(a, b);
let c = multiavatar_full("aaa", false, Some("05"), Some("C"));
assert_ne!(a, c);
}
#[test]
fn sans_env_omits_background() {
let full = multiavatar("Binx Bond");
let sans = multiavatar_with("Binx Bond", true);
assert!(sans.len() < full.len(), "sansEnv 应更短");
}
#[test]
fn deterministic_same_input() {
assert_eq!(multiavatar("demo"), multiavatar("demo"));
}
#[test]
fn avatar_object_immutable_and_lazy() {
let a = avatar("immutable-demo");
let b = avatar("immutable-demo");
assert_eq!(a.input(), b.input());
let _ = a.png_sized(128);
let _ = a.png_sized(256);
assert!(a.svg().starts_with("<svg"));
}
#[test]
fn optimize_off_keeps_raw() {
let opt_on = multiavatar("raw-compare");
let opt_off = {
let options = avatar_options::AvatarOptions::builder().optimize_svg(false).build();
avatar_with("raw-compare", &options).svg().to_string()
};
assert_ne!(opt_on, opt_off);
assert!(opt_off.contains("115.5"), "原始坐标应保留");
}