Added tests and testing in ci.
This commit is contained in:
parent
c14f47a74b
commit
b1e812314f
@ -35,6 +35,9 @@ android {
|
|||||||
disable 'InvalidPackage'
|
disable 'InvalidPackage'
|
||||||
}
|
}
|
||||||
vectorDrawables.useSupportLibrary = true
|
vectorDrawables.useSupportLibrary = true
|
||||||
|
|
||||||
|
// tests
|
||||||
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
@ -42,6 +45,11 @@ android {
|
|||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'),
|
proguardFiles getDefaultProguardFile('proguard-android.txt'),
|
||||||
'proguard-rules.pro'
|
'proguard-rules.pro'
|
||||||
}
|
}
|
||||||
|
debug {
|
||||||
|
buildConfigField "String", "LOGIN_URL", appLoginUrl
|
||||||
|
buildConfigField "String", "LOGIN_USERNAME", appLoginUsername
|
||||||
|
buildConfigField "String", "LOGIN_PASSWORD", appLoginPassword
|
||||||
|
}
|
||||||
}
|
}
|
||||||
flavorDimensions "build"
|
flavorDimensions "build"
|
||||||
productFlavors {
|
productFlavors {
|
||||||
@ -59,6 +67,15 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
// Testing
|
||||||
|
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
|
||||||
|
androidTestCompile 'com.android.support.test:runner:0.5'
|
||||||
|
// Espresso-contrib for DatePicker, RecyclerView, Drawer actions, Accessibility checks, CountingIdlingResource
|
||||||
|
androidTestCompile 'com.android.support.test.espresso:espresso-contrib:2.2.2'
|
||||||
|
// Espresso-intents for validation and stubbing of Intents
|
||||||
|
androidTestCompile 'com.android.support.test.espresso:espresso-intents:2.2.2'
|
||||||
|
|
||||||
|
|
||||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
|
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
|
||||||
|
|
||||||
@ -126,6 +143,7 @@ apply plugin: 'com.google.gms.google-services'
|
|||||||
|
|
||||||
afterEvaluate {
|
afterEvaluate {
|
||||||
initFabricPropertiesIfNeeded()
|
initFabricPropertiesIfNeeded()
|
||||||
|
initAppLoginPropertiesIfNeeded()
|
||||||
}
|
}
|
||||||
|
|
||||||
def initFabricPropertiesIfNeeded() {
|
def initFabricPropertiesIfNeeded() {
|
||||||
@ -137,4 +155,16 @@ def initFabricPropertiesIfNeeded() {
|
|||||||
entry(key: "apiKey", value: crashlyticsdemoApikey)
|
entry(key: "apiKey", value: crashlyticsdemoApikey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def initAppLoginPropertiesIfNeeded() {
|
||||||
|
def propertiesFile = file(System.getProperty("user.home") + '/.gradle/gradle.properties')
|
||||||
|
if (!propertiesFile.exists()) {
|
||||||
|
def commentMessage = "This is autogenerated local property from system environment to prevent key to be committed to source control."
|
||||||
|
ant.propertyfile(file: System.getProperty("user.home") + "/.gradle/gradle.properties", comment: commentMessage) {
|
||||||
|
entry(key: "appLoginUrl", value: System.getProperty("appLoginUrl"))
|
||||||
|
entry(key: "appLoginUsername", value: System.getProperty("appLoginUsername"))
|
||||||
|
entry(key: "appLoginPassword", value: System.getProperty("appLoginPassword"))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
package apps.amine.bou.readerforselfoss
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: test source adding
|
@ -0,0 +1,123 @@
|
|||||||
|
package apps.amine.bou.readerforselfoss
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.support.test.InstrumentationRegistry
|
||||||
|
import android.support.test.espresso.Espresso.onView
|
||||||
|
import android.support.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu
|
||||||
|
import android.support.test.espresso.action.ViewActions.*
|
||||||
|
import android.support.test.espresso.assertion.ViewAssertions.matches
|
||||||
|
import android.support.test.espresso.contrib.DrawerActions
|
||||||
|
import android.support.test.espresso.intent.Intents
|
||||||
|
import android.support.test.espresso.intent.Intents.intended
|
||||||
|
import android.support.test.espresso.intent.Intents.times
|
||||||
|
import android.support.test.espresso.intent.matcher.IntentMatchers.hasComponent
|
||||||
|
import android.support.test.espresso.matcher.ViewMatchers.*
|
||||||
|
import android.support.test.rule.ActivityTestRule
|
||||||
|
import android.support.test.runner.AndroidJUnit4
|
||||||
|
import android.view.KeyEvent
|
||||||
|
|
||||||
|
import com.mikepenz.aboutlibraries.ui.LibsActivity
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
|
import apps.amine.bou.readerforselfoss.settings.SettingsActivity
|
||||||
|
import apps.amine.bou.readerforselfoss.utils.Config
|
||||||
|
import org.junit.After
|
||||||
|
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
class HomeActivityEspressoTest {
|
||||||
|
lateinit var context: Context
|
||||||
|
|
||||||
|
@Rule @JvmField
|
||||||
|
val rule = ActivityTestRule(HomeActivity::class.java, true, false)
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun clearData() {
|
||||||
|
context = InstrumentationRegistry.getInstrumentation().targetContext
|
||||||
|
|
||||||
|
val editor =
|
||||||
|
context
|
||||||
|
.getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE)
|
||||||
|
.edit()
|
||||||
|
editor.clear()
|
||||||
|
|
||||||
|
editor.putString("url", BuildConfig.LOGIN_URL)
|
||||||
|
editor.putString("login", BuildConfig.LOGIN_USERNAME)
|
||||||
|
editor.putString("password", BuildConfig.LOGIN_PASSWORD)
|
||||||
|
|
||||||
|
editor.commit()
|
||||||
|
|
||||||
|
Intents.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun menuItems() {
|
||||||
|
|
||||||
|
rule.launchActivity(Intent())
|
||||||
|
|
||||||
|
onView(
|
||||||
|
withMenu(
|
||||||
|
id = R.id.action_search,
|
||||||
|
titleId = R.string.menu_home_search
|
||||||
|
)
|
||||||
|
).perform(click())
|
||||||
|
|
||||||
|
onView(withId(R.id.search_bar)).check(matches(isDisplayed()))
|
||||||
|
|
||||||
|
onView(withId(R.id.search_src_text)).perform(typeText("android"), pressKey(KeyEvent.KEYCODE_SEARCH), closeSoftKeyboard())
|
||||||
|
|
||||||
|
onView(withContentDescription(R.string.abc_toolbar_collapse_description)).perform(click())
|
||||||
|
|
||||||
|
|
||||||
|
onView(withMenu(id = R.id.readAll, titleId = R.string.readAll)).perform(click())
|
||||||
|
|
||||||
|
openActionBarOverflowOrOptionsMenu(context)
|
||||||
|
|
||||||
|
onView(withMenu(id = R.id.refresh, titleId = R.string.menu_home_refresh))
|
||||||
|
.perform(click())
|
||||||
|
|
||||||
|
openActionBarOverflowOrOptionsMenu(context)
|
||||||
|
|
||||||
|
onView(withText(R.string.action_disconnect)).perform(click())
|
||||||
|
|
||||||
|
intended(hasComponent(LoginActivity::class.java.name), times(1))
|
||||||
|
|
||||||
|
onView(isRoot()).perform(pressBack())
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun drawerTesting() {
|
||||||
|
|
||||||
|
rule.launchActivity(Intent())
|
||||||
|
|
||||||
|
onView(withId(R.id.material_drawer_layout)).perform(DrawerActions.open())
|
||||||
|
|
||||||
|
onView(withText(R.string.action_about)).perform(click())
|
||||||
|
intended(hasComponent(LibsActivity::class.java.name))
|
||||||
|
onView(isRoot()).perform(pressBack())
|
||||||
|
intended(hasComponent(HomeActivity::class.java.name))
|
||||||
|
|
||||||
|
onView(withId(R.id.material_drawer_layout)).perform(DrawerActions.open())
|
||||||
|
|
||||||
|
onView(withId(R.id.material_drawer_layout)).perform(DrawerActions.open())
|
||||||
|
onView(withText(R.string.drawer_action_clear)).perform(click())
|
||||||
|
|
||||||
|
// bug
|
||||||
|
//onView(withText(R.string.title_activity_settings)).perform(scrollTo(), click())
|
||||||
|
//intended(hasComponent(SettingsActivity::class.java.name))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: test articles opening and actions for cards and lists
|
||||||
|
|
||||||
|
@After
|
||||||
|
fun releaseIntents() {
|
||||||
|
Intents.release()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,121 @@
|
|||||||
|
package apps.amine.bou.readerforselfoss
|
||||||
|
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.support.test.InstrumentationRegistry.getInstrumentation
|
||||||
|
import android.support.test.espresso.Espresso.onView
|
||||||
|
import android.support.test.espresso.action.ViewActions.click
|
||||||
|
import android.support.test.espresso.assertion.ViewAssertions.matches
|
||||||
|
import android.support.test.espresso.intent.Intents
|
||||||
|
import android.support.test.espresso.intent.Intents.intended
|
||||||
|
import android.support.test.espresso.intent.Intents.times
|
||||||
|
import android.support.test.espresso.intent.matcher.IntentMatchers.*
|
||||||
|
import android.support.test.espresso.intent.matcher.UriMatchers.hasHost
|
||||||
|
import android.support.test.espresso.matcher.ViewMatchers.*
|
||||||
|
import android.support.test.rule.ActivityTestRule
|
||||||
|
import android.support.test.runner.AndroidJUnit4
|
||||||
|
|
||||||
|
import org.hamcrest.Matchers.allOf
|
||||||
|
import org.hamcrest.Matchers.equalTo
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
|
import apps.amine.bou.readerforselfoss.utils.Config
|
||||||
|
import org.junit.After
|
||||||
|
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
class IntroActivityEspressoTest {
|
||||||
|
|
||||||
|
@Rule @JvmField
|
||||||
|
val rule = ActivityTestRule(IntroActivity::class.java, true, false)
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun clearData() {
|
||||||
|
val editor =
|
||||||
|
getInstrumentation().targetContext
|
||||||
|
.getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE)
|
||||||
|
.edit()
|
||||||
|
editor.clear()
|
||||||
|
editor.commit()
|
||||||
|
|
||||||
|
Intents.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun nextEachTimes() {
|
||||||
|
|
||||||
|
rule.launchActivity(Intent())
|
||||||
|
|
||||||
|
onView(withText(R.string.intro_hello_title)).check(matches(isDisplayed()))
|
||||||
|
onView(withId(R.id.button_next)).perform(click())
|
||||||
|
onView(withText(R.string.intro_needs_selfoss_message)).check(matches(isDisplayed()))
|
||||||
|
onView(withId(R.id.button_next)).perform(click())
|
||||||
|
onView(withText(R.string.intro_all_set_message)).check(matches(isDisplayed()))
|
||||||
|
onView(withId(R.id.button_next)).perform(click())
|
||||||
|
|
||||||
|
intended(hasComponent(IntroActivity::class.java.name), times(1))
|
||||||
|
intended(hasComponent(LoginActivity::class.java.name), times(1))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun nextBackRandomTimes() {
|
||||||
|
val max = 5
|
||||||
|
val min = 1
|
||||||
|
|
||||||
|
val random = (Random().nextInt(max + 1 - min)) + min
|
||||||
|
|
||||||
|
rule.launchActivity(Intent())
|
||||||
|
|
||||||
|
onView(withText(R.string.intro_hello_title)).check(matches(isDisplayed()))
|
||||||
|
onView(withId(R.id.button_next)).perform(click())
|
||||||
|
|
||||||
|
repeat(random) {_ ->
|
||||||
|
onView(withText(R.string.intro_needs_selfoss_message)).check(matches(isDisplayed()))
|
||||||
|
onView(withId(R.id.button_next)).perform(click())
|
||||||
|
onView(withText(R.string.intro_all_set_message)).check(matches(isDisplayed()))
|
||||||
|
onView(withId(R.id.button_back)).perform(click())
|
||||||
|
}
|
||||||
|
|
||||||
|
onView(withId(R.id.button_next)).perform(click())
|
||||||
|
onView(withText(R.string.intro_all_set_message)).check(matches(isDisplayed()))
|
||||||
|
onView(withId(R.id.button_next)).perform(click())
|
||||||
|
|
||||||
|
intended(hasComponent(IntroActivity::class.java.name), times(1))
|
||||||
|
intended(hasComponent(LoginActivity::class.java.name), times(1))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun clickSelfossUrl() {
|
||||||
|
rule.launchActivity(Intent())
|
||||||
|
|
||||||
|
onView(withText(R.string.intro_hello_title)).check(matches(isDisplayed()))
|
||||||
|
|
||||||
|
onView(withId(R.id.button_next)).perform(click())
|
||||||
|
|
||||||
|
onView(withId(R.id.button_message)).perform(click())
|
||||||
|
|
||||||
|
intended(
|
||||||
|
allOf(
|
||||||
|
hasData(
|
||||||
|
hasHost(
|
||||||
|
equalTo("selfoss.aditu.de")
|
||||||
|
)
|
||||||
|
),
|
||||||
|
hasAction(Intent.ACTION_VIEW)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
fun releaseIntents() {
|
||||||
|
Intents.release()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,164 @@
|
|||||||
|
package apps.amine.bou.readerforselfoss
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.support.test.InstrumentationRegistry
|
||||||
|
import android.support.test.espresso.Espresso.onView
|
||||||
|
import android.support.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu
|
||||||
|
import android.support.test.espresso.action.ViewActions.*
|
||||||
|
import android.support.test.espresso.assertion.ViewAssertions.matches
|
||||||
|
import android.support.test.espresso.intent.Intents
|
||||||
|
import android.support.test.espresso.intent.Intents.intended
|
||||||
|
import android.support.test.espresso.intent.Intents.times
|
||||||
|
import android.support.test.espresso.intent.matcher.IntentMatchers.hasComponent
|
||||||
|
import android.support.test.espresso.matcher.ViewMatchers
|
||||||
|
import android.support.test.espresso.matcher.ViewMatchers.*
|
||||||
|
import android.support.test.rule.ActivityTestRule
|
||||||
|
import android.support.test.runner.AndroidJUnit4
|
||||||
|
|
||||||
|
import com.mikepenz.aboutlibraries.ui.LibsActivity
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
|
import apps.amine.bou.readerforselfoss.utils.Config
|
||||||
|
import org.junit.After
|
||||||
|
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
class LoginActivityEspressoTest {
|
||||||
|
|
||||||
|
@Rule @JvmField
|
||||||
|
val rule = ActivityTestRule(LoginActivity::class.java, true, false)
|
||||||
|
|
||||||
|
lateinit var context: Context
|
||||||
|
lateinit var url: String
|
||||||
|
lateinit var username: String
|
||||||
|
lateinit var password: String
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setUp() {
|
||||||
|
context = InstrumentationRegistry.getInstrumentation().targetContext
|
||||||
|
val editor =
|
||||||
|
context
|
||||||
|
.getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE)
|
||||||
|
.edit()
|
||||||
|
editor.clear()
|
||||||
|
editor.commit()
|
||||||
|
|
||||||
|
|
||||||
|
url = BuildConfig.LOGIN_URL
|
||||||
|
username = BuildConfig.LOGIN_USERNAME
|
||||||
|
password = BuildConfig.LOGIN_PASSWORD
|
||||||
|
|
||||||
|
Intents.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun menuItems() {
|
||||||
|
|
||||||
|
rule.launchActivity(Intent())
|
||||||
|
|
||||||
|
openActionBarOverflowOrOptionsMenu(context)
|
||||||
|
|
||||||
|
onView(withText(R.string.action_about)).perform(click())
|
||||||
|
|
||||||
|
intended(hasComponent(LibsActivity::class.java.name), times(1))
|
||||||
|
|
||||||
|
onView(isRoot()).perform(pressBack())
|
||||||
|
|
||||||
|
intended(hasComponent(LoginActivity::class.java.name))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun wrongLoginUrl() {
|
||||||
|
rule.launchActivity(Intent())
|
||||||
|
|
||||||
|
onView(withId(R.id.login_progress))
|
||||||
|
.check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE)))
|
||||||
|
|
||||||
|
onView(withId(R.id.url)).perform(click()).perform(typeText("WRONGURL"))
|
||||||
|
|
||||||
|
onView(withId(R.id.email_sign_in_button)).perform(click())
|
||||||
|
|
||||||
|
onView(withId(R.id.urlLayout)).check(matches(isHintOrErrorEnabled()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Add tests for multiple false urls with dialog
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun emptyAuthData() {
|
||||||
|
|
||||||
|
rule.launchActivity(Intent())
|
||||||
|
|
||||||
|
onView(withId(R.id.url)).perform(click()).perform(typeText(url), closeSoftKeyboard())
|
||||||
|
|
||||||
|
onView(withId(R.id.withLogin)).perform(click())
|
||||||
|
|
||||||
|
onView(withId(R.id.email_sign_in_button)).perform(click())
|
||||||
|
|
||||||
|
onView(withId(R.id.loginLayout)).check(matches(isHintOrErrorEnabled()))
|
||||||
|
onView(withId(R.id.passwordLayout)).check(matches(isHintOrErrorEnabled()))
|
||||||
|
|
||||||
|
onView(withId(R.id.login)).perform(click()).perform(typeText(username), closeSoftKeyboard())
|
||||||
|
|
||||||
|
onView(withId(R.id.passwordLayout)).check(matches(isHintOrErrorEnabled()))
|
||||||
|
|
||||||
|
onView(withId(R.id.email_sign_in_button)).perform(click())
|
||||||
|
|
||||||
|
onView(withId(R.id.passwordLayout)).check(
|
||||||
|
matches(
|
||||||
|
isHintOrErrorEnabled())
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun wrongAuthData() {
|
||||||
|
|
||||||
|
rule.launchActivity(Intent())
|
||||||
|
|
||||||
|
onView(withId(R.id.url)).perform(click()).perform(typeText(url), closeSoftKeyboard())
|
||||||
|
|
||||||
|
onView(withId(R.id.withLogin)).perform(click())
|
||||||
|
|
||||||
|
onView(withId(R.id.login)).perform(click()).perform(typeText(username), closeSoftKeyboard())
|
||||||
|
|
||||||
|
onView(withId(R.id.password)).perform(click()).perform(typeText("WRONGPASS"), closeSoftKeyboard())
|
||||||
|
|
||||||
|
onView(withId(R.id.email_sign_in_button)).perform(click())
|
||||||
|
|
||||||
|
onView(withId(R.id.urlLayout)).check(matches(isHintOrErrorEnabled()))
|
||||||
|
onView(withId(R.id.loginLayout)).check(matches(isHintOrErrorEnabled()))
|
||||||
|
onView(withId(R.id.passwordLayout)).check(matches(isHintOrErrorEnabled()))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun workingAuth() {
|
||||||
|
|
||||||
|
rule.launchActivity(Intent())
|
||||||
|
|
||||||
|
onView(withId(R.id.url)).perform(click()).perform(typeText(url), closeSoftKeyboard())
|
||||||
|
|
||||||
|
onView(withId(R.id.withLogin)).perform(click())
|
||||||
|
|
||||||
|
onView(withId(R.id.login)).perform(click()).perform(typeText(username), closeSoftKeyboard())
|
||||||
|
|
||||||
|
onView(withId(R.id.password)).perform(click()).perform(typeText(password), closeSoftKeyboard())
|
||||||
|
|
||||||
|
onView(withId(R.id.email_sign_in_button)).perform(click())
|
||||||
|
|
||||||
|
intended(hasComponent(HomeActivity::class.java.name))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
fun releaseIntents() {
|
||||||
|
Intents.release()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
package apps.amine.bou.readerforselfoss
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.SharedPreferences
|
||||||
|
import android.preference.PreferenceManager
|
||||||
|
import android.support.test.InstrumentationRegistry.getInstrumentation
|
||||||
|
import android.support.test.espresso.intent.Intents
|
||||||
|
import android.support.test.espresso.intent.Intents.intended
|
||||||
|
import android.support.test.espresso.intent.Intents.times
|
||||||
|
import android.support.test.espresso.intent.matcher.IntentMatchers.hasComponent
|
||||||
|
import android.support.test.rule.ActivityTestRule
|
||||||
|
import android.support.test.runner.AndroidJUnit4
|
||||||
|
import org.junit.After
|
||||||
|
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
class MainActivityEspressoTest {
|
||||||
|
|
||||||
|
lateinit var intent: Intent
|
||||||
|
lateinit var preferencesEditor: SharedPreferences.Editor
|
||||||
|
|
||||||
|
@Rule @JvmField
|
||||||
|
val rule = ActivityTestRule(MainActivity::class.java, true, false)
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setUp() {
|
||||||
|
intent = Intent()
|
||||||
|
val context = getInstrumentation().targetContext
|
||||||
|
|
||||||
|
// create a SharedPreferences editor
|
||||||
|
preferencesEditor = PreferenceManager.getDefaultSharedPreferences(context).edit()
|
||||||
|
|
||||||
|
Intents.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun checkFirstOpenLaunchesIntro() {
|
||||||
|
preferencesEditor.putBoolean("firstStart", true)
|
||||||
|
preferencesEditor.commit()
|
||||||
|
|
||||||
|
rule.launchActivity(intent)
|
||||||
|
|
||||||
|
intended(hasComponent(MainActivity::class.java.name))
|
||||||
|
intended(hasComponent(IntroActivity::class.java.name))
|
||||||
|
intended(hasComponent(LoginActivity::class.java.name), times(0))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun checkNotFirstOpenLaunchesLogin() {
|
||||||
|
preferencesEditor.putBoolean("firstStart", false)
|
||||||
|
preferencesEditor.commit()
|
||||||
|
|
||||||
|
rule.launchActivity(intent)
|
||||||
|
|
||||||
|
intended(hasComponent(MainActivity::class.java.name))
|
||||||
|
intended(hasComponent(LoginActivity::class.java.name))
|
||||||
|
intended(hasComponent(IntroActivity::class.java.name), times(0))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
fun releaseIntents() {
|
||||||
|
Intents.release()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package apps.amine.bou.readerforselfoss
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import android.support.design.widget.TextInputLayout
|
||||||
|
import android.support.test.espresso.matcher.ViewMatchers
|
||||||
|
|
||||||
|
import org.hamcrest.Description
|
||||||
|
import org.hamcrest.Matcher
|
||||||
|
import org.hamcrest.TypeSafeMatcher
|
||||||
|
import org.hamcrest.Matchers
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
fun isHintOrErrorEnabled(): Matcher<View> =
|
||||||
|
object : TypeSafeMatcher<View>() {
|
||||||
|
override fun describeTo(description: Description?) {}
|
||||||
|
|
||||||
|
override fun matchesSafely(item: View?): Boolean {
|
||||||
|
if (item !is TextInputLayout) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return item.isHintEnabled || item.isErrorEnabled
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun withMenu(id: Int, titleId: Int): Matcher<View> =
|
||||||
|
Matchers.anyOf(
|
||||||
|
ViewMatchers.withId(id),
|
||||||
|
ViewMatchers.withText(titleId)
|
||||||
|
)
|
@ -32,6 +32,7 @@
|
|||||||
<android.support.design.widget.TextInputLayout
|
<android.support.design.widget.TextInputLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/urlLayout"
|
||||||
>
|
>
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
|
@ -5,21 +5,20 @@
|
|||||||
<item android:id="@+id/action_search"
|
<item android:id="@+id/action_search"
|
||||||
android:title="@string/menu_home_search"
|
android:title="@string/menu_home_search"
|
||||||
android:icon="@drawable/ic_action_search"
|
android:icon="@drawable/ic_action_search"
|
||||||
app:showAsAction="ifRoom|collapseActionView"
|
app:showAsAction="always|collapseActionView"
|
||||||
app:actionViewClass="android.support.v7.widget.SearchView" />
|
app:actionViewClass="android.support.v7.widget.SearchView" />
|
||||||
|
|
||||||
<item android:id="@+id/readAll"
|
<item android:id="@+id/readAll"
|
||||||
android:icon="@drawable/ic_done_all_white_24dp"
|
android:icon="@drawable/ic_done_all_white_24dp"
|
||||||
android:title="@string/readAll"
|
android:title="@string/readAll"
|
||||||
android:orderInCategory="1"
|
android:orderInCategory="1"
|
||||||
app:showAsAction="ifRoom"/>
|
app:showAsAction="always"/>
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/refresh"
|
android:id="@+id/refresh"
|
||||||
android:icon="@drawable/ic_refresh"
|
android:icon="@drawable/ic_refresh"
|
||||||
android:orderInCategory="99"
|
android:orderInCategory="99"
|
||||||
android:title="@string/menu_home_refresh"
|
android:title="@string/menu_home_refresh" />
|
||||||
app:showAsAction="ifRoom" />
|
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_share_the_app"
|
android:id="@+id/action_share_the_app"
|
||||||
|
12
build.gradle
12
build.gradle
@ -30,3 +30,15 @@ allprojects {
|
|||||||
task clean(type: Delete) {
|
task clean(type: Delete) {
|
||||||
delete rootProject.buildDir
|
delete rootProject.buildDir
|
||||||
}
|
}
|
||||||
|
|
||||||
|
project.ext.preDexLibs = !project.hasProperty('disablePreDex')
|
||||||
|
|
||||||
|
subprojects {
|
||||||
|
project.plugins.whenPluginAdded { plugin ->
|
||||||
|
if ("com.android.build.gradle.AppPlugin".equals(plugin.class.name)) {
|
||||||
|
project.android.dexOptions.preDexLibraries = rootProject.ext.preDexLibs
|
||||||
|
} else if ("com.android.build.gradle.LibraryPlugin".equals(plugin.class.name)) {
|
||||||
|
project.android.dexOptions.preDexLibraries = rootProject.ext.preDexLibs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
15
circle.yml
15
circle.yml
@ -40,4 +40,17 @@ dependencies:
|
|||||||
|
|
||||||
test:
|
test:
|
||||||
override:
|
override:
|
||||||
- gradlew assemble -P crashlyticsdemoApikey=$FABRIC_API_KEY -P crashlyticsdemoApisecret=$FABRIC_API_SECRET
|
- (TERM="dumb" ./gradlew assemble --configure-on-demand --no-daemon -P crashlyticsdemoApikey=$FABRIC_API_KEY -P crashlyticsdemoApisecret=$FABRIC_API_SECRET -P appLoginUrl=$LOGIN_URL -P appLoginUsername=$LOGIN_USER_NAME -P appLoginPassword=$LOGIN_PASSWORD -PdisablePreDex -Pandroid.threadPoolSize=1 -Porg.gradle.parallel=false):
|
||||||
|
timeout: 720
|
||||||
|
- emulator -avd circleci-android22 -no-window:
|
||||||
|
background: true
|
||||||
|
parallel: true
|
||||||
|
- circle-android wait-for-boot
|
||||||
|
- sleep 30
|
||||||
|
- adb shell input keyevent 82
|
||||||
|
- adb shell input tap 650 300
|
||||||
|
- (TERM="dumb" ./gradlew connectedAndroidTest --configure-on-demand --no-daemon --stacktrace -P crashlyticsdemoApikey=$FABRIC_API_KEY -P crashlyticsdemoApisecret=$FABRIC_API_SECRET -P appLoginUrl=$LOGIN_URL -P appLoginUsername=$LOGIN_USER_NAME -P appLoginPassword=$LOGIN_PASSWORD -PdisablePreDex -Pandroid.threadPoolSize=1 -Porg.gradle.parallel=false):
|
||||||
|
timeout: 720
|
||||||
|
- cp -r app/build/outputs $CIRCLE_ARTIFACTS
|
||||||
|
- cp -r app/build/reports/androidTests $CIRCLE_ARTIFACTS
|
||||||
|
- cp -r app/build/outputs/androidTest-results/* $CIRCLE_TEST_REPORTS
|
||||||
|
Loading…
Reference in New Issue
Block a user