From 06eeb7d7dbe694bf5906d88cc5b932cb6834a91c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=84=82=CA=8F=E1=B4=87=E1=B4=85=20=F0=9F=84=B0=CA=99?= =?UTF-8?q?=E1=B4=85=E1=B4=9C=CA=9F=20=F0=9F=84=B0=E1=B4=8D=E1=B4=80?= =?UTF-8?q?=F0=9F=84=9D=20=E2=9C=A7?= Date: Tue, 17 Mar 2026 17:06:51 +0530 Subject: [PATCH 1/4] fix: reject empty name/ticker/desc in launch command MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 🄂ʏᴇᴅ 🄰ʙᴅᴜʟ 🄰ᴍᴀ🄝 ✧ --- src/pumpfun_cli/commands/launch.py | 6 +++ tests/test_commands/test_launch_cmd.py | 53 ++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 tests/test_commands/test_launch_cmd.py diff --git a/src/pumpfun_cli/commands/launch.py b/src/pumpfun_cli/commands/launch.py index 5e32549..ec0cd39 100644 --- a/src/pumpfun_cli/commands/launch.py +++ b/src/pumpfun_cli/commands/launch.py @@ -19,6 +19,12 @@ def launch( ): """Launch a new token on pump.fun (create_v2 + extend_account).""" state = ctx.obj + if not name or not name.strip(): + error("Token name cannot be empty.") + if not ticker or not ticker.strip(): + error("Token ticker cannot be empty.") + if not desc or not desc.strip(): + error("Token description cannot be empty.") if not state or not state.rpc: error("RPC endpoint not configured.", hint="Run: pumpfun config set rpc ") diff --git a/tests/test_commands/test_launch_cmd.py b/tests/test_commands/test_launch_cmd.py new file mode 100644 index 0000000..b82ea79 --- /dev/null +++ b/tests/test_commands/test_launch_cmd.py @@ -0,0 +1,53 @@ +from typer.testing import CliRunner + +from pumpfun_cli.cli import app + +runner = CliRunner() + + +def test_launch_empty_name(tmp_path, monkeypatch): + """launch rejects empty token name.""" + monkeypatch.setenv("XDG_CONFIG_HOME", str(tmp_path)) + result = runner.invoke(app, ["launch", "--name", "", "--ticker", "TST", "--desc", "test"]) + assert result.exit_code != 0 + assert "name" in result.output.lower() + + +def test_launch_whitespace_name(tmp_path, monkeypatch): + """launch rejects whitespace-only token name.""" + monkeypatch.setenv("XDG_CONFIG_HOME", str(tmp_path)) + result = runner.invoke(app, ["launch", "--name", " ", "--ticker", "TST", "--desc", "test"]) + assert result.exit_code != 0 + assert "name" in result.output.lower() + + +def test_launch_empty_ticker(tmp_path, monkeypatch): + """launch rejects empty ticker.""" + monkeypatch.setenv("XDG_CONFIG_HOME", str(tmp_path)) + result = runner.invoke(app, ["launch", "--name", "MyToken", "--ticker", "", "--desc", "test"]) + assert result.exit_code != 0 + assert "ticker" in result.output.lower() + + +def test_launch_whitespace_ticker(tmp_path, monkeypatch): + """launch rejects whitespace-only ticker.""" + monkeypatch.setenv("XDG_CONFIG_HOME", str(tmp_path)) + result = runner.invoke(app, ["launch", "--name", "MyToken", "--ticker", " ", "--desc", "test"]) + assert result.exit_code != 0 + assert "ticker" in result.output.lower() + + +def test_launch_empty_desc(tmp_path, monkeypatch): + """launch rejects empty description.""" + monkeypatch.setenv("XDG_CONFIG_HOME", str(tmp_path)) + result = runner.invoke(app, ["launch", "--name", "MyToken", "--ticker", "TST", "--desc", ""]) + assert result.exit_code != 0 + assert "description" in result.output.lower() + + +def test_launch_whitespace_desc(tmp_path, monkeypatch): + """launch rejects whitespace-only description.""" + monkeypatch.setenv("XDG_CONFIG_HOME", str(tmp_path)) + result = runner.invoke(app, ["launch", "--name", "MyToken", "--ticker", "TST", "--desc", " "]) + assert result.exit_code != 0 + assert "description" in result.output.lower() \ No newline at end of file From cce41d77bc06c28219192fdd7c88305c897ab4d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=84=82=CA=8F=E1=B4=87=E1=B4=85=20=F0=9F=84=B0=CA=99?= =?UTF-8?q?=E1=B4=85=E1=B4=9C=CA=9F=20=F0=9F=84=B0=E1=B4=8D=E1=B4=80?= =?UTF-8?q?=F0=9F=84=9D=20=E2=9C=A7?= Date: Tue, 17 Mar 2026 17:41:10 +0530 Subject: [PATCH 2/4] refactor: parametrize launch validation tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 🄂ʏᴇᴅ 🄰ʙᴅᴜʟ 🄰ᴍᴀ🄝 ✧ --- tests/test_commands/test_launch_cmd.py | 57 ++++++-------------------- 1 file changed, 13 insertions(+), 44 deletions(-) diff --git a/tests/test_commands/test_launch_cmd.py b/tests/test_commands/test_launch_cmd.py index b82ea79..fbb7525 100644 --- a/tests/test_commands/test_launch_cmd.py +++ b/tests/test_commands/test_launch_cmd.py @@ -1,3 +1,4 @@ +import pytest from typer.testing import CliRunner from pumpfun_cli.cli import app @@ -5,49 +6,17 @@ runner = CliRunner() -def test_launch_empty_name(tmp_path, monkeypatch): - """launch rejects empty token name.""" +@pytest.mark.parametrize("name,ticker,desc,expected_error", [ + ("", "TST", "test", "name"), + (" ", "TST", "test", "name"), + ("MyToken", "", "test", "ticker"), + ("MyToken", " ", "test", "ticker"), + ("MyToken", "TST", "", "description"), + ("MyToken", "TST", " ", "description"), +]) +def test_launch_rejects_empty_inputs(tmp_path, monkeypatch, name, ticker, desc, expected_error): + """launch rejects empty or whitespace-only name, ticker, or description.""" monkeypatch.setenv("XDG_CONFIG_HOME", str(tmp_path)) - result = runner.invoke(app, ["launch", "--name", "", "--ticker", "TST", "--desc", "test"]) + result = runner.invoke(app, ["launch", "--name", name, "--ticker", ticker, "--desc", desc]) assert result.exit_code != 0 - assert "name" in result.output.lower() - - -def test_launch_whitespace_name(tmp_path, monkeypatch): - """launch rejects whitespace-only token name.""" - monkeypatch.setenv("XDG_CONFIG_HOME", str(tmp_path)) - result = runner.invoke(app, ["launch", "--name", " ", "--ticker", "TST", "--desc", "test"]) - assert result.exit_code != 0 - assert "name" in result.output.lower() - - -def test_launch_empty_ticker(tmp_path, monkeypatch): - """launch rejects empty ticker.""" - monkeypatch.setenv("XDG_CONFIG_HOME", str(tmp_path)) - result = runner.invoke(app, ["launch", "--name", "MyToken", "--ticker", "", "--desc", "test"]) - assert result.exit_code != 0 - assert "ticker" in result.output.lower() - - -def test_launch_whitespace_ticker(tmp_path, monkeypatch): - """launch rejects whitespace-only ticker.""" - monkeypatch.setenv("XDG_CONFIG_HOME", str(tmp_path)) - result = runner.invoke(app, ["launch", "--name", "MyToken", "--ticker", " ", "--desc", "test"]) - assert result.exit_code != 0 - assert "ticker" in result.output.lower() - - -def test_launch_empty_desc(tmp_path, monkeypatch): - """launch rejects empty description.""" - monkeypatch.setenv("XDG_CONFIG_HOME", str(tmp_path)) - result = runner.invoke(app, ["launch", "--name", "MyToken", "--ticker", "TST", "--desc", ""]) - assert result.exit_code != 0 - assert "description" in result.output.lower() - - -def test_launch_whitespace_desc(tmp_path, monkeypatch): - """launch rejects whitespace-only description.""" - monkeypatch.setenv("XDG_CONFIG_HOME", str(tmp_path)) - result = runner.invoke(app, ["launch", "--name", "MyToken", "--ticker", "TST", "--desc", " "]) - assert result.exit_code != 0 - assert "description" in result.output.lower() \ No newline at end of file + assert expected_error in result.output.lower() \ No newline at end of file From 0975b268a81a35d77ba62031e1bdfbb5aef602a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=84=82=CA=8F=E1=B4=87=E1=B4=85=20=F0=9F=84=B0=CA=99?= =?UTF-8?q?=E1=B4=85=E1=B4=9C=CA=9F=20=F0=9F=84=B0=E1=B4=8D=E1=B4=80?= =?UTF-8?q?=F0=9F=84=9D=20=E2=9C=A7?= Date: Wed, 18 Mar 2026 14:41:57 +0530 Subject: [PATCH 3/4] fix: mock launch_token in tests and assert exact error messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 🄂ʏᴇᴅ 🄰ʙᴅᴜʟ 🄰ᴍᴀ🄝 ✧ --- tests/test_commands/test_launch_cmd.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/tests/test_commands/test_launch_cmd.py b/tests/test_commands/test_launch_cmd.py index fbb7525..1a041f1 100644 --- a/tests/test_commands/test_launch_cmd.py +++ b/tests/test_commands/test_launch_cmd.py @@ -1,3 +1,5 @@ +from unittest.mock import Mock + import pytest from typer.testing import CliRunner @@ -7,16 +9,20 @@ @pytest.mark.parametrize("name,ticker,desc,expected_error", [ - ("", "TST", "test", "name"), - (" ", "TST", "test", "name"), - ("MyToken", "", "test", "ticker"), - ("MyToken", " ", "test", "ticker"), - ("MyToken", "TST", "", "description"), - ("MyToken", "TST", " ", "description"), + ("", "TST", "test", "token name cannot be empty."), + (" ", "TST", "test", "token name cannot be empty."), + ("MyToken", "", "test", "token ticker cannot be empty."), + ("MyToken", " ", "test", "token ticker cannot be empty."), + ("MyToken", "TST", "", "token description cannot be empty."), + ("MyToken", "TST", " ", "token description cannot be empty."), ]) def test_launch_rejects_empty_inputs(tmp_path, monkeypatch, name, ticker, desc, expected_error): """launch rejects empty or whitespace-only name, ticker, or description.""" monkeypatch.setenv("XDG_CONFIG_HOME", str(tmp_path)) + launch_token_mock = Mock(side_effect=AssertionError("launch_token must not be called for invalid input")) + monkeypatch.setattr("pumpfun_cli.commands.launch.launch_token", launch_token_mock) + result = runner.invoke(app, ["launch", "--name", name, "--ticker", ticker, "--desc", desc]) assert result.exit_code != 0 - assert expected_error in result.output.lower() \ No newline at end of file + assert expected_error in result.output.lower() + launch_token_mock.assert_not_called() \ No newline at end of file From 42466dd46ed8905bfc7efba43e07946f6f4dfb2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=84=82=CA=8F=E1=B4=87=E1=B4=85=20=F0=9F=84=B0=CA=99?= =?UTF-8?q?=E1=B4=85=E1=B4=9C=CA=9F=20=F0=9F=84=B0=E1=B4=8D=E1=B4=80?= =?UTF-8?q?=F0=9F=84=9D=20=E2=9C=A7?= Date: Wed, 18 Mar 2026 15:22:53 +0530 Subject: [PATCH 4/4] fix: use tuple form for parametrize argument names (PT006) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 🄂ʏᴇᴅ 🄰ʙᴅᴜʟ 🄰ᴍᴀ🄝 ✧ --- tests/test_commands/test_launch_cmd.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_commands/test_launch_cmd.py b/tests/test_commands/test_launch_cmd.py index 1a041f1..d990536 100644 --- a/tests/test_commands/test_launch_cmd.py +++ b/tests/test_commands/test_launch_cmd.py @@ -8,7 +8,7 @@ runner = CliRunner() -@pytest.mark.parametrize("name,ticker,desc,expected_error", [ +@pytest.mark.parametrize(("name", "ticker", "desc", "expected_error"), [ ("", "TST", "test", "token name cannot be empty."), (" ", "TST", "test", "token name cannot be empty."), ("MyToken", "", "test", "token ticker cannot be empty."),