Skip to content

Commit

Permalink
Merge fd5c4c3 into c02fd22
Browse files Browse the repository at this point in the history
  • Loading branch information
xizzhu committed May 27, 2020
2 parents c02fd22 + fd5c4c3 commit 354e1b3
Show file tree
Hide file tree
Showing 24 changed files with 539 additions and 22 deletions.
7 changes: 5 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,15 @@ branches:
before_script:
- android list targets
- echo no | android create avd --force -n test -t android-25 --abi google_apis/arm64-v8a
- emulator -avd test -no-skin -no-window &
- emulator -avd test -no-window &
- android-wait-for-emulator
- adb shell settings put global window_animation_scale 0 &
- adb shell settings put global transition_animation_scale 0 &
- adb shell settings put global animator_duration_scale 0 &
- adb shell input keyevent 82 &

script:
- ./gradlew -Pcoverage clean coveralls
- ./gradlew -Pcoverage -PdisablePreDex clean coveralls

notifications:
email: false
6 changes: 2 additions & 4 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,6 @@ android {
}
}

tasks.withType(Test::class.java) {
maxParallelForks = Runtime.getRuntime().availableProcessors() / 2
}

dependencies {
implementation(Dependencies.Kotlin.stdlib)
implementation(Dependencies.Kotlin.coroutinesAndroid)
Expand Down Expand Up @@ -150,6 +146,8 @@ dependencies {
androidTestImplementation(Dependencies.Kotlin.coroutinesTest)
androidTestImplementation(Dependencies.AndroidX.Test.junit)
androidTestImplementation(Dependencies.AndroidX.Test.rules)
androidTestImplementation(Dependencies.AndroidX.Test.Espresso.core)
androidTestImplementation(Dependencies.AndroidX.Test.Espresso.contrib)
androidTestImplementation(Dependencies.Mockito.mockito)
androidTestImplementation(Dependencies.Mockito.android)
}
Expand Down
Binary file added app/src/androidTest/assets/中文和合本.zip
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

package me.xizzhu.android.joshua.core.repository.local.android

import android.content.Context
import android.database.Cursor
import android.database.sqlite.SQLiteDatabase
import androidx.annotation.CallSuper
Expand All @@ -33,19 +32,19 @@ abstract class BaseSqliteTest : BaseUnitTest() {
@CallSuper
override fun setup() {
super.setup()
clearLocalStorage()
androidDatabase = AndroidDatabase(ApplicationProvider.getApplicationContext())
clearLocalStorage()
}

private fun clearLocalStorage() {
ApplicationProvider.getApplicationContext<Context>().deleteDatabase(AndroidDatabase.DATABASE_NAME)
androidDatabase.removeAll()
}

@After
@CallSuper
override fun tearDown() {
androidDatabase.close()
clearLocalStorage()
androidDatabase.close()
super.tearDown()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,48 @@
package me.xizzhu.android.joshua.core.repository.remote.android

import android.util.JsonReader
import androidx.test.platform.app.InstrumentationRegistry
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.InputStream
import java.io.StringReader
import java.util.zip.ZipInputStream

var inputStream: InputStream? = null
private var inputStream: InputStream? = null

fun prepareTranslationList() {
inputStream = ByteArrayInputStream("""
{
"translations": [{
"name": "King James Version",
"shortName": "KJV",
"language": "en_gb",
"size": 1861133
}, {
"name": "中文和合本(简体)",
"shortName": "中文和合本",
"language": "zh_cn",
"size": 1781720
}]
}
""".trimIndent().toByteArray())
}

fun prepareKjv() {
inputStream = InstrumentationRegistry.getInstrumentation().context.assets.open("KJV.zip")
}

fun prepareCuv() {
inputStream = InstrumentationRegistry.getInstrumentation().context.assets.open("中文和合本.zip")
}

fun prepareSnIndexes() {
inputStream = InstrumentationRegistry.getInstrumentation().context.assets.open("sn_indexes.zip")
}

fun prepareSnEn() {
inputStream = InstrumentationRegistry.getInstrumentation().context.assets.open("sn_en.zip")
}

fun getInputStream(relativeUrl: String): InputStream = inputStream!!

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

package me.xizzhu.android.joshua.core.repository.remote.android

import androidx.test.platform.app.InstrumentationRegistry
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.channels.consumeEach
import kotlinx.coroutines.launch
Expand All @@ -43,7 +42,7 @@ class HttpStrongNumberServiceTest : BaseUnitTest() {
@Test
fun testFetchIndexes() {
runBlocking {
inputStream = InstrumentationRegistry.getInstrumentation().context.assets.open("sn_indexes.zip")
prepareSnIndexes()

val channel = Channel<Int>()
var channelCalled = false
Expand All @@ -69,7 +68,7 @@ class HttpStrongNumberServiceTest : BaseUnitTest() {
@Test
fun testFetchWords() {
runBlocking {
inputStream = InstrumentationRegistry.getInstrumentation().context.assets.open("sn_en.zip")
prepareSnEn()

val channel = Channel<Int>()
var channelCalled = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

package me.xizzhu.android.joshua.core.repository.remote.android

import androidx.test.platform.app.InstrumentationRegistry
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.channels.consumeEach
import kotlinx.coroutines.launch
Expand All @@ -26,7 +25,6 @@ import me.xizzhu.android.joshua.core.repository.remote.RemoteTranslationInfo
import me.xizzhu.android.joshua.tests.BaseUnitTest
import me.xizzhu.android.joshua.tests.MockContents
import org.junit.Before
import java.io.ByteArrayInputStream
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue
Expand All @@ -44,17 +42,22 @@ class HttpTranslationServiceTest : BaseUnitTest() {
@Test
fun testFetchTranslations() {
runBlocking {
inputStream = ByteArrayInputStream("{\"translations\":[{\"name\":\"Authorized King James\",\"shortName\":\"KJV\",\"language\":\"en_gb\",\"size\":1861134}]}".toByteArray())
prepareTranslationList()

assertEquals(listOf(RemoteTranslationInfo("KJV", "Authorized King James", "en_gb", 1861134L)),
httpTranslationService.fetchTranslations())
assertEquals(
listOf(
RemoteTranslationInfo("KJV", "King James Version", "en_gb", 1861133L),
RemoteTranslationInfo("中文和合本", "中文和合本(简体)", "zh_cn", 1781720L)
),
httpTranslationService.fetchTranslations()
)
}
}

@Test
fun testFetchTranslation() {
runBlocking {
inputStream = InstrumentationRegistry.getInstrumentation().context.assets.open("KJV.zip")
prepareKjv()

val channel = Channel<Int>()
var channelCalled = false
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright (C) 2020 Xizhi Zhu
*
* 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 me.xizzhu.android.joshua.end2end

import androidx.annotation.CallSuper
import androidx.test.core.app.ApplicationProvider
import androidx.test.espresso.IdlingPolicies
import me.xizzhu.android.joshua.core.repository.local.android.db.AndroidDatabase
import me.xizzhu.android.joshua.core.repository.local.android.db.MetadataDao
import java.util.concurrent.TimeUnit
import kotlin.test.AfterTest
import kotlin.test.BeforeTest
import kotlin.test.assertEquals
import kotlin.test.assertTrue

abstract class BaseE2eTest {
private lateinit var androidDatabase: AndroidDatabase

@BeforeTest
@CallSuper
open fun setup() {
IdlingPolicies.setMasterPolicyTimeout(5L, TimeUnit.MINUTES)
IdlingPolicies.setIdlingResourceTimeout(5L, TimeUnit.MINUTES)

androidDatabase = AndroidDatabase(ApplicationProvider.getApplicationContext())
resetLocalDatabase()
}

private fun resetLocalDatabase() {
androidDatabase.removeAll()
}

@AfterTest
@CallSuper
open fun tearDown() {
resetLocalDatabase()
androidDatabase.close()
}

protected fun assertNoCurrentTranslation() {
assertTrue(androidDatabase.metadataDao.read(MetadataDao.KEY_CURRENT_TRANSLATION, "").isEmpty())
}

protected fun assertCurrentTranslation(currentTranslation: String) {
assertEquals(currentTranslation, androidDatabase.metadataDao.read(MetadataDao.KEY_CURRENT_TRANSLATION, ""))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
* Copyright (C) 2020 Xizhi Zhu
*
* 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 me.xizzhu.android.joshua.end2end

import android.app.Activity
import android.content.Intent
import android.view.View
import android.view.WindowManager
import androidx.annotation.StringRes
import androidx.test.espresso.Espresso
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.action.ViewActions.longClick
import androidx.test.espresso.assertion.PositionAssertions.isCompletelyBelow
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.RootMatchers.isDialog
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.rule.ActivityTestRule
import org.hamcrest.Matcher

open class BaseRobot<T : Activity, SELF : BaseRobot<T, SELF>>(protected val activityRule: ActivityTestRule<T>) {
open fun launch(): SELF {
activityRule.launchActivity(Intent())
activityRule.activity.runOnUiThread {
activityRule.activity.window.addFlags(
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON or
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
)
}
return self()
}

@Suppress("UNCHECKED_CAST")
protected fun self(): SELF = this as SELF

fun pressBack(): SELF {
Espresso.pressBack()
return self()
}

fun clickDialogPositive(): SELF {
onView(withText(android.R.string.yes)).inRoot(isDialog()).perform(click())
return self()
}

fun clickDialogNegative(): SELF {
onView(withText(android.R.string.no)).inRoot(isDialog()).perform(click())
return self()
}

fun hasDialogWithText(@StringRes text: Int): SELF {
onView(withText(text)).inRoot(isDialog())
return self()
}

fun clickText(text: String): SELF {
onView(withText(text)).perform(click())
return self()
}

fun longClickText(text: String): SELF {
onView(withText(text)).perform(longClick())
return self()
}

fun hasText(@StringRes text: Int): SELF {
onView(withText(text)).check(matches(isDisplayed()))
return self()
}

fun hasText(text: String): SELF {
onView(withText(text)).check(matches(isDisplayed()))
return self()
}

fun isTextDisplayedBelow(@StringRes text: Int, matcher: Matcher<View>): SELF {
onView(withText(text)).check(matches(isDisplayed())).check(isCompletelyBelow(matcher))
return self()
}

fun isTextDisplayedBelow(text: String, matcher: Matcher<View>): SELF {
onView(withText(text)).check(matches(isDisplayed())).check(isCompletelyBelow(matcher))
return self()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright (C) 2020 Xizhi Zhu
*
* 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 me.xizzhu.android.joshua.end2end

import androidx.test.espresso.IdlingResource
import me.xizzhu.android.joshua.ui.ProgressDialog

class ProgressDialogIdlingResource(private val dialog: ProgressDialog) : IdlingResource {
private var resourceCallback: IdlingResource.ResourceCallback? = null

override fun getName(): String = ProgressDialogIdlingResource::class.java.name

override fun isIdleNow(): Boolean {
val idle = !dialog.isShowing()
if (idle) resourceCallback?.onTransitionToIdle()
return idle
}

override fun registerIdleTransitionCallback(callback: IdlingResource.ResourceCallback?) {
this.resourceCallback = callback
}
}
Loading

0 comments on commit 354e1b3

Please sign in to comment.