diff --git a/.drone.yml b/.drone.yml index 211e098d1..4f33e4cd6 100644 --- a/.drone.yml +++ b/.drone.yml @@ -47,28 +47,24 @@ steps: - scripts/wait_for_emulator.sh - ./gradlew --console=plain testGplayDebugUnitTest connectedGplayDebugAndroidTest -#services: -# - name: server -# image: nextcloudci/server:server-17 # also change in updateScreenshots.sh -# environment: -# EVAL: true -# commands: -# - BRANCH='stable22' /usr/local/bin/initnc.sh -# - echo 127.0.0.1 server >> /etc/hosts -# - su www-data -c "OC_PASS=user1 php /var/www/html/occ user:add --password-from-env --display-name='User One' user1" -# - su www-data -c "OC_PASS=user2 php /var/www/html/occ user:add --password-from-env --display-name='User Two' user2" -# - su www-data -c "OC_PASS=user3 php /var/www/html/occ user:add --password-from-env --display-name='User Three' user3" -# - su www-data -c "php /var/www/html/occ user:setting user2 files quota 1G" -# - su www-data -c "php /var/www/html/occ group:add users" -# - su www-data -c "php /var/www/html/occ group:adduser users user1" -# - su www-data -c "php /var/www/html/occ group:adduser users user2" -# - su www-data -c "git clone -b stable22 https://github.com/nextcloud/activity.git /var/www/html/apps/activity/" -# - su www-data -c "php /var/www/html/occ app:enable activity" -# - su www-data -c "git clone -b stable22 https://github.com/nextcloud/text.git /var/www/html/apps/text/" -# - su www-data -c "php /var/www/html/occ app:enable text" -# - su www-data -c "git clone -b stable22 https://github.com/nextcloud/end_to_end_encryption.git /var/www/html/apps/end_to_end_encryption/" -# - su www-data -c "php /var/www/html/occ app:enable end_to_end_encryption" -# - /usr/local/bin/run.sh +services: + - name: server + image: nextcloudci/server:server-17 + environment: + EVAL: "true" + commands: + - BRANCH='stable23' /usr/local/bin/initnc.sh + - echo 127.0.0.1 server >> /etc/hosts + - su www-data -c "OC_PASS=user1 php /var/www/html/occ user:add --password-from-env --display-name='User One' user1" + - su www-data -c "OC_PASS=user2 php /var/www/html/occ user:add --password-from-env --display-name='User Two' user2" + - su www-data -c "OC_PASS=user3 php /var/www/html/occ user:add --password-from-env --display-name='User Three' user3" + - su www-data -c "php /var/www/html/occ user:setting user2 files quota 1G" + - su www-data -c "php /var/www/html/occ group:add users" + - su www-data -c "php /var/www/html/occ group:adduser users user1" + - su www-data -c "php /var/www/html/occ group:adduser users user2" + - su www-data -c "git clone -b stable23 https://github.com/nextcloud/spreed.git /var/www/html/apps/spreed/" + - su www-data -c "php /var/www/html/occ app:enable spreed" + - /usr/local/bin/run.sh trigger: branch: diff --git a/app/build.gradle b/app/build.gradle index 632d0d027..10b55c802 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -87,6 +87,10 @@ android { ] } } + + testInstrumentationRunnerArgument "TEST_SERVER_URL", "${NC_TEST_SERVER_BASEURL}" + testInstrumentationRunnerArgument "TEST_SERVER_USERNAME", "${NC_TEST_SERVER_USERNAME}" + testInstrumentationRunnerArgument "TEST_SERVER_PASSWORD", "${NC_TEST_SERVER_PASSWORD}" } dexOptions { @@ -111,7 +115,7 @@ android { android.applicationVariants.all { variant -> String variantName = variant.name - String capVariantName = variantName.substring(0, 1).toUpperCase() + variantName.substring(1) + String capVariantName = variantName.substring(0, 1).toUpperCase(Locale.ROOT) + variantName.substring(1) tasks.register("spotbugs${capVariantName}Report", SpotBugsTask) { ignoreFailures = true // should continue checking effort = "max" @@ -297,16 +301,19 @@ dependencies { testImplementation "org.powermock:powermock-module-junit4:${powermockVersion}" testImplementation "org.powermock:powermock-api-mockito2:${powermockVersion}" + + androidTestImplementation "androidx.test:core:1.4.0" + + // Espresso core - androidTestImplementation "androidx.test.espresso:espresso-core:$espressoVersion" + androidTestImplementation ("androidx.test.espresso:espresso-core:$espressoVersion", { + exclude group: 'com.android.support', module: 'support-annotations' + }) androidTestImplementation "androidx.test.espresso:espresso-contrib:$espressoVersion" androidTestImplementation "androidx.test.espresso:espresso-web:$espressoVersion" androidTestImplementation "androidx.test.espresso:espresso-accessibility:$espressoVersion" androidTestImplementation('com.android.support.test.espresso:espresso-intents:3.0.2') - androidTestImplementation ('androidx.test.espresso:espresso-core:3.4.0', { - exclude group: 'com.android.support', module: 'support-annotations' - }) spotbugsPlugins 'com.h3xstream.findsecbugs:findsecbugs-plugin:1.11.0' spotbugsPlugins 'com.mebigfatguy.fb-contrib:fb-contrib:7.4.7' diff --git a/app/src/androidTest/java/com/nextcloud/talk/activities/MainActivityTest.kt b/app/src/androidTest/java/com/nextcloud/talk/activities/MainActivityTest.kt index 247d369ea..3b785c6ce 100644 --- a/app/src/androidTest/java/com/nextcloud/talk/activities/MainActivityTest.kt +++ b/app/src/androidTest/java/com/nextcloud/talk/activities/MainActivityTest.kt @@ -5,7 +5,7 @@ import androidx.test.espresso.intent.rule.IntentsTestRule import com.nextcloud.talk.models.database.UserEntity import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.schedulers.Schedulers -import junit.framework.Assert.assertTrue +import org.junit.Assert.assertTrue import org.junit.Rule import org.junit.Test @@ -23,7 +23,7 @@ class MainActivityTest { sut.userUtils.createOrUpdateUser( "test", "test", - "http://10.0.2.2/nc", + "http://server/nc", "test", null, true, @@ -49,7 +49,7 @@ class MainActivityTest { sut.runOnUiThread { sut.resetConversationsList() } - assertTrue(sut.userUtils.getIfUserWithUsernameAndServer("test", "http://10.0.2.2/nc")) + assertTrue(sut.userUtils.getIfUserWithUsernameAndServer("test", "http://server/nc")) try { } catch (e: InterruptedException) { diff --git a/app/src/androidTest/java/com/nextcloud/talk/ui/LoginIT.java b/app/src/androidTest/java/com/nextcloud/talk/ui/LoginIT.java new file mode 100644 index 000000000..e807f3775 --- /dev/null +++ b/app/src/androidTest/java/com/nextcloud/talk/ui/LoginIT.java @@ -0,0 +1,152 @@ +/* + * Nextcloud Talk application + * + * @author Tobias Kaminsky + * @author Tim Krüger + * Copyright (C) 2021 Tim Krüger + * Copyright (C) 2020 Tobias Kaminsky + * Copyright (C) 2020 Nextcloud GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +package com.nextcloud.talk.ui; + +import android.os.Bundle; + +import com.nextcloud.talk.R; +import com.nextcloud.talk.activities.MainActivity; + +import junit.framework.AssertionFailedError; + +import org.junit.Test; + +import java.util.Objects; + +import androidx.test.core.app.ActivityScenario; +import androidx.test.espresso.NoMatchingViewException; +import androidx.test.espresso.web.webdriver.DriverAtoms; +import androidx.test.espresso.web.webdriver.Locator; +import androidx.test.filters.LargeTest; + +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.action.ViewActions.click; +import static androidx.test.espresso.action.ViewActions.typeText; +import static androidx.test.espresso.assertion.ViewAssertions.matches; +import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; +import static androidx.test.espresso.matcher.ViewMatchers.withContentDescription; +import static androidx.test.espresso.matcher.ViewMatchers.withId; +import static androidx.test.espresso.matcher.ViewMatchers.withText; +import static androidx.test.espresso.web.sugar.Web.onWebView; +import static androidx.test.espresso.web.webdriver.DriverAtoms.findElement; +import static androidx.test.espresso.web.webdriver.DriverAtoms.webClick; +import static org.hamcrest.Matchers.not; +import static org.junit.Assert.assertEquals; + + +@LargeTest +public class LoginIT { + + @Test + public void login() throws InterruptedException { + + ActivityScenario activityScenario = ActivityScenario.launch(MainActivity.class); + + Bundle arguments = androidx.test.platform.app.InstrumentationRegistry.getArguments(); + + String baseUrl = arguments.getString("TEST_SERVER_URL"); + String loginName = arguments.getString("TEST_SERVER_USERNAME"); + String password = arguments.getString("TEST_SERVER_PASSWORD"); + + Thread.sleep(2000); + + try { + onView(withId(R.id.serverEntryTextInputEditText)).check(matches(isDisplayed())); + } catch (NoMatchingViewException e) { + try { + // can happen that an invalid account from previous tests is existing + onView(withText(R.string.nc_settings_remove_account)).perform(click()); + Thread.sleep(2000); + } catch (NoMatchingViewException ie) { + // is OK if the dialog is not shown + } + + try { + // Delete account if exists + onView(withId(R.id.switch_account_button)).perform(click()); + onView(withId(R.id.manage_settings)).perform(click()); + onView(withId(R.id.settings_remove_account)).perform(click()); + onView(withText(R.string.nc_settings_remove)).perform(click()); + // The remove button must be clicked two times + onView(withId(R.id.settings_remove_account)).perform(click()); + // And yes: The button must be clicked two times + onView(withText(R.string.nc_settings_remove)).perform(click()); + onView(withText(R.string.nc_settings_remove)).perform(click()); + } catch (Exception ie2) { + // ignore + } finally { + Thread.sleep(2000); + } + + } + + onView(withId(R.id.serverEntryTextInputEditText)).perform(typeText(baseUrl)); + // Click on EditText's drawable right + onView(withContentDescription(R.string.nc_server_connect)).perform(click()); + + Thread.sleep(4000); + + onWebView().forceJavascriptEnabled(); + + // click on login + onWebView() + .withElement(findElement(Locator.XPATH, "//p[@id='redirect-link']/a")) + .perform(webClick()); + + // username + onWebView() + .withElement(findElement(Locator.XPATH, "//input[@id='user']")) + .perform(DriverAtoms.webKeys(loginName)); + + // password + onWebView() + .withElement(findElement(Locator.XPATH, "//input[@id='password']")) + .perform(DriverAtoms.webKeys(password)); + + // click login + onWebView() + .withElement(findElement(Locator.XPATH, "//input[@id='submit-form']")) + .perform(webClick()); + + Thread.sleep(2000); + + // grant access + onWebView() + .withElement(findElement(Locator.XPATH, "//input[@type='submit']")) + .perform(webClick()); + + Thread.sleep(5 * 1000); + + onView(withId(R.id.switch_account_button)).perform(click()); + onView(withId(R.id.user_name)).check(matches(withText("User One"))); + + activityScenario.onActivity(activity -> { + assertEquals(loginName, Objects.requireNonNull(activity.userUtils.getCurrentUser()).getUserId()); + }); + + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/nextcloud/talk/controllers/ContactsController.java b/app/src/main/java/com/nextcloud/talk/controllers/ContactsController.java index 3d202cfd4..c9dbaf36a 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/ContactsController.java +++ b/app/src/main/java/com/nextcloud/talk/controllers/ContactsController.java @@ -80,6 +80,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Set; @@ -540,7 +541,8 @@ public class ContactsController extends BaseController implements SearchView.OnQ } else if (participant.getActorType() == Participant.ActorType.CIRCLES) { headerTitle = getResources().getString(R.string.nc_circles); } else { - headerTitle = participant.getDisplayName().substring(0, 1).toUpperCase(); + headerTitle = + participant.getDisplayName().substring(0, 1).toUpperCase(Locale.getDefault()); } GenericTextHeaderItem genericTextHeaderItem; diff --git a/app/src/main/java/com/nextcloud/talk/webrtc/MagicWebRTCUtils.java b/app/src/main/java/com/nextcloud/talk/webrtc/MagicWebRTCUtils.java index 9989203e5..68a8a3c74 100644 --- a/app/src/main/java/com/nextcloud/talk/webrtc/MagicWebRTCUtils.java +++ b/app/src/main/java/com/nextcloud/talk/webrtc/MagicWebRTCUtils.java @@ -92,8 +92,8 @@ public class MagicWebRTCUtils { public static boolean shouldEnableVideoHardwareAcceleration() { - return (!HARDWARE_ACCELERATION_VENDOR_BLACKLIST.contains(Build.MANUFACTURER.toLowerCase()) - && !HARDWARE_ACCELERATION_DEVICE_BLACKLIST.contains(Build.MODEL.toUpperCase())); + return (!HARDWARE_ACCELERATION_VENDOR_BLACKLIST.contains(Build.MANUFACTURER.toLowerCase(Locale.ROOT)) + && !HARDWARE_ACCELERATION_DEVICE_BLACKLIST.contains(Build.MODEL.toUpperCase(Locale.ROOT))); } public static String preferCodec(String sdpDescription, String codec, boolean isAudio) { diff --git a/gradle.properties b/gradle.properties index feaab547b..bed2185e4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,6 +2,8 @@ # Nextcloud Talk application # # @author Mario Danic +# @author Tim Krüger +# Copyright (C) 2021 Tim Krüger # Copyright (C) 2017-2019 Mario Danic # # This program is free software: you can redistribute it and/or modify @@ -39,3 +41,7 @@ org.gradle.daemon=true org.gradle.configureondemand=true org.gradle.caching=true org.gradle.parallel=true + +NC_TEST_SERVER_BASEURL=http://server +NC_TEST_SERVER_USERNAME=user1 +NC_TEST_SERVER_PASSWORD=user1 \ No newline at end of file diff --git a/scripts/analysis/lint-results.txt b/scripts/analysis/lint-results.txt index 7d0dd5fec..96101281e 100644 --- a/scripts/analysis/lint-results.txt +++ b/scripts/analysis/lint-results.txt @@ -1,2 +1,2 @@ DO NOT TOUCH; GENERATED BY DRONE - Lint Report: 1 error and 224 warnings + Lint Report: 1 error and 222 warnings