added DEV version to repo

This commit is contained in:
Fr4nz D13trich 2025-09-18 18:43:03 +02:00
parent 1ef725ef20
commit 23e673bfdf
2135 changed files with 97033 additions and 21206 deletions

View file

@ -2,7 +2,7 @@
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2018 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android;
@ -22,6 +22,8 @@ import android.view.View;
import com.facebook.testing.screenshot.Screenshot;
import com.facebook.testing.screenshot.internal.TestNameDetector;
import com.nextcloud.android.common.ui.theme.MaterialSchemes;
import com.nextcloud.android.common.ui.theme.MaterialSchemesImpl;
import com.nextcloud.client.account.User;
import com.nextcloud.client.account.UserAccountManager;
import com.nextcloud.client.account.UserAccountManagerImpl;
@ -38,7 +40,6 @@ import com.nextcloud.test.RandomStringGenerator;
import com.owncloud.android.datamodel.ArbitraryDataProvider;
import com.owncloud.android.datamodel.ArbitraryDataProviderImpl;
import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.datamodel.UploadsStorageManager;
import com.owncloud.android.db.OCUpload;
import com.owncloud.android.files.services.NameCollisionPolicy;
@ -54,6 +55,7 @@ import com.owncloud.android.lib.resources.status.OwnCloudVersion;
import com.owncloud.android.operations.CreateFolderOperation;
import com.owncloud.android.operations.UploadFileOperation;
import com.owncloud.android.utils.FileStorageUtils;
import com.owncloud.android.utils.theme.MaterialSchemesProvider;
import org.apache.commons.io.FileUtils;
import org.junit.After;
@ -182,7 +184,7 @@ public abstract class AbstractIT {
String darkModeParameter = arguments.getString("DARKMODE");
if (darkModeParameter != null) {
if (darkModeParameter.equalsIgnoreCase("dark")) {
if ("dark".equalsIgnoreCase(darkModeParameter)) {
DARK_MODE = "dark";
AppPreferencesImpl.fromContext(targetContext).setDarkThemeMode(DarkMode.DARK);
MainApp.setAppTheme(DarkMode.DARK);
@ -191,7 +193,7 @@ public abstract class AbstractIT {
}
}
if (DARK_MODE.equalsIgnoreCase("light") && COLOR.equalsIgnoreCase("blue")) {
if ("light".equalsIgnoreCase(DARK_MODE) && "blue".equalsIgnoreCase(COLOR)) {
// use already existing names
DARK_MODE = "";
COLOR = "";
@ -254,19 +256,12 @@ public abstract class AbstractIT {
file.mkdirs();
return file;
} else {
switch (name) {
case "empty.txt":
return createFile("empty.txt", 0);
case "nonEmpty.txt":
return createFile("nonEmpty.txt", 100);
case "chunkedFile.txt":
return createFile("chunkedFile.txt", 500000);
default:
return createFile(name, 0);
}
return switch (name) {
case "empty.txt" -> createFile("empty.txt", 0);
case "nonEmpty.txt" -> createFile("nonEmpty.txt", 100);
case "chunkedFile.txt" -> createFile("chunkedFile.txt", 500000);
default -> createFile(name, 0);
};
}
}
@ -301,7 +296,7 @@ public abstract class AbstractIT {
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
}
protected void onIdleSync(Runnable recipient) {
public void onIdleSync(Runnable recipient) {
InstrumentationRegistry.getInstrumentation().waitForIdle(recipient);
}
@ -355,7 +350,7 @@ public abstract class AbstractIT {
}
}
public OCFile createFolder(String remotePath) {
public void createFolder(String remotePath) {
RemoteOperationResult check = new ExistenceCheckRemoteOperation(remotePath, false).execute(client);
if (!check.isSuccess()) {
@ -363,8 +358,6 @@ public abstract class AbstractIT {
.execute(client)
.isSuccess());
}
return getStorageManager().getFileByDecryptedRemotePath(remotePath.endsWith("/") ? remotePath : remotePath + "/");
}
public void uploadFile(File file, String remotePath) {
@ -375,6 +368,11 @@ public abstract class AbstractIT {
public void uploadOCUpload(OCUpload ocUpload) {
ConnectivityService connectivityServiceMock = new ConnectivityService() {
@Override
public void isNetworkAndServerAvailable(@NonNull GenericCallback<Boolean> callback) {
}
@Override
public boolean isConnected() {
return false;
@ -457,12 +455,18 @@ public abstract class AbstractIT {
screenshot(view, "");
}
protected void screenshotViaName(Activity activity, String name) {
public void screenshotViaName(Activity activity, String name) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
Screenshot.snapActivity(activity).setName(name).record();
}
}
protected void screenshotViaName(View view, String name) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
Screenshot.snap(view).setName(name).record();
}
}
protected void screenshot(View view, String prefix) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
Screenshot.snap(view).setName(createName(prefix)).record();
@ -541,4 +545,38 @@ public abstract class AbstractIT {
protected static boolean removeAccount(Account account) {
return AccountManager.get(targetContext).removeAccountExplicitly(account);
}
protected MaterialSchemesProvider getMaterialSchemesProvider() {
return new MaterialSchemesProvider() {
@NonNull
@Override
public MaterialSchemes getMaterialSchemesForUser(@NonNull User user) {
return null;
}
@NonNull
@Override
public MaterialSchemes getMaterialSchemesForCapability(@NonNull OCCapability capability) {
return null;
}
@NonNull
@Override
public MaterialSchemes getMaterialSchemesForCurrentUser() {
return new MaterialSchemesImpl(R.color.primary, false);
}
@NonNull
@Override
public MaterialSchemes getDefaultMaterialSchemes() {
return null;
}
@NonNull
@Override
public MaterialSchemes getMaterialSchemesForPrimaryBackground() {
return null;
}
};
}
}

View file

@ -2,7 +2,7 @@
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2020 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android;
@ -13,7 +13,6 @@ import android.accounts.OperationCanceledException;
import android.content.ActivityNotFoundException;
import android.net.Uri;
import android.os.Bundle;
import com.nextcloud.client.account.User;
import com.nextcloud.client.account.UserAccountManager;
import com.nextcloud.client.account.UserAccountManagerImpl;
@ -174,9 +173,7 @@ public abstract class AbstractOnServerIT extends AbstractIT {
Assert.fail("Server not ready!");
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
@ -187,6 +184,11 @@ public abstract class AbstractOnServerIT extends AbstractIT {
public void uploadOCUpload(OCUpload ocUpload, int localBehaviour) {
ConnectivityService connectivityServiceMock = new ConnectivityService() {
@Override
public void isNetworkAndServerAvailable(@NonNull GenericCallback<Boolean> callback) {
}
@Override
public boolean isConnected() {
return false;

View file

@ -4,7 +4,7 @@
* SPDX-FileCopyrightText: 2020 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2020 Chris Narkiewicz <hello@ezaquarii.com>
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android;

View file

@ -1,8 +1,8 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2024 Your Name <your@email.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-FileCopyrightText: 2024 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android

View file

@ -2,7 +2,7 @@
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2018 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android;
@ -106,8 +106,8 @@ public class FileIT extends AbstractOnServerIT {
assertTrue(new SynchronizeFolderOperation(targetContext,
folderPath,
user,
System.currentTimeMillis(),
fileDataStorageManager)
fileDataStorageManager,
false)
.execute(targetContext)
.isSuccess());

View file

@ -0,0 +1,183 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2025 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
package com.owncloud.android
import androidx.annotation.UiThread
import androidx.test.core.app.launchActivity
import androidx.test.espresso.Espresso
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.IdlingRegistry
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.action.ViewActions.scrollTo
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.contrib.DrawerActions
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.isRoot
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withText
import com.owncloud.android.datamodel.OCFile
import com.owncloud.android.ui.activity.FileDisplayActivity
import com.owncloud.android.ui.activity.SettingsActivity
import com.owncloud.android.ui.activity.SyncedFoldersActivity
import com.owncloud.android.utils.EspressoIdlingResource
import com.owncloud.android.utils.ScreenshotTest
import org.junit.After
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.BeforeClass
import org.junit.ClassRule
import org.junit.Test
import tools.fastlane.screengrab.Screengrab
import tools.fastlane.screengrab.UiAutomatorScreenshotStrategy
import tools.fastlane.screengrab.locale.LocaleTestRule
class ScreenshotsIT : AbstractIT() {
@Before
fun registerIdlingResource() {
IdlingRegistry.getInstance().register(EspressoIdlingResource.countingIdlingResource)
}
@After
fun unregisterIdlingResource() {
IdlingRegistry.getInstance().unregister(EspressoIdlingResource.countingIdlingResource)
}
@Test
@UiThread
@ScreenshotTest
fun gridViewScreenshot() {
launchActivity<FileDisplayActivity>().use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
EspressoIdlingResource.increment()
onView(withId(R.id.switch_grid_view_button)).perform(click())
EspressoIdlingResource.decrement()
onView(isRoot()).check(matches(isDisplayed()))
Screengrab.screenshot("01_gridView")
// Switch back
onView(withId(R.id.switch_grid_view_button)).perform(click())
assertTrue(true)
}
}
}
}
@Test
@UiThread
@ScreenshotTest
fun listViewScreenshot() {
launchActivity<FileDisplayActivity>().use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
EspressoIdlingResource.increment()
val path = "/Camera/"
OCFile(path).apply {
storageManager.saveFile(this)
}
onView(withId(R.id.list_root)).perform(click())
EspressoIdlingResource.decrement()
onView(isRoot()).check(matches(isDisplayed()))
Screengrab.screenshot("02_listView")
assertTrue(true)
}
}
}
}
@Test
@UiThread
@ScreenshotTest
fun drawerScreenshot() {
launchActivity<FileDisplayActivity>().use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
EspressoIdlingResource.increment()
onView(withId(R.id.drawer_layout)).perform(DrawerActions.open())
EspressoIdlingResource.decrement()
onView(isRoot()).check(matches(isDisplayed()))
Screengrab.screenshot("03_drawer")
onView(withId(R.id.drawer_layout)).perform(DrawerActions.close())
assertTrue(true)
}
}
}
}
@Test
@UiThread
@ScreenshotTest
fun multipleAccountsScreenshot() {
launchActivity<FileDisplayActivity>().use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
EspressoIdlingResource.increment()
onView(withId(R.id.switch_account_button)).perform(click())
EspressoIdlingResource.decrement()
onView(isRoot()).check(matches(isDisplayed()))
Screengrab.screenshot("04_accounts")
Espresso.pressBack()
assertTrue(true)
}
}
}
}
@Test
@UiThread
@ScreenshotTest
fun autoUploadScreenshot() {
launchActivity<SyncedFoldersActivity>().use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
onView(isRoot()).check(matches(isDisplayed()))
Screengrab.screenshot("05_autoUpload")
assertTrue(true)
}
}
}
}
@Test
@UiThread
@ScreenshotTest
fun davdroidScreenshot() {
launchActivity<SettingsActivity>().use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
EspressoIdlingResource.increment()
onView(withText(R.string.prefs_category_more)).perform(scrollTo())
EspressoIdlingResource.decrement()
onView(isRoot()).check(matches(isDisplayed()))
Screengrab.screenshot("06_davdroid")
assertTrue(true)
}
}
}
}
companion object {
@ClassRule
@JvmField
val localeTestRule: LocaleTestRule = LocaleTestRule()
@BeforeClass
@JvmStatic
fun beforeScreenshot() {
Screengrab.setDefaultScreenshotStrategy(UiAutomatorScreenshotStrategy())
}
}
}

View file

@ -4,7 +4,7 @@
* SPDX-FileCopyrightText: 2020 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2020 Chris Narkiewicz <hello@ezaquarii.com>
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android;
@ -56,6 +56,11 @@ public class UploadIT extends AbstractOnServerIT {
targetContext.getContentResolver());
private ConnectivityService connectivityServiceMock = new ConnectivityService() {
@Override
public void isNetworkAndServerAvailable(@NonNull GenericCallback<Boolean> callback) {
}
@Override
public boolean isConnected() {
return false;
@ -274,6 +279,11 @@ public class UploadIT extends AbstractOnServerIT {
@Test
public void testUploadOnWifiOnlyButNoWifi() {
ConnectivityService connectivityServiceMock = new ConnectivityService() {
@Override
public void isNetworkAndServerAvailable(@NonNull GenericCallback<Boolean> callback) {
}
@Override
public boolean isConnected() {
return false;
@ -358,6 +368,11 @@ public class UploadIT extends AbstractOnServerIT {
@Test
public void testUploadOnWifiOnlyButMeteredWifi() {
ConnectivityService connectivityServiceMock = new ConnectivityService() {
@Override
public void isNetworkAndServerAvailable(@NonNull GenericCallback<Boolean> callback) {
}
@Override
public boolean isConnected() {
return false;
@ -452,7 +467,7 @@ public class UploadIT extends AbstractOnServerIT {
assertEquals(remotePath, ocFile.getRemotePath());
assertEquals(creationTimestamp, ocFile.getCreationTimestamp());
assertTrue(uploadTimestamp - 10 < ocFile.getUploadTimestamp() ||
assertTrue(uploadTimestamp - 10 < ocFile.getUploadTimestamp() &&
uploadTimestamp + 10 > ocFile.getUploadTimestamp());
}
@ -498,7 +513,7 @@ public class UploadIT extends AbstractOnServerIT {
OCFile ocFile = null;
for (OCFile f : files) {
if (f.getFileName().equals("metadata.jpg")) {
if ("metadata.jpg".equals(f.getFileName())) {
ocFile = f;
break;
}

View file

@ -3,7 +3,7 @@
*
* SPDX-FileCopyrightText: 2020 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.authentication

View file

@ -3,7 +3,7 @@
*
* SPDX-FileCopyrightText: 2023 Álvaro Brey <alvaro@alvarobrey.com>
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.authentication

View file

@ -3,7 +3,7 @@
*
* SPDX-FileCopyrightText: 2020 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.datamodel

View file

@ -3,7 +3,7 @@
*
* SPDX-FileCopyrightText: 2021 Álvaro Brey <alvaro@alvarobrey.com>
* SPDX-FileCopyrightText: 2021 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.datamodel
@ -43,7 +43,6 @@ class ContentResolverHelperIT {
}
@Test
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
fun contentResolver_onAndroid26_usesNewAPI() {
ContentResolverHelper
.queryResolver(resolver, URI, PROJECTION, SELECTION, null, SORT_COLUMN, SORT_DIRECTION, LIMIT)

View file

@ -0,0 +1,10 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2024 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
package com.owncloud.android.datamodel
data class Credentials(val publicKey: String, val certificate: String)

View file

@ -3,7 +3,7 @@
*
* SPDX-FileCopyrightText: 2020 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.datamodel;

View file

@ -3,7 +3,7 @@
*
* SPDX-FileCopyrightText: 2020 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.datamodel

View file

@ -3,7 +3,7 @@
*
* SPDX-FileCopyrightText: 2020 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.datamodel;

View file

@ -3,7 +3,7 @@
*
* SPDX-FileCopyrightText: 2020 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.datamodel

View file

@ -1,9 +1,9 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2023 Alper Ozturk <alper_ozturk@proton.me>
* SPDX-FileCopyrightText: 2023 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.datamodel

View file

@ -36,6 +36,7 @@ public class OCFileUnitTest {
private static final String STORAGE_PATH = "/mnt/sd/localpath/to/a/file.txt";
private static final String MIME_TYPE = "text/plain";
private static final long FILE_LENGTH = 9876543210L;
private static final long UPLOADED_TIMESTAMP = 8765431109L;
private static final long CREATION_TIMESTAMP = 8765432109L;
private static final long MODIFICATION_TIMESTAMP = 7654321098L;
private static final long MODIFICATION_TIMESTAMP_AT_LAST_SYNC_FOR_DATA = 6543210987L;
@ -63,6 +64,7 @@ public class OCFileUnitTest {
mFile.setStoragePath(STORAGE_PATH);
mFile.setMimeType(MIME_TYPE);
mFile.setFileLength(FILE_LENGTH);
mFile.setUploadTimestamp(UPLOADED_TIMESTAMP);
mFile.setCreationTimestamp(CREATION_TIMESTAMP);
mFile.setModificationTimestamp(MODIFICATION_TIMESTAMP);
mFile.setModificationTimestampAtLastSyncForData(MODIFICATION_TIMESTAMP_AT_LAST_SYNC_FOR_DATA);
@ -93,6 +95,7 @@ public class OCFileUnitTest {
assertThat(fileReadFromParcel.getStoragePath(), is(STORAGE_PATH));
assertThat(fileReadFromParcel.getMimeType(), is(MIME_TYPE));
assertThat(fileReadFromParcel.getFileLength(), is(FILE_LENGTH));
assertThat(fileReadFromParcel.getUploadTimestamp(), is(UPLOADED_TIMESTAMP));
assertThat(fileReadFromParcel.getCreationTimestamp(), is(CREATION_TIMESTAMP));
assertThat(fileReadFromParcel.getModificationTimestamp(), is(MODIFICATION_TIMESTAMP));
assertThat(

View file

@ -4,7 +4,7 @@
* SPDX-FileCopyrightText: 2017 JARP <jarp@customer-187-174-218-184.uninet-ide.com.mx
* SPDX-FileCopyrightText: 2019 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2021 Chris Narkiewicz <hello@ezaquarii.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.datamodel;

View file

@ -0,0 +1,39 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2025 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
package com.owncloud.android.extensions
import android.app.Activity
import android.content.Intent
import androidx.test.core.app.launchActivity
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.matcher.ViewMatchers.isRoot
import com.owncloud.android.AbstractIT
import com.owncloud.android.utils.EspressoIdlingResource
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
inline fun <reified T : Activity> AbstractIT.launchAndCapture(
testClassName: String,
actionName: String,
intent: Intent? = null,
crossinline before: (T) -> Unit
) {
launchActivity<T>(intent).use { scenario ->
scenario.onActivity { activity ->
onIdleSync {
EspressoIdlingResource.increment()
before(activity)
EspressoIdlingResource.decrement()
val screenshotName = createName(testClassName + "_" + actionName, "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(activity, screenshotName)
}
}
}
}

View file

@ -1,9 +1,9 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2022 Álvaro Brey Vilas
* SPDX-FileCopyrightText: 2022 Álvaro Brey <alvaro@alvarobrey.com>
* SPDX-FileCopyrightText: 2022 Nextcloud GmbH
* SPDX-License-Identifier: GPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
package com.owncloud.android.files
@ -331,10 +331,7 @@ class FileMenuFilterIT : AbstractIT() {
}
}
private data class ExpectedLockVisibilities(
val lockFile: Boolean,
val unlockFile: Boolean
)
private data class ExpectedLockVisibilities(val lockFile: Boolean, val unlockFile: Boolean)
private fun configureCapability(capability: OCCapability) {
every { mockStorageManager.getCapability(any<User>()) } returns capability

View file

@ -4,7 +4,7 @@
* SPDX-FileCopyrightText: 2020 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2020 Chris Narkiewicz <hello@ezaquarii.com>
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.files.services
@ -34,9 +34,9 @@ abstract class FileUploaderIT : AbstractOnServerIT() {
private var uploadsStorageManager: UploadsStorageManager? = null
private val connectivityServiceMock: ConnectivityService = object : ConnectivityService {
override fun isConnected(): Boolean {
return false
}
override fun isNetworkAndServerAvailable(callback: ConnectivityService.GenericCallback<Boolean>) = Unit
override fun isConnected(): Boolean = false
override fun isInternetWalled(): Boolean = false
override fun getConnectivity(): Connectivity = Connectivity.CONNECTED_WIFI

View file

@ -3,7 +3,7 @@
*
* SPDX-FileCopyrightText: 2021 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2021 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.operations

View file

@ -3,7 +3,7 @@
*
* SPDX-FileCopyrightText: 2020 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.operations;

View file

@ -2,7 +2,7 @@
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2020 Torsten Grote <t@grobox.de>
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.providers
@ -177,31 +177,30 @@ object DocumentsProviderUtils {
*/
@Suppress("EXPERIMENTAL_API_USAGE")
@VisibleForTesting
internal suspend fun getLoadedCursor(timeout: Long = 15_000, query: () -> Cursor?) =
withTimeout(timeout) {
suspendCancellableCoroutine<Cursor> { cont ->
val cursor = query() ?: throw IOException("Initial query returned no results")
cont.invokeOnCancellation { cursor.close() }
val loading = cursor.extras.getBoolean(EXTRA_LOADING, false)
if (loading) {
Log_OC.e("TEST", "Cursor was loading, wait for update...")
cursor.registerContentObserver(
object : ContentObserver(null) {
override fun onChange(selfChange: Boolean, uri: Uri?) {
cursor.close()
val newCursor = query()
if (newCursor == null) {
cont.cancel(IOException("Re-query returned no results"))
} else {
cont.resume(newCursor)
}
internal suspend fun getLoadedCursor(timeout: Long = 15_000, query: () -> Cursor?) = withTimeout(timeout) {
suspendCancellableCoroutine { cont ->
val cursor = query() ?: throw IOException("Initial query returned no results")
cont.invokeOnCancellation { cursor.close() }
val loading = cursor.extras?.getBoolean(EXTRA_LOADING, false) ?: false
if (loading) {
Log_OC.e("TEST", "Cursor was loading, wait for update...")
cursor.registerContentObserver(
object : ContentObserver(null) {
override fun onChange(selfChange: Boolean, uri: Uri?) {
cursor.close()
val newCursor = query()
if (newCursor == null) {
cont.cancel(IOException("Re-query returned no results"))
} else {
cont.resume(newCursor)
}
}
)
} else {
// not loading, return cursor right away
cont.resume(cursor)
}
}
)
} else {
// not loading, return cursor right away
cont.resume(cursor)
}
}
}
}

View file

@ -2,7 +2,7 @@
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2020 Torsten Grote <t@grobox.de>
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.providers
@ -53,6 +53,14 @@ class DocumentsStorageProviderIT : AbstractOnServerIT() {
// DocumentsProvider#onCreate() is called when the application is started
// which is *after* AbstractOnServerIT adds the accounts (when the app is freshly installed).
// So we need to query our roots here to ensure that the internal storage map is initialized.
storageManager.run {
val updatedRootPath = getFileByEncryptedRemotePath(ROOT_PATH).apply {
permissions = "RSMCKGWDNV"
}
saveFile(updatedRootPath)
}
contentResolver.query(DocumentsContract.buildRootsUri(authority), null, null, null)
assertTrue("Storage root does not exist", rootDir.exists())
assertTrue(rootDir.isDirectory)

View file

@ -3,7 +3,7 @@
*
* SPDX-FileCopyrightText: 2021 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2021 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.providers

View file

@ -1,32 +1,32 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2020 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2025 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.providers
import androidx.test.espresso.intent.rule.IntentsTestRule
import androidx.annotation.UiThread
import androidx.test.core.app.launchActivity
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.isRoot
import com.nextcloud.test.TestActivity
import com.owncloud.android.AbstractOnServerIT
import org.junit.Rule
import org.junit.Test
class UsersAndGroupsSearchProviderIT : AbstractOnServerIT() {
@get:Rule
val testActivityRule = IntentsTestRule(TestActivity::class.java, true, false)
@Test
@UiThread
fun searchUser() {
val activity = testActivityRule.launchActivity(null)
shortSleep()
activity.runOnUiThread {
// fragment.search("Admin")
launchActivity<TestActivity>().use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
onView(isRoot()).check(matches(isDisplayed()))
}
}
}
longSleep()
}
}

View file

@ -3,7 +3,7 @@
*
* SPDX-FileCopyrightText: 2020 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.ui
@ -45,14 +45,13 @@ class LoginIT : AbstractIT() {
ActivityScenario.launch(AuthenticatorActivity::class.java)
}
@Test
@Throws(InterruptedException::class)
@Suppress("MagicNumber", "SwallowedException")
/**
* The CI/CD pipeline is encountering issues related to the Android version for this functionality.
* Therefore the test will only be executed on Android versions 10 and above.
*/
@Test
@Throws(InterruptedException::class)
@Suppress("MagicNumber", "SwallowedException")
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.Q)
fun login() {
val arguments = InstrumentationRegistry.getArguments()
@ -71,7 +70,7 @@ class LoginIT : AbstractIT() {
Web.onWebView()
.withElement(DriverAtoms.findElement(Locator.XPATH, "//form[@id='login-form']/input[@type='submit']"))
.perform(DriverAtoms.webClick())
} catch (e: RuntimeException) {
} catch (_: RuntimeException) {
// NC < 25
Web.onWebView()
.withElement(DriverAtoms.findElement(Locator.XPATH, "//p[@id='redirect-link']/a"))
@ -94,7 +93,7 @@ class LoginIT : AbstractIT() {
Web.onWebView()
.withElement(DriverAtoms.findElement(Locator.XPATH, "//button[@type='submit']"))
.perform(DriverAtoms.webClick())
} catch (e: RuntimeException) {
} catch (_: RuntimeException) {
// NC < 25
Web.onWebView()
.withElement(DriverAtoms.findElement(Locator.XPATH, "//input[@type='submit']"))

View file

@ -0,0 +1,326 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2025 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-FileCopyrightText: 2020 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.ui.activity
import android.content.Intent
import androidx.annotation.UiThread
import androidx.fragment.app.DialogFragment
import androidx.test.core.app.launchActivity
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.isRoot
import com.nextcloud.client.account.UserAccountManagerImpl
import com.nextcloud.utils.extensions.getDecryptedPath
import com.owncloud.android.AbstractIT
import com.owncloud.android.R
import com.owncloud.android.datamodel.FileDataStorageManager
import com.owncloud.android.datamodel.OCFile
import com.owncloud.android.db.OCUpload
import com.owncloud.android.ui.dialog.ConflictsResolveDialog.Companion.newInstance
import com.owncloud.android.ui.dialog.ConflictsResolveDialog.Decision
import com.owncloud.android.ui.dialog.ConflictsResolveDialog.OnConflictDecisionMadeListener
import com.owncloud.android.utils.EspressoIdlingResource
import com.owncloud.android.utils.FileStorageUtils
import com.owncloud.android.utils.ScreenshotTest
import junit.framework.TestCase
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Test
class ConflictsResolveActivityIT : AbstractIT() {
private val testClassName = "com.owncloud.android.ui.activity.ConflictsResolveActivityIT"
private var returnCode = false
@Test
@UiThread
@ScreenshotTest
fun screenshotTextFiles() {
val newFile = OCFile("/newFile.txt").apply {
remoteId = "0001"
fileLength = 56000
modificationTimestamp = 1522019340
setStoragePath(FileStorageUtils.getSavePath(user.accountName) + "/nonEmpty.txt")
}
val existingFile = OCFile("/newFile.txt").apply {
remoteId = "0002"
fileLength = 1024000
modificationTimestamp = 1582019340
}
val storageManager = FileDataStorageManager(user, targetContext.contentResolver)
storageManager.saveNewFile(existingFile)
val intent = Intent(targetContext, ConflictsResolveActivity::class.java).apply {
putExtra(FileActivity.EXTRA_FILE, newFile)
putExtra(ConflictsResolveActivity.EXTRA_EXISTING_FILE, existingFile)
}
launchActivity<ConflictsResolveActivity>(intent).use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
EspressoIdlingResource.increment()
val dialog = newInstance(
storageManager.getDecryptedPath(existingFile),
targetContext,
newFile,
existingFile,
UserAccountManagerImpl
.fromContext(targetContext)
.getUser()
)
dialog.showDialog(sut)
EspressoIdlingResource.decrement()
val screenShotName = createName(testClassName + "_" + "screenshotTextFiles", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(dialog.requireDialog().window?.decorView, screenShotName)
}
}
}
}
@Test
@UiThread
fun cancel() {
val newUpload = OCUpload(
FileStorageUtils.getSavePath(user.accountName) + "/nonEmpty.txt",
"/newFile.txt",
user.accountName
)
val existingFile = OCFile("/newFile.txt").apply {
fileLength = 1024000
modificationTimestamp = 1582019340
}
val newFile = OCFile("/newFile.txt").apply {
fileLength = 56000
modificationTimestamp = 1522019340
setStoragePath(FileStorageUtils.getSavePath(user.accountName) + "/nonEmpty.txt")
}
EspressoIdlingResource.increment()
FileDataStorageManager(user, targetContext.contentResolver).run {
saveNewFile(existingFile)
}
EspressoIdlingResource.decrement()
val intent = Intent(targetContext, ConflictsResolveActivity::class.java).apply {
putExtra(FileActivity.EXTRA_FILE, newFile)
putExtra(ConflictsResolveActivity.EXTRA_EXISTING_FILE, existingFile)
putExtra(ConflictsResolveActivity.EXTRA_CONFLICT_UPLOAD_ID, newUpload.uploadId)
}
launchActivity<ConflictsResolveActivity>(intent).use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
EspressoIdlingResource.increment()
returnCode = false
sut.listener = OnConflictDecisionMadeListener { decision: Decision? ->
assertEquals(decision, Decision.CANCEL)
returnCode = true
}
EspressoIdlingResource.decrement()
onView(ViewMatchers.withText("Cancel")).perform(ViewActions.click())
TestCase.assertTrue(returnCode)
}
}
}
}
@Test
@UiThread
@ScreenshotTest
fun keepExisting() {
returnCode = false
val newUpload = OCUpload(
FileStorageUtils.getSavePath(user.accountName) + "/nonEmpty.txt",
"/newFile.txt",
user.accountName
)
val existingFile = OCFile("/newFile.txt").apply {
remoteId = "0001"
fileLength = 1024000
modificationTimestamp = 1582019340
}
val newFile = OCFile("/newFile.txt").apply {
fileLength = 56000
remoteId = "0002"
modificationTimestamp = 1522019340
setStoragePath(FileStorageUtils.getSavePath(user.accountName) + "/nonEmpty.txt")
}
EspressoIdlingResource.increment()
FileDataStorageManager(user, targetContext.contentResolver).run {
saveNewFile(existingFile)
}
EspressoIdlingResource.decrement()
val intent = Intent(targetContext, ConflictsResolveActivity::class.java).apply {
putExtra(FileActivity.EXTRA_FILE, newFile)
putExtra(ConflictsResolveActivity.EXTRA_EXISTING_FILE, existingFile)
putExtra(ConflictsResolveActivity.EXTRA_CONFLICT_UPLOAD_ID, newUpload.uploadId)
}
launchActivity<ConflictsResolveActivity>(intent).use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
EspressoIdlingResource.increment()
sut.listener = OnConflictDecisionMadeListener { decision: Decision? ->
assertEquals(decision, Decision.KEEP_SERVER)
returnCode = true
}
EspressoIdlingResource.decrement()
onView(ViewMatchers.withId(R.id.right_checkbox)).perform(ViewActions.click())
val dialog = sut.supportFragmentManager.findFragmentByTag("conflictDialog") as DialogFragment?
val screenShotName = createName(testClassName + "_" + "keepExisting", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(dialog?.requireDialog()?.window?.decorView, screenShotName)
onView(ViewMatchers.withText("OK")).perform(ViewActions.click())
assertTrue(returnCode)
}
}
}
}
@Test
@UiThread
@ScreenshotTest
fun keepNew() {
returnCode = false
val newUpload = OCUpload(
FileStorageUtils.getSavePath(user.accountName) + "/nonEmpty.txt",
"/newFile.txt",
user.accountName
)
val existingFile = OCFile("/newFile.txt").apply {
fileLength = 1024000
modificationTimestamp = 1582019340
remoteId = "00000123abc"
}
val newFile = OCFile("/newFile.txt").apply {
fileLength = 56000
modificationTimestamp = 1522019340
setStoragePath(FileStorageUtils.getSavePath(user.accountName) + "/nonEmpty.txt")
}
val storageManager = FileDataStorageManager(user, targetContext.contentResolver)
storageManager.saveNewFile(existingFile)
val intent = Intent(targetContext, ConflictsResolveActivity::class.java)
intent.putExtra(FileActivity.EXTRA_FILE, newFile)
intent.putExtra(ConflictsResolveActivity.EXTRA_EXISTING_FILE, existingFile)
intent.putExtra(ConflictsResolveActivity.EXTRA_CONFLICT_UPLOAD_ID, newUpload.uploadId)
launchActivity<ConflictsResolveActivity>(intent).use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
EspressoIdlingResource.increment()
sut.listener = OnConflictDecisionMadeListener { decision: Decision? ->
assertEquals(decision, Decision.KEEP_LOCAL)
returnCode = true
}
EspressoIdlingResource.decrement()
onView(ViewMatchers.withId(R.id.left_checkbox)).perform(ViewActions.click())
val dialog = sut.supportFragmentManager.findFragmentByTag("conflictDialog") as DialogFragment?
val screenShotName = createName(testClassName + "_" + "keepNew", "")
screenshotViaName(dialog?.requireDialog()?.window?.decorView, screenShotName)
onView(ViewMatchers.withText("OK")).perform(ViewActions.click())
assertTrue(returnCode)
}
}
}
}
@Test
@UiThread
@ScreenshotTest
fun keepBoth() {
returnCode = false
val newUpload = OCUpload(
FileStorageUtils.getSavePath(user.accountName) + "/nonEmpty.txt",
"/newFile.txt",
user.accountName
)
val existingFile = OCFile("/newFile.txt").apply {
remoteId = "0001"
fileLength = 1024000
modificationTimestamp = 1582019340
}
val newFile = OCFile("/newFile.txt").apply {
fileLength = 56000
remoteId = "0002"
modificationTimestamp = 1522019340
setStoragePath(FileStorageUtils.getSavePath(user.accountName) + "/nonEmpty.txt")
}
val storageManager = FileDataStorageManager(user, targetContext.contentResolver)
storageManager.saveNewFile(existingFile)
val intent = Intent(targetContext, ConflictsResolveActivity::class.java).apply {
putExtra(FileActivity.EXTRA_FILE, newFile)
putExtra(ConflictsResolveActivity.EXTRA_EXISTING_FILE, existingFile)
putExtra(ConflictsResolveActivity.EXTRA_CONFLICT_UPLOAD_ID, newUpload.uploadId)
}
launchActivity<ConflictsResolveActivity>(intent).use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
EspressoIdlingResource.increment()
sut.listener = OnConflictDecisionMadeListener { decision: Decision? ->
assertEquals(decision, Decision.KEEP_BOTH)
returnCode = true
}
EspressoIdlingResource.decrement()
onView(ViewMatchers.withId(R.id.right_checkbox)).perform(ViewActions.click())
onView(ViewMatchers.withId(R.id.left_checkbox)).perform(ViewActions.click())
onView(ViewMatchers.withId(R.id.left_checkbox)).perform(ViewActions.click())
val dialog = sut.supportFragmentManager.findFragmentByTag("conflictDialog") as DialogFragment?
val screenShotName = createName(testClassName + "_" + "keepBoth", "")
screenshotViaName(dialog?.requireDialog()?.window?.decorView, screenShotName)
onView(ViewMatchers.withText("OK")).perform(ViewActions.click())
assertTrue(returnCode)
}
}
}
}
@After
override fun after() {
storageManager.deleteAllFiles()
}
}

View file

@ -3,24 +3,42 @@
*
* SPDX-FileCopyrightText: 2020 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.ui.activity
import android.content.Intent
import androidx.test.espresso.intent.rule.IntentsTestRule
import androidx.annotation.UiThread
import androidx.test.core.app.launchActivity
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.IdlingRegistry
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.isRoot
import com.owncloud.android.AbstractIT
import com.owncloud.android.datamodel.OCFile
import com.owncloud.android.utils.EspressoIdlingResource
import com.owncloud.android.utils.ScreenshotTest
import org.junit.After
import org.junit.Assert.assertTrue
import org.junit.Rule
import org.junit.Before
import org.junit.Test
class ContactsPreferenceActivityIT : AbstractIT() {
@get:Rule
var activityRule = IntentsTestRule(ContactsPreferenceActivity::class.java, true, false)
private val testClassName = "com.owncloud.android.ui.activity.ContactsPreferenceActivityIT"
@Before
fun registerIdlingResource() {
IdlingRegistry.getInstance().register(EspressoIdlingResource.countingIdlingResource)
}
@After
fun unregisterIdlingResource() {
IdlingRegistry.getInstance().unregister(EspressoIdlingResource.countingIdlingResource)
}
@Test
@UiThread
@ScreenshotTest
fun openVCF() {
val file = getFile("vcard.vcf")
@ -29,23 +47,34 @@ class ContactsPreferenceActivityIT : AbstractIT() {
assertTrue(vcfFile.isDown)
val intent = Intent()
intent.putExtra(ContactsPreferenceActivity.EXTRA_FILE, vcfFile)
intent.putExtra(ContactsPreferenceActivity.EXTRA_USER, user)
val sut = activityRule.launchActivity(intent)
val intent = Intent(targetContext, ContactsPreferenceActivity::class.java).apply {
putExtra(ContactsPreferenceActivity.EXTRA_FILE, vcfFile)
putExtra(ContactsPreferenceActivity.EXTRA_USER, user)
}
shortSleep()
screenshot(sut)
launchActivity<ContactsPreferenceActivity>(intent).use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
val screenShotName = createName(testClassName + "_" + "openVCF", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut, screenShotName)
}
}
}
}
@Test
@UiThread
@ScreenshotTest
fun openContactsPreference() {
val sut = activityRule.launchActivity(null)
shortSleep()
screenshot(sut)
launchActivity<ContactsPreferenceActivity>().use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
val screenShotName = createName(testClassName + "_" + "openContactsPreference", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut, screenShotName)
}
}
}
}
}

View file

@ -0,0 +1,128 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2025 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-FileCopyrightText: 2020 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.ui.activity
import android.accounts.Account
import android.accounts.AccountManager
import android.net.Uri
import android.view.View
import androidx.annotation.UiThread
import androidx.test.core.app.launchActivity
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions
import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.platform.app.InstrumentationRegistry
import com.nextcloud.client.account.User
import com.nextcloud.client.account.UserAccountManager
import com.nextcloud.client.account.UserAccountManagerImpl
import com.nextcloud.test.RetryTestRule
import com.owncloud.android.AbstractIT
import com.owncloud.android.MainApp
import com.owncloud.android.R
import com.owncloud.android.lib.common.accounts.AccountUtils
import com.owncloud.android.utils.EspressoIdlingResource
import org.hamcrest.Matchers
import org.junit.Assert
import org.junit.BeforeClass
import org.junit.Rule
import org.junit.Test
import java.util.function.Supplier
class DrawerActivityIT : AbstractIT() {
@Rule
@JvmField
val retryTestRule = RetryTestRule()
@Test
@UiThread
fun switchAccountViaAccountList() {
launchActivity<FileDisplayActivity>().use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
EspressoIdlingResource.increment()
sut.setUser(user1)
Assert.assertEquals(account1, sut.user.get().toPlatformAccount())
onView(ViewMatchers.withId(R.id.switch_account_button)).perform(ViewActions.click())
onView(
Matchers.anyOf<View?>(
ViewMatchers.withText(account2Name),
ViewMatchers.withText(
account2DisplayName
)
)
).perform(ViewActions.click())
Assert.assertEquals(account2, sut.user.get().toPlatformAccount())
EspressoIdlingResource.decrement()
onView(ViewMatchers.withId(R.id.switch_account_button)).perform(ViewActions.click())
onView(ViewMatchers.withText(account1?.name)).perform(ViewActions.click())
}
}
}
}
companion object {
private var account1: Account? = null
private var user1: User? = null
private var account2: Account? = null
private var account2Name: String? = null
private var account2DisplayName: String? = null
@JvmStatic
@BeforeClass
fun beforeClass() {
val arguments = InstrumentationRegistry.getArguments()
val baseUrl = Uri.parse(arguments.getString("TEST_SERVER_URL"))
val platformAccountManager = AccountManager.get(targetContext)
val userAccountManager: UserAccountManager = UserAccountManagerImpl.fromContext(targetContext)
for (account in platformAccountManager.accounts) {
platformAccountManager.removeAccountExplicitly(account)
}
var loginName = "user1"
var password = "user1"
var temp = Account("$loginName@$baseUrl", MainApp.getAccountType(targetContext))
platformAccountManager.addAccountExplicitly(temp, password, null)
platformAccountManager.setUserData(
temp,
AccountUtils.Constants.KEY_OC_ACCOUNT_VERSION,
UserAccountManager.ACCOUNT_VERSION.toString()
)
platformAccountManager.setUserData(temp, AccountUtils.Constants.KEY_OC_VERSION, "14.0.0.0")
platformAccountManager.setUserData(temp, AccountUtils.Constants.KEY_OC_BASE_URL, baseUrl.toString())
platformAccountManager.setUserData(temp, AccountUtils.Constants.KEY_USER_ID, loginName) // same as userId
account1 = userAccountManager.getAccountByName("$loginName@$baseUrl")
user1 = userAccountManager.getUser(account1!!.name)
.orElseThrow<IllegalAccessError?>(Supplier { IllegalAccessError() })
loginName = "user2"
password = "user2"
temp = Account("$loginName@$baseUrl", MainApp.getAccountType(targetContext))
platformAccountManager.addAccountExplicitly(temp, password, null)
platformAccountManager.setUserData(
temp,
AccountUtils.Constants.KEY_OC_ACCOUNT_VERSION,
UserAccountManager.ACCOUNT_VERSION.toString()
)
platformAccountManager.setUserData(temp, AccountUtils.Constants.KEY_OC_VERSION, "14.0.0.0")
platformAccountManager.setUserData(temp, AccountUtils.Constants.KEY_OC_BASE_URL, baseUrl.toString())
platformAccountManager.setUserData(temp, AccountUtils.Constants.KEY_USER_ID, loginName) // same as userId
account2 = userAccountManager.getAccountByName("$loginName@$baseUrl")
account2Name = "$loginName@$baseUrl"
account2DisplayName = "User Two@$baseUrl"
}
}
}

View file

@ -2,7 +2,7 @@
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2019 Unpublished <unpublished@gmx.net>
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.ui.activity;

View file

@ -0,0 +1,213 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2025 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-FileCopyrightText: 2019 Kilian Périsset <kilian.perisset@infomaniak.com>
* SPDX-FileCopyrightText: 2019 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.ui.activity
import android.content.Intent
import android.view.View
import androidx.annotation.UiThread
import androidx.test.core.app.launchActivity
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.IdlingRegistry
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.isRoot
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.owncloud.android.AbstractIT
import com.owncloud.android.R
import com.owncloud.android.datamodel.OCFile
import com.owncloud.android.utils.EspressoIdlingResource
import com.owncloud.android.utils.ScreenshotTest
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class FolderPickerActivityIT : AbstractIT() {
private val testClassName = "com.owncloud.android.ui.activity.FolderPickerActivityIT"
@Before
fun registerIdlingResource() {
IdlingRegistry.getInstance().register(EspressoIdlingResource.countingIdlingResource)
}
@After
fun unregisterIdlingResource() {
IdlingRegistry.getInstance().unregister(EspressoIdlingResource.countingIdlingResource)
}
@Test
@UiThread
fun getActivityFile() {
launchActivity<FolderPickerActivity>().use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
val origin = OCFile("/test/file.test").apply {
remotePath = "/remotePath/test"
}
// Act
sut.file = origin
val target = sut.file
// Assert
assertEquals(origin, target)
}
}
}
}
@Test
@UiThread
fun getParentFolder_isNotRootFolder() {
launchActivity<FolderPickerActivity>().use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
// Arrange
val origin = OCFile("/test/").apply {
fileId = 1
remotePath = "/test/"
setStoragePath("/test/")
setFolder()
}
// Act
sut.file = origin
val target = sut.currentFolder
// Assert
assertEquals(origin, target)
}
}
}
}
@Test
@UiThread
fun getParentFolder_isRootFolder() {
launchActivity<FolderPickerActivity>().use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
// Arrange
val origin = OCFile("/").apply {
fileId = 1
remotePath = "/"
setStoragePath("/")
setFolder()
}
// Act
sut.file = origin
val target = sut.currentFolder
// Assert
assertEquals(origin, target)
}
}
}
}
@Suppress("DEPRECATION")
@Test
@UiThread
fun nullFile() {
launchActivity<FolderPickerActivity>().use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
// Arrange
val rootFolder = sut.storageManager.getFileByPath(OCFile.ROOT_PATH)
// Act
sut.file = null
val target = sut.currentFolder
// Assert
assertEquals(rootFolder, target)
}
}
}
}
@Test
@UiThread
fun getParentFolder() {
launchActivity<FolderPickerActivity>().use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
// Arrange
val origin = OCFile("/test/file.test").apply {
remotePath = "/test/file.test"
}
val target = OCFile("/test/")
// Act
sut.file = origin
// Assert
assertEquals(origin, target)
}
}
}
}
@Test
@UiThread
@ScreenshotTest
fun open() {
launchActivity<FolderPickerActivity>().use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
val origin = OCFile("/test/file.txt")
sut.file = origin
sut.findViewById<View>(R.id.folder_picker_btn_copy).requestFocus()
val screenShotName = createName(testClassName + "_" + "open", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut, screenShotName)
}
}
}
}
@Test
@UiThread
@ScreenshotTest
fun testMoveOrCopy() {
val intent = Intent(targetContext, FolderPickerActivity::class.java)
launchActivity<FolderPickerActivity>(intent).use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
val screenShotName = createName(testClassName + "_" + "testMoveOrCopy", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut, screenShotName)
}
}
}
}
@Test
@UiThread
@ScreenshotTest
fun testChooseLocationAction() {
val intent = Intent(targetContext, FolderPickerActivity::class.java).apply {
putExtra(FolderPickerActivity.EXTRA_ACTION, FolderPickerActivity.CHOOSE_LOCATION)
}
launchActivity<FolderPickerActivity>(intent).use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
val screenShotName = createName(testClassName + "_" + "testChooseLocationAction", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut, screenShotName)
}
}
}
}
}

View file

@ -0,0 +1,89 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2025 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-FileCopyrightText: 2020 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.ui.activity
import androidx.annotation.UiThread
import androidx.test.core.app.launchActivity
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.IdlingRegistry
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.isRoot
import com.owncloud.android.AbstractIT
import com.owncloud.android.lib.common.Quota
import com.owncloud.android.lib.common.UserInfo
import com.owncloud.android.utils.EspressoIdlingResource
import com.owncloud.android.utils.ScreenshotTest
import org.junit.After
import org.junit.Before
import org.junit.Test
class ManageAccountsActivityIT : AbstractIT() {
private val testClassName = "com.owncloud.android.ui.activity.ManageAccountsActivityIT"
@Before
fun registerIdlingResource() {
IdlingRegistry.getInstance().register(EspressoIdlingResource.countingIdlingResource)
}
@After
fun unregisterIdlingResource() {
IdlingRegistry.getInstance().unregister(EspressoIdlingResource.countingIdlingResource)
}
@Test
@UiThread
@ScreenshotTest
fun open() {
launchActivity<ManageAccountsActivity>().use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
val screenShotName = createName(testClassName + "_" + "open", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut, screenShotName)
}
}
}
}
@Test
@UiThread
@ScreenshotTest
fun userInfoDetail() {
launchActivity<ManageAccountsActivity>().use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
EspressoIdlingResource.increment()
val user = sut.accountManager.user
val userInfo = UserInfo(
"test",
true,
"Test User",
"test@nextcloud.com",
"+49 123 456",
"Address 123, Berlin",
"https://www.nextcloud.com",
"https://twitter.com/Nextclouders",
Quota(),
ArrayList()
)
EspressoIdlingResource.decrement()
sut.showUser(user, userInfo)
val screenShotName = createName(testClassName + "_" + "open", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(getCurrentActivity(), screenShotName)
}
}
}
}
}

