diff --git a/src/utils/__tests__/fetch.rs b/src/utils/__tests__/fetch.rs new file mode 100644 index 0000000..e677e1c --- /dev/null +++ b/src/utils/__tests__/fetch.rs @@ -0,0 +1,46 @@ +#[cfg(test)] +mod tests { + use crate::utils::fetch::fetch_and_cache; + + use std::{fs, path::PathBuf}; + + #[tokio::test] + async fn should_fetch_file() { + let host = "https://marshallku.com".to_string(); + let path = "/favicon.ico"; + let file_path = PathBuf::from("cdn_root/images/favicon.ico"); + + let result = fetch_and_cache(host, &file_path, path).await; + + assert!(result.is_ok()); + assert!(file_path.exists()); + + fs::remove_file(file_path).ok(); + } + + #[tokio::test] + async fn should_not_create_file_if_fetch_failed() { + let host = "https://marshallku.com".to_string(); + let path = "/must-be-404.ico"; + let file_path = PathBuf::from("cdn_root/images/must-be-404.ico"); + + let result = fetch_and_cache(host, &file_path, path).await; + + assert!(result.is_err()); + assert!(!file_path.exists()); + } + + #[tokio::test] + async fn should_create_parent_directory() { + let host = "https://marshallku.com".to_string(); + let path = "/logo/logo.svg"; + let file_path = PathBuf::from("cdn_root/images/logo/logo.svg"); + + let result = fetch_and_cache(host, &file_path, path).await; + + assert!(result.is_ok()); + assert!(file_path.exists()); + + fs::remove_file(file_path).ok(); + } +} diff --git a/src/tests/fixtures/image.jpg b/src/utils/__tests__/fixtures/image.jpg similarity index 100% rename from src/tests/fixtures/image.jpg rename to src/utils/__tests__/fixtures/image.jpg diff --git a/src/utils/__tests__/http.rs b/src/utils/__tests__/http.rs new file mode 100644 index 0000000..1c2cc01 --- /dev/null +++ b/src/utils/__tests__/http.rs @@ -0,0 +1,124 @@ +#[cfg(test)] +mod tests { + use http_body_util::BodyExt; + use reqwest::StatusCode; + use std::fs::File; + use std::io::prelude::*; + use std::path::PathBuf; + use tempfile::tempdir; + + use crate::utils::http::{get_cache_header, response_error, response_file}; + + #[tokio::test] + async fn test_response_file() { + let dir = tempdir().unwrap(); + let file_path = dir.path().join("test.txt"); + let mut file = File::create(file_path.clone()) + .and_then(|file| Ok(file)) + .unwrap(); + + file.write_all(b"test").unwrap(); + + let response = response_file(&file_path).await; + let body = response.collect().await.unwrap().to_bytes(); + + assert_eq!( + body, + "test".as_bytes(), + "File content does not match expected content" + ); + } + + #[tokio::test] + async fn test_response_file_with_empty_file() { + let dir = tempdir().unwrap(); + let file_path = dir.path().join("empty.txt"); + File::create(&file_path).unwrap(); + + let response = response_file(&file_path).await; + let body = response.collect().await.unwrap().to_bytes(); + + assert_eq!( + body, + "".as_bytes(), + "Response body is not empty for empty file" + ); + } + + #[tokio::test] + async fn test_response_file_with_large_file() { + let dir = tempdir().unwrap(); + let file_path = dir.path().join("large.txt"); + let mut file = File::create(&file_path).unwrap(); + + let large_content = vec![b'a'; 10_000]; + file.write_all(&large_content).unwrap(); + + let response = response_file(&file_path).await; + let body = response.collect().await.unwrap().to_bytes(); + + assert_eq!( + body, + large_content.as_slice(), + "Response body does not match large file content" + ); + } + + #[tokio::test] + async fn test_response_file_with_error() { + let file_path = PathBuf::from("non-existing-file.txt"); + let response = response_file(&file_path).await; + + assert_eq!( + response.status(), + StatusCode::INTERNAL_SERVER_ERROR, + "Expected internal server error for non-existing file" + ); + } + + #[test] + fn test_get_cache_header() { + let headers = get_cache_header(100); + let cache_control = headers.get("Cache-Control").unwrap().to_str().unwrap(); + + assert_eq!( + cache_control, "public, max-age=100", + "Cache-Control header does not match with positive cache age" + ); + } + + #[test] + fn test_get_cache_header_with_falsy_age() { + let headers = get_cache_header(0); + let cache_control = headers.get("Cache-Control").unwrap().to_str().unwrap(); + + assert_eq!( + cache_control, "no-cache", + "Cache-Control header does not match 'no-cache' for age 0" + ); + } + + #[test] + fn test_response_error() { + let response = response_error(StatusCode::NOT_FOUND); + let status = response.status(); + + assert_eq!( + status, + StatusCode::NOT_FOUND, + "Status code does not match NOT_FOUND" + ); + } + + #[test] + fn test_response_error_with_cache() { + let response = response_error(StatusCode::NOT_FOUND); + let headers = response.headers(); + let cache_control = headers.get("Cache-Control").unwrap().to_str().unwrap(); + + assert_eq!( + cache_control, "no-cache", + "Cache-Control header does not match 'no-cache' in error response" + ); + } +} diff --git a/src/utils/__tests__/img.rs b/src/utils/__tests__/img.rs new file mode 100644 index 0000000..82f69d4 --- /dev/null +++ b/src/utils/__tests__/img.rs @@ -0,0 +1,243 @@ +#[cfg(test)] +mod tests { + use crate::utils::{ + img::{save_image_to_webp, save_resized_image}, + path, + }; + + use image::{io::Reader as ImageReader, DynamicImage, RgbImage}; + use reqwest::StatusCode; + use std::{ + fs::{self, read, set_permissions}, + os::unix::fs::PermissionsExt, + }; + use tempfile::tempdir; + use webp::Decoder; + + const IMAGE_PATH: &str = "src/utils/__tests__/fixtures"; + const IMAGE_NAME: &str = "image"; + const IMAGE_EXT: &str = "jpg"; + + #[tokio::test] + async fn test_save_image_to_webp() { + const IMAGE_SIZE: u32 = 100; + + let dir = tempdir().unwrap(); + let output_path = dir.path().join("test_image.webp"); + + let image = DynamicImage::ImageRgb8(image::RgbImage::new(IMAGE_SIZE, IMAGE_SIZE)); + + match save_image_to_webp(&image, &output_path) { + Ok(_) => {} + Err(e) => { + panic!("Failed to save image as WebP: {}", e); + } + }; + + assert!( + output_path.exists(), + "Output file does not exist after saving image as WebP" + ); + + let webp_data = read(&output_path).unwrap(); + let decoded_webp = Decoder::new(&webp_data).decode().unwrap(); + + assert_eq!( + decoded_webp.width(), + IMAGE_SIZE, + "Decoded WebP width does not match original image width" + ); + assert_eq!( + decoded_webp.height(), + IMAGE_SIZE, + "Decoded WebP height does not match original image height" + ); + } + + #[tokio::test] + async fn test_save_image_to_webp_large_image() { + let image = DynamicImage::ImageRgb8(RgbImage::new(10000, 10000)); + let dir = tempdir().unwrap(); + let output_path = dir.path().join("large_image.webp"); + + match save_image_to_webp(&image, &output_path) { + Ok(_) => {} + Err(e) => { + panic!("Failed to save large image as WebP: {}", e); + } + }; + + assert!( + output_path.exists(), + "Output file does not exist after saving large image as WebP" + ); + } + + #[tokio::test] + async fn test_save_image_to_webp_read_only_file_system() { + let image = DynamicImage::ImageRgb8(RgbImage::new(100, 100)); + let dir = tempdir().unwrap(); + let output_path = dir.path().join("read_only_image.webp"); + + set_permissions(dir.path(), std::fs::Permissions::from_mode(0o444)).unwrap(); + + let result = save_image_to_webp(&image, &output_path); + + assert!( + result.is_err(), + "Expected error when saving to a read-only file system, but got success" + ); + assert!( + !output_path.exists(), + "Output file should not exist after attempting to save to a read-only file system" + ); + } + + #[tokio::test] + async fn test_save_image_to_webp_invalid_dimension() { + let dir = tempdir().unwrap(); + let output_path = dir.path().join("test_image.webp"); + + let invalid_cases = [ + DynamicImage::ImageLuma8(image::GrayImage::new(0, 0)), + DynamicImage::ImageLuma8(image::GrayImage::new(0, 100)), + DynamicImage::ImageLuma8(image::GrayImage::new(100, 0)), + ]; + + for invalid_image in invalid_cases.iter() { + let result = save_image_to_webp(&invalid_image, &output_path); + assert!( + result.is_err(), + "Expected error for invalid image dimensions, but got success" + ); + } + } + + #[tokio::test] + async fn test_save_resized_image() { + const TARGET_WIDTH: u32 = 100; + + let dir = tempdir().unwrap(); + + let image_path = format!("{}.{}", IMAGE_NAME, IMAGE_EXT); + let path = format!("{}.w{}.{}", IMAGE_NAME, TARGET_WIDTH, IMAGE_EXT); + + let file_path = dir.path().join(path.clone()); + let original_path = path::get_original_path(&path, true); + let original_file_path = dir.path().join(format!("image{}", original_path.clone())); + + match fs::copy( + format!("{}/{}", IMAGE_PATH, image_path.clone()), + file_path.clone(), + ) { + Ok(_) => {} + Err(_) => { + panic!("Failed to copy image file"); + } + }; + + let image = ImageReader::open(file_path.clone()) + .unwrap() + .decode() + .unwrap(); + + let response = + save_resized_image(image, Some(TARGET_WIDTH), &original_file_path, &file_path).await; + + assert_eq!( + response.status(), + StatusCode::OK, + "Expected OK status for resized image response, but got {}", + response.status() + ); + + let resized_image = ImageReader::open(file_path).unwrap().decode().unwrap(); + + assert_eq!( + resized_image.width(), + TARGET_WIDTH, + "Resized image width does not match target width" + ); + } + + #[tokio::test] + async fn test_save_resized_image_without_width() { + let dir = tempdir().unwrap(); + + let image_path = format!("{}.{}", IMAGE_NAME, IMAGE_EXT); + let file_path = dir.path().join(image_path.clone()); + + match fs::copy(format!("{}/{}", IMAGE_PATH, image_path), &file_path) { + Ok(_) => {} + Err(_) => { + panic!("Failed to copy image file"); + } + }; + + let image = ImageReader::open(&file_path).unwrap().decode().unwrap(); + + let response = save_resized_image(image, None, &file_path, &file_path).await; + + assert_eq!( + response.status(), + StatusCode::OK, + "Expected OK status for image response without width, but got {}", + response.status() + ); + } + + #[tokio::test] + async fn test_save_resized_image_with_larger_width() { + const ORIGINAL_WIDTH: u32 = 460; + const TARGET_WIDTH: u32 = 600; + + let dir = tempdir().unwrap(); + + let image_path = format!("{}.{}", IMAGE_NAME, IMAGE_EXT); + let path = format!("{}.w{}.{}", IMAGE_NAME, TARGET_WIDTH, IMAGE_EXT); + + let file_path = dir.path().join(path.clone()); + let original_path = path::get_original_path(&path, true); + let original_file_path = dir.path().join(format!("image{}", original_path.clone())); + + match fs::copy( + format!("{}/{}", IMAGE_PATH, image_path.clone()), + file_path.clone(), + ) { + Ok(_) => {} + Err(_) => { + panic!("Failed to copy image file"); + } + }; + + let image = ImageReader::open(file_path.clone()) + .unwrap() + .decode() + .unwrap(); + + let response = + save_resized_image(image, Some(TARGET_WIDTH), &original_file_path, &file_path).await; + + assert_eq!( + response.status(), + StatusCode::OK, + "Expected OK status for resized image response, but got {}", + response.status() + ); + + assert_eq!( + response.status(), + StatusCode::OK, + "Expected OK status for image response with larger target width, but got {}", + response.status() + ); + + let resized_image = ImageReader::open(&file_path).unwrap().decode().unwrap(); + + assert_eq!( + resized_image.width(), + ORIGINAL_WIDTH, + "Image width should not change when target width is larger than original" + ); + } +} diff --git a/src/utils/__tests__/mod.rs b/src/utils/__tests__/mod.rs new file mode 100644 index 0000000..3d1b496 --- /dev/null +++ b/src/utils/__tests__/mod.rs @@ -0,0 +1,4 @@ +mod fetch; +mod http; +mod img; +mod path; diff --git a/src/utils/__tests__/path.rs b/src/utils/__tests__/path.rs new file mode 100644 index 0000000..7b37640 --- /dev/null +++ b/src/utils/__tests__/path.rs @@ -0,0 +1,62 @@ +#[cfg(test)] +mod tests { + use crate::utils::path::{get_original_path, get_resize_width_from_path}; + + #[test] + fn test_get_resize_width_from_path() { + assert_eq!( + get_resize_width_from_path("/path/to/file.w100.jpg"), + Some(100) + ); + assert_eq!( + get_resize_width_from_path("/path/to/file.with.dot.w200.jpg"), + Some(200) + ); + assert_eq!( + get_resize_width_from_path("/path/to/file.with.dot.w200w.jpg"), + None + ); + assert_eq!( + get_resize_width_from_path("/path/to/file.with.dot.w300.jpg.webp"), + Some(300) + ); + assert_eq!( + get_resize_width_from_path("/path/to/file.with.dot.300.jpg.webp"), + None + ); + assert_eq!(get_resize_width_from_path("/path/to/file.jpg"), None); + assert_eq!( + get_resize_width_from_path("/path/to/file.with.dot.jpg"), + None + ); + } + + #[test] + fn test_get_original_path() { + let paths = vec![ + ["/path/to/file.w100.jpg", "/path/to/file.jpg"], + ["/path/to/webp.w100.jpg.webp", "/path/to/webp.jpg"], + [ + "/path/to/file.with.dot.w100.jpg", + "/path/to/file.with.dot.jpg", + ], + [ + "/path/to/webp.with.dot.w100.jpg.webp", + "/path/to/webp.with.dot.jpg", + ], + ["/path/to/file.jpg", "/path/to/file.jpg"], + ["/path/to/file.with.dot.jpg", "/path/to/file.with.dot.jpg"], + [ + "/path/to/webp.with.dot.jpg.webp", + "/path/to/webp.with.dot.jpg", + ], + ]; + + for (_, path) in paths.iter().enumerate() { + assert_eq!( + get_original_path(path[0], get_resize_width_from_path(path[0]).is_some()), + path[1] + ); + } + } +} diff --git a/src/utils/fetch.rs b/src/utils/fetch.rs index 68e8667..3d8dcda 100644 --- a/src/utils/fetch.rs +++ b/src/utils/fetch.rs @@ -23,49 +23,3 @@ pub async fn fetch_and_cache( fs::write(file_path, &response).ok(); Ok(()) } - -#[cfg(test)] -mod tests { - use super::*; - use std::fs; - - #[tokio::test] - async fn should_fetch_file() { - let host = "https://marshallku.com".to_string(); - let path = "/favicon.ico"; - let file_path = PathBuf::from("cdn_root/images/favicon.ico"); - - let result = fetch_and_cache(host, &file_path, path).await; - - assert!(result.is_ok()); - assert!(file_path.exists()); - - fs::remove_file(file_path).ok(); - } - - #[tokio::test] - async fn should_not_create_file_if_fetch_failed() { - let host = "https://marshallku.com".to_string(); - let path = "/must-be-404.ico"; - let file_path = PathBuf::from("cdn_root/images/must-be-404.ico"); - - let result = fetch_and_cache(host, &file_path, path).await; - - assert!(result.is_err()); - assert!(!file_path.exists()); - } - - #[tokio::test] - async fn should_create_parent_directory() { - let host = "https://marshallku.com".to_string(); - let path = "/logo/logo.svg"; - let file_path = PathBuf::from("cdn_root/images/logo/logo.svg"); - - let result = fetch_and_cache(host, &file_path, path).await; - - assert!(result.is_ok()); - assert!(file_path.exists()); - - fs::remove_file(file_path).ok(); - } -} diff --git a/src/utils/http.rs b/src/utils/http.rs index 5759551..42891e1 100644 --- a/src/utils/http.rs +++ b/src/utils/http.rs @@ -37,125 +37,3 @@ pub async fn response_file(file_path: &PathBuf) -> Response { (get_cache_header(YEAR_TO_SECONDS), body).into_response() } - -#[cfg(test)] -mod tests { - use super::*; - use http_body_util::BodyExt; - use std::fs::File; - use std::io::prelude::*; - use tempfile::tempdir; - - #[tokio::test] - async fn test_response_file() { - let dir = tempdir().unwrap(); - let file_path = dir.path().join("test.txt"); - let mut file = File::create(file_path.clone()) - .and_then(|file| Ok(file)) - .unwrap(); - - file.write_all(b"test").unwrap(); - - let response = response_file(&file_path).await; - let body = response.collect().await.unwrap().to_bytes(); - - assert_eq!( - body, - "test".as_bytes(), - "File content does not match expected content" - ); - } - - #[tokio::test] - async fn test_response_file_with_empty_file() { - let dir = tempdir().unwrap(); - let file_path = dir.path().join("empty.txt"); - File::create(&file_path).unwrap(); - - let response = response_file(&file_path).await; - let body = response.collect().await.unwrap().to_bytes(); - - assert_eq!( - body, - "".as_bytes(), - "Response body is not empty for empty file" - ); - } - - #[tokio::test] - async fn test_response_file_with_large_file() { - let dir = tempdir().unwrap(); - let file_path = dir.path().join("large.txt"); - let mut file = File::create(&file_path).unwrap(); - - let large_content = vec![b'a'; 10_000]; - file.write_all(&large_content).unwrap(); - - let response = response_file(&file_path).await; - let body = response.collect().await.unwrap().to_bytes(); - - assert_eq!( - body, - large_content.as_slice(), - "Response body does not match large file content" - ); - } - - #[tokio::test] - async fn test_response_file_with_error() { - let file_path = PathBuf::from("non-existing-file.txt"); - let response = response_file(&file_path).await; - - assert_eq!( - response.status(), - StatusCode::INTERNAL_SERVER_ERROR, - "Expected internal server error for non-existing file" - ); - } - - #[test] - fn test_get_cache_header() { - let headers = get_cache_header(100); - let cache_control = headers.get("Cache-Control").unwrap().to_str().unwrap(); - - assert_eq!( - cache_control, "public, max-age=100", - "Cache-Control header does not match with positive cache age" - ); - } - - #[test] - fn test_get_cache_header_with_falsy_age() { - let headers = get_cache_header(0); - let cache_control = headers.get("Cache-Control").unwrap().to_str().unwrap(); - - assert_eq!( - cache_control, "no-cache", - "Cache-Control header does not match 'no-cache' for age 0" - ); - } - - #[test] - fn test_response_error() { - let response = response_error(StatusCode::NOT_FOUND); - let status = response.status(); - - assert_eq!( - status, - StatusCode::NOT_FOUND, - "Status code does not match NOT_FOUND" - ); - } - - #[test] - fn test_response_error_with_cache() { - let response = response_error(StatusCode::NOT_FOUND); - let headers = response.headers(); - let cache_control = headers.get("Cache-Control").unwrap().to_str().unwrap(); - - assert_eq!( - cache_control, "no-cache", - "Cache-Control header does not match 'no-cache' in error response" - ); - } -} diff --git a/src/utils/img.rs b/src/utils/img.rs index d598fa7..adbf04b 100644 --- a/src/utils/img.rs +++ b/src/utils/img.rs @@ -45,244 +45,3 @@ pub async fn save_resized_image( Err(_) => response_error(StatusCode::INTERNAL_SERVER_ERROR), } } - -#[cfg(test)] -mod tests { - use crate::utils::path; - - use super::*; - use image::{io::Reader as ImageReader, DynamicImage, RgbImage}; - use std::{ - fs::{self, read, set_permissions}, - os::unix::fs::PermissionsExt, - }; - use tempfile::tempdir; - use webp::Decoder; - - const IMAGE_PATH: &str = "src/tests/fixtures"; - const IMAGE_NAME: &str = "image"; - const IMAGE_EXT: &str = "jpg"; - - #[tokio::test] - async fn test_save_image_to_webp() { - const IMAGE_SIZE: u32 = 100; - - let dir = tempdir().unwrap(); - let output_path = dir.path().join("test_image.webp"); - - let image = DynamicImage::ImageRgb8(image::RgbImage::new(IMAGE_SIZE, IMAGE_SIZE)); - - match save_image_to_webp(&image, &output_path) { - Ok(_) => {} - Err(e) => { - panic!("Failed to save image as WebP: {}", e); - } - }; - - assert!( - output_path.exists(), - "Output file does not exist after saving image as WebP" - ); - - let webp_data = read(&output_path).unwrap(); - let decoded_webp = Decoder::new(&webp_data).decode().unwrap(); - - assert_eq!( - decoded_webp.width(), - IMAGE_SIZE, - "Decoded WebP width does not match original image width" - ); - assert_eq!( - decoded_webp.height(), - IMAGE_SIZE, - "Decoded WebP height does not match original image height" - ); - } - - #[tokio::test] - async fn test_save_image_to_webp_large_image() { - let image = DynamicImage::ImageRgb8(RgbImage::new(10000, 10000)); - let dir = tempdir().unwrap(); - let output_path = dir.path().join("large_image.webp"); - - match save_image_to_webp(&image, &output_path) { - Ok(_) => {} - Err(e) => { - panic!("Failed to save large image as WebP: {}", e); - } - }; - - assert!( - output_path.exists(), - "Output file does not exist after saving large image as WebP" - ); - } - - #[tokio::test] - async fn test_save_image_to_webp_read_only_file_system() { - let image = DynamicImage::ImageRgb8(RgbImage::new(100, 100)); - let dir = tempdir().unwrap(); - let output_path = dir.path().join("read_only_image.webp"); - - set_permissions(dir.path(), std::fs::Permissions::from_mode(0o444)).unwrap(); - - let result = save_image_to_webp(&image, &output_path); - - assert!( - result.is_err(), - "Expected error when saving to a read-only file system, but got success" - ); - assert!( - !output_path.exists(), - "Output file should not exist after attempting to save to a read-only file system" - ); - } - - #[tokio::test] - async fn test_save_image_to_webp_invalid_dimension() { - let dir = tempdir().unwrap(); - let output_path = dir.path().join("test_image.webp"); - - let invalid_cases = [ - DynamicImage::ImageLuma8(image::GrayImage::new(0, 0)), - DynamicImage::ImageLuma8(image::GrayImage::new(0, 100)), - DynamicImage::ImageLuma8(image::GrayImage::new(100, 0)), - ]; - - for invalid_image in invalid_cases.iter() { - let result = save_image_to_webp(&invalid_image, &output_path); - assert!( - result.is_err(), - "Expected error for invalid image dimensions, but got success" - ); - } - } - - #[tokio::test] - async fn test_save_resized_image() { - const TARGET_WIDTH: u32 = 100; - - let dir = tempdir().unwrap(); - - let image_path = format!("{}.{}", IMAGE_NAME, IMAGE_EXT); - let path = format!("{}.w{}.{}", IMAGE_NAME, TARGET_WIDTH, IMAGE_EXT); - - let file_path = dir.path().join(path.clone()); - let original_path = path::get_original_path(&path, true); - let original_file_path = dir.path().join(format!("image{}", original_path.clone())); - - match fs::copy( - format!("{}/{}", IMAGE_PATH, image_path.clone()), - file_path.clone(), - ) { - Ok(_) => {} - Err(_) => { - panic!("Failed to copy image file"); - } - }; - - let image = ImageReader::open(file_path.clone()) - .unwrap() - .decode() - .unwrap(); - - let response = - save_resized_image(image, Some(TARGET_WIDTH), &original_file_path, &file_path).await; - - assert_eq!( - response.status(), - StatusCode::OK, - "Expected OK status for resized image response, but got {}", - response.status() - ); - - let resized_image = ImageReader::open(file_path).unwrap().decode().unwrap(); - - assert_eq!( - resized_image.width(), - TARGET_WIDTH, - "Resized image width does not match target width" - ); - } - - #[tokio::test] - async fn test_save_resized_image_without_width() { - let dir = tempdir().unwrap(); - - let image_path = format!("{}.{}", IMAGE_NAME, IMAGE_EXT); - let file_path = dir.path().join(image_path.clone()); - - match fs::copy(format!("{}/{}", IMAGE_PATH, image_path), &file_path) { - Ok(_) => {} - Err(_) => { - panic!("Failed to copy image file"); - } - }; - - let image = ImageReader::open(&file_path).unwrap().decode().unwrap(); - - let response = save_resized_image(image, None, &file_path, &file_path).await; - - assert_eq!( - response.status(), - StatusCode::OK, - "Expected OK status for image response without width, but got {}", - response.status() - ); - } - - #[tokio::test] - async fn test_save_resized_image_with_larger_width() { - const ORIGINAL_WIDTH: u32 = 460; - const TARGET_WIDTH: u32 = 600; - - let dir = tempdir().unwrap(); - - let image_path = format!("{}.{}", IMAGE_NAME, IMAGE_EXT); - let path = format!("{}.w{}.{}", IMAGE_NAME, TARGET_WIDTH, IMAGE_EXT); - - let file_path = dir.path().join(path.clone()); - let original_path = path::get_original_path(&path, true); - let original_file_path = dir.path().join(format!("image{}", original_path.clone())); - - match fs::copy( - format!("{}/{}", IMAGE_PATH, image_path.clone()), - file_path.clone(), - ) { - Ok(_) => {} - Err(_) => { - panic!("Failed to copy image file"); - } - }; - - let image = ImageReader::open(file_path.clone()) - .unwrap() - .decode() - .unwrap(); - - let response = - save_resized_image(image, Some(TARGET_WIDTH), &original_file_path, &file_path).await; - - assert_eq!( - response.status(), - StatusCode::OK, - "Expected OK status for resized image response, but got {}", - response.status() - ); - - assert_eq!( - response.status(), - StatusCode::OK, - "Expected OK status for image response with larger target width, but got {}", - response.status() - ); - - let resized_image = ImageReader::open(&file_path).unwrap().decode().unwrap(); - - assert_eq!( - resized_image.width(), - ORIGINAL_WIDTH, - "Image width should not change when target width is larger than original" - ); - } -} diff --git a/src/utils/mod.rs b/src/utils/mod.rs index b34d3f8..aea7e8d 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -1,3 +1,4 @@ +mod __tests__; pub mod fetch; pub mod http; pub mod img; diff --git a/src/utils/path.rs b/src/utils/path.rs index 7ac7bca..e890dd7 100644 --- a/src/utils/path.rs +++ b/src/utils/path.rs @@ -26,66 +26,3 @@ pub fn get_original_path(path: &str, has_resize: bool) -> String { format!("{}{}", dir, parts.join(".")) } - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_get_resize_width_from_path() { - assert_eq!( - get_resize_width_from_path("/path/to/file.w100.jpg"), - Some(100) - ); - assert_eq!( - get_resize_width_from_path("/path/to/file.with.dot.w200.jpg"), - Some(200) - ); - assert_eq!( - get_resize_width_from_path("/path/to/file.with.dot.w200w.jpg"), - None - ); - assert_eq!( - get_resize_width_from_path("/path/to/file.with.dot.w300.jpg.webp"), - Some(300) - ); - assert_eq!( - get_resize_width_from_path("/path/to/file.with.dot.300.jpg.webp"), - None - ); - assert_eq!(get_resize_width_from_path("/path/to/file.jpg"), None); - assert_eq!( - get_resize_width_from_path("/path/to/file.with.dot.jpg"), - None - ); - } - - #[test] - fn test_get_original_path() { - let paths = vec![ - ["/path/to/file.w100.jpg", "/path/to/file.jpg"], - ["/path/to/webp.w100.jpg.webp", "/path/to/webp.jpg"], - [ - "/path/to/file.with.dot.w100.jpg", - "/path/to/file.with.dot.jpg", - ], - [ - "/path/to/webp.with.dot.w100.jpg.webp", - "/path/to/webp.with.dot.jpg", - ], - ["/path/to/file.jpg", "/path/to/file.jpg"], - ["/path/to/file.with.dot.jpg", "/path/to/file.with.dot.jpg"], - [ - "/path/to/webp.with.dot.jpg.webp", - "/path/to/webp.with.dot.jpg", - ], - ]; - - for (_, path) in paths.iter().enumerate() { - assert_eq!( - get_original_path(path[0], get_resize_width_from_path(path[0]).is_some()), - path[1] - ); - } - } -}