mirror of
https://github.com/sudoxnym/habitica-android.git
synced 2026-04-14 19:56:32 +00:00
try enabling UI tests again
This commit is contained in:
parent
7f26f973f9
commit
cd1492ca2d
5 changed files with 70 additions and 61 deletions
50
.github/workflows/android.yml
vendored
50
.github/workflows/android.yml
vendored
|
|
@ -40,31 +40,31 @@ jobs:
|
|||
with:
|
||||
arguments: testProdDebugUnitTest
|
||||
|
||||
# ui-test:
|
||||
# runs-on: macos-latest
|
||||
# strategy:
|
||||
# matrix:
|
||||
# api-level: [24, 26, 28, 29, 30, 31]
|
||||
# steps:
|
||||
# - uses: actions/checkout@v2
|
||||
# - name: set up JDK 11
|
||||
# uses: actions/setup-java@v2
|
||||
# with:
|
||||
# java-version: '11'
|
||||
# distribution: 'adopt'
|
||||
# cache: gradle
|
||||
# - name: Prepare
|
||||
# run: ./.github/prepare-workflow
|
||||
# - name: Validate Gradle wrapper
|
||||
# uses: gradle/wrapper-validation-action@e6e38bacfdf1a337459f332974bb2327a31aaf4b
|
||||
# - name: run tests
|
||||
# uses: reactivecircus/android-emulator-runner@v2
|
||||
# with:
|
||||
# api-level: ${{ matrix.api-level }}
|
||||
# arch: x86_64
|
||||
# emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
||||
# disable-animations: true
|
||||
# script: ./gradlew connectedProdDebugAndroidTest
|
||||
ui-test:
|
||||
runs-on: macos-latest
|
||||
strategy:
|
||||
matrix:
|
||||
api-level: [24, 26, 28, 29, 30, 31]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: set up JDK 11
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
java-version: '11'
|
||||
distribution: 'adopt'
|
||||
cache: gradle
|
||||
- name: Prepare
|
||||
run: ./.github/prepare-workflow
|
||||
- name: Validate Gradle wrapper
|
||||
uses: gradle/wrapper-validation-action@e6e38bacfdf1a337459f332974bb2327a31aaf4b
|
||||
- name: run tests
|
||||
uses: reactivecircus/android-emulator-runner@v2
|
||||
with:
|
||||
api-level: ${{ matrix.api-level }}
|
||||
arch: x86_64
|
||||
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
||||
disable-animations: true
|
||||
script: ./gradlew connectedProdDebugAndroidTest
|
||||
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
|
|
|
|||
|
|
@ -76,6 +76,8 @@ dependencies {
|
|||
androidTestImplementation 'androidx.test.ext:junit-ktx:1.1.5'
|
||||
androidTestImplementation "io.mockk:mockk-android:$mockk_version"
|
||||
androidTestImplementation "io.kotest:kotest-assertions-core:$kotest_version"
|
||||
androidTestImplementation("org.jetbrains.kotlin:kotlin-reflect:$kotlin_version")
|
||||
|
||||
androidTestUtil("androidx.test:orchestrator:1.4.2")
|
||||
|
||||
implementation 'com.facebook.shimmer:shimmer:0.5.0'
|
||||
|
|
@ -285,6 +287,10 @@ android {
|
|||
disable 'MissingTranslation', 'InvalidPackage'
|
||||
enable 'LogConditional', 'IconExpectedSize', 'MissingRegistered', 'TypographyQuotes'
|
||||
}
|
||||
|
||||
packagingOptions {
|
||||
resources.excludes.add("META-INF/*")
|
||||
}
|
||||
}
|
||||
|
||||
android.testOptions {
|
||||
|
|
|
|||
|
|
@ -24,13 +24,14 @@ import io.github.kakaocup.kakao.spinner.KSpinner
|
|||
import io.github.kakaocup.kakao.spinner.KSpinnerItem
|
||||
import io.github.kakaocup.kakao.text.KButton
|
||||
import io.github.kakaocup.kakao.toolbar.KToolbar
|
||||
import io.mockk.coVerify
|
||||
import io.mockk.every
|
||||
import io.mockk.justRun
|
||||
import io.mockk.mockk
|
||||
import io.mockk.mockkObject
|
||||
import io.mockk.slot
|
||||
import io.mockk.verify
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
|
|
@ -162,7 +163,7 @@ class TaskFormActivityTest : ActivityTestCase() {
|
|||
device.activities.isCurrent(TaskFormActivity::class.java)
|
||||
textEditText.typeText("New Habit")
|
||||
KButton { withId(R.id.action_save) }.click()
|
||||
verify(exactly = 1) { taskRepository.createTaskInBackground(any(), assignChanges) }
|
||||
verify(exactly = 1) { taskRepository.createTaskInBackground(any(), emptyMap()) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -176,7 +177,7 @@ class TaskFormActivityTest : ActivityTestCase() {
|
|||
val bundle = Bundle()
|
||||
bundle.putString(TaskFormActivity.TASK_TYPE_KEY, TaskType.HABIT.value)
|
||||
bundle.putString(TaskFormActivity.TASK_ID_KEY, task.id!!)
|
||||
every { taskRepository.getUnmanagedTask(any()) } returns Flowable.just(task)
|
||||
every { taskRepository.getUnmanagedTask(any()) } returns flowOf(task)
|
||||
|
||||
val intent = Intent(ApplicationProvider.getApplicationContext(), TaskFormActivity::class.java)
|
||||
intent.putExtras(bundle)
|
||||
|
|
@ -184,7 +185,7 @@ class TaskFormActivityTest : ActivityTestCase() {
|
|||
screen {
|
||||
toolbar {
|
||||
KView { withId(R.id.action_save) }.click()
|
||||
verify(exactly = 1) { taskRepository.updateTaskInBackground(any(), assignChanges) }
|
||||
verify(exactly = 1) { taskRepository.updateTaskInBackground(any(), emptyMap()) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -200,7 +201,7 @@ class TaskFormActivityTest : ActivityTestCase() {
|
|||
bundle.putString(TaskFormActivity.TASK_TYPE_KEY, TaskType.DAILY.value)
|
||||
bundle.putString(TaskFormActivity.TASK_TYPE_KEY, TaskType.DAILY.value)
|
||||
bundle.putString(TaskFormActivity.TASK_ID_KEY, task.id!!)
|
||||
every { taskRepository.getUnmanagedTask(any()) } returns Flowable.just(task)
|
||||
every { taskRepository.getUnmanagedTask(any()) } returns flowOf(task)
|
||||
|
||||
val intent = Intent(ApplicationProvider.getApplicationContext(), TaskFormActivity::class.java)
|
||||
intent.putExtras(bundle)
|
||||
|
|
@ -209,7 +210,7 @@ class TaskFormActivityTest : ActivityTestCase() {
|
|||
device.activities.isCurrent(TaskFormActivity::class.java)
|
||||
KButton { withId(R.id.action_delete) }.click()
|
||||
KButton { withText(R.string.delete_task) }.click()
|
||||
verify(exactly = 1) { taskRepository.deleteTask(task.id!!) }
|
||||
coVerify(exactly = 1) { taskRepository.deleteTask(task.id!!) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -287,8 +288,8 @@ class TaskFormActivityTest : ActivityTestCase() {
|
|||
val bundle = Bundle()
|
||||
bundle.putString(TaskFormActivity.TASK_TYPE_KEY, TaskType.DAILY.value)
|
||||
bundle.putString(TaskFormActivity.TASK_ID_KEY, task.id!!)
|
||||
every { taskRepository.getUnmanagedTask(any()) } returns Flowable.just(task)
|
||||
justRun { taskRepository.updateTaskInBackground(capture(taskSlot), assignChanges) }
|
||||
every { taskRepository.getUnmanagedTask(any()) } returns flowOf(task)
|
||||
justRun { taskRepository.updateTaskInBackground(capture(taskSlot), emptyMap()) }
|
||||
|
||||
val intent = Intent(ApplicationProvider.getApplicationContext(), TaskFormActivity::class.java)
|
||||
intent.putExtras(bundle)
|
||||
|
|
@ -313,7 +314,7 @@ class TaskFormActivityTest : ActivityTestCase() {
|
|||
typeText("3")
|
||||
}
|
||||
KButton { withId(R.id.action_save) }.click()
|
||||
verify { taskRepository.updateTaskInBackground(any(), assignChanges) }
|
||||
verify { taskRepository.updateTaskInBackground(any(), emptyMap()) }
|
||||
assert(taskSlot.captured.everyX == 3)
|
||||
assert(taskSlot.captured.frequency == Frequency.WEEKLY)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,12 +22,13 @@ import io.github.kakaocup.kakao.text.KTextView
|
|||
import io.kotest.matchers.shouldBe
|
||||
import io.mockk.CapturingSlot
|
||||
import io.mockk.clearMocks
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.coVerify
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.mockkObject
|
||||
import io.mockk.spyk
|
||||
import io.mockk.verify
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import org.hamcrest.Matcher
|
||||
import org.hamcrest.Matchers.isA
|
||||
import org.junit.Test
|
||||
|
|
@ -70,10 +71,10 @@ class ItemScreen : Screen<ItemScreen>() {
|
|||
internal class ItemRecyclerFragmentTest : FragmentTestCase<ItemRecyclerFragment, FragmentRecyclerviewBinding, ItemScreen>(false) {
|
||||
override fun makeFragment() {
|
||||
every { inventoryRepository.getOwnedItems("eggs") } answers {
|
||||
Flowable.just(user.items?.eggs!!.filter { it.numberOwned > 0 })
|
||||
flowOf(user.items?.eggs!!.filter { it.numberOwned > 0 })
|
||||
}
|
||||
every { inventoryRepository.getOwnedItems("hatchingPotions") } answers {
|
||||
Flowable.just(user.items?.hatchingPotions!!.filter { it.numberOwned > 0 })
|
||||
flowOf(user.items?.hatchingPotions!!.filter { it.numberOwned > 0 })
|
||||
}
|
||||
fragment = spyk()
|
||||
fragment.shouldInitializeComponent = false
|
||||
|
|
@ -113,10 +114,10 @@ internal class ItemRecyclerFragmentTest : FragmentTestCase<ItemRecyclerFragment,
|
|||
every { inventoryRepository.getOwnedItems("food") } answers {
|
||||
var items = user.items?.food!!.filter { it.numberOwned > 0 }
|
||||
items = (items + items).sortedBy { it.key }
|
||||
Flowable.just(items)
|
||||
flowOf(items)
|
||||
}
|
||||
every { inventoryRepository.getItems(Food::class.java, any()) } answers {
|
||||
Flowable.just((content.eggs + content.eggs).sortedBy { it.key })
|
||||
flowOf((content.eggs + content.eggs).sortedBy { it.key })
|
||||
}
|
||||
fragment.itemType = "food"
|
||||
val foundItems = mutableListOf<CharSequence?>()
|
||||
|
|
@ -134,7 +135,7 @@ internal class ItemRecyclerFragmentTest : FragmentTestCase<ItemRecyclerFragment,
|
|||
@Test
|
||||
fun canHatchPetWithEggs() {
|
||||
val slot = CapturingSlot<HatchPetUseCase.RequestValues>()
|
||||
every { hatchPetUseCase.callInteractor(capture(slot)) } returns mockk(relaxed = true)
|
||||
coEvery { hatchPetUseCase.callInteractor(capture(slot)) } returns mockk(relaxed = true)
|
||||
fragment.itemType = "eggs"
|
||||
launchFragment()
|
||||
screen {
|
||||
|
|
@ -142,7 +143,7 @@ internal class ItemRecyclerFragmentTest : FragmentTestCase<ItemRecyclerFragment,
|
|||
childWith<ItemItem> { withDescendant { withText("Wolf") } }.click()
|
||||
KView { withText(R.string.hatch_with_potion) }.click()
|
||||
KView { withText("Shade") }.click()
|
||||
verify { hatchPetUseCase.callInteractor(any()) }
|
||||
coVerify { hatchPetUseCase.callInteractor(any()) }
|
||||
slot.captured.egg.key shouldBe "Wolf"
|
||||
slot.captured.potion.key shouldBe "Shade"
|
||||
}
|
||||
|
|
@ -152,7 +153,7 @@ internal class ItemRecyclerFragmentTest : FragmentTestCase<ItemRecyclerFragment,
|
|||
@Test
|
||||
fun canHatchPetWithPotions() {
|
||||
val slot = CapturingSlot<HatchPetUseCase.RequestValues>()
|
||||
every { hatchPetUseCase.callInteractor(capture(slot)) } returns mockk(relaxed = true)
|
||||
coEvery { hatchPetUseCase.callInteractor(capture(slot)) } returns mockk(relaxed = true)
|
||||
fragment.itemType = "hatchingPotions"
|
||||
launchFragment()
|
||||
screen {
|
||||
|
|
@ -160,7 +161,7 @@ internal class ItemRecyclerFragmentTest : FragmentTestCase<ItemRecyclerFragment,
|
|||
childWith<ItemItem> { withDescendant { withText("Shade") } }.click()
|
||||
KView { withText(R.string.hatch_egg) }.click()
|
||||
KView { withText("Wolf") }.click()
|
||||
verify { hatchPetUseCase.callInteractor(any()) }
|
||||
coVerify { hatchPetUseCase.callInteractor(any()) }
|
||||
slot.captured.egg.key shouldBe "Wolf"
|
||||
slot.captured.potion.key shouldBe "Shade"
|
||||
}
|
||||
|
|
@ -170,19 +171,19 @@ internal class ItemRecyclerFragmentTest : FragmentTestCase<ItemRecyclerFragment,
|
|||
@Test
|
||||
fun canSellItems() {
|
||||
val slot = CapturingSlot<OwnedItem>()
|
||||
every { inventoryRepository.sellItem(capture(slot)) } returns mockk(relaxed = true)
|
||||
coEvery { inventoryRepository.sellItem(capture(slot)) } returns mockk(relaxed = true)
|
||||
fragment.itemType = "eggs"
|
||||
launchFragment()
|
||||
screen {
|
||||
recycler {
|
||||
childWith<ItemItem> { withDescendant { withText("Cactus") } }.click()
|
||||
KView { withText("Sell (3 Gold)") }.click()
|
||||
verify { inventoryRepository.sellItem(any()) }
|
||||
coVerify { inventoryRepository.sellItem(any()) }
|
||||
slot.captured.key shouldBe "Cactus"
|
||||
|
||||
childWith<ItemItem> { withDescendant { withText("Panda Cub") } }.click()
|
||||
KView { withText("Sell (3 Gold)") }.click()
|
||||
verify { inventoryRepository.sellItem(any()) }
|
||||
coVerify { inventoryRepository.sellItem(any()) }
|
||||
slot.captured.key shouldBe "PandaCub"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,10 +14,11 @@ import io.github.kakaocup.kakao.recycler.KRecyclerItem
|
|||
import io.github.kakaocup.kakao.recycler.KRecyclerView
|
||||
import io.github.kakaocup.kakao.screen.Screen
|
||||
import io.github.kakaocup.kakao.text.KTextView
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.coVerify
|
||||
import io.mockk.every
|
||||
import io.mockk.spyk
|
||||
import io.mockk.verify
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import org.hamcrest.Matcher
|
||||
import org.junit.Test
|
||||
|
||||
|
|
@ -54,7 +55,7 @@ internal class TaskRecyclerViewFragmentTest : FragmentTestCase<TaskRecyclerViewF
|
|||
|
||||
@Test
|
||||
fun displaysHabits() {
|
||||
every { taskRepository.getTasks(TaskType.HABIT, any()) } returns Flowable.just(tasks.filter { it.type == TaskType.HABIT })
|
||||
every { taskRepository.getTasks(TaskType.HABIT, any(), emptyArray()) } returns flowOf(tasks.filter { it.type == TaskType.HABIT })
|
||||
fragment.taskType = TaskType.HABIT
|
||||
launchFragment()
|
||||
screen {
|
||||
|
|
@ -73,7 +74,7 @@ internal class TaskRecyclerViewFragmentTest : FragmentTestCase<TaskRecyclerViewF
|
|||
|
||||
@Test
|
||||
fun displaysDailies() {
|
||||
every { taskRepository.getTasks(TaskType.DAILY, any()) } returns Flowable.just(tasks.filter { it.type == TaskType.DAILY })
|
||||
every { taskRepository.getTasks(TaskType.DAILY, any(), emptyArray()) } returns flowOf(tasks.filter { it.type == TaskType.DAILY })
|
||||
fragment.taskType = TaskType.DAILY
|
||||
launchFragment()
|
||||
screen {
|
||||
|
|
@ -88,7 +89,7 @@ internal class TaskRecyclerViewFragmentTest : FragmentTestCase<TaskRecyclerViewF
|
|||
|
||||
@Test
|
||||
fun displaysTodos() {
|
||||
every { taskRepository.getTasks(TaskType.TODO, any()) } returns Flowable.just(tasks.filter { it.type == TaskType.TODO })
|
||||
every { taskRepository.getTasks(TaskType.TODO, any(), emptyArray()) } returns flowOf(tasks.filter { it.type == TaskType.TODO })
|
||||
fragment.taskType = TaskType.TODO
|
||||
launchFragment()
|
||||
screen {
|
||||
|
|
@ -179,7 +180,7 @@ internal class TaskRecyclerViewFragmentTest : FragmentTestCase<TaskRecyclerViewF
|
|||
@Test
|
||||
fun scoreHabitUp() {
|
||||
val habits = tasks.filter { it.type == TaskType.HABIT }
|
||||
every { taskRepository.getTasks(TaskType.HABIT, any()) } returns Flowable.just(habits)
|
||||
every { taskRepository.getTasks(TaskType.HABIT, any(), emptyArray()) } returns flowOf(habits)
|
||||
fragment.taskType = TaskType.HABIT
|
||||
launchFragment()
|
||||
screen {
|
||||
|
|
@ -190,7 +191,7 @@ internal class TaskRecyclerViewFragmentTest : FragmentTestCase<TaskRecyclerViewF
|
|||
KView(this.parent) {
|
||||
withId(R.id.btnPlus)
|
||||
}.click()
|
||||
verify(exactly = 1) { taskRepository.taskChecked(any(), habits.first().id!!, true, false, any()) }
|
||||
coVerify(exactly = 1) { taskRepository.taskChecked(any(), habits.first().id!!, true, false, any()) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -200,7 +201,7 @@ internal class TaskRecyclerViewFragmentTest : FragmentTestCase<TaskRecyclerViewF
|
|||
fun scoreHabitDown() {
|
||||
val habits = tasks.filter { it.type == TaskType.HABIT }
|
||||
val firstHabit = habits.first()
|
||||
every { taskRepository.getTasks(TaskType.HABIT, any()) } returns Flowable.just(habits)
|
||||
every { taskRepository.getTasks(TaskType.HABIT, any(), emptyArray()) } returns flowOf(habits)
|
||||
fragment.taskType = TaskType.HABIT
|
||||
launchFragment()
|
||||
screen {
|
||||
|
|
@ -211,7 +212,7 @@ internal class TaskRecyclerViewFragmentTest : FragmentTestCase<TaskRecyclerViewF
|
|||
KView(this.parent) {
|
||||
withId(R.id.btnMinus)
|
||||
}.click()
|
||||
verify(exactly = 1) { taskRepository.taskChecked(any(), firstHabit.id!!, false, false, any()) }
|
||||
coVerify(exactly = 1) { taskRepository.taskChecked(any(), firstHabit.id!!, false, false, any()) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -220,7 +221,7 @@ internal class TaskRecyclerViewFragmentTest : FragmentTestCase<TaskRecyclerViewF
|
|||
@Test
|
||||
fun completeDaily() {
|
||||
val dailies = tasks.filter { it.type == TaskType.DAILY }
|
||||
every { taskRepository.getTasks(TaskType.DAILY, any()) } returns Flowable.just(dailies)
|
||||
every { taskRepository.getTasks(TaskType.DAILY, any(), emptyArray()) } returns flowOf(dailies)
|
||||
fragment.taskType = TaskType.DAILY
|
||||
launchFragment()
|
||||
screen {
|
||||
|
|
@ -230,13 +231,13 @@ internal class TaskRecyclerViewFragmentTest : FragmentTestCase<TaskRecyclerViewF
|
|||
KView(this.parent) {
|
||||
withId(R.id.checkBoxHolder)
|
||||
}.click()
|
||||
verify(exactly = 1) { taskRepository.taskChecked(any(), dailies.first().id!!, true, false, any()) }
|
||||
coVerify(exactly = 1) { taskRepository.taskChecked(any(), dailies.first().id!!, true, false, any()) }
|
||||
}
|
||||
childAt<TaskItem>(1) {
|
||||
KView(this.parent) {
|
||||
withId(R.id.checkBoxHolder)
|
||||
}.click()
|
||||
verify(exactly = 1) { taskRepository.taskChecked(any(), dailies[1].id!!, false, false, any()) }
|
||||
coVerify(exactly = 1) { taskRepository.taskChecked(any(), dailies[1].id!!, false, false, any()) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -245,7 +246,7 @@ internal class TaskRecyclerViewFragmentTest : FragmentTestCase<TaskRecyclerViewF
|
|||
@Test
|
||||
fun completeTodo() {
|
||||
val todos = tasks.filter { it.type == TaskType.TODO }
|
||||
every { taskRepository.getTasks(TaskType.TODO, any()) } returns Flowable.just(todos)
|
||||
coEvery { taskRepository.getTasks(TaskType.TODO, any(), emptyArray()) } returns flowOf(todos)
|
||||
fragment.taskType = TaskType.TODO
|
||||
launchFragment()
|
||||
screen {
|
||||
|
|
@ -255,7 +256,7 @@ internal class TaskRecyclerViewFragmentTest : FragmentTestCase<TaskRecyclerViewF
|
|||
KView(this.parent) {
|
||||
withId(R.id.checkBoxHolder)
|
||||
}.click()
|
||||
verify(exactly = 1) { taskRepository.taskChecked(any(), todos.first().id!!, true, false, any()) }
|
||||
coVerify(exactly = 1) { taskRepository.taskChecked(any(), todos.first().id!!, true, false, any()) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue