Skip to content

Commit b08eb3a

Browse files
authored
Refactor NextDNS tests (home-assistant#154901)
1 parent c74c317 commit b08eb3a

File tree

16 files changed

+371
-399
lines changed

16 files changed

+371
-399
lines changed

homeassistant/components/nextdns/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@
77
"integration_type": "service",
88
"iot_class": "cloud_polling",
99
"loggers": ["nextdns"],
10-
"quality_scale": "bronze",
10+
"quality_scale": "silver",
1111
"requirements": ["nextdns==4.1.0"]
1212
}

homeassistant/components/nextdns/quality_scale.yaml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,7 @@ rules:
3737
log-when-unavailable: done
3838
parallel-updates: done
3939
reauthentication-flow: done
40-
test-coverage:
41-
status: todo
42-
comment: Patch NextDns object instead of functions.
40+
test-coverage: done
4341

4442
# Gold
4543
devices: done
Lines changed: 2 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -1,164 +1,15 @@
11
"""Tests for the NextDNS integration."""
22

3-
from contextlib import contextmanager
4-
from unittest.mock import patch
5-
6-
from nextdns import (
7-
AnalyticsDnssec,
8-
AnalyticsEncryption,
9-
AnalyticsIpVersions,
10-
AnalyticsProtocols,
11-
AnalyticsStatus,
12-
ConnectionStatus,
13-
Settings,
14-
)
15-
163
from homeassistant.core import HomeAssistant
174

185
from tests.common import MockConfigEntry
196

20-
CONNECTION_STATUS = ConnectionStatus(connected=True, profile_id="abcdef")
21-
PROFILES = [{"id": "xyz12", "fingerprint": "aabbccdd123", "name": "Fake Profile"}]
22-
STATUS = AnalyticsStatus(
23-
default_queries=40, allowed_queries=30, blocked_queries=20, relayed_queries=10
24-
)
25-
DNSSEC = AnalyticsDnssec(not_validated_queries=25, validated_queries=75)
26-
ENCRYPTION = AnalyticsEncryption(encrypted_queries=60, unencrypted_queries=40)
27-
IP_VERSIONS = AnalyticsIpVersions(ipv4_queries=90, ipv6_queries=10)
28-
PROTOCOLS = AnalyticsProtocols(
29-
doh_queries=20,
30-
doh3_queries=15,
31-
doq_queries=10,
32-
dot_queries=30,
33-
tcp_queries=0,
34-
udp_queries=40,
35-
)
36-
SETTINGS = Settings(
37-
ai_threat_detection=True,
38-
allow_affiliate=True,
39-
anonymized_ecs=True,
40-
bav=True,
41-
block_bypass_methods=True,
42-
block_csam=True,
43-
block_ddns=True,
44-
block_disguised_trackers=True,
45-
block_nrd=True,
46-
block_page=False,
47-
block_parked_domains=True,
48-
cache_boost=True,
49-
cname_flattening=True,
50-
cryptojacking_protection=True,
51-
dga_protection=True,
52-
dns_rebinding_protection=True,
53-
google_safe_browsing=False,
54-
idn_homograph_attacks_protection=True,
55-
logs=True,
56-
logs_location="ch",
57-
logs_retention=720,
58-
safesearch=False,
59-
threat_intelligence_feeds=True,
60-
typosquatting_protection=True,
61-
web3=True,
62-
youtube_restricted_mode=False,
63-
block_9gag=True,
64-
block_amazon=True,
65-
block_bereal=True,
66-
block_blizzard=True,
67-
block_chatgpt=True,
68-
block_dailymotion=True,
69-
block_discord=True,
70-
block_disneyplus=True,
71-
block_ebay=True,
72-
block_facebook=True,
73-
block_fortnite=True,
74-
block_google_chat=True,
75-
block_hbomax=True,
76-
block_hulu=True,
77-
block_imgur=True,
78-
block_instagram=True,
79-
block_leagueoflegends=True,
80-
block_mastodon=True,
81-
block_messenger=True,
82-
block_minecraft=True,
83-
block_netflix=True,
84-
block_pinterest=True,
85-
block_playstation_network=True,
86-
block_primevideo=True,
87-
block_reddit=True,
88-
block_roblox=True,
89-
block_signal=True,
90-
block_skype=True,
91-
block_snapchat=True,
92-
block_spotify=True,
93-
block_steam=True,
94-
block_telegram=True,
95-
block_tiktok=True,
96-
block_tinder=True,
97-
block_tumblr=True,
98-
block_twitch=True,
99-
block_twitter=True,
100-
block_vimeo=True,
101-
block_vk=True,
102-
block_whatsapp=True,
103-
block_xboxlive=True,
104-
block_youtube=True,
105-
block_zoom=True,
106-
block_dating=True,
107-
block_gambling=True,
108-
block_online_gaming=True,
109-
block_piracy=True,
110-
block_porn=True,
111-
block_social_networks=True,
112-
block_video_streaming=True,
113-
)
114-
115-
116-
@contextmanager
117-
def mock_nextdns():
118-
"""Mock the NextDNS class."""
119-
with (
120-
patch(
121-
"homeassistant.components.nextdns.NextDns.get_profiles",
122-
return_value=PROFILES,
123-
),
124-
patch(
125-
"homeassistant.components.nextdns.NextDns.get_analytics_status",
126-
return_value=STATUS,
127-
),
128-
patch(
129-
"homeassistant.components.nextdns.NextDns.get_analytics_encryption",
130-
return_value=ENCRYPTION,
131-
),
132-
patch(
133-
"homeassistant.components.nextdns.NextDns.get_analytics_dnssec",
134-
return_value=DNSSEC,
135-
),
136-
patch(
137-
"homeassistant.components.nextdns.NextDns.get_analytics_ip_versions",
138-
return_value=IP_VERSIONS,
139-
),
140-
patch(
141-
"homeassistant.components.nextdns.NextDns.get_analytics_protocols",
142-
return_value=PROTOCOLS,
143-
),
144-
patch(
145-
"homeassistant.components.nextdns.NextDns.get_settings",
146-
return_value=SETTINGS,
147-
),
148-
patch(
149-
"homeassistant.components.nextdns.NextDns.connection_status",
150-
return_value=CONNECTION_STATUS,
151-
),
152-
):
153-
yield
154-
1557

