"""Tests for the username enumeration plugin.""" import importlib.util import sys from pathlib import Path # plugins/ is not a Python package -- load the module from file path _spec = importlib.util.spec_from_file_location( "plugins.username", Path(__file__).resolve().parent.parent / "plugins" / "username.py", ) _mod = importlib.util.module_from_spec(_spec) sys.modules[_spec.name] = _mod _spec.loader.exec_module(_mod) from plugins.username import ( # noqa: E402 _BY_CATEGORY, _BY_NAME, _SERVICES, _USERNAME_RE, _Service, classify, classify_body, classify_json, classify_status, format_list, format_single, format_summary, ) class TestUsernameRegex: def test_valid_simple(self): assert _USERNAME_RE.match("john") def test_valid_with_dots(self): assert _USERNAME_RE.match("john.doe") def test_valid_with_hyphens(self): assert _USERNAME_RE.match("john-doe") def test_valid_with_underscores(self): assert _USERNAME_RE.match("john_doe") def test_valid_numeric(self): assert _USERNAME_RE.match("user123") def test_valid_max_length(self): assert _USERNAME_RE.match("a" * 39) def test_invalid_too_long(self): assert _USERNAME_RE.match("a" * 40) is None def test_invalid_empty(self): assert _USERNAME_RE.match("") is None def test_invalid_spaces(self): assert _USERNAME_RE.match("john doe") is None def test_invalid_special_chars(self): assert _USERNAME_RE.match("john@doe") is None assert _USERNAME_RE.match("john!") is None assert _USERNAME_RE.match("user#1") is None def test_invalid_slash(self): assert _USERNAME_RE.match("user/name") is None class TestServiceRegistry: def test_no_duplicate_names(self): names = [s.name for s in _SERVICES] assert len(names) == len(set(names)) def test_all_have_required_fields(self): for svc in _SERVICES: assert svc.name, "service must have a name" assert svc.url, "service must have a url" assert "{user}" in svc.url, f"{svc.name}: url must contain {{user}}" assert svc.method in ("status", "json", "body"), ( f"{svc.name}: invalid method '{svc.method}'" ) assert svc.category in ("dev", "social", "media", "other"), ( f"{svc.name}: invalid category '{svc.category}'" ) def test_minimum_service_count(self): assert len(_SERVICES) >= 20 def test_lookup_table_matches(self): assert len(_BY_NAME) == len(_SERVICES) def test_categories_cover_all(self): total = sum(len(svcs) for svcs in _BY_CATEGORY.values()) assert total == len(_SERVICES) def test_all_four_categories_present(self): for cat in ("dev", "social", "media", "other"): assert cat in _BY_CATEGORY, f"missing category: {cat}" assert len(_BY_CATEGORY[cat]) > 0 class TestClassifyStatus: def test_found(self): assert classify_status(200) == "found" def test_not_found(self): assert classify_status(404) == "not_found" def test_error_zero(self): assert classify_status(0) == "error" def test_error_redirect(self): assert classify_status(302) == "error" def test_error_server(self): assert classify_status(500) == "error" class TestClassifyJson: def _svc(self, name: str) -> _Service: return _Service(name=name, url="https://example.com/{user}", method="json", category="dev") def test_github_found(self): body = '{"login": "john", "id": 123}' assert classify_json(self._svc("GitHub"), 200, body) == "found" def test_github_not_found(self): assert classify_json(self._svc("GitHub"), 404, "") == "not_found" def test_gitlab_found(self): body = '[{"id": 1, "username": "john"}]' assert classify_json(self._svc("GitLab"), 200, body) == "found" def test_gitlab_not_found(self): assert classify_json(self._svc("GitLab"), 200, "[]") == "not_found" def test_docker_hub_found(self): body = '{"id": "abc123", "username": "john"}' assert classify_json(self._svc("Docker Hub"), 200, body) == "found" def test_docker_hub_not_found(self): assert classify_json(self._svc("Docker Hub"), 404, "") == "not_found" def test_keybase_found(self): body = '{"them": [{"id": "abc"}]}' assert classify_json(self._svc("Keybase"), 200, body) == "found" def test_keybase_not_found(self): body = '{"them": []}' assert classify_json(self._svc("Keybase"), 200, body) == "not_found" def test_devto_found(self): body = '{"username": "john"}' assert classify_json(self._svc("Dev.to"), 200, body) == "found" def test_devto_not_found(self): assert classify_json(self._svc("Dev.to"), 404, "") == "not_found" def test_reddit_found(self): body = '{"kind": "t2", "data": {"name": "john"}}' assert classify_json(self._svc("Reddit"), 200, body) == "found" def test_reddit_not_found(self): body = '{"error": 404}' assert classify_json(self._svc("Reddit"), 200, body) == "not_found" def test_gravatar_found(self): body = '{"entry": [{"id": "123"}]}' assert classify_json(self._svc("Gravatar"), 200, body) == "found" def test_gravatar_not_found(self): assert classify_json(self._svc("Gravatar"), 404, "") == "not_found" def test_error_on_bad_json(self): assert classify_json(self._svc("GitHub"), 200, "not json") == "error" def test_error_on_empty_body(self): assert classify_json(self._svc("GitHub"), 200, "") == "error" def test_error_on_zero_status(self): assert classify_json(self._svc("GitHub"), 0, "") == "error" class TestClassifyBody: def test_telegram_found(self): body = '