mirror of
https://github.com/EDCD/EDMarketConnector.git
synced 2026-10-22 17:22:09 +03:00
147 lines
5.5 KiB
Python
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"
|