def tests_camera_no_image_update(self, m): """Tests that camera updates correctly with no timeline events.""" # Set up URL's m.post(CONST.LOGIN_URL, text=LOGIN.post_response_ok()) m.get(CONST.OAUTH_TOKEN_URL, text=OAUTH_CLAIMS.get_response_ok()) m.post(CONST.LOGOUT_URL, text=LOGOUT.post_response_ok()) m.get(CONST.PANEL_URL, text=PANEL.get_response_ok(mode=CONST.MODE_STANDBY)) m.get(CONST.DEVICES_URL, text=IRCAMERA.device(devid=IRCAMERA.DEVICE_ID, status=CONST.STATUS_ONLINE, low_battery=False, no_response=False)) # Logout to reset everything self.abode.logout() # Get our camera device = self.abode.get_device(IRCAMERA.DEVICE_ID) # Test that we have our device self.assertIsNotNone(device) self.assertEqual(device.status, CONST.STATUS_ONLINE) # Set up timeline response url = str.replace(CONST.TIMELINE_IMAGES_ID_URL, '$DEVID$', IRCAMERA.DEVICE_ID) m.get(url, text='[]') # Refresh the image self.assertFalse(device.refresh_image()) self.assertIsNone(device.image_url)
def tests_sound_settings(self, m): """Check that device panel sound settings are working.""" m.post(CONST.LOGIN_URL, text=LOGIN.post_response_ok()) m.get(CONST.OAUTH_TOKEN_URL, text=OAUTH_CLAIMS.get_response_ok()) m.post(CONST.LOGOUT_URL, text=LOGOUT.post_response_ok()) m.get(CONST.PANEL_URL, text=PANEL.get_response_ok()) m.put(CONST.SOUNDS_URL, text=MOCK.generic_response_ok()) try: self.abode.set_setting(CONST.SETTING_DOOR_CHIME, CONST.SETTING_SOUND_LOW) self.abode.set_setting(CONST.SETTING_ALARM_LENGTH, CONST.SETTING_ALARM_LENGTH_2MIN) self.abode.set_setting(CONST.SETTING_FINAL_BEEPS, CONST.SETTING_FINAL_BEEPS_3SEC) except abodepy.AbodeException: self.fail("set_setting() raised AbodeException unexpectedly") with self.assertRaises(abodepy.AbodeException): self.abode.set_setting(CONST.SETTING_DOOR_CHIME, "foobar") with self.assertRaises(abodepy.AbodeException): self.abode.set_setting(CONST.SETTING_ALARM_LENGTH, "foobar") with self.assertRaises(abodepy.AbodeException): self.abode.set_setting(CONST.SETTING_FINAL_BEEPS, "foobar")
def tests_general_settings(self, m): """Check that device panel general settings are working.""" m.post(CONST.LOGIN_URL, text=LOGIN.post_response_ok()) m.get(CONST.OAUTH_TOKEN_URL, text=OAUTH_CLAIMS.get_response_ok()) m.post(CONST.LOGOUT_URL, text=LOGOUT.post_response_ok()) m.get(CONST.PANEL_URL, text=PANEL.get_response_ok()) m.put(CONST.SETTINGS_URL, text=MOCK.generic_response_ok()) try: self.abode.set_setting(CONST.SETTING_CAMERA_RESOLUTION, CONST.SETTING_CAMERA_RES_640_480) self.abode.set_setting(CONST.SETTING_CAMERA_GRAYSCALE, CONST.SETTING_ENABLE) self.abode.set_setting(CONST.SETTING_SILENCE_SOUNDS, CONST.SETTING_ENABLE) except abodepy.AbodeException: self.fail("set_setting() raised AbodeException unexpectedly") with self.assertRaises(abodepy.AbodeException): self.abode.set_setting(CONST.SETTING_CAMERA_RESOLUTION, "foobar") with self.assertRaises(abodepy.AbodeException): self.abode.set_setting(CONST.SETTING_CAMERA_GRAYSCALE, "foobar") with self.assertRaises(abodepy.AbodeException): self.abode.set_setting(CONST.SETTING_SILENCE_SOUNDS, "foobar")
def tests_reauthorize(self, m): """Check that Abode can reauthorize after token timeout.""" new_token = "FOOBAR" m.post(CONST.LOGIN_URL, [{ 'text': LOGIN.post_response_ok(auth_token=new_token), 'status_code': 200 }]) m.get(CONST.OAUTH_TOKEN_URL, text=OAUTH_CLAIMS.get_response_ok()) m.get(CONST.DEVICES_URL, [{ 'text': MOCK.response_forbidden(), 'status_code': 403 }, { 'text': DEVICES.EMPTY_DEVICE_RESPONSE, 'status_code': 200 }]) m.get(CONST.PANEL_URL, text=PANEL.get_response_ok()) # Forces a device update self.abode.get_devices() # pylint: disable=W0212 self.assertEqual(self.abode._token, new_token)
def tests_automation_init(self, m): """Check the Abode automation class init's properly.""" # Set up URLs m.post(CONST.LOGIN_URL, text=LOGIN.post_response_ok()) m.get(CONST.OAUTH_TOKEN_URL, text=OAUTH_CLAIMS.get_response_ok()) m.post(CONST.LOGOUT_URL, text=LOGOUT.post_response_ok()) m.get(CONST.PANEL_URL, text=PANEL.get_response_ok()) # Set up automation automation_text = AUTOMATION.get_response_ok(name='Auto Away', enabled=True, aid=AID_1) automation_json = json.loads(automation_text) m.get(CONST.AUTOMATION_URL, text=automation_text) # Logout to reset everything self.abode.logout() # Get our specific automation automation = self.abode.get_automation(AID_1) # Check automation states match self.assertIsNotNone(automation) # pylint: disable=W0212 self.assertEqual(automation._automation, automation_json) self.assertEqual(automation.automation_id, str(automation_json['id'])) self.assertEqual(automation.name, automation_json['name']) self.assertEqual(automation.is_enabled, automation_json['enabled']) self.assertIsNotNone(automation.desc)
def tests_lm_temp_only(self, m): """Tests that sensor/LM devices properties work as expected.""" # Set up URL's m.post(CONST.LOGIN_URL, text=LOGIN.post_response_ok()) m.get(CONST.OAUTH_TOKEN_URL, text=OAUTH_CLAIMS.get_response_ok()) m.post(CONST.LOGOUT_URL, text=LOGOUT.post_response_ok()) m.get(CONST.PANEL_URL, text=PANEL.get_response_ok(mode=CONST.MODE_STANDBY)) m.get(CONST.DEVICES_URL, text=LM.device(devid=LM.DEVICE_ID, status='72 °F', temp='72 °F', lux='', humidity='')) # Logout to reset everything self.abode.logout() # Get our power switch device = self.abode.get_device(LM.DEVICE_ID) # Test our device self.assertIsNotNone(device) self.assertEqual(device.status, '72 °F') self.assertTrue(device.has_temp) self.assertFalse(device.has_humidity) self.assertFalse(device.has_lux) self.assertEqual(device.temp, 72) self.assertEqual(device.temp_unit, '°F') self.assertIsNone(device.humidity) self.assertIsNone(device.humidity_unit) self.assertIsNone(device.lux) self.assertIsNone(device.lux_unit)
def tests_auto_login(self, m): """Test that automatic login works.""" auth_token = MOCK.AUTH_TOKEN user_json = USER.get_response_ok() login_json = LOGIN.post_response_ok(auth_token, user_json) panel_json = PANEL.get_response_ok() m.post(CONST.LOGIN_URL, text=login_json) m.get(CONST.OAUTH_TOKEN_URL, text=OAUTH_CLAIMS.get_response_ok()) m.get(CONST.PANEL_URL, text=panel_json) m.post(CONST.LOGOUT_URL, text=LOGOUT.post_response_ok()) abode = abodepy.Abode(username='******', password='******', auto_login=True, get_devices=False, disable_cache=True) # pylint: disable=W0212 self.assertEqual(abode._cache[CONST.ID], 'fizz') self.assertEqual(abode._cache[CONST.PASSWORD], 'buzz') self.assertEqual(abode._token, MOCK.AUTH_TOKEN) self.assertEqual(abode._panel, json.loads(panel_json)) self.assertEqual(abode._user, json.loads(user_json)) self.assertIsNone(abode._devices) self.assertIsNone(abode._automations) abode.logout() abode = None
def tests_automation_trigger(self, m): """Check that automations can be triggered.""" # Set up URL's m.post(CONST.LOGIN_URL, text=LOGIN.post_response_ok()) m.get(CONST.OAUTH_TOKEN_URL, text=OAUTH_CLAIMS.get_response_ok()) m.post(CONST.LOGOUT_URL, text=LOGOUT.post_response_ok()) m.get(CONST.PANEL_URL, text=PANEL.get_response_ok()) # Set up automation automation_text = '[' + \ AUTOMATION.get_response_ok( name='Test Automation One', enabled=True, aid=AID_1) + ']' m.get(CONST.AUTOMATION_URL, text=automation_text) # Logout to reset everything self.abode.logout() # Get the automation and test # pylint: disable=W0212 automation = self.abode.get_automation(AID_1) self.assertIsNotNone(automation) # Set up our automation trigger reply set_active_url = str.replace(CONST.AUTOMATION_APPLY_URL, '$AUTOMATIONID$', automation.automation_id) m.post(set_active_url, text=MOCK.generic_response_ok()) # Test triggering self.assertTrue(automation.trigger())
def tests_siren_settings(self, m): """Check that device panel siren settings are working.""" m.post(CONST.LOGIN_URL, text=LOGIN.post_response_ok()) m.get(CONST.OAUTH_TOKEN_URL, text=OAUTH_CLAIMS.get_response_ok()) m.post(CONST.LOGOUT_URL, text=LOGOUT.post_response_ok()) m.get(CONST.PANEL_URL, text=PANEL.get_response_ok()) m.put(CONST.SIREN_URL, text=MOCK.generic_response_ok()) try: self.abode.set_setting(CONST.SETTING_SIREN_ENTRY_EXIT_SOUNDS, CONST.SETTING_ENABLE) self.abode.set_setting(CONST.SETTING_SIREN_CONFIRM_SOUNDS, CONST.SETTING_ENABLE) self.abode.set_setting(CONST.SETTING_SIREN_TAMPER_SOUNDS, CONST.SETTING_ENABLE) except abodepy.AbodeException: self.fail("set_setting() raised AbodeException unexpectedly") with self.assertRaises(abodepy.AbodeException): self.abode.set_setting(CONST.SETTING_SIREN_ENTRY_EXIT_SOUNDS, "foobar") with self.assertRaises(abodepy.AbodeException): self.abode.set_setting(CONST.SETTING_SIREN_CONFIRM_SOUNDS, "foobar") with self.assertRaises(abodepy.AbodeException): self.abode.set_setting(CONST.SETTING_SIREN_TAMPER_SOUNDS, "foobar")
def tests_generic_device_refresh(self, m): """Check the generic Abode device class init's properly.""" # Set up URL's m.post(CONST.LOGIN_URL, text=LOGIN.post_response_ok()) m.get(CONST.OAUTH_TOKEN_URL, text=OAUTH_CLAIMS.get_response_ok()) m.post(CONST.LOGOUT_URL, text=LOGOUT.post_response_ok()) m.get(CONST.PANEL_URL, text=PANEL.get_response_ok()) # Set up online device device_text_online = '[' + \ GLASS.device(status=CONST.STATUS_ONLINE) + ']' m.get(CONST.DEVICES_URL, text=device_text_online) # Set up offline device device_text_offline = '[' + \ GLASS.device(status=CONST.STATUS_OFFLINE) + ']' device_url = str.replace(CONST.DEVICE_URL, '$DEVID$', GLASS.DEVICE_ID) m.get(device_url, text=device_text_offline) # Logout to reset everything self.abode.logout() # Get the first device and test device = self.abode.get_device(GLASS.DEVICE_ID) self.assertEqual(device.status, CONST.STATUS_ONLINE) # Refresh the device and test device = self.abode.get_device(GLASS.DEVICE_ID, refresh=True) self.assertEqual(device.status, CONST.STATUS_OFFLINE)
def tests_area_settings(self, m): """Check that device panel areas settings are working.""" m.post(CONST.LOGIN_URL, text=LOGIN.post_response_ok()) m.get(CONST.OAUTH_TOKEN_URL, text=OAUTH_CLAIMS.get_response_ok()) m.post(CONST.LOGOUT_URL, text=LOGOUT.post_response_ok()) m.get(CONST.PANEL_URL, text=PANEL.get_response_ok()) m.put(CONST.AREAS_URL, text=MOCK.generic_response_ok()) try: self.abode.set_setting(CONST.SETTING_ENTRY_DELAY_AWAY, CONST.SETTING_ENTRY_EXIT_DELAY_10SEC) self.abode.set_setting(CONST.SETTING_EXIT_DELAY_AWAY, CONST.SETTING_ENTRY_EXIT_DELAY_30SEC) except abodepy.AbodeException: self.fail("set_setting() raised AbodeException unexpectedly") with self.assertRaises(abodepy.AbodeException): self.abode.set_setting(CONST.SETTING_ENTRY_DELAY_AWAY, "foobar") # 10 seconds is invalid here with self.assertRaises(abodepy.AbodeException): self.abode.set_setting(CONST.SETTING_EXIT_DELAY_AWAY, CONST.SETTING_ENTRY_EXIT_DELAY_10SEC)
def tests_device_registration(self, m): """Tests that we can register for device events with a device.""" # Set up URL's m.post(CONST.LOGIN_URL, text=LOGIN.post_response_ok()) m.get(CONST.OAUTH_TOKEN_URL, text=OAUTH_CLAIMS.get_response_ok()) m.post(CONST.LOGOUT_URL, text=LOGOUT.post_response_ok()) m.get(CONST.PANEL_URL, text=PANEL.get_response_ok(mode=CONST.MODE_STANDBY)) m.get(CONST.DEVICES_URL, text=COVER.device(devid=COVER.DEVICE_ID, status=CONST.STATUS_CLOSED, low_battery=False, no_response=False)) # Logout to reset everything self.abode.logout() # Get our device device = self.abode.get_device(COVER.DEVICE_ID) self.assertIsNotNone(device) # Get the event controller events = self.abode.events self.assertIsNotNone(events) def _our_callback(device): self.assertIsNotNone(device) # Register our device self.assertTrue(events.add_device_callback(device, _our_callback))
def tests_invalid_all_device_unregister(self, m): """Tests that invalid devices are not all unregistered.""" # Set up URL's m.post(CONST.LOGIN_URL, text=LOGIN.post_response_ok()) m.get(CONST.OAUTH_TOKEN_URL, text=OAUTH_CLAIMS.get_response_ok()) m.post(CONST.LOGOUT_URL, text=LOGOUT.post_response_ok()) m.get(CONST.PANEL_URL, text=PANEL.get_response_ok(mode=CONST.MODE_STANDBY)) m.get(CONST.DEVICES_URL, text=COVER.device(devid=COVER.DEVICE_ID, status=CONST.STATUS_CLOSED, low_battery=False, no_response=False)) # Logout to reset everything self.abode.logout() # Get our device device = self.abode.get_device(COVER.DEVICE_ID) self.assertIsNotNone(device) # Get the event controller events = self.abode.events self.assertIsNotNone(events) # Test that no device returns false self.assertFalse(events.remove_all_device_callbacks(None)) # Create a fake device and attempt to unregister that fake_device = AbodeBinarySensor(json.loads(DOORCONTACT.device()), self.abode) with self.assertRaises(abodepy.AbodeException): events.remove_all_device_callbacks(fake_device)
def tests_camera_no_image_update(self, m): """Tests that camera updates correctly with no timeline events.""" # Set up URL's m.post(CONST.LOGIN_URL, text=LOGIN.post_response_ok()) m.get(CONST.OAUTH_TOKEN_URL, text=OAUTH_CLAIMS.get_response_ok()) m.post(CONST.LOGOUT_URL, text=LOGOUT.post_response_ok()) m.get(CONST.PANEL_URL, text=PANEL.get_response_ok(mode=CONST.MODE_STANDBY)) m.get(CONST.DEVICES_URL, text=self.all_devices) # Test our camera devices for device in self.abode.get_devices(): # Skip alarm devices if device.type_tag == CONST.DEVICE_ALARM: continue # Test that we have our device self.assertIsNotNone(device) self.assertEqual(device.status, CONST.STATUS_ONLINE) # Set up timeline response url = str.replace(CONST.TIMELINE_IMAGES_ID_URL, "$DEVID$", device.device_id) m.get(url, text="[]") # Refresh the image self.assertFalse(device.refresh_image()) self.assertIsNone(device.image_url)
def test_invalid_cookies(self, m): """Check that empty cookies file is loaded successfully.""" m.post(CONST.LOGIN_URL, text=LOGIN.post_response_ok()) m.get(CONST.OAUTH_TOKEN_URL, text=OAUTH_CLAIMS.get_response_ok()) m.post(CONST.LOGOUT_URL, text=LOGOUT.post_response_ok()) m.get(CONST.DEVICES_URL, text=DEVICES.EMPTY_DEVICE_RESPONSE) m.get(CONST.PANEL_URL, text=PANEL.get_response_ok()) # Test empty cookies file invalid_cache_path = "./test_cookies_invalid.pickle" # Remove the file if it exists if os.path.exists(invalid_cache_path): os.remove(invalid_cache_path) # Create an invalid pickle file with open(invalid_cache_path, 'a') as file: file.write("Invalid file goes here") # Assert that cookies file exists self.assertTrue(os.path.exists(invalid_cache_path)) # Cookies are created empty_abode = abodepy.Abode(username='******', password='******', auto_login=True, get_devices=False, disable_cache=False, cache_path=invalid_cache_path) # Test that some cache exists # pylint: disable=W0212 self.assertIsNotNone(empty_abode._cache['id']) self.assertIsNotNone(empty_abode._cache['password']) self.assertIsNotNone(empty_abode._cache['uuid'])
def tests_camera_privacy_mode(self, m): """Tests camera privacy mode.""" # Set up mock URLs m.post(CONST.LOGIN_URL, text=LOGIN.post_response_ok()) m.get(CONST.OAUTH_TOKEN_URL, text=OAUTH_CLAIMS.get_response_ok()) m.post(CONST.LOGOUT_URL, text=LOGOUT.post_response_ok()) m.get(CONST.PANEL_URL, text=PANEL.get_response_ok(mode=CONST.MODE_STANDBY)) m.get(CONST.DEVICES_URL, text=self.all_devices) # Get the IP camera and test we have it device = self.abode.get_device(IPCAM.DEVICE_ID) self.assertIsNotNone(device) self.assertEqual(device.status, CONST.STATUS_ONLINE) # Set up params URL response for privacy mode on m.put(CONST.PARAMS_URL + device.device_id, text=IPCAM.device(privacy=0)) # Set privacy mode on self.assertTrue(device.privacy_mode(True)) # Set up params URL response for privacy mode off m.put(CONST.PARAMS_URL + device.device_id, text=IPCAM.device(privacy=1)) # Set privacy mode off self.assertTrue(device.privacy_mode(False)) # Test that an invalid privacy response throws exception with self.assertRaises(abodepy.AbodeException): device.privacy_mode(True)
def tests_cookies(self, m): """Check that cookies are saved and loaded successfully.""" m.post(CONST.LOGIN_URL, text=LOGIN.post_response_ok()) m.get(CONST.OAUTH_TOKEN_URL, text=OAUTH_CLAIMS.get_response_ok()) m.post(CONST.LOGOUT_URL, text=LOGOUT.post_response_ok()) m.get(CONST.DEVICES_URL, text=DEVICES.EMPTY_DEVICE_RESPONSE) m.get(CONST.PANEL_URL, text=PANEL.get_response_ok()) # Define test pickle file and cleanup old one if exists cache_path = "./test_cookies.pickle" if os.path.exists(cache_path): os.remove(cache_path) # Assert that no cookies file exists self.assertFalse(os.path.exists(cache_path)) # Create abode abode = abodepy.Abode(username='******', password='******', auto_login=False, get_devices=False, disable_cache=False, cache_path=cache_path) # Mock cookie created by Abode after login cookie = requests.cookies.create_cookie(name='SESSION', value='COOKIE') # pylint: disable=protected-access abode._session.cookies.set_cookie(cookie) abode.login() # Test that our cookies are fully realized prior to login # pylint: disable=W0212 self.assertIsNotNone(abode._cache['id']) self.assertIsNotNone(abode._cache['password']) self.assertIsNotNone(abode._cache['uuid']) self.assertIsNotNone(abode._cache['cookies']) # Test that we now have a cookies file self.assertTrue(os.path.exists(cache_path)) # Copy our current cookies file and data first_cookies_data = abode._cache # New abode instance reads in old data abode = abodepy.Abode(username='******', password='******', auto_login=False, get_devices=False, disable_cache=False, cache_path=cache_path) # Test that the cookie data is the same self.assertEqual(abode._cache['uuid'], first_cookies_data['uuid']) # Cleanup cookies os.remove(cache_path)
def tests_camera_image_write(self, m): """Tests that camera images will write to a file.""" # Set up URL's m.post(CONST.LOGIN_URL, text=LOGIN.post_response_ok()) m.get(CONST.OAUTH_TOKEN_URL, text=OAUTH_CLAIMS.get_response_ok()) m.post(CONST.LOGOUT_URL, text=LOGOUT.post_response_ok()) m.get(CONST.PANEL_URL, text=PANEL.get_response_ok(mode=CONST.MODE_STANDBY)) m.get(CONST.DEVICES_URL, text=self.all_devices) # Test our camera devices for device in self.abode.get_devices(): # Skip alarm devices if device.type_tag == CONST.DEVICE_ALARM: continue # Specify which device module to use based on type_tag cam_type = set_cam_type(device.type_tag) # Test that we have our device self.assertIsNotNone(device) self.assertEqual(device.status, CONST.STATUS_ONLINE) # Set up timeline response url = str.replace(CONST.TIMELINE_IMAGES_ID_URL, "$DEVID$", device.device_id) m.get(url, text="[" + cam_type.timeline_event(device.device_id) + "]") # Set up our file path response file_path = CONST.BASE_URL + cam_type.FILE_PATH m.head( file_path, status_code=302, headers={"Location": cam_type.LOCATION_HEADER}, ) # Set up our image response image_response = "this is a beautiful jpeg image" m.get(cam_type.LOCATION_HEADER, text=image_response) # Refresh the image path = "test.jpg" self.assertTrue(device.image_to_file(path, get_image=True)) # Test the file written and cleanup image_data = open(path, "r").read() self.assertTrue(image_response, image_data) os.remove(path) # Test that bad response returns False m.get(cam_type.LOCATION_HEADER, status_code=400) with self.assertRaises(abodepy.AbodeException): device.image_to_file(path, get_image=True) # Test that the image fails to update returns False m.get(url, text="[]") self.assertFalse(device.image_to_file(path, get_image=True))
def tests_dimmer_status_changes(self, m): """Tests that dimmer device changes work as expected.""" # Set up URL's m.post(CONST.LOGIN_URL, text=LOGIN.post_response_ok()) m.get(CONST.OAUTH_TOKEN_URL, text=OAUTH_CLAIMS.get_response_ok()) m.post(CONST.LOGOUT_URL, text=LOGOUT.post_response_ok()) m.get(CONST.PANEL_URL, text=PANEL.get_response_ok(mode=CONST.MODE_STANDBY)) m.get(CONST.DEVICES_URL, text=DIMMER.device(devid=DIMMER.DEVICE_ID, status=CONST.STATUS_OFF, level=0, low_battery=False, no_response=False)) # Logout to reset everything self.abode.logout() # Get our dimmer device = self.abode.get_device(DIMMER.DEVICE_ID) # Test that we have our device self.assertIsNotNone(device) self.assertEqual(device.status, CONST.STATUS_OFF) self.assertFalse(device.is_on) # Set up control url response control_url = CONST.BASE_URL + DIMMER.CONTROL_URL m.put(control_url, text=DEVICES.status_put_response_ok( devid=DIMMER.DEVICE_ID, status=CONST.STATUS_ON_INT)) # Change the mode to "on" self.assertTrue(device.switch_on()) self.assertEqual(device.status, CONST.STATUS_ON) self.assertTrue(device.is_on) # Change response m.put(control_url, text=DEVICES.status_put_response_ok( devid=DIMMER.DEVICE_ID, status=CONST.STATUS_OFF_INT)) # Change the mode to "off" self.assertTrue(device.switch_off()) self.assertEqual(device.status, CONST.STATUS_OFF) self.assertFalse(device.is_on) # Test that an invalid status response throws exception m.put(control_url, text=DEVICES.status_put_response_ok( devid=DIMMER.DEVICE_ID, status=CONST.STATUS_OFF_INT)) with self.assertRaises(abodepy.AbodeException): device.switch_on()
def tests_camera_image_write(self, m): """Tests that camera images will write to a file.""" # Set up URL's m.post(CONST.LOGIN_URL, text=LOGIN.post_response_ok()) m.get(CONST.OAUTH_TOKEN_URL, text=OAUTH_CLAIMS.get_response_ok()) m.post(CONST.LOGOUT_URL, text=LOGOUT.post_response_ok()) m.get(CONST.PANEL_URL, text=PANEL.get_response_ok(mode=CONST.MODE_STANDBY)) m.get(CONST.DEVICES_URL, text=IRCAMERA.device(devid=IRCAMERA.DEVICE_ID, status=CONST.STATUS_ONLINE, low_battery=False, no_response=False)) # Logout to reset everything self.abode.logout() # Get our camera device = self.abode.get_device(IRCAMERA.DEVICE_ID) # Test that we have our device self.assertIsNotNone(device) self.assertEqual(device.status, CONST.STATUS_ONLINE) # Set up timeline response url = str.replace(CONST.TIMELINE_IMAGES_ID_URL, '$DEVID$', IRCAMERA.DEVICE_ID) m.get(url, text='[' + IRCAMERA.timeline_event(IRCAMERA.DEVICE_ID) + ']') # Set up our file path response file_path = CONST.BASE_URL + IRCAMERA.FILE_PATH m.head(file_path, status_code=302, headers={'Location': IRCAMERA.LOCATION_HEADER}) # Set up our image response image_response = "this is a beautiful jpeg image" m.get(IRCAMERA.LOCATION_HEADER, text=image_response) # Refresh the image path = "test.jpg" self.assertTrue(device.image_to_file(path, get_image=True)) # Test the file written and cleanup image_data = open(path, 'r').read() self.assertTrue(image_response, image_data) os.remove(path) # Test that bad response returns False m.get(IRCAMERA.LOCATION_HEADER, status_code=400) with self.assertRaises(abodepy.AbodeException): device.image_to_file(path, get_image=True) # Test that the image fails to update returns False m.get(url, text='[]') self.assertFalse(device.image_to_file(path, get_image=True))
def tests_continuous_bad_auth(self, m): """Check that Abode won't get stuck with repeated failed retries.""" m.post(CONST.LOGIN_URL, text=LOGIN.post_response_ok()) m.get(CONST.OAUTH_TOKEN_URL, text=OAUTH_CLAIMS.get_response_ok()) m.get(CONST.DEVICES_URL, text=MOCK.response_forbidden(), status_code=403) with self.assertRaises(abodepy.AbodeException): self.abode.get_devices()
def tests_login_failure(self, m): """Test login failed.""" m.post(CONST.LOGIN_URL, text=LOGIN.post_response_bad_request(), status_code=400) m.get(CONST.OAUTH_TOKEN_URL, text=OAUTH_CLAIMS.get_response_ok()) # Check that we raise an Exception with a failed login request. with self.assertRaises(abodepy.AbodeAuthenticationException): self.abode_no_cred.login(username=USERNAME, password=PASSWORD)
def tests_settings_validation(self, m): """Check that device panel general settings are working.""" m.post(CONST.LOGIN_URL, text=LOGIN.post_response_ok()) m.get(CONST.OAUTH_TOKEN_URL, text=OAUTH_CLAIMS.get_response_ok()) m.post(CONST.LOGOUT_URL, text=LOGOUT.post_response_ok()) m.get(CONST.PANEL_URL, text=PANEL.get_response_ok()) m.get(CONST.SETTINGS_URL, text=MOCK.generic_response_ok()) with self.assertRaises(abodepy.AbodeException): self.abode.set_setting("fliptrix", "foobar")
def tests_camera_capture(self, m): """Tests that camera devices capture new images.""" # Set up URL's m.post(CONST.LOGIN_URL, text=LOGIN.post_response_ok()) m.get(CONST.OAUTH_TOKEN_URL, text=OAUTH_CLAIMS.get_response_ok()) m.post(CONST.LOGOUT_URL, text=LOGOUT.post_response_ok()) m.get(CONST.PANEL_URL, text=PANEL.get_response_ok(mode=CONST.MODE_STANDBY)) m.get(CONST.DEVICES_URL, text=self.all_devices) # Test our camera devices for device in self.abode.get_devices(): # Skip alarm devices if device.type_tag == CONST.DEVICE_ALARM: continue # Specify which device module to use based on type_tag cam_type = set_cam_type(device.type_tag) # Test that we have the camera devices self.assertIsNotNone(device) self.assertEqual(device.status, CONST.STATUS_ONLINE) # Determine URL based on device type if device.type_tag == CONST.DEVICE_IP_CAM: url = CONST.BASE_URL + cam_type.CONTROL_URL_SNAPSHOT elif device.type_tag == CONST.DEVICE_MOTION_CAMERA: url = CONST.BASE_URL + cam_type.CONTROL_URL # Set up capture URL response m.put(url, text=MOCK.generic_response_ok()) # Capture an image self.assertTrue(device.capture()) # Change capture URL responses m.put(url, text=cam_type.get_capture_timeout(), status_code=600) # Capture an image with a failure self.assertFalse(device.capture()) # Remove control URLs from JSON to test if Abode makes # changes to JSON # pylint: disable=protected-access for key in list(device._json_state.keys()): if key.startswith("control_url"): # pylint: disable=protected-access del device._json_state[key] # Test that AbodeException is raised with no control URLs with self.assertRaises(AbodeException) as exc: device.capture() self.assertEqual(str(exc.exception), ERROR.MISSING_CONTROL_URL)
def tests_manual_login(self, m): """Check that we can manually use the login() function.""" m.post(CONST.LOGIN_URL, text=LOGIN.post_response_ok()) m.get(CONST.OAUTH_TOKEN_URL, text=OAUTH_CLAIMS.get_response_ok()) self.abode_no_cred.login(username=USERNAME, password=PASSWORD) # pylint: disable=protected-access self.assertEqual(self.abode_no_cred._cache[CONST.ID], USERNAME) # pylint: disable=protected-access self.assertEqual(self.abode_no_cred._cache[CONST.PASSWORD], PASSWORD)
def tests_logout_exception(self, m): """Test logout exception.""" m.post(CONST.LOGIN_URL, text=LOGIN.post_response_ok()) m.get(CONST.OAUTH_TOKEN_URL, text=OAUTH_CLAIMS.get_response_ok()) m.get(CONST.DEVICES_URL, text=DEVICES.EMPTY_DEVICE_RESPONSE) m.get(CONST.PANEL_URL, text=PANEL.get_response_ok()) m.post(CONST.LOGOUT_URL, exc=requests.exceptions.ConnectTimeout) self.abode.login() # Check that we eat the exception gracefully self.assertFalse(self.abode.logout())
def tests_dimmer_device_properties(self, m): """Tests that dimmer light devices properties work as expected.""" # Set up URL's m.post(CONST.LOGIN_URL, text=LOGIN.post_response_ok()) m.get(CONST.OAUTH_TOKEN_URL, text=OAUTH_CLAIMS.get_response_ok()) m.post(CONST.LOGOUT_URL, text=LOGOUT.post_response_ok()) m.get(CONST.PANEL_URL, text=PANEL.get_response_ok(mode=CONST.MODE_STANDBY)) m.get(CONST.DEVICES_URL, text=DIMMER.device(devid=DIMMER.DEVICE_ID, status=CONST.STATUS_OFF, level=0, low_battery=False, no_response=False)) # Logout to reset everything self.abode.logout() # Get our dimmer device = self.abode.get_device(DIMMER.DEVICE_ID) # Test our device self.assertIsNotNone(device) self.assertEqual(device.status, CONST.STATUS_OFF) self.assertEqual(device.brightness, "0") self.assertTrue(device.has_brightness) self.assertTrue(device.is_dimmable) self.assertFalse(device.has_color) self.assertFalse(device.is_color_capable) self.assertFalse(device.battery_low) self.assertFalse(device.no_response) self.assertFalse(device.is_on) # Set up our direct device get url device_url = str.replace(CONST.DEVICE_URL, '$DEVID$', DIMMER.DEVICE_ID) # Change device properties m.get(device_url, text=DIMMER.device(devid=DIMMER.DEVICE_ID, status=CONST.STATUS_ON, level=87, low_battery=True, no_response=True)) # Refesh device and test changes device.refresh() self.assertEqual(device.status, CONST.STATUS_ON) self.assertEqual(device.brightness, "87") self.assertTrue(device.battery_low) self.assertTrue(device.no_response) self.assertTrue(device.is_on)
def test_all_device_refresh(self, m): """Check that device refresh works and reuses the same objects.""" dc1_devid = 'RF:01' dc1a = DOOR_CONTACT.device( devid=dc1_devid, status=CONST.STATUS_ON) dc2_devid = 'RF:02' dc2a = DOOR_CONTACT.device( devid=dc2_devid, status=CONST.STATUS_OFF) m.post(CONST.LOGIN_URL, text=LOGIN.post_response_ok()) m.get(CONST.OAUTH_TOKEN_URL, text=OAUTH_CLAIMS.get_response_ok()) m.post(CONST.LOGOUT_URL, text=LOGOUT.post_response_ok()) m.get(CONST.DEVICES_URL, text='[' + dc1a + ',' + dc2a + ']') m.get(CONST.PANEL_URL, text=PANEL.get_response_ok()) # Reset self.abode.logout() # Get all devices self.abode.get_devices() # Get and check devices # pylint: disable=W0212 dc1a_dev = self.abode.get_device(dc1_devid) self.assertEqual(json.loads(dc1a)['id'], dc1a_dev.device_id) dc2a_dev = self.abode.get_device(dc2_devid) self.assertEqual(json.loads(dc2a)['id'], dc2a_dev.device_id) # Change device states dc1b = DOOR_CONTACT.device( devid=dc1_devid, status=CONST.STATUS_OFF) dc2b = DOOR_CONTACT.device( devid=dc2_devid, status=CONST.STATUS_ON) m.get(CONST.DEVICES_URL, text='[' + dc1b + ',' + dc2b + ']') # Refresh all devices self.abode.get_devices(refresh=True) # Get and check devices again, ensuring they are the same object # Future note: "if a is b" tests that the object is the same # Thus asserting dc1a_dev is dc1b_dev tests if they are the same object dc1b_dev = self.abode.get_device(dc1_devid) self.assertEqual(json.loads(dc1b)['id'], dc1b_dev.device_id) self.assertIs(dc1a_dev, dc1b_dev) dc2b_dev = self.abode.get_device(dc2_devid) self.assertEqual(json.loads(dc2b)['id'], dc2b_dev.device_id) self.assertIs(dc2a_dev, dc2b_dev)
def tests_manual_login_with_mfa(self, m): """Check that we can login with MFA code.""" m.post(CONST.LOGIN_URL, text=LOGIN.post_response_ok()) m.get(CONST.OAUTH_TOKEN_URL, text=OAUTH_CLAIMS.get_response_ok()) self.abode_no_cred.login(username=USERNAME, password=PASSWORD, mfa_code=654321) # pylint: disable=protected-access self.assertEqual(self.abode_no_cred._cache[CONST.ID], USERNAME) # pylint: disable=protected-access self.assertEqual(self.abode_no_cred._cache[CONST.PASSWORD], PASSWORD)
def tests_multiple_automations(self, m): """Check that multiple automations work and return correctly.""" # Set up URL's m.post(CONST.LOGIN_URL, text=LOGIN.post_response_ok()) m.get(CONST.OAUTH_TOKEN_URL, text=OAUTH_CLAIMS.get_response_ok()) m.post(CONST.LOGOUT_URL, text=LOGOUT.post_response_ok()) m.get(CONST.PANEL_URL, text=PANEL.get_response_ok()) # Set up automations automation_text = '[' + \ AUTOMATION.get_response_ok( aid=1, name='Test Automation Uno', is_active=True, the_type=CONST.AUTOMATION_TYPE_LOCATION, sub_type=CONST.AUTOMATION_SUBTYPE_ENTERING_HOME) + ',' + \ AUTOMATION.get_response_ok( aid=2, name='Test Automation Dos', is_active=True, the_type=CONST.AUTOMATION_TYPE_STATUS) + ',' + \ AUTOMATION.get_response_ok( aid=3, name='Test Automation Tres', is_active=True, the_type=CONST.AUTOMATION_TYPE_SCHEDULE) + ']' automation_json = json.loads(automation_text) m.get(CONST.AUTOMATION_URL, text=automation_text) # Logout to reset everything self.abode.logout() # Test that the automations return the correct number automations = self.abode.get_automations() self.assertEqual(len(automations), 3) # Get the first automation and test # pylint: disable=W0212 automation_1 = self.abode.get_automation(1) self.assertIsNotNone(automation_1) self.assertEqual(automation_1._automation, automation_json[0]) automation_2 = self.abode.get_automation(2) self.assertIsNotNone(automation_2) self.assertEqual(automation_2._automation, automation_json[1]) automation_3 = self.abode.get_automation(3) self.assertIsNotNone(automation_3) self.assertEqual(automation_3._automation, automation_json[2])