diff --git a/.bazelrc b/.bazelrc new file mode 100644 index 000000000..d484f9da4 --- /dev/null +++ b/.bazelrc @@ -0,0 +1,74 @@ +# Configurations for testing with Bazel +# Select a configuration by running `bazel test //my:target --config={headless, gui, local_device}` + +# Headless instrumentation tests +test:headless --test_arg=--enable_display=false + +# Graphical instrumentation tests. Ensure that $DISPLAY is set. +test:gui --test_env=DISPLAY +test:gui --test_arg=--enable_display=true + +# Testing with a local emulator or device. Ensure that `adb devices` lists the device. +# Run tests serially. +test:local_device --test_strategy=exclusive +# Use the local device broker type, as opposed to WRAPPED_EMULATOR. +test:local_device --test_arg=--device_broker_type=LOCAL_ADB_SERVER +# Uncomment and set $device_id if there is more than one connected device. +# test:local_device --test_arg=--device_serial_number=$device_id + +test --flaky_test_attempts=3 + +# The unified launcher runs in Python 2 host configuration +# https://github.com/bazelbuild/bazel/issues/7899 +build --host_force_python=PY2 + +# ------------------------ +# General RBE configuration +# ------------------------ +build:remote --jobs=100 + +# Java toolchain setup +build:remote --java_toolchain=@bazel_tools//tools/jdk:toolchain_hostjdk8 +build:remote --host_java_toolchain=@bazel_tools//tools/jdk:toolchain_hostjdk8 +build:remote --host_javabase=@rbe_default//java:jdk +build:remote --javabase=@rbe_default//java:jdk + +# C++ toolchain setup +build:remote --extra_toolchains=@rbe_default//config:cc-toolchain +build:remote --crosstool_top=@rbe_default//cc:toolchain + +# Remote instance setup +build:remote --remote_instance_name=projects/bazel-untrusted/instances/default_instance +build:remote --project_id=bazel-untrusted + +# Set various strategies so that all actions execute remotely. Mixing remote +# and local execution will lead to errors unless the toolchain and remote +# machine exactly match the host machine. +build:remote --spawn_strategy=remote +build:remote --define=EXECUTOR=remote + +# Enable the remote cache so action results can be shared across machines, +# developers, and workspaces. +build:remote --remote_cache=remotebuildexecution.googleapis.com + +# Enable remote execution so actions are performed on the remote systems. +build:remote --remote_executor=remotebuildexecution.googleapis.com + +# Enable authentication. This will pick up application default credentials by +# default. +build:remote --google_default_credentials + +# ------------------------------------------- +# Custom RBE configuration for Android builds +# ------------------------------------------- + +build:remote_android --config=remote # Reuse general configuration + +# Platform configuration +build:remote_android --extra_execution_platforms=:android_platform +build:remote_android --host_platform=:android_platform +build:remote_android --platforms=:android_platform + +build:remote_android --strategy=DexBuilder=remote +build:remote_android --noexperimental_check_desugar_deps # Workaround for singlejar incompatibility with RBE +build:remote_android --incompatible_strict_action_env diff --git a/.github/ci-gradle.properties b/.github/ci-gradle.properties new file mode 100644 index 000000000..e69de29bb diff --git a/.github/workflows/composescreenshot.yml b/.github/workflows/composescreenshot.yml new file mode 100644 index 000000000..c717f8305 --- /dev/null +++ b/.github/workflows/composescreenshot.yml @@ -0,0 +1,24 @@ +# Workflow name +name: Compose Preview Screenshot +on: + # When it will be triggered + # And in which branch + pull_request: + branches: [ main ] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Set Up JDK + uses: actions/setup-java@v3 + with: + distribution: 'zulu' # See 'Supported distributions' for available options + java-version: '17' + cache: 'gradle' + + - name: Build project and run screenshot tests + working-directory: ./ui/PreviewScreenshot + run: ./gradlew validateDebugScreenshotTest diff --git a/.github/workflows/copy-branch.yml b/.github/workflows/copy-branch.yml new file mode 100644 index 000000000..f8f8572d9 --- /dev/null +++ b/.github/workflows/copy-branch.yml @@ -0,0 +1,31 @@ +# Duplicates default main branch to the old master branch + +name: Duplicates main to old master branch + +# Controls when the action will run. Triggers the workflow on push or pull request +# events but only for the main branch +on: + push: + branches: [ main ] + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "copy-branch" + copy-branch: + # The type of runner that the job will run on + runs-on: ubuntu-latest + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it, + # but specifies master branch (old default). + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + ref: master + + - run: | + git config user.name github-actions + git config user.email github-actions@github.com + git merge origin/main + git push diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml new file mode 100644 index 000000000..41735cbf2 --- /dev/null +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -0,0 +1,16 @@ +name: Validate Gradle Wrapper + +on: + push: + branches: [ main ] + + pull_request: + branches: [ main ] + +jobs: + validation: + name: Validation + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: gradle/wrapper-validation-action@v1 diff --git a/.github/workflows/test-all.yml b/.github/workflows/test-all.yml new file mode 100644 index 000000000..2c0b5d626 --- /dev/null +++ b/.github/workflows/test-all.yml @@ -0,0 +1,43 @@ +# Workflow name +name: Build + Test all +on: + # When it will be triggered + # And in which branch + pull_request: + branches: [ main ] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Enable KVM group perms + 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 + ls /dev/kvm + + - name: Set Up JDK + uses: actions/setup-java@v3 + with: + distribution: 'zulu' # See 'Supported distributions' for available options + java-version: '17' + cache: 'gradle' + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Setup Android SDK + uses: android-actions/setup-android@v3 + + - name: Build project and run local and device tests + run: ./test_all.sh + + - name: Upload test reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: test-reports + path: '**/app/build/reports/androidTests' diff --git a/.gitignore b/.gitignore index 28c0a8191..2e822ca17 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,9 @@ local.properties build .gradle +# Eclipse project files +.project +.settings/ +.classpath +bazel-* +.DS_Store diff --git a/BUILD.bazel b/BUILD.bazel new file mode 100644 index 000000000..114654e5c --- /dev/null +++ b/BUILD.bazel @@ -0,0 +1,54 @@ +load("@rules_jvm_external//:defs.bzl", "artifact") +load("//:common_defs.bzl", "androidxLibVersion", "coreVersion", "espressoVersion", "extJUnitVersion", "extTruthVersion", "rulesVersion", "runnerVersion") + +licenses(["notice"]) # Apache 2.0 + +android_library( + name = "test_deps", + visibility = ["//visibility:public"], + exports = [ + artifact("androidx.annotation:annotation"), + artifact("androidx.test.espresso:espresso-core"), + artifact("androidx.test:rules"), + artifact("androidx.test:runner"), + artifact("androidx.test:monitor"), + artifact("androidx.test.ext:junit"), + artifact("androidx.test:core"), + artifact("com.google.guava:guava"), + artifact("com.google.inject:guice"), + artifact("javax.inject:javax.inject"), + artifact("junit:junit"), + artifact("org.hamcrest:java-hamcrest"), + ], +) + +# Platform configuration for emulators on RBE for Bazel CI +platform( + name = "android_platform", + constraint_values = [ + "@bazel_tools//platforms:x86_64", + "@bazel_tools//platforms:linux", + "@bazel_toolchains//constraints:xenial", + "@bazel_tools//tools/cpp:clang", + ], + # TODO(@jin): s/di-cloud-exp/rbe-containers/ when the official android-test container with libxcursor1 and libxcomposite1 is ready. + # URI for official container: docker://gcr.io/rbe-containers/ubuntu16_04-android_test@sha256: + remote_execution_properties = """ + properties: { + name: "container-image" + value: "docker://gcr.io/di-cloud-exp/rbe-ubuntu16-04-android@sha256:eb3828f71faf595f44b20b97d205e73e8a21982f1d7a170c3ec8f9d33ce3179a" + } + properties: { + name: "dockerNetwork" + value: "standard" + } + properties: { + name: "dockerPrivileged" + value: "true" + } + properties: { + name: "gceMachineType" + value: "n1-standard-2" + } +""", +) diff --git a/CONTRIB.md b/CONTRIB.md deleted file mode 100644 index fe1f58833..000000000 --- a/CONTRIB.md +++ /dev/null @@ -1,34 +0,0 @@ -# How to become a contributor and submit your own code - -## Contributor License Agreements - -We'd love to accept your sample apps and patches! Before we can take them, we -have to jump a couple of legal hurdles. - -Please fill out either the individual or corporate Contributor License Agreement (CLA). - - * If you are an individual writing original source code and you're sure you - own the intellectual property, then you'll need to sign an [individual CLA] - (https://cla.developers.google.com). - * If you work for a company that wants to allow you to contribute your work, - then you'll need to sign a [corporate CLA] - (https://cla.developers.google.com). - -Follow either of the two links above to access the appropriate CLA and -instructions for how to sign and return it. Once we receive it, we'll be able to -accept your pull requests. - -## Contributing A Patch - -1. Submit an issue describing your proposed change to the repo in question. -1. The repo owner will respond to your issue promptly. -1. If your proposed change is accepted, and you haven't already done so, sign a - Contributor License Agreement (see details above). -1. Fork the desired repo, develop and test your code changes. -1. Ensure that your code adheres to the existing style in the sample to which - you are contributing. Refer to the - [Android Code Style Guide] - (https://source.android.com/source/code-style.html) for the - recommended coding standards for this organization. -1. Ensure that your code has an appropriate set of unit tests which all pass. -1. Submit a pull request. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7b86f95d7..f282da6a4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,5 +1,23 @@ # How to become a contributor and submit your own code +To contribute with a small fix, simply create a pull request. If you want to add a new sample or plan to request a big change, [contact us](https://groups.google.com/forum/#!forum/android-testing-support-library) first. + +## Contributing new samples + +If you want to contribute full samples, we'd love to review and accept them. In case you need ideas, these are some samples on the roadmap: + +* Advanced Idling Resource +* RecyclerView actions +* Sharding +* RunListener +* Rules + +You can also contribute to this list if you have a sample request. + +## Code style and structure + +Please check out the [Code Style for Contributors](https://source.android.com/source/code-style.html) section in AOSP. Also, check out the rest of the samples and maintain as much consistency with them as possible. + ## Contributor License Agreements We'd love to accept your sample apps and patches! Before we can take them, we diff --git a/README.md b/README.md index 94b9462c7..09c9728d1 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,58 @@ Android testing samples =================================== - A collection of samples demonstrating different frameworks and techniques for automated testing. +### Espresso Samples + +**[BasicSample](https://github.com/googlesamples/android-testing/blob/main/ui/espresso/BasicSample)** - Basic Espresso sample + +**[CustomMatcherSample](https://github.com/googlesamples/android-testing/blob/main/ui/espresso/CustomMatcherSample)** - Shows how to extend Espresso to match the *hint* property of an EditText + +**[DataAdapterSample](https://github.com/googlesamples/android-testing/blob/main/ui/espresso/DataAdapterSample)** - Showcases the `onData()` entry point for Espresso, for lists and AdapterViews + +**[FragmentScenarioSample](https://github.com/googlesamples/android-testing/blob/main/ui/espresso/FragmentScenarioSample)** - Basic usage of `FragmentScenario` with Espresso. + +**[IdlingResourceSample](https://github.com/googlesamples/android-testing/blob/main/ui/espresso/IdlingResourceSample)** - Synchronization with background jobs + +**[IntentsBasicSample](https://github.com/googlesamples/android-testing/blob/main/ui/espresso/IntentsBasicSample)** - Basic usage of `intended()` and `intending()` + +**[IntentsAdvancedSample](https://github.com/googlesamples/android-testing/blob/main/ui/espresso/IntentsAdvancedSample)** - Simulates a user fetching a bitmap using the camera + +**[MultiWindowSample](https://github.com/googlesamples/android-testing/blob/main/ui/espresso/MultiWindowSample)** - Shows how to point Espresso to different windows + +**[RecyclerViewSample](https://github.com/googlesamples/android-testing/blob/main/ui/espresso/RecyclerViewSample)** - RecyclerView actions for Espresso + +**[ScreenshotSample](https://github.com/googlesamples/android-testing/blob/main/ui/espresso/ScreenshotSample)** - Screenshot capturing and saving using Espresso and androidx.test.core APIs + +**[WebBasicSample](https://github.com/googlesamples/android-testing/blob/main/ui/espresso/WebBasicSample)** - Use Espresso-web to interact with WebViews + +**[BasicSampleBundled](https://github.com/googlesamples/android-testing/blob/main/ui/espresso/BasicSampleBundled)** - Basic sample for Eclipse and other IDEs + +**[MultiProcessSample](https://github.com/googlesamples/android-testing/blob/main/ui/espresso/MultiProcessSample)** - Showcases how to use multiprocess Espresso. +### UiAutomator Sample + +**[BasicSample](https://github.com/googlesamples/android-testing/tree/main/ui/uiautomator/BasicSample)** - Basic UI Automator sample + +### AndroidJUnitRunner Sample + +**[AndroidJunitRunnerSample](https://github.com/googlesamples/android-testing/tree/main/runner/AndroidJunitRunnerSample)** - Showcases test annotations, parameterized tests and testsuite creation + +### JUnit4 Rules Sample + +**All previous samples use ActivityTestRule or IntentsTestRule but there's one specific to ServiceTestRule: + +**[BasicSample](https://github.com/googlesamples/android-testing/blob/main/ui/espresso/BasicSample)** - Simple usage of `ActivityTestRule` + +**[IntentsBasicSample](https://github.com/googlesamples/android-testing/blob/main/ui/espresso/IntentsBasicSample)** - Simple usage of `IntentsTestRule` + +**[ServiceTestRuleSample](https://github.com/googlesamples/android-testing/tree/main/integration/ServiceTestRuleSample)** - Simple usage of `ServiceTestRule` + Prerequisites -------------- -- Android SDK v22 -- Android Build Tools v22 -- Android Support Repository rev13 +- Android SDK v28 +- Android Build Tools v28.03 Getting Started --------------- @@ -21,6 +64,71 @@ These samples use the Gradle build system. To build a project, enter the project There is a top-level `build.gradle` file if you want to build and test all samples from the root directory. This is mostly helpful to build on a CI (Continuous Integration) server. +AndroidX Test Library +--------------- +Many of these samples use the AndroidX Test Library. Visit the [Testing site on developer.android.com](https://developer.android.com/training/testing) for more information. + +Experimental Bazel Support +-------------------------- + +[![Build status](https://badge.buildkite.com/18dda320b265e9a8f20cb6141b1e80ca58fb62bdb443e527be.svg)](https://buildkite.com/bazel/android-testing) + +Some of these samples can be tested with [Bazel](https://bazel.build) on Linux. These samples contain a `BUILD.bazel` file, which is similar to a `build.gradle` file. The external dependencies are defined in the top level `WORKSPACE` file. + +This is __experimental__ feature. To run the tests, please install the latest version of Bazel (0.12.0 or later) by following the [instructions on the Bazel website](https://docs.bazel.build/versions/master/install-ubuntu.html). + +### Bazel commands + +``` +# Clone the repository if you haven't. +$ git clone https://github.com/google/android-testing +$ cd android-testing + +# Edit the path to your local SDK at the top of the WORKSPACE file +$ $EDITOR WORKSPACE + +# Test everything in a headless mode (no graphical display) +$ bazel test //... --config=headless + +# Test a single test, e.g. ui/espresso/BasicSample/BUILD.bazel +$ bazel test //ui/uiautomator/BasicSample:BasicSampleInstrumentationTest_21_x86 --config=headless + +# Query for all android_instrumentation_test targets +$ bazel query 'kind(android_instrumentation_test, //...)' +//ui/uiautomator/BasicSample:BasicSampleInstrumentationTest_23_x86 +//ui/uiautomator/BasicSample:BasicSampleInstrumentationTest_22_x86 +//ui/uiautomator/BasicSample:BasicSampleInstrumentationTest_21_x86 +//ui/uiautomator/BasicSample:BasicSampleInstrumentationTest_19_x86 +//ui/espresso/RecyclerViewSample:RecyclerViewSampleInstrumentationTest_23_x86 +//ui/espresso/RecyclerViewSample:RecyclerViewSampleInstrumentationTest_22_x86 +//ui/espresso/RecyclerViewSample:RecyclerViewSampleInstrumentationTest_21_x86 +//ui/espresso/RecyclerViewSample:RecyclerViewSampleInstrumentationTest_19_x86 +//ui/espresso/MultiWindowSample:MultiWindowSampleInstrumentationTest_23_x86 +//ui/espresso/MultiWindowSample:MultiWindowSampleInstrumentationTest_22_x86 +... + +# Test everything with GUI enabled +$ bazel test //... --config=gui + +# Test with a local device or emulator. Ensure that `adb devices` lists the device. +$ bazel test //... --config=local_device + +# If multiple devices are connected, add --device_serial_number=$identifier where $identifier is the name of the device in `adb devices` +$ bazel test //... --config=local_device --test_arg=--device_serial_number=$identifier +``` + +For more information, check out the documentation for [Android Instrumentation Tests in Bazel](https://docs.bazel.build/versions/master/android-instrumentation-test.html). You may also want to check out [Building an Android App with Bazel](https://docs.bazel.build/versions/master/tutorial/android-app.html), and the list of [Android Rules](https://docs.bazel.build/versions/master/be/android.html) in the Bazel Build Encyclopedia. + +Known issues: + +* Building of APKs is supported on Linux, Mac and Windows, but testing is only supported on Linux. +* `android_instrumentation_test.target_device` attribute still needs to be specified even if `--config=local_device` is used. +* If using a local device or emulator, the APKs are not uninstalled automatically after the test. Use this command to +remove the packages: + * `adb shell pm list packages com.example.android.testing | cut -d ':' -f 2 | tr -d '\r' | xargs -L1 -t adb uninstall` + +Please file Bazel related issues against the [Bazel](https://github.com/bazelbuild/bazel) repository instead of this repository. + Support ------- @@ -52,5 +160,3 @@ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - - diff --git a/WORKSPACE b/WORKSPACE new file mode 100644 index 000000000..868cb6fde --- /dev/null +++ b/WORKSPACE @@ -0,0 +1,115 @@ +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") +load("@bazel_tools//tools/build_defs/repo:jvm.bzl", "jvm_maven_import_external") + +# Set the path to your local SDK installation, or use the ANDROID_HOME environment variable. +android_sdk_repository(name = "androidsdk") + +# Required for running emulator tests on RBE on Bazel CI +android_ndk_repository(name = "androidndk") + +# Android Test Support +# +# This repository contains the supporting tools to run Android instrumentation tests, +# like the emulator definitions (android_device) and the device broker/test runner. +ATS_TAG = "1edfdab3134a7f01b37afabd3eebfd2c5bb05151" + +ATS_SHA256 = "dcd1ff76aef1a26329d77863972780c8fe1fc8ff625747342239f0489c2837ec" + +http_archive( + name = "android_test_support", + sha256 = ATS_SHA256, + strip_prefix = "android-test-%s" % ATS_TAG, + urls = ["https://github.com/android/android-test/archive/%s.tar.gz" % ATS_TAG], +) + +load("@android_test_support//:repo.bzl", "android_test_repositories") + +android_test_repositories() + +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + +RULES_JVM_EXTERNAL_TAG = "3.1" + +RULES_JVM_EXTERNAL_SHA = "e246373de2353f3d34d35814947aa8b7d0dd1a58c2f7a6c41cfeaff3007c2d14" + +http_archive( + name = "rules_jvm_external", + sha256 = RULES_JVM_EXTERNAL_SHA, + strip_prefix = "rules_jvm_external-%s" % RULES_JVM_EXTERNAL_TAG, + url = "https://github.com/bazelbuild/rules_jvm_external/archive/%s.zip" % RULES_JVM_EXTERNAL_TAG, +) + +load("@rules_jvm_external//:defs.bzl", "maven_install") +load("@rules_jvm_external//:specs.bzl", "maven") +load( + "//:common_defs.bzl", + "androidxLibVersion", + "coreVersion", + "espressoVersion", + "extJUnitVersion", + "extTruthVersion", + "rulesVersion", + "runnerVersion", + "uiAutomatorVersion", +) + +maven_install( + name = "maven", + artifacts = [ + "androidx.annotation:annotation:" + androidxLibVersion, + "androidx.core:core:" + androidxLibVersion, + "androidx.recyclerview:recyclerview:" + androidxLibVersion, + "androidx.test:core:" + coreVersion, + "androidx.test.espresso:espresso-accessibility:" + espressoVersion, + "androidx.test.espresso:espresso-contrib:" + espressoVersion, + "androidx.test.espresso:espresso-core:" + espressoVersion, + "androidx.test.espresso:espresso-idling-resource:" + espressoVersion, + "androidx.test.espresso:espresso-intents:" + espressoVersion, + "androidx.test.ext:junit:" + extJUnitVersion, + "androidx.test.ext:truth:" + extTruthVersion, + "androidx.test:monitor:" + runnerVersion, + "androidx.test:rules:" + rulesVersion, + "androidx.test:runner:" + runnerVersion, + "androidx.test.uiautomator:uiautomator:" + uiAutomatorVersion, + "androidx.viewpager:viewpager:1.0.0", + maven.artifact( + "com.google.inject", + "guice", + "4.0", + neverlink = True, + ), + "junit:junit:4.12", + "javax.inject:javax.inject:1", + "org.hamcrest:java-hamcrest:2.0.0.0", + maven.artifact( + "org.robolectric", + "robolectric", + "4.3-beta-1", + neverlink = True, + exclusions = ["com.google.guava:guava"], + ), + "com.google.guava:guava:26.0-android", + "com.google.truth:truth:0.42", + "com.google.android.apps.common.testing.accessibility.framework:accessibility-test-framework:2.0", + ], + jetify = True, + repositories = [ + "https://maven.google.com", + "https://repo1.maven.org/maven2", + ], + version_conflict_policy = "pinned", +) + +http_archive( + name = "bazel_toolchains", + sha256 = "4d348abfaddbcee0c077fc51bb1177065c3663191588ab3d958f027cbfe1818b", + strip_prefix = "bazel-toolchains-2.1.0", + urls = [ + "https://github.com/bazelbuild/bazel-toolchains/releases/download/2.1.0/bazel-toolchains-2.1.0.tar.gz", + "https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/archive/2.1.0.tar.gz", + ], +) + +load("@bazel_toolchains//rules:rbe_repo.bzl", "rbe_autoconfig") + +rbe_autoconfig(name = "rbe_default") diff --git a/bazelci/buildkite-pipeline.yml b/bazelci/buildkite-pipeline.yml new file mode 100644 index 000000000..89474fcfe --- /dev/null +++ b/bazelci/buildkite-pipeline.yml @@ -0,0 +1,138 @@ +# https://github.com/googlesamples/android-testing#experimental-bazel-support +--- +platforms: + ubuntu1804: + build_targets: + - "//..." + - "-//ui/uiautomator/BasicSample:BasicSampleInstrumentationTest_23_x86" # BazelCI does not have Android Emulator + - "-//ui/uiautomator/BasicSample:BasicSampleInstrumentationTest_22_x86" + - "-//ui/uiautomator/BasicSample:BasicSampleInstrumentationTest_21_x86" + - "-//ui/uiautomator/BasicSample:BasicSampleInstrumentationTest_19_x86" + - "-//ui/espresso/RecyclerViewSample:RecyclerViewSampleInstrumentationTest_23_x86" + - "-//ui/espresso/RecyclerViewSample:RecyclerViewSampleInstrumentationTest_22_x86" + - "-//ui/espresso/RecyclerViewSample:RecyclerViewSampleInstrumentationTest_21_x86" + - "-//ui/espresso/RecyclerViewSample:RecyclerViewSampleInstrumentationTest_19_x86" + - "-//ui/espresso/MultiWindowSample:MultiWindowSampleInstrumentationTest_23_x86" + - "-//ui/espresso/MultiWindowSample:MultiWindowSampleInstrumentationTest_22_x86" + - "-//ui/espresso/MultiWindowSample:MultiWindowSampleInstrumentationTest_21_x86" + - "-//ui/espresso/MultiWindowSample:MultiWindowSampleInstrumentationTest_19_x86" + - "-//ui/espresso/IntentsBasicSample:IntentsBasicSampleInstrumentationTest_23_x86" + - "-//ui/espresso/IntentsBasicSample:IntentsBasicSampleInstrumentationTest_22_x86" + - "-//ui/espresso/IntentsBasicSample:IntentsBasicSampleInstrumentationTest_21_x86" + - "-//ui/espresso/IntentsBasicSample:IntentsBasicSampleInstrumentationTest_19_x86" + - "-//ui/espresso/IntentsAdvancedSample:IntentsAdvancedSampleInstrumentationTest_23_x86" + - "-//ui/espresso/IntentsAdvancedSample:IntentsAdvancedSampleInstrumentationTest_22_x86" + - "-//ui/espresso/IntentsAdvancedSample:IntentsAdvancedSampleInstrumentationTest_21_x86" + - "-//ui/espresso/IntentsAdvancedSample:IntentsAdvancedSampleInstrumentationTest_19_x86" + - "-//ui/espresso/IdlingResourceSample:IdlingResourceSampleInstrumentationTest_23_x86" + - "-//ui/espresso/IdlingResourceSample:IdlingResourceSampleInstrumentationTest_22_x86" + - "-//ui/espresso/IdlingResourceSample:IdlingResourceSampleInstrumentationTest_21_x86" + - "-//ui/espresso/IdlingResourceSample:IdlingResourceSampleInstrumentationTest_19_x86" + - "-//ui/espresso/DataAdapterSample:DataAdapterSampleInstrumentationTest_23_x86" + - "-//ui/espresso/DataAdapterSample:DataAdapterSampleInstrumentationTest_22_x86" + - "-//ui/espresso/DataAdapterSample:DataAdapterSampleInstrumentationTest_21_x86" + - "-//ui/espresso/DataAdapterSample:DataAdapterSampleInstrumentationTest_19_x86" + - "-//ui/espresso/CustomMatcherSample:CustomMatcherSampleInstrumentationTest_23_x86" + - "-//ui/espresso/CustomMatcherSample:CustomMatcherSampleInstrumentationTest_22_x86" + - "-//ui/espresso/CustomMatcherSample:CustomMatcherSampleInstrumentationTest_21_x86" + - "-//ui/espresso/CustomMatcherSample:CustomMatcherSampleInstrumentationTest_19_x86" + - "-//ui/espresso/BasicSample:BasicSampleInstrumentationTest_23_x86" + - "-//ui/espresso/BasicSample:BasicSampleInstrumentationTest_22_x86" + - "-//ui/espresso/BasicSample:BasicSampleInstrumentationTest_21_x86" + - "-//ui/espresso/BasicSample:BasicSampleInstrumentationTest_19_x86" + - "-//ui/espresso/AccessibilitySample:BasicSampleInstrumentationTest_23_x86" + - "-//ui/espresso/AccessibilitySample:BasicSampleInstrumentationTest_22_x86" + - "-//ui/espresso/AccessibilitySample:BasicSampleInstrumentationTest_21_x86" + - "-//ui/espresso/AccessibilitySample:BasicSampleInstrumentationTest_19_x86" + test_flags: + - "--config=remote_android" + - "--flaky_test_attempts=3" + test_targets: + - "//..." + - "-//ui/espresso/AccessibilitySample/..." + - "-//ui/uiautomator/BasicSample:BasicSampleInstrumentationTest_23_x86" # BazelCI does not have Android Emulator + - "-//ui/uiautomator/BasicSample:BasicSampleInstrumentationTest_22_x86" + - "-//ui/uiautomator/BasicSample:BasicSampleInstrumentationTest_21_x86" + - "-//ui/uiautomator/BasicSample:BasicSampleInstrumentationTest_19_x86" + - "-//ui/espresso/RecyclerViewSample:RecyclerViewSampleInstrumentationTest_23_x86" + - "-//ui/espresso/RecyclerViewSample:RecyclerViewSampleInstrumentationTest_22_x86" + - "-//ui/espresso/RecyclerViewSample:RecyclerViewSampleInstrumentationTest_21_x86" + - "-//ui/espresso/RecyclerViewSample:RecyclerViewSampleInstrumentationTest_19_x86" + - "-//ui/espresso/MultiWindowSample:MultiWindowSampleInstrumentationTest_23_x86" + - "-//ui/espresso/MultiWindowSample:MultiWindowSampleInstrumentationTest_22_x86" + - "-//ui/espresso/MultiWindowSample:MultiWindowSampleInstrumentationTest_21_x86" + - "-//ui/espresso/MultiWindowSample:MultiWindowSampleInstrumentationTest_19_x86" + - "-//ui/espresso/IntentsBasicSample:IntentsBasicSampleInstrumentationTest_23_x86" + - "-//ui/espresso/IntentsBasicSample:IntentsBasicSampleInstrumentationTest_22_x86" + - "-//ui/espresso/IntentsBasicSample:IntentsBasicSampleInstrumentationTest_21_x86" + - "-//ui/espresso/IntentsBasicSample:IntentsBasicSampleInstrumentationTest_19_x86" + - "-//ui/espresso/IntentsAdvancedSample:IntentsAdvancedSampleInstrumentationTest_23_x86" + - "-//ui/espresso/IntentsAdvancedSample:IntentsAdvancedSampleInstrumentationTest_22_x86" + - "-//ui/espresso/IntentsAdvancedSample:IntentsAdvancedSampleInstrumentationTest_21_x86" + - "-//ui/espresso/IntentsAdvancedSample:IntentsAdvancedSampleInstrumentationTest_19_x86" + - "-//ui/espresso/IdlingResourceSample:IdlingResourceSampleInstrumentationTest_23_x86" + - "-//ui/espresso/IdlingResourceSample:IdlingResourceSampleInstrumentationTest_22_x86" + - "-//ui/espresso/IdlingResourceSample:IdlingResourceSampleInstrumentationTest_21_x86" + - "-//ui/espresso/IdlingResourceSample:IdlingResourceSampleInstrumentationTest_19_x86" + - "-//ui/espresso/DataAdapterSample:DataAdapterSampleInstrumentationTest_23_x86" + - "-//ui/espresso/DataAdapterSample:DataAdapterSampleInstrumentationTest_22_x86" + - "-//ui/espresso/DataAdapterSample:DataAdapterSampleInstrumentationTest_21_x86" + - "-//ui/espresso/DataAdapterSample:DataAdapterSampleInstrumentationTest_19_x86" + - "-//ui/espresso/CustomMatcherSample:CustomMatcherSampleInstrumentationTest_23_x86" + - "-//ui/espresso/CustomMatcherSample:CustomMatcherSampleInstrumentationTest_22_x86" + - "-//ui/espresso/CustomMatcherSample:CustomMatcherSampleInstrumentationTest_21_x86" + - "-//ui/espresso/CustomMatcherSample:CustomMatcherSampleInstrumentationTest_19_x86" + - "-//ui/espresso/BasicSample:BasicSampleInstrumentationTest_23_x86" + - "-//ui/espresso/BasicSample:BasicSampleInstrumentationTest_22_x86" + - "-//ui/espresso/BasicSample:BasicSampleInstrumentationTest_21_x86" + - "-//ui/espresso/BasicSample:BasicSampleInstrumentationTest_19_x86" + - "-//ui/espresso/AccessibilitySample:BasicSampleInstrumentationTest_23_x86" + - "-//ui/espresso/AccessibilitySample:BasicSampleInstrumentationTest_22_x86" + - "-//ui/espresso/AccessibilitySample:BasicSampleInstrumentationTest_21_x86" + - "-//ui/espresso/AccessibilitySample:BasicSampleInstrumentationTest_19_x86" + macos: + # Testing does not work for macos and windows yet + build_targets: # Results of `bazel query 'kind(android_binary, //...)' + - "//ui/uiautomator/BasicSample:BasicSampleTest" + - "//ui/uiautomator/BasicSample:BasicSample" + - "//ui/espresso/RecyclerViewSample:RecyclerViewSampleTest" + - "//ui/espresso/RecyclerViewSample:RecyclerViewSample" + - "//ui/espresso/MultiWindowSample:MultiWindowSampleTest" + - "//ui/espresso/MultiWindowSample:MultiWindowSample" + - "//ui/espresso/IntentsBasicSample:IntentsBasicSampleTest" + - "//ui/espresso/IntentsBasicSample:IntentsBasicSample" + - "//ui/espresso/IntentsAdvancedSample:IntentsAdvancedSampleTest" + - "//ui/espresso/IntentsAdvancedSample:IntentsAdvancedSample" + - "//ui/espresso/IdlingResourceSample:IdlingResourceSampleTest" + - "//ui/espresso/IdlingResourceSample:IdlingResourceSample" + - "//ui/espresso/DataAdapterSample:DataAdapterSampleTest" + - "//ui/espresso/DataAdapterSample:DataAdapterSample" + - "//ui/espresso/CustomMatcherSample:CustomMatcherSampleTest" + - "//ui/espresso/CustomMatcherSample:CustomMatcherSample" + - "//ui/espresso/BasicSample:BasicSampleTest" + - "//ui/espresso/BasicSample:BasicSample" + - "//ui/espresso/AccessibilitySample:BasicSampleTest" + - "//ui/espresso/AccessibilitySample:BasicSample" + windows: + build_targets: # Results of `bazel query 'kind(android_binary, //...)' + - "//ui/uiautomator/BasicSample:BasicSampleTest" + - "//ui/uiautomator/BasicSample:BasicSample" + - "//ui/espresso/RecyclerViewSample:RecyclerViewSampleTest" + - "//ui/espresso/RecyclerViewSample:RecyclerViewSample" + - "//ui/espresso/MultiWindowSample:MultiWindowSampleTest" + - "//ui/espresso/MultiWindowSample:MultiWindowSample" + - "//ui/espresso/IntentsBasicSample:IntentsBasicSampleTest" + - "//ui/espresso/IntentsBasicSample:IntentsBasicSample" + - "//ui/espresso/IntentsAdvancedSample:IntentsAdvancedSampleTest" + - "//ui/espresso/IntentsAdvancedSample:IntentsAdvancedSample" + - "//ui/espresso/IdlingResourceSample:IdlingResourceSampleTest" + - "//ui/espresso/IdlingResourceSample:IdlingResourceSample" + - "//ui/espresso/DataAdapterSample:DataAdapterSampleTest" + - "//ui/espresso/DataAdapterSample:DataAdapterSample" + - "//ui/espresso/CustomMatcherSample:CustomMatcherSampleTest" + - "//ui/espresso/CustomMatcherSample:CustomMatcherSample" + - "//ui/espresso/BasicSample:BasicSampleTest" + - "//ui/espresso/BasicSample:BasicSample" + - "//ui/espresso/AccessibilitySample:BasicSampleTest" + - "//ui/espresso/AccessibilitySample:BasicSample" + diff --git a/build.gradle b/build.gradle deleted file mode 100644 index 5331d94cc..000000000 --- a/build.gradle +++ /dev/null @@ -1,47 +0,0 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. - -buildscript { - repositories { - jcenter() - } - dependencies { - classpath 'com.android.tools.build:gradle:1.1.3' - - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files - } -} - -allprojects { - repositories { - jcenter() - } - - // Temporary workaround for bug: https://code.google.com/p/android-test-kit/issues/detail?id=136 - configurations.all { - resolutionStrategy.force 'com.android.support:support-annotations:22.1.0' - } - - apply plugin: 'findbugs' - - task findbugs(type: FindBugs) { - ignoreFailures = true - effort = "max" - reportLevel = "high" - //excludeFilter = new File("${project.rootDir}/config/quality/findbugs/findbugs-filter.xml") - classes = files("$project.buildDir/intermediates/classes/") - - source 'src' - include '**/*.java' - exclude '**/gen/**' - - reports { - xml { - destination "$project.buildDir/reports/findbugs/findbugs.xml" - xml.withMessages true - } - } - - classpath = files() - } -} diff --git a/common_defs.bzl b/common_defs.bzl new file mode 100644 index 000000000..6e4f4f3b5 --- /dev/null +++ b/common_defs.bzl @@ -0,0 +1,15 @@ +# Common constants for bazel builds + +# keep naming convention consistent with gradle variables, so version numbers can be auto-incremented +# via a script + +androidxLibVersion = "1.0.0" +coreVersion = "1.2.0-beta01" +extJUnitVersion = "1.1.1-beta01" +extTruthVersion = "1.2.0-beta01" +runnerVersion = "1.2.0-beta01" +rulesVersion = "1.2.0-beta01" +espressoVersion = "3.2.0-beta01" +uiAutomatorVersion = "2.2.0" +minSdkVersion = "14" +targetSdkVersion = "28" diff --git a/downloads/espresso-cheat-sheet-2.1.0.pdf b/downloads/espresso-cheat-sheet-2.1.0.pdf deleted file mode 100644 index de3c2074a..000000000 Binary files a/downloads/espresso-cheat-sheet-2.1.0.pdf and /dev/null differ diff --git a/downloads/espresso-cheat-sheet-2.1.0.png b/downloads/espresso-cheat-sheet-2.1.0.png deleted file mode 100644 index f53b5c0e7..000000000 Binary files a/downloads/espresso-cheat-sheet-2.1.0.png and /dev/null differ diff --git a/espresso/BasicSample/app/build.gradle b/espresso/BasicSample/app/build.gradle deleted file mode 100644 index c9af8c1a9..000000000 --- a/espresso/BasicSample/app/build.gradle +++ /dev/null @@ -1,33 +0,0 @@ -apply plugin: 'com.android.application' - -android { - compileSdkVersion 22 - buildToolsVersion '22.0.1' - defaultConfig { - applicationId "com.example.android.testing.espresso.BasicSample" - minSdkVersion 10 - targetSdkVersion 22 - versionCode 1 - versionName "1.0" - - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" - } - packagingOptions { - exclude 'LICENSE.txt' - } - lintOptions { - abortOnError false - } - productFlavors { - } -} - -dependencies { - // App dependencies - compile 'com.android.support:support-annotations:22.1.0' - compile 'com.google.guava:guava:18.0' - // Testing-only dependencies - androidTestCompile 'com.android.support.test:runner:0.2' - androidTestCompile 'com.android.support.test:rules:0.2' - androidTestCompile 'com.android.support.test.espresso:espresso-core:2.1' -} diff --git a/espresso/BasicSample/build.gradle b/espresso/BasicSample/build.gradle deleted file mode 100644 index 25fad9a55..000000000 --- a/espresso/BasicSample/build.gradle +++ /dev/null @@ -1,19 +0,0 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. - -buildscript { - repositories { - jcenter() - } - dependencies { - classpath 'com.android.tools.build:gradle:1.1.3' - - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files - } -} - -allprojects { - repositories { - jcenter() - } -} diff --git a/espresso/BasicSample/gradle/wrapper/gradle-wrapper.jar b/espresso/BasicSample/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 8c0fb64a8..000000000 Binary files a/espresso/BasicSample/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/espresso/BasicSample/gradle/wrapper/gradle-wrapper.properties b/espresso/BasicSample/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 0ed71dbdb..000000000 --- a/espresso/BasicSample/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -#Wed Nov 05 14:10:42 GMT 2014 -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip diff --git a/espresso/BasicSampleBundled/.classpath b/espresso/BasicSampleBundled/.classpath deleted file mode 100644 index 2ed571346..000000000 --- a/espresso/BasicSampleBundled/.classpath +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/espresso/BasicSampleBundled/.gitignore b/espresso/BasicSampleBundled/.gitignore deleted file mode 100644 index 4a23383d6..000000000 --- a/espresso/BasicSampleBundled/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -bin -gen -.settings -project.properties diff --git a/espresso/BasicSampleBundled/.project b/espresso/BasicSampleBundled/.project deleted file mode 100644 index 71a8acadd..000000000 --- a/espresso/BasicSampleBundled/.project +++ /dev/null @@ -1,33 +0,0 @@ - - - BasicSampleBundled - - - - - - com.android.ide.eclipse.adt.ResourceManagerBuilder - - - - - com.android.ide.eclipse.adt.PreCompilerBuilder - - - - - org.eclipse.jdt.core.javabuilder - - - - - com.android.ide.eclipse.adt.ApkBuilder - - - - - - com.android.ide.eclipse.adt.AndroidNature - org.eclipse.jdt.core.javanature - - diff --git a/espresso/BasicSampleBundled/AndroidManifest.xml b/espresso/BasicSampleBundled/AndroidManifest.xml deleted file mode 100644 index bc45cedcc..000000000 --- a/espresso/BasicSampleBundled/AndroidManifest.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/espresso/BasicSampleBundled/README.md b/espresso/BasicSampleBundled/README.md deleted file mode 100644 index b965e88e4..000000000 --- a/espresso/BasicSampleBundled/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# Basic sample for Espresso using static JAR files - -*If you are using Espresso with Eclipse, try this sample first.* - -This project uses Eclipse and ADT to build and run the tests. - -1. Download the project code, preferably using `git clone`. -1. Check out the static JAR files required to run the Espresso tests in the libs/ folder of the project -1. Run the ./remove_license.sh script to remove duplicated LICENSE.txt files. This step is required because some of the test dependencies contain LICENSE.txt files which result in this build error: -"Error generating final archive: Found duplicate file for APK: LICENSE.txt". -The problem is that the same LICENSE.TXT file is found multiple times and AAPT does not know how to resolve this conflict. -1. Check out the relevant code: - * The application under test is located in `src/` - * Tests are in `tests/` -1. Create the test configuration with a custom runner: `android.support.test.runner.AndroidJUnitRunner` - * Open *Run* menu | *Run Configurations* - * Click on Android JUnit Test - * Add a new configuration by pressing the "new launch configuration" button - * Select your project by clicking the "Browse" button - * Add a *Specific instrumentation runner*: `android.support.test.runner.AndroidJUnitRunner` -1. Connect a device or start an emulator - * Turn animations off [link link] -1. Run the newly created configuration - -The application will be started on the device/emulator and a series of actions will be performed automatically. diff --git a/espresso/BasicSampleBundled/ic_launcher-web.png b/espresso/BasicSampleBundled/ic_launcher-web.png deleted file mode 100644 index 745d2e70b..000000000 Binary files a/espresso/BasicSampleBundled/ic_launcher-web.png and /dev/null differ diff --git a/espresso/BasicSampleBundled/libs/android-support-v4.jar b/espresso/BasicSampleBundled/libs/android-support-v4.jar deleted file mode 100644 index bd450c734..000000000 Binary files a/espresso/BasicSampleBundled/libs/android-support-v4.jar and /dev/null differ diff --git a/espresso/BasicSampleBundled/libs/dagger-1.2.1.jar b/espresso/BasicSampleBundled/libs/dagger-1.2.1.jar deleted file mode 100644 index 90d950993..000000000 Binary files a/espresso/BasicSampleBundled/libs/dagger-1.2.1.jar and /dev/null differ diff --git a/espresso/BasicSampleBundled/libs/dagger-compiler-1.2.1.jar b/espresso/BasicSampleBundled/libs/dagger-compiler-1.2.1.jar deleted file mode 100644 index f2aa56df7..000000000 Binary files a/espresso/BasicSampleBundled/libs/dagger-compiler-1.2.1.jar and /dev/null differ diff --git a/espresso/BasicSampleBundled/libs/espresso-contrib-2.1-release.jar b/espresso/BasicSampleBundled/libs/espresso-contrib-2.1-release.jar deleted file mode 100644 index 0a7d3d00d..000000000 Binary files a/espresso/BasicSampleBundled/libs/espresso-contrib-2.1-release.jar and /dev/null differ diff --git a/espresso/BasicSampleBundled/libs/espresso-core-2.1-release.jar b/espresso/BasicSampleBundled/libs/espresso-core-2.1-release.jar deleted file mode 100644 index 2d9bcf2c3..000000000 Binary files a/espresso/BasicSampleBundled/libs/espresso-core-2.1-release.jar and /dev/null differ diff --git a/espresso/BasicSampleBundled/libs/espresso-idling-resource-2.1-release.jar b/espresso/BasicSampleBundled/libs/espresso-idling-resource-2.1-release.jar deleted file mode 100644 index aa81282c2..000000000 Binary files a/espresso/BasicSampleBundled/libs/espresso-idling-resource-2.1-release.jar and /dev/null differ diff --git a/espresso/BasicSampleBundled/libs/espresso-intents-2.1-release.jar b/espresso/BasicSampleBundled/libs/espresso-intents-2.1-release.jar deleted file mode 100644 index f25b32c2c..000000000 Binary files a/espresso/BasicSampleBundled/libs/espresso-intents-2.1-release.jar and /dev/null differ diff --git a/espresso/BasicSampleBundled/libs/exposed-instrumentation-api-publish-0.2-release.jar b/espresso/BasicSampleBundled/libs/exposed-instrumentation-api-publish-0.2-release.jar deleted file mode 100644 index c3c396378..000000000 Binary files a/espresso/BasicSampleBundled/libs/exposed-instrumentation-api-publish-0.2-release.jar and /dev/null differ diff --git a/espresso/BasicSampleBundled/libs/guava-14.0.1.jar b/espresso/BasicSampleBundled/libs/guava-14.0.1.jar deleted file mode 100644 index 3a3d9258e..000000000 Binary files a/espresso/BasicSampleBundled/libs/guava-14.0.1.jar and /dev/null differ diff --git a/espresso/BasicSampleBundled/libs/hamcrest-core-1.1.jar b/espresso/BasicSampleBundled/libs/hamcrest-core-1.1.jar deleted file mode 100644 index 8483191e8..000000000 Binary files a/espresso/BasicSampleBundled/libs/hamcrest-core-1.1.jar and /dev/null differ diff --git a/espresso/BasicSampleBundled/libs/hamcrest-integration-1.1.jar b/espresso/BasicSampleBundled/libs/hamcrest-integration-1.1.jar deleted file mode 100644 index a7cf7db65..000000000 Binary files a/espresso/BasicSampleBundled/libs/hamcrest-integration-1.1.jar and /dev/null differ diff --git a/espresso/BasicSampleBundled/libs/hamcrest-library-1.1.jar b/espresso/BasicSampleBundled/libs/hamcrest-library-1.1.jar deleted file mode 100644 index e7adc06e9..000000000 Binary files a/espresso/BasicSampleBundled/libs/hamcrest-library-1.1.jar and /dev/null differ diff --git a/espresso/BasicSampleBundled/libs/javawriter-2.1.1.jar b/espresso/BasicSampleBundled/libs/javawriter-2.1.1.jar deleted file mode 100644 index 62ad1d805..000000000 Binary files a/espresso/BasicSampleBundled/libs/javawriter-2.1.1.jar and /dev/null differ diff --git a/espresso/BasicSampleBundled/libs/javax.annotation-api-1.2.jar b/espresso/BasicSampleBundled/libs/javax.annotation-api-1.2.jar deleted file mode 100644 index 9ab39ffa4..000000000 Binary files a/espresso/BasicSampleBundled/libs/javax.annotation-api-1.2.jar and /dev/null differ diff --git a/espresso/BasicSampleBundled/libs/javax.inject-1.jar b/espresso/BasicSampleBundled/libs/javax.inject-1.jar deleted file mode 100644 index b2a9d0bf7..000000000 Binary files a/espresso/BasicSampleBundled/libs/javax.inject-1.jar and /dev/null differ diff --git a/espresso/BasicSampleBundled/libs/jsr305-1.3.9.jar b/espresso/BasicSampleBundled/libs/jsr305-1.3.9.jar deleted file mode 100644 index a9afc6619..000000000 Binary files a/espresso/BasicSampleBundled/libs/jsr305-1.3.9.jar and /dev/null differ diff --git a/espresso/BasicSampleBundled/libs/junit-dep-4.10.jar b/espresso/BasicSampleBundled/libs/junit-dep-4.10.jar deleted file mode 100644 index 1290fef5c..000000000 Binary files a/espresso/BasicSampleBundled/libs/junit-dep-4.10.jar and /dev/null differ diff --git a/espresso/BasicSampleBundled/libs/rules-0.2-release.jar b/espresso/BasicSampleBundled/libs/rules-0.2-release.jar deleted file mode 100644 index b2d1d3d0d..000000000 Binary files a/espresso/BasicSampleBundled/libs/rules-0.2-release.jar and /dev/null differ diff --git a/espresso/BasicSampleBundled/libs/runner-0.2-release.jar b/espresso/BasicSampleBundled/libs/runner-0.2-release.jar deleted file mode 100644 index c3775f3bf..000000000 Binary files a/espresso/BasicSampleBundled/libs/runner-0.2-release.jar and /dev/null differ diff --git a/espresso/BasicSampleBundled/libs/uiautomator-v18-2.1.0-release.jar b/espresso/BasicSampleBundled/libs/uiautomator-v18-2.1.0-release.jar deleted file mode 100644 index c007653b3..000000000 Binary files a/espresso/BasicSampleBundled/libs/uiautomator-v18-2.1.0-release.jar and /dev/null differ diff --git a/espresso/BasicSampleBundled/proguard-project.txt b/espresso/BasicSampleBundled/proguard-project.txt deleted file mode 100644 index f2fe1559a..000000000 --- a/espresso/BasicSampleBundled/proguard-project.txt +++ /dev/null @@ -1,20 +0,0 @@ -# To enable ProGuard in your project, edit project.properties -# to define the proguard.config property as described in that file. -# -# Add project specific ProGuard rules here. -# By default, the flags in this file are appended to flags specified -# in ${sdk.dir}/tools/proguard/proguard-android.txt -# You can edit the include path and order by changing the ProGuard -# include property in project.properties. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# Add any project specific keep options here: - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} diff --git a/espresso/BasicSampleBundled/project.properties b/espresso/BasicSampleBundled/project.properties deleted file mode 100644 index 00cf62bac..000000000 --- a/espresso/BasicSampleBundled/project.properties +++ /dev/null @@ -1,14 +0,0 @@ -# This file is automatically generated by Android Tools. -# Do not modify this file -- YOUR CHANGES WILL BE ERASED! -# -# This file must be checked in Version Control Systems. -# -# To customize properties used by the Ant build system edit -# "ant.properties", and override values to adapt the script to your -# project structure. -# -# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): -#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt - -# Project target. -target=android-22 diff --git a/espresso/BasicSampleBundled/remove_license.sh b/espresso/BasicSampleBundled/remove_license.sh deleted file mode 100755 index 99cb55b84..000000000 --- a/espresso/BasicSampleBundled/remove_license.sh +++ /dev/null @@ -1,5 +0,0 @@ -zip -d libs/hamcrest-core-1.1.jar LICENSE.txt -zip -d libs/hamcrest-library-1.1.jar LICENSE.txt -zip -d libs/hamcrest-integration-1.1.jar LICENSE.txt -zip -d libs/junit-dep-4.10.jar LICENSE.txt - diff --git a/espresso/BasicSampleBundled/res/drawable-hdpi/ic_launcher.png b/espresso/BasicSampleBundled/res/drawable-hdpi/ic_launcher.png deleted file mode 100644 index 5a06f0fda..000000000 Binary files a/espresso/BasicSampleBundled/res/drawable-hdpi/ic_launcher.png and /dev/null differ diff --git a/espresso/BasicSampleBundled/res/drawable-mdpi/ic_launcher.png b/espresso/BasicSampleBundled/res/drawable-mdpi/ic_launcher.png deleted file mode 100644 index 1758c24c1..000000000 Binary files a/espresso/BasicSampleBundled/res/drawable-mdpi/ic_launcher.png and /dev/null differ diff --git a/espresso/BasicSampleBundled/res/drawable-xhdpi/ic_launcher.png b/espresso/BasicSampleBundled/res/drawable-xhdpi/ic_launcher.png deleted file mode 100644 index fc92a5613..000000000 Binary files a/espresso/BasicSampleBundled/res/drawable-xhdpi/ic_launcher.png and /dev/null differ diff --git a/espresso/BasicSampleBundled/res/drawable-xxhdpi/ic_launcher.png b/espresso/BasicSampleBundled/res/drawable-xxhdpi/ic_launcher.png deleted file mode 100644 index 9837c49b8..000000000 Binary files a/espresso/BasicSampleBundled/res/drawable-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/espresso/BasicSampleBundled/res/values-v11/styles.xml b/espresso/BasicSampleBundled/res/values-v11/styles.xml deleted file mode 100644 index 51e666758..000000000 --- a/espresso/BasicSampleBundled/res/values-v11/styles.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - diff --git a/espresso/BasicSampleBundled/res/values-v14/styles.xml b/espresso/BasicSampleBundled/res/values-v14/styles.xml deleted file mode 100644 index 9b9dee210..000000000 --- a/espresso/BasicSampleBundled/res/values-v14/styles.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - diff --git a/espresso/BasicSampleBundled/src/com/example/android/testing/espresso/basicsamplebundled/ShowTextActivity.java b/espresso/BasicSampleBundled/src/com/example/android/testing/espresso/basicsamplebundled/ShowTextActivity.java deleted file mode 100644 index a0d4c0bb5..000000000 --- a/espresso/BasicSampleBundled/src/com/example/android/testing/espresso/basicsamplebundled/ShowTextActivity.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2015, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.example.android.testing.espresso.basicsamplebundled; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.widget.TextView; - -import com.google.common.base.Strings; - -/** - * A simple {@link Activity} that shows a message. - */ -public class ShowTextActivity extends Activity { - - // The name of the extra data sent through an {@link Intent}. - public final static String KEY_EXTRA_MESSAGE = - "com.example.android.testing.espresso.basicsample.MESSAGE"; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_show_text); - - // Get the message from the Intent. - Intent intent = getIntent(); - String message = Strings.nullToEmpty(intent.getStringExtra(KEY_EXTRA_MESSAGE)); - - // Show message. - ((TextView)findViewById(R.id.show_text_view)).setText(message); - } - - /** - * Creates an {@link Intent} for {@link ShowTextActivity} with the message to be displayed. - * @param context the {@link Context} where the {@link Intent} will be used - * @param message a {@link String} with text to be displayed - * @return an {@link Intent} used to start {@link ShowTextActivity} - */ - static protected Intent newStartIntent(Context context, String message) { - Intent newIntent = new Intent(context, ShowTextActivity.class); - newIntent.putExtra(KEY_EXTRA_MESSAGE, message); - return newIntent; - } -} diff --git a/espresso/BasicSampleBundled/tests/com/example/android/testing/espresso/basicsamplebundled/tests/ChangeTextBehaviorTest.java b/espresso/BasicSampleBundled/tests/com/example/android/testing/espresso/basicsamplebundled/tests/ChangeTextBehaviorTest.java deleted file mode 100644 index e36f77e3b..000000000 --- a/espresso/BasicSampleBundled/tests/com/example/android/testing/espresso/basicsamplebundled/tests/ChangeTextBehaviorTest.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2015, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.example.android.testing.espresso.basicsamplebundled.tests; - -import static android.support.test.espresso.Espresso.onView; -import static android.support.test.espresso.action.ViewActions.click; -import static android.support.test.espresso.action.ViewActions.closeSoftKeyboard; -import static android.support.test.espresso.action.ViewActions.typeText; -import static android.support.test.espresso.assertion.ViewAssertions.matches; -import static android.support.test.espresso.matcher.ViewMatchers.withId; -import static android.support.test.espresso.matcher.ViewMatchers.withText; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -import android.app.Activity; -import android.support.test.espresso.action.ViewActions; -import android.support.test.espresso.matcher.ViewMatchers; -import android.support.test.rule.ActivityTestRule; -import android.support.test.runner.AndroidJUnit4; -import android.test.ActivityInstrumentationTestCase2; -import android.test.suitebuilder.annotation.LargeTest; - -import com.example.android.testing.espresso.basicsamplebundled.MainActivity; -import com.example.android.testing.espresso.basicsamplebundled.R; - - - - -/** - * Basic tests showcasing simple view matchers and actions like {@link ViewMatchers#withId}, - * {@link ViewActions#click} and {@link ViewActions#typeText}. - *

