8000 NT-1549 : Choose another reward flow by Arkariang · Pull Request #993 · kickstarter/android-oss · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

NT-1549 : Choose another reward flow #993

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 25, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import com.kickstarter.libs.KSString
import com.kickstarter.libs.rx.transformers.Transformers.combineLatestPair
import com.kickstarter.libs.rx.transformers.Transformers.takeWhen
import com.kickstarter.libs.utils.ObjectUtils
import com.kickstarter.libs.utils.RewardUtils
import com.kickstarter.libs.utils.RewardUtils.isDigital
import com.kickstarter.libs.utils.RewardUtils.isShippable
import com.kickstarter.mock.factories.ShippingRuleFactory
Expand Down Expand Up @@ -136,6 +135,17 @@ class BackingAddOnsFragmentViewModel {
.filter { ObjectUtils.isNotNull(it) }
.map { requireNotNull(it) }

val isSameReward = rewardPledge
.compose<Pair<Reward, Reward>>(combineLatestPair(backingReward))
.map { it.first.id() == it.second.id() }

isSameReward
.filter { !it }
.compose(bindToLifecycle())
.subscribe {
this.currentSelection.clear()
}

val reward = Observable.merge(rewardPledge, backingReward)

projectAndReward = project
Expand All @@ -159,23 +169,30 @@ class BackingAddOnsFragmentViewModel {

// - In case of digital Reward to follow the same flow as the rest of use cases use and empty shippingRule
reward
.filter { isDigital(it) }
.filter { isDigital(it) || !isShippable(it)}
.distinctUntilChanged()
.compose(bindToLifecycle())
.subscribe {
this.shippingSelectorIsGone.onNext(true)
this.shippingRuleSelected.onNext(ShippingRuleFactory.emptyShippingRule())
}

val addOnsFromBacking = backing
.compose<Pair<Backing, Boolean>>(combineLatestPair(isSameReward))
.filter { it.second }
.map { it.first }
.map { it.addOns()?.toList() }
.filter { ObjectUtils.isNotNull(it) }
.map { requireNotNull(it) }
.distinctUntilChanged()

val combinedList = addOnsFromBacking
.compose<Pair<List<Reward>, List<Reward>>>(combineLatestPair(addOnsFromGraph))
.map { joinSelectedWithAvailableAddOns(it.first, it.second) }
.distinctUntilChanged()

val addonsList = Observable.merge(addOnsFromGraph, combinedList)
.distinctUntilChanged()

shippingRules
.compose<Pair<List<ShippingRule>, Project>>(combineLatestPair(project))
Expand Down Expand Up @@ -203,7 +220,6 @@ class BackingAddOnsFragmentViewModel {
.compose(bindToLifecycle())
.subscribe {
shippingRules.onNext(it)
this.shippingSelectorIsGone.onNext(false)
}

Observable
Expand Down Expand Up @@ -240,11 +256,6 @@ class BackingAddOnsFragmentViewModel {
.compose(bindToLifecycle())
.subscribe(this.isEmptyState)

reward
.map { !isShippable(it) }
.compose(bindToLifecycle())
.subscribe(this.shippingSelectorIsGone)

this.quantityPerId
.compose<Pair<Pair<Int, Long>, Triple<ProjectData, List<Reward>, ShippingRule>>>(combineLatestPair(this.addOnsListFiltered))
.compose(bindToLifecycle())
Expand All @@ -253,9 +264,14 @@ class BackingAddOnsFragmentViewModel {
updateQuantityById(it.first)
this.totalSelectedAddOns.onNext(calculateTotal(it.second.second))
}

// - this.quantityPerId.startWith(Pair(-1,-1L) because we need to trigger this validation everytime the AddOns selection changes
val isButtonEnabled = Observable.combineLatest(backingShippingRule, addOnsFromBacking, this.shippingRuleSelected, this.quantityPerId.startWith(Pair(-1, -1L))) { backedRule, backedList, actualRule, _ ->
// - .startWith(Pair(-1,-1L) because we need to trigger this validation everytime the AddOns selection changes
// - .startWith(ShippingRuleFactory.emptyShippingRule()) because we need to trigger this validation every time the AddOns selection changes for digital rewards as well
val isButtonEnabled = Observable.combineLatest(
backingShippingRule.startWith(ShippingRuleFactory.emptyShippingRule()),
addOnsFromBacking,
this.shippingRuleSelected,
this.quantityPerId.startWith(Pair(0, 0L))) {
backedRule, backedList, actualRule, _ ->
return@combineLatest isDifferentLocation(backedRule, actualRule) || isDifferentSelection(backedList)
}
.distinctUntilChanged()
Expand Down Expand Up @@ -301,14 +317,36 @@ class BackingAddOnsFragmentViewModel {
}
}

/**
* Extract the ID:quantity from the original baked AddOns list
* in case the ID's of those addOns and the quantity are the same
* as the current selected ones the selection is the same as the
* backed one.
*
* @param backedList -> addOns list from backing object
* @return Boolean -> true in case different selection or new item selected false otherwise
*/
private fun isDifferentSelection(backedList: List<Reward>): Boolean {

val backedSelection: MutableMap<Long, Int> = mutableMapOf()
backedList
.map {
backedSelection.put(it.id(), it.quantity() ?: 0)
}

return backedSelection != this.currentSelection
val isBackedItemList = this.currentSelection.map { item ->
if (backedSelection.containsKey(item.key)) backedSelection[item.key] == item.value
else false
}

val isNewItemSelected = this.currentSelection.map { item ->
if (!backedSelection.containsKey(item.key)) item.value > 0
else false
}.any { it }

val sameSelection = isBackedItemList.filter { it }.size == backedSelection.size

return !sameSelection || isNewItemSelected
}

private fun isDifferentLocation(backedRule: ShippingRule, actualRule: ShippingRule) =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ class BackingAddOnsFragmentViewModelTest : KSRobolectricTestCase() {
bundle.putSerializable(ArgumentsKey.PLEDGE_PLEDGE_REASON, PledgeReason.PLEDGE)
this.vm.arguments(bundle)

this.shippingSelectorIsGone.assertValues(false, true)
this.shippingSelectorIsGone.assertValues(true)

this.lakeTest.assertValue("Add-Ons Page Viewed")
}
Expand Down Expand Up @@ -411,7 +411,7 @@ class BackingAddOnsFragmentViewModelTest : KSRobolectricTestCase() {
bundle.putSerializable(ArgumentsKey.PLEDGE_PLEDGE_REASON, PledgeReason.PLEDGE)
this.vm.arguments(bundle)

this.shippingSelectorIsGone.assertValues(false, true)
this.shippingSelectorIsGone.assertValues(true)

this.lakeTest.assertValue("Add-Ons Page Viewed")
}
Expand Down Expand Up @@ -656,6 +656,72 @@ class BackingAddOnsFragmentViewModelTest : KSRobolectricTestCase() {
this.lakeTest.assertValues("Add-Ons Page Viewed", "Add-Ons Continue Button Clicked")
}

@Test
fun givenBackedAddOns_whenUpdatingRewardChooseAnotherReward_AddOnsListNotBacked() {
val shippingRule = ShippingRulesEnvelopeFactory.shippingRules()

val addOn = RewardFactory.addOn().toBuilder()
.shippingRules(shippingRule.shippingRules())
.shippingPreferenceType(Reward.ShippingPreference.UNRESTRICTED) // - Reward from GraphQL use this field
.build()
val addOn2 = addOn.toBuilder().id(8).build()
val addOn3 = addOn.toBuilder().id(99).build()

val listAddons = listOf(addOn, addOn2, addOn3)
val listAddonsBacked = listOf(addOn2.toBuilder().quantity(2).build(), addOn3.toBuilder().quantity(1).build())

val config = ConfigFactory.configForUSUser()
val currentConfig = MockCurrentConfig()
currentConfig.config(config)

setUpEnvironment(buildEnvironmentWith(listAddons, shippingRule, currentConfig))

val backedRw = RewardFactory.rewardHasAddOns().toBuilder()
.shippingType(Reward.ShippingPreference.UNRESTRICTED.name.toLowerCase())
.shippingRules(shippingRule.shippingRules())
.shippingPreferenceType(Reward.ShippingPreference.UNRESTRICTED) // - Reward from GraphQL use this field
.shippingPreference(Reward.ShippingPreference.UNRESTRICTED.name.toLowerCase()) // - Reward from V1 use this field.
.shippingType(Reward.SHIPPING_TYPE_ANYWHERE) // - Reward from V1 use this field to check if is Digital
.build()

// - Digital Reward
val newRw = RewardFactory.rewardHasAddOns().toBuilder()
.shippingType(Reward.ShippingPreference.NOSHIPPING.name.toLowerCase())
.shippingPreferenceType(Reward.ShippingPreference.NONE) // - Reward from GraphQL use this field
.shippingType(Reward.SHIPPING_TYPE_NO_SHIPPING) // - Reward from V1 use this field
.build()
val project = ProjectFactory.project()

// -Build the backing with location and list of AddOns
val backing = BackingFactory.backing(project, UserFactory.user(), backedRw)
.toBuilder()
.locationId(ShippingRuleFactory.usShippingRule().location().id())
.location(ShippingRuleFactory.usShippingRule().location())
.addOns(listAddonsBacked)
.build()

val backedProject = project.toBuilder()
.rewards(listOf(backedRw))
.backing(backing)
.build()

val projectData = ProjectDataFactory.project(backedProject, null, null)
val pledgeReason = PledgeFlowContext.forPledgeReason(PledgeReason.UPDATE_REWARD)

val bundle = Bundle()
bundle.putParcelable(ArgumentsKey.PLEDGE_PLEDGE_DATA, PledgeData.with(pledgeReason, projectData, newRw))
bundle.putSerializable(ArgumentsKey.PLEDGE_PLEDGE_REASON, PledgeReason.UPDATE_REWARD)

this.vm.arguments(bundle)

this.addOnsList.assertValues(Triple(projectData ,listAddons , shippingRule.shippingRules().first()))

// - Always 0 first time, them summatory of all addOns quantity every time the list gets updated
this.totalSelectedAddOns.assertValues(0)

this.lakeTest.assertValues("Add-Ons Page Viewed")
}

@Test
fun emptyState_whenNoAddOnsForShippingRule_shouldShowEmptyViewState() {
val shippingRuleAddOn = ShippingRuleFactory.germanyShippingRule()
Expand Down
0