[#598] Refactoring ScreenshotTest to a separate test module
* Temporary enable FTL test * Enable emulator.wft tests for ui-integration-test module on CI * Test Fladle configuration for ui-integration-test module * Fix Fladle for ui-integration-test module * Rename ui-integration-test module flade configuration * Disable again FTL action from PRs * Clear support for FTL from ui-integration-test module * Refactor the emulator.wtf support across our modules. * [#598] Refactoring ScreenshotTest to a separate test module - Created a new com.android.test module - Moved our ScreenShotTest to the separate module - Enabled the new module for emulator.wtf service - Cleaned up the app module from ScreenShotTest - Updated Architecture and Setup documentation * Exclude pure test modules from Detekt check * Improved run configurations - Changed common emulator.wtf run configuration name to align with the rest of our configurations - Added configuration for the new screenshot tests module - Updated documentation * Linked code TODO * Disabled self-instrumenting - As it appeared to be the way how to leverage the app module Gradle settings in this new module - App name is taken from app module settings - Screenshot tests works with pseudolocales again
This commit is contained in:
parent
2c14ee8bd3
commit
4eddf4e74b
|
@ -294,7 +294,7 @@ jobs:
|
||||||
ORG_GRADLE_PROJECT_ZCASH_DEBUG_APP_NAME_SUFFIX: ""
|
ORG_GRADLE_PROJECT_ZCASH_DEBUG_APP_NAME_SUFFIX: ""
|
||||||
ORG_GRADLE_PROJECT_ZCASH_EMULATOR_WTF_API_KEY: ${{ secrets.EMULATOR_WTF_API_KEY }}
|
ORG_GRADLE_PROJECT_ZCASH_EMULATOR_WTF_API_KEY: ${{ secrets.EMULATOR_WTF_API_KEY }}
|
||||||
run: |
|
run: |
|
||||||
./gradlew testDebugWithEmulatorWtf :app:testZcashmainnetDebugWithEmulatorWtf :ui-integration-test:testZcashmainnetDebugWithEmulatorWtf
|
./gradlew testDebugWithEmulatorWtf :app:testZcashmainnetDebugWithEmulatorWtf :ui-integration-test:testZcashmainnetDebugWithEmulatorWtf :ui-screenshot-test:testZcashmainnetDebugWithEmulatorWtf
|
||||||
- name: Collect Artifacts
|
- name: Collect Artifacts
|
||||||
if: ${{ always() }}
|
if: ${{ always() }}
|
||||||
timeout-minutes: 1
|
timeout-minutes: 1
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="testOnEmulatorWtf" type="GradleRunConfiguration" factoryName="Gradle">
|
<configuration default="false" name="test_with_emulatorWtf" type="GradleRunConfiguration" factoryName="Gradle">
|
||||||
<ExternalSystemSettings>
|
<ExternalSystemSettings>
|
||||||
<option name="executionName" />
|
<option name="executionName" />
|
||||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||||
|
@ -13,6 +13,7 @@
|
||||||
<option value="testDebugWithEmulatorWtf" />
|
<option value="testDebugWithEmulatorWtf" />
|
||||||
<option value=":app:testZcashmainnetDebugWithEmulatorWtf" />
|
<option value=":app:testZcashmainnetDebugWithEmulatorWtf" />
|
||||||
<option value=":ui-integration-test:testZcashmainnetDebugWithEmulatorWtf" />
|
<option value=":ui-integration-test:testZcashmainnetDebugWithEmulatorWtf" />
|
||||||
|
<option value=":ui-screenshot-test:testZcashmainnetDebugWithEmulatorWtf" />
|
||||||
</list>
|
</list>
|
||||||
</option>
|
</option>
|
||||||
<option name="vmOptions" />
|
<option name="vmOptions" />
|
|
@ -0,0 +1,57 @@
|
||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="ui-screenshot-test:connectedCheck" type="AndroidTestRunConfigurationType" factoryName="Android Instrumented Tests">
|
||||||
|
<module name="zcash-android-app.ui-screenshot-test" />
|
||||||
|
<option name="TESTING_TYPE" value="0" />
|
||||||
|
<option name="METHOD_NAME" value="" />
|
||||||
|
<option name="CLASS_NAME" value="" />
|
||||||
|
<option name="PACKAGE_NAME" value="" />
|
||||||
|
<option name="INSTRUMENTATION_RUNNER_CLASS" value="" />
|
||||||
|
<option name="EXTRA_OPTIONS" value="" />
|
||||||
|
<option name="INCLUDE_GRADLE_EXTRA_OPTIONS" value="true" />
|
||||||
|
<option name="RETENTION_ENABLED" value="No" />
|
||||||
|
<option name="RETENTION_MAX_SNAPSHOTS" value="2" />
|
||||||
|
<option name="RETENTION_COMPRESS_SNAPSHOTS" value="false" />
|
||||||
|
<option name="CLEAR_LOGCAT" value="false" />
|
||||||
|
<option name="SHOW_LOGCAT_AUTOMATICALLY" value="false" />
|
||||||
|
<option name="SKIP_NOOP_APK_INSTALLATIONS" value="true" />
|
||||||
|
<option name="FORCE_STOP_RUNNING_APP" value="true" />
|
||||||
|
<option name="INSPECTION_WITHOUT_ACTIVITY_RESTART" value="false" />
|
||||||
|
<option name="TARGET_SELECTION_MODE" value="DEVICE_AND_SNAPSHOT_COMBO_BOX" />
|
||||||
|
<option name="SELECTED_CLOUD_MATRIX_CONFIGURATION_ID" value="-1" />
|
||||||
|
<option name="SELECTED_CLOUD_MATRIX_PROJECT_ID" value="" />
|
||||||
|
<option name="DEBUGGER_TYPE" value="Auto" />
|
||||||
|
<Auto>
|
||||||
|
<option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
|
||||||
|
<option name="SHOW_STATIC_VARS" value="true" />
|
||||||
|
<option name="WORKING_DIR" value="" />
|
||||||
|
<option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
|
||||||
|
<option name="SHOW_OPTIMIZED_WARNING" value="true" />
|
||||||
|
</Auto>
|
||||||
|
<Hybrid>
|
||||||
|
<option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
|
||||||
|
<option name="SHOW_STATIC_VARS" value="true" />
|
||||||
|
<option name="WORKING_DIR" value="" />
|
||||||
|
<option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
|
||||||
|
<option name="SHOW_OPTIMIZED_WARNING" value="true" />
|
||||||
|
</Hybrid>
|
||||||
|
<Java />
|
||||||
|
<Native>
|
||||||
|
<option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
|
||||||
|
<option name="SHOW_STATIC_VARS" value="true" />
|
||||||
|
<option name="WORKING_DIR" value="" />
|
||||||
|
<option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
|
||||||
|
<option name="SHOW_OPTIMIZED_WARNING" value="true" />
|
||||||
|
</Native>
|
||||||
|
<Profilers>
|
||||||
|
<option name="ADVANCED_PROFILING_ENABLED" value="false" />
|
||||||
|
<option name="STARTUP_PROFILING_ENABLED" value="false" />
|
||||||
|
<option name="STARTUP_CPU_PROFILING_ENABLED" value="false" />
|
||||||
|
<option name="STARTUP_CPU_PROFILING_CONFIGURATION_NAME" value="Java/Kotlin Method Sample (legacy)" />
|
||||||
|
<option name="STARTUP_NATIVE_MEMORY_PROFILING_ENABLED" value="false" />
|
||||||
|
<option name="NATIVE_MEMORY_SAMPLE_RATE_BYTES" value="2048" />
|
||||||
|
</Profilers>
|
||||||
|
<method v="2">
|
||||||
|
<option name="Android.Gradle.BeforeRunTask" enabled="true" />
|
||||||
|
</method>
|
||||||
|
</configuration>
|
||||||
|
</component>
|
|
@ -10,9 +10,6 @@ plugins {
|
||||||
|
|
||||||
val packageName = project.property("ZCASH_RELEASE_PACKAGE_NAME").toString()
|
val packageName = project.property("ZCASH_RELEASE_PACKAGE_NAME").toString()
|
||||||
|
|
||||||
// Force orchestrator to be used for this module, because we need cleared state to generate screenshots
|
|
||||||
val isOrchestratorEnabled = true
|
|
||||||
|
|
||||||
val testnetNetworkName = "Testnet"
|
val testnetNetworkName = "Testnet"
|
||||||
|
|
||||||
android {
|
android {
|
||||||
|
@ -26,19 +23,9 @@ android {
|
||||||
versionCode = project.property("ZCASH_VERSION_CODE").toString().toInt()
|
versionCode = project.property("ZCASH_VERSION_CODE").toString().toInt()
|
||||||
versionName = project.property("ZCASH_VERSION_NAME").toString()
|
versionName = project.property("ZCASH_VERSION_NAME").toString()
|
||||||
|
|
||||||
if (isOrchestratorEnabled) {
|
|
||||||
testInstrumentationRunnerArguments["clearPackageData"] = "true"
|
|
||||||
}
|
|
||||||
|
|
||||||
testInstrumentationRunner = "co.electriccoin.zcash.test.ZcashUiTestRunner"
|
testInstrumentationRunner = "co.electriccoin.zcash.test.ZcashUiTestRunner"
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isOrchestratorEnabled) {
|
|
||||||
testOptions {
|
|
||||||
execution = "ANDROIDX_TEST_ORCHESTRATOR"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
isCoreLibraryDesugaringEnabled = true
|
isCoreLibraryDesugaringEnabled = true
|
||||||
}
|
}
|
||||||
|
@ -182,16 +169,9 @@ dependencies {
|
||||||
implementation(projects.spackleAndroidLib)
|
implementation(projects.spackleAndroidLib)
|
||||||
implementation(projects.uiLib)
|
implementation(projects.uiLib)
|
||||||
|
|
||||||
androidTestImplementation(libs.androidx.compose.test.junit)
|
|
||||||
androidTestImplementation(libs.androidx.navigation.compose)
|
|
||||||
androidTestImplementation(libs.androidx.uiAutomator)
|
|
||||||
androidTestImplementation(libs.bundles.androidx.test)
|
|
||||||
androidTestImplementation(projects.sdkExtLib)
|
|
||||||
androidTestImplementation(projects.sdkExtUiLib)
|
|
||||||
androidTestImplementation(projects.spackleLib)
|
|
||||||
androidTestImplementation(projects.testLib)
|
androidTestImplementation(projects.testLib)
|
||||||
|
|
||||||
if (isOrchestratorEnabled) {
|
if (project.property("IS_USE_TEST_ORCHESTRATOR").toString().toBoolean()) {
|
||||||
androidTestUtil(libs.androidx.test.orchestrator) {
|
androidTestUtil(libs.androidx.test.orchestrator) {
|
||||||
artifact {
|
artifact {
|
||||||
type = "apk"
|
type = "apk"
|
||||||
|
@ -312,7 +292,3 @@ fladle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
emulatorwtf {
|
|
||||||
directoriesToPull.set(listOf("/sdcard/googletest/test_outputfiles"))
|
|
||||||
}
|
|
||||||
|
|
|
@ -24,6 +24,9 @@ plugins {
|
||||||
id("secant.rosetta-conventions")
|
id("secant.rosetta-conventions")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val uiIntegrationModuleName: String = projects.uiIntegrationTest.name
|
||||||
|
val uiScreenshotModuleName: String = projects.uiScreenshotTest.name
|
||||||
|
|
||||||
tasks {
|
tasks {
|
||||||
register("detektAll", io.gitlab.arturbosch.detekt.Detekt::class) {
|
register("detektAll", io.gitlab.arturbosch.detekt.Detekt::class) {
|
||||||
parallel = true
|
parallel = true
|
||||||
|
@ -35,6 +38,8 @@ tasks {
|
||||||
exclude("**/commonTest/**")
|
exclude("**/commonTest/**")
|
||||||
exclude("**/jvmTest/**")
|
exclude("**/jvmTest/**")
|
||||||
exclude("**/androidTest/**")
|
exclude("**/androidTest/**")
|
||||||
|
// To exclude the whole pure test modules
|
||||||
|
exclude(uiIntegrationModuleName, uiScreenshotModuleName)
|
||||||
// To regenerate the config, run the task `detektGenerateConfig`
|
// To regenerate the config, run the task `detektGenerateConfig`
|
||||||
config.setFrom(files("${rootProject.projectDir}/tools/detekt.yml"))
|
config.setFrom(files("${rootProject.projectDir}/tools/detekt.yml"))
|
||||||
buildUponDefaultConfig = true
|
buildUponDefaultConfig = true
|
||||||
|
@ -134,5 +139,6 @@ kover {
|
||||||
"ui-design-lib",
|
"ui-design-lib",
|
||||||
"ui-integration-test",
|
"ui-integration-test",
|
||||||
"ui-lib",
|
"ui-lib",
|
||||||
|
"ui-screenshot-test",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,20 +26,22 @@ The logical components of the app are implemented as a number of Gradle modules.
|
||||||
|
|
||||||
* `app` — Compiles all of the modules together into the final application. This module contains minimal actual code. Note that the Java package structure for this module is under `co.electriccoin.zcash.app` while the Android package name is `co.electriccoin.zcash`.
|
* `app` — Compiles all of the modules together into the final application. This module contains minimal actual code. Note that the Java package structure for this module is under `co.electriccoin.zcash.app` while the Android package name is `co.electriccoin.zcash`.
|
||||||
* `build-info-lib` — Collects information from the build environment (e.g. Git SHA, Git commit count) and compiles them into the application. Can also be used for injection of API keys or other secrets.
|
* `build-info-lib` — Collects information from the build environment (e.g. Git SHA, Git commit count) and compiles them into the application. Can also be used for injection of API keys or other secrets.
|
||||||
* `crash` — For collecting and reporting exceptions and crashes
|
* crash — For collecting and reporting exceptions and crashes
|
||||||
* `crash-lib` — Common crash collection logic for Kotlin and JVM. This is not fully-featured by itself, but the long-term plan is multiplatform support.
|
* `crash-lib` — Common crash collection logic for Kotlin and JVM. This is not fully-featured by itself, but the long-term plan is multiplatform support.
|
||||||
* `crash-android-lib` — Android-specific crash collection logic, built on top of the common and JVM implementation in `crash-lib`
|
* `crash-android-lib` — Android-specific crash collection logic, built on top of the common and JVM implementation in `crash-lib`
|
||||||
* ui
|
* ui
|
||||||
* `ui-design` — Contains UI theme elements only. Besides offering modularization, this allows for hiding of some Material Design components behind our own custom components.
|
* `ui-design` — Contains UI theme elements only. Besides offering modularization, this allows for hiding of some Material Design components behind our own custom components.
|
||||||
* `ui-lib` — User interface that the user interacts with. This contains 99% of the UI code, along with localizations, icons, and other assets.
|
* `ui-lib` — User interface that the user interacts with. This contains 99% of the UI code, along with localizations, icons, and other assets.
|
||||||
|
* ui-test
|
||||||
* `ui-integration-test` — Is a pure test module dedicated for integration tests only. It has Android Test Orchestrator turned on — it allows us to run each of our tests within its own invocation of Instrumentation, and thus brings us benefits for the testing environment (minimal shared state, crashes are isolated, permissions are reset).
|
* `ui-integration-test` — Is a pure test module dedicated for integration tests only. It has Android Test Orchestrator turned on — it allows us to run each of our tests within its own invocation of Instrumentation, and thus brings us benefits for the testing environment (minimal shared state, crashes are isolated, permissions are reset).
|
||||||
|
* `ui-screenshot-test` — Is also a pure test module, whose purpose is to provide a wrapper for the ui screenshot tests. It has the Android Test Orchestrator turned on too.
|
||||||
* preference
|
* preference
|
||||||
* `preference-api-lib` — Multiplatform interfaces for key-value storage of preferences.
|
* `preference-api-lib` — Multiplatform interfaces for key-value storage of preferences.
|
||||||
* `preference-impl-android-lib` — Android-specific implementation for preference storage.
|
* `preference-impl-android-lib` — Android-specific implementation for preference storage.
|
||||||
* sdk
|
* sdk
|
||||||
* `sdk-ext-lib` — Contains extensions on top of the to the Zcash SDK. Some of these extensions might be migrated into the SDK eventually, while others might represent Android-centric idioms. Depending on how this module evolves, it could adopt another name such as `wallet-lib` or be split into two.
|
* `sdk-ext-lib` — Contains extensions on top of the to the Zcash SDK. Some of these extensions might be migrated into the SDK eventually, while others might represent Android-centric idioms. Depending on how this module evolves, it could adopt another name such as `wallet-lib` or be split into two.
|
||||||
* `sdk-ext-ui` — Place for Zcash SDK components (same as `sdk-ext-lib`), which are related to the UI (e.g. depend on user locale and thus need to be translated via `strings.xml`).
|
* `sdk-ext-ui` — Place for Zcash SDK components (same as `sdk-ext-lib`), which are related to the UI (e.g. depend on user locale and thus need to be translated via `strings.xml`).
|
||||||
* `spackle` — Random utilities, to fill in the cracks in the frameworks.
|
* spackle — Random utilities, to fill in the cracks in the frameworks.
|
||||||
* `spackle-lib` — Multiplatform implementation for Kotlin and JVM
|
* `spackle-lib` — Multiplatform implementation for Kotlin and JVM
|
||||||
* `spackle-android-lib` — Android-specific additions.
|
* `spackle-android-lib` — Android-specific additions.
|
||||||
|
|
||||||
|
@ -68,11 +70,12 @@ The following diagram shows a rough depiction of dependencies between the module
|
||||||
subgraph ui
|
subgraph ui
|
||||||
uiDesignLib[[ui-design-lib]];
|
uiDesignLib[[ui-design-lib]];
|
||||||
uiLib[[ui-lib]];
|
uiLib[[ui-lib]];
|
||||||
uiIntegrationTest[[ui-integration-test]];
|
|
||||||
end
|
end
|
||||||
uiDesignLib[[ui-design-lib]] --> uiLib[[ui-lib]];
|
uiDesignLib[[ui-design-lib]] --> uiLib[[ui-lib]];
|
||||||
uiLib[[ui-lib]] --> uiIntegrationTest[[ui-integration-test]];
|
subgraph ui-test
|
||||||
uiDesignLib[[ui-design-lib]] --> uiIntegrationTest[[ui-integration-test]];
|
uiIntegrationTest[[ui-integration-test]];
|
||||||
|
uiScreenshotTest[[ui-screenshot-test]];
|
||||||
|
end
|
||||||
subgraph spackle
|
subgraph spackle
|
||||||
spackleLib[[spackle-lib]];
|
spackleLib[[spackle-lib]];
|
||||||
spackleAndroidLib[[spackle-android-lib]];
|
spackleAndroidLib[[spackle-android-lib]];
|
||||||
|
@ -81,6 +84,7 @@ The following diagram shows a rough depiction of dependencies between the module
|
||||||
preference --> ui[[ui]];
|
preference --> ui[[ui]];
|
||||||
sdk --> ui[[ui]];
|
sdk --> ui[[ui]];
|
||||||
spackle[[spackle]] --> ui[[ui]];
|
spackle[[spackle]] --> ui[[ui]];
|
||||||
|
ui[[ui]] --> ui-test[[ui-test]];
|
||||||
ui[[ui]] --> app{app};
|
ui[[ui]] --> app{app};
|
||||||
crash[[crash]] --> app{app};
|
crash[[crash]] --> app{app};
|
||||||
```
|
```
|
||||||
|
|
|
@ -65,11 +65,11 @@ Start by making sure the command line with Gradle works first, because **all the
|
||||||
1. Delete the invisible `.idea` in the root directory of the project. This directory is partially ignored by Git, so deleting it will remove the files that are untracked
|
1. Delete the invisible `.idea` in the root directory of the project. This directory is partially ignored by Git, so deleting it will remove the files that are untracked
|
||||||
1. Restore the missing files in `.idea` folder from Git
|
1. Restore the missing files in `.idea` folder from Git
|
||||||
1. Relaunch Android Studio
|
1. Relaunch Android Studio
|
||||||
2. Clean the individual Gradle project by running `./gradlew clean` which will purge local build outputs.
|
1. Clean the individual Gradle project by running `./gradlew clean` which will purge local build outputs.
|
||||||
3. Run Gradle with the argument `--rerun-tasks` which will effectively disable the build cache by re-running tasks and repopulating the cache. E.g. `./gradlew assemble --rerun-tasks`
|
1. Run Gradle with the argument `--rerun-tasks` which will effectively disable the build cache by re-running tasks and repopulating the cache. E.g. `./gradlew assemble --rerun-tasks`
|
||||||
4. Reboot your computer, which will ensure that Gradle and Kotlin daemons are completely killed and relaunched
|
1. Reboot your computer, which will ensure that Gradle and Kotlin daemons are completely killed and relaunched
|
||||||
5. Delete the global Gradle cache under `~/.gradle/caches`
|
1. Delete the global Gradle cache under `~/.gradle/caches`
|
||||||
6. If adding a new dependency or updating a dependency, a warning that a dependency cannot be found may indicate the Maven repository restrictions need adjusting
|
1. If adding a new dependency or updating a dependency, a warning that a dependency cannot be found may indicate the Maven repository restrictions need adjusting
|
||||||
|
|
||||||
## Gradle Tasks
|
## Gradle Tasks
|
||||||
A variety of Gradle tasks are set up within the project, and these tasks are also accessible in Android Studio as run configurations.
|
A variety of Gradle tasks are set up within the project, and these tasks are also accessible in Android Studio as run configurations.
|
||||||
|
@ -82,9 +82,9 @@ A variety of Gradle tasks are set up within the project, and these tasks are als
|
||||||
* `lint` - Performs static analysis with Android lint
|
* `lint` - Performs static analysis with Android lint
|
||||||
* `dependencyUpdates` - Checks for available dependency updates. It will only suggest final releases, unless a particular dependency is already using a non-final release (e.g. alpha, beta, RC).
|
* `dependencyUpdates` - Checks for available dependency updates. It will only suggest final releases, unless a particular dependency is already using a non-final release (e.g. alpha, beta, RC).
|
||||||
|
|
||||||
A few notes on running instrumentation tests on the app module:
|
A few notes on running instrumentation tests on the `ui-screenshot-test` module:
|
||||||
- Screenshots are generated automatically and copied to (/app/build/reports/androidTests/connected/zcash_screenshots)[../app/build/reports/androidTests/connected/zcash_screenshots]
|
- Screenshots are generated automatically and copied to [/ui-screenshot-test/build/output](../ui-screenshot-test/build/outputs)
|
||||||
- Running the Android tests on the app module will erase the data stored by the app. This is because Test Orchestrator is required to reset app state to successfully perform integration tests.
|
- Running the Android tests on the `ui-screenshot-test` module will erase the data stored by the app. This is because Test Orchestrator is required to reset app state to successfully perform integration tests.
|
||||||
|
|
||||||
Gradle Managed Devices are also configured with our build scripts. We have found best results running tests one module at a time, rather than trying to run them all at once. For example: `./gradlew :ui-lib:pixel2TargetDebugAndroidTest` will run the UI tests on a Pixel 2 sized device using our target API version.
|
Gradle Managed Devices are also configured with our build scripts. We have found best results running tests one module at a time, rather than trying to run them all at once. For example: `./gradlew :ui-lib:pixel2TargetDebugAndroidTest` will run the UI tests on a Pixel 2 sized device using our target API version.
|
||||||
|
|
||||||
|
@ -160,7 +160,7 @@ For Continuous Integration, see [CI.md](CI.md). The rest of this section is reg
|
||||||
1. If you are an Electric Coin Co team member: We are still setting up a process for this, because emulator.wtf does not yet support individual API tokens
|
1. If you are an Electric Coin Co team member: We are still setting up a process for this, because emulator.wtf does not yet support individual API tokens
|
||||||
1. If you are an open source contributor: Visit http://emulator.wtf and request an API key
|
1. If you are an open source contributor: Visit http://emulator.wtf and request an API key
|
||||||
1. Set the emulator.wtf API key as a global Gradle property `ZCASH_EMULATOR_WTF_API_KEY` under `~/.gradle/gradle.properties`
|
1. Set the emulator.wtf API key as a global Gradle property `ZCASH_EMULATOR_WTF_API_KEY` under `~/.gradle/gradle.properties`
|
||||||
1. Run the Gradle task `./gradlew testDebugWithEmulatorWtf :app:testZcashmainnetDebugWithEmulatorWtf :ui-integration-test:testZcashmainnetDebugWithEmulatorWtf` (emulator.wtf tasks do build the app, so you don't need to build them beforehand)
|
1. Run the Gradle task `./gradlew testDebugWithEmulatorWtf :app:testZcashmainnetDebugWithEmulatorWtf :ui-integration-test:testZcashmainnetDebugWithEmulatorWtf :ui-screenshot-test:testZcashmainnetDebugWithEmulatorWtf` (emulator.wtf tasks do build the app, so you don't need to build them beforehand)
|
||||||
|
|
||||||
## Testnet funds
|
## Testnet funds
|
||||||
|
|
||||||
|
|
|
@ -273,6 +273,7 @@ include("test-lib")
|
||||||
include("ui-design-lib")
|
include("ui-design-lib")
|
||||||
include("ui-integration-test")
|
include("ui-integration-test")
|
||||||
include("ui-lib")
|
include("ui-lib")
|
||||||
|
include("ui-screenshot-test")
|
||||||
|
|
||||||
val zcashSdkIncludedBuildPath = extra["SDK_INCLUDED_BUILD_PATH"].toString()
|
val zcashSdkIncludedBuildPath = extra["SDK_INCLUDED_BUILD_PATH"].toString()
|
||||||
|
|
||||||
|
|
|
@ -36,16 +36,13 @@ import kotlin.time.Duration.Companion.seconds
|
||||||
|
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
|
|
||||||
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
|
|
||||||
val walletViewModel by viewModels<WalletViewModel>()
|
val walletViewModel by viewModels<WalletViewModel>()
|
||||||
|
|
||||||
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
|
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
|
||||||
val storageCheckViewModel by viewModels<StorageCheckViewModel>()
|
val storageCheckViewModel by viewModels<StorageCheckViewModel>()
|
||||||
|
|
||||||
@VisibleForTesting(otherwise = VisibleForTesting.NONE)
|
|
||||||
lateinit var navControllerForTesting: NavHostController
|
lateinit var navControllerForTesting: NavHostController
|
||||||
|
|
||||||
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
|
|
||||||
val configurationOverrideFlow = MutableStateFlow<ConfigurationOverride?>(null)
|
val configurationOverrideFlow = MutableStateFlow<ConfigurationOverride?>(null)
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package co.electriccoin.zcash.ui
|
package co.electriccoin.zcash.ui
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import androidx.annotation.VisibleForTesting
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.navigation.NavHostController
|
import androidx.navigation.NavHostController
|
||||||
import androidx.navigation.NavOptionsBuilder
|
import androidx.navigation.NavOptionsBuilder
|
||||||
|
@ -141,33 +140,23 @@ private fun NavHostController.popBackStackJustOnce(currentRouteToBePopped: Strin
|
||||||
}
|
}
|
||||||
|
|
||||||
object NavigationTargets {
|
object NavigationTargets {
|
||||||
@VisibleForTesting
|
|
||||||
const val HOME = "home"
|
const val HOME = "home"
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
const val PROFILE = "profile"
|
const val PROFILE = "profile"
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
const val WALLET_ADDRESS_DETAILS = "wallet_address_details"
|
const val WALLET_ADDRESS_DETAILS = "wallet_address_details"
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
const val SETTINGS = "settings"
|
const val SETTINGS = "settings"
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
const val SEED = "seed"
|
const val SEED = "seed"
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
const val REQUEST = "request"
|
const val REQUEST = "request"
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
const val SEND = "send"
|
const val SEND = "send"
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
const val SUPPORT = "support"
|
const val SUPPORT = "support"
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
const val ABOUT = "about"
|
const val ABOUT = "about"
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
const val SCAN = "scan"
|
const val SCAN = "scan"
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,5 +7,6 @@
|
||||||
<string name="about_build_header">Build</string>
|
<string name="about_build_header">Build</string>
|
||||||
<string name="about_legal_header">Legal</string>
|
<string name="about_legal_header">Legal</string>
|
||||||
<!-- TODO [#392] Update with real legal info. -->
|
<!-- TODO [#392] Update with real legal info. -->
|
||||||
|
<!-- TODO [#392] https://github.com/zcash/secant-android-wallet/issues/392 -->
|
||||||
<string name="about_legal_info">GitHub Issue #392</string>
|
<string name="about_legal_info">GitHub Issue #392</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
plugins {
|
||||||
|
id("com.android.test")
|
||||||
|
kotlin("android")
|
||||||
|
id("secant.android-build-conventions")
|
||||||
|
id("wtf.emulator.gradle")
|
||||||
|
id("secant.emulator-wtf-conventions")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Force orchestrator to be used for this module, because we need cleared state to generate screenshots
|
||||||
|
val isOrchestratorEnabled = true
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace = "co.electroniccoin.zcash.ui.screenshot"
|
||||||
|
// Target needs to be set to com.android.application type module
|
||||||
|
targetProjectPath = ":${projects.app.name}"
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
if (isOrchestratorEnabled) {
|
||||||
|
testInstrumentationRunnerArguments["clearPackageData"] = "true"
|
||||||
|
}
|
||||||
|
|
||||||
|
testInstrumentationRunner = "co.electriccoin.zcash.test.ZcashUiTestRunner"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define the same flavors as in app module
|
||||||
|
flavorDimensions.add("network")
|
||||||
|
productFlavors {
|
||||||
|
create("zcashtestnet") {
|
||||||
|
dimension = "network"
|
||||||
|
}
|
||||||
|
create("zcashmainnet") {
|
||||||
|
dimension = "network"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isOrchestratorEnabled) {
|
||||||
|
testOptions {
|
||||||
|
execution = "ANDROIDX_TEST_ORCHESTRATOR"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buildFeatures {
|
||||||
|
compose = true
|
||||||
|
}
|
||||||
|
|
||||||
|
composeOptions {
|
||||||
|
kotlinCompilerExtensionVersion = libs.androidx.compose.compiler.get().versionConstraint.displayName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(projects.uiLib)
|
||||||
|
implementation(projects.testLib)
|
||||||
|
implementation(projects.spackleAndroidLib)
|
||||||
|
implementation(projects.sdkExtLib)
|
||||||
|
implementation(projects.sdkExtUiLib)
|
||||||
|
|
||||||
|
implementation(libs.bundles.androidx.test)
|
||||||
|
implementation(libs.bundles.androidx.compose.core)
|
||||||
|
implementation(libs.bundles.play.core)
|
||||||
|
|
||||||
|
implementation(libs.androidx.compose.test.junit)
|
||||||
|
implementation(libs.androidx.navigation.compose)
|
||||||
|
implementation(libs.androidx.uiAutomator)
|
||||||
|
|
||||||
|
if (isOrchestratorEnabled) {
|
||||||
|
androidTestUtil(libs.androidx.test.orchestrator) {
|
||||||
|
artifact {
|
||||||
|
type = "apk"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
emulatorwtf {
|
||||||
|
directoriesToPull.set(listOf("/sdcard/googletest/test_outputfiles"))
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest>
|
||||||
|
|
||||||
|
</manifest>
|
|
@ -1,4 +1,4 @@
|
||||||
package co.electriccoin.zcash.app
|
package co.electroniccoin.zcash.ui.screenshot
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
@ -132,6 +132,7 @@ class ScreenshotTest : UiTestPrerequisites() {
|
||||||
|
|
||||||
private fun take_screenshots_for_restore_wallet(resContext: Context, tag: String) {
|
private fun take_screenshots_for_restore_wallet(resContext: Context, tag: String) {
|
||||||
// TODO [#286]: Screenshot tests fail on Firebase Test Lab
|
// TODO [#286]: Screenshot tests fail on Firebase Test Lab
|
||||||
|
// TODO [#286]: https://github.com/zcash/secant-android-wallet/issues/286
|
||||||
if (FirebaseTestLabUtil.isFirebaseTestLab(ApplicationProvider.getApplicationContext())) {
|
if (FirebaseTestLabUtil.isFirebaseTestLab(ApplicationProvider.getApplicationContext())) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -213,6 +214,7 @@ class ScreenshotTest : UiTestPrerequisites() {
|
||||||
|
|
||||||
private fun take_screenshots_for_new_wallet_and_rest_of_app(resContext: Context, tag: String) {
|
private fun take_screenshots_for_new_wallet_and_rest_of_app(resContext: Context, tag: String) {
|
||||||
// TODO [#286]: Screenshot tests fail on Firebase Test Lab
|
// TODO [#286]: Screenshot tests fail on Firebase Test Lab
|
||||||
|
// TODO [#286]: https://github.com/zcash/secant-android-wallet/issues/286
|
||||||
if (FirebaseTestLabUtil.isFirebaseTestLab(ApplicationProvider.getApplicationContext())) {
|
if (FirebaseTestLabUtil.isFirebaseTestLab(ApplicationProvider.getApplicationContext())) {
|
||||||
return
|
return
|
||||||
}
|
}
|
Loading…
Reference in New Issue