mirror of https://github.com/nextcloud/android
223 lines
7.1 KiB
Kotlin
223 lines
7.1 KiB
Kotlin
/*
|
|
* Nextcloud - Android Client
|
|
*
|
|
* SPDX-FileCopyrightText: 2020 Chris Narkiewicz <hello@ezaquarii.com>
|
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
|
*/
|
|
package com.nextcloud.client.files
|
|
|
|
import android.net.Uri
|
|
import com.nextcloud.client.account.Server
|
|
import com.nextcloud.client.account.User
|
|
import com.nextcloud.client.account.UserAccountManager
|
|
import com.owncloud.android.lib.resources.status.OwnCloudVersion
|
|
import org.junit.Assert.assertEquals
|
|
import org.junit.Assert.assertNotNull
|
|
import org.junit.Assert.assertNull
|
|
import org.junit.Assert.assertSame
|
|
import org.junit.Before
|
|
import org.junit.Test
|
|
import org.junit.runner.RunWith
|
|
import org.junit.runners.Parameterized
|
|
import org.junit.runners.Suite
|
|
import org.mockito.Mock
|
|
import org.mockito.MockitoAnnotations
|
|
import org.mockito.kotlin.mock
|
|
import org.mockito.kotlin.whenever
|
|
import java.net.URI
|
|
|
|
@RunWith(Suite::class)
|
|
@Suite.SuiteClasses(
|
|
DeepLinkHandlerTest.DeepLinkPattern::class,
|
|
DeepLinkHandlerTest.FileDeepLink::class
|
|
)
|
|
class DeepLinkHandlerTest {
|
|
|
|
@RunWith(Parameterized::class)
|
|
class DeepLinkPattern {
|
|
|
|
companion object {
|
|
val FILE_ID = 1234
|
|
val SERVER_BASE_URLS = listOf(
|
|
"http://hostname.net",
|
|
"https://hostname.net",
|
|
"http://hostname.net/subdir1",
|
|
"https://hostname.net/subdir1",
|
|
"http://hostname.net/subdir1/subdir2",
|
|
"https://hostname.net/subdir1/subdir2",
|
|
"http://hostname.net/subdir1/subdir2/subdir3",
|
|
"https://hostname.net/subdir1/subdir2/subdir3"
|
|
)
|
|
val INDEX_PHP_PATH = listOf(
|
|
"",
|
|
"/index.php"
|
|
)
|
|
|
|
@Parameterized.Parameters
|
|
@JvmStatic
|
|
fun urls(): Array<Array<Any>> {
|
|
val testInput = mutableListOf<Array<Any>>()
|
|
SERVER_BASE_URLS.forEach { baseUrl ->
|
|
INDEX_PHP_PATH.forEach { indexPath ->
|
|
val url = "$baseUrl$indexPath/f/$FILE_ID"
|
|
testInput.add(arrayOf(baseUrl, indexPath, "$FILE_ID", url))
|
|
}
|
|
}
|
|
return testInput.toTypedArray()
|
|
}
|
|
}
|
|
|
|
@Parameterized.Parameter(0)
|
|
lateinit var baseUrl: String
|
|
|
|
@Parameterized.Parameter(1)
|
|
lateinit var indexPath: String
|
|
|
|
@Parameterized.Parameter(2)
|
|
lateinit var fileId: String
|
|
|
|
@Parameterized.Parameter(3)
|
|
lateinit var url: String
|
|
|
|
@Test
|
|
fun matches_deep_link_patterns() {
|
|
val match = DeepLinkHandler.DEEP_LINK_PATTERN.matchEntire(url)
|
|
assertNotNull("Url [$url] does not match pattern", match)
|
|
assertEquals(baseUrl, match?.groupValues?.get(DeepLinkHandler.BASE_URL_GROUP_INDEX))
|
|
assertEquals(indexPath, match?.groupValues?.get(DeepLinkHandler.INDEX_PATH_GROUP_INDEX))
|
|
assertEquals(fileId, match?.groupValues?.get(DeepLinkHandler.FILE_ID_GROUP_INDEX))
|
|
}
|
|
|
|
@Test
|
|
fun no_trailing_path_allowed_after_file_id() {
|
|
val invalidUrl = "$url/"
|
|
val match = DeepLinkHandler.DEEP_LINK_PATTERN.matchEntire(invalidUrl)
|
|
assertNull(match)
|
|
}
|
|
}
|
|
|
|
class FileDeepLink {
|
|
|
|
companion object {
|
|
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")
|
|
|
|
fun createMockUser(serverBaseUrl: String): User {
|
|
val user = mock<User>()
|
|
val uri = URI.create(serverBaseUrl)
|
|
val server = Server(uri = uri, version = OwnCloudVersion.nextcloud_19)
|
|
whenever(user.server).thenReturn(server)
|
|
return user
|
|
}
|
|
}
|
|
|
|
@Mock
|
|
lateinit var userAccountManager: UserAccountManager
|
|
lateinit var allUsers: List<User>
|
|
lateinit var handler: DeepLinkHandler
|
|
|
|
@Before
|
|
fun setUp() {
|
|
MockitoAnnotations.initMocks(this)
|
|
whenever(userAccountManager.allUsers).thenAnswer { allUsers }
|
|
allUsers = emptyList()
|
|
handler = DeepLinkHandler(userAccountManager)
|
|
}
|
|
|
|
@Test
|
|
fun no_user_can_open_file() {
|
|
// GIVEN
|
|
// no user capable of opening the file
|
|
allUsers = listOf(
|
|
createMockUser(OTHER_SERVER_BASE_URL),
|
|
createMockUser(OTHER_SERVER_BASE_URL)
|
|
)
|
|
|
|
// WHEN
|
|
// deep link is parsed
|
|
val match = handler.parseDeepLink(DEEP_LINK)
|
|
|
|
// THEN
|
|
// link is valid
|
|
// no user can open the file
|
|
assertNotNull(match)
|
|
assertEquals(0, match?.users?.size)
|
|
}
|
|
|
|
@Test
|
|
fun single_user_can_open_file() {
|
|
// GIVEN
|
|
// multiple users registered
|
|
// one user capable of opening the link
|
|
val matchingUser = createMockUser(SERVER_BASE_URL)
|
|
allUsers = listOf(
|
|
createMockUser(OTHER_SERVER_BASE_URL),
|
|
matchingUser,
|
|
createMockUser(OTHER_SERVER_BASE_URL)
|
|
)
|
|
|
|
// WHEN
|
|
// deep link is parsed
|
|
val match = handler.parseDeepLink(DEEP_LINK)
|
|
|
|
// THEN
|
|
// link can be opened by single user
|
|
assertNotNull(match)
|
|
assertSame(matchingUser, match?.users?.get(0))
|
|
}
|
|
|
|
@Test
|
|
fun multiple_users_can_open_file() {
|
|
// GIVEN
|
|
// mutltiple users registered
|
|
// multiple users capable of opening the link
|
|
val matchingUsers = setOf(
|
|
createMockUser(SERVER_BASE_URL),
|
|
createMockUser(SERVER_BASE_URL)
|
|
)
|
|
val otherUsers = setOf(
|
|
createMockUser(OTHER_SERVER_BASE_URL),
|
|
createMockUser(OTHER_SERVER_BASE_URL)
|
|
)
|
|
allUsers = listOf(matchingUsers, otherUsers).flatten()
|
|
|
|
// WHEN
|
|
// deep link is parsed
|
|
val match = handler.parseDeepLink(DEEP_LINK)
|
|
|
|
// THEN
|
|
// link can be opened by multiple matching users
|
|
assertNotNull(match)
|
|
assertEquals(matchingUsers, match?.users?.toSet())
|
|
}
|
|
|
|
@Test
|
|
fun match_contains_extracted_file_id() {
|
|
// WHEN
|
|
// valid deep file link is parsed
|
|
val match = handler.parseDeepLink(DEEP_LINK)
|
|
|
|
// THEN
|
|
// file id is returned
|
|
assertEquals(FILE_ID, match?.fileId)
|
|
}
|
|
|
|
@Test
|
|
fun no_match_for_invalid_link() {
|
|
// GIVEN
|
|
// invalid deep link
|
|
val invalidLink = Uri.parse("http://www.dodgylink.com/index.php")
|
|
|
|
// WHEN
|
|
// deep link is parsed
|
|
val match = handler.parseDeepLink(invalidLink)
|
|
|
|
// THEN
|
|
// no match
|
|
assertNull(match)
|
|
}
|
|
}
|
|
}
|