mirror of
https://github.com/logos-blockchain/lez-programs.git
synced 2026-07-17 20:39:28 +00:00
Add program-neutral wallet access, a stable account model, reusable QML controls, transaction confirmation, submitted-transaction presentation, and isolated contract tests.\n\nRefs #227
340 lines
13 KiB
QML
340 lines
13 KiB
QML
import QtQuick
|
|
import QtTest
|
|
import Logos.Wallet as Wallet
|
|
|
|
Item {
|
|
id: root
|
|
width: 800
|
|
height: 600
|
|
|
|
Component {
|
|
id: backendComponent
|
|
|
|
QtObject {
|
|
property bool isWalletOpen: false
|
|
property bool walletExists: true
|
|
property string walletHome: "/wallet"
|
|
property int openCalls: 0
|
|
property int createCalls: 0
|
|
property int publicAccountCalls: 0
|
|
property int privateAccountCalls: 0
|
|
property int disconnectCalls: 0
|
|
|
|
function openExisting() {
|
|
openCalls++
|
|
isWalletOpen = true
|
|
return true
|
|
}
|
|
|
|
function createNewDefault(_password) {
|
|
createCalls++
|
|
isWalletOpen = true
|
|
return "alpha beta gamma"
|
|
}
|
|
|
|
function createAccountPublic() {
|
|
publicAccountCalls++
|
|
return "a".repeat(64)
|
|
}
|
|
|
|
function createAccountPrivate() {
|
|
privateAccountCalls++
|
|
return "b".repeat(64)
|
|
}
|
|
|
|
function disconnectWallet() {
|
|
disconnectCalls++
|
|
isWalletOpen = false
|
|
}
|
|
}
|
|
}
|
|
|
|
Component {
|
|
id: modelComponent
|
|
ListModel { }
|
|
}
|
|
|
|
Component {
|
|
id: controlComponent
|
|
Wallet.WalletControl {
|
|
width: 320
|
|
height: implicitHeight
|
|
viewportWidth: 800
|
|
}
|
|
}
|
|
|
|
Component {
|
|
id: compactWindowComponent
|
|
|
|
Window {
|
|
width: 360
|
|
height: 240
|
|
visible: true
|
|
|
|
property alias control: walletControl
|
|
|
|
Wallet.WalletControl {
|
|
id: walletControl
|
|
x: 20
|
|
y: 8
|
|
width: 320
|
|
height: implicitHeight
|
|
viewportWidth: parent.width
|
|
}
|
|
}
|
|
}
|
|
|
|
Component {
|
|
id: compactDialogWindowComponent
|
|
|
|
Window {
|
|
width: 360
|
|
height: 600
|
|
visible: true
|
|
|
|
property alias control: walletControl
|
|
|
|
Wallet.WalletControl {
|
|
id: walletControl
|
|
x: parent.width - width - 12
|
|
y: 8
|
|
width: 40
|
|
height: implicitHeight
|
|
viewportWidth: parent.width
|
|
}
|
|
}
|
|
}
|
|
|
|
TestCase {
|
|
name: "WalletControl"
|
|
when: windowShown
|
|
|
|
function createControl(walletProperties, accounts) {
|
|
const backend = createTemporaryObject(backendComponent, root, walletProperties || {})
|
|
verify(backend, "Backend exists")
|
|
const model = createTemporaryObject(modelComponent, root)
|
|
verify(model, "Account model exists")
|
|
for (const account of accounts || [])
|
|
model.append(account)
|
|
const control = createTemporaryObject(controlComponent, root, {
|
|
wallet: backend,
|
|
accountModel: model
|
|
})
|
|
verify(control, "Wallet control exists")
|
|
return { backend, model, control }
|
|
}
|
|
|
|
function test_opensExistingWallet() {
|
|
const fixture = createControl({ walletExists: true }, [])
|
|
const connectButton = findChild(fixture.control, "walletConnectButton")
|
|
verify(connectButton, "Connect button exists")
|
|
mouseClick(connectButton)
|
|
compare(fixture.backend.openCalls, 1)
|
|
tryCompare(fixture.control, "connected", true)
|
|
}
|
|
|
|
function test_requiresSeedBackupAcknowledgement() {
|
|
const fixture = createControl({ walletExists: false }, [])
|
|
mouseClick(findChild(fixture.control, "walletConnectButton"))
|
|
|
|
const dialog = findChild(fixture.control, "createWalletDialog")
|
|
tryCompare(dialog, "opened", true)
|
|
const password = findChild(dialog, "walletPasswordField")
|
|
const confirmation = findChild(dialog, "walletConfirmPasswordField")
|
|
const createButton = findChild(dialog, "createWalletButton")
|
|
verify(password && confirmation && createButton, "Wallet fields exist")
|
|
|
|
password.text = "secret"
|
|
confirmation.text = "different"
|
|
mouseClick(createButton)
|
|
compare(fixture.backend.createCalls, 0)
|
|
verify(dialog.errorText.length > 0)
|
|
|
|
confirmation.text = "secret"
|
|
mouseClick(createButton)
|
|
compare(fixture.backend.createCalls, 1)
|
|
compare(dialog.mnemonic, "alpha beta gamma")
|
|
|
|
const acknowledgement = findChild(dialog, "walletBackupAcknowledgement")
|
|
const continueButton = findChild(dialog, "walletContinueButton")
|
|
verify(acknowledgement && continueButton, "Backup controls exist")
|
|
verify(!continueButton.enabled)
|
|
mouseClick(acknowledgement)
|
|
verify(continueButton.enabled)
|
|
mouseClick(continueButton)
|
|
tryCompare(dialog, "opened", false)
|
|
}
|
|
|
|
function test_clampsSelectionAndDisconnectsLocally() {
|
|
const fixture = createControl({ isWalletOpen: true }, [
|
|
{ name: "One", address: "a".repeat(64), balance: "10", isPublic: true },
|
|
{ name: "Two", address: "b".repeat(64), balance: "20", isPublic: false }
|
|
])
|
|
fixture.control.selectedIndex = 1
|
|
compare(fixture.control.selectedAddress, "b".repeat(64))
|
|
fixture.model.clear()
|
|
tryCompare(fixture.control, "selectedIndex", 0)
|
|
compare(fixture.control.selectedAddress, "")
|
|
|
|
fixture.model.append({
|
|
name: "One", address: "a".repeat(64), balance: "10", isPublic: true
|
|
})
|
|
mouseClick(findChild(fixture.control, "walletAccountButton"))
|
|
const disconnectButton = findChild(fixture.control, "walletDisconnectButton")
|
|
tryVerify(function() { return disconnectButton.visible })
|
|
mouseClick(disconnectButton)
|
|
compare(fixture.backend.disconnectCalls, 1)
|
|
tryCompare(fixture.control, "connected", false)
|
|
}
|
|
|
|
function test_connectedButtonClosesOpenMenu() {
|
|
const fixture = createControl({ isWalletOpen: true }, [
|
|
{ name: "One", address: "a".repeat(64), balance: "10", isPublic: true }
|
|
])
|
|
const accountButton = findChild(fixture.control, "walletAccountButton")
|
|
const menu = findChild(fixture.control, "walletMenu")
|
|
|
|
mouseClick(accountButton)
|
|
tryCompare(menu, "opened", true)
|
|
mouseClick(accountButton)
|
|
tryCompare(menu, "opened", false)
|
|
}
|
|
|
|
function test_openMenuTracksControlMovement() {
|
|
const fixture = createControl({ isWalletOpen: true }, [
|
|
{ name: "One", address: "a".repeat(64), balance: "10", isPublic: true }
|
|
])
|
|
fixture.control.x = 20
|
|
fixture.control.y = 20
|
|
const accountButton = findChild(fixture.control, "walletAccountButton")
|
|
const menu = findChild(fixture.control, "walletMenu")
|
|
|
|
mouseClick(accountButton)
|
|
tryCompare(menu, "opened", true)
|
|
const initialMenu = menu.contentItem.mapToItem(root, 0, 0)
|
|
const initialButton = accountButton.mapToItem(root, 0, 0)
|
|
|
|
fixture.control.x += 300
|
|
fixture.control.y += 30
|
|
wait(0)
|
|
|
|
const movedMenu = menu.contentItem.mapToItem(root, 0, 0)
|
|
const movedButton = accountButton.mapToItem(root, 0, 0)
|
|
compare(movedMenu.x - movedButton.x, initialMenu.x - initialButton.x)
|
|
compare(movedMenu.y - movedButton.y, initialMenu.y - initialButton.y)
|
|
}
|
|
|
|
function test_selectsAccount() {
|
|
const fixture = createControl({ isWalletOpen: true }, [
|
|
{ name: "One", address: "a".repeat(64), balance: "10", isPublic: true },
|
|
{ name: "Two", address: "b".repeat(64), balance: "20", isPublic: false }
|
|
])
|
|
mouseClick(findChild(fixture.control, "walletAccountButton"))
|
|
const accountsButton = findChild(fixture.control, "walletAccountsButton")
|
|
tryVerify(function() { return accountsButton.visible })
|
|
mouseClick(accountsButton)
|
|
|
|
const accountList = findChild(fixture.control, "walletAccountList")
|
|
tryCompare(accountList, "count", 2)
|
|
tryVerify(function() { return accountList.itemAtIndex(1) !== null })
|
|
const secondAccount = accountList.itemAtIndex(1)
|
|
secondAccount.clicked()
|
|
tryCompare(fixture.control, "selectedIndex", 1)
|
|
compare(fixture.control.selectedAddress, "b".repeat(64))
|
|
}
|
|
|
|
function test_createsAccount() {
|
|
const fixture = createControl({ isWalletOpen: true }, [
|
|
{ name: "One", address: "a".repeat(64), balance: "10", isPublic: true }
|
|
])
|
|
mouseClick(findChild(fixture.control, "walletAccountButton"))
|
|
const accountsButton = findChild(fixture.control, "walletAccountsButton")
|
|
tryVerify(function() { return accountsButton.visible })
|
|
mouseClick(accountsButton)
|
|
|
|
const addButton = findChild(fixture.control, "walletAddAccountButton")
|
|
tryVerify(function() { return addButton.visible })
|
|
addButton.clicked()
|
|
const dialog = findChild(fixture.control, "createAccountDialog")
|
|
tryCompare(dialog, "opened", true)
|
|
findChild(dialog, "createAccountButton").clicked()
|
|
compare(fixture.backend.publicAccountCalls, 1)
|
|
tryCompare(dialog, "opened", false)
|
|
}
|
|
|
|
function test_compactLayoutHasStableWidth() {
|
|
const fixture = createControl({ isWalletOpen: false }, [])
|
|
fixture.control.viewportWidth = 480
|
|
verify(fixture.control.compactLayout)
|
|
compare(fixture.control.implicitWidth, 40)
|
|
fixture.control.viewportWidth = 900
|
|
verify(!fixture.control.compactLayout)
|
|
compare(fixture.control.implicitWidth, 108)
|
|
}
|
|
|
|
function test_walletDialogsUseWindowViewport() {
|
|
const window = createTemporaryObject(compactDialogWindowComponent, root)
|
|
verify(window, "Compact window exists")
|
|
waitForRendering(window.contentItem)
|
|
|
|
const dialogNames = [
|
|
"createWalletDialog",
|
|
"createAccountDialog",
|
|
"walletMessageDialog"
|
|
]
|
|
for (const name of dialogNames) {
|
|
const dialog = findChild(window.control, name)
|
|
verify(dialog, name + " exists")
|
|
dialog.open()
|
|
tryCompare(dialog, "opened", true)
|
|
compare(dialog.width, window.width - 32)
|
|
verify(dialog.x >= 0)
|
|
verify(dialog.x + dialog.width <= window.width)
|
|
dialog.close()
|
|
tryCompare(dialog, "opened", false)
|
|
}
|
|
}
|
|
|
|
function test_accountsRemainReachableInShortWindow() {
|
|
const backend = createTemporaryObject(backendComponent, root, { isWalletOpen: true })
|
|
const model = createTemporaryObject(modelComponent, root)
|
|
verify(backend && model, "Wallet fixture exists")
|
|
for (let index = 0; index < 10; ++index) {
|
|
model.append({
|
|
name: "Account " + index,
|
|
address: String(index).repeat(64),
|
|
balance: String(index),
|
|
isPublic: true
|
|
})
|
|
}
|
|
|
|
const window = createTemporaryObject(compactWindowComponent, root)
|
|
verify(window, "Short window exists")
|
|
window.control.wallet = backend
|
|
window.control.accountModel = model
|
|
waitForRendering(window.contentItem)
|
|
|
|
mouseClick(findChild(window.control, "walletAccountButton"))
|
|
const menu = findChild(window.control, "walletMenu")
|
|
tryCompare(menu, "opened", true)
|
|
mouseClick(findChild(window.control, "walletAccountsButton"))
|
|
|
|
const accountList = findChild(window.control, "walletAccountList")
|
|
const addButton = findChild(window.control, "walletAddAccountButton")
|
|
tryCompare(accountList, "count", 10)
|
|
verify(menu.y >= 12, "Menu top: " + menu.y)
|
|
verify(menu.y + menu.height <= window.height - 12,
|
|
"Menu bottom: " + (menu.y + menu.height)
|
|
+ ", window: " + window.height)
|
|
verify(accountList.height > 0)
|
|
verify(accountList.contentHeight > accountList.height)
|
|
verify(addButton && addButton.visible, "Add account button is visible")
|
|
const addPosition = addButton.mapToItem(window.contentItem, 0, 0)
|
|
verify(addPosition.y >= menu.y)
|
|
verify(addPosition.y + addButton.height <= menu.y + menu.height,
|
|
"Add account bottom: " + (addPosition.y + addButton.height)
|
|
+ ", menu bottom: " + (menu.y + menu.height))
|
|
}
|
|
}
|
|
}
|