diff options
| author | Yuval Adam <_@yuv.al> | 2025-07-18 20:48:13 +0200 |
|---|---|---|
| committer | Yuval Adam <_@yuv.al> | 2025-07-18 20:48:13 +0200 |
| commit | 16424507b8b4ecc9a5706da32e6da929e3effa19 (patch) | |
| tree | f6a9bc22af14c3babb4fc47854ae6bd3722d249f | |
| parent | 8ed818f331b000cbcd91e3ee5f96098af7b03ff1 (diff) | |
refactor
| -rw-r--r-- | pyproject.toml | 2 | ||||
| -rwxr-xr-x | regflow/domains.py (renamed from regflow/domain_manager.py) | 14 | ||||
| -rw-r--r-- | regflow/providers/cloudflare.py (renamed from regflow/providers/cloudflare_api.py) | 0 | ||||
| -rw-r--r-- | regflow/providers/namecheap.py (renamed from regflow/providers/namecheap_api.py) | 23 | ||||
| -rw-r--r-- | regflow/tests/test_integration.py | 195 |
5 files changed, 216 insertions, 18 deletions
diff --git a/pyproject.toml b/pyproject.toml index ec332f1..3fde396 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,7 +20,7 @@ dev = [ ] [project.scripts] -regflow = "regflow.domain_manager:main" +regflow = "regflow.domains:main" [tool.hatch.build.targets.wheel] packages = ["regflow"]
\ No newline at end of file diff --git a/regflow/domain_manager.py b/regflow/domains.py index 8905a0a..1e86780 100755 --- a/regflow/domain_manager.py +++ b/regflow/domains.py @@ -3,8 +3,8 @@ import sys from typing import Dict, Any, Optional from .config import Config -from .providers.namecheap_api import NamecheapAPI -from .providers.cloudflare_api import CloudflareAPI +from .providers.namecheap import NamecheapAPI +from .providers.cloudflare import CloudflareAPI class DomainManager: @@ -54,7 +54,7 @@ class DomainManager: # Check if nameservers match cf_ns = set(status["nameservers"]["cloudflare"]) nc_ns = set(nc_nameservers) - + # Only consider nameservers matching if we have both sets and they match if len(cf_ns) > 0 and len(nc_ns) > 0: status["nameservers_match"] = cf_ns == nc_ns @@ -108,9 +108,13 @@ class DomainManager: if len(nc_ns) == 0 and len(cf_ns) == 0: print("⚠ Cannot retrieve nameservers from either service") elif len(nc_ns) == 0: - print("⚠ Cannot retrieve Namecheap nameservers - unable to verify configuration") + print( + "⚠ Cannot retrieve Namecheap nameservers - unable to verify configuration" + ) elif len(cf_ns) == 0: - print("⚠ Cannot retrieve Cloudflare nameservers - unable to verify configuration") + print( + "⚠ Cannot retrieve Cloudflare nameservers - unable to verify configuration" + ) elif status["nameservers_match"]: print("✓ Nameservers are properly configured") else: diff --git a/regflow/providers/cloudflare_api.py b/regflow/providers/cloudflare.py index edc17a7..edc17a7 100644 --- a/regflow/providers/cloudflare_api.py +++ b/regflow/providers/cloudflare.py diff --git a/regflow/providers/namecheap_api.py b/regflow/providers/namecheap.py index 20cdfa9..f91acc6 100644 --- a/regflow/providers/namecheap_api.py +++ b/regflow/providers/namecheap.py @@ -167,15 +167,15 @@ class NamecheapAPI: try: # Get list of all domains in the account root = self._make_request("namecheap.domains.getList", {}) - + ns = {"ns": "http://api.namecheap.com/xml.response"} - + # Look for the domain in the list for domain_elem in root.findall(".//ns:Domain", ns): domain_name = domain_elem.get("Name") if domain_name and domain_name.lower() == domain.lower(): return True - + return False except Exception: # If API call fails, assume not registered @@ -188,13 +188,13 @@ class NamecheapAPI: # Use getInfo to get domain details including nameservers root = self._make_request("namecheap.domains.getInfo", params) - + ns = {"ns": "http://api.namecheap.com/xml.response"} nameservers = [] # Look for nameservers in the domain info response # The structure might be different, let's check multiple possible locations - + # Try to find nameservers in DnsDetails dns_details = root.find(".//ns:DnsDetails", ns) if dns_details is not None: @@ -202,14 +202,14 @@ class NamecheapAPI: for ns_elem in dns_details.findall(".//ns:Nameserver", ns): if ns_elem.text: nameservers.append(ns_elem.text) - + # If no nameservers found in DnsDetails, try other locations if not nameservers: # Try to find in different structure for ns_elem in root.findall(".//ns:Nameserver", ns): if ns_elem.text: nameservers.append(ns_elem.text) - + # If still no nameservers, check for attributes in the domain result if not nameservers: domain_result = root.find(".//ns:DomainGetInfoResult", ns) @@ -219,20 +219,23 @@ class NamecheapAPI: ns_attr = domain_result.get(f"Nameserver{i}") if ns_attr: nameservers.append(ns_attr) - + # Also check for DNS details in attributes dns_type = domain_result.get("DnsProviderType") if dns_type == "CUSTOM": # For custom DNS, nameservers should be in the response # Try looking for nameservers in different attribute names for attr_name in domain_result.attrib: - if "nameserver" in attr_name.lower() or "ns" in attr_name.lower(): + if ( + "nameserver" in attr_name.lower() + or "ns" in attr_name.lower() + ): ns_value = domain_result.get(attr_name) if ns_value and ns_value not in nameservers: nameservers.append(ns_value) return nameservers - except Exception as e: + except Exception: # For debugging, you might want to print the exception # print(f"Error getting nameservers for {domain}: {e}") return [] diff --git a/regflow/tests/test_integration.py b/regflow/tests/test_integration.py index 4b44471..8c63445 100644 --- a/regflow/tests/test_integration.py +++ b/regflow/tests/test_integration.py @@ -1,7 +1,8 @@ import pytest from ..config import Config -from ..providers.namecheap_api import NamecheapAPI -from ..providers.cloudflare_api import CloudflareAPI +from ..providers.namecheap import NamecheapAPI +from ..providers.cloudflare import CloudflareAPI +from ..domains import DomainManager @pytest.fixture @@ -22,6 +23,12 @@ def cloudflare_api(config): return CloudflareAPI(config) +@pytest.fixture +def domain_manager(config): + """Create DomainManager instance""" + return DomainManager(config) + + def test_namecheap_credentials_loaded(config): """Test that Namecheap credentials are loaded""" assert config.namecheap_api_key, "Namecheap API key not found" @@ -127,3 +134,187 @@ def test_cloudflare_dns_records(cloudflare_api): assert "type" in record, "Record should have 'type' field" assert "name" in record, "Record should have 'name' field" assert "content" in record, "Record should have 'content' field" + + +# New tests for domain registration and nameserver functionality + + +def test_namecheap_domain_registration_check_existing(namecheap_api): + """Test domain registration check for existing domain""" + # Test with stackvital.com which we know exists + is_registered = namecheap_api.is_domain_registered("stackvital.com") + assert is_registered, "stackvital.com should be registered" + + +def test_namecheap_domain_registration_check_nonexistent(namecheap_api): + """Test domain registration check for non-existent domain""" + # Test with a domain that definitely doesn't exist in the account + is_registered = namecheap_api.is_domain_registered("nonexistent-domain-12345.com") + assert not is_registered, "Non-existent domain should not be registered" + + +def test_namecheap_get_nameservers_existing_domain(namecheap_api): + """Test nameserver retrieval for existing domain""" + nameservers = namecheap_api.get_domain_nameservers("stackvital.com") + + assert isinstance(nameservers, list), "Nameservers should be a list" + assert len(nameservers) > 0, "Should have at least one nameserver" + + # Check that all nameservers are strings + for ns in nameservers: + assert isinstance(ns, str), "Each nameserver should be a string" + assert "." in ns, "Nameserver should be a valid domain name" + + +def test_namecheap_get_nameservers_nonexistent_domain(namecheap_api): + """Test nameserver retrieval for non-existent domain""" + nameservers = namecheap_api.get_domain_nameservers("nonexistent-domain-12345.com") + + # Should return empty list for non-existent domain + assert isinstance(nameservers, list), ( + "Should return a list even for non-existent domain" + ) + assert len(nameservers) == 0, "Should return empty list for non-existent domain" + + +def test_cloudflare_zone_exists_check(cloudflare_api): + """Test Cloudflare zone existence check""" + # Test with stackvital.com which should exist in Cloudflare + zone_exists = cloudflare_api.zone_exists("stackvital.com") + assert zone_exists, "stackvital.com should exist in Cloudflare" + + # Test with a domain that doesn't exist + zone_exists = cloudflare_api.zone_exists("nonexistent-domain-12345.com") + assert not zone_exists, "Non-existent domain should not exist in Cloudflare" + + +def test_domain_manager_get_status_existing_domain(domain_manager): + """Test domain status retrieval for existing domain""" + status = domain_manager.get_domain_status("stackvital.com") + + # Verify status structure + assert "domain" in status, "Status should contain domain field" + assert "registered" in status, "Status should contain registered field" + assert "cloudflare_zone" in status, "Status should contain cloudflare_zone field" + assert "nameservers" in status, "Status should contain nameservers field" + assert "nameservers_match" in status, ( + "Status should contain nameservers_match field" + ) + + # Verify domain name + assert status["domain"] == "stackvital.com", "Domain name should match" + + # Verify registration status + assert status["registered"], "stackvital.com should be registered" + + # Verify Cloudflare zone exists + assert status["cloudflare_zone"] is not None, "Cloudflare zone should exist" + assert "id" in status["cloudflare_zone"], "Zone should have ID" + assert "name" in status["cloudflare_zone"], "Zone should have name" + assert "status" in status["cloudflare_zone"], "Zone should have status" + + # Verify nameservers structure + assert "namecheap" in status["nameservers"], "Should have namecheap nameservers" + assert "cloudflare" in status["nameservers"], "Should have cloudflare nameservers" + assert isinstance(status["nameservers"]["namecheap"], list), ( + "Namecheap nameservers should be a list" + ) + assert isinstance(status["nameservers"]["cloudflare"], list), ( + "Cloudflare nameservers should be a list" + ) + + # Verify nameservers are populated + assert len(status["nameservers"]["namecheap"]) > 0, ( + "Should have Namecheap nameservers" + ) + assert len(status["nameservers"]["cloudflare"]) > 0, ( + "Should have Cloudflare nameservers" + ) + + +def test_domain_manager_get_status_nonexistent_domain(domain_manager): + """Test domain status retrieval for non-existent domain""" + status = domain_manager.get_domain_status("nonexistent-domain-12345.com") + + # Verify status structure + assert "domain" in status, "Status should contain domain field" + assert "registered" in status, "Status should contain registered field" + assert "cloudflare_zone" in status, "Status should contain cloudflare_zone field" + assert "nameservers" in status, "Status should contain nameservers field" + assert "nameservers_match" in status, ( + "Status should contain nameservers_match field" + ) + + # Verify domain name + assert status["domain"] == "nonexistent-domain-12345.com", ( + "Domain name should match" + ) + + # Verify registration status + assert not status["registered"], "Non-existent domain should not be registered" + + # Verify Cloudflare zone doesn't exist + assert status["cloudflare_zone"] is None, "Cloudflare zone should not exist" + + # Verify nameservers are empty + assert len(status["nameservers"]["namecheap"]) == 0, ( + "Should have no Namecheap nameservers" + ) + assert len(status["nameservers"]["cloudflare"]) == 0, ( + "Should have no Cloudflare nameservers" + ) + + # Verify nameservers don't match + assert not status["nameservers_match"], ( + "Nameservers should not match for non-existent domain" + ) + + +def test_nameserver_matching_logic(domain_manager): + """Test nameserver matching logic with stackvital.com""" + status = domain_manager.get_domain_status("stackvital.com") + + # Get the nameservers + nc_nameservers = status["nameservers"]["namecheap"] + cf_nameservers = status["nameservers"]["cloudflare"] + + # Both should have nameservers + assert len(nc_nameservers) > 0, "Should have Namecheap nameservers" + assert len(cf_nameservers) > 0, "Should have Cloudflare nameservers" + + # Check if they match (they should for stackvital.com) + nc_set = set(nc_nameservers) + cf_set = set(cf_nameservers) + + # The nameservers should match + assert nc_set == cf_set, "Nameservers should match for properly configured domain" + assert status["nameservers_match"], "Status should indicate nameservers match" + + +def test_domain_manager_print_status_no_errors(domain_manager, capsys): + """Test that print_domain_status runs without errors""" + # This should not raise any exceptions + domain_manager.print_domain_status("stackvital.com") + + # Verify some output was produced + captured = capsys.readouterr() + assert "Domain Status: stackvital.com" in captured.out, ( + "Should print domain status header" + ) + assert "registered" in captured.out.lower(), "Should mention registration status" + assert "nameservers" in captured.out.lower(), "Should mention nameservers" + + +def test_setup_domain_dry_run_existing_domain(domain_manager): + """Test setup_domain with dry run for existing domain""" + result = domain_manager.setup_domain( + "stackvital.com", dry_run=True, force_registration=False + ) + + # Should succeed since domain is already registered + assert "success" in result, "Result should contain success field" + assert result.get("success"), "Should succeed for existing domain" + assert "errors" in result, "Result should contain errors field" + assert len(result["errors"]) == 0, "Should have no errors" + assert "steps_completed" in result, "Result should contain steps_completed field" + assert len(result["steps_completed"]) > 0, "Should have completed some steps" |