View file

@ -3,7 +3,7 @@
*
* SPDX-FileCopyrightText: 2020 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.ui.activity

View file

@ -1,66 +1,111 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2025 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-FileCopyrightText: 2020 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.ui.activity
import android.content.Intent
import androidx.annotation.UiThread
import androidx.test.core.app.launchActivity
import androidx.test.espresso.Espresso
import androidx.test.espresso.intent.rule.IntentsTestRule
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.IdlingRegistry
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.isRoot
import com.owncloud.android.AbstractIT
import com.owncloud.android.utils.EspressoIdlingResource
import com.owncloud.android.utils.ScreenshotTest
import org.junit.Rule
import org.junit.After
import org.junit.Before
import org.junit.Test
class PassCodeActivityIT : AbstractIT() {
@get:Rule
var activityRule = IntentsTestRule(PassCodeActivity::class.java, true, false)
private val testClassName = "com.owncloud.android.ui.activity.PassCodeActivityIT"
@Before
fun registerIdlingResource() {
IdlingRegistry.getInstance().register(EspressoIdlingResource.countingIdlingResource)
}
@After
fun unregisterIdlingResource() {
IdlingRegistry.getInstance().unregister(EspressoIdlingResource.countingIdlingResource)
}
@Test
@UiThread
@ScreenshotTest
fun check() {
val sut = activityRule.launchActivity(Intent(PassCodeActivity.ACTION_CHECK))
val intent = Intent(targetContext, PassCodeActivity::class.java).apply {
action = PassCodeActivity.ACTION_CHECK
}
waitForIdleSync()
launchActivity<PassCodeActivity>(intent).use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
EspressoIdlingResource.increment()
sut.binding.txt0.clearFocus()
Espresso.closeSoftKeyboard()
EspressoIdlingResource.decrement()
sut.runOnUiThread { sut.binding.txt0.clearFocus() }
Espresso.closeSoftKeyboard()
shortSleep()
waitForIdleSync()
screenshot(sut)
val screenShotName = createName(testClassName + "_" + "check", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut, screenShotName)
}
}
}
}
@Test
@UiThread
@ScreenshotTest
fun request() {
val sut = activityRule.launchActivity(Intent(PassCodeActivity.ACTION_REQUEST_WITH_RESULT))
val intent = Intent(targetContext, PassCodeActivity::class.java).apply {
action = PassCodeActivity.ACTION_REQUEST_WITH_RESULT
}
waitForIdleSync()
launchActivity<PassCodeActivity>(intent).use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
EspressoIdlingResource.increment()
sut.binding.txt0.clearFocus()
Espresso.closeSoftKeyboard()
EspressoIdlingResource.decrement()
sut.runOnUiThread { sut.binding.txt0.clearFocus() }
Espresso.closeSoftKeyboard()
shortSleep()
waitForIdleSync()
screenshot(sut)
val screenShotName = createName(testClassName + "_" + "request", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut, screenShotName)
}
}
}
}
@Test
@UiThread
@ScreenshotTest
fun delete() {
val sut = activityRule.launchActivity(Intent(PassCodeActivity.ACTION_CHECK_WITH_RESULT))
val intent = Intent(targetContext, PassCodeActivity::class.java).apply {
action = PassCodeActivity.ACTION_CHECK_WITH_RESULT
}
waitForIdleSync()
launchActivity<PassCodeActivity>(intent).use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
EspressoIdlingResource.increment()
sut.binding.txt0.clearFocus()
Espresso.closeSoftKeyboard()
EspressoIdlingResource.decrement()
sut.runOnUiThread { sut.binding.txt0.clearFocus() }
Espresso.closeSoftKeyboard()
shortSleep()
waitForIdleSync()
screenshot(sut)
val screenShotName = createName(testClassName + "_" + "delete", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut, screenShotName)
}
}
}
}
}

View file

@ -1,28 +1,53 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2025 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-FileCopyrightText: 2022 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2022 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.ui.activity
import android.app.Activity
import androidx.test.espresso.intent.rule.IntentsTestRule
import androidx.annotation.UiThread
import androidx.test.core.app.launchActivity
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.IdlingRegistry
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.isRoot
import com.owncloud.android.AbstractIT
import com.owncloud.android.utils.EspressoIdlingResource
import com.owncloud.android.utils.ScreenshotTest
import org.junit.Rule
import org.junit.After
import org.junit.Before
import org.junit.Test
class ReceiveExternalFilesActivityIT : AbstractIT() {
@get:Rule
val activityRule = IntentsTestRule(ReceiveExternalFilesActivity::class.java, true, false)
private val testClassName = "com.owncloud.android.ui.activity.ReceiveExternalFilesActivityIT"
@Before
fun registerIdlingResource() {
IdlingRegistry.getInstance().register(EspressoIdlingResource.countingIdlingResource)
}
@After
fun unregisterIdlingResource() {
IdlingRegistry.getInstance().unregister(EspressoIdlingResource.countingIdlingResource)
}
@Test
@UiThread
@ScreenshotTest
fun open() {
val sut: Activity = activityRule.launchActivity(null)
screenshot(sut)
launchActivity<ReceiveExternalFilesActivity>().use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
val screenShotName = createName(testClassName + "_" + "open", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut, screenShotName)
}
}
}
}
@Test

View file

@ -1,30 +1,38 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2025 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-FileCopyrightText: 2020 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.ui.activity
import android.content.Intent
import androidx.test.espresso.intent.rule.IntentsTestRule
import com.nextcloud.test.GrantStoragePermissionRule
import androidx.annotation.UiThread
import androidx.test.core.app.launchActivity
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.IdlingRegistry
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.isRoot
import com.nextcloud.test.GrantStoragePermissionRule.Companion.grant
import com.owncloud.android.AbstractIT
import com.owncloud.android.utils.EspressoIdlingResource
import com.owncloud.android.utils.FileStorageUtils
import com.owncloud.android.utils.ScreenshotTest
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TestRule
import java.io.File
class UploadFilesActivityIT : AbstractIT() {
@get:Rule
var activityRule = IntentsTestRule(UploadFilesActivity::class.java, true, false)
private val testClassName = "com.owncloud.android.ui.activity.UploadFilesActivityIT"
@get:Rule
var permissionRule = GrantStoragePermissionRule.grant()
var storagePermissionRule: TestRule = grant()
private val directories = listOf("A", "B", "C", "D")
.map { File("${FileStorageUtils.getTemporalPath(account.name)}${File.separator}$it") }
@ -39,60 +47,133 @@ class UploadFilesActivityIT : AbstractIT() {
directories.forEach { it.deleteRecursively() }
}
@Before
fun registerIdlingResource() {
IdlingRegistry.getInstance().register(EspressoIdlingResource.countingIdlingResource)
}
@After
fun unregisterIdlingResource() {
IdlingRegistry.getInstance().unregister(EspressoIdlingResource.countingIdlingResource)
}
@Test
@UiThread
@ScreenshotTest
fun noneSelected() {
val sut: UploadFilesActivity = activityRule.launchActivity(null)
launchActivity<UploadFilesActivity>().use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
EspressoIdlingResource.increment()
sut.runOnUiThread {
sut.fileListFragment.setFiles(
directories +
listOf(
File("1.txt"),
File("2.pdf"),
File("3.mp3")
sut.fileListFragment.setFiles(
directories +
listOf(
File("1.txt"),
File("2.pdf"),
File("3.mp3")
)
)
)
EspressoIdlingResource.decrement()
val screenShotName = createName(testClassName + "_" + "noneSelected", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut.fileListFragment.binding?.listRoot, screenShotName)
}
}
}
waitForIdleSync()
longSleep()
screenshot(sut.fileListFragment.binding.listRoot)
}
@Test
@UiThread
@ScreenshotTest
fun localFolderPickerMode() {
val sut: UploadFilesActivity = activityRule.launchActivity(
Intent().apply {
putExtra(
UploadFilesActivity.KEY_LOCAL_FOLDER_PICKER_MODE,
true
)
putExtra(
UploadFilesActivity.REQUEST_CODE_KEY,
FileDisplayActivity.REQUEST_CODE__SELECT_FILES_FROM_FILE_SYSTEM
)
}
)
sut.runOnUiThread {
sut.fileListFragment.setFiles(
directories
val intent = Intent(targetContext, UploadFilesActivity::class.java).apply {
putExtra(
UploadFilesActivity.KEY_LOCAL_FOLDER_PICKER_MODE,
true
)
putExtra(
UploadFilesActivity.REQUEST_CODE_KEY,
FileDisplayActivity.REQUEST_CODE__SELECT_FILES_FROM_FILE_SYSTEM
)
}
waitForIdleSync()
launchActivity<UploadFilesActivity>(intent).use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
EspressoIdlingResource.increment()
screenshot(sut)
sut.fileListFragment.setFiles(
directories
)
EspressoIdlingResource.decrement()
val screenShotName = createName(testClassName + "_" + "localFolderPickerMode", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut, screenShotName)
}
}
}
}
fun fileSelected() {
val sut: UploadFilesActivity = activityRule.launchActivity(null)
@Test
@UiThread
@ScreenshotTest
fun search() {
launchActivity<UploadFilesActivity>().use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
EspressoIdlingResource.increment()
// TODO select one
sut.fileListFragment.performSearch("1.txt", arrayListOf(), false)
sut.fileListFragment.setFiles(
directories +
listOf(
File("1.txt"),
File("2.pdf"),
File("3.mp3")
)
)
screenshot(sut)
EspressoIdlingResource.decrement()
val screenShotName = createName(testClassName + "_" + "search", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut, screenShotName)
}
}
}
}
@Test
@UiThread
@ScreenshotTest
fun selectAll() {
launchActivity<UploadFilesActivity>().use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
EspressoIdlingResource.increment()
sut.fileListFragment.setFiles(
listOf(
File("1.txt"),
File("2.pdf"),
File("3.mp3")
)
)
sut.fileListFragment.selectAllFiles(true)
EspressoIdlingResource.decrement()
val screenShotName = createName(testClassName + "_" + "selectAll", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut.fileListFragment.binding?.listRoot, screenShotName)
}
}
}
}
}

View file

@ -0,0 +1,71 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2025 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-FileCopyrightText: 2020 Andy Scherzinger <info@andy-scherzinger.de>
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.ui.activity
import android.content.Intent
import androidx.annotation.UiThread
import androidx.test.core.app.launchActivity
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.IdlingRegistry
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.isRoot
import com.owncloud.android.AbstractIT
import com.owncloud.android.lib.common.UserInfo
import com.owncloud.android.utils.EspressoIdlingResource
import com.owncloud.android.utils.ScreenshotTest
import org.junit.After
import org.junit.Before
import org.junit.Test
class UserInfoActivityIT : AbstractIT() {
private val testClassName = "com.owncloud.android.ui.activity.UserInfoActivityIT"
@Before
fun registerIdlingResource() {
IdlingRegistry.getInstance().register(EspressoIdlingResource.countingIdlingResource)
}
@After
fun unregisterIdlingResource() {
IdlingRegistry.getInstance().unregister(EspressoIdlingResource.countingIdlingResource)
}
@Test
@UiThread
@ScreenshotTest
fun fullUserInfoDetail() {
val intent = Intent(targetContext, UserInfoActivity::class.java).apply {
putExtra(UserInfoActivity.KEY_ACCOUNT, user)
val userInfo = UserInfo(
"test",
true,
"Firstname Familyname",
"oss@rocks.com",
"+49 7613 672 255",
"Awesome Place Av.",
"https://www.nextcloud.com",
"nextclouders",
null,
null
)
putExtra(UserInfoActivity.KEY_USER_DATA, userInfo)
}
launchActivity<UserInfoActivity>(intent).use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
val screenShotName = createName(testClassName + "_" + "fullUserInfoDetail", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut, screenShotName)
}
}
}
}
}

View file

@ -3,7 +3,7 @@
*
* SPDX-FileCopyrightText: 2022 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2022 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.ui.adapter

View file

@ -0,0 +1,777 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2025 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-FileCopyrightText: 2020 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.ui.dialog
import android.accounts.Account
import android.accounts.AccountManager
import android.app.Dialog
import android.content.Intent
import android.net.http.SslCertificate
import android.net.http.SslError
import android.os.Looper
import android.view.ViewGroup
import android.webkit.SslErrorHandler
import android.widget.TextView
import androidx.activity.result.contract.ActivityResultContract
import androidx.annotation.UiThread
import androidx.fragment.app.DialogFragment
import androidx.test.core.app.ActivityScenario
import androidx.test.core.app.launchActivity
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.IdlingRegistry
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.isRoot
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.nextcloud.android.common.ui.color.ColorUtil
import com.nextcloud.android.lib.resources.profile.Action
import com.nextcloud.android.lib.resources.profile.HoverCard
import com.nextcloud.client.account.RegisteredUser
import com.nextcloud.client.account.Server
import com.nextcloud.client.device.DeviceInfo
import com.nextcloud.client.documentscan.AppScanOptionalFeature
import com.nextcloud.ui.ChooseAccountDialogFragment.Companion.newInstance
import com.nextcloud.ui.SetOnlineStatusBottomSheet
import com.nextcloud.ui.fileactions.FileActionsBottomSheet.Companion.newInstance
import com.nextcloud.utils.EditorUtils
import com.owncloud.android.AbstractIT
import com.owncloud.android.MainApp
import com.owncloud.android.R
import com.owncloud.android.authentication.EnforcedServer
import com.owncloud.android.datamodel.ArbitraryDataProvider
import com.owncloud.android.datamodel.ArbitraryDataProviderImpl
import com.owncloud.android.datamodel.FileDataStorageManager
import com.owncloud.android.datamodel.OCFile
import com.owncloud.android.lib.common.Creator
import com.owncloud.android.lib.common.DirectEditing
import com.owncloud.android.lib.common.Editor
import com.owncloud.android.lib.common.OwnCloudAccount
import com.owncloud.android.lib.common.accounts.AccountTypeUtils
import com.owncloud.android.lib.common.accounts.AccountUtils
import com.owncloud.android.lib.resources.status.CapabilityBooleanType
import com.owncloud.android.lib.resources.status.OCCapability
import com.owncloud.android.lib.resources.status.OwnCloudVersion
import com.owncloud.android.lib.resources.users.Status
import com.owncloud.android.lib.resources.users.StatusType
import com.owncloud.android.ui.activity.FileDisplayActivity
import com.owncloud.android.ui.dialog.LoadingDialog.Companion.newInstance
import com.owncloud.android.ui.dialog.RenameFileDialogFragment.Companion.newInstance
import com.owncloud.android.ui.dialog.SharePasswordDialogFragment.Companion.newInstance
import com.owncloud.android.ui.dialog.SslUntrustedCertDialog.Companion.newInstanceForEmptySslError
import com.owncloud.android.ui.dialog.StoragePermissionDialogFragment.Companion.newInstance
import com.owncloud.android.ui.fragment.OCFileListBottomSheetActions
import com.owncloud.android.ui.fragment.OCFileListBottomSheetDialog
import com.owncloud.android.ui.fragment.ProfileBottomSheetDialog
import com.owncloud.android.utils.EspressoIdlingResource
import com.owncloud.android.utils.MimeTypeUtil
import com.owncloud.android.utils.ScreenshotTest
import com.owncloud.android.utils.theme.CapabilityUtils
import com.owncloud.android.utils.theme.ViewThemeUtils
import io.mockk.mockk
import org.junit.After
import org.junit.Before
import org.junit.Test
import java.net.URI
import java.util.function.Supplier
@Suppress("TooManyFunctions")
class DialogFragmentIT : AbstractIT() {
private val testClassName = "com.owncloud.android.ui.dialog.DialogFragmentIT"
private val serverUrl = "https://nextcloud.localhost"
@Before
fun registerIdlingResource() {
IdlingRegistry.getInstance().register(EspressoIdlingResource.countingIdlingResource)
}
@After
fun unregisterIdlingResource() {
IdlingRegistry.getInstance().unregister(EspressoIdlingResource.countingIdlingResource)
}
@After
fun quitLooperIfNeeded() {
Looper.myLooper()?.quitSafely()
}
@Test
@UiThread
@ScreenshotTest
fun testRenameFileDialog() {
if (Looper.myLooper() == null) {
Looper.prepare()
}
newInstance(
OCFile("/Test/"),
OCFile("/")
).run {
showDialog(this)
}
}
@Test
@UiThread
@ScreenshotTest
fun testLoadingDialog() {
newInstance("Wait…").run {
showDialog(this)
}
}
@Test
@UiThread
@ScreenshotTest
fun testConfirmationDialogWithOneAction() {
ConfirmationDialogFragment.newInstance(
R.string.upload_list_empty_text_auto_upload,
arrayOf(),
R.string.filedetails_sync_file,
R.string.common_ok,
-1,
-1,
-1
).run {
showDialog(this)
}
}
@Test
@UiThread
@ScreenshotTest
fun testConfirmationDialogWithTwoAction() {
ConfirmationDialogFragment.newInstance(
R.string.upload_list_empty_text_auto_upload,
arrayOf(),
R.string.filedetails_sync_file,
R.string.common_ok,
R.string.common_cancel,
-1,
-1
).run {
showDialog(this)
}
}
@Test
@UiThread
@ScreenshotTest
fun testConfirmationDialogWithThreeAction() {
ConfirmationDialogFragment.newInstance(
R.string.upload_list_empty_text_auto_upload,
arrayOf(),
R.string.filedetails_sync_file,
R.string.common_ok,
R.string.common_cancel,
R.string.common_confirm,
-1
).run {
showDialog(this)
}
}
@Test
@UiThread
@ScreenshotTest
fun testConfirmationDialogWithThreeActionRTL() {
enableRTL()
ConfirmationDialogFragment.newInstance(
R.string.upload_list_empty_text_auto_upload,
arrayOf(),
-1,
R.string.common_ok,
R.string.common_cancel,
R.string.common_confirm,
-1
).run {
showDialog(this)
resetLocale()
}
}
@Test
@UiThread
@ScreenshotTest
fun testRemoveFileDialog() {
RemoveFilesDialogFragment.newInstance(OCFile("/Test.md")).run {
showDialog(this)
}
}
@Test
@UiThread
@ScreenshotTest
fun testRemoveFilesDialog() {
val toDelete = ArrayList<OCFile>().apply {
add(OCFile("/Test.md"))
add(OCFile("/Document.odt"))
}
val dialog: RemoveFilesDialogFragment = RemoveFilesDialogFragment.newInstance(toDelete)
showDialog(dialog)
}
@Test
@UiThread
@ScreenshotTest
fun testRemoveFolderDialog() {
val dialog = RemoveFilesDialogFragment.newInstance(OCFile("/Folder/"))
showDialog(dialog)
}
@Test
@UiThread
@ScreenshotTest
fun testRemoveFoldersDialog() {
val toDelete = ArrayList<OCFile>()
toDelete.add(OCFile("/Folder/"))
toDelete.add(OCFile("/Documents/"))
val dialog: RemoveFilesDialogFragment = RemoveFilesDialogFragment.newInstance(toDelete)
showDialog(dialog)
}
@Test
@UiThread
@ScreenshotTest
fun testNewFolderDialog() {
if (Looper.myLooper() == null) {
Looper.prepare()
}
val sut = CreateFolderDialogFragment.newInstance(OCFile("/"))
showDialog(sut)
}
@Test
@UiThread
@ScreenshotTest
fun testEnforcedPasswordDialog() {
if (Looper.myLooper() == null) {
Looper.prepare()
}
val sut = newInstance(OCFile("/"), true, false)
showDialog(sut)
}
@Test
@UiThread
@ScreenshotTest
fun testOptionalPasswordDialog() {
if (Looper.myLooper() == null) {
Looper.prepare()
}
val sut = newInstance(OCFile("/"), true, true)
showDialog(sut)
}
@Test
@UiThread
@ScreenshotTest
fun testAccountChooserDialog() {
val intent = Intent(targetContext, FileDisplayActivity::class.java)
ActivityScenario.launch<FileDisplayActivity>(intent).use { scenario ->
scenario.onActivity { activity: FileDisplayActivity ->
EspressoIdlingResource.increment()
val userAccountManager = activity.userAccountManager
val accountManager = AccountManager.get(targetContext)
for (account in accountManager.getAccountsByType(MainApp.getAccountType(targetContext))) {
accountManager.removeAccountExplicitly(account)
}
val newAccount = Account("test@https://nextcloud.localhost", MainApp.getAccountType(targetContext))
accountManager.addAccountExplicitly(newAccount, "password", null)
accountManager.setUserData(newAccount, AccountUtils.Constants.KEY_OC_BASE_URL, serverUrl)
accountManager.setUserData(newAccount, AccountUtils.Constants.KEY_USER_ID, "test")
accountManager.setAuthToken(
newAccount,
AccountTypeUtils.getAuthTokenTypePass(newAccount.type),
"password"
)
val newUser = userAccountManager.getUser(newAccount.name)
.orElseThrow(Supplier { RuntimeException() })
userAccountManager.setCurrentOwnCloudAccount(newAccount.name)
val newAccount2 = Account("user1@nextcloud.localhost", MainApp.getAccountType(targetContext))
accountManager.addAccountExplicitly(newAccount2, "password", null)
accountManager.setUserData(newAccount2, AccountUtils.Constants.KEY_OC_BASE_URL, serverUrl)
accountManager.setUserData(newAccount2, AccountUtils.Constants.KEY_USER_ID, "user1")
accountManager.setUserData(newAccount2, AccountUtils.Constants.KEY_OC_VERSION, "20.0.0")
accountManager.setAuthToken(
newAccount2,
AccountTypeUtils.getAuthTokenTypePass(newAccount.type),
"password"
)
val fileDataStorageManager = FileDataStorageManager(
newUser,
targetContext.contentResolver
)
val capability = OCCapability().apply {
userStatus = CapabilityBooleanType.TRUE
userStatusSupportsEmoji = CapabilityBooleanType.TRUE
}
fileDataStorageManager.saveCapabilities(capability)
EspressoIdlingResource.decrement()
try {
onIdleSync {
val sut = newInstance(
RegisteredUser(
newAccount,
OwnCloudAccount(newAccount, targetContext),
Server(URI.create(serverUrl), OwnCloudVersion.nextcloud_20)
)
)
showDialog(activity, sut)
sut.setStatus(
Status(
StatusType.DND,
"Busy fixing 🐛…",
"",
-1
),
targetContext
)
screenshot(sut, "dnd")
sut.setStatus(
Status(
StatusType.ONLINE,
"",
"",
-1
),
targetContext
)
screenshot(sut, "online")
sut.setStatus(
Status(
StatusType.ONLINE,
"Let's have some fun",
"🎉",
-1
),
targetContext
)
screenshot(sut, "fun")
sut.setStatus(
Status(StatusType.OFFLINE, "", "", -1),
targetContext
)
screenshot(sut, "offline")
sut.setStatus(
Status(StatusType.AWAY, "Vacation", "🌴", -1),
targetContext
)
screenshot(sut, "away")
}
} catch (e: AccountUtils.AccountNotFoundException) {
throw java.lang.RuntimeException(e)
}
}
}
}
@Test
@UiThread
@ScreenshotTest
@Throws(AccountUtils.AccountNotFoundException::class)
fun testAccountChooserDialogWithStatusDisabled() {
val accountManager = AccountManager.get(targetContext)
for (account in accountManager.accounts) {
accountManager.removeAccountExplicitly(account)
}
val newAccount = Account("test@https://nextcloud.localhost", MainApp.getAccountType(targetContext))
accountManager.addAccountExplicitly(newAccount, "password", null)
accountManager.setUserData(newAccount, AccountUtils.Constants.KEY_OC_BASE_URL, serverUrl)
accountManager.setUserData(newAccount, AccountUtils.Constants.KEY_USER_ID, "test")
accountManager.setAuthToken(newAccount, AccountTypeUtils.getAuthTokenTypePass(newAccount.type), "password")
launchActivity<FileDisplayActivity>().use { scenario ->
scenario.onActivity { fda ->
onIdleSync {
EspressoIdlingResource.increment()
val userAccountManager = fda.userAccountManager
val newUser = userAccountManager.getUser(newAccount.name).get()
val fileDataStorageManager = FileDataStorageManager(
newUser,
targetContext.contentResolver
)
val capability = OCCapability().apply {
userStatus = CapabilityBooleanType.FALSE
}
fileDataStorageManager.saveCapabilities(capability)
EspressoIdlingResource.decrement()
val sut =
newInstance(
RegisteredUser(
newAccount,
OwnCloudAccount(newAccount, targetContext),
Server(
URI.create(serverUrl),
OwnCloudVersion.nextcloud_20
)
)
)
onView(isRoot()).check(matches(isDisplayed()))
showDialog(fda, sut)
}
}
}
}
@Test
@UiThread
@ScreenshotTest
fun testBottomSheet() {
if (Looper.myLooper() == null) {
Looper.prepare()
}
val action: OCFileListBottomSheetActions = object : OCFileListBottomSheetActions {
override fun createFolder() = Unit
override fun uploadFromApp() = Unit
override fun uploadFiles() = Unit
override fun newDocument() = Unit
override fun newSpreadsheet() = Unit
override fun newPresentation() = Unit
override fun directCameraUpload() = Unit
override fun scanDocUpload() = Unit
override fun showTemplate(creator: Creator?, headline: String?) = Unit
override fun createRichWorkspace() = Unit
}
val info = DeviceInfo()
val ocFile = OCFile("/test.md").apply {
remoteId = "00000001"
}
val intent = Intent(targetContext, FileDisplayActivity::class.java)
launchActivity<FileDisplayActivity>(intent).use { scenario ->
scenario.onActivity { fda ->
onIdleSync {
EspressoIdlingResource.increment()
// add direct editing info
var directEditing = DirectEditing()
val creators = directEditing.creators.toMutableMap()
val editors = directEditing.editors.toMutableMap()
creators.put(
"1",
Creator(
"1",
"text",
"text file",
".md",
"application/octet-stream",
false
)
)
creators.put(
"2",
Creator(
"2",
"md",
"markdown file",
".md",
"application/octet-stream",
false
)
)
editors.put(
"text",
Editor(
"1",
"Text",
ArrayList(mutableListOf(MimeTypeUtil.MIMETYPE_TEXT_MARKDOWN)),
ArrayList(),
false
)
)
directEditing = DirectEditing(editors, creators)
val json = Gson().toJson(directEditing)
ArbitraryDataProviderImpl(targetContext).storeOrUpdateKeyValue(
user.accountName,
ArbitraryDataProvider.DIRECT_EDITING,
json
)
// activate templates
val capability = fda.capabilities.apply {
richDocuments = CapabilityBooleanType.TRUE
richDocumentsDirectEditing = CapabilityBooleanType.TRUE
richDocumentsTemplatesAvailable = CapabilityBooleanType.TRUE
accountName = user.accountName
}
CapabilityUtils.updateCapability(capability)
val appScanOptionalFeature: AppScanOptionalFeature = object : AppScanOptionalFeature() {
override fun getScanContract(): ActivityResultContract<Unit, String?> =
throw UnsupportedOperationException("Document scan is not available")
}
val materialSchemesProvider = getMaterialSchemesProvider()
val viewThemeUtils = ViewThemeUtils(
materialSchemesProvider.getMaterialSchemesForCurrentUser(),
ColorUtil(targetContext)
)
val editorUtils = EditorUtils(ArbitraryDataProviderImpl(targetContext))
val sut = OCFileListBottomSheetDialog(
fda,
action,
info,
user,
ocFile,
fda.themeUtils,
viewThemeUtils,
editorUtils,
appScanOptionalFeature
)
EspressoIdlingResource.decrement()
sut.show()
sut.behavior.setState(BottomSheetBehavior.STATE_EXPANDED)
val viewGroup = sut.window?.findViewById<ViewGroup>(android.R.id.content) ?: return@onIdleSync
hideCursors(viewGroup)
val screenShotName = createName(testClassName + "_" + "testBottomSheet", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut.window?.decorView, screenShotName)
}
}
}
}
@Test
@UiThread
@ScreenshotTest
fun testOnlineStatusBottomSheet() {
if (Looper.myLooper() == null) {
Looper.prepare()
}
// show dialog
val intent = Intent(targetContext, FileDisplayActivity::class.java)
launchActivity<FileDisplayActivity>(intent).use { scenario ->
scenario.onActivity { fda ->
onIdleSync {
EspressoIdlingResource.increment()
val sut = SetOnlineStatusBottomSheet(
Status(StatusType.DND, "Focus time", "\uD83E\uDD13", -1)
)
EspressoIdlingResource.decrement()
sut.show(fda.supportFragmentManager, "set_online_status")
val screenShotName = createName(testClassName + "_" + "testOnlineStatusBottomSheet", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut.view, screenShotName)
}
}
}
}
@Test
@UiThread
@ScreenshotTest
fun testProfileBottomSheet() {
if (Looper.myLooper() == null) {
Looper.prepare()
}
// Fixed values for HoverCard
val actions: MutableList<Action> = ArrayList()
actions.add(
Action(
"profile",
"View profile",
"https://dev.nextcloud.com/core/img/actions/profile.svg",
"https://dev.nextcloud.com/index.php/u/christine"
)
)
actions.add(
Action(
"core",
"christine.scott@nextcloud.com",
"https://dev.nextcloud.com/core/img/actions/mail.svg",
"mailto:christine.scott@nextcloud.com"
)
)
actions.add(
Action(
"spreed",
"Talk to Christine",
"https://dev.nextcloud.com/apps/spreed/img/app-dark.svg",
"https://dev.nextcloud.com/apps/spreed/?callUser=christine"
)
)
val hoverCard = HoverCard("christine", "Christine Scott", actions)
// show dialog
val intent = Intent(targetContext, FileDisplayActivity::class.java)
launchActivity<FileDisplayActivity>(intent).use { scenario ->
scenario.onActivity { fda ->
onIdleSync {
EspressoIdlingResource.increment()
val sut = ProfileBottomSheetDialog(
fda,
user,
hoverCard,
fda.viewThemeUtils
)
EspressoIdlingResource.decrement()
sut.show()
val screenShotName = createName(testClassName + "_" + "testProfileBottomSheet", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut.window?.decorView, screenShotName)
}
}
}
}
@Test
@UiThread
@ScreenshotTest
fun testSslUntrustedCertDialog() {
if (Looper.myLooper() == null) {
Looper.prepare()
}
val certificate = SslCertificate("foo", "bar", "2022/01/10", "2022/01/30")
val sslError = SslError(SslError.SSL_UNTRUSTED, certificate)
val handler = mockk<SslErrorHandler>(relaxed = true)
newInstanceForEmptySslError(sslError, handler).run {
showDialog(this)
}
}
@Test
@UiThread
@ScreenshotTest
fun testStoragePermissionDialog() {
if (Looper.myLooper() == null) {
Looper.prepare()
}
newInstance(false).run {
showDialog(this)
}
}
@Test
@UiThread
@ScreenshotTest
fun testFileActionsBottomSheet() {
if (Looper.myLooper() == null) {
Looper.prepare()
}
val ocFile = OCFile("/test.md").apply {
remoteId = "0001"
}
newInstance(ocFile, false).run {
showDialog(this)
}
}
private fun showDialog(dialog: DialogFragment) {
launchActivity<FileDisplayActivity>().use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
onView(isRoot()).check(matches(isDisplayed()))
showDialog(sut, dialog)
}
}
}
}
private fun showDialog(sut: FileDisplayActivity, dialog: DialogFragment) {
dialog.show(sut.supportFragmentManager, null)
onIdleSync {
val dialogInstance = waitForDialog(dialog)
?: throw IllegalStateException("Dialog was not created")
val viewGroup = dialogInstance.window?.findViewById<ViewGroup>(android.R.id.content) ?: return@onIdleSync
hideCursors(viewGroup)
onView(isRoot()).check(matches(isDisplayed()))
screenshot(dialogInstance.window?.decorView)
}
}
private fun waitForDialog(dialogFragment: DialogFragment, timeoutMs: Long = 5000): Dialog? {
val start = System.currentTimeMillis()
while (System.currentTimeMillis() - start < timeoutMs) {
val dialog = dialogFragment.dialog
if (dialog != null) return dialog
Thread.sleep(100)
}
return null
}
private fun hideCursors(viewGroup: ViewGroup) {
for (i in 0..<viewGroup.childCount) {
val child = viewGroup.getChildAt(i)
if (child is ViewGroup) {
hideCursors(child)
}
if (child is TextView) {
child.isCursorVisible = false
}
}
}
@Test
fun testGson() {
val t = ArrayList<EnforcedServer?>().apply {
add(EnforcedServer("name", "url"))
add(EnforcedServer("name2", "url1"))
}
val s = Gson().toJson(t)
val t2 = Gson().fromJson<ArrayList<EnforcedServer>>(
s,
object : TypeToken<ArrayList<EnforcedServer?>?>() {
}.type
)
val temp = ArrayList<String?>()
for (p in t2) {
temp.add(p.name)
}
}
}

