"""Tests for core history loading and parsing.""" import os import tempfile from datetime import datetime import pytest from shellhist.core import HistoryEntry, HistoryStore, HistoryLoader class TestHistoryEntry: """Test HistoryEntry dataclass.""" def test_create_entry(self): """Test creating a basic history entry.""" entry = HistoryEntry(command="git status") assert entry.command == "git status" assert entry.timestamp is None assert entry.line_number == 0 assert entry.shell_type == "unknown" def test_entry_with_timestamp(self): """Test creating an entry with timestamp.""" ts = datetime.now() entry = HistoryEntry(command="ls -la", timestamp=ts) assert entry.timestamp == ts def test_entry_equality(self): """Test entry equality based on command.""" entry1 = HistoryEntry(command="git status") entry2 = HistoryEntry(command="git status") entry3 = HistoryEntry(command="git log") assert entry1 == entry2 assert entry1 != entry3 def test_entry_hash(self): """Test entry hash for use in sets/dicts.""" entry1 = HistoryEntry(command="git status") entry2 = HistoryEntry(command="git status") entry_set = {entry1, entry2} assert len(entry_set) == 1 class TestHistoryStore: """Test HistoryStore class.""" def test_empty_store(self): """Test creating an empty store.""" store = HistoryStore() assert len(store.entries) == 0 assert len(store.command_frequency) == 0 def test_add_entry(self): """Test adding entries to the store.""" store = HistoryStore() entry = HistoryEntry(command="git status") store.add_entry(entry) assert len(store.entries) == 1 assert store.get_frequency("git status") == 1 def test_frequency_tracking(self): """Test command frequency tracking.""" store = HistoryStore() for _ in range(3): store.add_entry(HistoryEntry(command="git status")) store.add_entry(HistoryEntry(command="git log")) assert store.get_frequency("git status") == 3 assert store.get_frequency("git log") == 1 assert store.get_frequency("unknown") == 0 def test_most_frequent(self): """Test getting most frequent commands.""" store = HistoryStore() store.add_entry(HistoryEntry(command="git status")) store.add_entry(HistoryEntry(command="git status")) store.add_entry(HistoryEntry(command="git status")) store.add_entry(HistoryEntry(command="git log")) store.add_entry(HistoryEntry(command="ls")) most_frequent = store.get_most_frequent(limit=2) assert most_frequent[0] == ("git status", 3) assert most_frequent[1] == ("git log", 1) def test_get_unique_commands(self): """Test getting unique commands.""" store = HistoryStore() store.add_entry(HistoryEntry(command="git status")) store.add_entry(HistoryEntry(command="git status")) store.add_entry(HistoryEntry(command="git log")) unique = store.get_unique_commands() assert len(unique) == 2 assert "git status" in unique assert "git log" in unique class TestHistoryLoader: """Test HistoryLoader class.""" def test_load_bash_history(self): """Test parsing bash history format.""" with tempfile.NamedTemporaryFile(mode='w', suffix='_bash_history', delete=False) as f: f.write("git status\n") f.write("git log --oneline\n") f.write("ls -la\n") f.write("npm install\n") temp_path = f.name try: loader = HistoryLoader(history_path=temp_path) store = loader.load() assert len(store.entries) == 4 assert store.get_unique_commands() == [ "git status", "git log --oneline", "ls -la", "npm install", ] finally: os.unlink(temp_path) def test_load_bash_history_with_timestamps(self): """Test parsing bash history with timestamps.""" with tempfile.NamedTemporaryFile(mode='w', suffix='_bash_history', delete=False) as f: f.write("#1700000000\n") f.write("git status\n") f.write("#1700000001\n") f.write("git log\n") temp_path = f.name try: loader = HistoryLoader(history_path=temp_path) store = loader.load() assert len(store.entries) == 2 assert store.entries[0].timestamp is not None finally: os.unlink(temp_path) def test_load_zsh_history(self): """Test parsing zsh history format.""" import os with tempfile.NamedTemporaryFile(mode='w', suffix='_zsh_history', delete=False) as f: f.write(": 1700000000:0;git status\n") f.write(": 1700000001:0;git log --oneline\n") f.write("ls -la\n") temp_path = f.name try: os.environ["SHELL"] = "/bin/zsh" loader = HistoryLoader(history_path=temp_path) store = loader.load() assert len(store.entries) == 3 assert store.entries[0].timestamp is not None del os.environ["SHELL"] finally: os.unlink(temp_path) def test_file_not_found(self): """Test error handling for missing file.""" loader = HistoryLoader(history_path="/nonexistent/path") with pytest.raises(FileNotFoundError): loader.load() def test_from_file_convenience_method(self): """Test the from_file class method.""" with tempfile.NamedTemporaryFile(mode='w', suffix='_history', delete=False) as f: f.write("echo test\n") temp_path = f.name try: store = HistoryLoader.from_file(temp_path) assert len(store.entries) == 1 finally: os.unlink(temp_path)