Add some tests

This commit is contained in:
Jorge Martín 2022-06-10 09:51:20 +02:00
parent 2fbec133b6
commit 64334c3437
8 changed files with 309 additions and 2 deletions

View file

@ -29,7 +29,7 @@ def jjwt = "0.11.5"
def vanniktechEmoji = "0.15.0"
// Testing
def mockk = "1.12.4"
def mockk = "1.12.3"
def espresso = "3.4.0"
def androidxTest = "1.4.0"
def androidxOrchestrator = "1.4.1"

View file

@ -547,5 +547,6 @@ dependencies {
androidTestImplementation('com.adevinta.android:barista:4.2.0') {
exclude group: 'org.jetbrains.kotlin'
}
androidTestImplementation libs.mockk.mockkAndroid
androidTestUtil libs.androidx.orchestrator
}

View file

@ -0,0 +1,46 @@
/*
* Copyright (c) 2022 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 im.vector.app
import android.os.Build
import java.lang.reflect.Field
/**
* Used to override [Build.VERSION.SDK_INT]. Ideally an interface should be used instead, but that approach forces us to either add suppress lint annotations
* and potentially miss an API version issue or write a custom lint rule, which seems like an overkill.
*/
object AndroidVersionTestOverrider {
private var initialValue: Int? = null
fun override(newVersion: Int) {
if (initialValue == null) {
initialValue = Build.VERSION.SDK_INT
}
val field = Build.VERSION::class.java.getField("SDK_INT")
setStaticField(field, newVersion)
}
fun restore() {
initialValue?.let { override(it) }
}
private fun setStaticField(field: Field, value: Any) {
field.isAccessible = true
field.set(null, value)
}
}

View file

