BIT-405: AuthTokenInterceptor (#57)

This commit is contained in:
Ramsey Smith
2023-09-21 11:35:32 -06:00
committed by GitHub
parent dc793accd0
commit b8d19fcedf
5 changed files with 198 additions and 22 deletions

View File

@@ -0,0 +1,43 @@
package com.x8bit.bitwarden.data.platform.datasource.network.interceptor
import junit.framework.TestCase.assertEquals
import okhttp3.Request
import org.junit.Assert.assertThrows
import org.junit.Test
import java.io.IOException
import javax.inject.Singleton
@Singleton
class AuthTokenInterceptorTest {
private val interceptor: AuthTokenInterceptor = AuthTokenInterceptor()
private val mockAuthToken = "yourAuthToken"
private val request: Request = Request
.Builder()
.url("http://localhost")
.build()
@Test
fun `intercept should add the auth token when set`() {
interceptor.authToken = mockAuthToken
val response = interceptor.intercept(
chain = FakeInterceptorChain(request = request),
)
assertEquals(
"Bearer $mockAuthToken",
response.request.header("Authorization"),
)
}
@Test
fun `intercept should throw an exception when an auth token is missing`() {
val throwable = assertThrows(IOException::class.java) {
interceptor.intercept(
chain = FakeInterceptorChain(request = request),
)
}
assertEquals(
"Auth token is missing!",
throwable.cause?.message,
)
}
}

View File

@@ -0,0 +1,69 @@
package com.x8bit.bitwarden.data.platform.datasource.network.interceptor
import okhttp3.Call
import okhttp3.Connection
import okhttp3.Interceptor
import okhttp3.Protocol
import okhttp3.Request
import okhttp3.Response
import java.util.concurrent.TimeUnit
/**
* Helper class for implementing a [Interceptor.Chain] in a way that a [Request] passed in to
* [proceed] will be returned in a valid [Response] object that can be queried. This wrapping is
* performed by the [responseProvider].
*/
class FakeInterceptorChain(
private val request: Request,
private val responseProvider: (Request) -> Response = DEFAULT_RESPONSE_PROVIDER,
) : Interceptor.Chain {
override fun request(): Request = request
override fun proceed(request: Request): Response = responseProvider(request)
override fun connection(): Connection = notImplemented()
override fun call(): Call = notImplemented()
override fun connectTimeoutMillis(): Int = notImplemented()
override fun withConnectTimeout(
timeout: Int,
unit: TimeUnit,
): Interceptor.Chain = notImplemented()
override fun readTimeoutMillis(): Int = notImplemented()
override fun withReadTimeout(
timeout: Int,
unit: TimeUnit,
): Interceptor.Chain = notImplemented()
override fun writeTimeoutMillis(): Int = notImplemented()
override fun withWriteTimeout(
timeout: Int,
unit: TimeUnit,
): Interceptor.Chain = notImplemented()
private fun notImplemented(): Nothing {
throw NotImplementedError("This is not yet required by tests")
}
companion object {
/**
* A default response provider that provides a basic successful response. This is useful
* when the details of the response are not as important as retrieving the [Request] that
* was used to build it.
*/
val DEFAULT_RESPONSE_PROVIDER: (Request) -> Response = { request ->
Response
.Builder()
.code(200)
.message("OK")
.protocol(Protocol.HTTP_1_1)
.request(request)
.build()
}
}
}