diff --git a/.github/workflows/build-apk.yml b/.github/workflows/build-apk.yml deleted file mode 100644 index 4e63952..0000000 --- a/.github/workflows/build-apk.yml +++ /dev/null @@ -1,46 +0,0 @@ -name: Build Gradle - -on: - push: - branches: - - master - - develop - -jobs: - build: - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v2 - - - name: Setup JDK 8 - uses: actions/setup-java@v1.4.3 - with: - java-version: 8 - - - name: Make gradlew executable - run: chmod +x ./gradlew - - - name: check ktlint format - run: ./gradlew ktlintCheck - - - name: assemble with Gradle - run: ./gradlew assemble - - - uses: r0adkll/sign-android-release@v1 - name: Sign app APK - # ID used to access action output - id: sign_app - with: - releaseDirectory: app/build/outputs/apk/release - signingKeyBase64: ${{ secrets.SIGNING_KEY }} - alias: ${{ secrets.ALIAS }} - keyStorePassword: ${{ secrets.KEY_STORE_PASSWORD }} - keyPassword: ${{ secrets.KEY_PASSWORD }} - env: - // override default build-tools version (29.0.3) -- optional - BUILD_TOOLS_VERSION: "30.0.2" - - - uses: actions/upload-artifact@v2 - with: - name: release apk - path: ${{steps.sign_app.outputs.signedReleaseFile}} diff --git a/app/build.gradle b/app/build.gradle index 7ad1cff..cd11abe 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -119,11 +119,11 @@ dependencies { implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.retrofit2:converter-gson:2.9.0' implementation 'com.squareup.retrofit2:converter-scalars:2.9.0' - implementation 'com.google.code.gson:gson:2.8.6' + implementation 'com.google.code.gson:gson:2.8.7' // OKHTTP implementation 'com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.2' - implementation 'com.squareup.okhttp3:okhttp' + implementation 'com.squareup.okhttp3:okhttp:5.0.0-alpha.2' implementation 'com.squareup.okhttp3:okhttp-tls:5.0.0-alpha.2' // TESTS @@ -136,7 +136,7 @@ dependencies { androidTestImplementation 'androidx.test:core:1.3.0' testImplementation 'androidx.test:core:1.3.0' testImplementation 'androidx.arch.core:core-testing:2.1.0' - testImplementation 'org.mockito:mockito-core:3.9.0' + testImplementation 'org.mockito:mockito-core:3.11.2' androidTestImplementation('com.android.support.test.espresso:espresso-contrib:3.0.2') { exclude group: 'com.android.support', module: 'appcompat' exclude module: 'support-annotations' diff --git a/build.gradle b/build.gradle index 61aa555..5fcace5 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = "1.5.10" + ext.kotlin_version = '1.5.20' repositories { google() mavenCentral() diff --git a/tests/CleanerFullTest.kt b/tests/CleanerFullTest.kt new file mode 100644 index 0000000..70896e5 --- /dev/null +++ b/tests/CleanerFullTest.kt @@ -0,0 +1,191 @@ +package com.sweven.blockcovid + +import android.view.View +import android.view.ViewGroup +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.action.ViewActions.click +import androidx.test.espresso.action.ViewActions.closeSoftKeyboard +import androidx.test.espresso.action.ViewActions.replaceText +import androidx.test.espresso.matcher.ViewMatchers.isDisplayed +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.withText +import androidx.test.filters.LargeTest +import androidx.test.rule.ActivityTestRule +import androidx.test.runner.AndroidJUnit4 +import org.hamcrest.Description +import org.hamcrest.Matcher +import org.hamcrest.Matchers.allOf +import org.hamcrest.TypeSafeMatcher +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@LargeTest +@RunWith(AndroidJUnit4::class) +class CleanerFullTest { + + @Rule + @JvmField + var mActivityTestRule = ActivityTestRule(StartActivity::class.java) + + @Test + fun cleanerFullRun() { + val textInputEditText = onView( + allOf( + withId(R.id.username), + isDisplayed() + ) + ) + textInputEditText.perform(replaceText("cleaner"), closeSoftKeyboard()) + + val textInputEditText2 = onView( + allOf( + withId(R.id.password), + isDisplayed() + ) + ) + textInputEditText2.perform(replaceText("password"), closeSoftKeyboard()) + + val extendedFloatingActionButton = onView( + allOf( + withId(R.id.login_button), + childAtPosition( + allOf( + withId(R.id.container), + childAtPosition( + withId(android.R.id.content), + 0 + ) + ), + 2 + ), + isDisplayed() + ) + ) + extendedFloatingActionButton.perform(click()) + + Thread.sleep(500) + + val extendedFloatingActionButton1 = onView( + allOf( + withId(R.id.refresh_button), + childAtPosition( + childAtPosition( + withId(R.id.nav_host_fragment_cleaner), + 0 + ), + 2 + ), + isDisplayed() + ) + ) + extendedFloatingActionButton1.perform(click()) + + Thread.sleep(500) + + val actionMenuItemView = onView( + allOf( + withId(R.id.navigation_login), + childAtPosition( + childAtPosition( + withId(R.id.action_bar), + 1 + ), + 0 + ), + isDisplayed() + ) + ) + actionMenuItemView.perform(click()) + + val materialButton = onView( + allOf( + withId(R.id.change_password_button), + childAtPosition( + childAtPosition( + withId(R.id.nav_host_fragment_cleaner), + 0 + ), + 1 + ), + isDisplayed() + ) + ) + materialButton.perform(click()) + + val textInputEditText3 = onView( + allOf( + withId(R.id.edit_old_password), + isDisplayed() + ) + ) + textInputEditText3.perform(replaceText("password"), closeSoftKeyboard()) + + val textInputEditText4 = onView( + allOf( + withId(R.id.edit_new_password), + isDisplayed() + ) + ) + textInputEditText4.perform(replaceText("password"), closeSoftKeyboard()) + + val textInputEditText5 = onView( + allOf( + withId(R.id.edit_repeat_password), + isDisplayed() + ) + ) + textInputEditText5.perform(replaceText("password"), closeSoftKeyboard()) + + val extendedFloatingActionButton3 = onView( + allOf( + withId(R.id.change_password_button), + childAtPosition( + childAtPosition( + withId(R.id.nav_host_fragment_cleaner), + 0 + ), + 3 + ), + isDisplayed() + ) + ) + extendedFloatingActionButton3.perform(click()) + + Thread.sleep(500) + + val materialButton2 = onView( + allOf( + withId(R.id.logout_button), withText("Logout"), + childAtPosition( + childAtPosition( + withId(R.id.nav_host_fragment_cleaner), + 0 + ), + 2 + ), + isDisplayed() + ) + ) + materialButton2.perform(click()) + } + + private fun childAtPosition( + parentMatcher: Matcher, + position: Int + ): Matcher { + + return object : TypeSafeMatcher() { + override fun describeTo(description: Description) { + description.appendText("Child at position $position in parent ") + parentMatcher.describeTo(description) + } + + public override fun matchesSafely(view: View): Boolean { + val parent = view.parent + return parent is ViewGroup && parentMatcher.matches(parent) && + view == parent.getChildAt(position) + } + } + } +} diff --git a/tests/UserFullTest.kt b/tests/UserFullTest.kt new file mode 100644 index 0000000..7c06839 --- /dev/null +++ b/tests/UserFullTest.kt @@ -0,0 +1,520 @@ +import android.view.View +import android.view.ViewGroup +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.UiController +import androidx.test.espresso.ViewAction +import androidx.test.espresso.action.ViewActions.click +import androidx.test.espresso.action.ViewActions.closeSoftKeyboard +import androidx.test.espresso.action.ViewActions.replaceText +import androidx.test.espresso.assertion.ViewAssertions +import androidx.test.espresso.matcher.ViewMatchers.isClickable +import androidx.test.espresso.matcher.ViewMatchers.isDisplayed +import androidx.test.espresso.matcher.ViewMatchers.isEnabled +import androidx.test.espresso.matcher.ViewMatchers.withClassName +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.withText +import androidx.test.filters.LargeTest +import androidx.test.rule.ActivityTestRule +import androidx.test.runner.AndroidJUnit4 +import com.sweven.blockcovid.R +import com.sweven.blockcovid.StartActivity +import org.hamcrest.Description +import org.hamcrest.Matcher +import org.hamcrest.Matchers.`is` +import org.hamcrest.Matchers.allOf +import org.hamcrest.TypeSafeMatcher +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@LargeTest +@RunWith(AndroidJUnit4::class) +class UserFullTest { + + @Rule + @JvmField + var mActivityTestRule = ActivityTestRule(StartActivity::class.java) + + @Test + fun userFullTest() { + val textInputEditText = onView( + allOf( + withId(R.id.username), + childAtPosition( + childAtPosition( + withId(R.id.username_layout), + 0 + ), + 0 + ), + isDisplayed() + ) + ) + textInputEditText.perform(replaceText("useradmin"), closeSoftKeyboard()) + + val textInputEditText2 = onView( + allOf( + withId(R.id.password), + isDisplayed() + ) + ) + textInputEditText2.perform(replaceText("password"), closeSoftKeyboard()) + + val extendedFloatingActionButton = onView( + allOf( + withId(R.id.login_button), + childAtPosition( + allOf( + withId(R.id.container), + childAtPosition( + withId(android.R.id.content), + 0 + ) + ), + 2 + ), + isDisplayed() + ) + ) + extendedFloatingActionButton.perform(click()) + + Thread.sleep(500) + + val bottomNavigationItemView = onView( + allOf( + withId(R.id.navigation_settings), + childAtPosition( + childAtPosition( + withId(R.id.nav_view), + 0 + ), + 2 + ), + isDisplayed() + ) + ) + bottomNavigationItemView.perform(click()) + + val switchMaterial = onView( + allOf( + withId(R.id.dark_theme_switch), + childAtPosition( + allOf( + withId(R.id.frame_layout_theme), + childAtPosition( + withClassName(`is`("androidx.constraintlayout.widget.ConstraintLayout")), + 0 + ) + ), + 1 + ), + isDisplayed() + ) + ) + switchMaterial.perform(click()) + + val switchMaterial2 = onView( + allOf( + withId(R.id.dark_theme_switch), + childAtPosition( + allOf( + withId(R.id.frame_layout_theme), + childAtPosition( + withClassName(`is`("androidx.constraintlayout.widget.ConstraintLayout")), + 0 + ) + ), + 1 + ), + isDisplayed() + ) + ) + switchMaterial2.perform(click()) + + val materialButton = onView( + allOf( + withId(R.id.nfc_reader_button), + childAtPosition( + childAtPosition( + withClassName(`is`("androidx.constraintlayout.widget.ConstraintLayout")), + 1 + ), + 1 + ), + isDisplayed() + ) + ) + materialButton.perform(click()) + + val bottomNavigationItemView2 = onView( + allOf( + withId(R.id.navigation_user_rooms), + childAtPosition( + childAtPosition( + withId(R.id.nav_view), + 0 + ), + 1 + ), + isDisplayed() + ) + ) + bottomNavigationItemView2.perform(click()) + + Thread.sleep(500) + + val materialCardView = onView( + allOf( + withId(R.id.room_card), + childAtPosition( + childAtPosition( + withId(R.id.room_recycler_user), + 0 + ), + 0 + ), + isDisplayed() + ) + ) + materialCardView.perform(click()) + + onView(withId(1)).check(ViewAssertions.matches(allOf(isEnabled(), isClickable()))).perform( + object : ViewAction { + + override fun getConstraints(): Matcher { + return isEnabled() + } + + override fun getDescription(): String { + return "click plus button" + } + + override fun perform(uiController: UiController, view: View) { + view.performClick() + } + } + ) + + Thread.sleep(500) + + val extendedFloatingActionButton1 = onView( + allOf( + withId(R.id.reserve_button), + childAtPosition( + childAtPosition( + withId(R.id.nav_host_fragment_user), + 0 + ), + 6 + ), + isDisplayed() + ) + ) + extendedFloatingActionButton1.perform(click()) + + Thread.sleep(500) + + val appCompatImageButton = onView( + allOf( + childAtPosition( + allOf( + withId(R.id.action_bar), + childAtPosition( + withId(R.id.action_bar_container), + 0 + ) + ), + 2 + ), + isDisplayed() + ) + ) + appCompatImageButton.perform(click()) + + val extendedFloatingActionButton2 = onView( + allOf( + withId(R.id.refresh_button), + childAtPosition( + childAtPosition( + withId(R.id.nav_host_fragment_user), + 0 + ), + 2 + ), + isDisplayed() + ) + ) + extendedFloatingActionButton2.perform(click()) + + Thread.sleep(500) + + val actionMenuItemView = onView( + allOf( + withId(R.id.navigation_login), + childAtPosition( + childAtPosition( + withId(R.id.action_bar), + 1 + ), + 0 + ), + isDisplayed() + ) + ) + actionMenuItemView.perform(click()) + + val materialButton7 = onView( + allOf( + withId(R.id.my_reservations_button), + childAtPosition( + childAtPosition( + withId(R.id.nav_host_fragment_user), + 0 + ), + 1 + ), + isDisplayed() + ) + ) + materialButton7.perform(click()) + + Thread.sleep(500) + + val materialCardView3 = onView( + allOf( + withId(R.id.reservation_card), + childAtPosition( + childAtPosition( + withId(R.id.reservation_recycler_user), + 0 + ), + 0 + ), + isDisplayed() + ) + ) + materialCardView3.perform(click()) + + Thread.sleep(500) + + val textInputEditText7 = onView( + allOf( + withId(R.id.edit_arrival_time), + childAtPosition( + childAtPosition( + withId(R.id.arrival_time), + 0 + ), + 1 + ), + isDisplayed() + ) + ) + textInputEditText7.perform(click()) + + val materialButton8 = onView( + allOf( + withId(R.id.material_timepicker_ok_button), withText("OK"), + childAtPosition( + childAtPosition( + withId(android.R.id.content), + 0 + ), + 6 + ), + isDisplayed() + ) + ) + materialButton8.perform(click()) + + val textInputEditText8 = onView( + allOf( + withId(R.id.edit_exit_time), + childAtPosition( + childAtPosition( + withId(R.id.exit_time), + 0 + ), + 1 + ), + isDisplayed() + ) + ) + textInputEditText8.perform(click()) + + Thread.sleep(500) + + val materialButton9 = onView( + allOf( + withId(R.id.material_timepicker_ok_button), withText("OK"), + childAtPosition( + childAtPosition( + withId(android.R.id.content), + 0 + ), + 6 + ), + isDisplayed() + ) + ) + materialButton9.perform(click()) + + val materialButton10 = onView( + allOf( + withId(R.id.edit_reservation_button), + childAtPosition( + childAtPosition( + withId(R.id.nav_host_fragment_user), + 0 + ), + 6 + ), + isDisplayed() + ) + ) + materialButton10.perform(click()) + + Thread.sleep(500) + + val materialButton11 = onView( + allOf( + withId(R.id.my_reservations_button), + childAtPosition( + childAtPosition( + withId(R.id.nav_host_fragment_user), + 0 + ), + 1 + ), + isDisplayed() + ) + ) + materialButton11.perform(click()) + + Thread.sleep(500) + + val materialCardView4 = onView( + allOf( + withId(R.id.reservation_card), + childAtPosition( + childAtPosition( + withId(R.id.reservation_recycler_user), + 0 + ), + 0 + ), + isDisplayed() + ) + ) + materialCardView4.perform(click()) + + Thread.sleep(500) + + val materialButton12 = onView( + allOf( + withId(R.id.remove_reservation_button), + childAtPosition( + childAtPosition( + withId(R.id.nav_host_fragment_user), + 0 + ), + 7 + ), + isDisplayed() + ) + ) + materialButton12.perform(click()) + + Thread.sleep(500) + + val materialButton13 = onView( + allOf( + withId(R.id.change_password_button), + childAtPosition( + childAtPosition( + withId(R.id.nav_host_fragment_user), + 0 + ), + 2 + ), + isDisplayed() + ) + ) + materialButton13.perform(click()) + + val textInputEditText9 = onView( + allOf( + withId(R.id.edit_old_password), + isDisplayed() + ) + ) + textInputEditText9.perform(replaceText("password"), closeSoftKeyboard()) + + val textInputEditText10 = onView( + allOf( + withId(R.id.edit_new_password), + isDisplayed() + ) + ) + textInputEditText10.perform(replaceText("password"), closeSoftKeyboard()) + + val textInputEditText11 = onView( + allOf( + withId(R.id.edit_repeat_password), + isDisplayed() + ) + ) + textInputEditText11.perform(replaceText("password"), closeSoftKeyboard()) + + val extendedFloatingActionButton3 = onView( + allOf( + withId(R.id.change_password_button), + childAtPosition( + childAtPosition( + withId(R.id.nav_host_fragment_user), + 0 + ), + 3 + ), + isDisplayed() + ) + ) + extendedFloatingActionButton3.perform(click()) + + Thread.sleep(500) + + val materialButton14 = onView( + allOf( + withId(R.id.logout_button), withText("Logout"), + childAtPosition( + childAtPosition( + withId(R.id.nav_host_fragment_user), + 0 + ), + 3 + ), + isDisplayed() + ) + ) + materialButton14.perform(click()) + } + + private fun childAtPosition( + parentMatcher: Matcher, + position: Int + ): Matcher { + + return object : TypeSafeMatcher() { + override fun describeTo(description: Description) { + description.appendText("Child at position $position in parent ") + parentMatcher.describeTo(description) + } + + public override fun matchesSafely(view: View): Boolean { + val parent = view.parent + return parent is ViewGroup && parentMatcher.matches(parent) && + view == parent.getChildAt(position) + } + } + } +}