Skip to content

Commit

Permalink
Merge pull request #35 from robert-alfaro/bugfix/test-fixes
Browse files Browse the repository at this point in the history
Fix various unit tests
  • Loading branch information
kingy444 authored Feb 15, 2024
2 parents 538dd3d + 7e1e7e6 commit e60af51
Show file tree
Hide file tree
Showing 11 changed files with 101 additions and 51 deletions.
6 changes: 5 additions & 1 deletion aiopvapi/helpers/api_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,11 @@ def _parse(self, *keys, converter=None, data=None):
_LOGGER.debug("Key '%s' missing", err)
return None
if converter:
return converter(val)
try:
return converter(val)
except UnicodeDecodeError as err:
_LOGGER.error("UnicodeDecodeError converting '%s', err=%s", val, err)
return None
return val


Expand Down
1 change: 1 addition & 0 deletions aiopvapi/helpers/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
FWVERSION = "fwversion"
USER_DATA = "userData"

MID_POSITION_V2 = 32767
MAX_POSITION_V2 = 65535

SHADE_BATTERY_STRENGTH = "batteryStrength"
Expand Down
2 changes: 1 addition & 1 deletion aiopvapi/resources/scene.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ async def activate(self) -> list[int]:
_val = await self.request.get(
self.base_path, params={ATTR_SCENE_ID: self._id}
)
# v2 returns format {'sceneIds': ids} so flattening the list to align v3
# v2 returns format {'shadeIds': ids} so flattening the list to align v3
_val = _val.get(ATTR_SHADE_IDS)
# should return an array of ID's that belong to the scene
return _val
1 change: 0 additions & 1 deletion requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,3 @@ nox
pytest-cov
python-coveralls
wheel
json
2 changes: 1 addition & 1 deletion tests/fake_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ def __init__(self, *, loop, api_version=2):
web.put("/api/shades/{shade_id}", self.add_shade_to_room),
web.delete("/api/sceneMembers", self.remove_shade_from_scene),
web.get("/api/fwversion", self.get_fwversion),
web.get("/userdata", self.get_user_data),
web.get("/api/userdata", self.get_user_data),
]
)
self.runner = None
Expand Down
10 changes: 7 additions & 3 deletions tests/test_apiresource.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from unittest.mock import Mock

from aiopvapi.helpers.api_base import ApiResource, ApiEntryPoint
from aiopvapi.helpers.aiorequest import AioRequest
from tests.fake_server import TestFakeServer, FAKE_BASE_URL


Expand All @@ -13,9 +14,10 @@ def get_resource_uri(self):

def get_resource(self):
"""Get the resource being tested."""
_request = Mock()
_request = Mock(spec=AioRequest)
_request.hub_ip = FAKE_BASE_URL
_request.api_version = 2
_request.api_path = "api"
return ApiResource(_request, "base", self.get_resource_raw_data())

def setUp(self):
Expand All @@ -31,7 +33,7 @@ def test_id_property(self):

def test_full_path(self):
self.assertEqual(
self.resource._base_path, "http://{}/api/base".format(FAKE_BASE_URL)
self.resource.base_path, "http://{}/api/base".format(FAKE_BASE_URL)
)

def test_name_property(self):
Expand Down Expand Up @@ -60,11 +62,12 @@ def get_resource(self):
_request = Mock()
_request.hub_ip = FAKE_BASE_URL
_request.api_version = 3
_request.api_path = "home"
return ApiResource(_request, "base", self.get_resource_raw_data())

def test_full_path(self):
self.assertEqual(
self.resource._base_path, "http://{}/home/base".format(FAKE_BASE_URL)
self.resource.base_path, "http://{}/home/base".format(FAKE_BASE_URL)
)

# def test_delete_200(self, mocked):
Expand Down Expand Up @@ -184,6 +187,7 @@ def test_clean_names():
req = Mock()
req.hub_ip = "123.123.123"
req.api_version = 2
req.api_path = "api"
api = ApiEntryPoint(req, "abc")
try:
api._sanitize_resources(test_data1)
Expand Down
19 changes: 10 additions & 9 deletions tests/test_hub.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ def fake_aiorequest():

def test_version():
version1 = Version(123, 456, 789)
assert version1._build == 123
assert version1._revision == 456
assert version1._sub_revision == 789
assert version1._revision == 123
assert version1._sub_revision == 456
assert version1._build == 789

version2 = Version(123, 456, 789)

Expand All @@ -47,14 +47,14 @@ async def go():

hub = self.loop.run_until_complete(go())

assert hub._base_path == "http://" + FAKE_BASE_URL + "/api"
assert hub.base_path == "http://" + FAKE_BASE_URL + "/api"

# self.request.get.mock.assert_called_once_with(FAKE_BASE_URL + "/userdata")
data = json.loads(USER_DATA_VALUE)

assert hub.main_processor_info == data["userData"]["firmware"]["mainProcessor"]
assert hub.main_processor_version == "BUILD: 395 REVISION: 2 SUB_REVISION: 0"
assert hub.radio_version == "BUILD: 1307 REVISION: 2 SUB_REVISION: 0"
assert hub.main_processor_version == Version(2, 0, 395) # "REVISION: 2 SUB_REVISION: 0 BUILD: 395"
assert hub.radio_version == [Version(2, 0, 1307)] # ["REVISION: 2 SUB_REVISION: 0 BUILD: 1307"]
assert hub.ssid == "cisco789"
assert hub.name == "Hubby"

Expand All @@ -73,12 +73,13 @@ async def go():

hub = self.loop.run_until_complete(go())

assert hub._base_path == "http://" + FAKE_BASE_URL + "/gateway"
assert hub.base_path == "http://" + FAKE_BASE_URL + "/home"

# self.request.get.mock.assert_called_once_with(FAKE_BASE_URL + "/userdata")
data = json.loads(USER_DATA_VALUE)

assert hub.main_processor_info == data["userData"]["firmware"]["mainProcessor"]
assert hub.main_processor_version == "BUILD: 395 REVISION: 2 SUB_REVISION: 0"
assert hub.radio_version == ["BUILD: 1307 REVISION: 2 SUB_REVISION: 0"]
assert hub.main_processor_version == Version(2, 0, 395) # "REVISION: 2 SUB_REVISION: 0 BUILD: 395"
assert hub.radio_version == [Version(2, 0, 1307)] # ["REVISION: 2 SUB_REVISION: 0 BUILD: 1307"]
assert hub.ssid == "cisco789"
assert hub.name == "00:26:74:af:fd:ae"
31 changes: 24 additions & 7 deletions tests/test_room.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import asyncio
from aiohttp import ClientResponse
from unittest.mock import Mock

from aiopvapi.helpers.aiorequest import PvApiResponseStatusError
from aiopvapi.helpers.aiorequest import AioRequest, PvApiResponseStatusError
from aiopvapi.resources.room import Room
from tests.fake_server import FAKE_BASE_URL
from tests.test_apiresource import TestApiResource
from tests.test_scene_members import AsyncMock


