import pytest import pandas as pd from unittest.mock import Mock from epc_api.client import EpcClient from model_data.Property import Property from open_uprn.OpenUprnClient import OpenUprnClient from model_data.EpcClean import EpcClean # Define some test data mock_epc_response = { "rows": [ { "inspection-date": "2023-06-01", "some-other-key": "some-value", "roof-description": "Roof Description", "walls-description": "Walls Description", "windows-description": "Windows Description", "mainheat-description": "Main Heating Description", "hotwater-description": "Hot Water Description", "transaction-type": "rental", "lighting-description": "Good Lighting Efficiency", }, { "inspection-date": "2023-05-01", "some-other-key": "some-other-value", "roof-description": "Roof Description", "walls-description": "Walls Description", "windows-description": "Windows Description", "mainheat-description": "Main Heating Description", "hotwater-description": "Hot Water Description", "transaction-type": "rental", "lighting-description": "Good Lighting Efficiency", } ] } mock_epc_response_dupe = { 'rows': [ { 'inspection-date': '2023-06-01', 'some-other-key': 'some-value', 'roof-description': 'Roof Description', 'walls-description': 'Walls Description', 'windows-description': 'Windows Description', 'mainheat-description': 'Main Heating Description', 'hotwater-description': 'Hot Water Description', "transaction-type": "rental", "lighting-description": "Good Lighting Efficiency", }, { 'inspection-date': '2023-05-01', 'some-other-key': 'some-other-value', 'roof-description': 'Roof Description', 'walls-description': 'Walls Description', 'windows-description': 'Windows Description', 'mainheat-description': 'Main Heating Description', 'hotwater-description': 'Hot Water Description', "transaction-type": "rental", "lighting-description": "Good Lighting Efficiency", }, { 'inspection-date': '2023-06-01', 'some-other-key': 'duplicate-date', 'roof-description': 'Roof Description', 'walls-description': 'Walls Description', 'windows-description': 'Windows Description', 'mainheat-description': 'Main Heating Description', 'hotwater-description': 'Hot Water Description', "transaction-type": "rental", "lighting-description": "Good Lighting Efficiency", } ] } class TestProperty: @pytest.fixture(autouse=True) def property_instance(self, mock_epc_client, mock_open_uprn_client, mock_cleaner): return Property("AB12CD", "Test Address", epc_client=mock_epc_client) @pytest.fixture(autouse=True) def property_instance_dupe_data(self, mock_epc_client_dupe_data): return Property("AB12CD", "Test Address", epc_client=mock_epc_client_dupe_data) @pytest.fixture def mock_epc_client(self): mock_epc_client = Mock(spec=EpcClient()) mock_epc_client.domestic.search.return_value = mock_epc_response.copy() mock_epc_client.auth_token = "mocked_auth_token" return mock_epc_client @pytest.fixture def mock_epc_client_dupe_data(self): mock_epc_client_dupe_data = Mock(spec=EpcClient()) mock_epc_client_dupe_data.domestic.search.return_value = mock_epc_response_dupe.copy() mock_epc_client_dupe_data.auth_token = "mocked_auth_token" return mock_epc_client_dupe_data @pytest.fixture def mock_open_uprn_client(self): mock_open_uprn_client = Mock(spec=OpenUprnClient(path=None, uprns=[12345])) mock_open_uprn_client.data = pd.DataFrame( [ {"UPRN": 12345, "longitude": 1.2345, "latitude": 2.3456}, {"UPRN": 12346, "longitude": 3.4567, "latitude": 4.5678} ] ) return mock_open_uprn_client @pytest.fixture def mock_cleaner(self): mock_cleaner = Mock(spec=EpcClean(data=[ {"roof-description": "Roof Description"}, {"walls-description": "Walls Description"}, {"windows-description": "Windows Description"}, {"mainheat-description": "Main Heating Description"}, {"hotwater-description": "Hot Water Description"}, {"lighting-description": "Good Lighting Efficiency"}, {"low-energy-lighting": 0} ])) mock_cleaner.cleaned = { "roof-description": [{"original_description": "Roof Description"}], "walls-description": [{"original_description": "Walls Description"}], "windows-description": [{"original_description": "Windows Description"}], "mainheat-description": [{"original_description": "Main Heating Description"}], "hotwater-description": [{"original_description": "Hot Water Description"}], "lighting-description": [{"original_description": "Good Lighting Efficiency"}] } return mock_cleaner def test_init(self, mock_epc_client): inst1 = Property("AB12CD", "Test Address", epc_client=mock_epc_client) # Should be mocked auth token assert inst1.epc_client.auth_token == "mocked_auth_token" inst2 = Property("AB12CD", "Test Address") assert inst2.epc_client.auth_token inst3 = Property("AB12CD", "Test Address", data={"some": "data"}) assert inst3.data == {"some": "data"} data = inst3.search_address_epc() assert data is None def test_search_address_epc(self, property_instance): # Call the method to test property_instance.search_address_epc() # Verify that the correct data is being returned assert property_instance.data == mock_epc_response["rows"][0] def test_search_address_epc_multiple_results(self, property_instance_dupe_data, mock_epc_client_dupe_data): with pytest.raises(Exception, match="More than one result found for this address - investigate me"): property_instance_dupe_data.search_address_epc() def test_get_coordinates(self, property_instance, mock_open_uprn_client): # Set up the mock OpenUprnClient property_instance.data = {"uprn": 12345} property_instance.get_coordinates(mock_open_uprn_client) # Verify that the coordinates are set correctly assert property_instance.coordinates == { "uprn": 12345, "longitude": 1.2345, "latitude": 2.3456 } def test_get_coordinates_without_open_uprn_data(self, property_instance, mock_open_uprn_client): # Modify the mock OpenUprnClient to not have read any data mock_open_uprn_client.data = None # Verify that ValueError is raised when OpenUprnClient data is None with pytest.raises(ValueError, match="OpenUprnClient has not read data"): property_instance.get_coordinates(mock_open_uprn_client) def test_get_components(self, property_instance, mock_cleaner, mock_epc_client): property_instance.search_address_epc() property_instance.get_components(mock_cleaner) # Verify that the components are set correctly assert property_instance.roof == {"original_description": "Roof Description"} assert property_instance.walls == {"original_description": "Walls Description"} assert property_instance.windows == {"original_description": "Windows Description"} assert property_instance.main_heating == {"original_description": "Main Heating Description"} assert property_instance.hotwater == {"original_description": "Hot Water Description"} def test_get_components_without_cleaned_data(self, property_instance, mock_cleaner): # Modify the mock EpcClean to not have cleaned data mock_cleaner.cleaned = {} # Verify that ValueError is raised when EpcClean doesn't contain cleaned data with pytest.raises(ValueError, match="Cleaner does not contain cleaned data"): property_instance.get_components(mock_cleaner) def test_get_components_no_data(self, property_instance, mock_cleaner): # Modify the mock cleaner to have no attributes for a specific description mock_cleaner.cleaned = { "roof-description": [] } # Verify that ValueError is raised when no attributes are found with pytest.raises(ValueError, match="Property does not contain data"): property_instance.get_components(mock_cleaner) def test_get_components_no_attributes(self, property_instance, mock_cleaner): # Modify the mock cleaner to have no attributes for a specific description mock_cleaner.cleaned = { "roof-description": [] } property_instance.search_address_epc() # Verify that ValueError is raised when no attributes are found with pytest.raises(ValueError, match="Either No attributes or multiple found for roof-description"): property_instance.get_components(mock_cleaner) def test_get_components_multiple_attributes(self, property_instance, mock_cleaner): # This shouldn't happen - it would mean a cleaning error property_instance.search_address_epc() mock_cleaner.cleaned = { "roof-description": [ {"original_description": "Roof Description"}, {"original_description": "Roof Description"} ] } # Verify that ValueError is raised when multiple attributes are found with pytest.raises(ValueError, match="Either No attributes or multiple found for roof-description"): property_instance.get_components(mock_cleaner)