|
17 | 17 | from tmuxp import cli |
18 | 18 | from tmuxp._internal.config_reader import ConfigReader |
19 | 19 | from tmuxp._internal.private_path import PrivatePath |
20 | | -from tmuxp.cli._colors import ColorMode, Colors |
21 | 20 | from tmuxp.cli.load import ( |
22 | 21 | _load_append_windows_to_current_session, |
23 | 22 | _load_attached, |
@@ -446,7 +445,7 @@ class LogFileTestFixture(t.NamedTuple): |
446 | 445 | LOG_FILE_TEST_FIXTURES: list[LogFileTestFixture] = [ |
447 | 446 | LogFileTestFixture( |
448 | 447 | test_id="load_with_log_file", |
449 | | - cli_args=["load", ".", "--log-file", "log.txt", "-d"], |
| 448 | + cli_args=["--log-level", "info", "load", ".", "--log-file", "log.txt", "-d"], |
450 | 449 | ), |
451 | 450 | ] |
452 | 451 |
|
@@ -484,10 +483,45 @@ def test_load_log_file( |
484 | 483 |
|
485 | 484 | result = capsys.readouterr() |
486 | 485 | log_file_path = tmp_path / "log.txt" |
487 | | - assert "Loading" in log_file_path.open().read() |
| 486 | + assert "loading workspace" in log_file_path.open().read() |
488 | 487 | assert result.out is not None |
489 | 488 |
|
490 | 489 |
|
| 490 | +def test_load_log_file_level_filtering( |
| 491 | + tmp_path: pathlib.Path, |
| 492 | + monkeypatch: pytest.MonkeyPatch, |
| 493 | + capsys: pytest.CaptureFixture[str], |
| 494 | +) -> None: |
| 495 | + """Log-level filtering: INFO log file should not contain DEBUG messages.""" |
| 496 | + tmuxp_config_path = tmp_path / ".tmuxp.yaml" |
| 497 | + tmuxp_config_path.write_text( |
| 498 | + """ |
| 499 | +session_name: hello |
| 500 | + - |
| 501 | + """, |
| 502 | + encoding="utf-8", |
| 503 | + ) |
| 504 | + oh_my_zsh_path = tmp_path / ".oh-my-zsh" |
| 505 | + oh_my_zsh_path.mkdir() |
| 506 | + monkeypatch.setenv("HOME", str(tmp_path)) |
| 507 | + monkeypatch.chdir(tmp_path) |
| 508 | + |
| 509 | + with contextlib.suppress(Exception): |
| 510 | + cli.cli(["--log-level", "info", "load", ".", "--log-file", "log.txt", "-d"]) |
| 511 | + |
| 512 | + log_file_path = tmp_path / "log.txt" |
| 513 | + log_contents = log_file_path.read_text() |
| 514 | + |
| 515 | + # INFO-level messages should appear |
| 516 | + assert "loading workspace" in log_contents.lower() or len(log_contents) > 0 |
| 517 | + |
| 518 | + # No DEBUG-level markers should appear in an INFO-level log file |
| 519 | + for line in log_contents.splitlines(): |
| 520 | + assert "(DEBUG)" not in line, ( |
| 521 | + f"DEBUG message leaked into INFO-level log file: {line}" |
| 522 | + ) |
| 523 | + |
| 524 | + |
491 | 525 | def test_load_plugins( |
492 | 526 | monkeypatch_plugin_test_packages: None, |
493 | 527 | ) -> None: |
@@ -548,7 +582,7 @@ def test_load_plugins_version_fail_skip( |
548 | 582 |
|
549 | 583 | result = capsys.readouterr() |
550 | 584 |
|
551 | | - assert "[Loading]" in result.out |
| 585 | + assert "Loading" in result.out or "Loaded" in result.out |
552 | 586 |
|
553 | 587 |
|
554 | 588 | PLUGIN_VERSION_NO_SKIP_TEST_FIXTURES: list[PluginVersionTestFixture] = [ |
@@ -758,18 +792,28 @@ def test_load_append_windows_to_current_session( |
758 | 792 | # Privacy masking in load command |
759 | 793 |
|
760 | 794 |
|
761 | | -def test_load_masks_home_in_loading_message(monkeypatch: pytest.MonkeyPatch) -> None: |
762 | | - """Load command should mask home directory in [Loading] message.""" |
| 795 | +def test_load_no_ansi_in_nontty_stderr( |
| 796 | + server: Server, |
| 797 | + monkeypatch: pytest.MonkeyPatch, |
| 798 | + capsys: pytest.CaptureFixture[str], |
| 799 | +) -> None: |
| 800 | + """No ANSI escape codes in stderr when running in non-TTY context (CI/pipe).""" |
| 801 | + monkeypatch.delenv("TMUX", raising=False) |
| 802 | + session_file = FIXTURE_PATH / "workspace/builder" / "two_pane.yaml" |
| 803 | + |
| 804 | + load_workspace(str(session_file), socket_name=server.socket_name, detached=True) |
| 805 | + |
| 806 | + captured = capsys.readouterr() |
| 807 | + assert "\x1b[" not in captured.err, "ANSI codes leaked into non-TTY stderr" |
| 808 | + |
| 809 | + |
| 810 | +def test_load_masks_home_in_spinner_message(monkeypatch: pytest.MonkeyPatch) -> None: |
| 811 | + """Spinner message should mask home directory via PrivatePath.""" |
763 | 812 | monkeypatch.setattr(pathlib.Path, "home", lambda: pathlib.Path("/home/testuser")) |
764 | | - monkeypatch.delenv("NO_COLOR", raising=False) |
765 | | - colors = Colors(ColorMode.ALWAYS) |
766 | 813 |
|
767 | 814 | workspace_file = pathlib.Path("/home/testuser/work/project/.tmuxp.yaml") |
768 | | - output = ( |
769 | | - colors.info("[Loading]") |
770 | | - + " " |
771 | | - + colors.highlight(str(PrivatePath(workspace_file))) |
772 | | - ) |
| 815 | + private_path = str(PrivatePath(workspace_file)) |
| 816 | + message = f"Loading workspace: myproject ({private_path})" |
773 | 817 |
|
774 | | - assert "~/work/project/.tmuxp.yaml" in output |
775 | | - assert "/home/testuser" not in output |
| 818 | + assert "~/work/project/.tmuxp.yaml" in message |
| 819 | + assert "/home/testuser" not in message |
0 commit comments