ROOM_RAW_DATA = {
"order": 2,
Expand All @@ -23,26 +27,28 @@ def get_resource_uri(self):
return "http://{}/api/rooms/26756".format(FAKE_BASE_URL)

def get_resource(self):
_request = Mock()
_request = Mock(spec=AioRequest)
_request.hub_ip = FAKE_BASE_URL
_request.api_version = 2
_request.api_path = "api"
return Room(ROOM_RAW_DATA, _request)

def test_full_path(self):
self.assertEqual(
self.resource._base_path, "http://{}/api/rooms".format(FAKE_BASE_URL)
self.resource.base_path, "http://{}/api/rooms".format(FAKE_BASE_URL)
)

def test_name_property(self):
# No name_unicode, so base64 encoded is returned
self.assertEqual("RGluaW5nIFJvb20=", self.resource.name)
# No name_unicode, although name is base64 encoded
# thus base64 decoded is returned
self.assertEqual("Dining Room", self.resource.name)

def test_delete_room_success(self):
"""Tests deleting a room"""

async def go():
await self.start_fake_server()
room = Room(self.get_resource_raw_data(), self.request)
room = self.get_resource()
resp = await room.delete()
return resp

Expand All @@ -54,8 +60,19 @@ def test_delete_room_fail(self):

async def go():
await self.start_fake_server()
room = Room(self.get_resource_raw_data(), self.request)
# room = self.get_resource()

loop = asyncio.get_event_loop()
request = AioRequest(FAKE_BASE_URL, loop, api_version=2)

response = Mock(spec=ClientResponse)
response.status = 500
response.release = AsyncMock(return_value=None)
request.websession.delete = AsyncMock(return_value=response)

room = Room(ROOM_RAW_DATA, request)
room._resource_path += "1"

resp = await room.delete()
return resp

Expand Down
37 changes: 28 additions & 9 deletions tests/test_scene.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import asyncio
from aiohttp import ClientResponse
from unittest.mock import Mock

from aiopvapi.helpers.aiorequest import PvApiResponseStatusError
from aiopvapi.helpers.aiorequest import AioRequest, PvApiResponseStatusError
from aiopvapi.resources.scene import Scene

from tests.fake_server import FAKE_BASE_URL
from tests.test_apiresource import TestApiResource
from tests.test_scene_members import AsyncMock


SCENE_RAW_DATA = {
"roomId": 26756,
"name": "RGluaW5nIFZhbmVzIE9wZW4=",
"name": "RGluaW5nIFZhbmVzIE9wZW4=", # "Dining Vanes Open"
"colorId": 0,
"iconId": 0,
"id": 37217,
Expand All @@ -24,21 +28,23 @@ def get_resource_uri(self):
return "http://{}/api/scenes/37217".format(FAKE_BASE_URL)

def get_resource(self):
_request = Mock()
_request = Mock(spec=AioRequest)
_request.hub_ip = FAKE_BASE_URL
_request.api_version = 2
_request.api_path = "api"
return Scene(SCENE_RAW_DATA, _request)

def test_name_property(self):
# No name_unicode, so base64 encoded is returned
self.assertEqual("RGluaW5nIFZhbmVzIE9wZW4=", self.resource.name)
# No name_unicode, although name is base64 encoded
# thus base64 decoded is returned
self.assertEqual("Dining Vanes Open", self.resource.name)

def test_room_id_property(self):
self.assertEqual(26756, self.resource.room_id)

def test_full_path(self):
self.assertEqual(
self.resource._base_path,
self.resource.base_path,
"http://{}/api/scenes".format(FAKE_BASE_URL),
)

Expand All @@ -47,19 +53,32 @@ def test_activate_200(self):

async def go():
await self.start_fake_server()
scene = Scene({"id": 10}, self.request)
scene = self.get_resource()
scene.request.get = AsyncMock(return_value={'shadeIds': [10]})
resp = await scene.activate()
return resp

resp = self.loop.run_until_complete(go())
self.assertEqual(resp["id"], 10)
self.assertEqual(resp[0], 10)

def test_activate_404(self):
"""Test scene activation"""

async def go():
await self.start_fake_server()
scene = Scene({"id": 11}, self.request)
# scene = self.get_resource()

loop = asyncio.get_event_loop()
request = AioRequest(FAKE_BASE_URL, loop, api_version=2)

response = Mock(spec=ClientResponse)
response.status = 404
response.release = AsyncMock(return_value=None)
request.websession.get = AsyncMock(return_value=response)

scene = Scene(SCENE_RAW_DATA, request)
scene._resource_path += "1"

resp = await scene.activate()
return resp

Expand Down
2 changes: 1 addition & 1 deletion tests/test_scene_members.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class TestSceneMembers(unittest.TestCase):
def setUp(self):
self.fake_ip = '123.123.123.123'

@mock.patch('aiopvapi.helpers.aiorequest.check_response', new=AsyncMock())
@mock.patch('aiopvapi.helpers.aiorequest.AioRequest.check_response', new=AsyncMock())
def test_remove_shade_from_scene(self):
"""Tests create new scene."""
loop = asyncio.get_event_loop()
Expand Down
Loading

0 comments on commit e60af51

Please sign in to comment.