1568
async def init_integration(
1579
hass: HomeAssistant, mock_config_entry: MockConfigEntry
15810
) -> None:
15911
"""Set up the NextDNS integration in Home Assistant."""
16012
mock_config_entry.add_to_hass(hass)
16113

162-
with mock_nextdns():
163-
await hass.config_entries.async_setup(mock_config_entry.entry_id)
164-
await hass.async_block_till_done()
14+
await hass.config_entries.async_setup(mock_config_entry.entry_id)
15+
await hass.async_block_till_done()

tests/components/nextdns/conftest.py

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,40 @@
11
"""Common fixtures for the NextDNS tests."""
22

33
from collections.abc import Generator
4-
from unittest.mock import AsyncMock, patch
4+
from unittest.mock import AsyncMock, Mock, patch
55

6+
from nextdns import (
7+
AnalyticsDnssec,
8+
AnalyticsEncryption,
9+
AnalyticsIpVersions,
10+
AnalyticsProtocols,
11+
AnalyticsStatus,
12+
ConnectionStatus,
13+
ProfileInfo,
14+
Settings,
15+
)
616
import pytest
717

818
from homeassistant.components.nextdns.const import CONF_PROFILE_ID, DOMAIN
919
from homeassistant.const import CONF_API_KEY
1020

11-
from tests.common import MockConfigEntry
21+
from tests.common import (
22+
MockConfigEntry,
23+
load_json_array_fixture,
24+
load_json_object_fixture,
25+
)
26+
27+
ANALYTICS = load_json_object_fixture("analytics.json", DOMAIN)
28+
ANALYTICS_DNSSEC = AnalyticsDnssec(**ANALYTICS["dnssec"])
29+
ANALYTICS_ENCRYPTION = AnalyticsEncryption(**ANALYTICS["encryption"])
30+
ANALYTICS_IP_VERSIONS = AnalyticsIpVersions(**ANALYTICS["ip_versions"])
31+
ANALYTICS_PROTOCOLS = AnalyticsProtocols(**ANALYTICS["protocols"])
32+
ANALYTICS_STATUS = AnalyticsStatus(**ANALYTICS["status"])
33+
CONNECTION_STATUS = ConnectionStatus(
34+
**load_json_object_fixture("connection_status.json", DOMAIN)
35+
)
36+
PROFILES = load_json_array_fixture("profiles.json", DOMAIN)
37+
SETTINGS = Settings(**load_json_object_fixture("settings.json", DOMAIN))
1238

1339

