Skip to content

Commit

Permalink
[ECO-5063] feat: integration tests checking agent params
Browse files Browse the repository at this point in the history
Added tests that checks channel params and rest request headers contains agent information
  • Loading branch information
ttypic committed Feb 26, 2025
1 parent 0731ea2 commit e419db6
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 0 deletions.
2 changes: 2 additions & 0 deletions chat-android/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ dependencies {
testImplementation(libs.mockk)
testImplementation(libs.coroutine.test)
testImplementation(libs.bundles.ktor.client)
testImplementation(libs.nanohttpd)
testImplementation(libs.turbine)
androidTestImplementation(libs.androidx.test.core)
androidTestImplementation(libs.androidx.test.runner)
androidTestImplementation(libs.androidx.junit)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.ably.chat.integration

import fi.iki.elonen.NanoHTTPD
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import java.io.ByteArrayInputStream

data class Request(
val path: String,
val params: Map<String, String> = emptyMap(),
val headers: Map<String, String> = emptyMap(),
)

data class Response(
val mimeType: String,
val data: ByteArray,
)

fun json(json: String): Response = Response(
mimeType = "application/json",
data = json.toByteArray(),
)

fun interface RequestHandler {
fun handle(request: Request): Response
}

class EmbeddedServer(port: Int, private val requestHandler: RequestHandler? = null) : NanoHTTPD(port) {
private val _servedRequests = MutableSharedFlow<Request>(
extraBufferCapacity = 1,
onBufferOverflow = BufferOverflow.DROP_OLDEST,
)

val servedRequests: Flow<Request> = _servedRequests

override fun serve(session: IHTTPSession): Response {
val request = Request(
path = session.uri,
params = session.parms,
headers = session.headers,
)
_servedRequests.tryEmit(request)
val response = requestHandler?.handle(request)
return response?.toNanoHttp() ?: newFixedLengthResponse("<!DOCTYPE html><title>404</title>")
}
}

private fun Response.toNanoHttp(): NanoHTTPD.Response = NanoHTTPD.newFixedLengthResponse(
NanoHTTPD.Response.Status.OK,
mimeType,
ByteArrayInputStream(data),
data.size.toLong(),
)
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package com.ably.chat.integration

import com.ably.chat.BuildConfig
import com.ably.chat.Message
import com.ably.chat.MessageEvent
import com.ably.chat.MessageMetadata
import com.ably.chat.RoomOptions
import com.ably.chat.RoomStatus
import com.ably.chat.assertWaiter
import io.ably.lib.realtime.channelOptions
import io.ably.lib.types.MessageAction
import java.util.UUID
import kotlinx.coroutines.CompletableDeferred
Expand Down Expand Up @@ -248,6 +250,17 @@ class MessagesIntegrationTest {
assertEquals(deletedMessage.action, receivedMsg2.action)
}

@Test
fun `messages channel should include agent channel param`() = runTest {
val chatClient = sandbox.createSandboxChatClient()
val roomId = UUID.randomUUID().toString()
val room = chatClient.rooms.get(roomId)
assertEquals(
"chat-kotlin/${BuildConfig.APP_VERSION}",
room.messages.channel.channelOptions?.params?.get("agent")
)
}

companion object {
private lateinit var sandbox: Sandbox

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package com.ably.chat.integration

import app.cash.turbine.test
import com.ably.chat.ChatClient
import com.ably.chat.assertWaiter
import fi.iki.elonen.NanoHTTPD
import io.ably.lib.realtime.AblyRealtime
import io.ably.lib.types.ClientOptions
import java.util.UUID
import kotlinx.coroutines.test.runTest
import org.junit.AfterClass
import org.junit.Assert
import org.junit.BeforeClass
import org.junit.Test

class RequestHeaderTest {

@Test
fun `should use additional agents in Realtime wrapper SDK client calls`() = runTest {
val ablyRealtime = createAblyRealtime()
val chatClient = ChatClient(ablyRealtime)
val roomId = UUID.randomUUID().toString()

server.servedRequests.test {
chatClient.rooms.get(roomId).messages.get()
val agents = awaitItem().headers["ably-agent"]?.split(" ") ?: setOf()
Assert.assertTrue(
agents.contains("chat-kotlin/${com.ably.chat.BuildConfig.APP_VERSION}")
)
}
}

companion object {

const val PORT = 27332
lateinit var server: EmbeddedServer

@JvmStatic
@BeforeClass
fun setUp() = runTest {
server = EmbeddedServer(PORT) {
when (it.path) {
"/time" -> json("[1739551931167]")
else -> json("[]")
}
}
server.start(NanoHTTPD.SOCKET_READ_TIMEOUT, true)
assertWaiter { server.wasStarted() }
}

@JvmStatic
@AfterClass
fun tearDown() {
server.stop()
}
}
}

private fun createAblyRealtime(): AblyRealtime {
val options = ClientOptions("xxxxx:yyyyyyy").apply {
port = RequestHeaderTest.PORT
useBinaryProtocol = false
realtimeHost = "localhost"
restHost = "localhost"
tls = false
autoConnect = false
}

return AblyRealtime(options)
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.ably.lib.realtime

import io.ably.lib.realtime.ChannelStateListener.ChannelStateChange
import io.ably.lib.types.ChannelOptions
import io.ably.lib.types.ClientOptions
import io.ably.lib.types.ErrorInfo

Expand Down Expand Up @@ -37,3 +38,6 @@ fun buildRealtimeConnection() = AblyRealtime(
autoConnect = false
},
).connection

val ChannelBase.channelOptions: ChannelOptions?
get() = options
5 changes: 5 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ mockk = "1.13.13"
coroutine = "1.9.0"
build-config = "5.5.1"
ktor = "3.0.1"
nanohttpd = "2.3.0"
turbine = "1.2.0"

[libraries]
junit = { group = "junit", name = "junit", version.ref = "junit" }
Expand Down Expand Up @@ -52,6 +54,9 @@ coroutine-test = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-t
ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" }
ktor-client-cio = { module = "io.ktor:ktor-client-cio", version.ref = "ktor" }

nanohttpd = { group = "org.nanohttpd", name = "nanohttpd", version.ref = "nanohttpd" }
turbine = { group = "app.cash.turbine", name = "turbine", version.ref = "turbine" }

[bundles]
ktor-client = ["ktor-client-core", "ktor-client-cio"]

Expand Down

0 comments on commit e419db6

Please sign in to comment.