feat(@desktop/wallet): Integrate recurring onramp providers in Recurrent tab
fixes #14820
This commit is contained in:
parent
3f77a16317
commit
aa03edf17c
|
@ -7,15 +7,17 @@ type Item* = object
|
||||||
logoUrl: string
|
logoUrl: string
|
||||||
siteUrl: string
|
siteUrl: string
|
||||||
hostname: string
|
hostname: string
|
||||||
|
recurrentSiteUrl: string
|
||||||
|
|
||||||
proc initItem*(name, description, fees, logoUrl, siteUrl,
|
proc initItem*(name, description, fees, logoUrl, siteUrl,
|
||||||
hostname: string): Item =
|
hostname, recurrentSiteUrl,: string): Item =
|
||||||
result.name = name
|
result.name = name
|
||||||
result.description = description
|
result.description = description
|
||||||
result.fees = fees
|
result.fees = fees
|
||||||
result.logoUrl = logoUrl
|
result.logoUrl = logoUrl
|
||||||
result.siteUrl = siteUrl
|
result.siteUrl = siteUrl
|
||||||
result.hostname = hostname
|
result.hostname = hostname
|
||||||
|
result.recurrentSiteUrl = recurrentSiteUrl
|
||||||
|
|
||||||
proc `$`*(self: Item): string =
|
proc `$`*(self: Item): string =
|
||||||
result = "Item("
|
result = "Item("
|
||||||
|
@ -25,6 +27,7 @@ proc `$`*(self: Item): string =
|
||||||
result &= fmt"logoUrl:{self.logoUrl}, "
|
result &= fmt"logoUrl:{self.logoUrl}, "
|
||||||
result &= fmt"siteUrl:{self.siteUrl}"
|
result &= fmt"siteUrl:{self.siteUrl}"
|
||||||
result &= fmt"hostname:{self.hostname}"
|
result &= fmt"hostname:{self.hostname}"
|
||||||
|
result &= fmt"recurrentSiteUrl:{self.recurrentSiteUrl}"
|
||||||
result &= ")"
|
result &= ")"
|
||||||
|
|
||||||
method getName*(self: Item): string {.base.} =
|
method getName*(self: Item): string {.base.} =
|
||||||
|
@ -44,3 +47,6 @@ method getSiteUrl*(self: Item): string {.base.} =
|
||||||
|
|
||||||
method getHostname*(self: Item): string {.base.} =
|
method getHostname*(self: Item): string {.base.} =
|
||||||
return self.hostname
|
return self.hostname
|
||||||
|
|
||||||
|
method getRecurrentSiteUrl*(self: Item): string {.base.} =
|
||||||
|
return self.recurrentSiteUrl
|
||||||
|
|
|
@ -10,6 +10,7 @@ type
|
||||||
LogoUrl
|
LogoUrl
|
||||||
SiteUrl
|
SiteUrl
|
||||||
Hostname
|
Hostname
|
||||||
|
RecurrentSiteUrl
|
||||||
|
|
||||||
QtObject:
|
QtObject:
|
||||||
type
|
type
|
||||||
|
@ -36,7 +37,8 @@ QtObject:
|
||||||
ModelRole.Fees.int:"fees",
|
ModelRole.Fees.int:"fees",
|
||||||
ModelRole.LogoUrl.int:"logoUrl",
|
ModelRole.LogoUrl.int:"logoUrl",
|
||||||
ModelRole.SiteUrl.int:"siteUrl",
|
ModelRole.SiteUrl.int:"siteUrl",
|
||||||
ModelRole.Hostname.int:"hostname"
|
ModelRole.Hostname.int:"hostname",
|
||||||
|
ModelRole.RecurrentSiteUrl.int:"recurrentSiteUrl"
|
||||||
}.toTable
|
}.toTable
|
||||||
|
|
||||||
method data(self: Model, index: QModelIndex, role: int): QVariant =
|
method data(self: Model, index: QModelIndex, role: int): QVariant =
|
||||||
|
@ -62,6 +64,8 @@ QtObject:
|
||||||
result = newQVariant(item.getSiteUrl)
|
result = newQVariant(item.getSiteUrl)
|
||||||
of ModelRole.Hostname:
|
of ModelRole.Hostname:
|
||||||
result = newQVariant(item.getHostname)
|
result = newQVariant(item.getHostname)
|
||||||
|
of ModelRole.RecurrentSiteUrl:
|
||||||
|
result = newQVariant(item.getRecurrentSiteUrl)
|
||||||
|
|
||||||
proc setItems*(self: Model, items: seq[Item]) =
|
proc setItems*(self: Model, items: seq[Item]) =
|
||||||
self.beginResetModel()
|
self.beginResetModel()
|
||||||
|
|
|
@ -40,7 +40,8 @@ method updateCryptoServices*(self: Module, cryptoServices: seq[CryptoRampDto]) =
|
||||||
w.fees,
|
w.fees,
|
||||||
w.logoUrl,
|
w.logoUrl,
|
||||||
w.siteUrl,
|
w.siteUrl,
|
||||||
w.hostname
|
w.hostname,
|
||||||
|
w.recurrentSiteUrl,
|
||||||
))
|
))
|
||||||
self.view.setItems(items)
|
self.view.setItems(items)
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ type
|
||||||
logoUrl*: string
|
logoUrl*: string
|
||||||
siteUrl*: string
|
siteUrl*: string
|
||||||
hostname*: string
|
hostname*: string
|
||||||
|
recurrentSiteUrl*: string
|
||||||
|
|
||||||
proc newDto*(
|
proc newDto*(
|
||||||
name: string,
|
name: string,
|
||||||
|
@ -17,7 +18,8 @@ proc newDto*(
|
||||||
fees: string,
|
fees: string,
|
||||||
logoUrl: string,
|
logoUrl: string,
|
||||||
siteUrl: string,
|
siteUrl: string,
|
||||||
hostname: string
|
hostname: string,
|
||||||
|
recurrentSiteUrl: string
|
||||||
): CryptoRampDto =
|
): CryptoRampDto =
|
||||||
return CryptoRampDto(
|
return CryptoRampDto(
|
||||||
name: name,
|
name: name,
|
||||||
|
@ -25,7 +27,8 @@ proc newDto*(
|
||||||
fees: fees,
|
fees: fees,
|
||||||
logoUrl: logoUrl,
|
logoUrl: logoUrl,
|
||||||
siteUrl: siteUrl,
|
siteUrl: siteUrl,
|
||||||
hostname: hostname
|
hostname: hostname,
|
||||||
|
recurrentSiteUrl: recurrentSiteUrl
|
||||||
)
|
)
|
||||||
|
|
||||||
proc `$`*(self: CryptoRampDto): string =
|
proc `$`*(self: CryptoRampDto): string =
|
||||||
|
@ -36,6 +39,7 @@ proc `$`*(self: CryptoRampDto): string =
|
||||||
result &= fmt"logoUrl:{self.logoUrl}, "
|
result &= fmt"logoUrl:{self.logoUrl}, "
|
||||||
result &= fmt"siteUrl:{self.siteUrl}, "
|
result &= fmt"siteUrl:{self.siteUrl}, "
|
||||||
result &= fmt"hostname:{self.hostname}"
|
result &= fmt"hostname:{self.hostname}"
|
||||||
|
result &= fmt"recurrentSiteUrl:{self.recurrentSiteUrl}"
|
||||||
result &= ")"
|
result &= ")"
|
||||||
|
|
||||||
proc toCryptoRampDto*(jsonObj: JsonNode): CryptoRampDto =
|
proc toCryptoRampDto*(jsonObj: JsonNode): CryptoRampDto =
|
||||||
|
@ -46,3 +50,4 @@ proc toCryptoRampDto*(jsonObj: JsonNode): CryptoRampDto =
|
||||||
discard jsonObj.getProp("logoUrl", result.logoUrl)
|
discard jsonObj.getProp("logoUrl", result.logoUrl)
|
||||||
discard jsonObj.getProp("siteUrl", result.siteUrl)
|
discard jsonObj.getProp("siteUrl", result.siteUrl)
|
||||||
discard jsonObj.getProp("hostname", result.hostname)
|
discard jsonObj.getProp("hostname", result.hostname)
|
||||||
|
discard jsonObj.getProp("recurrentSiteUrl", result.recurrentSiteUrl)
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
import QtQuick 2.15
|
import QtQuick 2.15
|
||||||
import QtTest 1.15
|
import QtTest 1.15
|
||||||
|
|
||||||
|
import SortFilterProxyModel 0.2
|
||||||
|
|
||||||
import StatusQ.Core.Theme 0.1
|
import StatusQ.Core.Theme 0.1
|
||||||
|
import StatusQ.Core.Utils 0.1 as SQUtils
|
||||||
|
|
||||||
import Models 1.0
|
import Models 1.0
|
||||||
import utils 1.0
|
import utils 1.0
|
||||||
|
@ -14,13 +17,23 @@ Item {
|
||||||
height: 800
|
height: 800
|
||||||
|
|
||||||
OnRampProvidersModel{
|
OnRampProvidersModel{
|
||||||
id: onRampProvidersModal
|
id: _onRampProvidersModel
|
||||||
|
}
|
||||||
|
|
||||||
|
SortFilterProxyModel {
|
||||||
|
id: recurrentOnRampProvidersModel
|
||||||
|
sourceModel: _onRampProvidersModel
|
||||||
|
filters: ValueFilter {
|
||||||
|
roleName: "recurrentSiteUrl"
|
||||||
|
value: ""
|
||||||
|
inverted: true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: componentUnderTest
|
id: componentUnderTest
|
||||||
BuyCryptoModal {
|
BuyCryptoModal {
|
||||||
onRampProvidersModel: onRampProvidersModal
|
onRampProvidersModel: _onRampProvidersModel
|
||||||
onClosed: destroy()
|
onClosed: destroy()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,6 +60,32 @@ Item {
|
||||||
verify(!!controlUnderTest.opened)
|
verify(!!controlUnderTest.opened)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testDelegateItems(providersList, modelToCompareAgainst) {
|
||||||
|
for(let i =0; i< providersList.count; i++) {
|
||||||
|
let delegateUnderTest = providersList.itemAtIndex(i)
|
||||||
|
verify(!!delegateUnderTest)
|
||||||
|
|
||||||
|
compare(delegateUnderTest.title, modelToCompareAgainst.get(i).name)
|
||||||
|
compare(delegateUnderTest.subTitle, modelToCompareAgainst.get(i).description)
|
||||||
|
compare(delegateUnderTest.asset.name, modelToCompareAgainst.get(i).logoUrl)
|
||||||
|
|
||||||
|
const feesText = findChild(delegateUnderTest, "feesText")
|
||||||
|
verify(!!feesText)
|
||||||
|
compare(feesText.text, modelToCompareAgainst.get(i).fees)
|
||||||
|
|
||||||
|
const externalLinkIcon = findChild(delegateUnderTest, "externalLinkIcon")
|
||||||
|
verify(!!externalLinkIcon)
|
||||||
|
compare(externalLinkIcon.icon, "tiny/external")
|
||||||
|
compare(externalLinkIcon.color, Theme.palette.baseColor1)
|
||||||
|
|
||||||
|
// Hover over the item and check hovered state
|
||||||
|
mouseMove(delegateUnderTest, delegateUnderTest.width/2, delegateUnderTest.height/2)
|
||||||
|
verify(delegateUnderTest.sensor.containsMouse)
|
||||||
|
compare(externalLinkIcon.color, Theme.palette.directColor1)
|
||||||
|
verify(delegateUnderTest.color, Theme.palette.baseColor2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function test_launchAndCloseModal() {
|
function test_launchAndCloseModal() {
|
||||||
launchPopup()
|
launchPopup()
|
||||||
|
|
||||||
|
@ -64,7 +103,7 @@ Item {
|
||||||
verify(!!footer)
|
verify(!!footer)
|
||||||
compare(footer.rightButtons.count, 1)
|
compare(footer.rightButtons.count, 1)
|
||||||
compare(footer.rightButtons.get(0).text, qsTr("Done"))
|
compare(footer.rightButtons.get(0).text, qsTr("Done"))
|
||||||
mouseClick(footer.rightButtons.get(0), Qt.LeftButton)
|
mouseClick(footer.rightButtons.get(0))
|
||||||
|
|
||||||
// popup should be closed
|
// popup should be closed
|
||||||
verify(!controlUnderTest.opened)
|
verify(!controlUnderTest.opened)
|
||||||
|
@ -78,6 +117,11 @@ Item {
|
||||||
const tabBar = findChild(controlUnderTest, "tabBar")
|
const tabBar = findChild(controlUnderTest, "tabBar")
|
||||||
verify(!!tabBar)
|
verify(!!tabBar)
|
||||||
|
|
||||||
|
// find providers list
|
||||||
|
const providersList = findChild(controlUnderTest, "providersList")
|
||||||
|
waitForRendering(providersList)
|
||||||
|
verify(!!providersList)
|
||||||
|
|
||||||
// should have 2 items
|
// should have 2 items
|
||||||
compare(tabBar.count, 2)
|
compare(tabBar.count, 2)
|
||||||
|
|
||||||
|
@ -90,57 +134,88 @@ Item {
|
||||||
// item 1 should have text "Recurrent"
|
// item 1 should have text "Recurrent"
|
||||||
compare(tabBar.itemAt(1).text, qsTr("Recurrent"))
|
compare(tabBar.itemAt(1).text, qsTr("Recurrent"))
|
||||||
|
|
||||||
// TODO: this will be implemnted under https://github.com/status-im/status-desktop/issues/14820
|
// close popup
|
||||||
// until then this list will be empty
|
controlUnderTest.close()
|
||||||
mouseClick(tabBar.itemAt(1), Qt.LeftButton)
|
verify(!controlUnderTest.opened)
|
||||||
compare(tabBar.currentIndex, 1)
|
}
|
||||||
|
|
||||||
|
function test_modalContent_OneTime_tab() {
|
||||||
|
// Launch modal
|
||||||
|
launchPopup()
|
||||||
|
|
||||||
|
// find tab bar
|
||||||
|
const tabBar = findChild(controlUnderTest, "tabBar")
|
||||||
|
verify(!!tabBar)
|
||||||
|
|
||||||
|
// find providers list
|
||||||
const providersList = findChild(controlUnderTest, "providersList")
|
const providersList = findChild(controlUnderTest, "providersList")
|
||||||
waitForRendering(providersList)
|
waitForRendering(providersList)
|
||||||
verify(!!providersList)
|
verify(!!providersList)
|
||||||
compare(providersList.count, 0)
|
|
||||||
|
|
||||||
// check data on 1st tab --------------------------------------------------------
|
mouseClick(tabBar.itemAt(0))
|
||||||
mouseClick(tabBar.itemAt(0), Qt.LeftButton)
|
|
||||||
compare(tabBar.currentIndex, 0)
|
compare(tabBar.currentIndex, 0)
|
||||||
|
|
||||||
waitForRendering(providersList)
|
|
||||||
verify(!!providersList)
|
|
||||||
|
|
||||||
// verify that 3 items are listed
|
// verify that 3 items are listed
|
||||||
compare(providersList.count, 3)
|
compare(providersList.count, 3)
|
||||||
|
|
||||||
// check if delegate contents are as expected
|
// check if delegate contents are as expected
|
||||||
for(let i =0; i< providersList.count; i++) {
|
testDelegateItems(providersList, _onRampProvidersModel)
|
||||||
let delegateUnderTest = providersList.itemAtIndex(i)
|
|
||||||
|
let delegateUnderTest = providersList.itemAtIndex(0)
|
||||||
verify(!!delegateUnderTest)
|
verify(!!delegateUnderTest)
|
||||||
|
|
||||||
compare(delegateUnderTest.title, onRampProvidersModal.get(i).name)
|
|
||||||
compare(delegateUnderTest.subTitle, onRampProvidersModal.get(i).description)
|
|
||||||
compare(delegateUnderTest.asset.name, onRampProvidersModal.get(i).logoUrl)
|
|
||||||
|
|
||||||
const feesText = findChild(delegateUnderTest, "feesText")
|
|
||||||
verify(!!feesText)
|
|
||||||
compare(feesText.text, onRampProvidersModal.get(i).fees)
|
|
||||||
|
|
||||||
const externalLinkIcon = findChild(delegateUnderTest, "externalLinkIcon")
|
|
||||||
verify(!!externalLinkIcon)
|
|
||||||
compare(externalLinkIcon.icon, "tiny/external")
|
|
||||||
compare(externalLinkIcon.color, Theme.palette.baseColor1)
|
|
||||||
|
|
||||||
// Hover over the item and check hovered state
|
|
||||||
mouseMove(delegateUnderTest, delegateUnderTest.width/2, delegateUnderTest.height/2)
|
|
||||||
verify(delegateUnderTest.sensor.containsMouse)
|
|
||||||
compare(externalLinkIcon.color, Theme.palette.directColor1)
|
|
||||||
verify(delegateUnderTest.color, Theme.palette.baseColor2)
|
|
||||||
}
|
|
||||||
|
|
||||||
// test mouse click
|
// test mouse click
|
||||||
tryCompare(notificationSpy, "count", 0)
|
tryCompare(notificationSpy, "count", 0)
|
||||||
mouseClick(providersList.itemAtIndex(0))
|
mouseClick(delegateUnderTest)
|
||||||
tryCompare(notificationSpy, "count", 1)
|
tryCompare(notificationSpy, "count", 1)
|
||||||
compare(notificationSpy.signalArguments[0][0],onRampProvidersModal.get(0).siteUrl)
|
compare(notificationSpy.signalArguments[0][0], _onRampProvidersModel.get(0).siteUrl)
|
||||||
compare(notificationSpy.signalArguments[0][1],onRampProvidersModal.get(0).hostname)
|
compare(notificationSpy.signalArguments[0][1], _onRampProvidersModel.get(0).hostname)
|
||||||
|
notificationSpy.clear()
|
||||||
|
|
||||||
|
// popup should be closed
|
||||||
|
verify(!controlUnderTest.opened)
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_modalContent_recurrent_tab() {
|
||||||
|
// Launch modal
|
||||||
|
launchPopup()
|
||||||
|
|
||||||
|
// find tab bar
|
||||||
|
const tabBar = findChild(controlUnderTest, "tabBar")
|
||||||
|
verify(!!tabBar)
|
||||||
|
|
||||||
|
// find providers list
|
||||||
|
const providersList = findChild(controlUnderTest, "providersList")
|
||||||
|
waitForRendering(providersList)
|
||||||
|
verify(!!providersList)
|
||||||
|
|
||||||
|
|
||||||
|
// check data in "Recurrent" tab --------------------------------------------------------
|
||||||
|
mouseClick(tabBar.itemAt(1))
|
||||||
|
compare(tabBar.currentIndex, 1)
|
||||||
|
waitForRendering(providersList)
|
||||||
|
verify(!!providersList)
|
||||||
|
|
||||||
|
// verify that 1 item is listed
|
||||||
|
compare(providersList.count, 1)
|
||||||
|
|
||||||
|
// check if delegate contents are as expected
|
||||||
|
testDelegateItems(providersList, recurrentOnRampProvidersModel)
|
||||||
|
|
||||||
|
let delegateUnderTest = providersList.itemAtIndex(0)
|
||||||
|
verify(!!delegateUnderTest)
|
||||||
|
|
||||||
|
// test mouse click
|
||||||
|
tryCompare(notificationSpy, "count", 0)
|
||||||
|
verify(controlUnderTest.opened)
|
||||||
|
mouseClick(delegateUnderTest)
|
||||||
|
tryCompare(notificationSpy, "count", 1)
|
||||||
|
compare(notificationSpy.signalArguments[0][0], recurrentOnRampProvidersModel.get(0).recurrentSiteUrl)
|
||||||
|
compare(notificationSpy.signalArguments[0][1], recurrentOnRampProvidersModel.get(0).hostname)
|
||||||
|
notificationSpy.clear()
|
||||||
|
|
||||||
|
// popup should be closed
|
||||||
|
verify(!controlUnderTest.opened)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ ListModel {
|
||||||
logoUrl: ModelsData.onRampProviderImages.ramp,
|
logoUrl: ModelsData.onRampProviderImages.ramp,
|
||||||
siteUrl: "https://ramp.network/buy?hostApiKey=zrtf9u2uqebeyzcs37fu5857tktr3eg9w5tffove&swapAsset=DAI,ETH,USDC,USDT",
|
siteUrl: "https://ramp.network/buy?hostApiKey=zrtf9u2uqebeyzcs37fu5857tktr3eg9w5tffove&swapAsset=DAI,ETH,USDC,USDT",
|
||||||
hostname: "ramp.network",
|
hostname: "ramp.network",
|
||||||
recurrentSiteURL: ""
|
recurrentSiteUrl: ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "MoonPay",
|
name: "MoonPay",
|
||||||
|
@ -18,7 +18,7 @@ ListModel {
|
||||||
logoUrl: ModelsData.onRampProviderImages.moonPay,
|
logoUrl: ModelsData.onRampProviderImages.moonPay,
|
||||||
siteUrl: "https://buy.moonpay.com/?apiKey=pk_live_YQC6CQPA5qqDu0unEwHJyAYQyeIqFGR",
|
siteUrl: "https://buy.moonpay.com/?apiKey=pk_live_YQC6CQPA5qqDu0unEwHJyAYQyeIqFGR",
|
||||||
hostname: "moonpay.com",
|
hostname: "moonpay.com",
|
||||||
recurrentSiteURL: "https://buy.moonpay.com/?apiKey=pk_live_YQC6CQPA5qqDu0unEwHJyAYQyeIqFGR",
|
recurrentSiteUrl: "https://buy.moonpay.com/?apiKey=pk_live_ABCCQPA5qqDu0unEwHJyAYQyeIqFGR",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Latamex",
|
name: "Latamex",
|
||||||
|
@ -27,7 +27,7 @@ ListModel {
|
||||||
logoUrl: ModelsData.onRampProviderImages.latamex,
|
logoUrl: ModelsData.onRampProviderImages.latamex,
|
||||||
siteUrl: "https://latamex.com/",
|
siteUrl: "https://latamex.com/",
|
||||||
hostname: "latamex.com",
|
hostname: "latamex.com",
|
||||||
recurrentSiteURL: "",
|
recurrentSiteUrl: "",
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -46,12 +46,11 @@ StatusDialog {
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
model: SortFilterProxyModel {
|
model: SortFilterProxyModel {
|
||||||
sourceModel: !!root.onRampProvidersModel ? root.onRampProvidersModel : null
|
sourceModel: !!root.onRampProvidersModel ? root.onRampProvidersModel : null
|
||||||
// TODO: this temporary and changed under https://github.com/status-im/status-desktop/issues/14820
|
|
||||||
// when recurrentSiteURL is available
|
|
||||||
filters: ValueFilter {
|
filters: ValueFilter {
|
||||||
enabled: tabBar.currentIndex
|
enabled: tabBar.currentIndex
|
||||||
roleName: "name"
|
roleName: "recurrentSiteUrl"
|
||||||
value: ""
|
value: ""
|
||||||
|
inverted: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delegate: StatusListItem {
|
delegate: StatusListItem {
|
||||||
|
@ -78,7 +77,7 @@ StatusDialog {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
onClicked: {
|
onClicked: {
|
||||||
let url = tabBar.currentIndex ? recurrentSiteURL : siteUrl
|
let url = tabBar.currentIndex ? recurrentSiteUrl : siteUrl
|
||||||
Global.openLinkWithConfirmation(url, hostname)
|
Global.openLinkWithConfirmation(url, hostname)
|
||||||
root.close()
|
root.close()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue