package de.softwareapp_hb.privateqrscanner.util import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse import org.junit.Assert.assertNotNull import org.junit.Assert.assertTrue import org.junit.Test class ScanContentParsersTest { @Test fun extractPhoneNumber_handlesTelUri() { val phone = ScanContentParsers.extractPhoneNumber("tel:+123456789?foo=bar") assertEquals("+123456789", phone) } @Test fun parseSms_handlesSmstoWithBody() { val (number, body) = ScanContentParsers.parseSms("SMSTO:+49123456:hello there") assertEquals("+49123456", number) assertEquals("hello there", body) } @Test fun extractEmail_handlesMailtoAndPlainText() { assertEquals("x@y.com", ScanContentParsers.extractEmail("mailto:x@y.com?subject=hi")) assertEquals("a.b+c@d.dev", ScanContentParsers.extractEmail("contact me at a.b+c@d.dev now")) } @Test fun parseContact_handlesVCard() { val raw = """ BEGIN:VCARD VERSION:3.0 FN:Jane Doe ORG:Acme Corp TITLE:Ops Lead TEL;TYPE=CELL:+1234567 EMAIL:jane@acme.com ADR:;;Main Street 1;Berlin;;;Germany NOTE:VIP END:VCARD """.trimIndent() val parsed = ScanContentParsers.parseContact(raw) assertNotNull(parsed) assertEquals("Jane Doe", parsed?.fullName) assertEquals("Acme Corp", parsed?.organization) assertEquals("Ops Lead", parsed?.title) assertEquals("+1234567", parsed?.phones?.firstOrNull()) assertEquals("jane@acme.com", parsed?.emails?.firstOrNull()) assertTrue(parsed?.address?.contains("Main Street 1") == true) assertEquals("VIP", parsed?.note) } @Test fun parseContact_handlesMeCard() { val raw = "MECARD:N:Doe,John;TEL:+49111;EMAIL:john@doe.dev;ADR:Street 9;NOTE:Friend;;" val parsed = ScanContentParsers.parseContact(raw) assertNotNull(parsed) assertEquals("John Doe", parsed?.fullName) assertEquals("+49111", parsed?.phones?.firstOrNull()) assertEquals("john@doe.dev", parsed?.emails?.firstOrNull()) assertEquals("Street 9", parsed?.address) assertEquals("Friend", parsed?.note) } @Test fun parseContact_handlesParameterizedVCardKeysAndNameOrder() { val raw = """ BEGIN:VCARD VERSION:3.0 N:Doe;John;;Dr.; ORG;CHARSET=UTF-8:ACME Inc TITLE;LANGUAGE=en:Engineering Manager TEL;TYPE=WORK,VOICE:+12025550123 EMAIL;TYPE=INTERNET:john.doe@acme.com END:VCARD """.trimIndent() val parsed = ScanContentParsers.parseContact(raw) assertNotNull(parsed) assertEquals("Dr. John Doe", parsed?.fullName) assertEquals("ACME Inc", parsed?.organization) assertEquals("Engineering Manager", parsed?.title) assertEquals("+12025550123", parsed?.phones?.firstOrNull()) assertEquals("john.doe@acme.com", parsed?.emails?.firstOrNull()) } @Test fun parseCalendarEvent_handlesVEvent() { val raw = """ BEGIN:VCALENDAR VERSION:2.0 BEGIN:VEVENT SUMMARY:Team Sync DESCRIPTION:Weekly planning LOCATION:Room A DTSTART:20270110T103000Z DTEND:20270110T110000Z END:VEVENT END:VCALENDAR """.trimIndent() val parsed = ScanContentParsers.parseCalendarEvent(raw) assertNotNull(parsed) assertEquals("Team Sync", parsed?.title) assertEquals("Weekly planning", parsed?.description) assertEquals("Room A", parsed?.location) assertNotNull(parsed?.startMillis) assertNotNull(parsed?.endMillis) assertFalse(parsed?.allDay ?: true) } @Test fun parseContact_handlesTecItVCardPayload() { val raw = """ BEGIN:VCARD VERSION:3.0 N:Doe;John;;; FN:John Doe ORG:TEC-IT TITLE:Position ADR;TYPE=WORK:;;203 New York Ave;New York;NY;11377;USA TEL;TYPE=WORK,VOICE:+43 7252 72720 TEL;TYPE=CELL:+43 660 1234567 TEL;TYPE=FAX:+43 7252 72720-77 EMAIL;TYPE=INTERNET:support@tec-it.com URL:http://www.tec-it.com LOGO;VALUE=URI:http://lh5.googleusercontent.com/-7RwzuzOVTsw/SypSXHmWr7I/AAAAAAAAAB0/5vE5NqugtLQ/TEC-IT_Banner_120x29.gif END:VCARD """.trimIndent() val parsed = ScanContentParsers.parseContact(raw) assertNotNull(parsed) assertEquals("John Doe", parsed?.fullName) assertEquals("TEC-IT", parsed?.organization) assertEquals("Position", parsed?.title) assertEquals("support@tec-it.com", parsed?.emails?.firstOrNull()) assertTrue(parsed?.phones?.contains("+43 7252 72720") == true) assertTrue(parsed?.phones?.contains("+43 660 1234567") == true) assertTrue(parsed?.phones?.contains("+43 7252 72720-77") == true) assertTrue(parsed?.address?.contains("203 New York Ave") == true) assertTrue(parsed?.address?.contains("New York") == true) assertTrue(parsed?.address?.contains("NY") == true) assertTrue(parsed?.address?.contains("11377") == true) assertTrue(parsed?.address?.contains("USA") == true) } @Test fun parseContact_handlesTecItMeCardPayload() { val raw = "MECARD:N:Doe,John;ORG:TEC-IT;TITLE:Position;ADR:203 New York Ave, New York, NY 11377, USA;TEL:+43 7252 72720;TEL:+43 660 1234567;TEL:+43 7252 72720-77;EMAIL:support@tec-it.com;URL:http://www.tec-it.com;NOTE:Logo http://lh5.googleusercontent.com/-7RwzuzOVTsw/SypSXHmWr7I/AAAAAAAAAB0/5vE5NqugtLQ/TEC-IT_Banner_120x29.gif;;" val parsed = ScanContentParsers.parseContact(raw) assertNotNull(parsed) assertEquals("John Doe", parsed?.fullName) assertEquals("TEC-IT", parsed?.organization) assertEquals("Position", parsed?.title) assertEquals("support@tec-it.com", parsed?.emails?.firstOrNull()) assertTrue(parsed?.phones?.contains("+43 7252 72720") == true) assertTrue(parsed?.phones?.contains("+43 660 1234567") == true) assertTrue(parsed?.phones?.contains("+43 7252 72720-77") == true) assertEquals("203 New York Ave, New York, NY 11377, USA", parsed?.address) } @Test fun parseWifi_handlesStandardPayload() { val raw = "WIFI:T:WPA;S:OfficeNet;P:superSecret;H:false;;" val parsed = ScanContentParsers.parseWifi(raw) assertNotNull(parsed) assertEquals("OfficeNet", parsed?.ssid) assertEquals("WPA", parsed?.security) assertEquals("superSecret", parsed?.password) assertEquals(false, parsed?.hidden) } @Test fun parseWifi_handlesEscapedCharactersAndHiddenFlag() { val raw = "WIFI:T:WPA2;S:Cafe\\;Guest\\,2nd\\:Floor;P:p\\\\ass\\;word;H:true;;" val parsed = ScanContentParsers.parseWifi(raw) assertNotNull(parsed) assertEquals("Cafe;Guest,2nd:Floor", parsed?.ssid) assertEquals("WPA2", parsed?.security) assertEquals("p\\ass;word", parsed?.password) assertEquals(true, parsed?.hidden) } }