View file

@ -1,26 +1,36 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2025 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-FileCopyrightText: 2020 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.ui.dialog
import androidx.annotation.UiThread
import androidx.fragment.app.FragmentManager
import androidx.recyclerview.widget.RecyclerView
import androidx.test.espresso.intent.rule.IntentsTestRule
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.core.app.launchActivity
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.IdlingRegistry
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.isRoot
import com.nextcloud.test.TestActivity
import com.owncloud.android.AbstractIT
import com.owncloud.android.R
import com.owncloud.android.datamodel.OCFile
import com.owncloud.android.utils.EspressoIdlingResource
import com.owncloud.android.utils.ScreenshotTest
import org.junit.After
import org.junit.Assert
import org.junit.Rule
import org.junit.Before
import org.junit.Test
class SendFilesDialogTest : AbstractIT() {
private val testClassName = "com.owncloud.android.ui.dialog.SendFilesDialogTest"
companion object {
private val FILES_SAME_TYPE = setOf(
OCFile("/1.jpg").apply {
@ -43,52 +53,77 @@ class SendFilesDialogTest : AbstractIT() {
)
}
@get:Rule
val testActivityRule = IntentsTestRule(TestActivity::class.java, true, false)
@Before
fun registerIdlingResource() {
IdlingRegistry.getInstance().register(EspressoIdlingResource.countingIdlingResource)
}
private fun showDialog(files: Set<OCFile>): SendFilesDialog {
val activity = testActivityRule.launchActivity(null)
@After
fun unregisterIdlingResource() {
IdlingRegistry.getInstance().unregister(EspressoIdlingResource.countingIdlingResource)
}
val fm: FragmentManager = activity.supportFragmentManager
val ft = fm.beginTransaction()
ft.addToBackStack(null)
private fun showDialog(files: Set<OCFile>, onComplete: (SendFilesDialog) -> Unit) {
launchActivity<TestActivity>().use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
EspressoIdlingResource.increment()
val sut = SendFilesDialog.newInstance(files)
sut.show(ft, "TAG_SEND_SHARE_DIALOG")
val fm: FragmentManager = sut.supportFragmentManager
val ft = fm.beginTransaction()
ft.addToBackStack(null)
InstrumentationRegistry.getInstrumentation().waitForIdleSync()
shortSleep()
val dialog = SendFilesDialog.newInstance(files)
dialog.show(ft, "TAG_SEND_SHARE_DIALOG")
onComplete(dialog)
return sut
EspressoIdlingResource.decrement()
}
}
}
}
@Test
@UiThread
@ScreenshotTest
fun showDialog() {
val sut = showDialog(FILES_SAME_TYPE)
val recyclerview: RecyclerView = sut.requireDialog().findViewById(R.id.send_button_recycler_view)
Assert.assertNotNull("Adapter is null", recyclerview.adapter)
Assert.assertNotEquals("Send button list is empty", 0, recyclerview.adapter!!.itemCount)
showDialog(FILES_SAME_TYPE) { sut ->
val recyclerview: RecyclerView = sut.requireDialog().findViewById(R.id.send_button_recycler_view)
Assert.assertNotNull("Adapter is null", recyclerview.adapter)
Assert.assertNotEquals("Send button list is empty", 0, recyclerview.adapter!!.itemCount)
}
}
@Test
@UiThread
@ScreenshotTest
fun showDialog_Screenshot() {
val sut = showDialog(FILES_SAME_TYPE)
sut.requireDialog().window?.decorView.let { screenshot(it) }
showDialog(FILES_SAME_TYPE) { sut ->
val screenShotName = createName(testClassName + "_" + "showDialog_Screenshot", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut.requireDialog().window?.decorView, screenShotName)
}
}
@Test
@UiThread
@ScreenshotTest
fun showDialogDifferentTypes() {
val sut = showDialog(FILES_MIXED_TYPE)
val recyclerview: RecyclerView = sut.requireDialog().findViewById(R.id.send_button_recycler_view)
Assert.assertNotNull("Adapter is null", recyclerview.adapter)
Assert.assertNotEquals("Send button list is empty", 0, recyclerview.adapter!!.itemCount)
showDialog(FILES_MIXED_TYPE) { sut ->
val recyclerview: RecyclerView = sut.requireDialog().findViewById(R.id.send_button_recycler_view)
Assert.assertNotNull("Adapter is null", recyclerview.adapter)
Assert.assertNotEquals("Send button list is empty", 0, recyclerview.adapter!!.itemCount)
}
}
@Test
@UiThread
@ScreenshotTest
fun showDialogDifferentTypes_Screenshot() {
val sut = showDialog(FILES_MIXED_TYPE)
sut.requireDialog().window?.decorView.let { screenshot(it) }
showDialog(FILES_MIXED_TYPE) { sut ->
val screenShotName = createName(testClassName + "_" + "showDialogDifferentTypes_Screenshot", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut.requireDialog().window?.decorView, screenShotName)
}
}
}

View file

@ -1,46 +1,55 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2025 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-FileCopyrightText: 2020 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.ui.dialog
import androidx.annotation.UiThread
import androidx.fragment.app.FragmentManager
import androidx.test.espresso.intent.rule.IntentsTestRule
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.core.app.launchActivity
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.isRoot
import com.nextcloud.test.TestActivity
import com.owncloud.android.AbstractIT
import com.owncloud.android.datamodel.OCFile
import com.owncloud.android.lib.resources.status.OCCapability
import com.owncloud.android.utils.EspressoIdlingResource
import com.owncloud.android.utils.ScreenshotTest
import org.junit.Rule
import org.junit.Test
class SendShareDialogTest : AbstractIT() {
@get:Rule
val testActivityRule = IntentsTestRule(TestActivity::class.java, true, false)
private val testClassName = "com.owncloud.android.ui.dialog.SendShareDialogTest"
@Test
@UiThread
@ScreenshotTest
fun showDialog() {
val activity = testActivityRule.launchActivity(null)
launchActivity<TestActivity>().use { scenario ->
scenario.onActivity { activity ->
onIdleSync {
EspressoIdlingResource.increment()
val fm: FragmentManager = activity.supportFragmentManager
val ft = fm.beginTransaction()
ft.addToBackStack(null)
val fm: FragmentManager = activity.supportFragmentManager
val ft = fm.beginTransaction()
ft.addToBackStack(null)
val file = OCFile("/1.jpg").apply {
mimeType = "image/jpg"
}
EspressoIdlingResource.decrement()
val file = OCFile("/1.jpg").apply {
mimeType = "image/jpg"
val sut = SendShareDialog.newInstance(file, false, OCCapability())
sut.show(ft, "TAG_SEND_SHARE_DIALOG")
val screenShotName = createName(testClassName + "_" + "showDialog", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut.requireDialog().window?.decorView, screenShotName)
}
}
}
val sut = SendShareDialog.newInstance(file, false, OCCapability())
sut.show(ft, "TAG_SEND_SHARE_DIALOG")
InstrumentationRegistry.getInstrumentation().waitForIdleSync()
shortSleep()
shortSleep()
sut.requireDialog().window?.decorView.let { screenshot(it) }
}
}

View file

@ -1,79 +1,101 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2025 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-FileCopyrightText: 2020 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.ui.dialog
import androidx.test.espresso.intent.rule.IntentsTestRule
import androidx.test.internal.runner.junit4.statement.UiThreadStatement.runOnUiThread
import androidx.annotation.UiThread
import androidx.test.core.app.launchActivity
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.IdlingRegistry
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.isRoot
import com.nextcloud.test.TestActivity
import com.owncloud.android.AbstractIT
import com.owncloud.android.ui.dialog.setupEncryption.SetupEncryptionDialogFragment
import com.owncloud.android.utils.EspressoIdlingResource
import com.owncloud.android.utils.ScreenshotTest
import org.junit.Rule
import org.junit.After
import org.junit.Before
import org.junit.Test
class SetupEncryptionDialogFragmentIT : AbstractIT() {
@get:Rule
val testActivityRule = IntentsTestRule(TestActivity::class.java, true, false)
private val testClassName = "com.owncloud.android.ui.dialog.SetupEncryptionDialogFragmentIT"
@Before
fun registerIdlingResource() {
IdlingRegistry.getInstance().register(EspressoIdlingResource.countingIdlingResource)
}
@After
fun unregisterIdlingResource() {
IdlingRegistry.getInstance().unregister(EspressoIdlingResource.countingIdlingResource)
}
@Test
@UiThread
@ScreenshotTest
fun showMnemonic() {
val activity = testActivityRule.launchActivity(null)
launchActivity<TestActivity>().use { scenario ->
scenario.onActivity { activity ->
onIdleSync {
EspressoIdlingResource.increment()
val sut = SetupEncryptionDialogFragment.newInstance(user, 0)
val sut = SetupEncryptionDialogFragment.newInstance(user, 0)
sut.show(activity.supportFragmentManager, "1")
sut.show(activity.supportFragmentManager, "1")
val keyWords = arrayListOf(
"ability",
"able",
"about",
"above",
"absent",
"absorb",
"abstract",
"absurd",
"abuse",
"access",
"accident",
"account",
"accuse"
)
sut.setMnemonic(keyWords)
sut.showMnemonicInfo()
EspressoIdlingResource.decrement()
val keyWords = arrayListOf(
"ability",
"able",
"about",
"above",
"absent",
"absorb",
"abstract",
"absurd",
"abuse",
"access",
"accident",
"account",
"accuse"
)
shortSleep()
runOnUiThread {
sut.setMnemonic(keyWords)
sut.showMnemonicInfo()
val screenShotName = createName(testClassName + "_" + "showMnemonic", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut.requireDialog().window?.decorView, screenShotName)
}
}
}
waitForIdleSync()
screenshot(sut.requireDialog().window!!.decorView)
}
@Test
@UiThread
@ScreenshotTest
fun error() {
val activity = testActivityRule.launchActivity(null)
launchActivity<TestActivity>().use { scenario ->
scenario.onActivity { activity ->
onIdleSync {
EspressoIdlingResource.increment()
val sut = SetupEncryptionDialogFragment.newInstance(user, 0)
val sut = SetupEncryptionDialogFragment.newInstance(user, 0)
sut.show(activity.supportFragmentManager, "1")
sut.errorSavingKeys()
sut.show(activity.supportFragmentManager, "1")
EspressoIdlingResource.decrement()
shortSleep()
runOnUiThread {
sut.errorSavingKeys()
val screenShotName = createName(testClassName + "_" + "error", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut.requireDialog().window?.decorView, screenShotName)
}
}
}
shortSleep()
waitForIdleSync()
screenshot(sut.requireDialog().window!!.decorView)
}
}

View file

@ -0,0 +1,89 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2024 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
package com.owncloud.android.ui.dialog
import androidx.annotation.UiThread
import androidx.test.core.app.launchActivity
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.IdlingRegistry
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.isRoot
import com.owncloud.android.AbstractIT
import com.owncloud.android.datamodel.OCFile
import com.owncloud.android.ui.activity.FileDisplayActivity
import com.owncloud.android.ui.dialog.SyncFileNotEnoughSpaceDialogFragment.Companion.newInstance
import com.owncloud.android.utils.EspressoIdlingResource
import com.owncloud.android.utils.ScreenshotTest
import org.junit.After
import org.junit.Before
import org.junit.Test
class SyncFileNotEnoughSpaceDialogFragmentTest : AbstractIT() {
private val testClassName = "com.owncloud.android.ui.dialog.SyncFileNotEnoughSpaceDialogFragmentTest"
@Before
fun registerIdlingResource() {
IdlingRegistry.getInstance().register(EspressoIdlingResource.countingIdlingResource)
}
@After
fun unregisterIdlingResource() {
IdlingRegistry.getInstance().unregister(EspressoIdlingResource.countingIdlingResource)
}
@Test
@ScreenshotTest
@UiThread
fun showNotEnoughSpaceDialogForFolder() {
launchActivity<FileDisplayActivity>().use { scenario ->
scenario.onActivity { sut ->
val ocFile = OCFile("/Document/").apply {
fileLength = 5000000
setFolder()
}
onIdleSync {
EspressoIdlingResource.increment()
newInstance(ocFile, 1000).apply {
show(sut.supportFragmentManager, "1")
}
EspressoIdlingResource.decrement()
val screenShotName = createName(testClassName + "_" + "showNotEnoughSpaceDialogForFolder", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut, screenShotName)
}
}
}
}
@Test
@ScreenshotTest
@UiThread
fun showNotEnoughSpaceDialogForFile() {
launchActivity<FileDisplayActivity>().use { scenario ->
scenario.onActivity { sut ->
val ocFile = OCFile("/Video.mp4").apply {
fileLength = 1000000
}
onIdleSync {
EspressoIdlingResource.increment()
newInstance(ocFile, 2000).apply {
show(sut.supportFragmentManager, "2")
}
EspressoIdlingResource.decrement()
val screenShotName = createName(testClassName + "_" + "showNotEnoughSpaceDialogForFile", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut, screenShotName)
}
}
}
}
}

View file

@ -1,15 +1,21 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2025 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-FileCopyrightText: 2020 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.ui.fragment
import android.graphics.BitmapFactory
import androidx.test.espresso.intent.rule.IntentsTestRule
import androidx.test.internal.runner.junit4.statement.UiThreadStatement.runOnUiThread
import androidx.annotation.UiThread
import androidx.test.core.app.launchActivity
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.IdlingRegistry
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.isRoot
import com.nextcloud.test.TestActivity
import com.owncloud.android.AbstractIT
import com.owncloud.android.R
@ -17,155 +23,171 @@ import com.owncloud.android.lib.resources.users.StatusType
import com.owncloud.android.ui.TextDrawable
import com.owncloud.android.utils.BitmapUtils
import com.owncloud.android.utils.DisplayUtils
import com.owncloud.android.utils.EspressoIdlingResource
import com.owncloud.android.utils.ScreenshotTest
import org.junit.Rule
import org.junit.After
import org.junit.Before
import org.junit.Test
class AvatarIT : AbstractIT() {
@get:Rule
val testActivityRule = IntentsTestRule(TestActivity::class.java, true, false)
private val testClassName = "com.owncloud.android.ui.fragment.AvatarIT"
@Before
fun registerIdlingResource() {
IdlingRegistry.getInstance().register(EspressoIdlingResource.countingIdlingResource)
}
@After
fun unregisterIdlingResource() {
IdlingRegistry.getInstance().unregister(EspressoIdlingResource.countingIdlingResource)
}
@Test
@UiThread
@ScreenshotTest
fun showAvatars() {
val avatarRadius = targetContext.resources.getDimension(R.dimen.list_item_avatar_icon_radius)
val width = DisplayUtils.convertDpToPixel(2 * avatarRadius, targetContext)
val sut = testActivityRule.launchActivity(null)
val fragment = AvatarTestFragment()
launchActivity<TestActivity>().use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
EspressoIdlingResource.increment()
sut.addFragment(fragment)
val avatarRadius = targetContext.resources.getDimension(R.dimen.list_item_avatar_icon_radius)
val width = DisplayUtils.convertDpToPixel(2 * avatarRadius, targetContext)
val fragment = AvatarTestFragment()
runOnUiThread {
fragment.addAvatar("Admin", avatarRadius, width, targetContext)
fragment.addAvatar("Test Server Admin", avatarRadius, width, targetContext)
fragment.addAvatar("Cormier Paulette", avatarRadius, width, targetContext)
fragment.addAvatar("winston brent", avatarRadius, width, targetContext)
fragment.addAvatar("Baker James Lorena", avatarRadius, width, targetContext)
fragment.addAvatar("Baker James Lorena", avatarRadius, width, targetContext)
fragment.addAvatar("email@nextcloud.localhost", avatarRadius, width, targetContext)
sut.addFragment(fragment)
fragment.run {
addAvatar("Admin", avatarRadius, width, targetContext)
addAvatar("Test Server Admin", avatarRadius, width, targetContext)
addAvatar("Cormier Paulette", avatarRadius, width, targetContext)
addAvatar("winston brent", avatarRadius, width, targetContext)
addAvatar("Baker James Lorena", avatarRadius, width, targetContext)
addAvatar("Baker James Lorena", avatarRadius, width, targetContext)
addAvatar("email@nextcloud.localhost", avatarRadius, width, targetContext)
}
EspressoIdlingResource.decrement()
val screenShotName = createName(testClassName + "_" + "showAvatars", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut, screenShotName)
}
}
}
shortSleep()
waitForIdleSync()
screenshot(sut)
}
@Test
@UiThread
@ScreenshotTest
fun showAvatarsWithStatus() {
val avatarRadius = targetContext.resources.getDimension(R.dimen.list_item_avatar_icon_radius)
val width = DisplayUtils.convertDpToPixel(2 * avatarRadius, targetContext)
val sut = testActivityRule.launchActivity(null)
val fragment = AvatarTestFragment()
launchActivity<TestActivity>().use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
EspressoIdlingResource.increment()
val paulette = BitmapFactory.decodeFile(getFile("paulette.jpg").absolutePath)
val christine = BitmapFactory.decodeFile(getFile("christine.jpg").absolutePath)
val textBitmap = BitmapUtils.drawableToBitmap(TextDrawable.createNamedAvatar("Admin", avatarRadius))
val avatarRadius = targetContext.resources.getDimension(R.dimen.list_item_avatar_icon_radius)
val width = DisplayUtils.convertDpToPixel(2 * avatarRadius, targetContext)
val fragment = AvatarTestFragment()
sut.addFragment(fragment)
val paulette = BitmapFactory.decodeFile(getFile("paulette.jpg").absolutePath)
val christine = BitmapFactory.decodeFile(getFile("christine.jpg").absolutePath)
val textBitmap = BitmapUtils.drawableToBitmap(TextDrawable.createNamedAvatar("Admin", avatarRadius))
runOnUiThread {
fragment.addBitmap(
BitmapUtils.createAvatarWithStatus(paulette, StatusType.ONLINE, "😘", targetContext),
width * 2,
1,
targetContext
)
sut.addFragment(fragment)
fragment.addBitmap(
BitmapUtils.createAvatarWithStatus(christine, StatusType.ONLINE, "☁️", targetContext),
width * 2,
1,
targetContext
)
fragment.run {
addBitmap(
BitmapUtils.createAvatarWithStatus(paulette, StatusType.ONLINE, "😘", targetContext),
width * 2,
1,
targetContext
)
addBitmap(
BitmapUtils.createAvatarWithStatus(christine, StatusType.ONLINE, "☁️", targetContext),
width * 2,
1,
targetContext
)
addBitmap(
BitmapUtils.createAvatarWithStatus(christine, StatusType.ONLINE, "🌴️", targetContext),
width * 2,
1,
targetContext
)
addBitmap(
BitmapUtils.createAvatarWithStatus(christine, StatusType.ONLINE, "", targetContext),
width * 2,
1,
targetContext
)
addBitmap(
BitmapUtils.createAvatarWithStatus(paulette, StatusType.DND, "", targetContext),
width * 2,
1,
targetContext
)
addBitmap(
BitmapUtils.createAvatarWithStatus(christine, StatusType.AWAY, "", targetContext),
width * 2,
1,
targetContext
)
addBitmap(
BitmapUtils.createAvatarWithStatus(paulette, StatusType.OFFLINE, "", targetContext),
width * 2,
1,
targetContext
)
addBitmap(
BitmapUtils.createAvatarWithStatus(textBitmap, StatusType.ONLINE, "😘", targetContext),
width,
2,
targetContext
)
addBitmap(
BitmapUtils.createAvatarWithStatus(textBitmap, StatusType.ONLINE, "☁️", targetContext),
width,
2,
targetContext
)
addBitmap(
BitmapUtils.createAvatarWithStatus(textBitmap, StatusType.ONLINE, "🌴️", targetContext),
width,
2,
targetContext
)
addBitmap(
BitmapUtils.createAvatarWithStatus(textBitmap, StatusType.ONLINE, "", targetContext),
width,
2,
targetContext
)
addBitmap(
BitmapUtils.createAvatarWithStatus(textBitmap, StatusType.DND, "", targetContext),
width,
2,
targetContext
)
addBitmap(
BitmapUtils.createAvatarWithStatus(textBitmap, StatusType.AWAY, "", targetContext),
width,
2,
targetContext
)
addBitmap(
BitmapUtils.createAvatarWithStatus(textBitmap, StatusType.OFFLINE, "", targetContext),
width,
2,
targetContext
)
}
EspressoIdlingResource.decrement()
fragment.addBitmap(
BitmapUtils.createAvatarWithStatus(christine, StatusType.ONLINE, "🌴️", targetContext),
width * 2,
1,
targetContext
)
fragment.addBitmap(
BitmapUtils.createAvatarWithStatus(christine, StatusType.ONLINE, "", targetContext),
width * 2,
1,
targetContext
)
fragment.addBitmap(
BitmapUtils.createAvatarWithStatus(paulette, StatusType.DND, "", targetContext),
width * 2,
1,
targetContext
)
fragment.addBitmap(
BitmapUtils.createAvatarWithStatus(christine, StatusType.AWAY, "", targetContext),
width * 2,
1,
targetContext
)
fragment.addBitmap(
BitmapUtils.createAvatarWithStatus(paulette, StatusType.OFFLINE, "", targetContext),
width * 2,
1,
targetContext
)
fragment.addBitmap(
BitmapUtils.createAvatarWithStatus(textBitmap, StatusType.ONLINE, "😘", targetContext),
width,
2,
targetContext
)
fragment.addBitmap(
BitmapUtils.createAvatarWithStatus(textBitmap, StatusType.ONLINE, "☁️", targetContext),
width,
2,
targetContext
)
fragment.addBitmap(
BitmapUtils.createAvatarWithStatus(textBitmap, StatusType.ONLINE, "🌴️", targetContext),
width,
2,
targetContext
)
fragment.addBitmap(
BitmapUtils.createAvatarWithStatus(textBitmap, StatusType.ONLINE, "", targetContext),
width,
2,
targetContext
)
fragment.addBitmap(
BitmapUtils.createAvatarWithStatus(textBitmap, StatusType.DND, "", targetContext),
width,
2,
targetContext
)
fragment.addBitmap(
BitmapUtils.createAvatarWithStatus(textBitmap, StatusType.AWAY, "", targetContext),
width,
2,
targetContext
)
fragment.addBitmap(
BitmapUtils.createAvatarWithStatus(textBitmap, StatusType.OFFLINE, "", targetContext),
width,
2,
targetContext
)
val screenShotName = createName(testClassName + "_" + "showAvatarsWithStatus", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut, screenShotName)
}
}
}
shortSleep()
waitForIdleSync()
screenshot(sut)
}
}

