Add account family + storage services (#250)
This commit is contained in:
parent
91ac1d956e
commit
e3bdcea15a
9 changed files with 523 additions and 45 deletions
|
@ -13,34 +13,68 @@ class AccountService(object):
|
|||
self.session = session
|
||||
self.params = params
|
||||
self._service_root = service_root
|
||||
|
||||
self._devices = []
|
||||
self._family = []
|
||||
self._storage = None
|
||||
|
||||
self._acc_endpoint = "%s/setup/web/device" % self._service_root
|
||||
self._account_devices_url = "%s/getDevices" % self._acc_endpoint
|
||||
|
||||
req = self.session.get(self._account_devices_url, params=self.params)
|
||||
self.response = req.json()
|
||||
|
||||
for device_info in self.response["devices"]:
|
||||
# device_id = device_info['udid']
|
||||
# self._devices[device_id] = AccountDevice(device_info)
|
||||
self._devices.append(AccountDevice(device_info))
|
||||
self._acc_endpoint = "%s/setup/web" % self._service_root
|
||||
self._acc_devices_url = "%s/device/getDevices" % self._acc_endpoint
|
||||
self._acc_family_details_url = "%s/family/getFamilyDetails" % self._acc_endpoint
|
||||
self._acc_family_member_photo_url = (
|
||||
"%s/family/getMemberPhoto" % self._acc_endpoint
|
||||
)
|
||||
self._acc_storage_url = "https://setup.icloud.com/setup/ws/1/storageUsageInfo"
|
||||
|
||||
@property
|
||||
def devices(self):
|
||||
"""Gets the account devices."""
|
||||
"""Returns current paired devices."""
|
||||
if not self._devices:
|
||||
req = self.session.get(self._acc_devices_url, params=self.params)
|
||||
response = req.json()
|
||||
|
||||
for device_info in response["devices"]:
|
||||
self._devices.append(AccountDevice(device_info))
|
||||
|
||||
return self._devices
|
||||
|
||||
@property
|
||||
def family(self):
|
||||
"""Returns family members."""
|
||||
if not self._family:
|
||||
req = self.session.get(self._acc_family_details_url, params=self.params)
|
||||
response = req.json()
|
||||
|
||||
for member_info in response["familyMembers"]:
|
||||
self._family.append(
|
||||
FamilyMember(
|
||||
member_info,
|
||||
self.session,
|
||||
self.params,
|
||||
self._acc_family_member_photo_url,
|
||||
)
|
||||
)
|
||||
|
||||
return self._family
|
||||
|
||||
@property
|
||||
def storage(self):
|
||||
"""Returns storage infos."""
|
||||
if not self._storage:
|
||||
req = self.session.get(self._acc_storage_url, params=self.params)
|
||||
response = req.json()
|
||||
|
||||
self._storage = AccountStorage(response)
|
||||
|
||||
return self._storage
|
||||
|
||||
|
||||
@six.python_2_unicode_compatible
|
||||
class AccountDevice(dict):
|
||||
"""Account device."""
|
||||
|
||||
def __getattr__(self, name):
|
||||
try:
|
||||
return self[underscore_to_camelcase(name)]
|
||||
except KeyError:
|
||||
raise AttributeError(name)
|
||||
def __getattr__(self, key):
|
||||
return self[underscore_to_camelcase(key)]
|
||||
|
||||
def __str__(self):
|
||||
return u"{display_name}: {name}".format(
|
||||
|
@ -55,3 +89,251 @@ class AccountDevice(dict):
|
|||
else six.text_type(self).encode("utf8", "replace")
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class FamilyMember(object):
|
||||
"""A family member."""
|
||||
|
||||
def __init__(self, member_info, session, params, acc_family_member_photo_url):
|
||||
self._attrs = member_info
|
||||
self._session = session
|
||||
self._params = params
|
||||
self._acc_family_member_photo_url = acc_family_member_photo_url
|
||||
|
||||
@property
|
||||
def last_name(self):
|
||||
"""Gets the last name."""
|
||||
return self._attrs.get("lastName")
|
||||
|
||||
@property
|
||||
def dsid(self):
|
||||
"""Gets the dsid."""
|
||||
return self._attrs.get("dsid")
|
||||
|
||||
@property
|
||||
def original_invitation_email(self):
|
||||
"""Gets the original invitation."""
|
||||
return self._attrs.get("originalInvitationEmail")
|
||||
|
||||
@property
|
||||
def full_name(self):
|
||||
"""Gets the full name."""
|
||||
return self._attrs.get("fullName")
|
||||
|
||||
@property
|
||||
def age_classification(self):
|
||||
"""Gets the age classification."""
|
||||
return self._attrs.get("ageClassification")
|
||||
|
||||
@property
|
||||
def apple_id_for_purchases(self):
|
||||
"""Gets the apple id for purchases."""
|
||||
return self._attrs.get("appleIdForPurchases")
|
||||
|
||||
@property
|
||||
def apple_id(self):
|
||||
"""Gets the apple id."""
|
||||
return self._attrs.get("appleId")
|
||||
|
||||
@property
|
||||
def family_id(self):
|
||||
"""Gets the family id."""
|
||||
return self._attrs.get("familyId")
|
||||
|
||||
@property
|
||||
def first_name(self):
|
||||
"""Gets the first name."""
|
||||
return self._attrs.get("firstName")
|
||||
|
||||
@property
|
||||
def has_parental_privileges(self):
|
||||
"""Has parental privileges."""
|
||||
return self._attrs.get("hasParentalPrivileges")
|
||||
|
||||
@property
|
||||
def has_screen_time_enabled(self):
|
||||
"""Has screen time enabled."""
|
||||
return self._attrs.get("hasScreenTimeEnabled")
|
||||
|
||||
@property
|
||||
def has_ask_to_buy_enabled(self):
|
||||
"""Has to ask for buying."""
|
||||
return self._attrs.get("hasAskToBuyEnabled")
|
||||
|
||||
@property
|
||||
def has_share_purchases_enabled(self):
|
||||
"""Has share purshases."""
|
||||
return self._attrs.get("hasSharePurchasesEnabled")
|
||||
|
||||
@property
|
||||
def share_my_location_enabled_family_members(self):
|
||||
"""Has share my location with family."""
|
||||
return self._attrs.get("shareMyLocationEnabledFamilyMembers")
|
||||
|
||||
@property
|
||||
def has_share_my_location_enabled(self):
|
||||
"""Has share my location."""
|
||||
return self._attrs.get("hasShareMyLocationEnabled")
|
||||
|
||||
@property
|
||||
def dsid_for_purchases(self):
|
||||
"""Gets the dsid for purchases."""
|
||||
return self._attrs.get("dsidForPurchases")
|
||||
|
||||
def get_photo(self):
|
||||
"""Returns the photo."""
|
||||
params_photo = dict(self._params)
|
||||
params_photo.update({"memberId": self.dsid})
|
||||
return self._session.get(
|
||||
self._acc_family_member_photo_url, params=params_photo, stream=True
|
||||
)
|
||||
|
||||
def __getitem__(self, key):
|
||||
if self._attrs.get(key):
|
||||
return self._attrs[key]
|
||||
return getattr(self, key)
|
||||
|
||||
def __str__(self):
|
||||
return u"{full_name}: {age_classification}".format(
|
||||
full_name=self.full_name, age_classification=self.age_classification,
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
return "<{display}>".format(
|
||||
display=(
|
||||
six.text_type(self)
|
||||
if sys.version_info[0] >= 3
|
||||
else six.text_type(self).encode("utf8", "replace")
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class AccountStorageUsageForMedia(object):
|
||||
"""Storage used for a specific media type into the account."""
|
||||
|
||||
def __init__(self, usage_data):
|
||||
self.usage_data = usage_data
|
||||
|
||||
@property
|
||||
def key(self):
|
||||
"""Gets the key."""
|
||||
return self.usage_data["mediaKey"]
|
||||
|
||||
@property
|
||||
def label(self):
|
||||
"""Gets the label."""
|
||||
return self.usage_data["displayLabel"]
|
||||
|
||||
@property
|
||||
def color(self):
|
||||
"""Gets the HEX color."""
|
||||
return self.usage_data["displayColor"]
|
||||
|
||||
@property
|
||||
def usage_in_bytes(self):
|
||||
"""Gets the usage in bytes."""
|
||||
return self.usage_data["usageInBytes"]
|
||||
|
||||
def __str__(self):
|
||||
return u"{key}: {usage}".format(key=self.key, usage=self.usage_in_bytes)
|
||||
|
||||
def __repr__(self):
|
||||
return "<{display}>".format(
|
||||
display=(
|
||||
six.text_type(self)
|
||||
if sys.version_info[0] >= 3
|
||||
else six.text_type(self).encode("utf8", "replace")
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class AccountStorageUsage(object):
|
||||
"""Storage used for a specific media type into the account."""
|
||||
|
||||
def __init__(self, usage_data, quota_data):
|
||||
self.usage_data = usage_data
|
||||
self.quota_data = quota_data
|
||||
|
||||
@property
|
||||
def comp_storage_in_bytes(self):
|
||||
"""Gets the comp storage in bytes."""
|
||||
return self.usage_data["compStorageInBytes"]
|
||||
|
||||
@property
|
||||
def used_storage_in_bytes(self):
|
||||
"""Gets the used storage in bytes."""
|
||||
return self.usage_data["usedStorageInBytes"]
|
||||
|
||||
@property
|
||||
def used_storage_in_percent(self):
|
||||
"""Gets the used storage in percent."""
|
||||
return self.used_storage_in_bytes * 100 / self.total_storage_in_bytes
|
||||
|
||||
@property
|
||||
def available_storage_in_bytes(self):
|
||||
"""Gets the available storage in bytes."""
|
||||
return self.total_storage_in_bytes - self.used_storage_in_bytes
|
||||
|
||||
@property
|
||||
def available_storage_in_percent(self):
|
||||
"""Gets the available storage in percent."""
|
||||
return self.available_storage_in_bytes * 100 / self.total_storage_in_bytes
|
||||
|
||||
@property
|
||||
def total_storage_in_bytes(self):
|
||||
"""Gets the total storage in bytes."""
|
||||
return self.usage_data["totalStorageInBytes"]
|
||||
|
||||
@property
|
||||
def commerce_storage_in_bytes(self):
|
||||
"""Gets the commerce storage in bytes."""
|
||||
return self.usage_data["commerceStorageInBytes"]
|
||||
|
||||
@property
|
||||
def quota_over(self):
|
||||
"""Gets the over quota."""
|
||||
return self.quota_data["overQuota"]
|
||||
|
||||
@property
|
||||
def quota_tier_max(self):
|
||||
"""Gets the max tier quota."""
|
||||
return self.quota_data["haveMaxQuotaTier"]
|
||||
|
||||
@property
|
||||
def quota_almost_full(self):
|
||||
"""Gets the almost full quota."""
|
||||
return self.quota_data["almost-full"]
|
||||
|
||||
@property
|
||||
def quota_paid(self):
|
||||
"""Gets the paid quota."""
|
||||
return self.quota_data["paidQuota"]
|
||||
|
||||
def __str__(self):
|
||||
return u"{used_percent}%% used of {total} bytes".format(
|
||||
used_percent=self.used_storage_in_percent, total=self.total_storage_in_bytes
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
return "<{display}>".format(
|
||||
display=(
|
||||
six.text_type(self)
|
||||
if sys.version_info[0] >= 3
|
||||
else six.text_type(self).encode("utf8", "replace")
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class AccountStorage(object):
|
||||
"""Storage of the account."""
|
||||
|
||||
def __init__(self, storage_data):
|
||||
self.usage = AccountStorageUsage(
|
||||
storage_data.get("storageUsageInfo"), storage_data.get("quotaStatus")
|
||||
)
|
||||
self.usages_by_media = {}
|
||||
|
||||
for usage_media in storage_data.get("storageUsageByMedia"):
|
||||
self.usages_by_media[usage_media["mediaKey"]] = AccountStorageUsageForMedia(
|
||||
usage_media
|
||||
)
|
||||
|
|
|
@ -20,8 +20,9 @@ from .const_login import (
|
|||
VERIFICATION_CODE_OK,
|
||||
VERIFICATION_CODE_KO,
|
||||
)
|
||||
from .const_account import ACCOUNT_DEVICES_WORKING
|
||||
from .const_findmyiphone import FMI_FMLY_WORKING
|
||||
from .const_account import ACCOUNT_DEVICES_WORKING, ACCOUNT_STORAGE_WORKING
|
||||
from .const_account_family import ACCOUNT_FAMILY_WORKING
|
||||
from .const_findmyiphone import FMI_FAMILY_WORKING
|
||||
|
||||
|
||||
class ResponseMock(Response):
|
||||
|
@ -76,10 +77,14 @@ class PyiCloudSessionMock(base.PyiCloudSession):
|
|||
# Account
|
||||
if "device/getDevices" in url and method == "GET":
|
||||
return ResponseMock(ACCOUNT_DEVICES_WORKING)
|
||||
if "family/getFamilyDetails" in url and method == "GET":
|
||||
return ResponseMock(ACCOUNT_FAMILY_WORKING)
|
||||
if "setup/ws/1/storageUsageInfo" in url and method == "GET":
|
||||
return ResponseMock(ACCOUNT_STORAGE_WORKING)
|
||||
|
||||
# Find My iPhone
|
||||
if "fmi" in url and method == "POST":
|
||||
return ResponseMock(FMI_FMLY_WORKING)
|
||||
return ResponseMock(FMI_FAMILY_WORKING)
|
||||
|
||||
return None
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
"""Test constants."""
|
||||
from .const_login import PRIMARY_EMAIL, APPLE_ID_EMAIL, ICLOUD_ID_EMAIL
|
||||
from .const_account_family import PRIMARY_EMAIL, APPLE_ID_EMAIL, ICLOUD_ID_EMAIL
|
||||
|
||||
# Base
|
||||
AUTHENTICATED_USER = PRIMARY_EMAIL
|
||||
|
|
|
@ -75,3 +75,45 @@ ACCOUNT_DEVICES_WORKING = {
|
|||
},
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
ACCOUNT_STORAGE_WORKING = {
|
||||
"storageUsageByMedia": [
|
||||
{
|
||||
"mediaKey": "photos",
|
||||
"displayLabel": "Photos et vidéos",
|
||||
"displayColor": "ffcc00",
|
||||
"usageInBytes": 0,
|
||||
},
|
||||
{
|
||||
"mediaKey": "backup",
|
||||
"displayLabel": "Sauvegarde",
|
||||
"displayColor": "5856d6",
|
||||
"usageInBytes": 799008186,
|
||||
},
|
||||
{
|
||||
"mediaKey": "docs",
|
||||
"displayLabel": "Documents",
|
||||
"displayColor": "ff9500",
|
||||
"usageInBytes": 449092146,
|
||||
},
|
||||
{
|
||||
"mediaKey": "mail",
|
||||
"displayLabel": "Mail",
|
||||
"displayColor": "007aff",
|
||||
"usageInBytes": 1101522944,
|
||||
},
|
||||
],
|
||||
"storageUsageInfo": {
|
||||
"compStorageInBytes": 0,
|
||||
"usedStorageInBytes": 2348632876,
|
||||
"totalStorageInBytes": 5368709120,
|
||||
"commerceStorageInBytes": 0,
|
||||
},
|
||||
"quotaStatus": {
|
||||
"overQuota": False,
|
||||
"haveMaxQuotaTier": False,
|
||||
"almost-full": False,
|
||||
"paidQuota": False,
|
||||
},
|
||||
}
|
||||
|
|
97
tests/const_account_family.py
Normal file
97
tests/const_account_family.py
Normal file
|
@ -0,0 +1,97 @@
|
|||
"""Account family test constants."""
|
||||
|
||||
# Fakers
|
||||
FIRST_NAME = "Quentin"
|
||||
LAST_NAME = "TARANTINO"
|
||||
FULL_NAME = FIRST_NAME + " " + LAST_NAME
|
||||
PERSON_ID = (FIRST_NAME + LAST_NAME).lower()
|
||||
PRIMARY_EMAIL = PERSON_ID + "@hotmail.fr"
|
||||
APPLE_ID_EMAIL = PERSON_ID + "@me.com"
|
||||
ICLOUD_ID_EMAIL = PERSON_ID + "@icloud.com"
|
||||
|
||||
MEMBER_1_FIRST_NAME = "John"
|
||||
MEMBER_1_LAST_NAME = "TRAVOLTA"
|
||||
MEMBER_1_FULL_NAME = MEMBER_1_FIRST_NAME + " " + MEMBER_1_LAST_NAME
|
||||
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_FULL_NAME = MEMBER_2_FIRST_NAME + " " + MEMBER_2_LAST_NAME
|
||||
MEMBER_2_PERSON_ID = (MEMBER_2_FIRST_NAME + MEMBER_2_LAST_NAME).lower()
|
||||
MEMBER_2_APPLE_ID = MEMBER_2_PERSON_ID + "@outlook.fr"
|
||||
|
||||
FAMILY_ID = "family_" + PERSON_ID
|
||||
|
||||
# Data
|
||||
ACCOUNT_FAMILY_WORKING = {
|
||||
"status-message": "Member of a family.",
|
||||
"familyInvitations": [],
|
||||
"outgoingTransferRequests": [],
|
||||
"isMemberOfFamily": True,
|
||||
"family": {
|
||||
"familyId": FAMILY_ID,
|
||||
"transferRequests": [],
|
||||
"invitations": [],
|
||||
"organizer": PERSON_ID,
|
||||
"members": [PERSON_ID, MEMBER_2_PERSON_ID, MEMBER_1_PERSON_ID],
|
||||
"outgoingTransferRequests": [],
|
||||
"etag": "12",
|
||||
},
|
||||
"familyMembers": [
|
||||
{
|
||||
"lastName": LAST_NAME,
|
||||
"dsid": PERSON_ID,
|
||||
"originalInvitationEmail": PRIMARY_EMAIL,
|
||||
"fullName": FULL_NAME,
|
||||
"ageClassification": "ADULT",
|
||||
"appleIdForPurchases": PRIMARY_EMAIL,
|
||||
"appleId": PRIMARY_EMAIL,
|
||||
"familyId": FAMILY_ID,
|
||||
"firstName": FIRST_NAME,
|
||||
"hasParentalPrivileges": True,
|
||||
"hasScreenTimeEnabled": False,
|
||||
"hasAskToBuyEnabled": False,
|
||||
"hasSharePurchasesEnabled": True,
|
||||
"shareMyLocationEnabledFamilyMembers": [],
|
||||
"hasShareMyLocationEnabled": True,
|
||||
"dsidForPurchases": PERSON_ID,
|
||||
},
|
||||
{
|
||||
"lastName": MEMBER_2_LAST_NAME,
|
||||
"dsid": MEMBER_2_PERSON_ID,
|
||||
"originalInvitationEmail": MEMBER_2_APPLE_ID,
|
||||
"fullName": MEMBER_2_FULL_NAME,
|
||||
"ageClassification": "ADULT",
|
||||
"appleIdForPurchases": MEMBER_2_APPLE_ID,
|
||||
"appleId": MEMBER_2_APPLE_ID,
|
||||
"familyId": FAMILY_ID,
|
||||
"firstName": MEMBER_2_FIRST_NAME,
|
||||
"hasParentalPrivileges": False,
|
||||
"hasScreenTimeEnabled": False,
|
||||
"hasAskToBuyEnabled": False,
|
||||
"hasSharePurchasesEnabled": False,
|
||||
"hasShareMyLocationEnabled": False,
|
||||
"dsidForPurchases": MEMBER_2_PERSON_ID,
|
||||
},
|
||||
{
|
||||
"lastName": MEMBER_1_LAST_NAME,
|
||||
"dsid": MEMBER_1_PERSON_ID,
|
||||
"originalInvitationEmail": MEMBER_1_APPLE_ID,
|
||||
"fullName": MEMBER_1_FULL_NAME,
|
||||
"ageClassification": "ADULT",
|
||||
"appleIdForPurchases": MEMBER_1_APPLE_ID,
|
||||
"appleId": MEMBER_1_APPLE_ID,
|
||||
"familyId": FAMILY_ID,
|
||||
"firstName": MEMBER_1_FIRST_NAME,
|
||||
"hasParentalPrivileges": False,
|
||||
"hasScreenTimeEnabled": False,
|
||||
"hasAskToBuyEnabled": False,
|
||||
"hasSharePurchasesEnabled": True,
|
||||
"hasShareMyLocationEnabled": True,
|
||||
"dsidForPurchases": MEMBER_1_PERSON_ID,
|
||||
},
|
||||
],
|
||||
"status": 0,
|
||||
"showAddMemberButton": True,
|
||||
}
|
|
@ -1,17 +1,19 @@
|
|||
"""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"
|
||||
from .const_account_family import (
|
||||
FIRST_NAME,
|
||||
LAST_NAME,
|
||||
PERSON_ID,
|
||||
FULL_NAME,
|
||||
MEMBER_1_FIRST_NAME,
|
||||
MEMBER_1_APPLE_ID,
|
||||
MEMBER_1_LAST_NAME,
|
||||
MEMBER_1_PERSON_ID,
|
||||
MEMBER_2_APPLE_ID,
|
||||
MEMBER_2_FIRST_NAME,
|
||||
MEMBER_2_LAST_NAME,
|
||||
MEMBER_2_PERSON_ID,
|
||||
)
|
||||
|
||||
# Fakers
|
||||
UUID = "ABCDEFGH-1234-5678-1234-ABCDEFGHIJKL"
|
||||
|
@ -23,7 +25,7 @@ LOCATION_LONGITUDE = 6.1234567890123456
|
|||
# id = rawDeviceModel + prsId (if not None)
|
||||
# baUUID = UUID + id
|
||||
# So they can still be faked and unique
|
||||
FMI_FMLY_WORKING = {
|
||||
FMI_FAMILY_WORKING = {
|
||||
"userInfo": {
|
||||
"accountFormatter": 0,
|
||||
"firstName": FIRST_NAME,
|
||||
|
|
|
@ -1,20 +1,19 @@
|
|||
"""Login test constants."""
|
||||
|
||||
# Base
|
||||
FIRST_NAME = "Quentin"
|
||||
LAST_NAME = "TARANTINO"
|
||||
FULL_NAME = FIRST_NAME + " " + LAST_NAME
|
||||
from .const_account_family import (
|
||||
FIRST_NAME,
|
||||
LAST_NAME,
|
||||
PERSON_ID,
|
||||
FULL_NAME,
|
||||
PRIMARY_EMAIL,
|
||||
APPLE_ID_EMAIL,
|
||||
ICLOUD_ID_EMAIL,
|
||||
)
|
||||
|
||||
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": {
|
||||
|
|
|
@ -14,6 +14,7 @@ class AccountServiceTest(TestCase):
|
|||
|
||||
def test_devices(self):
|
||||
"""Tests devices."""
|
||||
assert self.service.devices
|
||||
assert len(self.service.devices) == 2
|
||||
|
||||
for device in self.service.devices:
|
||||
|
@ -31,3 +32,53 @@ class AccountServiceTest(TestCase):
|
|||
assert device["modelSmallPhotoURL2x"]
|
||||
assert device["modelSmallPhotoURL1x"]
|
||||
assert device["modelDisplayName"]
|
||||
|
||||
def test_family(self):
|
||||
"""Tests family members."""
|
||||
assert self.service.family
|
||||
assert len(self.service.family) == 3
|
||||
|
||||
for member in self.service.family:
|
||||
assert member.last_name
|
||||
assert member.dsid
|
||||
assert member.original_invitation_email
|
||||
assert member.full_name
|
||||
assert member.age_classification
|
||||
assert member.apple_id_for_purchases
|
||||
assert member.apple_id
|
||||
assert member.first_name
|
||||
assert not member.has_screen_time_enabled
|
||||
assert not member.has_ask_to_buy_enabled
|
||||
assert not member.share_my_location_enabled_family_members
|
||||
assert member.dsid_for_purchases
|
||||
|
||||
def test_storage(self):
|
||||
"""Tests storage."""
|
||||
assert self.service.storage
|
||||
|
||||
assert self.service.storage.usage
|
||||
assert (
|
||||
self.service.storage.usage.comp_storage_in_bytes
|
||||
or self.service.storage.usage.comp_storage_in_bytes == 0
|
||||
)
|
||||
assert self.service.storage.usage.used_storage_in_bytes
|
||||
assert self.service.storage.usage.used_storage_in_percent
|
||||
assert self.service.storage.usage.available_storage_in_bytes
|
||||
assert self.service.storage.usage.available_storage_in_percent
|
||||
assert self.service.storage.usage.total_storage_in_bytes
|
||||
assert (
|
||||
self.service.storage.usage.commerce_storage_in_bytes
|
||||
or self.service.storage.usage.commerce_storage_in_bytes == 0
|
||||
)
|
||||
assert not self.service.storage.usage.quota_over
|
||||
assert not self.service.storage.usage.quota_tier_max
|
||||
assert not self.service.storage.usage.quota_almost_full
|
||||
assert not self.service.storage.usage.quota_paid
|
||||
|
||||
assert self.service.storage.usages_by_media
|
||||
|
||||
for usage_media in self.service.storage.usages_by_media.values():
|
||||
assert usage_media.key
|
||||
assert usage_media.label
|
||||
assert usage_media.color
|
||||
assert usage_media.usage_in_bytes or usage_media.usage_in_bytes == 0
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
from pyicloud import cmdline
|
||||
from . import PyiCloudServiceMock
|
||||
from .const import AUTHENTICATED_USER, REQUIRES_2SA_USER, VALID_PASSWORD
|
||||
from .const_findmyiphone import FMI_FMLY_WORKING
|
||||
from .const_findmyiphone import FMI_FAMILY_WORKING
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
@ -103,7 +103,7 @@ class TestCmdline(TestCase):
|
|||
])
|
||||
# fmt: on
|
||||
|
||||
devices = FMI_FMLY_WORKING.get("content")
|
||||
devices = FMI_FAMILY_WORKING.get("content")
|
||||
for device in devices:
|
||||
file_name = device.get("name").strip().lower() + ".fmip_snapshot"
|
||||
|
||||
|
|
Loading…
Reference in a new issue