@ -0,0 +1,79 @@
/*
* Copyright (c) 2022 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 im.vector.app.features.voice
import android.Manifest
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.rule.GrantPermissionRule
import io.mockk.spyk
import io.mockk.verify
import kotlinx.coroutines.Dispatchers
import org.amshove.kluent.shouldBeNull
import org.amshove.kluent.shouldExist
import org.amshove.kluent.shouldNotBeNull
import org.amshove.kluent.shouldNotExist
import org.junit.Rule
import org.junit.Test
import java.io.File
class VoiceRecorderLTests {
@get:Rule
val grantPermissionRule: GrantPermissionRule = GrantPermissionRule.grant(Manifest.permission.RECORD_AUDIO)
private val context = InstrumentationRegistry.getInstrumentation().targetContext
private val recorder = spyk(VoiceRecorderL(context, Dispatchers.IO))
@Test
fun startRecordCreatesOggFile() = with(recorder) {
getVoiceMessageFile().shouldBeNull()
startRecord("some_room_id")
getVoiceMessageFile().shouldNotBeNullAndExist()
stopRecord()
}
@Test
fun stopRecordKeepsFile() = with(recorder) {
getVoiceMessageFile().shouldBeNull()
startRecord("some_room_id")
stopRecord()
getVoiceMessageFile().shouldNotBeNullAndExist()
}
@Test
fun cancelRecordRemovesFileAfterStopping() = with(recorder) {
startRecord("some_room_id")
val file = recorder.getVoiceMessageFile()
file.shouldNotBeNullAndExist()
cancelRecord()
verify { stopRecord() }
getVoiceMessageFile().shouldBeNull()
file!!.shouldNotExist()
}
}
private fun File?.shouldNotBeNullAndExist() {
shouldNotBeNull()
shouldExist()
}

View file

@ -0,0 +1,47 @@
/*
* Copyright (c) 2022 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 im.vector.app.features.voice
import android.os.Build
import androidx.test.platform.app.InstrumentationRegistry
import im.vector.app.AndroidVersionTestOverrider
import org.amshove.kluent.shouldBeInstanceOf
import org.junit.After
import org.junit.Test
class VoiceRecorderProviderTests {
private val context = InstrumentationRegistry.getInstrumentation().targetContext
private val provider = VoiceRecorderProvider(context)
@After
fun tearDown() {
AndroidVersionTestOverrider.restore()
}
@Test
fun provideVoiceRecorderOnAndroidQReturnsQRecorder() {
AndroidVersionTestOverrider.override(Build.VERSION_CODES.Q)
provider.provideVoiceRecorder().shouldBeInstanceOf(VoiceRecorderQ::class)
}
@Test
fun provideVoiceRecorderOnOlderAndroidVersionReturnsLRecorder() {
AndroidVersionTestOverrider.override(Build.VERSION_CODES.LOLLIPOP)
provider.provideVoiceRecorder().shouldBeInstanceOf(VoiceRecorderL::class)
}
}

View file

@ -0,0 +1,78 @@
/*
* Copyright (c) 2022 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 im.vector.app.features.voice
import android.Manifest
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.rule.GrantPermissionRule
import io.mockk.spyk
import io.mockk.verify
import org.amshove.kluent.shouldBeNull
import org.amshove.kluent.shouldExist
import org.amshove.kluent.shouldNotBeNull
import org.amshove.kluent.shouldNotExist
import org.junit.Rule
import org.junit.Test
import java.io.File
class VoiceRecorderQTests {
@get:Rule
val grantPermissionRule: GrantPermissionRule = GrantPermissionRule.grant(Manifest.permission.RECORD_AUDIO)
private val context = InstrumentationRegistry.getInstrumentation().targetContext
private val recorder = spyk(VoiceRecorderQ(context))
@Test
fun startRecordCreatesOggFile() = with(recorder) {
getVoiceMessageFile().shouldBeNull()
startRecord("some_room_id")
getVoiceMessageFile().shouldNotBeNullAndExist()
stopRecord()
}
@Test
fun stopRecordKeepsFile() = with(recorder) {
getVoiceMessageFile().shouldBeNull()
startRecord("some_room_id")
stopRecord()
getVoiceMessageFile().shouldNotBeNullAndExist()
}
@Test
fun cancelRecordRemovesFileAfterStopping() = with(recorder) {
startRecord("some_room_id")
val file = recorder.getVoiceMessageFile()
file.shouldNotBeNullAndExist()
cancelRecord()
verify { stopRecord() }
getVoiceMessageFile().shouldBeNull()
file!!.shouldNotExist()
}
}
private fun File?.shouldNotBeNullAndExist() {
shouldNotBeNull()
shouldExist()
}

View file

@ -0,0 +1,56 @@
/*
* Copyright (c) 2022 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 im.vector.app.features.voice
import android.net.Uri
import androidx.test.platform.app.InstrumentationRegistry
import kotlinx.coroutines.Dispatchers
import org.amshove.kluent.shouldBeEqualTo
import org.amshove.kluent.shouldExist
import org.junit.After
import org.junit.Test
import org.matrix.android.sdk.api.session.content.ContentAttachmentData
import java.io.File
class VoiceRecorderTests {
private val context = InstrumentationRegistry.getInstrumentation().targetContext
private val voiceRecorder = VoiceRecorderL(context, Dispatchers.IO)
private val audioDirectory = File(context.cacheDir, "voice_records")
@After
fun tearDown() {
audioDirectory.deleteRecursively()
}
@Test
fun ensureAudioDirectoryCreatesIt() {
voiceRecorder.ensureAudioDirectory(context)
audioDirectory.shouldExist()
}
@Test
fun findVoiceFileSearchesInDirectory() {
val filename = "someFile.ogg"
val attachment = ContentAttachmentData(
queryUri = Uri.parse(filename),
mimeType = "ogg",
type = ContentAttachmentData.Type.AUDIO
)
attachment.findVoiceFile(audioDirectory) shouldBeEqualTo File(audioDirectory, filename)
}
}

View file

@ -27,7 +27,7 @@ import java.util.UUID
abstract class AbstractVoiceRecorder(
private val context: Context,
internal val filenameExt: String
private val filenameExt: String,
) : VoiceRecorder {
private val outputDirectory: File by lazy { ensureAudioDirectory(context) }