Compare commits

...

3 commits

Author SHA1 Message Date
Rohit Verma
14d6c80241
fix: remove location manager and update listener on pause (#6483)
Some checks failed
Android CI / Run tests and generate APK (push) Has been cancelled
Co-authored-by: Nicolas Raoul <nicolas.raoul@gmail.com>
2025-10-11 23:33:44 +09:00
VoidRaven
4c621364c9
Fix/6404 app crashes theme change multi upload (#6429)
* Prevent IndexOutOfBoundsException in setUploadMediaDetails by validating index and list size (#6404)

* fixed UninitializedPropertyAccessException by safely initializing and accessing imageAdapter (#6404)

* fixed indexOutOfBoundsException by safely handling saved state and index in onViewCreated (#6404)

* resolve Unresolved reference by replacing setImageToBeUploaded with direct field assignments (#6404)

* Fix test compilation by removing obsolete testSetImageToBeUploaded and adding tha testInitializeFragmentWithUploadItem (#6404)

* Fix test compilation by removing testInitializeFragmentWithUploadItem with unresolved onImageProcessed (#6404)

* fix: test failures in UploadMediaDetailFragmentUnitTest by removing obsolete tests and initializing defaultKvStore (#6404)

* Fixed all the typos

---------

Co-authored-by: Nicolas Raoul <nicolas.raoul@gmail.com>
2025-10-11 21:38:07 +09:00
Amir E. Aharoni
2a9d5db51e
Consistent spelling of "screenshots" in the issue template (#6481)
"Screenshot" is written as one word without a hyphen everywhere
else in this app's code, and generally in the English language.
2025-10-11 21:33:54 +09:00
7 changed files with 157 additions and 116 deletions

View file

@ -70,7 +70,7 @@ body:
required: false required: false
- type: textarea - type: textarea
attributes: attributes:
label: Screen-shots label: Screenshots
description: Add screenshots related to the issue (if available). Can be created by pressing the Volume Down and Power Button at the same time on Android 4.0 and higher. description: Add screenshots related to the issue (if available). Can be created by pressing the Volume Down and Power Button at the same time on Android 4.0 and higher.
validations: validations:
required: false required: false

View file

@ -47,6 +47,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import timber.log.Timber
import java.util.TreeMap import java.util.TreeMap
import javax.inject.Inject import javax.inject.Inject
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
@ -211,8 +212,12 @@ class ImageFragment :
savedInstanceState: Bundle?, savedInstanceState: Bundle?,
): View? { ): View? {
_binding = FragmentCustomSelectorBinding.inflate(inflater, container, false) _binding = FragmentCustomSelectorBinding.inflate(inflater, container, false)
imageAdapter =
ImageAdapter(requireActivity(), activity as ImageSelectListener, imageLoader!!) // ensures imageAdapter is initialized
if (!::imageAdapter.isInitialized) {
imageAdapter = ImageAdapter(requireActivity(), activity as ImageSelectListener, imageLoader!!)
Timber.d("Initialized imageAdapter in onCreateView")
}
// Set single selection mode if needed // Set single selection mode if needed
val singleSelection = (activity as? CustomSelectorActivity)?.intent?.getBooleanExtra(CustomSelectorActivity.EXTRA_SINGLE_SELECTION, false) == true val singleSelection = (activity as? CustomSelectorActivity)?.intent?.getBooleanExtra(CustomSelectorActivity.EXTRA_SINGLE_SELECTION, false) == true
imageAdapter.setSingleSelection(singleSelection) imageAdapter.setSingleSelection(singleSelection)
@ -370,7 +375,12 @@ class ImageFragment :
* notifyDataSetChanged, rebuild the holder views to account for deleted images. * notifyDataSetChanged, rebuild the holder views to account for deleted images.
*/ */
override fun onResume() { override fun onResume() {
imageAdapter.notifyDataSetChanged() if (::imageAdapter.isInitialized) {
imageAdapter.notifyDataSetChanged()
Timber.d("Notified imageAdapter in onResume")
} else {
Timber.w("imageAdapter not initialized in onResume")
}
super.onResume() super.onResume()
} }
@ -380,14 +390,19 @@ class ImageFragment :
* Save the Image Fragment state. * Save the Image Fragment state.
*/ */
override fun onDestroy() { override fun onDestroy() {
imageAdapter.cleanUp() if (::imageAdapter.isInitialized) {
imageAdapter.cleanUp()
Timber.d("Cleaned up imageAdapter in onDestroy")
} else {
Timber.w("imageAdapter not initialized in onDestroy, skipping cleanup")
}
val position = val position =
(selectorRV?.layoutManager as GridLayoutManager) (selectorRV?.layoutManager as? GridLayoutManager)
.findFirstVisibleItemPosition() ?.findFirstVisibleItemPosition() ?: -1
// Check for empty RecyclerView. // check for valid position and non-empty image list
if (position != -1 && filteredImages.size > 0) { if (position != -1 && filteredImages.isNotEmpty() && ::imageAdapter.isInitialized) {
context?.let { context -> context?.let { context ->
context context
.getSharedPreferences( .getSharedPreferences(
@ -396,34 +411,57 @@ class ImageFragment :
)?.let { prefs -> )?.let { prefs ->
prefs.edit()?.let { editor -> prefs.edit()?.let { editor ->
editor.putLong("ItemId", imageAdapter.getImageIdAt(position))?.apply() editor.putLong("ItemId", imageAdapter.getImageIdAt(position))?.apply()
Timber.d("Saved last visible item ID: %d", imageAdapter.getImageIdAt(position))
} }
} }
} }
} else {
Timber.d("Skipped saving item ID: position=%d, filteredImages.size=%d, imageAdapter initialized=%b",
position, filteredImages.size, ::imageAdapter.isInitialized)
} }
super.onDestroy() super.onDestroy()
} }
override fun onDestroyView() { override fun onDestroyView() {
_binding = null _binding = null
selectorRV = null
loader = null
switch = null
progressLayout = null
super.onDestroyView() super.onDestroyView()
} }
override fun refresh() { override fun refresh() {
imageAdapter.refresh(filteredImages, allImages, getUploadingContributions()) if (::imageAdapter.isInitialized) {
imageAdapter.refresh(filteredImages, allImages, getUploadingContributions())
Timber.d("Refreshed imageAdapter")
} else {
Timber.w("imageAdapter not initialized in refresh")
}
} }
/** /**
* Removes the image from the actionable image map * Removes the image from the actionable image map
*/ */
fun removeImage(image: Image) { fun removeImage(image: Image) {
imageAdapter.removeImageFromActionableImageMap(image) if (::imageAdapter.isInitialized) {
imageAdapter.removeImageFromActionableImageMap(image)
Timber.d("Removed image from actionable image map")
} else {
Timber.w("imageAdapter not initialized in removeImage")
}
} }
/** /**
* Clears the selected images * Clears the selected images
*/ */
fun clearSelectedImages() { fun clearSelectedImages() {
imageAdapter.clearSelectedImages() if (::imageAdapter.isInitialized) {
imageAdapter.clearSelectedImages()
Timber.d("Cleared selected images")
} else {
Timber.w("imageAdapter not initialized in clearSelectedImages")
}
} }
/** /**
@ -434,6 +472,15 @@ class ImageFragment :
selectedImages: ArrayList<Image>, selectedImages: ArrayList<Image>,
shouldRefresh: Boolean, shouldRefresh: Boolean,
) { ) {
if (::imageAdapter.isInitialized) {
imageAdapter.setSelectedImages(selectedImages)
if (shouldRefresh) {
imageAdapter.refresh(filteredImages, allImages, getUploadingContributions())
}
Timber.d("Passed %d selected images to imageAdapter, shouldRefresh=%b", selectedImages.size, shouldRefresh)
} else {
Timber.w("imageAdapter not initialized in passSelectedImages")
}
} }
/** /**
@ -443,6 +490,7 @@ class ImageFragment :
if (!progressDialog.isShowing) { if (!progressDialog.isShowing) {
progressDialogLayout.progressDialogText.text = text progressDialogLayout.progressDialogText.text = text
progressDialog.show() progressDialog.show()
Timber.d("Showing mark/unmark progress dialog: %s", text)
} }
} }
@ -452,6 +500,7 @@ class ImageFragment :
fun dismissMarkUnmarkProgressDialog() { fun dismissMarkUnmarkProgressDialog() {
if (progressDialog.isShowing) { if (progressDialog.isShowing) {
progressDialog.dismiss() progressDialog.dismiss()
Timber.d("Dismissed mark/unmark progress dialog")
} }
} }
@ -461,4 +510,4 @@ class ImageFragment :
listOf(Contribution.STATE_IN_PROGRESS, Contribution.STATE_FAILED, Contribution.STATE_QUEUED, Contribution.STATE_PAUSED), listOf(Contribution.STATE_IN_PROGRESS, Contribution.STATE_FAILED, Contribution.STATE_QUEUED, Contribution.STATE_PAUSED),
)?.subscribeOn(Schedulers.io()) )?.subscribeOn(Schedulers.io())
?.blockingGet() ?: emptyList() ?.blockingGet() ?: emptyList()
} }

View file

@ -287,6 +287,8 @@ class ExploreMapFragment : CommonsDaggerSupportFragment(), ExploreMapContract.Vi
super.onPause() super.onPause()
// unregistering the broadcastReceiver, as it was causing an exception and a potential crash // unregistering the broadcastReceiver, as it was causing an exception and a potential crash
unregisterNetworkReceiver() unregisterNetworkReceiver()
locationManager.unregisterLocationManager()
locationManager.removeLocationListener(this)
} }
fun requestLocationIfNeeded() { fun requestLocationIfNeeded() {

View file

@ -508,24 +508,17 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
fragments = mutableListOf() fragments = mutableListOf()
} }
for (uploadableFile in uploadableFiles) { for (uploadableFile in uploadableFiles) {
val uploadMediaDetailFragment = UploadMediaDetailFragment() val uploadMediaDetailFragment = UploadMediaDetailFragment()
if (!uploadIsOfAPlace) { // set fragment properties but defer initialization
uploadMediaDetailFragment.uploadableFile = uploadableFile
uploadMediaDetailFragment.place = place
uploadMediaDetailFragment.inAppPictureLocation = if (!uploadIsOfAPlace) {
handleLocation() handleLocation()
uploadMediaDetailFragment.setImageToBeUploaded( currLocation
uploadableFile,
place,
currLocation
)
locationManager!!.unregisterLocationManager()
} else { } else {
uploadMediaDetailFragment.setImageToBeUploaded( currLocation
uploadableFile,
place,
currLocation
)
} }
val uploadMediaDetailFragmentCallback: UploadMediaDetailFragmentCallback = val uploadMediaDetailFragmentCallback: UploadMediaDetailFragmentCallback =
@ -580,13 +573,19 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
if (isFragmentsSaved) { if (isFragmentsSaved) {
val fragment = fragments!![0] as UploadMediaDetailFragment? val fragment = fragments!![0] as UploadMediaDetailFragment?
fragment!!.fragmentCallback = uploadMediaDetailFragmentCallback fragment!!.fragmentCallback = uploadMediaDetailFragmentCallback
fragment.initializeFragment()
} else { } else {
uploadMediaDetailFragment.fragmentCallback = uploadMediaDetailFragmentCallback uploadMediaDetailFragment.fragmentCallback = uploadMediaDetailFragmentCallback
fragments!!.add(uploadMediaDetailFragment) fragments!!.add(uploadMediaDetailFragment)
} }
} }
//If fragments are not created, create them and add them to the fragments ArrayList // unregister location manager after loop if needed
if (!uploadIsOfAPlace) {
locationManager!!.unregisterLocationManager()
}
// If fragments are not created, create them and add them to the fragments ArrayList
if (!isFragmentsSaved) { if (!isFragmentsSaved) {
uploadCategoriesFragment = UploadCategoriesFragment() uploadCategoriesFragment = UploadCategoriesFragment()
if (place != null) { if (place != null) {

View file

@ -119,8 +119,8 @@ class UploadMediaDetailFragment : UploadBaseFragment(), UploadMediaDetailsContra
private var basicKvStore: BasicKvStore? = null private var basicKvStore: BasicKvStore? = null
private val keyForShowingAlertDialog = "isNoNetworkAlertDialogShowing" private val keyForShowingAlertDialog = "isNoNetworkAlertDialogShowing"
private var uploadableFile: UploadableFile? = null internal var uploadableFile: UploadableFile? = null
private var place: Place? = null internal var place: Place? = null
private lateinit var uploadMediaDetailAdapter: UploadMediaDetailAdapter private lateinit var uploadMediaDetailAdapter: UploadMediaDetailAdapter
var indexOfFragment = 0 var indexOfFragment = 0
var isExpanded = true var isExpanded = true
@ -142,19 +142,24 @@ class UploadMediaDetailFragment : UploadBaseFragment(), UploadMediaDetailsContra
} }
} }
fun setImageToBeUploaded(
uploadableFile: UploadableFile?, place: Place?, inAppPictureLocation: LatLng?
) {
this.uploadableFile = uploadableFile
this.place = place
this.inAppPictureLocation = inAppPictureLocation
}
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View { ): View {
_binding = FragmentUploadMediaDetailFragmentBinding.inflate(inflater, container, false) _binding = FragmentUploadMediaDetailFragmentBinding.inflate(inflater, container, false)
_binding!!.mediaDetailCardView.handleKeyboardInsets() _binding!!.mediaDetailCardView.handleKeyboardInsets()
// intialise the adapter early to prevent uninitialized access
uploadMediaDetailAdapter = UploadMediaDetailAdapter(
this,
defaultKvStore.getString(Prefs.DESCRIPTION_LANGUAGE, "")!!,
recentLanguagesDao, voiceInputResultLauncher
)
uploadMediaDetailAdapter.callback =
UploadMediaDetailAdapter.Callback { titleStringID: Int, messageStringId: Int ->
showInfoAlert(titleStringID, messageStringId)
}
uploadMediaDetailAdapter.eventListener = this
binding.rvDescriptions.layoutManager = LinearLayoutManager(context)
binding.rvDescriptions.adapter = uploadMediaDetailAdapter
return binding.root return binding.root
} }
@ -163,20 +168,48 @@ class UploadMediaDetailFragment : UploadBaseFragment(), UploadMediaDetailsContra
basicKvStore = BasicKvStore(requireActivity(), "CurrentUploadImageQualities") basicKvStore = BasicKvStore(requireActivity(), "CurrentUploadImageQualities")
if (fragmentCallback != null) { // restore adapter items from savedInstanceState if available
indexOfFragment = fragmentCallback!!.getIndexInViewFlipper(this)
initializeFragment()
}
if (savedInstanceState != null) { if (savedInstanceState != null) {
if (uploadMediaDetailAdapter.items.isEmpty() && fragmentCallback != null) { val savedItems = savedInstanceState.getParcelableArrayList<UploadMediaDetail>(UPLOAD_MEDIA_DETAILS)
uploadMediaDetailAdapter.items = savedInstanceState.getParcelableArrayList(UPLOAD_MEDIA_DETAILS)!! Timber.d("Restoring state: savedItems size = %s", savedItems?.size ?: "null")
presenter.setUploadMediaDetails(uploadMediaDetailAdapter.items, indexOfFragment) if (savedItems != null && savedItems.isNotEmpty()) {
uploadMediaDetailAdapter.items = savedItems
// only call setUploadMediaDetails if indexOfFragment is valid
if (fragmentCallback != null) {
indexOfFragment = fragmentCallback!!.getIndexInViewFlipper(this)
if (indexOfFragment >= 0) {
presenter.setUploadMediaDetails(uploadMediaDetailAdapter.items, indexOfFragment)
Timber.d("Restored and set upload media details for index %d", indexOfFragment)
} else {
Timber.w("Invalid indexOfFragment %d, skipping setUploadMediaDetails", indexOfFragment)
}
} else {
Timber.w("fragmentCallback is null, skipping setUploadMediaDetails")
}
} else {
// initialize with a default UploadMediaDetail if saved state is empty or null
uploadMediaDetailAdapter.items = mutableListOf(UploadMediaDetail())
Timber.d("Initialized default UploadMediaDetail due to empty or null savedItems")
}
} else {
// intitialise with a default UploadMediaDetail for fresh fragment
if (uploadMediaDetailAdapter.items.isEmpty()) {
uploadMediaDetailAdapter.items = mutableListOf(UploadMediaDetail())
Timber.d("Initialized default UploadMediaDetail for new fragment")
} }
} }
if (fragmentCallback != null) {
indexOfFragment = fragmentCallback!!.getIndexInViewFlipper(this)
Timber.d("Fragment callback present, indexOfFragment = %d", indexOfFragment)
initializeFragment()
} else {
Timber.w("Fragment callback is null, skipping initializeFragment")
}
try { try {
if (!presenter.getImageQuality(indexOfFragment, inAppPictureLocation, requireActivity())) { if (indexOfFragment >= 0 && !presenter.getImageQuality(indexOfFragment, inAppPictureLocation, requireActivity())) {
Timber.d("Image quality check failed, redirecting to MainActivity")
startActivityWithFlags( startActivityWithFlags(
requireActivity(), requireActivity(),
MainActivity::class.java, MainActivity::class.java,
@ -184,11 +217,12 @@ class UploadMediaDetailFragment : UploadBaseFragment(), UploadMediaDetailsContra
Intent.FLAG_ACTIVITY_SINGLE_TOP Intent.FLAG_ACTIVITY_SINGLE_TOP
) )
} }
} catch (_: Exception) { } catch (e: Exception) {
Timber.e(e, "Error during image quality check")
} }
} }
private fun initializeFragment() { internal fun initializeFragment() {
if (_binding == null) { if (_binding == null) {
return return
} }
@ -206,7 +240,6 @@ class UploadMediaDetailFragment : UploadBaseFragment(), UploadMediaDetailsContra
presenter.setupBasicKvStoreFactory { BasicKvStore(requireActivity(), it) } presenter.setupBasicKvStoreFactory { BasicKvStore(requireActivity(), it) }
presenter.receiveImage(uploadableFile, place, inAppPictureLocation) presenter.receiveImage(uploadableFile, place, inAppPictureLocation)
initRecyclerView()
with (binding){ with (binding){
if (indexOfFragment == 0) { if (indexOfFragment == 0) {
@ -265,24 +298,6 @@ class UploadMediaDetailFragment : UploadBaseFragment(), UploadMediaDetailsContra
} }
} }
/**
* init the description recycler veiw and caption recyclerview
*/
private fun initRecyclerView() {
uploadMediaDetailAdapter = UploadMediaDetailAdapter(
this,
defaultKvStore.getString(Prefs.DESCRIPTION_LANGUAGE, "")!!,
recentLanguagesDao, voiceInputResultLauncher
)
uploadMediaDetailAdapter.callback =
UploadMediaDetailAdapter.Callback { titleStringID: Int, messageStringId: Int ->
showInfoAlert(titleStringID, messageStringId)
}
uploadMediaDetailAdapter.eventListener = this
binding.rvDescriptions.layoutManager = LinearLayoutManager(context)
binding.rvDescriptions.adapter = uploadMediaDetailAdapter
}
private fun showInfoAlert(titleStringID: Int, messageStringId: Int) { private fun showInfoAlert(titleStringID: Int, messageStringId: Int) {
showAlertDialog( showAlertDialog(
requireActivity(), requireActivity(),
@ -590,16 +605,14 @@ class UploadMediaDetailFragment : UploadBaseFragment(), UploadMediaDetailsContra
var defaultLongitude = -122.431297 var defaultLongitude = -122.431297
var defaultZoom = 16.0 var defaultZoom = 16.0
val locationPickerIntent: Intent
/* Retrieve image location from EXIF if present or /* Retrieve image location from EXIF if present or
check if user has provided location while using the in-app camera. check if user has provided location while using the in-app camera.
Use location of last UploadItem if none of them is available */ Use location of last UploadItem if none of them is available */
val locationPickerIntent: Intent
if (uploadItem.gpsCoords != null && uploadItem.gpsCoords!! if (uploadItem.gpsCoords != null && uploadItem.gpsCoords!!
.decLatitude != 0.0 && uploadItem.gpsCoords!!.decLongitude != 0.0 .decLatitude != 0.0 && uploadItem.gpsCoords!!.decLongitude != 0.0
) { ) {
defaultLatitude = uploadItem.gpsCoords!! defaultLatitude = uploadItem.gpsCoords!!.decLatitude
.decLatitude
defaultLongitude = uploadItem.gpsCoords!!.decLongitude defaultLongitude = uploadItem.gpsCoords!!.decLongitude
defaultZoom = uploadItem.gpsCoords!!.zoomLevel defaultZoom = uploadItem.gpsCoords!!.zoomLevel
@ -615,8 +628,7 @@ class UploadMediaDetailFragment : UploadBaseFragment(), UploadMediaDetailsContra
defaultLongitude = locationLatLng[1].toDouble() defaultLongitude = locationLatLng[1].toDouble()
} }
if (defaultKvStore.getString(LAST_ZOOM) != null) { if (defaultKvStore.getString(LAST_ZOOM) != null) {
defaultZoom = defaultKvStore.getString(LAST_ZOOM)!! defaultZoom = defaultKvStore.getString(LAST_ZOOM)!!.toDouble()
.toDouble()
} }
locationPickerIntent = LocationPicker.IntentBuilder() locationPickerIntent = LocationPicker.IntentBuilder()
@ -907,4 +919,4 @@ class UploadMediaDetailFragment : UploadBaseFragment(), UploadMediaDetailsContra
const val UPLOADABLE_FILE: String = "uploadable_file" const val UPLOADABLE_FILE: String = "uploadable_file"
const val UPLOAD_MEDIA_DETAILS: String = "upload_media_detail_adapter" const val UPLOAD_MEDIA_DETAILS: String = "upload_media_detail_adapter"
} }
} }

View file

@ -69,7 +69,18 @@ class UploadMediaPresenter @Inject constructor(
uploadMediaDetails: List<UploadMediaDetail>, uploadMediaDetails: List<UploadMediaDetail>,
uploadItemIndex: Int uploadItemIndex: Int
) { ) {
repository.getUploads()[uploadItemIndex].uploadMediaDetails = uploadMediaDetails.toMutableList() val uploadItems = repository.getUploads()
if (uploadItemIndex >= 0 && uploadItemIndex < uploadItems.size) {
if (uploadMediaDetails.isNotEmpty()) {
uploadItems[uploadItemIndex].uploadMediaDetails = uploadMediaDetails.toMutableList()
Timber.d("Set uploadMediaDetails for index %d, size %d", uploadItemIndex, uploadMediaDetails.size)
} else {
uploadItems[uploadItemIndex].uploadMediaDetails = mutableListOf(UploadMediaDetail())
Timber.w("Received empty uploadMediaDetails for index %d, initialized default", uploadItemIndex)
}
} else {
Timber.e("Invalid index %d for uploadItems size %d, skipping setUploadMediaDetails", uploadItemIndex, uploadItems.size)
}
} }
override fun setupBasicKvStoreFactory(factory: (String) -> BasicKvStore) { override fun setupBasicKvStoreFactory(factory: (String) -> BasicKvStore) {

View file

@ -145,6 +145,8 @@ class UploadMediaDetailFragmentUnitTest {
ibExpandCollapse = view.findViewById(R.id.ib_expand_collapse) ibExpandCollapse = view.findViewById(R.id.ib_expand_collapse)
Whitebox.setInternalState(fragment, "uploadMediaDetailAdapter", uploadMediaDetailAdapter) Whitebox.setInternalState(fragment, "uploadMediaDetailAdapter", uploadMediaDetailAdapter)
Whitebox.setInternalState(fragment, "defaultKvStore", defaultKvStore)
`when`(defaultKvStore.getString("description_language", "")).thenReturn("en")
} }
@Test @Test
@ -160,16 +162,10 @@ class UploadMediaDetailFragmentUnitTest {
fragment.onCreate(Bundle()) fragment.onCreate(Bundle())
} }
@Test
@Throws(Exception::class)
fun testSetImageToBeUploaded() {
Shadows.shadowOf(Looper.getMainLooper()).idle()
fragment.setImageToBeUploaded(null, null, location)
}
@Test @Test
@Throws(Exception::class) @Throws(Exception::class)
fun testOnCreateView() { fun testOnCreateView() {
Shadows.shadowOf(Looper.getMainLooper()).idle()
fragment.onCreateView(layoutInflater, null, savedInstanceState) fragment.onCreateView(layoutInflater, null, savedInstanceState)
} }
@ -181,34 +177,6 @@ class UploadMediaDetailFragmentUnitTest {
fragment.onViewCreated(view, savedInstanceState) fragment.onViewCreated(view, savedInstanceState)
} }
@Test
@Throws(Exception::class)
fun testInit() {
Shadows.shadowOf(Looper.getMainLooper()).idle()
Whitebox.setInternalState(fragment, "presenter", presenter)
val method: Method =
UploadMediaDetailFragment::class.java.getDeclaredMethod(
"initializeFragment",
)
method.isAccessible = true
method.invoke(fragment)
}
@Test
@Throws(Exception::class)
fun testInitCaseGetIndexInViewFlipperNonZero() {
Shadows.shadowOf(Looper.getMainLooper()).idle()
Whitebox.setInternalState(fragment, "presenter", presenter)
`when`(callback.getIndexInViewFlipper(fragment)).thenReturn(1)
`when`(callback.totalNumberOfSteps).thenReturn(5)
val method: Method =
UploadMediaDetailFragment::class.java.getDeclaredMethod(
"initializeFragment",
)
method.isAccessible = true
method.invoke(fragment)
}
@Test @Test
@Throws(Exception::class) @Throws(Exception::class)
fun testShowInfoAlert() { fun testShowInfoAlert() {
@ -317,7 +285,7 @@ class UploadMediaDetailFragmentUnitTest {
@Test @Test
@Throws(Exception::class) @Throws(Exception::class)
fun testShowExternalMap() { fun testShowExternalMap() {
shadowOf(Looper.getMainLooper()).idle() Shadows.shadowOf(Looper.getMainLooper()).idle()
`when`(uploadItem.gpsCoords).thenReturn(imageCoordinates) `when`(uploadItem.gpsCoords).thenReturn(imageCoordinates)
`when`(imageCoordinates.decLatitude).thenReturn(0.0) `when`(imageCoordinates.decLatitude).thenReturn(0.0)
`when`(imageCoordinates.decLongitude).thenReturn(0.0) `when`(imageCoordinates.decLongitude).thenReturn(0.0)
@ -328,7 +296,7 @@ class UploadMediaDetailFragmentUnitTest {
@Test @Test
@Throws(Exception::class) @Throws(Exception::class)
fun testOnCameraPositionCallbackOnMapIconClicked() { fun testOnCameraPositionCallbackOnMapIconClicked() {
shadowOf(Looper.getMainLooper()).idle() Shadows.shadowOf(Looper.getMainLooper()).idle()
Mockito.mock(LocationPicker::class.java) Mockito.mock(LocationPicker::class.java)
val intent = Mockito.mock(Intent::class.java) val intent = Mockito.mock(Intent::class.java)
val cameraPosition = Mockito.mock(CameraPosition::class.java) val cameraPosition = Mockito.mock(CameraPosition::class.java)
@ -357,7 +325,7 @@ class UploadMediaDetailFragmentUnitTest {
@Test @Test
@Throws(Exception::class) @Throws(Exception::class)
fun testOnCameraPositionCallbackAddLocationDialog() { fun testOnCameraPositionCallbackAddLocationDialog() {
shadowOf(Looper.getMainLooper()).idle() Shadows.shadowOf(Looper.getMainLooper()).idle()
Mockito.mock(LocationPicker::class.java) Mockito.mock(LocationPicker::class.java)
val intent = Mockito.mock(Intent::class.java) val intent = Mockito.mock(Intent::class.java)
val cameraPosition = Mockito.mock(CameraPosition::class.java) val cameraPosition = Mockito.mock(CameraPosition::class.java)
@ -427,7 +395,7 @@ class UploadMediaDetailFragmentUnitTest {
@Test @Test
@Throws(Exception::class) @Throws(Exception::class)
fun testRememberedZoomLevelOnNull() { fun testRememberedZoomLevelOnNull() {
shadowOf(Looper.getMainLooper()).idle() Shadows.shadowOf(Looper.getMainLooper()).idle()
Whitebox.setInternalState(fragment, "defaultKvStore", defaultKvStore) Whitebox.setInternalState(fragment, "defaultKvStore", defaultKvStore)
`when`(uploadItem.gpsCoords).thenReturn(null) `when`(uploadItem.gpsCoords).thenReturn(null)
`when`(defaultKvStore.getString(LAST_ZOOM)).thenReturn("13.0") `when`(defaultKvStore.getString(LAST_ZOOM)).thenReturn("13.0")
@ -443,7 +411,7 @@ class UploadMediaDetailFragmentUnitTest {
@Test @Test
@Throws(Exception::class) @Throws(Exception::class)
fun testRememberedZoomLevelOnNotNull() { fun testRememberedZoomLevelOnNotNull() {
shadowOf(Looper.getMainLooper()).idle() Shadows.shadowOf(Looper.getMainLooper()).idle()
`when`(uploadItem.gpsCoords).thenReturn(imageCoordinates) `when`(uploadItem.gpsCoords).thenReturn(imageCoordinates)
`when`(imageCoordinates.decLatitude).thenReturn(8.0) `when`(imageCoordinates.decLatitude).thenReturn(8.0)
`when`(imageCoordinates.decLongitude).thenReturn(-8.0) `when`(imageCoordinates.decLongitude).thenReturn(-8.0)
@ -456,4 +424,4 @@ class UploadMediaDetailFragmentUnitTest {
val shadowIntent: ShadowIntent = shadowOf(startedIntent) val shadowIntent: ShadowIntent = shadowOf(startedIntent)
Assert.assertEquals(shadowIntent.intentClass, LocationPickerActivity::class.java) Assert.assertEquals(shadowIntent.intentClass, LocationPickerActivity::class.java)
} }
} }