use qrc::payload::emvco::{MerchantAccount, MerchantPayment};
use qrc::payload::mecard::MeCard;
use qrc::payload::wifi::{WifiNetwork, WifiSecurity};
use qrc::QRCode;
fn encodes(payload: &str) {
assert!(QRCode::from_string(payload.to_string())
.try_to_qrcode()
.is_ok());
}
#[test]
fn wifi_wpa_with_password_and_hidden() {
let wifi = WifiNetwork::new("Cafe; Guest")
.security(WifiSecurity::Wpa)
.password("p:a,s\"s\\word")
.hidden(true);
let s = wifi.to_qr_string();
assert_eq!(
s,
"WIFI:T:WPA;S:Cafe\\; Guest;P:p\\:a\\,s\\\"s\\\\word;H:true;;"
);
assert_eq!(wifi.to_string(), s);
encodes(&s);
}
#[test]
fn wifi_open_network_omits_password() {
let s = WifiNetwork::new("Free WiFi")
.security(WifiSecurity::None)
.password("ignored")
.to_qr_string();
assert_eq!(s, "WIFI:T:nopass;S:Free WiFi;;");
}
#[test]
fn wifi_wep_without_password_or_hidden() {
let s = WifiNetwork::new("Old")
.security(WifiSecurity::Wep)
.to_qr_string();
assert_eq!(s, "WIFI:T:WEP;S:Old;;");
assert_eq!(WifiSecurity::default(), WifiSecurity::Wpa);
assert_eq!(WifiNetwork::default(), WifiNetwork::new(""));
}
#[test]
fn mecard_full_and_minimal() {
let card = MeCard::new("Doe,Jane")
.reading("doe,jane")
.phone("+15550100")
.email("jane@acme.example")
.url("https://acme.example")
.address("1 Market St")
.birthday("19900101")
.note("hi; there");
let s = card.to_mecard();
assert!(s.starts_with("MECARD:N:Doe\\,Jane;"));
assert!(s.contains("TEL:+15550100;"));
assert!(s.contains("SOUND:doe\\,jane;"));
assert!(s.contains("NOTE:hi\\; there;"));
assert!(s.ends_with(";;"));
assert_eq!(card.to_string(), s);
encodes(&s);
let minimal = MeCard::new("Solo").to_mecard();
assert_eq!(minimal, "MECARD:N:Solo;;");
assert_eq!(MeCard::default(), MeCard::new(""));
}
#[test]
fn emvco_dynamic_payment_round_trips_and_has_valid_crc() {
let account = MerchantAccount::new(26, "com.example.pay").merchant_id("12345678");
let payment = MerchantPayment::new(account, "840", "US", "Acme Coffee", "Springfield")
.category_code("5814")
.amount("4.50");
let s = payment.to_emvco();
assert!(s.starts_with("000201")); assert!(s.contains("010212")); assert!(s.contains("5303840")); assert!(s.contains("54044.50")); assert!(s.contains("5802US")); assert_eq!(payment.to_string(), s);
encodes(&s);
let (body, crc) = s.split_at(s.len() - 4);
let mut c: u16 = 0xFFFF;
for &b in body.as_bytes() {
c ^= u16::from(b) << 8;
for _ in 0..8 {
c = if c & 0x8000 != 0 {
(c << 1) ^ 0x1021
} else {
c << 1
};
}
}
assert_eq!(crc, format!("{c:04X}"));
}
#[test]
fn emvco_static_payment_and_tag_clamping() {
let account = MerchantAccount::new(10, "com.example"); let s = MerchantPayment::new(account, "978", "FR", "Boulangerie", "Paris").to_emvco();
assert!(s.contains("010211")); assert!(!s.contains("5404"));
assert!(s.contains("26150011com.example"));
let high = MerchantAccount::new(99, "g");
let s = MerchantPayment::new(high, "840", "US", "M", "C").to_emvco();
assert!(s.contains("51050001g")); }