android/app/src/androidTest/java/com/nextcloud/client/files/DeepLinkHandlerTest.kt

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)
}
}
}