Fixed #4784 : Inform users about unsupported features in beta flavor (#4834)

* Display toast and disable API in LeaderboardFragment beta flavor

* Display toast and disable API in AchievementsFragment beta flavor

* Removed unused Gravity import

* Added Toast appearance tests for AchievementsFragment

* Added Toast appearance tests for LeaderboardFragment

* Improve Context detection in Achievements+Leaderboard fragments to ensure Context found for Toast

* Add testOnCreateView for AchievementsFragment
This commit is contained in:
Jacob Fano 2022-02-23 21:40:51 -08:00 committed by GitHub
parent 18a9170691
commit 1405300fd5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 154 additions and 2 deletions

View file

@ -3,6 +3,7 @@ package fr.free.nrw.commons.profile.achievements;
import android.accounts.Account;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.util.DisplayMetrics;
@ -15,6 +16,7 @@ import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.appcompat.view.ContextThemeWrapper;
import androidx.appcompat.widget.AppCompatTextView;
@ -29,6 +31,7 @@ import fr.free.nrw.commons.Utils;
import fr.free.nrw.commons.auth.SessionManager;
import fr.free.nrw.commons.di.CommonsDaggerSupportFragment;
import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient;
import fr.free.nrw.commons.utils.ConfigUtils;
import fr.free.nrw.commons.utils.ViewUtil;
import fr.free.nrw.commons.profile.ProfileActivity;
import io.reactivex.android.schedulers.AndroidSchedulers;
@ -179,11 +182,46 @@ public class AchievementsFragment extends CommonsDaggerSupportFragment {
tvAchievementsOfUser.setVisibility(View.VISIBLE);
tvAchievementsOfUser.setText(getString(R.string.achievements_of_user,userName));
}
// Achievements currently unimplemented in Beta flavor. Skip all API calls.
if(ConfigUtils.isBetaFlavour()) {
progressBar.setVisibility(View.GONE);
imageByWikiText.setText(R.string.no_image);
imageRevertedText.setText(R.string.no_image_reverted);
imageUploadedText.setText(R.string.no_image_uploaded);
wikidataEditsText.setText("0");
imagesFeatured.setText("0");
tvQualityImages.setText("0");
thanksReceived.setText("0");
setMenuVisibility(true);
return rootView;
}
setWikidataEditCount();
setAchievements();
return rootView;
}
@Override
public void setMenuVisibility(boolean visible) {
super.setMenuVisibility(visible);
// Whenever this fragment is revealed in a menu,
// notify Beta users the page data is unavailable
if(ConfigUtils.isBetaFlavour() && visible) {
Context ctx = null;
if(getContext() != null) {
ctx = getContext();
} else if(getView() != null && getView().getContext() != null) {
ctx = getView().getContext();
}
if(ctx != null) {
Toast.makeText(ctx,
R.string.achievements_unavailable_beta,
Toast.LENGTH_LONG).show();
}
}
}
/**
* To invoke the AlertDialog on clicking info button
*/

View file

