Skip to content

Commit 1480311

Browse files
committed
test: instrumented end-to-end coverage of export return values
Covers Gaps 5 + 6: - `exportConfig` returns a count reflecting non-internal preferences; internal keys ('version' etc.) are filtered out of both the JSON output and the count tally - `exportDictionaries` returns a populated DictionaryExportSummary whose customWordsCount/disabledWordsCount/languageCount tallies match the real on-disk per-language prefs Required because the existing BackupRestoreManagerTest.exportConfig tests assert only that count > 0 — they don't pin the internal-key filter. Without this guard a regression that re-introduced "version" into the exported preferences block would pass silently. — opus 4.7
1 parent d386a2d commit 1480311

1 file changed

Lines changed: 99 additions & 0 deletions

File tree

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package tribixbite.cleverkeys
2+
3+
import android.content.Context
4+
import androidx.test.core.app.ApplicationProvider
5+
import androidx.test.ext.junit.runners.AndroidJUnit4
6+
import org.junit.Assert.*
7+
import org.junit.Before
8+
import org.junit.Test
9+
import org.junit.runner.RunWith
10+
import java.io.File
11+
12+
/**
13+
* End-to-end coverage of the export side of `BackupRestoreManager`:
14+
* - `exportConfig` returns the count of non-internal preferences written
15+
* to the JSON file (Gap 5)
16+
* - `exportDictionaries` returns a populated [BackupRestoreManager.DictionaryExportSummary]
17+
* with real customWords/disabledWords/languageCount tallies (Gap 6)
18+
*
19+
* Both run against a real Context + real `SharedPreferences` instance + real
20+
* `file://` URI in `cacheDir`. This is the only path that exercises the
21+
* filtering of internal-only keys (e.g. "version") from the count.
22+
*/
23+
@RunWith(AndroidJUnit4::class)
24+
class BackupRestoreManagerExportEndToEndTest {
25+
26+
private lateinit var context: Context
27+
private lateinit var manager: BackupRestoreManager
28+
private lateinit var tmpDir: File
29+
30+
@Before
31+
fun setUp() {
32+
context = ApplicationProvider.getApplicationContext()
33+
manager = BackupRestoreManager(context)
34+
tmpDir = context.cacheDir.resolve("export-test").apply { deleteRecursively(); mkdirs() }
35+
}
36+
37+
@Test
38+
fun exportConfig_returnsCountReflectingNonInternalKeys() {
39+
val prefs = context.getSharedPreferences("export_test_prefs_1", Context.MODE_PRIVATE)
40+
prefs.edit().clear()
41+
.putInt("keyboard_height", 50)
42+
.putBoolean("swipe_typing_enabled", true)
43+
.putString("primary_language", "en")
44+
.putInt("version", 99) // internal — must NOT count toward returned tally
45+
.commit()
46+
val outFile = File(tmpDir, "out.json")
47+
48+
val count = manager.exportConfig(android.net.Uri.fromFile(outFile), prefs)
49+
50+
// The returned count is the number of entries in the `preferences` JSON
51+
// object — defaults + non-internal stored keys. The "version" key is
52+
// filtered out by `isInternalPreference`, so it must not contribute.
53+
assertTrue("Count must include user-set keys: was $count", count >= 3)
54+
// File should exist + contain expected user keys.
55+
assertTrue(outFile.exists())
56+
val text = outFile.readText()
57+
assertTrue(text.contains("keyboard_height"))
58+
assertTrue(text.contains("swipe_typing_enabled"))
59+
assertTrue(text.contains("primary_language"))
60+
// The internal "version" key must not appear inside the `preferences`
61+
// block. Metadata is allowed to have its own keys (export_date etc.).
62+
// Walk the JSON to confirm `preferences` does not include "version".
63+
val root = com.google.gson.JsonParser.parseString(text).asJsonObject
64+
val preferences = root.getAsJsonObject("preferences")
65+
assertFalse(
66+
"internal 'version' key must be filtered from preferences block",
67+
preferences.has("version")
68+
)
69+
}
70+
71+
@Test
72+
fun exportDictionaries_returnsSummaryWithRealCounts() {
73+
val prefs = DirectBootAwarePreferences.get_shared_preferences(context)
74+
// Ensure deterministic state: clear and seed.
75+
prefs.edit()
76+
.remove(LanguagePreferenceKeys.customWordsKey("en"))
77+
.remove(LanguagePreferenceKeys.disabledWordsKey("en"))
78+
.commit()
79+
prefs.edit()
80+
.putString(LanguagePreferenceKeys.customWordsKey("en"), """{"foo":1,"bar":2}""")
81+
.putStringSet(LanguagePreferenceKeys.disabledWordsKey("en"), setOf("baddie"))
82+
.commit()
83+
val outFile = File(tmpDir, "dict-out.json")
84+
85+
val summary = manager.exportDictionaries(android.net.Uri.fromFile(outFile))
86+
87+
assertEquals(2, summary.customWordsCount)
88+
assertEquals(1, summary.disabledWordsCount)
89+
assertTrue(
90+
"languageCount must include at least 'en'",
91+
summary.languageCount >= 1
92+
)
93+
// Cleanup so other tests aren't affected.
94+
prefs.edit()
95+
.remove(LanguagePreferenceKeys.customWordsKey("en"))
96+
.remove(LanguagePreferenceKeys.disabledWordsKey("en"))
97+
.commit()
98+
}
99+
}

0 commit comments

Comments
 (0)