Files
QRGen/core/tests/integration_test.rs
T

151 lines
4.2 KiB
Rust

use qr_core::qr::{QrCode, QrConfig, VersionMode};
use qr_core::version::EcLevel;
#[test]
fn test_encode_simple_text() {
let config = QrConfig::default();
let qr = QrCode::encode("HELLO WORLD", config).unwrap();
assert_eq!(qr.version.0, 1);
assert_eq!(qr.size(), 21);
}
#[test]
fn test_all_levels() {
for level in [EcLevel::L, EcLevel::M, EcLevel::Q, EcLevel::H] {
let config = QrConfig {
level,
..Default::default()
};
let qr = QrCode::encode("TEST", config).unwrap();
assert!(qr.size() >= 21);
assert!(qr.size() <= 177);
}
}
#[test]
fn test_chinese_text() {
let config = QrConfig::default();
let qr = QrCode::encode("你好世界", config).unwrap();
assert!(qr.size() >= 21);
}
#[test]
fn test_url_encoding() {
let config = QrConfig::default();
let qr = QrCode::encode("https://example.com/path?q=1", config).unwrap();
assert!(qr.size() >= 21);
}
#[test]
fn test_numeric_only_small_version() {
let mut config = QrConfig::default();
config.version = VersionMode::Fixed(1);
let qr = QrCode::encode("12345678901234567890", config).unwrap();
assert_eq!(qr.version.0, 1);
}
#[test]
fn test_fixed_version() {
let config = QrConfig {
version: VersionMode::Fixed(5),
..Default::default()
};
let qr = QrCode::encode("FIXED VERSION TEST", config).unwrap();
assert_eq!(qr.version.0, 5);
}
#[test]
fn test_empty_input_fails() {
let config = QrConfig::default();
let result = QrCode::encode("", config);
assert!(result.is_err());
}
#[test]
fn test_svg_output() {
let qr = QrCode::encode("TEST", QrConfig::default()).unwrap();
let svg = qr.to_svg();
assert!(svg.contains("<svg"));
assert!(svg.contains("</svg>"));
assert!(svg.contains("fill=\"black\""));
}
#[test]
fn test_ascii_output() {
let qr = QrCode::encode("TEST", QrConfig::default()).unwrap();
let ascii = qr.to_ascii(false);
assert!(!ascii.is_empty());
assert!(ascii.contains('\n'));
// 应该有暗模块
assert!(ascii.contains("██"));
}
#[test]
fn test_png_output() {
let qr = QrCode::encode("TEST", QrConfig::default()).unwrap();
let png = qr.to_png_bytes(4).unwrap();
assert!(!png.is_empty());
// PNG 文件应以 8 字节魔术签名开头
assert_eq!(&png[..8], &[137, 80, 78, 71, 13, 10, 26, 10]);
}
#[test]
fn test_modules_matrix() {
let qr = QrCode::encode("QR", QrConfig::default()).unwrap();
let modules = qr.modules();
assert_eq!(modules.len(), qr.size() as usize);
assert_eq!(modules[0].len(), qr.size() as usize);
// 至少有一些暗模块
let has_dark = modules.iter().any(|row| row.iter().any(|&m| m));
assert!(has_dark, "QR 码应该包含暗模块");
}
#[test]
fn test_margin_is_included_in_dimensions() {
let mut config = QrConfig::default();
config.margin = 2;
let qr = QrCode::encode("MARGIN TEST", config).unwrap();
// SVG 的总宽度应该包含 margin
let svg = qr.to_svg();
let matrix_size = qr.size() as u32;
let expected_total = matrix_size + 2 * 2u32;
assert!(svg.contains(&format!("width=\"{}\"", expected_total)));
// ASCII 输出行应该包含 margin 列
let ascii = qr.to_ascii(false);
let first_line = ascii.lines().next().unwrap();
let chars_per_module = 2; // ██ 是两个字符
assert_eq!(
first_line.chars().count(),
expected_total as usize * chars_per_module
);
}
#[test]
fn test_long_text_auto_version() {
// 长文本应该自动选择更高的版本
let long_text = "A".repeat(200);
let qr = QrCode::encode(&long_text, QrConfig::default()).unwrap();
// 至少要 Version 2 以上
assert!(qr.version.0 >= 2);
}
#[test]
fn test_special_chars() {
let config = QrConfig::default();
let qr = QrCode::encode("$%*+-./: SPACE", config).unwrap();
assert!(qr.size() >= 21);
}
#[test]
fn test_numeric_mode_efficiency() {
// 纯数字在 Version 1 L 级最多 41 位(约 7089 位数字)
let digits = "1".repeat(20);
let mut config = QrConfig::default();
config.version = VersionMode::Fixed(1);
config.level = EcLevel::L;
let qr = QrCode::encode(&digits, config).unwrap();
assert_eq!(qr.version.0, 1);
}