package com.peachpasswords.ui.vault import com.peachpasswords.vault.VaultEntry import com.peachpasswords.vault.VaultSettings import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue import org.junit.Test import java.time.LocalDate class ExportRoundTripTest { // PeachScript packs the id as 16 raw UUID bytes (browser parity), so test // entries use real UUIDs as production entries do (addEntry assigns one). private fun entry() = VaultEntry( id = "11111111-2222-3333-4444-555555555555", title = "GitHub", type = "login", username = "june", password = "hunter2", url = "https://github.com", notes = "my note", totp = "JBSWY3DPEHPK3PXP", createdAt = 0, modifiedAt = 0, ) @Test fun csv_formula_injection_is_guarded() { assertEquals("'=1+1", CsvExport.encodeField("=1+1")) assertEquals("'@cmd", CsvExport.encodeField("@cmd")) assertEquals("'-2", CsvExport.encodeField("-2")) } @Test fun csv_quotes_fields_with_commas_and_quotes() { assertEquals("\"a,b\"", CsvExport.encodeField("a,b")) assertEquals("\"he\"\"llo\"", CsvExport.encodeField("he\"llo")) assertEquals("plain", CsvExport.encodeField("plain")) } @Test fun csv_has_header_and_row() { val csv = CsvExport.toCsv(listOf(entry())) val lines = csv.trim().split("\r\n") assertEquals("title,username,password,url,notes", lines[0]) assertTrue(lines[1].startsWith("GitHub,june,hunter2,")) } @Test fun peachscript_export_is_peachscript_text() { val out = PeachScriptExport.buildEncrypted(listOf(entry()), "backup-pass-12") assertTrue(PeachScriptImport.looksLikePeachScript(out)) assertTrue(PeachScriptImport.isEncrypted(out)) } @Test fun peachscript_encrypted_round_trips_with_correct_password() { val blob = PeachScriptExport.buildEncrypted(listOf(entry()), "backup-pass-12") assertTrue(PeachScriptImport.isEncrypted(blob)) val ok = PeachScriptImport.decryptAndParse(blob, "backup-pass-12") assertTrue(ok is PeachScriptImport.DecryptResult.Success) ok as PeachScriptImport.DecryptResult.Success assertEquals(1, ok.entries.size) assertEquals("hunter2", ok.entries[0].password) assertEquals("june", ok.entries[0].username) assertEquals("my note", ok.entries[0].notes) assertEquals("JBSWY3DPEHPK3PXP", ok.entries[0].totp) } @Test fun peachscript_encrypted_rejects_wrong_password() { val blob = PeachScriptExport.buildEncrypted(listOf(entry()), "backup-pass-12") val r = PeachScriptImport.decryptAndParse(blob, "wrong-password") assertTrue(r is PeachScriptImport.DecryptResult.WrongPassword) } @Test fun peachscript_round_trips_settings_and_license_metadata() { val settings = VaultSettings(accentColor = "sage", reduceMotion = true) val blob = PeachScriptExport.buildEncrypted( entries = listOf(entry()), backupPassword = "backup-pass-12", settings = settings, licenseKey = "PPK-test-license", licenseActivatedAt = 1_782_000_000_000L, ) val ok = PeachScriptImport.decryptAndParse(blob, "backup-pass-12") assertTrue(ok is PeachScriptImport.DecryptResult.Success) ok as PeachScriptImport.DecryptResult.Success assertEquals("sage", ok.settings.accentColor) assertTrue(ok.settings.reduceMotion) assertEquals("PPK-test-license", ok.licenseKey) assertEquals(1_782_000_000_000L, ok.licenseActivatedAt) } @Test fun export_file_names_match_browser_date_format() { val date = LocalDate.of(2026, 6, 26) assertEquals("peach-backup-2026-06-26.peach", exportFileName("peach-backup", "peach", date)) assertEquals("peach-export-2026-06-26.csv", exportFileName("peach-export", "csv", date)) } }