39546-vm/core/tests.py
2026-04-11 02:09:51 +00:00

222 lines
8.7 KiB
Python

from django.contrib.auth import get_user_model
from django.core.files.uploadedfile import SimpleUploadedFile
from django.test import TestCase
from django.urls import reverse
from .models import Business, BusinessMembership, Customer, Job, JobMedia, ProofCard, ReviewRequest
User = get_user_model()
class TrustForgeFlowTests(TestCase):
def setUp(self):
self.user = User.objects.create_user(
username='owner@example.com',
email='owner@example.com',
password='StrongPass123!',
)
self.business = Business.objects.create(
name='Forge Roofing',
slug='forge-roofing',
industry='Roofing',
primary_city='Austin',
primary_state='TX',
google_review_url='https://example.com/google-review',
)
self.membership = BusinessMembership.objects.create(
user=self.user,
business=self.business,
role=BusinessMembership.Role.OWNER,
)
self.customer = Customer.objects.create(
business=self.business,
full_name='Jordan Lee',
email='jordan@example.com',
city='Austin',
state='TX',
)
self.job = Job.objects.create(
business=self.business,
customer=self.customer,
service_type='Roof repair',
city='Austin',
state='TX',
)
JobMedia.objects.create(
job=self.job,
media_type=JobMedia.MediaType.BEFORE,
file=SimpleUploadedFile('before-sample.jpg', b'before-image-bytes', content_type='image/jpeg'),
)
JobMedia.objects.create(
job=self.job,
media_type=JobMedia.MediaType.AFTER,
file=SimpleUploadedFile('after-sample.jpg', b'after-image-bytes', content_type='image/jpeg'),
)
self.proof_card = ProofCard.objects.create(job=self.job, customer_display_name='Verified homeowner')
self.review_request = ReviewRequest.objects.create(job=self.job)
def test_home_loads(self):
response = self.client.get(reverse('home'))
self.assertEqual(response.status_code, 200)
self.assertContains(response, 'TrustForge')
def test_dashboard_requires_login(self):
response = self.client.get(reverse('dashboard'))
self.assertEqual(response.status_code, 302)
self.assertIn(reverse('login'), response.url)
def test_login_with_email_redirects_to_dashboard(self):
response = self.client.post(
reverse('login'),
{'username': 'owner@example.com', 'password': 'StrongPass123!'},
)
self.assertRedirects(response, reverse('dashboard'))
def test_logged_in_user_without_membership_redirects_to_onboarding(self):
user = User.objects.create_user(
username='solo@example.com',
email='solo@example.com',
password='StrongPass123!',
)
self.client.force_login(user)
response = self.client.get(reverse('dashboard'))
self.assertRedirects(response, reverse('business_onboarding'))
def test_dashboard_only_shows_active_business_data(self):
other_business = Business.objects.create(
name='Hidden Plumbing',
slug='hidden-plumbing',
industry='Plumbing',
primary_city='Dallas',
primary_state='TX',
)
other_customer = Customer.objects.create(
business=other_business,
full_name='Taylor Shade',
city='Dallas',
state='TX',
)
Job.objects.create(
business=other_business,
customer=other_customer,
service_type='Leak repair',
city='Dallas',
state='TX',
)
self.client.force_login(self.user)
response = self.client.get(reverse('dashboard'))
self.assertEqual(response.status_code, 200)
self.assertContains(response, 'Forge Roofing proof momentum')
self.assertNotContains(response, 'Leak repair')
def test_technician_cannot_edit_proof_card(self):
technician = User.objects.create_user(
username='tech@example.com',
email='tech@example.com',
password='StrongPass123!',
)
BusinessMembership.objects.create(
user=technician,
business=self.business,
role=BusinessMembership.Role.TECHNICIAN,
)
self.client.force_login(technician)
response = self.client.get(reverse('proof_card_edit', args=[self.proof_card.id]))
self.assertEqual(response.status_code, 403)
def test_public_review_positive_feedback_publishes_proof(self):
response = self.client.post(
reverse('review_request', args=[self.review_request.token]),
{'experience': 'great', 'testimonial': 'They showed up on time and the roof looks incredible.'},
)
self.assertEqual(response.status_code, 200)
self.proof_card.refresh_from_db()
self.assertEqual(self.proof_card.status, 'published')
self.assertEqual(self.proof_card.rating, 5)
def test_public_gallery_only_shows_published_cards_for_requested_business(self):
self.proof_card.status = ProofCard.Status.PUBLISHED
self.proof_card.is_featured = True
self.proof_card.testimonial_quote = 'Published proof for Forge Roofing.'
self.proof_card.save(update_fields=['status', 'is_featured', 'testimonial_quote'])
other_business = Business.objects.create(
name='Quiet Electric',
slug='quiet-electric',
industry='Electrical',
primary_city='Denver',
primary_state='CO',
)
other_customer = Customer.objects.create(
business=other_business,
full_name='Morgan Bright',
city='Denver',
state='CO',
)
other_job = Job.objects.create(
business=other_business,
customer=other_customer,
service_type='Panel upgrade',
city='Denver',
state='CO',
)
ProofCard.objects.create(
job=other_job,
customer_display_name='Verified homeowner',
status=ProofCard.Status.PUBLISHED,
testimonial_quote='This should not appear in Forge Roofing gallery.',
)
draft_customer = Customer.objects.create(
business=self.business,
full_name='Casey Draft',
city='Austin',
state='TX',
)
draft_job = Job.objects.create(
business=self.business,
customer=draft_customer,
service_type='Draft-only repair',
city='Austin',
state='TX',
)
ProofCard.objects.create(
job=draft_job,
customer_display_name='Hidden draft',
status=ProofCard.Status.DRAFT,
testimonial_quote='Draft cards should stay private.',
)
response = self.client.get(reverse('public_proof_gallery', args=[self.business.slug]))
self.assertEqual(response.status_code, 200)
self.assertContains(response, 'Forge Roofing completed work')
self.assertContains(response, 'Published proof for Forge Roofing.')
self.assertContains(response, self.job.before_media.file.url)
self.assertContains(response, self.job.after_media.file.url)
self.assertNotContains(response, 'This should not appear in Forge Roofing gallery.')
self.assertNotContains(response, 'Draft cards should stay private.')
def test_workspace_proof_detail_renders_uploaded_media(self):
self.client.force_login(self.user)
response = self.client.get(reverse('proof_card_detail', args=[self.proof_card.id]))
self.assertEqual(response.status_code, 200)
self.assertContains(response, self.job.before_media.file.url)
self.assertContains(response, self.job.after_media.file.url)
def test_public_proof_detail_requires_published_status(self):
response = self.client.get(reverse('public_proof_detail', args=[self.business.slug, self.proof_card.id]))
self.assertEqual(response.status_code, 404)
self.proof_card.status = ProofCard.Status.PUBLISHED
self.proof_card.testimonial_quote = 'Proof card is now public.'
self.proof_card.save(update_fields=['status', 'testimonial_quote'])
response = self.client.get(reverse('public_proof_detail', args=[self.business.slug, self.proof_card.id]))
self.assertEqual(response.status_code, 200)
self.assertContains(response, 'Proof card is now public.')
self.assertContains(response, self.job.before_media.file.url)
self.assertContains(response, self.job.after_media.file.url)