Переглянути джерело

Rework ExtendedURLValidator and tests

* Tidy implementation of validator
* Tests improved and moved to tests/integration (as they call resolve
  internally)
master
David Winterbottom 12 роки тому
джерело
коміт
0aed77500a

+ 20
- 19
oscar/core/validators.py Переглянути файл

9
 class ExtendedURLValidator(validators.URLValidator):
9
 class ExtendedURLValidator(validators.URLValidator):
10
 
10
 
11
     def __init__(self, *args, **kwargs):
11
     def __init__(self, *args, **kwargs):
12
-        new_kwargs = kwargs.copy()
13
-        self.verify_exists = new_kwargs.pop('verify_exists', False)
14
-        super(ExtendedURLValidator, self).__init__(*args, **new_kwargs)
12
+        # 'verify_exists' has been removed in Django 1.5 and so we no longer
13
+        # pass it up to the core validator class
14
+        self.is_local_url = False
15
+        self.verify_exists = kwargs.pop('verify_exists', False)
16
+        super(ExtendedURLValidator, self).__init__(*args, **kwargs)
15
 
17
 
16
     def __call__(self, value):
18
     def __call__(self, value):
17
         try:
19
         try:
18
             super(ExtendedURLValidator, self).__call__(value)
20
             super(ExtendedURLValidator, self).__call__(value)
19
         except ValidationError:
21
         except ValidationError:
20
-            if value:
22
+            # The parent validator will raise an exception if the URL does not
23
+            # exist and so we test here to see if the value is a local URL.
24
+            if self.verify_exists and value:
21
                 self.validate_local_url(value)
25
                 self.validate_local_url(value)
22
             else:
26
             else:
23
                 raise
27
                 raise
24
 
28
 
25
     def validate_local_url(self, value):
29
     def validate_local_url(self, value):
26
-        """
27
-        Validate local URL name
28
-        """
30
+        value = self.clean_url(value)
29
         try:
31
         try:
30
-            value = self.fix_local_url(value)
31
-            if self.verify_exists:
32
-                resolve(value)
33
-            self.is_local_url = True
32
+            resolve(value)
34
         except Http404:
33
         except Http404:
35
             # We load flatpages here as it causes a circular reference problem
34
             # We load flatpages here as it causes a circular reference problem
36
             # sometimes.  FlatPages is None if not installed
35
             # sometimes.  FlatPages is None if not installed
37
             FlatPage = get_model('flatpages', 'FlatPage')
36
             FlatPage = get_model('flatpages', 'FlatPage')
38
             if FlatPage is not None:
37
             if FlatPage is not None:
39
-                for page in FlatPage.objects.all().only(('url')):
40
-                    if value == page.url:
41
-                        return
38
+                try:
39
+                    FlatPage.objects.get(url=value)
40
+                except FlatPage.DoesNotExist:
41
+                    self.is_local_url = True
42
+                else:
43
+                    return
42
             raise ValidationError(_('Specified page does not exist'))
44
             raise ValidationError(_('Specified page does not exist'))
45
+        else:
46
+            self.is_local_url = True
43
 
47
 
44
-    def fix_local_url(self, value):
48
+    def clean_url(self, value):
45
         """
49
         """
46
-        Puts preceding and trailing slashes to local URL name
50
+        Ensure url has a preceding slash and no query string
47
         """
51
         """
48
         if value != '/':
52
         if value != '/':
49
             value = '/' + value.lstrip('/')
53
             value = '/' + value.lstrip('/')
50
-
51
         q_index = value.find('?')
54
         q_index = value.find('?')
52
-
53
         if q_index > 0:
55
         if q_index > 0:
54
             value = value[:q_index]
56
             value = value[:q_index]
55
-
56
         return value
57
         return value
57
 
58
 
58
 
59
 

+ 68
- 0
tests/integration/core/validator_tests.py Переглянути файл

