From 91ac1d956e3522f8f1bd7b8a6188b51bf6fc6c0f Mon Sep 17 00:00:00 2001 From: Quentame Date: Fri, 3 Apr 2020 18:50:12 +0200 Subject: [PATCH] Test rework + add account & fmi device test (#266) * Rework tests * Add account test * Add Find My iPhone devices test * Remove logger * Working with Python 3.4 * Make test working in more setups @patch("keyring.get_password", return_value=None) * Fix Python 2.7 ASCII * Pylint * Self reviewed --- pyicloud/base.py | 28 +- tests/__init__.py | 249 +++----- tests/const.py | 10 + tests/const_account.py | 77 +++ tests/const_findmyiphone.py | 1136 +++++++++++++++++++++++++++++++++++ tests/const_login.py | 413 +++++++++++++ tests/test_account.py | 33 + tests/test_cmdline.py | 30 +- tests/test_findmyiphone.py | 86 +++ 9 files changed, 1868 insertions(+), 194 deletions(-) create mode 100644 tests/const.py create mode 100644 tests/const_account.py create mode 100644 tests/const_findmyiphone.py create mode 100644 tests/const_login.py create mode 100644 tests/test_account.py create mode 100644 tests/test_findmyiphone.py diff --git a/pyicloud/base.py b/pyicloud/base.py index b73c878..23e2b4f 100644 --- a/pyicloud/base.py +++ b/pyicloud/base.py @@ -56,9 +56,9 @@ class PyiCloudSession(Session): def __init__(self, service): self.service = service - super(PyiCloudSession, self).__init__() + Session.__init__(self) - def request(self, *args, **kwargs): # pylint: disable=arguments-differ + def request(self, method, url, **kwargs): # pylint: disable=arguments-differ # Charge logging to the right service endpoint callee = inspect.stack()[2] @@ -67,10 +67,10 @@ class PyiCloudSession(Session): if self.service.password_filter not in request_logger.filters: request_logger.addFilter(self.service.password_filter) - request_logger.debug("%s %s %s", args[0], args[1], kwargs.get("data", "")) + request_logger.debug("%s %s %s", method, url, kwargs.get("data", "")) kwargs.pop("retried", None) - response = super(PyiCloudSession, self).request(*args, **kwargs) + response = super(PyiCloudSession, self).request(method, url, **kwargs) content_type = response.headers.get("Content-Type", "").split(";")[0] json_mimetypes = ["application/json", "text/json"] @@ -82,7 +82,7 @@ class PyiCloudSession(Session): ) request_logger.warn(api_error) kwargs["retried"] = True - return self.request(*args, **kwargs) + return self.request(method, url, **kwargs) self._raise_error(response.status_code, response.reason) if content_type not in json_mimetypes: @@ -150,6 +150,9 @@ class PyiCloudService(object): pyicloud.iphone.location() """ + HOME_ENDPOINT = "https://www.icloud.com" + SETUP_ENDPOINT = "https://setup.icloud.com/setup/ws/1" + def __init__( self, apple_id, @@ -170,10 +173,7 @@ class PyiCloudService(object): self.password_filter = PyiCloudPasswordFilter(password) LOGGER.addFilter(self.password_filter) - self._home_endpoint = "https://www.icloud.com" - self._setup_endpoint = "https://setup.icloud.com/setup/ws/1" - - self._base_login_url = "%s/login" % self._setup_endpoint + self._base_login_url = "%s/login" % self.SETUP_ENDPOINT if cookie_directory: self._cookie_directory = os.path.expanduser( @@ -186,8 +186,8 @@ class PyiCloudService(object): self.session.verify = verify self.session.headers.update( { - "Origin": self._home_endpoint, - "Referer": "%s/" % self._home_endpoint, + "Origin": self.HOME_ENDPOINT, + "Referer": "%s/" % self.HOME_ENDPOINT, "User-Agent": "Opera/9.52 (X11; Linux i686; U; en)", } ) @@ -270,7 +270,7 @@ class PyiCloudService(object): def trusted_devices(self): """Returns devices trusted for two-step authentication.""" request = self.session.get( - "%s/listDevices" % self._setup_endpoint, params=self.params + "%s/listDevices" % self.SETUP_ENDPOINT, params=self.params ) return request.json().get("devices") @@ -278,7 +278,7 @@ class PyiCloudService(object): """Requests that a verification code is sent to the given device.""" data = json.dumps(device) request = self.session.post( - "%s/sendVerificationCode" % self._setup_endpoint, + "%s/sendVerificationCode" % self.SETUP_ENDPOINT, params=self.params, data=data, ) @@ -291,7 +291,7 @@ class PyiCloudService(object): try: self.session.post( - "%s/validateVerificationCode" % self._setup_endpoint, + "%s/validateVerificationCode" % self.SETUP_ENDPOINT, params=self.params, data=data, ) diff --git a/tests/__init__.py b/tests/__init__.py index 04b92f7..14be3e8 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,13 +1,87 @@ """Library tests.""" +import json +from requests import Session, Response from pyicloud import base from pyicloud.exceptions import PyiCloudFailedLoginException from pyicloud.services.findmyiphone import FindMyiPhoneServiceManager, AppleDevice +from .const import ( + AUTHENTICATED_USER, + REQUIRES_2SA_USER, + VALID_USERS, + VALID_PASSWORD, +) +from .const_login import ( + LOGIN_WORKING, + LOGIN_2SA, + TRUSTED_DEVICES, + TRUSTED_DEVICE_1, + VERIFICATION_CODE_OK, + VERIFICATION_CODE_KO, +) +from .const_account import ACCOUNT_DEVICES_WORKING +from .const_findmyiphone import FMI_FMLY_WORKING -AUTHENTICATED_USER = "authenticated_user" -REQUIRES_2SA_USER = "requires_2sa_user" -VALID_USERS = [AUTHENTICATED_USER, REQUIRES_2SA_USER] + +class ResponseMock(Response): + """Mocked Response.""" + + def __init__(self, result, status_code=200): + Response.__init__(self) + self.result = result + self.status_code = status_code + + @property + def text(self): + return json.dumps(self.result) + + +class PyiCloudSessionMock(base.PyiCloudSession): + """Mocked PyiCloudSession.""" + + def request(self, method, url, **kwargs): + data = json.loads(kwargs.get("data", "{}")) + + # Login + if self.service.SETUP_ENDPOINT in url: + if "login" in url and method == "POST": + if ( + data.get("apple_id") not in VALID_USERS + or data.get("password") != VALID_PASSWORD + ): + self._raise_error(None, "Unknown reason") + if ( + data.get("apple_id") == REQUIRES_2SA_USER + and data.get("password") == VALID_PASSWORD + ): + return ResponseMock(LOGIN_2SA) + return ResponseMock(LOGIN_WORKING) + + if "listDevices" in url and method == "GET": + return ResponseMock(TRUSTED_DEVICES) + + if "sendVerificationCode" in url and method == "POST": + if data == TRUSTED_DEVICE_1: + return ResponseMock(VERIFICATION_CODE_OK) + return ResponseMock(VERIFICATION_CODE_KO) + + if "validateVerificationCode" in url and method == "POST": + TRUSTED_DEVICE_1.update({"verificationCode": "0", "trustBrowser": True}) + if data == TRUSTED_DEVICE_1: + self.service.user["apple_id"] = AUTHENTICATED_USER + return ResponseMock(VERIFICATION_CODE_OK) + self._raise_error(None, "FOUND_CODE") + + # Account + if "device/getDevices" in url and method == "GET": + return ResponseMock(ACCOUNT_DEVICES_WORKING) + + # Find My iPhone + if "fmi" in url and method == "POST": + return ResponseMock(FMI_FMLY_WORKING) + + return None class PyiCloudServiceMock(base.PyiCloudService): @@ -22,174 +96,7 @@ class PyiCloudServiceMock(base.PyiCloudService): client_id=None, with_family=True, ): + base.PyiCloudSession = PyiCloudSessionMock base.PyiCloudService.__init__( self, apple_id, password, cookie_directory, verify, client_id, with_family ) - base.FindMyiPhoneServiceManager = FindMyiPhoneServiceManagerMock - - def authenticate(self): - if ( - not self.user.get("apple_id") - or self.user.get("apple_id") not in VALID_USERS - ): - raise PyiCloudFailedLoginException( - "Invalid email/password combination.", None - ) - if not self.user.get("password") or self.user.get("password") != "valid_pass": - raise PyiCloudFailedLoginException( - "Invalid email/password combination.", None - ) - - self.params.update({"dsid": "ID"}) - self._webservices = { - "account": {"url": "account_url",}, - "findme": {"url": "findme_url",}, - "calendar": {"url": "calendar_url",}, - "contacts": {"url": "contacts_url",}, - "reminders": {"url": "reminders_url",}, - } - - @property - def requires_2sa(self): - return self.user["apple_id"] is REQUIRES_2SA_USER - - @property - def trusted_devices(self): - return [ - { - "deviceType": "SMS", - "areaCode": "", - "phoneNumber": "*******58", - "deviceId": "1", - } - ] - - def send_verification_code(self, device): - return device - - def validate_verification_code(self, device, code): - if not device or code != 0: - self.user["apple_id"] = AUTHENTICATED_USER - self.authenticate() - return not self.requires_2sa - - -IPHONE_DEVICE_ID = "X1x/X&x=" -IPHONE_DEVICE = AppleDevice( - { - "msg": { - "strobe": False, - "userText": False, - "playSound": True, - "vibrate": True, - "createTimestamp": 1568031021347, - "statusCode": "200", - }, - "canWipeAfterLock": True, - "baUUID": "", - "wipeInProgress": False, - "lostModeEnabled": False, - "activationLocked": True, - "passcodeLength": 6, - "deviceStatus": "200", - "deviceColor": "1-6-0", - "features": { - "MSG": True, - "LOC": True, - "LLC": False, - "CLK": False, - "TEU": True, - "LMG": False, - "SND": True, - "CLT": False, - "LKL": False, - "SVP": False, - "LST": True, - "LKM": False, - "WMG": True, - "SPN": False, - "XRM": False, - "PIN": False, - "LCK": True, - "REM": False, - "MCS": False, - "CWP": False, - "KEY": False, - "KPD": False, - "WIP": True, - }, - "lowPowerMode": True, - "rawDeviceModel": "iPhone11,8", - "id": IPHONE_DEVICE_ID, - "remoteLock": None, - "isLocating": True, - "modelDisplayName": "iPhone", - "lostTimestamp": "", - "batteryLevel": 0.47999998927116394, - "mesg": None, - "locationEnabled": True, - "lockedTimestamp": None, - "locFoundEnabled": False, - "snd": {"createTimestamp": 1568031021347, "statusCode": "200"}, - "fmlyShare": False, - "lostDevice": { - "stopLostMode": False, - "emailUpdates": False, - "userText": True, - "sound": False, - "ownerNbr": "", - "text": "", - "createTimestamp": 1558383841233, - "statusCode": "2204", - }, - "lostModeCapable": True, - "wipedTimestamp": None, - "deviceDisplayName": "iPhone XR", - "prsId": None, - "audioChannels": [], - "locationCapable": True, - "batteryStatus": "NotCharging", - "trackingInfo": None, - "name": "Quentin's iPhone", - "isMac": False, - "thisDevice": False, - "deviceClass": "iPhone", - "location": { - "isOld": False, - "isInaccurate": False, - "altitude": 0.0, - "positionType": "GPS", - "latitude": 46.012345678, - "floorLevel": 0, - "horizontalAccuracy": 12.012345678, - "locationType": "", - "timeStamp": 1568827039692, - "locationFinished": False, - "verticalAccuracy": 0.0, - "longitude": 5.012345678, - }, - "deviceModel": "iphoneXR-1-6-0", - "maxMsgChar": 160, - "darkWake": False, - "remoteWipe": None, - }, - None, - None, - None, -) - -DEVICES = { - IPHONE_DEVICE_ID: IPHONE_DEVICE, -} - - -class FindMyiPhoneServiceManagerMock(FindMyiPhoneServiceManager): - """Mocked FindMyiPhoneServiceManager.""" - - def __init__(self, service_root, session, params, with_family=False): - FindMyiPhoneServiceManager.__init__( - self, service_root, session, params, with_family - ) - - def refresh_client(self): - self._devices = DEVICES diff --git a/tests/const.py b/tests/const.py new file mode 100644 index 0000000..9aa8b5a --- /dev/null +++ b/tests/const.py @@ -0,0 +1,10 @@ +"""Test constants.""" +from .const_login import PRIMARY_EMAIL, APPLE_ID_EMAIL, ICLOUD_ID_EMAIL + +# Base +AUTHENTICATED_USER = PRIMARY_EMAIL +REQUIRES_2SA_USER = "requires_2sa_user" +VALID_USERS = [AUTHENTICATED_USER, REQUIRES_2SA_USER, APPLE_ID_EMAIL, ICLOUD_ID_EMAIL] +VALID_PASSWORD = "valid_password" + +CLIENT_ID = "client_id" diff --git a/tests/const_account.py b/tests/const_account.py new file mode 100644 index 0000000..c6d7219 --- /dev/null +++ b/tests/const_account.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- +"""Account test constants.""" +from .const_login import FIRST_NAME + +# Fakers +PAYMENT_METHOD_ID_1 = "PAYMENT_METHOD_ID_1" +PAYMENT_METHOD_ID_2 = "PAYMENT_METHOD_ID_2" +PAYMENT_METHOD_ID_3 = "PAYMENT_METHOD_ID_3" +PAYMENT_METHOD_ID_4 = "PAYMENT_METHOD_ID_4" + +# Data +ACCOUNT_DEVICES_WORKING = { + "devices": [ + { + "serialNumber": "●●●●●●●NG123", + "osVersion": "OSX;10.15.3", + "modelLargePhotoURL2x": "https://statici.icloud.com/fmipmobile/deviceImages-4.0/MacBookPro/MacBookPro15,1-spacegray/online-infobox__2x.png", + "modelLargePhotoURL1x": "https://statici.icloud.com/fmipmobile/deviceImages-4.0/MacBookPro/MacBookPro15,1-spacegray/online-infobox.png", + "paymentMethods": [PAYMENT_METHOD_ID_3], + "name": "MacBook Pro de " + FIRST_NAME, + "imei": "", + "model": "MacBookPro15,1", + "udid": "MacBookPro15,1" + FIRST_NAME, + "modelSmallPhotoURL2x": "https://statici.icloud.com/fmipmobile/deviceImages-4.0/MacBookPro/MacBookPro15,1-spacegray/online-sourcelist__2x.png", + "modelSmallPhotoURL1x": "https://statici.icloud.com/fmipmobile/deviceImages-4.0/MacBookPro/MacBookPro15,1-spacegray/online-sourcelist.png", + "modelDisplayName": 'MacBook Pro 15"', + }, + { + "serialNumber": "●●●●●●●UX123", + "osVersion": "iOS;13.3", + "modelLargePhotoURL2x": "https://statici.icloud.com/fmipmobile/deviceImages-4.0/iPhone/iPhone12,1-1-6-0/online-infobox__2x.png", + "modelLargePhotoURL1x": "https://statici.icloud.com/fmipmobile/deviceImages-4.0/iPhone/iPhone12,1-1-6-0/online-infobox.png", + "paymentMethods": [ + PAYMENT_METHOD_ID_4, + PAYMENT_METHOD_ID_2, + PAYMENT_METHOD_ID_1, + ], + "name": "iPhone de " + FIRST_NAME, + "imei": "●●●●●●●●●●12345", + "model": "iPhone12,1", + "udid": "iPhone12,1" + FIRST_NAME, + "modelSmallPhotoURL2x": "https://statici.icloud.com/fmipmobile/deviceImages-4.0/iPhone/iPhone12,1-1-6-0/online-sourcelist__2x.png", + "modelSmallPhotoURL1x": "https://statici.icloud.com/fmipmobile/deviceImages-4.0/iPhone/iPhone12,1-1-6-0/online-sourcelist.png", + "modelDisplayName": "iPhone 11", + }, + ], + "paymentMethods": [ + { + "lastFourDigits": "333", + "balanceStatus": "NOTAPPLICABLE", + "suspensionReason": "ACTIVE", + "id": PAYMENT_METHOD_ID_3, + "type": "Boursorama Banque", + }, + { + "lastFourDigits": "444", + "balanceStatus": "NOTAPPLICABLE", + "suspensionReason": "ACTIVE", + "id": PAYMENT_METHOD_ID_4, + "type": "Carte Crédit Agricole", + }, + { + "lastFourDigits": "2222", + "balanceStatus": "NOTAPPLICABLE", + "suspensionReason": "ACTIVE", + "id": PAYMENT_METHOD_ID_2, + "type": "Lydia", + }, + { + "lastFourDigits": "111", + "balanceStatus": "NOTAPPLICABLE", + "suspensionReason": "ACTIVE", + "id": PAYMENT_METHOD_ID_1, + "type": "Boursorama Banque", + }, + ], +} diff --git a/tests/const_findmyiphone.py b/tests/const_findmyiphone.py new file mode 100644 index 0000000..959bc86 --- /dev/null +++ b/tests/const_findmyiphone.py @@ -0,0 +1,1136 @@ +"""Find my iPhone test constants.""" +from .const import CLIENT_ID +from .const_login import FIRST_NAME, LAST_NAME, PERSON_ID, FULL_NAME + +# Base +MEMBER_1_FIRST_NAME = "John" +MEMBER_1_LAST_NAME = "TRAVOLTA" +MEMBER_1_PERSON_ID = (MEMBER_1_FIRST_NAME + MEMBER_1_LAST_NAME).lower() +MEMBER_1_APPLE_ID = MEMBER_1_PERSON_ID + "@icloud.com" + +MEMBER_2_FIRST_NAME = "Uma" +MEMBER_2_LAST_NAME = "THURMAN" +MEMBER_2_PERSON_ID = (MEMBER_2_FIRST_NAME + MEMBER_2_LAST_NAME).lower() +MEMBER_2_APPLE_ID = MEMBER_2_PERSON_ID + "@outlook.fr" + +# Fakers +UUID = "ABCDEFGH-1234-5678-1234-ABCDEFGHIJKL" +LOCATION_LATITUDE = 45.123456789012345 +LOCATION_LONGITUDE = 6.1234567890123456 + +# Data +# Re-generated device : +# id = rawDeviceModel + prsId (if not None) +# baUUID = UUID + id +# So they can still be faked and unique +FMI_FMLY_WORKING = { + "userInfo": { + "accountFormatter": 0, + "firstName": FIRST_NAME, + "lastName": LAST_NAME, + "membersInfo": { + MEMBER_1_PERSON_ID: { + "accountFormatter": 0, + "firstName": MEMBER_1_FIRST_NAME, + "lastName": MEMBER_1_LAST_NAME, + "deviceFetchStatus": "LOADING", + "useAuthWidget": True, + "isHSA": True, + "appleId": MEMBER_1_APPLE_ID, + }, + MEMBER_2_PERSON_ID: { + "accountFormatter": 0, + "firstName": MEMBER_2_FIRST_NAME, + "lastName": MEMBER_2_LAST_NAME, + "deviceFetchStatus": "LOADING", + "useAuthWidget": True, + "isHSA": True, + "appleId": MEMBER_2_APPLE_ID, + }, + }, + "hasMembers": True, + }, + "serverContext": { + "minCallbackIntervalInMS": 5000, + "enable2FAFamilyActions": False, + "preferredLanguage": "fr-fr", + "lastSessionExtensionTime": None, + "enableMapStats": True, + "callbackIntervalInMS": 2000, + "validRegion": True, + "timezone": { + "currentOffset": -25200000, + "previousTransition": 1583661599999, + "previousOffset": -28800000, + "tzCurrentName": "Pacific Daylight Time", + "tzName": "America/Los_Angeles", + }, + "authToken": None, + "maxCallbackIntervalInMS": 60000, + "classicUser": False, + "isHSA": True, + "trackInfoCacheDurationInSecs": 86400, + "imageBaseUrl": "https://statici.icloud.com", + "minTrackLocThresholdInMts": 100, + "maxLocatingTime": 90000, + "sessionLifespan": 900000, + "info": "info_id", + "prefsUpdateTime": 1413548552466, + "useAuthWidget": True, + "clientId": CLIENT_ID, + "enable2FAFamilyRemove": False, + "serverTimestamp": 1585867038112, + "deviceImageVersion": "4", + "macCount": 0, + "deviceLoadStatus": "200", + "maxDeviceLoadTime": 60000, + "prsId": PERSON_ID, + "showSllNow": False, + "cloudUser": True, + "enable2FAErase": False, + }, + "alert": None, + "userPreferences": { + "webPrefs": {"id": "web_prefs", "selectedDeviceId": "iPhone4,1",} + }, + "content": [ + { + "msg": { + "strobe": False, + "userText": False, + "playSound": True, + "vibrate": True, + "createTimestamp": 1584520568680, + "statusCode": "200", + }, + "canWipeAfterLock": True, + "baUUID": UUID + "iPhone12,1", + "wipeInProgress": False, + "lostModeEnabled": False, + "activationLocked": True, + "passcodeLength": 6, + "deviceStatus": "200", + "deviceColor": "1-6-0", + "features": { + "BTR": False, + "LLC": False, + "CLK": False, + "TEU": True, + "SND": True, + "CLT": False, + "SVP": False, + "SPN": False, + "XRM": False, + "CWP": False, + "MSG": True, + "LOC": True, + "LMG": False, + "LKL": False, + "LST": True, + "LKM": False, + "WMG": True, + "PSS": False, + "PIN": False, + "LCK": True, + "REM": False, + "MCS": False, + "KEY": False, + "KPD": False, + "WIP": True, + }, + "lowPowerMode": True, + "rawDeviceModel": "iPhone12,1", + "id": "iPhone12,1", + "remoteLock": None, + "isLocating": True, + "modelDisplayName": "iPhone", + "lostTimestamp": "", + "batteryLevel": 0.8299999833106995, + "mesg": None, + "locationEnabled": True, + "lockedTimestamp": None, + "locFoundEnabled": False, + "snd": {"createTimestamp": 1584520568680, "statusCode": "200"}, + "fmlyShare": False, + "lostDevice": None, + "lostModeCapable": True, + "wipedTimestamp": None, + "deviceDisplayName": "iPhone 11", + "prsId": None, + "audioChannels": [], + "locationCapable": True, + "batteryStatus": "NotCharging", + "trackingInfo": None, + "name": "iPhone de " + FIRST_NAME, + "isMac": False, + "thisDevice": False, + "deviceClass": "iPhone", + "location": { + "isOld": False, + "isInaccurate": False, + "altitude": 0.0, + "positionType": "GPS", + "latitude": LOCATION_LATITUDE, + "floorLevel": 0, + "horizontalAccuracy": 4.5370291025030465, + "locationType": "", + "timeStamp": 1585867037749, + "locationFinished": True, + "verticalAccuracy": 0.0, + "longitude": LOCATION_LONGITUDE, + }, + "deviceModel": "iphone11-1-6-0", + "maxMsgChar": 160, + "darkWake": False, + "remoteWipe": None, + }, + { + "msg": { + "strobe": False, + "userText": True, + "playSound": False, + "vibrate": False, + "createTimestamp": 1583057432463, + "statusCode": "205", + }, + "canWipeAfterLock": True, + "baUUID": "", + "wipeInProgress": False, + "lostModeEnabled": False, + "activationLocked": False, + "passcodeLength": 4, + "deviceStatus": "203", + "deviceColor": None, + "features": { + "BTR": False, + "LLC": False, + "CLK": False, + "TEU": True, + "SND": True, + "CLT": False, + "SVP": False, + "SPN": False, + "XRM": False, + "CWP": False, + "MSG": True, + "LOC": True, + "LMG": False, + "LKL": True, + "LST": True, + "LKM": False, + "WMG": False, + "PSS": False, + "PIN": False, + "LCK": True, + "REM": True, + "MCS": False, + "KEY": False, + "KPD": False, + "WIP": True, + }, + "lowPowerMode": False, + "rawDeviceModel": "iPhone4,1", + "id": "iPhone4,1", + "remoteLock": None, + "isLocating": False, + "modelDisplayName": "iPhone", + "lostTimestamp": "", + "batteryLevel": 0.0, + "mesg": {"createTimestamp": 1583057432463, "statusCode": "205"}, + "locationEnabled": True, + "lockedTimestamp": None, + "locFoundEnabled": False, + "snd": None, + "fmlyShare": False, + "lostDevice": { + "stopLostMode": False, + "emailUpdates": True, + "userText": True, + "sound": False, + "ownerNbr": "", + "text": "", + "createTimestamp": 1463594549526, + "statusCode": "2201", + }, + "lostModeCapable": True, + "wipedTimestamp": None, + "deviceDisplayName": "iPhone 4s", + "prsId": None, + "audioChannels": [], + "locationCapable": True, + "batteryStatus": "Unknown", + "trackingInfo": None, + "name": "iPhone " + FULL_NAME, + "isMac": False, + "thisDevice": False, + "deviceClass": "iPhone", + "location": None, + "deviceModel": "FifthGen", + "maxMsgChar": 160, + "darkWake": False, + "remoteWipe": None, + }, + { + "msg": { + "strobe": False, + "userText": True, + "playSound": False, + "vibrate": False, + "createTimestamp": 1583057432463, + "statusCode": "205", + }, + "canWipeAfterLock": True, + "baUUID": "", + "wipeInProgress": False, + "lostModeEnabled": False, + "activationLocked": False, + "passcodeLength": 4, + "deviceStatus": "203", + "deviceColor": "white", + "features": { + "BTR": False, + "LLC": False, + "CLK": False, + "TEU": True, + "SND": True, + "CLT": False, + "SVP": False, + "SPN": False, + "XRM": False, + "CWP": False, + "MSG": True, + "LOC": True, + "LMG": False, + "LKL": True, + "LST": True, + "LKM": False, + "WMG": False, + "PSS": False, + "PIN": False, + "LCK": True, + "REM": True, + "MCS": False, + "KEY": False, + "KPD": False, + "WIP": True, + }, + "lowPowerMode": False, + "rawDeviceModel": "iPod4,1", + "id": "iPod4,1", + "remoteLock": None, + "isLocating": False, + "modelDisplayName": "iPod", + "lostTimestamp": "", + "batteryLevel": 0.0, + "mesg": {"createTimestamp": 1583057432463, "statusCode": "205"}, + "locationEnabled": True, + "lockedTimestamp": None, + "locFoundEnabled": False, + "snd": None, + "fmlyShare": False, + "lostDevice": None, + "lostModeCapable": True, + "wipedTimestamp": None, + "deviceDisplayName": "iPod touch (4th generation)", + "prsId": None, + "audioChannels": [], + "locationCapable": True, + "batteryStatus": "Unknown", + "trackingInfo": None, + "name": "iPod Touch 4 " + MEMBER_2_FIRST_NAME, + "isMac": False, + "thisDevice": False, + "deviceClass": "iPod", + "location": None, + "deviceModel": "FourthGen-white", + "maxMsgChar": 160, + "darkWake": False, + "remoteWipe": None, + }, + { + "msg": { + "strobe": False, + "userText": False, + "playSound": True, + "vibrate": False, + "createTimestamp": 1398963329049, + "statusCode": "200", + }, + "canWipeAfterLock": False, + "baUUID": "", + "wipeInProgress": False, + "lostModeEnabled": False, + "activationLocked": False, + "passcodeLength": 4, + "deviceStatus": "203", + "deviceColor": None, + "features": { + "BTR": False, + "LLC": False, + "CLK": False, + "TEU": False, + "SND": True, + "CLT": False, + "SVP": False, + "SPN": False, + "XRM": False, + "CWP": False, + "MSG": True, + "LOC": True, + "LMG": True, + "LKL": True, + "LST": False, + "LKM": True, + "WMG": False, + "PSS": False, + "PIN": True, + "LCK": True, + "REM": True, + "MCS": False, + "KEY": True, + "KPD": True, + "WIP": True, + }, + "lowPowerMode": False, + "rawDeviceModel": "MacBookPro10,1", + "id": "MacBookPro10,1", + "remoteLock": None, + "isLocating": False, + "modelDisplayName": "MacBook Pro", + "lostTimestamp": "", + "batteryLevel": 0.0, + "mesg": None, + "locationEnabled": True, + "lockedTimestamp": None, + "locFoundEnabled": False, + "snd": {"createTimestamp": 1398963329049, "statusCode": "200"}, + "fmlyShare": False, + "lostDevice": None, + "lostModeCapable": False, + "wipedTimestamp": None, + "deviceDisplayName": 'MacBook Pro 15"', + "prsId": None, + "audioChannels": [], + "locationCapable": True, + "batteryStatus": "Unknown", + "trackingInfo": None, + "name": "Retina " + MEMBER_2_FIRST_NAME, + "isMac": True, + "thisDevice": False, + "deviceClass": "MacBookPro", + "location": None, + "deviceModel": "MacBookPro10_1", + "maxMsgChar": 500, + "darkWake": False, + "remoteWipe": None, + }, + { + "msg": { + "strobe": False, + "userText": True, + "playSound": False, + "vibrate": False, + "createTimestamp": 1583057432463, + "statusCode": "200", + }, + "canWipeAfterLock": False, + "baUUID": "", + "wipeInProgress": False, + "lostModeEnabled": False, + "activationLocked": False, + "passcodeLength": 6, + "deviceStatus": "203", + "deviceColor": None, + "features": { + "BTR": False, + "LLC": False, + "CLK": False, + "TEU": False, + "SND": True, + "CLT": False, + "SVP": False, + "SPN": False, + "XRM": False, + "CWP": False, + "MSG": True, + "LOC": True, + "LMG": True, + "LKL": True, + "LST": False, + "LKM": True, + "WMG": False, + "PSS": False, + "PIN": True, + "LCK": True, + "REM": True, + "MCS": False, + "KEY": False, + "KPD": True, + "WIP": True, + }, + "lowPowerMode": False, + "rawDeviceModel": "MacBookPro11,3", + "id": "MacBookPro11,3", + "remoteLock": {"createTimestamp": 1433338956786, "statusCode": "2201"}, + "isLocating": False, + "modelDisplayName": "MacBook Pro", + "lostTimestamp": "", + "batteryLevel": 0.0, + "mesg": {"createTimestamp": 1583057432463, "statusCode": "200"}, + "locationEnabled": True, + "lockedTimestamp": None, + "locFoundEnabled": False, + "snd": None, + "fmlyShare": False, + "lostDevice": None, + "lostModeCapable": False, + "wipedTimestamp": None, + "deviceDisplayName": 'MacBook Pro 15"', + "prsId": None, + "audioChannels": [], + "locationCapable": True, + "batteryStatus": "Unknown", + "trackingInfo": None, + "name": "Retina " + FIRST_NAME, + "isMac": True, + "thisDevice": False, + "deviceClass": "MacBookPro", + "location": None, + "deviceModel": "MacBookPro11_3", + "maxMsgChar": 500, + "darkWake": False, + "remoteWipe": None, + }, + { + "msg": { + "strobe": False, + "userText": True, + "playSound": False, + "vibrate": False, + "createTimestamp": 1583057432463, + "statusCode": "200", + }, + "canWipeAfterLock": False, + "baUUID": UUID + "MacBookPro15,1", + "wipeInProgress": False, + "lostModeEnabled": False, + "activationLocked": True, + "passcodeLength": 6, + "deviceStatus": "201", + "deviceColor": "spacegray", + "features": { + "BTR": False, + "LLC": False, + "CLK": False, + "TEU": False, + "SND": True, + "CLT": False, + "SVP": False, + "SPN": False, + "XRM": False, + "CWP": False, + "MSG": True, + "LOC": True, + "LMG": True, + "LKL": False, + "LST": False, + "LKM": True, + "WMG": False, + "PSS": False, + "PIN": True, + "LCK": True, + "REM": True, + "MCS": False, + "KEY": True, + "KPD": True, + "WIP": True, + }, + "lowPowerMode": False, + "rawDeviceModel": "MacBookPro15,1", + "id": "MacBookPro15,1", + "remoteLock": None, + "isLocating": False, + "modelDisplayName": "MacBook Pro", + "lostTimestamp": "", + "batteryLevel": 0.26968246698379517, + "mesg": {"createTimestamp": 1583057432463, "statusCode": "200"}, + "locationEnabled": True, + "lockedTimestamp": None, + "locFoundEnabled": False, + "snd": None, + "fmlyShare": False, + "lostDevice": None, + "lostModeCapable": False, + "wipedTimestamp": None, + "deviceDisplayName": 'MacBook Pro 15"', + "prsId": None, + "audioChannels": [], + "locationCapable": True, + "batteryStatus": "Charging", + "trackingInfo": None, + "name": "MacBook Pro de " + FIRST_NAME, + "isMac": True, + "thisDevice": False, + "deviceClass": "MacBookPro", + "location": { + "isOld": False, + "isInaccurate": False, + "altitude": 0.0, + "positionType": "Wifi", + "latitude": LOCATION_LATITUDE, + "floorLevel": 0, + "horizontalAccuracy": 65.0, + "locationType": "", + "timeStamp": 1585867020040, + "locationFinished": False, + "verticalAccuracy": 0.0, + "longitude": LOCATION_LONGITUDE, + }, + "deviceModel": "MacBookPro15_1-spacegray", + "maxMsgChar": 500, + "darkWake": False, + "remoteWipe": None, + }, + { + "msg": None, + "canWipeAfterLock": False, + "baUUID": "", + "wipeInProgress": False, + "lostModeEnabled": False, + "activationLocked": False, + "passcodeLength": 6, + "deviceStatus": "200", + "deviceColor": "0", + "features": { + "BTR": True, + "LLC": False, + "CLK": False, + "TEU": False, + "SND": True, + "CLT": False, + "SVP": False, + "SPN": False, + "XRM": False, + "CWP": False, + "MSG": True, + "LOC": True, + "LMG": False, + "LKL": False, + "LST": False, + "LKM": False, + "WMG": False, + "PSS": True, + "PIN": False, + "LCK": False, + "REM": False, + "MCS": True, + "KEY": False, + "KPD": False, + "WIP": False, + }, + "lowPowerMode": False, + "rawDeviceModel": "AirPods_8207", + "id": "AirPods_8207", + "remoteLock": None, + "isLocating": False, + "modelDisplayName": "Accessory", + "lostTimestamp": "", + "batteryLevel": 0.0, + "mesg": None, + "locationEnabled": True, + "lockedTimestamp": None, + "locFoundEnabled": False, + "snd": None, + "fmlyShare": False, + "lostDevice": None, + "lostModeCapable": False, + "wipedTimestamp": None, + "deviceDisplayName": "Accessory", + "prsId": None, + "audioChannels": [ + {"name": "left", "available": 1, "playing": False, "muted": False}, + {"name": "right", "available": 1, "playing": False, "muted": False}, + ], + "locationCapable": True, + "batteryStatus": "Unknown", + "trackingInfo": None, + "name": "AirPods de " + FULL_NAME, + "isMac": False, + "thisDevice": False, + "deviceClass": "Accessory", + "location": { + "isOld": False, + "isInaccurate": False, + "altitude": 0.0, + "positionType": "GPS", + "latitude": LOCATION_LATITUDE, + "floorLevel": 0, + "horizontalAccuracy": 4.5370291025030465, + "locationType": "", + "timeStamp": 1585867037749, + "locationFinished": True, + "verticalAccuracy": 0.0, + "longitude": LOCATION_LONGITUDE, + }, + "deviceModel": "AirPods_8207-0", + "maxMsgChar": 160, + "darkWake": False, + "remoteWipe": None, + }, + { + "msg": None, + "canWipeAfterLock": False, + "baUUID": "", + "wipeInProgress": False, + "lostModeEnabled": False, + "activationLocked": False, + "passcodeLength": 4, + "deviceStatus": "201", + "deviceColor": None, + "features": { + "BTR": False, + "LLC": False, + "CLK": False, + "TEU": False, + "SND": True, + "CLT": False, + "SVP": False, + "SPN": False, + "XRM": False, + "CWP": False, + "MSG": True, + "LOC": True, + "LMG": True, + "LKL": False, + "LST": False, + "LKM": True, + "WMG": False, + "PSS": False, + "PIN": True, + "LCK": True, + "REM": True, + "MCS": False, + "KEY": True, + "KPD": True, + "WIP": True, + }, + "lowPowerMode": False, + "rawDeviceModel": "MacBookPro10,1", + "id": "MacBookPro10,1" + MEMBER_2_PERSON_ID, + "remoteLock": None, + "isLocating": False, + "modelDisplayName": "MacBook Pro", + "lostTimestamp": "", + "batteryLevel": 0.0, + "mesg": None, + "locationEnabled": True, + "lockedTimestamp": None, + "locFoundEnabled": False, + "snd": None, + "fmlyShare": False, + "lostDevice": None, + "lostModeCapable": False, + "wipedTimestamp": None, + "deviceDisplayName": 'MacBook Pro 15"', + "prsId": MEMBER_2_PERSON_ID, + "audioChannels": [], + "locationCapable": True, + "batteryStatus": "Unknown", + "trackingInfo": None, + "name": "MacBook Pro de " + MEMBER_2_FIRST_NAME, + "isMac": True, + "thisDevice": False, + "deviceClass": "MacBookPro", + "location": None, + "deviceModel": "MacBookPro10_1", + "maxMsgChar": 500, + "darkWake": False, + "remoteWipe": None, + }, + { + "msg": None, + "canWipeAfterLock": True, + "baUUID": UUID + "iPhone12,1" + MEMBER_2_PERSON_ID, + "wipeInProgress": False, + "lostModeEnabled": False, + "activationLocked": True, + "passcodeLength": 6, + "deviceStatus": "200", + "deviceColor": "1-7-0", + "features": { + "BTR": False, + "LLC": False, + "CLK": False, + "TEU": True, + "SND": True, + "CLT": False, + "SVP": False, + "SPN": False, + "XRM": False, + "CWP": False, + "MSG": True, + "LOC": True, + "LMG": False, + "LKL": False, + "LST": True, + "LKM": False, + "WMG": True, + "PSS": False, + "PIN": False, + "LCK": True, + "REM": True, + "MCS": False, + "KEY": False, + "KPD": False, + "WIP": True, + }, + "lowPowerMode": False, + "rawDeviceModel": "iPhone12,1", + "id": "iPhone12,1" + MEMBER_2_PERSON_ID, + "remoteLock": None, + "isLocating": False, + "modelDisplayName": "iPhone", + "lostTimestamp": "", + "batteryLevel": 0.3400000035762787, + "mesg": None, + "locationEnabled": True, + "lockedTimestamp": None, + "locFoundEnabled": True, + "snd": None, + "fmlyShare": False, + "lostDevice": None, + "lostModeCapable": True, + "wipedTimestamp": None, + "deviceDisplayName": "iPhone 11", + "prsId": MEMBER_2_PERSON_ID, + "audioChannels": [], + "locationCapable": True, + "batteryStatus": "NotCharging", + "trackingInfo": None, + "name": "iPhone " + MEMBER_2_FIRST_NAME, + "isMac": False, + "thisDevice": False, + "deviceClass": "iPhone", + "location": None, + "deviceModel": "iphone11-1-7-0", + "maxMsgChar": 160, + "darkWake": False, + "remoteWipe": None, + }, + { + "msg": { + "strobe": False, + "userText": True, + "playSound": False, + "vibrate": False, + "createTimestamp": 1583057432335, + "statusCode": "200", + }, + "canWipeAfterLock": False, + "baUUID": "", + "wipeInProgress": False, + "lostModeEnabled": False, + "activationLocked": False, + "passcodeLength": 6, + "deviceStatus": "203", + "deviceColor": None, + "features": { + "BTR": False, + "LLC": False, + "CLK": False, + "TEU": False, + "SND": True, + "CLT": False, + "SVP": False, + "SPN": False, + "XRM": False, + "CWP": False, + "MSG": True, + "LOC": True, + "LMG": True, + "LKL": True, + "LST": False, + "LKM": True, + "WMG": False, + "PSS": False, + "PIN": True, + "LCK": True, + "REM": True, + "MCS": False, + "KEY": True, + "KPD": True, + "WIP": True, + }, + "lowPowerMode": False, + "rawDeviceModel": "iMac10,1", + "id": "iMac10,1" + MEMBER_1_PERSON_ID, + "remoteLock": None, + "isLocating": False, + "modelDisplayName": "iMac", + "lostTimestamp": "", + "batteryLevel": 0.0, + "mesg": {"createTimestamp": 1583057432335, "statusCode": "200"}, + "locationEnabled": True, + "lockedTimestamp": None, + "locFoundEnabled": False, + "snd": None, + "fmlyShare": True, + "lostDevice": None, + "lostModeCapable": False, + "wipedTimestamp": None, + "deviceDisplayName": "iMac", + "prsId": MEMBER_1_PERSON_ID, + "audioChannels": [], + "locationCapable": True, + "batteryStatus": "Unknown", + "trackingInfo": None, + "name": 'iMac 27" ' + MEMBER_1_LAST_NAME, + "isMac": True, + "thisDevice": False, + "deviceClass": "iMac", + "location": None, + "deviceModel": "iMac10_1", + "maxMsgChar": 500, + "darkWake": False, + "remoteWipe": None, + }, + { + "msg": None, + "canWipeAfterLock": True, + "baUUID": UUID + "iPad7,3" + MEMBER_1_PERSON_ID, + "wipeInProgress": False, + "lostModeEnabled": False, + "activationLocked": True, + "passcodeLength": 6, + "deviceStatus": "201", + "deviceColor": "2-2-0", + "features": { + "BTR": False, + "LLC": False, + "CLK": False, + "TEU": True, + "SND": True, + "CLT": False, + "SVP": False, + "SPN": False, + "XRM": False, + "CWP": False, + "MSG": True, + "LOC": True, + "LMG": False, + "LKL": True, + "LST": True, + "LKM": False, + "WMG": True, + "PSS": False, + "PIN": False, + "LCK": True, + "REM": True, + "MCS": False, + "KEY": False, + "KPD": False, + "WIP": True, + }, + "lowPowerMode": False, + "rawDeviceModel": "iPad7,3", + "id": "iPad7,3" + MEMBER_1_PERSON_ID, + "remoteLock": None, + "isLocating": False, + "modelDisplayName": "iPad", + "lostTimestamp": "", + "batteryLevel": 0.3799999952316284, + "mesg": None, + "locationEnabled": True, + "lockedTimestamp": None, + "locFoundEnabled": False, + "snd": None, + "fmlyShare": True, + "lostDevice": None, + "lostModeCapable": True, + "wipedTimestamp": None, + "deviceDisplayName": "iPad Pro", + "prsId": MEMBER_1_PERSON_ID, + "audioChannels": [], + "locationCapable": True, + "batteryStatus": "NotCharging", + "trackingInfo": None, + "name": "iPad " + MEMBER_1_LAST_NAME, + "isMac": False, + "thisDevice": False, + "deviceClass": "iPad", + "location": None, + "deviceModel": "NinthGen-2-2-0", + "maxMsgChar": 160, + "darkWake": False, + "remoteWipe": None, + }, + { + "msg": { + "strobe": False, + "userText": True, + "playSound": False, + "vibrate": False, + "createTimestamp": 1583057432335, + "statusCode": "205", + }, + "canWipeAfterLock": True, + "baUUID": "", + "wipeInProgress": False, + "lostModeEnabled": False, + "activationLocked": False, + "passcodeLength": 4, + "deviceStatus": "203", + "deviceColor": None, + "features": { + "BTR": False, + "LLC": False, + "CLK": False, + "TEU": True, + "SND": True, + "CLT": False, + "SVP": False, + "SPN": False, + "XRM": False, + "CWP": False, + "MSG": True, + "LOC": True, + "LMG": False, + "LKL": True, + "LST": True, + "LKM": False, + "WMG": False, + "PSS": False, + "PIN": False, + "LCK": True, + "REM": True, + "MCS": False, + "KEY": False, + "KPD": False, + "WIP": True, + }, + "lowPowerMode": False, + "rawDeviceModel": "iPhone4,1", + "id": "iPhone4,1" + MEMBER_1_PERSON_ID, + "remoteLock": None, + "isLocating": False, + "modelDisplayName": "iPhone", + "lostTimestamp": "", + "batteryLevel": 0.0, + "mesg": {"createTimestamp": 1583057432335, "statusCode": "205"}, + "locationEnabled": True, + "lockedTimestamp": None, + "locFoundEnabled": False, + "snd": None, + "fmlyShare": True, + "lostDevice": None, + "lostModeCapable": True, + "wipedTimestamp": None, + "deviceDisplayName": "iPhone 4s", + "prsId": MEMBER_1_PERSON_ID, + "audioChannels": [], + "locationCapable": True, + "batteryStatus": "Unknown", + "trackingInfo": None, + "name": "iPhone", + "isMac": False, + "thisDevice": False, + "deviceClass": "iPhone", + "location": None, + "deviceModel": "FifthGen", + "maxMsgChar": 160, + "darkWake": False, + "remoteWipe": None, + }, + { + "msg": { + "strobe": False, + "userText": True, + "playSound": False, + "vibrate": False, + "createTimestamp": 1583057432335, + "statusCode": "200", + }, + "canWipeAfterLock": True, + "baUUID": "", + "wipeInProgress": False, + "lostModeEnabled": False, + "activationLocked": True, + "passcodeLength": 6, + "deviceStatus": "201", + "deviceColor": "e1e4e3-d7d9d8", + "features": { + "BTR": False, + "LLC": False, + "CLK": False, + "TEU": True, + "SND": True, + "CLT": False, + "SVP": False, + "SPN": False, + "XRM": False, + "CWP": False, + "MSG": True, + "LOC": True, + "LMG": False, + "LKL": False, + "LST": True, + "LKM": False, + "WMG": True, + "PSS": False, + "PIN": False, + "LCK": True, + "REM": True, + "MCS": False, + "KEY": False, + "KPD": False, + "WIP": True, + }, + "lowPowerMode": True, + "rawDeviceModel": "iPhone6,2", + "id": "iPhone6,2" + MEMBER_1_PERSON_ID, + "remoteLock": None, + "isLocating": True, + "modelDisplayName": "iPhone", + "lostTimestamp": "", + "batteryLevel": 0.800000011920929, + "mesg": {"createTimestamp": 1583057432335, "statusCode": "200"}, + "locationEnabled": True, + "lockedTimestamp": None, + "locFoundEnabled": False, + "snd": None, + "fmlyShare": True, + "lostDevice": None, + "lostModeCapable": True, + "wipedTimestamp": None, + "deviceDisplayName": "iPhone 5s", + "prsId": MEMBER_1_PERSON_ID, + "audioChannels": [], + "locationCapable": True, + "batteryStatus": "NotCharging", + "trackingInfo": None, + "name": "iPhone de " + MEMBER_1_FIRST_NAME, + "isMac": False, + "thisDevice": False, + "deviceClass": "iPhone", + "location": { + "isOld": False, + "isInaccurate": False, + "altitude": 0.0, + "positionType": "GPS", + "latitude": LOCATION_LATITUDE, + "floorLevel": 0, + "horizontalAccuracy": 50.0, + "locationType": "", + "timeStamp": 1585866941186, + "locationFinished": False, + "verticalAccuracy": 0.0, + "longitude": LOCATION_LONGITUDE, + }, + "deviceModel": "5s-e1e4e3-d7d9d8", + "maxMsgChar": 160, + "darkWake": False, + "remoteWipe": None, + }, + ], + "statusCode": "200", +} diff --git a/tests/const_login.py b/tests/const_login.py new file mode 100644 index 0000000..bd54b04 --- /dev/null +++ b/tests/const_login.py @@ -0,0 +1,413 @@ +"""Login test constants.""" + +# Base +FIRST_NAME = "Quentin" +LAST_NAME = "TARANTINO" +FULL_NAME = FIRST_NAME + " " + LAST_NAME + +PERSON_ID = (FIRST_NAME + LAST_NAME).lower() +NOTIFICATION_ID = "12345678-1234-1234-1234-123456789012" + PERSON_ID +A_DS_ID = "123456-12-12345678-1234-1234-1234-123456789012" + PERSON_ID +WIDGET_KEY = "widget_key" + PERSON_ID + +PRIMARY_EMAIL = PERSON_ID + "@hotmail.fr" +APPLE_ID_EMAIL = PERSON_ID + "@me.com" +ICLOUD_ID_EMAIL = PERSON_ID + "@icloud.com" + + +# Data +LOGIN_WORKING = { + "dsInfo": { + "lastName": LAST_NAME, + "iCDPEnabled": False, + "tantorMigrated": True, + "dsid": PERSON_ID, + "hsaEnabled": True, + "ironcadeMigrated": True, + "locale": "fr-fr_FR", + "brZoneConsolidated": False, + "isManagedAppleID": False, + "gilligan-invited": "true", + "appleIdAliases": [APPLE_ID_EMAIL, ICLOUD_ID_EMAIL], + "hsaVersion": 2, + "isPaidDeveloper": False, + "countryCode": "FRA", + "notificationId": NOTIFICATION_ID, + "primaryEmailVerified": True, + "aDsID": A_DS_ID, + "locked": False, + "hasICloudQualifyingDevice": True, + "primaryEmail": PRIMARY_EMAIL, + "appleIdEntries": [ + {"isPrimary": True, "type": "EMAIL", "value": PRIMARY_EMAIL}, + {"type": "EMAIL", "value": APPLE_ID_EMAIL}, + {"type": "EMAIL", "value": ICLOUD_ID_EMAIL}, + ], + "gilligan-enabled": "true", + "fullName": FULL_NAME, + "languageCode": "fr-fr", + "appleId": PRIMARY_EMAIL, + "firstName": FIRST_NAME, + "iCloudAppleIdAlias": ICLOUD_ID_EMAIL, + "notesMigrated": True, + "hasPaymentInfo": False, + "pcsDeleted": False, + "appleIdAlias": APPLE_ID_EMAIL, + "brMigrated": True, + "statusCode": 2, + "familyEligible": True, + }, + "hasMinimumDeviceForPhotosWeb": True, + "iCDPEnabled": False, + "webservices": { + "reminders": { + "url": "https://p31-remindersws.icloud.com:443", + "status": "active", + }, + "notes": {"url": "https://p38-notesws.icloud.com:443", "status": "active"}, + "mail": {"url": "https://p38-mailws.icloud.com:443", "status": "active"}, + "ckdatabasews": { + "pcsRequired": True, + "url": "https://p31-ckdatabasews.icloud.com:443", + "status": "active", + }, + "photosupload": { + "pcsRequired": True, + "url": "https://p31-uploadphotosws.icloud.com:443", + "status": "active", + }, + "photos": { + "pcsRequired": True, + "uploadUrl": "https://p31-uploadphotosws.icloud.com:443", + "url": "https://p31-photosws.icloud.com:443", + "status": "active", + }, + "drivews": { + "pcsRequired": True, + "url": "https://p31-drivews.icloud.com:443", + "status": "active", + }, + "uploadimagews": { + "url": "https://p31-uploadimagews.icloud.com:443", + "status": "active", + }, + "schoolwork": {}, + "cksharews": {"url": "https://p31-ckshare.icloud.com:443", "status": "active"}, + "findme": {"url": "https://p31-fmipweb.icloud.com:443", "status": "active"}, + "ckdeviceservice": {"url": "https://p31-ckdevice.icloud.com:443"}, + "iworkthumbnailws": { + "url": "https://p31-iworkthumbnailws.icloud.com:443", + "status": "active", + }, + "calendar": { + "url": "https://p31-calendarws.icloud.com:443", + "status": "active", + }, + "docws": { + "pcsRequired": True, + "url": "https://p31-docws.icloud.com:443", + "status": "active", + }, + "settings": { + "url": "https://p31-settingsws.icloud.com:443", + "status": "active", + }, + "ubiquity": { + "url": "https://p31-ubiquityws.icloud.com:443", + "status": "active", + }, + "streams": {"url": "https://p31-streams.icloud.com:443", "status": "active"}, + "keyvalue": { + "url": "https://p31-keyvalueservice.icloud.com:443", + "status": "active", + }, + "archivews": { + "url": "https://p31-archivews.icloud.com:443", + "status": "active", + }, + "push": {"url": "https://p31-pushws.icloud.com:443", "status": "active"}, + "iwmb": {"url": "https://p31-iwmb.icloud.com:443", "status": "active"}, + "iworkexportws": { + "url": "https://p31-iworkexportws.icloud.com:443", + "status": "active", + }, + "geows": {"url": "https://p31-geows.icloud.com:443", "status": "active"}, + "account": { + "iCloudEnv": {"shortId": "p", "vipSuffix": "prod"}, + "url": "https://p31-setup.icloud.com:443", + "status": "active", + }, + "fmf": {"url": "https://p31-fmfweb.icloud.com:443", "status": "active"}, + "contacts": { + "url": "https://p31-contactsws.icloud.com:443", + "status": "active", + }, + }, + "pcsEnabled": True, + "configBag": { + "urls": { + "accountCreateUI": "https://appleid.apple.com/widget/account/?widgetKey=" + + WIDGET_KEY + + "#!create", + "accountLoginUI": "https://idmsa.apple.com/appleauth/auth/signin?widgetKey=" + + WIDGET_KEY, + "accountLogin": "https://setup.icloud.com/setup/ws/1/accountLogin", + "accountRepairUI": "https://appleid.apple.com/widget/account/?widgetKey=" + + WIDGET_KEY + + "#!repair", + "downloadICloudTerms": "https://setup.icloud.com/setup/ws/1/downloadLiteTerms", + "repairDone": "https://setup.icloud.com/setup/ws/1/repairDone", + "accountAuthorizeUI": "https://idmsa.apple.com/appleauth/auth/authorize/signin?client_id=" + + WIDGET_KEY, + "vettingUrlForEmail": "https://id.apple.com/IDMSEmailVetting/vetShareEmail", + "accountCreate": "https://setup.icloud.com/setup/ws/1/createLiteAccount", + "getICloudTerms": "https://setup.icloud.com/setup/ws/1/getTerms", + "vettingUrlForPhone": "https://id.apple.com/IDMSEmailVetting/vetSharePhone", + }, + "accountCreateEnabled": "true", + }, + "hsaTrustedBrowser": True, + "appsOrder": [ + "mail", + "contacts", + "calendar", + "photos", + "iclouddrive", + "notes3", + "reminders", + "pages", + "numbers", + "keynote", + "newspublisher", + "fmf", + "find", + "settings", + ], + "version": 2, + "isExtendedLogin": False, + "pcsServiceIdentitiesIncluded": True, + "hsaChallengeRequired": False, + "requestInfo": {"country": "FR", "timeZone": "GMT+1", "region": "IDF"}, + "pcsDeleted": False, + "iCloudInfo": {"SafariBookmarksHasMigratedToCloudKit": True}, + "apps": { + "calendar": {}, + "reminders": {}, + "keynote": {"isQualifiedForBeta": True}, + "settings": {"canLaunchWithOneFactor": True}, + "mail": {}, + "numbers": {"isQualifiedForBeta": True}, + "photos": {}, + "pages": {"isQualifiedForBeta": True}, + "notes3": {}, + "find": {"canLaunchWithOneFactor": True}, + "iclouddrive": {}, + "newspublisher": {"isHidden": True}, + "fmf": {}, + "contacts": {}, + }, +} + +# Setup data +LOGIN_2SA = { + "dsInfo": { + "lastName": LAST_NAME, + "iCDPEnabled": False, + "tantorMigrated": True, + "dsid": PERSON_ID, + "hsaEnabled": True, + "ironcadeMigrated": True, + "locale": "fr-fr_FR", + "brZoneConsolidated": False, + "isManagedAppleID": False, + "gilligan-invited": "true", + "appleIdAliases": [APPLE_ID_EMAIL, ICLOUD_ID_EMAIL], + "hsaVersion": 2, + "isPaidDeveloper": False, + "countryCode": "FRA", + "notificationId": NOTIFICATION_ID, + "primaryEmailVerified": True, + "aDsID": A_DS_ID, + "locked": False, + "hasICloudQualifyingDevice": True, + "primaryEmail": PRIMARY_EMAIL, + "appleIdEntries": [ + {"isPrimary": True, "type": "EMAIL", "value": PRIMARY_EMAIL}, + {"type": "EMAIL", "value": APPLE_ID_EMAIL}, + {"type": "EMAIL", "value": ICLOUD_ID_EMAIL}, + ], + "gilligan-enabled": "true", + "fullName": FULL_NAME, + "languageCode": "fr-fr", + "appleId": PRIMARY_EMAIL, + "firstName": FIRST_NAME, + "iCloudAppleIdAlias": ICLOUD_ID_EMAIL, + "notesMigrated": True, + "hasPaymentInfo": True, + "pcsDeleted": False, + "appleIdAlias": APPLE_ID_EMAIL, + "brMigrated": True, + "statusCode": 2, + "familyEligible": True, + }, + "hasMinimumDeviceForPhotosWeb": True, + "iCDPEnabled": False, + "webservices": { + "reminders": { + "url": "https://p31-remindersws.icloud.com:443", + "status": "active", + }, + "notes": {"url": "https://p38-notesws.icloud.com:443", "status": "active"}, + "mail": {"url": "https://p38-mailws.icloud.com:443", "status": "active"}, + "ckdatabasews": { + "pcsRequired": True, + "url": "https://p31-ckdatabasews.icloud.com:443", + "status": "active", + }, + "photosupload": { + "pcsRequired": True, + "url": "https://p31-uploadphotosws.icloud.com:443", + "status": "active", + }, + "photos": { + "pcsRequired": True, + "uploadUrl": "https://p31-uploadphotosws.icloud.com:443", + "url": "https://p31-photosws.icloud.com:443", + "status": "active", + }, + "drivews": { + "pcsRequired": True, + "url": "https://p31-drivews.icloud.com:443", + "status": "active", + }, + "uploadimagews": { + "url": "https://p31-uploadimagews.icloud.com:443", + "status": "active", + }, + "schoolwork": {}, + "cksharews": {"url": "https://p31-ckshare.icloud.com:443", "status": "active"}, + "findme": {"url": "https://p31-fmipweb.icloud.com:443", "status": "active"}, + "ckdeviceservice": {"url": "https://p31-ckdevice.icloud.com:443"}, + "iworkthumbnailws": { + "url": "https://p31-iworkthumbnailws.icloud.com:443", + "status": "active", + }, + "calendar": { + "url": "https://p31-calendarws.icloud.com:443", + "status": "active", + }, + "docws": { + "pcsRequired": True, + "url": "https://p31-docws.icloud.com:443", + "status": "active", + }, + "settings": { + "url": "https://p31-settingsws.icloud.com:443", + "status": "active", + }, + "ubiquity": { + "url": "https://p31-ubiquityws.icloud.com:443", + "status": "active", + }, + "streams": {"url": "https://p31-streams.icloud.com:443", "status": "active"}, + "keyvalue": { + "url": "https://p31-keyvalueservice.icloud.com:443", + "status": "active", + }, + "archivews": { + "url": "https://p31-archivews.icloud.com:443", + "status": "active", + }, + "push": {"url": "https://p31-pushws.icloud.com:443", "status": "active"}, + "iwmb": {"url": "https://p31-iwmb.icloud.com:443", "status": "active"}, + "iworkexportws": { + "url": "https://p31-iworkexportws.icloud.com:443", + "status": "active", + }, + "geows": {"url": "https://p31-geows.icloud.com:443", "status": "active"}, + "account": { + "iCloudEnv": {"shortId": "p", "vipSuffix": "prod"}, + "url": "https://p31-setup.icloud.com:443", + "status": "active", + }, + "fmf": {"url": "https://p31-fmfweb.icloud.com:443", "status": "active"}, + "contacts": { + "url": "https://p31-contactsws.icloud.com:443", + "status": "active", + }, + }, + "pcsEnabled": True, + "configBag": { + "urls": { + "accountCreateUI": "https://appleid.apple.com/widget/account/?widgetKey=" + + WIDGET_KEY + + "#!create", + "accountLoginUI": "https://idmsa.apple.com/appleauth/auth/signin?widgetKey=" + + WIDGET_KEY, + "accountLogin": "https://setup.icloud.com/setup/ws/1/accountLogin", + "accountRepairUI": "https://appleid.apple.com/widget/account/?widgetKey=" + + WIDGET_KEY + + "#!repair", + "downloadICloudTerms": "https://setup.icloud.com/setup/ws/1/downloadLiteTerms", + "repairDone": "https://setup.icloud.com/setup/ws/1/repairDone", + "accountAuthorizeUI": "https://idmsa.apple.com/appleauth/auth/authorize/signin?client_id=" + + WIDGET_KEY, + "vettingUrlForEmail": "https://id.apple.com/IDMSEmailVetting/vetShareEmail", + "accountCreate": "https://setup.icloud.com/setup/ws/1/createLiteAccount", + "getICloudTerms": "https://setup.icloud.com/setup/ws/1/getTerms", + "vettingUrlForPhone": "https://id.apple.com/IDMSEmailVetting/vetSharePhone", + }, + "accountCreateEnabled": "true", + }, + "hsaTrustedBrowser": False, + "appsOrder": [ + "mail", + "contacts", + "calendar", + "photos", + "iclouddrive", + "notes3", + "reminders", + "pages", + "numbers", + "keynote", + "newspublisher", + "fmf", + "find", + "settings", + ], + "version": 2, + "isExtendedLogin": False, + "pcsServiceIdentitiesIncluded": False, + "hsaChallengeRequired": True, + "requestInfo": {"country": "FR", "timeZone": "GMT+1", "region": "IDF"}, + "pcsDeleted": False, + "iCloudInfo": {"SafariBookmarksHasMigratedToCloudKit": True}, + "apps": { + "calendar": {}, + "reminders": {}, + "keynote": {"isQualifiedForBeta": True}, + "settings": {"canLaunchWithOneFactor": True}, + "mail": {}, + "numbers": {"isQualifiedForBeta": True}, + "photos": {}, + "pages": {"isQualifiedForBeta": True}, + "notes3": {}, + "find": {"canLaunchWithOneFactor": True}, + "iclouddrive": {}, + "newspublisher": {"isHidden": True}, + "fmf": {}, + "contacts": {}, + }, +} + +TRUSTED_DEVICE_1 = { + "deviceType": "SMS", + "areaCode": "", + "phoneNumber": "*******58", + "deviceId": "1", +} +TRUSTED_DEVICES = {"devices": [TRUSTED_DEVICE_1]} + +VERIFICATION_CODE_OK = {"success": True} +VERIFICATION_CODE_KO = {"success": False} diff --git a/tests/test_account.py b/tests/test_account.py new file mode 100644 index 0000000..e626fa0 --- /dev/null +++ b/tests/test_account.py @@ -0,0 +1,33 @@ +"""Account service tests.""" +from unittest import TestCase +from . import PyiCloudServiceMock +from .const import AUTHENTICATED_USER, VALID_PASSWORD + + +class AccountServiceTest(TestCase): + """"Account service tests""" + + service = None + + def setUp(self): + self.service = PyiCloudServiceMock(AUTHENTICATED_USER, VALID_PASSWORD).account + + def test_devices(self): + """Tests devices.""" + assert len(self.service.devices) == 2 + + for device in self.service.devices: + assert device.name + assert device.model + assert device.udid + assert device["serialNumber"] + assert device["osVersion"] + assert device["modelLargePhotoURL2x"] + assert device["modelLargePhotoURL1x"] + assert device["paymentMethods"] + assert device["name"] + assert device["model"] + assert device["udid"] + assert device["modelSmallPhotoURL2x"] + assert device["modelSmallPhotoURL1x"] + assert device["modelDisplayName"] diff --git a/tests/test_cmdline.py b/tests/test_cmdline.py index b63dfa0..57a0da3 100644 --- a/tests/test_cmdline.py +++ b/tests/test_cmdline.py @@ -1,6 +1,8 @@ """Cmdline tests.""" from pyicloud import cmdline -from . import PyiCloudServiceMock, AUTHENTICATED_USER, REQUIRES_2SA_USER, DEVICES +from . import PyiCloudServiceMock +from .const import AUTHENTICATED_USER, REQUIRES_2SA_USER, VALID_PASSWORD +from .const_findmyiphone import FMI_FMLY_WORKING import os import sys @@ -45,8 +47,11 @@ class TestCmdline(TestCase): with pytest.raises(SystemExit, match="2"): self.main(["--username"]) + @patch("keyring.get_password", return_value=None) @patch("getpass.getpass") - def test_username_password_invalid(self, mock_getpass): + def test_username_password_invalid( + self, mock_getpass, mock_get_password + ): # pylint: disable=unused-argument """Test username and password commands.""" # No password supplied mock_getpass.return_value = None @@ -66,8 +71,11 @@ class TestCmdline(TestCase): ): self.main(["--username", "invalid_user", "--password", "invalid_pass"]) + @patch("keyring.get_password", return_value=None) @patch("pyicloud.cmdline.input") - def test_username_password_requires_2sa(self, mock_input): + def test_username_password_requires_2sa( + self, mock_input, mock_get_password + ): # pylint: disable=unused-argument """Test username and password commands.""" # Valid connection for the first time mock_input.return_value = "0" @@ -75,25 +83,29 @@ class TestCmdline(TestCase): # fmt: off self.main([ '--username', REQUIRES_2SA_USER, - '--password', 'valid_pass', + '--password', VALID_PASSWORD, '--non-interactive', ]) # fmt: on - def test_device_outputfile(self): + @patch("keyring.get_password", return_value=None) + def test_device_outputfile( + self, mock_get_password + ): # pylint: disable=unused-argument """Test the outputfile command.""" with pytest.raises(SystemExit, match="0"): # fmt: off self.main([ '--username', AUTHENTICATED_USER, - '--password', 'valid_pass', + '--password', VALID_PASSWORD, '--non-interactive', '--outputfile' ]) # fmt: on - for key in DEVICES: - file_name = DEVICES[key].content["name"].strip().lower() + ".fmip_snapshot" + devices = FMI_FMLY_WORKING.get("content") + for device in devices: + file_name = device.get("name").strip().lower() + ".fmip_snapshot" pickle_file = open(file_name, "rb") assert pickle_file @@ -105,7 +117,7 @@ class TestCmdline(TestCase): contents.append(pickle.load(opened_file)) except EOFError: break - assert contents == [DEVICES[key].content] + assert contents == [device] pickle_file.close() os.remove(file_name) diff --git a/tests/test_findmyiphone.py b/tests/test_findmyiphone.py new file mode 100644 index 0000000..3b2b07f --- /dev/null +++ b/tests/test_findmyiphone.py @@ -0,0 +1,86 @@ +"""Find My iPhone service tests.""" +from unittest import TestCase +from . import PyiCloudServiceMock +from .const import AUTHENTICATED_USER, VALID_PASSWORD + + +class FindMyiPhoneServiceTest(TestCase): + """"Find My iPhone service tests""" + + service = None + + def setUp(self): + self.service = PyiCloudServiceMock(AUTHENTICATED_USER, VALID_PASSWORD) + + def test_devices(self): + """Tests devices.""" + assert len(list(self.service.devices)) == 13 + + for device in self.service.devices: + assert device["canWipeAfterLock"] is not None + assert device["baUUID"] is not None + assert device["wipeInProgress"] is not None + assert device["lostModeEnabled"] is not None + assert device["activationLocked"] is not None + assert device["passcodeLength"] is not None + assert device["deviceStatus"] is not None + assert device["features"] is not None + assert device["lowPowerMode"] is not None + assert device["rawDeviceModel"] is not None + assert device["id"] is not None + assert device["isLocating"] is not None + assert device["modelDisplayName"] is not None + assert device["lostTimestamp"] is not None + assert device["batteryLevel"] is not None + assert device["locationEnabled"] is not None + assert device["locFoundEnabled"] is not None + assert device["fmlyShare"] is not None + assert device["lostModeCapable"] is not None + assert device["wipedTimestamp"] is None + assert device["deviceDisplayName"] is not None + assert device["audioChannels"] is not None + assert device["locationCapable"] is not None + assert device["batteryStatus"] is not None + assert device["trackingInfo"] is None + assert device["name"] is not None + assert device["isMac"] is not None + assert device["thisDevice"] is not None + assert device["deviceClass"] is not None + assert device["deviceModel"] is not None + assert device["maxMsgChar"] is not None + assert device["darkWake"] is not None + assert device["remoteWipe"] is None + + assert device.data["canWipeAfterLock"] is not None + assert device.data["baUUID"] is not None + assert device.data["wipeInProgress"] is not None + assert device.data["lostModeEnabled"] is not None + assert device.data["activationLocked"] is not None + assert device.data["passcodeLength"] is not None + assert device.data["deviceStatus"] is not None + assert device.data["features"] is not None + assert device.data["lowPowerMode"] is not None + assert device.data["rawDeviceModel"] is not None + assert device.data["id"] is not None + assert device.data["isLocating"] is not None + assert device.data["modelDisplayName"] is not None + assert device.data["lostTimestamp"] is not None + assert device.data["batteryLevel"] is not None + assert device.data["locationEnabled"] is not None + assert device.data["locFoundEnabled"] is not None + assert device.data["fmlyShare"] is not None + assert device.data["lostModeCapable"] is not None + assert device.data["wipedTimestamp"] is None + assert device.data["deviceDisplayName"] is not None + assert device.data["audioChannels"] is not None + assert device.data["locationCapable"] is not None + assert device.data["batteryStatus"] is not None + assert device.data["trackingInfo"] is None + assert device.data["name"] is not None + assert device.data["isMac"] is not None + assert device.data["thisDevice"] is not None + assert device.data["deviceClass"] is not None + assert device.data["deviceModel"] is not None + assert device.data["maxMsgChar"] is not None + assert device.data["darkWake"] is not None + assert device.data["remoteWipe"] is None