use image::{ImageBuffer, Rgba, RgbaImage};
use qrc::payload::vcard::BusinessCard;
use qrc::{BlendOptions, EcLevel, ModuleShape, QRCode};
use std::collections::HashMap;
const URL: &str = "https://example.com/coverage";
#[test]
fn constructors_all_variants() {
let a = QRCode::new(URL.as_bytes().to_vec());
let b = QRCode::from_string(URL.to_string());
let c = QRCode::from_bytes(URL.as_bytes().to_vec());
assert_eq!(a.data, b.data);
assert_eq!(b.data, c.data);
assert_eq!(a.get_encoding_format(), "utf-8");
}
#[test]
#[should_panic(expected = "Failed to encode")]
fn to_qrcode_panics_on_oversized_data() {
let _ = QRCode::from_string("Z".repeat(8000)).to_qrcode();
}
#[test]
fn try_to_qrcode_reports_capacity_error() {
assert!(QRCode::from_string("Z".repeat(8000))
.try_to_qrcode()
.is_err());
assert!(QRCode::from_string(URL.to_string()).try_to_qrcode().is_ok());
}
#[test]
fn every_output_format() {
let qr = QRCode::from_string(URL.to_string());
assert_eq!(qr.to_png(64).dimensions(), (64, 64));
assert_eq!(qr.to_image(64).dimensions(), (64, 64));
assert!(!qr.to_png_bytes(64).unwrap().is_empty());
assert!(!qr.to_jpg(64).unwrap().is_empty());
assert!(!qr.to_jpg_with_quality(64, 50).unwrap().is_empty());
assert!(!qr.to_gif(64).unwrap().is_empty());
assert!(qr.to_svg(64).contains("<svg"));
assert!(qr.to_png_bytes(0).is_err());
assert!(qr.to_jpg(0).is_err());
assert!(qr.to_jpg_with_quality(0, 50).is_err());
}
#[test]
fn all_module_shapes_render() {
for shape in [
ModuleShape::Square,
ModuleShape::RoundedSquare,
ModuleShape::Circle,
ModuleShape::Diamond,
] {
let img = QRCode::from_string(URL.to_string())
.with_shape(shape)
.with_ec_level(EcLevel::H)
.to_png(120);
assert_eq!(img.dimensions(), (120, 120));
}
}
#[test]
fn default_instance() {
let d = QRCode::default();
assert!(d.data.is_empty());
assert_eq!(d.get_encoding_format(), "utf-8");
}
#[test]
fn svg_for_every_non_square_shape() {
for shape in [
ModuleShape::RoundedSquare,
ModuleShape::Circle,
ModuleShape::Diamond,
] {
let svg = QRCode::from_string(URL.to_string())
.with_shape(shape)
.to_svg(150);
assert!(svg.contains("<svg"));
}
}
#[test]
fn colorize_and_resize() {
let qr = QRCode::from_string(URL.to_string());
assert!(qr.colorize(Rgba([0, 102, 204, 255])).dimensions().0 > 0);
assert_eq!(qr.resize(80, 40).dimensions(), (80, 40));
let circ = QRCode::from_string(URL.to_string()).with_shape(ModuleShape::Circle);
assert!(circ.colorize(Rgba([10, 20, 30, 255])).dimensions().0 > 0);
assert_eq!(circ.resize(60, 60).dimensions(), (60, 60));
}
#[test]
fn overlay_watermark_and_art() {
let qr = QRCode::from_string(URL.to_string()).with_ec_level(EcLevel::H);
let logo: RgbaImage = ImageBuffer::from_pixel(24, 24, Rgba([220, 20, 60, 255]));
let mut logo = logo;
logo.put_pixel(0, 0, Rgba([0, 0, 0, 0]));
let overlaid = qr.overlay_image(&logo);
assert!(overlaid.width() > 24);
let big: RgbaImage = ImageBuffer::from_pixel(4000, 4000, Rgba([1, 2, 3, 255]));
let _ = qr.overlay_image(&big);
let mut canvas = qr.to_png(200);
QRCode::add_image_watermark(&mut canvas, &logo);
assert!(qr.to_control_image(256).width() >= 256);
let bg: RgbaImage = ImageBuffer::from_pixel(64, 64, Rgba([10, 80, 160, 255]));
assert!(qr.blend_image(&bg, &BlendOptions::default()).width() > 0);
}
#[test]
fn batch_combine_dynamic_multilanguage_compress() {
let codes = QRCode::batch_generate_qr_codes(vec!["a".into(), "b".into()]);
assert_eq!(codes.len(), 2);
assert!(QRCode::combine_qr_codes(&codes).is_ok());
assert!(QRCode::combine_qr_codes(&[]).is_err());
let dynamic = QRCode::create_dynamic("https://example.com/r/abc");
assert!(!dynamic.data.is_empty());
let mut map = HashMap::new();
map.insert("en".to_string(), "Hello".to_string());
map.insert("fr".to_string(), "Bonjour".to_string());
assert_eq!(QRCode::create_multilanguage(&map, "fr").data, b"Bonjour");
let _ = QRCode::create_multilanguage(&map, "de");
assert!(!QRCode::compress_data("a long string ".repeat(20).as_str()).is_empty());
}
#[test]
fn encoding_format_ok_and_error() {
let qr = QRCode::from_string(URL.to_string());
let updated = qr.set_encoding_format("utf-8").unwrap();
assert_eq!(updated.get_encoding_format(), "utf-8");
assert!(qr.set_encoding_format("latin-1").is_err());
}
#[test]
fn business_card_every_field_and_escaping() {
let card = BusinessCard::new("Jane Doe")
.name("Jane", "Doe")
.organization("Acme, Inc.") .title("CEO")
.phone("+1-555-0100")
.email("jane@acme.example")
.url("https://acme.example")
.address("1 Market St; Suite 2") .note("Line1\nLine2"); let v = card.to_vcard();
assert!(v.starts_with("BEGIN:VCARD"));
assert!(v.contains("FN:Jane Doe"));
assert!(v.contains("ORG:Acme\\, Inc."));
assert!(v.contains("ADR;TYPE=WORK:") || v.contains("1 Market St\\; Suite 2"));
assert!(v.contains("NOTE:Line1\\nLine2"));
assert!(v.trim_end().ends_with("END:VCARD"));
assert_eq!(card.to_string(), v);
assert!(BusinessCard::new("Solo").to_vcard().contains("FN:Solo"));
let escaped = BusinessCard::new("X").note("a\\b\rc").to_vcard();
assert!(escaped.contains("NOTE:a\\\\bc"));
}
#[cfg(feature = "wasm")]
#[test]
fn wasm_bindings_cover_every_branch() {
use qrc::wasm::WasmQRCode;
let mut qr = WasmQRCode::new(URL);
for lvl in ["L", "M", "Q", "H", "x"] {
qr.set_ec_level(lvl); }
for shape in ["square", "rounded", "circle", "diamond", "x"] {
qr.set_shape(shape); }
assert!(qr.to_svg(128).contains("<svg"));
assert!(!qr.to_png_bytes(128).is_empty());
assert!(!qr.to_jpg(128).is_empty());
assert!(qr.to_png_bytes(0).is_empty());
assert!(qr.to_jpg(0).is_empty());
}