mirror of
https://github.com/home-assistant/core.git
synced 2025-07-13 08:17:08 +00:00
Improve test coverage for nextcloud (#123148)
* add first data driven tests * remove unused mock * test unique_id migration * test errors during setup * test error during data update * test update entity * system_versionis always available * make use of snapshot_platform helper * use parametrize test for coordinator update errors * apply suggestions * don't touch internals on coordinator tests * rework to use async_get_or_create instead of mock_registry
This commit is contained in:
parent
e2d84f9a58
commit
ea04269c49
@ -32,12 +32,12 @@ class NextcloudUpdateSensor(NextcloudEntity, UpdateEntity):
|
||||
"""Represents a Nextcloud update entity."""
|
||||
|
||||
@property
|
||||
def installed_version(self) -> str | None:
|
||||
def installed_version(self) -> str:
|
||||
"""Version installed and in use."""
|
||||
return self.coordinator.data.get("system_version")
|
||||
return self.coordinator.data["system_version"]
|
||||
|
||||
@property
|
||||
def latest_version(self) -> str | None:
|
||||
def latest_version(self) -> str:
|
||||
"""Latest version available for install."""
|
||||
return self.coordinator.data.get(
|
||||
"update_available_version", self.installed_version
|
||||
@ -46,7 +46,5 @@ class NextcloudUpdateSensor(NextcloudEntity, UpdateEntity):
|
||||
@property
|
||||
def release_url(self) -> str | None:
|
||||
"""URL to the full release notes of the latest version available."""
|
||||
if self.latest_version:
|
||||
ver = "-".join(self.latest_version.split(".")[:3])
|
||||
return f"https://nextcloud.com/changelog/#{ver}"
|
||||
return None
|
||||
|
@ -1 +1,38 @@
|
||||
"""Tests for the Nextcloud integration."""
|
||||
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
from homeassistant.components.nextcloud.const import DOMAIN
|
||||
from homeassistant.const import CONF_URL
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from .const import MOCKED_ENTRY_ID
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
||||
def mock_config_entry(config: dict) -> MockConfigEntry:
|
||||
"""Return a mocked config entry."""
|
||||
return MockConfigEntry(
|
||||
domain=DOMAIN, title=config[CONF_URL], data=config, entry_id=MOCKED_ENTRY_ID
|
||||
)
|
||||
|
||||
|
||||
async def init_integration(
|
||||
hass: HomeAssistant, config: dict, data: dict
|
||||
) -> MockConfigEntry:
|
||||
"""Set up the nextcloud integration."""
|
||||
entry = mock_config_entry(config)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.nextcloud.NextcloudMonitor",
|
||||
) as mock_nextcloud_monitor,
|
||||
):
|
||||
mock_nextcloud_monitor.update = Mock(return_value=True)
|
||||
mock_nextcloud_monitor.return_value.data = data
|
||||
assert await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
return entry
|
||||
|
@ -1,19 +1,11 @@
|
||||
"""Fixtrues for the Nextcloud integration tests."""
|
||||
|
||||
from collections.abc import Generator
|
||||
from unittest.mock import AsyncMock, Mock, patch
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_nextcloud_monitor() -> Mock:
|
||||
"""Mock of NextcloudMonitor."""
|
||||
return Mock(
|
||||
update=Mock(return_value=True),
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_setup_entry() -> Generator[AsyncMock]:
|
||||
"""Override async_setup_entry."""
|
||||
|
182
tests/components/nextcloud/const.py
Normal file
182
tests/components/nextcloud/const.py
Normal file
@ -0,0 +1,182 @@
|
||||
"""Constants for nextcloud tests."""
|
||||
|
||||
from homeassistant.const import CONF_PASSWORD, CONF_URL, CONF_USERNAME, CONF_VERIFY_SSL
|
||||
|
||||
MOCKED_ENTRY_ID = "1234567890abcdef"
|
||||
|
||||
VALID_CONFIG = {
|
||||
CONF_URL: "https://my.nc_url.local",
|
||||
CONF_USERNAME: "nc_user",
|
||||
CONF_PASSWORD: "nc_pass",
|
||||
CONF_VERIFY_SSL: True,
|
||||
}
|
||||
|
||||
NC_DATA = {
|
||||
"nextcloud": {
|
||||
"system": {
|
||||
"version": "28.0.4.1",
|
||||
"theme": "",
|
||||
"enable_avatars": "yes",
|
||||
"enable_previews": "yes",
|
||||
"memcache.local": "\\OC\\Memcache\\APCu",
|
||||
"memcache.distributed": "none",
|
||||
"filelocking.enabled": "yes",
|
||||
"memcache.locking": "none",
|
||||
"debug": "no",
|
||||
"freespace": 32769138688,
|
||||
"cpuload": [2.06640625, 1.58447265625, 1.45263671875],
|
||||
"mem_total": 30728192,
|
||||
"mem_free": 6753280,
|
||||
"swap_total": 10484736,
|
||||
"swap_free": 10484736,
|
||||
"apps": {
|
||||
"num_installed": 41,
|
||||
"num_updates_available": 0,
|
||||
"app_updates": [],
|
||||
},
|
||||
"update": {"lastupdatedat": 1713048517, "available": False},
|
||||
},
|
||||
"storage": {
|
||||
"num_users": 2,
|
||||
"num_files": 6783,
|
||||
"num_storages": 4,
|
||||
"num_storages_local": 1,
|
||||
"num_storages_home": 2,
|
||||
"num_storages_other": 1,
|
||||
},
|
||||
"shares": {
|
||||
"num_shares": 2,
|
||||
"num_shares_user": 0,
|
||||
"num_shares_groups": 0,
|
||||
"num_shares_link": 2,
|
||||
"num_shares_mail": 0,
|
||||
"num_shares_room": 0,
|
||||
"num_shares_link_no_password": 2,
|
||||
"num_fed_shares_sent": 0,
|
||||
"num_fed_shares_received": 1,
|
||||
"permissions_3_17": 1,
|
||||
"permissions_3_31": 1,
|
||||
},
|
||||
},
|
||||
"server": {
|
||||
"webserver": "Apache/2.4.57 (Debian)",
|
||||
"php": {
|
||||
"version": "8.2.18",
|
||||
"memory_limit": 536870912,
|
||||
"max_execution_time": 3600,
|
||||
"upload_max_filesize": 536870912,
|
||||
"opcache_revalidate_freq": 60,
|
||||
"opcache": {
|
||||
"opcache_enabled": True,
|
||||
"cache_full": False,
|
||||
"restart_pending": False,
|
||||
"restart_in_progress": False,
|
||||
"memory_usage": {
|
||||
"used_memory": 72027112,
|
||||
"free_memory": 62190616,
|
||||
"wasted_memory": 0,
|
||||
"current_wasted_percentage": 0,
|
||||
},
|
||||
"interned_strings_usage": {
|
||||
"buffer_size": 33554432,
|
||||
"used_memory": 12630360,
|
||||
"free_memory": 20924072,
|
||||
"number_of_strings": 69242,
|
||||
},
|
||||
"opcache_statistics": {
|
||||
"num_cached_scripts": 1406,
|
||||
"num_cached_keys": 2654,
|
||||
"max_cached_keys": 16229,
|
||||
"hits": 9739971,
|
||||
"start_time": 1722222008,
|
||||
"last_restart_time": 0,
|
||||
"oom_restarts": 0,
|
||||
"hash_restarts": 0,
|
||||
"manual_restarts": 0,
|
||||
"misses": 1406,
|
||||
"blacklist_misses": 0,
|
||||
"blacklist_miss_ratio": 0,
|
||||
"opcache_hit_rate": 99.9855667222406,
|
||||
},
|
||||
"jit": {
|
||||
"enabled": True,
|
||||
"on": True,
|
||||
"kind": 5,
|
||||
"opt_level": 5,
|
||||
"opt_flags": 6,
|
||||
"buffer_size": 134217712,
|
||||
"buffer_free": 133190688,
|
||||
},
|
||||
},
|
||||
"apcu": {
|
||||
"cache": {
|
||||
"num_slots": 4099,
|
||||
"ttl": 0,
|
||||
"num_hits": 590911,
|
||||
"num_misses": 55250,
|
||||
"num_inserts": 55421,
|
||||
"num_entries": 102,
|
||||
"expunges": 0,
|
||||
"start_time": 1722222008,
|
||||
"mem_size": 175296,
|
||||
"memory_type": "mmap",
|
||||
},
|
||||
"sma": {"num_seg": 1, "seg_size": 33554312, "avail_mem": 33342368},
|
||||
},
|
||||
"extensions": [
|
||||
"Core",
|
||||
"date",
|
||||
"libxml",
|
||||
"openssl",
|
||||
"pcre",
|
||||
"sqlite3",
|
||||
"zlib",
|
||||
"ctype",
|
||||
"curl",
|
||||
"dom",
|
||||
"fileinfo",
|
||||
"filter",
|
||||
"hash",
|
||||
"iconv",
|
||||
"json",
|
||||
"mbstring",
|
||||
"SPL",
|
||||
"session",
|
||||
"PDO",
|
||||
"pdo_sqlite",
|
||||
"standard",
|
||||
"posix",
|
||||
"random",
|
||||
"Reflection",
|
||||
"Phar",
|
||||
"SimpleXML",
|
||||
"tokenizer",
|
||||
"xml",
|
||||
"xmlreader",
|
||||
"xmlwriter",
|
||||
"mysqlnd",
|
||||
"apache2handler",
|
||||
"apcu",
|
||||
"bcmath",
|
||||
"exif",
|
||||
"ftp",
|
||||
"gd",
|
||||
"gmp",
|
||||
"imagick",
|
||||
"intl",
|
||||
"ldap",
|
||||
"memcached",
|
||||
"pcntl",
|
||||
"pdo_mysql",
|
||||
"pdo_pgsql",
|
||||
"redis",
|
||||
"sodium",
|
||||
"sysvsem",
|
||||
"zip",
|
||||
"Zend OPcache",
|
||||
],
|
||||
},
|
||||
"database": {"type": "sqlite3", "version": "3.40.1", "size": "4784128"},
|
||||
},
|
||||
"activeUsers": {"last5minutes": 0, "last1hour": 0, "last24hours": 0},
|
||||
}
|
277
tests/components/nextcloud/snapshots/test_binary_sensor.ambr
Normal file
277
tests/components/nextcloud/snapshots/test_binary_sensor.ambr
Normal file
@ -0,0 +1,277 @@
|
||||
# serializer version: 1
|
||||
# name: test_async_setup_entry[binary_sensor.my_nc_url_local_avatars_enabled-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'binary_sensor',
|
||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||
'entity_id': 'binary_sensor.my_nc_url_local_avatars_enabled',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Avatars enabled',
|
||||
'platform': 'nextcloud',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'nextcloud_system_enable_avatars',
|
||||
'unique_id': '1234567890abcdef#system_enable_avatars',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_async_setup_entry[binary_sensor.my_nc_url_local_avatars_enabled-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'my.nc_url.local Avatars enabled',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'binary_sensor.my_nc_url_local_avatars_enabled',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'on',
|
||||
})
|
||||
# ---
|
||||
# name: test_async_setup_entry[binary_sensor.my_nc_url_local_debug_enabled-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'binary_sensor',
|
||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||
'entity_id': 'binary_sensor.my_nc_url_local_debug_enabled',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Debug enabled',
|
||||
'platform': 'nextcloud',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'nextcloud_system_debug',
|
||||
'unique_id': '1234567890abcdef#system_debug',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_async_setup_entry[binary_sensor.my_nc_url_local_debug_enabled-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'my.nc_url.local Debug enabled',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'binary_sensor.my_nc_url_local_debug_enabled',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'off',
|
||||
})
|
||||
# ---
|
||||
# name: test_async_setup_entry[binary_sensor.my_nc_url_local_filelocking_enabled-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'binary_sensor',
|
||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||
'entity_id': 'binary_sensor.my_nc_url_local_filelocking_enabled',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Filelocking enabled',
|
||||
'platform': 'nextcloud',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'nextcloud_system_filelocking_enabled',
|
||||
'unique_id': '1234567890abcdef#system_filelocking.enabled',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_async_setup_entry[binary_sensor.my_nc_url_local_filelocking_enabled-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'my.nc_url.local Filelocking enabled',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'binary_sensor.my_nc_url_local_filelocking_enabled',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'on',
|
||||
})
|
||||
# ---
|
||||
# name: test_async_setup_entry[binary_sensor.my_nc_url_local_jit_active-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'binary_sensor',
|
||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||
'entity_id': 'binary_sensor.my_nc_url_local_jit_active',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'JIT active',
|
||||
'platform': 'nextcloud',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'nextcloud_jit_on',
|
||||
'unique_id': '1234567890abcdef#jit_on',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_async_setup_entry[binary_sensor.my_nc_url_local_jit_active-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'my.nc_url.local JIT active',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'binary_sensor.my_nc_url_local_jit_active',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'on',
|
||||
})
|
||||
# ---
|
||||
# name: test_async_setup_entry[binary_sensor.my_nc_url_local_jit_enabled-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'binary_sensor',
|
||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||
'entity_id': 'binary_sensor.my_nc_url_local_jit_enabled',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'JIT enabled',
|
||||
'platform': 'nextcloud',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'nextcloud_jit_enabled',
|
||||
'unique_id': '1234567890abcdef#jit_enabled',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_async_setup_entry[binary_sensor.my_nc_url_local_jit_enabled-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'my.nc_url.local JIT enabled',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'binary_sensor.my_nc_url_local_jit_enabled',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'on',
|
||||
})
|
||||
# ---
|
||||
# name: test_async_setup_entry[binary_sensor.my_nc_url_local_previews_enabled-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'binary_sensor',
|
||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||
'entity_id': 'binary_sensor.my_nc_url_local_previews_enabled',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Previews enabled',
|
||||
'platform': 'nextcloud',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'nextcloud_system_enable_previews',
|
||||
'unique_id': '1234567890abcdef#system_enable_previews',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_async_setup_entry[binary_sensor.my_nc_url_local_previews_enabled-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'my.nc_url.local Previews enabled',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'binary_sensor.my_nc_url_local_previews_enabled',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'on',
|
||||
})
|
||||
# ---
|
@ -2,7 +2,7 @@
|
||||
# name: test_reauth
|
||||
dict({
|
||||
'password': 'other_password',
|
||||
'url': 'nc_url',
|
||||
'url': 'https://my.nc_url.local',
|
||||
'username': 'other_user',
|
||||
'verify_ssl': True,
|
||||
})
|
||||
@ -10,7 +10,7 @@
|
||||
# name: test_user_create_entry
|
||||
dict({
|
||||
'password': 'nc_pass',
|
||||
'url': 'nc_url',
|
||||
'url': 'https://my.nc_url.local',
|
||||
'username': 'nc_user',
|
||||
'verify_ssl': True,
|
||||
})
|
||||
|
3973
tests/components/nextcloud/snapshots/test_sensor.ambr
Normal file
3973
tests/components/nextcloud/snapshots/test_sensor.ambr
Normal file
File diff suppressed because it is too large
Load Diff
57
tests/components/nextcloud/snapshots/test_update.ambr
Normal file
57
tests/components/nextcloud/snapshots/test_update.ambr
Normal file
@ -0,0 +1,57 @@
|
||||
# serializer version: 1
|
||||
# name: test_async_setup_entry[update.my_nc_url_local_none-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'update',
|
||||
'entity_category': <EntityCategory.CONFIG: 'config'>,
|
||||
'entity_id': 'update.my_nc_url_local_none',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': None,
|
||||
'platform': 'nextcloud',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': '1234567890abcdef#update',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_async_setup_entry[update.my_nc_url_local_none-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'auto_update': False,
|
||||
'entity_picture': 'https://brands.home-assistant.io/_/nextcloud/icon.png',
|
||||
'friendly_name': 'my.nc_url.local None',
|
||||
'in_progress': False,
|
||||
'installed_version': '28.0.4.1',
|
||||
'latest_version': '28.0.4.1',
|
||||
'release_summary': None,
|
||||
'release_url': 'https://nextcloud.com/changelog/#28-0-4',
|
||||
'skipped_version': None,
|
||||
'supported_features': <UpdateEntityFeature: 0>,
|
||||
'title': None,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'update.my_nc_url_local_none',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'off',
|
||||
})
|
||||
# ---
|
33
tests/components/nextcloud/test_binary_sensor.py
Normal file
33
tests/components/nextcloud/test_binary_sensor.py
Normal file
@ -0,0 +1,33 @@
|
||||
"""Tests for the Nextcloud binary sensors."""
|
||||
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from . import init_integration
|
||||
from .const import NC_DATA, VALID_CONFIG
|
||||
|
||||
from tests.common import snapshot_platform
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||
async def test_async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
entity_registry: er.EntityRegistry,
|
||||
snapshot: SnapshotAssertion,
|
||||
) -> None:
|
||||
"""Test a successful setup entry."""
|
||||
with patch(
|
||||
"homeassistant.components.nextcloud.PLATFORMS", [Platform.BINARY_SENSOR]
|
||||
):
|
||||
entry = await init_integration(hass, VALID_CONFIG, NC_DATA)
|
||||
|
||||
states = hass.states.async_all()
|
||||
assert len(states) == 6
|
||||
|
||||
await snapshot_platform(hass, entity_registry, snapshot, entry.entry_id)
|
@ -1,6 +1,6 @@
|
||||
"""Tests for the Nextcloud config flow."""
|
||||
|
||||
from unittest.mock import Mock, patch
|
||||
from unittest.mock import patch
|
||||
|
||||
from nextcloudmonitor import (
|
||||
NextcloudMonitorAuthorizationError,
|
||||
@ -12,24 +12,19 @@ from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.components.nextcloud.const import DOMAIN
|
||||
from homeassistant.config_entries import SOURCE_REAUTH, SOURCE_USER
|
||||
from homeassistant.const import CONF_PASSWORD, CONF_URL, CONF_USERNAME, CONF_VERIFY_SSL
|
||||
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.data_entry_flow import FlowResultType
|
||||
|
||||
from .const import VALID_CONFIG
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
pytestmark = pytest.mark.usefixtures("mock_setup_entry")
|
||||
|
||||
VALID_CONFIG = {
|
||||
CONF_URL: "nc_url",
|
||||
CONF_USERNAME: "nc_user",
|
||||
CONF_PASSWORD: "nc_pass",
|
||||
CONF_VERIFY_SSL: True,
|
||||
}
|
||||
|
||||
|
||||
async def test_user_create_entry(
|
||||
hass: HomeAssistant, mock_nextcloud_monitor: Mock, snapshot: SnapshotAssertion
|
||||
hass: HomeAssistant, snapshot: SnapshotAssertion
|
||||
) -> None:
|
||||
"""Test that the user step works."""
|
||||
# start user flow
|
||||
@ -85,7 +80,7 @@ async def test_user_create_entry(
|
||||
# test success
|
||||
with patch(
|
||||
"homeassistant.components.nextcloud.config_flow.NextcloudMonitor",
|
||||
return_value=mock_nextcloud_monitor,
|
||||
return_value=True,
|
||||
):
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
@ -94,17 +89,15 @@ async def test_user_create_entry(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result["title"] == "nc_url"
|
||||
assert result["title"] == "https://my.nc_url.local"
|
||||
assert result["data"] == snapshot
|
||||
|
||||
|
||||
async def test_user_already_configured(
|
||||
hass: HomeAssistant, mock_nextcloud_monitor: Mock
|
||||
) -> None:
|
||||
async def test_user_already_configured(hass: HomeAssistant) -> None:
|
||||
"""Test that errors are shown when duplicates are added."""
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
title="nc_url",
|
||||
title="https://my.nc_url.local",
|
||||
unique_id="nc_url",
|
||||
data=VALID_CONFIG,
|
||||
)
|
||||
@ -119,7 +112,7 @@ async def test_user_already_configured(
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.nextcloud.config_flow.NextcloudMonitor",
|
||||
return_value=mock_nextcloud_monitor,
|
||||
return_value=True,
|
||||
):
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
@ -131,13 +124,11 @@ async def test_user_already_configured(
|
||||
assert result["reason"] == "already_configured"
|
||||
|
||||
|
||||
async def test_reauth(
|
||||
hass: HomeAssistant, mock_nextcloud_monitor: Mock, snapshot: SnapshotAssertion
|
||||
) -> None:
|
||||
async def test_reauth(hass: HomeAssistant, snapshot: SnapshotAssertion) -> None:
|
||||
"""Test that the re-auth flow works."""
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
title="nc_url",
|
||||
title="https://my.nc_url.local",
|
||||
unique_id="nc_url",
|
||||
data=VALID_CONFIG,
|
||||
)
|
||||
@ -206,7 +197,7 @@ async def test_reauth(
|
||||
# test success
|
||||
with patch(
|
||||
"homeassistant.components.nextcloud.config_flow.NextcloudMonitor",
|
||||
return_value=mock_nextcloud_monitor,
|
||||
return_value=True,
|
||||
):
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
|
69
tests/components/nextcloud/test_coordinator.py
Normal file
69
tests/components/nextcloud/test_coordinator.py
Normal file
@ -0,0 +1,69 @@
|
||||
"""Tests for the Nextcloud coordinator."""
|
||||
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
from freezegun.api import FrozenDateTimeFactory
|
||||
from nextcloudmonitor import (
|
||||
NextcloudMonitor,
|
||||
NextcloudMonitorAuthorizationError,
|
||||
NextcloudMonitorConnectionError,
|
||||
NextcloudMonitorError,
|
||||
NextcloudMonitorRequestError,
|
||||
)
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.nextcloud.const import DEFAULT_SCAN_INTERVAL
|
||||
from homeassistant.const import STATE_UNAVAILABLE
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from . import mock_config_entry
|
||||
from .const import NC_DATA, VALID_CONFIG
|
||||
|
||||
from tests.common import async_fire_time_changed
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("error"),
|
||||
[
|
||||
(NextcloudMonitorAuthorizationError),
|
||||
(NextcloudMonitorConnectionError),
|
||||
(NextcloudMonitorRequestError),
|
||||
],
|
||||
)
|
||||
async def test_data_update(
|
||||
hass: HomeAssistant, freezer: FrozenDateTimeFactory, error: NextcloudMonitorError
|
||||
) -> None:
|
||||
"""Test a coordinator data updates."""
|
||||
entry = mock_config_entry(VALID_CONFIG)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.nextcloud.NextcloudMonitor", spec=NextcloudMonitor
|
||||
) as mock_nextcloud_monitor,
|
||||
):
|
||||
mock_nextcloud_monitor.return_value.update = Mock(
|
||||
return_value=True,
|
||||
side_effect=[None, error, None],
|
||||
)
|
||||
mock_nextcloud_monitor.return_value.data = NC_DATA
|
||||
assert await hass.config_entries.async_setup(entry.entry_id)
|
||||
|
||||
# Test successful setup and first data fetch
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
states = hass.states.async_all()
|
||||
assert (state != STATE_UNAVAILABLE for state in states)
|
||||
|
||||
# Test states get unavailable on error
|
||||
freezer.tick(DEFAULT_SCAN_INTERVAL)
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
states = hass.states.async_all()
|
||||
assert (state == STATE_UNAVAILABLE for state in states)
|
||||
|
||||
# Test successful data fetch
|
||||
freezer.tick(DEFAULT_SCAN_INTERVAL)
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
states = hass.states.async_all()
|
||||
assert (state != STATE_UNAVAILABLE for state in states)
|
95
tests/components/nextcloud/test_init.py
Normal file
95
tests/components/nextcloud/test_init.py
Normal file
@ -0,0 +1,95 @@
|
||||
"""Tests for the Nextcloud init."""
|
||||
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
from nextcloudmonitor import (
|
||||
NextcloudMonitorAuthorizationError,
|
||||
NextcloudMonitorConnectionError,
|
||||
NextcloudMonitorError,
|
||||
NextcloudMonitorRequestError,
|
||||
)
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.nextcloud.const import DOMAIN
|
||||
from homeassistant.config_entries import ConfigEntryState
|
||||
from homeassistant.const import CONF_URL, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from . import init_integration, mock_config_entry
|
||||
from .const import MOCKED_ENTRY_ID, NC_DATA, VALID_CONFIG
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||
async def test_async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
) -> None:
|
||||
"""Test a successful setup entry."""
|
||||
assert await init_integration(hass, VALID_CONFIG, NC_DATA)
|
||||
|
||||
|
||||
async def test_unique_id_migration(
|
||||
hass: HomeAssistant,
|
||||
entity_registry: er.EntityRegistry,
|
||||
) -> None:
|
||||
"""Test migration of unique ids to stable ones."""
|
||||
|
||||
object_id = "my_nc_url_local_system_version"
|
||||
entity_id = f"{Platform.SENSOR}.{object_id}"
|
||||
|
||||
entry = mock_config_entry(VALID_CONFIG)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
entity = entity_registry.async_get_or_create(
|
||||
Platform.SENSOR,
|
||||
DOMAIN,
|
||||
f"{VALID_CONFIG[CONF_URL]}#nextcloud_system_version",
|
||||
suggested_object_id=object_id,
|
||||
config_entry=entry,
|
||||
)
|
||||
|
||||
# test old unique id
|
||||
assert entity.entity_id == entity_id
|
||||
assert entity.unique_id == f"{VALID_CONFIG[CONF_URL]}#nextcloud_system_version"
|
||||
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.nextcloud.NextcloudMonitor"
|
||||
) as mock_nextcloud_monitor,
|
||||
):
|
||||
mock_nextcloud_monitor.update = Mock(return_value=True)
|
||||
mock_nextcloud_monitor.return_value.data = NC_DATA
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# test migrated unique id
|
||||
reg_entry = entity_registry.async_get(entity_id)
|
||||
assert reg_entry.unique_id == f"{MOCKED_ENTRY_ID}#system_version"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("exception", "expcted_entry_state"),
|
||||
[
|
||||
(NextcloudMonitorAuthorizationError, ConfigEntryState.SETUP_ERROR),
|
||||
(NextcloudMonitorConnectionError, ConfigEntryState.SETUP_RETRY),
|
||||
(NextcloudMonitorRequestError, ConfigEntryState.SETUP_RETRY),
|
||||
],
|
||||
)
|
||||
async def test_setup_entry_errors(
|
||||
hass: HomeAssistant,
|
||||
exception: NextcloudMonitorError,
|
||||
expcted_entry_state: ConfigEntryState,
|
||||
) -> None:
|
||||
"""Test a successful setup entry."""
|
||||
|
||||
entry = mock_config_entry(VALID_CONFIG)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.nextcloud.NextcloudMonitor", side_effect=exception
|
||||
),
|
||||
):
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
assert entry.state == expcted_entry_state
|
31
tests/components/nextcloud/test_sensor.py
Normal file
31
tests/components/nextcloud/test_sensor.py
Normal file
@ -0,0 +1,31 @@
|
||||
"""Tests for the Nextcloud sensors."""
|
||||
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from . import init_integration
|
||||
from .const import NC_DATA, VALID_CONFIG
|
||||
|
||||
from tests.common import snapshot_platform
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||
async def test_async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
entity_registry: er.EntityRegistry,
|
||||
snapshot: SnapshotAssertion,
|
||||
) -> None:
|
||||
"""Test a successful setup entry."""
|
||||
with patch("homeassistant.components.nextcloud.PLATFORMS", [Platform.SENSOR]):
|
||||
entry = await init_integration(hass, VALID_CONFIG, NC_DATA)
|
||||
|
||||
states = hass.states.async_all()
|
||||
assert len(states) == 80
|
||||
|
||||
await snapshot_platform(hass, entity_registry, snapshot, entry.entry_id)
|
80
tests/components/nextcloud/test_update.py
Normal file
80
tests/components/nextcloud/test_update.py
Normal file
@ -0,0 +1,80 @@
|
||||
"""Tests for the Nextcloud update entity."""
|
||||
|
||||
from copy import deepcopy
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.const import STATE_OFF, STATE_ON, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from . import init_integration
|
||||
from .const import NC_DATA, VALID_CONFIG
|
||||
|
||||
from tests.common import snapshot_platform
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||
async def test_async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
entity_registry: er.EntityRegistry,
|
||||
snapshot: SnapshotAssertion,
|
||||
) -> None:
|
||||
"""Test a successful setup entry."""
|
||||
with patch("homeassistant.components.nextcloud.PLATFORMS", [Platform.UPDATE]):
|
||||
entry = await init_integration(hass, VALID_CONFIG, NC_DATA)
|
||||
|
||||
states = hass.states.async_all()
|
||||
assert len(states) == 1
|
||||
|
||||
await snapshot_platform(hass, entity_registry, snapshot, entry.entry_id)
|
||||
|
||||
|
||||
async def test_setup_entity_without_update(
|
||||
hass: HomeAssistant, snapshot: SnapshotAssertion
|
||||
) -> None:
|
||||
"""Test update entity is created w/o available update."""
|
||||
with patch("homeassistant.components.nextcloud.PLATFORMS", [Platform.UPDATE]):
|
||||
await init_integration(hass, VALID_CONFIG, NC_DATA)
|
||||
|
||||
states = hass.states.async_all()
|
||||
assert len(states) == 1
|
||||
assert states[0].state == STATE_OFF
|
||||
assert states[0].attributes["installed_version"] == "28.0.4.1"
|
||||
assert states[0].attributes["latest_version"] == "28.0.4.1"
|
||||
assert (
|
||||
states[0].attributes["release_url"] == "https://nextcloud.com/changelog/#28-0-4"
|
||||
)
|
||||
|
||||
|
||||
async def test_setup_entity_with_update(
|
||||
hass: HomeAssistant, snapshot: SnapshotAssertion
|
||||
) -> None:
|
||||
"""Test update entity is created with available update."""
|
||||
data = deepcopy(NC_DATA)
|
||||
data["nextcloud"]["system"]["update"]["available"] = True
|
||||
data["nextcloud"]["system"]["update"]["available_version"] = "30.0.0.0"
|
||||
with patch("homeassistant.components.nextcloud.PLATFORMS", [Platform.UPDATE]):
|
||||
await init_integration(hass, VALID_CONFIG, data)
|
||||
|
||||
states = hass.states.async_all()
|
||||
assert len(states) == 1
|
||||
assert states[0].state == STATE_ON
|
||||
assert states[0].attributes["installed_version"] == "28.0.4.1"
|
||||
assert states[0].attributes["latest_version"] == "30.0.0.0"
|
||||
assert (
|
||||
states[0].attributes["release_url"] == "https://nextcloud.com/changelog/#30-0-0"
|
||||
)
|
||||
|
||||
|
||||
async def test_setup_no_entity(hass: HomeAssistant) -> None:
|
||||
"""Test no update entity is created, when no data available."""
|
||||
data = deepcopy(NC_DATA)
|
||||
data["nextcloud"]["system"].pop("update") # only nc<28.0.0
|
||||
with patch("homeassistant.components.nextcloud.PLATFORMS", [Platform.UPDATE]):
|
||||
await init_integration(hass, VALID_CONFIG, data)
|
||||
|
||||
states = hass.states.async_all()
|
||||
assert len(states) == 0
|
Loading…
x
Reference in New Issue
Block a user