Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First commit for Espresso test #462

Open
wants to merge 62 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
71bef76
First commit for Espresso test
SyedaGini Jun 17, 2024
1f64a50
ci(ui-automation): Add Espresso for GiniBankSDKExample
SyedaGini Jul 2, 2024
df1c9ed
ci(ui-automation): Fix requested suggestions
SyedaGini Jul 4, 2024
2d7df38
ci(bank-sdk): Create dedicated workflow for running UI tests
a-szotyori Jul 8, 2024
72a9477
ci(bank-sdk): Fix UI tests workflow
a-szotyori Jul 9, 2024
6b8fcc6
ci(bank-sdk): Run the UI tests from the release workflow
a-szotyori Jul 9, 2024
d2ffcb8
ci(bank-sdk): Introduce new test and resource classes.
SyedaGini Jul 11, 2024
e66b5c5
Merge branch 'main' into test-automation
a-szotyori Jul 16, 2024
f9a0381
refactor(ui-automation): Use string resource ids for the Help Screen
a-szotyori Jul 16, 2024
2aea8c9
ci(bank-sdk): Try running the emulator for UI tests without `-no-window`
a-szotyori Jul 16, 2024
96fd6fc
refactor(ui-automation): Use resource ids for the Onboarding Screen T…
SyedaGini Jul 16, 2024
88dd996
ci(ui-automation): Introduce new screen and test classes
SyedaGini Jul 16, 2024
1de6c50
ci(bank-sdk): Revert running the emulator for UI tests without `-no-w…
a-szotyori Jul 16, 2024
e097417
ci: Update emulator Android API level for UI tests to 34
a-szotyori Aug 21, 2024
3b858f1
Merge branch 'main' into test-automation
a-szotyori Aug 21, 2024
e33a4b6
ci (ui-automation): Resolved CaptureScreen ui-tests and added Extract…
SyedaGini Aug 21, 2024
06d1db4
ci (ui-automation): Implemented test-cases for Extraction Screen
SyedaGini Aug 22, 2024
61e5d08
refactor(ui-automation): Added assertion for test-cases and updated e…
SyedaGini Aug 28, 2024
ac9ea32
ci (ui-automation): added function to ExtractionScreen
SyedaGinii Aug 29, 2024
6a17f53
ci (ui-automation): added ReviewScreenTests
SyedaGinii Aug 29, 2024
03e7594
ci (ui-automation): added test-cases for ImportPdfImageTest.kt
SyedaGinii Aug 30, 2024
050ddbe
refactor(ui-automation): Update PdfUploader.Kt and mutliple test-classes
SyedaGinii Sep 3, 2024
0673760
Added automation for Digital Invoice Screen
SyedaGinii Sep 9, 2024
0438289
ci(ui-automation): Push test documents to emulator before running UI …
a-szotyori Sep 9, 2024
beb4231
Address comments on PR
SyedaGinii Sep 11, 2024
ae34c24
Added automation for No Result Screen
SyedaGinii Sep 13, 2024
4d2b4ef
Fixed comments on PR
SyedaGinii Sep 13, 2024
d081257
Addressed comments on PR
SyedaGinii Sep 17, 2024
052c50f
Addressed comments on PR
SyedaGinii Sep 17, 2024
55088e6
Merge pull request #574 from gini/automation(no-result-screen)
SyedaGinii Sep 18, 2024
233ab1b
Added assertion for checks
SyedaGinii Sep 18, 2024
9e2869d
Merge branch 'test-automation' into automation(digital-invoice-screen)
SyedaGinii Sep 18, 2024
4d30565
Merge pull request #565 from gini/automation(digital-invoice-screen)
SyedaGinii Sep 18, 2024
b8c126f
Added automation for File Import Error Screen
SyedaGinii Sep 18, 2024
50fedb8
Remove toast assertion from test-cases
SyedaGinii Sep 20, 2024
2825b0b
Merge pull request #580 from gini/automation(file-import-error-dialog)
SyedaGinii Sep 23, 2024
0546575
Added automation for Edit Button on Digital Invoice Screen
SyedaGinii Sep 24, 2024
ff585d7
Addressed comment on PR
SyedaGinii Sep 24, 2024
623d37c
Merge pull request #587 from gini/automation(edit-button-digital-invo…
SyedaGinii Sep 25, 2024
6d90b76
Added automation for Error Screens
SyedaGinii Sep 30, 2024
1cc32a5
Added test-case number 2 with validations
SyedaGinii Oct 1, 2024
5b7c09e
Merge pull request #589 from gini/automation(errors-screen)
SyedaGinii Oct 1, 2024
501766c
ci: Add adb push command to CI
Oct 16, 2024
e2e03d8
ci: Add sample documents for UI tests
Oct 4, 2024
b51e147
fix:(bank-sdk) Add delay for tests. Add scroll search of file
Oct 17, 2024
ad442be
ci: Fix api-level of emulator
Oct 17, 2024
ade70e3
Merge pull request #600 from gini/PP-860_automation_test_files
GeraltRiv Oct 22, 2024
c566d77
ci: Fix failing tests for assertions
SyedaGinii Oct 22, 2024
16fb023
ci: Add scrollTo option
Oct 22, 2024
8f6dc36
Merge pull request #607 from gini/PM-122_test-automation_scroll_to
GeraltRiv Oct 23, 2024
46f2cec
Merge pull request #605 from gini/PM-122-fix-failing-test-cases
SyedaGinii Oct 23, 2024
6b3eae0
ci: Fix failing test of CaptureScreenTests > test2_flashEnabledWhenIm…
SyedaGinii Oct 23, 2024
ebffcfa
Merge pull request #608 from gini/PM-122-fix-failing-test-cases
SyedaGinii Oct 23, 2024
1d1263c
test: (bank-sdk) Add possibility to skip tests
Oct 28, 2024
be13e08
ci: Add possibility to skip tests
Oct 28, 2024
44fca15
Merge pull request #613 from gini/PM-122_test-automation_skip_photo_p…
GeraltRiv Dec 13, 2024
d4e4f65
bank-sdk test
Dec 16, 2024
26df142
bank-sdk test
Dec 16, 2024
8ade701
test
Dec 20, 2024
39aa1a0
test
Dec 20, 2024
8de117e
test
Dec 20, 2024
71e2e45
test
Dec 20, 2024
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
90 changes: 90 additions & 0 deletions .github/workflows/bank-sdk.check.ui-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
name: Check Bank SDK - UI Tests

# TODO: Update triggers to execute only on workflow_call (from the release workflow) and via manual triggering
# (UI tests are slow and we should not run them on every push)
on:
push:
paths:
- 'bank-sdk/**'
- 'capture-sdk/**'
- 'bank-api-library/**'
- 'core-api-library/**'
- 'gradle/**'
branches:
- '**'
tags-ignore:
- '**'
pull_request:
types: [opened, edited, reopened]
paths:
- 'bank-sdk/**'
- 'capture-sdk/**'
- 'bank-api-library/**'
- 'core-api-library/**'
- 'gradle/**'
workflow_call:
secrets:
GINI_MOBILE_TEST_CLIENT_SECRET:
required: true

jobs:
ui-tests:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v3

- name: setup java
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '17'
cache: 'gradle'

- name: enable KVM group perms for emulator
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm

- name: avd cache
uses: actions/cache@v4
id: avd-cache
with:
path: |
~/.android/avd/*
~/.android/adb*
key: avd-x86_64-34-${{ github.ref_name }}

- name: create avd and generate snapshot for caching
if: steps.avd-cache.outputs.cache-hit != 'true'
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 34
arch: x86_64
force-avd-creation: false
emulator-options: -no-window -gpu swiftshader_indirect -no-audio -no-boot-anim -camera-back emulated
disable-animations: true
script: echo "Generated AVD snapshot for caching."

- name: run example app instrumented tests
timeout-minutes: 20
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 34
arch: x86_64
force-avd-creation: false
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back emulated
disable-animations: true
script: >
adb uninstall net.gini.android.bank.sdk.exampleapp.test ;
./gradlew bank-sdk:example-app:connectedDevExampleAppDebugAndroidTest
-PclientId="gini-mobile-test"
-PclientSecret="${{ secrets.GINI_MOBILE_TEST_CLIENT_SECRET }}"

- name: archive instrumented test results
if: always()
uses: actions/upload-artifact@v3
with:
name: bank-sdk-example-app-instrumented-test-results
path: bank-sdk/example-app/build/outputs/androidTest-results/connected
15 changes: 0 additions & 15 deletions .github/workflows/bank-sdk.check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -126,21 +126,6 @@ jobs:
name: bank-sdk-instrumented-test-results
path: bank-sdk/sdk/build/outputs/androidTest-results/connected

- name: run example app instrumented tests
timeout-minutes: 20
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 33
arch: x86_64
force-avd-creation: false
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: true
script: >
adb uninstall net.gini.android.bank.sdk.exampleapp.test ;
./gradlew bank-sdk:example-app:connectedDevExampleAppDebugAndroidTest
-PclientId="gini-mobile-test"
-PclientSecret="${{ secrets.GINI_MOBILE_TEST_CLIENT_SECRET }}"

- name: archive instrumented test results
if: always()
uses: actions/upload-artifact@v3
Expand Down
7 changes: 6 additions & 1 deletion .github/workflows/bank-sdk.release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,14 @@ jobs:
secrets:
GINI_MOBILE_TEST_CLIENT_SECRET: ${{ secrets.GINI_MOBILE_TEST_CLIENT_SECRET }}
BANK_SDK_EXAMPLE_APP_KEYSTORE_PASSWORD: ${{ secrets.BANK_SDK_EXAMPLE_APP_KEYSTORE_PASSWORD }}

check-ui-tests:
uses: ./.github/workflows/bank-sdk.check.ui-tests.yml
secrets:
GINI_MOBILE_TEST_CLIENT_SECRET: ${{ secrets.GINI_MOBILE_TEST_CLIENT_SECRET }}

release:
needs: check
needs: [check, check-ui-tests]
runs-on: ubuntu-latest
steps:
- name: checkout
Expand Down
10 changes: 7 additions & 3 deletions bank-sdk/example-app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ android {

// Use the test runner with JUnit4 support
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
testInstrumentationRunnerArguments["clearPackageData"] = "true"

multiDexEnabled = true
}
Expand Down Expand Up @@ -189,25 +190,28 @@ dependencies {
implementation(libs.hilt.library)
implementation(libs.navigation.fragment.ktx)
implementation(libs.navigation.ui.ktx)
implementation(libs.androidx.test.junit.ktx)
kapt(libs.hilt.compiler)

implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.test.espresso.idlingresource)

testImplementation(libs.junit)

androidTestImplementation(libs.androidx.test.runner)
androidTestImplementation(libs.truth)
androidTestImplementation(libs.androidx.test.rules)
androidTestImplementation(libs.androidx.test.espresso.core)
androidTestImplementation(libs.androidx.test.espresso.intents)
androidTestImplementation(libs.androidx.test.runner)
androidTestImplementation(libs.androidx.test.core)
androidTestImplementation(libs.androidx.test.junit)
androidTestImplementation(libs.androidx.test.rules)
androidTestImplementation(libs.androidx.test.uiautomator)
androidTestImplementation(libs.mockito.core)
androidTestImplementation(libs.mockito.android)
androidTestImplementation(libs.androidx.multidex)
androidTestImplementation(libs.androidx.test.junit)

androidTestUtil(libs.androidx.test.orchestrator)

}

// this is needed because of Dagger-Hilt
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package net.gini.android.bank.sdk.exampleapp.ui.resources
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.UiSelector


class ImageUploader {
private val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
fun uploadImageFromPhotos() {
device.waitForIdle()
val selectPhoto = device.findObject(
UiSelector()
.className("android.widget.ImageView")
.resourceId("com.google.android.providers.media.module:id/icon_thumbnail")
)
if (selectPhoto != null) {
selectPhoto.click()
} else {
throw Exception("First photo not found")
}
}

fun clickAddButton() {
val addButton = device.findObject(
UiSelector()
.className("android.widget.Button")
.resourceId("com.google.android.providers.media.module:id/button_add")
)
if (addButton.exists()) {
addButton.click()
} else {
throw java.lang.Exception("Add button not found")
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package net.gini.android.bank.sdk.exampleapp.ui.resources

import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.UiSelector

class PdfUploader {
private val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
fun uploadPdfFromFiles() {
device.waitForIdle()
val tabTitle = device.findObject(UiSelector().className("android.widget.TextView").text("Recent"))
if (tabTitle.exists()) {
//Interact with hamburger menu
val hamburgerMenu = device.findObject(UiSelector().className("android.widget.ImageButton"))
hamburgerMenu.exists()
hamburgerMenu.click()
SyedaGinii marked this conversation as resolved.
Show resolved Hide resolved

// Click the 'Downloads' option
val downloadsOption = device.findObject(UiSelector()
.className("android.widget.TextView")
.text("Downloads"))
downloadsOption.exists()
downloadsOption.click()

//Select desired pdf file
val selectPdfFile = device.findObject(UiSelector().text("sample.pdf"))
selectPdfFile.click()
}
else {
//Select desired pdf file
val selectPdfFile = device.findObject(UiSelector().text("sample.pdf"))
selectPdfFile.click()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package net.gini.android.bank.sdk.exampleapp.ui.resources
import androidx.test.espresso.IdlingResource

class SimpleIdlingResource(private val waitTime: Long) : IdlingResource {

@Volatile
private var isIdleNow = true
private var callback: IdlingResource.ResourceCallback? = null

override fun getName() = SimpleIdlingResource::class.java.name

override fun isIdleNow() = isIdleNow

override fun registerIdleTransitionCallback(callback: IdlingResource.ResourceCallback) {
this.callback = callback
}

fun setIdleState(isIdleNow: Boolean) {
this.isIdleNow = isIdleNow
if (isIdleNow && callback != null) {
callback!!.onTransitionToIdle()
}
}

fun waitForIdle() {
isIdleNow = false
Thread {
try {
Thread.sleep(waitTime)
} catch (e: InterruptedException) {
e.printStackTrace()
}
setIdleState(true)
}.start()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package net.gini.android.bank.sdk.exampleapp.ui.screens

import android.app.Activity
import android.app.Instrumentation
import android.content.Intent
import android.net.Uri
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.intent.Intents.intending
import androidx.test.espresso.intent.matcher.IntentMatchers.hasAction
import androidx.test.espresso.intent.matcher.IntentMatchers.hasType
import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.withText
import org.hamcrest.Matchers.allOf

class CaptureScreen {
fun assertCameraTitle(): CaptureScreen {
onView(withId(net.gini.android.capture.R.id.gc_camera_title)).check(matches(withText(net.gini.android.capture.R.string.gc_camera_info_label_only_invoice)))
return this
}

fun clickCameraButton(): CaptureScreen {
onView(withId(net.gini.android.capture.R.id.gc_button_camera_trigger)).perform(click())
return this
}

fun clickHelpButton(): CaptureScreen {
onView(withId(net.gini.android.capture.R.id.gc_action_show_onboarding)).perform(click())
return this
}

fun clickCancelButton(): CaptureScreen {
onView(withId(net.gini.android.capture.R.id.gc_navigation_bar)).perform(click())
return this
}

fun assertFlashIconIsDisplayed(): CaptureScreen {
onView(withId(net.gini.android.capture.R.id.gc_camera_flash_button_subtitle)).check(
matches(
isDisplayed()
)
)
return this
}

fun assertFlashIconIsOn(): CaptureScreen {
onView(withId(net.gini.android.capture.R.id.gc_camera_flash_button_subtitle)).check(
matches(
withText(net.gini.android.capture.R.string.gc_camera_flash_on_subtitle)
)
)
return this
}

fun assertFlashIconIsOff(): CaptureScreen {
onView(withId(net.gini.android.capture.R.id.gc_camera_flash_button_subtitle)).check(
matches(
withText(net.gini.android.capture.R.string.gc_camera_flash_off_subtitle)
)
)
return this
}

fun clickFilesButton(): CaptureScreen {
onView(withId(net.gini.android.capture.R.id.gc_button_import_document)).perform(click())
return this
}

fun clickPhotos(): CaptureScreen {
onView(
allOf(withId(net.gini.android.capture.R.id.gc_app_label), withText("Photos")))
.perform(click())
return this
}

fun clickFiles(): CaptureScreen {
onView(
allOf(withId(net.gini.android.capture.R.id.gc_app_label), withText("Files")))
.perform(click())
return this
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package net.gini.android.bank.sdk.exampleapp.ui.screens

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.scrollTo
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.withText
import net.gini.android.bank.sdk.exampleapp.R

class ConfigurationScreen {

fun scrollToAnalysisText(): ConfigurationScreen {
onView(withText("Analysis"))
.perform(scrollTo())
return this
}

fun clickFlashToggleToEnable(): ConfigurationScreen {
onView(ViewMatchers.withId(R.id.switch_flashOnByDefault)).perform(closeSoftKeyboard(), click())
return this
}

fun assertFlashToggleIsDisable(): ConfigurationScreen {
onView(ViewMatchers.withId(R.id.switch_flashOnByDefault)).check(matches(isDisplayed()))
return this
}
}
Loading
Loading