From 1405300fd5c12847b9d8836943ff95a2d004f3dd Mon Sep 17 00:00:00 2001
From: Jacob Fano <46112489+KosOrKosm@users.noreply.github.com>
Date: Wed, 23 Feb 2022 21:40:51 -0800
Subject: [PATCH] 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
---
.../achievements/AchievementsFragment.java | 38 ++++++++++++++
.../leaderboard/LeaderboardFragment.java | 33 +++++++++++-
app/src/main/res/values/strings.xml | 2 +
.../LeaderboardFragmentUnitTests.kt | 32 ++++++++++++
.../AchievementsFragmentUnitTests.kt | 51 ++++++++++++++++++-
5 files changed, 154 insertions(+), 2 deletions(-)
diff --git a/app/src/main/java/fr/free/nrw/commons/profile/achievements/AchievementsFragment.java b/app/src/main/java/fr/free/nrw/commons/profile/achievements/AchievementsFragment.java
index 7f4b10c69..51371da44 100644
--- a/app/src/main/java/fr/free/nrw/commons/profile/achievements/AchievementsFragment.java
+++ b/app/src/main/java/fr/free/nrw/commons/profile/achievements/AchievementsFragment.java
@@ -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
*/
diff --git a/app/src/main/java/fr/free/nrw/commons/profile/leaderboard/LeaderboardFragment.java b/app/src/main/java/fr/free/nrw/commons/profile/leaderboard/LeaderboardFragment.java
index 0cd6f41d3..6705f408c 100644
--- a/app/src/main/java/fr/free/nrw/commons/profile/leaderboard/LeaderboardFragment.java
+++ b/app/src/main/java/fr/free/nrw/commons/profile/leaderboard/LeaderboardFragment.java
@@ -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
*/
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 2b4e4215e..7df28eb75 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -686,4 +686,6 @@ Upload your first media by tapping on the add button.
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!
Add location
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.
+ Achievements are only available in the prod flavor.
+ The leaderboard is only available in the prod flavor.
diff --git a/app/src/test/kotlin/fr/free/nrw/commons/leaderboard/LeaderboardFragmentUnitTests.kt b/app/src/test/kotlin/fr/free/nrw/commons/leaderboard/LeaderboardFragmentUnitTests.kt
index 27c1f8f08..1adf5b7d0 100644
--- a/app/src/test/kotlin/fr/free/nrw/commons/leaderboard/LeaderboardFragmentUnitTests.kt
+++ b/app/src/test/kotlin/fr/free/nrw/commons/leaderboard/LeaderboardFragmentUnitTests.kt
@@ -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))
+ }
+
}
\ No newline at end of file
diff --git a/app/src/test/kotlin/fr/free/nrw/commons/profile/achievements/AchievementsFragmentUnitTests.kt b/app/src/test/kotlin/fr/free/nrw/commons/profile/achievements/AchievementsFragmentUnitTests.kt
index 96d99061c..3e6b0f1cf 100644
--- a/app/src/test/kotlin/fr/free/nrw/commons/profile/achievements/AchievementsFragmentUnitTests.kt
+++ b/app/src/test/kotlin/fr/free/nrw/commons/profile/achievements/AchievementsFragmentUnitTests.kt
@@ -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))
+ }
+
}
\ No newline at end of file