Skip to content
This repository was archived by the owner on Jul 2, 2025. It is now read-only.

Commit 588851a

Browse files
fix code review
1 parent a06b60e commit 588851a

File tree

16 files changed

+426
-83
lines changed

16 files changed

+426
-83
lines changed

android/canonical/app/build.gradle

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ android {
2828
minifyEnabled false
2929
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
3030
}
31+
32+
staging {
33+
initWith(buildTypes.debug) // keep versionName and PIN from 'debug'
34+
defaultConfig.minSdkVersion 18
35+
}
3136
}
3237

3338
compileOptions {
@@ -38,6 +43,10 @@ android {
3843
kotlinOptions {
3944
jvmTarget = JavaVersion.VERSION_1_8.toString()
4045
}
46+
47+
testOptions {
48+
unitTests.returnDefaultValues = true
49+
}
4150
}
4251

4352
dependencies {
@@ -54,18 +63,56 @@ dependencies {
5463
implementation 'com.google.android.libraries.places:places:2.3.0'
5564
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
5665
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0'
57-
implementation 'com.google.firebase:firebase-analytics:17.4.4'
58-
implementation 'com.google.firebase:firebase-auth:19.3.2'
66+
implementation 'com.google.firebase:firebase-analytics-ktx:17.4.4'
67+
implementation 'com.google.firebase:firebase-auth-ktx:19.3.2'
5968
implementation 'com.google.firebase:firebase-firestore-ktx:21.4.3'
6069

6170
implementation 'com.google.android.material:material:1.1.0'
6271
implementation 'androidx.percentlayout:percentlayout:1.0.0'
6372
implementation 'androidx.cardview:cardview:1.0.0'
6473

74+
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.3'
75+
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.3'
76+
77+
debugImplementation "androidx.fragment:fragment-testing:1.2.5"
78+
6579
kapt 'com.android.databinding:compiler:3.1.4'
66-
testImplementation 'junit:junit:4.12'
80+
81+
// Core library
82+
androidTestImplementation 'androidx.test:core:1.0.0'
83+
84+
// AndroidJUnitRunner and JUnit Rules
85+
androidTestImplementation 'androidx.test:runner:1.1.0'
86+
androidTestImplementation 'androidx.test:rules:1.1.0'
87+
88+
89+
// Assertions
6790
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
91+
androidTestImplementation 'androidx.test.ext:truth:1.0.0'
92+
androidTestImplementation 'com.google.truth:truth:0.42'
93+
94+
// Espresso dependencies
6895
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
96+
androidTestImplementation 'com.android.support.test.uiautomator:uiautomator-v18:2.1.3'
97+
// androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.1.0'
98+
// androidTestImplementation 'androidx.test.espresso:espresso-intents:3.1.0'
99+
// androidTestImplementation 'androidx.test.espresso:espresso-accessibility:3.1.0'
100+
// androidTestImplementation 'androidx.test.espresso:espresso-web:3.1.0'
101+
// androidTestImplementation 'androidx.test.espresso.idling:idling-concurrent:3.1.0'
102+
103+
// The following Espresso dependency can be either "implementation"
104+
// or "androidTestImplementation", depending on whether you want the
105+
// dependency to appear on your APK's compile classpath or the test APK
106+
// classpath.
107+
androidTestImplementation 'androidx.test.espresso:espresso-idling-resource:3.1.0'
108+
109+
testImplementation 'junit:junit:4.12'
110+
testImplementation "androidx.arch.core:core-testing:2.1.0"
111+
testImplementation "androidx.test.ext:junit-ktx:1.1.1"
112+
testImplementation "androidx.test:core-ktx:1.2.0"
113+
testImplementation "org.robolectric:robolectric:4.1"
114+
115+
69116

70117

71118
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package com.google.samples.quickstart.canonical
2+
3+
import androidx.test.espresso.Espresso.onView
4+
import androidx.test.espresso.action.ViewActions
5+
import androidx.test.espresso.matcher.ViewMatchers
6+
import androidx.test.ext.junit.runners.AndroidJUnit4
7+
import androidx.test.platform.app.InstrumentationRegistry
8+
import androidx.test.rule.ActivityTestRule
9+
import androidx.test.rule.GrantPermissionRule
10+
import androidx.test.uiautomator.UiDevice
11+
import androidx.test.uiautomator.UiSelector
12+
import org.junit.Before
13+
import org.junit.Rule
14+
import org.junit.Test
15+
import org.junit.runner.RunWith
16+
17+
18+
@RunWith(AndroidJUnit4::class)
19+
class MapsFragmentTest {
20+
21+
@get:Rule
22+
var activityRule: ActivityTestRule<MainActivity>
23+
= ActivityTestRule(MainActivity::class.java)
24+
25+
@Rule @JvmField
26+
val grantPermissionRule: GrantPermissionRule = GrantPermissionRule.grant(android.Manifest.permission.ACCESS_FINE_LOCATION)
27+
28+
lateinit var device : UiDevice
29+
30+
@Before
31+
fun setup() {
32+
device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
33+
// Your google account must have logged in before test.
34+
// Otherwise the main page will be changed to login page,
35+
// and all the test will fail.
36+
// You only need to login the first time you open the app after
37+
// installing it.
38+
}
39+
40+
41+
@Test
42+
fun searchDestination() {
43+
onView(ViewMatchers.withId(R.id.bottom_navigation_item_map))
44+
.perform(ViewActions.click())
45+
Thread.sleep(3000)
46+
onView(ViewMatchers.withId(R.id.autocomplete_fragment))
47+
.perform(ViewActions.click())
48+
val new = device.findObject(UiSelector().text("Search"))
49+
new.text = "Central Park"
50+
Thread.sleep(2000)
51+
device.click(300,800)
52+
Thread.sleep(2000)
53+
}
54+
}
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
package com.google.samples.quickstart.canonical
2+
3+
import androidx.fragment.app.testing.launchFragmentInContainer
4+
import androidx.test.espresso.Espresso.onView
5+
import androidx.test.espresso.action.ViewActions.click
6+
import androidx.test.espresso.assertion.ViewAssertions.matches
7+
import androidx.test.espresso.matcher.RootMatchers.isDialog
8+
import androidx.test.espresso.matcher.RootMatchers.withDecorView
9+
import androidx.test.espresso.matcher.ViewMatchers.*
10+
import androidx.test.ext.junit.runners.AndroidJUnit4
11+
import androidx.test.rule.ActivityTestRule
12+
import org.hamcrest.core.IsNot.not
13+
import org.junit.Before
14+
import org.junit.Rule
15+
import org.junit.Test
16+
import org.junit.runner.RunWith
17+
18+
19+
@RunWith(AndroidJUnit4::class)
20+
class RunFragmentTest {
21+
22+
@get:Rule
23+
var activityRule: ActivityTestRule<MainActivity>
24+
= ActivityTestRule(MainActivity::class.java)
25+
26+
@Before
27+
fun makeSureYourAccountHasLoggedIn() {
28+
// Your google account must have logged in before test.
29+
// Otherwise the main page will be changed to login page,
30+
// and all the test will fail.
31+
// You only need to login the first time you open the app after
32+
// installing it.
33+
}
34+
35+
@Test
36+
fun startClickTest() {
37+
// launchFragmentInContainer<RunFragment>()
38+
onView(withId(R.id.start_pause_btn))
39+
.perform(click())
40+
Thread.sleep(2000)
41+
onView(withId(R.id.running_chronometer))
42+
.check(matches(withText("00:02")))
43+
}
44+
45+
@Test
46+
fun pauseClickTest() {
47+
// launchFragmentInContainer<RunFragment>()
48+
onView(withId(R.id.start_pause_btn))
49+
.perform(click())
50+
Thread.sleep(2000)
51+
onView(withId(R.id.start_pause_btn))
52+
.perform(click())
53+
Thread.sleep(2000)
54+
onView(withId(R.id.running_chronometer))
55+
.check(matches(withText("00:02")))
56+
}
57+
58+
@Test
59+
fun startAndPauseClickTest() {
60+
// launchFragmentInContainer<RunFragment>()
61+
onView(withId(R.id.start_pause_btn))
62+
.perform(click())
63+
Thread.sleep(2000)
64+
onView(withId(R.id.start_pause_btn))
65+
.perform(click())
66+
Thread.sleep(1000)
67+
onView(withId(R.id.start_pause_btn))
68+
.perform(click())
69+
Thread.sleep(1000)
70+
onView(withId(R.id.running_chronometer))
71+
.check(matches(withText("00:03")))
72+
}
73+
74+
@Test
75+
fun resetClickWhenWorkingTest() {
76+
// launchFragmentInContainer<RunFragment>()
77+
onView(withId(R.id.start_pause_btn))
78+
.perform(click())
79+
Thread.sleep(2000)
80+
onView(withId(R.id.reset_btn))
81+
.perform(click())
82+
onView(withId(R.id.running_chronometer))
83+
.check(matches(withText("00:00")))
84+
}
85+
86+
@Test
87+
fun resetClickWhenPausingTest() {
88+
// launchFragmentInContainer<RunFragment>()
89+
onView(withId(R.id.start_pause_btn))
90+
.perform(click())
91+
Thread.sleep(2000)
92+
onView(withId(R.id.running_chronometer))
93+
.check(matches(withText("00:02")))
94+
95+
onView(withId(R.id.start_pause_btn))
96+
.perform(click())
97+
Thread.sleep(2000)
98+
onView(withId(R.id.running_chronometer))
99+
.check(matches(withText("00:02")))
100+
101+
onView(withId(R.id.reset_btn))
102+
.perform(click())
103+
onView(withId(R.id.running_chronometer))
104+
.check(matches(withText("00:00")))
105+
}
106+
107+
@Test
108+
fun submitClickWhenWorkingTest() {
109+
// launchFragmentInContainer<RunFragment>()
110+
onView(withId(R.id.start_pause_btn))
111+
.perform(click())
112+
Thread.sleep(2000)
113+
onView(withId(R.id.running_chronometer))
114+
.check(matches(withText("00:02")))
115+
116+
onView(withId(R.id.submit_btn))
117+
.perform(click())
118+
onView(withText("Submission Confirm"))
119+
.inRoot(isDialog())
120+
.check(matches(isDisplayed()))
121+
}
122+
123+
@Test
124+
fun submitClickWhenPausingTest() {
125+
// launchFragmentInContainer<RunFragment>()
126+
onView(withId(R.id.start_pause_btn))
127+
.perform(click())
128+
Thread.sleep(2000)
129+
onView(withId(R.id.start_pause_btn))
130+
.perform(click())
131+
Thread.sleep(1000)
132+
133+
onView(withId(R.id.submit_btn))
134+
.perform(click())
135+
onView(withText("Submission Confirm"))
136+
.inRoot(isDialog())
137+
.check(matches(isDisplayed()))
138+
}
139+
140+
@Test
141+
fun submitClickBeforeWorkingTest() {
142+
onView(withId(R.id.submit_btn))
143+
.perform(click())
144+
onView(withText(R.string.submit_illegal))
145+
.inRoot(withDecorView(not(activityRule.activity.window.decorView)))
146+
.check(matches(isDisplayed()))
147+
}
148+
149+
}

android/canonical/app/src/main/AndroidManifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:tools="http://schemas.android.com/tools"
34
package="com.google.samples.quickstart.canonical">
45

56
<!--

android/canonical/app/src/main/java/com/google/samples/quickstart/canonical/LoginFragment.kt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@ import android.view.ViewGroup
1010
import androidx.fragment.app.activityViewModels
1111
import androidx.lifecycle.Observer
1212
import com.google.android.gms.common.SignInButton
13-
import com.google.firebase.firestore.SetOptions
14-
import com.google.firebase.firestore.ktx.firestore
15-
import com.google.firebase.ktx.Firebase
1613
import com.google.samples.quickstart.canonical.SignInViewModel.Companion.FIREBASE_AUTH_WITH_GOOGLE_FAIL
1714
import com.google.samples.quickstart.canonical.SignInViewModel.Companion.FIREBASE_AUTH_WITH_GOOGLE_SUCCESSFUL
1815
import com.google.samples.quickstart.canonical.SignInViewModel.Companion.GOOGLE_SIGN_IN_UNSUCCESSFUL

android/canonical/app/src/main/java/com/google/samples/quickstart/canonical/MainActivity.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ class MainActivity : AppCompatActivity() {
6464
else -> false
6565
}
6666
} catch (e:Exception) {
67-
Log.e(MAIN_ACTIVITY_TAG, "setOnNavigationItemSelectedListener failed", e)
67+
Log.e(MAIN_ACTIVITY_TAG, "Navigation failed", e)
6868
false
6969
}
7070
}
@@ -95,7 +95,9 @@ class MainActivity : AppCompatActivity() {
9595
Log.d(MAIN_ACTIVITY_TAG, "Already login")
9696
setupNavigationBar()
9797
// Init Profile
98-
profileVM.initAppUser(signInVM.getFirebaseAuthCurUser()!!)
98+
val firebaseUser = signInVM.getFirebaseAuthCurUser()
99+
profileVM.initAppUser(firebaseUser?.displayName ?: "", firebaseUser?.email ?: "",
100+
firebaseUser?.uid ?: "", firebaseUser?.photoUrl.toString())
99101
logoutUserObserver()
100102
}
101103

android/canonical/app/src/main/java/com/google/samples/quickstart/canonical/ProfileFragment.kt

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,16 @@ import android.view.LayoutInflater
66
import android.view.View
77
import android.view.ViewGroup
88
import android.widget.ImageButton
9+
import android.widget.ImageView
910
import android.widget.ListView
1011
import androidx.fragment.app.Fragment
1112
import androidx.fragment.app.activityViewModels
12-
import androidx.lifecycle.Observer
1313
import androidx.databinding.DataBindingUtil
1414
import com.google.samples.quickstart.canonical.databinding.FragmentProfileBinding
15+
import kotlinx.coroutines.CoroutineScope
16+
import kotlinx.coroutines.Dispatchers
17+
import kotlinx.coroutines.launch
18+
import kotlinx.android.synthetic.main.fragment_profile.*
1519

1620

1721
class ProfileFragment : Fragment() {
@@ -20,12 +24,14 @@ class ProfileFragment : Fragment() {
2024
private val profileVM : ProfileViewModel by activityViewModels()
2125
private lateinit var binding : FragmentProfileBinding
2226

23-
private fun downloadPhotoAndSetView(view: View) {
27+
private fun downloadPhotoAndSetView(userImage: ImageView) {
2428
val url = profileVM.getUserPhotoURL()
2529
if (url != "") {
2630
Log.d(PROFILE_TAG, url)
27-
DownloadImageTask(view.findViewById(R.id.usr_img))
28-
.execute(url)
31+
CoroutineScope(Dispatchers.Main).launch{
32+
val bmImage = profileVM.downloadImage(url)
33+
userImage.setImageBitmap(bmImage)
34+
}
2935
}
3036
}
3137

@@ -59,11 +65,11 @@ class ProfileFragment : Fragment() {
5965
refreshButton.setOnClickListener {
6066
profileVM.refreshUser(view.findViewById<ListView>(R.id.run_history_list_view).adapter
6167
as RunHistoryAdapter)
62-
downloadPhotoAndSetView(view)
68+
downloadPhotoAndSetView(usr_img)
6369
}
6470
setRunHistory()
6571
// update UI
66-
downloadPhotoAndSetView(view)
72+
downloadPhotoAndSetView(usr_img)
6773
}
6874

6975
companion object {

0 commit comments

Comments
 (0)