test(android): cover camera clip upload URL JSON parsing

This commit is contained in:
Ayaan Zaidi
2026-02-27 08:52:34 +05:30
committed by Ayaan Zaidi
parent 67609cc16f
commit 120a7abbab
2 changed files with 69 additions and 4 deletions

View File

@@ -9,9 +9,25 @@ import ai.openclaw.android.gateway.GatewaySession
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.withContext
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.contentOrNull
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.RequestBody.Companion.asRequestBody
internal fun parseCameraClipUploadUrl(responseBody: String): String? {
if (responseBody.isBlank()) return null
val root =
try {
Json.parseToJsonElement(responseBody).asObjectOrNull()
} catch (_: Throwable) {
return null
} ?: return null
val urlPrimitive = root["url"] as? JsonPrimitive ?: return null
if (!urlPrimitive.isString) return null
return urlPrimitive.contentOrNull?.trim()?.ifEmpty { null }
}
class CameraHandler(
private val appContext: Context,
private val camera: CameraCaptureManager,
@@ -69,7 +85,7 @@ class CameraHandler(
clipLogFile?.appendText("[CLIP $ts] $msg\n")
android.util.Log.w("openclaw", "camera.clip: $msg")
}
val includeAudio = paramsJson?.contains("\"includeAudio\":true") != false
val includeAudio = parseIncludeAudio(paramsJson) ?: true
if (includeAudio) externalAudioCaptureActive.value = true
try {
clipLogFile?.writeText("") // clear
@@ -123,9 +139,7 @@ class CameraHandler(
clipLog("upload response: ${resp.code} $respBody")
filePayload.file.delete()
if (!resp.isSuccessful) throw Exception("upload failed: HTTP ${resp.code}")
// Parse URL from response
val urlMatch = Regex("\"url\":\"([^\"]+)\"").find(respBody)
urlMatch?.groupValues?.get(1) ?: throw Exception("no url in response: $respBody")
parseCameraClipUploadUrl(respBody) ?: throw Exception("no url in response: $respBody")
}
} catch (err: Throwable) {
clipLog("upload failed: ${err.message}, falling back to base64")
@@ -154,4 +168,24 @@ class CameraHandler(
if (includeAudio) externalAudioCaptureActive.value = false
}
}
private fun parseIncludeAudio(paramsJson: String?): Boolean? {
if (paramsJson.isNullOrBlank()) return null
val root =
try {
Json.parseToJsonElement(paramsJson).asObjectOrNull()
} catch (_: Throwable) {
null
} ?: return null
val value =
(root["includeAudio"] as? JsonPrimitive)
?.contentOrNull
?.trim()
?.lowercase()
return when (value) {
"true" -> true
"false" -> false
else -> null
}
}
}

View File

@@ -0,0 +1,31 @@
package ai.openclaw.android.node
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
import org.junit.Test
class CameraHandlerTest {
@Test
fun parseCameraClipUploadUrl_returnsUrlForValidPayload() {
val actual = parseCameraClipUploadUrl("""{"url":"https://example.com/upload/clip.mp4"}""")
assertEquals("https://example.com/upload/clip.mp4", actual)
}
@Test
fun parseCameraClipUploadUrl_trimsUrlWhitespace() {
val actual = parseCameraClipUploadUrl("""{"url":" https://example.com/u.mp4 "}""")
assertEquals("https://example.com/u.mp4", actual)
}
@Test
fun parseCameraClipUploadUrl_returnsNullForMalformedPayloads() {
assertNull(parseCameraClipUploadUrl(""))
assertNull(parseCameraClipUploadUrl("not-json"))
assertNull(parseCameraClipUploadUrl("""{"ok":true}"""))
assertNull(parseCameraClipUploadUrl("""{"url":123}"""))
assertNull(parseCameraClipUploadUrl("""{"url":" "}"""))
}
}