""" Tests for the Database abstraction layer. All tests run against the real SQLite database at vehicle_database/vehicle_database.db. """ import pytest from console.db import Database @pytest.fixture(scope="module") def db(): """Provide a shared Database instance for all tests in this module.""" return Database() # ========================================================================= # Vehicle navigation # ========================================================================= class TestGetBrands: def test_returns_nonempty_list(self, db): brands = db.get_brands() assert isinstance(brands, list) assert len(brands) > 0 def test_each_brand_has_name_key(self, db): brands = db.get_brands() for b in brands: assert "name" in b def test_each_brand_has_id_and_country(self, db): brands = db.get_brands() for b in brands: assert "id" in b assert "country" in b class TestGetModels: def test_no_filter_returns_nonempty(self, db): models = db.get_models() assert isinstance(models, list) assert len(models) > 0 def test_filter_by_uppercase_brand(self, db): models = db.get_models(brand="TOYOTA") assert isinstance(models, list) assert len(models) > 0 def test_filter_by_lowercase_brand(self, db): """Brand filtering must be case-insensitive.""" models = db.get_models(brand="toyota") assert isinstance(models, list) assert len(models) > 0 def test_each_model_has_id_and_name(self, db): models = db.get_models() for m in models[:5]: assert "id" in m assert "name" in m class TestGetYears: def test_returns_list(self, db): years = db.get_years() assert isinstance(years, list) assert len(years) > 0 def test_filter_by_brand(self, db): years = db.get_years(brand="TOYOTA") assert isinstance(years, list) assert len(years) > 0 def test_each_year_has_id_and_year(self, db): years = db.get_years() for y in years[:5]: assert "id" in y assert "year" in y class TestGetEngines: def test_returns_list(self, db): engines = db.get_engines() assert isinstance(engines, list) assert len(engines) > 0 def test_filter_by_brand(self, db): engines = db.get_engines(brand="TOYOTA") assert isinstance(engines, list) assert len(engines) > 0 class TestGetModelYearEngine: def test_returns_list(self, db): result = db.get_model_year_engine( brand="TOYOTA", model="Corolla", year=2020, engine_id=None ) assert isinstance(result, list) # ========================================================================= # Parts catalog # ========================================================================= class TestGetCategories: def test_returns_exactly_12(self, db): categories = db.get_categories() assert isinstance(categories, list) assert len(categories) == 12 def test_each_has_expected_keys(self, db): categories = db.get_categories() for c in categories: assert "id" in c assert "name" in c class TestGetGroups: def test_returns_nonempty_for_known_category(self, db): groups = db.get_groups(category_id=2) assert isinstance(groups, list) assert len(groups) > 0 def test_each_group_has_name(self, db): groups = db.get_groups(category_id=2) for g in groups: assert "name" in g class TestGetParts: def test_returns_list(self, db): parts = db.get_parts() assert isinstance(parts, list) assert len(parts) > 0 def test_pagination(self, db): page1 = db.get_parts(page=1, per_page=5) page2 = db.get_parts(page=2, per_page=5) assert len(page1) <= 5 assert len(page2) <= 5 # Pages should contain different items (if enough data) if page1 and page2: ids1 = {p["id"] for p in page1} ids2 = {p["id"] for p in page2} assert ids1.isdisjoint(ids2) class TestGetPart: def test_returns_dict_with_oem_part_number(self, db): part = db.get_part(1) assert isinstance(part, dict) assert "oem_part_number" in part def test_includes_group_and_category_info(self, db): part = db.get_part(1) assert "group_name" in part assert "category_name" in part def test_nonexistent_returns_none(self, db): part = db.get_part(999999) assert part is None class TestGetAlternatives: def test_returns_list(self, db): alts = db.get_alternatives(1) assert isinstance(alts, list) class TestGetCrossReferences: def test_returns_list(self, db): refs = db.get_cross_references(1) assert isinstance(refs, list) class TestGetVehiclesForPart: def test_returns_list(self, db): vehicles = db.get_vehicles_for_part(1) assert isinstance(vehicles, list) assert len(vehicles) > 0 # ========================================================================= # Search # ========================================================================= class TestSearchParts: def test_returns_results_for_brake(self, db): results = db.search_parts("brake") assert isinstance(results, list) assert len(results) > 0 def test_each_result_has_expected_keys(self, db): results = db.search_parts("brake") for r in results[:3]: assert "id" in r assert "name" in r assert "oem_part_number" in r class TestSearchPartNumber: def test_returns_results_for_04465(self, db): results = db.search_part_number("04465") assert isinstance(results, list) assert len(results) > 0 def test_each_result_has_match_type(self, db): results = db.search_part_number("04465") for r in results: assert "match_type" in r # ========================================================================= # VIN cache # ========================================================================= class TestVinCache: def test_get_nonexistent_vin_returns_none(self, db): result = db.get_vin_cache("00000000000000000") assert result is None # ========================================================================= # Stats # ========================================================================= class TestGetStats: def test_returns_dict_with_required_keys(self, db): stats = db.get_stats() assert isinstance(stats, dict) assert "brands" in stats assert "models" in stats assert "parts" in stats def test_counts_are_positive(self, db): stats = db.get_stats() assert stats["brands"] > 0 assert stats["models"] > 0 assert stats["parts"] > 0 def test_includes_top_brands(self, db): stats = db.get_stats() assert "top_brands" in stats assert isinstance(stats["top_brands"], list) # ========================================================================= # Manufacturers # ========================================================================= class TestGetManufacturers: def test_returns_nonempty_list(self, db): manufacturers = db.get_manufacturers() assert isinstance(manufacturers, list) assert len(manufacturers) > 0 def test_each_has_name(self, db): manufacturers = db.get_manufacturers() for m in manufacturers: assert "name" in m assert "id" in m # ========================================================================= # Admin CRUD — smoke tests # ========================================================================= class TestCrossrefsPaginated: def test_returns_list(self, db): refs = db.get_crossrefs_paginated(page=1, per_page=5) assert isinstance(refs, list) assert len(refs) <= 5