From 732b343b89c29e7e47b5d3b0821fce40289d1b05 Mon Sep 17 00:00:00 2001 From: Aditya-Srivastav <54016427+4D17Y4@users.noreply.github.com> Date: Sun, 18 Jul 2021 05:47:01 +0530 Subject: [PATCH] [GSoC] Custom Selector Tests (#4494) * Localisation updates from https://translatewiki.net. * Fixes #4357 After switching to different account, contributions screen shows pictures of previous account (#4421) * Update UploadMediaDetailFragment.java * Update LoginActivity.java Clear CompositeDisposable after logging in successfully. It may help solve the problem of saving the contribution to the previous account * Revert "Update UploadMediaDetailFragment.java" This reverts commit b1b4257f205b022ffaadee9f947357e5fc04c337. Co-authored-by: Obsidian_zero <1198474846@qq.com> * Remove unnecessary whitespace from a message (#4439) * Merge v3.0.1 into master (#4446) * Versioning and changelog for v3.0.0 (#4152) * Versioning for v3.0.0 * Update changelog.md * Handled migration 8-9-10 in BookmarksLocationDao (#4154) * #Fixes #4141 - Handled migrations for BookmarkLocationsDao from 8-9-10 * #Fixes #4141 - Handled migrations for BookmarkLocationsDao from 8-9-10 * Fixes #4179 (#4180) * Handled null pointer exception in MainActivity->ContributionsFragment#backButtonClicked() * Updated >ContributionsFragment#backButtonClicked() to handle back press properly * Fixes #4179 (#4181) * Handled possible null check on MediaDetails in BookmarkListRootFragment#backPressed() * Cherrypick for hotfix3.1 (#4205) * Fixes #4159 On Explore Tab, All Available Options on toolbar in media detail view are only targeting the first media in the list. Fixes #4159 On Explore Tab, All Available Options on toolbar in media detail view are only targeting the first media in the list. * fixed bug: App crashes on viewing review in Review Fragment #4132 (#4146) * fixed bug:app crashes on viewing review in Review Fragment #4135 * Fixed the issue with back button in contribution tab. (#4177) Co-authored-by: Pratham2305 * Fixed the issue with back navigation button on toolbar in explore tab. (#4175) * Fix (#4148) Issues on theme change * fixed themeChange crashes * fixed comments * Overlooked the title bar Co-authored-by: Pratham Pahariya <54663429+Pratham2305@users.noreply.github.com> Co-authored-by: Shabir Ahmad <56585337+shabar-shab@users.noreply.github.com> Co-authored-by: Pratham2305 Co-authored-by: Aditya-Srivastav <54016427+4D17Y4@users.noreply.github.com> * Fixes #4173 (#4396) * Fix #4147 Pre-fill desc in Nearby uploads with Wikidata item's label + description (#4390) * Update query to fetch descriptions * Make description added to NearbyResultItem * Make string operations to display description and label in a combined way * Fix reviews, remove long description from list and swap label and description texts * Fix repeated information issue * Fix double information issue * fix style issues * Remove douplicated information * Changes made (#4354) * Remove nonexistent method * Fix #4283 IllegalStateException (#4440) * Fix #4283 IllegalStateException * Fix flickering issue * Versioning for v3.0.1 * Update changelog.md Co-authored-by: Ashish Co-authored-by: neslihanturan Co-authored-by: Pratham Pahariya <54663429+Pratham2305@users.noreply.github.com> Co-authored-by: Shabir Ahmad <56585337+shabar-shab@users.noreply.github.com> Co-authored-by: Pratham2305 Co-authored-by: Aditya-Srivastav <54016427+4D17Y4@users.noreply.github.com> Co-authored-by: Madhur Gupta <30932899+madhurgupta10@users.noreply.github.com> Co-authored-by: Vinayak Aggarwal <56196007+vinayak0505@users.noreply.github.com> * Localisation updates from https://translatewiki.net. * Added a feature for editing coordinates (#4418) * not * Place Picker added * Pick location and API call linked * minor warnings resolved * Code conventions followed * issue fixed * Wikitext edited properly * minor modification * Location Picker added * Bottom sheet removed * Location picker fully implemented * credit added * credit added * issues fixed * issues fixed * minor issue fixed * Some build issues occured merging release v3.0 are fixed. One paranthesis issue is solved, a method about UploadService is removed, since we don't use it anymore. (#4451) * Localisation updates from https://translatewiki.net. * Fixes 4344 - Duplicate Uploads (#4442) * Fixes 4344 - Update the retention policy of the Work Manager to ExistingWorkPolicy.APPEND_OR_REPLACE- which would append the new work to the end of existing one. This helps remove the while loop in UploadWorker which was meant to handle the cases where a new worker would be created for retries. The while loop seemed to have race conditions uploading duplicate entries. * Update states to IN_PROGRESS before uploads are processed * Fixes #3694 Pre-select places as depictions (#4452) * WikidataEditService: stop automatically adding WikidataPlace as a depiction When the user initiates the upload process from Nearby and also manually adds the place as a depiction, the depiction is added twice. Since this behavior is invisible to the user, it is being removed in preparation for auto-selecting the place as a depiction on the DepictsFragment screen. * DepictsFragment: auto-select place as a depiction Pass the Place reference from UploadActivity to DepictsFragment and select the corresponding DepictedItem. Using the place id, retrieve the corresponding Entity to create and select a DepictedItem. * UploadRepository: use Place from UploadItem to obtain a DepictedItem Instead of passing a Place object from UploadActivity to DepictsFragment and then passing the Place object up the chain to obtain and select a DepictedItem, retrieve the Place object directly within UploadRepository * DepictsFragment: select Place depiction when fragment becomes visible * UploadDepictsAdapter: make adapter aware of selection state Update selection state when recycled list items are automatically selected, preventing automatically selected items from appearing as unselected until they are forced to re-bind (i.e. after scrolling) * DepictsFragment: pre-select place depictions for all UploadItems If several images are selected and set to different places, pre-select all place depictions to reinforce the intended upload workflow philosophy (i.e. all images in a set are intended to be from/of the same place). See discussion in commons-app/apps-android-commons#3694 * DepictsFragment: scroll to the top every time list is updated * Typo fixes (#4461) * Fixed typo on class documentation of TextUtils * corrected comma placement in documentation * Fixed typos in comments * fix-issue-4424 (#4445) Co-authored-by: Pratham2305 * fix edit categories ui (#4414) Co-authored-by: Pratham2305 * Fix doom version issue (#4463) * Update db version * DBOpenHelper version update * fix :Back Pressed Event not work in Explore tab when user not login (#4404) * fix :Back Pressed Event not work in Explore tab * minor changes * fix :Upload count or number of contribution does not get updated when media is successful uploaded (#4399) * * fix:Number of Contributions not updated * Add javadocs * minor changes * made minor changes * String was nonsense and untranslatible, fixed (#4466) * Ability to show captions and descriptions in all entered languages (#4355) * implement Ability to show captions and descriptions in all entered languages *Add Javadoc * handle Back event of fragment(mediaDetailFragment) * fix minor bugs * add internationalization * revert previous changes * fix visibility bug * resolve conflict * Fixes #4437 - Changed indentation on files with 2 spaces to 4 spaces (#4462) * Edited Project.xml to make indent size 4 * Changed files with 2 space indentation to use 4 space indentation * Edited Project.xml to make indent size 4 * changed files with 2 space indent to 4 space indent * fix :Back Pressed Event not work in Explore tab when user not login (#4404) * fix :Back Pressed Event not work in Explore tab * minor changes * fix :Upload count or number of contribution does not get updated when media is successful uploaded (#4399) * * fix:Number of Contributions not updated * Add javadocs * minor changes * made minor changes * String was nonsense and untranslatible, fixed (#4466) * Ability to show captions and descriptions in all entered languages (#4355) * implement Ability to show captions and descriptions in all entered languages *Add Javadoc * handle Back event of fragment(mediaDetailFragment) * fix minor bugs * add internationalization * revert previous changes * fix visibility bug * resolve conflict Co-authored-by: Prince kushwaha <65972015+Prince-kushwaha@users.noreply.github.com> Co-authored-by: neslihanturan * Use more understandable strings (#4470) * Fix #3792 Missing Column Issue (#4468) * Fix Missing Column Issue * Fix tests * Add UploadCategoriesFragment Unit Tests (#4473) * Panorama (#4467) * panoramic images fixed * made requested changes * Minor refactoring Co-authored-by: Aditya Srivastava * Localisation updates from https://translatewiki.net. * Main activity title is sometimes "Contributions", sometimes "Commons" (#4472) Fixes #4438 Replace == with equals() in onRestoreInstanceState * Localisation updates from https://translatewiki.net. * caption and description copyable (#4481) * Removed next button in quiz (#4382) * issues resolved * modification done * warning fixed * issues resolved * Button added * don't know function added * Button added * modification done * modification done * Localisation updates from https://translatewiki.net. * Added option to show and modify location while uploading (#4475) * initial commit * Everything done * minor modification * minor modification * Issues fixed * minor modifications * issue fixed * Issues fixed * Tutorial removed from log out state (#4479) * tutorial removed from log out state * Issue removed * Update changelog.md * Versioning for v3.0.2 * Fix #4482 (#4484) * Fix crash when image resolution is very high (#4483) * Localisation updates from https://translatewiki.net. * Add Contributions Fragment Unit Tests (#4490) * Fix Tests Errors (#4491) * Add UploadMediaDetailFragment Unit Tests (#4492) * Localisation updates from https://translatewiki.net. * Folder Fragment test * Folder Fragment test done * Initialised xmls, made folder and image item. * xmls done * xmls completed * removed unwanted attribute * Created models, adapters and view models (#4441) * created models, adapters and view models * Added Image Fragment * back button linked * Documentation and refractor * spaces * Butterknife annotation * DiffUtil * Added Examples * Extended Custom selector From Base Activity * made view model injectable * [GSOC] Added Image Fetch (#4449) * Added basic Fetch * added permission request * Folder count rectified * Loaded thumbnail * disabled overlay * Added sha1 function * Documented the code * [GSoC] Image Selection (#4457) * Localisation updates from https://translatewiki.net. * Fixes #4357 After switching to different account, contributions screen shows pictures of previous account (#4421) * Update UploadMediaDetailFragment.java * Update LoginActivity.java Clear CompositeDisposable after logging in successfully. It may help solve the problem of saving the contribution to the previous account * Revert "Update UploadMediaDetailFragment.java" This reverts commit b1b4257f205b022ffaadee9f947357e5fc04c337. Co-authored-by: Obsidian_zero <1198474846@qq.com> * Remove unnecessary whitespace from a message (#4439) * Merge v3.0.1 into master (#4446) * Versioning and changelog for v3.0.0 (#4152) * Versioning for v3.0.0 * Update changelog.md * Handled migration 8-9-10 in BookmarksLocationDao (#4154) * #Fixes #4141 - Handled migrations for BookmarkLocationsDao from 8-9-10 * #Fixes #4141 - Handled migrations for BookmarkLocationsDao from 8-9-10 * Fixes #4179 (#4180) * Handled null pointer exception in MainActivity->ContributionsFragment#backButtonClicked() * Updated >ContributionsFragment#backButtonClicked() to handle back press properly * Fixes #4179 (#4181) * Handled possible null check on MediaDetails in BookmarkListRootFragment#backPressed() * Cherrypick for hotfix3.1 (#4205) * Fixes #4159 On Explore Tab, All Available Options on toolbar in media detail view are only targeting the first media in the list. Fixes #4159 On Explore Tab, All Available Options on toolbar in media detail view are only targeting the first media in the list. * fixed bug: App crashes on viewing review in Review Fragment #4132 (#4146) * fixed bug:app crashes on viewing review in Review Fragment #4135 * Fixed the issue with back button in contribution tab. (#4177) Co-authored-by: Pratham2305 * Fixed the issue with back navigation button on toolbar in explore tab. (#4175) * Fix (#4148) Issues on theme change * fixed themeChange crashes * fixed comments * Overlooked the title bar Co-authored-by: Pratham Pahariya <54663429+Pratham2305@users.noreply.github.com> Co-authored-by: Shabir Ahmad <56585337+shabar-shab@users.noreply.github.com> Co-authored-by: Pratham2305 Co-authored-by: Aditya-Srivastav <54016427+4D17Y4@users.noreply.github.com> * Fixes #4173 (#4396) * Fix #4147 Pre-fill desc in Nearby uploads with Wikidata item's label + description (#4390) * Update query to fetch descriptions * Make description added to NearbyResultItem * Make string operations to display description and label in a combined way * Fix reviews, remove long description from list and swap label and description texts * Fix repeated information issue * Fix double information issue * fix style issues * Remove douplicated information * Changes made (#4354) * Remove nonexistent method * Fix #4283 IllegalStateException (#4440) * Fix #4283 IllegalStateException * Fix flickering issue * Versioning for v3.0.1 * Update changelog.md Co-authored-by: Ashish Co-authored-by: neslihanturan Co-authored-by: Pratham Pahariya <54663429+Pratham2305@users.noreply.github.com> Co-authored-by: Shabir Ahmad <56585337+shabar-shab@users.noreply.github.com> Co-authored-by: Pratham2305 Co-authored-by: Aditya-Srivastav <54016427+4D17Y4@users.noreply.github.com> Co-authored-by: Madhur Gupta <30932899+madhurgupta10@users.noreply.github.com> Co-authored-by: Vinayak Aggarwal <56196007+vinayak0505@users.noreply.github.com> * Localisation updates from https://translatewiki.net. * Added basic Fetch * added permission request * Folder count rectified * Loaded thumbnail * disabled overlay * Added sha1 function * Documented the code * Added a feature for editing coordinates (#4418) * not * Place Picker added * Pick location and API call linked * minor warnings resolved * Code conventions followed * issue fixed * Wikitext edited properly * minor modification * Location Picker added * Bottom sheet removed * Location picker fully implemented * credit added * credit added * issues fixed * issues fixed * minor issue fixed * Some build issues occured merging release v3.0 are fixed. One paranthesis issue is solved, a method about UploadService is removed, since we don't use it anymore. (#4451) * Localisation updates from https://translatewiki.net. * Fixes 4344 - Duplicate Uploads (#4442) * Fixes 4344 - Update the retention policy of the Work Manager to ExistingWorkPolicy.APPEND_OR_REPLACE- which would append the new work to the end of existing one. This helps remove the while loop in UploadWorker which was meant to handle the cases where a new worker would be created for retries. The while loop seemed to have race conditions uploading duplicate entries. * Update states to IN_PROGRESS before uploads are processed * Image selection added * Forwarded activity result to upload wizard * Initialised xmls, made folder and image item. * xmls done * xmls completed * removed unwanted attribute * Created models, adapters and view models (#4441) * created models, adapters and view models * Added Image Fragment * back button linked * Documentation and refractor * spaces * Butterknife annotation * DiffUtil * Added Examples * Extended Custom selector From Base Activity * made view model injectable * Added basic Fetch * added permission request * Folder count rectified * Loaded thumbnail * disabled overlay * Added sha1 function * Documented the code * Image selection added * Forwarded activity result to upload wizard * [GSOC] Added Image Fetch (#4449) * Added basic Fetch * added permission request * Folder count rectified * Loaded thumbnail * disabled overlay * Added sha1 function * Documented the code * fixed merge errors * Documented the remaining function Co-authored-by: translatewiki.net Co-authored-by: obsidian-zero <63155026+obsidian-zero@users.noreply.github.com> Co-authored-by: Obsidian_zero <1198474846@qq.com> Co-authored-by: Amir E. Aharoni Co-authored-by: Josephine Lim Co-authored-by: Ashish Co-authored-by: neslihanturan Co-authored-by: Pratham Pahariya <54663429+Pratham2305@users.noreply.github.com> Co-authored-by: Shabir Ahmad <56585337+shabar-shab@users.noreply.github.com> Co-authored-by: Pratham2305 Co-authored-by: Madhur Gupta <30932899+madhurgupta10@users.noreply.github.com> Co-authored-by: Vinayak Aggarwal <56196007+vinayak0505@users.noreply.github.com> Co-authored-by: Ayan Sarkar <71203077+Ayan-10@users.noreply.github.com> * [GSoC] Show uploaded images differently. (#4464) * uploaded images shown differently * Loaded images before query * Handled exceptions, Made ImageLoader injectable, Document and clean code * [GSoC] Added Uploaded status table in room database. (#4476) * added Uploaded status table in room database * Added unique property, minor refractoring * Database intigrated * Database integrated * Handled result null exception * Exceptions handled and refractored * Introduced constants * moved to sealed class * No database insert on network error * queried original image * documented the code * Updated uploaded status on upload success * Image Helper test (#4485) * [GSoC] Adapter Tests (#4488) * Added FolderAdapterTest * Image Adapter Test * Folder Fragment test * Folder Fragment test done * Fragment test complete * Added Custom Selector View Model Test * ImageFileLoaderTest * Update strings.xml * Custom Selector Activiy test * Image Loader Test Co-authored-by: translatewiki.net Co-authored-by: obsidian-zero <63155026+obsidian-zero@users.noreply.github.com> Co-authored-by: Obsidian_zero <1198474846@qq.com> Co-authored-by: Amir E. Aharoni Co-authored-by: Josephine Lim Co-authored-by: Ashish Co-authored-by: neslihanturan Co-authored-by: Pratham Pahariya <54663429+Pratham2305@users.noreply.github.com> Co-authored-by: Shabir Ahmad <56585337+shabar-shab@users.noreply.github.com> Co-authored-by: Pratham2305 Co-authored-by: Madhur Gupta <30932899+madhurgupta10@users.noreply.github.com> Co-authored-by: Vinayak Aggarwal <56196007+vinayak0505@users.noreply.github.com> Co-authored-by: Ayan Sarkar <71203077+Ayan-10@users.noreply.github.com> Co-authored-by: Brigham Byerly <6891883+byerlyb20@users.noreply.github.com> Co-authored-by: Jamie Brown Co-authored-by: Prince kushwaha <65972015+Prince-kushwaha@users.noreply.github.com> Co-authored-by: Nicolas Raoul Co-authored-by: Ashar --- .../ui/selector/FolderFragment.kt | 19 +- .../ui/selector/ImageFragment.kt | 27 ++- .../customselector/ui/selector/ImageLoader.kt | 6 +- .../explore/ExploreListRootFragment.java | 2 +- .../ui/selector/CustomSelectorActivityTest.kt | 96 ++++++++ .../selector/CustomSelectorViewModelTest.kt | 41 ++++ .../ui/selector/FolderFragmentTest.kt | 130 +++++++++++ .../ui/selector/ImageFileLoaderTest.kt | 123 ++++++++++ .../ui/selector/ImageFragmentTest.kt | 135 +++++++++++ .../ui/selector/ImageLoaderTest.kt | 218 ++++++++++++++++++ app/src/test/resources/imageLoaderTestFile | 0 11 files changed, 786 insertions(+), 11 deletions(-) create mode 100644 app/src/test/kotlin/fr/free/nrw/commons/customselector/ui/selector/CustomSelectorActivityTest.kt create mode 100644 app/src/test/kotlin/fr/free/nrw/commons/customselector/ui/selector/CustomSelectorViewModelTest.kt create mode 100644 app/src/test/kotlin/fr/free/nrw/commons/customselector/ui/selector/FolderFragmentTest.kt create mode 100644 app/src/test/kotlin/fr/free/nrw/commons/customselector/ui/selector/ImageFileLoaderTest.kt create mode 100644 app/src/test/kotlin/fr/free/nrw/commons/customselector/ui/selector/ImageFragmentTest.kt create mode 100644 app/src/test/kotlin/fr/free/nrw/commons/customselector/ui/selector/ImageLoaderTest.kt create mode 100644 app/src/test/resources/imageLoaderTestFile diff --git a/app/src/main/java/fr/free/nrw/commons/customselector/ui/selector/FolderFragment.kt b/app/src/main/java/fr/free/nrw/commons/customselector/ui/selector/FolderFragment.kt index 1d5901c9d..e43c0798c 100644 --- a/app/src/main/java/fr/free/nrw/commons/customselector/ui/selector/FolderFragment.kt +++ b/app/src/main/java/fr/free/nrw/commons/customselector/ui/selector/FolderFragment.kt @@ -4,9 +4,11 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.ProgressBar import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.GridLayoutManager +import androidx.recyclerview.widget.RecyclerView import fr.free.nrw.commons.R import fr.free.nrw.commons.customselector.helper.ImageHelper import fr.free.nrw.commons.customselector.model.Result @@ -16,7 +18,6 @@ import fr.free.nrw.commons.customselector.ui.adapter.FolderAdapter import fr.free.nrw.commons.di.CommonsDaggerSupportFragment import fr.free.nrw.commons.media.MediaClient import fr.free.nrw.commons.upload.FileProcessor -import kotlinx.android.synthetic.main.fragment_custom_selector.* import kotlinx.android.synthetic.main.fragment_custom_selector.view.* import javax.inject.Inject @@ -27,6 +28,12 @@ class FolderFragment : CommonsDaggerSupportFragment() { */ private var viewModel: CustomSelectorViewModel? = null + /** + * View Elements + */ + private var selectorRV: RecyclerView? = null + private var loader: ProgressBar? = null + /** * View Model Factory. */ @@ -75,6 +82,8 @@ class FolderFragment : CommonsDaggerSupportFragment() { val root = inflater.inflate(R.layout.fragment_custom_selector, container, false) folderAdapter = FolderAdapter(activity!!, activity as FolderClickListener) gridLayoutManager = GridLayoutManager(context, columnCount()) + selectorRV = root.selector_rv + loader = root.loader with(root.selector_rv){ this.layoutManager = gridLayoutManager setHasFixedSize(true) @@ -96,9 +105,13 @@ class FolderFragment : CommonsDaggerSupportFragment() { val folders = ImageHelper.folderListFromImages(result.images) folderAdapter.init(folders) folderAdapter.notifyDataSetChanged() - selector_rv.visibility = View.VISIBLE + selectorRV?.let { + it.visibility = View.VISIBLE + } + } + loader?.let { + it.visibility = if (result.status is CallbackStatus.FETCHING) View.VISIBLE else View.GONE } - loader.visibility = if (result.status is CallbackStatus.FETCHING) View.VISIBLE else View.GONE } /** diff --git a/app/src/main/java/fr/free/nrw/commons/customselector/ui/selector/ImageFragment.kt b/app/src/main/java/fr/free/nrw/commons/customselector/ui/selector/ImageFragment.kt index a2de0ed29..f1583c54f 100644 --- a/app/src/main/java/fr/free/nrw/commons/customselector/ui/selector/ImageFragment.kt +++ b/app/src/main/java/fr/free/nrw/commons/customselector/ui/selector/ImageFragment.kt @@ -4,9 +4,11 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.ProgressBar import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.GridLayoutManager +import androidx.recyclerview.widget.RecyclerView import fr.free.nrw.commons.R import fr.free.nrw.commons.customselector.helper.ImageHelper import fr.free.nrw.commons.customselector.listeners.ImageSelectListener @@ -28,7 +30,13 @@ class ImageFragment: CommonsDaggerSupportFragment() { /** * View model for images. */ - private lateinit var viewModel: CustomSelectorViewModel + private var viewModel: CustomSelectorViewModel? = null + + /** + * View Elements + */ + private var selectorRV: RecyclerView? = null + private var loader: ProgressBar? = null /** * View model Factory. @@ -98,10 +106,13 @@ class ImageFragment: CommonsDaggerSupportFragment() { this.adapter = imageAdapter } - viewModel.result.observe(viewLifecycleOwner, Observer{ + viewModel?.result?.observe(viewLifecycleOwner, Observer{ handleResult(it) }) + selectorRV = root.selector_rv + loader = root.loader + return root } @@ -113,13 +124,19 @@ class ImageFragment: CommonsDaggerSupportFragment() { val images = result.images if(images.isNotEmpty()) { imageAdapter.init(ImageHelper.filterImages(images,bucketId)) - selector_rv.visibility = View.VISIBLE + selectorRV?.let{ + it.visibility = View.VISIBLE + } } else{ - selector_rv.visibility = View.GONE + selectorRV?.let{ + it.visibility = View.GONE + } } } - loader.visibility = if (result.status is CallbackStatus.FETCHING) View.VISIBLE else View.GONE + loader?.let { + it.visibility = if (result.status is CallbackStatus.FETCHING) View.VISIBLE else View.GONE + } } /** diff --git a/app/src/main/java/fr/free/nrw/commons/customselector/ui/selector/ImageLoader.kt b/app/src/main/java/fr/free/nrw/commons/customselector/ui/selector/ImageLoader.kt index f2d4d5709..5680cc775 100644 --- a/app/src/main/java/fr/free/nrw/commons/customselector/ui/selector/ImageLoader.kt +++ b/app/src/main/java/fr/free/nrw/commons/customselector/ui/selector/ImageLoader.kt @@ -19,6 +19,7 @@ import timber.log.Timber import java.io.IOException import java.net.UnknownHostException import java.util.* +import java.util.concurrent.TimeUnit import javax.inject.Inject import kotlin.collections.HashMap @@ -179,7 +180,8 @@ class ImageLoader @Inject constructor( return Result.TRUE } else { uploadedStatus.lastUpdated?.let { - if (it.date >= Calendar.getInstance().time.date - INVALIDATE_DAY_COUNT) { + val duration = Calendar.getInstance().time.time - it.time + if (TimeUnit.MILLISECONDS.toDays(duration) < INVALIDATE_DAY_COUNT) { return Result.FALSE } } @@ -218,7 +220,7 @@ class ImageLoader @Inject constructor( } companion object { - const val INVALIDATE_DAY_COUNT: Int = 7 + const val INVALIDATE_DAY_COUNT: Long = 7 } } \ No newline at end of file diff --git a/app/src/main/java/fr/free/nrw/commons/explore/ExploreListRootFragment.java b/app/src/main/java/fr/free/nrw/commons/explore/ExploreListRootFragment.java index 32b38fea7..e88f14b55 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/ExploreListRootFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/explore/ExploreListRootFragment.java @@ -40,7 +40,7 @@ public class ExploreListRootFragment extends CommonsDaggerSupportFragment implem featuredArguments.putString("categoryName", title); listFragment.setArguments(featuredArguments); } - + @Nullable @Override public View onCreateView(@NonNull final LayoutInflater inflater, diff --git a/app/src/test/kotlin/fr/free/nrw/commons/customselector/ui/selector/CustomSelectorActivityTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/customselector/ui/selector/CustomSelectorActivityTest.kt new file mode 100644 index 000000000..6d55a49e2 --- /dev/null +++ b/app/src/test/kotlin/fr/free/nrw/commons/customselector/ui/selector/CustomSelectorActivityTest.kt @@ -0,0 +1,96 @@ +package fr.free.nrw.commons.customselector.ui.selector + +import android.net.Uri +import android.os.Bundle +import fr.free.nrw.commons.TestCommonsApplication +import fr.free.nrw.commons.customselector.model.Folder +import fr.free.nrw.commons.customselector.model.Image +import org.junit.Before +import org.junit.Test +import org.junit.jupiter.api.Assertions.assertNotNull +import org.junit.runner.RunWith +import org.mockito.MockitoAnnotations +import org.robolectric.Robolectric +import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config + +/** + * Custom Selector Activity Test + */ +@RunWith(RobolectricTestRunner::class) +@Config(sdk = [21], application = TestCommonsApplication::class) +class CustomSelectorActivityTest { + + private lateinit var activity: CustomSelectorActivity + + /** + * Set up the tests. + */ + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + activity = Robolectric.buildActivity(CustomSelectorActivity::class.java) + .get() + val onCreate = activity.javaClass.getDeclaredMethod("onCreate", Bundle::class.java) + onCreate.isAccessible = true + onCreate.invoke(activity, null) + } + + /** + * Test activity not null. + */ + @Test + @Throws(Exception::class) + fun testActivityNotNull() { + assertNotNull(activity) + } + + /** + * Test changeTitle function. + */ + @Test + @Throws(Exception::class) + fun testChangeTitle() { + val func = activity.javaClass.getDeclaredMethod("changeTitle", String::class.java) + func.isAccessible = true + func.invoke(activity, "test") + } + + /** + * Test onFolderClick function. + */ + @Test + @Throws(Exception::class) + fun testOnFolderClick() { + activity.onFolderClick(Folder(1, "test", arrayListOf())); + } + + /** + * Test selectedImagesChanged function. + */ + @Test + @Throws(Exception::class) + fun testOnSelectedImagesChanged() { + activity.onSelectedImagesChanged(ArrayList()) + } + + /** + * Test onDone function. + */ + @Test + @Throws(Exception::class) + fun testOnDone() { + activity.onDone() + activity.onSelectedImagesChanged(ArrayList(arrayListOf(Image(1, "test", Uri.parse("test"), "test", 1)))); + activity.onDone() + } + + /** + * Test onBackPressed Function. + */ + @Test + @Throws(Exception::class) + fun testOnBackPressed() { + activity.onBackPressed() + } +} \ No newline at end of file diff --git a/app/src/test/kotlin/fr/free/nrw/commons/customselector/ui/selector/CustomSelectorViewModelTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/customselector/ui/selector/CustomSelectorViewModelTest.kt new file mode 100644 index 000000000..309392d4d --- /dev/null +++ b/app/src/test/kotlin/fr/free/nrw/commons/customselector/ui/selector/CustomSelectorViewModelTest.kt @@ -0,0 +1,41 @@ +package fr.free.nrw.commons.customselector.ui.selector + +import android.content.Context +import org.junit.Before +import org.junit.Test +import org.mockito.Mock +import org.mockito.MockitoAnnotations + +/** + * Custom Selector View Model test. + */ +class CustomSelectorViewModelTest { + + private lateinit var viewModel: CustomSelectorViewModel + + @Mock + private lateinit var imageFileLoader: ImageFileLoader + + @Mock + private lateinit var context: Context + + /** + * Set up the test. + */ + @Before + fun setUp(){ + MockitoAnnotations.initMocks(this) + viewModel = CustomSelectorViewModel(context, imageFileLoader); + } + + /** + * Test onCleared(); + */ + @Test + fun testOnCleared(){ + val func = viewModel.javaClass.getDeclaredMethod("onCleared") + func.isAccessible = true + func.invoke(viewModel); + } + +} \ No newline at end of file diff --git a/app/src/test/kotlin/fr/free/nrw/commons/customselector/ui/selector/FolderFragmentTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/customselector/ui/selector/FolderFragmentTest.kt new file mode 100644 index 000000000..53094d6f7 --- /dev/null +++ b/app/src/test/kotlin/fr/free/nrw/commons/customselector/ui/selector/FolderFragmentTest.kt @@ -0,0 +1,130 @@ +package fr.free.nrw.commons.customselector.ui.selector + +import android.content.Context +import android.os.Bundle +import android.os.Looper +import android.view.LayoutInflater +import android.view.View +import fr.free.nrw.commons.customselector.model.Result +import android.widget.ProgressBar +import androidx.fragment.app.FragmentManager +import androidx.fragment.app.FragmentTransaction +import androidx.recyclerview.widget.RecyclerView +import com.facebook.drawee.backends.pipeline.Fresco +import com.facebook.soloader.SoLoader +import fr.free.nrw.commons.R +import fr.free.nrw.commons.TestAppAdapter +import fr.free.nrw.commons.TestCommonsApplication +import fr.free.nrw.commons.customselector.model.CallbackStatus +import fr.free.nrw.commons.customselector.ui.adapter.FolderAdapter +import org.junit.Before +import org.junit.Test +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.MockitoAnnotations +import org.powermock.reflect.Whitebox +import org.robolectric.Robolectric +import org.robolectric.RobolectricTestRunner +import org.robolectric.RuntimeEnvironment +import org.robolectric.Shadows +import org.robolectric.annotation.Config +import org.robolectric.annotation.LooperMode +import org.wikipedia.AppAdapter +import java.lang.reflect.Field + +/** + * Custom Selector Folder Fragment Test. + */ +@RunWith(RobolectricTestRunner::class) +@Config(sdk = [21], application = TestCommonsApplication::class) +@LooperMode(LooperMode.Mode.PAUSED) +class FolderFragmentTest { + + private lateinit var fragment: FolderFragment + private lateinit var view: View + private lateinit var selectorRV : RecyclerView + private lateinit var loader : ProgressBar + private lateinit var layoutInflater: LayoutInflater + private lateinit var context: Context + private lateinit var viewModelField:Field + + @Mock + private lateinit var adapter: FolderAdapter + + @Mock + private lateinit var savedInstanceState: Bundle + + /** + * Setup the folder fragment. + */ + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + context = RuntimeEnvironment.application.applicationContext + AppAdapter.set(TestAppAdapter()) + SoLoader.setInTestMode() + Fresco.initialize(context) + val activity = Robolectric.buildActivity(CustomSelectorActivity::class.java).create().get() + + fragment = FolderFragment.newInstance() + val fragmentManager: FragmentManager = activity.supportFragmentManager + val fragmentTransaction: FragmentTransaction = fragmentManager.beginTransaction() + fragmentTransaction.add(fragment, null) + fragmentTransaction.commit() + + layoutInflater = LayoutInflater.from(activity) + view = layoutInflater.inflate(R.layout.fragment_custom_selector, null) as View + + selectorRV = view.findViewById(R.id.selector_rv) + loader = view.findViewById(R.id.loader) + + Whitebox.setInternalState(fragment, "folderAdapter", adapter) + Whitebox.setInternalState(fragment, "selectorRV", selectorRV ) + Whitebox.setInternalState(fragment, "loader", loader) + + viewModelField = fragment.javaClass.getDeclaredField("viewModel") + viewModelField.isAccessible = true + } + + /** + * Test onCreateView + */ + @Test + @Throws(Exception::class) + fun testOnCreateView() { + Shadows.shadowOf(Looper.getMainLooper()).idle() + viewModelField.set(fragment, null) + fragment.onCreateView(layoutInflater, null, savedInstanceState) + } + + /** + * Test onCreate + */ + @Test + @Throws(Exception::class) + fun testOnCreate() { + Shadows.shadowOf(Looper.getMainLooper()).idle() + fragment.onCreate(savedInstanceState) + } + + /** + * Test columnCount. + */ + @Test + fun testColumnCount() { + val func = fragment.javaClass.getDeclaredMethod("columnCount") + func.isAccessible = true + assertEquals(2, func.invoke(fragment)) + } + + /** + * Test handleResult. + */ + @Test + fun testHandleResult() { + val func = fragment.javaClass.getDeclaredMethod("handleResult", Result::class.java) + func.isAccessible = true + func.invoke(fragment, Result(CallbackStatus.SUCCESS, arrayListOf())) + } +} \ No newline at end of file diff --git a/app/src/test/kotlin/fr/free/nrw/commons/customselector/ui/selector/ImageFileLoaderTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/customselector/ui/selector/ImageFileLoaderTest.kt new file mode 100644 index 000000000..e30d47216 --- /dev/null +++ b/app/src/test/kotlin/fr/free/nrw/commons/customselector/ui/selector/ImageFileLoaderTest.kt @@ -0,0 +1,123 @@ +package fr.free.nrw.commons.customselector.ui.selector + +import android.content.ContentResolver +import android.content.Context +import android.provider.MediaStore +import com.nhaarman.mockitokotlin2.anyOrNull +import com.nhaarman.mockitokotlin2.doReturn +import com.nhaarman.mockitokotlin2.mock +import com.nhaarman.mockitokotlin2.same +import fr.free.nrw.commons.TestCommonsApplication +import fr.free.nrw.commons.customselector.listeners.ImageLoaderListener +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.Mockito.`when` +import org.mockito.MockitoAnnotations +import org.powermock.reflect.Whitebox +import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config +import org.robolectric.annotation.LooperMode +import org.robolectric.fakes.RoboCursor +import java.io.File +import kotlin.coroutines.CoroutineContext + +/** + * Custom Selector Image File loader test. + */ +@RunWith(RobolectricTestRunner::class) +@Config(sdk = [21], application = TestCommonsApplication::class) +@LooperMode(LooperMode.Mode.PAUSED) +class ImageFileLoaderTest { + + @Mock + private lateinit var mockContentResolver: ContentResolver + + @Mock + private lateinit var context: Context; + + @Mock + private lateinit var imageLoaderListener: ImageLoaderListener + + @Mock + private lateinit var coroutineScope: CoroutineScope + + private lateinit var imageCursor: RoboCursor + private lateinit var coroutineContext: CoroutineContext + private lateinit var projection: List + private lateinit var imageFileLoader: ImageFileLoader + + /** + * Setup before tests. + */ + @Before + fun setup() { + MockitoAnnotations.initMocks(this) + coroutineContext = Dispatchers.Main + imageCursor = RoboCursor() + imageFileLoader = ImageFileLoader(context) + projection = listOf( + MediaStore.Images.Media._ID, + MediaStore.Images.Media.DISPLAY_NAME, + MediaStore.Images.Media.DATA, + MediaStore.Images.Media.BUCKET_ID, + MediaStore.Images.Media.BUCKET_DISPLAY_NAME + ) + + Whitebox.setInternalState(imageFileLoader, "coroutineContext", coroutineContext) + } + + /** + * Test loading device images. + */ + @Test + fun testLoadDeviceImages() { + imageFileLoader.loadDeviceImages(imageLoaderListener, coroutineScope) + } + + /** + * Test get images from the device function. + */ + @Test + fun testGetImages() { + val func = imageFileLoader.javaClass.getDeclaredMethod( + "getImages", + ImageLoaderListener::class.java + ) + func.isAccessible = true + + val image1 = arrayOf(1, "imageLoaderTestFile", "src/test/resources/imageLoaderTestFile", 1, "downloads") + val image2 = arrayOf(2, "imageLoaderTestFile", null, 1, "downloads") + File("src/test/resources/imageLoaderTestFile").createNewFile() + + imageCursor.setColumnNames(projection) + imageCursor.setResults(arrayOf(image1, image2)); + + val contentResolver: ContentResolver = mock { + on { + query( + same(MediaStore.Images.Media.EXTERNAL_CONTENT_URI), + anyOrNull(), + anyOrNull(), + anyOrNull(), + anyOrNull() + ) + } doReturn imageCursor; + } + + // test null cursor. + `when`( + context.contentResolver + ).thenReturn(mockContentResolver) + func.invoke(imageFileLoader, imageLoaderListener); + + // test demo cursor. + `when`( + context.contentResolver + ).thenReturn(contentResolver) + func.invoke(imageFileLoader, imageLoaderListener); + } +} \ No newline at end of file diff --git a/app/src/test/kotlin/fr/free/nrw/commons/customselector/ui/selector/ImageFragmentTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/customselector/ui/selector/ImageFragmentTest.kt new file mode 100644 index 000000000..9794003c8 --- /dev/null +++ b/app/src/test/kotlin/fr/free/nrw/commons/customselector/ui/selector/ImageFragmentTest.kt @@ -0,0 +1,135 @@ +package fr.free.nrw.commons.customselector.ui.selector + +import android.content.Context +import android.os.Bundle +import android.os.Looper +import android.view.LayoutInflater +import android.view.View +import android.widget.ProgressBar +import androidx.fragment.app.FragmentManager +import androidx.fragment.app.FragmentTransaction +import androidx.recyclerview.widget.RecyclerView +import com.facebook.drawee.backends.pipeline.Fresco +import com.facebook.soloader.SoLoader +import fr.free.nrw.commons.R +import fr.free.nrw.commons.TestAppAdapter +import fr.free.nrw.commons.TestCommonsApplication +import fr.free.nrw.commons.customselector.model.CallbackStatus +import fr.free.nrw.commons.customselector.model.Image +import fr.free.nrw.commons.customselector.model.Result +import fr.free.nrw.commons.customselector.ui.adapter.ImageAdapter +import org.junit.Before +import org.junit.Test +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.MockitoAnnotations +import org.powermock.reflect.Whitebox +import org.robolectric.Robolectric +import org.robolectric.RobolectricTestRunner +import org.robolectric.RuntimeEnvironment +import org.robolectric.Shadows +import org.robolectric.annotation.Config +import org.robolectric.annotation.LooperMode +import org.wikipedia.AppAdapter +import java.lang.reflect.Field + +/** + * Custom Selector Image Fragment Test. + */ +@RunWith(RobolectricTestRunner::class) +@Config(sdk = [21], application = TestCommonsApplication::class) +@LooperMode(LooperMode.Mode.PAUSED) +class ImageFragmentTest { + + private lateinit var fragment: ImageFragment + private lateinit var view: View + private lateinit var selectorRV : RecyclerView + private lateinit var loader : ProgressBar + private lateinit var layoutInflater: LayoutInflater + private lateinit var context: Context + private lateinit var viewModelField: Field + + @Mock + private lateinit var image: Image + + @Mock + private lateinit var adapter: ImageAdapter + + @Mock + private lateinit var savedInstanceState: Bundle + + /** + * Setup the image fragment. + */ + @Before + fun setUp(){ + MockitoAnnotations.initMocks(this) + context = RuntimeEnvironment.application.applicationContext + AppAdapter.set(TestAppAdapter()) + SoLoader.setInTestMode() + Fresco.initialize(context) + val activity = Robolectric.buildActivity(CustomSelectorActivity::class.java).create().get() + + fragment = ImageFragment.newInstance(1) + val fragmentManager: FragmentManager = activity.supportFragmentManager + val fragmentTransaction: FragmentTransaction = fragmentManager.beginTransaction() + fragmentTransaction.add(fragment, null) + fragmentTransaction.commit() + + layoutInflater = LayoutInflater.from(activity) + view = layoutInflater.inflate(R.layout.fragment_custom_selector, null, false) as View + selectorRV = view.findViewById(R.id.selector_rv) + loader = view.findViewById(R.id.loader) + + Whitebox.setInternalState(fragment, "imageAdapter", adapter) + Whitebox.setInternalState(fragment, "selectorRV", selectorRV ) + Whitebox.setInternalState(fragment, "loader", loader) + + viewModelField = fragment.javaClass.getDeclaredField("viewModel") + viewModelField.isAccessible = true + } + + /** + * Test onCreate + */ + @Test + @Throws(Exception::class) + fun testOnCreate(){ + Shadows.shadowOf(Looper.getMainLooper()).idle() + fragment.onCreate(savedInstanceState); + } + + /** + * Test onCreateView + */ + @Test + @Throws(Exception::class) + fun testOnCreateView() { + Shadows.shadowOf(Looper.getMainLooper()).idle() + viewModelField.set(fragment, null) + fragment.onCreateView(layoutInflater, null, savedInstanceState) + } + + /** + * Test handleResult. + */ + @Test + fun testHandleResult(){ + val func = fragment.javaClass.getDeclaredMethod("handleResult", Result::class.java) + func.isAccessible = true + func.invoke(fragment, Result(CallbackStatus.SUCCESS, arrayListOf())) + func.invoke(fragment, Result(CallbackStatus.SUCCESS, arrayListOf(image,image))) + } + + /** + * Test getSpanCount. + */ + @Test + fun testGetSpanCount() { + val func = fragment.javaClass.getDeclaredMethod("getSpanCount") + func.isAccessible = true + assertEquals(3, func.invoke(fragment)) + } + +} \ No newline at end of file diff --git a/app/src/test/kotlin/fr/free/nrw/commons/customselector/ui/selector/ImageLoaderTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/customselector/ui/selector/ImageLoaderTest.kt new file mode 100644 index 000000000..cb7cf3a50 --- /dev/null +++ b/app/src/test/kotlin/fr/free/nrw/commons/customselector/ui/selector/ImageLoaderTest.kt @@ -0,0 +1,218 @@ +package fr.free.nrw.commons.customselector.ui.selector + +import android.content.ContentResolver +import android.content.Context +import android.net.Uri +import com.nhaarman.mockitokotlin2.any +import com.nhaarman.mockitokotlin2.whenever +import fr.free.nrw.commons.TestCommonsApplication +import fr.free.nrw.commons.customselector.database.UploadedStatus +import fr.free.nrw.commons.customselector.database.UploadedStatusDao +import fr.free.nrw.commons.customselector.model.Image +import fr.free.nrw.commons.customselector.ui.adapter.ImageAdapter +import fr.free.nrw.commons.filepicker.PickedFiles +import fr.free.nrw.commons.filepicker.UploadableFile +import fr.free.nrw.commons.media.MediaClient +import fr.free.nrw.commons.upload.FileProcessor +import fr.free.nrw.commons.upload.FileUtilsWrapper +import io.reactivex.Single +import junit.framework.Assert +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.* +import org.powermock.api.mockito.PowerMockito +import org.powermock.core.classloader.annotations.PrepareForTest +import org.powermock.modules.junit4.PowerMockRunner +import org.powermock.reflect.Whitebox +import org.robolectric.annotation.Config +import java.io.File +import java.io.FileInputStream +import java.lang.Exception +import java.util.* +import kotlin.collections.HashMap + +/** + * Image Loader Test. + */ +@RunWith(PowerMockRunner::class) +@PrepareForTest(PickedFiles::class) +@Config(sdk = [21], application = TestCommonsApplication::class) +class ImageLoaderTest { + + @Mock + private lateinit var uri:Uri + + @Mock + private lateinit var mediaClient: MediaClient + + @Mock + private lateinit var single: Single + + @Mock + private lateinit var fileProcessor: FileProcessor + + @Mock + private lateinit var fileUtilsWrapper: FileUtilsWrapper + + @Mock + private lateinit var uploadedStatusDao: UploadedStatusDao + + @Mock + private lateinit var holder: ImageAdapter.ImageViewHolder + + @Mock + private lateinit var context: Context + + @Mock + private lateinit var uploadableFile: UploadableFile + + @Mock + private lateinit var inputStream: FileInputStream + + @Mock + private lateinit var contentResolver: ContentResolver + + @Mock + private lateinit var image: Image; + + private lateinit var imageLoader: ImageLoader; + private var mapImageSHA1: HashMap = HashMap() + private var mapHolderImage : HashMap = HashMap() + private var mapResult: HashMap = HashMap() + + /** + * Setup before test. + */ + @Before + fun setup() { + MockitoAnnotations.initMocks(this) + imageLoader = + ImageLoader(mediaClient, fileProcessor, fileUtilsWrapper, uploadedStatusDao, context) + + Whitebox.setInternalState(imageLoader, "mapImageSHA1", mapImageSHA1); + Whitebox.setInternalState(imageLoader, "mapHolderImage", mapHolderImage); + Whitebox.setInternalState(imageLoader, "mapResult", mapResult); + Whitebox.setInternalState(imageLoader, "context", context) + } + + /** + * Test queryAndSetView. + */ + @Test + fun testQueryAndSetView(){ + // TODO + imageLoader.queryAndSetView(holder,image) + } + + /** + * Test querySha1 + */ + @Test + fun testQuerySha1() { + val func = imageLoader.javaClass.getDeclaredMethod( + "querySHA1", + String::class.java + ) + func.isAccessible = true + + Mockito.`when`(single.blockingGet()).thenReturn(true) + Mockito.`when`(mediaClient.checkFileExistsUsingSha("testSha1")).thenReturn(single) + Mockito.`when`(fileUtilsWrapper.getSHA1(any())).thenReturn("testSha1") + + // test without saving in map. + func.invoke(imageLoader, "testSha1"); + + // test with map save. + mapResult["testSha1"] = ImageLoader.Result.FALSE + func.invoke(imageLoader, "testSha1"); + } + + /** + * Test getSha1 + */ + @Test + @Throws (Exception::class) + fun testGetSha1() { + val func = imageLoader.javaClass.getDeclaredMethod( + "getSHA1", + Image::class.java + ) + func.isAccessible = true + + PowerMockito.mockStatic(PickedFiles::class.java); + BDDMockito.given(PickedFiles.pickedExistingPicture(context, image.uri)) + .willReturn(UploadableFile(uri, File("ABC"))); + + whenever(fileUtilsWrapper.getFileInputStream("ABC")).thenReturn(inputStream) + whenever(fileUtilsWrapper.getSHA1(inputStream)).thenReturn("testSha1") + + Assert.assertEquals("testSha1", func.invoke(imageLoader, image)); + whenever(PickedFiles.pickedExistingPicture(context,Uri.parse("test"))).thenReturn(uploadableFile) + + mapImageSHA1[image] = "testSha2" + Assert.assertEquals("testSha2", func.invoke(imageLoader, image)); + } + + /** + * Test insertIntoUploaded Function. + */ + @Test + @Throws (Exception::class) + fun testInsertIntoUploaded() { + val func = imageLoader.javaClass.getDeclaredMethod( + "insertIntoUploaded", + String::class.java, + String::class.java, + Boolean::class.java, + Boolean::class.java) + func.isAccessible = true + + func.invoke(imageLoader, "", "", true, true) + } + + /** + * Test getImageSha1. + */ + @Test + @Throws (Exception::class) + fun testGetImageSHA1() { + val func = imageLoader.javaClass.getDeclaredMethod( + "getImageSHA1", + Uri::class.java) + func.isAccessible = true + + whenever(contentResolver.openInputStream(uri)).thenReturn(inputStream) + whenever(context.contentResolver).thenReturn(contentResolver) + whenever(fileUtilsWrapper.getSHA1(inputStream)).thenReturn("testSha1") + + Assert.assertEquals("testSha1", func.invoke(imageLoader,uri)) + } + + /** + * Test getResultFromUploadedStatus. + */ + @Test + @Throws (Exception::class) + fun testGetResultFromUploadedStatus() { + val func = imageLoader.javaClass.getDeclaredMethod( + "getResultFromUploadedStatus", + UploadedStatus::class.java) + func.isAccessible = true + + // test Result.TRUE + Assert.assertEquals(ImageLoader.Result.TRUE, + func.invoke(imageLoader, + UploadedStatus("", "", true, true))) + + // test Result.FALSE + Assert.assertEquals(ImageLoader.Result.FALSE, + func.invoke(imageLoader, + UploadedStatus("", "", false, false, Calendar.getInstance().time))) + + // test Result.INVALID + Assert.assertEquals(ImageLoader.Result.INVALID, + func.invoke(imageLoader, UploadedStatus("", "", false, false, Date(0)))) + + } +} \ No newline at end of file diff --git a/app/src/test/resources/imageLoaderTestFile b/app/src/test/resources/imageLoaderTestFile new file mode 100644 index 000000000..e69de29bb