1440
@pytest.fixture
@@ -30,3 +56,32 @@ def mock_config_entry() -> MockConfigEntry:
3056
data={CONF_API_KEY: "fake_api_key", CONF_PROFILE_ID: "xyz12"},
3157
entry_id="d9aa37407ddac7b964a99e86312288d6",
3258
)
59+
60+
61+
@pytest.fixture
62+
def mock_nextdns_client() -> Generator[AsyncMock]:
63+
"""Mock a NextDNS client."""
64+
65+
with (
66+
patch("homeassistant.components.nextdns.NextDns", autospec=True) as mock_client,
67+
patch(
68+
"homeassistant.components.nextdns.config_flow.NextDns",
69+
new=mock_client,
70+
),
71+
):
72+
client = mock_client.create.return_value
73+
client.clear_logs.return_value = True
74+
client.connection_status.return_value = CONNECTION_STATUS
75+
client.get_analytics_dnssec.return_value = ANALYTICS_DNSSEC
76+
client.get_analytics_encryption.return_value = ANALYTICS_ENCRYPTION
77+
client.get_analytics_ip_versions.return_value = ANALYTICS_IP_VERSIONS
78+
client.get_analytics_protocols.return_value = ANALYTICS_PROTOCOLS
79+
client.get_analytics_status.return_value = ANALYTICS_STATUS
80+
client.get_profile_id = Mock(return_value="xyz12")
81+
client.get_profile_name = Mock(return_value="Fake Profile")
82+
client.get_profiles.return_value = PROFILES
83+
client.get_settings.return_value = SETTINGS
84+
client.set_setting.return_value = True
85+
client.profiles = [ProfileInfo(**PROFILES[0])]
86+
87+
yield client
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"protocols": {
3+
"doh_queries": 20,
4+
"doh3_queries": 15,
5+
"doq_queries": 10,
6+
"dot_queries": 30,
7+
"tcp_queries": 0,
8+
"udp_queries": 40
9+
},
10+
"status": {
11+
"default_queries": 40,
12+
"allowed_queries": 30,
13+
"blocked_queries": 20,
14+
"relayed_queries": 10
15+
},
16+
"ip_versions": { "ipv4_queries": 90, "ipv6_queries": 10 },
17+
"encryption": { "encrypted_queries": 60, "unencrypted_queries": 40 },
18+
"dnssec": { "not_validated_queries": 25, "validated_queries": 75 }
19+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"connected": true,
3+
"profile_id": "abcdef"
4+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[{ "id": "xyz12", "fingerprint": "aabbccdd123", "name": "Fake Profile" }]
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
{
2+
"ai_threat_detection": true,
3+
"allow_affiliate": true,
4+
"anonymized_ecs": true,
5+
"bav": true,
6+
"block_bypass_methods": true,
7+
"block_csam": true,
8+
"block_ddns": true,
9+
"block_disguised_trackers": true,
10+
"block_nrd": true,
11+
"block_page": false,
12+
"block_parked_domains": true,
13+
"cache_boost": true,
14+
"cname_flattening": true,
15+
"cryptojacking_protection": true,
16+
"dga_protection": true,
17+
"dns_rebinding_protection": true,
18+
"google_safe_browsing": false,
19+
"idn_homograph_attacks_protection": true,
20+
"logs": true,
21+
"logs_location": "ch",
22+
"logs_retention": 720,
23+
"safesearch": false,
24+
"threat_intelligence_feeds": true,
25+
"typosquatting_protection": true,
26+
"web3": true,
27+
"youtube_restricted_mode": false,
28+
"block_9gag": true,
29+
"block_amazon": true,
30+
"block_bereal": true,
31+
"block_blizzard": true,
32+
"block_chatgpt": true,
33+
"block_dailymotion": true,
34+
"block_discord": true,
35+
"block_disneyplus": true,
36+
"block_ebay": true,
37+
"block_facebook": true,
38+
"block_fortnite": true,
39+
"block_google_chat": true,
40+
"block_hbomax": true,
41+
"block_hulu": true,
42+
"block_imgur": true,
43+
"block_instagram": true,
44+
"block_leagueoflegends": true,
45+
"block_mastodon": true,
46+
"block_messenger": true,
47+
"block_minecraft": true,
48+
"block_netflix": true,
49+
"block_pinterest": true,
50+
"block_playstation_network": true,
51+
"block_primevideo": true,
52+
"block_reddit": true,
53+
"block_roblox": true,
54+
"block_signal": true,
55+
"block_skype": true,
56+
"block_snapchat": true,
57+
"block_spotify": true,
58+
"block_steam": true,
59+
"block_telegram": true,
60+
"block_tiktok": true,
61+
"block_tinder": true,
62+
"block_tumblr": true,
63+
"block_twitch": true,
64+
"block_twitter": true,
65+
"block_vimeo": true,
66+
"block_vk": true,
67+
"block_whatsapp": true,
68+
"block_xboxlive": true,
69+
"block_youtube": true,
70+
"block_zoom": true,
71+
"block_dating": true,
72+
"block_gambling": true,
73+
"block_online_gaming": true,
74+
"block_piracy": true,
75+
"block_porn": true,
76+
"block_social_networks": true,
77+
"block_video_streaming": true
78+
}

0 commit comments

Comments
 (0)