Files
shell-history-automation-tool/shellhist/tests/test_core.py
7000pctAUTO 7b3ceb1439
Some checks failed
CI / test (push) Has been cancelled
Shellhist CI / test (push) Has been cancelled
Shellhist CI / build (push) Has been cancelled
test: add -> None return type annotations to all test methods
2026-01-31 14:21:27 +00:00

191 lines
6.3 KiB
Python

"""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) -> None:
"""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) -> None:
"""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) -> None:
"""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) -> None:
"""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) -> None:
"""Test creating an empty store."""
store = HistoryStore()
assert len(store.entries) == 0
assert len(store.command_frequency) == 0
def test_add_entry(self) -> None:
"""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) -> None:
"""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) -> None:
"""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) -> None:
"""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) -> None:
"""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) -> None:
"""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) -> None:
"""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) -> None:
"""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) -> None:
"""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)