| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- import pytest
- from PySide6.QtWidgets import QMainWindow
- from hookvision.models import HookState, Config
- from hookvision.main_window import MainWindow
- from hookvision.config_loader import load_config
- class TestParseAIObjects:
- def test_none_payload(self, qapp, sample_config_path):
- config = load_config(sample_config_path)
- mw = MainWindow(config)
- assert mw.parse_ai_objects(None, 640, 360) == []
- assert mw.parse_ai_objects({}, 640, 360) == []
- def test_empty_objects(self, qapp, sample_config_path):
- config = load_config(sample_config_path)
- mw = MainWindow(config)
- result = mw.parse_ai_objects({"width": 640, "height": 360, "objects": []}, 640, 360)
- assert result == []
- def test_valid_objects(self, qapp, sample_config_path):
- config = load_config(sample_config_path)
- mw = MainWindow(config)
- payload = {
- "width": 640,
- "height": 360,
- "objects": [
- "0|100|200|50|80|hoist",
- "0|300|150|40|60|cup",
- ]
- }
- result = mw.parse_ai_objects(payload, 640, 360)
- assert len(result) == 2
- assert result[0]["label"] == "hook"
- assert result[0]["x"] == 100
- assert result[0]["y"] == 200
- assert result[0]["color"] == (0, 0, 255)
- assert result[1]["label"] == "lug"
- assert result[1]["color"] == (255, 0, 0)
- def test_scale_transformation(self, qapp, sample_config_path):
- config = load_config(sample_config_path)
- mw = MainWindow(config)
- payload = {
- "width": 320,
- "height": 180,
- "objects": ["0|50|50|100|100|hoist"],
- }
- result = mw.parse_ai_objects(payload, 640, 360)
- assert result[0]["x"] == 100
- assert result[0]["y"] == 100
- assert result[0]["w"] == 200
- assert result[0]["h"] == 200
- def test_ready_object_excluded(self, qapp, sample_config_path):
- config = load_config(sample_config_path)
- mw = MainWindow(config)
- payload = {
- "width": 640,
- "height": 360,
- "objects": [
- "0|100|200|50|80|hoist",
- "0|300|150|40|60|ready",
- ]
- }
- result = mw.parse_ai_objects(payload, 640, 360, include_ready=False)
- assert len(result) == 1
- assert result[0]["label"] == "hook"
- def test_ready_object_included(self, qapp, sample_config_path):
- config = load_config(sample_config_path)
- mw = MainWindow(config)
- payload = {
- "width": 640,
- "height": 360,
- "objects": [
- "0|100|200|50|80|ready",
- ]
- }
- result = mw.parse_ai_objects(payload, 640, 360, include_ready=True)
- assert len(result) == 1
- assert "ready" in result[0]["label"]
- def test_malformed_objects_skipped(self, qapp, sample_config_path):
- config = load_config(sample_config_path)
- mw = MainWindow(config)
- payload = {
- "width": 640,
- "height": 360,
- "objects": [
- "not_enough_parts",
- "0|abc|def|ghi|jkl|hoist",
- "0|100|200|50|80|hoist",
- ]
- }
- result = mw.parse_ai_objects(payload, 640, 360)
- assert len(result) == 1
- def test_zero_orig_size_no_division_error(self, qapp, sample_config_path):
- config = load_config(sample_config_path)
- mw = MainWindow(config)
- payload = {
- "width": 0,
- "height": 0,
- "objects": ["0|100|200|50|80|hoist"],
- }
- result = mw.parse_ai_objects(payload, 640, 360)
- assert len(result) == 1
- assert result[0]["x"] == 100
- assert result[0]["y"] == 200
- class TestRectsIntersect:
- def setup_method(self):
- self.mw = MainWindow(Config())
- def test_overlapping(self, qapp):
- mw = MainWindow(Config())
- a = {"x": 0, "y": 0, "w": 100, "h": 100}
- b = {"x": 50, "y": 50, "w": 100, "h": 100}
- assert mw.rects_intersect(a, b) is True
- def test_non_overlapping(self, qapp):
- mw = MainWindow(Config())
- a = {"x": 0, "y": 0, "w": 50, "h": 50}
- b = {"x": 100, "y": 100, "w": 50, "h": 50}
- assert mw.rects_intersect(a, b) is False
- def test_touching_edge_intersecting(self, qapp):
- mw = MainWindow(Config())
- a = {"x": 0, "y": 0, "w": 50, "h": 50}
- b = {"x": 50, "y": 0, "w": 50, "h": 50}
- # 边沿相接触视为相交(用于挂钩/吊耳判定的宽松策略)
- assert mw.rects_intersect(a, b) is True
- def test_one_contains_other(self, qapp):
- mw = MainWindow(Config())
- a = {"x": 0, "y": 0, "w": 200, "h": 200}
- b = {"x": 50, "y": 50, "w": 50, "h": 50}
- assert mw.rects_intersect(a, b) is True
- class TestHasIntersectingPair:
- def test_no_pairs(self, qapp):
- mw = MainWindow(Config())
- assert mw._has_intersecting_pair(None, None) is False
- def test_left_pair_intersects(self, qapp):
- mw = MainWindow(Config())
- left_pair = (
- {"x": 0, "y": 0, "w": 100, "h": 100},
- {"x": 50, "y": 50, "w": 100, "h": 100},
- )
- assert mw._has_intersecting_pair(left_pair, None) is True
- def test_right_pair_intersects(self, qapp):
- mw = MainWindow(Config())
- right_pair = (
- {"x": 0, "y": 0, "w": 100, "h": 100},
- {"x": 50, "y": 50, "w": 100, "h": 100},
- )
- assert mw._has_intersecting_pair(None, right_pair) is True
- def test_pair_not_intersecting(self, qapp):
- mw = MainWindow(Config())
- pair = (
- {"x": 0, "y": 0, "w": 50, "h": 50},
- {"x": 100, "y": 100, "w": 50, "h": 50},
- )
- assert mw._has_intersecting_pair(pair, None) is False
|