@ -6,6 +6,7 @@ import static fr.free.nrw.commons.profile.leaderboard.LeaderboardConstants.PAGE_
import static fr.free.nrw.commons.profile.leaderboard.LeaderboardConstants.START_OFFSET;
import android.accounts.Account;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
@ -29,6 +30,7 @@ import fr.free.nrw.commons.auth.SessionManager;
import fr.free.nrw.commons.di.CommonsDaggerSupportFragment;
import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient;
import fr.free.nrw.commons.profile.ProfileActivity;
import fr.free.nrw.commons.utils.ConfigUtils;
import fr.free.nrw.commons.utils.ViewUtil;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
@ -121,8 +123,16 @@ public class LeaderboardFragment extends CommonsDaggerSupportFragment {
View rootView = inflater.inflate(R.layout.fragment_leaderboard, container, false);
ButterKnife.bind(this, rootView);
progressBar.setVisibility(View.VISIBLE);
hideLayouts();
// Leaderboard currently unimplemented in Beta flavor. Skip all API calls and disable menu
if(ConfigUtils.isBetaFlavour()) {
progressBar.setVisibility(View.GONE);
scrollButton.setVisibility(View.GONE);
return rootView;
}
progressBar.setVisibility(View.VISIBLE);
setSpinners();
/**
@ -174,6 +184,27 @@ public class LeaderboardFragment extends CommonsDaggerSupportFragment {
return rootView;
}
@Override
public void setMenuVisibility(boolean visible) {
super.setMenuVisibility(visible);
// Whenever this fragment is revealed in a menu,
// notify Beta users the page data is unavailable
if(ConfigUtils.isBetaFlavour() && visible) {
Context ctx = null;
if(getContext() != null) {
ctx = getContext();
} else if(getView() != null && getView().getContext() != null) {
ctx = getView().getContext();
}
if(ctx != null) {
Toast.makeText(ctx,
R.string.leaderboard_unavailable_beta,
Toast.LENGTH_LONG).show();
}
}
}
/**
* Refreshes the leaderboard list
*/

View file

@ -686,4 +686,6 @@ Upload your first media by tapping on the add button.</string>
<string name="no_location_found_message">How about adding the place where this image was taken?\nLocation data helps Wiki editors find your picture, making it much more useful.\nThank you!</string>
<string name="add_location">Add location</string>
<string name="feedback_sharing_data_alert">Please remove from this email any information that you are not comfortable sharing publicly. Also, please be aware that your email address with which you are posting, and the associated name and profile picture, will be visible publicly.</string>
<string name="achievements_unavailable_beta">Achievements are only available in the prod flavor.</string>
<string name="leaderboard_unavailable_beta">The leaderboard is only available in the prod flavor.</string>
</resources>

View file

@ -4,6 +4,7 @@ import android.accounts.Account
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.ProgressBar
import android.widget.Spinner
@ -18,6 +19,7 @@ import fr.free.nrw.commons.profile.ProfileActivity
import fr.free.nrw.commons.profile.leaderboard.LeaderboardFragment
import fr.free.nrw.commons.profile.leaderboard.LeaderboardListAdapter
import fr.free.nrw.commons.profile.leaderboard.LeaderboardListViewModel
import fr.free.nrw.commons.utils.ConfigUtils.isBetaFlavour
import org.junit.Assert
import org.junit.Before
import org.junit.Test
@ -31,6 +33,7 @@ import org.robolectric.RobolectricTestRunner
import org.robolectric.RuntimeEnvironment
import org.robolectric.annotation.Config
import org.robolectric.annotation.LooperMode
import org.robolectric.shadows.ShadowToast
import org.wikipedia.AppAdapter
import java.lang.reflect.Method
@ -69,6 +72,9 @@ class LeaderboardFragmentUnitTests {
@Mock
private lateinit var button: Button
@Mock
private lateinit var parentView: ViewGroup
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
@ -93,6 +99,7 @@ class LeaderboardFragmentUnitTests {
Whitebox.setInternalState(fragment, "viewModel", viewModel)
Whitebox.setInternalState(fragment, "scrollButton", button)
Whitebox.setInternalState(fragment, "leaderboardListRecyclerView", recyclerView)
Whitebox.setInternalState(fragment, "mView", parentView)
}
@Test
@ -200,4 +207,29 @@ class LeaderboardFragmentUnitTests {
method.invoke(fragment)
}
@Test
@Throws(Exception::class)
fun testMenuVisibilityOverrideNotVisible() {
val method: Method = LeaderboardFragment::class.java.getDeclaredMethod(
"setMenuVisibility",
Boolean::class.java
)
method.isAccessible = true
method.invoke(fragment, false)
Assert.assertNull(ShadowToast.getLatestToast())
}
@Test
@Throws(Exception::class)
fun testMenuVisibilityOverrideVisibleWithContext() {
`when`(parentView.context).thenReturn(context)
val method: Method = LeaderboardFragment::class.java.getDeclaredMethod(
"setMenuVisibility",
Boolean::class.java
)
method.isAccessible = true
method.invoke(fragment, true)
Assert.assertEquals(ShadowToast.getTextOfLatestToast().toString(), context.getString(R.string.leaderboard_unavailable_beta))
}
}

View file

@ -2,13 +2,17 @@ package fr.free.nrw.commons.profile.achievements
import android.content.Context
import android.os.Looper
import android.view.LayoutInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.ProgressBar
import android.widget.TextView
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentTransaction
import com.dinuscxj.progressbar.CircleProgressBar
import fr.free.nrw.commons.R
import fr.free.nrw.commons.TestAppAdapter
import fr.free.nrw.commons.TestCommonsApplication
import fr.free.nrw.commons.auth.SessionManager
@ -28,6 +32,7 @@ import org.robolectric.Shadows
import org.robolectric.annotation.Config
import org.robolectric.annotation.LooperMode
import org.robolectric.fakes.RoboMenuItem
import org.robolectric.shadows.ShadowToast
import org.wikipedia.AppAdapter
import java.lang.reflect.Method
@ -45,6 +50,10 @@ class AchievementsFragmentUnitTests {
private lateinit var achievements: Achievements
private lateinit var view: View
private lateinit var layoutInflater: LayoutInflater
@Mock
private lateinit var imageView: ImageView
@ -90,6 +99,9 @@ class AchievementsFragmentUnitTests {
@Mock
private lateinit var sessionManager: SessionManager
@Mock
private lateinit var parentView: ViewGroup
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
@ -101,7 +113,11 @@ class AchievementsFragmentUnitTests {
val fragmentManager: FragmentManager = activity.supportFragmentManager
val fragmentTransaction: FragmentTransaction = fragmentManager.beginTransaction()
fragmentTransaction.add(fragment, null)
fragmentTransaction.commit()
fragmentTransaction.commitNowAllowingStateLoss()
layoutInflater = LayoutInflater.from(activity)
view = LayoutInflater.from(activity)
.inflate(R.layout.fragment_achievements, null) as View
achievements = Achievements(0, 0, 0, 0, 0, 0, 0)
@ -137,11 +153,18 @@ class AchievementsFragmentUnitTests {
Whitebox.setInternalState(fragment, "imagesRevertLimitText", imagesRevertLimitText)
Whitebox.setInternalState(fragment, "item", menuItem)
Whitebox.setInternalState(fragment, "sessionManager", sessionManager)
Whitebox.setInternalState(fragment, "mView", parentView)
Mockito.`when`(sessionManager.userName).thenReturn("Test")
}
@Test
@Throws(Exception::class)
fun testOnCreateView() {
fragment.onCreateView(layoutInflater, null, null)
}
@Test
@Throws(Exception::class)
fun checkFragmentNotNull() {
@ -326,4 +349,30 @@ class AchievementsFragmentUnitTests {
method.isAccessible = true
method.invoke(fragment)
}
@Test
@Throws(Exception::class)
fun testMenuVisibilityOverrideNotVisible() {
val method: Method = AchievementsFragment::class.java.getDeclaredMethod(
"setMenuVisibility",
Boolean::class.java
)
method.isAccessible = true
method.invoke(fragment, false)
Assert.assertNull(ShadowToast.getLatestToast())
}
@Test
@Throws(Exception::class)
fun testMenuVisibilityOverrideVisibleWithContext() {
Mockito.`when`(parentView.context).thenReturn(context)
val method: Method = AchievementsFragment::class.java.getDeclaredMethod(
"setMenuVisibility",
Boolean::class.java
)
method.isAccessible = true
method.invoke(fragment, true)
Assert.assertEquals(ShadowToast.getTextOfLatestToast().toString(), context.getString(R.string.achievements_unavailable_beta))
}
}