|
| 1 | +""" |
| 2 | +Test suite for hatch --version command implementation. |
| 3 | +
|
| 4 | +This module tests the version command functionality: |
| 5 | +- Version retrieval from importlib.metadata |
| 6 | +- Error handling for PackageNotFoundError |
| 7 | +- CLI version display format |
| 8 | +- Import safety after removing __version__ |
| 9 | +- No conflicts with existing flags |
| 10 | +
|
| 11 | +Tests follow CrackingShells testing standards using wobble framework. |
| 12 | +""" |
| 13 | + |
| 14 | +import unittest |
| 15 | +import sys |
| 16 | +from pathlib import Path |
| 17 | +from unittest.mock import patch, MagicMock |
| 18 | +from io import StringIO |
| 19 | + |
| 20 | +# Add parent directory to path |
| 21 | +sys.path.insert(0, str(Path(__file__).parent.parent)) |
| 22 | + |
| 23 | +from hatch.cli_hatch import main, get_hatch_version |
| 24 | + |
| 25 | +try: |
| 26 | + from wobble.decorators import regression_test, integration_test |
| 27 | +except ImportError: |
| 28 | + # Fallback decorators if wobble not available |
| 29 | + def regression_test(func): |
| 30 | + return func |
| 31 | + |
| 32 | + def integration_test(scope="component"): |
| 33 | + def decorator(func): |
| 34 | + return func |
| 35 | + return decorator |
| 36 | + |
| 37 | + |
| 38 | +class TestVersionCommand(unittest.TestCase): |
| 39 | + """Test suite for hatch --version command implementation.""" |
| 40 | + |
| 41 | + @regression_test |
| 42 | + def test_get_hatch_version_retrieves_from_metadata(self): |
| 43 | + """Test get_hatch_version() retrieves version from importlib.metadata.""" |
| 44 | + with patch('hatch.cli_hatch.version', return_value='0.7.0-dev.3') as mock_version: |
| 45 | + result = get_hatch_version() |
| 46 | + |
| 47 | + self.assertEqual(result, '0.7.0-dev.3') |
| 48 | + mock_version.assert_called_once_with('hatch') |
| 49 | + |
| 50 | + @regression_test |
| 51 | + def test_get_hatch_version_handles_package_not_found(self): |
| 52 | + """Test get_hatch_version() handles PackageNotFoundError gracefully.""" |
| 53 | + from importlib.metadata import PackageNotFoundError |
| 54 | + |
| 55 | + with patch('hatch.cli_hatch.version', side_effect=PackageNotFoundError()): |
| 56 | + result = get_hatch_version() |
| 57 | + |
| 58 | + self.assertEqual(result, 'unknown (development mode)') |
| 59 | + |
| 60 | + @integration_test(scope="component") |
| 61 | + def test_version_command_displays_correct_format(self): |
| 62 | + """Test version command displays correct format via CLI.""" |
| 63 | + test_args = ['hatch', '--version'] |
| 64 | + |
| 65 | + with patch('sys.argv', test_args): |
| 66 | + with patch('hatch.cli_hatch.get_hatch_version', return_value='0.7.0-dev.3'): |
| 67 | + with patch('sys.stdout', new_callable=StringIO) as mock_stdout: |
| 68 | + with self.assertRaises(SystemExit) as cm: |
| 69 | + main() |
| 70 | + |
| 71 | + # argparse action='version' exits with code 0 |
| 72 | + self.assertEqual(cm.exception.code, 0) |
| 73 | + |
| 74 | + # Verify output format: "hatch 0.7.0-dev.3" |
| 75 | + output = mock_stdout.getvalue().strip() |
| 76 | + self.assertRegex(output, r'hatch\s+0\.7\.0-dev\.3') |
| 77 | + |
| 78 | + @integration_test(scope="component") |
| 79 | + def test_import_hatch_without_version_attribute(self): |
| 80 | + """Test that importing hatch module works without __version__ attribute.""" |
| 81 | + try: |
| 82 | + import hatch |
| 83 | + |
| 84 | + # Import should succeed |
| 85 | + self.assertIsNotNone(hatch) |
| 86 | + |
| 87 | + # __version__ should not exist (removed in implementation) |
| 88 | + self.assertFalse(hasattr(hatch, '__version__'), |
| 89 | + "hatch.__version__ should not exist after cleanup") |
| 90 | + |
| 91 | + except ImportError as e: |
| 92 | + self.fail(f"Failed to import hatch module: {e}") |
| 93 | + |
| 94 | + @regression_test |
| 95 | + def test_no_conflict_with_package_version_flag(self): |
| 96 | + """Test that --version (Hatch) doesn't conflict with -v (package version).""" |
| 97 | + # Test package add command with -v flag (package version specification) |
| 98 | + test_args = ['hatch', 'package', 'add', 'test-package', '-v', '1.0.0'] |
| 99 | + |
| 100 | + with patch('sys.argv', test_args): |
| 101 | + with patch('hatch.cli_hatch.HatchEnvironmentManager') as mock_env: |
| 102 | + mock_env_instance = MagicMock() |
| 103 | + mock_env.return_value = mock_env_instance |
| 104 | + mock_env_instance.add_package_to_environment.return_value = True |
| 105 | + |
| 106 | + try: |
| 107 | + main() |
| 108 | + except SystemExit as e: |
| 109 | + # Should execute successfully (exit code 0) |
| 110 | + self.assertEqual(e.code, 0) |
| 111 | + |
| 112 | + # Verify package add was called with version argument |
| 113 | + mock_env_instance.add_package_to_environment.assert_called_once() |
| 114 | + call_args = mock_env_instance.add_package_to_environment.call_args |
| 115 | + |
| 116 | + # Version argument should be '1.0.0' |
| 117 | + self.assertEqual(call_args[0][2], '1.0.0') # Third positional arg is version |
| 118 | + |
| 119 | + |
| 120 | +if __name__ == '__main__': |
| 121 | + unittest.main() |
| 122 | + |
0 commit comments