dynamicweb/datacenterlight/test_views.py
2026-10-04 12:26:48 +01:00

591 lines
16 KiB
Python

# datacenterlight/tests/test_views.py
import json
from unittest.mock import patch
from django.contrib.messages import get_messages
from django.contrib.sessions.middleware import SessionMiddleware
from django.contrib.auth.models import AnonymousUser
from django.core.exceptions import ValidationError
from django.test import RequestFactory, TestCase
from django.urls import reverse
from datacenterlight.forms import ContactForm
from datacenterlight.views import (
ContactUsView,
IndexView,
OrderConfirmationView,
PaymentOrderView,
WhyDataCenterLightView,
create_incomplete_intent_request,
get_error_response_dict,
show_error,
)
from utils.forms import BillingAddressFormSignup
from factories import CMSIntegrationFactory
class SessionRequestMixin:
"""
Adds a real Django session to RequestFactory requests.
"""
def add_session(self, request):
middleware = SessionMiddleware(lambda request: None)
middleware.process_request(request)
request.session.save()
return request
class ContactUsViewTests(TestCase, SessionRequestMixin):
def setUp(self):
self.factory = RequestFactory()
def test_get_redirects_to_index(self):
response = self.client.get(
reverse("datacenterlight:contact_us")
)
self.assertRedirects(
response,
reverse("datacenterlight:index"),
fetch_redirect_response=False,
)
def test_form_valid_renders_index_template(self):
request = self.factory.post(
reverse("datacenterlight:contact_us")
)
view = ContactUsView()
view.setup(request)
form = ContactForm()
response = view.form_valid(form)
self.assertEqual(response.status_code, 200)
self.assertContains(response, "Thank you")
def test_form_invalid_renders_index_template(self):
request = self.factory.post(
reverse("datacenterlight:contact_us")
)
view = ContactUsView()
view.setup(request)
# Bind the form with invalid/missing data.
form = ContactForm(data={})
self.assertFalse(form.is_valid())
response = view.form_invalid(form)
self.assertEqual(response.status_code, 200)
self.assertContains(response, "index")
class IndexViewTests(TestCase, SessionRequestMixin):
def setUp(self):
self.factory = RequestFactory()
def test_get_redirects_to_cms_index(self):
response = self.client.get(
reverse("datacenterlight:whydatacenterlight")
)
self.assertRedirects(
response,
reverse("datacenterlight:cms_index"),
fetch_redirect_response=False,
)
def test_index_t_redirect_chain(self):
response = self.client.get(
reverse("datacenterlight:index_t"),
follow=True,
)
self.assertEqual(response.status_code, 200)
self.assertEqual(
response.redirect_chain[0][0],
reverse("datacenterlight:cms_index"),
)
def test_index_g_uses_index_view(self):
response = self.client.get(
reverse("datacenterlight:index_g"),
follow=True,
)
self.assertEqual(response.status_code, 200)
self.assertEqual(
response.redirect_chain[0][0],
reverse("datacenterlight:cms_index"),
)
def test_index_f_uses_index_view(self):
response = self.client.get(
reverse("datacenterlight:index_f"),
follow=True,
)
self.assertEqual(response.status_code, 200)
self.assertEqual(
response.redirect_chain[0][0],
reverse("datacenterlight:cms_index"),
)
def test_index_l_uses_index_view(self):
response = self.client.get(
reverse("datacenterlight:index_l"),
follow=True,
)
self.assertEqual(response.status_code, 200)
self.assertEqual(
response.redirect_chain[0][0],
reverse("datacenterlight:cms_index"),
)
def test_cms_index_redirects_to_cms(self):
response = self.client.get(
reverse("datacenterlight:cms_index"),
follow=True,
)
def test_get_success_url(self):
request = self.factory.get(
reverse("datacenterlight:index")
)
view = IndexView()
view.setup(request)
self.assertEqual(
view.get_success_url(),
reverse("datacenterlight:index") + "#requestform",
)
def test_get_context_data_contains_base_url(self):
request = self.factory.get(
reverse("datacenterlight:index")
)
view = IndexView()
view.setup(request)
with patch(
"datacenterlight.views.CreateView.get_context_data",
return_value={},
):
context = view.get_context_data()
self.assertIn("base_url", context)
self.assertIn("contact_form", context)
self.assertIs(context["contact_form"], ContactForm)
self.assertEqual(
context["base_url"],
f"{request.scheme}://{request.get_host()}",
)
# ------------------------------------------------------------------
# validate_cores
# ------------------------------------------------------------------
def test_validate_cores_accepts_one(self):
request = self.factory.post("/")
view = IndexView()
view.setup(request)
self.assertIsNone(view.validate_cores(1))
def test_validate_cores_accepts_48(self):
request = self.factory.post("/")
view = IndexView()
view.setup(request)
self.assertIsNone(view.validate_cores(48))
def test_validate_cores_rejects_zero(self):
request = self.factory.post("/")
view = IndexView()
view.setup(request)
with self.assertRaises(ValidationError):
view.validate_cores(0)
def test_validate_cores_rejects_more_than_48(self):
request = self.factory.post("/")
view = IndexView()
view.setup(request)
with self.assertRaises(ValidationError):
view.validate_cores(49)
def test_validate_cores_rejects_negative_number(self):
request = self.factory.post("/")
view = IndexView()
view.setup(request)
with self.assertRaises(ValidationError):
view.validate_cores(-1)
# ------------------------------------------------------------------
# validate_memory
# ------------------------------------------------------------------
def test_validate_memory_requires_pid(self):
request = self.factory.post(
"/",
{
"ram": "1",
},
)
view = IndexView()
view.setup(request)
with self.assertRaises(ValidationError):
view.validate_memory(1)
def test_validate_memory_rejects_unknown_plugin(self):
request = self.factory.post(
"/",
{
"pid": "999999999",
},
)
view = IndexView()
view.setup(request)
with self.assertRaises(ValidationError):
view.validate_memory(1)
# ------------------------------------------------------------------
# validate_storage
# ------------------------------------------------------------------
def test_validate_storage_accepts_10(self):
request = self.factory.post("/")
view = IndexView()
view.setup(request)
self.assertIsNone(view.validate_storage(10))
def test_validate_storage_accepts_2000(self):
request = self.factory.post("/")
view = IndexView()
view.setup(request)
self.assertIsNone(view.validate_storage(2000))
def test_validate_storage_rejects_below_10(self):
request = self.factory.post("/")
view = IndexView()
view.setup(request)
with self.assertRaises(ValidationError):
view.validate_storage(9)
def test_validate_storage_rejects_above_2000(self):
request = self.factory.post("/")
view = IndexView()
view.setup(request)
with self.assertRaises(ValidationError):
view.validate_storage(2001)
# ------------------------------------------------------------------
# POST without a valid pricing name
# ------------------------------------------------------------------
def test_post_with_unknown_pricing_name_redirects_to_referer(self):
response = self.client.post(
reverse("datacenterlight:index"),
{
"cpu": "2",
"ram": "4",
"storage": "20",
"config": "1",
"pricing_name": "definitely-does-not-exist",
},
HTTP_REFERER="/some-page/",
)
self.assertEqual(response.status_code, 302)
self.assertEqual(
response["Location"],
"/some-page/#order_form",
)
messages = list(
get_messages(response.wsgi_request)
)
self.assertTrue(messages)
self.assertIn(
"Incorrect pricing name",
str(messages[0]),
)
class WhyDataCenterLightViewTests(TestCase):
def test_template_name(self):
view = WhyDataCenterLightView()
self.assertEqual(
view.template_name,
"datacenterlight/whydatacenterlight.html",
)
def test_get_redirects_to_cms_index(self):
response = self.client.get(
reverse("datacenterlight:whydatacenterlight")
)
self.assertRedirects(
response,
reverse("datacenterlight:cms_index"),
fetch_redirect_response=False,
)
class PaymentOrderViewTests(TestCase, SessionRequestMixin):
def setUp(self):
self.factory = RequestFactory()
CMSIntegrationFactory.create(name="default", domain=None)
def set_payment_session(self, **extra):
session = self.client.session
session["vat_validation_status"] = "not_needed"
session["card_id"] = None
session["token"] = None
session["id_payment_method"] = None
session.update(extra)
session.save()
def test_product_lookup_with_unknown_product_returns_empty_json(self):
self.set_payment_session()
response = self.client.post(
reverse("datacenterlight:payment"),
{
"product": "1",
"generic_payment_form-product_name": "999999999",
},
)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.json(), {})
def test_get_form_class_for_anonymous_user(self):
request = self.factory.get(
reverse("datacenterlight:payment")
)
request.user = AnonymousUser()
view = PaymentOrderView()
view.setup(request)
form_class = view.get_form_class()
self.assertIsNotNone(form_class)
self.assertIs(form_class, BillingAddressFormSignup)
def test_generic_payment_page_renders(self):
self.set_payment_session()
response = self.client.get(
reverse("datacenterlight:payment"),
{
"type": "generic",
},
)
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(
response,
"datacenterlight/landing_payment.html",
)
class OrderConfirmationViewTests(TestCase, SessionRequestMixin):
def setUp(self):
self.factory = RequestFactory()
CMSIntegrationFactory.create(name="default", domain=None)
def test_get_without_payment_data_redirects_to_index(self):
response = self.client.get(
reverse("datacenterlight:order_confirmation")
)
self.assertRedirects(
response,
reverse("datacenterlight:index"),
fetch_redirect_response=False,
)
def test_post_without_payment_method_returns_error(self):
response = self.client.post(
reverse("datacenterlight:order_confirmation")
)
self.assertEqual(response.status_code, 200)
data = response.json()
self.assertIn("status", data)
self.assertFalse(data["status"])
def test_order_confirmation_url_exists(self):
response = self.client.get(
reverse("datacenterlight:order_confirmation")
)
self.assertIn(
response.status_code,
(200, 302, 404),
)
@patch(
"datacenterlight.views.StripeUtils."
"get_cards_details_from_payment_method"
)
def test_generic_recurring_payment_renders_confirmation(
self,
mock_get_card_details,
):
mock_get_card_details.return_value = {
"response_object": {
"brand": "visa",
"last4": "4242",
"exp_month": 12,
"exp_year": 2030,
}
}
session = self.client.session
session["generic_payment_type"] = "generic"
session["generic_payment_details"] = {
"amount": 100,
"amount_before_vat": 100,
"vat_rate": 0,
"vat_amount": 0,
"product_name": "Test Product",
"product_id": 1,
"product_slug": "test-product",
"recurring": True,
"description": "Test product",
"recurring_interval": "month",
"exclude_vat_calculations": False,
}
session["id_payment_method"] = "pm_test"
session["customer"] = "cus_test"
session["vat_validation_status"] = "not_needed"
session.save()
response = self.client.get(
reverse("datacenterlight:order_confirmation")
)
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(
response,
"datacenterlight/order_detail.html",
)
self.assertIn(
"generic_payment_details",
response.context,
)
mock_get_card_details.assert_called_once_with(
"pm_test"
)
class HelperFunctionTests(TestCase, SessionRequestMixin):
def setUp(self):
self.factory = RequestFactory()
def test_create_incomplete_intent_request(self):
request = self.factory.post(
"/payment/",
{
"amount": "100",
},
)
self.add_session(request)
request.session["specs"] = {
"cpu": 2,
"ram": 4,
"storage": 20,
}
request.session["template"] = {
"id": 123,
}
request.session.save()
result = create_incomplete_intent_request(request)
self.assertIsInstance(result, str)
def test_show_error_returns_json_response(self):
request = self.factory.get(
reverse("datacenterlight:payment")
)
self.add_session(request)
# Add messages middleware because show_error()
# uses django.contrib.messages.
from django.contrib.messages.middleware import MessageMiddleware
MessageMiddleware(
lambda request: None
).process_request(request)
response = show_error(
"Something went wrong",
request,
)
self.assertEqual(
response.status_code,
200,
)
data = json.loads(
response.content.decode("utf-8")
)
self.assertFalse(data["status"])
self.assertEqual(
data["msg_title"],
"Error.",
)