# HG changeset patch # User Branko Majic # Date 2013-10-19 13:19:57 # Node ID dadf26dab8badd28dd36a4e917e4ecb2f5426704 # Parent 843dbaebdae4356ba775c96c5e76be880a6c7f0a CONNT-19: Added test for SearchManager. Added tests for custom manager use in Entity and Project models. Added tests for SearchView. diff --git a/conntrackt/tests/test_managers.py b/conntrackt/tests/test_managers.py new file mode 100644 --- /dev/null +++ b/conntrackt/tests/test_managers.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2013 Branko Majic +# +# This file is part of Django Conntrackt. +# +# Django Conntrackt is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Django Conntrackt is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# Django Conntrackt. If not, see . +# + + +# Python third-party library imports. +import mock + +# Django imports. +from django.test import TestCase +from django.db import models + +# Application imports. +from conntrackt.models import SearchManager, Project + + +class SearchManagerTest(TestCase): + + @mock.patch("conntrackt.models.Q") + def test_search(self, q_object): + """ + Test the search method of custom manager. + """ + + # Create a dummy model that uses the custom manager. + class TestModel(models.Model): + objects = SearchManager() + + # Mock the filter call so we can check what it got called with. + TestModel.objects.filter = mock.MagicMock() + + # Set-up an instance of mocked Q object that we'll use for validating + # the call. + q_instance = mock.Mock() + + # Mock the __or__ call. + q_or_method = mock.Mock() + q_or_method.return_value = q_instance + q_instance.__or__ = q_or_method + + # Finaly, when the constructor is called, we should return our own + # instance. + q_object.return_value = q_instance + + # Call the search. + results = TestModel.objects.search("test") + + # Check if we had bee called with our mocked Q instance. + TestModel.objects.filter.assert_has_calls([mock.call(q_instance)]) + TestModel.objects.filter.assert_called_with(q_instance) + q_instance.__or__.assert_called_with(q_instance) diff --git a/conntrackt/tests/test_models.py b/conntrackt/tests/test_models.py --- a/conntrackt/tests/test_models.py +++ b/conntrackt/tests/test_models.py @@ -26,6 +26,7 @@ from django.test import TestCase # Application imports. from conntrackt.models import Project, Location, Entity, Interface, Communication +from conntrackt.models import SearchManager # Test imports. from .factories import ProjectFactory, LocationFactory @@ -64,6 +65,13 @@ class ProjectTest(TestCase): self.assertEqual(project.get_absolute_url(), "/conntrackt/project/1/") + def test_custom_manager(self): + """ + Tests if the custom manager is being used. + """ + + self.assertIsInstance(Project.objects, SearchManager) + class LocationTest(TestCase): @@ -159,6 +167,13 @@ class EntityTest(TestCase): entity.project = new_project self.assertRaisesRegexp(ValidationError, "The entity cannot be moved to different project as long as it has valid communications with entities in current project.", entity.clean) + def test_custom_manager(self): + """ + Tests if the custom manager is being used. + """ + + self.assertIsInstance(Entity.objects, SearchManager) + class InterfaceTest(TestCase): diff --git a/conntrackt/tests/test_views.py b/conntrackt/tests/test_views.py --- a/conntrackt/tests/test_views.py +++ b/conntrackt/tests/test_views.py @@ -31,11 +31,12 @@ from django.core.urlresolvers import rev from django.http import Http404 from django.test import RequestFactory from django.test import TestCase +from django.utils.http import urlquote # Application imports from conntrackt.models import Project, Location, Entity, Interface, Communication -from conntrackt.views import IndexView +from conntrackt.views import IndexView, SearchView from conntrackt.views import entity_iptables, project_iptables, project_diagram from conntrackt.views import ProjectView, ProjectCreateView, ProjectUpdateView, ProjectDeleteView @@ -1532,3 +1533,74 @@ class RedirectToNextMixinTest(TestCase): view.next_parameter = "custom" self.assertEqual("/next", view.get_success_url()) + + +class SearchViewTest(PermissionTestMixin, TestCase): + + sufficient_permissions = ("view",) + view_class = SearchView + + def setUp(self): + """ + Set-up some test data. + """ + + setup_test_data() + + def test_empty_query_error_message(self): + """ + Verifies that an error is reported to the user in case an empty query is + submitted. + """ + + # Get the view. + view = SearchView.as_view() + + # Generate the request + request = RequestFactory().get("/fake-path?q=") + request.user = mock.Mock() + request._dont_enforce_csrf_checks = True + request._messages = FakeMessages() + + # Get the response. + response = view(request) + + self.assertIn("Search query is not allowed to be empty.", request._messages.messages) + + def test_strip_search_term(self): + """ + Verifies that the search term is stripped when search is performed. + """ + + # Get the view. + view = SearchView.as_view() + + # Set-up a request. + search_term = " \t \t something with lots of tabs \t \t" + stripped_search_term = "something with lots of tabs" + request = RequestFactory().get("/fake-path?q=%s" % urlquote(search_term)) + request.user = mock.Mock() + request._dont_enforce_csrf_checks = True + + # Get the response. + response = view(request) + + # Validate the response. + self.assertEqual(stripped_search_term, response.context_data["search_term"]) + + def test_no_query_context(self): + """ + Tests that context is not set if no query was sent. + """ + + # Get the view. + view = SearchView.as_view() + + # Set-up a request. + response = generate_get_response(view) + + self.assertNotIn("entities", response.context_data) + self.assertNotIn("projects", response.context_data) + self.assertNotIn("search_term", response.context_data) + # Only the "view" context variable should be present. + self.assertEqual(1, len(response.context_data))