Skip to content

Commit 673393e

Browse files
committed
test: composite keys
1 parent 1c0e83d commit 673393e

File tree

1 file changed

+76
-0
lines changed
  • crates/pop-cli/src/commands/call

1 file changed

+76
-0
lines changed

crates/pop-cli/src/commands/call/chain.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1242,4 +1242,80 @@ mod tests {
12421242

12431243
Ok(())
12441244
}
1245+
1246+
#[tokio::test]
1247+
async fn query_storage_with_composite_key_works() -> Result<()> {
1248+
// Spawn a test node and prepare chain configuration via the command flow
1249+
let node = TestNode::spawn().await?;
1250+
let node_url = node.ws_url();
1251+
1252+
// Provide composite key parts separately to ensure the command converts them into a tuple
1253+
let mut call_config = CallChainCommand {
1254+
pallet: Some("Assets".to_string()),
1255+
function: Some("Account".to_string()),
1256+
args: vec![
1257+
"10000".to_string(), // AssetId
1258+
// Alice AccountId32 (hex) in dev networks
1259+
"0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d".to_string(),
1260+
],
1261+
..Default::default()
1262+
};
1263+
1264+
let mut cli = MockCli::new()
1265+
.expect_select(
1266+
"Select a chain (type to filter):".to_string(),
1267+
Some(true),
1268+
true,
1269+
Some(vec![("Custom".to_string(), "Type the chain URL manually".to_string())]),
1270+
0,
1271+
None,
1272+
)
1273+
.expect_input("Which chain would you like to interact with?", node_url.into());
1274+
1275+
let chain = chain::configure(
1276+
"Which chain would you like to interact with?",
1277+
node_url,
1278+
&None,
1279+
|_| true,
1280+
&mut cli,
1281+
)
1282+
.await?;
1283+
1284+
// Configure the call; since pallet and storage name are provided and args present,
1285+
// this should not prompt further.
1286+
// For composite keys the command should convert the
1287+
// two args into a single tuple string argument.
1288+
let call = call_config.configure_call(&chain, &mut cli)?;
1289+
assert_eq!(call.function.pallet(), "Assets");
1290+
assert_eq!(call.function.name(), "Account");
1291+
assert_eq!(call.args.len(), 1, "Composite key should be represented as a single tuple arg");
1292+
1293+
// Perform the query similar to the execute() path
1294+
if let CallItem::Storage(storage) = &call.function {
1295+
let keys = if let Some(key_ty) = storage.key_id {
1296+
let metadata = chain.client.metadata();
1297+
let registry = metadata.types();
1298+
let type_info = registry
1299+
.resolve(key_ty)
1300+
.ok_or(anyhow::anyhow!("Failed to resolve storage key type: {key_ty}"))?;
1301+
let name = type_info.path.segments.last().unwrap_or(&"".to_string()).to_string();
1302+
let key_param = type_to_param(&name, registry, key_ty)
1303+
.map_err(|e| anyhow!("Failed to parse storage key type: {e}"))?;
1304+
1305+
pop_chains::parse_dispatchable_arguments(&[key_param], call.args.clone())
1306+
.map_err(|e| anyhow!("Failed to parse storage arguments: {e}"))?
1307+
} else {
1308+
vec![]
1309+
};
1310+
1311+
// Execute the storage query; result may be None if the (AssetId, AccountId)
1312+
// combination does not exist on the fresh test chain, but the query should succeed
1313+
// without errors.
1314+
let _maybe_value = storage.query(&chain.client, keys).await?;
1315+
} else {
1316+
panic!("Expected a storage query");
1317+
}
1318+
1319+
cli.verify()
1320+
}
12451321
}

0 commit comments

Comments
 (0)