""" Test Output Formatting for New Database Commands - Clean Implementation This test validates the multiple output format support for the new db-prefixed database commands, ensuring users can get results in their preferred format without any legacy interface dependencies. Requirements tested: - db-query command with table, JSON, YAML format output - db-schema command with table, JSON, YAML format output - Format validation and error handling - Empty result formatting across all formats - Clean implementation without legacy interface pollution """ import pytest import json import yaml from click.testing import CliRunner from unittest.mock import patch, MagicMock from markitect.cli import cli class TestDbQueryOutputFormatting: """Test suite for db-query command output formatting.""" def setup_method(self): """Set up test fixtures.""" self.runner = CliRunner() self.sample_data = [ { 'id': 1, 'filename': 'document1.md', 'created_at': '2025-09-30 10:00:00', 'front_matter': '{"title": "First Document", "author": "John Doe"}' }, { 'id': 2, 'filename': 'document2.md', 'created_at': '2025-09-30 11:00:00', 'front_matter': '{"title": "Second Document", "author": "Jane Smith"}' } ] def test_db_query_table_format_output(self): """ Test that db-query with table format produces human-readable output. Clean implementation using new db-query command only. """ with patch('markitect.cli.DatabaseManager') as mock_db_mgr: mock_db_instance = MagicMock() mock_db_mgr.return_value = mock_db_instance mock_db_instance.execute_query.return_value = self.sample_data result = self.runner.invoke(cli, [ 'db-query', 'SELECT * FROM markdown_files', '--format', 'table' ]) assert result.exit_code == 0 # Table format should include column headers and data assert 'filename' in result.output assert 'document1.md' in result.output assert 'document2.md' in result.output # Should have some kind of visual structure (lines, spacing, etc.) output_lines = result.output.split('\n') assert len(output_lines) >= 3 # At least header + 2 data rows def test_db_query_json_format_output(self): """ Test that db-query with JSON format produces valid JSON output. Clean implementation using new db-query command only. """ with patch('markitect.cli.DatabaseManager') as mock_db_mgr: mock_db_instance = MagicMock() mock_db_mgr.return_value = mock_db_instance mock_db_instance.execute_query.return_value = self.sample_data result = self.runner.invoke(cli, [ 'db-query', 'SELECT * FROM markdown_files', '--format', 'json' ]) assert result.exit_code == 0 # Output should be valid JSON try: parsed_json = json.loads(result.output.strip()) assert isinstance(parsed_json, list) assert len(parsed_json) == 2 assert parsed_json[0]['filename'] == 'document1.md' assert parsed_json[1]['filename'] == 'document2.md' except json.JSONDecodeError: pytest.fail(f"Output should be valid JSON. Got: {repr(result.output)}") def test_db_query_yaml_format_output(self): """ Test that db-query with YAML format produces valid YAML output. Clean implementation using new db-query command only. """ with patch('markitect.cli.DatabaseManager') as mock_db_mgr: mock_db_instance = MagicMock() mock_db_mgr.return_value = mock_db_instance mock_db_instance.execute_query.return_value = self.sample_data result = self.runner.invoke(cli, [ 'db-query', 'SELECT * FROM markdown_files', '--format', 'yaml' ]) assert result.exit_code == 0 # Output should be valid YAML try: parsed_yaml = yaml.safe_load(result.output) assert isinstance(parsed_yaml, list) assert len(parsed_yaml) == 2 assert parsed_yaml[0]['filename'] == 'document1.md' assert parsed_yaml[1]['filename'] == 'document2.md' except yaml.YAMLError: pytest.fail(f"Output should be valid YAML. Got: {repr(result.output)}") def test_db_query_default_format_is_table(self): """ Test that db-query default output format is table when not specified. Clean implementation using new db-query command only. """ with patch('markitect.cli.DatabaseManager') as mock_db_mgr: mock_db_instance = MagicMock() mock_db_mgr.return_value = mock_db_instance mock_db_instance.execute_query.return_value = self.sample_data # Without specifying format result = self.runner.invoke(cli, ['db-query', 'SELECT * FROM markdown_files']) assert result.exit_code == 0 # Should look like table format (not JSON or YAML) assert not result.output.strip().startswith('[') # Not JSON array assert not result.output.strip().startswith('-') # Not YAML array def test_db_query_empty_result_formatting(self): """ Test that db-query handles empty results correctly in all formats. Clean implementation using new db-query command only. """ with patch('markitect.cli.DatabaseManager') as mock_db_mgr: mock_db_instance = MagicMock() mock_db_mgr.return_value = mock_db_instance mock_db_instance.execute_query.return_value = [] # Test JSON format with empty results result = self.runner.invoke(cli, [ 'db-query', 'SELECT * FROM markdown_files WHERE id = -1', '--format', 'json' ]) assert result.exit_code == 0 try: parsed = json.loads(result.output.strip()) assert parsed == [] except json.JSONDecodeError: # Might show "No results" message instead assert 'no results' in result.output.lower() # Test YAML format with empty results result = self.runner.invoke(cli, [ 'db-query', 'SELECT * FROM markdown_files WHERE id = -1', '--format', 'yaml' ]) assert result.exit_code == 0 # Test table format with empty results result = self.runner.invoke(cli, [ 'db-query', 'SELECT * FROM markdown_files WHERE id = -1', '--format', 'table' ]) assert result.exit_code == 0 def test_db_query_invalid_format_handling(self): """ Test that db-query handles invalid format specifications gracefully. Clean implementation using new db-query command only. """ result = self.runner.invoke(cli, [ 'db-query', 'SELECT * FROM markdown_files', '--format', 'invalid_format' ]) # Should either use default format or show error assert result.exit_code != 0 or 'invalid' in result.output.lower() class TestDbSchemaOutputFormatting: """Test suite for db-schema command output formatting.""" def setup_method(self): """Set up test fixtures.""" self.runner = CliRunner() self.schema_data = { 'markdown_files': { 'columns': [ {'name': 'id', 'type': 'INTEGER', 'primary_key': True, 'nullable': False}, {'name': 'filename', 'type': 'TEXT', 'primary_key': False, 'nullable': False}, {'name': 'front_matter', 'type': 'TEXT', 'primary_key': False, 'nullable': True}, {'name': 'content', 'type': 'TEXT', 'primary_key': False, 'nullable': True}, {'name': 'created_at', 'type': 'TIMESTAMP', 'primary_key': False, 'nullable': True} ] } } def test_db_schema_table_format(self): """ Test that db-schema command produces readable table format. Clean implementation using new db-schema command only. """ with patch('markitect.cli.DatabaseManager') as mock_db_mgr: mock_db_instance = MagicMock() mock_db_mgr.return_value = mock_db_instance mock_db_instance.get_schema.return_value = self.schema_data result = self.runner.invoke(cli, ['db-schema', '--format', 'table']) assert result.exit_code == 0 assert 'markdown_files' in result.output assert 'filename' in result.output assert 'INTEGER' in result.output assert 'TEXT' in result.output def test_db_schema_json_format(self): """ Test that db-schema command produces valid JSON format. Clean implementation using new db-schema command only. """ with patch('markitect.cli.DatabaseManager') as mock_db_mgr: mock_db_instance = MagicMock() mock_db_mgr.return_value = mock_db_instance mock_db_instance.get_schema.return_value = self.schema_data result = self.runner.invoke(cli, ['db-schema', '--format', 'json']) assert result.exit_code == 0 try: parsed = json.loads(result.output.strip()) assert 'markdown_files' in parsed assert 'columns' in parsed['markdown_files'] except json.JSONDecodeError: pytest.fail(f"Schema JSON output should be valid JSON. Got: {repr(result.output)}") def test_db_schema_yaml_format(self): """ Test that db-schema command produces valid YAML format. Clean implementation using new db-schema command only. """ with patch('markitect.cli.DatabaseManager') as mock_db_mgr: mock_db_instance = MagicMock() mock_db_mgr.return_value = mock_db_instance mock_db_instance.get_schema.return_value = self.schema_data result = self.runner.invoke(cli, ['db-schema', '--format', 'yaml']) assert result.exit_code == 0 try: parsed = yaml.safe_load(result.output) assert 'markdown_files' in parsed assert 'columns' in parsed['markdown_files'] except yaml.YAMLError: pytest.fail(f"Schema YAML output should be valid YAML. Got: {repr(result.output)}") class TestDbCommandsFormatConsistency: """Test suite for format consistency across db- commands.""" def setup_method(self): """Set up test fixtures.""" self.runner = CliRunner() def test_format_option_consistency_db_commands(self): """ Test that --format option works consistently across db- commands. Clean implementation using new db- commands only. """ commands = [ ['db-query', 'SELECT COUNT(*) FROM markdown_files'], ['db-schema'] ] formats = ['table', 'json', 'yaml'] for command in commands: for fmt in formats: # Test that all commands accept the format option result = self.runner.invoke(cli, command + ['--format', fmt, '--help']) # Should not error on the format option itself assert 'unrecognized arguments' not in result.output.lower() def test_format_error_consistency_db_commands(self): """ Test that format errors are handled consistently across db- commands. Clean implementation using new db- commands only. """ commands = [ ['db-query', 'SELECT COUNT(*) FROM markdown_files'], ['db-schema'] ] for command in commands: result = self.runner.invoke(cli, command + ['--format', 'invalid']) # Should either reject invalid format or use default # Consistent error handling across all commands assert result.exit_code == 0 or 'invalid' in result.output.lower() class TestDbCommandsAdvanced: """Test suite for advanced db- command functionality.""" def setup_method(self): """Set up test fixtures.""" self.runner = CliRunner() def test_db_query_sql_safety_constraints(self): """ Test that db-query enforces SQL safety constraints. Clean implementation using new db-query command only. """ dangerous_queries = [ 'DROP TABLE markdown_files', 'DELETE FROM markdown_files', 'UPDATE markdown_files SET content = NULL', 'INSERT INTO markdown_files VALUES (1, "test.md")' ] for query in dangerous_queries: result = self.runner.invoke(cli, ['db-query', query]) # Should either fail with exit code != 0 or show safety message assert (result.exit_code != 0 or 'not allowed' in result.output.lower() or 'forbidden' in result.output.lower() or 'denied' in result.output.lower() or 'read-only' in result.output.lower()) def test_db_commands_help_functionality(self): """ Test that db- commands provide helpful usage information. Clean implementation using new db- commands only. """ commands = ['db-query', 'db-schema', 'db-delete', 'db-stats'] for command in commands: result = self.runner.invoke(cli, [command, '--help']) assert result.exit_code == 0 assert command in result.output.lower() assert 'usage' in result.output.lower() or 'help' in result.output.lower()