Refactor uploads (#2981)

* Feature/refractor uploads [WIP] (#2887)

* Fix duplicate param information (#2515)

* Bug fix issue #2476 (#2526)

* Added wikidataEntityID in all db versions, handled db.execSql via method runQuery

* Versioning and changelog for v2.10.2 (#2531)

* Update changelog.md

* Versioning for v2.10.2

* Update changelog.md

* Bugfix/issue 2580 (#2584)

* Corrected string placedholders in certain string files

* Corrected string placedholders in certain string files[Bug fix #2580]

* Bug Fix #2585 (#2647)

* Bug Fix #2585
* Added null checks on view in SearchImageFragment when updating views from external sources
* Disposed the disposables in SearchActivity and SearchImageFragment when no longer in active lifecycle

* use FragmentUtils to verify fragment active state

* Bug Fix issue #2648 (#2678)

* Bug Fix issue #2648
* Handled external storage permission before file download

* * Removed redudant check for permission in MediaDetailPagerFragment (Dexter already does that)
* Removed duplicate code in PermissionUtil$checkPermissionsAndPerformAction, used the existing function with conditional extra parameters

* string name typo correction

* BugFix issue #2652 (#2706)

* Addded null check on bookmark before operating on it

* BugFix issue #2711 (#2712)

* Added null checks in OkHttpJsonApiClient$searchImages MwQueryResponse

* BugFix #2718 (#2719)

* Handled null auth cookies

* Fix #2791: NPE when nominating for deletion and leaving screen (#2792)

* Bug Fix issue #2789 (#2790)

* Handled Illegal State Exception for non existent appropriate view parents in ViewUtils$showShortSnackbar

* BugFix #2720 (#2831)

BugFix deprecated licenes #2720

* ui fixes, wip, upload

* *Issue #2886, BugFix #2832[wip]
* updated UploadActivity code
* modified ui
* Updated UploadPresenterTest

* * updated interfaces names to follow names suffixed with Contract
* added test cases

* card view elevation

* view pager disabled swipe

* bug fix, duplicate image

* used existing non-swipable view pager

* Avoid image view resize with keyboard, added adjustPan and stateVisible as softinputMode for UploadActivity

* retain UploadBaseFragment instances on orientation changes

* * Added test cases for UploadMediaPresenter
* Injected io and main thread schedulers

* categories presenter test cased wip

* Added CategoriesPresenter test

* * Added the logic to show open map (with to be uploaded image's coordinates while uploading image)

* codacy suggested changes * added java docs

* Added travis_wait fot android-wait-for-emulator

* ranamed interface onResponseCallback to Callback

* * Added api to delete picture in UploadModel
* cleanUp in UploadModel. once upload has been initiated
* Removed unused methods from UploadModel and the corresponding test class

* * Added tests for UploadPresenter
* Travis suggested changes
* Addded copy previous title and description

* * Made the upload add descriptions visible when keyboard visible
* add description request focus only when user manually requests it

* Added JavaDocs, review suggested changes

* Fix dagger injection

* use DialogUtil to show info in descriptions

* use activity context for DialogUtil

* Minor changes

* Bug fix, reduced the add description edit text clickable bound (#2973)

* Bugfix/uploads (#3000)

* merged with master

* BugFix IllegalStateException
* setRetainState(true), not required with FragmentStatePagerAdapter
* Increase the ViewPager's Offscreen Limit, we want all the fragments to be active

* BugFix, clear selected categoris for previous upload session
* Clear Selected Categories
* Addded JavaDocs for CategoriesModel

* Code Formatting in app/src/main/java/fr/free/nrw/commons/upload/UploadModel.java

* Added class level JavaDoc UploadRemoteDataSource

* Added class level JavaDoc for UploadRepository

* Added JavaDocs for ThumbnailsAdapter

* Added JavaDocs for MediaLicensePresenter, CategoriesPresenter

* Removed null check on category query
* Show default catgeories based on image title and gps location when category text empty
* Allow search for empty category search

* Attached image scale listener to upload media image

* Bug fix, reduced the add description edit text clickable bound

* Fix memory leak (#3001)

* Bugfix/uploads (#3002)

* merged with master

* BugFix IllegalStateException
* setRetainState(true), not required with FragmentStatePagerAdapter
* Increase the ViewPager's Offscreen Limit, we want all the fragments to be active

* BugFix, clear selected categoris for previous upload session
* Clear Selected Categories
* Addded JavaDocs for CategoriesModel

* Code Formatting in app/src/main/java/fr/free/nrw/commons/upload/UploadModel.java

* Added class level JavaDoc UploadRemoteDataSource

* Added class level JavaDoc for UploadRepository

* Added JavaDocs for ThumbnailsAdapter

* Added JavaDocs for MediaLicensePresenter, CategoriesPresenter

* Removed null check on category query
* Show default catgeories based on image title and gps location when category text empty
* Allow search for empty category search

* Attached image scale listener to upload media image

* Bug fix, reduced the add description edit text clickable bound

* Added tooltip in Title in UploadMediaFragment

* BugFix recent categories

* Updated test methods

* Bugfix/uploads (#3011)

* merged with master

* BugFix IllegalStateException
* setRetainState(true), not required with FragmentStatePagerAdapter
* Increase the ViewPager's Offscreen Limit, we want all the fragments to be active

* BugFix, clear selected categoris for previous upload session
* Clear Selected Categories
* Addded JavaDocs for CategoriesModel

* Code Formatting in app/src/main/java/fr/free/nrw/commons/upload/UploadModel.java

* Added class level JavaDoc UploadRemoteDataSource

* Added class level JavaDoc for UploadRepository

* Added JavaDocs for ThumbnailsAdapter

* Added JavaDocs for MediaLicensePresenter, CategoriesPresenter

* Removed null check on category query
* Show default catgeories based on image title and gps location when category text empty
* Allow search for empty category search

* Attached image scale listener to upload media image

* Bug fix, reduced the add description edit text clickable bound

* Added tooltip in Title in UploadMediaFragment

* BugFix recent categories

* Updated test methods

* Avoid memory leak, free the adpater in MediaLicenseFragment.onDestroyView

* bugfix/uploads (#3012)

* merged with master

* BugFix IllegalStateException
* setRetainState(true), not required with FragmentStatePagerAdapter
* Increase the ViewPager's Offscreen Limit, we want all the fragments to be active

* BugFix, clear selected categoris for previous upload session
* Clear Selected Categories
* Addded JavaDocs for CategoriesModel

* Code Formatting in app/src/main/java/fr/free/nrw/commons/upload/UploadModel.java

* Added class level JavaDoc UploadRemoteDataSource

* Added class level JavaDoc for UploadRepository

* Added JavaDocs for ThumbnailsAdapter

* Added JavaDocs for MediaLicensePresenter, CategoriesPresenter

* Removed null check on category query
* Show default catgeories based on image title and gps location when category text empty
* Allow search for empty category search

* Attached image scale listener to upload media image

* Bug fix, reduced the add description edit text clickable bound

* Added tooltip in Title in UploadMediaFragment

* BugFix recent categories

* Updated test methods

* Avoid memory leak, free the adpater in MediaLicenseFragment.onDestroyView

* BugFix Illegal State Exception in ViewpPagerAdapter

* Remove irrelevant comment

* merge conflict with strings (#3016)
This commit is contained in:
Ashish Kumar 2019-06-14 01:09:41 +05:30 committed by Vivek Maskara
parent 04b051b37a
commit 7a5dc77057
68 changed files with 3753 additions and 2086 deletions

View file

@ -0,0 +1,80 @@
package fr.free.nrw.commons.upload
import com.nhaarman.mockito_kotlin.verify
import fr.free.nrw.commons.category.CategoryItem
import fr.free.nrw.commons.repository.UploadRepository
import fr.free.nrw.commons.upload.categories.CategoriesContract
import fr.free.nrw.commons.upload.categories.CategoriesPresenter
import io.reactivex.Observable
import io.reactivex.schedulers.TestScheduler
import org.junit.Before
import org.junit.Test
import org.mockito.ArgumentMatchers
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.MockitoAnnotations
/**
* The class contains unit test cases for CategoriesPresenter
*/
class CategoriesPresenterTest {
@Mock
internal var repository: UploadRepository? = null
@Mock
internal var view: CategoriesContract.View? = null
var categoriesPresenter: CategoriesPresenter? = null
var testScheduler: TestScheduler? = null
val categoryItems: ArrayList<CategoryItem> = ArrayList()
@Mock
lateinit var categoryItem: CategoryItem
var testObservable: Observable<CategoryItem>? = null
private val imageTitleList = ArrayList<String>()
/**
* initial setup
*/
@Before
@Throws(Exception::class)
fun setUp() {
MockitoAnnotations.initMocks(this)
testScheduler = TestScheduler()
categoryItems.add(categoryItem)
testObservable = Observable.just(categoryItem)
categoriesPresenter = CategoriesPresenter(repository, testScheduler, testScheduler)
categoriesPresenter?.onAttachView(view)
}
/**
* unit test case for method CategoriesPresenter.searchForCategories
*/
@Test
fun searchForCategoriesTest() {
Mockito.`when`(repository?.sortBySimilarity(ArgumentMatchers.anyString())).thenReturn(Comparator<CategoryItem> { _, _ -> 1 })
Mockito.`when`(repository?.selectedCategories).thenReturn(categoryItems)
Mockito.`when`(repository?.searchAll(ArgumentMatchers.anyString(), ArgumentMatchers.anyList())).thenReturn(Observable.empty())
categoriesPresenter?.searchForCategories("test")
verify(view)?.showProgress(true)
verify(view)?.showError(null)
verify(view)?.setCategories(null)
testScheduler?.triggerActions()
verify(view)?.setCategories(categoryItems)
verify(view)?.showProgress(false)
}
/**
* unit test for method CategoriesPresenter.verifyCategories
*/
@Test
fun verifyCategoriesTest() {
Mockito.`when`(repository?.selectedCategories).thenReturn(categoryItems)
categoriesPresenter?.verifyCategories()
verify(repository)?.setSelectedCategories(ArgumentMatchers.anyList())
verify(view)?.goToNextScreen()
}
}

View file

@ -0,0 +1,66 @@
package fr.free.nrw.commons.upload
import com.nhaarman.mockito_kotlin.verify
import fr.free.nrw.commons.Utils
import fr.free.nrw.commons.repository.UploadRepository
import fr.free.nrw.commons.upload.license.MediaLicenseContract
import fr.free.nrw.commons.upload.license.MediaLicensePresenter
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers
import org.mockito.InjectMocks
import org.mockito.Mock
import org.mockito.MockitoAnnotations
import org.powermock.api.mockito.PowerMockito
import org.powermock.core.classloader.annotations.PrepareForTest
import org.powermock.modules.junit4.PowerMockRunner
/**
* The class contains unit test cases for MediaLicensePresenter
*/
@RunWith(PowerMockRunner::class)
@PrepareForTest(Utils::class)
class MediaLicensePresenterTest {
@Mock
internal var repository: UploadRepository? = null
@Mock
internal var view: MediaLicenseContract.View? = null
@InjectMocks
var mediaLicensePresenter: MediaLicensePresenter? = null
/**
* initial setup test environemnt
*/
@Before
@Throws(Exception::class)
fun setUp() {
MockitoAnnotations.initMocks(this)
mediaLicensePresenter?.onAttachView(view)
PowerMockito.mockStatic(Utils::class.java)
PowerMockito.`when`(Utils.licenseNameFor(ArgumentMatchers.anyString())).thenReturn(1)
}
/**
* unit test case for method MediaLicensePresenter.getLicense
*/
@Test
fun getLicenseTest() {
mediaLicensePresenter?.getLicenses()
verify(view)?.setLicenses(ArgumentMatchers.anyList())
verify(view)?.setSelectedLicense(ArgumentMatchers.any())
}
/**
* unit test case for method MediaLicensePresenter.selectLicense
*/
@Test
fun selectLicenseTest() {
mediaLicensePresenter?.selectLicense(ArgumentMatchers.anyString())
verify(view)?.updateLicenseSummary(ArgumentMatchers.any(), ArgumentMatchers.anyInt())
}
}

View file

@ -0,0 +1,110 @@
package fr.free.nrw.commons.upload
import fr.free.nrw.commons.filepicker.UploadableFile
import fr.free.nrw.commons.nearby.Place
import fr.free.nrw.commons.repository.UploadRepository
import fr.free.nrw.commons.upload.mediaDetails.UploadMediaDetailsContract
import fr.free.nrw.commons.upload.mediaDetails.UploadMediaPresenter
import fr.free.nrw.commons.utils.ImageUtils.*
import io.reactivex.Observable
import io.reactivex.Single
import io.reactivex.schedulers.TestScheduler
import org.junit.Before
import org.junit.Test
import org.mockito.ArgumentMatchers
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
/**
* The class contains unit test cases for UploadMediaPresenter
*/
class UploadMediaPresenterTest {
@Mock
internal var repository: UploadRepository? = null
@Mock
internal var view: UploadMediaDetailsContract.View? = null
private var uploadMediaPresenter: UploadMediaPresenter? = null
@Mock
private var uploadableFile: UploadableFile? = null
@Mock
private var place: Place? = null
@Mock
private var uploadItem: UploadModel.UploadItem? = null
private var testObservableUploadItem: Observable<UploadModel.UploadItem>? = null
private var testSingleImageResult: Single<Int>? = null
private var testScheduler: TestScheduler? = null
/**
* initial setup unit test environment
*/
@Before
@Throws(Exception::class)
fun setUp() {
MockitoAnnotations.initMocks(this)
testObservableUploadItem = Observable.just(uploadItem)
testSingleImageResult = Single.just(1)
testScheduler = TestScheduler()
uploadMediaPresenter = UploadMediaPresenter(repository, testScheduler, testScheduler)
uploadMediaPresenter?.onAttachView(view)
}
/**
* unit test for method UploadMediaPresenter.receiveImage
*/
@Test
fun receiveImageTest() {
Mockito.`when`(repository?.preProcessImage(ArgumentMatchers.any(UploadableFile::class.java), ArgumentMatchers.any(Place::class.java), ArgumentMatchers.anyString(), ArgumentMatchers.any(UploadMediaPresenter::class.java))).thenReturn(testObservableUploadItem)
uploadMediaPresenter?.receiveImage(uploadableFile, ArgumentMatchers.anyString(), place)
verify(view)?.showProgress(true)
testScheduler?.triggerActions()
verify(view)?.onImageProcessed(ArgumentMatchers.any(UploadModel.UploadItem::class.java), ArgumentMatchers.any(Place::class.java))
verify(view)?.showProgress(false)
}
/**
* unit test for method UploadMediaPresenter.verifyImageQuality
*/
@Test
fun verifyImageQualityTest() {
Mockito.`when`(repository?.getImageQuality(ArgumentMatchers.any(UploadModel.UploadItem::class.java), ArgumentMatchers.any(Boolean::class.java))).thenReturn(testSingleImageResult)
Mockito.`when`(uploadItem?.imageQuality).thenReturn(ArgumentMatchers.anyInt())
uploadMediaPresenter?.verifyImageQuality(uploadItem, true)
verify(view)?.showProgress(true)
testScheduler?.triggerActions()
verify(view)?.showProgress(false)
}
/**
* unit test for method UploadMediaPresenter.handleImageResult
*/
@Test
fun handleImageResult() {
//Positive case test
uploadMediaPresenter?.handleImageResult(IMAGE_KEEP)
verify(view)?.onImageValidationSuccess()
//Duplicate file name
uploadMediaPresenter?.handleImageResult(FILE_NAME_EXISTS)
verify(view)?.showDuplicatePicturePopup()
//Empty Title test
uploadMediaPresenter?.handleImageResult(EMPTY_TITLE)
verify(view)?.showMessage(ArgumentMatchers.anyInt(), ArgumentMatchers.anyInt())
//Bad Picture test
//Empty Title test
uploadMediaPresenter?.handleImageResult(-7)
verify(view)?.showBadImagePopup(ArgumentMatchers.anyInt())
}
}

View file

@ -87,24 +87,6 @@ class UploadModelTest {
}
}
@Test
fun verifyPreviousNotAvailable() {
uploadModel!!.preProcessImages(getMediaList(), mock(Place::class.java), "external") { _, _ -> }
assertFalse(uploadModel!!.isPreviousAvailable)
}
@Test
fun verifyNextAvailable() {
uploadModel!!.preProcessImages(getMediaList(), mock(Place::class.java), "external") { _, _ -> }
assertTrue(uploadModel!!.isNextAvailable)
}
@Test
fun isSubmitAvailable() {
uploadModel!!.preProcessImages(getMediaList(), mock(Place::class.java), "external") { _, _ -> }
assertTrue(uploadModel!!.isNextAvailable)
}
@Test
fun getCurrentStep() {
uploadModel!!.preProcessImages(getMediaList(), mock(Place::class.java), "external") { _, _ -> }
@ -135,38 +117,6 @@ class UploadModelTest {
}
}
@Test
fun isTopCardState() {
uploadModel!!.preProcessImages(getMediaList(), mock(Place::class.java), "external") { _, _ -> }
assertTrue(uploadModel!!.isTopCardState)
}
@Test
fun next() {
uploadModel!!.preProcessImages(getMediaList(), mock(Place::class.java), "external") { _, _ -> }
assertTrue(uploadModel!!.currentStep == 1)
uploadModel!!.next()
assertTrue(uploadModel!!.currentStep == 2)
}
@Test
fun previous() {
uploadModel!!.preProcessImages(getMediaList(), mock(Place::class.java), "external") { _, _ -> }
assertTrue(uploadModel!!.currentStep == 1)
uploadModel!!.next()
assertTrue(uploadModel!!.currentStep == 2)
uploadModel!!.previous()
assertTrue(uploadModel!!.currentStep == 1)
}
@Test
fun isShowingItem() {
val preProcessImages = uploadModel!!.preProcessImages(getMediaList(), mock(Place::class.java), "external") { _, _ -> }
preProcessImages.doOnComplete {
assertTrue(uploadModel!!.isShowingItem)
}
}
private fun getMediaList(): List<UploadableFile> {
val element = getElement()
val element2 = getElement()

View file

@ -1,43 +1,82 @@
package fr.free.nrw.commons.upload
import com.nhaarman.mockito_kotlin.verify
import fr.free.nrw.commons.contributions.Contribution
import fr.free.nrw.commons.filepicker.UploadableFile
import fr.free.nrw.commons.mwapi.MediaWikiApi
import fr.free.nrw.commons.nearby.Place
import fr.free.nrw.commons.repository.UploadRepository
import io.reactivex.Observable
import org.junit.Before
import org.junit.Test
import org.mockito.*
import org.mockito.ArgumentMatchers
import org.mockito.InjectMocks
import org.mockito.Mock
import org.mockito.Mockito.`when`
import org.mockito.Mockito.mock
import org.mockito.MockitoAnnotations
import java.util.ArrayList
/**
* The clas contains unit test cases for UploadPresenter
*/
class UploadPresenterTest {
@Mock
internal var uploadModel: UploadModel? = null
internal var repository: UploadRepository? = null
@Mock
internal var uploadController: UploadController? = null
internal var view: UploadContract.View? = null
@Mock
internal var mediaWikiApi: MediaWikiApi? = null
var contribution: Contribution? = null
@Mock
private lateinit var uploadableFile: UploadableFile
@InjectMocks
var uploadPresenter: UploadPresenter? = null
private var uploadableFiles: ArrayList<UploadableFile> = ArrayList()
/**
* initial setup, test environment
*/
@Before
@Throws(Exception::class)
fun setUp() {
MockitoAnnotations.initMocks(this)
`when`(uploadModel!!.preProcessImages(ArgumentMatchers.anyListOf(UploadableFile::class.java),
ArgumentMatchers.any(Place::class.java),
ArgumentMatchers.anyString(),
ArgumentMatchers.any(SimilarImageInterface::class.java)))
.thenReturn(Observable.just(mock(UploadModel.UploadItem::class.java)))
uploadPresenter?.onAttachView(view)
`when`(repository?.buildContributions()).thenReturn(Observable.just(contribution))
`when`(view?.isLoggedIn).thenReturn(true)
uploadableFiles.add(uploadableFile)
`when`(view?.uploadableFiles).thenReturn(uploadableFiles)
`when`(uploadableFile?.filePath).thenReturn("data://test")
}
/**
* unit test case for method UploadPresenter.handleSubmit
*/
@Test
fun receiveMultipleItems() {
val element = Mockito.mock(UploadableFile::class.java)
val element2 = Mockito.mock(UploadableFile::class.java)
var uriList: List<UploadableFile> = mutableListOf<UploadableFile>(element, element2)
uploadPresenter!!.receive(uriList, "external", mock(Place::class.java))
fun handleSubmitTest() {
uploadPresenter?.handleSubmit()
verify(view)?.isLoggedIn
verify(view)?.showProgress(true)
verify(repository)?.buildContributions()
val buildContributions = repository?.buildContributions()
buildContributions?.test()?.assertNoErrors()?.assertValue {
verify(repository)?.prepareService()
verify(view)?.showProgress(false)
verify(view)?.showMessage(ArgumentMatchers.any(Int::class.java))
verify(view)?.finish()
true
}
}
/**
* unit test for UploadMediaPresenter.deletePictureAtIndex
*/
@Test
fun deletePictureAtIndexTest() {
uploadPresenter?.deletePictureAtIndex(0)
verify(repository)?.deletePicture(ArgumentMatchers.anyString())
verify(view)?.showMessage(ArgumentMatchers.anyInt())//As there is only one while which we are asking for deletion, upload should be cancelled and this flow should be triggered
verify(view)?.finish()
}
}