Merge pull request #5587 from element-hq/feature/bma/robustWellknown

Improve wellknown retrieval API
This commit is contained in:
Benoit Marty 2025-10-23 11:28:30 +02:00 committed by GitHub
commit 6326d1fc22
16 changed files with 202 additions and 104 deletions

@ -1 +1 @@
Subproject commit dac93821a6f9f9ad1494d3c69c115ef0696eb7ce Subproject commit 867d1118e157ba89a4f5462f8d9c13e206f10026

View file

@ -41,7 +41,7 @@ class DefaultAccountProviderAccessControl(
// Ensure that Element Pro is not required for this account provider // Ensure that Element Pro is not required for this account provider
val wellKnown = wellknownRetriever.getElementWellKnown( val wellKnown = wellknownRetriever.getElementWellKnown(
baseUrl = accountProviderUrl.ensureProtocol(), baseUrl = accountProviderUrl.ensureProtocol(),
) ).dataOrNull()
if (wellKnown?.enforceElementPro == true) { if (wellKnown?.enforceElementPro == true) {
throw AccountProviderAccessException.NeedElementProException( throw AccountProviderAccessException.NeedElementProException(
unauthorisedAccountProviderTitle = title, unauthorisedAccountProviderTitle = title,

View file

@ -46,7 +46,7 @@ class HomeserverResolver(
wellknownRetriever.getWellKnown(url) wellknownRetriever.getWellKnown(url)
} }
} }
val isValid = wellKnown?.isValid().orFalse() val isValid = wellKnown?.dataOrNull()?.isValid().orFalse()
if (isValid) { if (isValid) {
// Emit the list as soon as possible // Emit the list as soon as possible
currentList.add( currentList.add(

View file

@ -30,7 +30,7 @@ class DefaultWebClientUrlForAuthenticationRetriever(
Timber.w("Temporary account creation flow is only supported on matrix.org") Timber.w("Temporary account creation flow is only supported on matrix.org")
throw AccountCreationNotSupported() throw AccountCreationNotSupported()
} }
val wellknown = wellknownRetriever.getElementWellKnown(homeServerUrl) val wellknown = wellknownRetriever.getElementWellKnown(homeServerUrl).dataOrNull()
?: throw AccountCreationNotSupported() ?: throw AccountCreationNotSupported()
val registrationHelperUrl = wellknown.registrationHelperUrl val registrationHelperUrl = wellknown.registrationHelperUrl
return if (registrationHelperUrl != null) { return if (registrationHelperUrl != null) {

View file

@ -16,6 +16,7 @@ import io.element.android.libraries.matrix.test.AN_ACCOUNT_PROVIDER
import io.element.android.libraries.matrix.test.AN_ACCOUNT_PROVIDER_2 import io.element.android.libraries.matrix.test.AN_ACCOUNT_PROVIDER_2
import io.element.android.libraries.matrix.test.AN_ACCOUNT_PROVIDER_URL import io.element.android.libraries.matrix.test.AN_ACCOUNT_PROVIDER_URL
import io.element.android.libraries.wellknown.api.ElementWellKnown import io.element.android.libraries.wellknown.api.ElementWellKnown
import io.element.android.libraries.wellknown.api.WellknownRetrieverResult
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertThrows import org.junit.Assert.assertThrows
import org.junit.Test import org.junit.Test
@ -155,7 +156,13 @@ class DefaultAccountProviderAccessControlTest {
defaultHomeserverListResult = { allowedAccountProviders }, defaultHomeserverListResult = { allowedAccountProviders },
), ),
wellknownRetriever = FakeWellknownRetriever( wellknownRetriever = FakeWellknownRetriever(
getElementWellKnownResult = { elementWellKnown }, getElementWellKnownResult = {
if (elementWellKnown == null) {
WellknownRetrieverResult.NotFound
} else {
WellknownRetrieverResult.Success(elementWellKnown)
}
},
), ),
) )

View file

@ -23,6 +23,7 @@ import io.element.android.libraries.matrix.test.A_HOMESERVER_URL
import io.element.android.libraries.matrix.test.auth.FakeMatrixAuthenticationService import io.element.android.libraries.matrix.test.auth.FakeMatrixAuthenticationService
import io.element.android.libraries.wellknown.api.ElementWellKnown import io.element.android.libraries.wellknown.api.ElementWellKnown
import io.element.android.libraries.wellknown.api.WellknownRetriever import io.element.android.libraries.wellknown.api.WellknownRetriever
import io.element.android.libraries.wellknown.api.WellknownRetrieverResult
import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.WarmUpRule
import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.lambda.lambdaRecorder
import io.element.android.tests.testutils.lambda.value import io.element.android.tests.testutils.lambda.value
@ -114,9 +115,11 @@ class ChangeServerPresenterTest {
@Test @Test
fun `present - change server element pro required error`() = runTest { fun `present - change server element pro required error`() = runTest {
val getElementWellKnownResult = lambdaRecorder<String, ElementWellKnown> { val getElementWellKnownResult = lambdaRecorder<String, WellknownRetrieverResult<ElementWellKnown>> {
anElementWellKnown( WellknownRetrieverResult.Success(
enforceElementPro = true, anElementWellKnown(
enforceElementPro = true,
)
) )
} }
createPresenter( createPresenter(

View file

@ -18,6 +18,7 @@ import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.matrix.test.A_HOMESERVER_URL import io.element.android.libraries.matrix.test.A_HOMESERVER_URL
import io.element.android.libraries.wellknown.api.WellKnown import io.element.android.libraries.wellknown.api.WellKnown
import io.element.android.libraries.wellknown.api.WellKnownBaseConfig import io.element.android.libraries.wellknown.api.WellKnownBaseConfig
import io.element.android.libraries.wellknown.api.WellknownRetrieverResult
import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.WarmUpRule
import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.lambda.lambdaRecorder
import io.element.android.tests.testutils.lambda.value import io.element.android.tests.testutils.lambda.value
@ -94,12 +95,12 @@ class SearchAccountProviderPresenterTest {
@Test @Test
fun `present - enter text one result with wellknown`() = runTest { fun `present - enter text one result with wellknown`() = runTest {
val getWellKnownResult = lambdaRecorder<String, WellKnown> { val getWellKnownResult = lambdaRecorder<String, WellknownRetrieverResult<WellKnown>> {
when (it) { when (it) {
"https://test.org" -> error("not found") "https://test.org" -> WellknownRetrieverResult.NotFound
"https://test.com" -> error("not found") "https://test.com" -> WellknownRetrieverResult.NotFound
"https://test.io" -> aWellKnown() "https://test.io" -> WellknownRetrieverResult.Success(aWellKnown())
"https://test" -> error("not found") "https://test" -> WellknownRetrieverResult.NotFound
else -> error("should not happen") else -> error("should not happen")
} }
} }
@ -138,12 +139,12 @@ class SearchAccountProviderPresenterTest {
@Test @Test
fun `present - enter text two results with wellknown`() = runTest { fun `present - enter text two results with wellknown`() = runTest {
val getWellKnownResult = lambdaRecorder<String, WellKnown> { val getWellKnownResult = lambdaRecorder<String, WellknownRetrieverResult<WellKnown>> {
when (it) { when (it) {
"https://test.org" -> aWellKnown() "https://test.org" -> WellknownRetrieverResult.Success(aWellKnown())
"https://test.com" -> error("not found") "https://test.com" -> WellknownRetrieverResult.NotFound
"https://test.io" -> aWellKnown() "https://test.io" -> WellknownRetrieverResult.Success(aWellKnown())
"https://test" -> error("not found") "https://test" -> WellknownRetrieverResult.NotFound
else -> error("should not happen") else -> error("should not happen")
} }
} }

View file

@ -286,7 +286,7 @@ class RustMatrixClient(
override suspend fun getUrl(url: String): Result<ByteArray> = withContext(sessionDispatcher) { override suspend fun getUrl(url: String): Result<ByteArray> = withContext(sessionDispatcher) {
runCatchingExceptions { runCatchingExceptions {
innerClient.getUrl(url) innerClient.getUrl(url)
} }.mapFailure { it.mapClientException() }
} }
override suspend fun getRoom(roomId: RoomId): BaseRoom? = withContext(sessionDispatcher) { override suspend fun getRoom(roomId: RoomId): BaseRoom? = withContext(sessionDispatcher) {

View file

@ -8,6 +8,6 @@
package io.element.android.libraries.wellknown.api package io.element.android.libraries.wellknown.api
interface SessionWellknownRetriever { interface SessionWellknownRetriever {
suspend fun getWellKnown(): WellKnown? suspend fun getWellKnown(): WellknownRetrieverResult<WellKnown>
suspend fun getElementWellKnown(): ElementWellKnown? suspend fun getElementWellKnown(): WellknownRetrieverResult<ElementWellKnown>
} }

View file

@ -8,6 +8,6 @@
package io.element.android.libraries.wellknown.api package io.element.android.libraries.wellknown.api
interface WellknownRetriever { interface WellknownRetriever {
suspend fun getWellKnown(baseUrl: String): WellKnown? suspend fun getWellKnown(baseUrl: String): WellknownRetrieverResult<WellKnown>
suspend fun getElementWellKnown(baseUrl: String): ElementWellKnown? suspend fun getElementWellKnown(baseUrl: String): WellknownRetrieverResult<ElementWellKnown>
} }

View file

@ -0,0 +1,31 @@
/*
* Copyright 2025 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.libraries.wellknown.api
sealed interface WellknownRetrieverResult<out T> {
/**
* Well-known data has been successfully retrieved.
*/
data class Success<out T>(val data: T) : WellknownRetrieverResult<T>
/**
* Well-known data is not found (file does not exist server side, we got a 404).
*/
data object NotFound : WellknownRetrieverResult<Nothing>
/**
* Any other error.
*/
data class Error(val exception: Exception) : WellknownRetrieverResult<Nothing>
fun dataOrNull(): T? = when (this) {
is Success<T> -> data
is Error -> null
NotFound -> null
}
}

View file

@ -13,9 +13,11 @@ import io.element.android.libraries.androidutils.json.JsonProvider
import io.element.android.libraries.core.extensions.mapCatchingExceptions import io.element.android.libraries.core.extensions.mapCatchingExceptions
import io.element.android.libraries.di.SessionScope import io.element.android.libraries.di.SessionScope
import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.exception.ClientException
import io.element.android.libraries.wellknown.api.ElementWellKnown import io.element.android.libraries.wellknown.api.ElementWellKnown
import io.element.android.libraries.wellknown.api.SessionWellknownRetriever import io.element.android.libraries.wellknown.api.SessionWellknownRetriever
import io.element.android.libraries.wellknown.api.WellKnown import io.element.android.libraries.wellknown.api.WellKnown
import io.element.android.libraries.wellknown.api.WellknownRetrieverResult
import timber.log.Timber import timber.log.Timber
@ContributesBinding(SessionScope::class) @ContributesBinding(SessionScope::class)
@ -26,29 +28,40 @@ class DefaultSessionWellknownRetriever(
) : SessionWellknownRetriever { ) : SessionWellknownRetriever {
private val domain by lazy { matrixClient.userIdServerName() } private val domain by lazy { matrixClient.userIdServerName() }
override suspend fun getWellKnown(): WellKnown? { override suspend fun getWellKnown(): WellknownRetrieverResult<WellKnown> {
val url = "https://$domain/.well-known/matrix/client" val url = "https://$domain/.well-known/matrix/client"
return matrixClient return matrixClient
.getUrl(url) .getUrl(url)
.mapCatchingExceptions { .mapCatchingExceptions {
val data = String(it) val data = String(it)
json().decodeFromString(InternalWellKnown.serializer(), data) json().decodeFromString<InternalWellKnown>(data).map()
} }
.onFailure { Timber.e(it, "Failed to retrieve .well-known from $domain") } .toWellknownRetrieverResult()
.map { it.map() }
.getOrNull()
} }
override suspend fun getElementWellKnown(): ElementWellKnown? { override suspend fun getElementWellKnown(): WellknownRetrieverResult<ElementWellKnown> {
val url = "https://$domain/.well-known/element/element.json" val url = "https://$domain/.well-known/element/element.json"
return matrixClient return matrixClient
.getUrl(url) .getUrl(url)
.mapCatchingExceptions { .mapCatchingExceptions {
val data = String(it) val data = String(it)
json().decodeFromString(InternalElementWellKnown.serializer(), data) json().decodeFromString<InternalElementWellKnown>(data).map()
} }
.onFailure { Timber.e(it, "Failed to retrieve Element .well-known from $domain") } .toWellknownRetrieverResult()
.map { it.map() }
.getOrNull()
} }
private fun <T> Result<T>.toWellknownRetrieverResult(): WellknownRetrieverResult<T> = fold(
onSuccess = {
WellknownRetrieverResult.Success(it)
},
onFailure = {
Timber.e(it, "Failed to retrieve Element .well-known from $domain")
// This check on message value is not ideal but this is what we got from the SDK.
if ((it as? ClientException.Generic)?.message?.contains("404") == true) {
WellknownRetrieverResult.NotFound
} else {
WellknownRetrieverResult.Error(it as Exception)
}
}
)
} }

View file

@ -10,46 +10,72 @@ package io.element.android.libraries.wellknown.impl
import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.ContributesBinding import dev.zacsweers.metro.ContributesBinding
import dev.zacsweers.metro.Inject import dev.zacsweers.metro.Inject
import io.element.android.libraries.core.extensions.runCatchingExceptions
import io.element.android.libraries.core.uri.ensureProtocol import io.element.android.libraries.core.uri.ensureProtocol
import io.element.android.libraries.network.RetrofitFactory import io.element.android.libraries.network.RetrofitFactory
import io.element.android.libraries.wellknown.api.ElementWellKnown import io.element.android.libraries.wellknown.api.ElementWellKnown
import io.element.android.libraries.wellknown.api.WellKnown import io.element.android.libraries.wellknown.api.WellKnown
import io.element.android.libraries.wellknown.api.WellknownRetriever import io.element.android.libraries.wellknown.api.WellknownRetriever
import io.element.android.libraries.wellknown.api.WellknownRetrieverResult
import retrofit2.HttpException
import timber.log.Timber import timber.log.Timber
import java.net.HttpURLConnection
@ContributesBinding(AppScope::class) @ContributesBinding(AppScope::class)
@Inject @Inject
class DefaultWellknownRetriever( class DefaultWellknownRetriever(
private val retrofitFactory: RetrofitFactory, private val retrofitFactory: RetrofitFactory,
) : WellknownRetriever { ) : WellknownRetriever {
override suspend fun getWellKnown(baseUrl: String): WellKnown? { override suspend fun getWellKnown(baseUrl: String): WellknownRetrieverResult<WellKnown> {
val wellknownApi = buildWellknownApi(baseUrl) ?: return null return buildWellknownApi(baseUrl)
return try { .map { wellknownApi ->
wellknownApi.getWellKnown().map() try {
} catch (e: Exception) { val result = wellknownApi.getWellKnown().map()
Timber.e(e, "Failed to retrieve well-known data for $baseUrl") WellknownRetrieverResult.Success(result)
null } catch (e: Exception) {
} Timber.e(e, "Failed to retrieve well-known data for $baseUrl")
if ((e as? HttpException)?.code() == HttpURLConnection.HTTP_NOT_FOUND) {
WellknownRetrieverResult.NotFound
} else {
WellknownRetrieverResult.Error(e)
}
}
}
.fold(
onSuccess = { it },
onFailure = { WellknownRetrieverResult.Error(it as Exception) }
)
} }
override suspend fun getElementWellKnown(baseUrl: String): ElementWellKnown? { override suspend fun getElementWellKnown(baseUrl: String): WellknownRetrieverResult<ElementWellKnown> {
val wellknownApi = buildWellknownApi(baseUrl) ?: return null return buildWellknownApi(baseUrl)
return try { .map { wellknownApi ->
wellknownApi.getElementWellKnown().map() try {
} catch (e: Exception) { val result = wellknownApi.getElementWellKnown().map()
Timber.e(e, "Failed to retrieve Element well-known data for $baseUrl") WellknownRetrieverResult.Success(result)
null } catch (e: Exception) {
} // Is it a 404?
Timber.e(e, "Failed to retrieve Element well-known data for $baseUrl")
if ((e as? HttpException)?.code() == HttpURLConnection.HTTP_NOT_FOUND) {
WellknownRetrieverResult.NotFound
} else {
WellknownRetrieverResult.Error(e)
}
}
}
.fold(
onSuccess = { it },
onFailure = { WellknownRetrieverResult.Error(it as Exception) }
)
} }
private fun buildWellknownApi(accountProviderUrl: String): WellknownAPI? { private fun buildWellknownApi(accountProviderUrl: String): Result<WellknownAPI> {
return try { return runCatchingExceptions {
retrofitFactory.create(accountProviderUrl.ensureProtocol()) retrofitFactory.create(accountProviderUrl.ensureProtocol())
.create(WellknownAPI::class.java) .create(WellknownAPI::class.java)
} catch (e: Exception) { }.onFailure { e ->
// If the base URL is not valid, we cannot retrieve the well-known data // If the base URL is not valid, we cannot retrieve the well-known data
Timber.e(e, "Failed to create Retrofit instance for $accountProviderUrl") Timber.e(e, "Failed to create Retrofit instance for $accountProviderUrl")
null
} }
} }
} }

View file

@ -14,6 +14,7 @@ import io.element.android.libraries.matrix.test.FakeMatrixClient
import io.element.android.libraries.wellknown.api.ElementWellKnown import io.element.android.libraries.wellknown.api.ElementWellKnown
import io.element.android.libraries.wellknown.api.WellKnown import io.element.android.libraries.wellknown.api.WellKnown
import io.element.android.libraries.wellknown.api.WellKnownBaseConfig import io.element.android.libraries.wellknown.api.WellKnownBaseConfig
import io.element.android.libraries.wellknown.api.WellknownRetrieverResult
import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.lambda.lambdaRecorder
import io.element.android.tests.testutils.lambda.value import io.element.android.tests.testutils.lambda.value
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
@ -29,9 +30,11 @@ class DefaultSessionWellknownRetrieverTest {
getUrlLambda = getUrlLambda, getUrlLambda = getUrlLambda,
) )
assertThat(sut.getWellKnown()).isEqualTo( assertThat(sut.getWellKnown()).isEqualTo(
WellKnown( WellknownRetrieverResult.Success(
homeServer = null, WellKnown(
identityServer = null, homeServer = null,
identityServer = null,
)
) )
) )
getUrlLambda.assertions().isCalledOnce() getUrlLambda.assertions().isCalledOnce()
@ -55,13 +58,15 @@ class DefaultSessionWellknownRetrieverTest {
} }
) )
assertThat(sut.getWellKnown()).isEqualTo( assertThat(sut.getWellKnown()).isEqualTo(
WellKnown( WellknownRetrieverResult.Success(
homeServer = WellKnownBaseConfig( WellKnown(
baseURL = "https://example.org", homeServer = WellKnownBaseConfig(
), baseURL = "https://example.org",
identityServer = WellKnownBaseConfig( ),
baseURL = "https://identity.example.org", identityServer = WellKnownBaseConfig(
), baseURL = "https://identity.example.org",
),
)
) )
) )
} }
@ -81,13 +86,15 @@ class DefaultSessionWellknownRetrieverTest {
} }
) )
assertThat(sut.getWellKnown()).isEqualTo( assertThat(sut.getWellKnown()).isEqualTo(
WellKnown( WellknownRetrieverResult.Success(
homeServer = WellKnownBaseConfig( WellKnown(
baseURL = "https://example.org", homeServer = WellKnownBaseConfig(
), baseURL = "https://example.org",
identityServer = WellKnownBaseConfig( ),
baseURL = null, identityServer = WellKnownBaseConfig(
), baseURL = null,
),
)
) )
) )
} }
@ -110,13 +117,15 @@ class DefaultSessionWellknownRetrieverTest {
}, },
) )
assertThat(sut.getWellKnown()).isEqualTo( assertThat(sut.getWellKnown()).isEqualTo(
WellKnown( WellknownRetrieverResult.Success(
homeServer = WellKnownBaseConfig( WellKnown(
baseURL = "https://example.org", homeServer = WellKnownBaseConfig(
), baseURL = "https://example.org",
identityServer = WellKnownBaseConfig( ),
baseURL = "https://identity.example.org", identityServer = WellKnownBaseConfig(
), baseURL = "https://identity.example.org",
),
)
) )
) )
} }
@ -135,7 +144,7 @@ class DefaultSessionWellknownRetrieverTest {
) )
} }
) )
assertThat(sut.getWellKnown()).isNull() assertThat(sut.getWellKnown()).isInstanceOf(WellknownRetrieverResult.Error::class.java)
} }
@Test @Test
@ -145,7 +154,7 @@ class DefaultSessionWellknownRetrieverTest {
Result.failure(AN_EXCEPTION) Result.failure(AN_EXCEPTION)
} }
) )
assertThat(sut.getWellKnown()).isNull() assertThat(sut.getWellKnown()).isInstanceOf(WellknownRetrieverResult.Error::class.java)
} }
@Test @Test
@ -157,11 +166,13 @@ class DefaultSessionWellknownRetrieverTest {
getUrlLambda = getUrlLambda, getUrlLambda = getUrlLambda,
) )
assertThat(sut.getElementWellKnown()).isEqualTo( assertThat(sut.getElementWellKnown()).isEqualTo(
ElementWellKnown( WellknownRetrieverResult.Success(
registrationHelperUrl = null, ElementWellKnown(
enforceElementPro = null, registrationHelperUrl = null,
rageshakeUrl = null, enforceElementPro = null,
brandColor = null, rageshakeUrl = null,
brandColor = null,
)
) )
) )
getUrlLambda.assertions().isCalledOnce() getUrlLambda.assertions().isCalledOnce()
@ -183,11 +194,13 @@ class DefaultSessionWellknownRetrieverTest {
} }
) )
assertThat(sut.getElementWellKnown()).isEqualTo( assertThat(sut.getElementWellKnown()).isEqualTo(
ElementWellKnown( WellknownRetrieverResult.Success(
registrationHelperUrl = "a_registration_url", ElementWellKnown(
enforceElementPro = true, registrationHelperUrl = "a_registration_url",
rageshakeUrl = "a_rageshake_url", enforceElementPro = true,
brandColor = "#FF0000", rageshakeUrl = "a_rageshake_url",
brandColor = "#FF0000",
)
) )
) )
} }
@ -207,11 +220,13 @@ class DefaultSessionWellknownRetrieverTest {
}, },
) )
assertThat(sut.getElementWellKnown()).isEqualTo( assertThat(sut.getElementWellKnown()).isEqualTo(
ElementWellKnown( WellknownRetrieverResult.Success(
registrationHelperUrl = "a_registration_url", ElementWellKnown(
enforceElementPro = true, registrationHelperUrl = "a_registration_url",
rageshakeUrl = "a_rageshake_url", enforceElementPro = true,
brandColor = null, rageshakeUrl = "a_rageshake_url",
brandColor = null,
)
) )
) )
} }
@ -228,7 +243,7 @@ class DefaultSessionWellknownRetrieverTest {
) )
} }
) )
assertThat(sut.getElementWellKnown()).isNull() assertThat(sut.getElementWellKnown()).isInstanceOf(WellknownRetrieverResult.Error::class.java)
} }
@Test @Test
@ -238,7 +253,7 @@ class DefaultSessionWellknownRetrieverTest {
Result.failure(AN_EXCEPTION) Result.failure(AN_EXCEPTION)
} }
) )
assertThat(sut.getElementWellKnown()).isNull() assertThat(sut.getElementWellKnown()).isInstanceOf(WellknownRetrieverResult.Error::class.java)
} }
private fun createDefaultSessionWellknownRetriever( private fun createDefaultSessionWellknownRetriever(

View file

@ -10,17 +10,18 @@ package io.element.android.features.wellknown.test
import io.element.android.libraries.wellknown.api.ElementWellKnown import io.element.android.libraries.wellknown.api.ElementWellKnown
import io.element.android.libraries.wellknown.api.SessionWellknownRetriever import io.element.android.libraries.wellknown.api.SessionWellknownRetriever
import io.element.android.libraries.wellknown.api.WellKnown import io.element.android.libraries.wellknown.api.WellKnown
import io.element.android.libraries.wellknown.api.WellknownRetrieverResult
import io.element.android.tests.testutils.simulateLongTask import io.element.android.tests.testutils.simulateLongTask
class FakeSessionWellknownRetriever( class FakeSessionWellknownRetriever(
private val getWellKnownResult: () -> WellKnown? = { null }, private val getWellKnownResult: () -> WellknownRetrieverResult<WellKnown> = { WellknownRetrieverResult.NotFound },
private val getElementWellKnownResult: () -> ElementWellKnown? = { null }, private val getElementWellKnownResult: () -> WellknownRetrieverResult<ElementWellKnown> = { WellknownRetrieverResult.NotFound },
) : SessionWellknownRetriever { ) : SessionWellknownRetriever {
override suspend fun getWellKnown(): WellKnown? = simulateLongTask { override suspend fun getWellKnown(): WellknownRetrieverResult<WellKnown> = simulateLongTask {
getWellKnownResult() getWellKnownResult()
} }
override suspend fun getElementWellKnown(): ElementWellKnown? = simulateLongTask { override suspend fun getElementWellKnown(): WellknownRetrieverResult<ElementWellKnown> = simulateLongTask {
getElementWellKnownResult() getElementWellKnownResult()
} }
} }

View file

@ -10,17 +10,18 @@ package io.element.android.features.wellknown.test
import io.element.android.libraries.wellknown.api.ElementWellKnown import io.element.android.libraries.wellknown.api.ElementWellKnown
import io.element.android.libraries.wellknown.api.WellKnown import io.element.android.libraries.wellknown.api.WellKnown
import io.element.android.libraries.wellknown.api.WellknownRetriever import io.element.android.libraries.wellknown.api.WellknownRetriever
import io.element.android.libraries.wellknown.api.WellknownRetrieverResult
import io.element.android.tests.testutils.simulateLongTask import io.element.android.tests.testutils.simulateLongTask
class FakeWellknownRetriever( class FakeWellknownRetriever(
private val getWellKnownResult: (String) -> WellKnown? = { null }, private val getWellKnownResult: (String) -> WellknownRetrieverResult<WellKnown> = { WellknownRetrieverResult.NotFound },
private val getElementWellKnownResult: (String) -> ElementWellKnown? = { null }, private val getElementWellKnownResult: (String) -> WellknownRetrieverResult<ElementWellKnown> = { WellknownRetrieverResult.NotFound },
) : WellknownRetriever { ) : WellknownRetriever {
override suspend fun getWellKnown(baseUrl: String): WellKnown? = simulateLongTask { override suspend fun getWellKnown(baseUrl: String): WellknownRetrieverResult<WellKnown> = simulateLongTask {
getWellKnownResult(baseUrl) getWellKnownResult(baseUrl)
} }
override suspend fun getElementWellKnown(baseUrl: String): ElementWellKnown? = simulateLongTask { override suspend fun getElementWellKnown(baseUrl: String): WellknownRetrieverResult<ElementWellKnown> = simulateLongTask {
getElementWellKnownResult(baseUrl) getElementWellKnownResult(baseUrl)
} }
} }