11/*
22 * Nextcloud - Android Client
33 *
4+ * SPDX-FileCopyrightText: 2025 Philipp Hasper <vcs@hasper.info>
45 * SPDX-FileCopyrightText: 2025 Alper Ozturk <alper.ozturk@nextcloud.com>
56 * SPDX-FileCopyrightText: 2022 Tobias Kaminsky <tobias@kaminsky.me>
67 * SPDX-FileCopyrightText: 2022 Nextcloud GmbH
78 * SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
89 */
910package com.owncloud.android.ui.activity
1011
12+ import android.content.Intent
13+ import android.net.Uri
14+ import android.view.KeyEvent
1115import androidx.test.core.app.launchActivity
1216import androidx.test.espresso.Espresso.onView
17+ import androidx.test.espresso.action.ViewActions
1318import androidx.test.espresso.assertion.ViewAssertions.matches
19+ import androidx.test.espresso.matcher.ViewMatchers.hasDescendant
1420import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
21+ import androidx.test.espresso.matcher.ViewMatchers.isEnabled
1522import androidx.test.espresso.matcher.ViewMatchers.isRoot
23+ import androidx.test.espresso.matcher.ViewMatchers.withId
24+ import androidx.test.espresso.matcher.ViewMatchers.withText
25+ import com.nextcloud.client.preferences.AppPreferencesImpl
26+ import com.nextcloud.test.GrantStoragePermissionRule
27+ import com.nextcloud.test.withSelectedText
28+ import com.nextcloud.utils.extensions.removeFileExtension
1629import com.owncloud.android.AbstractIT
30+ import com.owncloud.android.R
31+ import com.owncloud.android.datamodel.OCFile
1732import com.owncloud.android.utils.ScreenshotTest
33+ import org.junit.Rule
1834import org.junit.Test
35+ import org.junit.rules.TestRule
36+ import java.io.File
1937
2038class ReceiveExternalFilesActivityIT : AbstractIT () {
2139 private val testClassName = " com.owncloud.android.ui.activity.ReceiveExternalFilesActivityIT"
2240
41+ @get:Rule
42+ var storagePermissionRule: TestRule = GrantStoragePermissionRule .grant()
43+
2344 @Test
2445 @ScreenshotTest
2546 fun open () {
@@ -40,4 +61,109 @@ class ReceiveExternalFilesActivityIT : AbstractIT() {
4061 open()
4162 removeAccount(secondAccount)
4263 }
64+
65+ /*
66+ TODO: Tests to add
67+ 1. Change file name, then navigate to another folder, then back press to top folder -> filename must still stay changed
68+ 2. Have a file name without a dot
69+ 3. BUG: Change name multiple times (first long name, then short), leaving and re-entering the text field
70+ 3. Share a folder, not a file
71+ 4. Share multiple files
72+ 5. Use unexpected characters, like a "/"
73+ */
74+
75+ fun createSendIntent (file : File ): Intent = Intent (targetContext, ReceiveExternalFilesActivity ::class .java).apply {
76+ action = Intent .ACTION_SEND
77+ addFlags(Intent .FLAG_GRANT_READ_URI_PERMISSION )
78+ putExtra(Intent .EXTRA_STREAM , Uri .fromFile(file))
79+ }
80+
81+ // public fun createSendIntent(context: Context, files: Array<File>): Intent = Intent().apply {
82+ // action = Intent.ACTION_SEND_MULTIPLE
83+ // type = getUniqueMimetype(files)
84+ // addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
85+ // putParcelableArrayListExtra(Intent.EXTRA_STREAM, ArrayList(files.map { it.toURI() }))
86+ // }
87+
88+ @Test
89+ fun renameSingleFileUpload () {
90+ val imageFile = getDummyFile(" image.jpg" )
91+ val intent = createSendIntent(imageFile)
92+
93+ // Create folders with the necessary permissions
94+ val mainFolder = OCFile (" /folder/" ).apply {
95+ permissions = OCFile .PERMISSION_CAN_CREATE_FILE_AND_FOLDER
96+ setFolder()
97+ fileDataStorageManager.saveNewFile(this )
98+ }
99+ val subFolder = OCFile (" ${mainFolder.remotePath} sub folder/" ).apply {
100+ permissions = OCFile .PERMISSION_CAN_CREATE_FILE_AND_FOLDER
101+ setFolder()
102+ fileDataStorageManager.saveNewFile(this )
103+ }
104+
105+ // Store the folder in preferences, so the activity starts from there.
106+ @Suppress(" DEPRECATION" )
107+ val preferences = AppPreferencesImpl .fromContext(targetContext)
108+ preferences.setLastUploadPath(mainFolder.remotePath)
109+
110+ launchActivity<ReceiveExternalFilesActivity >(intent).use {
111+ val expectedMainFolderTitle = (getCurrentActivity() as ToolbarActivity ).getActionBarTitle(mainFolder, false )
112+ // Verify that the test starts in the expected folder. If this fails, change the setup calls above
113+ onView(withId(R .id.toolbar))
114+ .check(matches(hasDescendant(withText(expectedMainFolderTitle))))
115+
116+ onView(withText(R .string.uploader_btn_upload_text))
117+ .check(matches(isDisplayed()))
118+ .check(matches(isEnabled()))
119+
120+ // Test the pre-selection behavior (filename, but without extension, shall be selected)
121+ onView(withId(R .id.user_input))
122+ .check(matches(withText(imageFile.name)))
123+ .perform(ViewActions .click())
124+ .check(matches(withSelectedText(imageFile.name.removeFileExtension())))
125+
126+ // Set a new file name
127+ val secondFileName = " New filename.jpg"
128+ onView(withId(R .id.user_input))
129+ .perform(ViewActions .typeTextIntoFocusedView(secondFileName.removeFileExtension()))
130+ .check(matches(withText(secondFileName)))
131+ // Leave the field and come back to verify the pre-selection behavior correctly handles the new name
132+ .perform(ViewActions .pressKey(KeyEvent .KEYCODE_TAB ))
133+ .perform(ViewActions .click())
134+ .check(matches(withSelectedText(secondFileName.removeFileExtension())))
135+
136+ // Set a file name without file extension
137+ val thirdFileName = " no extension"
138+ onView(withId(R .id.user_input))
139+ .perform(ViewActions .clearText())
140+ .perform(ViewActions .typeTextIntoFocusedView(thirdFileName))
141+ .check(matches(withText(thirdFileName)))
142+ // Leave the field and come back to verify the pre-selection behavior correctly handles the new name
143+ .perform(ViewActions .pressKey(KeyEvent .KEYCODE_TAB ))
144+ .perform(ViewActions .click())
145+ .check(matches(withSelectedText(thirdFileName)))
146+
147+ /*
148+ * TODO - NOMERGE: check that the new name is actually used during the upload!
149+ */
150+
151+ // Enter the subfolder and verify that the text stays intact
152+ val expectedSubFolderTitle = (getCurrentActivity() as ToolbarActivity ).getActionBarTitle(subFolder, false )
153+ onView(withText(expectedSubFolderTitle))
154+ .perform(ViewActions .click())
155+ onView(withId(R .id.toolbar))
156+ .check(matches(hasDescendant(withText(expectedSubFolderTitle))))
157+ onView(withId(R .id.user_input))
158+ .check(matches(withText(secondFileName)))
159+ .perform(ViewActions .click())
160+ .check(matches(withSelectedText(secondFileName.removeFileExtension())))
161+
162+ // Set a new, shorter file name
163+ val fourthFileName = " short.jpg"
164+ onView(withId(R .id.user_input))
165+ .perform(ViewActions .typeTextIntoFocusedView(fourthFileName.removeFileExtension()))
166+ .check(matches(withText(fourthFileName)))
167+ }
168+ }
43169}
0 commit comments