Files
2026-01-25 16:03:13 -05:00

147 lines
5.5 KiB
Python

# flake8: noqa
# mypy: ignore-errors
"""Test outfitting."""
import pytest
import json
from unittest.mock import patch
import outfitting
@pytest.fixture
def mock_modules_json(tmp_path):
"""Create a dummy modules.json file for the lookup function."""
data = {
"hpt_beamlaser_fixed_medium": {"mass": 4.0},
"federation_dropship_armour_grade1": {"mass": 0.0},
"int_engine_size2_class1": {"mass": 2.0},
}
modules_path = tmp_path / "modules.json"
modules_path.write_text(json.dumps(data))
return modules_path
class TestOutfitting:
def test_lookup_armour(self, mock_modules_json):
"""Verify that ship-specific armour is parsed correctly."""
module = {"id": 100, "name": "Federation_Dropship_Armour_Grade1"}
# Ship map uses internal symbol -> Display Name
ship_map = {"federation_dropship": "Federal Dropship"}
with patch("outfitting.config.app_dir_path", mock_modules_json.parent):
# Reset moduledata for the test
outfitting.moduledata = {}
result = outfitting.lookup(module, ship_map)
assert result["category"] == "standard"
assert result["ship"] == "Federal Dropship"
assert result["name"] == "Lightweight Alloy" # From armour_map
assert result["rating"] == "I"
def test_lookup_hardpoint_weapon(self, mock_modules_json):
"""Verify hardpoint parsing for standard weapons."""
module = {"id": 200, "name": "Hpt_BeamLaser_Fixed_Medium"}
with patch("outfitting.config.app_dir_path", mock_modules_json.parent):
outfitting.moduledata = {}
result = outfitting.lookup(module, {})
assert result["category"] == "hardpoint"
assert result["name"] == "Beam Laser"
assert result["mount"] == "Fixed"
assert result["class"] == "2"
assert result["rating"] == "D" # Assuming D is mapped for Medium Fixed Beam
def test_lookup_skip_cosmetics(self, mock_modules_json):
"""Verify that paintjobs and decals return None as uninteresting."""
module = {"id": 300, "name": "PaintJob_Anaconda_Default"}
with patch("outfitting.config.app_dir_path", mock_modules_json.parent):
result = outfitting.lookup(module, {})
assert result is None
def test_lookup_error_missing_name(self):
"""Verify ValueError is raised if the name field is missing."""
with pytest.raises(ValueError, match="missing a 'name' field"):
outfitting.lookup({"id": 400}, {})
def test_lookup_unknown_prefix(self, mock_modules_json):
"""Verify that an unknown module prefix triggers a ValueError."""
module = {"id": 500, "name": "Unknown_Module_Size1_Class1"}
with patch("outfitting.config.app_dir_path", mock_modules_json.parent):
with pytest.raises(ValueError, match="Unknown prefix"):
outfitting.lookup(module, {})
@patch("outfitting.lookup")
def test_export_structure(self, mock_lookup, tmp_path):
"""Verify the CSV export header and row generation."""
mock_lookup.return_value = {
"category": "hardpoint",
"name": "Laser",
"mount": "Fixed",
"guidance": "",
"ship": "",
"class": "1",
"rating": "E",
"id": 123,
}
data = {
"lastSystem": {"name": "Sol"},
"lastStarport": {
"name": "Daedalus",
"modules": {"1": {"id": 1, "name": "M_Name"}},
},
"timestamp": "2026-01-25",
}
export_file = tmp_path / "outfitting.csv"
outfitting.export(data, str(export_file))
content = export_file.read_text()
assert "System,Station,Category,Name" in content
assert "Sol,Daedalus, hardpoint, Laser" in content
@pytest.fixture(autouse=True)
def setup_moduledata(tmp_path):
"""Global setup for moduledata to satisfy the __debug__ mass checks."""
mock_json_content = {
"hpt_slugshot_fixed_large_range": {"mass": 8.0},
"int_guardianfsdbooster_size5": {"mass": 0.0},
"int_guardianpowerplant_size5": {"mass": 20.0},
"hpt_plasma_pointdefence_turret_tiny": {"mass": 0.5},
"int_dronecontrol_collection_size1_class1": {"mass": 2.0},
"int_hyperdrive_overcharge_size6_class3": {"mass": 40.0},
}
modules_json = tmp_path / "modules.json"
modules_json.write_text(json.dumps(mock_json_content))
with patch("outfitting.config.app_dir_path", tmp_path):
outfitting.moduledata = {} # Force reload
yield
class TestOutfittingAdvanced:
def test_lookup_guardian_internal_no_class(self):
"""Verify internal Guardian modules that lack a 'Class' in the symbol."""
# Guardian FSD Boosters only have Size, no Class (e.g., Int_GuardianFSDBooster_Size5)
module = {"id": 1002, "name": "Int_GuardianFSDBooster_Size5"}
result = outfitting.lookup(module, {})
assert result["name"] == "Guardian FSD Booster"
assert result["class"] == "5"
assert result["rating"] == "H" # Hardcoded in lookup logic
def test_lookup_drone_control_normalization(self):
"""Verify 'int' is popped for drone controllers to match standard_map."""
module = {"id": 1005, "name": "Int_DroneControl_Collection_Size1_Class1"}
result = outfitting.lookup(module, {})
assert result["category"] == "internal"
assert result["name"] == "Collector Limpet Controller"
assert result["class"] == "1"