Exemple #1
0
    def tests_auto_fetch(self, m):
        """Test that automatic device and automation retrieval 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.PANEL_URL, text=panel_json)
        m.get(CONST.DEVICES_URL, text=DEVICES.EMPTY_DEVICE_RESPONSE)
        m.get(CONST.AUTOMATION_URL, text=DEVICES.EMPTY_DEVICE_RESPONSE)
        m.post(CONST.LOGOUT_URL, text=LOGOUT.post_response_ok())

        abode = abodepy.Abode(username='******',
                              password='******',
                              auto_login=False,
                              get_devices=True,
                              get_automations=True)

        # pylint: disable=W0212
        self.assertEqual(abode._username, 'fizz')
        self.assertEqual(abode._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))

        # Contains one device, our alarm
        self.assertEqual(abode._devices, {'area_1': abode.get_alarm()})

        # Contains no automations
        self.assertEqual(abode._automations, {})

        abode.logout()

        abode = None
Exemple #2
0
    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")
Exemple #3
0
    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)
Exemple #4
0
    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")
Exemple #5
0
    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)
Exemple #6
0
    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)
Exemple #7
0
    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)
Exemple #8
0
    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)
Exemple #9
0
    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)
Exemple #10
0
    def tests_device_status_changes(self, m):
        """Tests that device status changes work as expected."""
        # Set up URL's
        m.post(CONST.LOGIN_URL, text=LOGIN.post_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=POWERSENSOR.device(devid=POWERSENSOR.DEVICE_ID,
                                      status=CONST.STATUS_OFF,
                                      low_battery=False,
                                      no_response=False))

        # Logout to reset everything
        self.abode.logout()

        # Get our power switch
        device = self.abode.get_device(POWERSENSOR.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 + POWERSENSOR.CONTROL_URL
        m.put(control_url,
              text=DEVICES.status_put_response_ok(devid=POWERSENSOR.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=POWERSENSOR.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 device ID in response throws exception
        m.put(control_url,
              text=DEVICES.status_put_response_ok(devid='ZW:deadbeef',
                                                  status=CONST.STATUS_OFF_INT))

        with self.assertRaises(abodepy.AbodeException):
            device.switch_on()

        # Test that an invalid status in response throws exception
        m.put(control_url,
              text=DEVICES.status_put_response_ok(devid=POWERSENSOR.DEVICE_ID,
                                                  status=CONST.STATUS_OFF_INT))

        with self.assertRaises(abodepy.AbodeException):
            device.switch_on()
Exemple #11
0
    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())
Exemple #12
0
    def tests_settings_failed(self, m):
        """Check that the Skybell device settings fail without changing."""
        m.post(CONST.LOGIN_URL, text=LOGIN.post_response_ok())

        # Set up device
        device_text = '[' + DEVICE.get_response_ok() + ']'
        info_text = DEVICE_INFO.get_response_ok()
        info_url = str.replace(CONST.DEVICE_INFO_URL, '$DEVID$', DEVICE.DEVID)

        settings_text = DEVICE_SETTINGS.get_response_ok(do_not_disturb=True)
        settings_url = str.replace(CONST.DEVICE_SETTINGS_URL, '$DEVID$',
                                   DEVICE.DEVID)
        activities_url = str.replace(CONST.DEVICE_ACTIVITIES_URL, '$DEVID$',
                                     DEVICE.DEVID)

        m.get(CONST.DEVICES_URL, text=device_text)
        m.get(info_url, text=info_text)
        m.get(settings_url, text=settings_text)
        m.get(activities_url, text=DEVICE_ACTIVITIES.EMPTY_ACTIVITIES_RESPONSE)
        m.patch(settings_url,
                text=DEVICE_SETTINGS.PATHCH_RESPONSE_BAD_REQUEST,
                status_code=400)

        # Logout to reset everything
        self.skybell.logout()

        # Get our specific device
        device = self.skybell.get_device(DEVICE.DEVID)
        self.assertIsNotNone(device)
        self.assertEqual(device.do_not_disturb, True)

        # Test setting to false then validate still True
        device.do_not_disturb = False
        self.assertEqual(device.do_not_disturb, True)
Exemple #13
0
    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 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)
Exemple #15
0
    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")
Exemple #16
0
    def test_empty_cookies(self, m):
        """Check that empty cookies file is loaded successfully."""
        m.post(CONST.LOGIN_URL, text=LOGIN.post_response_ok())

        # Test empty cookies file
        empty_cache_path = "./test_cookies_empty.pickle"

        # Remove the file if it exists
        if os.path.exists(empty_cache_path):
            os.remove(empty_cache_path)

        # Create an empty file
        with open(empty_cache_path, 'a'):
            os.utime(empty_cache_path, None)

        # Assert that empty cookies file exists
        self.assertTrue(os.path.exists(empty_cache_path))

        # Cookies are created
        empty_skybell = skybellpy.Skybell(username='******',
                                          password='******',
                                          auto_login=False,
                                          cache_path=empty_cache_path,
                                          login_sleep=False)

        # Test that our cookies are fully realized prior to login
        # pylint: disable=W0212
        self.assertIsNotNone(empty_skybell._cache['app_id'])
        self.assertIsNotNone(empty_skybell._cache['client_id'])
        self.assertIsNotNone(empty_skybell._cache['token'])
        self.assertIsNone(empty_skybell._cache['access_token'])
Exemple #17
0
    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'])
Exemple #18
0
    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.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))
Exemple #19
0
    def tests_full_setup(self, m):
        """Test that Skybell is set up propertly."""
        access_token = MOCK.ACCESS_TOKEN
        login_json = LOGIN.post_response_ok(access_token=access_token)

        m.post(CONST.LOGIN_URL, text=login_json)
        m.get(CONST.DEVICES_URL, text=DEVICE.EMPTY_DEVICE_RESPONSE)

        self.skybell.get_devices()

        # pylint: disable=protected-access
        original_session = self.skybell._session

        # pylint: disable=W0212
        self.assertEqual(self.skybell._username, USERNAME)
        self.assertEqual(self.skybell._password, PASSWORD)
        self.assertEqual(self.skybell._cache['access_token'],
                         MOCK.ACCESS_TOKEN)
        self.assertEqual(len(self.skybell._devices), 0)
        self.assertIsNotNone(self.skybell._session)
        self.assertEqual(self.skybell._session, original_session)

        self.skybell.logout()

        self.assertIsNone(self.skybell._cache['access_token'])
        self.assertIsNone(self.skybell._devices)
        self.assertIsNotNone(self.skybell._session)
        self.assertNotEqual(self.skybell._session, original_session)

        self.skybell.logout()
Exemple #20
0
    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.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)
Exemple #21
0
    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
Exemple #22
0
    def tests_settings_change(self, m):
        """Check that the Skybell device changes data."""
        m.post(CONST.LOGIN_URL, text=LOGIN.post_response_ok())

        # Set up device
        device_text = '[' + DEVICE.get_response_ok() + ']'
        info_text = DEVICE_INFO.get_response_ok()
        info_url = str.replace(CONST.DEVICE_INFO_URL, '$DEVID$', DEVICE.DEVID)

        settings_text = DEVICE_SETTINGS.get_response_ok()
        settings_url = str.replace(CONST.DEVICE_SETTINGS_URL, '$DEVID$',
                                   DEVICE.DEVID)
        activities_url = str.replace(CONST.DEVICE_ACTIVITIES_URL, '$DEVID$',
                                     DEVICE.DEVID)

        m.get(CONST.DEVICES_URL, text=device_text)
        m.get(info_url, text=info_text)
        m.get(settings_url, text=settings_text)
        m.get(activities_url, text=DEVICE_ACTIVITIES.EMPTY_ACTIVITIES_RESPONSE)
        m.patch(settings_url, text=DEVICE_SETTINGS.PATCH_RESPONSE_OK)

        # Logout to reset everything
        self.skybell.logout()

        # Get our specific device
        # pylint: disable=W0212
        device = self.skybell.get_device(DEVICE.DEVID)
        self.assertIsNotNone(device)

        # Change and test new values
        for value in CONST.SETTINGS_DO_NOT_DISTURB_VALUES:
            device.do_not_disturb = value
            self.assertEqual(device.do_not_disturb,
                             distutils.util.strtobool(value))

        for value in CONST.SETTINGS_OUTDOOR_CHIME_VALUES:
            device.outdoor_chime_level = value
            self.assertEqual(device.outdoor_chime_level, value)

        for value in [True, False]:
            device.motion_sensor = value
            self.assertEqual(device.motion_sensor, value)

        for value in CONST.SETTINGS_MOTION_THRESHOLD_VALUES:
            device.motion_threshold = value
            self.assertEqual(device.motion_threshold, value)

        for value in CONST.SETTINGS_VIDEO_PROFILE_VALUES:
            device.video_profile = value
            self.assertEqual(device.video_profile, value)

        for value in CONST.SETTINGS_LED_VALUES:
            rgb = (value, value, value)
            device.led_rgb = rgb
            self.assertEqual(device.led_rgb, rgb)

        for value in CONST.SETTINGS_LED_INTENSITY_VALUES:
            device.led_intensity = value
            self.assertEqual(device.led_intensity, value)
Exemple #23
0
    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.DEVICES_URL,
              text=MOCK.response_forbidden(), status_code=403)

        with self.assertRaises(abodepy.AbodeException):
            self.abode.get_devices()
Exemple #24
0
    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))
Exemple #25
0
    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)
Exemple #26
0
    def tests_activities(self, m):
        """Check that the Skybell device activities work."""
        m.post(CONST.LOGIN_URL, text=LOGIN.post_response_ok())

        # Set up device
        device_text = '[' + DEVICE.get_response_ok() + ']'

        avatar_text = DEVICE_AVATAR.get_response_ok()
        avatar_url = str.replace(CONST.DEVICE_AVATAR_URL,
                                 '$DEVID$', DEVICE.DEVID)

        info_text = DEVICE_INFO.get_response_ok()
        info_url = str.replace(CONST.DEVICE_INFO_URL, '$DEVID$', DEVICE.DEVID)

        settings_text = DEVICE_SETTINGS.get_response_ok()
        settings_url = str.replace(CONST.DEVICE_SETTINGS_URL,
                                   '$DEVID$', DEVICE.DEVID)

        activities_text = '[' + \
                          DEVICE_ACTIVITIES.get_response_ok(
                              dev_id=DEVICE.DEVID,
                              event=CONST.EVENT_BUTTON) + ',' + \
                          DEVICE_ACTIVITIES.get_response_ok(
                              dev_id=DEVICE.DEVID,
                              event=CONST.EVENT_MOTION) + ',' + \
                          DEVICE_ACTIVITIES.get_response_ok(
                              dev_id=DEVICE.DEVID,
                              event=CONST.EVENT_ON_DEMAND) + ']'
        activities_json = json.loads(activities_text)

        activities_url = str.replace(CONST.DEVICE_ACTIVITIES_URL,
                                     '$DEVID$', DEVICE.DEVID)

        m.get(CONST.DEVICES_URL, text=device_text)
        m.get(avatar_url, text=avatar_text)
        m.get(info_url, text=info_text)
        m.get(settings_url, text=settings_text)
        m.get(activities_url, text=activities_text)

        # Logout to reset everything
        self.skybell.logout()

        # Get our specific device
        device = self.skybell.get_device(DEVICE.DEVID)
        self.assertIsNotNone(device)
        # pylint: disable=W0212
        self.assertEqual(device._activities, activities_json)

        # Get all activities from device
        activities = device.activities(limit=100)
        self.assertIsNotNone(activities)
        self.assertEqual(len(activities), 3)

        # Get only button activities
        activities = device.activities(event=CONST.EVENT_BUTTON)
        self.assertIsNotNone(activities)
        self.assertEqual(len(activities), 1)
        self.assertEqual(activities[0][CONST.EVENT], CONST.EVENT_BUTTON)
Exemple #27
0
    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))
Exemple #28
0
    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.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")
Exemple #29
0
    def tests_continuous_bad_auth(self, m):
        """Check that Skybell won't get stuck with repeated failed retries."""
        m.post(CONST.LOGIN_URL, text=LOGIN.post_response_ok())
        m.get(CONST.DEVICES_URL, text=MOCK.UNAUTORIZED, status_code=401)

        with self.assertRaises(skybellpy.SkybellException):
            self.skybell.get_devices(refresh=True)

        self.skybell.logout()
Exemple #30
0
    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())

        self.skybell_no_cred.login(username=USERNAME, password=PASSWORD)

        # pylint: disable=protected-access
        self.assertEqual(self.skybell_no_cred._username, USERNAME)
        # pylint: disable=protected-access
        self.assertEqual(self.skybell_no_cred._password, PASSWORD)