Skip to content

Commit

Permalink
test(app): add tests for intro & update affected (existing) tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ashutoshgngwr committed Sep 4, 2020
1 parent d3dfbe9 commit 749c30c
Show file tree
Hide file tree
Showing 4 changed files with 173 additions and 17 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package com.github.ashutoshgngwr.noice

import androidx.lifecycle.Lifecycle
import androidx.test.core.app.ActivityScenario
import androidx.test.core.app.ApplicationProvider
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.NoMatchingViewException
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.action.ViewActions.swipeLeft
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.intent.Intents
import androidx.test.espresso.intent.Intents.intended
import androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent
import androidx.test.espresso.matcher.ViewMatchers.*
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.hamcrest.Matchers.allOf
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
class AppIntroActivityTest {

@Rule
@JvmField
val retryTestRule = RetryTestRule(5)

private lateinit var activityScenario: ActivityScenario<AppIntroActivity>

@Before
fun setup() {
activityScenario = ActivityScenario.launch(AppIntroActivity::class.java)
}

@After
fun teardown() {
Utils.withDefaultSharedPreferences(ApplicationProvider.getApplicationContext()) {
it.edit().clear().commit()
}
}

@Test
fun testOnSkipPressed() {
onView(withText(R.string.app_intro_skip_button))
.check(matches(isDisplayed()))
.perform(click())

// should destroy the activity and update the preferences
assertEquals(Lifecycle.State.DESTROYED, activityScenario.state)
Utils.withDefaultSharedPreferences(ApplicationProvider.getApplicationContext()) {
assertTrue(it.getBoolean(AppIntroActivity.PREF_HAS_USER_SEEN_APP_INTRO, false))
}
}

@Test
fun testOnDonePressed() {
do { // find the last slide (where done button is shown)
try {
onView(allOf(isDisplayed(), withText(R.string.app_intro_done_button)))
.check(matches(isDisplayed()))
break
} catch (e: NoMatchingViewException) {
onView(withId(R.id.view_pager)).perform(swipeLeft())
}
} while (true)

onView(withText(R.string.app_intro_done_button))
.perform(click())

// should destroy the activity and update the preferences
assertEquals(Lifecycle.State.DESTROYED, activityScenario.state)
Utils.withDefaultSharedPreferences(ApplicationProvider.getApplicationContext()) {
assertTrue(it.getBoolean(AppIntroActivity.PREF_HAS_USER_SEEN_APP_INTRO, false))
}

}

@Test
fun testMaybeStart_whenUserIsTryingToSeeItForTheFirstTime() {
Intents.init()
try {
// leveraging currently created activityScenario to start another instance of self. (:
activityScenario.onActivity {
AppIntroActivity.maybeStart(it)
}

intended(hasComponent(AppIntroActivity::class.qualifiedName))
} finally {
Intents.release()
}
}

@Test
fun testMaybeStart_whenUserHasAlreadySeenIt() {
Intents.init()
try {
// when user has already seen the activity once, i.e., if the preference is present in the
// storage, maybeStart shouldn't start the activity.
Utils.withDefaultSharedPreferences(ApplicationProvider.getApplicationContext()) {
it.edit().putBoolean(AppIntroActivity.PREF_HAS_USER_SEEN_APP_INTRO, true).commit()
}

activityScenario.onActivity {
AppIntroActivity.maybeStart(it)
}

assertEquals(0, Intents.getIntents().size)
} finally {
Intents.release()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import androidx.test.espresso.contrib.NavigationViewActions
import androidx.test.espresso.intent.Intents
import androidx.test.espresso.intent.Intents.intended
import androidx.test.espresso.intent.matcher.IntentMatchers.filterEquals
import androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent
import androidx.test.espresso.matcher.RootMatchers.isDialog
import androidx.test.espresso.matcher.ViewMatchers.*
import androidx.test.ext.junit.runners.AndroidJUnit4
Expand All @@ -30,6 +31,7 @@ import io.mockk.*
import kotlinx.android.synthetic.main.activity_main.*
import org.greenrobot.eventbus.EventBus
import org.hamcrest.Matchers.allOf
import org.junit.After
import org.junit.Assert.*
import org.junit.Before
import org.junit.Rule
Expand All @@ -47,9 +49,21 @@ class MainActivityTest {

@Before
fun setup() {
// mark app intro as seen to run main activity tests in peace
Utils.withDefaultSharedPreferences(ApplicationProvider.getApplicationContext()) {
it.edit().putBoolean(AppIntroActivity.PREF_HAS_USER_SEEN_APP_INTRO, true).commit()
}

activityScenario = launch(MainActivity::class.java)
}

@After
fun teardown() {
Utils.withDefaultSharedPreferences(ApplicationProvider.getApplicationContext()) {
it.edit().clear().commit()
}
}

@Test
fun testIfSoundLibraryIsVisibleOnStart() {
activityScenario.onActivity {
Expand Down Expand Up @@ -173,6 +187,23 @@ class MainActivityTest {
}
}

@Test
fun testHelpMenuItem() {
Intents.init()
try {
onView(withId(R.id.layout_main))
.check(matches(isClosed(Gravity.START)))
.perform(DrawerActions.open(Gravity.START))

onView(withId(R.id.navigation_drawer))
.perform(NavigationViewActions.navigateTo(R.id.help))

intended(hasComponent(AppIntroActivity::class.qualifiedName))
} finally {
Intents.release()
}
}

@Test
fun testSupportDevelopmentMenuItem() {
onView(withId(R.id.layout_main))
Expand All @@ -199,26 +230,28 @@ class MainActivityTest {
@Test
fun testReportIssuesMenuItem() {
Intents.init()
onView(withId(R.id.layout_main))
.check(matches(isClosed(Gravity.START)))
.perform(DrawerActions.open(Gravity.START))
try {
onView(withId(R.id.layout_main))
.check(matches(isClosed(Gravity.START)))
.perform(DrawerActions.open(Gravity.START))

onView(withId(R.id.navigation_drawer))
.perform(NavigationViewActions.navigateTo(R.id.report_issue))

intended(
filterEquals(
Intent(
Intent.ACTION_VIEW, Uri.parse(
InstrumentationRegistry.getInstrumentation()
.targetContext
.getString(R.string.app_issues_url)
onView(withId(R.id.navigation_drawer))
.perform(NavigationViewActions.navigateTo(R.id.report_issue))

intended(
filterEquals(
Intent(
Intent.ACTION_VIEW, Uri.parse(
InstrumentationRegistry.getInstrumentation()
.targetContext
.getString(R.string.app_issues_url)
)
)
)
)
)

Intents.release()
} finally {
Intents.release()
}
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ class GenerateScreenshots {
@JvmStatic
@BeforeClass
fun setupAll() {
// prevent app intro from showing up
Utils.withDefaultSharedPreferences(ApplicationProvider.getApplicationContext()) {
it.edit().putBoolean(AppIntroActivity.PREF_HAS_USER_SEEN_APP_INTRO, true).commit()
}

// using mocks to save a few presets for screenshots
Preset.writeAllToUserPreferences(
ApplicationProvider.getApplicationContext(), arrayListOf(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.github.ashutoshgngwr.noice
import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.annotation.VisibleForTesting
import androidx.core.app.ActivityCompat
import androidx.fragment.app.Fragment
import com.github.appintro.AppIntro
Expand All @@ -12,7 +13,8 @@ import com.github.appintro.AppIntroPageTransformerType
class AppIntroActivity : AppIntro() {

companion object {
private const val PREF_HAS_USER_SEEN_APP_INTRO = "has_user_seen_app_intro"
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
const val PREF_HAS_USER_SEEN_APP_INTRO = "has_user_seen_app_intro"

/**
* [maybeStart] displays the [AppIntroActivity] if user hasn't seen it before.
Expand Down

0 comments on commit 749c30c

Please sign in to comment.