Files
shell-history-alias-generator/tests/test_parsers.py
2026-02-01 08:51:40 +00:00

219 lines
7.6 KiB
Python

"""Tests for history parsers."""
import pytest
import tempfile
import os
from shell_alias_gen.parsers import (
HistoryParserFactory,
BashHistoryParser,
ZshHistoryParser,
FishHistoryParser,
ParsedCommand,
)
class TestParsedCommand:
"""Tests for ParsedCommand class."""
def test_normalized(self):
"""Test command normalization."""
cmd = ParsedCommand(raw_command=" git status ")
assert cmd.normalized == "git status"
def test_words(self):
"""Test word splitting."""
cmd = ParsedCommand(raw_command="git checkout -b feature")
assert cmd.words == ["git", "checkout", "-b", "feature"]
class TestBashHistoryParser:
"""Tests for BashHistoryParser class."""
def test_parse_content(self):
"""Test parsing bash history content."""
parser = BashHistoryParser()
content = "ls -la\ncd /tmp\ngit status"
commands = parser.parse_content(content)
assert len(commands) == 3
assert commands[0].raw_command == "ls -la"
assert commands[1].raw_command == "cd /tmp"
def test_parse_file(self):
"""Test parsing bash history file."""
parser = BashHistoryParser()
with tempfile.NamedTemporaryFile(mode='w', suffix='.bash_history', delete=False) as f:
f.write("echo hello\nworld\n")
f.flush()
filepath = f.name
try:
commands = parser.parse_file(filepath)
assert len(commands) == 2
finally:
os.unlink(filepath)
def test_parse_file_not_found(self):
"""Test parsing non-existent file."""
parser = BashHistoryParser()
commands = parser.parse_file("/nonexistent/path")
assert commands == []
def test_parse_content_skips_comments(self):
"""Test that comments are skipped."""
parser = BashHistoryParser()
content = "# this is a comment\nls -la\n# another comment"
commands = parser.parse_content(content)
assert len(commands) == 1
assert commands[0].raw_command == "ls -la"
class TestZshHistoryParser:
"""Tests for ZshHistoryParser class."""
def test_parse_content(self):
"""Test parsing zsh history content."""
parser = ZshHistoryParser()
content = ": 1704067200:0;ls -la\n: 1704067201:0;cd /tmp"
commands = parser.parse_content(content)
assert len(commands) == 2
assert commands[0].raw_command == "ls -la"
assert commands[1].raw_command == "cd /tmp"
def test_parse_content_with_special_chars(self):
"""Test parsing zsh content with special characters."""
parser = ZshHistoryParser()
content = ": 1704067200:0;git commit -m 'fix: bug fix'"
commands = parser.parse_content(content)
assert len(commands) == 1
assert commands[0].raw_command == "git commit -m 'fix: bug fix'"
def test_parse_file(self):
"""Test parsing zsh history file."""
parser = ZshHistoryParser()
with tempfile.NamedTemporaryFile(mode='w', suffix='.zsh_history', delete=False) as f:
f.write(": 1704067200:0;echo test\n")
f.flush()
filepath = f.name
try:
commands = parser.parse_file(filepath)
assert len(commands) == 1
finally:
os.unlink(filepath)
class TestFishHistoryParser:
"""Tests for FishHistoryParser class."""
def test_parse_content(self):
"""Test parsing fish history content."""
parser = FishHistoryParser()
import json
content = json.dumps([
{"text": "ls -la", "timestamp": 1704067200},
{"text": "cd /tmp", "timestamp": 1704067201},
])
commands = parser.parse_content(content)
assert len(commands) == 2
assert commands[0].raw_command == "ls -la"
def test_parse_content_invalid_json(self):
"""Test parsing invalid json returns empty."""
parser = FishHistoryParser()
commands = parser.parse_content("not valid json")
assert commands == []
def test_parse_content_empty_list(self):
"""Test parsing empty list."""
parser = FishHistoryParser()
commands = parser.parse_content("[]")
assert commands == []
def test_parse_file(self):
"""Test parsing fish history file."""
parser = FishHistoryParser()
with tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False) as f:
import json
json.dump([{"text": "test command"}], f)
filepath = f.name
try:
commands = parser.parse_file(filepath)
assert len(commands) == 1
finally:
os.unlink(filepath)
class TestHistoryParserFactory:
"""Tests for HistoryParserFactory class."""
def test_get_bash_parser(self):
"""Test getting bash parser."""
parser = HistoryParserFactory.get_parser("bash")
assert isinstance(parser, BashHistoryParser)
def test_get_zsh_parser(self):
"""Test getting zsh parser."""
parser = HistoryParserFactory.get_parser("zsh")
assert isinstance(parser, ZshHistoryParser)
def test_get_fish_parser(self):
"""Test getting fish parser."""
parser = HistoryParserFactory.get_parser("fish")
assert isinstance(parser, FishHistoryParser)
def test_get_unknown_parser(self):
"""Test getting unknown parser returns None."""
parser = HistoryParserFactory.get_parser("unknown")
assert parser is None
def test_get_supported_shells(self):
"""Test getting supported shells list."""
shells = HistoryParserFactory.get_supported_shells()
assert "bash" in shells
assert "zsh" in shells
assert "fish" in shells
def test_detect_shell_from_file(self):
"""Test shell detection from file path."""
assert HistoryParserFactory.detect_shell_from_file("/path/.bash_history") == "bash"
assert HistoryParserFactory.detect_shell_from_file("/path/.zsh_history") == "zsh"
assert HistoryParserFactory.detect_shell_from_file("/path/commands.json") == "fish"
def test_case_insensitive_shell(self):
"""Test shell type is case insensitive."""
parser1 = HistoryParserFactory.get_parser("BASH")
parser2 = HistoryParserFactory.get_parser("Bash")
assert isinstance(parser1, BashHistoryParser)
assert isinstance(parser2, BashHistoryParser)
class TestBaseParserValidation:
"""Tests for base parser validation methods."""
def test_valid_alias_names(self):
"""Test valid alias name validation."""
parser = BashHistoryParser()
assert parser.validate_alias_name("gco") is True
assert parser.validate_alias_name("_git") is True
assert parser.validate_alias_name("git_checkout") is True
def test_invalid_alias_names(self):
"""Test invalid alias name validation."""
parser = BashHistoryParser()
assert parser.validate_alias_name("") is False
assert parser.validate_alias_name("123abc") is False
assert parser.validate_alias_name("git-commit") is False
def test_sanitize_alias_name(self):
"""Test alias name sanitization."""
parser = BashHistoryParser()
assert parser.sanitize_alias_name("git checkout") == "gitcheckout"
assert parser.sanitize_alias_name("123test").startswith("alias")
assert parser.sanitize_alias_name("docker-compose") == "dockercompose"