From 5f17e4bad9e2d3be3057155bd9128f68e42603bd Mon Sep 17 00:00:00 2001 From: David Reed <212698+dreed47@users.noreply.github.com> Date: Fri, 14 May 2021 23:06:02 -0400 Subject: [PATCH] added config_flow and test cases --- .gitignore | 1 + README.md | 16 +- custom_components/__init__.py | 1 + custom_components/redfin/__init__.py | 53 +++++- custom_components/redfin/config_flow.py | 179 ++++++++++++++++++ custom_components/redfin/const.py | 21 ++ custom_components/redfin/manifest.json | 3 +- custom_components/redfin/sensor.py | 82 ++++---- custom_components/redfin/translations/en.json | 44 +++++ requirements.test.txt | 11 ++ tests/README.md | 8 +- tests/__init__.py | 1 + tests/test_api.py | 29 +++ tests/test_config_flow.py | 26 +++ tests/test_init.py | 8 + tests/{test.py => test_redfin_wrapper.py} | 11 +- 16 files changed, 434 insertions(+), 60 deletions(-) create mode 100644 custom_components/__init__.py create mode 100644 custom_components/redfin/config_flow.py create mode 100644 custom_components/redfin/const.py create mode 100644 custom_components/redfin/translations/en.json create mode 100644 requirements.test.txt create mode 100644 tests/__init__.py create mode 100644 tests/test_api.py create mode 100644 tests/test_config_flow.py create mode 100644 tests/test_init.py rename tests/{test.py => test_redfin_wrapper.py} (92%) diff --git a/.gitignore b/.gitignore index f26500f..1507065 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ venv .venv .vscode +*.pyc diff --git a/README.md b/README.md index cd20773..e3f939c 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ This is a _Custom Integration_ for [Home Assistant](https://www.home-assistant.io/). It uses the unofficial [Redfin](https://www.redfin.com) API to get property value estimates. -![GitHub release](https://img.shields.io/badge/release-v1.0.2-blue) +![GitHub release](https://img.shields.io/badge/release-v1.1.0-blue) [![hacs_badge](https://img.shields.io/badge/HACS-Default-orange.svg)](https://github.com/custom-components/hacs) There is currently support for the Sensor device type within Home Assistant. @@ -22,7 +22,11 @@ To manually add Redfin to your installation, create this folder structure in you Then drop the following files into that folder: ```yaml +translations/en.json __init__.py +config_flow.py +const.py +hacs.json sensor.py manifest.json ``` @@ -33,15 +37,7 @@ You will need the Redfin property ID for each property you’d like to track. Th For example, given this Redfin URL: https://www.redfin.com/DC/Washington/1745-Q-St-NW-20009/unit-3/home/9860590 the property ID is 9860590. -To enable this sensor, add the following lines to your `configuration.yaml`. - -```yaml -sensor: - - platform: redfin - property_ids: - - "12345678" - - "34567890" -``` +To enable this sensor, add new Redfin integration component in the Home Assistant UI and follow the prompts to add your properties. The sensor provides the following attributes: diff --git a/custom_components/__init__.py b/custom_components/__init__.py new file mode 100644 index 0000000..f3b0d32 --- /dev/null +++ b/custom_components/__init__.py @@ -0,0 +1 @@ +"""""" diff --git a/custom_components/redfin/__init__.py b/custom_components/redfin/__init__.py index 9a66f1c..7d02f65 100644 --- a/custom_components/redfin/__init__.py +++ b/custom_components/redfin/__init__.py @@ -1 +1,52 @@ -"""The Redfin component.""" +"""Redfin Component.""" +import logging + +from homeassistant import config_entries, core + +from homeassistant.core import HomeAssistant +from homeassistant.helpers.typing import ConfigType + +from .const import DOMAIN, CONF_PROPERTIES +from homeassistant.const import CONF_NAME, CONF_SCAN_INTERVAL + +_LOGGER = logging.getLogger(__name__) + + +async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: + # We allow setup only through config flow type of config + return True + + +async def async_setup_entry( + hass: core.HomeAssistant, entry: config_entries.ConfigEntry +) -> bool: + """Set up Redfin component from a ConfigEntry.""" + hass.data.setdefault(DOMAIN, {}) + hass_data = dict() + hass_data[CONF_NAME] = entry.options[CONF_NAME] + hass_data[CONF_SCAN_INTERVAL] = entry.options[CONF_SCAN_INTERVAL] + hass_data[CONF_PROPERTIES] = entry.options[CONF_PROPERTIES] + # Registers update listener to update config entry when options are updated. + unsub_options_update_listener = entry.add_update_listener(options_update_listener) + # Store a reference to the unsubscribe function to cleanup if an entry is unloaded. + hass_data["unsub_options_update_listener"] = unsub_options_update_listener + hass.data[DOMAIN][entry.entry_id] = hass_data + + # Forward the setup to the sensor component. + hass.async_create_task( + hass.config_entries.async_forward_entry_setup(entry, "sensor") + ) + return True + + +async def options_update_listener( + hass: core.HomeAssistant, config_entry: config_entries.ConfigEntry +): + _LOGGER.debug("%s options updated: %s", DOMAIN, config_entry.as_dict()["options"]) + """Handle options update.""" + try: + result = await hass.config_entries.async_reload(config_entry.entry_id) + except config_entries.OperationNotAllowed: + _LOGGER.error("Entry cannot be reloaded. ID = %s Restart is required.", config_entry.entry_id) + except config_entries.UnknownEntry: + _LOGGER.error("Invalid entry specified. ID = %s", config_entry.entry_id) diff --git a/custom_components/redfin/config_flow.py b/custom_components/redfin/config_flow.py new file mode 100644 index 0000000..4809a93 --- /dev/null +++ b/custom_components/redfin/config_flow.py @@ -0,0 +1,179 @@ +from copy import deepcopy +import logging +from typing import Any, Dict, Optional + +from homeassistant import config_entries, core +from homeassistant.const import CONF_NAME, CONF_SCAN_INTERVAL +from homeassistant.core import callback +import homeassistant.helpers.config_validation as cv +import voluptuous as vol +from homeassistant.helpers.entity_registry import ( + async_entries_for_config_entry, + async_get_registry, +) + +from .const import (CONF_PROPERTIES, DOMAIN, DEFAULT_SCAN_INTERVAL, DEFAULT_NAME, + CONF_PROPERTY_ID, CONF_SCAN_INTERVAL_MIN, CONF_SCAN_INTERVAL_MAX) + +_LOGGER = logging.getLogger(__name__) + +CONF_SCHEMA = vol.Schema( + { + vol.Required(CONF_NAME, default=DEFAULT_NAME): str, + vol.Optional(CONF_SCAN_INTERVAL, default=DEFAULT_SCAN_INTERVAL + ): vol.All(vol.Coerce(int), vol.Range(min=CONF_SCAN_INTERVAL_MIN, max=CONF_SCAN_INTERVAL_MAX)) + } +) +PROPERTY_SCHEMA = vol.Schema( + { + vol.Optional(CONF_PROPERTY_ID): cv.string, + vol.Optional("add_another"): cv.boolean, + } +) + + +class RedfinConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): + """Redfin config flow.""" + + VERSION = 1 + + data: Optional[Dict[str, Any]] + options: Optional[Dict[str, Any]] = {} + + async def async_step_user(self, user_input: Optional[Dict[str, Any]] = None): + """Invoked when a user initiates a flow via the user interface.""" + errors: Dict[str, str] = {} + + if self._async_current_entries(): + return self.async_abort(reason="single_instance_allowed") + if self.hass.data.get(DOMAIN): + return self.async_abort(reason="single_instance_allowed") + + if user_input is not None: + self.data = dict() # user_input + self.options = user_input + self.options[CONF_PROPERTIES] = [] + # Return the form of the next step. + return await self.async_step_property() + + return self.async_show_form( + step_id="user", data_schema=CONF_SCHEMA, errors=errors + ) + + async def async_step_property(self, user_input: Optional[Dict[str, Any]] = None): + """Second step in config flow to add a property id's.""" + errors: Dict[str, str] = {} + + if user_input is not None: + + # check for duplicate property id's + is_dup = False + for params in self.options[CONF_PROPERTIES]: + if user_input[CONF_PROPERTY_ID] == params[CONF_PROPERTY_ID]: + is_dup = True + if is_dup == True: + errors["base"] = "duplicate_property_id" + else: + self.options[CONF_PROPERTIES].append( + {"property_id": user_input[CONF_PROPERTY_ID]} + ) + + if not errors: + # If user ticked the box show this form again so they can add + if user_input.get("add_another", False): + return await self.async_step_property() + + # User is done adding properties, create the config entry. + _LOGGER.debug("%s component added a new config entry: %s", DOMAIN, self.options) + return self.async_create_entry(title=self.options["name"], data=self.data, options=self.options) + + return self.async_show_form( + step_id="property", data_schema=PROPERTY_SCHEMA, errors=errors + ) + + @staticmethod + @callback + def async_get_options_flow(config_entry): + return OptionsFlowHandler(config_entry) + + +class OptionsFlowHandler(config_entries.OptionsFlow): + """Handles options flow for the component.""" + + def __init__(self, config_entry: config_entries.ConfigEntry) -> None: + self.config_entry = config_entry + + async def async_step_init( + self, user_input: Dict[str, Any] = None + ) -> Dict[str, Any]: + """Manage the options for the component.""" + errors: Dict[str, str] = {} + # Grab all configured propert id's from the entity registry so we can populate the + # multi-select dropdown that will allow a user to remove a property. + entity_registry = await async_get_registry(self.hass) + entries = async_entries_for_config_entry( + entity_registry, self.config_entry.entry_id + ) + # Default value for our multi-select. + all_properties = {e.entity_id: e.original_name for e in entries} + property_map = {e.entity_id: e for e in entries} + + if user_input is not None: + updated_properties = deepcopy(self.config_entry.options[CONF_PROPERTIES]) + + # Remove any unchecked properties. + removed_entities = [ + entity_id + for entity_id in property_map.keys() + if entity_id not in user_input["properties"] + ] + for entity_id in removed_entities: + # Unregister from HA + entity_registry.async_remove(entity_id) + # Remove from our configured properties. + entry = property_map[entity_id] + property_id = entry.unique_id + updated_properties = [e for e in updated_properties if e[CONF_PROPERTY_ID] != property_id] + + if user_input.get(CONF_PROPERTY_ID): + + # check for duplicate property id's + is_dup = False + for params in updated_properties: + if user_input[CONF_PROPERTY_ID] == params[CONF_PROPERTY_ID]: + is_dup = True + if is_dup == True: + errors["base"] = "duplicate_property_id" + else: + # Add the new property. + updated_properties.append( + {CONF_PROPERTY_ID: user_input[CONF_PROPERTY_ID]} + ) + + if not errors: + # Value of data will be set on the options property of the config_entry + # instance. + return self.async_create_entry( + title="", + data={ + CONF_NAME: user_input[CONF_NAME], + CONF_SCAN_INTERVAL: user_input[CONF_SCAN_INTERVAL], + CONF_PROPERTIES: updated_properties + }, + ) + + options_schema = vol.Schema( + { + vol.Optional("properties", default=list(all_properties.keys())): cv.multi_select( + all_properties + ), + vol.Optional(CONF_NAME, default=self.config_entry.options[CONF_NAME]): str, + vol.Optional(CONF_SCAN_INTERVAL, default=self.config_entry.options[CONF_SCAN_INTERVAL] + ): vol.All(vol.Coerce(int), vol.Range(min=CONF_SCAN_INTERVAL_MIN, max=CONF_SCAN_INTERVAL_MAX)), + vol.Optional(CONF_PROPERTY_ID): cv.string, + } + ) + + return self.async_show_form( + step_id="init", data_schema=options_schema, errors=errors + ) diff --git a/custom_components/redfin/const.py b/custom_components/redfin/const.py new file mode 100644 index 0000000..e724a84 --- /dev/null +++ b/custom_components/redfin/const.py @@ -0,0 +1,21 @@ +DOMAIN = "redfin" + +DEFAULT_NAME = "Redfin" + +ATTRIBUTION = "Data provided by Redfin.com" +ATTR_AMOUNT = "amount" +ATTR_AMOUNT_FORMATTED = "amount_formatted" +ATTR_ADDRESS = "address" +ATTR_FULL_ADDRESS = "full_address" +ATTR_CURRENCY = "amount_currency" +ATTR_STREET_VIEW = "street_view" +ATTR_REDFIN_URL = "redfin_url" + +CONF_PROPERTIES = "properties" +CONF_PROPERTY_ID = "property_id" +CONF_PROPERTY_IDS = "property_ids" +DEFAULT_SCAN_INTERVAL = 60 +CONF_SCAN_INTERVAL_MIN = 5 +CONF_SCAN_INTERVAL_MAX = 600 + +ICON = "mdi:home-variant" diff --git a/custom_components/redfin/manifest.json b/custom_components/redfin/manifest.json index 82352ef..e5e2499 100644 --- a/custom_components/redfin/manifest.json +++ b/custom_components/redfin/manifest.json @@ -7,5 +7,6 @@ "codeowners": ["@dreed47"], "requirements": ["redfin==0.1.1"], "iot_class": "cloud_polling", - "version": "1.0.2" + "version": "1.1.0", + "config_flow": true } diff --git a/custom_components/redfin/sensor.py b/custom_components/redfin/sensor.py index 7b0b283..848faa7 100644 --- a/custom_components/redfin/sensor.py +++ b/custom_components/redfin/sensor.py @@ -4,30 +4,21 @@ import voluptuous as vol from redfin import Redfin +from homeassistant import config_entries, core +from .const import (DEFAULT_NAME, DOMAIN, CONF_PROPERTIES, ATTRIBUTION, + CONF_PROPERTY_IDS, ICON, CONF_PROPERTY_ID, ATTR_AMOUNT, ATTR_AMOUNT_FORMATTED, + ATTR_ADDRESS, ATTR_FULL_ADDRESS, ATTR_CURRENCY, ATTR_STREET_VIEW, ATTR_REDFIN_URL) +#from homeassistant.helpers.aiohttp_client import async_get_clientsession +from homeassistant.core import callback from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity -from homeassistant.const import ATTR_ATTRIBUTION, CONF_NAME +from homeassistant.helpers.event import async_track_time_interval +from homeassistant.const import ATTR_ATTRIBUTION, CONF_NAME, CONF_SCAN_INTERVAL import homeassistant.helpers.config_validation as cv _LOGGER = logging.getLogger(__name__) _RESOURCE = "https://www.redfin.com" -ATTRIBUTION = "Data provided by Redfin.com" - -CONF_PROPERTY_IDS = "property_ids" - -DEFAULT_NAME = "Redfin" -NAME = "redfin" - -ICON = "mdi:home-variant" - -ATTR_AMOUNT = "amount" -ATTR_AMOUNT_FORMATTED = "amount_formatted" -ATTR_ADDRESS = "address" -ATTR_FULL_ADDRESS = "full_address" -ATTR_CURRENCY = "amount_currency" -ATTR_STREET_VIEW = "street_view" -ATTR_REDFIN_URL = "redfin_url" PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( { @@ -39,34 +30,34 @@ SCAN_INTERVAL = timedelta(hours=12) -def setup_platform(hass, config, add_entities, discovery_info=None): - """Set up the Redfin sensor.""" - - name = config.get(CONF_NAME) - properties = config[CONF_PROPERTY_IDS] - - sensors = [] - for property_id in properties: - params = {"property_id": property_id} - sensors.append(RedfinDataSensor(name, params)) - add_entities(sensors, True) +async def async_setup_entry( + hass: core.HomeAssistant, + config_entry: config_entries.ConfigEntry, + async_add_entities, +): + """Setup sensors from a config entry created in the integrations UI.""" + config = hass.data[DOMAIN][config_entry.entry_id] + sensors = [RedfinDataSensor(config[CONF_NAME], params, config[CONF_SCAN_INTERVAL]) for params in config[CONF_PROPERTIES]] + async_add_entities(sensors, update_before_add=True) class RedfinDataSensor(SensorEntity): """Implementation of a Redfin sensor.""" - def __init__(self, name, params): + def __init__(self, name, params, interval): """Initialize the sensor.""" self._name = name self.params = params self.data = None self.address = None + self.property_id = params[CONF_PROPERTY_ID] self._state = None + self._interval = timedelta(minutes=interval) @property def unique_id(self): """Return the property_id.""" - return self.params["property_id"] + return self.params[CONF_PROPERTY_ID] @property def name(self): @@ -90,6 +81,7 @@ def extra_state_attributes(self): attributes = self.data attributes[ATTR_ADDRESS] = self.address attributes[ATTR_ATTRIBUTION] = ATTRIBUTION + attributes[CONF_PROPERTY_ID] = self.params[CONF_PROPERTY_ID] return attributes @property @@ -97,43 +89,53 @@ def icon(self): """Icon to use in the frontend, if any.""" return ICON + async def async_added_to_hass(self): + """Start custom polling.""" + + @callback + def async_update(event_time=None): + """Update the entity.""" + self.async_schedule_update_ha_state(True) + + async_track_time_interval(self.hass, async_update, self._interval) + def update(self): """Get the latest data and update the states.""" client = Redfin() try: - avm_details = client.avm_details(self.params["property_id"], "") + avm_details = client.avm_details(self.params[CONF_PROPERTY_ID], "") if avm_details["resultCode"] != 0: _LOGGER.error("The API returned: %s", avm_details["errorMessage"]) except: _LOGGER.error("Unable to retrieve data from %s", _RESOURCE) return - _LOGGER.debug("The avm_details API returned: %s for property id: %s", - avm_details["errorMessage"], self.params["property_id"]) + _LOGGER.debug("%s - The avm_details API returned: %s for property id: %s", + self._name, avm_details["errorMessage"], self.params[CONF_PROPERTY_ID]) try: above_the_fold = client.above_the_fold( - self.params["property_id"], "") + self.params[CONF_PROPERTY_ID], "") if above_the_fold["resultCode"] != 0: _LOGGER.error("The API returned: %s", above_the_fold["errorMessage"]) except: _LOGGER.error("Unable to retrieve data from %s", _RESOURCE) return - _LOGGER.debug("The above_the_fold API returned: %s for property id: %s", - above_the_fold["errorMessage"], self.params["property_id"]) + _LOGGER.debug("%s - The above_the_fold API returned: %s for property id: %s", + self._name, above_the_fold["errorMessage"], self.params[CONF_PROPERTY_ID]) try: - info_panel = client.info_panel(self.params["property_id"], "") + info_panel = client.info_panel(self.params[CONF_PROPERTY_ID], "") if info_panel["resultCode"] != 0: _LOGGER.error("The API returned: %s", info_panel["errorMessage"]) except: _LOGGER.error("Unable to retrieve data from %s", _RESOURCE) return - _LOGGER.debug("The info_panel API returned: %s for property id: %s", - info_panel["errorMessage"], self.params["property_id"]) + _LOGGER.debug("%s - The info_panel API returned: %s for property id: %s", + self._name, info_panel["errorMessage"], self.params[CONF_PROPERTY_ID]) if 'url' in info_panel["payload"]["mainHouseInfo"]: redfinUrl = _RESOURCE + \ @@ -174,11 +176,13 @@ def update(self): details[ATTR_FULL_ADDRESS] = self.address details[ATTR_REDFIN_URL] = redfinUrl details[ATTR_STREET_VIEW] = streetViewUrl + details[CONF_PROPERTY_ID] = self.params[CONF_PROPERTY_ID] self.data = details if self.data is not None: self._state = self.data[ATTR_AMOUNT_FORMATTED] + self.property_id = self.params[CONF_PROPERTY_ID] else: self._state = None _LOGGER.error("Unable to get Redfin estimate from response") diff --git a/custom_components/redfin/translations/en.json b/custom_components/redfin/translations/en.json new file mode 100644 index 0000000..9ac817a --- /dev/null +++ b/custom_components/redfin/translations/en.json @@ -0,0 +1,44 @@ +{ + "config": { + "abort": { + "single_instance_allowed": "Only a single configuration of Redfin component is allowed." + }, + "error": { + "duplicate_property_id": "Duplicate property Id" + }, + "step": { + "user": { + "data": { + "name": "Name", + "scan_interval": "Interval between data updates (Min)" + }, + "description": "Setup a new Redfin integration.", + "title": "Redfin" + }, + "property": { + "data": { + "add_another": "Add another property?", + "name": "Name of the sensor.", + "property_id": "Property ID" + }, + "description": "Add a Property ID, check the box to add another.", + "title": "Add a Redfin Property ID" + } + } + }, + "options": { + "error": { + "duplicate_property_id": "Duplicate property Id" + }, + "step": { + "init": { + "title": "Manage Properties", + "data": { + "scan_interval": "Interval between data updates (Min)", + "property_id": "New Property ID" + }, + "description": "Remove existing properties or add a new property." + } + } + } +} diff --git a/requirements.test.txt b/requirements.test.txt new file mode 100644 index 0000000..fadb5ce --- /dev/null +++ b/requirements.test.txt @@ -0,0 +1,11 @@ +# Strictly for tests +# pip3 install -r requirements.test.txt +bleak +attrs==20.3.0 +pytest +pytest-cov==2.10.1 +pytest-homeassistant-custom-component +# From the manifest.json for this component +redfin==0.1.1 +# to run tests use +# pytest tests/.py -v diff --git a/tests/README.md b/tests/README.md index 0de0b4d..f23b9bb 100644 --- a/tests/README.md +++ b/tests/README.md @@ -5,10 +5,8 @@ Create a virtual environment and install all necessary dependencies: ```bash python3 -m venv .venv source .venv/bin/activate -python3 -m pip install redfin +pip3 install -r requirements.test.txt ``` -# TODO - -Convert these tests to [`pytest`](https://docs.pytest.org/en/latest/). While tests aren't required to publish a custom component for Home Assistant, they will generally make development less error prone. Home Assistant uses [`pytest`](https://docs.pytest.org/en/latest/) for its tests. -| +To run tests use: +`pytest tests/.py -s -vv` diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..f3b0d32 --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1 @@ +"""""" diff --git a/tests/test_api.py b/tests/test_api.py new file mode 100644 index 0000000..2c0d7ce --- /dev/null +++ b/tests/test_api.py @@ -0,0 +1,29 @@ +"""Test component api.""" +from homeassistant.setup import async_setup_component +from custom_components.redfin.const import DOMAIN +from redfin import Redfin + +client = Redfin() + + +def test_api_call(): + """ """ + + address = '1712 Glen Echo Rd Unit C,Nashville, TN 37215' + + response = client.search(address) + assert response['errorMessage'] == "Success" + + url = response['payload']['exactMatch']['url'] + initial_info = client.initial_info(url) + assert initial_info['errorMessage'] == "Success" + + property_id = initial_info['payload']['propertyId'] + mls_data = client.below_the_fold(property_id) + assert mls_data['errorMessage'] == "Success" + + above_the_fold = client.above_the_fold(property_id, "") + assert above_the_fold['errorMessage'] == "Success" + + info_panel = client.info_panel(property_id, "") + assert info_panel['errorMessage'] == "Success" diff --git a/tests/test_config_flow.py b/tests/test_config_flow.py new file mode 100644 index 0000000..40cb6ce --- /dev/null +++ b/tests/test_config_flow.py @@ -0,0 +1,26 @@ +"""Tests for the config flow.""" +from unittest import mock + +from homeassistant.const import CONF_DEVICE_CLASS, CONF_DEVICE_ID, CONF_HOST, CONF_PORT +from pytest_homeassistant_custom_component.common import MockConfigEntry, patch + +from custom_components.redfin import config_flow +from custom_components.redfin.const import DOMAIN + + +async def test_flow_user_init(hass): + """Test the initialization of the form in the first step of the config flow.""" + result = await hass.config_entries.flow.async_init( + config_flow.DOMAIN, context={"source": "user"} + ) + expected = { + "data_schema": config_flow.CONF_SCHEMA, + "description_placeholders": None, + "errors": {}, + "flow_id": mock.ANY, + "handler": "redfin", + "step_id": "user", + "type": "form", + "last_step": None, + } + assert expected == result diff --git a/tests/test_init.py b/tests/test_init.py new file mode 100644 index 0000000..618e669 --- /dev/null +++ b/tests/test_init.py @@ -0,0 +1,8 @@ +"""Test component setup.""" +from homeassistant.setup import async_setup_component +from custom_components.redfin.const import DOMAIN + + +async def test_async_setup(hass): + """Test the component gets setup.""" + assert await async_setup_component(hass, DOMAIN, {}) is True diff --git a/tests/test.py b/tests/test_redfin_wrapper.py similarity index 92% rename from tests/test.py rename to tests/test_redfin_wrapper.py index d7d9f3e..7ada277 100644 --- a/tests/test.py +++ b/tests/test_redfin_wrapper.py @@ -12,6 +12,9 @@ address = '1712 Glen Echo Rd Unit C,Nashville, TN 37215' response = client.search(address) + +pp.pprint(response['errorMessage']) + url = response['payload']['exactMatch']['url'] initial_info = client.initial_info(url) @@ -47,9 +50,9 @@ else: amountFormatted = 'Not Set' -pp.pprint(initial_info) -pp.pprint(mls_data) -pp.pprint(above_the_fold) -pp.pprint(avm_details) +# pp.pprint(initial_info) +# pp.pprint(mls_data) +# pp.pprint(above_the_fold) +# pp.pprint(avm_details) print("...end of tests")