- Added ContactFormSubmission model to store contact form submissions. - Created ContactForm for handling form submissions. - Implemented admin interface for managing contact form submissions. - Developed views and JavaScript for handling contact form submission via AJAX. - Added SMTP settings model for email configuration. - Created notification email templates for contact form submissions. - Updated frontend to include contact form modal and associated styles. - Added tests for contact form submission and validation.
115 lines
4.1 KiB
Python
115 lines
4.1 KiB
Python
from django.test import TestCase
|
|
from django.urls import reverse
|
|
|
|
from .newsletter import (
|
|
extract_token,
|
|
generate_one_click_token,
|
|
render_placeholders,
|
|
render_newsletter_html,
|
|
verify_one_click_token,
|
|
)
|
|
from .models import ContactFormSubmission
|
|
from .security import decrypt_text, encrypt_text
|
|
|
|
|
|
class NewsletterTemplateTests(TestCase):
|
|
def test_render_placeholders_replaces_known_keys(self):
|
|
template = "confirm={{confirm_url}} email={{email}} token={{token}}"
|
|
rendered = render_placeholders(
|
|
template,
|
|
{
|
|
"confirm_url": "https://example.com/confirm?token=abc",
|
|
"email": "demo@example.com",
|
|
"token": "abc",
|
|
},
|
|
)
|
|
|
|
self.assertEqual(
|
|
rendered,
|
|
"confirm=https://example.com/confirm?token=abc email=demo@example.com token=abc",
|
|
)
|
|
|
|
def test_extract_token_supports_top_level_and_nested_data(self):
|
|
self.assertEqual(extract_token({"token": "t1"}), "t1")
|
|
self.assertEqual(extract_token({"data": {"unsubscribe_token": "t2"}}), "t2")
|
|
self.assertEqual(extract_token({}), "")
|
|
|
|
def test_encrypt_decrypt_roundtrip(self):
|
|
secret = "mailrelay-secret"
|
|
encrypted = encrypt_text(secret)
|
|
self.assertTrue(encrypted.startswith("enc1:"))
|
|
self.assertNotEqual(encrypted, secret)
|
|
self.assertEqual(decrypt_text(encrypted), secret)
|
|
|
|
def test_one_click_token_roundtrip(self):
|
|
token = generate_one_click_token(
|
|
subscriber_id="sub-1",
|
|
list_id="list-1",
|
|
site_id="site-1",
|
|
campaign_id="cmp-1",
|
|
secret="test-secret",
|
|
ttl_seconds=60,
|
|
)
|
|
payload, error = verify_one_click_token(token, "test-secret")
|
|
self.assertIsNone(error)
|
|
self.assertEqual(payload["subscriber_id"], "sub-1")
|
|
self.assertEqual(payload["list_id"], "list-1")
|
|
|
|
def test_one_click_token_invalid_signature(self):
|
|
token = generate_one_click_token(
|
|
subscriber_id="sub-1",
|
|
list_id="list-1",
|
|
site_id="site-1",
|
|
campaign_id="cmp-1",
|
|
secret="test-secret",
|
|
ttl_seconds=60,
|
|
)
|
|
payload, error = verify_one_click_token(token, "other-secret")
|
|
self.assertIsNone(payload)
|
|
self.assertEqual(error, "invalid")
|
|
|
|
def test_render_newsletter_html_absolutizes_relative_links(self):
|
|
rendered = render_newsletter_html(
|
|
'<p><a href="/a">A</a><img src="/media/x.jpg"></p>',
|
|
values={},
|
|
site_base_url="https://news.example.com",
|
|
)
|
|
self.assertIn('href="https://news.example.com/a"', rendered)
|
|
self.assertIn('src="https://news.example.com/media/x.jpg"', rendered)
|
|
|
|
def test_contact_form_submit_saves_submission(self):
|
|
response = self.client.post(
|
|
reverse("contact_form_submit"),
|
|
data={
|
|
"name": "Tester",
|
|
"contact": "tester@example.com",
|
|
"email": "tester@example.com",
|
|
"category": "other",
|
|
"message": "hello",
|
|
"source_page": "/",
|
|
},
|
|
HTTP_X_REQUESTED_WITH="XMLHttpRequest",
|
|
)
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertEqual(ContactFormSubmission.objects.count(), 1)
|
|
submission = ContactFormSubmission.objects.first()
|
|
self.assertEqual(submission.name, "Tester")
|
|
self.assertEqual(submission.email, "tester@example.com")
|
|
self.assertEqual(submission.category, "other")
|
|
|
|
def test_contact_form_submit_rejects_invalid_email(self):
|
|
response = self.client.post(
|
|
reverse("contact_form_submit"),
|
|
data={
|
|
"name": "Tester",
|
|
"contact": "123",
|
|
"email": "not-an-email",
|
|
"category": "other",
|
|
"message": "hello",
|
|
"source_page": "/",
|
|
},
|
|
HTTP_X_REQUESTED_WITH="XMLHttpRequest",
|
|
)
|
|
self.assertEqual(response.status_code, 400)
|
|
self.assertEqual(ContactFormSubmission.objects.count(), 0)
|