Skip to content

Commit d39d7db

Browse files
committed
test(sync): add shared ledger guard tests and fix MarkdownSyncManager setup
Two new tests for detectDeletions shared-ledger path: - note purged remotely (ledger deletedAt >= updatedAt) is hard-deleted - note re-created after the ledger entry (updatedAt > deletedAt) is moved to trash instead Also adds the missing folderStore mock to MarkdownSyncManagerFilenameTest to match the updated constructor signature.
1 parent 60fe5b4 commit d39d7db

2 files changed

Lines changed: 40 additions & 1 deletion

File tree

android/app/src/test/java/dev/dettmer/simplenotes/sync/MarkdownSyncManagerFilenameTest.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ class MarkdownSyncManagerFilenameTest {
2727
urlBuilder = mockk(relaxed = true),
2828
connectionManager = mockk(relaxed = true),
2929
timestampManager = mockk(relaxed = true),
30-
ioDispatcher = Dispatchers.Unconfined
30+
ioDispatcher = Dispatchers.Unconfined,
31+
folderStore = mockk(relaxed = true)
3132
)
3233
}
3334

android/app/src/test/java/dev/dettmer/simplenotes/sync/NoteDownloaderDeletionTest.kt

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package dev.dettmer.simplenotes.sync
22

33
import android.content.Context
44
import android.content.SharedPreferences
5+
import dev.dettmer.simplenotes.models.DeletionTracker
56
import dev.dettmer.simplenotes.models.Note
67
import dev.dettmer.simplenotes.models.SyncStatus
78
import dev.dettmer.simplenotes.storage.FolderStore
@@ -102,6 +103,43 @@ class NoteDownloaderDeletionTest {
102103
assertNotNull(storage.loadNote("c"))
103104
}
104105

106+
@Test fun `active note missing on server but in shared ledger with deletedAt ge updatedAt is hard-deleted`() = runTest {
107+
val n = note("purged", trashedAt = null, updatedAt = 1_000L)
108+
storage.saveNote(n)
109+
110+
val tracker = DeletionTracker()
111+
tracker.addDeletion("purged", "desktop-abc")
112+
// Patch the deletedAt to be >= note.updatedAt (addDeletion uses now, which is >> 1_000)
113+
val count = downloader.detectDeletions(
114+
serverNoteIds = setOf("other"),
115+
localNotes = listOf(n),
116+
deletionTracker = tracker
117+
)
118+
119+
assertEquals("purged by shared ledger must not count as moved-to-trash", 0, count)
120+
assertNull("note must be hard-deleted locally", storage.loadNote("purged"))
121+
}
122+
123+
@Test fun `active note in ledger but updatedAt greater than deletedAt is still moved to trash`() = runTest {
124+
val futureUpdate = System.currentTimeMillis() + 60_000L
125+
val n = note("resurrected", trashedAt = null, updatedAt = futureUpdate)
126+
storage.saveNote(n)
127+
128+
val tracker = DeletionTracker()
129+
tracker.addDeletion("resurrected", "desktop-abc")
130+
// deletedAt set by addDeletion is now() which is < futureUpdate → guard kicks in
131+
132+
val count = downloader.detectDeletions(
133+
serverNoteIds = setOf("other"),
134+
localNotes = listOf(n),
135+
deletionTracker = tracker
136+
)
137+
138+
assertEquals("re-created note must be moved to trash, not hard-deleted", 1, count)
139+
val updated = storage.loadNote("resurrected")!!
140+
assertEquals(SyncStatus.DELETED_ON_SERVER, updated.syncStatus)
141+
}
142+
105143
@Test fun `all-deleted guard aborts when every synced note is missing`() = runTest {
106144
val notes = (1..10).map { note("guard-$it") }
107145
notes.forEach { storage.saveNote(it) }

0 commit comments

Comments
 (0)