ExportRoundTripTest.kt

3.8 KB · raw

1package com.peachpasswords.ui.vault23import com.peachpasswords.vault.VaultEntry4import com.peachpasswords.vault.VaultSettings5import org.junit.Assert.assertEquals6import org.junit.Assert.assertTrue7import org.junit.Test8import java.time.LocalDate910class ExportRoundTripTest {1112    // PeachScript packs the id as 16 raw UUID bytes (browser parity), so test13    // entries use real UUIDs as production entries do (addEntry assigns one).14    private fun entry() = VaultEntry(15        id = "11111111-2222-3333-4444-555555555555", title = "GitHub", type = "login",16        username = "june", password = "hunter2", url = "https://github.com",17        notes = "my note", totp = "JBSWY3DPEHPK3PXP", createdAt = 0, modifiedAt = 0,18    )1920    @Test fun csv_formula_injection_is_guarded() {21        assertEquals("'=1+1", CsvExport.encodeField("=1+1"))22        assertEquals("'@cmd", CsvExport.encodeField("@cmd"))23        assertEquals("'-2", CsvExport.encodeField("-2"))24    }2526    @Test fun csv_quotes_fields_with_commas_and_quotes() {27        assertEquals("\"a,b\"", CsvExport.encodeField("a,b"))28        assertEquals("\"he\"\"llo\"", CsvExport.encodeField("he\"llo"))29        assertEquals("plain", CsvExport.encodeField("plain"))30    }3132    @Test fun csv_has_header_and_row() {33        val csv = CsvExport.toCsv(listOf(entry()))34        val lines = csv.trim().split("\r\n")35        assertEquals("title,username,password,url,notes", lines[0])36        assertTrue(lines[1].startsWith("GitHub,june,hunter2,"))37    }3839    @Test fun peachscript_export_is_peachscript_text() {40        val out = PeachScriptExport.buildEncrypted(listOf(entry()), "backup-pass-12")41        assertTrue(PeachScriptImport.looksLikePeachScript(out))42        assertTrue(PeachScriptImport.isEncrypted(out))43    }4445    @Test fun peachscript_encrypted_round_trips_with_correct_password() {46        val blob = PeachScriptExport.buildEncrypted(listOf(entry()), "backup-pass-12")47        assertTrue(PeachScriptImport.isEncrypted(blob))48        val ok = PeachScriptImport.decryptAndParse(blob, "backup-pass-12")49        assertTrue(ok is PeachScriptImport.DecryptResult.Success)50        ok as PeachScriptImport.DecryptResult.Success51        assertEquals(1, ok.entries.size)52        assertEquals("hunter2", ok.entries[0].password)53        assertEquals("june", ok.entries[0].username)54        assertEquals("my note", ok.entries[0].notes)55        assertEquals("JBSWY3DPEHPK3PXP", ok.entries[0].totp)56    }5758    @Test fun peachscript_encrypted_rejects_wrong_password() {59        val blob = PeachScriptExport.buildEncrypted(listOf(entry()), "backup-pass-12")60        val r = PeachScriptImport.decryptAndParse(blob, "wrong-password")61        assertTrue(r is PeachScriptImport.DecryptResult.WrongPassword)62    }6364    @Test fun peachscript_round_trips_settings_and_license_metadata() {65        val settings = VaultSettings(accentColor = "sage", reduceMotion = true)66        val blob = PeachScriptExport.buildEncrypted(67            entries = listOf(entry()),68            backupPassword = "backup-pass-12",69            settings = settings,70            licenseKey = "PPK-test-license",71            licenseActivatedAt = 1_782_000_000_000L,72        )7374        val ok = PeachScriptImport.decryptAndParse(blob, "backup-pass-12")7576        assertTrue(ok is PeachScriptImport.DecryptResult.Success)77        ok as PeachScriptImport.DecryptResult.Success78        assertEquals("sage", ok.settings.accentColor)79        assertTrue(ok.settings.reduceMotion)80        assertEquals("PPK-test-license", ok.licenseKey)81        assertEquals(1_782_000_000_000L, ok.licenseActivatedAt)82    }8384    @Test fun export_file_names_match_browser_date_format() {85        val date = LocalDate.of(2026, 6, 26)86        assertEquals("peach-backup-2026-06-26.peach", exportFileName("peach-backup", "peach", date))87        assertEquals("peach-export-2026-06-26.csv", exportFileName("peach-export", "csv", date))88    }89}