added DEV version to repo
This commit is contained in:
parent
1ef725ef20
commit
23e673bfdf
2135 changed files with 97033 additions and 21206 deletions
|
|
@ -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.nextcloud.client
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
* Nextcloud - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2021 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.nextcloud.client;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Nextcloud - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2025 Alper Ozturk <alper.ozturk@nextcloud.com>
|
||||
* SPDX-FileCopyrightText: 2019 Tobias Kaminsky <tobias@kaminsky.me>
|
||||
* SPDX-FileCopyrightText: 2019 Nextcloud GmbH
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
|
||||
*/
|
||||
package com.nextcloud.client
|
||||
|
||||
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.ui.activity.CommunityActivity
|
||||
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
|
||||
|
||||
class CommunityActivityIT : AbstractIT() {
|
||||
private val testClassName = "com.nextcloud.client.CommunityActivityIT"
|
||||
|
||||
@Before
|
||||
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 open() {
|
||||
launchActivity<CommunityActivity>().use { scenario ->
|
||||
scenario.onActivity { sut ->
|
||||
onIdleSync {
|
||||
val screenShotName = createName(testClassName + "_" + "open", "")
|
||||
onView(isRoot()).check(matches(isDisplayed()))
|
||||
screenshotViaName(sut, screenShotName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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.nextcloud.client;
|
||||
|
||||
|
|
|
|||
|
|
@ -3,26 +3,26 @@
|
|||
*
|
||||
* SPDX-FileCopyrightText: 2019 Tobias Kaminsky <tobias@kaminsky.me>
|
||||
* SPDX-FileCopyrightText: 2019 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.nextcloud.client
|
||||
|
||||
import android.app.Activity
|
||||
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.closeSoftKeyboard
|
||||
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||
import androidx.test.espresso.contrib.DrawerActions
|
||||
import androidx.test.espresso.contrib.NavigationViewActions
|
||||
import androidx.test.espresso.contrib.RecyclerViewActions
|
||||
import androidx.test.espresso.intent.rule.IntentsTestRule
|
||||
import androidx.test.espresso.matcher.ViewMatchers
|
||||
import androidx.test.espresso.matcher.ViewMatchers.hasDescendant
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withId
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withText
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import com.nextcloud.test.RetryTestRule
|
||||
import com.owncloud.android.AbstractOnServerIT
|
||||
import com.owncloud.android.R
|
||||
|
|
@ -35,33 +35,39 @@ import com.owncloud.android.lib.resources.shares.ShareType
|
|||
import com.owncloud.android.operations.CreateFolderOperation
|
||||
import com.owncloud.android.ui.activity.FileDisplayActivity
|
||||
import com.owncloud.android.ui.adapter.OCFileListItemViewHolder
|
||||
import org.junit.Assert
|
||||
import com.owncloud.android.utils.EspressoIdlingResource
|
||||
import org.junit.After
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
|
||||
class FileDisplayActivityIT : AbstractOnServerIT() {
|
||||
@get:Rule
|
||||
val activityRule = IntentsTestRule(
|
||||
FileDisplayActivity::class.java,
|
||||
true,
|
||||
false
|
||||
)
|
||||
@Before
|
||||
fun registerIdlingResource() {
|
||||
IdlingRegistry.getInstance().register(EspressoIdlingResource.countingIdlingResource)
|
||||
}
|
||||
|
||||
@After
|
||||
fun unregisterIdlingResource() {
|
||||
IdlingRegistry.getInstance().unregister(EspressoIdlingResource.countingIdlingResource)
|
||||
}
|
||||
|
||||
@get:Rule
|
||||
val retryRule = RetryTestRule() // showShares is flaky
|
||||
|
||||
// @ScreenshotTest // todo run without real server
|
||||
@Suppress("DEPRECATION")
|
||||
@Test
|
||||
fun showShares() {
|
||||
Assert.assertTrue(ExistenceCheckRemoteOperation("/shareToAdmin/", true).execute(client).isSuccess)
|
||||
Assert.assertTrue(CreateFolderRemoteOperation("/shareToAdmin/", true).execute(client).isSuccess)
|
||||
Assert.assertTrue(CreateFolderRemoteOperation("/shareToGroup/", true).execute(client).isSuccess)
|
||||
Assert.assertTrue(CreateFolderRemoteOperation("/shareViaLink/", true).execute(client).isSuccess)
|
||||
Assert.assertTrue(CreateFolderRemoteOperation("/noShare/", true).execute(client).isSuccess)
|
||||
// assertTrue(new CreateFolderRemoteOperation("/shareToCircle/", true).execute(client).isSuccess());
|
||||
assertTrue(ExistenceCheckRemoteOperation("/shareToAdmin/", true).execute(client).isSuccess)
|
||||
assertTrue(CreateFolderRemoteOperation("/shareToAdmin/", true).execute(client).isSuccess)
|
||||
assertTrue(CreateFolderRemoteOperation("/shareToGroup/", true).execute(client).isSuccess)
|
||||
assertTrue(CreateFolderRemoteOperation("/shareViaLink/", true).execute(client).isSuccess)
|
||||
assertTrue(CreateFolderRemoteOperation("/noShare/", true).execute(client).isSuccess)
|
||||
|
||||
// share folder to user "admin"
|
||||
Assert.assertTrue(
|
||||
assertTrue(
|
||||
CreateShareRemoteOperation(
|
||||
"/shareToAdmin/",
|
||||
ShareType.USER,
|
||||
|
|
@ -73,7 +79,7 @@ class FileDisplayActivityIT : AbstractOnServerIT() {
|
|||
)
|
||||
|
||||
// share folder via public link
|
||||
Assert.assertTrue(
|
||||
assertTrue(
|
||||
CreateShareRemoteOperation(
|
||||
"/shareViaLink/",
|
||||
ShareType.PUBLIC_LINK,
|
||||
|
|
@ -85,7 +91,7 @@ class FileDisplayActivityIT : AbstractOnServerIT() {
|
|||
)
|
||||
|
||||
// share folder to group
|
||||
Assert.assertTrue(
|
||||
assertTrue(
|
||||
CreateShareRemoteOperation(
|
||||
"/shareToGroup/",
|
||||
ShareType.GROUP,
|
||||
|
|
@ -96,101 +102,53 @@ class FileDisplayActivityIT : AbstractOnServerIT() {
|
|||
).execute(client).isSuccess
|
||||
)
|
||||
|
||||
// share folder to circle
|
||||
// get share
|
||||
// RemoteOperationResult searchResult = new GetShareesRemoteOperation("publicCircle", 1, 50).execute(client);
|
||||
// assertTrue(searchResult.getLogMessage(), searchResult.isSuccess());
|
||||
//
|
||||
// JSONObject resultJson = (JSONObject) searchResult.getData().get(0);
|
||||
// String circleId = resultJson.getJSONObject("value").getString("shareWith");
|
||||
//
|
||||
// assertTrue(new CreateShareRemoteOperation("/shareToCircle/",
|
||||
// ShareType.CIRCLE,
|
||||
// circleId,
|
||||
// false,
|
||||
// "",
|
||||
// OCShare.DEFAULT_PERMISSION)
|
||||
// .execute(client).isSuccess());
|
||||
launchActivity<FileDisplayActivity>().use { scenario ->
|
||||
scenario.onActivity { sut ->
|
||||
onIdleSync {
|
||||
// open drawer
|
||||
onView(withId(R.id.drawer_layout)).perform(DrawerActions.open())
|
||||
|
||||
val sut: Activity = activityRule.launchActivity(null)
|
||||
InstrumentationRegistry.getInstrumentation().waitForIdleSync()
|
||||
|
||||
// open drawer
|
||||
onView(withId(R.id.drawer_layout)).perform(DrawerActions.open())
|
||||
|
||||
// click "shared"
|
||||
onView(withId(R.id.nav_view))
|
||||
.perform(NavigationViewActions.navigateTo(R.id.nav_shared))
|
||||
shortSleep()
|
||||
shortSleep()
|
||||
// screenshot(sut) // todo run without real server
|
||||
// click "shared"
|
||||
onView(withId(R.id.nav_view))
|
||||
.perform(NavigationViewActions.navigateTo(R.id.nav_shared))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
@Test
|
||||
fun allFiles() {
|
||||
val sut = activityRule.launchActivity(null)
|
||||
launchActivity<FileDisplayActivity>().use { scenario ->
|
||||
scenario.onActivity { sut ->
|
||||
onIdleSync {
|
||||
EspressoIdlingResource.increment()
|
||||
// given test folder
|
||||
assertTrue(
|
||||
CreateFolderOperation("/test/", user, targetContext, storageManager)
|
||||
.execute(client)
|
||||
.isSuccess
|
||||
)
|
||||
|
||||
// given test folder
|
||||
Assert.assertTrue(
|
||||
CreateFolderOperation("/test/", user, targetContext, storageManager)
|
||||
.execute(client)
|
||||
.isSuccess
|
||||
)
|
||||
// navigate into it
|
||||
val test = storageManager.getFileByPath("/test/")
|
||||
sut.file = test
|
||||
sut.startSyncFolderOperation(test, false)
|
||||
assertEquals(storageManager.getFileByPath("/test/"), sut.currentDir)
|
||||
EspressoIdlingResource.decrement()
|
||||
|
||||
// navigate into it
|
||||
val test = storageManager.getFileByPath("/test/")
|
||||
sut.file = test
|
||||
sut.startSyncFolderOperation(test, false)
|
||||
Assert.assertEquals(storageManager.getFileByPath("/test/"), sut.currentDir)
|
||||
// open drawer
|
||||
onView(withId(R.id.drawer_layout)).perform(DrawerActions.open())
|
||||
|
||||
// open drawer
|
||||
onView(withId(R.id.drawer_layout)).perform(DrawerActions.open())
|
||||
// click "all files"
|
||||
onView(withId(R.id.nav_view))
|
||||
.perform(NavigationViewActions.navigateTo(R.id.nav_all_files))
|
||||
|
||||
// click "all files"
|
||||
onView(withId(R.id.nav_view))
|
||||
.perform(NavigationViewActions.navigateTo(R.id.nav_all_files))
|
||||
|
||||
// then should be in root again
|
||||
shortSleep()
|
||||
Assert.assertEquals(storageManager.getFileByPath("/"), sut.currentDir)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun checkToolbarTitleOnNavigation() {
|
||||
// Create folder structure
|
||||
val topFolder = "folder1"
|
||||
val childFolder = "folder2"
|
||||
|
||||
CreateFolderOperation("/$topFolder/", user, targetContext, storageManager)
|
||||
.execute(client)
|
||||
|
||||
CreateFolderOperation("/$topFolder/$childFolder/", user, targetContext, storageManager)
|
||||
.execute(client)
|
||||
|
||||
activityRule.launchActivity(null)
|
||||
|
||||
shortSleep()
|
||||
|
||||
// go into "foo"
|
||||
onView(withText(topFolder)).perform(click())
|
||||
shortSleep()
|
||||
|
||||
// check title is right
|
||||
checkToolbarTitle(topFolder)
|
||||
|
||||
// go into "bar"
|
||||
onView(withText(childFolder)).perform(click())
|
||||
shortSleep()
|
||||
|
||||
// check title is right
|
||||
checkToolbarTitle(childFolder)
|
||||
|
||||
// browse back up, we should be back in "foo"
|
||||
Espresso.pressBack()
|
||||
shortSleep()
|
||||
|
||||
// check title is right
|
||||
checkToolbarTitle(topFolder)
|
||||
// then should be in root again
|
||||
assertEquals(storageManager.getFileByPath("/"), sut.currentDir)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkToolbarTitle(childFolder: String) {
|
||||
|
|
@ -203,8 +161,10 @@ class FileDisplayActivityIT : AbstractOnServerIT() {
|
|||
)
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
@Test
|
||||
fun browseFavoriteAndBack() {
|
||||
EspressoIdlingResource.increment()
|
||||
// Create folder structure
|
||||
val topFolder = "folder1"
|
||||
|
||||
|
|
@ -212,52 +172,68 @@ class FileDisplayActivityIT : AbstractOnServerIT() {
|
|||
.execute(client)
|
||||
ToggleFavoriteRemoteOperation(true, "/$topFolder/")
|
||||
.execute(client)
|
||||
EspressoIdlingResource.decrement()
|
||||
|
||||
val sut = activityRule.launchActivity(null)
|
||||
launchActivity<FileDisplayActivity>().use { scenario ->
|
||||
scenario.onActivity { sut ->
|
||||
onIdleSync {
|
||||
// navigate to favorites
|
||||
onView(withId(R.id.drawer_layout)).perform(DrawerActions.open())
|
||||
onView(withId(R.id.nav_view))
|
||||
.perform(NavigationViewActions.navigateTo(R.id.nav_favorites))
|
||||
|
||||
// navigate to favorites
|
||||
onView(withId(R.id.drawer_layout)).perform(DrawerActions.open())
|
||||
onView(withId(R.id.nav_view))
|
||||
.perform(NavigationViewActions.navigateTo(R.id.nav_favorites))
|
||||
shortSleep()
|
||||
// check sort button is not shown, favorites are not sortable
|
||||
onView(
|
||||
withId(R.id.sort_button)
|
||||
).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE)))
|
||||
|
||||
// check sort button is not shown, favorites are not sortable
|
||||
onView(withId(R.id.sort_button)).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE)))
|
||||
// browse into folder
|
||||
onView(withId(R.id.list_root))
|
||||
.perform(closeSoftKeyboard())
|
||||
.perform(
|
||||
RecyclerViewActions.actionOnItemAtPosition<OCFileListItemViewHolder>(
|
||||
0,
|
||||
click()
|
||||
)
|
||||
)
|
||||
checkToolbarTitle(topFolder)
|
||||
// sort button should now be visible
|
||||
onView(withId(R.id.sort_button)).check(matches(ViewMatchers.isDisplayed()))
|
||||
|
||||
// browse into folder
|
||||
onView(withId(R.id.list_root))
|
||||
.perform(closeSoftKeyboard())
|
||||
.perform(
|
||||
RecyclerViewActions.actionOnItemAtPosition<OCFileListItemViewHolder>(
|
||||
0,
|
||||
click()
|
||||
)
|
||||
)
|
||||
shortSleep()
|
||||
checkToolbarTitle(topFolder)
|
||||
// sort button should now be visible
|
||||
onView(withId(R.id.sort_button)).check(matches(ViewMatchers.isDisplayed()))
|
||||
|
||||
// browse back, should be back to All Files
|
||||
Espresso.pressBack()
|
||||
checkToolbarTitle(sut.getString(R.string.app_name))
|
||||
onView(withId(R.id.sort_button)).check(matches(ViewMatchers.isDisplayed()))
|
||||
// browse back, should be back to All Files
|
||||
Espresso.pressBack()
|
||||
checkToolbarTitle(sut.getString(R.string.app_name))
|
||||
onView(withId(R.id.sort_button)).check(matches(ViewMatchers.isDisplayed()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
@Test
|
||||
fun switchToGridView() {
|
||||
activityRule.launchActivity(null)
|
||||
Assert.assertTrue(
|
||||
CreateFolderOperation("/test/", user, targetContext, storageManager)
|
||||
.execute(client)
|
||||
.isSuccess
|
||||
)
|
||||
onView(withId(R.id.switch_grid_view_button)).perform(click())
|
||||
launchActivity<FileDisplayActivity>().use { scenario ->
|
||||
scenario.onActivity { sut ->
|
||||
onIdleSync {
|
||||
assertTrue(
|
||||
CreateFolderOperation("/test/", user, targetContext, storageManager)
|
||||
.execute(client)
|
||||
.isSuccess
|
||||
)
|
||||
onView(withId(R.id.switch_grid_view_button)).perform(click())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun openAccountSwitcher() {
|
||||
activityRule.launchActivity(null)
|
||||
onView(withId(R.id.switch_account_button)).perform(click())
|
||||
launchActivity<FileDisplayActivity>().use { scenario ->
|
||||
scenario.onActivity { sut ->
|
||||
onIdleSync {
|
||||
onView(withId(R.id.switch_account_button)).perform(click())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,35 +1,50 @@
|
|||
/*
|
||||
* Nextcloud - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2024 Alper Ozturk <alper.ozturk@nextcloud.com>
|
||||
* SPDX-FileCopyrightText: 2019 Tobias Kaminsky <tobias@kaminsky.me>
|
||||
* SPDX-FileCopyrightText: 2019 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.nextcloud.client
|
||||
|
||||
import android.Manifest
|
||||
import androidx.test.espresso.Espresso
|
||||
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.contrib.DrawerActions
|
||||
import androidx.test.espresso.contrib.NavigationViewActions
|
||||
import androidx.test.espresso.intent.rule.IntentsTestRule
|
||||
import androidx.test.espresso.matcher.ViewMatchers
|
||||
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.lib.common.utils.Log_OC
|
||||
import com.owncloud.android.ui.activity.FileDisplayActivity
|
||||
import com.owncloud.android.ui.fragment.EmptyListState
|
||||
import com.owncloud.android.utils.EspressoIdlingResource
|
||||
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
|
||||
|
||||
class FileDisplayActivityScreenshotIT : AbstractIT() {
|
||||
@get:Rule
|
||||
val activityRule = IntentsTestRule(
|
||||
FileDisplayActivity::class.java,
|
||||
true,
|
||||
false
|
||||
)
|
||||
private val testClassName = "com.nextcloud.client.FileDisplayActivityScreenshotIT"
|
||||
|
||||
@Before
|
||||
fun registerIdlingResource() {
|
||||
IdlingRegistry.getInstance().register(EspressoIdlingResource.countingIdlingResource)
|
||||
}
|
||||
|
||||
@After
|
||||
fun unregisterIdlingResource() {
|
||||
IdlingRegistry.getInstance().unregister(EspressoIdlingResource.countingIdlingResource)
|
||||
}
|
||||
|
||||
@get:Rule
|
||||
val permissionRule: GrantPermissionRule = GrantPermissionRule.grant(
|
||||
|
|
@ -41,82 +56,110 @@ class FileDisplayActivityScreenshotIT : AbstractIT() {
|
|||
}
|
||||
|
||||
@Test
|
||||
@UiThread
|
||||
@ScreenshotTest
|
||||
fun open() {
|
||||
try {
|
||||
val sut = activityRule.launchActivity(null)
|
||||
launchActivity<FileDisplayActivity>().use { scenario ->
|
||||
scenario.onActivity { sut ->
|
||||
onIdleSync {
|
||||
EspressoIdlingResource.increment()
|
||||
|
||||
shortSleep()
|
||||
sut.runOnUiThread {
|
||||
sut.listOfFilesFragment!!.setFabEnabled(false)
|
||||
sut.resetScrolling(true)
|
||||
sut.listOfFilesFragment!!.setEmptyListLoadingMessage()
|
||||
sut.listOfFilesFragment!!.isLoading = false
|
||||
sut.run {
|
||||
listOfFilesFragment?.let {
|
||||
it.setFabEnabled(false)
|
||||
resetScrolling(true)
|
||||
it.setEmptyListMessage(EmptyListState.LOADING)
|
||||
it.isLoading = false
|
||||
}
|
||||
}
|
||||
|
||||
EspressoIdlingResource.decrement()
|
||||
|
||||
val screenShotName = createName(testClassName + "_" + "open", "")
|
||||
onView(isRoot()).check(matches(isDisplayed()))
|
||||
screenshotViaName(sut, screenShotName)
|
||||
}
|
||||
}
|
||||
}
|
||||
shortSleep()
|
||||
waitForIdleSync()
|
||||
screenshot(sut)
|
||||
} catch (e: SecurityException) {
|
||||
Log_OC.e(TAG, "Error caught at open $e")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThread
|
||||
@ScreenshotTest
|
||||
fun showMediaThenAllFiles() {
|
||||
try {
|
||||
val fileDisplayActivity = activityRule.launchActivity(null)
|
||||
val sut = fileDisplayActivity.listOfFilesFragment
|
||||
Assert.assertNotNull(sut)
|
||||
sut!!.setFabEnabled(false)
|
||||
sut.setEmptyListLoadingMessage()
|
||||
sut.isLoading = false
|
||||
launchActivity<FileDisplayActivity>().use { scenario ->
|
||||
scenario.onActivity { sut ->
|
||||
onIdleSync {
|
||||
EspressoIdlingResource.increment()
|
||||
val fragment = sut.listOfFilesFragment
|
||||
Assert.assertNotNull(fragment)
|
||||
fragment!!.setFabEnabled(false)
|
||||
fragment.setEmptyListMessage(EmptyListState.LOADING)
|
||||
fragment.isLoading = false
|
||||
EspressoIdlingResource.decrement()
|
||||
|
||||
// open drawer
|
||||
Espresso.onView(ViewMatchers.withId(R.id.drawer_layout)).perform(DrawerActions.open())
|
||||
onView(ViewMatchers.withId(R.id.drawer_layout)).perform(DrawerActions.open())
|
||||
|
||||
// click "all files"
|
||||
Espresso.onView(ViewMatchers.withId(R.id.nav_view))
|
||||
.perform(NavigationViewActions.navigateTo(R.id.nav_gallery))
|
||||
onView(ViewMatchers.withId(R.id.nav_view))
|
||||
.perform(NavigationViewActions.navigateTo(R.id.nav_gallery))
|
||||
|
||||
// wait
|
||||
shortSleep()
|
||||
onView(ViewMatchers.withId(R.id.drawer_layout)).perform(DrawerActions.open())
|
||||
onView(ViewMatchers.withId(R.id.nav_view))
|
||||
.perform(NavigationViewActions.navigateTo(R.id.nav_all_files))
|
||||
|
||||
// click "all files"
|
||||
Espresso.onView(ViewMatchers.withId(R.id.drawer_layout)).perform(DrawerActions.open())
|
||||
Espresso.onView(ViewMatchers.withId(R.id.nav_view))
|
||||
.perform(NavigationViewActions.navigateTo(R.id.nav_all_files))
|
||||
EspressoIdlingResource.increment()
|
||||
fragment.setFabEnabled(false)
|
||||
fragment.setEmptyListMessage(EmptyListState.LOADING)
|
||||
fragment.isLoading = false
|
||||
EspressoIdlingResource.decrement()
|
||||
|
||||
// then compare screenshot
|
||||
shortSleep()
|
||||
sut.setFabEnabled(false)
|
||||
sut.setEmptyListLoadingMessage()
|
||||
sut.isLoading = false
|
||||
shortSleep()
|
||||
screenshot(fileDisplayActivity)
|
||||
val screenShotName = createName(testClassName + "_" + "showMediaThenAllFiles", "")
|
||||
onView(isRoot()).check(matches(isDisplayed()))
|
||||
screenshotViaName(sut, screenShotName)
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: SecurityException) {
|
||||
Log_OC.e(TAG, "Error caught at open $e")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThread
|
||||
@ScreenshotTest
|
||||
fun drawer() {
|
||||
try {
|
||||
val sut = activityRule.launchActivity(null)
|
||||
Espresso.onView(ViewMatchers.withId(R.id.drawer_layout)).perform(DrawerActions.open())
|
||||
launchActivity<FileDisplayActivity>().use { scenario ->
|
||||
scenario.onActivity { sut ->
|
||||
onIdleSync {
|
||||
onView(ViewMatchers.withId(R.id.drawer_layout)).perform(DrawerActions.open())
|
||||
|
||||
shortSleep()
|
||||
sut.runOnUiThread {
|
||||
sut.hideInfoBox()
|
||||
sut.resetScrolling(true)
|
||||
sut.listOfFilesFragment!!.setFabEnabled(false)
|
||||
sut.listOfFilesFragment!!.setEmptyListLoadingMessage()
|
||||
sut.listOfFilesFragment!!.isLoading = false
|
||||
EspressoIdlingResource.increment()
|
||||
|
||||
sut.run {
|
||||
hideInfoBox()
|
||||
resetScrolling(true)
|
||||
|
||||
listOfFilesFragment?.let {
|
||||
it.setFabEnabled(false)
|
||||
it.setEmptyListMessage(EmptyListState.LOADING)
|
||||
it.isLoading = false
|
||||
}
|
||||
}
|
||||
|
||||
EspressoIdlingResource.decrement()
|
||||
|
||||
val screenShotName = createName(testClassName + "_" + "drawer", "")
|
||||
onView(isRoot()).check(matches(isDisplayed()))
|
||||
screenshotViaName(sut, screenShotName)
|
||||
}
|
||||
}
|
||||
}
|
||||
shortSleep()
|
||||
waitForIdleSync()
|
||||
screenshot(sut)
|
||||
} catch (e: SecurityException) {
|
||||
Log_OC.e(TAG, "Error caught at open $e")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Nextcloud - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2025 Alper Ozturk <alper.ozturk@nextcloud.com>
|
||||
* SPDX-FileCopyrightText: 2019 Tobias Kaminsky <tobias@kaminsky.me>
|
||||
* SPDX-FileCopyrightText: 2019 Nextcloud GmbH
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
|
||||
*/
|
||||
package com.nextcloud.client
|
||||
|
||||
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.client.onboarding.FirstRunActivity
|
||||
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.Test
|
||||
|
||||
class FirstRunActivityIT : AbstractIT() {
|
||||
private val testClassName = "com.nextcloud.client.FirstRunActivityIT"
|
||||
|
||||
@Before
|
||||
fun registerIdlingResource() {
|
||||
IdlingRegistry.getInstance().register(EspressoIdlingResource.countingIdlingResource)
|
||||
}
|
||||
|
||||
@After
|
||||
fun unregisterIdlingResource() {
|
||||
IdlingRegistry.getInstance().unregister(EspressoIdlingResource.countingIdlingResource)
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThread
|
||||
@ScreenshotTest
|
||||
fun open() {
|
||||
launchActivity<FirstRunActivity>().use { scenario ->
|
||||
scenario.onActivity { sut ->
|
||||
onIdleSync {
|
||||
val screenShotName = createName(testClassName + "_" + "open", "")
|
||||
onView(isRoot()).check(matches(isDisplayed()))
|
||||
screenshotViaName(sut, screenShotName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,71 +1,109 @@
|
|||
/*
|
||||
* Nextcloud - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2025 Alper Ozturk <alper.ozturk@nextcloud.com>
|
||||
* SPDX-FileCopyrightText: 2019 Tobias Kaminsky <tobias@kaminsky.me>
|
||||
* SPDX-FileCopyrightText: 2019 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.nextcloud.client
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.os.Looper
|
||||
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.datamodel.ArbitraryDataProviderImpl
|
||||
import com.owncloud.android.ui.activity.RequestCredentialsActivity
|
||||
import com.owncloud.android.ui.activity.SettingsActivity
|
||||
import com.owncloud.android.utils.EncryptionUtils
|
||||
import com.owncloud.android.utils.EspressoIdlingResource
|
||||
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
|
||||
|
||||
@Suppress("FunctionNaming")
|
||||
class SettingsActivityIT : AbstractIT() {
|
||||
@get:Rule
|
||||
val activityRule = IntentsTestRule(
|
||||
SettingsActivity::class.java,
|
||||
true,
|
||||
false
|
||||
)
|
||||
private val testClassName = "com.nextcloud.client.SettingsActivityIT"
|
||||
|
||||
@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
|
||||
fun open() {
|
||||
val sut: Activity = activityRule.launchActivity(null)
|
||||
screenshot(sut)
|
||||
launchActivity<SettingsActivity>().use { scenario ->
|
||||
scenario.onActivity { sut ->
|
||||
onIdleSync {
|
||||
val screenShotName = createName(testClassName + "_" + "open", "")
|
||||
onView(isRoot()).check(matches(isDisplayed()))
|
||||
screenshotViaName(sut, screenShotName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThread
|
||||
@ScreenshotTest
|
||||
fun showMnemonic_Error() {
|
||||
val sut = activityRule.launchActivity(null)
|
||||
sut.handleMnemonicRequest(null)
|
||||
shortSleep()
|
||||
waitForIdleSync()
|
||||
screenshot(sut)
|
||||
launchActivity<SettingsActivity>().use { scenario ->
|
||||
scenario.onActivity { sut ->
|
||||
onIdleSync {
|
||||
sut.handleMnemonicRequest(null)
|
||||
val screenShotName = createName(testClassName + "_" + "showMnemonic_Error", "")
|
||||
onView(isRoot()).check(matches(isDisplayed()))
|
||||
screenshotViaName(sut, screenShotName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
@Test
|
||||
@UiThread
|
||||
fun showMnemonic() {
|
||||
if (Looper.myLooper() == null) {
|
||||
Looper.prepare()
|
||||
}
|
||||
val intent = Intent()
|
||||
intent.putExtra(RequestCredentialsActivity.KEY_CHECK_RESULT, RequestCredentialsActivity.KEY_CHECK_RESULT_TRUE)
|
||||
val arbitraryDataProvider = ArbitraryDataProviderImpl(targetContext)
|
||||
arbitraryDataProvider.storeOrUpdateKeyValue(user.accountName, EncryptionUtils.MNEMONIC, "Secret mnemonic")
|
||||
val sut = activityRule.launchActivity(null)
|
||||
sut.runOnUiThread {
|
||||
sut.handleMnemonicRequest(intent)
|
||||
val intent = Intent().apply {
|
||||
putExtra(RequestCredentialsActivity.KEY_CHECK_RESULT, RequestCredentialsActivity.KEY_CHECK_RESULT_TRUE)
|
||||
}
|
||||
|
||||
Looper.myLooper()?.quitSafely()
|
||||
Assert.assertTrue(true) // if we reach this, everything is ok
|
||||
ArbitraryDataProviderImpl(targetContext).run {
|
||||
storeOrUpdateKeyValue(user.accountName, EncryptionUtils.MNEMONIC, "Secret mnemonic")
|
||||
}
|
||||
|
||||
launchActivity<SettingsActivity>().use { scenario ->
|
||||
scenario.onActivity { sut ->
|
||||
onIdleSync {
|
||||
sut.handleMnemonicRequest(intent)
|
||||
onView(isRoot()).check(matches(isDisplayed()))
|
||||
Looper.myLooper()?.quitSafely()
|
||||
Assert.assertTrue(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* 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.nextcloud.client
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Looper
|
||||
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.client.preferences.SubFolderRule
|
||||
import com.owncloud.android.AbstractIT
|
||||
import com.owncloud.android.datamodel.MediaFolderType
|
||||
import com.owncloud.android.datamodel.SyncedFolder
|
||||
import com.owncloud.android.datamodel.SyncedFolderDisplayItem
|
||||
import com.owncloud.android.ui.activity.SyncedFoldersActivity
|
||||
import com.owncloud.android.ui.dialog.SyncedFolderPreferencesDialogFragment.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 SyncedFoldersActivityIT : AbstractIT() {
|
||||
private val testClassName = "com.nextcloud.client.SyncedFoldersActivityIT"
|
||||
|
||||
@Before
|
||||
fun registerIdlingResource() {
|
||||
IdlingRegistry.getInstance().register(EspressoIdlingResource.countingIdlingResource)
|
||||
}
|
||||
|
||||
@After
|
||||
fun unregisterIdlingResource() {
|
||||
IdlingRegistry.getInstance().unregister(EspressoIdlingResource.countingIdlingResource)
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThread
|
||||
@ScreenshotTest
|
||||
fun open() {
|
||||
launchActivity<SyncedFoldersActivity>().use { scenario ->
|
||||
scenario.onActivity { sut ->
|
||||
onIdleSync {
|
||||
EspressoIdlingResource.increment()
|
||||
sut.adapter.clear()
|
||||
EspressoIdlingResource.decrement()
|
||||
|
||||
val screenShotName = createName(testClassName + "_" + "open", "")
|
||||
onView(isRoot()).check(matches(isDisplayed()))
|
||||
screenshotViaName(sut.binding.emptyList.emptyListView, screenShotName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThread
|
||||
@ScreenshotTest
|
||||
fun testSyncedFolderDialog() {
|
||||
val item = SyncedFolderDisplayItem(
|
||||
1,
|
||||
"/sdcard/DCIM/",
|
||||
"/InstantUpload/",
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
"test@https://nextcloud.localhost",
|
||||
0,
|
||||
0,
|
||||
true,
|
||||
1000,
|
||||
"Name",
|
||||
MediaFolderType.IMAGE,
|
||||
false,
|
||||
SubFolderRule.YEAR_MONTH,
|
||||
false,
|
||||
SyncedFolder.NOT_SCANNED_YET
|
||||
)
|
||||
val fragment = newInstance(item, 0)
|
||||
|
||||
val intent = Intent(targetContext, SyncedFoldersActivity::class.java)
|
||||
launchActivity<SyncedFoldersActivity>(intent).use { scenario ->
|
||||
scenario.onActivity { sut ->
|
||||
onIdleSync {
|
||||
EspressoIdlingResource.increment()
|
||||
fragment?.show(sut.supportFragmentManager, "")
|
||||
EspressoIdlingResource.decrement()
|
||||
|
||||
val screenShotName = createName(testClassName + "_" + "testSyncedFolderDialog", "")
|
||||
onView(isRoot()).check(matches(isDisplayed()))
|
||||
screenshot(fragment?.requireDialog()?.window?.decorView, screenShotName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThread
|
||||
@ScreenshotTest
|
||||
fun showPowerCheckDialog() {
|
||||
if (Looper.myLooper() == null) {
|
||||
Looper.prepare()
|
||||
}
|
||||
|
||||
val intent = Intent(targetContext, SyncedFoldersActivity::class.java)
|
||||
|
||||
launchActivity<SyncedFoldersActivity>(intent).use { scenario ->
|
||||
scenario.onActivity { sut ->
|
||||
onIdleSync {
|
||||
EspressoIdlingResource.increment()
|
||||
val dialog = sut.buildPowerCheckDialog()
|
||||
dialog.show()
|
||||
EspressoIdlingResource.decrement()
|
||||
|
||||
val screenShotName = createName(testClassName + "_" + "showPowerCheckDialog", "")
|
||||
onView(isRoot()).check(matches(isDisplayed()))
|
||||
screenshot(dialog.window?.decorView, screenShotName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
* SPDX-FileCopyrightText: 2023 Álvaro Brey <alvaro@alvarobrey.com>
|
||||
* SPDX-FileCopyrightText: 2019-2024 Nextcloud GmbH
|
||||
* SPDX-FileCopyrightText: 2019 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.nextcloud.client
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* 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.nextcloud.client
|
||||
|
||||
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.contrib.DrawerActions
|
||||
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
|
||||
import androidx.test.espresso.matcher.ViewMatchers.isRoot
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withId
|
||||
import com.owncloud.android.AbstractIT
|
||||
import com.owncloud.android.R
|
||||
import com.owncloud.android.ui.activity.UploadListActivity
|
||||
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 UploadListActivityActivityIT : AbstractIT() {
|
||||
private val testClassName = "com.nextcloud.client.UploadListActivityActivityIT"
|
||||
|
||||
@Before
|
||||
fun registerIdlingResource() {
|
||||
IdlingRegistry.getInstance().register(EspressoIdlingResource.countingIdlingResource)
|
||||
}
|
||||
|
||||
@After
|
||||
fun unregisterIdlingResource() {
|
||||
IdlingRegistry.getInstance().unregister(EspressoIdlingResource.countingIdlingResource)
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThread
|
||||
@ScreenshotTest
|
||||
fun openDrawer() {
|
||||
launchActivity<UploadListActivity>().use { scenario ->
|
||||
scenario.onActivity { sut ->
|
||||
onIdleSync {
|
||||
onView(isRoot()).check(matches(isDisplayed()))
|
||||
onView(withId(R.id.drawer_layout)).perform(DrawerActions.open())
|
||||
|
||||
val screenShotName = createName(testClassName + "_" + "openDrawer", "")
|
||||
screenshotViaName(sut, screenShotName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* 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.nextcloud.client.account
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* 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.nextcloud.client.account
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* SPDX-FileCopyrightText: 2019 Tobias Kaminsky <tobias@kaminsky.me>
|
||||
* SPDX-FileCopyrightText: 2019 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.nextcloud.client.account;
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* 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.nextcloud.client.account
|
||||
|
||||
|
|
@ -12,7 +12,7 @@ import android.net.Uri
|
|||
import android.os.Parcel
|
||||
import com.owncloud.android.lib.common.OwnCloudAccount
|
||||
import com.owncloud.android.lib.common.OwnCloudBasicCredentials
|
||||
import com.owncloud.android.lib.resources.status.OwnCloudVersion
|
||||
import com.owncloud.android.lib.resources.status.NextcloudVersion
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertNotSame
|
||||
|
|
@ -31,7 +31,7 @@ class RegisteredUserTest {
|
|||
val ownCloudAccount = OwnCloudAccount(uri, credentials)
|
||||
val server = Server(
|
||||
uri = URI(uri.toString()),
|
||||
version = OwnCloudVersion.nextcloud_17
|
||||
version = NextcloudVersion.nextcloud_31
|
||||
)
|
||||
return RegisteredUser(
|
||||
account = account,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
* Nextcloud - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2019-2023 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.nextcloud.client.account;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,15 @@
|
|||
/*
|
||||
* Nextcloud - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2024 Alper Ozturk <alper_ozturk@proton.me>
|
||||
* SPDX-FileCopyrightText: 2024 Alper Ozturk <alper.ozturk@nextcloud.com>
|
||||
* SPDX-FileCopyrightText: 2024 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.nextcloud.client.assistant
|
||||
|
||||
import com.nextcloud.client.assistant.repository.AssistantRepository
|
||||
import com.owncloud.android.AbstractOnServerIT
|
||||
import com.owncloud.android.lib.resources.assistant.v2.model.TaskTypeData
|
||||
import com.owncloud.android.lib.resources.status.NextcloudVersion
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Before
|
||||
|
|
@ -21,7 +22,7 @@ class AssistantRepositoryTests : AbstractOnServerIT() {
|
|||
|
||||
@Before
|
||||
fun setup() {
|
||||
sut = AssistantRepository(nextcloudClient)
|
||||
sut = AssistantRepository(nextcloudClient, capability)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -33,10 +34,7 @@ class AssistantRepositoryTests : AbstractOnServerIT() {
|
|||
}
|
||||
|
||||
val result = sut?.getTaskTypes()
|
||||
assertTrue(result?.isSuccess == true)
|
||||
|
||||
val taskTypes = result?.resultData?.types
|
||||
assertTrue(taskTypes?.isNotEmpty() == true)
|
||||
assertTrue(result?.isNotEmpty() == true)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -48,10 +46,7 @@ class AssistantRepositoryTests : AbstractOnServerIT() {
|
|||
}
|
||||
|
||||
val result = sut?.getTaskList("assistant")
|
||||
assertTrue(result?.isSuccess == true)
|
||||
|
||||
val taskList = result?.resultData?.tasks
|
||||
assertTrue(taskList?.isEmpty() == true || (taskList?.size ?: 0) > 0)
|
||||
assertTrue(result?.isEmpty() == true || (result?.size ?: 0) > 0)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -63,8 +58,14 @@ class AssistantRepositoryTests : AbstractOnServerIT() {
|
|||
}
|
||||
|
||||
val input = "Give me some random output for test purpose"
|
||||
val type = "OCP\\TextProcessing\\FreePromptTaskType"
|
||||
val result = sut?.createTask(input, type)
|
||||
val taskType = TaskTypeData(
|
||||
"core:text2text",
|
||||
"Free text to text prompt",
|
||||
"Runs an arbitrary prompt through a language model that returns a reply",
|
||||
emptyMap(),
|
||||
emptyMap()
|
||||
)
|
||||
val result = sut?.createTask(input, taskType)
|
||||
assertTrue(result?.isSuccess == true)
|
||||
}
|
||||
|
||||
|
|
@ -80,13 +81,11 @@ class AssistantRepositoryTests : AbstractOnServerIT() {
|
|||
|
||||
sleep(120)
|
||||
|
||||
val resultOfTaskList = sut?.getTaskList("assistant")
|
||||
assertTrue(resultOfTaskList?.isSuccess == true)
|
||||
val taskList = sut?.getTaskList("assistant")
|
||||
assertTrue(taskList != null)
|
||||
|
||||
sleep(120)
|
||||
|
||||
val taskList = resultOfTaskList?.resultData?.tasks
|
||||
|
||||
assert((taskList?.size ?: 0) > 0)
|
||||
|
||||
val result = sut?.deleteTask(taskList!!.first().id)
|
||||
|
|
|
|||
|
|
@ -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.nextcloud.client.database.migrations
|
||||
|
||||
|
|
|
|||
|
|
@ -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.nextcloud.client.documentscan
|
||||
|
||||
|
|
|
|||
|
|
@ -3,39 +3,68 @@
|
|||
*
|
||||
* 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.nextcloud.client.etm
|
||||
|
||||
import android.app.Activity
|
||||
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.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 EtmActivityTest : AbstractIT() {
|
||||
@get:Rule
|
||||
var activityRule = IntentsTestRule(EtmActivity::class.java, true, false)
|
||||
private val testClassName = "com.nextcloud.client.etm.EtmActivityTest"
|
||||
|
||||
@Before
|
||||
fun registerIdlingResource() {
|
||||
IdlingRegistry.getInstance().register(EspressoIdlingResource.countingIdlingResource)
|
||||
}
|
||||
|
||||
@After
|
||||
fun unregisterIdlingResource() {
|
||||
IdlingRegistry.getInstance().unregister(EspressoIdlingResource.countingIdlingResource)
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThread
|
||||
@ScreenshotTest
|
||||
fun overview() {
|
||||
val sut: Activity = activityRule.launchActivity(null)
|
||||
|
||||
waitForIdleSync()
|
||||
|
||||
screenshot(sut)
|
||||
launchActivity<EtmActivity>().use { scenario ->
|
||||
scenario.onActivity { sut ->
|
||||
onIdleSync {
|
||||
val screenShotName = createName(testClassName + "_" + "overview", "")
|
||||
onView(isRoot()).check(matches(isDisplayed()))
|
||||
screenshotViaName(sut, screenShotName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThread
|
||||
@ScreenshotTest
|
||||
fun accounts() {
|
||||
val sut: EtmActivity = activityRule.launchActivity(null)
|
||||
launchActivity<EtmActivity>().use { scenario ->
|
||||
scenario.onActivity { sut ->
|
||||
onIdleSync {
|
||||
EspressoIdlingResource.increment()
|
||||
sut.vm.onPageSelected(1)
|
||||
EspressoIdlingResource.decrement()
|
||||
|
||||
UiThreadStatement.runOnUiThread { sut.vm.onPageSelected(1) }
|
||||
|
||||
screenshot(sut)
|
||||
val screenShotName = createName(testClassName + "_" + "accounts", "")
|
||||
onView(isRoot()).check(matches(isDisplayed()))
|
||||
screenshotViaName(sut, screenShotName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
* Nextcloud - Android Client
|
||||
*
|
||||
* 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.nextcloud.client.files
|
||||
|
||||
|
|
@ -37,8 +37,8 @@ class DeepLinkHandlerTest {
|
|||
class DeepLinkPattern {
|
||||
|
||||
companion object {
|
||||
val FILE_ID = 1234
|
||||
val SERVER_BASE_URLS = listOf(
|
||||
private const val FILE_ID = 1234
|
||||
private val SERVER_BASE_URLS = listOf(
|
||||
"http://hostname.net",
|
||||
"https://hostname.net",
|
||||
"http://hostname.net/subdir1",
|
||||
|
|
@ -48,7 +48,7 @@ class DeepLinkHandlerTest {
|
|||
"http://hostname.net/subdir1/subdir2/subdir3",
|
||||
"https://hostname.net/subdir1/subdir2/subdir3"
|
||||
)
|
||||
val INDEX_PHP_PATH = listOf(
|
||||
private val INDEX_PHP_PATH = listOf(
|
||||
"",
|
||||
"/index.php"
|
||||
)
|
||||
|
|
@ -102,12 +102,12 @@ class DeepLinkHandlerTest {
|
|||
const val OTHER_SERVER_BASE_URL = "https://someotherserver.net"
|
||||
const val SERVER_BASE_URL = "https://server.net"
|
||||
const val FILE_ID = "1234567890"
|
||||
val DEEP_LINK = Uri.parse("$SERVER_BASE_URL/index.php/f/$FILE_ID")
|
||||
val DEEP_LINK: Uri = Uri.parse("$SERVER_BASE_URL/index.php/f/$FILE_ID")
|
||||
|
||||
fun createMockUser(serverBaseUrl: String): User {
|
||||
val user = mock<User>()
|
||||
val uri = URI.create(serverBaseUrl)
|
||||
val server = Server(uri = uri, version = OwnCloudVersion.nextcloud_19)
|
||||
val server = Server(uri = uri, version = OwnCloudVersion.nextcloud_20)
|
||||
whenever(user.server).thenReturn(server)
|
||||
return user
|
||||
}
|
||||
|
|
@ -115,8 +115,8 @@ class DeepLinkHandlerTest {
|
|||
|
||||
@Mock
|
||||
lateinit var userAccountManager: UserAccountManager
|
||||
lateinit var allUsers: List<User>
|
||||
lateinit var handler: DeepLinkHandler
|
||||
private lateinit var allUsers: List<User>
|
||||
private lateinit var handler: DeepLinkHandler
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
* Nextcloud - Android Client
|
||||
*
|
||||
* 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.nextcloud.client.files.download
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
* Nextcloud - Android Client
|
||||
*
|
||||
* 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.nextcloud.client.files.download
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
* Nextcloud - Android Client
|
||||
*
|
||||
* 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.nextcloud.client.files.download
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
* Nextcloud - Android Client
|
||||
*
|
||||
* 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.nextcloud.client.files.download
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
* Nextcloud - Android Client
|
||||
*
|
||||
* 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.nextcloud.client.integrations.deck
|
||||
|
||||
|
|
@ -65,9 +65,7 @@ class DeckApiTest {
|
|||
companion object {
|
||||
@Parameterized.Parameters
|
||||
@JvmStatic
|
||||
fun initParametrs(): Array<String> {
|
||||
return DeckApiImpl.DECK_APP_PACKAGES
|
||||
}
|
||||
fun initParametrs(): Array<String> = DeckApiImpl.DECK_APP_PACKAGES
|
||||
}
|
||||
|
||||
@Before
|
||||
|
|
|
|||
|
|
@ -2,10 +2,11 @@
|
|||
* Nextcloud - Android Client
|
||||
*
|
||||
* 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.nextcloud.client.jobs
|
||||
|
||||
import android.content.Context
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.Observer
|
||||
|
|
@ -19,13 +20,19 @@ import androidx.work.WorkInfo
|
|||
import androidx.work.WorkManager
|
||||
import com.nextcloud.client.account.User
|
||||
import com.nextcloud.client.core.Clock
|
||||
import com.nextcloud.utils.extensions.toByteArray
|
||||
import com.owncloud.android.lib.common.utils.Log_OC
|
||||
import org.apache.commons.io.FileUtils
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertNotNull
|
||||
import org.junit.Assert.assertNull
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Assert.fail
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.rules.TemporaryFolder
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.Suite
|
||||
import org.mockito.ArgumentMatcher
|
||||
|
|
@ -37,6 +44,8 @@ import org.mockito.kotlin.eq
|
|||
import org.mockito.kotlin.mock
|
||||
import org.mockito.kotlin.verify
|
||||
import org.mockito.kotlin.whenever
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.util.Date
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.CountDownLatch
|
||||
|
|
@ -82,9 +91,11 @@ class BackgroundJobManagerTest {
|
|||
internal lateinit var workManager: WorkManager
|
||||
internal lateinit var clock: Clock
|
||||
internal lateinit var backgroundJobManager: BackgroundJobManagerImpl
|
||||
internal lateinit var context: Context
|
||||
|
||||
@Before
|
||||
fun setUpFixture() {
|
||||
context = mock()
|
||||
user = mock()
|
||||
whenever(user.accountName).thenReturn(USER_ACCOUNT_NAME)
|
||||
workManager = mock()
|
||||
|
|
@ -302,16 +313,36 @@ class BackgroundJobManagerTest {
|
|||
private lateinit var jobInfo: LiveData<JobInfo?>
|
||||
private lateinit var request: OneTimeWorkRequest
|
||||
|
||||
@get:Rule
|
||||
var folder: TemporaryFolder = TemporaryFolder()
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
var selectedContactsFile: File? = null
|
||||
try {
|
||||
selectedContactsFile = folder.newFile("hashset_cache.txt")
|
||||
} catch (_: IOException) {
|
||||
Log_OC.e("ImmediateContactsImport", "error creating temporary test file in ")
|
||||
fail("hashset_cache cannot be found")
|
||||
}
|
||||
|
||||
if (selectedContactsFile == null) {
|
||||
fail("hashset_cache cannot be found")
|
||||
}
|
||||
|
||||
val requestCaptor: KArgumentCaptor<OneTimeWorkRequest> = argumentCaptor()
|
||||
workInfo = MutableLiveData()
|
||||
whenever(workManager.getWorkInfoByIdLiveData(any())).thenReturn(workInfo)
|
||||
|
||||
val selectedContacts = intArrayOf(1, 2, 3)
|
||||
val contractsAsByteArray = selectedContacts.toByteArray()
|
||||
FileUtils.writeByteArrayToFile(selectedContactsFile, contractsAsByteArray)
|
||||
|
||||
jobInfo = backgroundJobManager.startImmediateContactsImport(
|
||||
contactsAccountName = "name",
|
||||
contactsAccountType = "type",
|
||||
vCardFilePath = "/path/to/vcard/file",
|
||||
selectedContacts = intArrayOf(1, 2, 3)
|
||||
selectedContactsFilePath = selectedContactsFile!!.absolutePath
|
||||
)
|
||||
verify(workManager).enqueueUniqueWork(
|
||||
any(),
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
/*
|
||||
* Nextcloud - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2020 Tobias Kaminsky <tobias@kaminsky.me>
|
||||
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH
|
||||
* SPDX-FileCopyrightText: 2024 Alper Ozturk <alper.ozturk@nextcloud.com>
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
package com.nextcloud.client.jobs
|
||||
|
|
@ -11,73 +10,120 @@ import android.Manifest
|
|||
import androidx.test.rule.GrantPermissionRule
|
||||
import androidx.work.WorkManager
|
||||
import com.nextcloud.client.core.ClockImpl
|
||||
import com.nextcloud.client.preferences.AppPreferences
|
||||
import com.nextcloud.client.preferences.AppPreferencesImpl
|
||||
import com.nextcloud.test.RetryTestRule
|
||||
import com.owncloud.android.AbstractIT
|
||||
import com.nextcloud.utils.extensions.toByteArray
|
||||
import com.owncloud.android.AbstractOnServerIT
|
||||
import com.owncloud.android.R
|
||||
import com.owncloud.android.datamodel.OCFile
|
||||
import com.owncloud.android.lib.common.utils.Log_OC
|
||||
import com.owncloud.android.operations.DownloadFileOperation
|
||||
import ezvcard.Ezvcard
|
||||
import ezvcard.VCard
|
||||
import junit.framework.Assert.assertEquals
|
||||
import junit.framework.Assert.assertTrue
|
||||
import org.apache.commons.io.FileUtils
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Assert.fail
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.rules.TemporaryFolder
|
||||
import java.io.BufferedInputStream
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.IOException
|
||||
|
||||
class ContactsBackupIT : AbstractOnServerIT() {
|
||||
val workmanager = WorkManager.getInstance(targetContext)
|
||||
val preferences = AppPreferencesImpl.fromContext(targetContext)
|
||||
private val backgroundJobManager = BackgroundJobManagerImpl(workmanager, ClockImpl(), preferences)
|
||||
private val workManager = WorkManager.getInstance(targetContext)
|
||||
private val preferences: AppPreferences = AppPreferencesImpl.fromContext(targetContext)
|
||||
private val backgroundJobManager = BackgroundJobManagerImpl(workManager, ClockImpl(), preferences)
|
||||
|
||||
@get:Rule
|
||||
val writeContactsRule = GrantPermissionRule.grant(Manifest.permission.WRITE_CONTACTS)
|
||||
val writeContactsRule: GrantPermissionRule = GrantPermissionRule.grant(Manifest.permission.WRITE_CONTACTS)
|
||||
|
||||
@get:Rule
|
||||
val readContactsRule = GrantPermissionRule.grant(Manifest.permission.READ_CONTACTS)
|
||||
val readContactsRule: GrantPermissionRule = GrantPermissionRule.grant(Manifest.permission.READ_CONTACTS)
|
||||
|
||||
@get:Rule
|
||||
val retryTestRule = RetryTestRule() // flaky test
|
||||
|
||||
@get:Rule
|
||||
var folder: TemporaryFolder = TemporaryFolder()
|
||||
|
||||
private val vcard: String = "vcard.vcf"
|
||||
private var selectedContactsFile: File? = null
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
try {
|
||||
selectedContactsFile = folder.newFile("hashset_cache.txt")
|
||||
} catch (_: IOException) {
|
||||
Log_OC.e("ContactsBackupIT", "error creating temporary test file in ")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun importExport() {
|
||||
val intArray = IntArray(1)
|
||||
intArray[0] = 0
|
||||
val intArray = intArrayOf(0)
|
||||
if (selectedContactsFile == null) {
|
||||
fail("hashset_cache cannot be found")
|
||||
}
|
||||
|
||||
val contractsAsByteArray = intArray.toByteArray()
|
||||
FileUtils.writeByteArrayToFile(selectedContactsFile, contractsAsByteArray)
|
||||
|
||||
// import file to local contacts
|
||||
backgroundJobManager.startImmediateContactsImport(null, null, getFile(vcard).absolutePath, intArray)
|
||||
|
||||
shortSleep()
|
||||
backgroundJobManager.startImmediateContactsImport(
|
||||
null,
|
||||
null,
|
||||
getFile(vcard).absolutePath,
|
||||
selectedContactsFile!!.absolutePath
|
||||
)
|
||||
longSleep()
|
||||
|
||||
// export contact
|
||||
backgroundJobManager.startImmediateContactsBackup(user)
|
||||
|
||||
longSleep()
|
||||
|
||||
val backupFolder: String = targetContext.resources.getString(R.string.contacts_backup_folder) +
|
||||
val folderPath: String = targetContext.resources.getString(R.string.contacts_backup_folder) +
|
||||
OCFile.PATH_SEPARATOR
|
||||
|
||||
refreshFolder("/")
|
||||
longSleep()
|
||||
|
||||
refreshFolder(backupFolder)
|
||||
longSleep()
|
||||
|
||||
val backupOCFile = storageManager.getFolderContent(
|
||||
storageManager.getFileByDecryptedRemotePath(backupFolder),
|
||||
false
|
||||
)[0]
|
||||
refreshFolder(folderPath)
|
||||
longSleep()
|
||||
longSleep()
|
||||
|
||||
assertTrue(DownloadFileOperation(user, backupOCFile, AbstractIT.targetContext).execute(client).isSuccess)
|
||||
if (folderPath.isEmpty()) {
|
||||
fail("folderPath cannot be empty")
|
||||
}
|
||||
|
||||
val folder = fileDataStorageManager.getFileByDecryptedRemotePath(folderPath)
|
||||
if (folder == null) {
|
||||
fail("folder cannot be null")
|
||||
}
|
||||
|
||||
val ocFile = storageManager.getFolderContent(folder, false).firstOrNull()
|
||||
if (ocFile == null) {
|
||||
fail("ocFile cannot be null")
|
||||
}
|
||||
|
||||
if (ocFile?.storagePath == null) {
|
||||
fail("ocFile.storagePath cannot be null")
|
||||
}
|
||||
|
||||
assertTrue(DownloadFileOperation(user, ocFile, targetContext).execute(client).isSuccess)
|
||||
|
||||
val file = ocFile?.storagePath?.let { File(it) }
|
||||
if (file == null) {
|
||||
fail("file cannot be null")
|
||||
}
|
||||
|
||||
val backupFile = File(backupOCFile.storagePath)
|
||||
val vcardInputStream = BufferedInputStream(FileInputStream(getFile(vcard)))
|
||||
val backupFileInputStream = BufferedInputStream(FileInputStream(backupFile))
|
||||
val backupFileInputStream = BufferedInputStream(FileInputStream(file))
|
||||
|
||||
// verify same
|
||||
val originalCards: ArrayList<VCard> = ArrayList()
|
||||
|
|
@ -87,6 +133,17 @@ class ContactsBackupIT : AbstractOnServerIT() {
|
|||
backupCards.addAll(Ezvcard.parse(backupFileInputStream).all())
|
||||
|
||||
assertEquals(originalCards.size, backupCards.size)
|
||||
assertEquals(originalCards[0].formattedName.toString(), backupCards[0].formattedName.toString())
|
||||
|
||||
val originalCardFormattedName = originalCards.firstOrNull()?.formattedName
|
||||
if (originalCardFormattedName == null) {
|
||||
fail("originalCardFormattedName cannot be null")
|
||||
}
|
||||
|
||||
val backupCardFormattedName = backupCards.firstOrNull()?.formattedName
|
||||
if (backupCardFormattedName == null) {
|
||||
fail("backupCardFormattedName cannot be null")
|
||||
}
|
||||
|
||||
assertEquals(originalCardFormattedName.toString(), backupCardFormattedName.toString())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
* Nextcloud - Android Client
|
||||
*
|
||||
* 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.nextcloud.client.migrations
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
* Nextcloud - Android Client
|
||||
*
|
||||
* 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.nextcloud.client.migrations
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
* Nextcloud - Android Client
|
||||
*
|
||||
* 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.nextcloud.client.migrations
|
||||
|
||||
|
|
@ -69,25 +69,16 @@ class MockSharedPreferences : SharedPreferences {
|
|||
|
||||
override fun getInt(key: String?, defValue: Int): Int = store.getOrDefault(key, defValue) as Int
|
||||
|
||||
override fun getAll(): MutableMap<String?, Any?> {
|
||||
return HashMap(store)
|
||||
}
|
||||
override fun getAll(): MutableMap<String?, Any?> = HashMap(store)
|
||||
|
||||
override fun edit(): SharedPreferences.Editor {
|
||||
return MockEditor(store)
|
||||
}
|
||||
override fun edit(): SharedPreferences.Editor = MockEditor(store)
|
||||
|
||||
override fun getLong(key: String?, defValue: Long): Long {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
override fun getLong(key: String?, defValue: Long): Long = throw UnsupportedOperationException()
|
||||
|
||||
override fun getFloat(key: String?, defValue: Float): Float {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
override fun getFloat(key: String?, defValue: Float): Float = throw UnsupportedOperationException()
|
||||
|
||||
override fun getStringSet(key: String?, defValues: MutableSet<String>?): MutableSet<String>? {
|
||||
return store.getOrDefault(key, defValues) as MutableSet<String>?
|
||||
}
|
||||
override fun getStringSet(key: String?, defValues: MutableSet<String>?): MutableSet<String>? =
|
||||
store.getOrDefault(key, defValues) as MutableSet<String>?
|
||||
|
||||
override fun registerOnSharedPreferenceChangeListener(
|
||||
listener: SharedPreferences.OnSharedPreferenceChangeListener?
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
* Nextcloud - Android Client
|
||||
*
|
||||
* 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.nextcloud.client.migrations
|
||||
|
||||
|
|
|
|||
|
|
@ -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.nextcloud.client.network
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
* Nextcloud - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2024 Alper Ozturk <alper_ozturk@proton.me>
|
||||
* SPDX-FileCopyrightText: 2024 Alper Ozturk <alper.ozturk@nextcloud.com>
|
||||
* SPDX-FileCopyrightText: 2024 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.nextcloud.extensions
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
* Nextcloud - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2024 Alper Ozturk <alper_ozturk@proton.me>
|
||||
* SPDX-FileCopyrightText: 2024 Alper Ozturk <alper.ozturk@nextcloud.com>
|
||||
* SPDX-FileCopyrightText: 2024 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.nextcloud.extensions
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,176 @@
|
|||
/*
|
||||
* Nextcloud - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2025 Alper Ozturk <alper.ozturk@nextcloud.com>
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
package com.nextcloud.extensions
|
||||
import com.nextcloud.utils.extensions.isNotBlankAndEquals
|
||||
import junit.framework.TestCase.assertFalse
|
||||
import junit.framework.TestCase.assertTrue
|
||||
import org.junit.Test
|
||||
|
||||
@Suppress("TooManyFunctions")
|
||||
class StringExtensionTests {
|
||||
@Test
|
||||
fun testIsNotBlankAndEqualsWhenGivenBothStringsAreNull() {
|
||||
val str1: String? = null
|
||||
val str2: String? = null
|
||||
assertFalse(str1.isNotBlankAndEquals(str2))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsNotBlankAndEqualsWhenGivenFirstStringIsNull() {
|
||||
val str1: String? = null
|
||||
val str2 = "hello"
|
||||
assertFalse(str1.isNotBlankAndEquals(str2))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsNotBlankAndEqualsWhenGivenSecondStringIsNull() {
|
||||
val str1 = "hello"
|
||||
val str2: String? = null
|
||||
assertFalse(str1.isNotBlankAndEquals(str2))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsNotBlankAndEqualsWhenGivenBothStringsAreEmpty() {
|
||||
val str1 = ""
|
||||
val str2 = ""
|
||||
assertFalse(str1.isNotBlankAndEquals(str2))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsNotBlankAndEqualsWhenGivenFirstStringIsEmpty() {
|
||||
val str1 = ""
|
||||
val str2 = "hello"
|
||||
assertFalse(str1.isNotBlankAndEquals(str2))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsNotBlankAndEqualsWhenGivenSecondStringIsEmpty() {
|
||||
val str1 = "hello"
|
||||
val str2 = ""
|
||||
assertFalse(str1.isNotBlankAndEquals(str2))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsNotBlankAndEqualsWhenGivenBothStringsAreWhitespaceOnly() {
|
||||
val str1 = " "
|
||||
val str2 = " \t "
|
||||
assertFalse(str1.isNotBlankAndEquals(str2))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsNotBlankAndEqualsWhenGivenFirstStringIsWhitespaceOnly() {
|
||||
val str1 = " "
|
||||
val str2 = "hello"
|
||||
assertFalse(str1.isNotBlankAndEquals(str2))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsNotBlankAndEqualsWhenGivenSecondStringIsWhitespaceOnly() {
|
||||
val str1 = "hello"
|
||||
val str2 = " "
|
||||
assertFalse(str1.isNotBlankAndEquals(str2))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsNotBlankAndEqualsWhenGivenStringsAreDifferentButBothValid() {
|
||||
val str1 = "hello"
|
||||
val str2 = "world"
|
||||
assertFalse(str1.isNotBlankAndEquals(str2))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsNotBlankAndEqualsWhenGivenStringsHaveDifferentCase() {
|
||||
val str1 = "Hello"
|
||||
val str2 = "hello"
|
||||
assertTrue(str1.isNotBlankAndEquals(str2))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsNotBlankAndEqualsWhenGivenMixedCaseStrings() {
|
||||
val str1 = "HeLLo WoRLd"
|
||||
val str2 = "hello world"
|
||||
assertTrue(str1.isNotBlankAndEquals(str2))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsNotBlankAndEqualsWhenGivenUppercaseStrings() {
|
||||
val str1 = "HELLO"
|
||||
val str2 = "hello"
|
||||
assertTrue(str1.isNotBlankAndEquals(str2))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsNotBlankAndEqualsWhenGivenBothStringsAreIdenticalAndValid() {
|
||||
val str1 = "hello"
|
||||
val str2 = "hello"
|
||||
assertTrue(str1.isNotBlankAndEquals(str2))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsNotBlankAndEqualsWhenGivenBothStringsAreIdenticalWithSpaces() {
|
||||
val str1 = "hello world"
|
||||
val str2 = "hello world"
|
||||
assertTrue(str1.isNotBlankAndEquals(str2))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsNotBlankAndEqualsWhenGivenBothStringsAreIdenticalSingleCharacter() {
|
||||
val str1 = "a"
|
||||
val str2 = "A"
|
||||
assertTrue(str1.isNotBlankAndEquals(str2))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsNotBlankAndEqualsWhenGivenBothStringsAreIdenticalWithSpecialCharacters() {
|
||||
val str1 = "hello@world!123"
|
||||
val str2 = "HELLO@WORLD!123"
|
||||
assertTrue(str1.isNotBlankAndEquals(str2))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsNotBlankAndEqualsWhenGivenOneHasLeadingWhitespaceAndOtherDoesNot() {
|
||||
val str1 = " hello"
|
||||
val str2 = "HELLO"
|
||||
assertFalse(str1.isNotBlankAndEquals(str2))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsNotBlankAndEqualsWhenGivenOneHasTrailingWhitespaceAndOtherDoesNot() {
|
||||
val str1 = "hello"
|
||||
val str2 = "HELLO "
|
||||
assertFalse(str1.isNotBlankAndEquals(str2))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsNotBlankAndEqualsWhenGivenBothHaveIdenticalWhitespacePaddingDifferentCase() {
|
||||
val str1 = " hello "
|
||||
val str2 = " HELLO "
|
||||
assertTrue(str1.isNotBlankAndEquals(str2))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsNotBlankAndEqualsWhenGivenMixedWhitespaceCharacters() {
|
||||
val str1 = "\t"
|
||||
val str2 = "\n"
|
||||
assertFalse(str1.isNotBlankAndEquals(str2))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsNotBlankAndEqualsWhenGivenOneIsNullAndOtherIsEmpty() {
|
||||
val str1: String? = null
|
||||
val str2 = ""
|
||||
assertFalse(str1.isNotBlankAndEquals(str2))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsNotBlankAndEqualsWhenGivenOneIsNullAndOtherIsWhitespace() {
|
||||
val str1: String? = null
|
||||
val str2 = " "
|
||||
assertFalse(str1.isNotBlankAndEquals(str2))
|
||||
}
|
||||
}
|
||||
|
|
@ -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.nextcloud.sso
|
||||
|
||||
|
|
|
|||
|
|
@ -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.nextcloud.test
|
||||
|
||||
|
|
|
|||
|
|
@ -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.nextcloud.test
|
||||
|
||||
|
|
|
|||
|
|
@ -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.nextcloud.test
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* 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.nextcloud.test
|
||||
|
||||
|
|
@ -13,9 +13,7 @@ object RandomStringGenerator {
|
|||
|
||||
@JvmOverloads
|
||||
@JvmStatic
|
||||
fun make(length: Int = DEFAULT_LENGTH): String {
|
||||
return (1..length)
|
||||
.map { ALLOWED_CHARACTERS.random() }
|
||||
.joinToString("")
|
||||
}
|
||||
fun make(length: Int = DEFAULT_LENGTH): String = (1..length)
|
||||
.map { ALLOWED_CHARACTERS.random() }
|
||||
.joinToString("")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.nextcloud.test
|
||||
|
||||
|
|
@ -25,9 +25,7 @@ class RetryTestRule(val retryCount: Int = defaultRetryValue) : TestRule {
|
|||
private val defaultRetryValue: Int = if (BuildConfig.CI) 5 else 1
|
||||
}
|
||||
|
||||
override fun apply(base: Statement, description: Description): Statement {
|
||||
return statement(base, description)
|
||||
}
|
||||
override fun apply(base: Statement, description: Description): Statement = statement(base, description)
|
||||
|
||||
@Suppress("TooGenericExceptionCaught") // and this exactly what we want here
|
||||
private fun statement(base: Statement, description: Description): Statement {
|
||||
|
|
|
|||
|
|
@ -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.nextcloud.test
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
* Nextcloud - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2024 Alper Ozturk <alper_ozturk@proton.me>
|
||||
* SPDX-FileCopyrightText: 2024 Alper Ozturk <alper.ozturk@nextcloud.com>
|
||||
* SPDX-FileCopyrightText: 2024 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.nextcloud.test.model
|
||||
|
||||
|
|
@ -24,17 +24,11 @@ data class TestDataParcelable(val message: String) : Parcelable {
|
|||
parcel.writeString(message)
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
override fun describeContents(): Int = 0
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<TestDataParcelable> {
|
||||
override fun createFromParcel(parcel: Parcel): TestDataParcelable {
|
||||
return TestDataParcelable(parcel)
|
||||
}
|
||||
override fun createFromParcel(parcel: Parcel): TestDataParcelable = TestDataParcelable(parcel)
|
||||
|
||||
override fun newArray(size: Int): Array<TestDataParcelable?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
override fun newArray(size: Int): Array<TestDataParcelable?> = arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,124 +1,80 @@
|
|||
/*
|
||||
* 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.nextcloud.ui
|
||||
|
||||
import android.graphics.BitmapFactory
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
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.R
|
||||
import com.owncloud.android.utils.BitmapUtils
|
||||
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 BitmapIT : AbstractIT() {
|
||||
@get:Rule
|
||||
val testActivityRule = IntentsTestRule(TestActivity::class.java, true, false)
|
||||
private val testClassName = "com.nextcloud.ui.BitmapIT"
|
||||
|
||||
@Test
|
||||
@ScreenshotTest
|
||||
fun roundBitmap() {
|
||||
val file = getFile("christine.jpg")
|
||||
val bitmap = BitmapFactory.decodeFile(file.absolutePath)
|
||||
|
||||
val activity = testActivityRule.launchActivity(null)
|
||||
val imageView = ImageView(activity).apply {
|
||||
setImageBitmap(bitmap)
|
||||
}
|
||||
|
||||
val bitmap2 = BitmapFactory.decodeFile(file.absolutePath)
|
||||
val imageView2 = ImageView(activity).apply {
|
||||
setImageBitmap(BitmapUtils.roundBitmap(bitmap2))
|
||||
}
|
||||
|
||||
val linearLayout = LinearLayout(activity).apply {
|
||||
orientation = LinearLayout.VERTICAL
|
||||
setBackgroundColor(context.getColor(R.color.grey_200))
|
||||
}
|
||||
linearLayout.addView(imageView, 200, 200)
|
||||
linearLayout.addView(imageView2, 200, 200)
|
||||
activity.addView(linearLayout)
|
||||
|
||||
screenshot(activity)
|
||||
@Before
|
||||
fun registerIdlingResource() {
|
||||
IdlingRegistry.getInstance().register(EspressoIdlingResource.countingIdlingResource)
|
||||
}
|
||||
|
||||
// @Test
|
||||
// @ScreenshotTest
|
||||
// fun glideSVG() {
|
||||
// val activity = testActivityRule.launchActivity(null)
|
||||
// val accountProvider = UserAccountManagerImpl.fromContext(activity)
|
||||
// val clientFactory = ClientFactoryImpl(activity)
|
||||
//
|
||||
// val linearLayout = LinearLayout(activity).apply {
|
||||
// orientation = LinearLayout.VERTICAL
|
||||
// setBackgroundColor(context.getColor(R.color.grey_200))
|
||||
// }
|
||||
//
|
||||
// val file = getFile("christine.jpg")
|
||||
// val bitmap = BitmapFactory.decodeFile(file.absolutePath)
|
||||
//
|
||||
// ImageView(activity).apply {
|
||||
// setImageBitmap(bitmap)
|
||||
// linearLayout.addView(this, 50, 50)
|
||||
// }
|
||||
//
|
||||
// downloadIcon(
|
||||
// client.baseUri.toString() + "/apps/files/img/app.svg",
|
||||
// activity,
|
||||
// linearLayout,
|
||||
// accountProvider,
|
||||
// clientFactory
|
||||
// )
|
||||
//
|
||||
// downloadIcon(
|
||||
// client.baseUri.toString() + "/core/img/actions/group.svg",
|
||||
// activity,
|
||||
// linearLayout,
|
||||
// accountProvider,
|
||||
// clientFactory
|
||||
// )
|
||||
//
|
||||
// activity.addView(linearLayout)
|
||||
//
|
||||
// longSleep()
|
||||
//
|
||||
// screenshot(activity)
|
||||
// }
|
||||
//
|
||||
// private fun downloadIcon(
|
||||
// url: String,
|
||||
// activity: TestActivity,
|
||||
// linearLayout: LinearLayout,
|
||||
// accountProvider: UserAccountManager,
|
||||
// clientFactory: ClientFactory
|
||||
// ) {
|
||||
// val view = ImageView(activity).apply {
|
||||
// linearLayout.addView(this, 50, 50)
|
||||
// }
|
||||
// val target = object : SimpleTarget<Drawable>() {
|
||||
// override fun onResourceReady(resource: Drawable?, glideAnimation: GlideAnimation<in Drawable>?) {
|
||||
// view.setColorFilter(targetContext.getColor(R.color.dark), PorterDuff.Mode.SRC_ATOP)
|
||||
// view.setImageDrawable(resource)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// testActivityRule.runOnUiThread {
|
||||
// DisplayUtils.downloadIcon(
|
||||
// accountProvider,
|
||||
// clientFactory,
|
||||
// activity,
|
||||
// url,
|
||||
// target,
|
||||
// R.drawable.ic_user
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
@After
|
||||
fun unregisterIdlingResource() {
|
||||
IdlingRegistry.getInstance().unregister(EspressoIdlingResource.countingIdlingResource)
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThread
|
||||
@ScreenshotTest
|
||||
fun roundBitmap() {
|
||||
launchActivity<TestActivity>().use { scenario ->
|
||||
scenario.onActivity { activity ->
|
||||
onIdleSync {
|
||||
EspressoIdlingResource.increment()
|
||||
val file = getFile("christine.jpg")
|
||||
val bitmap = BitmapFactory.decodeFile(file.absolutePath)
|
||||
|
||||
val imageView = ImageView(activity).apply {
|
||||
setImageBitmap(bitmap)
|
||||
}
|
||||
|
||||
val bitmap2 = BitmapFactory.decodeFile(file.absolutePath)
|
||||
val imageView2 = ImageView(activity).apply {
|
||||
setImageBitmap(BitmapUtils.roundBitmap(bitmap2))
|
||||
}
|
||||
|
||||
val linearLayout = LinearLayout(activity).apply {
|
||||
orientation = LinearLayout.VERTICAL
|
||||
setBackgroundColor(context.getColor(R.color.grey_200))
|
||||
}
|
||||
linearLayout.addView(imageView, 200, 200)
|
||||
linearLayout.addView(imageView2, 200, 200)
|
||||
activity.addView(linearLayout)
|
||||
EspressoIdlingResource.decrement()
|
||||
|
||||
val screenShotName = createName(testClassName + "_" + "roundBitmap", "")
|
||||
onView(isRoot()).check(matches(isDisplayed()))
|
||||
screenshotViaName(activity, screenShotName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* 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.nextcloud.ui
|
||||
|
||||
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.resources.users.Status
|
||||
import com.owncloud.android.lib.resources.users.StatusType
|
||||
import com.owncloud.android.ui.activity.FileDisplayActivity
|
||||
import com.owncloud.android.utils.EspressoIdlingResource
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
|
||||
class SetOnlineStatusBottomSheetIT : AbstractIT() {
|
||||
@Before
|
||||
fun registerIdlingResource() {
|
||||
IdlingRegistry.getInstance().register(EspressoIdlingResource.countingIdlingResource)
|
||||
}
|
||||
|
||||
@After
|
||||
fun unregisterIdlingResource() {
|
||||
IdlingRegistry.getInstance().unregister(EspressoIdlingResource.countingIdlingResource)
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThread
|
||||
fun open() {
|
||||
launchActivity<FileDisplayActivity>().use { scenario ->
|
||||
scenario.onActivity { activity ->
|
||||
onIdleSync {
|
||||
EspressoIdlingResource.increment()
|
||||
val sut = SetOnlineStatusBottomSheet(
|
||||
Status(StatusType.DND, "Working hard…", "🤖", -1)
|
||||
)
|
||||
sut.show(activity.supportFragmentManager, "")
|
||||
EspressoIdlingResource.decrement()
|
||||
|
||||
onView(isRoot()).check(matches(isDisplayed()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* 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.nextcloud.ui
|
||||
|
||||
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.resources.users.ClearAt
|
||||
import com.owncloud.android.lib.resources.users.PredefinedStatus
|
||||
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.utils.EspressoIdlingResource
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
|
||||
class SetStatusMessageBottomSheetIT : AbstractIT() {
|
||||
@Before
|
||||
fun registerIdlingResource() {
|
||||
IdlingRegistry.getInstance().register(EspressoIdlingResource.countingIdlingResource)
|
||||
}
|
||||
|
||||
@After
|
||||
fun unregisterIdlingResource() {
|
||||
IdlingRegistry.getInstance().unregister(EspressoIdlingResource.countingIdlingResource)
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThread
|
||||
fun open() {
|
||||
launchActivity<FileDisplayActivity>().use { scenario ->
|
||||
scenario.onActivity { activity ->
|
||||
onIdleSync {
|
||||
EspressoIdlingResource.increment()
|
||||
val sut = SetStatusMessageBottomSheet(
|
||||
user,
|
||||
Status(StatusType.DND, "Working hard…", "🤖", -1)
|
||||
)
|
||||
sut.show(activity.supportFragmentManager, "")
|
||||
val predefinedStatus: ArrayList<PredefinedStatus> = arrayListOf(
|
||||
PredefinedStatus("meeting", "📅", "In a meeting", ClearAt("period", "3600")),
|
||||
PredefinedStatus("commuting", "🚌", "Commuting", ClearAt("period", "1800")),
|
||||
PredefinedStatus("be-right-back", "⏳", "Be right back", ClearAt("period", "900")),
|
||||
PredefinedStatus("remote-work", "🏡", "Working remotely", ClearAt("end-of", "day")),
|
||||
PredefinedStatus("sick-leave", "🤒", "Out sick", ClearAt("end-of", "day")),
|
||||
PredefinedStatus("vacationing", "🌴", "Vacationing", null)
|
||||
)
|
||||
sut.setPredefinedStatus(predefinedStatus)
|
||||
EspressoIdlingResource.decrement()
|
||||
|
||||
onView(isRoot()).check(matches(isDisplayed()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
241
app/src/androidTest/java/com/nextcloud/utils/AutoRenameTests.kt
Normal file
241
app/src/androidTest/java/com/nextcloud/utils/AutoRenameTests.kt
Normal file
|
|
@ -0,0 +1,241 @@
|
|||
/*
|
||||
* Nextcloud - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2024 Alper Ozturk <alper.ozturk@nextcloud.com>
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
package com.nextcloud.utils
|
||||
|
||||
import com.nextcloud.utils.autoRename.AutoRename
|
||||
import com.owncloud.android.AbstractOnServerIT
|
||||
import com.owncloud.android.datamodel.e2e.v2.decrypted.DecryptedFile
|
||||
import com.owncloud.android.lib.resources.status.NextcloudVersion
|
||||
import com.owncloud.android.lib.resources.status.OCCapability
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
|
||||
@Suppress("TooManyFunctions")
|
||||
class AutoRenameTests : AbstractOnServerIT() {
|
||||
|
||||
private var capability: OCCapability = fileDataStorageManager.getCapability(account.name)
|
||||
private val forbiddenFilenameExtension = "."
|
||||
private val forbiddenFilenameCharacter = ">"
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
testOnlyOnServer(NextcloudVersion.nextcloud_30)
|
||||
|
||||
capability = capability.apply {
|
||||
forbiddenFilenameExtensionJson = listOf(
|
||||
"""[" ",".",".part",".part"]""",
|
||||
"""[".",".part",".part"," "]""",
|
||||
"""[".",".part"," ", ".part"]""",
|
||||
"""[".part"," ", ".part","."]""",
|
||||
"""[" ",".",".PART",".PART"]""",
|
||||
"""[".",".PART",".PART"," "]""",
|
||||
"""[".",".PART"," ", ".PART"]""",
|
||||
"""[".PART"," ", ".PART","."]"""
|
||||
).random()
|
||||
forbiddenFilenameCharactersJson = """["<", ">", ":", "\\\\", "/", "|", "?", "*", "&"]"""
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testInvalidChar() {
|
||||
val filename = "file${forbiddenFilenameCharacter}file.txt"
|
||||
val result = AutoRename.rename(filename, capability)
|
||||
val expectedFilename = "file_file.txt"
|
||||
assert(result == expectedFilename) { "Expected $expectedFilename but got $result" }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testInvalidExtension() {
|
||||
val filename = "file$forbiddenFilenameExtension"
|
||||
val result = AutoRename.rename(filename, capability)
|
||||
val expectedFilename = "file_"
|
||||
assert(result == expectedFilename) { "Expected $expectedFilename but got $result" }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMultipleInvalidChars() {
|
||||
val filename = "file|name?<>.txt"
|
||||
val result = AutoRename.rename(filename, capability)
|
||||
val expectedFilename = "file_name___.txt"
|
||||
assert(result == expectedFilename) { "Expected $expectedFilename but got $result" }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testStartEndInvalidExtensions() {
|
||||
val filename = " .file.part "
|
||||
val result = AutoRename.rename(filename, capability)
|
||||
val expectedFilename = "_file_part"
|
||||
assert(result == expectedFilename) { "Expected $expectedFilename but got $result" }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testStartInvalidExtension() {
|
||||
val filename = " .file.part"
|
||||
val result = AutoRename.rename(filename, capability)
|
||||
val expectedFilename = "_file_part"
|
||||
assert(result == expectedFilename) { "Expected $expectedFilename but got $result" }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testEndInvalidExtension() {
|
||||
val filename = ".file.part "
|
||||
val result = AutoRename.rename(filename, capability)
|
||||
val expectedFilename = "_file_part"
|
||||
assert(result == expectedFilename) { "Expected $expectedFilename but got $result" }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMiddleNonPrintableChar() {
|
||||
val filename = "file\u0001name.txt"
|
||||
val result = AutoRename.rename(filename, capability)
|
||||
val expectedFilename = "filename.txt"
|
||||
assert(result == expectedFilename) { "Expected $expectedFilename but got $result" }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testStartNonPrintableChar() {
|
||||
val filename = "\u0001filename.txt"
|
||||
val result = AutoRename.rename(filename, capability)
|
||||
val expectedFilename = "filename.txt"
|
||||
assert(result == expectedFilename) { "Expected $expectedFilename but got $result" }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testEndNonPrintableChar() {
|
||||
val filename = "filename.txt\u0001"
|
||||
val result = AutoRename.rename(filename, capability)
|
||||
val expectedFilename = "filename.txt"
|
||||
assert(result == expectedFilename) { "Expected $expectedFilename but got $result" }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testExtensionNonPrintableChar() {
|
||||
val filename = "filename.t\u0001xt"
|
||||
val result = AutoRename.rename(filename, capability)
|
||||
val expectedFilename = "filename.txt"
|
||||
assert(result == expectedFilename) { "Expected $expectedFilename but got $result" }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMiddleInvalidFolderChar() {
|
||||
val folderPath = "abc/def/kg$forbiddenFilenameCharacter/lmo/pp/"
|
||||
val result = AutoRename.rename(folderPath, capability)
|
||||
val expectedFolderName = "abc/def/kg_/lmo/pp/"
|
||||
assert(result == expectedFolderName) { "Expected $expectedFolderName but got $result" }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testEndInvalidFolderChar() {
|
||||
val folderPath = "abc/def/kg/lmo/pp$forbiddenFilenameCharacter/"
|
||||
val result = AutoRename.rename(folderPath, capability)
|
||||
val expectedFolderName = "abc/def/kg/lmo/pp_/"
|
||||
assert(result == expectedFolderName) { "Expected $expectedFolderName but got $result" }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testStartInvalidFolderChar() {
|
||||
val folderPath = "${forbiddenFilenameCharacter}abc/def/kg/lmo/pp/"
|
||||
val result = AutoRename.rename(folderPath, capability)
|
||||
val expectedFolderName = "_abc/def/kg/lmo/pp/"
|
||||
assert(result == expectedFolderName) { "Expected $expectedFolderName but got $result" }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMixedInvalidChar() {
|
||||
val filename = " file\u0001na${forbiddenFilenameCharacter}me.txt "
|
||||
val result = AutoRename.rename(filename, capability)
|
||||
val expectedFilename = "filena_me.txt"
|
||||
assert(result == expectedFilename) { "Expected $expectedFilename but got $result" }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testStartsWithPathSeparator() {
|
||||
val folderPath = "/abc/def/kg/lmo/pp$forbiddenFilenameCharacter/file.txt/"
|
||||
val result = AutoRename.rename(folderPath, capability)
|
||||
val expectedFolderName = "/abc/def/kg/lmo/pp_/file.txt/"
|
||||
assert(result == expectedFolderName) { "Expected $expectedFolderName but got $result" }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testStartsWithPathSeparatorAndValidFilepath() {
|
||||
val folderPath = "/COm02/2569.webp/"
|
||||
val result = AutoRename.rename(folderPath, capability)
|
||||
val expectedFolderName = "/COm02/2569.webp/"
|
||||
assert(result == expectedFolderName) { "Expected $expectedFolderName but got $result" }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testValidFilename() {
|
||||
val filename = ".file.TXT"
|
||||
val result = AutoRename.rename(filename, capability)
|
||||
val expectedFilename = "_file.txt"
|
||||
assert(result == expectedFilename) { "Expected $expectedFilename but got $result" }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRenameExtensionForFolder() {
|
||||
val filename = "/Pictures/@User/SubDir/08.16.07 Ka Yel/"
|
||||
val result = AutoRename.rename(filename, capability)
|
||||
assert(result == filename) { "Expected $filename but got $result" }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRenameExtensionForFile() {
|
||||
val filename = "/Pictures/@User/SubDir/08.16.07 Ka Yel.TXT"
|
||||
val result = AutoRename.rename(filename, capability)
|
||||
val expectedFilename = "/Pictures/@User/SubDir/08.16.07 Ka Yel.txt"
|
||||
assert(result == expectedFilename) { "Expected $expectedFilename but got $result" }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testE2EEFile() {
|
||||
val decryptedFile = DecryptedFile(
|
||||
authenticationTag = "HQlWBdm+gYC5kZwWnqXR1Q==",
|
||||
filename = "a:a.jpg",
|
||||
nonce = "sigyys8SfPZSScDJ860vYw==",
|
||||
mimetype = "image/jpeg",
|
||||
key = "sigyys8SfPZSScDJ860vYw=="
|
||||
)
|
||||
|
||||
val result = AutoRename.rename(decryptedFile.filename, capability)
|
||||
val expectedFilename = "a_a.jpg"
|
||||
assert(result == expectedFilename) { "Expected $expectedFilename but got $result" }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRemovingLeadingWhitespace() {
|
||||
val filename = " readme.txt"
|
||||
val result = AutoRename.rename(filename, capability)
|
||||
val expectedFilename = "readme.txt"
|
||||
assert(result == expectedFilename) { "Expected $expectedFilename but got $result" }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRemovingTrailingWhitespace() {
|
||||
val filename = "readme.txt "
|
||||
val result = AutoRename.rename(filename, capability)
|
||||
val expectedFilename = "readme.txt"
|
||||
assert(result == expectedFilename) { "Expected $expectedFilename but got $result" }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRemovingTrailingAndLeadingWhitespace() {
|
||||
val filename = " readme.txt "
|
||||
val result = AutoRename.rename(filename, capability)
|
||||
val expectedFilename = "readme.txt"
|
||||
assert(result == expectedFilename) { "Expected $expectedFilename but got $result" }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testFolderNameLowercase() {
|
||||
val filename = "Foo.Bar.Baz"
|
||||
val result = AutoRename.rename(filename, capability, isFolderPath = true)
|
||||
val expectedFilename = "Foo.Bar.Baz"
|
||||
assert(result == expectedFilename) { "Expected $expectedFilename but got $result" }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Nextcloud - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2024 Alper Ozturk <alper.ozturk@nextcloud.com>
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
package com.nextcloud.utils
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import com.google.gson.Gson
|
||||
import com.owncloud.android.datamodel.Credentials
|
||||
import com.owncloud.android.ui.dialog.setupEncryption.CertificateValidator
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import java.io.InputStreamReader
|
||||
|
||||
class CertificateValidatorTests {
|
||||
|
||||
private var sut: CertificateValidator? = null
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
sut = CertificateValidator()
|
||||
}
|
||||
|
||||
@After
|
||||
fun destroy() {
|
||||
sut = null
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testValidateWhenGivenValidServerKeyAndCertificateShouldReturnTrue() {
|
||||
val inputStream =
|
||||
InstrumentationRegistry.getInstrumentation().context.assets.open("credentials.json")
|
||||
|
||||
val credentials = InputStreamReader(inputStream).use { reader ->
|
||||
Gson().fromJson(reader, Credentials::class.java)
|
||||
}
|
||||
|
||||
val isCertificateValid = sut?.validate(credentials.publicKey, credentials.certificate) ?: false
|
||||
assert(isCertificateValid)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,231 @@
|
|||
/*
|
||||
* Nextcloud - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2024 Alper Ozturk <alper.ozturk@nextcloud.com>
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
package com.nextcloud.utils
|
||||
|
||||
import com.nextcloud.utils.fileNameValidator.FileNameValidator
|
||||
import com.owncloud.android.AbstractOnServerIT
|
||||
import com.owncloud.android.R
|
||||
import com.owncloud.android.lib.resources.status.NextcloudVersion
|
||||
import com.owncloud.android.lib.resources.status.OCCapability
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertNull
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
|
||||
@Suppress("TooManyFunctions")
|
||||
class FileNameValidatorTests : AbstractOnServerIT() {
|
||||
|
||||
private var capability: OCCapability = fileDataStorageManager.getCapability(account.name)
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
capability = capability.apply {
|
||||
forbiddenFilenamesJson = """[".htaccess",".htaccess"]"""
|
||||
forbiddenFilenameBaseNamesJson = """
|
||||
["con", "prn", "aux", "nul", "com0", "com1", "com2", "com3", "com4",
|
||||
"com5", "com6", "com7", "com8", "com9", "com¹", "com²", "com³",
|
||||
"lpt0", "lpt1", "lpt2", "lpt3", "lpt4", "lpt5", "lpt6", "lpt7",
|
||||
"lpt8", "lpt9", "lpt¹", "lpt²", "lpt³"]
|
||||
"""
|
||||
forbiddenFilenameExtensionJson = """[" ",".",".part",".part"]"""
|
||||
forbiddenFilenameCharactersJson = """["<", ">", ":", "\\\\", "/", "|", "?", "*", "&"]"""
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testInvalidCharacter() {
|
||||
testOnlyOnServer(NextcloudVersion.nextcloud_30)
|
||||
|
||||
val result = FileNameValidator.checkFileName("file<name", capability, targetContext)
|
||||
assertEquals(
|
||||
String.format(targetContext.getString(R.string.file_name_validator_error_invalid_character), "<"),
|
||||
result
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testReservedName() {
|
||||
testOnlyOnServer(NextcloudVersion.nextcloud_30)
|
||||
|
||||
val result = FileNameValidator.checkFileName("CON", capability, targetContext)
|
||||
assertEquals(targetContext.getString(R.string.file_name_validator_error_reserved_names, "con"), result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testForbiddenFilenameExtension() {
|
||||
testOnlyOnServer(NextcloudVersion.nextcloud_30)
|
||||
|
||||
val result = FileNameValidator.checkFileName("my_fav_file.part", capability, targetContext)
|
||||
assertEquals(
|
||||
targetContext.getString(R.string.file_name_validator_error_forbidden_file_extensions, ".part"),
|
||||
result
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testEndsWithSpaceOrPeriod() {
|
||||
val firstFilename = "test "
|
||||
val secondFilename = "test."
|
||||
val result = FileNameValidator.checkFileName(firstFilename, capability, targetContext)
|
||||
val result2 = FileNameValidator.checkFileName(secondFilename, capability, targetContext)
|
||||
|
||||
if (capability.version.isOlderThan(NextcloudVersion.nextcloud_30)) {
|
||||
assertEquals(null, result)
|
||||
assertEquals(null, result2)
|
||||
} else {
|
||||
assertEquals(
|
||||
targetContext.getString(R.string.file_name_validator_error_forbidden_space_character_extensions),
|
||||
result
|
||||
)
|
||||
assertEquals(
|
||||
targetContext.getString(R.string.file_name_validator_error_forbidden_file_extensions, "."),
|
||||
result2
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testEmptyFileName() {
|
||||
val result = FileNameValidator.checkFileName("", capability, targetContext)
|
||||
assertEquals(targetContext.getString(R.string.filename_empty), result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testBlankFileName() {
|
||||
val result = FileNameValidator.checkFileName(" ", capability, targetContext)
|
||||
assertEquals(targetContext.getString(R.string.filename_empty), result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testFileAlreadyExists() {
|
||||
val existingFiles = setOf("existingFile")
|
||||
val result = FileNameValidator.checkFileName("existingFile", capability, targetContext, existingFiles)
|
||||
assertEquals(targetContext.getString(R.string.file_already_exists), result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testValidFileName() {
|
||||
val result = FileNameValidator.checkFileName("validFileName", capability, targetContext)
|
||||
assertNull(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsFileHidden() {
|
||||
assertTrue(FileNameValidator.isFileHidden(".hiddenFile"))
|
||||
assertFalse(FileNameValidator.isFileHidden("visibleFile"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsFileNameAlreadyExist() {
|
||||
val existingFiles = setOf("existingFile")
|
||||
assertTrue(FileNameValidator.isFileNameAlreadyExist("existingFile", existingFiles))
|
||||
assertFalse(FileNameValidator.isFileNameAlreadyExist("newFile", existingFiles))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testValidFolderAndFilePaths() {
|
||||
val folderPath = "validFolder"
|
||||
val filePaths = listOf("file1.txt", "file2.doc", "file3.jpg")
|
||||
|
||||
val result = FileNameValidator.checkFolderAndFilePaths(folderPath, filePaths, capability, targetContext)
|
||||
assertTrue(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testFolderPathWithReservedName() {
|
||||
testOnlyOnServer(NextcloudVersion.nextcloud_30)
|
||||
|
||||
val folderPath = "CON"
|
||||
val filePaths = listOf("file1.txt", "file2.doc", "file3.jpg")
|
||||
|
||||
val result = FileNameValidator.checkFolderAndFilePaths(folderPath, filePaths, capability, targetContext)
|
||||
assertFalse(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testFilePathWithReservedName() {
|
||||
testOnlyOnServer(NextcloudVersion.nextcloud_30)
|
||||
|
||||
val folderPath = "validFolder"
|
||||
val filePaths = listOf("file1.txt", "PRN.doc", "file3.jpg")
|
||||
|
||||
val result = FileNameValidator.checkFolderAndFilePaths(folderPath, filePaths, capability, targetContext)
|
||||
assertFalse(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testFolderPathWithInvalidCharacter() {
|
||||
testOnlyOnServer(NextcloudVersion.nextcloud_30)
|
||||
|
||||
val folderPath = "invalid<Folder"
|
||||
val filePaths = listOf("file1.txt", "file2.doc", "file3.jpg")
|
||||
|
||||
val result = FileNameValidator.checkFolderAndFilePaths(folderPath, filePaths, capability, targetContext)
|
||||
assertFalse(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testFilePathWithInvalidCharacter() {
|
||||
testOnlyOnServer(NextcloudVersion.nextcloud_30)
|
||||
|
||||
val folderPath = "validFolder"
|
||||
val filePaths = listOf("file1.txt", "file|2.doc", "file3.jpg")
|
||||
|
||||
val result = FileNameValidator.checkFolderAndFilePaths(folderPath, filePaths, capability, targetContext)
|
||||
assertFalse(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testFolderPathEndingWithSpace() {
|
||||
val folderPath = "folderWithSpace "
|
||||
val filePaths = listOf("file1.txt", "file2.doc", "file3.jpg")
|
||||
|
||||
val result = FileNameValidator.checkFolderAndFilePaths(folderPath, filePaths, capability, targetContext)
|
||||
assertEquals(capability.version.isOlderThan(NextcloudVersion.nextcloud_30), result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testFilePathEndingWithPeriod() {
|
||||
val folderPath = "validFolder"
|
||||
val filePaths = listOf("file1.txt", "file2.doc", "file3.")
|
||||
|
||||
val result = FileNameValidator.checkFolderAndFilePaths(folderPath, filePaths, capability, targetContext)
|
||||
assertEquals(capability.version.isOlderThan(NextcloudVersion.nextcloud_30), result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testFilePathWithNestedFolder() {
|
||||
testOnlyOnServer(NextcloudVersion.nextcloud_30)
|
||||
|
||||
val folderPath = "validFolder\\secondValidFolder\\CON"
|
||||
val filePaths = listOf("file1.txt", "file2.doc", "file3.")
|
||||
|
||||
val result = FileNameValidator.checkFolderAndFilePaths(folderPath, filePaths, capability, targetContext)
|
||||
assertFalse(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOnlyFolderPath() {
|
||||
val folderPath = "/A1/Aaaww/W/C2/"
|
||||
|
||||
val result = FileNameValidator.checkFolderAndFilePaths(folderPath, listOf(), capability, targetContext)
|
||||
assertTrue(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOnlyFolderPathWithOneReservedName() {
|
||||
testOnlyOnServer(NextcloudVersion.nextcloud_30)
|
||||
|
||||
val folderPath = "/A1/Aaaww/CON/W/C2/"
|
||||
|
||||
val result = FileNameValidator.checkFolderAndFilePaths(folderPath, listOf(), capability, targetContext)
|
||||
assertFalse(result)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,272 @@
|
|||
/*
|
||||
* Nextcloud - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2025 Alper Ozturk <alper.ozturk@nextcloud.com>
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
package com.nextcloud.utils
|
||||
|
||||
import com.owncloud.android.datamodel.quickPermission.QuickPermissionType
|
||||
import com.owncloud.android.lib.resources.shares.OCShare
|
||||
import com.owncloud.android.lib.resources.shares.ShareType
|
||||
import com.owncloud.android.lib.resources.shares.extensions.isAllowDownloadAndSyncEnabled
|
||||
import com.owncloud.android.lib.resources.shares.extensions.toggleAllowDownloadAndSync
|
||||
import com.owncloud.android.ui.fragment.util.SharePermissionManager
|
||||
import junit.framework.TestCase.assertEquals
|
||||
import junit.framework.TestCase.assertFalse
|
||||
import junit.framework.TestCase.assertTrue
|
||||
import org.junit.Test
|
||||
|
||||
@Suppress("TooManyFunctions")
|
||||
class SharePermissionManagerTest {
|
||||
|
||||
private fun createShare(sharePermission: Int, isFolder: Boolean = false, attributesJson: String? = null): OCShare =
|
||||
if (isFolder) {
|
||||
OCShare("/test")
|
||||
.apply {
|
||||
permissions = sharePermission
|
||||
attributes = attributesJson
|
||||
shareType = ShareType.INTERNAL
|
||||
sharedDate = 1188206955
|
||||
shareWith = "User 1"
|
||||
sharedWithDisplayName = "User 1"
|
||||
}
|
||||
} else {
|
||||
OCShare("/test.png")
|
||||
.apply {
|
||||
permissions = sharePermission
|
||||
attributes = attributesJson
|
||||
shareType = ShareType.INTERNAL
|
||||
sharedDate = 1188206955
|
||||
shareWith = "User 1"
|
||||
sharedWithDisplayName = "User 1"
|
||||
}
|
||||
}.apply {
|
||||
this.isFolder = isFolder
|
||||
}
|
||||
|
||||
// region Permission change tests
|
||||
@Test
|
||||
fun testTogglePermissionShouldAddPermissionFlagWhenChecked() {
|
||||
val initialPermission = OCShare.READ_PERMISSION_FLAG
|
||||
val updatedPermission =
|
||||
SharePermissionManager.togglePermission(true, initialPermission, OCShare.UPDATE_PERMISSION_FLAG)
|
||||
val updatedShare = createShare(updatedPermission)
|
||||
assertTrue(SharePermissionManager.isCustomPermission(updatedShare))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testTogglePermissionShouldRemovePermissionFlagWhenUnchecked() {
|
||||
val initialPermission = OCShare.READ_PERMISSION_FLAG + OCShare.UPDATE_PERMISSION_FLAG
|
||||
val updatedPermission =
|
||||
SharePermissionManager.togglePermission(false, initialPermission, OCShare.UPDATE_PERMISSION_FLAG)
|
||||
val updatedShare = createShare(updatedPermission)
|
||||
assertTrue(SharePermissionManager.isViewOnly(updatedShare))
|
||||
}
|
||||
// endregion
|
||||
|
||||
// region HasPermissions tests
|
||||
@Test
|
||||
fun testHasPermissionShouldReturnTrueIfPermissionPresent() {
|
||||
val permission = OCShare.READ_PERMISSION_FLAG + OCShare.UPDATE_PERMISSION_FLAG
|
||||
assertTrue(SharePermissionManager.hasPermission(permission, OCShare.UPDATE_PERMISSION_FLAG))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testHasPermissionShouldReturnFalseIfPermissionNotPresent() {
|
||||
val permission = OCShare.READ_PERMISSION_FLAG
|
||||
assertFalse(SharePermissionManager.hasPermission(permission, OCShare.UPDATE_PERMISSION_FLAG))
|
||||
}
|
||||
// endregion
|
||||
|
||||
// region Helper Method Tests
|
||||
@Test
|
||||
fun testCanEditShouldReturnTrueIfAllPermissionsPresent() {
|
||||
val share = createShare(OCShare.MAXIMUM_PERMISSIONS_FOR_FOLDER, isFolder = true)
|
||||
assertTrue(SharePermissionManager.canEdit(share))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCanEditShouldReturnFalseIfPermissionsAreInsufficient() {
|
||||
val share = createShare(OCShare.READ_PERMISSION_FLAG)
|
||||
assertFalse(SharePermissionManager.canEdit(share))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsViewOnlyShouldReturnTrueIfOnlyReadPermissionSet() {
|
||||
val share = createShare(OCShare.READ_PERMISSION_FLAG)
|
||||
assertTrue(SharePermissionManager.isViewOnly(share))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsFileRequestShouldReturnTrueIfOnlyCreatePermissionSetOnFolder() {
|
||||
val share = createShare(OCShare.CREATE_PERMISSION_FLAG, isFolder = true)
|
||||
assertTrue(SharePermissionManager.isFileRequest(share))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsFileRequestShouldReturnFalseIfOnlyCreatePermissionSetOnFile() {
|
||||
val share = createShare(OCShare.CREATE_PERMISSION_FLAG)
|
||||
assertFalse(SharePermissionManager.isFileRequest(share))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsSecureFileDropShouldReturnTrueIfReadAndCreatePermissionsPresent() {
|
||||
val permission = OCShare.READ_PERMISSION_FLAG + OCShare.CREATE_PERMISSION_FLAG
|
||||
val share = createShare(permission)
|
||||
assertTrue(SharePermissionManager.isSecureFileDrop(share))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCanReshareShouldReturnTrueIfSharePermissionIsPresent() {
|
||||
val share = createShare(OCShare.SHARE_PERMISSION_FLAG)
|
||||
assertTrue(SharePermissionManager.canReshare(share))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetMaximumPermissionForFolder() {
|
||||
assertEquals(
|
||||
OCShare.MAXIMUM_PERMISSIONS_FOR_FOLDER,
|
||||
SharePermissionManager.getMaximumPermission(isFolder = true)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetMaximumPermissionForFile() {
|
||||
assertEquals(
|
||||
OCShare.MAXIMUM_PERMISSIONS_FOR_FILE,
|
||||
SharePermissionManager.getMaximumPermission(isFolder = false)
|
||||
)
|
||||
}
|
||||
// endregion
|
||||
|
||||
// region GetSelectedTypeTests
|
||||
@Test
|
||||
fun testGetSelectedTypeShouldReturnCanEditWhenFullPermissionsGiven() {
|
||||
val share = createShare(OCShare.MAXIMUM_PERMISSIONS_FOR_FILE)
|
||||
assertEquals(QuickPermissionType.CAN_EDIT, SharePermissionManager.getSelectedType(share, encrypted = false))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetSelectedTypeShouldReturnSecureFileDropWhenEncryptedAndReadCreateGiven() {
|
||||
val permission = OCShare.READ_PERMISSION_FLAG + OCShare.CREATE_PERMISSION_FLAG
|
||||
val share = createShare(permission)
|
||||
assertEquals(
|
||||
QuickPermissionType.SECURE_FILE_DROP,
|
||||
SharePermissionManager.getSelectedType(share, encrypted = true)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetSelectedTypeShouldReturnFileRequestWhenCreatePermissionGiven() {
|
||||
val share = createShare(OCShare.CREATE_PERMISSION_FLAG, isFolder = true)
|
||||
assertEquals(QuickPermissionType.FILE_REQUEST, SharePermissionManager.getSelectedType(share, encrypted = false))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetSelectedTypeShouldReturnViewOnlyWhenReadPermissionGiven() {
|
||||
val share = createShare(OCShare.READ_PERMISSION_FLAG)
|
||||
assertEquals(QuickPermissionType.VIEW_ONLY, SharePermissionManager.getSelectedType(share, encrypted = false))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetSelectedTypeShouldReturnCustomPermissionOnlyWhenCustomPermissionGiven() {
|
||||
val share = createShare(OCShare.READ_PERMISSION_FLAG + OCShare.UPDATE_PERMISSION_FLAG)
|
||||
assertEquals(
|
||||
QuickPermissionType.CUSTOM_PERMISSIONS,
|
||||
SharePermissionManager.getSelectedType(share, encrypted = false)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetSelectedTypeShouldReturnNoneOnlyWhenNoPermissionGiven() {
|
||||
val share = createShare(OCShare.NO_PERMISSION)
|
||||
assertEquals(
|
||||
QuickPermissionType.NONE,
|
||||
SharePermissionManager.getSelectedType(share, encrypted = false)
|
||||
)
|
||||
}
|
||||
// endregion
|
||||
|
||||
// region CustomPermissions Tests
|
||||
@Test
|
||||
fun testIsCustomPermissionShouldReturnFalseWhenNoPermissionsGiven() {
|
||||
val permission = OCShare.NO_PERMISSION
|
||||
val share = createShare(permission, isFolder = false)
|
||||
assertFalse(SharePermissionManager.isCustomPermission(share))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsCustomPermissionShouldReturnFalseWhenNoReadPermissionsGiven() {
|
||||
val permission = OCShare.SHARE_PERMISSION_FLAG + OCShare.UPDATE_PERMISSION_FLAG
|
||||
val share = createShare(permission, isFolder = false)
|
||||
assertFalse(SharePermissionManager.isCustomPermission(share))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsCustomPermissionShouldReturnTrueWhenUpdatePermissionsGivenOnFile() {
|
||||
val permission = OCShare.READ_PERMISSION_FLAG + OCShare.UPDATE_PERMISSION_FLAG
|
||||
val share = createShare(permission, isFolder = false)
|
||||
assertTrue(SharePermissionManager.isCustomPermission(share))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsCustomPermissionShouldReturnTrueWhenUpdateAndSharePermissionsGivenOnFile() {
|
||||
val permission = OCShare.READ_PERMISSION_FLAG + OCShare.UPDATE_PERMISSION_FLAG + OCShare.SHARE_PERMISSION_FLAG
|
||||
val share = createShare(permission, isFolder = false)
|
||||
assertTrue(SharePermissionManager.isCustomPermission(share))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsCustomPermissionShouldReturnFalseWhenCreatePermissionsGivenOnFile() {
|
||||
val permission = OCShare.READ_PERMISSION_FLAG + OCShare.CREATE_PERMISSION_FLAG
|
||||
val share = createShare(permission, isFolder = false)
|
||||
assertFalse(SharePermissionManager.isCustomPermission(share))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsCustomPermissionShouldReturnFalseWhenDeletePermissionsGivenOnFile() {
|
||||
val permission = OCShare.READ_PERMISSION_FLAG + OCShare.DELETE_PERMISSION_FLAG
|
||||
val share = createShare(permission, isFolder = false)
|
||||
assertFalse(SharePermissionManager.isCustomPermission(share))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsCustomPermissionShouldReturnTrueWhenCreatePermissionsGivenOnFolder() {
|
||||
val permission = OCShare.READ_PERMISSION_FLAG + OCShare.CREATE_PERMISSION_FLAG
|
||||
val share = createShare(permission, isFolder = true)
|
||||
assertTrue(SharePermissionManager.isCustomPermission(share))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsCustomPermissionShouldReturnTrueWhenMixedPermissionsOnFile() {
|
||||
val permission = OCShare.READ_PERMISSION_FLAG + OCShare.UPDATE_PERMISSION_FLAG
|
||||
val share = createShare(permission, isFolder = false)
|
||||
assertTrue(SharePermissionManager.isCustomPermission(share))
|
||||
}
|
||||
// endregion
|
||||
|
||||
// region Attributes Tests
|
||||
@Test
|
||||
fun testToggleAllowDownloadAndSyncShouldCreateAttributeJsonIfNoneExists() {
|
||||
val ocShare = OCShare().apply {
|
||||
isFolder = true
|
||||
shareType = ShareType.USER
|
||||
permissions = 17
|
||||
}
|
||||
ocShare.attributes = toggleAllowDownloadAndSync(
|
||||
ocShare.attributes,
|
||||
isChecked = true,
|
||||
useV2DownloadAttributes = false
|
||||
)
|
||||
assertTrue(ocShare.isAllowDownloadAndSyncEnabled(false))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsAllowDownloadAndSyncEnabledShouldReturnFalseIfAttributeIsMissing() {
|
||||
val share = createShare(OCShare.READ_PERMISSION_FLAG, attributesJson = null)
|
||||
assertFalse(share.isAllowDownloadAndSyncEnabled(false))
|
||||
}
|
||||
// endregion
|
||||
}
|
||||
|
|
@ -2,51 +2,76 @@
|
|||
* Nextcloud - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2023 TSI-mc
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
|
||||
*/
|
||||
package com.nmc.android.ui
|
||||
|
||||
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
|
||||
import androidx.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withId
|
||||
import androidx.test.ext.junit.rules.ActivityScenarioRule
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.owncloud.android.AbstractIT
|
||||
import com.owncloud.android.R
|
||||
import org.junit.Rule
|
||||
import com.owncloud.android.utils.EspressoIdlingResource
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class LauncherActivityIT : AbstractIT() {
|
||||
|
||||
@get:Rule
|
||||
val activityRule = ActivityScenarioRule(LauncherActivity::class.java)
|
||||
@Before
|
||||
fun registerIdlingResource() {
|
||||
IdlingRegistry.getInstance().register(EspressoIdlingResource.countingIdlingResource)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSplashScreenWithEmptyTitlesShouldHideTitles() {
|
||||
waitForIdleSync()
|
||||
|
||||
onView(withId(R.id.ivSplash)).check(matches(isCompletelyDisplayed()))
|
||||
|
||||
onView(withId(R.id.splashScreenBold)).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE)))
|
||||
onView(withId(R.id.splashScreenNormal)).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE)))
|
||||
@After
|
||||
fun unregisterIdlingResource() {
|
||||
IdlingRegistry.getInstance().unregister(EspressoIdlingResource.countingIdlingResource)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSplashScreenWithTitlesShouldShowTitles() {
|
||||
waitForIdleSync()
|
||||
onView(withId(R.id.ivSplash)).check(matches(isCompletelyDisplayed()))
|
||||
|
||||
activityRule.scenario.onActivity {
|
||||
it.setSplashTitles("Example", "Cloud")
|
||||
@UiThread
|
||||
fun testSplashScreenWithEmptyTitlesShouldHideTitles() {
|
||||
launchActivity<LauncherActivity>().use { scenario ->
|
||||
scenario.onActivity { _ ->
|
||||
onIdleSync {
|
||||
onView(withId(R.id.ivSplash)).check(matches(isCompletelyDisplayed()))
|
||||
onView(
|
||||
withId(R.id.splashScreenBold)
|
||||
).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE)))
|
||||
onView(
|
||||
withId(R.id.splashScreenNormal)
|
||||
).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val onePercentArea = ViewMatchers.isDisplayingAtLeast(1)
|
||||
onView(withId(R.id.splashScreenBold)).check(matches(onePercentArea))
|
||||
onView(withId(R.id.splashScreenNormal)).check(matches(onePercentArea))
|
||||
@Test
|
||||
@UiThread
|
||||
fun testSplashScreenWithTitlesShouldShowTitles() {
|
||||
launchActivity<LauncherActivity>().use { scenario ->
|
||||
scenario.onActivity {
|
||||
onIdleSync {
|
||||
onView(withId(R.id.ivSplash)).check(matches(isCompletelyDisplayed()))
|
||||
|
||||
EspressoIdlingResource.increment()
|
||||
it.setSplashTitles("Example", "Cloud")
|
||||
EspressoIdlingResource.decrement()
|
||||
|
||||
val onePercentArea = ViewMatchers.isDisplayingAtLeast(1)
|
||||
onView(withId(R.id.splashScreenBold)).check(matches(onePercentArea))
|
||||
onView(withId(R.id.splashScreenNormal)).check(matches(onePercentArea))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
||||
|
|
|
|||
183
app/src/androidTest/java/com/owncloud/android/ScreenshotsIT.kt
Normal file
183
app/src/androidTest/java/com/owncloud/android/ScreenshotsIT.kt
Normal 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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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']"))
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue