260 lines
8.1 KiB
Python
260 lines
8.1 KiB
Python
"""
|
|
Unit tests for site assignment
|
|
"""
|
|
|
|
import pytest
|
|
from unittest.mock import Mock, MagicMock, patch
|
|
from src.generation.site_assignment import assign_sites_to_batch, _get_keyword_sites
|
|
from src.database.models import GeneratedContent, SiteDeployment
|
|
from src.generation.job_config import Job
|
|
|
|
|
|
class TestGetKeywordSites:
|
|
"""Tests for _get_keyword_sites helper"""
|
|
|
|
def test_exact_match(self):
|
|
site1 = Mock(spec=SiteDeployment)
|
|
site1.site_name = "engine-repair-abc"
|
|
|
|
site2 = Mock(spec=SiteDeployment)
|
|
site2.site_name = "car-maintenance-xyz"
|
|
|
|
result = _get_keyword_sites([site1, site2], "engine repair")
|
|
|
|
assert len(result) == 1
|
|
assert result[0] == site1
|
|
|
|
def test_partial_match(self):
|
|
site1 = Mock(spec=SiteDeployment)
|
|
site1.site_name = "my-engine-site"
|
|
|
|
result = _get_keyword_sites([site1], "engine")
|
|
|
|
assert len(result) == 1
|
|
|
|
def test_no_match(self):
|
|
site1 = Mock(spec=SiteDeployment)
|
|
site1.site_name = "random-site-123"
|
|
|
|
result = _get_keyword_sites([site1], "engine repair")
|
|
|
|
assert len(result) == 0
|
|
|
|
|
|
class TestAssignSitesToBatch:
|
|
"""Tests for assign_sites_to_batch function"""
|
|
|
|
def test_assign_with_sufficient_sites(self):
|
|
content1 = Mock(spec=GeneratedContent)
|
|
content1.id = 1
|
|
content1.tier = "tier1"
|
|
content1.keyword = "engine"
|
|
content1.site_deployment_id = None
|
|
|
|
content2 = Mock(spec=GeneratedContent)
|
|
content2.id = 2
|
|
content2.tier = "tier2"
|
|
content2.keyword = "car"
|
|
content2.site_deployment_id = None
|
|
|
|
site1 = Mock(spec=SiteDeployment)
|
|
site1.id = 10
|
|
site1.site_name = "site1"
|
|
site1.custom_hostname = "www.site1.com"
|
|
|
|
site2 = Mock(spec=SiteDeployment)
|
|
site2.id = 20
|
|
site2.site_name = "site2"
|
|
site2.pull_zone_bcdn_hostname = "site2.b-cdn.net"
|
|
|
|
job = Job(
|
|
project_id=1,
|
|
tiers={},
|
|
deployment_targets=None,
|
|
tier1_preferred_sites=None,
|
|
auto_create_sites=False,
|
|
create_sites_for_keywords=None
|
|
)
|
|
|
|
site_repo = Mock()
|
|
site_repo.get_all.return_value = [site1, site2]
|
|
site_repo.session = Mock()
|
|
|
|
bunny_client = Mock()
|
|
|
|
assign_sites_to_batch(
|
|
[content1, content2],
|
|
job,
|
|
site_repo,
|
|
bunny_client,
|
|
"test-project"
|
|
)
|
|
|
|
assert content1.site_deployment_id is not None
|
|
assert content2.site_deployment_id is not None
|
|
assert content1.site_deployment_id != content2.site_deployment_id
|
|
site_repo.session.commit.assert_called_once()
|
|
|
|
def test_assign_tier1_preferred_sites(self):
|
|
content1 = Mock(spec=GeneratedContent)
|
|
content1.id = 1
|
|
content1.tier = "tier1"
|
|
content1.keyword = "test"
|
|
content1.site_deployment_id = None
|
|
|
|
preferred_site = Mock(spec=SiteDeployment)
|
|
preferred_site.id = 10
|
|
preferred_site.site_name = "preferred"
|
|
preferred_site.custom_hostname = "www.preferred.com"
|
|
preferred_site.pull_zone_bcdn_hostname = "preferred.b-cdn.net"
|
|
|
|
other_site = Mock(spec=SiteDeployment)
|
|
other_site.id = 20
|
|
other_site.site_name = "other"
|
|
other_site.custom_hostname = None
|
|
other_site.pull_zone_bcdn_hostname = "other.b-cdn.net"
|
|
|
|
job = Job(
|
|
project_id=1,
|
|
tiers={},
|
|
deployment_targets=None,
|
|
tier1_preferred_sites=["www.preferred.com"],
|
|
auto_create_sites=False,
|
|
create_sites_for_keywords=None
|
|
)
|
|
|
|
site_repo = Mock()
|
|
site_repo.get_all.return_value = [preferred_site, other_site]
|
|
site_repo.get_by_hostname.return_value = preferred_site
|
|
site_repo.get_by_bcdn_hostname.return_value = None
|
|
site_repo.session = Mock()
|
|
|
|
bunny_client = Mock()
|
|
|
|
assign_sites_to_batch([content1], job, site_repo, bunny_client, "test")
|
|
|
|
assert content1.site_deployment_id == 10
|
|
|
|
def test_skip_already_assigned_articles(self):
|
|
content1 = Mock(spec=GeneratedContent)
|
|
content1.id = 1
|
|
content1.tier = "tier1"
|
|
content1.keyword = "test"
|
|
content1.site_deployment_id = 5
|
|
|
|
site_repo = Mock()
|
|
site_repo.get_all.return_value = []
|
|
site_repo.session = Mock()
|
|
|
|
job = Job(
|
|
project_id=1,
|
|
tiers={},
|
|
deployment_targets=None,
|
|
auto_create_sites=False
|
|
)
|
|
|
|
bunny_client = Mock()
|
|
|
|
assign_sites_to_batch([content1], job, site_repo, bunny_client, "test")
|
|
|
|
assert content1.site_deployment_id == 5
|
|
site_repo.session.add.assert_not_called()
|
|
|
|
def test_error_insufficient_sites_without_auto_create(self):
|
|
content1 = Mock(spec=GeneratedContent)
|
|
content1.id = 1
|
|
content1.tier = "tier1"
|
|
content1.keyword = "test"
|
|
content1.site_deployment_id = None
|
|
|
|
job = Job(
|
|
project_id=1,
|
|
tiers={},
|
|
deployment_targets=None,
|
|
auto_create_sites=False,
|
|
create_sites_for_keywords=None
|
|
)
|
|
|
|
site_repo = Mock()
|
|
site_repo.get_all.return_value = []
|
|
site_repo.session = Mock()
|
|
|
|
bunny_client = Mock()
|
|
|
|
with pytest.raises(ValueError, match="Insufficient sites"):
|
|
assign_sites_to_batch([content1], job, site_repo, bunny_client, "test")
|
|
|
|
@patch('src.generation.site_assignment.create_generic_sites')
|
|
def test_auto_create_sites_when_insufficient(self, mock_create):
|
|
content1 = Mock(spec=GeneratedContent)
|
|
content1.id = 1
|
|
content1.tier = "tier1"
|
|
content1.keyword = "test"
|
|
content1.site_deployment_id = None
|
|
|
|
new_site = Mock(spec=SiteDeployment)
|
|
new_site.id = 100
|
|
new_site.site_name = "auto-created"
|
|
new_site.pull_zone_bcdn_hostname = "auto.b-cdn.net"
|
|
|
|
mock_create.return_value = [new_site]
|
|
|
|
job = Job(
|
|
project_id=1,
|
|
tiers={},
|
|
deployment_targets=None,
|
|
auto_create_sites=True,
|
|
create_sites_for_keywords=None
|
|
)
|
|
|
|
site_repo = Mock()
|
|
site_repo.get_all.return_value = []
|
|
site_repo.session = Mock()
|
|
|
|
bunny_client = Mock()
|
|
|
|
assign_sites_to_batch([content1], job, site_repo, bunny_client, "test-project")
|
|
|
|
assert content1.site_deployment_id == 100
|
|
mock_create.assert_called_once_with(
|
|
count=1,
|
|
project_keyword="test-project",
|
|
bunny_client=bunny_client,
|
|
site_repo=site_repo,
|
|
region="DE"
|
|
)
|
|
|
|
@patch('src.generation.site_assignment.provision_keyword_sites')
|
|
def test_create_keyword_sites_before_assignment(self, mock_provision):
|
|
keyword_site = Mock(spec=SiteDeployment)
|
|
keyword_site.id = 50
|
|
keyword_site.site_name = "engine-repair-abc"
|
|
|
|
mock_provision.return_value = [keyword_site]
|
|
|
|
content1 = Mock(spec=GeneratedContent)
|
|
content1.id = 1
|
|
content1.tier = "tier1"
|
|
content1.keyword = "engine"
|
|
content1.site_deployment_id = None
|
|
|
|
job = Job(
|
|
project_id=1,
|
|
tiers={},
|
|
deployment_targets=None,
|
|
auto_create_sites=False,
|
|
create_sites_for_keywords=[{"keyword": "engine repair", "count": 1}]
|
|
)
|
|
|
|
site_repo = Mock()
|
|
site_repo.get_all.return_value = [keyword_site]
|
|
site_repo.session = Mock()
|
|
|
|
bunny_client = Mock()
|
|
|
|
assign_sites_to_batch([content1], job, site_repo, bunny_client, "test")
|
|
|
|
mock_provision.assert_called_once()
|
|
assert content1.site_deployment_id is not None
|
|
|