Files
lez-programs/apps/amm/tests/qml/tst_PoolsPage.qml
Ricardo Guilherme Schmidt 4cfc03a815 feat(apps/amm): drive the Pools list from AMM_POOLS_CONFIG
The Pools page shipped with a hardcoded four-pair sample. Replace it with a
config-driven "known pools" list, mirroring how the Swap token picker reads
TOKENS_CONFIG: the app loads a flat JSON array from the AMM_POOLS_CONFIG
environment variable and renders one row per entry. Adding pairs is a config
edit — no app change.

Pool discovery is an app concern, so the config is read in the backend
(AmmUiBackend::poolList, Qt JSON) rather than the amm_module — the module is
shedding app-specific view surface (tokenList/newPositionContext), so pools go
where tokens are heading, not where they are today. poolList() fails soft to an
empty list when AMM_POOLS_CONFIG is unset/unreadable/not an array, and skips
individual entries missing tokenA/tokenB/a numeric feeBps.

Each entry carries the display symbols (tokenA/tokenB), feeBps, and the on-chain
identifiers (poolId, tokenADefinitionId, tokenBDefinitionId) so a row can later
be resolved against chain state. PoolsPage takes injected backend/runtime and
loads via runtime.watch(backend.poolList()); the Repeater renders entries
generically.

The AMM testnet setup script now emits amm-pools.json from a POOL_SPECS array
(one line per seeded pool, currently the seeded TKA/TKB pool) and prints
AMM_POOLS_CONFIG in the launch instructions. Adds amm-pools.json.example, a
README section, and gitignores the runtime config files.
2026-08-13 14:13:31 +02:00

83 lines
2.1 KiB
QML

pragma ComponentBehavior: Bound
import QtQuick
import QtTest
import "../../qml/pages" as Pages
TestCase {
id: testCase
name: "PoolsPage"
Component {
id: backendComponent
QtObject {
property var poolListResult: [
{ "tokenA": "TKA", "tokenB": "TKB", "feeBps": 5 },
{ "tokenA": "TKC", "tokenB": "TKA", "feeBps": 30 }
]
function poolList() {
return poolListResult
}
}
}
Component {
id: runtimeComponent
QtObject {
function watch(value, succeeded, failed) {
if (value === undefined)
return
succeeded(value)
}
}
}
Component {
id: pageComponent
Pages.PoolsPage {
visible: false
width: 800
height: 600
}
}
function test_rowsAreDrivenByBackendPoolList() {
var backend = createTemporaryObject(backendComponent, testCase)
var runtime = createTemporaryObject(runtimeComponent, testCase)
var page = createTemporaryObject(pageComponent, testCase, {
"backend": backend,
"runtime": runtime
})
verify(backend)
verify(runtime)
verify(page)
// The config drives the row count — no pair is hardcoded in the page,
// so adding entries to poolList() is all it takes to render more rows.
compare(page.poolCount, 2)
verify(page.feeLabel(5).endsWith("%"))
var list = findChild(page, "poolsList")
var firstRow = findChild(page, "poolRow0")
verify(list)
verify(firstRow)
compare(firstRow.pairText, "TKA / TKB")
compare(firstRow.feeText, page.feeLabel(5))
}
function test_emptyPoolModelUsesTheEmptyState() {
var page = createTemporaryObject(pageComponent, testCase)
verify(page)
// No backend wired: pools defaults to [] and the empty state shows.
compare(page.poolCount, 0)
compare(page.showEmptyState, true)
}
}