From 8c6218a4bf2152a51771fb551e7721fd83db35fc Mon Sep 17 00:00:00 2001 From: Andrey Tolpeev Date: Sun, 25 Mar 2018 12:37:42 +0800 Subject: [PATCH 01/18] Update target and compile sdk to 27, build tools and support libs --- app/build.gradle | 131 +++++++++++------------ build.gradle | 10 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 3 files changed, 71 insertions(+), 72 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index cf372593..f7e1ea78 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,7 +16,6 @@ apply plugin: 'com.android.application' apply plugin: 'io.fabric' -apply plugin: 'com.neenbedankt.android-apt' apply from: 'jacoco.gradle' apply from: 'spoon.gradle' apply from: 'pmd.gradle' @@ -62,6 +61,8 @@ android { } } + flavorDimensions "default" + productFlavors { mock { applicationIdSuffix = ".mock" @@ -121,7 +122,6 @@ buildscript { dependencies { classpath 'com.getkeepsafe.dexcount:dexcount-gradle-plugin:0.1.1' - classpath 'com.neenbedankt.gradle.plugins:android-apt:1.6' classpath 'io.fabric.tools:gradle:1.+' } } @@ -139,94 +139,93 @@ repositories{ } dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) + implementation fileTree(dir: 'libs', include: ['*.jar']) // Android support libraries - compile "com.android.support:appcompat-v7:$rootProject.supportLibraryVersion" - compile "com.android.support:cardview-v7:$rootProject.supportLibraryVersion" - compile "com.android.support:support-v13:$rootProject.supportLibraryVersion" - compile "com.android.support:recyclerview-v7:$rootProject.supportLibraryVersion" - compile "com.android.support:design:$rootProject.supportLibraryVersion" - compile "com.android.support:customtabs:$rootProject.supportLibraryVersion" + implementation "com.android.support:appcompat-v7:$rootProject.supportLibraryVersion" + implementation "com.android.support:cardview-v7:$rootProject.supportLibraryVersion" + implementation "com.android.support:support-v13:$rootProject.supportLibraryVersion" + implementation "com.android.support:recyclerview-v7:$rootProject.supportLibraryVersion" + implementation "com.android.support:design:$rootProject.supportLibraryVersion" + implementation "com.android.support:customtabs:$rootProject.supportLibraryVersion" // Api third party libraries - compile 'com.squareup.okhttp3:okhttp:3.8.1' - compile 'com.squareup.okhttp3:logging-interceptor:3.8.1' - compile 'com.google.code.gson:gson:2.7' - compile 'com.squareup.retrofit2:retrofit:2.3.0' - compile 'com.squareup.retrofit2:converter-gson:2.3.0' - compile 'com.squareup.retrofit2:adapter-rxjava:2.3.0' + implementation 'com.squareup.okhttp3:okhttp:3.8.1' + implementation 'com.squareup.okhttp3:logging-interceptor:3.8.1' + implementation 'com.google.code.gson:gson:2.7' + implementation 'com.squareup.retrofit2:retrofit:2.3.0' + implementation 'com.squareup.retrofit2:converter-gson:2.3.0' + implementation 'com.squareup.retrofit2:adapter-rxjava:2.3.0' // Drawer - compile('com.mikepenz:materialdrawer:5.9.5@aar') { + implementation('com.mikepenz:materialdrawer:5.9.5@aar') { transitive = true } // Icons - compile 'com.joanzapata.iconify:android-iconify-material:2.2.2' - compile 'com.joanzapata.iconify:android-iconify-fontawesome:2.2.2' - compile 'com.joanzapata.iconify:android-iconify-material-community:2.2.2' + implementation 'com.joanzapata.iconify:android-iconify-material:2.2.2' + implementation 'com.joanzapata.iconify:android-iconify-fontawesome:2.2.2' + implementation 'com.joanzapata.iconify:android-iconify-material-community:2.2.2' // Dialogs - compile 'com.afollestad.material-dialogs:core:0.9.4.5' + implementation 'com.afollestad.material-dialogs:core:0.9.4.5' // Views - compile 'tr.xip.errorview:library:3.0.0' - compile 'com.pnikosis:materialish-progress:1.7' + implementation 'tr.xip.errorview:library:3.0.0' + implementation 'com.pnikosis:materialish-progress:1.7' // View injection - compile 'com.jakewharton:butterknife:8.8.0' - apt 'com.jakewharton:butterknife-compiler:8.8.0' + implementation 'com.jakewharton:butterknife:8.8.0' + annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.0' // Event bus - compile 'org.greenrobot:eventbus:3.0.0' + implementation 'org.greenrobot:eventbus:3.0.0' // Others - compile 'joda-time:joda-time:2.8.1' - compile 'com.bignerdranch.android:recyclerview-multiselect:0.2' - compile 'com.vinaysshenoy:mugen:1.0.2' - compile('com.mikepenz:aboutlibraries:5.9.7@aar') { + implementation 'joda-time:joda-time:2.8.1' + implementation 'com.bignerdranch.android:recyclerview-multiselect:0.2' + implementation 'com.vinaysshenoy:mugen:1.0.2' + implementation('com.mikepenz:aboutlibraries:5.9.7@aar') { transitive = true } - compile 'com.github.daniel-stoneuk:material-about-library:2.2.1' + implementation 'com.github.daniel-stoneuk:material-about-library:2.2.1' // Onboarding - compile 'uk.co.samuelwall:material-tap-target-prompt:2.0.0' + implementation 'uk.co.samuelwall:material-tap-target-prompt:2.0.0' // Dagger - apt 'com.google.dagger:dagger-compiler:2.11' - compile 'com.google.dagger:dagger:2.11' - provided 'javax.annotation:jsr250-api:1.0' + annotationProcessor 'com.google.dagger:dagger-compiler:2.11' + implementation 'com.google.dagger:dagger:2.11' // Rx - compile 'io.reactivex:rxandroid:1.2.1' - compile 'io.reactivex:rxjava:1.3.0' + implementation 'io.reactivex:rxandroid:1.2.1' + implementation 'io.reactivex:rxjava:1.3.0' // Rx cache - compile "com.github.VictorAlbertos.RxCache:runtime:1.7.0-1.x" - compile 'com.github.VictorAlbertos.Jolyglot:gson:0.0.3' + implementation "com.github.VictorAlbertos.RxCache:runtime:1.7.0-1.x" + implementation 'com.github.VictorAlbertos.Jolyglot:gson:0.0.3' // Encryption - compile 'com.facebook.conceal:conceal:1.1.3@aar' + implementation 'com.facebook.conceal:conceal:1.1.3@aar' // Rate app library - compile 'com.github.hotchemi:android-rate:1.0.1' + implementation 'com.github.hotchemi:android-rate:1.0.1' // Firebase - compile 'com.google.firebase:firebase-core:11.0.4' + implementation 'com.google.firebase:firebase-core:11.0.4' // Unit tests - testCompile "org.mockito:mockito-core:$rootProject.mockitoCoreVersion" - testCompile 'junit:junit:4.12' - testCompile 'org.hamcrest:hamcrest-junit:2.0.0.0' - testCompile "org.powermock:powermock-module-junit4:$rootProject.powerMockVersion" - testCompile "org.powermock:powermock-module-junit4-rule:$rootProject.powerMockVersion" - testCompile "org.powermock:powermock-api-mockito:$rootProject.powerMockVersion" - testCompile "org.powermock:powermock-classloading-xstream:$rootProject.powerMockVersion" + testImplementation "org.mockito:mockito-core:$rootProject.mockitoCoreVersion" + testImplementation 'junit:junit:4.12' + testImplementation 'org.hamcrest:hamcrest-junit:2.0.0.0' + testImplementation "org.powermock:powermock-module-junit4:$rootProject.powerMockVersion" + testImplementation "org.powermock:powermock-module-junit4-rule:$rootProject.powerMockVersion" + testImplementation "org.powermock:powermock-api-mockito:$rootProject.powerMockVersion" + testImplementation "org.powermock:powermock-classloading-xstream:$rootProject.powerMockVersion" // Ui tests - androidTestCompile "com.android.support.test:runner:$rootProject.espressoRunnerVersion" - androidTestCompile "com.android.support.test:rules:$rootProject.espressoRunnerVersion" - androidTestCompile "com.android.support.test.espresso:espresso-core:$rootProject.espressoVersion" - androidTestCompile "com.android.support.test.espresso:espresso-intents:$rootProject.espressoVersion" - androidTestCompile "com.android.support.test.espresso:espresso-contrib:$rootProject.espressoVersion" - androidTestCompile "com.android.support.test.espresso:espresso-web:$rootProject.espressoVersion" - androidTestCompile "org.mockito:mockito-core:$rootProject.mockitoCoreVersion" - androidTestCompile "com.crittercism.dexmaker:dexmaker:$rootProject.dexMakerVersion" - androidTestCompile "com.crittercism.dexmaker:dexmaker-dx:$rootProject.dexMakerVersion" - androidTestCompile "com.crittercism.dexmaker:dexmaker-mockito:$rootProject.dexMakerVersion" - androidTestCompile 'com.squareup.spoon:spoon-client:1.7.1' - androidTestCompile 'com.jraska:falcon-spoon-compat:1.0.4' - androidTestCompile 'com.github.fabioCollini:DaggerMock:0.7.0' + androidTestImplementation "com.android.support.test:runner:$rootProject.espressoRunnerVersion" + androidTestImplementation "com.android.support.test:rules:$rootProject.espressoRunnerVersion" + androidTestImplementation "com.android.support.test.espresso:espresso-core:$rootProject.espressoVersion" + androidTestImplementation "com.android.support.test.espresso:espresso-intents:$rootProject.espressoVersion" + androidTestImplementation "com.android.support.test.espresso:espresso-contrib:$rootProject.espressoVersion" + androidTestImplementation "com.android.support.test.espresso:espresso-web:$rootProject.espressoVersion" + androidTestImplementation "org.mockito:mockito-core:$rootProject.mockitoCoreVersion" + androidTestImplementation "com.crittercism.dexmaker:dexmaker:$rootProject.dexMakerVersion" + androidTestImplementation "com.crittercism.dexmaker:dexmaker-dx:$rootProject.dexMakerVersion" + androidTestImplementation "com.crittercism.dexmaker:dexmaker-mockito:$rootProject.dexMakerVersion" + androidTestImplementation 'com.squareup.spoon:spoon-client:1.7.1' + androidTestImplementation 'com.jraska:falcon-spoon-compat:1.0.4' + androidTestImplementation 'com.github.fabioCollini:DaggerMock:0.7.0' // Resolve conflits between apks - androidTestCompile "com.android.support:support-annotations:$rootProject.supportLibraryVersion" - androidTestCompile "com.android.support:design:$rootProject.supportLibraryVersion" - androidTestCompile "com.android.support:recyclerview-v7:$rootProject.supportLibraryVersion" + androidTestImplementation "com.android.support:support-annotations:$rootProject.supportLibraryVersion" + androidTestImplementation "com.android.support:design:$rootProject.supportLibraryVersion" + androidTestImplementation "com.android.support:recyclerview-v7:$rootProject.supportLibraryVersion" // Crashlytics - compile('com.crashlytics.sdk.android:crashlytics:2.6.8@aar') { - transitive = true; + implementation('com.crashlytics.sdk.android:crashlytics:2.6.8@aar') { + transitive = true } } diff --git a/build.gradle b/build.gradle index 3d3973cd..a8acae71 100644 --- a/build.gradle +++ b/build.gradle @@ -25,7 +25,7 @@ buildscript { } } dependencies { - classpath 'com.android.tools.build:gradle:2.3.3' + classpath 'com.android.tools.build:gradle:3.0.1' classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' classpath 'com.stanfy.spoon:spoon-gradle-plugin:1.2.1' classpath 'com.google.gms:google-services:3.0.0' @@ -51,12 +51,12 @@ ext { // sdk and tools minSdkVersion = 15 - targetSdkVersion = 26 - compileSdkVersion = 26 - buildToolsVersion = '26.0.1' + targetSdkVersion = 27 + compileSdkVersion = 27 + buildToolsVersion = '27.0.3' // dependencies versions - supportLibraryVersion = '26.0.0' + supportLibraryVersion = '27.1.0' espressoRunnerVersion = '1.0' espressoVersion = '3.0.0' dexMakerVersion = '1.4' diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 11ed0deb..58bf6886 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -17,4 +17,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip From 4601f7f7363c5bb87123eb6fecafaa1c690fb81e Mon Sep 17 00:00:00 2001 From: Andrey Tolpeev Date: Sun, 25 Mar 2018 12:47:37 +0800 Subject: [PATCH 02/18] Update build gradle classpath deps --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index a8acae71..cecf9b14 100644 --- a/build.gradle +++ b/build.gradle @@ -27,8 +27,8 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:3.0.1' classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' - classpath 'com.stanfy.spoon:spoon-gradle-plugin:1.2.1' - classpath 'com.google.gms:google-services:3.0.0' + classpath 'com.stanfy.spoon:spoon-gradle-plugin:1.2.2' + classpath 'com.google.gms:google-services:3.1.0' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files From dbd28e6f1797eff4bbd941e0f60d8edfb4944adc Mon Sep 17 00:00:00 2001 From: Andrey Tolpeev Date: Sun, 25 Mar 2018 12:51:08 +0800 Subject: [PATCH 03/18] Add google repository --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index cecf9b14..65a3a055 100644 --- a/build.gradle +++ b/build.gradle @@ -18,6 +18,7 @@ buildscript { repositories { + google() jcenter() mavenCentral() maven { From 8004e169bfdc8e9b60f41f781979bfb85e953b9b Mon Sep 17 00:00:00 2001 From: Andrey Tolpeev Date: Sun, 25 Mar 2018 12:54:51 +0800 Subject: [PATCH 04/18] Update circle ci config due api 27 update --- circle.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/circle.yml b/circle.yml index 95a5787b..305133c9 100644 --- a/circle.yml +++ b/circle.yml @@ -4,7 +4,7 @@ references: ~/TeamCityApp container_config: &container_config docker: - - image: circleci/android:api-26-alpha + - image: circleci/android:api-27-alpha working_directory: *workspace_root attach_workspace: &attach_workspace attach_workspace: @@ -21,7 +21,7 @@ jobs: - run: name: Download sdk command: | - echo y | sdkmanager "tools" "platform-tools" "build-tools;26.0.1" "extras;android;m2repository" "platforms;android-26" "emulator" --verbose + echo y | sdkmanager "tools" "platform-tools" "build-tools;27.0.3" "extras;android;m2repository" "platforms;android-27" "emulator" --verbose sdkmanager --update --verbose - run: name: Download dependencies From 250fd027557c400124c8e83520a2526d8fdc2613 Mon Sep 17 00:00:00 2001 From: Andrey Tolpeev Date: Sun, 25 Mar 2018 13:08:35 +0800 Subject: [PATCH 05/18] Remove lint check --- app/build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index f7e1ea78..b2de6834 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -103,7 +103,6 @@ android { lintOptions { disable 'InvalidPackage' - disable 'IconLauncherFormat' xmlReport false abortOnError true htmlOutput file("build/reports/lint-report/lint-report.html") From ade160cb0013db20c6c22b815609c979e62cb6bf Mon Sep 17 00:00:00 2001 From: Andrey Tolpeev Date: Sun, 25 Mar 2018 14:53:05 +0800 Subject: [PATCH 06/18] Fix circle ci apk paths --- circle.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/circle.yml b/circle.yml index 305133c9..e9987498 100644 --- a/circle.yml +++ b/circle.yml @@ -114,8 +114,8 @@ jobs: command: | ./google-cloud-sdk/bin/gcloud firebase test android models list (./google-cloud-sdk/bin/gcloud firebase test android run --type instrumentation \ - --app app/build/outputs/apk/app-mock-debug.apk \ - --test app/build/outputs/apk/app-mock-debug-androidTest.apk \ + --app app/build/outputs/apk/mock/debug/app-mock-debug.apk \ + --test app/build/outputs/apk/androidTest/mock/debug/app-mock-debug-androidTest.apk \ --device model=Nexus5X,version=23,locale=en,orientation=portrait \ --timeout 15m \ --results-bucket $PROJECT_ID \ From 14831a0230bf3b4cecebfbac98228cc9061d7641 Mon Sep 17 00:00:00 2001 From: Andrey Tolpeev Date: Sun, 25 Mar 2018 16:08:28 +0800 Subject: [PATCH 07/18] Try to execute UI tests on phys device --- circle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/circle.yml b/circle.yml index e9987498..df1fcaf7 100644 --- a/circle.yml +++ b/circle.yml @@ -116,7 +116,7 @@ jobs: (./google-cloud-sdk/bin/gcloud firebase test android run --type instrumentation \ --app app/build/outputs/apk/mock/debug/app-mock-debug.apk \ --test app/build/outputs/apk/androidTest/mock/debug/app-mock-debug-androidTest.apk \ - --device model=Nexus5X,version=23,locale=en,orientation=portrait \ + --device model=hammerhead,version=23,locale=en,orientation=portrait \ --timeout 15m \ --results-bucket $PROJECT_ID \ --environment-variables coverage=true,coverageFile="/sdcard/coverage.ec" \ From 6a9d16f7a578266c549ed797eb023d9dd156da3c Mon Sep 17 00:00:00 2001 From: Andrey Tolpeev Date: Sun, 25 Mar 2018 17:43:35 +0800 Subject: [PATCH 08/18] Change test lab device to Pixel, add showing stacktrace to coverage generation --- circle.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/circle.yml b/circle.yml index df1fcaf7..ff624c23 100644 --- a/circle.yml +++ b/circle.yml @@ -116,7 +116,7 @@ jobs: (./google-cloud-sdk/bin/gcloud firebase test android run --type instrumentation \ --app app/build/outputs/apk/mock/debug/app-mock-debug.apk \ --test app/build/outputs/apk/androidTest/mock/debug/app-mock-debug-androidTest.apk \ - --device model=hammerhead,version=23,locale=en,orientation=portrait \ + --device model=sailfish,version=25,locale=en,orientation=portrait \ --timeout 15m \ --results-bucket $PROJECT_ID \ --environment-variables coverage=true,coverageFile="/sdcard/coverage.ec" \ @@ -156,7 +156,7 @@ jobs: - run: name: Generate code coverage command: | - ./gradlew generateCodeCoverageReport + ./gradlew generateCodeCoverageReport --stacktrace mkdir -p app/build/circleci/artifacts/coverage/ find . -type f -regex ".*/build/coverage/generateCodeCoverageReport/generateCodeCoverageReport.xml" -exec cp {} app/build/circleci/artifacts/coverage/ \; - run: From 7a750abf821df2ccab31cda35f6ee44aedf1ad45 Mon Sep 17 00:00:00 2001 From: Andrey Tolpeev Date: Sun, 25 Mar 2018 19:54:38 +0800 Subject: [PATCH 09/18] Make artifact tests more stable --- app/build.gradle | 1 + .../view/ArtifactListFragmentTest.java | 62 +++++++++++++++++-- 2 files changed, 59 insertions(+), 4 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index b2de6834..479b9a66 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -218,6 +218,7 @@ dependencies { androidTestImplementation 'com.squareup.spoon:spoon-client:1.7.1' androidTestImplementation 'com.jraska:falcon-spoon-compat:1.0.4' androidTestImplementation 'com.github.fabioCollini:DaggerMock:0.7.0' + androidTestImplementation 'com.azimolabs.conditionwatcher:conditionwatcher:0.2' // Resolve conflits between apks androidTestImplementation "com.android.support:support-annotations:$rootProject.supportLibraryVersion" androidTestImplementation "com.android.support:design:$rootProject.supportLibraryVersion" diff --git a/app/src/androidTest/java/com/github/vase4kin/teamcityapp/artifact/view/ArtifactListFragmentTest.java b/app/src/androidTest/java/com/github/vase4kin/teamcityapp/artifact/view/ArtifactListFragmentTest.java index 4b9ac076..e9765fc1 100644 --- a/app/src/androidTest/java/com/github/vase4kin/teamcityapp/artifact/view/ArtifactListFragmentTest.java +++ b/app/src/androidTest/java/com/github/vase4kin/teamcityapp/artifact/view/ArtifactListFragmentTest.java @@ -23,6 +23,8 @@ import android.support.test.rule.GrantPermissionRule; import android.support.test.runner.AndroidJUnit4; +import com.azimolabs.conditionwatcher.ConditionWatcher; +import com.azimolabs.conditionwatcher.Instruction; import com.github.vase4kin.teamcityapp.R; import com.github.vase4kin.teamcityapp.TeamCityApplication; import com.github.vase4kin.teamcityapp.api.TeamCityService; @@ -80,6 +82,7 @@ public class ArtifactListFragmentTest { private static final String BUILD_TYPE_NAME = "name"; + private static final int TIMEOUT = 5000; @Rule public DaggerMockRule mAppComponentDaggerRule = new DaggerMockRule<>(AppComponent.class, new AppModule((TeamCityApplication) InstrumentationRegistry.getInstrumentation().getTargetContext().getApplicationContext())) @@ -124,6 +127,7 @@ public void setUp() { TeamCityApplication app = (TeamCityApplication) InstrumentationRegistry.getInstrumentation().getTargetContext().getApplicationContext(); app.getRestApiInjector().sharedUserStorage().clearAll(); app.getRestApiInjector().sharedUserStorage().saveGuestUserAccountAndSetItAsActive(Mocks.URL); + ConditionWatcher.setTimeoutLimit(TIMEOUT); } @Test @@ -154,9 +158,9 @@ public void testUserCanSeeArtifacts() { onView(withId(R.id.artifact_recycler_view)).check(hasItemsCount(3)); onView(withRecyclerView(R.id.artifact_recycler_view).atPositionOnView(0, R.id.itemTitle)).check(matches(withText("res"))); onView(withRecyclerView(R.id.artifact_recycler_view).atPositionOnView(1, R.id.itemTitle)).check(matches(withText("AndroidManifest.xml"))); - onView(withRecyclerView(R.id.artifact_recycler_view).atPositionOnView(1, R.id.itemSubTitle)).check(matches(withText("7.59 KB"))); + onView(withRecyclerView(R.id.artifact_recycler_view).atPositionOnView(1, R.id.itemSubTitle)).check(matches(withText("7.77 kB"))); onView(withRecyclerView(R.id.artifact_recycler_view).atPositionOnView(2, R.id.itemTitle)).check(matches(withText("index.html"))); - onView(withRecyclerView(R.id.artifact_recycler_view).atPositionOnView(2, R.id.itemSubTitle)).check(matches(withText("681 KB"))); + onView(withRecyclerView(R.id.artifact_recycler_view).atPositionOnView(2, R.id.itemSubTitle)).check(matches(withText("698 kB"))); } @Test @@ -253,9 +257,32 @@ public void testUserCanOpenArtifactWithChildren() throws Exception { // Checking first level artifacts onView(withId(R.id.artifact_recycler_view)).check(hasItemsCount(1)); onView(withRecyclerView(R.id.artifact_recycler_view).atPositionOnView(0, R.id.itemTitle)) - .check(matches(withText("res"))) + .check(matches(withText("res"))); + + // Clicking first level artifacts + onView(withRecyclerView(R.id.artifact_recycler_view).atPositionOnView(0, R.id.itemTitle)) .perform(click()); + ConditionWatcher.waitForCondition(new Instruction() { + @Override + public String getDescription() { + return "The artifact page is not loaded"; + } + + @Override + public boolean checkCondition() { + boolean isResFolderClicked = false; + try { + onView(withText("res_level_deeper1")).check(matches(isDisplayed())); + isResFolderClicked = true; + } catch (Exception ignored) { + onView(withRecyclerView(R.id.artifact_recycler_view).atPosition(0)) + .perform(click()); + } + return isResFolderClicked; + } + }); + // In case of the same recycler view ids onView(withText("res_level_deeper1")).check(matches(isDisplayed())); onView(withText("res_level_deeper2")).check(matches(isDisplayed())); @@ -369,12 +396,39 @@ public void testUserSeeSnackBarWithErrorMessageIfArtifactWasNotDownloaded() thro .check(matches(isDisplayed())) .perform(click()); - // Clicking on artifact to download + // Checking artifact title onView(withRecyclerView(R.id.artifact_recycler_view) .atPositionOnView(1, R.id.itemTitle)) .check(matches(withText("AndroidManifest.xml"))) .perform(click()); + // Clicking on artifact to download + onView(withRecyclerView(R.id.artifact_recycler_view) + .atPositionOnView(1, R.id.itemTitle)) + .perform(click()); + + ConditionWatcher.waitForCondition(new Instruction() { + @Override + public String getDescription() { + return "The artifact menu is not opened"; + } + + @Override + public boolean checkCondition() { + boolean isMenuOpened = false; + try { + onView(withText(R.string.artifact_download)) + .check(matches(isDisplayed())); + isMenuOpened = true; + } catch (Exception ignored) { + onView(withRecyclerView(R.id.artifact_recycler_view) + .atPositionOnView(1, R.id.itemTitle)) + .perform(click()); + } + return isMenuOpened; + } + }); + // Click on download option onView(withText(R.string.artifact_download)) .perform(click()); From c174cd5ba0d05292fdedc9faee462204a2d4b051 Mon Sep 17 00:00:00 2001 From: Andrey Tolpeev Date: Sun, 25 Mar 2018 21:13:58 +0800 Subject: [PATCH 10/18] Disable screenshots for testing purposes --- .../vase4kin/teamcityapp/helper/FalconScreenshotAction.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/app/src/androidTest/java/com/github/vase4kin/teamcityapp/helper/FalconScreenshotAction.java b/app/src/androidTest/java/com/github/vase4kin/teamcityapp/helper/FalconScreenshotAction.java index b17c29bd..799ff5f5 100644 --- a/app/src/androidTest/java/com/github/vase4kin/teamcityapp/helper/FalconScreenshotAction.java +++ b/app/src/androidTest/java/com/github/vase4kin/teamcityapp/helper/FalconScreenshotAction.java @@ -28,9 +28,6 @@ import org.hamcrest.Matcher; import org.hamcrest.Matchers; -import static android.support.test.espresso.Espresso.onView; -import static android.support.test.espresso.matcher.ViewMatchers.isRoot; - /** * Source: https://github.com/square/spoon/issues/214#issuecomment-81979248 */ @@ -75,6 +72,6 @@ private static Activity getActivity(View view) { } public static void perform(String tag, String className, String methodName) { - onView(isRoot()).perform(new FalconScreenshotAction(tag, className, methodName)); +// onView(isRoot()).perform(new FalconScreenshotAction(tag, className, methodName)); } } From d691fa50b79dcb201fef3c3cab2458f4807e20ea Mon Sep 17 00:00:00 2001 From: Andrey Tolpeev Date: Sun, 25 Mar 2018 21:31:08 +0800 Subject: [PATCH 11/18] Fix artifact tests --- .../teamcityapp/artifact/view/ArtifactListFragmentTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/androidTest/java/com/github/vase4kin/teamcityapp/artifact/view/ArtifactListFragmentTest.java b/app/src/androidTest/java/com/github/vase4kin/teamcityapp/artifact/view/ArtifactListFragmentTest.java index e9765fc1..5818a57a 100644 --- a/app/src/androidTest/java/com/github/vase4kin/teamcityapp/artifact/view/ArtifactListFragmentTest.java +++ b/app/src/androidTest/java/com/github/vase4kin/teamcityapp/artifact/view/ArtifactListFragmentTest.java @@ -158,9 +158,9 @@ public void testUserCanSeeArtifacts() { onView(withId(R.id.artifact_recycler_view)).check(hasItemsCount(3)); onView(withRecyclerView(R.id.artifact_recycler_view).atPositionOnView(0, R.id.itemTitle)).check(matches(withText("res"))); onView(withRecyclerView(R.id.artifact_recycler_view).atPositionOnView(1, R.id.itemTitle)).check(matches(withText("AndroidManifest.xml"))); - onView(withRecyclerView(R.id.artifact_recycler_view).atPositionOnView(1, R.id.itemSubTitle)).check(matches(withText("7.77 kB"))); + onView(withRecyclerView(R.id.artifact_recycler_view).atPositionOnView(1, R.id.itemSubTitle)).check(matches(withText("7.59 KB"))); onView(withRecyclerView(R.id.artifact_recycler_view).atPositionOnView(2, R.id.itemTitle)).check(matches(withText("index.html"))); - onView(withRecyclerView(R.id.artifact_recycler_view).atPositionOnView(2, R.id.itemSubTitle)).check(matches(withText("698 kB"))); + onView(withRecyclerView(R.id.artifact_recycler_view).atPositionOnView(2, R.id.itemSubTitle)).check(matches(withText("681 KB"))); } @Test From c094771e6d2ce8d7dbe205ec181098145e44a6ec Mon Sep 17 00:00:00 2001 From: Andrey Tolpeev Date: Sun, 25 Mar 2018 21:54:53 +0800 Subject: [PATCH 12/18] Make properties tests more stable --- .../view/PropertiesFragmentTest.java | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/app/src/androidTest/java/com/github/vase4kin/teamcityapp/properties/view/PropertiesFragmentTest.java b/app/src/androidTest/java/com/github/vase4kin/teamcityapp/properties/view/PropertiesFragmentTest.java index db70c70e..915806a3 100644 --- a/app/src/androidTest/java/com/github/vase4kin/teamcityapp/properties/view/PropertiesFragmentTest.java +++ b/app/src/androidTest/java/com/github/vase4kin/teamcityapp/properties/view/PropertiesFragmentTest.java @@ -21,6 +21,8 @@ import android.support.test.InstrumentationRegistry; import android.support.test.runner.AndroidJUnit4; +import com.azimolabs.conditionwatcher.ConditionWatcher; +import com.azimolabs.conditionwatcher.Instruction; import com.github.vase4kin.teamcityapp.R; import com.github.vase4kin.teamcityapp.TeamCityApplication; import com.github.vase4kin.teamcityapp.api.TeamCityService; @@ -67,6 +69,7 @@ public class PropertiesFragmentTest { private static final String NAME = "name"; + private static final int TIMEOUT = 5000; @Rule public DaggerMockRule mAppComponentDaggerRule = new DaggerMockRule<>(AppComponent.class, new AppModule((TeamCityApplication) InstrumentationRegistry.getInstrumentation().getTargetContext().getApplicationContext())) @@ -193,6 +196,7 @@ public void testUserCanSeeEmptyPropertiesMessageIfPropertiesAreEmpty() { @Test public void testUserCanCopyPropertyValueFromTheList() throws Exception { + ConditionWatcher.setTimeoutLimit(TIMEOUT); // Prepare mocks when(mTeamCityService.build(anyString())).thenReturn(Observable.just(mBuild)); @@ -216,7 +220,28 @@ public void testUserCanCopyPropertyValueFromTheList() throws Exception { .perform(click()); // Click on parameter - onView(withRecyclerView(R.id.properties_recycler_view).atPosition(0)).perform(click()); + onView(withRecyclerView(R.id.properties_recycler_view).atPosition(0)) + .perform(click()); + + ConditionWatcher.waitForCondition(new Instruction() { + @Override + public String getDescription() { + return "The parameters menu is not opened"; + } + + @Override + public boolean checkCondition() { + boolean isParameterClicked = false; + try { + onView(withText(R.string.build_element_copy)).check(matches(isDisplayed())); + isParameterClicked = true; + } catch (Exception ignored) { + onView(withRecyclerView(R.id.properties_recycler_view).atPosition(0)) + .perform(click()); + } + return isParameterClicked; + } + }); // Clicking on copy onView(withText(R.string.build_element_copy)).perform(click()); From c859e53bba08df4c9a16b7aca9a402b0f679a65a Mon Sep 17 00:00:00 2001 From: Andrey Tolpeev Date: Sun, 25 Mar 2018 22:15:27 +0800 Subject: [PATCH 13/18] Update jacoco version --- app/jacoco.gradle | 2 +- build.gradle | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/jacoco.gradle b/app/jacoco.gradle index 0df614ee..add2abf8 100644 --- a/app/jacoco.gradle +++ b/app/jacoco.gradle @@ -17,7 +17,7 @@ apply plugin: 'jacoco' jacoco { - toolVersion = "0.7.7.201606060606" + toolVersion = "0.8.1" reportsDir = file("$buildDir/coverage") } diff --git a/build.gradle b/build.gradle index 65a3a055..dc883d4c 100644 --- a/build.gradle +++ b/build.gradle @@ -30,6 +30,7 @@ buildscript { classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' classpath 'com.stanfy.spoon:spoon-gradle-plugin:1.2.2' classpath 'com.google.gms:google-services:3.1.0' + classpath 'org.jacoco:org.jacoco.core:0.8.1' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files From be4d2bbeece1e304a8c6f21012497f39b1c962e9 Mon Sep 17 00:00:00 2001 From: Andrey Tolpeev Date: Mon, 26 Mar 2018 21:49:38 +0800 Subject: [PATCH 14/18] Update versions --- README.md | 2 +- build.gradle | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d0f8041b..52c8c07b 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ [![License](https://img.shields.io/badge/license-Apache_2.0-blue.svg)](http://www.apache.org/licenses/LICENSE-2.0) [![Circle CI](https://circleci.com/gh/vase4kin/TeamCityApp/tree/master.svg?style=shield)](https://circleci.com/gh/vase4kin/TeamCityApp/tree/master) [![codecov](https://codecov.io/gh/vase4kin/TeamCityApp/branch/master/graph/badge.svg)](https://codecov.io/gh/vase4kin/TeamCityApp) -[![Release](https://img.shields.io/badge/release-1.2.6-blue.svg)](https://github.com/vase4kin/TeamCityApp/releases/latest) +[![Release](https://img.shields.io/badge/release-1.2.7-blue.svg)](https://github.com/vase4kin/TeamCityApp/releases/latest) ``` diff --git a/build.gradle b/build.gradle index dc883d4c..9564dc14 100644 --- a/build.gradle +++ b/build.gradle @@ -48,8 +48,8 @@ allprojects { ext { // versions - versionCode = 36 - versionName = "1.2.6" + versionCode = 37 + versionName = "1.2.7" // sdk and tools minSdkVersion = 15 From 195f495d3b59e3226428ecf033769b6d3d0744c7 Mon Sep 17 00:00:00 2001 From: Andrey Tolpeev Date: Mon, 26 Mar 2018 23:13:35 +0800 Subject: [PATCH 15/18] Update min sdk version to 19 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 9564dc14..affd514e 100644 --- a/build.gradle +++ b/build.gradle @@ -52,7 +52,7 @@ ext { versionName = "1.2.7" // sdk and tools - minSdkVersion = 15 + minSdkVersion = 19 targetSdkVersion = 27 compileSdkVersion = 27 buildToolsVersion = '27.0.3' From 12b6f0bebd0d96fba347a8832979409ae06c5599 Mon Sep 17 00:00:00 2001 From: Andrey Tolpeev Date: Tue, 27 Mar 2018 09:19:00 +0800 Subject: [PATCH 16/18] Add shimmer effect on skeleton views --- app/build.gradle | 1 + .../base/list/view/BaseListViewImpl.java | 3 ++ .../res/layout/layout_skeleton_agent_list.xml | 32 ++++++++++++------- .../res/layout/layout_skeleton_build_list.xml | 31 +++++++++++------- .../layout/layout_skeleton_changes_list.xml | 31 +++++++++++------- .../layout_skeleton_navigation_list.xml | 31 +++++++++++------- .../layout/layout_skeleton_overview_list.xml | 31 +++++++++++------- app/src/main/res/values/dimens.xml | 1 + 8 files changed, 105 insertions(+), 56 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 479b9a66..e5ed3269 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -178,6 +178,7 @@ dependencies { implementation('com.mikepenz:aboutlibraries:5.9.7@aar') { transitive = true } + implementation 'io.supercharge:shimmerlayout:2.1.0' implementation 'com.github.daniel-stoneuk:material-about-library:2.2.1' // Onboarding implementation 'uk.co.samuelwall:material-tap-target-prompt:2.0.0' diff --git a/app/src/main/java/com/github/vase4kin/teamcityapp/base/list/view/BaseListViewImpl.java b/app/src/main/java/com/github/vase4kin/teamcityapp/base/list/view/BaseListViewImpl.java index a0879059..e3b70acf 100644 --- a/app/src/main/java/com/github/vase4kin/teamcityapp/base/list/view/BaseListViewImpl.java +++ b/app/src/main/java/com/github/vase4kin/teamcityapp/base/list/view/BaseListViewImpl.java @@ -34,6 +34,7 @@ import butterknife.BindView; import butterknife.ButterKnife; import butterknife.Unbinder; +import io.supercharge.shimmerlayout.ShimmerLayout; import tr.xip.errorview.ErrorView; /** @@ -179,6 +180,7 @@ public void disableRecyclerView() { @Override public void showSkeletonView() { skeletonView.setVisibility(View.VISIBLE); + ((ShimmerLayout) skeletonView.getChildAt(0)).startShimmerAnimation(); } /** @@ -187,6 +189,7 @@ public void showSkeletonView() { @Override public void hideSkeletonView() { skeletonView.setVisibility(View.GONE); + ((ShimmerLayout) skeletonView.getChildAt(0)).stopShimmerAnimation(); } /** diff --git a/app/src/main/res/layout/layout_skeleton_agent_list.xml b/app/src/main/res/layout/layout_skeleton_agent_list.xml index 682214f9..fe3cd30f 100644 --- a/app/src/main/res/layout/layout_skeleton_agent_list.xml +++ b/app/src/main/res/layout/layout_skeleton_agent_list.xml @@ -13,26 +13,34 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> - - + app:shimmer_animation_duration="@integer/shimmer_length" + app:shimmer_color="@color/md_white_1000"> + + + + - + - + - + - + - + - + - + - + - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/layout_skeleton_build_list.xml b/app/src/main/res/layout/layout_skeleton_build_list.xml index de37bcb3..ff2e8d89 100644 --- a/app/src/main/res/layout/layout_skeleton_build_list.xml +++ b/app/src/main/res/layout/layout_skeleton_build_list.xml @@ -14,25 +14,34 @@ ~ limitations under the License. --> - + app:shimmer_animation_duration="@integer/shimmer_length" + app:shimmer_color="@color/md_white_1000"> - + - + - + - + - + - + - + - + - \ No newline at end of file + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/layout_skeleton_changes_list.xml b/app/src/main/res/layout/layout_skeleton_changes_list.xml index f73f8b56..866544ed 100644 --- a/app/src/main/res/layout/layout_skeleton_changes_list.xml +++ b/app/src/main/res/layout/layout_skeleton_changes_list.xml @@ -14,25 +14,34 @@ ~ limitations under the License. --> - + app:shimmer_animation_duration="@integer/shimmer_length" + app:shimmer_color="@color/md_white_1000"> - + - + - + - + - + - + - + - + - \ No newline at end of file + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/layout_skeleton_navigation_list.xml b/app/src/main/res/layout/layout_skeleton_navigation_list.xml index 89481acc..fba05858 100644 --- a/app/src/main/res/layout/layout_skeleton_navigation_list.xml +++ b/app/src/main/res/layout/layout_skeleton_navigation_list.xml @@ -14,25 +14,34 @@ ~ limitations under the License. --> - + app:shimmer_animation_duration="@integer/shimmer_length" + app:shimmer_color="@color/md_white_1000"> - + - + - + - + - + - + - + - + - \ No newline at end of file + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/layout_skeleton_overview_list.xml b/app/src/main/res/layout/layout_skeleton_overview_list.xml index 764fbc6b..01960cf8 100644 --- a/app/src/main/res/layout/layout_skeleton_overview_list.xml +++ b/app/src/main/res/layout/layout_skeleton_overview_list.xml @@ -14,25 +14,34 @@ ~ limitations under the License. --> - + app:shimmer_animation_duration="@integer/shimmer_length" + app:shimmer_color="@color/md_white_1000"> - + - + - + - + - + - + - + - + - \ No newline at end of file + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 3381bf55..34c2ba4c 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -26,4 +26,5 @@ -400 170dp 12dp + 1000 From 9562148a3c02d95c76edb972d3d0563f9695f712 Mon Sep 17 00:00:00 2001 From: Andrey Tolpeev Date: Tue, 27 Mar 2018 09:42:19 +0800 Subject: [PATCH 17/18] Pretty up skeleton views by making image skeletons oval --- .../drawable/skeleton_image_background.xml | 22 +++++++++++++++++++ .../drawable/skeleton_image_background2.xml | 22 +++++++++++++++++++ .../res/layout/layout_skeleton_agent_item.xml | 2 +- .../res/layout/layout_skeleton_agent_list.xml | 2 +- .../res/layout/layout_skeleton_build_list.xml | 2 +- .../layout_skeleton_build_list_item.xml | 2 +- .../layout_skeleton_change_list_item.xml | 2 +- .../layout/layout_skeleton_changes_list.xml | 2 +- .../layout_skeleton_navigation_list.xml | 2 +- .../layout/layout_skeleton_overview_item.xml | 2 +- .../layout/layout_skeleton_overview_list.xml | 2 +- .../layout/layout_skeleton_project_item.xml | 2 +- 12 files changed, 54 insertions(+), 10 deletions(-) create mode 100644 app/src/main/res/drawable/skeleton_image_background.xml create mode 100644 app/src/main/res/drawable/skeleton_image_background2.xml diff --git a/app/src/main/res/drawable/skeleton_image_background.xml b/app/src/main/res/drawable/skeleton_image_background.xml new file mode 100644 index 00000000..f28f1c06 --- /dev/null +++ b/app/src/main/res/drawable/skeleton_image_background.xml @@ -0,0 +1,22 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/skeleton_image_background2.xml b/app/src/main/res/drawable/skeleton_image_background2.xml new file mode 100644 index 00000000..1f4b74b7 --- /dev/null +++ b/app/src/main/res/drawable/skeleton_image_background2.xml @@ -0,0 +1,22 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/layout_skeleton_agent_item.xml b/app/src/main/res/layout/layout_skeleton_agent_item.xml index 5719b741..5acf8dc4 100644 --- a/app/src/main/res/layout/layout_skeleton_agent_item.xml +++ b/app/src/main/res/layout/layout_skeleton_agent_item.xml @@ -23,7 +23,7 @@ android:layout_width="44dp" android:layout_height="44dp" android:layout_marginRight="@dimen/default_margin" - android:background="@color/divider_color" /> + android:background="@drawable/skeleton_image_background" /> + app:shimmer_color="@color/base_item_color"> + app:shimmer_color="@color/base_item_color"> + android:background="@drawable/skeleton_image_background" /> + android:background="@drawable/skeleton_image_background" /> + app:shimmer_color="@color/base_item_color"> + app:shimmer_color="@color/base_item_color"> + android:background="@drawable/skeleton_image_background2" /> + app:shimmer_color="@color/base_item_color"> + android:background="@drawable/skeleton_image_background" /> Date: Tue, 27 Mar 2018 10:00:06 +0800 Subject: [PATCH 18/18] Enable shimmer effect for overview layout --- .../vase4kin/teamcityapp/overview/view/OverviewViewImpl.java | 3 +++ app/src/main/res/layout/layout_skeleton_overview_list.xml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/github/vase4kin/teamcityapp/overview/view/OverviewViewImpl.java b/app/src/main/java/com/github/vase4kin/teamcityapp/overview/view/OverviewViewImpl.java index d313d304..4614ad02 100644 --- a/app/src/main/java/com/github/vase4kin/teamcityapp/overview/view/OverviewViewImpl.java +++ b/app/src/main/java/com/github/vase4kin/teamcityapp/overview/view/OverviewViewImpl.java @@ -49,6 +49,7 @@ import butterknife.BindView; import butterknife.ButterKnife; import butterknife.Unbinder; +import io.supercharge.shimmerlayout.ShimmerLayout; import tr.xip.errorview.ErrorView; import uk.co.samuelwall.materialtaptargetprompt.MaterialTapTargetPrompt; @@ -137,6 +138,7 @@ public void hideCards() { @Override public void showSkeletonView() { skeletonView.setVisibility(View.VISIBLE); + ((ShimmerLayout) skeletonView.getChildAt(0)).startShimmerAnimation(); } /** @@ -145,6 +147,7 @@ public void showSkeletonView() { @Override public void hideSkeletonView() { skeletonView.setVisibility(View.GONE); + ((ShimmerLayout) skeletonView.getChildAt(0)).startShimmerAnimation(); } /** diff --git a/app/src/main/res/layout/layout_skeleton_overview_list.xml b/app/src/main/res/layout/layout_skeleton_overview_list.xml index ec6a0255..9a7ff678 100644 --- a/app/src/main/res/layout/layout_skeleton_overview_list.xml +++ b/app/src/main/res/layout/layout_skeleton_overview_list.xml @@ -19,7 +19,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" app:shimmer_animation_duration="@integer/shimmer_length" - app:shimmer_color="@color/base_item_color"> + app:shimmer_color="@color/divider_color">