mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 12:23:58 +01:00
Merge branch 'main' into fix/upload-limit-#3101
This commit is contained in:
commit
e17a668acc
14 changed files with 208 additions and 53 deletions
|
|
@ -173,19 +173,13 @@ class BookmarkItemsDao @Inject constructor(
|
||||||
categoryNameList: List<String>,
|
categoryNameList: List<String>,
|
||||||
categoryDescriptionList: List<String>,
|
categoryDescriptionList: List<String>,
|
||||||
categoryThumbnailList: List<String>
|
categoryThumbnailList: List<String>
|
||||||
): List<CategoryItem> {
|
): List<CategoryItem> = categoryNameList.mapIndexed { index, name ->
|
||||||
return buildList {
|
CategoryItem(
|
||||||
for (i in categoryNameList.indices) {
|
name = name,
|
||||||
add(
|
description = categoryDescriptionList.getOrNull(index),
|
||||||
CategoryItem(
|
thumbnail = categoryThumbnailList.getOrNull(index),
|
||||||
categoryNameList[i],
|
isSelected = false
|
||||||
categoryDescriptionList[i],
|
)
|
||||||
categoryThumbnailList[i],
|
|
||||||
false
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ import com.google.gson.annotations.SerializedName
|
||||||
*/
|
*/
|
||||||
class CampaignConfig {
|
class CampaignConfig {
|
||||||
@SerializedName("showOnlyLiveCampaigns")
|
@SerializedName("showOnlyLiveCampaigns")
|
||||||
private val showOnlyLiveCampaigns = false
|
var showOnlyLiveCampaigns = false
|
||||||
|
|
||||||
@SerializedName("sortBy")
|
@SerializedName("sortBy")
|
||||||
private val sortBy: String? = null
|
var sortBy: String? = null
|
||||||
}
|
}
|
||||||
|
|
@ -8,8 +8,8 @@ import fr.free.nrw.commons.campaigns.models.Campaign
|
||||||
*/
|
*/
|
||||||
class CampaignResponseDTO {
|
class CampaignResponseDTO {
|
||||||
@SerializedName("config")
|
@SerializedName("config")
|
||||||
val campaignConfig: CampaignConfig? = null
|
var campaignConfig: CampaignConfig? = null
|
||||||
|
|
||||||
@SerializedName("campaigns")
|
@SerializedName("campaigns")
|
||||||
val campaigns: List<Campaign>? = null
|
var campaigns: List<Campaign>? = null
|
||||||
}
|
}
|
||||||
|
|
@ -324,7 +324,7 @@ after opening the app.
|
||||||
)
|
)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.blockingGet()
|
.blockingGet()
|
||||||
Timber.d("Resuming " + stuckUploads.size + " uploads...")
|
Timber.d("Resuming %d uploads...", stuckUploads.size)
|
||||||
if (!stuckUploads.isEmpty()) {
|
if (!stuckUploads.isEmpty()) {
|
||||||
for (contribution in stuckUploads) {
|
for (contribution in stuckUploads) {
|
||||||
contribution.state = Contribution.STATE_QUEUED
|
contribution.state = Contribution.STATE_QUEUED
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ProgressBar
|
import android.widget.ProgressBar
|
||||||
import android.widget.Switch
|
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.constraintlayout.widget.ConstraintLayout
|
import androidx.constraintlayout.widget.ConstraintLayout
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
|
|
@ -20,6 +19,7 @@ import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.lifecycle.repeatOnLifecycle
|
import androidx.lifecycle.repeatOnLifecycle
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.google.android.material.switchmaterial.SwitchMaterial
|
||||||
import fr.free.nrw.commons.contributions.Contribution
|
import fr.free.nrw.commons.contributions.Contribution
|
||||||
import fr.free.nrw.commons.contributions.ContributionDao
|
import fr.free.nrw.commons.contributions.ContributionDao
|
||||||
import fr.free.nrw.commons.customselector.database.NotForUploadStatusDao
|
import fr.free.nrw.commons.customselector.database.NotForUploadStatusDao
|
||||||
|
|
@ -82,7 +82,7 @@ class ImageFragment :
|
||||||
*/
|
*/
|
||||||
private var selectorRV: RecyclerView? = null
|
private var selectorRV: RecyclerView? = null
|
||||||
private var loader: ProgressBar? = null
|
private var loader: ProgressBar? = null
|
||||||
private var switch: Switch? = null
|
private var switch: SwitchMaterial? = null
|
||||||
lateinit var filteredImages: ArrayList<Image>
|
lateinit var filteredImages: ArrayList<Image>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -112,8 +112,8 @@ class WikidataItemDetailsActivity : BaseActivity(), MediaDetailProvider, Categor
|
||||||
|
|
||||||
viewPagerAdapter!!.setTabs(
|
viewPagerAdapter!!.setTabs(
|
||||||
R.string.title_for_media to depictionImagesListFragment!!,
|
R.string.title_for_media to depictionImagesListFragment!!,
|
||||||
R.string.title_for_subcategories to childDepictionsFragment,
|
R.string.title_for_child_classes to childDepictionsFragment,
|
||||||
R.string.title_for_parent_categories to parentDepictionsFragment
|
R.string.title_for_parent_classes to parentDepictionsFragment
|
||||||
)
|
)
|
||||||
binding!!.viewPager.offscreenPageLimit = 2
|
binding!!.viewPager.offscreenPageLimit = 2
|
||||||
viewPagerAdapter!!.notifyDataSetChanged()
|
viewPagerAdapter!!.notifyDataSetChanged()
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ import java.io.File
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
import timber.log.Timber
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This activity will set two tabs, achievements and
|
* This activity will set two tabs, achievements and
|
||||||
|
|
@ -122,7 +123,7 @@ class ProfileActivity : BaseActivity() {
|
||||||
val rootView = window.decorView.findViewById<View>(android.R.id.content)
|
val rootView = window.decorView.findViewById<View>(android.R.id.content)
|
||||||
val screenShot = getScreenShot(rootView)
|
val screenShot = getScreenShot(rootView)
|
||||||
if (screenShot == null) {
|
if (screenShot == null) {
|
||||||
Log.e("ERROR", "ScreenShot is null")
|
Timber.e("ScreenShot is null")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
showAlert(screenShot)
|
showAlert(screenShot)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package fr.free.nrw.commons.settings
|
package fr.free.nrw.commons.settings
|
||||||
|
|
||||||
import android.Manifest.permission
|
import android.Manifest.permission
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.app.Dialog
|
import android.app.Dialog
|
||||||
import android.content.Context.MODE_PRIVATE
|
import android.content.Context.MODE_PRIVATE
|
||||||
|
|
@ -303,6 +304,11 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove the space for icons in the settings menu.
|
||||||
|
// This uses an internal API that shouldn't be used in app code,
|
||||||
|
// but it appears to be the most robust way to do this at the moment,
|
||||||
|
// disable the warning.
|
||||||
|
@SuppressLint("RestrictedApi")
|
||||||
override fun onCreateAdapter(preferenceScreen: PreferenceScreen): Adapter<PreferenceViewHolder>
|
override fun onCreateAdapter(preferenceScreen: PreferenceScreen): Adapter<PreferenceViewHolder>
|
||||||
{
|
{
|
||||||
return object : PreferenceGroupAdapter(preferenceScreen) {
|
return object : PreferenceGroupAdapter(preferenceScreen) {
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ object LocationUtils {
|
||||||
latLng = LatLng(latLngArray[1].trim().toDouble(),
|
latLng = LatLng(latLngArray[1].trim().toDouble(),
|
||||||
latLngArray[0].trim().toDouble(), 1f)
|
latLngArray[0].trim().toDouble(), 1f)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Timber.e("Error while parsing user entered lat long: %s", e)
|
Timber.e(e, "Error while parsing user entered lat long")
|
||||||
}
|
}
|
||||||
|
|
||||||
return latLng
|
return latLng
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:background="?attr/mainBackground">
|
android:background="?attr/mainBackground">
|
||||||
|
|
||||||
<Switch
|
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||||
android:id="@+id/switchWidget"
|
android:id="@+id/switchWidget"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<resources>
|
<resources>
|
||||||
<!--accessibility UI description strings-->
|
<!--accessibility UI description strings-->
|
||||||
<string name="commons_facebook">Commons Facebook Page</string>
|
<string name="commons_facebook">Commons Facebook Page</string>
|
||||||
<string name="commons_github">Commons Github Source Code</string>
|
<string name="commons_github">Commons GitHub Source Code</string>
|
||||||
<string name="commons_logo">Commons Logo</string>
|
<string name="commons_logo">Commons Logo</string>
|
||||||
<string name="commons_website">Commons Website</string>
|
<string name="commons_website">Commons Website</string>
|
||||||
<string name="exit_location_picker">Exit location picker</string>
|
<string name="exit_location_picker">Exit location picker</string>
|
||||||
|
|
@ -493,12 +493,12 @@ Upload your first media by tapping on the add button.</string>
|
||||||
<string name="check_category_failure_message">Could not request category check for %1$s</string>
|
<string name="check_category_failure_message">Could not request category check for %1$s</string>
|
||||||
<string name="check_category_toast">Requesting category check for %1$s</string>
|
<string name="check_category_toast">Requesting category check for %1$s</string>
|
||||||
<string name="nominate_for_deletion_done">Done</string>
|
<string name="nominate_for_deletion_done">Done</string>
|
||||||
<string name="send_thank_success_title">Sending Thanks: Success</string>
|
<string name="send_thank_success_title">Sending thanks: Success</string>
|
||||||
<string name="send_thank_success_message">Sent thanks to %1$s</string>
|
<string name="send_thank_success_message">Sent thanks to %1$s</string>
|
||||||
<string name="send_thank_failure_message">Failed to send thanks to %1$s</string>
|
<string name="send_thank_failure_message">Failed to send thanks to %1$s</string>
|
||||||
<string name="send_thank_failure_title">Sending Thanks: Failure</string>
|
<string name="send_thank_failure_title">Sending thanks: Failure</string>
|
||||||
|
|
||||||
<string name="send_thank_toast">Sending Thanks for %1$s</string>
|
<string name="send_thank_toast">Sending thanks for %1$s</string>
|
||||||
<string name="review_copyright">Does this follow the rules of copyright?</string>
|
<string name="review_copyright">Does this follow the rules of copyright?</string>
|
||||||
<string name="review_category">Is this correctly categorized?</string>
|
<string name="review_category">Is this correctly categorized?</string>
|
||||||
<string name="review_spam">Is this in-scope?</string>
|
<string name="review_spam">Is this in-scope?</string>
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,10 @@ package fr.free.nrw.commons
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.nhaarman.mockitokotlin2.any
|
import com.nhaarman.mockitokotlin2.any
|
||||||
import com.nhaarman.mockitokotlin2.verify
|
import com.nhaarman.mockitokotlin2.verify
|
||||||
|
import com.nhaarman.mockitokotlin2.times
|
||||||
|
import fr.free.nrw.commons.campaigns.CampaignResponseDTO
|
||||||
|
import fr.free.nrw.commons.campaigns.CampaignConfig
|
||||||
|
import fr.free.nrw.commons.campaigns.models.Campaign
|
||||||
import fr.free.nrw.commons.explore.depictions.DepictsClient
|
import fr.free.nrw.commons.explore.depictions.DepictsClient
|
||||||
import fr.free.nrw.commons.location.LatLng
|
import fr.free.nrw.commons.location.LatLng
|
||||||
import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient
|
import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient
|
||||||
|
|
@ -10,13 +14,22 @@ import fr.free.nrw.commons.nearby.model.NearbyQueryParams
|
||||||
import okhttp3.Call
|
import okhttp3.Call
|
||||||
import okhttp3.HttpUrl
|
import okhttp3.HttpUrl
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
|
import okhttp3.Request
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
|
import okhttp3.ResponseBody
|
||||||
|
import okhttp3.mockwebserver.MockResponse
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Assert.assertFalse
|
||||||
|
import org.junit.Assert.assertNotNull
|
||||||
|
import org.junit.Assert.assertTrue
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.mockito.Mock
|
import org.mockito.Mock
|
||||||
import org.mockito.Mockito
|
import org.mockito.Mockito
|
||||||
import org.mockito.Mockito.times
|
import org.mockito.Mockito.eq
|
||||||
import org.mockito.MockitoAnnotations
|
import org.mockito.MockitoAnnotations
|
||||||
|
import java.io.BufferedReader
|
||||||
|
import java.io.InputStreamReader
|
||||||
import java.lang.Exception
|
import java.lang.Exception
|
||||||
|
|
||||||
class OkHttpJsonApiClientTests {
|
class OkHttpJsonApiClientTests {
|
||||||
|
|
@ -45,34 +58,43 @@ class OkHttpJsonApiClientTests {
|
||||||
@Mock
|
@Mock
|
||||||
lateinit var response: Response
|
lateinit var response: Response
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
lateinit var responseBody: ResponseBody
|
||||||
|
|
||||||
|
private lateinit var mockWebServer: TestWebServer
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
MockitoAnnotations.openMocks(this)
|
MockitoAnnotations.openMocks(this)
|
||||||
okHttpJsonApiClient =
|
mockWebServer = TestWebServer()
|
||||||
OkHttpJsonApiClient(
|
mockWebServer.setUp()
|
||||||
okhttpClient,
|
okHttpJsonApiClient = OkHttpJsonApiClient(
|
||||||
depictsClient,
|
okhttpClient,
|
||||||
wikiMediaToolforgeUrl,
|
depictsClient,
|
||||||
sparqlQueryUrl,
|
wikiMediaToolforgeUrl,
|
||||||
campaignsUrl,
|
sparqlQueryUrl,
|
||||||
gson,
|
mockWebServer.getUrl(), //use the mock server for the campaignsUrl
|
||||||
)
|
gson
|
||||||
|
)
|
||||||
Mockito.`when`(okhttpClient.newCall(any())).thenReturn(call)
|
Mockito.`when`(okhttpClient.newCall(any())).thenReturn(call)
|
||||||
Mockito.`when`(call.execute()).thenReturn(response)
|
Mockito.`when`(call.execute()).thenReturn(response)
|
||||||
|
Mockito.`when`(response.isSuccessful).thenReturn(false)
|
||||||
|
Mockito.`when`(response.message).thenReturn("test")
|
||||||
|
Mockito.`when`(response.body).thenReturn(responseBody)
|
||||||
|
Mockito.`when`(responseBody.string()).thenReturn("{\"error\": \"test\"}")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testGetNearbyPlacesCustomQuery() {
|
fun testGetNearbyPlacesCustomQuery() {
|
||||||
Mockito.`when`(response.message).thenReturn("test")
|
|
||||||
try {
|
try {
|
||||||
okHttpJsonApiClient.getNearbyPlaces(latLng, "test", 10.0, "test")
|
okHttpJsonApiClient.getNearbyPlaces(latLng, "test", 10.0, "test")
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
assert(e.message.equals("test"))
|
assertEquals("test", e.message)
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
okHttpJsonApiClient.getNearbyPlaces(NearbyQueryParams.Rectangular(latLng, latLng), "test", true, "test")
|
okHttpJsonApiClient.getNearbyPlaces(NearbyQueryParams.Rectangular(latLng, latLng), "test", true, "test")
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
assert(e.message.equals("test"))
|
assertEquals("test", e.message)
|
||||||
}
|
}
|
||||||
verify(okhttpClient, times(2)).newCall(any())
|
verify(okhttpClient, times(2)).newCall(any())
|
||||||
verify(call, times(2)).execute()
|
verify(call, times(2)).execute()
|
||||||
|
|
@ -80,11 +102,10 @@ class OkHttpJsonApiClientTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testGetNearbyPlaces() {
|
fun testGetNearbyPlaces() {
|
||||||
Mockito.`when`(response.message).thenReturn("test")
|
|
||||||
try {
|
try {
|
||||||
okHttpJsonApiClient.getNearbyPlaces(latLng, "test", 10.0, null)
|
okHttpJsonApiClient.getNearbyPlaces(latLng, "test", 10.0, null)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
assert(e.message.equals("test"))
|
assertEquals("test", e.message)
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
okHttpJsonApiClient.getNearbyPlaces(
|
okHttpJsonApiClient.getNearbyPlaces(
|
||||||
|
|
@ -93,9 +114,8 @@ class OkHttpJsonApiClientTests {
|
||||||
true,
|
true,
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
assert(e.message.equals("test"))
|
assertEquals("test", e.message)
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
okHttpJsonApiClient.getNearbyPlaces(
|
okHttpJsonApiClient.getNearbyPlaces(
|
||||||
|
|
@ -105,7 +125,7 @@ class OkHttpJsonApiClientTests {
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
assert(e.message.equals("test"))
|
assertEquals("test", e.message)
|
||||||
}
|
}
|
||||||
verify(okhttpClient, times(3)).newCall(any())
|
verify(okhttpClient, times(3)).newCall(any())
|
||||||
verify(call, times(3)).execute()
|
verify(call, times(3)).execute()
|
||||||
|
|
@ -113,18 +133,121 @@ class OkHttpJsonApiClientTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testGetNearbyItemCount() {
|
fun testGetNearbyItemCount() {
|
||||||
Mockito.`when`(response.message).thenReturn("test")
|
|
||||||
try {
|
try {
|
||||||
okHttpJsonApiClient.getNearbyItemCount(NearbyQueryParams.Radial(latLng, 10f))
|
okHttpJsonApiClient.getNearbyItemCount(NearbyQueryParams.Radial(latLng, 10f))
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
assert(e.message.equals("test"))
|
assertEquals("test", e.message)
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
okHttpJsonApiClient.getNearbyItemCount(NearbyQueryParams.Rectangular(latLng, latLng))
|
okHttpJsonApiClient.getNearbyItemCount(NearbyQueryParams.Rectangular(latLng, latLng))
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
assert(e.message.equals("test"))
|
assertEquals("test", e.message)
|
||||||
}
|
}
|
||||||
verify(okhttpClient, times(2)).newCall(any())
|
verify(okhttpClient, times(2)).newCall(any())
|
||||||
verify(call, times(2)).execute()
|
verify(call, times(2)).execute()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@Test
|
||||||
|
fun testGetCampaignsWithData() {
|
||||||
|
//loads the json response from resources
|
||||||
|
val jsonResponse = loadJsonFromResource("campaigns_response_with_data.json")
|
||||||
|
|
||||||
|
//mocks the succesfull response chain
|
||||||
|
Mockito.`when`(response.isSuccessful).thenReturn(true)
|
||||||
|
Mockito.`when`(response.message).thenReturn("OK")
|
||||||
|
Mockito.`when`(response.body).thenReturn(responseBody)
|
||||||
|
Mockito.`when`(responseBody.string()).thenReturn(jsonResponse)
|
||||||
|
|
||||||
|
val campaignResponse = CampaignResponseDTO().apply {
|
||||||
|
campaignConfig = CampaignConfig().apply {
|
||||||
|
showOnlyLiveCampaigns = false
|
||||||
|
sortBy = "startDate"
|
||||||
|
}
|
||||||
|
campaigns = listOf(
|
||||||
|
Campaign().apply {
|
||||||
|
title = "Wiki Loves Monuments"
|
||||||
|
isWLMCampaign = true
|
||||||
|
},
|
||||||
|
Campaign().apply {
|
||||||
|
title = "Wiki Loves Nature"
|
||||||
|
isWLMCampaign = false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
//any() for the string argument and eq() for the class argument.
|
||||||
|
Mockito.`when`(
|
||||||
|
gson.fromJson(
|
||||||
|
any<String>(),
|
||||||
|
eq(CampaignResponseDTO::class.java)
|
||||||
|
)
|
||||||
|
).thenReturn(campaignResponse)
|
||||||
|
|
||||||
|
//call the getCampaigns
|
||||||
|
val result: CampaignResponseDTO? = okHttpJsonApiClient.getCampaigns().blockingGet()
|
||||||
|
|
||||||
|
//verify the results
|
||||||
|
assertNotNull(result)
|
||||||
|
assertNotNull(result?.campaigns)
|
||||||
|
assertEquals(2, result?.campaigns!!.size)
|
||||||
|
assertEquals("Wiki Loves Monuments", result.campaigns!![0].title)
|
||||||
|
assertTrue(result.campaigns!![0].isWLMCampaign)
|
||||||
|
assertEquals("Wiki Loves Nature", result.campaigns!![1].title)
|
||||||
|
assertEquals(false, result.campaigns!![1].isWLMCampaign)
|
||||||
|
assertNotNull(result.campaignConfig)
|
||||||
|
assertFalse(result.campaignConfig!!.showOnlyLiveCampaigns)
|
||||||
|
assertEquals("startDate", result.campaignConfig!!.sortBy)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testGetCampaignsEmpty() {
|
||||||
|
//loads the empty json response
|
||||||
|
val jsonResponse = loadJsonFromResource("campaigns_response_empty.json")
|
||||||
|
|
||||||
|
//mocks the successful response chain
|
||||||
|
Mockito.`when`(response.isSuccessful).thenReturn(true)
|
||||||
|
Mockito.`when`(response.message).thenReturn("OK")
|
||||||
|
Mockito.`when`(response.body).thenReturn(responseBody)
|
||||||
|
Mockito.`when`(responseBody.string()).thenReturn(jsonResponse)
|
||||||
|
|
||||||
|
val campaignResponse = CampaignResponseDTO().apply {
|
||||||
|
campaignConfig = CampaignConfig().apply {
|
||||||
|
showOnlyLiveCampaigns = false
|
||||||
|
sortBy = "startDate"
|
||||||
|
}
|
||||||
|
campaigns = emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
//use any() for the string argument and eq() for the class argument.
|
||||||
|
Mockito.`when`(
|
||||||
|
gson.fromJson(
|
||||||
|
any<String>(),
|
||||||
|
eq(CampaignResponseDTO::class.java)
|
||||||
|
)
|
||||||
|
).thenReturn(campaignResponse)
|
||||||
|
|
||||||
|
//calls getCampaigns
|
||||||
|
val result: CampaignResponseDTO? = okHttpJsonApiClient.getCampaigns().blockingGet()
|
||||||
|
|
||||||
|
//verify the results
|
||||||
|
assertNotNull(result)
|
||||||
|
assertNotNull(result?.campaigns)
|
||||||
|
assertTrue(result?.campaigns!!.isEmpty())
|
||||||
|
assertNotNull(result.campaignConfig)
|
||||||
|
assertFalse(result.campaignConfig!!.showOnlyLiveCampaigns)
|
||||||
|
assertEquals("startDate", result.campaignConfig!!.sortBy)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun loadJsonFromResource(fileName: String): String {
|
||||||
|
val resourcePath = "raw/$fileName"
|
||||||
|
//uses the classloader to find the resource in the test environment
|
||||||
|
val inputStream = javaClass.classLoader?.getResourceAsStream(resourcePath)
|
||||||
|
|
||||||
|
if (inputStream != null) {
|
||||||
|
//reads the entire stream content
|
||||||
|
return BufferedReader(InputStreamReader(inputStream)).use { it.readText() }
|
||||||
|
}
|
||||||
|
//throws an exception with the correct expected path
|
||||||
|
throw IllegalArgumentException("Resource $fileName not found. Please ensure the file is located in app/src/test/resources/raw/")
|
||||||
|
}
|
||||||
|
}
|
||||||
7
app/src/test/resources/raw/campaigns_response_empty.json
Normal file
7
app/src/test/resources/raw/campaigns_response_empty.json
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"showOnlyLiveCampaigns": false,
|
||||||
|
"sortBy": "startDate"
|
||||||
|
},
|
||||||
|
"campaigns": []
|
||||||
|
}
|
||||||
24
app/src/test/resources/raw/campaigns_response_with_data.json
Normal file
24
app/src/test/resources/raw/campaigns_response_with_data.json
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"showOnlyLiveCampaigns": false,
|
||||||
|
"sortBy": "startDate"
|
||||||
|
},
|
||||||
|
"campaigns": [
|
||||||
|
{
|
||||||
|
"title": "Wiki Loves Monuments",
|
||||||
|
"description": "A campaign to photograph monuments",
|
||||||
|
"startDate": "2025-09-01",
|
||||||
|
"endDate": "2025-09-30",
|
||||||
|
"link": "https://commons.wikimedia.org/wiki/Campaign:Wiki_Loves_Monuments",
|
||||||
|
"isWLMCampaign": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Wiki Loves Nature",
|
||||||
|
"description": "A campaign to photograph nature",
|
||||||
|
"startDate": "2025-06-01",
|
||||||
|
"endDate": "2025-06-30",
|
||||||
|
"link": "https://commons.wikimedia.org/wiki/Campaign:Wiki_Loves_Nature",
|
||||||
|
"isWLMCampaign": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue