@@ -8,11 +8,13 @@ import android.graphics.Bitmap
88import android.net.Uri
99import android.os.Environment
1010import android.view.View
11+ import androidx.recyclerview.widget.RecyclerView
1112import androidx.test.espresso.Espresso.onView
1213import androidx.test.espresso.NoMatchingViewException
1314import androidx.test.espresso.action.ViewActions.click
1415import androidx.test.espresso.action.ViewActions.replaceText
1516import androidx.test.espresso.assertion.ViewAssertions.matches
17+ import androidx.test.espresso.contrib.RecyclerViewActions
1618import androidx.test.espresso.intent.Intents
1719import androidx.test.espresso.intent.Intents.intended
1820import androidx.test.espresso.intent.Intents.intending
@@ -24,6 +26,8 @@ import androidx.test.rule.ActivityTestRule
2426import androidx.test.rule.GrantPermissionRule
2527import androidx.test.runner.AndroidJUnit4
2628import fr.free.nrw.commons.auth.LoginActivity
29+ import fr.free.nrw.commons.upload.DescriptionsAdapter
30+ import fr.free.nrw.commons.util.MyViewAction
2731import fr.free.nrw.commons.utils.ConfigUtils
2832import org.hamcrest.core.AllOf.allOf
2933import org.junit.After
@@ -65,68 +69,154 @@ class UploadTest {
6569 }
6670 UITestHelper .skipWelcome()
6771 UITestHelper .loginUser()
68- saveToInternalStorage()
6972 }
7073
7174 @After
7275 fun teardown () {
7376 Intents .release()
7477 }
7578
76- private fun saveToInternalStorage () {
77- val bitmapImage = randomBitmap
79+ @Test
80+ fun testUploadWithDescription () {
81+ if (! ConfigUtils .isBetaFlavour()) {
82+ throw Error (" This test should only be run in Beta!" )
83+ }
7884
79- // path to /data/data/yourapp/app_data/imageDir
80- val mypath = File (Environment .getExternalStorageDirectory(), " image.jpg" )
85+ setupSingleUpload(" image.jpg" )
8186
82- Timber .d( " Filepath: %s " , mypath.path )
87+ openGallery( )
8388
84- Timber .d(" Absolute Filepath: %s" , mypath.absolutePath)
89+ // Validate that an intent to get an image is sent
90+ intended(allOf(hasAction(Intent .ACTION_GET_CONTENT ), hasType(" image/*" )))
91+
92+ // Create filename with the current time (to prevent overwrites)
93+ val dateFormat = SimpleDateFormat (" yyMMdd-hhmmss" )
94+ val commonsFileName = " MobileTest " + dateFormat.format(Date ())
95+
96+ // Try to dismiss the error, if there is one (probably about duplicate files on Commons)
97+ dismissWarning(" Yes" )
98+
99+ onView(allOf<View >(isDisplayed(), withId(R .id.et_title)))
100+ .perform(replaceText(commonsFileName))
101+
102+ onView(allOf<View >(isDisplayed(), withId(R .id.description_item_edit_text)))
103+ .perform(replaceText(commonsFileName))
104+
105+
106+ onView(allOf(isDisplayed(), withId(R .id.btn_next)))
107+ .perform(click())
108+
109+ UITestHelper .sleep(5000 )
110+ dismissWarning(" Yes" )
111+
112+ UITestHelper .sleep(3000 )
113+
114+ onView(allOf(isDisplayed(), withId(R .id.et_search)))
115+ .perform(replaceText(" Uploaded with Mobile/Android Tests" ))
116+
117+ UITestHelper .sleep(3000 )
85118
86- var fos: FileOutputStream ? = null
87119 try {
88- fos = FileOutputStream (mypath)
89- // Use the compress method on the BitMap object to write image to the OutputStream
90- bitmapImage.compress(Bitmap .CompressFormat .JPEG , 100 , fos)
91- } catch (e: Exception ) {
92- e.printStackTrace()
93- } finally {
94- try {
95- fos?.close()
96- } catch (e: IOException ) {
97- e.printStackTrace()
98- }
120+ onView(allOf(isDisplayed(), UITestHelper .first(withParent(withId(R .id.rv_categories)))))
121+ .perform(click())
122+ } catch (ignored: NoMatchingViewException ) {
123+ }
124+
125+ onView(allOf(isDisplayed(), withId(R .id.btn_next)))
126+ .perform(click())
127+
128+ dismissWarning(" Yes, Submit" )
129+
130+ UITestHelper .sleep(500 )
131+
132+ onView(allOf(isDisplayed(), withId(R .id.btn_submit)))
133+ .perform(click())
99134
135+ UITestHelper .sleep(10000 )
136+
137+ val fileUrl = " https://commons.wikimedia.beta.wmflabs.org/wiki/File:" +
138+ commonsFileName.replace(' ' , ' _' ) + " .jpg"
139+ Timber .i(" File should be uploaded to $fileUrl " )
140+ }
141+
142+ private fun dismissWarning (warningText : String ) {
143+ try {
144+ onView(withText(warningText))
145+ .check(matches(isDisplayed()))
146+ .perform(click())
147+ } catch (ignored: NoMatchingViewException ) {
100148 }
101149 }
102150
103151 @Test
104- fun uploadTest () {
152+ fun testUploadWithoutDescription () {
105153 if (! ConfigUtils .isBetaFlavour()) {
106154 throw Error (" This test should only be run in Beta!" )
107155 }
108156
109- // Uri to return by our mock gallery selector
110- // Requires file 'image.jpg' to be placed at root of file structure
111- val imageUri = Uri .parse(" file://mnt/sdcard/image.jpg" )
157+ setupSingleUpload(" image.jpg" )
112158
113- // Build a result to return from the Camera app
114- val intent = Intent ()
115- intent.data = imageUri
116- val result = ActivityResult (Activity .RESULT_OK , intent)
159+ openGallery()
117160
118- // Stub out the File picker. When an intent is sent to the File picker, this tells
119- // Espresso to respond with the ActivityResult we just created
120- intending(allOf(hasAction(Intent .ACTION_GET_CONTENT ), hasType(" image/*" ))).respondWith(result)
161+ // Validate that an intent to get an image is sent
162+ intended(allOf(hasAction(Intent .ACTION_GET_CONTENT ), hasType(" image/*" )))
121163
122- // Open FAB
123- onView(allOf<View >(withId(R .id.fab_plus), isDisplayed()))
164+ // Create filename with the current time (to prevent overwrites)
165+ val dateFormat = SimpleDateFormat (" yyMMdd-hhmmss" )
166+ val commonsFileName = " MobileTest " + dateFormat.format(Date ())
167+
168+ // Try to dismiss the error, if there is one (probably about duplicate files on Commons)
169+ dismissWarning(" Yes" )
170+
171+ onView(allOf<View >(isDisplayed(), withId(R .id.et_title)))
172+ .perform(replaceText(commonsFileName))
173+
174+ onView(allOf(isDisplayed(), withId(R .id.btn_next)))
124175 .perform(click())
125176
126- // Click gallery
127- onView(allOf<View >(withId(R .id.fab_gallery), isDisplayed()))
177+ UITestHelper .sleep(10000 )
178+ dismissWarning(" Yes" )
179+
180+ UITestHelper .sleep(3000 )
181+
182+ onView(allOf(isDisplayed(), withId(R .id.et_search)))
183+ .perform(replaceText(" Test" ))
184+
185+ UITestHelper .sleep(3000 )
186+
187+ try {
188+ onView(allOf(isDisplayed(), UITestHelper .first(withParent(withId(R .id.rv_categories)))))
189+ .perform(click())
190+ } catch (ignored: NoMatchingViewException ) {
191+ }
192+
193+ onView(allOf(isDisplayed(), withId(R .id.btn_next)))
194+ .perform(click())
195+
196+ dismissWarning(" Yes, Submit" )
197+
198+ UITestHelper .sleep(500 )
199+
200+ onView(allOf(isDisplayed(), withId(R .id.btn_submit)))
128201 .perform(click())
129202
203+ UITestHelper .sleep(10000 )
204+
205+ val fileUrl = " https://commons.wikimedia.beta.wmflabs.org/wiki/File:" +
206+ commonsFileName.replace(' ' , ' _' ) + " .jpg"
207+ Timber .i(" File should be uploaded to $fileUrl " )
208+ }
209+
210+ @Test
211+ fun testUploadWithMultilingualDescription () {
212+ if (! ConfigUtils .isBetaFlavour()) {
213+ throw Error (" This test should only be run in Beta!" )
214+ }
215+
216+ setupSingleUpload(" image.jpg" )
217+
218+ openGallery()
219+
130220 // Validate that an intent to get an image is sent
131221 intended(allOf(hasAction(Intent .ACTION_GET_CONTENT ), hasType(" image/*" )))
132222
@@ -135,14 +225,28 @@ class UploadTest {
135225 val commonsFileName = " MobileTest " + dateFormat.format(Date ())
136226
137227 // Try to dismiss the error, if there is one (probably about duplicate files on Commons)
138- dismissWarning( " Yes " )
228+ dismissWarningDialog( )
139229
140230 onView(allOf<View >(isDisplayed(), withId(R .id.et_title)))
141231 .perform(replaceText(commonsFileName))
142232
143- onView(allOf<View >(isDisplayed(), withId(R .id.description_item_edit_text)))
144- .perform(replaceText(commonsFileName))
233+ onView(withId(R .id.rv_descriptions)).perform(
234+ RecyclerViewActions
235+ .actionOnItemAtPosition<DescriptionsAdapter .ViewHolder >(0 ,
236+ MyViewAction .typeTextInChildViewWithId(R .id.description_item_edit_text, " Test description" )))
237+
238+ onView(withId(R .id.btn_add_description))
239+ .perform(click())
240+
241+ onView(withId(R .id.rv_descriptions)).perform(
242+ RecyclerViewActions
243+ .actionOnItemAtPosition<DescriptionsAdapter .ViewHolder >(1 ,
244+ MyViewAction .selectSpinnerItemInChildViewWithId(R .id.spinner_description_languages, 2 )))
145245
246+ onView(withId(R .id.rv_descriptions)).perform(
247+ RecyclerViewActions
248+ .actionOnItemAtPosition<DescriptionsAdapter .ViewHolder >(1 ,
249+ MyViewAction .typeTextInChildViewWithId(R .id.description_item_edit_text, " Description" )))
146250
147251 onView(allOf(isDisplayed(), withId(R .id.btn_next)))
148252 .perform(click())
@@ -153,12 +257,12 @@ class UploadTest {
153257 UITestHelper .sleep(3000 )
154258
155259 onView(allOf(isDisplayed(), withId(R .id.et_search)))
156- .perform(replaceText(" Uploaded with Mobile/Android Tests " ))
260+ .perform(replaceText(" Test " ))
157261
158262 UITestHelper .sleep(3000 )
159263
160264 try {
161- onView(allOf(isDisplayed(), withParent(withId(R .id.rv_categories))))
265+ onView(allOf(isDisplayed(), UITestHelper .first( withParent(withId(R .id.rv_categories) ))))
162266 .perform(click())
163267 } catch (ignored: NoMatchingViewException ) {
164268 }
@@ -180,12 +284,69 @@ class UploadTest {
180284 Timber .i(" File should be uploaded to $fileUrl " )
181285 }
182286
183- private fun dismissWarning (warningText : String ) {
287+ private fun setupSingleUpload (imageName : String ) {
288+ saveToInternalStorage(imageName)
289+ singleImageIntent(imageName)
290+ }
291+
292+ private fun saveToInternalStorage (imageName : String ) {
293+ val bitmapImage = randomBitmap
294+
295+ // path to /data/data/yourapp/app_data/imageDir
296+ val mypath = File (Environment .getExternalStorageDirectory(), imageName)
297+
298+ Timber .d(" Filepath: %s" , mypath.path)
299+
300+ Timber .d(" Absolute Filepath: %s" , mypath.absolutePath)
301+
302+ var fos: FileOutputStream ? = null
184303 try {
185- onView(withText(warningText))
304+ fos = FileOutputStream (mypath)
305+ // Use the compress method on the BitMap object to write image to the OutputStream
306+ bitmapImage.compress(Bitmap .CompressFormat .JPEG , 100 , fos)
307+ } catch (e: Exception ) {
308+ e.printStackTrace()
309+ } finally {
310+ try {
311+ fos?.close()
312+ } catch (e: IOException ) {
313+ e.printStackTrace()
314+ }
315+
316+ }
317+ }
318+
319+ private fun singleImageIntent (imageName : String ) {
320+ // Uri to return by our mock gallery selector
321+ // Requires file 'image.jpg' to be placed at root of file structure
322+ val imageUri = Uri .parse(" file://mnt/sdcard/$imageName " )
323+
324+ // Build a result to return from the Camera app
325+ val intent = Intent ()
326+ intent.data = imageUri
327+ val result = ActivityResult (Activity .RESULT_OK , intent)
328+
329+ // Stub out the File picker. When an intent is sent to the File picker, this tells
330+ // Espresso to respond with the ActivityResult we just created
331+ intending(allOf(hasAction(Intent .ACTION_GET_CONTENT ), hasType(" image/*" ))).respondWith(result)
332+ }
333+
334+ private fun dismissWarningDialog () {
335+ try {
336+ onView(withText(" Yes" ))
186337 .check(matches(isDisplayed()))
187338 .perform(click())
188339 } catch (ignored: NoMatchingViewException ) {
189340 }
190341 }
342+
343+ private fun openGallery () {
344+ // Open FAB
345+ onView(allOf<View >(withId(R .id.fab_plus), isDisplayed()))
346+ .perform(click())
347+
348+ // Click gallery
349+ onView(allOf<View >(withId(R .id.fab_gallery), isDisplayed()))
350+ .perform(click())
351+ }
191352}
0 commit comments