Add Linker and Optimizer modules with API integration and frontend components
- Added Linker and Optimizer apps to `INSTALLED_APPS` in `settings.py`. - Configured API endpoints for Linker and Optimizer in `urls.py`. - Implemented `OptimizeContentFunction` for content optimization in the AI module. - Created prompts for content optimization and site structure generation. - Updated `OptimizerService` to utilize the new AI function for content optimization. - Developed frontend components including dashboards and content lists for Linker and Optimizer. - Integrated new routes and sidebar navigation for Linker and Optimizer in the frontend. - Enhanced content management with source and sync status filters in the Writer module. - Comprehensive test coverage added for new features and components.
This commit is contained in:
2
backend/igny8_core/business/billing/tests/__init__.py
Normal file
2
backend/igny8_core/business/billing/tests/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
# Billing tests
|
||||
|
||||
133
backend/igny8_core/business/billing/tests/test_phase4_credits.py
Normal file
133
backend/igny8_core/business/billing/tests/test_phase4_credits.py
Normal file
@@ -0,0 +1,133 @@
|
||||
"""
|
||||
Tests for Phase 4 credit deduction
|
||||
"""
|
||||
from unittest.mock import patch
|
||||
from django.test import TestCase
|
||||
from igny8_core.business.content.models import Content
|
||||
from igny8_core.business.billing.services.credit_service import CreditService
|
||||
from igny8_core.business.billing.constants import CREDIT_COSTS
|
||||
from igny8_core.business.billing.exceptions import InsufficientCreditsError
|
||||
from igny8_core.api.tests.test_integration_base import IntegrationTestBase
|
||||
|
||||
|
||||
class Phase4CreditTests(IntegrationTestBase):
|
||||
"""Tests for Phase 4 credit deduction"""
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
# Set initial credits
|
||||
self.account.credits = 1000
|
||||
self.account.save()
|
||||
|
||||
def test_linking_deducts_correct_credits(self):
|
||||
"""Test that linking deducts correct credits"""
|
||||
cost = CreditService.get_credit_cost('linking')
|
||||
expected_cost = CREDIT_COSTS.get('linking', 0)
|
||||
|
||||
self.assertEqual(cost, expected_cost)
|
||||
self.assertEqual(cost, 8) # From constants
|
||||
|
||||
def test_optimization_deducts_correct_credits(self):
|
||||
"""Test that optimization deducts correct credits based on word count"""
|
||||
word_count = 500
|
||||
cost = CreditService.get_credit_cost('optimization', word_count)
|
||||
|
||||
# Should be 1 credit per 200 words, so 500 words = 3 credits (max(1, 1 * 500/200) = 3)
|
||||
expected = max(1, int(CREDIT_COSTS.get('optimization', 1) * (word_count / 200)))
|
||||
self.assertEqual(cost, expected)
|
||||
|
||||
def test_optimization_credits_per_entry_point(self):
|
||||
"""Test that optimization credits are same regardless of entry point"""
|
||||
word_count = 400
|
||||
|
||||
# All entry points should use same credit calculation
|
||||
cost = CreditService.get_credit_cost('optimization', word_count)
|
||||
|
||||
# 400 words = 2 credits (1 * 400/200)
|
||||
self.assertEqual(cost, 2)
|
||||
|
||||
@patch('igny8_core.business.billing.services.credit_service.CreditService.deduct_credits')
|
||||
def test_pipeline_deducts_credits_at_each_stage(self, mock_deduct):
|
||||
"""Test that pipeline deducts credits at each stage"""
|
||||
from igny8_core.business.content.services.content_pipeline_service import ContentPipelineService
|
||||
from igny8_core.business.linking.services.linker_service import LinkerService
|
||||
from igny8_core.business.optimization.services.optimizer_service import OptimizerService
|
||||
|
||||
content = Content.objects.create(
|
||||
account=self.account,
|
||||
site=self.site,
|
||||
sector=self.sector,
|
||||
title="Test",
|
||||
word_count=400,
|
||||
source='igny8'
|
||||
)
|
||||
|
||||
# Mock the services
|
||||
with patch.object(LinkerService, 'process') as mock_link, \
|
||||
patch.object(OptimizerService, 'optimize_from_writer') as mock_optimize:
|
||||
|
||||
mock_link.return_value = content
|
||||
mock_optimize.return_value = content
|
||||
|
||||
service = ContentPipelineService()
|
||||
service.process_writer_content(content.id)
|
||||
|
||||
# Should deduct credits for both linking and optimization
|
||||
self.assertGreater(mock_deduct.call_count, 0)
|
||||
|
||||
def test_insufficient_credits_blocks_linking(self):
|
||||
"""Test that insufficient credits blocks linking"""
|
||||
self.account.credits = 5 # Less than linking cost (8)
|
||||
self.account.save()
|
||||
|
||||
with self.assertRaises(InsufficientCreditsError):
|
||||
CreditService.check_credits(self.account, 'linking')
|
||||
|
||||
def test_insufficient_credits_blocks_optimization(self):
|
||||
"""Test that insufficient credits blocks optimization"""
|
||||
self.account.credits = 1 # Less than optimization cost for 500 words
|
||||
self.account.save()
|
||||
|
||||
with self.assertRaises(InsufficientCreditsError):
|
||||
CreditService.check_credits(self.account, 'optimization', 500)
|
||||
|
||||
def test_credit_deduction_logged(self):
|
||||
"""Test that credit deduction is logged"""
|
||||
from igny8_core.business.billing.models import CreditUsageLog
|
||||
|
||||
initial_credits = self.account.credits
|
||||
cost = CreditService.get_credit_cost('linking')
|
||||
|
||||
CreditService.deduct_credits_for_operation(
|
||||
account=self.account,
|
||||
operation_type='linking',
|
||||
description="Test linking"
|
||||
)
|
||||
|
||||
self.account.refresh_from_db()
|
||||
self.assertEqual(self.account.credits, initial_credits - cost)
|
||||
|
||||
# Check that usage log was created
|
||||
log = CreditUsageLog.objects.filter(
|
||||
account=self.account,
|
||||
operation_type='linking'
|
||||
).first()
|
||||
self.assertIsNotNone(log)
|
||||
|
||||
def test_batch_operations_deduct_multiple_credits(self):
|
||||
"""Test that batch operations deduct multiple credits"""
|
||||
initial_credits = self.account.credits
|
||||
linking_cost = CreditService.get_credit_cost('linking')
|
||||
|
||||
# Deduct for 3 linking operations
|
||||
for i in range(3):
|
||||
CreditService.deduct_credits_for_operation(
|
||||
account=self.account,
|
||||
operation_type='linking',
|
||||
description=f"Linking {i}"
|
||||
)
|
||||
|
||||
self.account.refresh_from_db()
|
||||
expected_credits = initial_credits - (linking_cost * 3)
|
||||
self.assertEqual(self.account.credits, expected_credits)
|
||||
|
||||
Reference in New Issue
Block a user