summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYuval Adam <_@yuv.al>2025-07-18 20:48:13 +0200
committerYuval Adam <_@yuv.al>2025-07-18 20:48:13 +0200
commit16424507b8b4ecc9a5706da32e6da929e3effa19 (patch)
treef6a9bc22af14c3babb4fc47854ae6bd3722d249f
parent8ed818f331b000cbcd91e3ee5f96098af7b03ff1 (diff)
refactor
-rw-r--r--pyproject.toml2
-rwxr-xr-xregflow/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.py195
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"