Files
kadence/backend/tests/test_blocker.py
T
timka123 a75a011edb backend: a bare * in subdomain_expansions means every subdomain
An expansion list of labels guesses which subdomains exist; a '*' entry
makes the guess unnecessary. parse_expansions now reports (labels, wildcard,
rejected) instead of silently keeping junk, expand_entry keeps the base
domain plus the configured labels and leaves '*.base' as a pattern when the
wildcard is on, and the policy grows the 'allowed' masks the desktop
resolver needs to serve exceptions.
2026-10-19 18:45:20 +03:00

166 lines
6.9 KiB
Python

"""Blocking policy: when it is on, and what is on the list."""
from __future__ import annotations
from app.services import blocker_service, pomodoro, settings_service
def test_disabled_blocker_blocks_nothing(session, settings):
pomodoro.start(session, settings, kind="work")
policy = blocker_service.policy(session, settings)
assert policy["active"] is False and policy["domains"] == []
def test_during_work_mode_follows_the_timer(session, settings):
settings.blocker.enabled = True
settings.blocker.blocked_domains = ["youtube.com"]
settings_service.save_settings(session, settings)
assert blocker_service.policy(session, settings)["active"] is False
pomodoro.start(session, settings, kind="work")
policy = blocker_service.policy(session, settings)
assert policy["active"] is True
assert "www.youtube.com" in policy["domains"]
pomodoro.complete(session, settings, auto_next=False)
assert blocker_service.policy(session, settings)["active"] is False
def test_breaks_do_not_block_unless_asked(session, settings):
settings.blocker.enabled = True
settings_service.save_settings(session, settings)
pomodoro.start(session, settings, kind="short_break")
assert blocker_service.policy(session, settings)["active"] is False
settings.blocker.block_during_breaks = True
settings_service.save_settings(session, settings)
assert blocker_service.policy(session, settings)["active"] is True
def test_always_mode_ignores_the_timer(session, settings):
settings.blocker.enabled = True
settings.blocker.mode = "always"
settings_service.save_settings(session, settings)
assert blocker_service.policy(session, settings)["active"] is True
def test_allowlist_wins_over_the_blocklist(session, settings):
settings.blocker.blocked_domains = ["youtube.com"]
settings.blocker.allowed_domains = ["m.youtube.com"]
hosts = blocker_service.expand_domains(settings)
assert "youtube.com" in hosts
assert "m.youtube.com" not in hosts
def test_events_are_grouped_for_the_report(session, settings):
for _ in range(3):
blocker_service.record_event(session, settings, kind="domain", target="YouTube.com")
blocker_service.record_event(session, settings, kind="app", target="steam")
summary = blocker_service.events_for_day(session, settings)
assert summary["total"] == 4
assert summary["by_target"][0] == {"target": "youtube.com", "count": 3}
def test_masked_subdomains_are_expanded(session, settings):
"""A hosts file has no wildcards, so `*.x` has to become real names."""
settings.blocker.blocked_domains = ["*.google.com"]
settings.blocker.subdomain_expansions = ["www", "mail"]
hosts = blocker_service.expand_domains(settings)
assert hosts == ["google.com", "www.google.com", "mail.google.com"]
def test_allow_masks_carve_holes_in_block_masks(session, settings):
settings.blocker.blocked_domains = ["*.google.com", "reddit.com"]
settings.blocker.subdomain_expansions = ["www", "docs"]
settings.blocker.allowed_domains = ["docs.*", "m.reddit.com"]
hosts = blocker_service.expand_domains(settings)
assert "docs.google.com" not in hosts
assert "m.reddit.com" not in hosts
assert "www.google.com" in hosts and "reddit.com" in hosts
def test_patterns_a_hosts_file_cannot_express_are_reported(session, settings):
settings.blocker.blocked_domains = ["*gram*", "youtube.com", "*.x.com"]
assert blocker_service.unexpandable_masks(settings) == ["*gram*"]
hosts = blocker_service.expand_domains(settings)
assert "youtube.com" in hosts and "x.com" in hosts
def test_app_masks_are_passed_through_untouched(session, settings):
"""Process matching happens on the desktop, where globs work directly."""
settings.blocker.enabled = True
settings.blocker.mode = "always"
settings.blocker.blocked_apps = ["steam*", "*discord*"]
settings_service.save_settings(session, settings)
policy = blocker_service.policy(session, settings)
assert policy["apps"] == ["steam*", "*discord*"]
def test_a_wildcard_means_every_subdomain(session, settings):
"""`*` in the expansion list is the user asking for all of them.
It used to be refused (it is not a DNS label), which left `*.telegram.org`
expanded to just the bare domain with a red banner beside it. Now the labels
still expand, the pattern is handed to the clients that can match masks, and
only entries that are neither a label nor `*` are refused.
"""
settings.blocker.blocked_domains = ["*.telegram.org"]
settings.blocker.subdomain_expansions = ["*", "web", "", "not a label"]
expansion = blocker_service.parse_expansions(settings.blocker.subdomain_expansions)
assert expansion.labels == ["web"]
assert expansion.wildcard is True
assert expansion.rejected == ["not a label"]
hosts = blocker_service.expand_domains(settings)
assert hosts == ["telegram.org", "web.telegram.org"]
assert not any("*" in host for host in hosts)
# The pattern comes back too: a hosts file cannot say "every subdomain", so
# the desktop app's resolver stub and the phone's URL matcher take it.
assert blocker_service.unexpandable_masks(settings) == ["*.telegram.org"]
def test_without_a_wildcard_the_pattern_stays_in_the_expansion_list(session, settings):
"""`*.x.com` alone means the configured labels, not a wildcard — nothing else."""
settings.blocker.blocked_domains = ["*.google.com"]
settings.blocker.subdomain_expansions = ["www", "mail"]
assert blocker_service.unexpandable_masks(settings) == []
assert blocker_service.expand_domains(settings) == [
"google.com",
"www.google.com",
"mail.google.com",
]
def test_the_policy_reports_expansions_it_had_to_refuse(session, settings):
settings.blocker.enabled = True
settings.blocker.mode = "always"
settings.blocker.blocked_domains = ["*.telegram.org"]
settings.blocker.subdomain_expansions = ["*", ".."]
result = blocker_service.policy(session, settings)
assert result["invalid_expansions"] == [".."]
assert result["domains"] == ["telegram.org"]
assert result["unexpandable"] == ["*.telegram.org"]
def test_the_policy_carries_the_allow_masks_for_the_stub(session, settings):
"""The desktop app answers DNS for a whole zone, so it needs the exceptions.
Without them the resolver stub would sinkhole `music.youtube.com` along with
everything else under a wildcarded domain — an exception that works over the
hosts file but not over DNS is an exception nobody will trust.
"""
settings.blocker.enabled = True
settings.blocker.mode = "always"
settings.blocker.blocked_domains = ["*.youtube.com"]
settings.blocker.allowed_domains = [" music.youtube.com ", "*.docs.google.com"]
result = blocker_service.policy(session, settings)
assert result["allowed"] == ["music.youtube.com", "*.docs.google.com"]
assert "music.youtube.com" not in result["domains"]
assert "m.youtube.com" in result["all_domains"]