Browse Source

Add test for DefaultBugReporter

pull/1878/head
Benoit Marty 10 months ago
parent
commit
628d02beb1
  1. 9
      features/rageshake/impl/build.gradle.kts
  2. 23
      features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/BugReporterUrlProvider.kt
  3. 3
      features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporter.kt
  4. 34
      features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporterUrlProvider.kt
  5. 150
      features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporterTest.kt
  6. 31
      features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporterUrlProviderTest.kt
  7. 1
      gradle/libs.versions.toml
  8. 35
      services/toolbox/test/src/main/kotlin/io/element/android/services/toolbox/test/strings/FakeStringProvider.kt

9
features/rageshake/impl/build.gradle.kts

@ -23,6 +23,12 @@ plugins { @@ -23,6 +23,12 @@ plugins {
android {
namespace = "io.element.android.features.rageshake.impl"
testOptions {
unitTests {
isIncludeAndroidResources = true
}
}
}
anvil {
@ -57,6 +63,9 @@ dependencies { @@ -57,6 +63,9 @@ dependencies {
testImplementation(libs.test.turbine)
testImplementation(libs.test.mockk)
testImplementation(projects.libraries.matrix.test)
testImplementation(projects.libraries.sessionStorage.implMemory)
testImplementation(projects.features.rageshake.test)
testImplementation(projects.tests.testutils)
testImplementation(projects.services.toolbox.test)
testImplementation(libs.network.mockwebserver)
}

23
features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/BugReporterUrlProvider.kt

@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.features.rageshake.impl.reporter
import okhttp3.HttpUrl
fun interface BugReporterUrlProvider {
fun provide(): HttpUrl
}

3
features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporter.kt

@ -75,6 +75,7 @@ class DefaultBugReporter @Inject constructor( @@ -75,6 +75,7 @@ class DefaultBugReporter @Inject constructor(
private val userAgentProvider: UserAgentProvider,
private val sessionStore: SessionStore,
private val buildMeta: BuildMeta,
private val bugReporterUrlProvider: BugReporterUrlProvider,
) : BugReporter {
companion object {
// filenames
@ -223,7 +224,7 @@ class DefaultBugReporter @Inject constructor( @@ -223,7 +224,7 @@ class DefaultBugReporter @Inject constructor(
// build the request
val request = Request.Builder()
.url(context.getString(R.string.bug_report_url))
.url(bugReporterUrlProvider.provide())
.post(requestBody)
.build()

34
features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporterUrlProvider.kt

@ -0,0 +1,34 @@ @@ -0,0 +1,34 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.features.rageshake.impl.reporter
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.features.rageshake.impl.R
import io.element.android.libraries.di.AppScope
import io.element.android.services.toolbox.api.strings.StringProvider
import okhttp3.HttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrl
import javax.inject.Inject
@ContributesBinding(AppScope::class)
class DefaultBugReporterUrlProvider @Inject constructor(
private val stringProvider: StringProvider
) : BugReporterUrlProvider {
override fun provide(): HttpUrl {
return stringProvider.getString(R.string.bug_report_url).toHttpUrl()
}
}

150
features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporterTest.kt

@ -0,0 +1,150 @@ @@ -0,0 +1,150 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.features.rageshake.impl.reporter
import com.google.common.truth.Truth.assertThat
import io.element.android.features.rageshake.api.reporter.BugReporterListener
import io.element.android.features.rageshake.test.crash.FakeCrashDataStore
import io.element.android.features.rageshake.test.screenshot.FakeScreenshotHolder
import io.element.android.libraries.matrix.test.core.aBuildMeta
import io.element.android.libraries.network.useragent.DefaultUserAgentProvider
import io.element.android.libraries.sessionstorage.impl.memory.InMemorySessionStore
import io.element.android.services.toolbox.test.systemclock.FakeSystemClock
import io.element.android.tests.testutils.testCoroutineDispatchers
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
import okhttp3.OkHttpClient
import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.MockWebServer
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.RuntimeEnvironment
@RunWith(RobolectricTestRunner::class)
class DefaultBugReporterTest {
@Test
fun `test sendBugReport success`() = runTest {
val server = MockWebServer()
server.enqueue(
MockResponse()
.setResponseCode(200)
)
server.start()
val sut = createDefaultBugReporter(server)
var onUploadCancelledCalled = false
var onUploadFailedCalled = false
var progressValues = mutableListOf<Int>()
var onUploadSucceedCalled = false
sut.sendBugReport(
withDevicesLogs = true,
withCrashLogs = true,
withScreenshot = true,
theBugDescription = "a bug occurred",
canContact = true,
listener = object : BugReporterListener {
override fun onUploadCancelled() {
onUploadCancelledCalled = true
}
override fun onUploadFailed(reason: String?) {
onUploadFailedCalled = true
}
override fun onProgress(progress: Int) {
progressValues.add(progress)
}
override fun onUploadSucceed() {
onUploadSucceedCalled = true
}
},
)
server.shutdown()
assertThat(onUploadCancelledCalled).isFalse()
assertThat(onUploadFailedCalled).isFalse()
assertThat(progressValues.size).isEqualTo(10)
assertThat(onUploadSucceedCalled).isTrue()
}
@Test
fun `test sendBugReport error`() = runTest {
val server = MockWebServer()
server.enqueue(
MockResponse()
.setResponseCode(400)
.setBody("""{"error": "An error body"}""")
)
server.start()
val sut = createDefaultBugReporter(server)
var onUploadCancelledCalled = false
var onUploadFailedCalled = false
var onUploadFailedReason: String? = null
var progressValues = mutableListOf<Int>()
var onUploadSucceedCalled = false
sut.sendBugReport(
withDevicesLogs = true,
withCrashLogs = true,
withScreenshot = true,
theBugDescription = "a bug occurred",
canContact = true,
listener = object : BugReporterListener {
override fun onUploadCancelled() {
onUploadCancelledCalled = true
}
override fun onUploadFailed(reason: String?) {
onUploadFailedCalled = true
onUploadFailedReason = reason
}
override fun onProgress(progress: Int) {
progressValues.add(progress)
}
override fun onUploadSucceed() {
onUploadSucceedCalled = true
}
},
)
server.shutdown()
assertThat(onUploadCancelledCalled).isFalse()
assertThat(onUploadFailedCalled).isTrue()
assertThat(onUploadFailedReason).isEqualTo("An error body")
assertThat(progressValues.size).isEqualTo(10)
assertThat(onUploadSucceedCalled).isFalse()
}
private fun TestScope.createDefaultBugReporter(
server: MockWebServer
): DefaultBugReporter {
val buildMeta = aBuildMeta()
return DefaultBugReporter(
context = RuntimeEnvironment.getApplication(),
screenshotHolder = FakeScreenshotHolder(),
crashDataStore = FakeCrashDataStore(),
coroutineScope = this,
systemClock = FakeSystemClock(),
coroutineDispatchers = testCoroutineDispatchers(),
okHttpClient = { OkHttpClient.Builder().build() },
userAgentProvider = DefaultUserAgentProvider(buildMeta),
sessionStore = InMemorySessionStore(),
buildMeta = buildMeta,
bugReporterUrlProvider = { server.url("/") }
)
}
}

31
features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporterUrlProviderTest.kt

@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.features.rageshake.impl.reporter
import com.google.common.truth.Truth.assertThat
import io.element.android.services.toolbox.test.strings.FakeStringProvider
import okhttp3.HttpUrl.Companion.toHttpUrl
import org.junit.Test
class DefaultBugReporterUrlProviderTest {
@Test
fun `test DefaultBugReporterUrlProvider`() {
val sut = DefaultBugReporterUrlProvider(FakeStringProvider("https://example.org"))
val result = sut.provide()
assertThat(result).isEqualTo("https://example.org".toHttpUrl())
}
}

1
gradle/libs.versions.toml

@ -113,6 +113,7 @@ network_okhttp_bom = "com.squareup.okhttp3:okhttp-bom:4.12.0" @@ -113,6 +113,7 @@ network_okhttp_bom = "com.squareup.okhttp3:okhttp-bom:4.12.0"
network_okhttp_logging = { module = "com.squareup.okhttp3:logging-interceptor" }
network_okhttp_okhttp = { module = "com.squareup.okhttp3:okhttp" }
network_okhttp = { module = "com.squareup.okhttp3:okhttp" }
network_mockwebserver = { module = "com.squareup.okhttp3:mockwebserver" }
network_retrofit = "com.squareup.retrofit2:retrofit:2.9.0"
network_retrofit_converter_serialization = "com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:1.0.0"

35
services/toolbox/test/src/main/kotlin/io/element/android/services/toolbox/test/strings/FakeStringProvider.kt

@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.services.toolbox.test.strings
import io.element.android.services.toolbox.api.strings.StringProvider
class FakeStringProvider(
private val defaultResult: String = "A string"
) : StringProvider {
override fun getString(resId: Int): String {
return defaultResult
}
override fun getString(resId: Int, vararg formatArgs: Any?): String {
return defaultResult
}
override fun getQuantityString(resId: Int, quantity: Int, vararg formatArgs: Any?): String {
return defaultResult
}
}
Loading…
Cancel
Save