@@ -36,9 +36,31 @@ import java.util.concurrent.TimeUnit
3636import java.util.regex.Pattern
3737import java.net.URLEncoder
3838import java.nio.charset.StandardCharsets
39+ import kotlinx.serialization.json.Json
40+ import kotlinx.serialization.json.JsonArray
41+ import kotlinx.serialization.json.JsonObject
42+ import kotlinx.serialization.json.contentOrNull
43+ import kotlinx.serialization.json.jsonArray
44+ import kotlinx.serialization.json.jsonObject
45+ import kotlinx.serialization.json.jsonPrimitive
46+ import kotlinx.serialization.json.longOrNull
47+
48+ // --- Helpers to keep JSON access clean ---
49+ fun JsonObject.string (key : String ): String? =
50+ this [key]?.jsonPrimitive?.contentOrNull
51+
52+ fun JsonObject.long (key : String ): Long? =
53+ this [key]?.jsonPrimitive?.longOrNull
54+
55+ fun JsonObject.obj (key : String ): JsonObject ? =
56+ this [key]?.jsonObject
57+
58+ fun JsonObject.array (key : String ): JsonArray ? =
59+ this [key]?.jsonArray
60+
3961
4062fun String.encodeURL (): String =
41- URLEncoder .encode(this , StandardCharsets .UTF_8 .name())
63+ URLEncoder .encode(this , StandardCharsets .UTF_8 .name()).replace( " + " , " %20 " )
4264fun String.decodeURL (): String =
4365 URLDecoder .decode(this , StandardCharsets .UTF_8 .name())
4466
@@ -81,6 +103,7 @@ class AppFlowTest {
81103 private val testFileContent = " This is a file for integration testing."
82104
83105 companion object {
106+ private val json = Json { ignoreUnknownKeys = true }
84107
85108 private val client = OkHttpClient .Builder ()
86109 .connectTimeout(10 , TimeUnit .SECONDS )
@@ -109,7 +132,7 @@ class AppFlowTest {
109132// Try to delete every created file. Ignore failures but log them.
110133 createdFiles.forEach { filename ->
111134 try {
112- val encoded = Uri .encode(filename, null )
135+ val encoded = filename.encodeURL( )
113136
114137 val deleteReq1 = Request .Builder ()
115138 .url(" $serverUrl /$encoded " )
@@ -158,6 +181,16 @@ class AppFlowTest {
158181 return body == expectedContent
159182 }}
160183
184+ private fun getFilesJson (): JsonObject ? {
185+ val request = Request .Builder ().url(" $serverUrl /api/files" ).get().build()
186+
187+ client.newCall(request).execute().use { resp ->
188+ if (! resp.isSuccessful) return null ;
189+ val body = resp.body?.string() ? : return null
190+ return json.parseToJsonElement(body).jsonObject
191+ }}
192+
193+
161194 @Test
162195 fun testA_initialSetupAndFolderSelection () {
163196 // --- Step 1: Handle SetupActivity and Folder Picker ---
@@ -336,12 +369,35 @@ class AppFlowTest {
336369 }
337370 createdFiles.remove(testFileName) // dont try to delete this file after the tests
338371 }
339- fun testD_weirdFilename (){
372+
373+ @Test
374+ fun testD_FilenameEncoding (){
340375 assumeTrue(" Server URL not set – did testA fail?" , serverUrl != null )
341- val filename = """ weird %20!@+#{'$'}%^&*()[]{};,.txt""" .encodeURL()
342- val content = " |.|"
343- uploadFileHttp(filename, content)
344- Assert .assertTrue(checkFileContent(filename,content));
376+
377+ val filename1 = " a+b c.py"
378+ val filename2 = " a b+c.py"
379+ val content1 = " +"
380+ val content2 = " space"
381+ uploadFileHttp(filename1.encodeURL(), content1)
382+ uploadFileHttp(filename2.encodeURL(), content2)
383+
384+ Assert .assertTrue(checkFileContent(filename1.encodeURL(),content1));
385+ Assert .assertTrue(checkFileContent(filename2.encodeURL(),content2));
386+
387+ val jsonObj = getFilesJson()
388+ val files = jsonObj?.array(" files" ) ? : return
389+ val file1 = files.map { it.jsonObject }.firstOrNull { it.string(" name" ) == filename1 }
390+ val file2 = files.map { it.jsonObject }.firstOrNull { it.string(" name" ) == filename2 }
391+ Assert .assertNotNull(" File 'a+b c.py' not found in JSON" , file1)
392+ Assert .assertNotNull(" File 'a b+c.py' not found in JSON" , file2)
393+ Assert .assertTrue(
394+ " Wrong encoding for 'a+b c.py': ${file1?.string(" downloadUrl" )} " ,
395+ file1?.string(" downloadUrl" )?.endsWith(" a%2Bb%20c.py" ) == true
396+ )
397+ Assert .assertTrue(
398+ " Wrong encoding for 'a b+c.py': ${file2?.string(" downloadUrl" )} " ,
399+ file2?.string(" downloadUrl" )?.endsWith(" a%20b%2Bc.py" ) == true
400+ )
345401 }
346402
347403}
0 commit comments