@@ -2,17 +2,22 @@ package me.rosuh.easywatermark.render
22
33import me.rosuh.easywatermark.data.model.ImageFormat
44import me.rosuh.easywatermark.data.model.WatermarkMode
5+ import java.io.File
6+ import kotlin.io.path.createTempDirectory
57import kotlin.test.Test
68import kotlin.test.assertEquals
79import kotlin.test.assertFailsWith
810import kotlin.test.assertFalse
911import kotlin.test.assertTrue
1012
1113/* *
12- * S4d-139: unit tests for the pure [DesktopSaveDecision] seam extracted from
14+ * S4d-139 / S4d-222 : unit tests for the [DesktopSaveDecision] seam extracted from
1315 * `DesktopWatermarkFlow.runSaveFlow`. This is the runtime harness for the Desktop flow glue that
1416 * `:shared:desktopTest` can reach (the flow itself lives in `:desktopApp`, which has no test source set).
15- * Pure decisions only — no IO, no rendering.
17+ *
18+ * Most tests exercise pure decisions (no IO, no rendering). S4d-222 adds tests for
19+ * [resolveUniqueOutputFile], which performs filesystem existence checks only and does not create,
20+ * write, or delete files.
1621 */
1722class DesktopSaveDecisionTest {
1823
@@ -56,4 +61,52 @@ class DesktopSaveDecisionTest {
5661 assertTrue(DesktopSaveDecision .usesCallerInput(ByteArray (0 )), " even empty (non-null) bytes → caller input" )
5762 assertFalse(DesktopSaveDecision .usesCallerInput(null ), " null → fixture default" )
5863 }
64+
65+ @Test
66+ fun resolve_unique_uses_base_name_when_dir_is_empty () {
67+ val dir = createTempDirectory().toFile()
68+ val result = DesktopSaveDecision .resolveUniqueOutputFile(dir, ImageFormat .JPEG )
69+ assertEquals(File (dir, " watermarked.jpg" ), result)
70+ }
71+
72+ @Test
73+ fun resolve_unique_adds_suffix_when_base_exists () {
74+ val dir = createTempDirectory().toFile()
75+ File (dir, " watermarked.jpg" ).createNewFile()
76+ val result = DesktopSaveDecision .resolveUniqueOutputFile(dir, ImageFormat .JPEG )
77+ assertEquals(File (dir, " watermarked_1.jpg" ), result)
78+ }
79+
80+ @Test
81+ fun resolve_unique_finds_smallest_available_suffix_with_multiple_collisions () {
82+ val dir = createTempDirectory().toFile()
83+ File (dir, " watermarked.jpg" ).createNewFile()
84+ File (dir, " watermarked_1.jpg" ).createNewFile()
85+ val result = DesktopSaveDecision .resolveUniqueOutputFile(dir, ImageFormat .JPEG )
86+ assertEquals(File (dir, " watermarked_2.jpg" ), result)
87+ }
88+
89+ @Test
90+ fun resolve_unique_fills_numbering_gap_when_lower_suffix_is_free () {
91+ val dir = createTempDirectory().toFile()
92+ File (dir, " watermarked.jpg" ).createNewFile()
93+ File (dir, " watermarked_2.jpg" ).createNewFile()
94+ val result = DesktopSaveDecision .resolveUniqueOutputFile(dir, ImageFormat .JPEG )
95+ assertEquals(File (dir, " watermarked_1.jpg" ), result)
96+ }
97+
98+ @Test
99+ fun resolve_unique_does_not_create_the_returned_file () {
100+ val dir = createTempDirectory().toFile()
101+ val result = DesktopSaveDecision .resolveUniqueOutputFile(dir, ImageFormat .PNG )
102+ assertFalse(result.exists(), " helper must not create the file" )
103+ }
104+
105+ @Test
106+ fun resolve_unique_is_format_independent () {
107+ val dir = createTempDirectory().toFile()
108+ File (dir, " watermarked.jpg" ).createNewFile()
109+ val pngResult = DesktopSaveDecision .resolveUniqueOutputFile(dir, ImageFormat .PNG )
110+ assertEquals(File (dir, " watermarked.png" ), pngResult)
111+ }
59112}
0 commit comments