mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-22 21:31:09 -05:00
Add OWASP compliance mapping and security test case templates, and document version control implementation phases
This commit is contained in:
268
history_tracking/tests/test_managers.py
Normal file
268
history_tracking/tests/test_managers.py
Normal file
@@ -0,0 +1,268 @@
|
||||
from django.test import TestCase
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import transaction
|
||||
from django.utils import timezone
|
||||
|
||||
from history_tracking.models import VersionBranch, ChangeSet
|
||||
from history_tracking.managers import BranchManager, MergeStrategy
|
||||
from parks.models import Park
|
||||
|
||||
class BranchManagerTests(TestCase):
|
||||
def setUp(self):
|
||||
self.park = Park.objects.create(
|
||||
name='Test Park',
|
||||
slug='test-park',
|
||||
status='OPERATING'
|
||||
)
|
||||
self.content_type = ContentType.objects.get_for_model(Park)
|
||||
self.manager = BranchManager()
|
||||
self.main_branch = VersionBranch.objects.create(
|
||||
name='main',
|
||||
metadata={'type': 'default_branch'}
|
||||
)
|
||||
|
||||
def test_create_branch(self):
|
||||
"""Test branch creation with metadata"""
|
||||
branch = self.manager.create_branch(
|
||||
name='feature/test',
|
||||
metadata={'type': 'feature', 'description': 'Test branch'}
|
||||
)
|
||||
self.assertEqual(branch.name, 'feature/test')
|
||||
self.assertEqual(branch.metadata['type'], 'feature')
|
||||
self.assertTrue(branch.is_active)
|
||||
|
||||
def test_get_active_branches(self):
|
||||
"""Test retrieving only active branches"""
|
||||
# Create some branches
|
||||
feature_branch = self.manager.create_branch(
|
||||
name='feature/active',
|
||||
metadata={'type': 'feature'}
|
||||
)
|
||||
inactive_branch = self.manager.create_branch(
|
||||
name='feature/inactive',
|
||||
metadata={'type': 'feature'}
|
||||
)
|
||||
inactive_branch.is_active = False
|
||||
inactive_branch.save()
|
||||
|
||||
active_branches = self.manager.get_active_branches()
|
||||
self.assertIn(self.main_branch, active_branches)
|
||||
self.assertIn(feature_branch, active_branches)
|
||||
self.assertNotIn(inactive_branch, active_branches)
|
||||
|
||||
def test_get_branch_changes(self):
|
||||
"""Test retrieving changes for a specific branch"""
|
||||
# Create some changes in different branches
|
||||
main_change = ChangeSet.objects.create(
|
||||
branch=self.main_branch,
|
||||
content_type=self.content_type,
|
||||
object_id=self.park.id,
|
||||
data={'name': 'Main Change'},
|
||||
status='applied'
|
||||
)
|
||||
feature_branch = self.manager.create_branch(name='feature/test')
|
||||
feature_change = ChangeSet.objects.create(
|
||||
branch=feature_branch,
|
||||
content_type=self.content_type,
|
||||
object_id=self.park.id,
|
||||
data={'name': 'Feature Change'},
|
||||
status='applied'
|
||||
)
|
||||
|
||||
main_changes = self.manager.get_branch_changes(self.main_branch)
|
||||
feature_changes = self.manager.get_branch_changes(feature_branch)
|
||||
|
||||
self.assertIn(main_change, main_changes)
|
||||
self.assertNotIn(feature_change, main_changes)
|
||||
self.assertIn(feature_change, feature_changes)
|
||||
self.assertNotIn(main_change, feature_changes)
|
||||
|
||||
def test_merge_branches(self):
|
||||
"""Test merging changes between branches"""
|
||||
# Create feature branch with changes
|
||||
feature_branch = self.manager.create_branch(name='feature/test')
|
||||
change = ChangeSet.objects.create(
|
||||
branch=feature_branch,
|
||||
content_type=self.content_type,
|
||||
object_id=self.park.id,
|
||||
data={'name': 'Updated Name'},
|
||||
status='applied'
|
||||
)
|
||||
|
||||
# Merge feature branch into main
|
||||
self.manager.merge_branches(
|
||||
source_branch=feature_branch,
|
||||
target_branch=self.main_branch
|
||||
)
|
||||
|
||||
# Verify changes were copied to main branch
|
||||
main_changes = self.manager.get_branch_changes(self.main_branch)
|
||||
self.assertEqual(main_changes.count(), 1)
|
||||
merged_change = main_changes.first()
|
||||
self.assertEqual(merged_change.data, change.data)
|
||||
|
||||
def test_branch_deletion(self):
|
||||
"""Test branch deletion with cleanup"""
|
||||
feature_branch = self.manager.create_branch(name='feature/delete')
|
||||
ChangeSet.objects.create(
|
||||
branch=feature_branch,
|
||||
content_type=self.content_type,
|
||||
object_id=self.park.id,
|
||||
data={'name': 'Test Change'},
|
||||
status='applied'
|
||||
)
|
||||
|
||||
# Delete the branch
|
||||
self.manager.delete_branch(feature_branch)
|
||||
|
||||
# Verify branch and its changes are gone
|
||||
with self.assertRaises(VersionBranch.DoesNotExist):
|
||||
VersionBranch.objects.get(name='feature/delete')
|
||||
self.assertEqual(
|
||||
ChangeSet.objects.filter(branch=feature_branch).count(),
|
||||
0
|
||||
)
|
||||
|
||||
class MergeStrategyTests(TestCase):
|
||||
def setUp(self):
|
||||
self.park = Park.objects.create(
|
||||
name='Test Park',
|
||||
slug='test-park',
|
||||
status='OPERATING'
|
||||
)
|
||||
self.content_type = ContentType.objects.get_for_model(Park)
|
||||
self.main_branch = VersionBranch.objects.create(
|
||||
name='main',
|
||||
metadata={'type': 'default_branch'}
|
||||
)
|
||||
self.feature_branch = VersionBranch.objects.create(
|
||||
name='feature/test',
|
||||
metadata={'type': 'feature'}
|
||||
)
|
||||
self.merge_strategy = MergeStrategy()
|
||||
|
||||
def test_simple_merge(self):
|
||||
"""Test merging non-conflicting changes"""
|
||||
# Create changes in feature branch
|
||||
feature_changes = [
|
||||
ChangeSet.objects.create(
|
||||
branch=self.feature_branch,
|
||||
content_type=self.content_type,
|
||||
object_id=self.park.id,
|
||||
data={'name': 'New Name'},
|
||||
status='applied',
|
||||
applied_at=timezone.now()
|
||||
),
|
||||
ChangeSet.objects.create(
|
||||
branch=self.feature_branch,
|
||||
content_type=self.content_type,
|
||||
object_id=self.park.id,
|
||||
data={'description': 'New Description'},
|
||||
status='applied',
|
||||
applied_at=timezone.now()
|
||||
)
|
||||
]
|
||||
|
||||
# Perform merge
|
||||
with transaction.atomic():
|
||||
conflicts = self.merge_strategy.merge(
|
||||
source_branch=self.feature_branch,
|
||||
target_branch=self.main_branch
|
||||
)
|
||||
|
||||
self.assertEqual(conflicts, []) # No conflicts expected
|
||||
main_changes = ChangeSet.objects.filter(branch=self.main_branch)
|
||||
self.assertEqual(main_changes.count(), 2)
|
||||
|
||||
def test_conflict_detection(self):
|
||||
"""Test detection of conflicting changes"""
|
||||
# Create conflicting changes
|
||||
ChangeSet.objects.create(
|
||||
branch=self.main_branch,
|
||||
content_type=self.content_type,
|
||||
object_id=self.park.id,
|
||||
data={'name': 'Main Name'},
|
||||
status='applied',
|
||||
applied_at=timezone.now()
|
||||
)
|
||||
ChangeSet.objects.create(
|
||||
branch=self.feature_branch,
|
||||
content_type=self.content_type,
|
||||
object_id=self.park.id,
|
||||
data={'name': 'Feature Name'},
|
||||
status='applied',
|
||||
applied_at=timezone.now()
|
||||
)
|
||||
|
||||
# Attempt merge
|
||||
with transaction.atomic():
|
||||
conflicts = self.merge_strategy.merge(
|
||||
source_branch=self.feature_branch,
|
||||
target_branch=self.main_branch
|
||||
)
|
||||
|
||||
self.assertTrue(conflicts) # Conflicts should be detected
|
||||
conflict = conflicts[0]
|
||||
self.assertEqual(conflict['field'], 'name')
|
||||
self.assertEqual(conflict['target_value'], 'Main Name')
|
||||
self.assertEqual(conflict['source_value'], 'Feature Name')
|
||||
|
||||
def test_merge_ordering(self):
|
||||
"""Test that changes are merged in the correct order"""
|
||||
# Create sequential changes
|
||||
change1 = ChangeSet.objects.create(
|
||||
branch=self.feature_branch,
|
||||
content_type=self.content_type,
|
||||
object_id=self.park.id,
|
||||
data={'name': 'First Change'},
|
||||
status='applied',
|
||||
applied_at=timezone.now()
|
||||
)
|
||||
change2 = ChangeSet.objects.create(
|
||||
branch=self.feature_branch,
|
||||
content_type=self.content_type,
|
||||
object_id=self.park.id,
|
||||
data={'name': 'Second Change'},
|
||||
status='applied',
|
||||
applied_at=timezone.now()
|
||||
)
|
||||
|
||||
# Perform merge
|
||||
with transaction.atomic():
|
||||
self.merge_strategy.merge(
|
||||
source_branch=self.feature_branch,
|
||||
target_branch=self.main_branch
|
||||
)
|
||||
|
||||
# Verify changes were merged in order
|
||||
merged_changes = ChangeSet.objects.filter(
|
||||
branch=self.main_branch
|
||||
).order_by('applied_at')
|
||||
self.assertEqual(
|
||||
merged_changes[0].data['name'],
|
||||
'First Change'
|
||||
)
|
||||
self.assertEqual(
|
||||
merged_changes[1].data['name'],
|
||||
'Second Change'
|
||||
)
|
||||
|
||||
def test_merge_validation(self):
|
||||
"""Test validation of merge operations"""
|
||||
# Test merging inactive branch
|
||||
self.feature_branch.is_active = False
|
||||
self.feature_branch.save()
|
||||
|
||||
with self.assertRaises(ValidationError):
|
||||
self.merge_strategy.merge(
|
||||
source_branch=self.feature_branch,
|
||||
target_branch=self.main_branch
|
||||
)
|
||||
|
||||
# Test merging branch into itself
|
||||
with self.assertRaises(ValidationError):
|
||||
self.merge_strategy.merge(
|
||||
source_branch=self.main_branch,
|
||||
target_branch=self.main_branch
|
||||
)
|
||||
173
history_tracking/tests/test_models.py
Normal file
173
history_tracking/tests/test_models.py
Normal file
@@ -0,0 +1,173 @@
|
||||
from django.test import TestCase
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils import timezone
|
||||
|
||||
from history_tracking.models import VersionBranch, ChangeSet
|
||||
from parks.models import Park
|
||||
|
||||
class VersionBranchTests(TestCase):
|
||||
def setUp(self):
|
||||
self.main_branch = VersionBranch.objects.create(
|
||||
name='main',
|
||||
metadata={'type': 'default_branch'}
|
||||
)
|
||||
self.feature_branch = VersionBranch.objects.create(
|
||||
name='feature/new-layout',
|
||||
metadata={'type': 'feature'}
|
||||
)
|
||||
|
||||
def test_branch_creation(self):
|
||||
"""Test that branch creation works with valid data"""
|
||||
branch = VersionBranch.objects.create(
|
||||
name='test-branch',
|
||||
metadata={'type': 'test'}
|
||||
)
|
||||
self.assertEqual(branch.name, 'test-branch')
|
||||
self.assertEqual(branch.metadata['type'], 'test')
|
||||
self.assertTrue(branch.is_active)
|
||||
self.assertIsNotNone(branch.created_at)
|
||||
|
||||
def test_invalid_branch_name(self):
|
||||
"""Test that branch names are properly validated"""
|
||||
with self.assertRaises(ValidationError):
|
||||
VersionBranch.objects.create(name='', metadata={})
|
||||
|
||||
# Test overly long name
|
||||
with self.assertRaises(ValidationError):
|
||||
VersionBranch.objects.create(
|
||||
name='a' * 256,
|
||||
metadata={}
|
||||
)
|
||||
|
||||
def test_branch_deactivation(self):
|
||||
"""Test that branches can be deactivated"""
|
||||
self.feature_branch.is_active = False
|
||||
self.feature_branch.save()
|
||||
|
||||
branch = VersionBranch.objects.get(name='feature/new-layout')
|
||||
self.assertFalse(branch.is_active)
|
||||
|
||||
def test_branch_metadata(self):
|
||||
"""Test that branch metadata can be updated"""
|
||||
metadata = {
|
||||
'type': 'feature',
|
||||
'description': 'New layout implementation',
|
||||
'owner': 'test-user'
|
||||
}
|
||||
self.feature_branch.metadata = metadata
|
||||
self.feature_branch.save()
|
||||
|
||||
branch = VersionBranch.objects.get(name='feature/new-layout')
|
||||
self.assertEqual(branch.metadata, metadata)
|
||||
|
||||
class ChangeSetTests(TestCase):
|
||||
def setUp(self):
|
||||
self.main_branch = VersionBranch.objects.create(
|
||||
name='main',
|
||||
metadata={'type': 'default_branch'}
|
||||
)
|
||||
self.park = Park.objects.create(
|
||||
name='Test Park',
|
||||
slug='test-park',
|
||||
status='OPERATING'
|
||||
)
|
||||
self.content_type = ContentType.objects.get_for_model(Park)
|
||||
|
||||
def test_changeset_creation(self):
|
||||
"""Test that changeset creation works with valid data"""
|
||||
changeset = ChangeSet.objects.create(
|
||||
branch=self.main_branch,
|
||||
content_type=self.content_type,
|
||||
object_id=self.park.id,
|
||||
data={'name': 'Updated Park Name'},
|
||||
status='pending',
|
||||
description='Update park name'
|
||||
)
|
||||
self.assertEqual(changeset.branch, self.main_branch)
|
||||
self.assertEqual(changeset.content_type, self.content_type)
|
||||
self.assertEqual(changeset.object_id, self.park.id)
|
||||
self.assertEqual(changeset.status, 'pending')
|
||||
|
||||
def test_changeset_status_flow(self):
|
||||
"""Test that changeset status transitions work correctly"""
|
||||
changeset = ChangeSet.objects.create(
|
||||
branch=self.main_branch,
|
||||
content_type=self.content_type,
|
||||
object_id=self.park.id,
|
||||
data={'name': 'Updated Park Name'},
|
||||
status='pending'
|
||||
)
|
||||
|
||||
# Test status transition: pending -> applied
|
||||
changeset.status = 'applied'
|
||||
changeset.applied_at = timezone.now()
|
||||
changeset.save()
|
||||
|
||||
updated_changeset = ChangeSet.objects.get(pk=changeset.pk)
|
||||
self.assertEqual(updated_changeset.status, 'applied')
|
||||
self.assertIsNotNone(updated_changeset.applied_at)
|
||||
|
||||
def test_invalid_changeset_status(self):
|
||||
"""Test that invalid changeset statuses are rejected"""
|
||||
with self.assertRaises(ValidationError):
|
||||
ChangeSet.objects.create(
|
||||
branch=self.main_branch,
|
||||
content_type=self.content_type,
|
||||
object_id=self.park.id,
|
||||
data={'name': 'Updated Park Name'},
|
||||
status='invalid_status'
|
||||
)
|
||||
|
||||
def test_changeset_validation(self):
|
||||
"""Test that changesets require valid branch and content object"""
|
||||
# Test missing branch
|
||||
with self.assertRaises(ValidationError):
|
||||
ChangeSet.objects.create(
|
||||
content_type=self.content_type,
|
||||
object_id=self.park.id,
|
||||
data={'name': 'Updated Park Name'},
|
||||
status='pending'
|
||||
)
|
||||
|
||||
# Test invalid content object
|
||||
with self.assertRaises(ValidationError):
|
||||
ChangeSet.objects.create(
|
||||
branch=self.main_branch,
|
||||
content_type=self.content_type,
|
||||
object_id=99999, # Non-existent object
|
||||
data={'name': 'Updated Park Name'},
|
||||
status='pending'
|
||||
)
|
||||
|
||||
def test_changeset_relationship_cascade(self):
|
||||
"""Test that changesets are deleted when branch is deleted"""
|
||||
changeset = ChangeSet.objects.create(
|
||||
branch=self.main_branch,
|
||||
content_type=self.content_type,
|
||||
object_id=self.park.id,
|
||||
data={'name': 'Updated Park Name'},
|
||||
status='pending'
|
||||
)
|
||||
|
||||
# Delete the branch
|
||||
self.main_branch.delete()
|
||||
|
||||
# Verify changeset was deleted
|
||||
with self.assertRaises(ChangeSet.DoesNotExist):
|
||||
ChangeSet.objects.get(pk=changeset.pk)
|
||||
|
||||
def test_changeset_data_validation(self):
|
||||
"""Test that changeset data must be valid JSON"""
|
||||
changeset = ChangeSet.objects.create(
|
||||
branch=self.main_branch,
|
||||
content_type=self.content_type,
|
||||
object_id=self.park.id,
|
||||
data={'valid': 'json_data'},
|
||||
status='pending'
|
||||
)
|
||||
|
||||
# Test invalid JSON data
|
||||
with self.assertRaises(ValidationError):
|
||||
changeset.data = "invalid_json"
|
||||
changeset.save()
|
||||
223
history_tracking/tests/test_views.py
Normal file
223
history_tracking/tests/test_views.py
Normal file
@@ -0,0 +1,223 @@
|
||||
from django.test import TestCase, Client
|
||||
from django.urls import reverse
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.test import override_settings
|
||||
|
||||
from history_tracking.models import VersionBranch, ChangeSet
|
||||
from parks.models import Park
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
@override_settings(HTMX_ENABLED=True)
|
||||
class VersionControlViewsTests(TestCase):
|
||||
def setUp(self):
|
||||
self.client = Client()
|
||||
self.user = User.objects.create_superuser(
|
||||
username='admin',
|
||||
email='admin@example.com',
|
||||
password='testpass123'
|
||||
)
|
||||
self.client.login(username='admin', password='testpass123')
|
||||
|
||||
self.park = Park.objects.create(
|
||||
name='Test Park',
|
||||
slug='test-park',
|
||||
status='OPERATING'
|
||||
)
|
||||
self.content_type = ContentType.objects.get_for_model(Park)
|
||||
|
||||
self.main_branch = VersionBranch.objects.create(
|
||||
name='main',
|
||||
metadata={'type': 'default_branch'}
|
||||
)
|
||||
self.feature_branch = VersionBranch.objects.create(
|
||||
name='feature/test',
|
||||
metadata={'type': 'feature'}
|
||||
)
|
||||
|
||||
def test_version_control_panel(self):
|
||||
"""Test rendering of version control panel"""
|
||||
response = self.client.get(
|
||||
reverse('version_control_panel'),
|
||||
HTTP_HX_REQUEST='true',
|
||||
HTTP_HX_TARGET='version-control-panel'
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed('history_tracking/includes/version_control_ui.html')
|
||||
self.assertContains(response, 'main') # Should show main branch
|
||||
self.assertContains(response, 'feature/test') # Should show feature branch
|
||||
|
||||
def test_create_branch(self):
|
||||
"""Test branch creation through view"""
|
||||
response = self.client.post(
|
||||
reverse('create_branch'),
|
||||
{
|
||||
'name': 'feature/new',
|
||||
'metadata': '{"type": "feature", "description": "New feature"}'
|
||||
},
|
||||
HTTP_HX_REQUEST='true'
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTrue(
|
||||
VersionBranch.objects.filter(name='feature/new').exists()
|
||||
)
|
||||
self.assertContains(response, 'Branch created successfully')
|
||||
|
||||
def test_switch_branch(self):
|
||||
"""Test switching between branches"""
|
||||
response = self.client.post(
|
||||
reverse('switch_branch'),
|
||||
{'branch_id': self.feature_branch.id},
|
||||
HTTP_HX_REQUEST='true'
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, 'Switched to branch')
|
||||
self.assertContains(response, 'feature/test')
|
||||
|
||||
def test_merge_branch(self):
|
||||
"""Test branch merging through view"""
|
||||
# Create a change in feature branch
|
||||
ChangeSet.objects.create(
|
||||
branch=self.feature_branch,
|
||||
content_type=self.content_type,
|
||||
object_id=self.park.id,
|
||||
data={'name': 'Updated Name'},
|
||||
status='applied'
|
||||
)
|
||||
|
||||
response = self.client.post(
|
||||
reverse('merge_branch'),
|
||||
{
|
||||
'source_branch_id': self.feature_branch.id,
|
||||
'target_branch_id': self.main_branch.id
|
||||
},
|
||||
HTTP_HX_REQUEST='true'
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, 'Branch merged successfully')
|
||||
|
||||
# Verify changes were merged
|
||||
main_changes = ChangeSet.objects.filter(branch=self.main_branch)
|
||||
self.assertEqual(main_changes.count(), 1)
|
||||
|
||||
def test_merge_conflict_handling(self):
|
||||
"""Test handling of merge conflicts"""
|
||||
# Create conflicting changes
|
||||
ChangeSet.objects.create(
|
||||
branch=self.main_branch,
|
||||
content_type=self.content_type,
|
||||
object_id=self.park.id,
|
||||
data={'name': 'Main Name'},
|
||||
status='applied'
|
||||
)
|
||||
ChangeSet.objects.create(
|
||||
branch=self.feature_branch,
|
||||
content_type=self.content_type,
|
||||
object_id=self.park.id,
|
||||
data={'name': 'Feature Name'},
|
||||
status='applied'
|
||||
)
|
||||
|
||||
response = self.client.post(
|
||||
reverse('merge_branch'),
|
||||
{
|
||||
'source_branch_id': self.feature_branch.id,
|
||||
'target_branch_id': self.main_branch.id
|
||||
},
|
||||
HTTP_HX_REQUEST='true'
|
||||
)
|
||||
self.assertEqual(response.status_code, 409) # Conflict status
|
||||
self.assertContains(response, 'Merge conflicts detected')
|
||||
|
||||
def test_view_history(self):
|
||||
"""Test viewing version history"""
|
||||
# Create some changes
|
||||
change = ChangeSet.objects.create(
|
||||
branch=self.main_branch,
|
||||
content_type=self.content_type,
|
||||
object_id=self.park.id,
|
||||
data={'name': 'Updated Name'},
|
||||
status='applied'
|
||||
)
|
||||
|
||||
response = self.client.get(
|
||||
reverse('version_history', kwargs={'pk': self.park.pk}),
|
||||
HTTP_HX_REQUEST='true'
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, 'Updated Name')
|
||||
self.assertContains(response, str(change.created_at))
|
||||
|
||||
def test_branch_deletion(self):
|
||||
"""Test branch deletion through view"""
|
||||
response = self.client.post(
|
||||
reverse('delete_branch'),
|
||||
{'branch_id': self.feature_branch.id},
|
||||
HTTP_HX_REQUEST='true'
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, 'Branch deleted successfully')
|
||||
self.assertFalse(
|
||||
VersionBranch.objects.filter(id=self.feature_branch.id).exists()
|
||||
)
|
||||
|
||||
def test_unauthorized_access(self):
|
||||
"""Test that unauthorized users cannot access version control"""
|
||||
self.client.logout()
|
||||
response = self.client.get(
|
||||
reverse('version_control_panel'),
|
||||
HTTP_HX_REQUEST='true'
|
||||
)
|
||||
self.assertEqual(response.status_code, 302) # Redirect to login
|
||||
|
||||
def test_htmx_requirements(self):
|
||||
"""Test that views require HTMX headers"""
|
||||
# Try without HTMX headers
|
||||
response = self.client.get(reverse('version_control_panel'))
|
||||
self.assertEqual(response.status_code, 400)
|
||||
self.assertContains(
|
||||
response,
|
||||
'This endpoint requires HTMX',
|
||||
status_code=400
|
||||
)
|
||||
|
||||
def test_branch_validation(self):
|
||||
"""Test branch name validation in views"""
|
||||
response = self.client.post(
|
||||
reverse('create_branch'),
|
||||
{
|
||||
'name': 'invalid/branch/name/with/too/many/segments',
|
||||
'metadata': '{}'
|
||||
},
|
||||
HTTP_HX_REQUEST='true'
|
||||
)
|
||||
self.assertEqual(response.status_code, 400)
|
||||
self.assertContains(
|
||||
response,
|
||||
'Invalid branch name',
|
||||
status_code=400
|
||||
)
|
||||
|
||||
def test_branch_list_update(self):
|
||||
"""Test that branch list updates after operations"""
|
||||
response = self.client.get(
|
||||
reverse('branch_list'),
|
||||
HTTP_HX_REQUEST='true'
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, 'main')
|
||||
self.assertContains(response, 'feature/test')
|
||||
|
||||
# Create new branch
|
||||
new_branch = VersionBranch.objects.create(
|
||||
name='feature/new',
|
||||
metadata={'type': 'feature'}
|
||||
)
|
||||
|
||||
# List should update
|
||||
response = self.client.get(
|
||||
reverse('branch_list'),
|
||||
HTTP_HX_REQUEST='true'
|
||||
)
|
||||
self.assertContains(response, 'feature/new')
|
||||
Reference in New Issue
Block a user