"""Unit tests for devx.tools.check_api_identity_checks.""" from __future__ import annotations from pathlib import Path from unittest.mock import patch from click.testing import CliRunner from devx.tools.check_api_identity_checks import ( DEFAULT_NOQA_MARKER, DEFAULT_SCAN_DIRS, DEFAULT_SKIP_PATTERNS, _load_config, _matches_skip_pattern, cli, find_identity_checks, ) class TestFindIdentityChecks: def test_detects_is_true(self, tmp_path: Path) -> None: f = tmp_path / "test_foo.py" f.write_text("assert config.get('x') is True\n") issues = find_identity_checks(f, tmp_path, DEFAULT_NOQA_MARKER) assert len(issues) == 1 assert "is True" in issues[0] def test_detects_is_false(self, tmp_path: Path) -> None: f = tmp_path / "test_foo.py" f.write_text("if config.get('x') is False:\n pass\n") issues = find_identity_checks(f, tmp_path, DEFAULT_NOQA_MARKER) assert len(issues) == 1 assert "is False" in issues[0] def test_detects_is_not_true(self, tmp_path: Path) -> None: f = tmp_path / "test_foo.py" f.write_text("if config.get('x') is not True:\n fail()\n") issues = find_identity_checks(f, tmp_path, DEFAULT_NOQA_MARKER) assert len(issues) == 1 assert "is not True" in issues[0] def test_detects_is_not_false(self, tmp_path: Path) -> None: f = tmp_path / "test_foo.py" f.write_text("if config.get('x') is not False:\n fail()\n") issues = find_identity_checks(f, tmp_path, DEFAULT_NOQA_MARKER) assert len(issues) == 1 assert "is not False" in issues[0] def test_noqa_suppresses(self, tmp_path: Path) -> None: f = tmp_path / "test_foo.py" f.write_text("assert config.get('x') is True # noqa\n") issues = find_identity_checks(f, tmp_path, DEFAULT_NOQA_MARKER) assert len(issues) == 0 def test_no_false_positives(self, tmp_path: Path) -> None: f = tmp_path / "test_foo.py" f.write_text("assert config.get('x') == 'true'\nassert config.get('y') == True\nx = True\nif x:\n pass\n") issues = find_identity_checks(f, tmp_path, DEFAULT_NOQA_MARKER) assert len(issues) == 0 def test_multiple_issues(self, tmp_path: Path) -> None: f = tmp_path / "test_foo.py" f.write_text("if config.get('a') is True:\n pass\nif config.get('b') is not False:\n pass\n") issues = find_identity_checks(f, tmp_path, DEFAULT_NOQA_MARKER) assert len(issues) == 2 def test_file_not_found(self, tmp_path: Path) -> None: f = tmp_path / "nonexistent.py" issues = find_identity_checks(f, tmp_path, DEFAULT_NOQA_MARKER) assert issues == [] class TestMatchesSkipPattern: def test_matches_helpers(self) -> None: assert _matches_skip_pattern(Path("test_mattermost_helpers.py"), DEFAULT_SKIP_PATTERNS) def test_does_not_match_regular(self) -> None: assert not _matches_skip_pattern(Path("test_mattermost.py"), DEFAULT_SKIP_PATTERNS) def test_empty_patterns(self) -> None: assert not _matches_skip_pattern(Path("test_anything.py"), []) class TestLoadConfig: def test_defaults(self) -> None: with patch("devx.tools.check_api_identity_checks._load_pyproject_devx") as mock: mock.return_value = {} scan_dirs, skip_patterns, noqa = _load_config() assert scan_dirs == DEFAULT_SCAN_DIRS assert skip_patterns == DEFAULT_SKIP_PATTERNS assert noqa == DEFAULT_NOQA_MARKER def test_custom_config(self) -> None: with patch("devx.tools.check_api_identity_checks._load_pyproject_devx") as mock: mock.return_value = { "check_api_identity_checks": { "scan_dirs": ["tests/api"], "skip_patterns": ["test_*_unit.py"], "noqa_marker": "# allow", } } scan_dirs, skip_patterns, noqa = _load_config() assert scan_dirs == ["tests/api"] assert skip_patterns == ["test_*_unit.py"] assert noqa == "# allow" def test_invalid_config_returns_defaults(self) -> None: with patch("devx.tools.check_api_identity_checks._load_pyproject_devx") as mock: mock.return_value = {"check_api_identity_checks": "not a dict"} scan_dirs, _, _ = _load_config() assert scan_dirs == DEFAULT_SCAN_DIRS class TestCli: def test_no_issues(self, tmp_path: Path) -> None: runner = CliRunner() with ( patch("devx.tools.check_api_identity_checks._load_config") as mock_cfg, patch("devx.tools.check_api_identity_checks.Path.cwd", return_value=tmp_path), ): mock_cfg.return_value = (["tests/integration"], DEFAULT_SKIP_PATTERNS, DEFAULT_NOQA_MARKER) (tmp_path / "tests" / "integration").mkdir(parents=True) (tmp_path / "tests" / "integration" / "test_foo.py").write_text("assert config.get('x') == 'true'\n") result = runner.invoke(cli, []) assert result.exit_code == 0 assert "Passed" in result.output def test_with_issues(self, tmp_path: Path) -> None: runner = CliRunner() with ( patch("devx.tools.check_api_identity_checks._load_config") as mock_cfg, patch("devx.tools.check_api_identity_checks.Path.cwd", return_value=tmp_path), ): mock_cfg.return_value = (["tests/integration"], DEFAULT_SKIP_PATTERNS, DEFAULT_NOQA_MARKER) (tmp_path / "tests" / "integration").mkdir(parents=True) (tmp_path / "tests" / "integration" / "test_foo.py").write_text( "if config.get('x') is not True:\n fail()\n" ) result = runner.invoke(cli, []) assert result.exit_code != 0 assert "is not True" in result.output def test_skips_helpers(self, tmp_path: Path) -> None: runner = CliRunner() with ( patch("devx.tools.check_api_identity_checks._load_config") as mock_cfg, patch("devx.tools.check_api_identity_checks.Path.cwd", return_value=tmp_path), ): mock_cfg.return_value = (["tests/integration"], DEFAULT_SKIP_PATTERNS, DEFAULT_NOQA_MARKER) (tmp_path / "tests" / "integration").mkdir(parents=True) (tmp_path / "tests" / "integration" / "test_foo_helpers.py").write_text("assert x is True\n") result = runner.invoke(cli, []) assert result.exit_code == 0 def test_nonexistent_dir(self, tmp_path: Path) -> None: runner = CliRunner() with ( patch("devx.tools.check_api_identity_checks._load_config") as mock_cfg, patch("devx.tools.check_api_identity_checks.Path.cwd", return_value=tmp_path), ): mock_cfg.return_value = (["nonexistent"], DEFAULT_SKIP_PATTERNS, DEFAULT_NOQA_MARKER) result = runner.invoke(cli, []) assert result.exit_code == 0 def test_custom_scan_dir(self, tmp_path: Path) -> None: runner = CliRunner() with ( patch("devx.tools.check_api_identity_checks._load_config") as mock_cfg, patch("devx.tools.check_api_identity_checks.Path.cwd", return_value=tmp_path), ): mock_cfg.return_value = (["other"], DEFAULT_SKIP_PATTERNS, DEFAULT_NOQA_MARKER) (tmp_path / "custom").mkdir() (tmp_path / "custom" / "test_foo.py").write_text("if x is True:\n pass\n") result = runner.invoke(cli, ["--scan-dir", "custom"]) assert result.exit_code != 0