@@ -451,6 +451,98 @@ def test_sell_insufficient_balance_json(tmp_path, monkeypatch):
451451 assert "Insufficient" in result .output
452452
453453
454+ def test_buy_slippage_negative ():
455+ """Buy with negative slippage exits with error."""
456+ result = runner .invoke (app , ["--rpc" , "https://fake.rpc" , "buy" , "--slippage" , "-5" , _FAKE_MINT , "0.01" ])
457+ assert result .exit_code != 0
458+ assert "Slippage must be between 0 and 100" in result .output
459+
460+
461+ def test_buy_slippage_above_100 ():
462+ """Buy with slippage above 100 exits with error."""
463+ result = runner .invoke (app , ["--rpc" , "https://fake.rpc" , "buy" , "--slippage" , "999" , _FAKE_MINT , "0.01" ])
464+ assert result .exit_code != 0
465+ assert "Slippage must be between 0 and 100" in result .output
466+
467+
468+ def test_sell_slippage_negative ():
469+ """Sell with negative slippage exits with error."""
470+ result = runner .invoke (app , ["--rpc" , "https://fake.rpc" , "sell" , "--slippage" , "-5" , _FAKE_MINT , "all" ])
471+ assert result .exit_code != 0
472+ assert "Slippage must be between 0 and 100" in result .output
473+
474+
475+ def test_sell_slippage_above_100 ():
476+ """Sell with slippage above 100 exits with error."""
477+ result = runner .invoke (app , ["--rpc" , "https://fake.rpc" , "sell" , "--slippage" , "999" , _FAKE_MINT , "all" ])
478+ assert result .exit_code != 0
479+ assert "Slippage must be between 0 and 100" in result .output
480+
481+
482+ def test_buy_slippage_zero (tmp_path , monkeypatch ):
483+ """Buy with slippage=0 is valid (boundary)."""
484+ monkeypatch .setenv ("XDG_CONFIG_HOME" , str (tmp_path ))
485+ monkeypatch .setenv ("PUMPFUN_PASSWORD" , "testpass" )
486+
487+ from solders .keypair import Keypair
488+
489+ from pumpfun_cli .crypto import encrypt_keypair
490+
491+ config_dir = tmp_path / "pumpfun-cli"
492+ config_dir .mkdir ()
493+ encrypt_keypair (Keypair (), "testpass" , config_dir / "wallet.enc" )
494+
495+ with patch ("pumpfun_cli.commands.trade.buy_token" , new_callable = AsyncMock ) as mock_buy :
496+ mock_buy .return_value = {
497+ "action" : "buy" ,
498+ "mint" : _FAKE_MINT ,
499+ "sol_spent" : 0.01 ,
500+ "tokens_received" : 100.0 ,
501+ "signature" : "sig" ,
502+ "explorer" : "https://solscan.io/tx/sig" ,
503+ }
504+
505+ result = runner .invoke (
506+ app ,
507+ ["--json" , "--rpc" , "http://rpc" , "buy" , "--slippage" , "0" , _FAKE_MINT , "0.01" ],
508+ )
509+
510+ assert result .exit_code == 0
511+ assert "Slippage must be between" not in result .output
512+
513+
514+ def test_buy_slippage_100 (tmp_path , monkeypatch ):
515+ """Buy with slippage=100 is valid (boundary)."""
516+ monkeypatch .setenv ("XDG_CONFIG_HOME" , str (tmp_path ))
517+ monkeypatch .setenv ("PUMPFUN_PASSWORD" , "testpass" )
518+
519+ from solders .keypair import Keypair
520+
521+ from pumpfun_cli .crypto import encrypt_keypair
522+
523+ config_dir = tmp_path / "pumpfun-cli"
524+ config_dir .mkdir ()
525+ encrypt_keypair (Keypair (), "testpass" , config_dir / "wallet.enc" )
526+
527+ with patch ("pumpfun_cli.commands.trade.buy_token" , new_callable = AsyncMock ) as mock_buy :
528+ mock_buy .return_value = {
529+ "action" : "buy" ,
530+ "mint" : _FAKE_MINT ,
531+ "sol_spent" : 0.01 ,
532+ "tokens_received" : 100.0 ,
533+ "signature" : "sig" ,
534+ "explorer" : "https://solscan.io/tx/sig" ,
535+ }
536+
537+ result = runner .invoke (
538+ app ,
539+ ["--json" , "--rpc" , "http://rpc" , "buy" , "--slippage" , "100" , _FAKE_MINT , "0.01" ],
540+ )
541+
542+ assert result .exit_code == 0
543+ assert "Slippage must be between" not in result .output
544+
545+
454546def test_buy_json_output_has_expected_keys (tmp_path , monkeypatch ):
455547 """Verify JSON buy output has all expected keys."""
456548 monkeypatch .setenv ("XDG_CONFIG_HOME" , str (tmp_path ))
0 commit comments