diff --git a/app/build.gradle b/app/build.gradle index c9395a5dd5..359f71246e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -219,7 +219,6 @@ dependencies { testImplementation 'junit:junit:4.12' - testImplementation "io.mockk:mockk:1.9.3" testImplementation 'org.threeten:threetenbp:1.4.0' testImplementation "org.koin:koin-test:$koin_version" testImplementation 'androidx.arch.core:core-testing:2.0.1' diff --git a/app/src/main/java/org/fossasia/openevent/general/MainActivity.kt b/app/src/main/java/org/fossasia/openevent/general/MainActivity.kt index 3dcd9cd2cd..55c81f049f 100644 --- a/app/src/main/java/org/fossasia/openevent/general/MainActivity.kt +++ b/app/src/main/java/org/fossasia/openevent/general/MainActivity.kt @@ -13,16 +13,13 @@ import org.fossasia.openevent.general.auth.RC_CREDENTIALS_READ import org.fossasia.openevent.general.auth.SmartAuthViewModel import org.fossasia.openevent.general.auth.SmartAuthUtil import org.fossasia.openevent.general.auth.AuthFragment +import org.fossasia.openevent.general.utils.AppLinkUtils import org.fossasia.openevent.general.utils.Utils.navAnimGone import org.fossasia.openevent.general.utils.Utils.navAnimVisible import org.jetbrains.anko.design.snackbar import org.koin.androidx.viewmodel.ext.android.viewModel const val PLAY_STORE_BUILD_FLAVOR = "playStore" -const val EVENT_IDENTIFIER = "eventIdentifier" -const val VERIFICATION_TOKEN = "verificationToken" -private const val VERIFY = "verify" -private const val TOKEN = "token" class MainActivity : AppCompatActivity() { private lateinit var navController: NavController @@ -43,26 +40,12 @@ class MainActivity : AppCompatActivity() { currentFragmentId = destination.id handleNavigationVisibility(currentFragmentId) } - handleAppLinkIntent(intent) + AppLinkUtils.handleIntent(intent, navController) } override fun onNewIntent(intent: Intent?) { super.onNewIntent(intent) - handleAppLinkIntent(intent) - } - - private fun handleAppLinkIntent(intent: Intent?) { - val appLinkData = intent?.data - if (appLinkData != null) { - val bundle = Bundle() - if (appLinkData.lastPathSegment == VERIFY) { - bundle.putString(VERIFICATION_TOKEN, appLinkData.getQueryParameter(TOKEN)) - navController.navigate(R.id.profileFragment, bundle) - } else { - bundle.putString(EVENT_IDENTIFIER, appLinkData.lastPathSegment) - navController.navigate(R.id.eventDetailsFragment, bundle) - } - } + AppLinkUtils.handleIntent(intent, navController) } private fun setupBottomNavigationMenu(navController: NavController) { diff --git a/app/src/main/java/org/fossasia/openevent/general/auth/AuthApi.kt b/app/src/main/java/org/fossasia/openevent/general/auth/AuthApi.kt index 7e5e7b891b..af1ef3b7da 100644 --- a/app/src/main/java/org/fossasia/openevent/general/auth/AuthApi.kt +++ b/app/src/main/java/org/fossasia/openevent/general/auth/AuthApi.kt @@ -43,4 +43,7 @@ interface AuthApi { @POST("auth/verify-email") fun verifyEmail(@Body requestEmailVerification: RequestEmailVerification): Single + + @PATCH("auth/reset-password") + fun resetPassword(@Body requestPasswordReset: RequestPasswordReset): Single } diff --git a/app/src/main/java/org/fossasia/openevent/general/auth/AuthFragment.kt b/app/src/main/java/org/fossasia/openevent/general/auth/AuthFragment.kt index a0243842b5..31265cf166 100644 --- a/app/src/main/java/org/fossasia/openevent/general/auth/AuthFragment.kt +++ b/app/src/main/java/org/fossasia/openevent/general/auth/AuthFragment.kt @@ -67,6 +67,11 @@ class AuthFragment : Fragment(), ComplexBackPressFragment { val snackbarMessage = safeArgs.snackbarMessage if (!snackbarMessage.isNullOrEmpty()) rootView.snackbar(snackbarMessage) + val email = safeArgs.email + if (email != null) { + rootView.email.setText(email) + } + rootView.skipTextView.isVisible = safeArgs.showSkipButton rootView.skipTextView.setOnClickListener { findNavController(rootView).navigate( @@ -83,7 +88,6 @@ class AuthFragment : Fragment(), ComplexBackPressFragment { authViewModel.checkUser(rootView.email.text.toString()) } - rootView.email.setText(safeArgs.email) rootView.email.addTextChangedListener(object : TextWatcher { override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { /*Do Nothing*/ } override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { /*Do Nothing*/ } diff --git a/app/src/main/java/org/fossasia/openevent/general/auth/AuthService.kt b/app/src/main/java/org/fossasia/openevent/general/auth/AuthService.kt index f2a149dfaa..3a6bb69fe6 100644 --- a/app/src/main/java/org/fossasia/openevent/general/auth/AuthService.kt +++ b/app/src/main/java/org/fossasia/openevent/general/auth/AuthService.kt @@ -105,4 +105,8 @@ class AuthService( fun verifyEmail(token: String): Single { return authApi.verifyEmail(RequestEmailVerification(Token(token))) } + + fun resetPassword(requestPasswordReset: RequestPasswordReset): Single { + return authApi.resetPassword(requestPasswordReset) + } } diff --git a/app/src/main/java/org/fossasia/openevent/general/auth/ProfileFragment.kt b/app/src/main/java/org/fossasia/openevent/general/auth/ProfileFragment.kt index a330857e0e..1d8f48ea72 100644 --- a/app/src/main/java/org/fossasia/openevent/general/auth/ProfileFragment.kt +++ b/app/src/main/java/org/fossasia/openevent/general/auth/ProfileFragment.kt @@ -40,7 +40,7 @@ import org.fossasia.openevent.general.CircleTransform import org.fossasia.openevent.general.PLAY_STORE_BUILD_FLAVOR import org.fossasia.openevent.general.R import org.fossasia.openevent.general.BottomIconDoubleClick -import org.fossasia.openevent.general.VERIFICATION_TOKEN +import org.fossasia.openevent.general.utils.VERIFICATION_TOKEN import org.fossasia.openevent.general.utils.Utils import org.fossasia.openevent.general.utils.Utils.requireDrawable import org.fossasia.openevent.general.utils.extensions.nonNull diff --git a/app/src/main/java/org/fossasia/openevent/general/auth/RequestPasswordReset.kt b/app/src/main/java/org/fossasia/openevent/general/auth/RequestPasswordReset.kt new file mode 100644 index 0000000000..f0da1c1317 --- /dev/null +++ b/app/src/main/java/org/fossasia/openevent/general/auth/RequestPasswordReset.kt @@ -0,0 +1,7 @@ +package org.fossasia.openevent.general.auth + +import org.fossasia.openevent.general.auth.forgot.PasswordReset + +class RequestPasswordReset( + val data: PasswordReset +) diff --git a/app/src/main/java/org/fossasia/openevent/general/auth/ResetPasswordResponse.kt b/app/src/main/java/org/fossasia/openevent/general/auth/ResetPasswordResponse.kt new file mode 100644 index 0000000000..3cc1e14aac --- /dev/null +++ b/app/src/main/java/org/fossasia/openevent/general/auth/ResetPasswordResponse.kt @@ -0,0 +1,11 @@ +package org.fossasia.openevent.general.auth + +import com.github.jasminb.jsonapi.LongIdHandler +import com.github.jasminb.jsonapi.annotations.Id + +class ResetPasswordResponse( + @Id(LongIdHandler::class) + val id: Long? = null, + val email: String? = null, + val name: String? = null +) diff --git a/app/src/main/java/org/fossasia/openevent/general/auth/forgot/PasswordReset.kt b/app/src/main/java/org/fossasia/openevent/general/auth/forgot/PasswordReset.kt new file mode 100644 index 0000000000..929ca2e1d0 --- /dev/null +++ b/app/src/main/java/org/fossasia/openevent/general/auth/forgot/PasswordReset.kt @@ -0,0 +1,6 @@ +package org.fossasia.openevent.general.auth.forgot + +class PasswordReset( + val token: String, + val password: String +) diff --git a/app/src/main/java/org/fossasia/openevent/general/di/Modules.kt b/app/src/main/java/org/fossasia/openevent/general/di/Modules.kt index d1f4a88b9e..8b909b7906 100644 --- a/app/src/main/java/org/fossasia/openevent/general/di/Modules.kt +++ b/app/src/main/java/org/fossasia/openevent/general/di/Modules.kt @@ -212,7 +212,7 @@ val apiModule = module { val viewModelModule = module { viewModel { LoginViewModel(get(), get(), get()) } - viewModel { EventsViewModel(get(), get(), get(), get(), get(), get(), get()) } + viewModel { EventsViewModel(get(), get(), get(), get(), get(), get(), get(), get()) } viewModel { ProfileViewModel(get(), get()) } viewModel { SignUpViewModel(get(), get(), get()) } viewModel { diff --git a/app/src/main/java/org/fossasia/openevent/general/event/EventDetailsFragment.kt b/app/src/main/java/org/fossasia/openevent/general/event/EventDetailsFragment.kt index 9c2a4c313f..e16bed3d81 100644 --- a/app/src/main/java/org/fossasia/openevent/general/event/EventDetailsFragment.kt +++ b/app/src/main/java/org/fossasia/openevent/general/event/EventDetailsFragment.kt @@ -63,7 +63,7 @@ import kotlinx.android.synthetic.main.content_fetching_event_error.view.retry import kotlinx.android.synthetic.main.dialog_feedback.view.feedback import kotlinx.android.synthetic.main.dialog_feedback.view.feedbackTextInputLayout import kotlinx.android.synthetic.main.dialog_feedback.view.feedbackrating -import org.fossasia.openevent.general.EVENT_IDENTIFIER +import org.fossasia.openevent.general.utils.EVENT_IDENTIFIER import org.fossasia.openevent.general.R import org.fossasia.openevent.general.common.SessionClickListener import org.fossasia.openevent.general.common.SpeakerClickListener diff --git a/app/src/main/java/org/fossasia/openevent/general/event/EventsFragment.kt b/app/src/main/java/org/fossasia/openevent/general/event/EventsFragment.kt index 584ca50531..e30759aae1 100644 --- a/app/src/main/java/org/fossasia/openevent/general/event/EventsFragment.kt +++ b/app/src/main/java/org/fossasia/openevent/general/event/EventsFragment.kt @@ -2,10 +2,13 @@ package org.fossasia.openevent.general.event import android.graphics.Color import android.os.Bundle +import android.text.Editable +import android.text.TextWatcher import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.ImageView +import androidx.appcompat.app.AlertDialog import androidx.core.view.isVisible import androidx.core.widget.NestedScrollView import androidx.fragment.app.Fragment @@ -15,6 +18,10 @@ import androidx.navigation.Navigation.findNavController import androidx.navigation.fragment.FragmentNavigatorExtras import kotlinx.android.synthetic.main.content_no_internet.view.noInternetCard import kotlinx.android.synthetic.main.content_no_internet.view.retry +import kotlinx.android.synthetic.main.dialog_reset_password.view.confirmNewPassword +import kotlinx.android.synthetic.main.dialog_reset_password.view.newPassword +import kotlinx.android.synthetic.main.dialog_reset_password.view.textInputLayoutConfirmNewPassword +import kotlinx.android.synthetic.main.dialog_reset_password.view.textInputLayoutNewPassword import kotlinx.android.synthetic.main.fragment_events.view.eventsRecycler import kotlinx.android.synthetic.main.fragment_events.view.locationTextView import kotlinx.android.synthetic.main.fragment_events.view.shimmerEvents @@ -30,6 +37,7 @@ import kotlinx.android.synthetic.main.fragment_events.view.newNotificationDotToo import kotlinx.android.synthetic.main.fragment_events.view.notificationToolbar import org.fossasia.openevent.general.R import org.fossasia.openevent.general.BottomIconDoubleClick +import org.fossasia.openevent.general.utils.RESET_PASSWORD_TOKEN import org.fossasia.openevent.general.common.EventClickListener import org.fossasia.openevent.general.common.FavoriteFabClickListener import org.fossasia.openevent.general.data.Preference @@ -37,6 +45,8 @@ import org.fossasia.openevent.general.search.location.SAVED_LOCATION import org.fossasia.openevent.general.utils.extensions.nonNull import org.koin.androidx.viewmodel.ext.android.viewModel import org.fossasia.openevent.general.utils.Utils.setToolbar +import org.fossasia.openevent.general.utils.Utils.progressDialog +import org.fossasia.openevent.general.utils.Utils.show import org.fossasia.openevent.general.utils.extensions.setPostponeSharedElementTransition import org.fossasia.openevent.general.utils.extensions.setStartPostponedEnterTransition import org.fossasia.openevent.general.utils.extensions.hideWithFading @@ -44,6 +54,7 @@ import org.fossasia.openevent.general.utils.extensions.showWithFading import org.jetbrains.anko.design.longSnackbar const val BEEN_TO_WELCOME_SCREEN = "beenToWelcomeScreen" +private const val EVENTS_FRAGMENT = "eventsFragment" class EventsFragment : Fragment(), BottomIconDoubleClick { private val eventsViewModel by viewModel() @@ -65,6 +76,26 @@ class EventsFragment : Fragment(), BottomIconDoubleClick { } setToolbar(activity, show = false) + val progressDialog = progressDialog(context, getString(R.string.loading_message)) + + val token = arguments?.getString(RESET_PASSWORD_TOKEN) + if (token != null) + showResetPasswordAlertDialog(token) + + eventsViewModel.resetPasswordEmail + .nonNull() + .observe(viewLifecycleOwner, Observer { + findNavController(rootView).navigate( + EventsFragmentDirections.actionEventsToAuth(email = it, redirectedFrom = EVENTS_FRAGMENT) + ) + }) + + eventsViewModel.dialogProgress + .nonNull() + .observe(viewLifecycleOwner, Observer { + progressDialog.show(it) + }) + rootView.eventsRecycler.layoutManager = GridLayoutManager(activity, resources.getInteger(R.integer.events_column_count)) @@ -101,7 +132,7 @@ class EventsFragment : Fragment(), BottomIconDoubleClick { rootView.shimmerEvents.isVisible = it }) - eventsViewModel.error + eventsViewModel.message .nonNull() .observe(viewLifecycleOwner, Observer { rootView.longSnackbar(it) @@ -255,5 +286,86 @@ class EventsFragment : Fragment(), BottomIconDoubleClick { rootView.eventsEmptyView.isVisible = show } + private fun showResetPasswordAlertDialog(token: String) { + val layout = layoutInflater.inflate(R.layout.dialog_reset_password, null) + + val alertDialog = AlertDialog.Builder(requireContext()) + .setTitle(getString(R.string.title_change_password)) + .setView(layout) + .setPositiveButton(getString(R.string.change)) { _, _ -> + eventsViewModel.checkAndReset(token, layout.newPassword.text.toString()) + } + .setNegativeButton(getString(R.string.cancel)) { dialog, _ -> + dialog.cancel() + } + .setCancelable(false) + .show() + alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).isEnabled = false + + layout.newPassword.addTextChangedListener(object : TextWatcher { + override fun afterTextChanged(p0: Editable?) { + + /* to make PasswordToggle visible again, if made invisible + after empty field error + */ + if (!layout.textInputLayoutNewPassword.isEndIconVisible) { + layout.textInputLayoutNewPassword.isEndIconVisible = true + } + + if (layout.newPassword.text.toString().length >= 8) { + layout.textInputLayoutNewPassword.error = null + layout.textInputLayoutNewPassword.isErrorEnabled = false + } else { + layout.textInputLayoutNewPassword.error = getString(R.string.invalid_password_message) + } + if (layout.confirmNewPassword.text.toString() == layout.newPassword.text.toString()) { + layout.textInputLayoutConfirmNewPassword.error = null + layout.textInputLayoutConfirmNewPassword.isErrorEnabled = false + } else { + layout.textInputLayoutConfirmNewPassword.error = + getString(R.string.invalid_confirm_password_message) + } + when (layout.textInputLayoutConfirmNewPassword.isErrorEnabled || + layout.textInputLayoutNewPassword.isErrorEnabled) { + true -> alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).isEnabled = false + false -> alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).isEnabled = true + } + } + + override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) { /*Implement here*/ } + + override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) { /*Implement here*/ } + }) + + layout.confirmNewPassword.addTextChangedListener(object : TextWatcher { + override fun afterTextChanged(p0: Editable?) { + + /* to make PasswordToggle visible again, if made invisible + after empty field error + */ + if (!layout.textInputLayoutConfirmNewPassword.isEndIconVisible) { + layout.textInputLayoutConfirmNewPassword.isEndIconVisible = true + } + + if (layout.confirmNewPassword.text.toString() == layout.newPassword.text.toString()) { + layout.textInputLayoutConfirmNewPassword.error = null + layout.textInputLayoutConfirmNewPassword.isErrorEnabled = false + } else { + layout.textInputLayoutConfirmNewPassword.error = + getString(R.string.invalid_confirm_password_message) + } + when (layout.textInputLayoutConfirmNewPassword.isErrorEnabled || + layout.textInputLayoutNewPassword.isErrorEnabled) { + true -> alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).isEnabled = false + false -> alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).isEnabled = true + } + } + + override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) { /*Implement here*/ } + + override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) { /*Implement here*/ } + }) + } + override fun doubleClick() = rootView.scrollView.smoothScrollTo(0, 0) } diff --git a/app/src/main/java/org/fossasia/openevent/general/event/EventsViewModel.kt b/app/src/main/java/org/fossasia/openevent/general/event/EventsViewModel.kt index c3ac3c4b6a..814886e2b1 100644 --- a/app/src/main/java/org/fossasia/openevent/general/event/EventsViewModel.kt +++ b/app/src/main/java/org/fossasia/openevent/general/event/EventsViewModel.kt @@ -12,6 +12,9 @@ import io.reactivex.rxkotlin.plusAssign import io.reactivex.schedulers.Schedulers import org.fossasia.openevent.general.R import org.fossasia.openevent.general.auth.AuthHolder +import org.fossasia.openevent.general.auth.AuthService +import org.fossasia.openevent.general.auth.RequestPasswordReset +import org.fossasia.openevent.general.auth.forgot.PasswordReset import org.fossasia.openevent.general.common.SingleLiveEvent import org.fossasia.openevent.general.connectivity.MutableConnectionLiveData import org.fossasia.openevent.general.data.Preference @@ -30,6 +33,7 @@ class EventsViewModel( private val resource: Resource, private val mutableConnectionLiveData: MutableConnectionLiveData, private val authHolder: AuthHolder, + private val authService: AuthService, private val notificationService: NotificationService, private val config: PagedList.Config ) : ViewModel() { @@ -41,14 +45,18 @@ class EventsViewModel( val newNotifications: LiveData = mutableNewNotifications private val mutableProgress = MediatorLiveData() val progress: MediatorLiveData = mutableProgress + private val mutableDialogProgress = MutableLiveData() + val dialogProgress: LiveData = mutableDialogProgress private val mutablePagedEvents = MutableLiveData>() val pagedEvents: LiveData> = mutablePagedEvents - private val mutableError = SingleLiveEvent() - val error: LiveData = mutableError + private val mutableMessage = SingleLiveEvent() + val message: LiveData = mutableMessage var lastSearch = "" private val mutableSavedLocation = MutableLiveData() val savedLocation: LiveData = mutableSavedLocation private lateinit var sourceFactory: EventsDataSourceFactory + private val mutableResetPasswordEmail = MutableLiveData() + val resetPasswordEmail: LiveData = mutableResetPasswordEmail fun isLoggedIn() = authHolder.isLoggedIn() @@ -89,7 +97,7 @@ class EventsViewModel( } }, { Timber.e(it, "Error fetching events") - mutableError.value = resource.getString(R.string.error_fetching_events_message) + mutableMessage.value = resource.getString(R.string.error_fetching_events_message) }) } fun isConnected(): Boolean = mutableConnectionLiveData.value ?: false @@ -109,7 +117,7 @@ class EventsViewModel( Timber.d("Success") }, { Timber.e(it, "Error") - mutableError.value = resource.getString(R.string.error) + mutableMessage.value = resource.getString(R.string.error) }) } @@ -130,6 +138,36 @@ class EventsViewModel( }) } + fun checkAndReset(token: String, newPassword: String) { + val resetRequest = RequestPasswordReset(PasswordReset(token, newPassword)) + if (authHolder.isLoggedIn()) { + compositeDisposable += authService.logout() + .withDefaultSchedulers() + .doOnSubscribe { + mutableDialogProgress.value = true + }.subscribe { + resetPassword(resetRequest) + } + } else + resetPassword(resetRequest) + } + + private fun resetPassword(resetRequest: RequestPasswordReset) { + compositeDisposable += authService.resetPassword(resetRequest) + .withDefaultSchedulers() + .doOnSubscribe { + mutableDialogProgress.value = true + }.doFinally { + mutableDialogProgress.value = false + }.subscribe({ + Timber.e(it.toString()) + mutableMessage.value = resource.getString(R.string.reset_password_message) + mutableResetPasswordEmail.value = it.email + }, { + Timber.e(it, "Failed to reset password") + }) + } + override fun onCleared() { super.onCleared() compositeDisposable.clear() diff --git a/app/src/main/java/org/fossasia/openevent/general/utils/AppLinkData.kt b/app/src/main/java/org/fossasia/openevent/general/utils/AppLinkData.kt new file mode 100644 index 0000000000..3e5c76fe99 --- /dev/null +++ b/app/src/main/java/org/fossasia/openevent/general/utils/AppLinkData.kt @@ -0,0 +1,7 @@ +package org.fossasia.openevent.general.utils + +class AppLinkData ( + val destinationId: Int, + val argumentKey: String, + val argumentValue: String +) diff --git a/app/src/main/java/org/fossasia/openevent/general/utils/AppLinkUtils.kt b/app/src/main/java/org/fossasia/openevent/general/utils/AppLinkUtils.kt new file mode 100644 index 0000000000..26b346ae68 --- /dev/null +++ b/app/src/main/java/org/fossasia/openevent/general/utils/AppLinkUtils.kt @@ -0,0 +1,33 @@ +package org.fossasia.openevent.general.utils + +import android.content.Intent +import android.os.Bundle +import androidx.navigation.NavController +import org.fossasia.openevent.general.R + +const val EVENT_IDENTIFIER = "eventIdentifier" +const val VERIFICATION_TOKEN = "verificationToken" +const val RESET_PASSWORD_TOKEN = "resetPasswordToken" +private const val SEGMENT_VERIFY = "verify" +private const val SEGMENT_RESET_PASSWORD = "reset-password" +private const val SEGMENT_EVENT = "e" + +object AppLinkUtils { + fun getData(uri: String): AppLinkData? { + val value = uri.split("/", "?", "=").last() + return when (uri.split("/", "?", "=")[3]) { + SEGMENT_EVENT -> AppLinkData(R.id.eventDetailsFragment, EVENT_IDENTIFIER, value) + SEGMENT_VERIFY -> AppLinkData(R.id.profileFragment, VERIFICATION_TOKEN, value) + SEGMENT_RESET_PASSWORD -> AppLinkData(R.id.eventsFragment, RESET_PASSWORD_TOKEN, value) + else -> null + } + } + + fun handleIntent(intent: Intent?, navController: NavController) { + val uri = intent?.data.toString() + val data = getData(uri) ?: return + val bundle = Bundle() + bundle.putString(data.argumentKey, data.argumentValue) + navController.navigate(data.destinationId, bundle) + } +} diff --git a/app/src/main/res/layout/dialog_reset_password.xml b/app/src/main/res/layout/dialog_reset_password.xml new file mode 100644 index 0000000000..1b81da35bc --- /dev/null +++ b/app/src/main/res/layout/dialog_reset_password.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + diff --git a/app/src/main/res/navigation/navigation_graph.xml b/app/src/main/res/navigation/navigation_graph.xml index 52eec99f66..c5fa71cbe3 100644 --- a/app/src/main/res/navigation/navigation_graph.xml +++ b/app/src/main/res/navigation/navigation_graph.xml @@ -59,6 +59,13 @@ app:popExitAnim="@anim/slide_out_right" app:enterAnim="@anim/slide_in_right" app:exitAnim="@anim/slide_out_left"/> + + android:defaultValue="''"/> + android:defaultValue="''"/> + android:defaultValue="''"/> + app:nullable="true" + android:defaultValue="@null"/> Likes savedDate Enter a location + Reset password successfully, Please log in to continue Event Date : diff --git a/app/src/test/java/org/fossasia/openevent/general/AppLinkUtilsTest.kt b/app/src/test/java/org/fossasia/openevent/general/AppLinkUtilsTest.kt new file mode 100644 index 0000000000..bd86b6755f --- /dev/null +++ b/app/src/test/java/org/fossasia/openevent/general/AppLinkUtilsTest.kt @@ -0,0 +1,54 @@ +package org.fossasia.openevent.general + +import org.fossasia.openevent.general.utils.EVENT_IDENTIFIER +import org.fossasia.openevent.general.utils.RESET_PASSWORD_TOKEN +import org.fossasia.openevent.general.utils.AppLinkUtils +import org.fossasia.openevent.general.utils.VERIFICATION_TOKEN +import org.junit.Test +import org.junit.Assert.assertEquals + +private const val EVENT = "event" +private const val RESET_PASSWORD = "resetPassword" +private const val VERIFY_EMAIL = "verifyEmail" + +class AppLinkUtilsTest { + + private fun getAppLink(type: String): String { + return when (type) { + EVENT -> "https://eventyay.com/e/5f6d3feb" + RESET_PASSWORD -> "https://eventyay.com/reset-password?token=822980340478781748445098077144" + VERIFY_EMAIL -> "https://eventyay.com/verify?token=WyJsaXZlLmhhcnNoaXRAaG" + else -> "" + } + } + + @Test + fun `should get event link`() { + val uri = getAppLink(EVENT) + assertEquals(R.id.eventDetailsFragment, AppLinkUtils.getData(uri)?.destinationId) + assertEquals(EVENT_IDENTIFIER, AppLinkUtils.getData(uri)?.argumentKey) + assertEquals(""" + 5f6d3feb + """.trimIndent(), AppLinkUtils.getData(uri)?.argumentValue) + } + + @Test + fun `should get reset password link`() { + val uri = getAppLink(RESET_PASSWORD) + assertEquals(R.id.eventsFragment, AppLinkUtils.getData(uri)?.destinationId) + assertEquals(RESET_PASSWORD_TOKEN, AppLinkUtils.getData(uri)?.argumentKey) + assertEquals(""" + 822980340478781748445098077144 + """.trimIndent(), AppLinkUtils.getData(uri)?.argumentValue) + } + + @Test + fun `should get verify email link`() { + val uri = getAppLink(VERIFY_EMAIL) + assertEquals(R.id.profileFragment, AppLinkUtils.getData(uri)?.destinationId) + assertEquals(VERIFICATION_TOKEN, AppLinkUtils.getData(uri)?.argumentKey) + assertEquals(""" + WyJsaXZlLmhhcnNoaXRAaG + """.trimIndent(), AppLinkUtils.getData(uri)?.argumentValue) + } +} diff --git a/app/src/test/java/org/fossasia/openevent/general/event/EventUtilsTest.kt b/app/src/test/java/org/fossasia/openevent/general/event/EventUtilsTest.kt index 92d351658d..2fe0f57953 100644 --- a/app/src/test/java/org/fossasia/openevent/general/event/EventUtilsTest.kt +++ b/app/src/test/java/org/fossasia/openevent/general/event/EventUtilsTest.kt @@ -1,10 +1,5 @@ package org.fossasia.openevent.general.event -import io.mockk.MockKAnnotations -import io.mockk.every -import io.mockk.impl.annotations.MockK -import org.fossasia.openevent.general.R -import org.fossasia.openevent.general.data.Resource import org.junit.After import org.junit.Assert.assertEquals import org.junit.Before @@ -15,9 +10,6 @@ import java.util.TimeZone class EventUtilsTest { - @MockK - lateinit var resource: Resource - private var timeZone: TimeZone? = null @Before @@ -25,7 +17,6 @@ class EventUtilsTest { // Set fixed local time zone for tests timeZone = TimeZone.getDefault() TimeZone.setDefault(TimeZone.getTimeZone(ZoneId.of("Asia/Kolkata"))) - MockKAnnotations.init(this) } @After @@ -50,17 +41,6 @@ class EventUtilsTest { private fun getEventDateTime(dateTime: String, timeZone: String): ZonedDateTime = EventUtils.getEventDateTime(dateTime, timeZone) - private fun setupStringMock() { - every { resource.getString(R.string.event_name) }.returns("Event Name : ") - every { resource.getString(R.string.event_description) }.returns("Event Description : ") - every { resource.getString(R.string.starts_on) }.returns("Starts On : ") - every { resource.getString(R.string.start_time) }.returns("Start Time : ") - every { resource.getString(R.string.ends_on) }.returns("Ends On : ") - every { resource.getString(R.string.end_time) }.returns("End Time : ") - every { resource.getString(R.string.event_location) }.returns("Event Location : ") - every { resource.getString(R.string.event_link) }.returns("Event Link : ") - } - @Test fun `should get timezone name`() { val event = getEvent()