View file

@ -3,7 +3,7 @@
*
* SPDX-FileCopyrightText: 2020 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.ui.fragment
@ -21,8 +21,8 @@ import com.owncloud.android.R
import com.owncloud.android.ui.TextDrawable
internal class AvatarTestFragment : Fragment() {
lateinit var list1: LinearLayout
lateinit var list2: LinearLayout
private lateinit var list1: LinearLayout
private lateinit var list2: LinearLayout
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view: View = inflater.inflate(R.layout.avatar_fragment, null)
@ -34,7 +34,7 @@ internal class AvatarTestFragment : Fragment() {
}
fun addAvatar(name: String, avatarRadius: Float, width: Int, targetContext: Context) {
val margin = padding
val margin = PADDING
val imageView = ImageView(targetContext)
imageView.setImageDrawable(TextDrawable.createNamedAvatar(name, avatarRadius))
@ -47,7 +47,7 @@ internal class AvatarTestFragment : Fragment() {
}
fun addBitmap(bitmap: Bitmap, width: Int, list: Int, targetContext: Context) {
val margin = padding
val margin = PADDING
val imageView = ImageView(targetContext)
imageView.setImageBitmap(bitmap)
@ -64,6 +64,6 @@ internal class AvatarTestFragment : Fragment() {
}
companion object {
private const val padding = 10
private const val PADDING = 10
}
}

View file

@ -2,99 +2,159 @@
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2021 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.ui.fragment
import android.Manifest
import androidx.test.espresso.intent.rule.IntentsTestRule
import androidx.test.core.app.launchActivity
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.IdlingRegistry
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.isRoot
import androidx.test.rule.GrantPermissionRule
import com.owncloud.android.AbstractIT
import com.owncloud.android.R
import com.owncloud.android.datamodel.OCFile
import com.owncloud.android.ui.activity.ContactsPreferenceActivity
import com.owncloud.android.ui.fragment.contactsbackup.BackupListFragment
import com.owncloud.android.utils.EspressoIdlingResource
import com.owncloud.android.utils.ScreenshotTest
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
class BackupListFragmentIT : AbstractIT() {
@get:Rule
val testActivityRule = IntentsTestRule(ContactsPreferenceActivity::class.java, true, false)
@get:Rule
val permissionRule: GrantPermissionRule = GrantPermissionRule.grant(Manifest.permission.READ_CALENDAR)
private val testClassName = "com.owncloud.android.ui.fragment.BackupListFragmentIT"
@Before
fun registerIdlingResource() {
IdlingRegistry.getInstance().register(EspressoIdlingResource.countingIdlingResource)
}
@After
fun unregisterIdlingResource() {
IdlingRegistry.getInstance().unregister(EspressoIdlingResource.countingIdlingResource)
}
@Test
@ScreenshotTest
fun showLoading() {
val sut = testActivityRule.launchActivity(null)
val file = OCFile("/")
val transaction = sut.supportFragmentManager.beginTransaction()
launchActivity<ContactsPreferenceActivity>().use { scenario ->
scenario.onActivity { sut ->
val file = OCFile("/")
val transaction = sut.supportFragmentManager.beginTransaction()
transaction.replace(R.id.frame_container, BackupListFragment.newInstance(file, user))
transaction.commit()
onIdleSync {
EspressoIdlingResource.increment()
waitForIdleSync()
screenshot(sut)
transaction.replace(R.id.frame_container, BackupListFragment.newInstance(file, user))
transaction.commit()
EspressoIdlingResource.decrement()
val screenShotName = createName(testClassName + "_" + "showLoading", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut, screenShotName)
}
}
}
}
@Test
@ScreenshotTest
fun showContactList() {
val sut = testActivityRule.launchActivity(null)
val transaction = sut.supportFragmentManager.beginTransaction()
val file = getFile("vcard.vcf")
val ocFile = OCFile("/vcard.vcf")
ocFile.storagePath = file.absolutePath
ocFile.mimeType = "text/vcard"
launchActivity<ContactsPreferenceActivity>().use { scenario ->
scenario.onActivity { sut ->
val transaction = sut.supportFragmentManager.beginTransaction()
val file = getFile("vcard.vcf")
val ocFile = OCFile("/vcard.vcf").apply {
storagePath = file.absolutePath
mimeType = "text/vcard"
}
transaction.replace(R.id.frame_container, BackupListFragment.newInstance(ocFile, user))
transaction.commit()
onIdleSync {
EspressoIdlingResource.increment()
waitForIdleSync()
shortSleep()
screenshot(sut)
transaction.replace(R.id.frame_container, BackupListFragment.newInstance(ocFile, user))
transaction.commit()
EspressoIdlingResource.decrement()
val screenShotName = createName(testClassName + "_" + "showContactList", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut, screenShotName)
}
}
}
}
@Test
@ScreenshotTest
fun showCalendarList() {
val sut = testActivityRule.launchActivity(null)
val transaction = sut.supportFragmentManager.beginTransaction()
val file = getFile("calendar.ics")
val ocFile = OCFile("/Private calender_2020-09-01_10-45-20.ics.ics")
ocFile.storagePath = file.absolutePath
ocFile.mimeType = "text/calendar"
launchActivity<ContactsPreferenceActivity>().use { scenario ->
scenario.onActivity { sut ->
val transaction = sut.supportFragmentManager.beginTransaction()
val file = getFile("calendar.ics")
val ocFile = OCFile("/Private calender_2020-09-01_10-45-20.ics.ics").apply {
storagePath = file.absolutePath
mimeType = "text/calendar"
}
transaction.replace(R.id.frame_container, BackupListFragment.newInstance(ocFile, user))
transaction.commit()
onIdleSync {
EspressoIdlingResource.increment()
waitForIdleSync()
screenshot(sut)
transaction.replace(R.id.frame_container, BackupListFragment.newInstance(ocFile, user))
transaction.commit()
EspressoIdlingResource.decrement()
val screenShotName = createName(testClassName + "_" + "showCalendarList", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut, screenShotName)
}
}
}
}
@Test
@ScreenshotTest
fun showCalendarAndContactsList() {
val sut = testActivityRule.launchActivity(null)
val transaction = sut.supportFragmentManager.beginTransaction()
launchActivity<ContactsPreferenceActivity>().use { scenario ->
scenario.onActivity { sut ->
val transaction = sut.supportFragmentManager.beginTransaction()
val calendarFile = getFile("calendar.ics")
val calendarOcFile = OCFile("/Private calender_2020-09-01_10-45-20.ics.ics").apply {
storagePath = calendarFile.absolutePath
mimeType = "text/calendar"
}
val calendarFile = getFile("calendar.ics")
val calendarOcFile = OCFile("/Private calender_2020-09-01_10-45-20.ics")
calendarOcFile.storagePath = calendarFile.absolutePath
calendarOcFile.mimeType = "text/calendar"
val contactFile = getFile("vcard.vcf")
val contactOcFile = OCFile("/vcard.vcf").apply {
storagePath = contactFile.absolutePath
mimeType = "text/vcard"
}
val contactFile = getFile("vcard.vcf")
val contactOcFile = OCFile("/vcard.vcf")
contactOcFile.storagePath = contactFile.absolutePath
contactOcFile.mimeType = "text/vcard"
val files = arrayOf(calendarOcFile, contactOcFile)
val files = arrayOf(calendarOcFile, contactOcFile)
transaction.replace(R.id.frame_container, BackupListFragment.newInstance(files, user))
transaction.commit()
onIdleSync {
EspressoIdlingResource.increment()
waitForIdleSync()
screenshot(sut)
transaction.replace(R.id.frame_container, BackupListFragment.newInstance(files, user))
transaction.commit()
EspressoIdlingResource.decrement()
val screenShotName = createName(testClassName + "_" + "showCalendarAndContactsList", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut, screenShotName)
}
}
}
}
}

View file

@ -1,14 +1,21 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2024 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-FileCopyrightText: 2020 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2020 Chris Narkiewicz <hello@ezaquarii.com>
* SPDX-FileCopyrightText: 2020 Chris Narkiewicz <hello@ezaquarii.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.ui.fragment
import androidx.test.espresso.intent.rule.IntentsTestRule
import androidx.annotation.UiThread
import androidx.test.core.app.launchActivity
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.IdlingRegistry
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.isRoot
import com.nextcloud.test.TestActivity
import com.nextcloud.ui.ImageDetailFragment
import com.owncloud.android.AbstractIT
@ -18,80 +25,111 @@ import com.owncloud.android.lib.resources.activities.model.Activity
import com.owncloud.android.lib.resources.activities.model.RichElement
import com.owncloud.android.lib.resources.activities.model.RichObject
import com.owncloud.android.lib.resources.activities.models.PreviewObject
import com.owncloud.android.utils.EspressoIdlingResource
import com.owncloud.android.utils.ScreenshotTest
import org.junit.Rule
import org.junit.After
import org.junit.Before
import org.junit.Test
import java.io.File
import java.util.GregorianCalendar
class FileDetailFragmentStaticServerIT : AbstractIT() {
@get:Rule
val testActivityRule = IntentsTestRule(TestActivity::class.java, true, false)
private val testClassName = "com.owncloud.android.ui.fragment.FileDetailFragmentStaticServerIT"
var file = getFile("gps.jpg")
val oCFile = OCFile("/").apply {
@Before
fun registerIdlingResource() {
IdlingRegistry.getInstance().register(EspressoIdlingResource.countingIdlingResource)
}
@After
fun unregisterIdlingResource() {
IdlingRegistry.getInstance().unregister(EspressoIdlingResource.countingIdlingResource)
}
private var file: File = getFile("gps.jpg")
private val oCFile: OCFile = OCFile("/").apply {
storagePath = file.absolutePath
fileId = 12
fileDataStorageManager.saveFile(this)
}
@Test
@UiThread
@ScreenshotTest
fun showFileDetailActivitiesFragment() {
val sut = testActivityRule.launchActivity(null)
sut.addFragment(FileDetailActivitiesFragment.newInstance(oCFile, user))
launchActivity<TestActivity>().use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
EspressoIdlingResource.increment()
sut.addFragment(FileDetailActivitiesFragment.newInstance(oCFile, user))
EspressoIdlingResource.decrement()
waitForIdleSync()
shortSleep()
shortSleep()
screenshot(sut)
val screenShotName = createName(testClassName + "_" + "showFileDetailActivitiesFragment", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut, screenShotName)
}
}
}
}
@Test
@UiThread
@ScreenshotTest
fun showFileDetailSharingFragment() {
val sut = testActivityRule.launchActivity(null)
sut.addFragment(FileDetailSharingFragment.newInstance(oCFile, user))
launchActivity<TestActivity>().use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
EspressoIdlingResource.increment()
sut.addFragment(FileDetailSharingFragment.newInstance(oCFile, user))
EspressoIdlingResource.decrement()
waitForIdleSync()
shortSleep()
shortSleep()
screenshot(sut)
val screenShotName = createName(testClassName + "_" + "showFileDetailSharingFragment", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut, screenShotName)
}
}
}
}
@Test
@UiThread
@ScreenshotTest
fun showFileDetailDetailsFragment() {
val activity = testActivityRule.launchActivity(null)
val sut = ImageDetailFragment.newInstance(oCFile, user)
activity.addFragment(sut)
launchActivity<TestActivity>().use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
EspressoIdlingResource.increment()
val fragment = ImageDetailFragment.newInstance(oCFile, user).apply {
hideMap()
}
sut.addFragment(fragment)
EspressoIdlingResource.decrement()
shortSleep()
shortSleep()
waitForIdleSync()
activity.runOnUiThread {
sut.hideMap()
val screenShotName = createName(testClassName + "_" + "showFileDetailDetailsFragment", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut, screenShotName)
}
}
}
screenshot(activity)
}
@Test
@UiThread
@ScreenshotTest
@Suppress("MagicNumber")
fun showDetailsActivities() {
val date = GregorianCalendar()
date.set(2005, 4, 17, 10, 35, 30) // random date
val date = GregorianCalendar().apply {
set(2005, 4, 17, 10, 35, 30)
}
val richObjectList: ArrayList<RichObject> = ArrayList()
richObjectList.add(RichObject("file", "abc", "text.txt", "/text.txt", "link", "tag"))
richObjectList.add(RichObject("file", "1", "text.txt", "/text.txt", "link", "tag"))
val richObjectList = ArrayList<RichObject>().apply {
add(RichObject("file", "abc", "text.txt", "/text.txt", "link", "tag"))
add(RichObject("file", "1", "text.txt", "/text.txt", "link", "tag"))
}
val previewObjectList1: ArrayList<PreviewObject> = ArrayList()
previewObjectList1.add(PreviewObject(1, "source", "link", true, "text/plain", "view", "text.txt"))
val richObjectList2: ArrayList<RichObject> = ArrayList()
richObjectList2.add(RichObject("user", "admin", "Admin", "", "", ""))
val previewObjectList1 = ArrayList<PreviewObject>().apply {
add(PreviewObject(1, "source", "link", true, "text/plain", "view", "text.txt"))
}
val activities = mutableListOf(
Activity(
@ -132,67 +170,85 @@ class FileDetailFragmentStaticServerIT : AbstractIT() {
)
)
val sut = FileDetailFragment.newInstance(oCFile, user, 0)
testActivityRule.launchActivity(null).apply {
addFragment(sut)
waitForIdleSync()
runOnUiThread {
sut.fileDetailActivitiesFragment.populateList(activities as List<Any>?, true)
launchActivity<TestActivity>().use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
EspressoIdlingResource.increment()
val fragment = FileDetailFragment.newInstance(oCFile, user, 0)
sut.addFragment(fragment)
fragment.fileDetailActivitiesFragment.populateList(activities as List<Any>?, true)
EspressoIdlingResource.decrement()
val screenShotName = createName(testClassName + "_" + "showDetailsActivities", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut, screenShotName)
}
}
longSleep()
screenshot(sut.fileDetailActivitiesFragment.binding.swipeContainingList)
}
}
// @Test
// @ScreenshotTest
fun showDetailsActivitiesNone() {
val activity = testActivityRule.launchActivity(null)
val sut = FileDetailFragment.newInstance(oCFile, user, 0)
activity.addFragment(sut)
waitForIdleSync()
activity.runOnUiThread {
sut.fileDetailActivitiesFragment.populateList(emptyList(), true)
}
shortSleep()
shortSleep()
screenshot(sut.fileDetailActivitiesFragment.binding.list)
}
@Test
@UiThread
@ScreenshotTest
fun showDetailsActivitiesNone() {
launchActivity<TestActivity>().use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
EspressoIdlingResource.increment()
val fragment = FileDetailFragment.newInstance(oCFile, user, 0)
sut.addFragment(fragment)
fragment.fileDetailActivitiesFragment.populateList(emptyList(), true)
EspressoIdlingResource.decrement()
val screenShotName = createName(testClassName + "_" + "showDetailsActivitiesNone", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut, screenShotName)
}
}
}
}
@Test
@UiThread
@ScreenshotTest
fun showDetailsActivitiesError() {
val activity = testActivityRule.launchActivity(null)
val sut = FileDetailFragment.newInstance(oCFile, user, 0)
activity.addFragment(sut)
launchActivity<TestActivity>().use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
EspressoIdlingResource.increment()
val fragment = FileDetailFragment.newInstance(oCFile, user, 0)
sut.addFragment(fragment)
fragment.fileDetailActivitiesFragment.disableLoadingActivities()
fragment.fileDetailActivitiesFragment.setErrorContent(
targetContext.resources.getString(R.string.file_detail_activity_error)
)
EspressoIdlingResource.decrement()
waitForIdleSync()
activity.runOnUiThread {
sut.fileDetailActivitiesFragment.disableLoadingActivities()
sut
.fileDetailActivitiesFragment
.setErrorContent(targetContext.resources.getString(R.string.file_detail_activity_error))
val screenShotName = createName(testClassName + "_" + "showDetailsActivitiesError", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut, screenShotName)
}
}
}
shortSleep()
shortSleep()
screenshot(sut.fileDetailActivitiesFragment.binding.emptyList.emptyListView)
}
@Test
@UiThread
@ScreenshotTest
fun showDetailsSharing() {
val sut = testActivityRule.launchActivity(null)
sut.addFragment(FileDetailFragment.newInstance(oCFile, user, 1))
launchActivity<TestActivity>().use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
EspressoIdlingResource.increment()
val fragment = FileDetailFragment.newInstance(oCFile, user, 1)
sut.addFragment(fragment)
EspressoIdlingResource.decrement()
waitForIdleSync()
shortSleep()
shortSleep()
screenshot(sut)
val screenShotName = createName(testClassName + "_" + "showDetailsSharing", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut, screenShotName)
}
}
}
}
}

