Skip to content
This repository has been archived by the owner on Feb 1, 2021. It is now read-only.

Show list of accounts to enable self-funding #10

Open
wants to merge 36 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
70bb962
bump dependency versions and fix proguard and lint checks
mirceanis Jul 19, 2018
c782f83
add dependency to uport-sdk
mirceanis Jul 23, 2018
9df953b
add InMemorySharedPrefs test helper
mirceanis Jul 23, 2018
b1f4735
add an Onboarding manager that can decide if the app needs to show on…
mirceanis Jul 23, 2018
31f3063
add ApplicationTest - failing
mirceanis Jul 23, 2018
7add67f
add MainApplication with uPort sdk init
mirceanis Jul 23, 2018
21e60fb
add dependency injection basics using koin
mirceanis Jul 24, 2018
c7d5d7c
add an OnboardingActivity and a test to check it against user state (…
mirceanis Jul 24, 2018
92f3fba
adapt OnboardingStateTest to koin injection
mirceanis Jul 24, 2018
cb76d5d
add basic onboarding reroute with a test to check app startup when no…
mirceanis Jul 24, 2018
6b29ce2
ask uPort SDK to create an account during onboarding if one is not al…
mirceanis Jul 25, 2018
29e87a3
patch tests to work with new onboarding constraints
mirceanis Jul 25, 2018
ea55cf0
Merge pull request #6 from uport-project/feature/zh1/create-keypair-a…
mirceanis Jul 26, 2018
62affeb
add blank fragments to hold the rest of the onboarding screens
mirceanis Jul 30, 2018
764010c
add uport logo vector image
mirceanis Jul 30, 2018
508b993
add account creation progress using databinding
mirceanis Jul 30, 2018
8cec1c7
add configurable title to onboarding progress screen
mirceanis Jul 30, 2018
a330e18
make Onboarding progress screen cancelable
mirceanis Jul 30, 2018
3f1f571
add logo to create or recover screen
mirceanis Jul 30, 2018
099070e
add tos screen
mirceanis Jul 30, 2018
dd767e2
fix vector logos
mirceanis Jul 30, 2018
b3344f3
add account recovery functionality
mirceanis Jul 31, 2018
14fe7f1
add extra onboarding tests and refactor some old ones
mirceanis Jul 31, 2018
0ffc472
Merge pull request #7 from uport-project/feature/zh4/onboarding-screens
mirceanis Aug 17, 2018
1d4e31a
update some dependencies
mirceanis Aug 28, 2018
ce5a8b5
add account list item layout
mirceanis Aug 29, 2018
c02e829
add basic list adapter for accounts
mirceanis Aug 29, 2018
3562a35
add basic viewmodel for accounts
mirceanis Aug 31, 2018
adcfd29
update a bunch of layouts tied to dashboard
mirceanis Aug 31, 2018
476999e
add list of accounts to account fragment
mirceanis Aug 31, 2018
2897ced
display device address for account so that funding can be sent to the…
mirceanis Aug 31, 2018
048d266
update android-plugin & gradle wrapper to latest
mirceanis Sep 18, 2018
eba95f0
Merge remote-tracking branch 'origin/develop' into feature/zh5/displa…
mirceanis Sep 18, 2018
ac48712
clean-up after test so that app can still be run
mirceanis Sep 18, 2018
e7a2bba
add an assertion to check for default account being displayed in walk…
mirceanis Sep 18, 2018
0be0437
copy address to clipboard when account is clicked
mirceanis Sep 18, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlinx-serialization'
apply plugin: 'kotlin-kapt'

android {
compileSdkVersion compile_sdk_version
Expand Down Expand Up @@ -35,6 +36,19 @@ android {
}
}

lintOptions {
check 'Registered'
warningsAsErrors true
}

testOptions {
unitTests.returnDefaultValues = true
}

dataBinding {
enabled = true
}

packagingOptions {
exclude 'META-INF/DEPENDENCIES'
exclude 'META-INF/LICENSE'
Expand All @@ -50,34 +64,54 @@ android {

dependencies {

kapt(
"androidx.databinding:databinding-compiler:$android_gradle_plugin_version"
)

implementation(
"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version",
"org.jetbrains.kotlinx:kotlinx-serialization-runtime:$kotlin_serialization_version",

"com.android.support.constraint:constraint-layout:$constraint_layout_version",
"com.android.support:recyclerview-v7:$support_lib_version",
"com.android.support:appcompat-v7:$support_lib_version",
"com.android.support:cardview-v7:$support_lib_version",
"com.android.support:support-v4:$support_lib_version",
"com.android.support:design:$support_lib_version",

"com.github.uport-project:uport-android-sdk:$uport_sdk_version",

"com.journeyapps:zxing-android-embedded:$zxing_version",

"android.arch.lifecycle:extensions:$lifecycle_version",
"android.arch.navigation:navigation-fragment:$navigation_version",
"android.arch.navigation:navigation-ui:$navigation_version",

"org.koin:koin-android:$koin_version",
"org.koin:koin-android-architecture:$koin_version",
)

testImplementation(
"junit:junit:$junit_version",
"com.google.truth:truth:$google_truth_version",
"org.mockito:mockito-inline:$mockito_version",
"com.nhaarman:mockito-kotlin:$mockito_kotlin_version",
"org.koin:koin-test:$koin_version",
"com.github.dpreussler:android-tdd-utils:v0.1",
)

androidTestImplementation(
"com.android.support.test.espresso:espresso-core:$espresso_version",
"com.android.support.test.espresso:espresso-contrib:$espresso_version",
"com.android.support.test:runner:$test_runner_version",
"com.android.support.test:rules:$test_runner_version",
"com.nhaarman:mockito-kotlin:$mockito_kotlin_version",
"org.koin:koin-test:$koin_version",
)
}

kotlin {
experimental {
coroutines "enable"
}
}
6 changes: 6 additions & 0 deletions app/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,9 @@
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

-dontwarn javax.naming.**
-dontwarn java.lang.management.**
-dontwarn org.slf4j.**
-dontwarn android.**

This file was deleted.

36 changes: 32 additions & 4 deletions app/src/androidTest/java/me/uport/android/NavHostActivityTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ package me.uport.android
import android.support.test.espresso.Espresso.onView
import android.support.test.espresso.Espresso.pressBack
import android.support.test.espresso.action.ViewActions.click
import android.support.test.espresso.assertion.ViewAssertions.matches
import android.support.test.espresso.contrib.DrawerActions
import android.support.test.espresso.contrib.NavigationViewActions
import android.support.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition
Expand All @@ -30,31 +31,58 @@ import android.support.test.rule.ActivityTestRule
import android.support.test.rule.GrantPermissionRule
import android.support.test.runner.AndroidJUnit4
import android.support.v7.widget.RecyclerView.ViewHolder
import me.uport.android.onboarding.Onboarding
import me.uport.sdk.Uport
import me.uport.sdk.identity.Account
import org.hamcrest.Matchers.allOf
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith

import org.koin.standalone.inject
import org.koin.test.KoinTest

@LargeTest
@RunWith(AndroidJUnit4::class)
class NavHostActivityTest {
class NavHostActivityTest : KoinTest {

@Rule
@JvmField
var mActivityTestRule = ActivityTestRule(NavHostActivity::class.java)
var activityRule = ActivityTestRule(NavHostActivity::class.java, true, false)

@Rule
@JvmField
var mGrantPermissionRule: GrantPermissionRule =
GrantPermissionRule.grant(
"android.permission.CAMERA")

@Before
fun run_before_every_test() {

val uport: Uport by inject()
val onboarding: Onboarding by inject()

uport.defaultAccount = Account.blank.copy(deviceAddress = "0xsomething")
onboarding.markTosAccepted(true)
activityRule.launchActivity(null)
}

@After
fun run_after_every_test() {
val uPort by inject<Uport>()
uPort.defaultAccount?.let { uPort.deleteAccount(it) }
}

@Test
fun walkThroughSomeAppScreens() {

clickOnTab("Verifications")
clickOnTab("Accounts")

onView(withId(R.id.accountList)).check(matches(hasMinimumChildCount(1)))
onView(withText("0xsomething")).check(matches(isDisplayed()))

clickOnTab("Contacts")

//go to user profile
Expand Down Expand Up @@ -107,7 +135,7 @@ class NavHostActivityTest {

}

fun clickOnTab(tabText: String) {
private fun clickOnTab(tabText: String) {
val matcher = allOf(withText(tabText),
isDescendantOfA(withId(R.id.tabs)))
onView(matcher).perform(click())
Expand Down
133 changes: 133 additions & 0 deletions app/src/androidTest/java/me/uport/android/OnboardingFlowTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/*
* Copyright (c) 2018. uPort
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package me.uport.android

import android.support.annotation.IdRes
import android.support.test.espresso.Espresso.onView
import android.support.test.espresso.Espresso.pressBack
import android.support.test.espresso.NoActivityResumedException
import android.support.test.espresso.ViewInteraction
import android.support.test.espresso.action.ViewActions.click
import android.support.test.espresso.action.ViewActions.typeText
import android.support.test.espresso.assertion.ViewAssertions.matches
import android.support.test.espresso.matcher.ViewMatchers.*
import android.support.test.rule.ActivityTestRule
import android.support.test.runner.AndroidJUnit4
import android.widget.EditText
import android.widget.TextView
import junit.framework.Assert.assertTrue
import me.uport.android.onboarding.Onboarding
import org.hamcrest.Matchers.allOf
import org.hamcrest.Matchers.not
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.koin.standalone.inject
import org.koin.test.KoinTest


@RunWith(AndroidJUnit4::class)
class OnboardingFlowTest : KoinTest {

@JvmField
@Rule
val activityRule = ActivityTestRule(NavHostActivity::class.java, true, false)

@Before
fun run_before_every_test() {

val onboarding: Onboarding by inject()
onboarding.clearUser()

activityRule.launchActivity(null)
}


@Test
fun application_startup_with_blank_state_leads_to_onboarding_flow() {
onView(withId(R.id.onboarding_nav_host_frag)).check(matches(isDisplayed()))
}

@Test
fun walkthrough_account_recovery_happy_path() {

onView(withId(R.id.btn_accept)).perform(click())
onView(withId(R.id.btn_recover)).perform(click())

onEditTextWithinTilWithId(R.id.phrase_edit).perform(typeText("vessel ladder alter error federal sibling chat ability sun glass valve picture"))

onView(withId(R.id.btn_next)).perform(click())

onView(withText(R.string.identity_creation_success)).check(matches(isDisplayed()))
}

@Test
fun walkthrough_account_recovery_rejects_incomplete_phrases() {

onView(withId(R.id.btn_accept)).perform(click())
onView(withId(R.id.btn_recover)).perform(click())

onEditTextWithinTilWithId(R.id.phrase_edit).perform(typeText("this is a wrong phrase"))
onErrorViewWithinTilWithId(R.id.phrase_edit).check(matches(withText("phrase incomplete")))

onView(withId(R.id.btn_next)).perform(click())

//phrase editor is still displayed
onView(withId(R.id.phrase_edit)).check(matches(isDisplayed()))
}

@Test
fun walkthrough_account_creation() {
onView(withId(R.id.btn_accept)).perform(click())
onView(withId(R.id.btn_create)).perform(click())

onView(withText(R.string.identity_creation_success)).check(matches(isDisplayed()))
}

@Test
fun walkthrough_successful_onboarding_leads_to_dashboard() {
onView(withId(R.id.btn_accept)).perform(click())
onView(withId(R.id.btn_create)).perform(click())
onView(withId(R.id.btn_continue)).perform(click())
//goes to dashboard
onView(withId(R.id.nav_host_frag)).check(matches(isDisplayed()))
try {
//and does not go back
pressBack()
} catch (ex: Exception) {
assertTrue(ex is NoActivityResumedException)
}
}

fun onEditTextWithinTilWithId(@IdRes textInputLayoutId: Int): ViewInteraction {
//assuming TextInputLayout has only one EditText
return onView(allOf(
isDescendantOfA(withId(textInputLayoutId)),
isAssignableFrom(EditText::class.java))
)
}

fun onErrorViewWithinTilWithId(@IdRes textInputLayoutId: Int): ViewInteraction {
//assuming TextInputLayout has only one descendant of type TextView that is not also EditText
return onView(allOf(
isDescendantOfA(withId(textInputLayoutId)),
not(isAssignableFrom(EditText::class.java)),
isAssignableFrom(TextView::class.java)))
}
}
33 changes: 33 additions & 0 deletions app/src/androidTest/java/me/uport/android/fakes/MockUportSDK.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright (c) 2018. uPort
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package me.uport.android.fakes

import android.support.test.InstrumentationRegistry
import me.uport.sdk.Uport
import org.koin.dsl.module.applicationContext


val mockUport = Uport

val mockUportSDKModule = applicationContext {
bean { Uport.Configuration().setApplicationContext(InstrumentationRegistry.getTargetContext()) }
bean {
mockUport.initialize(get())
mockUport
}
}
Loading