#[cfg(test)]
mod tests {
use std::fs;
use std::path::PathBuf;
use bytes::Bytes;
use image::EncodableLayout;
#[cfg(feature = "net")]
use tee_morphosis::tee::uv::TEE_UV_LAYOUT;
use tee_morphosis::tee::{
Tee,
hsl::ddnet_color_to_hsl,
parts::{EyeType, TeePart},
skin::TEE_SKIN_LAYOUT,
};
fn fixture_path() -> PathBuf {
let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
path.push(".ref");
path.push("test_skin.png");
path
}
fn setup_output_dir(dir_name: &str) -> PathBuf {
let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
path.push(".test");
path.push(dir_name);
if path.exists() {
fs::remove_dir_all(&path).expect("Failed to clean up output directory");
}
fs::create_dir_all(&path).expect("Failed to create output directory");
path
}
fn get_tee() -> Tee {
let fixture = fixture_path();
assert!(
fixture.exists(),
"Test fixture not found at {:?}. Please download a skin and place it there.",
fixture
);
let skin_data = fs::read(&fixture).expect("Failed to read fixture file");
let tee = Tee::new(Bytes::from(skin_data), image::ImageFormat::Png)
.expect("Failed to parse TeeRaw");
tee
}
#[test]
fn test_save_raw_parts() {
let tee = get_tee();
let output_dir = setup_output_dir("raws");
tee.body
.value
.save(output_dir.join("body.png"))
.expect("Failed to save body");
tee.body
.shadow
.save(output_dir.join("body_shadow.png"))
.expect("Failed to save body shadow");
tee.feet
.value
.save(output_dir.join("feet.png"))
.expect("Failed to save feet");
tee.feet
.shadow
.save(output_dir.join("feet_shadow.png"))
.expect("Failed to save feet shadow");
tee.hand
.value
.save(output_dir.join("hand.png"))
.expect("Failed to save hand");
tee.hand
.shadow
.save(output_dir.join("hand_shadow.png"))
.expect("Failed to save hand shadow");
for eye_type in [
EyeType::Normal,
EyeType::Angry,
EyeType::Pain,
EyeType::Happy,
EyeType::Empty,
EyeType::Surprise,
] {
let eyes_image = tee.get_eye(eye_type);
let filename = format!("eye_{:?}.png", eye_type).to_lowercase();
eyes_image
.save(output_dir.join(filename))
.expect("Failed to save eyes");
}
let files: Vec<_> = fs::read_dir(&output_dir)
.unwrap()
.map(|e| e.unwrap().file_name())
.collect();
assert_eq!(files.len(), 12);
println!("✅ Raw parts successfully saved to: {:?}", output_dir);
}
#[cfg(feature = "net")]
#[tokio::test]
async fn test_save_raw_parts_from_url() {
let tee = Tee::new_from_url_with_uv(
"https://teedata.net/databasev2/skins/glow_rainbow/glow_rainbow.png",
TEE_UV_LAYOUT,
)
.await
.unwrap();
let output_dir = setup_output_dir("net_raws");
tee.body
.value
.save(output_dir.join("body.png"))
.expect("Failed to save body");
tee.body
.shadow
.save(output_dir.join("body_shadow.png"))
.expect("Failed to save body shadow");
tee.feet
.value
.save(output_dir.join("feet.png"))
.expect("Failed to save feet");
tee.feet
.shadow
.save(output_dir.join("feet_shadow.png"))
.expect("Failed to save feet shadow");
tee.hand
.value
.save(output_dir.join("hand.png"))
.expect("Failed to save hand");
tee.hand
.shadow
.save(output_dir.join("hand_shadow.png"))
.expect("Failed to save hand shadow");
for eye_type in [
EyeType::Normal,
EyeType::Angry,
EyeType::Pain,
EyeType::Happy,
EyeType::Empty,
EyeType::Surprise,
] {
let eyes_image = tee.get_eye(eye_type);
let filename = format!("eye_{:?}.png", eye_type).to_lowercase();
eyes_image
.save(output_dir.join(filename))
.expect("Failed to save eyes");
}
let files: Vec<_> = fs::read_dir(&output_dir)
.unwrap()
.map(|e| e.unwrap().file_name())
.collect();
assert_eq!(files.len(), 12);
println!("✅ Raw parts successfully saved to: {:?}", output_dir);
}
#[test]
fn test_save_composed_image() {
let tee = get_tee();
let output_dir = setup_output_dir("composed");
for eye_type in [
EyeType::Normal,
EyeType::Angry,
EyeType::Pain,
EyeType::Happy,
EyeType::Empty,
EyeType::Surprise,
] {
let image_bytes = tee
.compose(TEE_SKIN_LAYOUT, eye_type.clone(), image::ImageFormat::WebP)
.expect("Failed to compose image");
let filename = format!("composed_{:?}.webp", eye_type).to_lowercase();
fs::write(output_dir.join(filename), image_bytes.as_bytes())
.expect("Failed to write composed image");
}
let files: Vec<_> = fs::read_dir(&output_dir)
.unwrap()
.map(|e| e.unwrap().file_name())
.collect();
assert_eq!(files.len(), 6);
println!("✅ Composed images successfully saved to: {:?}", output_dir);
}
#[test]
fn hsl_transpose() {
let output_dir = setup_output_dir("hsled");
let hsl = ddnet_color_to_hsl(1900500);
'_body: {
let mut tee = get_tee();
tee.apply_hsl_to_parts(hsl, &[TeePart::Body, TeePart::BodyShadow]);
fs::write(
output_dir.join("body_hsled").with_extension("png"),
tee.compose_png(TEE_SKIN_LAYOUT, EyeType::Happy).unwrap(),
)
.unwrap();
}
'_body_feet: {
let mut tee = get_tee();
tee.apply_hsl_to_parts(
hsl,
&[
TeePart::Body,
TeePart::BodyShadow,
TeePart::Feet,
TeePart::FeetShadow,
],
);
fs::write(
output_dir.join("body_feet_hsled").with_extension("png"),
tee.compose_png(TEE_SKIN_LAYOUT, EyeType::Happy).unwrap(),
)
.unwrap();
}
'_feet: {
let mut tee = get_tee();
tee.apply_hsl_to_parts(hsl, &[TeePart::Feet, TeePart::FeetShadow]);
fs::write(
output_dir.join("feet_hsled").with_extension("png"),
tee.compose_png(TEE_SKIN_LAYOUT, EyeType::Happy).unwrap(),
)
.unwrap();
}
'_full: {
let mut tee = get_tee();
tee.apply_hsl_to_all(hsl);
fs::write(
output_dir.join("full_hsled").with_extension("png"),
tee.compose_png(TEE_SKIN_LAYOUT, EyeType::Happy).unwrap(),
)
.unwrap();
}
}
}