View file

@ -1,9 +1,10 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2025 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-FileCopyrightText: 2022 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2022 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.ui.fragment
@ -11,69 +12,89 @@ import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import androidx.test.espresso.intent.rule.IntentsTestRule
import androidx.annotation.UiThread
import androidx.test.core.app.launchActivity
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.IdlingRegistry
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.isRoot
import com.nextcloud.test.TestActivity
import com.owncloud.android.AbstractIT
import com.owncloud.android.datamodel.OCFile
import com.owncloud.android.datamodel.ThumbnailsCacheManager
import com.owncloud.android.datamodel.ThumbnailsCacheManager.InitDiskCacheTask
import com.owncloud.android.datamodel.ThumbnailsCacheManager.PREFIX_RESIZED_IMAGE
import com.owncloud.android.lib.common.utils.Log_OC
import com.owncloud.android.lib.resources.files.model.ImageDimension
import com.owncloud.android.utils.EspressoIdlingResource
import com.owncloud.android.utils.ScreenshotTest
import org.junit.After
import org.junit.Assert.assertNotNull
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import java.util.Random
class GalleryFragmentIT : AbstractIT() {
@get:Rule
val testActivityRule = IntentsTestRule(TestActivity::class.java, true, false)
lateinit var activity: TestActivity
val random = Random(1)
private val testClassName = "com.owncloud.android.ui.fragment.GalleryFragmentIT"
private val random = Random(1)
@Before
fun before() {
activity = testActivityRule.launchActivity(null)
fun registerIdlingResource() {
IdlingRegistry.getInstance().register(EspressoIdlingResource.countingIdlingResource)
// initialise thumbnails cache on background thread
InitDiskCacheTask().execute()
@Suppress("DEPRECATION")
ThumbnailsCacheManager.initDiskCacheAsync()
}
@After
override fun after() {
fun unregisterIdlingResource() {
IdlingRegistry.getInstance().unregister(EspressoIdlingResource.countingIdlingResource)
ThumbnailsCacheManager.clearCache()
super.after()
}
@Test
@UiThread
@ScreenshotTest
@Test
fun showEmpty() {
val sut = GalleryFragment()
activity.addFragment(sut)
launchActivity<TestActivity>().use { scenario ->
scenario.onActivity { activity ->
onIdleSync {
EspressoIdlingResource.increment()
val sut = GalleryFragment()
activity.addFragment(sut)
EspressoIdlingResource.decrement()
waitForIdleSync()
screenshot(activity)
val screenShotName = createName(testClassName + "_" + "showEmpty", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(activity, screenShotName)
}
}
}
}
@Test
@UiThread
@ScreenshotTest
fun showGallery() {
createImage(10000001, 700, 300)
createImage(10000002, 500, 300)
createImage(10000007, 300, 400)
launchActivity<TestActivity>().use { scenario ->
scenario.onActivity { activity ->
onIdleSync {
EspressoIdlingResource.increment()
createImage(10000001, 700, 300)
createImage(10000002, 500, 300)
createImage(10000007, 300, 400)
val sut = GalleryFragment()
activity.addFragment(sut)
val sut = GalleryFragment()
activity.addFragment(sut)
EspressoIdlingResource.decrement()
waitForIdleSync()
shortSleep()
screenshot(activity)
val screenShotName = createName(testClassName + "_" + "showGallery", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(activity, screenShotName)
}
}
}
}
private fun createImage(id: Int, width: Int? = null, height: Int? = null) {

View file

@ -1,74 +1,98 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2025 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-FileCopyrightText: 2023 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.ui.fragment
import androidx.test.espresso.intent.rule.IntentsTestRule
import androidx.annotation.UiThread
import androidx.test.core.app.launchActivity
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.IdlingRegistry
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.isRoot
import com.nextcloud.android.lib.resources.groupfolders.Groupfolder
import com.nextcloud.test.TestActivity
import com.owncloud.android.AbstractIT
import com.owncloud.android.utils.EspressoIdlingResource
import com.owncloud.android.utils.ScreenshotTest
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
class GroupfolderListFragmentIT : AbstractIT() {
@get:Rule
val testActivityRule = IntentsTestRule(TestActivity::class.java, true, false)
lateinit var activity: TestActivity
private val testClassName = "com.owncloud.android.ui.fragment.GroupfolderListFragmentIT"
@Before
fun before() {
activity = testActivityRule.launchActivity(null)
fun registerIdlingResource() {
IdlingRegistry.getInstance().register(EspressoIdlingResource.countingIdlingResource)
}
@After
fun unregisterIdlingResource() {
IdlingRegistry.getInstance().unregister(EspressoIdlingResource.countingIdlingResource)
}
@Test
@UiThread
@ScreenshotTest
fun showGroupfolder() {
val sut = GroupfolderListFragment()
activity.addFragment(sut)
launchActivity<TestActivity>().use { scenario ->
scenario.onActivity { activity ->
onIdleSync {
EspressoIdlingResource.increment()
shortSleep() // to let async task finish
val sut = GroupfolderListFragment()
activity.addFragment(sut)
activity.runOnUiThread {
sut.setAdapter(null)
sut.setData(
mapOf(
Pair("2", Groupfolder(2, "/subfolder/group"))
)
)
sut.setAdapter(null)
sut.setData(
mapOf(
Pair("2", Groupfolder(2, "/subfolder/group"))
)
)
EspressoIdlingResource.decrement()
val screenShotName = createName(testClassName + "_" + "showGroupfolder", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(activity, screenShotName)
}
}
}
waitForIdleSync()
shortSleep()
screenshot(activity)
}
@Test
@UiThread
@ScreenshotTest
fun showGroupfolders() {
val sut = GroupfolderListFragment()
activity.addFragment(sut)
launchActivity<TestActivity>().use { scenario ->
scenario.onActivity { activity ->
onIdleSync {
EspressoIdlingResource.increment()
shortSleep() // to let async task finish
val sut = GroupfolderListFragment()
activity.addFragment(sut)
activity.runOnUiThread {
sut.setAdapter(null)
sut.setData(
mapOf(
Pair("1", Groupfolder(1, "/test/")),
Pair("2", Groupfolder(2, "/subfolder/group"))
)
)
sut.setAdapter(null)
sut.setData(
mapOf(
Pair("1", Groupfolder(1, "/test/")),
Pair("2", Groupfolder(2, "/subfolder/group"))
)
)
EspressoIdlingResource.decrement()
val screenShotName = createName(testClassName + "_" + "showGroupfolders", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(activity, screenShotName)
}
}
}
waitForIdleSync()
shortSleep()
screenshot(activity)
}
}

View file

@ -1,364 +1,437 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2025 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-FileCopyrightText: 2020 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2020 Chris Narkiewicz <hello@ezaquarii.com>
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.ui.fragment
import androidx.test.espresso.intent.rule.IntentsTestRule
import com.nextcloud.test.GrantStoragePermissionRule
import androidx.annotation.UiThread
import androidx.test.core.app.launchActivity
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.IdlingRegistry
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.isRoot
import com.nextcloud.test.GrantStoragePermissionRule.Companion.grant
import com.nextcloud.test.TestActivity
import com.owncloud.android.AbstractIT
import com.owncloud.android.datamodel.OCFile
import com.owncloud.android.lib.resources.shares.ShareType
import com.owncloud.android.lib.resources.shares.ShareeUser
import com.owncloud.android.lib.resources.tags.Tag
import com.owncloud.android.utils.EspressoIdlingResource
import com.owncloud.android.utils.MimeType
import com.owncloud.android.utils.ScreenshotTest
import org.junit.After
import org.junit.Assert
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TestRule
class OCFileListFragmentStaticServerIT : AbstractIT() {
@get:Rule
val testActivityRule = IntentsTestRule(TestActivity::class.java, true, false)
private val testClassName = "com.owncloud.android.ui.fragment.OCFileListFragmentStaticServerIT"
@Before
fun registerIdlingResource() {
IdlingRegistry.getInstance().register(EspressoIdlingResource.countingIdlingResource)
}
@After
fun unregisterIdlingResource() {
IdlingRegistry.getInstance().unregister(EspressoIdlingResource.countingIdlingResource)
}
@get:Rule
val permissionRule = GrantStoragePermissionRule.grant()
var storagePermissionRule: TestRule = grant()
@Test
@UiThread
@ScreenshotTest
@Suppress("MagicNumber")
fun showFiles() {
val sut = testActivityRule.launchActivity(null)
launchActivity<TestActivity>().use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
EspressoIdlingResource.increment()
OCFile("/1.png").apply {
mimeType = "image/png"
fileLength = 1024000
modificationTimestamp = 1188206955000
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
sut.storageManager.saveFile(this)
OCFile("/1.png").apply {
remoteId = "00000001"
mimeType = "image/png"
fileLength = 1024000
modificationTimestamp = 1188206955000
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
sut.storageManager.saveFile(this)
}
OCFile("/image.png").apply {
remoteId = "00000002"
mimeType = "image/png"
isPreviewAvailable = false
fileLength = 3072000
modificationTimestamp = 746443755000
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
tags = listOf(Tag("", "Top secret", null))
sut.storageManager.saveFile(this)
}
OCFile("/live photo.png").apply {
remoteId = "00000003"
mimeType = "image/png"
isPreviewAvailable = false
fileLength = 3072000
modificationTimestamp = 746443755000
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
setLivePhoto("/video.mov")
sut.storageManager.saveFile(this)
}
OCFile("/video.mp4").apply {
remoteId = "00000004"
mimeType = "video/mp4"
isPreviewAvailable = false
fileLength = 12092000
modificationTimestamp = 746143952000
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
tags = listOf(Tag("", "Confidential", null), Tag("", "+5", null))
sut.storageManager.saveFile(this)
}
sut.addFragment(OCFileListFragment())
val fragment = (sut.fragment as OCFileListFragment)
val root = sut.storageManager.getFileByEncryptedRemotePath("/")
fragment.listDirectory(root, false, false)
EspressoIdlingResource.decrement()
val screenShotName = createName(testClassName + "_" + "showFiles", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut, screenShotName)
}
}
}
OCFile("/image.png").apply {
mimeType = "image/png"
isPreviewAvailable = false
fileLength = 3072000
modificationTimestamp = 746443755000
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
tags = listOf("Top secret")
sut.storageManager.saveFile(this)
}
OCFile("/live photo.png").apply {
mimeType = "image/png"
isPreviewAvailable = false
fileLength = 3072000
modificationTimestamp = 746443755000
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
setLivePhoto("/video.mov")
sut.storageManager.saveFile(this)
}
OCFile("/video.mp4").apply {
mimeType = "video/mp4"
isPreviewAvailable = false
fileLength = 12092000
modificationTimestamp = 746143952000
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
tags = listOf("Confidential", "+5")
sut.storageManager.saveFile(this)
}
sut.addFragment(OCFileListFragment())
val fragment = (sut.fragment as OCFileListFragment)
val root = sut.storageManager.getFileByEncryptedRemotePath("/")
shortSleep()
sut.runOnUiThread { fragment.listDirectory(root, false, false) }
waitForIdleSync()
screenshot(sut)
}
/**
* Use same values as {@link FileDetailSharingFragmentIT listSharesFileAllShareTypes }
*/
@Test
@UiThread
@ScreenshotTest
fun showSharedFiles() {
val sut = testActivityRule.launchActivity(null)
val fragment = OCFileListFragment()
launchActivity<TestActivity>().use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
EspressoIdlingResource.increment()
OCFile("/sharedToUser.jpg").apply {
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
isSharedWithSharee = true
sharees = listOf(ShareeUser("Admin", "Server Admin", ShareType.USER))
modificationTimestamp = 1000
sut.storageManager.saveFile(this)
val fragment = OCFileListFragment()
OCFile("/sharedToUser.jpg").apply {
remoteId = "00000001"
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
isSharedWithSharee = true
sharees = listOf(ShareeUser("Admin", "Server Admin", ShareType.USER))
modificationTimestamp = 1000
sut.storageManager.saveFile(this)
}
OCFile("/sharedToGroup.jpg").apply {
remoteId = "00000002"
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
isSharedWithSharee = true
sharees = listOf(ShareeUser("group", "Group", ShareType.GROUP))
modificationTimestamp = 1000
sut.storageManager.saveFile(this)
}
OCFile("/sharedToEmail.jpg").apply {
remoteId = "00000003"
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
isSharedWithSharee = true
sharees =
listOf(
ShareeUser("admin@nextcloud.localhost", "admin@nextcloud.localhost", ShareType.EMAIL)
)
modificationTimestamp = 1000
sut.storageManager.saveFile(this)
}
OCFile("/publicLink.jpg").apply {
remoteId = "00000004"
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
isSharedViaLink = true
modificationTimestamp = 1000
sut.storageManager.saveFile(this)
}
OCFile("/sharedToFederatedUser.jpg").apply {
remoteId = "00000005"
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
isSharedWithSharee = true
sharees = listOf(
ShareeUser(
"admin@remote.nextcloud.com",
"admin@remote.nextcloud.com (remote)",
ShareType.FEDERATED
)
)
modificationTimestamp = 1000
sut.storageManager.saveFile(this)
}
OCFile("/sharedToPersonalCircle.jpg").apply {
remoteId = "00000006"
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
isSharedWithSharee = true
sharees = listOf(ShareeUser("circle", "Circle (Personal circle)", ShareType.CIRCLE))
modificationTimestamp = 1000
sut.storageManager.saveFile(this)
}
OCFile("/sharedToUserRoom.jpg").apply {
remoteId = "00000007"
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
isSharedWithSharee = true
sharees = listOf(ShareeUser("Conversation", "Admin", ShareType.ROOM))
modificationTimestamp = 1000
sut.storageManager.saveFile(this)
}
OCFile("/sharedToGroupRoom.jpg").apply {
remoteId = "00000008"
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
isSharedWithSharee = true
sharees = listOf(ShareeUser("Conversation", "Meeting", ShareType.ROOM))
modificationTimestamp = 1000
sut.storageManager.saveFile(this)
}
OCFile("/sharedToUsers.jpg").apply {
remoteId = "00000009"
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
isSharedWithSharee = true
sharees = listOf(
ShareeUser("Admin", "Server Admin", ShareType.USER),
ShareeUser("User", "User", ShareType.USER),
ShareeUser("Christine", "Christine Scott", ShareType.USER)
)
modificationTimestamp = 1000
sut.storageManager.saveFile(this)
}
OCFile("/notShared.jpg").apply {
remoteId = "000000010"
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
modificationTimestamp = 1000
sut.storageManager.saveFile(this)
}
OCFile("/Foo%e2%80%aedm.exe").apply {
remoteId = "000000011"
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
modificationTimestamp = 1000
sut.storageManager.saveFile(this)
}
sut.addFragment(fragment)
val root = sut.storageManager.getFileByEncryptedRemotePath("/")
fragment.listDirectory(root, false, false)
fragment.adapter.setShowShareAvatar(true)
EspressoIdlingResource.decrement()
val screenShotName = createName(testClassName + "_" + "showSharedFiles", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut, screenShotName)
}
}
}
OCFile("/sharedToGroup.jpg").apply {
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
isSharedWithSharee = true
sharees = listOf(ShareeUser("group", "Group", ShareType.GROUP))
modificationTimestamp = 1000
sut.storageManager.saveFile(this)
}
OCFile("/sharedToEmail.jpg").apply {
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
isSharedWithSharee = true
sharees = listOf(ShareeUser("admin@nextcloud.localhost", "admin@nextcloud.localhost", ShareType.EMAIL))
modificationTimestamp = 1000
sut.storageManager.saveFile(this)
}
OCFile("/publicLink.jpg").apply {
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
isSharedViaLink = true
modificationTimestamp = 1000
sut.storageManager.saveFile(this)
}
OCFile("/sharedToFederatedUser.jpg").apply {
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
isSharedWithSharee = true
sharees = listOf(
ShareeUser("admin@remote.nextcloud.com", "admin@remote.nextcloud.com (remote)", ShareType.FEDERATED)
)
modificationTimestamp = 1000
sut.storageManager.saveFile(this)
}
OCFile("/sharedToPersonalCircle.jpg").apply {
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
isSharedWithSharee = true
sharees = listOf(ShareeUser("circle", "Circle (Personal circle)", ShareType.CIRCLE))
modificationTimestamp = 1000
sut.storageManager.saveFile(this)
}
// as we cannot distinguish circle types, we do not need them right now
// OCFile("/sharedToPublicCircle.jpg").apply {
// parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
// isSharedWithSharee = true
// sharees = listOf(ShareeUser("circle", "Circle (Public circle)", ShareType.CIRCLE))
// modificationTimestamp = 1000
// sut.storageManager.saveFile(this)
// }
//
// OCFile("/sharedToClosedCircle.jpg").apply {
// parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
// isSharedWithSharee = true
// sharees = listOf(ShareeUser("circle", "Circle (Closed circle)", ShareType.CIRCLE))
// modificationTimestamp = 1000
// sut.storageManager.saveFile(this)
// }
//
// OCFile("/sharedToSecretCircle.jpg").apply {
// parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
// isSharedWithSharee = true
// sharees = listOf(ShareeUser("circle", "Circle (Secret circle)", ShareType.CIRCLE))
// modificationTimestamp = 1000
// sut.storageManager.saveFile(this)
// }
OCFile("/sharedToUserRoom.jpg").apply {
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
isSharedWithSharee = true
sharees = listOf(ShareeUser("Conversation", "Admin", ShareType.ROOM))
modificationTimestamp = 1000
sut.storageManager.saveFile(this)
}
OCFile("/sharedToGroupRoom.jpg").apply {
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
isSharedWithSharee = true
sharees = listOf(ShareeUser("Conversation", "Meeting", ShareType.ROOM))
modificationTimestamp = 1000
sut.storageManager.saveFile(this)
}
OCFile("/sharedToUsers.jpg").apply {
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
isSharedWithSharee = true
sharees = listOf(
ShareeUser("Admin", "Server Admin", ShareType.USER),
ShareeUser("User", "User", ShareType.USER),
ShareeUser("Christine", "Christine Scott", ShareType.USER)
)
modificationTimestamp = 1000
sut.storageManager.saveFile(this)
}
OCFile("/notShared.jpg").apply {
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
modificationTimestamp = 1000
sut.storageManager.saveFile(this)
}
sut.addFragment(fragment)
shortSleep()
val root = sut.storageManager.getFileByEncryptedRemotePath("/")
sut.runOnUiThread {
fragment.listDirectory(root, false, false)
fragment.adapter.setShowShareAvatar(true)
}
waitForIdleSync()
shortSleep()
shortSleep()
shortSleep()
screenshot(sut)
}
/**
* Use same values as {@link FileDetailSharingFragmentIT listSharesFileAllShareTypes }
*/
@Test
@UiThread
@ScreenshotTest
fun showFolderTypes() {
val sut = testActivityRule.launchActivity(null)
val fragment = OCFileListFragment()
launchActivity<TestActivity>().use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
EspressoIdlingResource.increment()
OCFile("/normal/").apply {
mimeType = MimeType.DIRECTORY
modificationTimestamp = 1624003571000
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
sut.storageManager.saveFile(this)
val fragment = OCFileListFragment()
OCFile("/normal/").apply {
remoteId = "00000001"
mimeType = MimeType.DIRECTORY
modificationTimestamp = 1624003571000
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
sut.storageManager.saveFile(this)
}
OCFile("/sharedViaLink/").apply {
remoteId = "00000002"
mimeType = MimeType.DIRECTORY
isSharedViaLink = true
modificationTimestamp = 1619003571000
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
sut.storageManager.saveFile(this)
}
OCFile("/share/").apply {
remoteId = "00000003"
mimeType = MimeType.DIRECTORY
isSharedWithSharee = true
modificationTimestamp = 1619303571000
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
sut.storageManager.saveFile(this)
}
OCFile("/groupFolder/").apply {
remoteId = "00000004"
mimeType = MimeType.DIRECTORY
modificationTimestamp = 1615003571000
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
permissions += "M"
sut.storageManager.saveFile(this)
}
OCFile("/encrypted/").apply {
remoteId = "00000005"
mimeType = MimeType.DIRECTORY
isEncrypted = true
decryptedRemotePath = "/encrypted/"
modificationTimestamp = 1614003571000
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
sut.storageManager.saveFile(this)
}
OCFile("/locked/").apply {
remoteId = "00000006"
mimeType = MimeType.DIRECTORY
isLocked = true
decryptedRemotePath = "/locked/"
modificationTimestamp = 1613003571000
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
sut.storageManager.saveFile(this)
}
OCFile("/offlineOperation/").apply {
mimeType = MimeType.DIRECTORY
decryptedRemotePath = "/offlineOperation/"
modificationTimestamp = System.currentTimeMillis()
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
sut.storageManager.saveFile(this)
}
sut.addFragment(fragment)
val root = sut.storageManager.getFileByEncryptedRemotePath("/")
fragment.listDirectory(root, false, false)
fragment.adapter.setShowShareAvatar(true)
EspressoIdlingResource.decrement()
val screenShotName = createName(testClassName + "_" + "showFolderTypes", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut, screenShotName)
}
}
}
OCFile("/sharedViaLink/").apply {
mimeType = MimeType.DIRECTORY
isSharedViaLink = true
modificationTimestamp = 1619003571000
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
sut.storageManager.saveFile(this)
}
OCFile("/share/").apply {
mimeType = MimeType.DIRECTORY
isSharedWithSharee = true
modificationTimestamp = 1619303571000
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
sut.storageManager.saveFile(this)
}
OCFile("/groupFolder/").apply {
mimeType = MimeType.DIRECTORY
modificationTimestamp = 1615003571000
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
permissions += "M"
sut.storageManager.saveFile(this)
}
OCFile("/encrypted/").apply {
mimeType = MimeType.DIRECTORY
isEncrypted = true
decryptedRemotePath = "/encrypted/"
modificationTimestamp = 1614003571000
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
sut.storageManager.saveFile(this)
}
OCFile("/locked/").apply {
mimeType = MimeType.DIRECTORY
isLocked = true
decryptedRemotePath = "/locked/"
modificationTimestamp = 1613003571000
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
sut.storageManager.saveFile(this)
}
sut.addFragment(fragment)
shortSleep()
val root = sut.storageManager.getFileByEncryptedRemotePath("/")
sut.runOnUiThread {
fragment.listDirectory(root, false, false)
fragment.adapter.setShowShareAvatar(true)
}
waitForIdleSync()
shortSleep()
shortSleep()
shortSleep()
screenshot(sut)
}
@Test
@UiThread
@ScreenshotTest
@Suppress("MagicNumber")
fun showRichWorkspace() {
val sut = testActivityRule.launchActivity(null)
val fragment = OCFileListFragment()
launchActivity<TestActivity>().use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
EspressoIdlingResource.increment()
val folder = OCFile("/test/")
folder.setFolder()
sut.storageManager.saveFile(folder)
val fragment = OCFileListFragment()
val imageFile = OCFile("/test/image.png")
imageFile.mimeType = "image/png"
imageFile.fileLength = 1024000
imageFile.modificationTimestamp = 1188206955000
imageFile.parentId = sut.storageManager.getFileByEncryptedRemotePath("/test/").fileId
imageFile.storagePath = getFile("java.md").absolutePath
sut.storageManager.saveFile(imageFile)
val folder = OCFile("/test/")
folder.setFolder()
sut.storageManager.saveFile(folder)
sut.addFragment(fragment)
val testFolder: OCFile = sut.storageManager.getFileByEncryptedRemotePath("/test/")
testFolder.richWorkspace = getFile("java.md").readText()
val imageFile = OCFile("/test/image.png").apply {
remoteId = "00000001"
mimeType = "image/png"
fileLength = 1024000
modificationTimestamp = 1188206955000
parentId = sut.storageManager.getFileByEncryptedRemotePath("/test/").fileId
storagePath = getFile("java.md").absolutePath
}
sut.runOnUiThread { fragment.listDirectory(testFolder, false, false) }
sut.storageManager.saveFile(imageFile)
shortSleep()
sut.addFragment(fragment)
val testFolder: OCFile = sut.storageManager.getFileByEncryptedRemotePath("/test/")
testFolder.richWorkspace = getFile("java.md").readText()
fragment.listDirectory(testFolder, false, false)
screenshot(sut)
EspressoIdlingResource.decrement()
val screenShotName = createName(testClassName + "_" + "showRichWorkspace", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut, screenShotName)
}
}
}
}
@Test
@UiThread
fun shouldShowHeader() {
val activity = testActivityRule.launchActivity(null)
val sut = OCFileListFragment()
launchActivity<TestActivity>().use { scenario ->
scenario.onActivity { activity ->
onIdleSync {
EspressoIdlingResource.increment()
val sut = OCFileListFragment()
val folder = OCFile("/test/").apply {
remoteId = "000001"
setFolder()
}
activity.storageManager.saveFile(folder)
activity.addFragment(sut)
val testFolder: OCFile = activity.storageManager.getFileByEncryptedRemotePath("/test/")
EspressoIdlingResource.decrement()
val folder = OCFile("/test/")
folder.setFolder()
activity.storageManager.saveFile(folder)
// richWorkspace is not set
Assert.assertFalse(sut.adapter.shouldShowHeader())
activity.addFragment(sut)
val testFolder: OCFile = activity.storageManager.getFileByEncryptedRemotePath("/test/")
EspressoIdlingResource.increment()
testFolder.richWorkspace = " "
activity.storageManager.saveFile(testFolder)
sut.adapter.swapDirectory(user, testFolder, activity.storageManager, false, "")
EspressoIdlingResource.decrement()
activity.runOnUiThread {
// richWorkspace is not set
Assert.assertFalse(sut.adapter.shouldShowHeader())
Assert.assertFalse(sut.adapter.shouldShowHeader())
testFolder.richWorkspace = " "
activity.storageManager.saveFile(testFolder)
sut.adapter.swapDirectory(user, testFolder, activity.storageManager, false, "")
Assert.assertFalse(sut.adapter.shouldShowHeader())
EspressoIdlingResource.increment()
testFolder.richWorkspace = null
activity.storageManager.saveFile(testFolder)
sut.adapter.swapDirectory(user, testFolder, activity.storageManager, false, "")
EspressoIdlingResource.decrement()
Assert.assertFalse(sut.adapter.shouldShowHeader())
testFolder.richWorkspace = null
activity.storageManager.saveFile(testFolder)
sut.adapter.swapDirectory(user, testFolder, activity.storageManager, false, "")
Assert.assertFalse(sut.adapter.shouldShowHeader())
EspressoIdlingResource.increment()
testFolder.richWorkspace = "1"
activity.storageManager.saveFile(testFolder)
sut.adapter.setCurrentDirectory(testFolder)
EspressoIdlingResource.decrement()
testFolder.richWorkspace = "1"
activity.storageManager.saveFile(testFolder)
sut.adapter.setCurrentDirectory(testFolder)
Assert.assertTrue(sut.adapter.shouldShowHeader())
Assert.assertTrue(sut.adapter.shouldShowHeader())
}
}
}
}
}

View file

@ -3,168 +3,183 @@
*
* SPDX-FileCopyrightText: 2023 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.ui.fragment
import android.view.View
import androidx.test.espresso.intent.rule.IntentsTestRule
import com.nextcloud.test.GrantStoragePermissionRule
import androidx.annotation.UiThread
import androidx.test.core.app.launchActivity
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.IdlingRegistry
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.isRoot
import com.nextcloud.test.GrantStoragePermissionRule.Companion.grant
import com.nextcloud.test.TestActivity
import com.owncloud.android.AbstractIT
import com.owncloud.android.datamodel.OCFile
import com.owncloud.android.lib.resources.shares.OCShare
import com.owncloud.android.lib.resources.shares.ShareType
import com.owncloud.android.utils.EspressoIdlingResource
import com.owncloud.android.utils.ScreenshotTest
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TestRule
internal class SharedListFragmentIT : AbstractIT() {
@get:Rule
val testActivityRule = IntentsTestRule(TestActivity::class.java, true, false)
@get:Rule
val permissionRule = GrantStoragePermissionRule.grant()
lateinit var sut: TestActivity
private val testClassName = "com.owncloud.android.ui.fragment.SharedListFragmentIT"
@Before
fun before() {
sut = testActivityRule.launchActivity(null)
fun registerIdlingResource() {
IdlingRegistry.getInstance().register(EspressoIdlingResource.countingIdlingResource)
}
@After
fun unregisterIdlingResource() {
IdlingRegistry.getInstance().unregister(EspressoIdlingResource.countingIdlingResource)
}
@get:Rule
var storagePermissionRule: TestRule = grant()
@Test
@UiThread
@ScreenshotTest
fun showSharedFiles() {
val fragment = SharedListFragment()
launchActivity<TestActivity>().use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
EspressoIdlingResource.increment()
val file = OCFile("/shared to admin.png").apply {
remoteId = "00000001"
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
mimeType = "image/png"
fileLength = 1024000
modificationTimestamp = 1188206955
permissions = OCFile.PERMISSION_CAN_RESHARE
sut.storageManager.saveFile(this)
}
val fragment = SharedListFragment()
val file1 = OCFile("/shared to group.png").apply {
remoteId = "00000001"
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
mimeType = "image/png"
fileLength = 1024000
modificationTimestamp = 1188206955
permissions = OCFile.PERMISSION_CAN_RESHARE
sut.storageManager.saveFile(this)
}
val file = OCFile("/shared to admin.png").apply {
remoteId = "00000001"
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
mimeType = "image/png"
fileLength = 1024000
modificationTimestamp = 1188206955
permissions = OCFile.PERMISSION_CAN_RESHARE
sut.storageManager.saveFile(this)
}
val file2 = OCFile("/shared via public link.png").apply {
remoteId = "00000001"
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
mimeType = "image/png"
fileLength = 1024000
modificationTimestamp = 1188206955
permissions = OCFile.PERMISSION_CAN_RESHARE
sut.storageManager.saveFile(this)
}
val file1 = OCFile("/shared to group.png").apply {
remoteId = "00000001"
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
mimeType = "image/png"
fileLength = 1024000
modificationTimestamp = 1188206955
permissions = OCFile.PERMISSION_CAN_RESHARE
sut.storageManager.saveFile(this)
}
val file3 = OCFile("/shared to personal circle.png").apply {
remoteId = "00000001"
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
mimeType = "image/png"
fileLength = 1024000
modificationTimestamp = 1188206955
permissions = OCFile.PERMISSION_CAN_RESHARE
sut.storageManager.saveFile(this)
}
val file2 = OCFile("/shared via public link.png").apply {
remoteId = "00000001"
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
mimeType = "image/png"
fileLength = 1024000
modificationTimestamp = 1188206955
permissions = OCFile.PERMISSION_CAN_RESHARE
sut.storageManager.saveFile(this)
}
val file4 = OCFile("/shared to talk.png").apply {
remoteId = "00000001"
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
mimeType = "image/png"
fileLength = 1024000
modificationTimestamp = 1188206955
permissions = OCFile.PERMISSION_CAN_RESHARE
sut.storageManager.saveFile(this)
}
val file3 = OCFile("/shared to personal circle.png").apply {
remoteId = "00000001"
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
mimeType = "image/png"
fileLength = 1024000
modificationTimestamp = 1188206955
permissions = OCFile.PERMISSION_CAN_RESHARE
sut.storageManager.saveFile(this)
}
val shares = listOf(
OCShare(file.decryptedRemotePath).apply {
remoteId = 1
shareType = ShareType.USER
sharedWithDisplayName = "Admin"
permissions = OCShare.MAXIMUM_PERMISSIONS_FOR_FILE
userId = getUserId(user)
sharedDate = 1188206955
mimetype = "image/png"
sut.storageManager.saveShare(this)
},
val file4 = OCFile("/shared to talk.png").apply {
remoteId = "00000001"
parentId = sut.storageManager.getFileByEncryptedRemotePath("/").fileId
mimeType = "image/png"
fileLength = 1024000
modificationTimestamp = 1188206955
permissions = OCFile.PERMISSION_CAN_RESHARE
sut.storageManager.saveFile(this)
}
OCShare(file1.decryptedRemotePath).apply {
remoteId = 2
shareType = ShareType.GROUP
sharedWithDisplayName = "Group"
permissions = OCShare.MAXIMUM_PERMISSIONS_FOR_FILE
userId = getUserId(user)
sharedDate = 1188206955
mimetype = "image/png"
sut.storageManager.saveShare(this)
},
val shares = listOf(
OCShare(file.decryptedRemotePath).apply {
remoteId = 1
shareType = ShareType.USER
sharedWithDisplayName = "Admin"
permissions = OCShare.MAXIMUM_PERMISSIONS_FOR_FILE
userId = getUserId(user)
sharedDate = 1188206955
mimetype = "image/png"
sut.storageManager.saveShare(this)
},
OCShare(file2.decryptedRemotePath).apply {
remoteId = 3
shareType = ShareType.PUBLIC_LINK
label = "Customer"
sharedDate = 1188206955
mimetype = "image/png"
sut.storageManager.saveShare(this)
},
OCShare(file1.decryptedRemotePath).apply {
remoteId = 2
shareType = ShareType.GROUP
sharedWithDisplayName = "Group"
permissions = OCShare.MAXIMUM_PERMISSIONS_FOR_FILE
userId = getUserId(user)
sharedDate = 1188206955
mimetype = "image/png"
sut.storageManager.saveShare(this)
},
OCShare(file3.decryptedRemotePath).apply {
remoteId = 4
shareType = ShareType.CIRCLE
sharedWithDisplayName = "Personal circle"
permissions = OCShare.SHARE_PERMISSION_FLAG
userId = getUserId(user)
sharedDate = 1188206955
mimetype = "image/png"
sut.storageManager.saveShare(this)
},
OCShare(file2.decryptedRemotePath).apply {
remoteId = 3
shareType = ShareType.PUBLIC_LINK
label = "Customer"
sharedDate = 1188206955
mimetype = "image/png"
sut.storageManager.saveShare(this)
},
OCShare(file4.decryptedRemotePath).apply {
remoteId = 11
shareType = ShareType.ROOM
sharedWithDisplayName = "Admin"
permissions = OCShare.SHARE_PERMISSION_FLAG
userId = getUserId(user)
sharedDate = 1188206955
mimetype = "image/png"
sut.storageManager.saveShare(this)
OCShare(file3.decryptedRemotePath).apply {
remoteId = 4
shareType = ShareType.CIRCLE
sharedWithDisplayName = "Personal circle"
permissions = OCShare.SHARE_PERMISSION_FLAG
userId = getUserId(user)
sharedDate = 1188206955
mimetype = "image/png"
sut.storageManager.saveShare(this)
},
OCShare(file4.decryptedRemotePath).apply {
remoteId = 11
shareType = ShareType.ROOM
sharedWithDisplayName = "Admin"
permissions = OCShare.SHARE_PERMISSION_FLAG
userId = getUserId(user)
sharedDate = 1188206955
mimetype = "image/png"
sut.storageManager.saveShare(this)
}
)
sut.addFragment(fragment)
fragment.isLoading = false
fragment.mEmptyListContainer?.visibility = View.GONE
fragment.adapter.setData(
shares,
SearchType.SHARED_FILTER,
storageManager,
null,
true
)
EspressoIdlingResource.decrement()
val screenShotName = createName(testClassName + "_" + "showSharedFiles", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut, screenShotName)
}
}
)
sut.addFragment(fragment)
shortSleep()
sut.runOnUiThread {
fragment.isLoading = false
fragment.mEmptyListContainer.visibility = View.GONE
fragment.adapter.setData(
shares,
SearchType.SHARED_FILTER,
storageManager,
null,
true
)
}
waitForIdleSync()
shortSleep()
shortSleep()
shortSleep()
screenshot(sut)
}
}

View file

@ -3,7 +3,7 @@
*
* SPDX-FileCopyrightText: 2020 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.ui.fragment

View file

@ -1,86 +1,109 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2025 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-FileCopyrightText: 2020 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.ui.fragment
import androidx.test.espresso.intent.rule.IntentsTestRule
import androidx.test.internal.runner.junit4.statement.UiThreadStatement
import androidx.annotation.UiThread
import androidx.test.core.app.launchActivity
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.IdlingRegistry
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.isRoot
import com.nextcloud.test.TestActivity
import com.owncloud.android.AbstractIT
import com.owncloud.android.datamodel.OCFile
import com.owncloud.android.lib.common.SearchResultEntry
import com.owncloud.android.ui.unifiedsearch.UnifiedSearchSection
import com.owncloud.android.ui.unifiedsearch.UnifiedSearchViewModel
import org.junit.Rule
import com.owncloud.android.utils.EspressoIdlingResource
import org.junit.After
import org.junit.Before
import org.junit.Test
import java.io.File
class UnifiedSearchFragmentIT : AbstractIT() {
@get:Rule
val testActivityRule = IntentsTestRule(TestActivity::class.java, true, false)
@Test
fun showSearchResult() {
val activity = testActivityRule.launchActivity(null)
val sut = UnifiedSearchFragment.newInstance(null, null)
@Before
fun registerIdlingResource() {
IdlingRegistry.getInstance().register(EspressoIdlingResource.countingIdlingResource)
}
activity.addFragment(sut)
shortSleep()
UiThreadStatement.runOnUiThread {
sut.onSearchResultChanged(
listOf(
UnifiedSearchSection(
providerID = "files",
name = "Files",
entries = listOf(
SearchResultEntry(
"thumbnailUrl",
"Test",
"in Files",
"http://localhost/nc/index.php/apps/files/?dir=/Files&scrollto=Test",
"icon",
false
)
),
hasMoreResults = false
)
)
)
}
shortSleep()
@After
fun unregisterIdlingResource() {
IdlingRegistry.getInstance().unregister(EspressoIdlingResource.countingIdlingResource)
}
@Test
@UiThread
fun showSearchResult() {
launchActivity<TestActivity>().use { scenario ->
scenario.onActivity { activity ->
onIdleSync {
EspressoIdlingResource.increment()
val sut = UnifiedSearchFragment.newInstance(null, null)
activity.addFragment(sut)
sut.onSearchResultChanged(
listOf(
UnifiedSearchSection(
providerID = "files",
name = "Files",
entries = listOf(
SearchResultEntry(
"thumbnailUrl",
"Test",
"in Files",
"http://localhost/nc/index.php/apps/files/?dir=/Files&scrollto=Test",
"icon",
false
)
),
hasMoreResults = false
)
)
)
EspressoIdlingResource.decrement()
onView(isRoot()).check(matches(isDisplayed()))
}
}
}
}
@Test
@UiThread
fun search() {
val activity = testActivityRule.launchActivity(null) as TestActivity
val sut = UnifiedSearchFragment.newInstance(null, null)
val testViewModel = UnifiedSearchViewModel(activity.application)
testViewModel.setConnectivityService(activity.connectivityServiceMock)
val localRepository = UnifiedSearchFakeRepository()
testViewModel.setRepository(localRepository)
launchActivity<TestActivity>().use { scenario ->
scenario.onActivity { activity ->
onIdleSync {
EspressoIdlingResource.increment()
val ocFile = OCFile("/folder/test1.txt").apply {
storagePath = "/sdcard/1.txt"
storageManager.saveFile(this)
val sut = UnifiedSearchFragment.newInstance(null, null)
val testViewModel = UnifiedSearchViewModel(activity.application)
testViewModel.setConnectivityService(activity.connectivityServiceMock)
val localRepository = UnifiedSearchFakeRepository()
testViewModel.setRepository(localRepository)
val ocFile = OCFile("/folder/test1.txt").apply {
storagePath = "/sdcard/1.txt"
storageManager.saveFile(this)
}
File(ocFile.storagePath).createNewFile()
activity.addFragment(sut)
sut.setViewModel(testViewModel)
sut.vm.setQuery("test")
sut.vm.initialQuery()
EspressoIdlingResource.decrement()
onView(isRoot()).check(matches(isDisplayed()))
}
}
}
File(ocFile.storagePath).createNewFile()
activity.addFragment(sut)
shortSleep()
UiThreadStatement.runOnUiThread {
sut.setViewModel(testViewModel)
sut.vm.setQuery("test")
sut.vm.initialQuery()
}
shortSleep()
}
}

View file

@ -3,7 +3,7 @@
*
* SPDX-FileCopyrightText: 2020 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.ui.helpers

View file

@ -2,7 +2,7 @@
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2022 Álvaro Brey <alvaro@alvarobrey.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.ui.helpers

View file

@ -1,43 +1,63 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2025 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-FileCopyrightText: 2022 Álvaro Brey <alvaro@alvarobrey.com>
* SPDX-FileCopyrightText: 2022 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.ui.preview
import android.content.Intent
import androidx.test.espresso.intent.rule.IntentsTestRule
import androidx.annotation.UiThread
import androidx.test.core.app.launchActivity
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.IdlingRegistry
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.isRoot
import com.owncloud.android.AbstractIT
import com.owncloud.android.utils.EspressoIdlingResource
import com.owncloud.android.utils.ScreenshotTest
import org.junit.Rule
import org.junit.After
import org.junit.Before
import org.junit.Test
class PreviewBitmapScreenshotIT : AbstractIT() {
private val testClassName = "com.owncloud.android.ui.preview.PreviewBitmapScreenshotIT"
companion object {
private const val PNG_FILE_ASSET = "imageFile.png"
}
@get:Rule
val testActivityRule = IntentsTestRule(PreviewBitmapActivity::class.java, true, false)
@Before
fun registerIdlingResource() {
IdlingRegistry.getInstance().register(EspressoIdlingResource.countingIdlingResource)
}
@After
fun unregisterIdlingResource() {
IdlingRegistry.getInstance().unregister(EspressoIdlingResource.countingIdlingResource)
}
@Test
@UiThread
@ScreenshotTest
fun showBitmap() {
val pngFile = getFile(PNG_FILE_ASSET)
val activity = testActivityRule.launchActivity(
Intent().putExtra(
PreviewBitmapActivity.EXTRA_BITMAP_PATH,
pngFile.absolutePath
)
val intent = Intent(targetContext, PreviewBitmapActivity::class.java).putExtra(
PreviewBitmapActivity.EXTRA_BITMAP_PATH,
pngFile.absolutePath
)
shortSleep()
waitForIdleSync()
screenshot(activity)
launchActivity<PreviewBitmapActivity>(intent).use { scenario ->
scenario.onActivity { sut ->
onIdleSync {
val screenShotName = createName(testClassName + "_" + "showBitmap", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut, screenShotName)
}
}
}
}
}

View file

@ -0,0 +1,89 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2024 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
package com.owncloud.android.ui.preview
import androidx.annotation.UiThread
import androidx.test.core.app.launchActivity
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.IdlingRegistry
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.isRoot
import com.owncloud.android.AbstractIT
import com.owncloud.android.datamodel.OCFile
import com.owncloud.android.ui.activity.FileDisplayActivity
import com.owncloud.android.utils.EspressoIdlingResource
import com.owncloud.android.utils.MimeTypeUtil
import com.owncloud.android.utils.ScreenshotTest
import org.junit.After
import org.junit.Before
import org.junit.Test
import java.io.IOException
class PreviewTextFileFragmentTest : AbstractIT() {
private val testClassName = "com.owncloud.android.ui.preview.PreviewTextFileFragmentTest"
@Before
fun registerIdlingResource() {
IdlingRegistry.getInstance().register(EspressoIdlingResource.countingIdlingResource)
}
@After
fun unregisterIdlingResource() {
IdlingRegistry.getInstance().unregister(EspressoIdlingResource.countingIdlingResource)
}
@Test
@ScreenshotTest
@UiThread
@Throws(IOException::class)
fun displaySimpleTextFile() {
launchActivity<FileDisplayActivity>().use { scenario ->
scenario.onActivity { sut ->
val test = OCFile("/text.md").apply {
mimeType = MimeTypeUtil.MIMETYPE_TEXT_MARKDOWN
storagePath = getDummyFile("nonEmpty.txt").absolutePath
}
onIdleSync {
EspressoIdlingResource.increment()
sut.startTextPreview(test, true)
EspressoIdlingResource.decrement()
val screenShotName = createName(testClassName + "_" + "displaySimpleTextFile", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut, screenShotName)
}
}
}
}
@Test
@ScreenshotTest
@UiThread
@Throws(IOException::class)
fun displayJavaSnippetFile() {
launchActivity<FileDisplayActivity>().use { scenario ->
scenario.onActivity { sut ->
val test = OCFile("/java.md").apply {
mimeType = MimeTypeUtil.MIMETYPE_TEXT_MARKDOWN
storagePath = getFile("java.md").absolutePath
}
onIdleSync {
EspressoIdlingResource.increment()
sut.startTextPreview(test, true)
EspressoIdlingResource.decrement()
val screenShotName = createName(testClassName + "_" + "displayJavaSnippetFile", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut, screenShotName)
}
}
}
}
}

View file

@ -1,54 +1,70 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2025 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-FileCopyrightText: 2022 Álvaro Brey <alvaro@alvarobrey.com>
* SPDX-FileCopyrightText: 2022 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.ui.preview.pdf
import androidx.lifecycle.Lifecycle
import androidx.test.espresso.intent.rule.IntentsTestRule
import androidx.annotation.UiThread
import androidx.test.core.app.launchActivity
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.IdlingRegistry
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.isRoot
import com.nextcloud.test.TestActivity
import com.owncloud.android.AbstractIT
import com.owncloud.android.datamodel.OCFile
import com.owncloud.android.utils.EspressoIdlingResource
import com.owncloud.android.utils.ScreenshotTest
import org.junit.Rule
import org.junit.After
import org.junit.Before
import org.junit.Test
class PreviewPdfFragmentScreenshotIT : AbstractIT() {
private val testClassName = "com.owncloud.android.ui.preview.pdf.PreviewPdfFragmentScreenshotIT"
companion object {
private const val PDF_FILE_ASSET = "test.pdf"
}
@get:Rule
val testActivityRule = IntentsTestRule(TestActivity::class.java, true, false)
@Before
fun registerIdlingResource() {
IdlingRegistry.getInstance().register(EspressoIdlingResource.countingIdlingResource)
}
@After
fun unregisterIdlingResource() {
IdlingRegistry.getInstance().unregister(EspressoIdlingResource.countingIdlingResource)
}
@Test
@UiThread
@ScreenshotTest
fun showPdf() {
val activity = testActivityRule.launchActivity(null)
launchActivity<TestActivity>().use { scenario ->
scenario.onActivity { activity ->
onIdleSync {
EspressoIdlingResource.increment()
val pdfFile = getFile(PDF_FILE_ASSET)
val ocFile = OCFile("/test.pdf").apply {
storagePath = pdfFile.absolutePath
}
val pdfFile = getFile(PDF_FILE_ASSET)
val ocFile = OCFile("/test.pdf").apply {
storagePath = pdfFile.absolutePath
val sut = PreviewPdfFragment.newInstance(ocFile)
activity.addFragment(sut)
sut.dismissSnack()
EspressoIdlingResource.decrement()
val screenShotName = createName(testClassName + "_" + "showPdf", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(activity, screenShotName)
}
}
}
val sut = PreviewPdfFragment.newInstance(ocFile)
activity.addFragment(sut)
while (!sut.lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)) {
shortSleep()
}
activity.runOnUiThread {
sut.dismissSnack()
}
shortSleep()
waitForIdleSync()
screenshot(activity)
}
}

View file

@ -3,7 +3,7 @@
*
* SPDX-FileCopyrightText: 2020 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.ui.trashbin
@ -20,6 +20,7 @@ import androidx.test.espresso.matcher.ViewMatchers.isRoot
import com.owncloud.android.utils.EspressoIdlingResource
import com.owncloud.android.AbstractIT
import com.owncloud.android.MainApp
import com.owncloud.android.extensions.launchAndCapture
import com.owncloud.android.lib.common.accounts.AccountUtils
import com.owncloud.android.utils.ScreenshotTest
import org.junit.After
@ -30,7 +31,9 @@ class TrashbinActivityIT : AbstractIT() {
private val testClassName = "com.owncloud.android.ui.trashbin.TrashbinActivityIT"
enum class TestCase {
ERROR, EMPTY, FILES
ERROR,
EMPTY,
FILES
}
@Before
@ -69,84 +72,50 @@ class TrashbinActivityIT : AbstractIT() {
@UiThread
@ScreenshotTest
fun files() {
launchActivity<TrashbinActivity>().use { scenario ->
scenario.onActivity { sut ->
val trashbinRepository = TrashbinLocalRepository(TestCase.FILES)
sut.trashbinPresenter = TrashbinPresenter(trashbinRepository, sut)
onIdleSync {
EspressoIdlingResource.increment()
sut.loadFolder(
onComplete = { EspressoIdlingResource.decrement() },
onError = { EspressoIdlingResource.decrement() }
)
onView(isRoot()).check(matches(isDisplayed()))
val screenShotName = createName(testClassName + "_" + "files", "")
screenshotViaName(sut, screenShotName)
}
}
}
launchAndCapture<TrashbinActivity>(testClassName, "files", before = { sut ->
val trashbinRepository = TrashbinLocalRepository(TestCase.FILES)
sut.trashbinPresenter = TrashbinPresenter(trashbinRepository, sut)
sut.loadFolder(
onComplete = { EspressoIdlingResource.decrement() },
onError = { EspressoIdlingResource.decrement() }
)
})
}
@Test
@UiThread
@ScreenshotTest
fun empty() {
launchActivity<TrashbinActivity>().use { scenario ->
scenario.onActivity { sut ->
val trashbinRepository = TrashbinLocalRepository(TestCase.EMPTY)
sut.trashbinPresenter = TrashbinPresenter(trashbinRepository, sut)
onIdleSync {
EspressoIdlingResource.increment()
sut.loadFolder(
onComplete = { EspressoIdlingResource.decrement() },
onError = { EspressoIdlingResource.decrement() }
)
onView(isRoot()).check(matches(isDisplayed()))
val screenShotName = createName(testClassName + "_" + "empty", "")
screenshotViaName(sut, screenShotName)
}
}
}
launchAndCapture<TrashbinActivity>(testClassName, "empty", before = { sut ->
val trashbinRepository = TrashbinLocalRepository(TestCase.EMPTY)
sut.trashbinPresenter = TrashbinPresenter(trashbinRepository, sut)
sut.loadFolder(
onComplete = { EspressoIdlingResource.decrement() },
onError = { EspressoIdlingResource.decrement() }
)
})
}
@Test
@UiThread
@ScreenshotTest
fun loading() {
launchActivity<TrashbinActivity>().use { scenario ->
scenario.onActivity { sut ->
val trashbinRepository = TrashbinLocalRepository(TestCase.EMPTY)
sut.trashbinPresenter = TrashbinPresenter(trashbinRepository, sut)
onIdleSync {
EspressoIdlingResource.increment()
sut.showInitialLoading()
EspressoIdlingResource.decrement()
val screenShotName = createName(testClassName + "_" + "loading", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut, screenShotName)
}
}
}
launchAndCapture<TrashbinActivity>(testClassName, "loading", before = { sut ->
val trashbinRepository = TrashbinLocalRepository(TestCase.EMPTY)
sut.trashbinPresenter = TrashbinPresenter(trashbinRepository, sut)
sut.showInitialLoading()
})
}
@Test
@UiThread
@ScreenshotTest
fun normalUser() {
launchActivity<TrashbinActivity>().use { scenario ->
scenario.onActivity { sut ->
val trashbinRepository = TrashbinLocalRepository(TestCase.EMPTY)
sut.trashbinPresenter = TrashbinPresenter(trashbinRepository, sut)
onIdleSync {
EspressoIdlingResource.increment()
sut.showUser()
EspressoIdlingResource.decrement()
val screenShotName = createName(testClassName + "_" + "normalUser", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut, screenShotName)
}
}
}
launchAndCapture<TrashbinActivity>(testClassName, "normalUser", before = { sut ->
val trashbinRepository = TrashbinLocalRepository(TestCase.EMPTY)
sut.trashbinPresenter = TrashbinPresenter(trashbinRepository, sut)
sut.showUser()
})
}
@Test
@ -165,19 +134,10 @@ class TrashbinActivityIT : AbstractIT() {
putExtra(Intent.EXTRA_USER, "differentUser@https://nextcloud.localhost")
}
launchActivity<TrashbinActivity>(intent).use { scenario ->
scenario.onActivity { sut ->
val trashbinRepository = TrashbinLocalRepository(TestCase.EMPTY)
sut.trashbinPresenter = TrashbinPresenter(trashbinRepository, sut)
onIdleSync {
EspressoIdlingResource.increment()
sut.showUser()
EspressoIdlingResource.decrement()
val screenShotName = createName(testClassName + "_" + "differentUser", "")
onView(isRoot()).check(matches(isDisplayed()))
screenshotViaName(sut, screenShotName)
}
}
}
launchAndCapture<TrashbinActivity>(testClassName, "differentUser", intent = intent, before = { sut ->
val trashbinRepository = TrashbinLocalRepository(TestCase.EMPTY)
sut.trashbinPresenter = TrashbinPresenter(trashbinRepository, sut)
sut.showUser()
})
}
}

View file

@ -3,7 +3,7 @@
*
* SPDX-FileCopyrightText: 2020 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.ui.trashbin
@ -36,8 +36,10 @@ class TrashbinLocalRepository(private val testCase: TrashbinActivityIT.TestCase)
"image/png",
"/trashbin/test.png",
"subFolder/test.png",
1395847838, // random date
1395847908 // random date
// random date
1395847838,
// random date
1395847908
)
)
files.add(
@ -46,8 +48,10 @@ class TrashbinLocalRepository(private val testCase: TrashbinActivityIT.TestCase)
"image/jpeg",
"/trashbin/image.jpg",
"image.jpg",
1395841858, // random date
1395837858 // random date
// random date
1395841858,
// random date
1395837858
)
)
files.add(
@ -56,8 +60,10 @@ class TrashbinLocalRepository(private val testCase: TrashbinActivityIT.TestCase)
"DIR",
"/trashbin/folder/",
"folder",
1395347858, // random date
1395849858 // random date
// random date
1395347858,
// random date
1395849858
)
)

View file

@ -3,7 +3,7 @@
*
* SPDX-FileCopyrightText: 2017 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.util;
@ -25,6 +25,7 @@ import com.owncloud.android.datamodel.e2e.v1.decrypted.Encrypted;
import com.owncloud.android.datamodel.e2e.v1.encrypted.EncryptedFolderMetadataFileV1;
import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.lib.resources.e2ee.CsrHelper;
import com.owncloud.android.utils.crypto.CryptoHelper;
import com.owncloud.android.utils.EncryptionUtils;
import org.junit.Assert;
@ -44,7 +45,6 @@ import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.interfaces.RSAPublicKey;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@ -57,7 +57,6 @@ import javax.crypto.Cipher;
import static com.owncloud.android.utils.EncryptionUtils.decodeStringToBase64Bytes;
import static com.owncloud.android.utils.EncryptionUtils.decryptFile;
import static com.owncloud.android.utils.EncryptionUtils.decryptFolderMetaData;
import static com.owncloud.android.utils.EncryptionUtils.decryptPrivateKey;
import static com.owncloud.android.utils.EncryptionUtils.decryptStringAsymmetric;
import static com.owncloud.android.utils.EncryptionUtils.decryptStringSymmetric;
import static com.owncloud.android.utils.EncryptionUtils.deserializeJSON;
@ -79,6 +78,7 @@ import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertArrayEquals;
public class EncryptionTestIT extends AbstractIT {
@Rule public RetryTestRule retryTestRule = new RetryTestRule();
@ -149,7 +149,7 @@ public class EncryptionTestIT extends AbstractIT {
byte[] key2 = decodeStringToBase64Bytes(decryptedString);
assertTrue(Arrays.equals(key1, key2));
assertArrayEquals(key1, key2);
}
@Test
@ -164,7 +164,7 @@ public class EncryptionTestIT extends AbstractIT {
byte[] key2 = decodeStringToBase64Bytes(decryptedString);
assertTrue(Arrays.equals(key1, key2));
assertArrayEquals(key1, key2);
}
@Test(expected = BadPaddingException.class)
@ -261,13 +261,8 @@ public class EncryptionTestIT extends AbstractIT {
byte[] privateKeyBytes = privateKey.getEncoded();
String privateKeyString = encodeBytesToBase64String(privateKeyBytes);
String encryptedString;
if (new Random().nextBoolean()) {
encryptedString = EncryptionUtils.encryptPrivateKey(privateKeyString, keyPhrase);
} else {
encryptedString = EncryptionUtils.encryptPrivateKeyOld(privateKeyString, keyPhrase);
}
String decryptedString = decryptPrivateKey(encryptedString, keyPhrase);
String encryptedString = CryptoHelper.INSTANCE.encryptPrivateKey(privateKeyString, keyPhrase);
String decryptedString = CryptoHelper.INSTANCE.decryptPrivateKey(encryptedString, keyPhrase);
assertEquals(privateKeyString, decryptedString);
}
@ -502,7 +497,7 @@ public class EncryptionTestIT extends AbstractIT {
// de-serialize
EncryptedFolderMetadataFileV1 encryptedFolderMetadata2 = deserializeJSON(encryptedJson,
new TypeToken<EncryptedFolderMetadataFileV1>() {
new TypeToken<>() {
});
// decrypt

View file

@ -3,7 +3,7 @@
*
* SPDX-FileCopyrightText: 2021-2022 Chris Narkiewicz <hello@ezaquarii.com>
* SPDX-FileCopyrightText: 2019-2021 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.util;

View file

@ -3,7 +3,7 @@
*
* SPDX-FileCopyrightText: 2020 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.utils

View file

@ -3,7 +3,7 @@
*
* SPDX-FileCopyrightText: 2022 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2022 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.utils

View file

@ -1,9 +1,9 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2023 Alper Ozturk <alper_ozturk@proton.me>
* SPDX-FileCopyrightText: 2023 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.utils
@ -12,18 +12,15 @@ import android.graphics.Bitmap
import android.graphics.drawable.BitmapDrawable
import androidx.test.platform.app.InstrumentationRegistry
import org.junit.After
import org.junit.Assert.fail
import org.junit.Before
import org.junit.Test
class DrawableUtilTests {
private var sut: DrawableUtil? = null
private var context: Context? = null
@Before
fun setUp() {
sut = DrawableUtil()
context = InstrumentationRegistry.getInstrumentation().context
}
@ -32,18 +29,13 @@ class DrawableUtilTests {
val bitmap: Bitmap = Bitmap.createBitmap(2, 2, Bitmap.Config.ARGB_8888)
val drawable = BitmapDrawable(context?.resources, bitmap)
val layerDrawable = sut?.addDrawableAsOverlay(drawable, drawable)
val layerDrawable = DrawableUtil.addDrawableAsOverlay(drawable, drawable)
if (layerDrawable == null) {
fail("Layer drawable expected to be not null")
}
assert(layerDrawable?.numberOfLayers == 2)
assert(layerDrawable.numberOfLayers == 2)
}
@After
fun destroy() {
sut = null
context = null
}
}

View file

@ -3,7 +3,7 @@
*
* SPDX-FileCopyrightText: 2023 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.utils
@ -118,7 +118,7 @@ nDO4ew==
)
val users = mutableListOf(
DecryptedUser(userId, cert)
DecryptedUser(userId, cert, null)
)
// val filedrop = mutableMapOf(

View file

@ -3,7 +3,7 @@
*
* SPDX-FileCopyrightText: 2023 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.utils

View file

@ -3,13 +3,14 @@
*
* SPDX-FileCopyrightText: 2023 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.utils
import com.google.gson.reflect.TypeToken
import com.nextcloud.client.account.MockUser
import com.nextcloud.common.User
import com.nextcloud.utils.extensions.findMetadataKeyByUserId
import com.owncloud.android.EncryptionIT
import com.owncloud.android.datamodel.OCFile
import com.owncloud.android.datamodel.e2e.v1.decrypted.Data
@ -221,7 +222,7 @@ class EncryptionUtilsV2IT : EncryptionIT() {
val metadataKeyBase64 = EncryptionUtils.generateKeyString()
val metadataKey = EncryptionUtils.decodeStringToBase64Bytes(metadataKeyBase64)
val user = DecryptedUser("t1", encryptionTestUtils.t1PublicKey)
val user = DecryptedUser("t1", encryptionTestUtils.t1PublicKey, null)
val encryptedUser = encryptionUtilsV2.encryptUser(user, metadataKey)
assertNotEquals(encryptedUser.encryptedMetadataKey, metadataKeyBase64)
@ -274,6 +275,11 @@ class EncryptionUtilsV2IT : EncryptionIT() {
arbitraryDataProvider
)
// V1 doesn't have decryptedMetadataKey so that we can ignore it for comparison
for (user in decrypted.users) {
user.decryptedMetadataKey = null
}
assertEquals(metadataFile, decrypted)
}
@ -290,7 +296,8 @@ class EncryptionUtilsV2IT : EncryptionIT() {
mimeType = MimeType.JPEG
},
EncryptionUtils.generateIV(),
EncryptionUtils.generateUid(), // random string, not real tag
// random string, not real tag
EncryptionUtils.generateUid(),
EncryptionUtils.generateKey(),
metadataFile,
storageManager
@ -404,8 +411,8 @@ class EncryptionUtilsV2IT : EncryptionIT() {
assertTrue(true) // if we reach this, test is successful
}
private fun generateDecryptedFileV1(): com.owncloud.android.datamodel.e2e.v1.decrypted.DecryptedFile {
return com.owncloud.android.datamodel.e2e.v1.decrypted.DecryptedFile().apply {
private fun generateDecryptedFileV1(): com.owncloud.android.datamodel.e2e.v1.decrypted.DecryptedFile =
com.owncloud.android.datamodel.e2e.v1.decrypted.DecryptedFile().apply {
encrypted = Data().apply {
key = EncryptionUtils.generateKeyString()
filename = "Random filename.jpg"
@ -415,7 +422,6 @@ class EncryptionUtilsV2IT : EncryptionIT() {
initializationVector = EncryptionUtils.generateKeyString()
authenticationTag = EncryptionUtils.generateKeyString()
}
}
@Test
fun testMigrateDecryptedV1ToV2() {
@ -488,7 +494,7 @@ class EncryptionUtilsV2IT : EncryptionIT() {
var metadataFile = generateDecryptedFolderMetadataFile(enc1, enc1Cert)
metadataFile = encryptionUtilsV2.addShareeToMetadata(metadataFile, enc2.accountName, enc2Cert)
metadataFile = encryptionUtilsV2.addShareeToMetadata(metadataFile, enc2.accountName, enc2Cert, null)
val encryptedMetadataFile = encryptionUtilsV2.encryptFolderMetadataFile(
metadataFile,
@ -540,7 +546,12 @@ class EncryptionUtilsV2IT : EncryptionIT() {
val enc1 = MockUser("enc1", "Nextcloud")
val enc2 = MockUser("enc2", "Nextcloud")
var metadataFile = generateDecryptedFolderMetadataFile(enc1, enc1Cert)
metadataFile = encryptionUtilsV2.addShareeToMetadata(metadataFile, enc2.accountName, enc2Cert)
metadataFile = encryptionUtilsV2.addShareeToMetadata(
metadataFile,
enc2.accountName,
enc2Cert,
metadataFile.users.findMetadataKeyByUserId(enc2.accountName)
)
assertEquals(2, metadataFile.users.size)
@ -585,7 +596,7 @@ class EncryptionUtilsV2IT : EncryptionIT() {
)
val users = mutableListOf(
DecryptedUser(user.accountName, cert)
DecryptedUser(user.accountName, cert, null)
)
metadata.keyChecksums.add(encryptionUtilsV2.hashMetadataKey(metadata.metadataKey))
@ -733,8 +744,6 @@ class EncryptionUtilsV2IT : EncryptionIT() {
|Rei/RGBQ==","userId": "john"}],"version": "2"}
""".trimMargin()
val base64Metadata = EncryptionUtils.encodeStringToBase64String(metadata)
val privateKey = EncryptionUtils.PEMtoPrivateKey(encryptionTestUtils.t1PrivateKey)
val certificateT1 = EncryptionUtils.convertCertFromString(encryptionTestUtils.t1PublicKey)
val certificateEnc2 = EncryptionUtils.convertCertFromString(enc2Cert)
@ -745,23 +754,18 @@ class EncryptionUtilsV2IT : EncryptionIT() {
metadata
)
val base64Ans = encryptionUtilsV2.extractSignedString(signed)
// verify
val certs = listOf(
certificateEnc2,
certificateT1
)
assertTrue(encryptionUtilsV2.verifySignedMessage(signed, certs))
assertTrue(encryptionUtilsV2.verifySignedMessage(base64Ans, base64Metadata, certs))
assertTrue(encryptionUtilsV2.verifySignedData(signed, certs))
}
@Throws(Throwable::class)
@Test
fun sign() {
val sut = "randomstring123"
val json = "randomstring123"
val jsonBase64 = EncryptionUtils.encodeStringToBase64String(json)
val privateKey = EncryptionUtils.PEMtoPrivateKey(encryptionTestUtils.t1PrivateKey)
val certificate = EncryptionUtils.convertCertFromString(encryptionTestUtils.t1PublicKey)
@ -772,15 +776,12 @@ class EncryptionUtilsV2IT : EncryptionIT() {
sut
)
val base64Ans = encryptionUtilsV2.extractSignedString(signed)
// verify
val certs = listOf(
EncryptionUtils.convertCertFromString(enc2Cert),
certificate
)
assertTrue(encryptionUtilsV2.verifySignedMessage(signed, certs))
assertTrue(encryptionUtilsV2.verifySignedMessage(base64Ans, jsonBase64, certs))
assertTrue(encryptionUtilsV2.verifySignedData(signed, certs))
}
@Test
@ -856,6 +857,11 @@ class EncryptionUtilsV2IT : EncryptionIT() {
arbitraryDataProvider
)
// V1 doesn't have decryptedMetadataKey so that we can ignore it for comparison
for (user in decryptedFolderMetadata2.users) {
user.decryptedMetadataKey = null
}
// compare
assertTrue(
EncryptionTestIT.compareJsonStrings(

View file

@ -1,7 +1,7 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2024 Your Name <your@email.com>
* SPDX-FileCopyrightText: 2024 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

View file

@ -3,7 +3,7 @@
*
* SPDX-FileCopyrightText: 2022 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2022 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.utils

View file

@ -3,7 +3,7 @@
*
* SPDX-FileCopyrightText: 2020 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.utils
@ -141,7 +141,6 @@ class FileStorageUtilsIT : AbstractIT() {
assertEquals("Internal storage/", pathToUserFriendlyDisplay("/storage/emulated/0/"))
}
private fun pathToUserFriendlyDisplay(path: String): String {
return pathToUserFriendlyDisplay(path, targetContext, targetContext.resources)
}
private fun pathToUserFriendlyDisplay(path: String): String =
pathToUserFriendlyDisplay(path, targetContext, targetContext.resources)
}

View file

@ -2,7 +2,7 @@
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2020 Andy Scherzinger <info@andy-scherzinger.de>
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.utils

View file

@ -1,7 +1,7 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2024 Your Name <your@email.com>
* SPDX-FileCopyrightText: 2024 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
package com.owncloud.android.utils

View file

@ -2,7 +2,7 @@
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2020 Andy Scherzinger <info@andy-scherzinger.de>
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.utils
@ -11,6 +11,7 @@ import com.owncloud.android.AbstractIT
import com.owncloud.android.datamodel.MediaFolder
import com.owncloud.android.datamodel.MediaFolderType
import com.owncloud.android.datamodel.SyncedFolder
import com.owncloud.android.utils.SyncedFolderUtils.hasExcludePrefix
import org.apache.commons.io.FileUtils
import org.junit.AfterClass
import org.junit.Assert
@ -205,6 +206,21 @@ class SyncedFolderUtilsTest : AbstractIT() {
Assert.assertFalse(SyncedFolderUtils.isQualifyingMediaFolder(folder))
}
@Test
fun testInstantUploadPathIgnoreExcludedPrefixes() {
val testFiles = listOf(
"IMG_nnn.jpg",
"my_documents",
"Music",
".trashed_IMG_nnn.jpg",
".pending_IMG_nnn.jpg",
".nomedia",
".thumbdata_IMG_nnn",
".thumbnail"
).filter { !hasExcludePrefix(it) }
Assert.assertTrue(testFiles.size == 3)
}
companion object {
private const val SELFIE = "selfie.png"
private const val SCREENSHOT = "screenshot.JPG"

View file

@ -3,7 +3,7 @@
*
* SPDX-FileCopyrightText: 2023 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.owncloud.android.utils.theme
@ -17,9 +17,12 @@ import org.junit.Test
class CapabilityUtilsIT : AbstractIT() {
@Test
fun checkOutdatedWarning() {
assertFalse(test(NextcloudVersion.nextcloud_28))
assertFalse(test(NextcloudVersion.nextcloud_27))
assertFalse(test(NextcloudVersion.nextcloud_31))
assertFalse(test(NextcloudVersion.nextcloud_30))
assertTrue(test(NextcloudVersion.nextcloud_29))
assertTrue(test(NextcloudVersion.nextcloud_28))
assertTrue(test(NextcloudVersion.nextcloud_27))
assertTrue(test(NextcloudVersion.nextcloud_26))
assertTrue(test(NextcloudVersion.nextcloud_25))
assertTrue(test(NextcloudVersion.nextcloud_24))
@ -27,13 +30,8 @@ class CapabilityUtilsIT : AbstractIT() {
assertTrue(test(NextcloudVersion.nextcloud_22))
assertTrue(test(NextcloudVersion.nextcloud_21))
assertTrue(test(OwnCloudVersion.nextcloud_20))
assertTrue(test(OwnCloudVersion.nextcloud_19))
assertTrue(test(OwnCloudVersion.nextcloud_18))
assertTrue(test(OwnCloudVersion.nextcloud_17))
assertTrue(test(OwnCloudVersion.nextcloud_16))
}
private fun test(version: OwnCloudVersion): Boolean {
return CapabilityUtils.checkOutdatedWarning(targetContext.resources, version, false)
}
private fun test(version: OwnCloudVersion): Boolean =
CapabilityUtils.checkOutdatedWarning(targetContext.resources, version, false)
}