- * Note that there is no need to tell Espresso that a view is in a different {@link Activity}. - */ -@RunWith(AndroidJUnit4.class) -@LargeTest -public class ChangeTextBehaviorTest { - - public static final String STRING_TO_BE_TYPED = "Espresso"; - - /** - * A JUnit {@link Rule @Rule} to launch your activity under test. This is a replacement - * for {@link ActivityInstrumentationTestCase2}. - *

- * Rules are interceptors which are executed for each test method and will run before - * any of your setup code in the {@link Before @Before} method. - *

- * {@link ActivityTestRule} will create and launch of the activity for you and also expose - * the activity under test. To get a reference to the activity you can use - * the {@link ActivityTestRule#getActivity()} method. - */ - @Rule - public ActivityTestRule mActivityRule = new ActivityTestRule( - MainActivity.class); - - @Test - public void changeText_sameActivity() { - // Type text and then press the button. - onView(withId(R.id.editTextUserInput)) - .perform(typeText(STRING_TO_BE_TYPED), closeSoftKeyboard()); - onView(withId(R.id.changeTextBt)).perform(click()); - - // Check that the text was changed. - onView(withId(R.id.textToBeChanged)).check(matches(withText(STRING_TO_BE_TYPED))); - } - - @Test - public void changeText_newActivity() { - // Type text and then press the button. - onView(withId(R.id.editTextUserInput)).perform(typeText(STRING_TO_BE_TYPED), - closeSoftKeyboard()); - onView(withId(R.id.activityChangeTextBtn)).perform(click()); - - // This view is in a different Activity, no need to tell Espresso. - onView(withId(R.id.show_text_view)).check(matches(withText(STRING_TO_BE_TYPED))); - } -} \ No newline at end of file diff --git a/espresso/BasicSampleBundled/tests/com/example/android/testing/espresso/basicsamplebundled/tests/EnableJUnit4InEclipse.java b/espresso/BasicSampleBundled/tests/com/example/android/testing/espresso/basicsamplebundled/tests/EnableJUnit4InEclipse.java deleted file mode 100644 index 68922a58b..000000000 --- a/espresso/BasicSampleBundled/tests/com/example/android/testing/espresso/basicsamplebundled/tests/EnableJUnit4InEclipse.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2015, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.example.android.testing.espresso.basicsamplebundled.tests; - -import junit.framework.TestCase; - -/** - * Unfortunately this is required by Eclipse to run JUnit4 style tests. - * - *

- * This workaround tricks Eclipse into thinking there are actual tests to run. To find out if any - * tests are available, Eclipse looks at classes which extend from {@link TestCase} or - * {@link TestSuite}. As JUnit4 tests do not extend from {@link TestCase} anymore this pre-check - * fails and Eclipse will not even attempt to start the runner. - * - *

- * Once Eclipse detects this TestCase, the AndroidJUnitRunner will be able to detect the rest of the - * tests. - */ -public class EnableJUnit4InEclipse extends TestCase { - public void testDummy() {}; -} diff --git a/espresso/CustomMatcherSample/app/build.gradle b/espresso/CustomMatcherSample/app/build.gradle deleted file mode 100644 index 476cb5a4d..000000000 --- a/espresso/CustomMatcherSample/app/build.gradle +++ /dev/null @@ -1,39 +0,0 @@ -apply plugin: 'com.android.application' - -android { - compileSdkVersion 22 - buildToolsVersion '22.0.1' - defaultConfig { - applicationId "com.example.android.testing.espresso.CustomMatcherSample" - minSdkVersion 10 - targetSdkVersion 22 - versionCode 1 - versionName "1.0" - - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - packagingOptions { - exclude 'LICENSE.txt' - } - lintOptions { - abortOnError false - } - productFlavors { - } -} - -dependencies { - // App dependencies - compile 'com.android.support:support-annotations:22.1.0' - compile 'com.google.guava:guava:18.0' - // Testing-only dependencies - androidTestCompile 'com.android.support.test:runner:0.2' - androidTestCompile 'com.android.support.test:rules:0.2' - androidTestCompile 'com.android.support.test.espresso:espresso-core:2.1' -} diff --git a/espresso/CustomMatcherSample/build.gradle b/espresso/CustomMatcherSample/build.gradle deleted file mode 100644 index 25fad9a55..000000000 --- a/espresso/CustomMatcherSample/build.gradle +++ /dev/null @@ -1,19 +0,0 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. - -buildscript { - repositories { - jcenter() - } - dependencies { - classpath 'com.android.tools.build:gradle:1.1.3' - - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files - } -} - -allprojects { - repositories { - jcenter() - } -} diff --git a/espresso/CustomMatcherSample/gradle/wrapper/gradle-wrapper.jar b/espresso/CustomMatcherSample/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 8c0fb64a8..000000000 Binary files a/espresso/CustomMatcherSample/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/espresso/DataAdapterSample/app/build.gradle b/espresso/DataAdapterSample/app/build.gradle deleted file mode 100644 index 0c01fae84..000000000 --- a/espresso/DataAdapterSample/app/build.gradle +++ /dev/null @@ -1,30 +0,0 @@ -apply plugin: 'com.android.application' - -android { - compileSdkVersion 22 - buildToolsVersion '22.0.1' - defaultConfig { - applicationId "com.example.android.testing.espresso.DataAdapterSample" - minSdkVersion 10 - targetSdkVersion 22 - versionCode 1 - versionName "1.0" - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" - - } - packagingOptions { - exclude 'LICENSE.txt' - } - productFlavors { - } -} - -dependencies { - // App dependencies - compile 'com.android.support:support-annotations:22.1.0' - compile 'com.google.guava:guava:18.0' - // Testing-only dependencies - androidTestCompile 'com.android.support.test:runner:0.2' - androidTestCompile 'com.android.support.test:rules:0.2' - androidTestCompile 'com.android.support.test.espresso:espresso-core:2.1' -} diff --git a/espresso/DataAdapterSample/build.gradle b/espresso/DataAdapterSample/build.gradle deleted file mode 100644 index 25fad9a55..000000000 --- a/espresso/DataAdapterSample/build.gradle +++ /dev/null @@ -1,19 +0,0 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. - -buildscript { - repositories { - jcenter() - } - dependencies { - classpath 'com.android.tools.build:gradle:1.1.3' - - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files - } -} - -allprojects { - repositories { - jcenter() - } -} diff --git a/espresso/DataAdapterSample/gradle/wrapper/gradle-wrapper.jar b/espresso/DataAdapterSample/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 8c0fb64a8..000000000 Binary files a/espresso/DataAdapterSample/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/espresso/IntentsBasicSample/app/build.gradle b/espresso/IntentsBasicSample/app/build.gradle deleted file mode 100644 index ada6996f9..000000000 --- a/espresso/IntentsBasicSample/app/build.gradle +++ /dev/null @@ -1,34 +0,0 @@ -apply plugin: 'com.android.application' - -android { - compileSdkVersion 22 - buildToolsVersion '22.0.1' - defaultConfig { - applicationId "com.example.android.testing.espresso.BasicSample" - minSdkVersion 10 - targetSdkVersion 22 - versionCode 1 - versionName "1.0" - - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" - } - packagingOptions { - exclude 'LICENSE.txt' - } - lintOptions { - abortOnError false - } - productFlavors { - } -} - -dependencies { - // App dependencies - compile 'com.google.guava:guava:18.0' - - // Testing-only dependencies - androidTestCompile 'com.android.support.test:runner:0.2' - androidTestCompile 'com.android.support.test:rules:0.2' - androidTestCompile 'com.android.support.test.espresso:espresso-core:2.1' - androidTestCompile 'com.android.support.test.espresso:espresso-intents:2.1' -} diff --git a/espresso/IntentsBasicSample/build.gradle b/espresso/IntentsBasicSample/build.gradle deleted file mode 100644 index 25fad9a55..000000000 --- a/espresso/IntentsBasicSample/build.gradle +++ /dev/null @@ -1,19 +0,0 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. - -buildscript { - repositories { - jcenter() - } - dependencies { - classpath 'com.android.tools.build:gradle:1.1.3' - - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files - } -} - -allprojects { - repositories { - jcenter() - } -} diff --git a/espresso/IntentsBasicSample/gradle/wrapper/gradle-wrapper.jar b/espresso/IntentsBasicSample/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 8c0fb64a8..000000000 Binary files a/espresso/IntentsBasicSample/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/espresso/MultiWindowSample/app/build.gradle b/espresso/MultiWindowSample/app/build.gradle deleted file mode 100644 index 053d7d7a4..000000000 --- a/espresso/MultiWindowSample/app/build.gradle +++ /dev/null @@ -1,40 +0,0 @@ - -apply plugin: 'com.android.application' - -android { - compileSdkVersion 22 - buildToolsVersion '22.0.1' - defaultConfig { - applicationId "com.example.android.testing.espresso.MultiWindowSample" - minSdkVersion 10 - targetSdkVersion 22 - versionCode 1 - versionName "1.0" - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" - - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - packagingOptions { - exclude 'LICENSE.txt' - } - lintOptions { - abortOnError false - } - productFlavors { - } -} - -dependencies { - // App dependencies - compile 'com.android.support:support-annotations:22.1.0' - compile 'com.google.guava:guava:18.0' - // Testing-only dependencies - androidTestCompile 'com.android.support.test:runner:0.2' - androidTestCompile 'com.android.support.test:rules:0.2' - androidTestCompile 'com.android.support.test.espresso:espresso-core:2.1' -} diff --git a/espresso/MultiWindowSample/build.gradle b/espresso/MultiWindowSample/build.gradle deleted file mode 100644 index 25fad9a55..000000000 --- a/espresso/MultiWindowSample/build.gradle +++ /dev/null @@ -1,19 +0,0 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. - -buildscript { - repositories { - jcenter() - } - dependencies { - classpath 'com.android.tools.build:gradle:1.1.3' - - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files - } -} - -allprojects { - repositories { - jcenter() - } -} diff --git a/espresso/MultiWindowSample/gradle.properties b/espresso/MultiWindowSample/gradle.properties deleted file mode 100644 index 1d3591c8a..000000000 --- a/espresso/MultiWindowSample/gradle.properties +++ /dev/null @@ -1,18 +0,0 @@ -# Project-wide Gradle settings. - -# IDE (e.g. Android Studio) users: -# Gradle settings configured through the IDE *will override* -# any settings specified in this file. - -# For more details on how to configure your build environment visit -# http://www.gradle.org/docs/current/userguide/build_environment.html - -# Specifies the JVM arguments used for the daemon process. -# The setting is particularly useful for tweaking memory settings. -# Default value: -Xmx10248m -XX:MaxPermSize=256m -# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 - -# When configured, Gradle will run in incubating parallel mode. -# This option should only be used with decoupled projects. More details, visit -# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true \ No newline at end of file diff --git a/espresso/MultiWindowSample/gradle/wrapper/gradle-wrapper.jar b/espresso/MultiWindowSample/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 8c0fb64a8..000000000 Binary files a/espresso/MultiWindowSample/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/espresso/MultiWindowSample/gradle/wrapper/gradle-wrapper.properties b/espresso/MultiWindowSample/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index ed7059864..000000000 --- a/espresso/MultiWindowSample/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -#Mon Nov 17 11:45:05 GMT 2014 -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip diff --git a/espresso/MultiWindowSample/gradlew b/espresso/MultiWindowSample/gradlew deleted file mode 100755 index 91a7e269e..000000000 --- a/espresso/MultiWindowSample/gradlew +++ /dev/null @@ -1,164 +0,0 @@ -#!/usr/bin/env bash - -############################################################################## -## -## Gradle start up script for UN*X -## -############################################################################## - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn ( ) { - echo "$*" -} - -die ( ) { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; -esac - -# For Cygwin, ensure paths are in UNIX format before anything is touched. -if $cygwin ; then - [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` -fi - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >&- -APP_HOME="`pwd -P`" -cd "$SAVED" >&- - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") -} -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" - -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 8c0fb64a8..000000000 Binary files a/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 0c71e760d..000000000 --- a/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -#Wed Apr 10 15:27:10 PDT 2013 -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip diff --git a/gradlew b/gradlew deleted file mode 100755 index 91a7e269e..000000000 --- a/gradlew +++ /dev/null @@ -1,164 +0,0 @@ -#!/usr/bin/env bash - -############################################################################## -## -## Gradle start up script for UN*X -## -############################################################################## - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn ( ) { - echo "$*" -} - -die ( ) { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; -esac - -# For Cygwin, ensure paths are in UNIX format before anything is touched. -if $cygwin ; then - [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` -fi - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >&- -APP_HOME="`pwd -P`" -cd "$SAVED" >&- - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") -} -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" - -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/gradlew.bat b/gradlew.bat deleted file mode 100644 index aec99730b..000000000 --- a/gradlew.bat +++ /dev/null @@ -1,90 +0,0 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windowz variants - -if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/espresso/BasicSample/.gitignore b/integration/ServiceTestRuleSample/.gitignore similarity index 100% rename from espresso/BasicSample/.gitignore rename to integration/ServiceTestRuleSample/.gitignore diff --git a/integration/ServiceTestRuleSample/README.md b/integration/ServiceTestRuleSample/README.md new file mode 100644 index 000000000..21c8a9d71 --- /dev/null +++ b/integration/ServiceTestRuleSample/README.md @@ -0,0 +1,25 @@ +# Basic sample for ServiceTestRule + +This rule provides a simplified mechanism to start and shutdown your service before and after +the duration of your test. It also guarantees that the service is successfully connected when starting +(or binding to) a service. The service can be started (or bound) using one of the helper methods. +It will automatically be stopped (or unbound) after the test completes and any methods annotated with @After are finished. + +Note: This rule doesn't support `IntentService` because it's automatically destroyed when +`IntentService#onHandleIntent(android.content.Intent)` + finishes all outstanding commands. So there is no guarantee to establish a successful connection in a timely manner. + +This project uses the Gradle build system. You don't need an IDE to build and execute it but Android Studio is recommended. + +1. Download the project code, preferably using `git clone`. +1. Open the Android SDK Manager (*Tools* Menu | *Android*) and make sure you have installed the *Support Repository* under *Extras*. +1. In Android Studio, select *File* | *Open...* and point to the `./build.gradle` file. +1. Check out the relevant code: + * The application under test is located in `src/main/java` + * Tests are in `src/androidTest/java` +1. Connect a device or start an emulator +1. Run the newly created configuration + +The application will be started on the device/emulator and a series of actions will be performed automatically. + +If you are using Android Studio, the *Run* window will show the test results. diff --git a/integration/ServiceTestRuleSample/app/build.gradle b/integration/ServiceTestRuleSample/app/build.gradle new file mode 100644 index 000000000..5d2f7c613 --- /dev/null +++ b/integration/ServiceTestRuleSample/app/build.gradle @@ -0,0 +1,42 @@ +apply plugin: "com.android.application" + +android { + compileSdk 34 + defaultConfig { + applicationId "com.example.android.testing.integrationtesting.ServiceTestRuleSample" + minSdkVersion 21 + targetSdkVersion 34 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + productFlavors { + } + testOptions { + managedDevices { + devices { + // run with ../gradlew nexusOneApi30DebugAndroidTest + nexusOneApi30(com.android.build.api.dsl.ManagedVirtualDevice) { + // A lower resolution device is used here for better emulator performance + device = "Nexus One" + apiLevel = 30 + // Also use the AOSP ATD image for better emulator performance + systemImageSource = "aosp-atd" + } + } + } + } + namespace "com.example.android.testing.ServiceTestRuleSample" + lint { + abortOnError false + } +} + +dependencies { + // Testing-only dependencies + androidTestImplementation "androidx.test:core:" + rootProject.coreVersion; + androidTestImplementation "androidx.test.ext:junit:" + rootProject.extJUnitVersion; + androidTestImplementation "androidx.test:runner:" + rootProject.runnerVersion; + androidTestImplementation "androidx.test:rules:" + rootProject.rulesVersion; +} diff --git a/integration/ServiceTestRuleSample/app/src/androidTest/java/com/example/android/testing/ServiceTestRuleSample/LocalServiceTest.java b/integration/ServiceTestRuleSample/app/src/androidTest/java/com/example/android/testing/ServiceTestRuleSample/LocalServiceTest.java new file mode 100644 index 000000000..d81362862 --- /dev/null +++ b/integration/ServiceTestRuleSample/app/src/androidTest/java/com/example/android/testing/ServiceTestRuleSample/LocalServiceTest.java @@ -0,0 +1,77 @@ +/* + * Copyright 2015, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.android.testing.ServiceTestRuleSample; + +import android.content.Intent; +import android.os.IBinder; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.MediumTest; +import androidx.test.rule.ServiceTestRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.concurrent.TimeoutException; + +import static androidx.test.core.app.ApplicationProvider.getApplicationContext; +import static org.hamcrest.CoreMatchers.any; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +/** + * JUnit4 test that uses a {@link ServiceTestRule} to interact with a bound service. + *

+ * {@link ServiceTestRule} is a JUnit rule that provides a + * simplified mechanism to start and shutdown your service before + * and after the duration of your test. It also guarantees that the service is successfully + * connected when starting (or binding to) a service. The service can be started + * (or bound) using one of the helper methods. It will automatically be stopped (or unbound) after + * the test completes and any methods annotated with + * After are + * finished. + *

+ * Note: This rule doesn't support {@link android.app.IntentService} because it's automatically + * destroyed when {@link android.app.IntentService#onHandleIntent(android.content.Intent)} finishes + * all outstanding commands. So there is no guarantee to establish a successful connection + * in a timely manner. + */ +@MediumTest +@RunWith(AndroidJUnit4.class) +public class LocalServiceTest { + @Rule + public final ServiceTestRule mServiceRule = new ServiceTestRule(); + + @Test + public void testWithBoundService() throws TimeoutException { + // Create the service Intent. + Intent serviceIntent = + new Intent(getApplicationContext(), LocalService.class); + + // Data can be passed to the service via the Intent. + serviceIntent.putExtra(LocalService.SEED_KEY, 42L); + + // Bind the service and grab a reference to the binder. + IBinder binder = mServiceRule.bindService(serviceIntent); + + // Get the reference to the service, or you can call public methods on the binder directly. + LocalService service = ((LocalService.LocalBinder) binder).getService(); + + // Verify that the service is working correctly. + assertThat(service.getRandomInt(), is(any(Integer.class))); + } +} diff --git a/integration/ServiceTestRuleSample/app/src/main/AndroidManifest.xml b/integration/ServiceTestRuleSample/app/src/main/AndroidManifest.xml new file mode 100644 index 000000000..5dc076f8c --- /dev/null +++ b/integration/ServiceTestRuleSample/app/src/main/AndroidManifest.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + diff --git a/integration/ServiceTestRuleSample/app/src/main/java/com/example/android/testing/ServiceTestRuleSample/LocalService.java b/integration/ServiceTestRuleSample/app/src/main/java/com/example/android/testing/ServiceTestRuleSample/LocalService.java new file mode 100644 index 000000000..3eb0caef2 --- /dev/null +++ b/integration/ServiceTestRuleSample/app/src/main/java/com/example/android/testing/ServiceTestRuleSample/LocalService.java @@ -0,0 +1,68 @@ +/* + * Copyright 2015, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.android.testing.ServiceTestRuleSample; + +import android.app.Service; +import android.content.Intent; +import android.os.Binder; +import android.os.IBinder; + +import java.util.Random; + +/** + * {@link Service} that generates random numbers. + *

+ * A seed for the random number generator can be set via the {@link Intent} passed to + * {@link #onBind(Intent)}. + */ +public class LocalService extends Service { + // Used as a key for the Intent. + public static final String SEED_KEY = "SEED_KEY"; + + // Binder given to clients + private final IBinder mBinder = new LocalBinder(); + + // Random number generator + private Random mGenerator = new Random(); + + private long mSeed; + + @Override + public IBinder onBind(Intent intent) { + // If the Intent comes with a seed for the number generator, apply it. + if (intent.hasExtra(SEED_KEY)) { + mSeed = intent.getLongExtra(SEED_KEY, 0); + mGenerator.setSeed(mSeed); + } + return mBinder; + } + + public class LocalBinder extends Binder { + + public LocalService getService() { + // Return this instance of LocalService so clients can call public methods. + return LocalService.this; + } + } + + /** + * Returns a random integer in [0, 100). + */ + public int getRandomInt() { + return mGenerator.nextInt(100); + } +} diff --git a/integration/ServiceTestRuleSample/app/src/main/res/mipmap-hdpi/ic_launcher.png b/integration/ServiceTestRuleSample/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 000000000..52b03d09f Binary files /dev/null and b/integration/ServiceTestRuleSample/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/integration/ServiceTestRuleSample/app/src/main/res/mipmap-mdpi/ic_launcher.png b/integration/ServiceTestRuleSample/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 000000000..a54984340 Binary files /dev/null and b/integration/ServiceTestRuleSample/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/integration/ServiceTestRuleSample/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/integration/ServiceTestRuleSample/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 000000000..77f72db4f Binary files /dev/null and b/integration/ServiceTestRuleSample/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/integration/ServiceTestRuleSample/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/integration/ServiceTestRuleSample/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..b160e33dc Binary files /dev/null and b/integration/ServiceTestRuleSample/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/integration/ServiceTestRuleSample/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/integration/ServiceTestRuleSample/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 000000000..4c98df212 Binary files /dev/null and b/integration/ServiceTestRuleSample/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/integration/ServiceTestRuleSample/app/src/main/res/values-v13/styles.xml b/integration/ServiceTestRuleSample/app/src/main/res/values-v13/styles.xml new file mode 100644 index 000000000..7e86bfa57 --- /dev/null +++ b/integration/ServiceTestRuleSample/app/src/main/res/values-v13/styles.xml @@ -0,0 +1,20 @@ + + + + + + + diff --git a/ui/espresso/FragmentScenarioSample/app/src/sharedTest/java/com/example/android/testing/espresso/fragmentscenario/SampleDialogFragmentTest.kt b/ui/espresso/FragmentScenarioSample/app/src/sharedTest/java/com/example/android/testing/espresso/fragmentscenario/SampleDialogFragmentTest.kt new file mode 100644 index 000000000..8844e0f71 --- /dev/null +++ b/ui/espresso/FragmentScenarioSample/app/src/sharedTest/java/com/example/android/testing/espresso/fragmentscenario/SampleDialogFragmentTest.kt @@ -0,0 +1,53 @@ +package com.example.android.testing.espresso.fragmentscenario + +import androidx.fragment.app.testing.launchFragment +import androidx.fragment.app.testing.launchFragmentInContainer +import androidx.test.espresso.Espresso +import androidx.test.espresso.assertion.ViewAssertions +import androidx.test.espresso.matcher.RootMatchers.isDialog +import androidx.test.espresso.matcher.ViewMatchers +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.google.common.truth.Truth.assertThat +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.annotation.LooperMode + +/** + * A test using the androidx.test unified API, which can execute on an Android device or locally using Robolectric. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class SampleDialogFragmentTest { + + @Test + fun launchDialogFragmentAndVerifyUI() { + // Use launchFragment to launch the dialog fragment in a dialog. + val scenario = launchFragment() + + scenario.onFragment { fragment -> + assertThat(fragment.dialog).isNotNull() + assertThat(fragment.requireDialog().isShowing).isTrue() + } + + // Now use espresso to look for the fragment's text view and verify it is displayed. + Espresso.onView(ViewMatchers.withId(R.id.textView)).inRoot(isDialog()) + .check(ViewAssertions.matches(ViewMatchers.withText("I am a fragment"))); + } + + @Test + fun launchDialogFragmentEmbeddedToHostActivityAndVerifyUI() { + // Use launchFragmentInContainer to inflate a dialog fragment's view into Activity's content view. + val scenario = launchFragmentInContainer() + + scenario.onFragment { fragment -> + // Dialog is not created because you use launchFragmentInContainer and the view is inflated + // into the Activity's content view. + assertThat(fragment.dialog).isNull() + } + + // Now use espresso to look for the fragment's text view and verify it is displayed. + Espresso.onView(ViewMatchers.withId(R.id.textView)) + .check(ViewAssertions.matches(ViewMatchers.withText("I am a fragment"))); + } +} diff --git a/ui/espresso/FragmentScenarioSample/app/src/sharedTest/java/com/example/android/testing/espresso/fragmentscenario/SampleFragmentTest.kt b/ui/espresso/FragmentScenarioSample/app/src/sharedTest/java/com/example/android/testing/espresso/fragmentscenario/SampleFragmentTest.kt new file mode 100644 index 000000000..b35a058d0 --- /dev/null +++ b/ui/espresso/FragmentScenarioSample/app/src/sharedTest/java/com/example/android/testing/espresso/fragmentscenario/SampleFragmentTest.kt @@ -0,0 +1,29 @@ +package com.example.android.testing.espresso.fragmentscenario + +import androidx.fragment.app.testing.launchFragmentInContainer +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.withText +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.annotation.LooperMode + +/** + * A test using the androidx.test unified API, which can execute on an Android device or locally using Robolectric. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class SampleFragmentTest { + @Test + fun launchFragmentAndVerifyUI() { + // use launchInContainer to launch the fragment with UI + launchFragmentInContainer() + + // now use espresso to look for the fragment's text view and verify it is displayed + onView(withId(R.id.textView)).check(matches(withText("I am a fragment"))); + } +} diff --git a/ui/espresso/FragmentScenarioSample/build.gradle b/ui/espresso/FragmentScenarioSample/build.gradle new file mode 100644 index 000000000..c2a028acf --- /dev/null +++ b/ui/espresso/FragmentScenarioSample/build.gradle @@ -0,0 +1,41 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + ext.kotlinVersion = "1.9.22" + ext.agpVersion = "8.5.0" + repositories { + google() + mavenCentral() + + } + dependencies { + classpath "com.android.tools.build:gradle:$agpVersion" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion" + } +} + +allprojects { + repositories { + google() + mavenCentral() + + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} + +ext { + buildToolsVersion = "32.0.0" + androidxCoreVersion = "1.9.0" + androidxCompatVersion = "1.5.1" + androidxFragmentVersion = "1.5.3" + coreVersion = "1.6.1" + extJUnitVersion = "1.2.1" + runnerVersion = "1.6.1" + rulesVersion = "1.6.1" + espressoVersion = "3.6.1" + robolectricVersion = "4.13" + truthVersion = "1.1.3" +} diff --git a/ui/espresso/FragmentScenarioSample/gradle.properties b/ui/espresso/FragmentScenarioSample/gradle.properties new file mode 100644 index 000000000..119137565 --- /dev/null +++ b/ui/espresso/FragmentScenarioSample/gradle.properties @@ -0,0 +1,26 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx1536m +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Automatically convert third-party libraries to use AndroidX +android.enableJetifier=true +# Kotlin code style for this project: "official" or "obsolete": +kotlin.code.style=official +android.defaults.buildfeatures.buildconfig=true +android.nonTransitiveRClass=false +android.nonFinalResIds=false +# use compiled resources for Robolectric. See http://robolectric.org/migrating/#migrating-to-40 +# Not needed for Android Studio 3.4+ diff --git a/ui/espresso/FragmentScenarioSample/gradle/wrapper/gradle-wrapper.jar b/ui/espresso/FragmentScenarioSample/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 000000000..f6b961fd5 Binary files /dev/null and b/ui/espresso/FragmentScenarioSample/gradle/wrapper/gradle-wrapper.jar differ diff --git a/ui/espresso/FragmentScenarioSample/gradle/wrapper/gradle-wrapper.properties b/ui/espresso/FragmentScenarioSample/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..c00c06d34 --- /dev/null +++ b/ui/espresso/FragmentScenarioSample/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Sat Apr 27 14:01:24 PDT 2019 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip diff --git a/espresso/DataAdapterSample/gradlew b/ui/espresso/FragmentScenarioSample/gradlew similarity index 83% rename from espresso/DataAdapterSample/gradlew rename to ui/espresso/FragmentScenarioSample/gradlew index 91a7e269e..cccdd3d51 100755 --- a/espresso/DataAdapterSample/gradlew +++ b/ui/espresso/FragmentScenarioSample/gradlew @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/usr/bin/env sh ############################################################################## ## @@ -6,20 +6,38 @@ ## ############################################################################## -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" -warn ( ) { +warn () { echo "$*" } -die ( ) { +die () { echo echo "$*" echo @@ -30,6 +48,7 @@ die ( ) { cygwin=false msys=false darwin=false +nonstop=false case "`uname`" in CYGWIN* ) cygwin=true @@ -40,31 +59,11 @@ case "`uname`" in MINGW* ) msys=true ;; + NONSTOP* ) + nonstop=true + ;; esac -# For Cygwin, ensure paths are in UNIX format before anything is touched. -if $cygwin ; then - [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` -fi - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >&- -APP_HOME="`pwd -P`" -cd "$SAVED" >&- - CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -90,7 +89,7 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then @@ -114,6 +113,7 @@ fi if $cygwin ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` @@ -154,11 +154,19 @@ if $cygwin ; then esac fi -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " } -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" +exec "$JAVACMD" "$@" diff --git a/espresso/MultiWindowSample/gradlew.bat b/ui/espresso/FragmentScenarioSample/gradlew.bat similarity index 88% rename from espresso/MultiWindowSample/gradlew.bat rename to ui/espresso/FragmentScenarioSample/gradlew.bat index aec99730b..e95643d6a 100644 --- a/espresso/MultiWindowSample/gradlew.bat +++ b/ui/espresso/FragmentScenarioSample/gradlew.bat @@ -8,14 +8,14 @@ @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome @@ -46,10 +46,9 @@ echo location of your Java installation. goto fail :init -@rem Get command-line arguments, handling Windowz variants +@rem Get command-line arguments, handling Windows variants if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args :win9xME_args @rem Slurp the command line arguments. @@ -60,11 +59,6 @@ set _SKIP=2 if "x%~1" == "x" goto execute set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ :execute @rem Setup the command line diff --git a/ui/espresso/FragmentScenarioSample/settings.gradle b/ui/espresso/FragmentScenarioSample/settings.gradle new file mode 100644 index 000000000..e7b4def49 --- /dev/null +++ b/ui/espresso/FragmentScenarioSample/settings.gradle @@ -0,0 +1 @@ +include ':app' diff --git a/ui/espresso/IdlingResourceSample/.gitignore b/ui/espresso/IdlingResourceSample/.gitignore new file mode 100644 index 000000000..1406630a7 --- /dev/null +++ b/ui/espresso/IdlingResourceSample/.gitignore @@ -0,0 +1,6 @@ +.gradle +local.properties +.idea +.DS_Store +build +*.iml diff --git a/ui/espresso/IdlingResourceSample/BUILD.bazel b/ui/espresso/IdlingResourceSample/BUILD.bazel new file mode 100644 index 000000000..d00591676 --- /dev/null +++ b/ui/espresso/IdlingResourceSample/BUILD.bazel @@ -0,0 +1,64 @@ +load("@rules_jvm_external//:defs.bzl", "artifact") +load("//:common_defs.bzl", "minSdkVersion", "targetSdkVersion") + +licenses(["notice"]) # Apache 2.0 + +android_library( + name = "IdlingResourceSampleLib", + srcs = glob(["app/src/main/**/*.java"]), + custom_package = "com.example.android.testing.espresso.IdlingResourceSample", + manifest = "app/src/main/AndroidManifest.xml", + resource_files = glob(["app/src/main/res/**/*"]), + deps = [ + artifact("androidx.annotation:annotation"), + artifact("androidx.test.espresso:espresso-idling-resource"), + artifact("com.google.guava:guava"), + ], +) + +android_binary( + name = "IdlingResourceSample", + custom_package = "com.example.android.testing.espresso.IdlingResourceSample", + manifest = "app/src/main/AppManifest.xml", + manifest_values = { + "minSdkVersion": minSdkVersion, + "targetSdkVersion": targetSdkVersion, + }, + deps = [":IdlingResourceSampleLib"], +) + +android_library( + name = "IdlingResourceSampleTestLib", + srcs = glob(["app/src/androidTest/**/*.java"]), + custom_package = "com.example.android.testing.espresso.IdlingResourceSample.test", + deps = [ + artifact("androidx.test.espresso:espresso_idling_resource"), + ":IdlingResourceSampleLib", + "//:test_deps", + ], +) + +android_binary( + name = "IdlingResourceSampleTest", + custom_package = "com.example.android.testing.espresso.IdlingResourceSample.test", + instruments = ":IdlingResourceSample", + manifest = "app/src/androidTest/AndroidManifest.xml", + manifest_values = { + "minSdkVersion": minSdkVersion, + "targetSdkVersion": targetSdkVersion, + }, + deps = [":IdlingResourceSampleTestLib"], +) + +API_LEVELS = [ + "19_x86", + "21_x86", + "22_x86", + "23_x86", +] + +[android_instrumentation_test( + name = "IdlingResourceSampleInstrumentationTest_%s" % API_LEVEL, + target_device = "@android_test_support//tools/android/emulated_devices/generic_phone:android_%s_qemu2" % API_LEVEL, + test_app = ":IdlingResourceSampleTest", +) for API_LEVEL in API_LEVELS] diff --git a/ui/espresso/IdlingResourceSample/README.md b/ui/espresso/IdlingResourceSample/README.md new file mode 100644 index 000000000..7732d03c5 --- /dev/null +++ b/ui/espresso/IdlingResourceSample/README.md @@ -0,0 +1,34 @@ +# Basic Idling Resource sample for Espresso + +The centerpiece of Espresso is its ability to seamlessly synchronize all test operations with the application under test. By default, Espresso waits for UI events in the current message queue to be processed and default AsyncTasks* to complete before it moves on to the next test operation. This should address the majority of application/test synchronization in your application. + +However, there are instances where applications perform background operations (such as communicating with web services) via non-standard means; for example: direct creation and management of threads. + +This sample showcases how to implement a very simple IdlingResource interface and expose it to a test. The application shows a message to the user after a delay that is executed on a different thread. + +Consider using the CountingIdlingResource class from the espresso-contrib package. It's a very easy to use Idling Resource implementation that can handle multiple parallel operations keeping track of the number of pending operations. + +Note that the `espresso-idling-resource` dependency is added into the `implementation` scope. + +This sample use AndroidX: + +``` + androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' + implementation 'androidx.test.espresso:espresso-idling-resource:3.1.1' +``` + +If you haven't yet migrated to AndroidX: + +``` + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' + implementation 'com.android.support.test.espresso:espresso-idling-resource:3.0.2' +``` + + +This dependency and its implementation are added to the app under test but are not needed in production. This bloats the released app but it's kept this way to simplify the sample. You can: + * ProGuard/shrink your release build to minimize impact + * Use a build type or product flavor for tests and remove the Idling Resource classes in the production/release variant. + * Add the dependency to `androidTestCompile` and inject an IdlingResource-aware MessageDelayer from the test. + * Keep them, since the added methods and size are insignificant. + + diff --git a/ui/espresso/IdlingResourceSample/app/build.gradle b/ui/espresso/IdlingResourceSample/app/build.gradle new file mode 100644 index 000000000..4da492c38 --- /dev/null +++ b/ui/espresso/IdlingResourceSample/app/build.gradle @@ -0,0 +1,67 @@ +/* + * Copyright 2016, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +apply plugin: "com.android.application" + +android { + compileSdk 34 + + defaultConfig { + applicationId "com.example.android.testing.espresso.IdlingResourceSample" + minSdkVersion 21 + targetSdkVersion 34 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + testOptions { + unitTests { + includeAndroidResources = true + } + managedDevices { + devices { + // run with ../gradlew nexusOneApi30DebugAndroidTest + nexusOneApi30(com.android.build.api.dsl.ManagedVirtualDevice) { + // A lower resolution device is used here for better emulator performance + device = "Nexus One" + apiLevel = 30 + // Also use the AOSP ATD image for better emulator performance + systemImageSource = "aosp-atd" + } + } + } + } + namespace "com.example.android.testing.espresso.IdlingResourceSample" + testNamespace "com.example.android.testing.espresso.IdlingResourceSample.test" + lint { + abortOnError false + } +} + +dependencies { + // App dependencies + implementation "androidx.annotation:annotation:" + rootProject.androidxAnnotationVersion + implementation "com.google.guava:guava:" + rootProject.guavaVersion + + // Testing-only dependencies + androidTestImplementation "androidx.test:core:" + rootProject.coreVersion + androidTestImplementation "androidx.test.ext:junit:" + rootProject.extJUnitVersion + androidTestImplementation "androidx.test:runner:" + rootProject.runnerVersion + androidTestImplementation "androidx.test.espresso:espresso-core:" + rootProject.espressoVersion + // Note that espresso-idling-resource is used in the code under test. + implementation "androidx.test.espresso:espresso-idling-resource:" + rootProject.espressoVersion +} diff --git a/ui/espresso/IdlingResourceSample/app/src/androidTest/AndroidManifest.xml b/ui/espresso/IdlingResourceSample/app/src/androidTest/AndroidManifest.xml new file mode 100644 index 000000000..532b5cee8 --- /dev/null +++ b/ui/espresso/IdlingResourceSample/app/src/androidTest/AndroidManifest.xml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/ui/espresso/IdlingResourceSample/app/src/androidTest/java/com/example/android/testing/espresso/IdlingResourceSample/ChangeTextBehaviorTest.java b/ui/espresso/IdlingResourceSample/app/src/androidTest/java/com/example/android/testing/espresso/IdlingResourceSample/ChangeTextBehaviorTest.java new file mode 100644 index 000000000..5487c748f --- /dev/null +++ b/ui/espresso/IdlingResourceSample/app/src/androidTest/java/com/example/android/testing/espresso/IdlingResourceSample/ChangeTextBehaviorTest.java @@ -0,0 +1,86 @@ +/* + * Copyright 2016, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.android.testing.espresso.IdlingResourceSample; + +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.action.ViewActions.click; +import static androidx.test.espresso.action.ViewActions.closeSoftKeyboard; +import static androidx.test.espresso.action.ViewActions.typeText; +import static androidx.test.espresso.assertion.ViewAssertions.matches; +import static androidx.test.espresso.matcher.ViewMatchers.withId; +import static androidx.test.espresso.matcher.ViewMatchers.withText; + +import androidx.test.core.app.ActivityScenario; +import androidx.test.espresso.IdlingRegistry; +import androidx.test.espresso.IdlingResource; +import androidx.test.filters.LargeTest; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + + +/** + * Same as Espresso's BasicSample, but with an Idling Resource to help with synchronization. + */ +@RunWith(AndroidJUnit4.class) +@LargeTest +public class ChangeTextBehaviorTest { + + private static final String STRING_TO_BE_TYPED = "Espresso"; + + private IdlingResource mIdlingResource; + + + /** + * Use {@link ActivityScenario to launch and get access to the activity. + * {@link ActivityScenario#onActivity(ActivityScenario.ActivityAction)} provides a thread-safe + * mechanism to access the activity. + */ + @Before + public void registerIdlingResource() { + ActivityScenario activityScenario = ActivityScenario.launch(MainActivity.class); + activityScenario.onActivity(new ActivityScenario.ActivityAction() { + @Override + public void perform(MainActivity activity) { + mIdlingResource = activity.getIdlingResource(); + // To prove that the test fails, omit this call: + IdlingRegistry.getInstance().register(mIdlingResource); + } + }); + } + + @Test + public void changeText_sameActivity() { + // Type text and then press the button. + onView(withId(R.id.editTextUserInput)) + .perform(typeText(STRING_TO_BE_TYPED), closeSoftKeyboard()); + onView(withId(R.id.changeTextBt)).perform(click()); + + // Check that the text was changed. + onView(withId(R.id.textToBeChanged)).check(matches(withText(STRING_TO_BE_TYPED))); + } + + @After + public void unregisterIdlingResource() { + if (mIdlingResource != null) { + IdlingRegistry.getInstance().unregister(mIdlingResource); + } + } +} \ No newline at end of file diff --git a/ui/espresso/IdlingResourceSample/app/src/main/AndroidManifest.xml b/ui/espresso/IdlingResourceSample/app/src/main/AndroidManifest.xml new file mode 100644 index 000000000..efadc3623 --- /dev/null +++ b/ui/espresso/IdlingResourceSample/app/src/main/AndroidManifest.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + diff --git a/ui/espresso/IdlingResourceSample/app/src/main/AppManifest.xml b/ui/espresso/IdlingResourceSample/app/src/main/AppManifest.xml new file mode 100644 index 000000000..956e6aed9 --- /dev/null +++ b/ui/espresso/IdlingResourceSample/app/src/main/AppManifest.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + diff --git a/ui/espresso/IdlingResourceSample/app/src/main/java/com/example/android/testing/espresso/IdlingResourceSample/IdlingResource/SimpleIdlingResource.java b/ui/espresso/IdlingResourceSample/app/src/main/java/com/example/android/testing/espresso/IdlingResourceSample/IdlingResource/SimpleIdlingResource.java new file mode 100644 index 000000000..9436043fd --- /dev/null +++ b/ui/espresso/IdlingResourceSample/app/src/main/java/com/example/android/testing/espresso/IdlingResourceSample/IdlingResource/SimpleIdlingResource.java @@ -0,0 +1,63 @@ +/* + * Copyright 2016, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.android.testing.espresso.IdlingResourceSample.IdlingResource; + +import androidx.annotation.Nullable; +import androidx.test.espresso.IdlingResource; + +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * A very simple implementation of {@link IdlingResource}. + *

+ * Consider using CountingIdlingResource from espresso-contrib package if you use this class from + * multiple threads or need to keep a count of pending operations. + */ + +public class SimpleIdlingResource implements IdlingResource { + + @Nullable private volatile ResourceCallback mCallback; + + // Idleness is controlled with this boolean. + private AtomicBoolean mIsIdleNow = new AtomicBoolean(true); + + @Override + public String getName() { + return this.getClass().getName(); + } + + @Override + public boolean isIdleNow() { + return mIsIdleNow.get(); + } + + @Override + public void registerIdleTransitionCallback(ResourceCallback callback) { + mCallback = callback; + } + + /** + * Sets the new idle state, if isIdleNow is true, it pings the {@link ResourceCallback}. + * @param isIdleNow false if there are pending operations, true if idle. + */ + public void setIdleState(boolean isIdleNow) { + mIsIdleNow.set(isIdleNow); + if (isIdleNow && mCallback != null) { + mCallback.onTransitionToIdle(); + } + } +} diff --git a/ui/espresso/IdlingResourceSample/app/src/main/java/com/example/android/testing/espresso/IdlingResourceSample/MainActivity.java b/ui/espresso/IdlingResourceSample/app/src/main/java/com/example/android/testing/espresso/IdlingResourceSample/MainActivity.java new file mode 100644 index 000000000..ee03e4c78 --- /dev/null +++ b/ui/espresso/IdlingResourceSample/app/src/main/java/com/example/android/testing/espresso/IdlingResourceSample/MainActivity.java @@ -0,0 +1,88 @@ +/* + * Copyright 2016, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.android.testing.espresso.IdlingResourceSample; + +import android.app.Activity; +import android.os.Bundle; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; +import androidx.test.espresso.IdlingResource; +import android.view.View; +import android.widget.EditText; +import android.widget.TextView; + +import com.example.android.testing.espresso.IdlingResourceSample.IdlingResource.SimpleIdlingResource; + +/** + * Gets a text String from the user and displays it back after a while. + */ +public class MainActivity extends Activity implements View.OnClickListener, + MessageDelayer.DelayerCallback { + + // The TextView used to display the message inside the Activity. + private TextView mTextView; + + // The EditText where the user types the message. + private EditText mEditText; + + // The Idling Resource which will be null in production. + @Nullable private SimpleIdlingResource mIdlingResource; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + // Set the listeners for the buttons. + findViewById(R.id.changeTextBt).setOnClickListener(this); + + mTextView = (TextView) findViewById(R.id.textToBeChanged); + mEditText = (EditText) findViewById(R.id.editTextUserInput); + } + + @Override + public void onClick(View view) { + // Get the text from the EditText view. + final String text = mEditText.getText().toString(); + + if (view.getId() == R.id.changeTextBt) { + // Set a temporary text. + mTextView.setText(R.string.waiting_msg); + // Submit the message to the delayer. + MessageDelayer.processMessage(text, this, mIdlingResource); + } + } + + @Override + public void onDone(String text) { + // The delayer notifies the activity via a callback. + mTextView.setText(text); + } + + /** + * Only called from test, creates and returns a new {@link SimpleIdlingResource}. + */ + @VisibleForTesting + @NonNull + public IdlingResource getIdlingResource() { + if (mIdlingResource == null) { + mIdlingResource = new SimpleIdlingResource(); + } + return mIdlingResource; + } +} diff --git a/ui/espresso/IdlingResourceSample/app/src/main/java/com/example/android/testing/espresso/IdlingResourceSample/MessageDelayer.java b/ui/espresso/IdlingResourceSample/app/src/main/java/com/example/android/testing/espresso/IdlingResourceSample/MessageDelayer.java new file mode 100644 index 000000000..30e2f43a9 --- /dev/null +++ b/ui/espresso/IdlingResourceSample/app/src/main/java/com/example/android/testing/espresso/IdlingResourceSample/MessageDelayer.java @@ -0,0 +1,65 @@ +/* + * Copyright 2016, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.android.testing.espresso.IdlingResourceSample; + +import android.os.Handler; +import androidx.annotation.Nullable; +import androidx.test.espresso.IdlingResource; + +import com.example.android.testing.espresso.IdlingResourceSample.IdlingResource.SimpleIdlingResource; + +/** + * Takes a String and returns it after a while via a callback. + *

+ * This executes a long-running operation on a different thread that results in problems with + * Espresso if an {@link IdlingResource} is not implemented and registered. + */ +class MessageDelayer { + + private static final int DELAY_MILLIS = 3000; + + interface DelayerCallback { + void onDone(String text); + } + + /** + * Takes a String and returns it after {@link #DELAY_MILLIS} via a {@link DelayerCallback}. + * @param message the String that will be returned via the callback + * @param callback used to notify the caller asynchronously + */ + static void processMessage(final String message, final DelayerCallback callback, + @Nullable final SimpleIdlingResource idlingResource) { + // The IdlingResource is null in production. + if (idlingResource != null) { + idlingResource.setIdleState(false); + } + + // Delay the execution, return message via callback. + Handler handler = new Handler(); + handler.postDelayed(new Runnable() { + @Override + public void run() { + if (callback != null) { + callback.onDone(message); + if (idlingResource != null) { + idlingResource.setIdleState(true); + } + } + } + }, DELAY_MILLIS); + } +} diff --git a/uiautomator/BasicSample/app/src/main/res/drawable-hdpi/ic_launcher.png b/ui/espresso/IdlingResourceSample/app/src/main/res/drawable-hdpi/ic_launcher.png similarity index 100% rename from uiautomator/BasicSample/app/src/main/res/drawable-hdpi/ic_launcher.png rename to ui/espresso/IdlingResourceSample/app/src/main/res/drawable-hdpi/ic_launcher.png diff --git a/uiautomator/BasicSample/app/src/main/res/drawable-mdpi/ic_launcher.png b/ui/espresso/IdlingResourceSample/app/src/main/res/drawable-mdpi/ic_launcher.png similarity index 100% rename from uiautomator/BasicSample/app/src/main/res/drawable-mdpi/ic_launcher.png rename to ui/espresso/IdlingResourceSample/app/src/main/res/drawable-mdpi/ic_launcher.png diff --git a/uiautomator/BasicSample/app/src/main/res/drawable-xhdpi/ic_launcher.png b/ui/espresso/IdlingResourceSample/app/src/main/res/drawable-xhdpi/ic_launcher.png similarity index 100% rename from uiautomator/BasicSample/app/src/main/res/drawable-xhdpi/ic_launcher.png rename to ui/espresso/IdlingResourceSample/app/src/main/res/drawable-xhdpi/ic_launcher.png diff --git a/uiautomator/BasicSample/app/src/main/res/drawable-xxhdpi/ic_launcher.png b/ui/espresso/IdlingResourceSample/app/src/main/res/drawable-xxhdpi/ic_launcher.png similarity index 100% rename from uiautomator/BasicSample/app/src/main/res/drawable-xxhdpi/ic_launcher.png rename to ui/espresso/IdlingResourceSample/app/src/main/res/drawable-xxhdpi/ic_launcher.png diff --git a/uiautomator/BasicSample/app/src/main/res/drawable-xxxhdpi/ic_launcher.png b/ui/espresso/IdlingResourceSample/app/src/main/res/drawable-xxxhdpi/ic_launcher.png similarity index 100% rename from uiautomator/BasicSample/app/src/main/res/drawable-xxxhdpi/ic_launcher.png rename to ui/espresso/IdlingResourceSample/app/src/main/res/drawable-xxxhdpi/ic_launcher.png diff --git a/uiautomator/BasicSample/app/src/main/res/layout/activity_main.xml b/ui/espresso/IdlingResourceSample/app/src/main/res/layout/activity_main.xml similarity index 82% rename from uiautomator/BasicSample/app/src/main/res/layout/activity_main.xml rename to ui/espresso/IdlingResourceSample/app/src/main/res/layout/activity_main.xml index 8c1b00559..41f67e320 100644 --- a/uiautomator/BasicSample/app/src/main/res/layout/activity_main.xml +++ b/ui/espresso/IdlingResourceSample/app/src/main/res/layout/activity_main.xml @@ -1,12 +1,12 @@ + + + + diff --git a/ui/espresso/MultiProcessSample/build.gradle b/ui/espresso/MultiProcessSample/build.gradle new file mode 100644 index 000000000..370d04433 --- /dev/null +++ b/ui/espresso/MultiProcessSample/build.gradle @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + ext.agpVersion = "8.5.0" + repositories { + // Insert local test repo here + google() + mavenCentral() + } + dependencies { + classpath "com.android.tools.build:gradle:$agpVersion" + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + // Insert local test repo here + google() + mavenCentral() + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} + +ext { + androidxAnnotationVersion = "1.5.0" + coreVersion = "1.6.1" + extJUnitVersion = "1.2.1" + runnerVersion = "1.6.1" + rulesVersion = "1.6.1" + espressoVersion = "3.6.1" +} diff --git a/ui/espresso/MultiProcessSample/gradle.properties b/ui/espresso/MultiProcessSample/gradle.properties new file mode 100644 index 000000000..4626299b8 --- /dev/null +++ b/ui/espresso/MultiProcessSample/gradle.properties @@ -0,0 +1,37 @@ +# +# Copyright (C) 2017 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. + +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html + +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx1536m + +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true +android.useAndroidX=true +android.defaults.buildfeatures.buildconfig=true +android.nonTransitiveRClass=false +android.nonFinalResIds=false diff --git a/ui/espresso/MultiProcessSample/gradle/wrapper/gradle-wrapper.jar b/ui/espresso/MultiProcessSample/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 000000000..13372aef5 Binary files /dev/null and b/ui/espresso/MultiProcessSample/gradle/wrapper/gradle-wrapper.jar differ diff --git a/ui/espresso/MultiProcessSample/gradle/wrapper/gradle-wrapper.properties b/ui/espresso/MultiProcessSample/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..05697bdc1 --- /dev/null +++ b/ui/espresso/MultiProcessSample/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Mon Jul 16 13:09:42 PDT 2018 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip diff --git a/espresso/IntentsBasicSample/gradlew b/ui/espresso/MultiProcessSample/gradlew similarity index 95% rename from espresso/IntentsBasicSample/gradlew rename to ui/espresso/MultiProcessSample/gradlew index 91a7e269e..9d82f7891 100755 --- a/espresso/IntentsBasicSample/gradlew +++ b/ui/espresso/MultiProcessSample/gradlew @@ -42,11 +42,6 @@ case "`uname`" in ;; esac -# For Cygwin, ensure paths are in UNIX format before anything is touched. -if $cygwin ; then - [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` -fi - # Attempt to set APP_HOME # Resolve links: $0 may be a link PRG="$0" @@ -61,9 +56,9 @@ while [ -h "$PRG" ] ; do fi done SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >&- +cd "`dirname \"$PRG\"`/" >/dev/null APP_HOME="`pwd -P`" -cd "$SAVED" >&- +cd "$SAVED" >/dev/null CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar @@ -114,6 +109,7 @@ fi if $cygwin ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` diff --git a/espresso/BasicSample/gradlew.bat b/ui/espresso/MultiProcessSample/gradlew.bat similarity index 100% rename from espresso/BasicSample/gradlew.bat rename to ui/espresso/MultiProcessSample/gradlew.bat diff --git a/ui/espresso/MultiProcessSample/settings.gradle b/ui/espresso/MultiProcessSample/settings.gradle new file mode 100644 index 000000000..eb53b2405 --- /dev/null +++ b/ui/espresso/MultiProcessSample/settings.gradle @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +include ':app' diff --git a/espresso/MultiWindowSample/.gitignore b/ui/espresso/MultiWindowSample/.gitignore similarity index 100% rename from espresso/MultiWindowSample/.gitignore rename to ui/espresso/MultiWindowSample/.gitignore diff --git a/ui/espresso/MultiWindowSample/BUILD.bazel b/ui/espresso/MultiWindowSample/BUILD.bazel new file mode 100644 index 000000000..74af5e864 --- /dev/null +++ b/ui/espresso/MultiWindowSample/BUILD.bazel @@ -0,0 +1,62 @@ +load("@rules_jvm_external//:defs.bzl", "artifact") +load("//:common_defs.bzl", "minSdkVersion", "targetSdkVersion") + +licenses(["notice"]) # Apache 2.0 + +android_library( + name = "MultiWindowSampleLib", + srcs = glob(["app/src/main/**/*.java"]), + custom_package = "com.example.android.testing.espresso.MultiWindowSample", + manifest = "app/src/main/AndroidManifest.xml", + resource_files = glob(["app/src/main/res/**/*"]), + deps = [ + artifact("androidx.annotation:annotation"), + artifact("com.google.guava:guava"), + ], +) + +android_binary( + name = "MultiWindowSample", + custom_package = "com.example.android.testing.espresso.MultiWindowSample", + manifest = "app/src/main/AppManifest.xml", + manifest_values = { + "minSdkVersion": minSdkVersion, + "targetSdkVersion": targetSdkVersion, + }, + deps = [":MultiWindowSampleLib"], +) + +android_library( + name = "MultiWindowSampleTestLib", + srcs = glob(["app/src/androidTest/**/*.java"]), + custom_package = "com.example.android.testing.espresso.MultiWindowSample.test", + deps = [ + ":MultiWindowSampleLib", + "//:test_deps", + ], +) + +android_binary( + name = "MultiWindowSampleTest", + custom_package = "com.example.android.testing.espresso.MultiWindowSample.test", + instruments = ":MultiWindowSample", + manifest = "app/src/androidTest/AndroidManifest.xml", + manifest_values = { + "minSdkVersion": minSdkVersion, + "targetSdkVersion": targetSdkVersion, + }, + deps = [":MultiWindowSampleTestLib"], +) + +API_LEVELS = [ + "19_x86", + "21_x86", + "22_x86", + "23_x86", +] + +[android_instrumentation_test( + name = "MultiWindowSampleInstrumentationTest_%s" % API_LEVEL, + target_device = "@android_test_support//tools/android/emulated_devices/generic_phone:android_%s_qemu2" % API_LEVEL, + test_app = ":MultiWindowSampleTest", +) for API_LEVEL in API_LEVELS] diff --git a/espresso/MultiWindowSample/README.md b/ui/espresso/MultiWindowSample/README.md similarity index 74% rename from espresso/MultiWindowSample/README.md rename to ui/espresso/MultiWindowSample/README.md index 76587c983..5af23f3a6 100644 --- a/espresso/MultiWindowSample/README.md +++ b/ui/espresso/MultiWindowSample/README.md @@ -9,8 +9,8 @@ transparency is the view hierarchy. By default Espresso uses a heuristic to guess which Window you intend to interact with. This heuristic is normally 'good enough' however if you want to interact with a Window that it does not select then you'll have to swap in your own root window matcher. -Initially we only have 1 window, but by typing into the auto complete text view another -window will be layered on top of the screen. Espresso ignores this layer because it is +Initially there's only one window, but typing into the auto-complete text view creates another +window that will be layered on top of the screen. Espresso ignores this layer because it is not connected to the keyboard/ime. Espresso provides the ability to switch the default window matcher used in both onView and onData @@ -24,13 +24,14 @@ This project uses the Gradle build system. You don't need an IDE to build and ex 1. Check out the relevant code: * The application under test is located in `src/main/java` * Tests are in `src/androidTest/java` -1. Create the test configuration with a custom runner: `android.support.test.runner.AndroidJUnitRunner` +1. Create the test configuration with a custom runner: `androidx.test.runner.AndroidJUnitRunner` * Open *Run* menu | *Edit Configurations* * Add a new *Android Tests* configuration * Choose a module - * Add a *Specific instrumentation runner*: `android.support.test.runner.AndroidJUnitRunner` + * Add a *Specific instrumentation runner*: `androidx.test.runner.AndroidJUnitRunner` 1. Connect a device or start an emulator - * [https://code.google.com/p/android-test-kit/wiki/DisablingAnimations Turn animations off]. + * Turn animations off. + (On your device, under Settings->Developer options disable the following 3 settings: "Window animation scale", "Transition animation scale" and "Animator duration scale") 1. Run the newly created configuration The application will be started on the device/emulator and a series of actions will be performed automatically. diff --git a/ui/espresso/MultiWindowSample/app/build.gradle b/ui/espresso/MultiWindowSample/app/build.gradle new file mode 100644 index 000000000..c3653ba44 --- /dev/null +++ b/ui/espresso/MultiWindowSample/app/build.gradle @@ -0,0 +1,57 @@ + +apply plugin: "com.android.application" + +android { + compileSdk 34 + defaultConfig { + applicationId "com.example.android.testing.espresso.MultiWindowSample" + minSdkVersion 21 + targetSdkVersion 34 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" + } + } + productFlavors { + } + testOptions { + unitTests { + includeAndroidResources = true + } + managedDevices { + devices { + // run with ../gradlew nexusOneApi30DebugAndroidTest + nexusOneApi30(com.android.build.api.dsl.ManagedVirtualDevice) { + // A lower resolution device is used here for better emulator performance + device = "Nexus One" + apiLevel = 30 + // Also use the AOSP ATD image for better emulator performance + systemImageSource = "aosp-atd" + } + } + } + } + namespace "com.example.android.testing.espresso.MultiWindowSample" + testNamespace "com.example.android.testing.espresso.MultiWindowSample.test" + lint { + abortOnError false + } +} + +dependencies { + // App dependencies + implementation "androidx.annotation:annotation:" + rootProject.androidxAnnotationVersion; + implementation "com.google.guava:guava:" + rootProject.guavaVersion + // Testing-only dependencies + androidTestImplementation "androidx.test:core:" + rootProject.coreVersion; + androidTestImplementation "androidx.test.ext:junit:" + rootProject.extJUnitVersion; + androidTestImplementation "androidx.test:runner:" + rootProject.runnerVersion; + androidTestImplementation "androidx.test:rules:" + rootProject.rulesVersion; + androidTestImplementation "androidx.test.espresso:espresso-core:" + rootProject.espressoVersion; +} diff --git a/ui/espresso/MultiWindowSample/app/src/androidTest/AndroidManifest.xml b/ui/espresso/MultiWindowSample/app/src/androidTest/AndroidManifest.xml new file mode 100644 index 000000000..2b7f2d567 --- /dev/null +++ b/ui/espresso/MultiWindowSample/app/src/androidTest/AndroidManifest.xml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/espresso/MultiWindowSample/app/src/androidTest/java/com/example/android/testing/espresso/MultiWindowSample/MultiWindowTest.java b/ui/espresso/MultiWindowSample/app/src/androidTest/java/com/example/android/testing/espresso/MultiWindowSample/MultiWindowTest.java similarity index 81% rename from espresso/MultiWindowSample/app/src/androidTest/java/com/example/android/testing/espresso/MultiWindowSample/MultiWindowTest.java rename to ui/espresso/MultiWindowSample/app/src/androidTest/java/com/example/android/testing/espresso/MultiWindowSample/MultiWindowTest.java index b7a0ef526..82ba28df9 100644 --- a/espresso/MultiWindowSample/app/src/androidTest/java/com/example/android/testing/espresso/MultiWindowSample/MultiWindowTest.java +++ b/ui/espresso/MultiWindowSample/app/src/androidTest/java/com/example/android/testing/espresso/MultiWindowSample/MultiWindowTest.java @@ -15,28 +15,27 @@ */ package com.example.android.testing.espresso.MultiWindowSample; -import android.support.test.rule.ActivityTestRule; -import android.support.test.runner.AndroidJUnit4; -import android.test.ActivityInstrumentationTestCase2; -import android.test.suitebuilder.annotation.LargeTest; +import androidx.test.filters.LargeTest; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.rule.ActivityTestRule; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; -import static android.support.test.espresso.Espresso.onData; -import static android.support.test.espresso.Espresso.onView; -import static android.support.test.espresso.action.ViewActions.click; -import static android.support.test.espresso.action.ViewActions.closeSoftKeyboard; -import static android.support.test.espresso.action.ViewActions.typeText; -import static android.support.test.espresso.action.ViewActions.typeTextIntoFocusedView; -import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist; -import static android.support.test.espresso.assertion.ViewAssertions.matches; -import static android.support.test.espresso.matcher.RootMatchers.withDecorView; -import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; -import static android.support.test.espresso.matcher.ViewMatchers.withId; -import static android.support.test.espresso.matcher.ViewMatchers.withText; +import static androidx.test.espresso.Espresso.onData; +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.action.ViewActions.click; +import static androidx.test.espresso.action.ViewActions.closeSoftKeyboard; +import static androidx.test.espresso.action.ViewActions.typeText; +import static androidx.test.espresso.action.ViewActions.typeTextIntoFocusedView; +import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist; +import static androidx.test.espresso.assertion.ViewAssertions.matches; +import static androidx.test.espresso.matcher.RootMatchers.withDecorView; +import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; +import static androidx.test.espresso.matcher.ViewMatchers.withId; +import static androidx.test.espresso.matcher.ViewMatchers.withText; import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; @@ -62,8 +61,8 @@ * onData * interactions. * - * @see android.support.test.espresso.Espresso#onView - * @see android.support.test.espresso.Espresso#onData + * @see androidx.test.espresso.Espresso#onView + * @see androidx.test.espresso.Espresso#onData */ @RunWith(AndroidJUnit4.class) @LargeTest @@ -71,7 +70,7 @@ public class MultiWindowTest { /** * A JUnit {@link Rule @Rule} to launch your activity under test. This is a replacement - * for {@link ActivityInstrumentationTestCase2}. + * for {@link android.test.ActivityInstrumentationTestCase2}. *

* Rules are interceptors which are executed for each test method and will run before * any of your setup code in the {@link Before @Before} method. @@ -156,7 +155,6 @@ public void autoCompleteTextView_onDataClickAndCheck() { onView(withId(R.id.auto_complete_text_view)) .check(matches(withText("Baltic Sea"))); } - } diff --git a/espresso/MultiWindowSample/app/src/main/AndroidManifest.xml b/ui/espresso/MultiWindowSample/app/src/main/AndroidManifest.xml similarity index 83% rename from espresso/MultiWindowSample/app/src/main/AndroidManifest.xml rename to ui/espresso/MultiWindowSample/app/src/main/AndroidManifest.xml index 61e99df72..55ce6446b 100644 --- a/espresso/MultiWindowSample/app/src/main/AndroidManifest.xml +++ b/ui/espresso/MultiWindowSample/app/src/main/AndroidManifest.xml @@ -1,6 +1,5 @@ - + + android:label="@string/app_name" + android:exported="true" > diff --git a/ui/espresso/MultiWindowSample/app/src/main/AppManifest.xml b/ui/espresso/MultiWindowSample/app/src/main/AppManifest.xml new file mode 100644 index 000000000..a2e63567b --- /dev/null +++ b/ui/espresso/MultiWindowSample/app/src/main/AppManifest.xml @@ -0,0 +1,7 @@ + + + + + + diff --git a/espresso/MultiWindowSample/app/src/main/java/com/example/android/testing/espresso/MultiWindowSample/SuggestActivity.java b/ui/espresso/MultiWindowSample/app/src/main/java/com/example/android/testing/espresso/MultiWindowSample/SuggestActivity.java similarity index 100% rename from espresso/MultiWindowSample/app/src/main/java/com/example/android/testing/espresso/MultiWindowSample/SuggestActivity.java rename to ui/espresso/MultiWindowSample/app/src/main/java/com/example/android/testing/espresso/MultiWindowSample/SuggestActivity.java diff --git a/ui/espresso/MultiWindowSample/app/src/main/res/drawable-hdpi/ic_launcher.png b/ui/espresso/MultiWindowSample/app/src/main/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 000000000..6b0f252c4 Binary files /dev/null and b/ui/espresso/MultiWindowSample/app/src/main/res/drawable-hdpi/ic_launcher.png differ diff --git a/ui/espresso/MultiWindowSample/app/src/main/res/drawable-mdpi/ic_launcher.png b/ui/espresso/MultiWindowSample/app/src/main/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 000000000..b2fe59cc2 Binary files /dev/null and b/ui/espresso/MultiWindowSample/app/src/main/res/drawable-mdpi/ic_launcher.png differ diff --git a/ui/espresso/MultiWindowSample/app/src/main/res/drawable-xhdpi/ic_launcher.png b/ui/espresso/MultiWindowSample/app/src/main/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 000000000..0edc166fe Binary files /dev/null and b/ui/espresso/MultiWindowSample/app/src/main/res/drawable-xhdpi/ic_launcher.png differ diff --git a/ui/espresso/MultiWindowSample/app/src/main/res/drawable-xxhdpi/ic_launcher.png b/ui/espresso/MultiWindowSample/app/src/main/res/drawable-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..252724020 Binary files /dev/null and b/ui/espresso/MultiWindowSample/app/src/main/res/drawable-xxhdpi/ic_launcher.png differ diff --git a/ui/espresso/MultiWindowSample/app/src/main/res/drawable-xxxhdpi/ic_launcher.png b/ui/espresso/MultiWindowSample/app/src/main/res/drawable-xxxhdpi/ic_launcher.png new file mode 100644 index 000000000..0e23e29d8 Binary files /dev/null and b/ui/espresso/MultiWindowSample/app/src/main/res/drawable-xxxhdpi/ic_launcher.png differ diff --git a/espresso/MultiWindowSample/app/src/main/res/layout/suggest_activity.xml b/ui/espresso/MultiWindowSample/app/src/main/res/layout/suggest_activity.xml similarity index 100% rename from espresso/MultiWindowSample/app/src/main/res/layout/suggest_activity.xml rename to ui/espresso/MultiWindowSample/app/src/main/res/layout/suggest_activity.xml diff --git a/espresso/MultiWindowSample/app/src/main/res/values/strings.xml b/ui/espresso/MultiWindowSample/app/src/main/res/values/strings.xml similarity index 100% rename from espresso/MultiWindowSample/app/src/main/res/values/strings.xml rename to ui/espresso/MultiWindowSample/app/src/main/res/values/strings.xml diff --git a/espresso/MultiWindowSample/app/src/main/res/values/styles.xml b/ui/espresso/MultiWindowSample/app/src/main/res/values/styles.xml similarity index 100% rename from espresso/MultiWindowSample/app/src/main/res/values/styles.xml rename to ui/espresso/MultiWindowSample/app/src/main/res/values/styles.xml diff --git a/ui/espresso/MultiWindowSample/build.gradle b/ui/espresso/MultiWindowSample/build.gradle new file mode 100644 index 000000000..89808fc94 --- /dev/null +++ b/ui/espresso/MultiWindowSample/build.gradle @@ -0,0 +1,36 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + ext.agpVersion = "8.5.0" + repositories { + // Insert local test repo here + google() + mavenCentral() + } + dependencies { + classpath "com.android.tools.build:gradle:$agpVersion" + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + // Insert local test repo here + google() + mavenCentral() + } +} + +ext { + buildToolsVersion = "32.0.0" + androidxAnnotationVersion = "1.5.0" + guavaVersion = "31.1-android" + coreVersion = "1.6.1" + extJUnitVersion = "1.2.1" + runnerVersion = "1.6.1" + rulesVersion = "1.6.1" + espressoVersion = "3.6.1" +} + diff --git a/ui/espresso/MultiWindowSample/gradle.properties b/ui/espresso/MultiWindowSample/gradle.properties new file mode 100644 index 000000000..0b1d21b54 --- /dev/null +++ b/ui/espresso/MultiWindowSample/gradle.properties @@ -0,0 +1,22 @@ +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. + +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html + +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +# Default value: -Xmx10248m -XX:MaxPermSize=256m +# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 + +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true +android.defaults.buildfeatures.buildconfig=true +android.nonFinalResIds=false +android.nonTransitiveRClass=false +android.useAndroidX=true \ No newline at end of file diff --git a/ui/espresso/MultiWindowSample/gradle/wrapper/gradle-wrapper.jar b/ui/espresso/MultiWindowSample/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 000000000..41d9927a4 Binary files /dev/null and b/ui/espresso/MultiWindowSample/gradle/wrapper/gradle-wrapper.jar differ diff --git a/ui/espresso/MultiWindowSample/gradle/wrapper/gradle-wrapper.properties b/ui/espresso/MultiWindowSample/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..48c0a02ca --- /dev/null +++ b/ui/espresso/MultiWindowSample/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/ui/espresso/MultiWindowSample/gradlew b/ui/espresso/MultiWindowSample/gradlew new file mode 100755 index 000000000..1b6c78733 --- /dev/null +++ b/ui/espresso/MultiWindowSample/gradlew @@ -0,0 +1,234 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +APP_NAME="Gradle" +APP_BASE_NAME=${0##*/} + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/ui/espresso/MultiWindowSample/gradlew.bat b/ui/espresso/MultiWindowSample/gradlew.bat new file mode 100644 index 000000000..ac1b06f93 --- /dev/null +++ b/ui/espresso/MultiWindowSample/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/ui/espresso/MultiWindowSample/settings.gradle b/ui/espresso/MultiWindowSample/settings.gradle new file mode 100644 index 000000000..e7b4def49 --- /dev/null +++ b/ui/espresso/MultiWindowSample/settings.gradle @@ -0,0 +1 @@ +include ':app' diff --git a/ui/espresso/RecyclerViewSample/.gitignore b/ui/espresso/RecyclerViewSample/.gitignore new file mode 100644 index 000000000..1406630a7 --- /dev/null +++ b/ui/espresso/RecyclerViewSample/.gitignore @@ -0,0 +1,6 @@ +.gradle +local.properties +.idea +.DS_Store +build +*.iml diff --git a/ui/espresso/RecyclerViewSample/BUILD.bazel b/ui/espresso/RecyclerViewSample/BUILD.bazel new file mode 100644 index 000000000..3d0dcea3e --- /dev/null +++ b/ui/espresso/RecyclerViewSample/BUILD.bazel @@ -0,0 +1,60 @@ +load("@rules_jvm_external//:defs.bzl", "artifact") +load("//:common_defs.bzl", "minSdkVersion", "targetSdkVersion") + +licenses(["notice"]) # Apache 2.0 + +android_library( + name = "RecyclerViewSampleLib", + srcs = glob(["app/src/main/**/*.java"]), + custom_package = "com.example.android.testing.espresso.RecyclerViewSample", + manifest = "app/src/main/AndroidManifest.xml", + resource_files = glob(["app/src/main/res/**/*"]), + deps = [ + artifact("androidx.recyclerview:recyclerview"), + artifact("androidx.annotation:annotation"), + artifact("com.google.guava:guava"), + ], +) + +android_binary( + name = "RecyclerViewSample", + custom_package = "com.example.android.testing.espresso.RecyclerViewSample", + manifest = "app/src/main/AppManifest.xml", + deps = [":RecyclerViewSampleLib"], +) + +android_library( + name = "RecyclerViewSampleTestLib", + srcs = glob(["app/src/androidTest/**/*.java"]), + custom_package = "com.example.android.testing.espresso.RecyclerViewSample.test", + deps = [ + artifact("androidx.test.espresso:espresso-contrib"), + ":RecyclerViewSampleLib", + "//:test_deps", + ], +) + +android_binary( + name = "RecyclerViewSampleTest", + custom_package = "com.example.android.testing.espresso.RecyclerViewSample.test", + instruments = ":RecyclerViewSample", + manifest = "app/src/androidTest/AndroidManifest.xml", + manifest_values = { + "minSdkVersion": minSdkVersion, + "targetSdkVersion": targetSdkVersion, + }, + deps = [":RecyclerViewSampleTestLib"], +) + +API_LEVELS = [ + "19_x86", + "21_x86", + "22_x86", + "23_x86", +] + +[android_instrumentation_test( + name = "RecyclerViewSampleInstrumentationTest_%s" % API_LEVEL, + target_device = "@android_test_support//tools/android/emulated_devices/generic_phone:android_%s_qemu2" % API_LEVEL, + test_app = ":RecyclerViewSampleTest", +) for API_LEVEL in API_LEVELS] diff --git a/ui/espresso/RecyclerViewSample/README.md b/ui/espresso/RecyclerViewSample/README.md new file mode 100644 index 000000000..23b523fe7 --- /dev/null +++ b/ui/espresso/RecyclerViewSample/README.md @@ -0,0 +1,7 @@ +# RecyclerView sample for Espresso + +Espresso has a special entry point to interact with AdapterViews, `onData()`, however, RecyclerViews work differently than AdapterViews. + +In order to interact with RecyclerViews using Espresso, the `espresso-contrib` package has a collection of `RecyclerViewActions` that can be used to scroll to positions or perform actions on items. + +In this example you'll find a basic Activity that shows a list and an example of how to scroll through it, perform some ViewActions and check ViewAssertions using Espresso. diff --git a/ui/espresso/RecyclerViewSample/app/build.gradle b/ui/espresso/RecyclerViewSample/app/build.gradle new file mode 100644 index 000000000..498d3fb96 --- /dev/null +++ b/ui/espresso/RecyclerViewSample/app/build.gradle @@ -0,0 +1,74 @@ +/* + * Copyright 2016, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +apply plugin: "com.android.application" + +android { + compileSdk 34 + defaultConfig { + applicationId "com.example.android.testing.espresso.RecyclerViewSample" + minSdkVersion 21 + targetSdkVersion 34 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + + multiDexEnabled true + } + compileOptions { + sourceCompatibility 1.8 + targetCompatibility 1.8 + } + + testOptions { + unitTests { + includeAndroidResources = true + } + managedDevices { + devices { + // run with ../gradlew nexusOneApi30DebugAndroidTest + nexusOneApi30(com.android.build.api.dsl.ManagedVirtualDevice) { + // A lower resolution device is used here for better emulator performance + device = "Nexus One" + apiLevel = 30 + // Also use the AOSP ATD image for better emulator performance + systemImageSource = "aosp-atd" + } + } + } + } + namespace "com.example.android.testing.espresso.RecyclerViewSample" + testNamespace "com.example.android.testing.espresso.RecyclerViewSample.test" + lint { + abortOnError false + } +} + +dependencies { + // App dependencies + implementation "androidx.annotation:annotation:" + rootProject.androidxAnnotationVersion; + implementation "androidx.recyclerview:recyclerview:" + rootProject.androidxRecyclerVersion; + implementation "androidx.multidex:multidex:2.0.1" + + // Testing-only dependencies + androidTestImplementation "androidx.test:core:" + rootProject.coreVersion; + androidTestImplementation "androidx.test.ext:junit:" + rootProject.extJUnitVersion; + androidTestImplementation "androidx.test:runner:" + rootProject.runnerVersion; + androidTestImplementation "androidx.test.espresso:espresso-core:" + rootProject.espressoVersion; + androidTestImplementation "androidx.test.espresso:espresso-contrib:" + rootProject.espressoVersion; + +} diff --git a/ui/espresso/RecyclerViewSample/app/src/androidTest/AndroidManifest.xml b/ui/espresso/RecyclerViewSample/app/src/androidTest/AndroidManifest.xml new file mode 100644 index 000000000..6a97e6f1c --- /dev/null +++ b/ui/espresso/RecyclerViewSample/app/src/androidTest/AndroidManifest.xml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/ui/espresso/RecyclerViewSample/app/src/androidTest/java/com/example/android/testing/espresso/RecyclerViewSample/RecyclerViewSampleTest.java b/ui/espresso/RecyclerViewSample/app/src/androidTest/java/com/example/android/testing/espresso/RecyclerViewSample/RecyclerViewSampleTest.java new file mode 100644 index 000000000..ffefd1b33 --- /dev/null +++ b/ui/espresso/RecyclerViewSample/app/src/androidTest/java/com/example/android/testing/espresso/RecyclerViewSample/RecyclerViewSampleTest.java @@ -0,0 +1,111 @@ +/* + * Copyright 2016, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.android.testing.espresso.RecyclerViewSample; + +import static androidx.test.core.app.ApplicationProvider.getApplicationContext; +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.action.ViewActions.click; +import static androidx.test.espresso.assertion.ViewAssertions.matches; +import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant; +import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; +import static androidx.test.espresso.matcher.ViewMatchers.withText; + +import androidx.test.core.app.ActivityScenario; +import androidx.test.espresso.contrib.RecyclerViewActions; +import androidx.test.espresso.matcher.ViewMatchers; +import androidx.test.espresso.PerformException; +import androidx.test.ext.junit.rules.ActivityScenarioRule; +import androidx.test.filters.LargeTest; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.hamcrest.TypeSafeMatcher; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + + +/** + * Test class showcasing some {@link RecyclerViewActions} from Espresso. + */ +@RunWith(AndroidJUnit4.class) +@LargeTest +public class RecyclerViewSampleTest { + + private static final int ITEM_BELOW_THE_FOLD = 40; + + /** + * Use {@link ActivityScenario} to create and launch the activity under test. This is a + * replacement for {@link androidx.test.rule.ActivityTestRule}. + */ + @Rule + public ActivityScenarioRule activityScenarioRule = + new ActivityScenarioRule(MainActivity.class); + + @Test(expected = PerformException.class) + public void itemWithText_doesNotExist() { + // Attempt to scroll to an item that contains the special text. + onView(ViewMatchers.withId(R.id.recyclerView)) + // scrollTo will fail the test if no item matches. + .perform(RecyclerViewActions.scrollTo( + hasDescendant(withText("not in the list")) + )); + } + + @Test + public void scrollToItemBelowFold_checkItsText() { + // First scroll to the position that needs to be matched and click on it. + onView(ViewMatchers.withId(R.id.recyclerView)) + .perform(RecyclerViewActions.actionOnItemAtPosition(ITEM_BELOW_THE_FOLD, click())); + + // Match the text in an item below the fold and check that it's displayed. + String itemElementText = getApplicationContext().getResources().getString( + R.string.item_element_text) + String.valueOf(ITEM_BELOW_THE_FOLD); + onView(withText(itemElementText)).check(matches(isDisplayed())); + } + + @Test + public void itemInMiddleOfList_hasSpecialText() { + // First, scroll to the view holder using the isInTheMiddle matcher. + onView(ViewMatchers.withId(R.id.recyclerView)) + .perform(RecyclerViewActions.scrollToHolder(isInTheMiddle())); + + // Check that the item has the special text. + String middleElementText = + getApplicationContext().getResources().getString(R.string.middle); + onView(withText(middleElementText)).check(matches(isDisplayed())); + } + + /** + * Matches the {@link CustomAdapter.ViewHolder}s in the middle of the list. + */ + private static Matcher isInTheMiddle() { + return new TypeSafeMatcher() { + @Override + protected boolean matchesSafely(CustomAdapter.ViewHolder customHolder) { + return customHolder.getIsInTheMiddle(); + } + + @Override + public void describeTo(Description description) { + description.appendText("item in the middle"); + } + }; + } +} diff --git a/ui/espresso/RecyclerViewSample/app/src/main/AndroidManifest.xml b/ui/espresso/RecyclerViewSample/app/src/main/AndroidManifest.xml new file mode 100644 index 000000000..510abe51b --- /dev/null +++ b/ui/espresso/RecyclerViewSample/app/src/main/AndroidManifest.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + diff --git a/ui/espresso/RecyclerViewSample/app/src/main/AppManifest.xml b/ui/espresso/RecyclerViewSample/app/src/main/AppManifest.xml new file mode 100644 index 000000000..e7b375245 --- /dev/null +++ b/ui/espresso/RecyclerViewSample/app/src/main/AppManifest.xml @@ -0,0 +1,23 @@ + + + + + + + + diff --git a/ui/espresso/RecyclerViewSample/app/src/main/java/com/example/android/testing/espresso/RecyclerViewSample/CustomAdapter.java b/ui/espresso/RecyclerViewSample/app/src/main/java/com/example/android/testing/espresso/RecyclerViewSample/CustomAdapter.java new file mode 100644 index 000000000..85642e25b --- /dev/null +++ b/ui/espresso/RecyclerViewSample/app/src/main/java/com/example/android/testing/espresso/RecyclerViewSample/CustomAdapter.java @@ -0,0 +1,100 @@ +/* + * Copyright 2016, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.android.testing.espresso.RecyclerViewSample; + +import android.content.Context; +import androidx.recyclerview.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import java.util.List; + +/** + * Provides views to {@link RecyclerView} with data from a data set. + */ +public class CustomAdapter extends RecyclerView.Adapter { + + private final List mDataSet; + + private final Context mContext; + + /** + * Provide a reference to the type of views that you are using + * (custom {@link RecyclerView.ViewHolder}). + */ + static class ViewHolder extends RecyclerView.ViewHolder { + private final TextView textView; + + // We'll use this field to showcase matching the holder from the test. + private boolean mIsInTheMiddle = false; + + ViewHolder(View v) { + super(v); + textView = (TextView) v.findViewById(R.id.textView); + } + + TextView getTextView() { + return textView; + } + + boolean getIsInTheMiddle() { + return mIsInTheMiddle; + } + + void setIsInTheMiddle(boolean isInTheMiddle) { + mIsInTheMiddle = isInTheMiddle; + } + } + + /** + * Initialize the dataset of the Adapter. + * + * @param dataSet String[] containing the data to populate views to be used by RecyclerView. + */ + CustomAdapter(List dataSet, Context context) { + mDataSet = dataSet; + mContext = context; + } + + @Override + public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { + // Create a new view. + View v = LayoutInflater.from(viewGroup.getContext()) + .inflate(R.layout.text_row_item, viewGroup, false); + + return new ViewHolder(v); + } + + @Override + public void onBindViewHolder(ViewHolder viewHolder, final int position) { + if (position == mDataSet.size() / 2 /* calculate middle element position */) { + viewHolder.setIsInTheMiddle(true); + viewHolder.getTextView().setText(mContext.getResources().getString(R.string.middle)); + } else { + viewHolder.setIsInTheMiddle(false); + viewHolder.getTextView().setText(mDataSet.get(position)); + } + } + + // Return the size of your data set (invoked by the layout manager) + @Override + public int getItemCount() { + return mDataSet.size(); + } +} diff --git a/ui/espresso/RecyclerViewSample/app/src/main/java/com/example/android/testing/espresso/RecyclerViewSample/MainActivity.java b/ui/espresso/RecyclerViewSample/app/src/main/java/com/example/android/testing/espresso/RecyclerViewSample/MainActivity.java new file mode 100644 index 000000000..d43c8ee29 --- /dev/null +++ b/ui/espresso/RecyclerViewSample/app/src/main/java/com/example/android/testing/espresso/RecyclerViewSample/MainActivity.java @@ -0,0 +1,52 @@ +/* + * Copyright 2016, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.android.testing.espresso.RecyclerViewSample; + +import android.app.Activity; +import android.os.Bundle; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import java.util.ArrayList; +import java.util.List; + +/** + * Shows a list using a RecyclerView. + */ +public class MainActivity extends Activity { + + private static final int DATASET_COUNT = 50; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + // Create a RecyclerView, a LayoutManager, a data Adapter and wire everything up. + RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView); + + LinearLayoutManager layoutManager = new LinearLayoutManager(getApplicationContext()); + recyclerView.setLayoutManager(layoutManager); + + List dataSet = new ArrayList<>(DATASET_COUNT); + for (int i = 0; i < DATASET_COUNT; i++) { + dataSet.add(getString(R.string.item_element_text) + i); + } + CustomAdapter adapter = new CustomAdapter(dataSet, getApplicationContext()); + recyclerView.setAdapter(adapter); + } +} diff --git a/ui/espresso/RecyclerViewSample/app/src/main/res/drawable-hdpi/ic_launcher.png b/ui/espresso/RecyclerViewSample/app/src/main/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 000000000..6b0f252c4 Binary files /dev/null and b/ui/espresso/RecyclerViewSample/app/src/main/res/drawable-hdpi/ic_launcher.png differ diff --git a/ui/espresso/RecyclerViewSample/app/src/main/res/drawable-mdpi/ic_launcher.png b/ui/espresso/RecyclerViewSample/app/src/main/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 000000000..b2fe59cc2 Binary files /dev/null and b/ui/espresso/RecyclerViewSample/app/src/main/res/drawable-mdpi/ic_launcher.png differ diff --git a/ui/espresso/RecyclerViewSample/app/src/main/res/drawable-xhdpi/ic_launcher.png b/ui/espresso/RecyclerViewSample/app/src/main/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 000000000..0edc166fe Binary files /dev/null and b/ui/espresso/RecyclerViewSample/app/src/main/res/drawable-xhdpi/ic_launcher.png differ diff --git a/ui/espresso/RecyclerViewSample/app/src/main/res/drawable-xxhdpi/ic_launcher.png b/ui/espresso/RecyclerViewSample/app/src/main/res/drawable-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..252724020 Binary files /dev/null and b/ui/espresso/RecyclerViewSample/app/src/main/res/drawable-xxhdpi/ic_launcher.png differ diff --git a/ui/espresso/RecyclerViewSample/app/src/main/res/drawable-xxxhdpi/ic_launcher.png b/ui/espresso/RecyclerViewSample/app/src/main/res/drawable-xxxhdpi/ic_launcher.png new file mode 100644 index 000000000..0e23e29d8 Binary files /dev/null and b/ui/espresso/RecyclerViewSample/app/src/main/res/drawable-xxxhdpi/ic_launcher.png differ diff --git a/ui/espresso/RecyclerViewSample/app/src/main/res/layout/activity_main.xml b/ui/espresso/RecyclerViewSample/app/src/main/res/layout/activity_main.xml new file mode 100644 index 000000000..7420c2544 --- /dev/null +++ b/ui/espresso/RecyclerViewSample/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,30 @@ + + + + + + + diff --git a/ui/espresso/RecyclerViewSample/app/src/main/res/layout/text_row_item.xml b/ui/espresso/RecyclerViewSample/app/src/main/res/layout/text_row_item.xml new file mode 100644 index 000000000..9b94684b8 --- /dev/null +++ b/ui/espresso/RecyclerViewSample/app/src/main/res/layout/text_row_item.xml @@ -0,0 +1,30 @@ + + + + + + + \ No newline at end of file diff --git a/ui/espresso/RecyclerViewSample/app/src/main/res/values-v13/styles.xml b/ui/espresso/RecyclerViewSample/app/src/main/res/values-v13/styles.xml new file mode 100644 index 000000000..d2284893e --- /dev/null +++ b/ui/espresso/RecyclerViewSample/app/src/main/res/values-v13/styles.xml @@ -0,0 +1,19 @@ + + + + + \ No newline at end of file diff --git a/ui/espresso/ScreenshotSample/app/src/main/res/values/colors.xml b/ui/espresso/ScreenshotSample/app/src/main/res/values/colors.xml new file mode 100644 index 000000000..09837df62 --- /dev/null +++ b/ui/espresso/ScreenshotSample/app/src/main/res/values/colors.xml @@ -0,0 +1,10 @@ + + + #FFBB86FC + #FF6200EE + #FF3700B3 + #FF03DAC5 + #FF018786 + #FF000000 + #FFFFFFFF + \ No newline at end of file diff --git a/ui/espresso/ScreenshotSample/app/src/main/res/values/strings.xml b/ui/espresso/ScreenshotSample/app/src/main/res/values/strings.xml new file mode 100644 index 000000000..18ad9a3ec --- /dev/null +++ b/ui/espresso/ScreenshotSample/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + ScreenshotSample + \ No newline at end of file diff --git a/ui/espresso/ScreenshotSample/app/src/main/res/values/themes.xml b/ui/espresso/ScreenshotSample/app/src/main/res/values/themes.xml new file mode 100644 index 000000000..1cb135be5 --- /dev/null +++ b/ui/espresso/ScreenshotSample/app/src/main/res/values/themes.xml @@ -0,0 +1,18 @@ + + + + \ No newline at end of file diff --git a/ui/espresso/ScreenshotSample/build.gradle b/ui/espresso/ScreenshotSample/build.gradle new file mode 100644 index 000000000..d2d1f7450 --- /dev/null +++ b/ui/espresso/ScreenshotSample/build.gradle @@ -0,0 +1,31 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +buildscript { + ext.agpVersion = "8.5.0" + ext.kotlinVersion = "1.9.22" + ext.androidxCoreVersion = "1.9.0" + ext.buildToolsVersion = "32.0.0" + ext.androidxCompatVersion = "1.5.1" + ext.coreVersion = "1.6.1" + ext.extJUnitVersion = "1.2.1" + ext.runnerVersion = "1.6.1" + ext.rulesVersion = "1.6.1" + ext.espressoVersion = "3.6.1" + ext.servicesVersion = "1.5.0" + ext.truthVersion = "1.1.3" + + repositories { + google() + mavenCentral() + } + dependencies { + classpath "com.android.tools.build:gradle:$agpVersion" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion" + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/ui/espresso/ScreenshotSample/gradle.properties b/ui/espresso/ScreenshotSample/gradle.properties new file mode 100644 index 000000000..8145fa7be --- /dev/null +++ b/ui/espresso/ScreenshotSample/gradle.properties @@ -0,0 +1,24 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app"s APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Automatically convert third-party libraries to use AndroidX +android.enableJetifier=true +# Kotlin code style for this project: "official" or "obsolete": +kotlin.code.style=official +android.defaults.buildfeatures.buildconfig=true +android.nonTransitiveRClass=false +android.nonFinalResIds=false \ No newline at end of file diff --git a/ui/espresso/ScreenshotSample/gradle/wrapper/gradle-wrapper.jar b/ui/espresso/ScreenshotSample/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 000000000..e708b1c02 Binary files /dev/null and b/ui/espresso/ScreenshotSample/gradle/wrapper/gradle-wrapper.jar differ diff --git a/ui/espresso/ScreenshotSample/gradle/wrapper/gradle-wrapper.properties b/ui/espresso/ScreenshotSample/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..6cc5d8679 --- /dev/null +++ b/ui/espresso/ScreenshotSample/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Thu Aug 01 20:15:00 UTC 2024 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/espresso/BasicSample/gradlew b/ui/espresso/ScreenshotSample/gradlew similarity index 63% rename from espresso/BasicSample/gradlew rename to ui/espresso/ScreenshotSample/gradlew index 91a7e269e..4f906e0c8 100755 --- a/espresso/BasicSample/gradlew +++ b/ui/espresso/ScreenshotSample/gradlew @@ -1,4 +1,20 @@ -#!/usr/bin/env bash +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ############################################################################## ## @@ -6,20 +22,38 @@ ## ############################################################################## -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" -warn ( ) { +warn () { echo "$*" } -die ( ) { +die () { echo echo "$*" echo @@ -30,6 +64,7 @@ die ( ) { cygwin=false msys=false darwin=false +nonstop=false case "`uname`" in CYGWIN* ) cygwin=true @@ -40,33 +75,14 @@ case "`uname`" in MINGW* ) msys=true ;; + NONSTOP* ) + nonstop=true + ;; esac -# For Cygwin, ensure paths are in UNIX format before anything is touched. -if $cygwin ; then - [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` -fi - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >&- -APP_HOME="`pwd -P`" -cd "$SAVED" >&- - CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then @@ -90,7 +106,7 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then @@ -110,11 +126,13 @@ if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + # We build the pattern for arguments to be converted via cygpath ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` SEP="" @@ -138,27 +156,30 @@ if $cygwin ; then else eval `echo args$i`="\"$arg\"" fi - i=$((i+1)) + i=`expr $i + 1` done case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " } -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" +exec "$JAVACMD" "$@" diff --git a/ui/espresso/ScreenshotSample/gradlew.bat b/ui/espresso/ScreenshotSample/gradlew.bat new file mode 100644 index 000000000..ac1b06f93 --- /dev/null +++ b/ui/espresso/ScreenshotSample/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/ui/espresso/ScreenshotSample/settings.gradle b/ui/espresso/ScreenshotSample/settings.gradle new file mode 100644 index 000000000..3822a81e2 --- /dev/null +++ b/ui/espresso/ScreenshotSample/settings.gradle @@ -0,0 +1,9 @@ +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + } +} +rootProject.name = "ScreenshotSample" +include ':app' diff --git a/ui/espresso/WebBasicSample/.gitignore b/ui/espresso/WebBasicSample/.gitignore new file mode 100644 index 000000000..1406630a7 --- /dev/null +++ b/ui/espresso/WebBasicSample/.gitignore @@ -0,0 +1,6 @@ +.gradle +local.properties +.idea +.DS_Store +build +*.iml diff --git a/espresso/BasicSample/README.md b/ui/espresso/WebBasicSample/README.md similarity index 54% rename from espresso/BasicSample/README.md rename to ui/espresso/WebBasicSample/README.md index a51c33ad7..babb0f1f3 100644 --- a/espresso/BasicSample/README.md +++ b/ui/espresso/WebBasicSample/README.md @@ -1,6 +1,10 @@ -# Basic sample for Espresso +# Basic sample for Espresso Web -*If you are new to Espresso, try this sample first.* +Espresso Web is an API that can be used to write automated tests for hybrid applications which +contain one or more WebViews. Similar to onData, WebView interactions are actually composed of +several ViewActions, however ViewActions in Espresso Web are composed of Web Driver Atoms. +Espresso Web takes care of synchronization and tries to minimize boilerplate to a bare minimum, +while still giving you an Espresso-like feel to interacting with WebViews. This project uses the Gradle build system. You don't need an IDE to build and execute it but Android Studio is recommended. @@ -10,13 +14,14 @@ This project uses the Gradle build system. You don't need an IDE to build and ex 1. Check out the relevant code: * The application under test is located in `src/main/java` * Tests are in `src/androidTest/java` -1. Create the test configuration with a custom runner: `android.support.test.runner.AndroidJUnitRunner` +1. Create the test configuration with a custom runner: `androidx.test.runner.AndroidJUnitRunner` * Open *Run* menu | *Edit Configurations* * Add a new *Android Tests* configuration * Choose a module - * Add a *Specific instrumentation runner*: `android.support.test.runner.AndroidJUnitRunner` + * Add a *Specific instrumentation runner*: `androidx.test.runner.AndroidJUnitRunner` 1. Connect a device or start an emulator - * [Turn animations off](https://code.google.com/p/android-test-kit/wiki/DisablingAnimations). + * Turn animations off. + (On your device, under Settings->Developer options disable the following 3 settings: "Window animation scale", "Transition animation scale" and "Animator duration scale") 1. Run the newly created configuration The application will be started on the device/emulator and a series of actions will be performed automatically. diff --git a/ui/espresso/WebBasicSample/app/build.gradle b/ui/espresso/WebBasicSample/app/build.gradle new file mode 100644 index 000000000..6c79f8355 --- /dev/null +++ b/ui/espresso/WebBasicSample/app/build.gradle @@ -0,0 +1,54 @@ +apply plugin: "com.android.application" + +android { + compileSdk 34 + defaultConfig { + applicationId "com.example.android.testing.espresso.web.BasicSample" + minSdkVersion 21 + targetSdkVersion 34 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + productFlavors { + } + packagingOptions { + resources { + excludes += ["META-INF/maven/com.google.guava/guava/pom.properties", "META-INF/maven/com.google.guava/guava/pom.xml"] + } + } + testOptions { + unitTests { + includeAndroidResources = true + } + managedDevices { + devices { + // run with ../gradlew nexusOneApi30DebugAndroidTest + nexusOneApi30(com.android.build.api.dsl.ManagedVirtualDevice) { + // A lower resolution device is used here for better emulator performance + device = "Nexus One" + apiLevel = 30 + // Also use the AOSP ATD image for better emulator performance + systemImageSource = "aosp-atd" + } + } + } + } + namespace "com.example.android.testing.espresso.web.BasicSample" + lint { + abortOnError false + } +} + +dependencies { + // App dependencies + implementation "androidx.annotation:annotation:"+ rootProject.androidxAnnotationVersion; + implementation "com.google.guava:guava:" + rootProject.guavaVersion + // Testing-only dependencies + androidTestImplementation "androidx.test:core:" + rootProject.coreVersion; + androidTestImplementation "androidx.test.ext:junit:" + rootProject.extJUnitVersion; + androidTestImplementation "androidx.test:runner:" + rootProject.runnerVersion; + androidTestImplementation "androidx.test:rules:" + rootProject.rulesVersion; + androidTestImplementation "androidx.test.espresso:espresso-web:" + rootProject.espressoVersion; +} diff --git a/ui/espresso/WebBasicSample/app/src/androidTest/java/com/example/android/testing/espresso/web/BasicSample/WebViewActivityTest.java b/ui/espresso/WebBasicSample/app/src/androidTest/java/com/example/android/testing/espresso/web/BasicSample/WebViewActivityTest.java new file mode 100644 index 000000000..e194d3631 --- /dev/null +++ b/ui/espresso/WebBasicSample/app/src/androidTest/java/com/example/android/testing/espresso/web/BasicSample/WebViewActivityTest.java @@ -0,0 +1,136 @@ +/* + * Copyright 2015, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.android.testing.espresso.web.BasicSample; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import android.content.Intent; + +import androidx.test.core.app.ActivityScenario; +import androidx.test.espresso.web.sugar.Web; +import androidx.test.espresso.web.webdriver.DriverAtoms; +import androidx.test.espresso.web.webdriver.Locator; +import androidx.test.filters.LargeTest; +import androidx.test.rule.ActivityTestRule; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import android.webkit.WebView; + +import static androidx.test.espresso.web.assertion.WebViewAssertions.webMatches; +import static androidx.test.espresso.web.sugar.Web.onWebView; +import static androidx.test.espresso.web.webdriver.DriverAtoms.clearElement; +import static androidx.test.espresso.web.webdriver.DriverAtoms.findElement; +import static androidx.test.espresso.web.webdriver.DriverAtoms.getText; +import static androidx.test.espresso.web.webdriver.DriverAtoms.webClick; +import static org.hamcrest.Matchers.containsString; + +/** + * Basic sample that shows the usage of Espresso web showcasing {@link Web#onWebView()} API. + *

+ * The sample has a simple layout which contains a single {@link WebView}. The HTML page displays + * a form with an input tag and buttons to submit the form. + */ +@LargeTest +@RunWith(AndroidJUnit4.class) +public class WebViewActivityTest { + + private static final String MACCHIATO = "Macchiato"; + private static final String DOPPIO = "Doppio"; + + /** + * A JUnit {@link Rule @Rule} to launch your activity under test. This is a replacement + * for {@link android.test.ActivityInstrumentationTestCase2}. + *

+ * Rules are interceptors which are executed for each test method and will run before + * any of your setup code in the {@link Before @Before} method. + *

+ * {@link ActivityTestRule} will create and launch of the activity for you and also expose + * the activity under test. To get a reference to the activity you can use + * the {@link ActivityTestRule#getActivity()} method. + */ + @Rule + public ActivityTestRule mActivityRule = new ActivityTestRule( + WebViewActivity.class, false, false) { + @Override + protected void afterActivityLaunched() { + // Technically we do not need to do this - WebViewActivity has javascript turned on. + // Other WebViews in your app may have javascript turned off, however since the only way + // to automate WebViews is through javascript, it must be enabled. + onWebView().forceJavascriptEnabled(); + } + }; + + @Test + public void typeTextInInput_clickButton_SubmitsForm() { + // Lazily launch the Activity with a custom start Intent per test + mActivityRule.launchActivity(withWebFormIntent()); + + // Selects the WebView in your layout. If you have multiple WebViews you can also use a + // matcher to select a given WebView, onWebView(withId(R.id.web_view)). + onWebView() + // Find the input element by ID + .withElement(findElement(Locator.ID, "text_input")) + // Clear previous input + .perform(clearElement()) + // Enter text into the input element + .perform(DriverAtoms.webKeys(MACCHIATO)) + // Find the submit button + .withElement(findElement(Locator.ID, "submitBtn")) + // Simulate a click via javascript + .perform(webClick()) + // Find the response element by ID + .withElement(findElement(Locator.ID, "response")) + // Verify that the response page contains the entered text + .check(webMatches(getText(), containsString(MACCHIATO))); + } + + @Test + public void typeTextInInput_clickButton_ChangesText() { + // Lazily launch the Activity with a custom start Intent per test + mActivityRule.launchActivity(withWebFormIntent()); + + // Selects the WebView in your layout. If you have multiple WebViews you can also use a + // matcher to select a given WebView, onWebView(withId(R.id.web_view)). + onWebView() + // Find the input element by ID + .withElement(findElement(Locator.ID, "text_input")) + // Clear previous input + .perform(clearElement()) + // Enter text into the input element + .perform(DriverAtoms.webKeys(DOPPIO)) + // Find the change text button. + .withElement(findElement(Locator.ID, "changeTextBtn")) + // Click on it. + .perform(webClick()) + // Find the message element by ID + .withElement(findElement(Locator.ID, "message")) + // Verify that the text is displayed + .check(webMatches(getText(), containsString(DOPPIO))); + } + + /** + * @return start {@link Intent} for the simple web form URL. + */ + private static Intent withWebFormIntent() { + Intent basicFormIntent = new Intent(); + basicFormIntent.putExtra(WebViewActivity.KEY_URL_TO_LOAD, WebViewActivity.WEB_FORM_URL); + return basicFormIntent; + } + +} diff --git a/ui/espresso/WebBasicSample/app/src/main/AndroidManifest.xml b/ui/espresso/WebBasicSample/app/src/main/AndroidManifest.xml new file mode 100644 index 000000000..965a7a568 --- /dev/null +++ b/ui/espresso/WebBasicSample/app/src/main/AndroidManifest.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + diff --git a/ui/espresso/WebBasicSample/app/src/main/assets/web_form.html b/ui/espresso/WebBasicSample/app/src/main/assets/web_form.html new file mode 100644 index 000000000..f2aeae26a --- /dev/null +++ b/ui/espresso/WebBasicSample/app/src/main/assets/web_form.html @@ -0,0 +1,77 @@ + + + + + Hello Espresso Web + + + + + + + +

+

Hello Espresso Web!

+ +
+

Need some Espresso

+
+
+
+
+
+ + + + diff --git a/ui/espresso/WebBasicSample/app/src/main/assets/web_form_response.html b/ui/espresso/WebBasicSample/app/src/main/assets/web_form_response.html new file mode 100644 index 000000000..0c50cc7da --- /dev/null +++ b/ui/espresso/WebBasicSample/app/src/main/assets/web_form_response.html @@ -0,0 +1,66 @@ + + + + + The end of the line! + + + + + + + +
+

+ +

+ + + diff --git a/ui/espresso/WebBasicSample/app/src/main/java/com/example/android/testing/espresso/web/BasicSample/WebViewActivity.java b/ui/espresso/WebBasicSample/app/src/main/java/com/example/android/testing/espresso/web/BasicSample/WebViewActivity.java new file mode 100644 index 000000000..d791241cc --- /dev/null +++ b/ui/espresso/WebBasicSample/app/src/main/java/com/example/android/testing/espresso/web/BasicSample/WebViewActivity.java @@ -0,0 +1,66 @@ +/* + * Copyright 2015, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.android.testing.espresso.web.BasicSample; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import androidx.annotation.NonNull; +import androidx.annotation.VisibleForTesting; +import android.text.TextUtils; +import android.webkit.WebView; +import android.webkit.WebViewClient; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * An {@link Activity} that gets a text string from the user and displays it back when the user + * clicks on one of the two buttons. The first one shows it in the same activity and the second + * one opens another activity and displays the message. + */ +public class WebViewActivity extends Activity { + + public static final String KEY_URL_TO_LOAD = "KEY_URL_TO_LOAD"; + + @VisibleForTesting + protected static final String WEB_FORM_URL = "file:///android_asset/web_form.html"; + + private WebView mWebView; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_web_view); + mWebView = (WebView) findViewById(R.id.web_view); + mWebView.getSettings().setJavaScriptEnabled(true); + mWebView.loadUrl(urlFromIntent(getIntent())); + mWebView.requestFocus(); + mWebView.setWebViewClient(new WebViewClient() { + @Override + public boolean shouldOverrideUrlLoading(WebView view, String url) { + return false; + } + }); + } + + private static String urlFromIntent(@NonNull Intent intent) { + checkNotNull(intent, "Intent cannot be null!"); + String url = intent.getStringExtra(KEY_URL_TO_LOAD); + return !TextUtils.isEmpty(url) ? url : WEB_FORM_URL; + } + +} diff --git a/ui/espresso/WebBasicSample/app/src/main/res/drawable-hdpi/ic_launcher.png b/ui/espresso/WebBasicSample/app/src/main/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 000000000..6b0f252c4 Binary files /dev/null and b/ui/espresso/WebBasicSample/app/src/main/res/drawable-hdpi/ic_launcher.png differ diff --git a/ui/espresso/WebBasicSample/app/src/main/res/drawable-mdpi/ic_launcher.png b/ui/espresso/WebBasicSample/app/src/main/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 000000000..b2fe59cc2 Binary files /dev/null and b/ui/espresso/WebBasicSample/app/src/main/res/drawable-mdpi/ic_launcher.png differ diff --git a/ui/espresso/WebBasicSample/app/src/main/res/drawable-xhdpi/ic_launcher.png b/ui/espresso/WebBasicSample/app/src/main/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 000000000..0edc166fe Binary files /dev/null and b/ui/espresso/WebBasicSample/app/src/main/res/drawable-xhdpi/ic_launcher.png differ diff --git a/ui/espresso/WebBasicSample/app/src/main/res/drawable-xxhdpi/ic_launcher.png b/ui/espresso/WebBasicSample/app/src/main/res/drawable-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..252724020 Binary files /dev/null and b/ui/espresso/WebBasicSample/app/src/main/res/drawable-xxhdpi/ic_launcher.png differ diff --git a/ui/espresso/WebBasicSample/app/src/main/res/drawable-xxxhdpi/ic_launcher.png b/ui/espresso/WebBasicSample/app/src/main/res/drawable-xxxhdpi/ic_launcher.png new file mode 100644 index 000000000..0e23e29d8 Binary files /dev/null and b/ui/espresso/WebBasicSample/app/src/main/res/drawable-xxxhdpi/ic_launcher.png differ diff --git a/espresso/BasicSampleBundled/res/layout/activity_show_text.xml b/ui/espresso/WebBasicSample/app/src/main/res/layout/activity_web_view.xml similarity index 57% rename from espresso/BasicSampleBundled/res/layout/activity_show_text.xml rename to ui/espresso/WebBasicSample/app/src/main/res/layout/activity_web_view.xml index 87faee86d..ae3e7ef35 100644 --- a/espresso/BasicSampleBundled/res/layout/activity_show_text.xml +++ b/ui/espresso/WebBasicSample/app/src/main/res/layout/activity_web_view.xml @@ -15,16 +15,18 @@ ~ limitations under the License. --> + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" + android:padding="@dimen/activity_horizontal_margin" + tools:context=".WebViewActaivity"> - + diff --git a/ui/espresso/WebBasicSample/app/src/main/res/values-v13/styles.xml b/ui/espresso/WebBasicSample/app/src/main/res/values-v13/styles.xml new file mode 100644 index 000000000..90618916c --- /dev/null +++ b/ui/espresso/WebBasicSample/app/src/main/res/values-v13/styles.xml @@ -0,0 +1,19 @@ + + + +