1
+from django.test import TestCase
2
+from django.core.exceptions import ValidationError
3
+from django.contrib.flatpages.models import FlatPage
4
+
5
+from oscar.core.validators import ExtendedURLValidator
6
+from oscar.core.validators import URLDoesNotExistValidator
7
+
8
+
9
+class TestExtendedURLValidatorWithVerifications(TestCase):
10
+    """
11
+    ExtendedURLValidator with verify_exists=True
12
+    """
13
+
14
+    def setUp(self):
15
+        self.validator = ExtendedURLValidator(verify_exists=True)
16
+
17
+    def test_validates_local_url(self):
18
+        try:
19
+            self.validator('/')
20
+        except ValidationError:
21
+            self.fail('ExtendedURLValidator raised ValidationError'
22
+                      'unexpectedly!')
23
+
24
+    def test_validates_local_url_with_query_strings(self):
25
+        try:
26
+            self.validator('/?q=test')  # Query strings shouldn't affect validation
27
+        except ValidationError:
28
+            self.fail('ExtendedURLValidator raised ValidationError'
29
+                      'unexpectedly!')
30
+
31
+    def test_raises_validation_error_for_missing_urls(self):
32
+        with self.assertRaises(ValidationError):
33
+            self.validator('/invalid/')
34
+
35
+    def test_validates_urls_missing_preceding_slash(self):
36
+        try:
37
+            self.validator('catalogue/')
38
+        except ValidationError:
39
+            self.fail('ExtendedURLValidator raised ValidationError'
40
+                      'unexpectedly!')
41
+
42
+    def test_raises_validation_error_for_urls_without_trailing_slash(self):
43
+        with self.assertRaises(ValidationError):
44
+            self.validator('/catalogue')  # Missing the / is bad
45
+
46
+    def test_validates_flatpages_urls(self):
47
+        FlatPage.objects.create(title='test page', url='/test/page/')
48
+        try:
49
+            self.validator('/test/page/')
50
+        except ValidationError:
51
+            self.fail('ExtendedURLValidator raises ValidationError'
52
+                      'unexpectedly!')
53
+
54
+
55
+class TestExtendedURLValidatorWithoutVerifyExists(TestCase):
56
+    """
57
+    ExtendedURLValidator with verify_exists=False
58
+    """
59
+
60
+    def setUp(self):
61
+        self.validator = URLDoesNotExistValidator()
62
+
63
+    def test_raises_exception_for_local_urls(self):
64
+        self.assertRaises(ValidationError, self.validator, '/')
65
+
66
+    def test_raises_exception_for_flatpages(self):
67
+        FlatPage.objects.create(title='test page', url='/test/page/')
68
+        self.assertRaises(ValidationError, self.validator, '/test/page/')

+ 3
- 62
tests/unit/core/loading_tests.py Переглянути файл

1
 from os.path import dirname
1
 from os.path import dirname
2
 from django.test import TestCase
2
 from django.test import TestCase
3
-from django.core.exceptions import ValidationError
4
 from django.conf import settings
3
 from django.conf import settings
5
-from django.contrib.flatpages.models import FlatPage
6
 from django.test.utils import override_settings
4
 from django.test.utils import override_settings
7
 
5
 
8
 import oscar
6
 import oscar
9
-from oscar.core.loading import (
10
-    import_module, AppNotFoundError, get_classes,
11
-    get_class, ClassNotFoundError)
12
-from oscar.core.validators import (
13
-    ExtendedURLValidator, URLDoesNotExistValidator)
14
 from tests import temporary_python_path
7
 from tests import temporary_python_path
8
+from oscar.core.loading import (
9
+    import_module, AppNotFoundError,
10
+    get_classes, get_class, ClassNotFoundError)
15
 
11
 
16
 
12
 
17
 class TestImportModule(TestCase):
13
 class TestImportModule(TestCase):
92
                 self.assertEqual('shipping.methods', Free.__module__)
88
                 self.assertEqual('shipping.methods', Free.__module__)
93
 
89
 
94
 
90
 
95
-class TestExtendedURLValidator(TestCase):
96
-    """
97
-    ExtendedURLValidator
98
-    """
99
-
100
-    def test_validates_local_url(self):
101
-        v = ExtendedURLValidator(verify_exists=True)
102
-
103
-        try:
104
-            v('/')
105
-        except ValidationError:
106
-            self.fail('ExtendedURLValidator raised ValidationError'
107
-                      'unexpectedly!')
108
-
109
-        try:
110
-            v('/?q=test')  # Query strings shouldn't affect validation
111
-        except ValidationError:
112
-            self.fail('ExtendedURLValidator raised ValidationError'
113
-                      'unexpectedly!')
114
-
115
-        with self.assertRaises(ValidationError):
116
-            v('/invalid/')
117
-
118
-        with self.assertRaises(ValidationError):
119
-            v('/invalid/?q=test')  # Query strings shouldn't affect validation
120
-
121
-        try:
122
-            v('catalogue/')
123
-        except ValidationError:
124
-            self.fail('ExtendedURLValidator raised ValidationError'
125
-                      'unexpectedly!')
126
-
127
-        with self.assertRaises(ValidationError):
128
-            v('/catalogue')  # Missing the / is bad
129
-
130
-        FlatPage(title='test page', url='/test/page/').save()
131
-        try:
132
-            v('/test/page/')
133
-        except ValidationError:
134
-            self.fail('ExtendedURLValidator raises ValidationError'
135
-                      'unexpectedly!')
136
-
137
-    def test_raises_exception_for_missing_url(self):
138
-        validator = URLDoesNotExistValidator()
139
-        self.assertRaises(ValidationError, validator, '/')
140
-        try:
141
-            validator('/invalid/')
142
-        except ValidationError:
143
-            self.fail('URLDoesNotExistValidator raised ValidationError'
144
-                      'unexpectedly!')
145
-
146
-        FlatPage(title='test page', url='/test/page/').save()
147
-        self.assertRaises(ValidationError, validator, '/test/page/')
148
-
149
-
150
 class ClassLoadingWithLocalOverrideWithMultipleSegmentsTests(TestCase):
91
 class ClassLoadingWithLocalOverrideWithMultipleSegmentsTests(TestCase):
151
 
92
 
152
     def setUp(self):
93
     def setUp(self):

Завантаження…
Відмінити
Зберегти