File: unit_tests.py

package info (click to toggle)
django-js-reverse 0.9.1-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 240 kB
  • sloc: python: 938; makefile: 5
file content (303 lines) | stat: -rwxr-xr-x 14,154 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

import io
import json
import os
import re
import subprocess
import sys
import unittest

import django
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.core.management import call_command
from django.template import Context, RequestContext, Template
from django.utils.encoding import smart_str
from helper import is_django_ver_gte_2
from utils import script_prefix

sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', '..') + os.sep)
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'

from django.test import TestCase, RequestFactory  # noqa: E402 isort:skip
from django.test.client import Client  # noqa: E402 isort:skip
from django.test.utils import override_settings  # noqa: E402 isort:skip


class AbstractJSReverseTestCase(object):
    client = Client()

    @classmethod
    def setUpClass(cls):
        if hasattr(django, 'setup'):
            # for django >= 1.7
            django.setup()
        super(AbstractJSReverseTestCase, cls).setUpClass()

    def assertEqualJSEval(self, js, url_call, expected_url):
        script = '{}return {};'.format(js, url_call)
        module = 'console.log(new Function({})());'.format(json.dumps(script))
        stdout = (
            subprocess
            .check_output(['node', '-e', module.encode('utf8')])
            .decode('utf8')
        )
        self.assertEqual(re.sub(r'\n$', '', stdout), expected_url)

    def assertEqualJSUrlEval(self, *args, **kwargs):
        js = smart_str(self.client.post('/jsreverse/').content)
        self.assertEqualJSEval(js, *args, **kwargs)


@override_settings(ROOT_URLCONF='django_js_reverse.tests.test_urls')
class JSReverseViewTestCaseMinified(AbstractJSReverseTestCase, TestCase):
    def test_view_no_url_args(self):
        self.assertEqualJSUrlEval('Urls.test_no_url_args()', '/test_no_url_args/')

    def test_camel_case(self):
        self.assertEqualJSUrlEval('Urls.testNoUrlArgs()', '/test_no_url_args/')

    def test_view_one_url_arg(self):
        self.assertEqualJSUrlEval('Urls.test_one_url_args("arg_one")', '/test_one_url_args/arg_one/')

    def test_view_two_url_args(self):
        self.assertEqualJSUrlEval('Urls.test_two_url_args("arg_one", "arg_two")', '/test_two_url_args/arg_one-arg_two/')

    def test_view_optional_url_arg(self):
        self.assertEqualJSUrlEval('Urls.test_optional_url_arg("arg_two")',
                                  '/test_optional_url_arg/2_arg_two/')
        self.assertEqualJSUrlEval('Urls.test_optional_url_arg("arg_one", "arg_two")',
                                  '/test_optional_url_arg/1_arg_one-2_arg_two/')

    def test_unicode_url_name(self):
        self.assertEqualJSUrlEval('Urls.test_unicode_url_name()', '/test_unicode_url_name/')

    @override_settings(JS_REVERSE_JS_VAR_NAME='Foo')
    def test_js_var_name_changed_valid(self):
        self.assertEqualJSUrlEval('Foo.test_no_url_args()', '/test_no_url_args/')

    @override_settings(JS_REVERSE_JS_VAR_NAME='1test')
    def test_js_var_name_changed_to_invalid(self):
        with self.assertRaises(ImproperlyConfigured):
            self.client.post('/jsreverse/')

    def test_namespaces(self):
        self.assertEqualJSUrlEval('Urls["ns1:test_two_url_args"]("arg_one", "arg_two")',
                                  '/ns1/test_two_url_args/arg_one-arg_two/')
        self.assertEqualJSUrlEval('Urls["ns2:test_two_url_args"]("arg_one", "arg_two")',
                                  '/ns2/test_two_url_args/arg_one-arg_two/')

    def test_namespaces_with_args(self):
        self.assertEqualJSUrlEval('Urls["ns_arg:test_two_url_args"]("arg_one", "arg_two", "arg_three")',
                                  '/nsarg_one/test_two_url_args/arg_two-arg_three/')

    def test_namespaces_nested(self):
        self.assertEqualJSUrlEval('Urls["nestedns:ns1:test_two_url_args"]("arg_one", "arg_two")',
                                  '/nestedns/ns1/test_two_url_args/arg_one-arg_two/')

    def test_content_type(self):
        response = self.client.post('/jsreverse/')
        self.assertEqual(response['Content-Type'], 'application/javascript')

    @override_settings(JS_REVERSE_JS_MINIFY='invalid')
    def test_js_minfiy_changed_to_invalid(self):
        with self.assertRaises(ImproperlyConfigured):
            self.client.post('/jsreverse/')

    def test_namespace_in_urls(self):
        response = self.client.get('/jsreverse/')
        self.assertContains(response, 'exclude_namespace', status_code=200)

    @override_settings(JS_REVERSE_EXCLUDE_NAMESPACES=['exclude_namespace'])
    def test_namespace_not_in_response(self):
        response = self.client.get('/jsreverse/')
        self.assertNotContains(response, 'exclude_namespace', status_code=200)

    @override_settings(JS_REVERSE_INCLUDE_ONLY_NAMESPACES=['ns1'])
    def test_only_namespace_in_response(self):
        response = self.client.get('/jsreverse/')
        self.assertContains(response, 'ns1', status_code=200)
        self.assertNotContains(response, 'ns2', status_code=200)
        self.assertNotContains(response, 'ns_arg', status_code=200)
        self.assertNotContains(response, 'nesteadns', status_code=200)
        self.assertNotContains(response, 'exclude_namespace', status_code=200)
        self.assertNotContains(response, 'nsdn', status_code=200)
        self.assertNotContains(response, 'nsno', status_code=200)

    @override_settings(JS_REVERSE_INCLUDE_ONLY_NAMESPACES=['nsdn:nsdn'])
    def test_only_namespace_nestead_in_response(self):
        response = self.client.get('/jsreverse/')
        self.assertContains(response, 'nsdn:nsdn2:ns1', status_code=200)
        self.assertNotContains(response, 'nsdn:ns1', status_code=200)

    @override_settings(JS_REVERSE_INCLUDE_ONLY_NAMESPACES=[''])
    def test_only_empty_namespaces(self):
        response = self.client.get('/jsreverse/')
        self.assertEqualJSUrlEval('Urls["test_two_url_args"]("arg_one", "arg_two")',
                                  '/test_two_url_args/arg_one-arg_two/')
        self.assertNotContains(response, 'ns1', status_code=200)
        self.assertNotContains(response, 'ns2', status_code=200)

    @override_settings(JS_REVERSE_INCLUDE_ONLY_NAMESPACES=['nsno\0'])
    def test_only_namespaces_without_subnss(self):
        response = self.client.get('/jsreverse/')
        self.assertEqualJSUrlEval('Urls["nsno:test_two_url_args"]("arg_one", "arg_two")',
                                  '/nsno/ns1/test_two_url_args/arg_one-arg_two/')
        self.assertNotContains(response, 'nsno:nsdn0', status_code=200)

    def test_script_prefix_v1(self):
        with script_prefix('/foobarlala/'):
            self.assertEqualJSUrlEval('Urls["nestedns:ns1:test_two_url_args"]("arg_one", "arg_two")',
                                      '/foobarlala/nestedns/ns1/test_two_url_args/arg_one-arg_two/')

    def test_duplicate_name(self):
        self.assertEqualJSUrlEval('Urls.test_duplicate_name("arg_one")',
                                  '/test_duplicate_name/arg_one/')
        self.assertEqualJSUrlEval('Urls.test_duplicate_name("arg_one", "arg_two")',
                                  '/test_duplicate_name/arg_one-arg_two/')

    def test_duplicate_argcount(self):
        self.assertEqualJSUrlEval('Urls.test_duplicate_argcount({arg_one: "arg_one"})',
                                  '/test_duplicate_argcount/arg_one-/')
        self.assertEqualJSUrlEval('Urls.test_duplicate_argcount({arg_two: "arg_two"})',
                                  '/test_duplicate_argcount/-arg_two/')
        self.assertEqualJSUrlEval('Urls.test_duplicate_argcount({arg_one: "arg_one", arg_two: "arg_two"})',
                                  '/test_duplicate_argcount/arg_one-arg_two/')

    @override_settings(JS_REVERSE_INCLUDE_ONLY_NAMESPACES=['nsno\0'])
    @override_settings(JS_REVERSE_EXCLUDE_NAMESPACES=['exclude_namespace'])
    def test_include_exclude_configuration(self):
        with self.assertRaises(ImproperlyConfigured):
            self.client.post('/jsreverse/')

    def test_int_args(self):
        self.assertEqualJSUrlEval('Urls.test_two_url_args(0, 5)', '/test_two_url_args/0-5/')
        self.assertEqualJSUrlEval('Urls.test_two_url_args("", 5)', '/test_two_url_args/-5/')

    def test_float_args(self):
        self.assertEqualJSUrlEval('Urls.test_two_url_args(0, 5.5)', '/test_two_url_args/0-5.5/')
        self.assertEqualJSUrlEval('Urls.test_two_url_args(0.00001, 5.5)', '/test_two_url_args/0.00001-5.5/')

    def test_django_path_syntax(self):
        if is_django_ver_gte_2():
            self.assertEqualJSUrlEval('Urls.test_django_gte_2_path_syntax(42, "foo")',
                                      '/test_django_gte_2_path_syntax/42/foo/')


@override_settings(JS_REVERSE_JS_MINIFY=False)
@override_settings(ROOT_URLCONF='django_js_reverse.tests.test_urls')
class JSReverseViewTestCaseNotMinified(JSReverseViewTestCaseMinified):
    def test_minification(self):
        js_not_minified = smart_str(self.client.post('/jsreverse/').content)
        with override_settings(JS_REVERSE_JS_MINIFY=True):
            js_minified = smart_str(self.client.post('/jsreverse/').content)
            self.assertTrue(len(js_minified) < len(js_not_minified))


@override_settings(ROOT_URLCONF='django_js_reverse.tests.test_urls')
class JSReverseViewTestCaseGlobalObjectName(JSReverseViewTestCaseMinified):
    def test_global_object_name_default(self):
        js_content = smart_str(self.client.post('/jsreverse/').content)
        self.assertTrue(js_content.startswith('this.'))

    @override_settings(JS_REVERSE_JS_GLOBAL_OBJECT_NAME='window')
    def test_global_object_name_change(self):
        js_content = smart_str(self.client.post('/jsreverse/').content)
        self.assertTrue(js_content.startswith('window.'))

    @override_settings(JS_REVERSE_JS_GLOBAL_OBJECT_NAME='1test')
    def test_global_object_name_change_invalid_identifier(self):
        with self.assertRaises(ImproperlyConfigured):
            self.client.post('/jsreverse/')


@override_settings(ROOT_URLCONF='django_js_reverse.tests.test_urls')
class JSReverseStaticFileSaveTest(AbstractJSReverseTestCase, TestCase):
    def test_reverse_js_file_save(self):
        call_command('collectstatic_js_reverse')

        path = os.path.join(settings.STATIC_ROOT, 'django_js_reverse', 'js', 'reverse.js')
        f = io.open(path)
        content1 = f.read()

        r2 = self.client.get('/jsreverse/')
        content2 = r2.content.decode()

        self.assertEqual(len(content1), len(content2), 'Static file don\'t match http response content_1')
        self.assertEqual(content1, content2, 'Static file don\'t match http response content_2')

        # test for exception if STATIC_ROOT is not set
        with override_settings(STATIC_ROOT=None):
            with self.assertRaises(ImproperlyConfigured):
                call_command('collectstatic_js_reverse')

    def test_reverse_js_file_save_with_output_path_option(self):
        js_output_path = os.path.join(os.path.dirname(__file__), 'tmp', 'some_path')
        with override_settings(JS_REVERSE_OUTPUT_PATH=js_output_path):
            call_command('collectstatic_js_reverse')

            f = io.open(os.path.join(js_output_path, 'reverse.js'))
            content1 = f.read()

            r2 = self.client.get('/jsreverse/')
            content2 = r2.content.decode()

            self.assertEqual(len(content1), len(content2), 'Static file don\'t match http response content_1')
            self.assertEqual(content1, content2, 'Static file don\'t match http response content_2')

            # should not raise ImproperlyConfigured exception if STATIC_ROOT is not set
            with override_settings(STATIC_ROOT=None):
                call_command('collectstatic_js_reverse')

    def test_script_prefix_noslash(self):
        script_prefix = '/test/foo/bar'
        with override_settings(JS_REVERSE_SCRIPT_PREFIX=script_prefix):
            self.assertEqualJSUrlEval('Urls.test_no_url_args()', '{0}/test_no_url_args/'.format(script_prefix))

    def test_script_prefix(self):
        script_prefix = '/test/foo/bar/'
        with override_settings(JS_REVERSE_SCRIPT_PREFIX=script_prefix):
            self.assertEqualJSUrlEval('Urls.test_no_url_args()', '{0}test_no_url_args/'.format(script_prefix))


@override_settings(
    ROOT_URLCONF='django_js_reverse.tests.test_urls',

    TEMPLATE_CONTEXT_PROCESSORS=['django.core.context_processors.request'],
)
class JSReverseTemplateTagTest(AbstractJSReverseTestCase, TestCase):
    def test_tpl_tag_with_request_in_context(self):
        request = RequestFactory().post('/jsreverse/')
        request.urlconf = 'django_js_reverse.tests.test_urlconf_urls'
        tpl = Template('{% load js_reverse %}{% js_reverse_inline %}')
        js = tpl.render(RequestContext(request))
        self.assertEqualJSEval(js, 'Urls.test_changed_urlconf()', '/test_changed_urlconf/')

    def test_tpl_tag_with_dict_request_in_context(self):
        request = {'urlconf': 'django_js_reverse.tests.test_urlconf_urls'}
        tpl = Template('{% load js_reverse %}{% js_reverse_inline %}')
        js = tpl.render(Context({'request': request}))
        self.assertEqualJSEval(js, 'Urls.test_changed_urlconf()', '/test_changed_urlconf/')

    def test_tpl_tag_without_request_in_context(self):
        context_instance = Context()
        tpl = Template('{% load js_reverse %}{% js_reverse_inline %}')
        js_from_tag = tpl.render(context_instance)
        js_from_view = smart_str(self.client.post('/jsreverse/').content)
        self.assertEqual(js_from_tag, js_from_view)

    def test_tpl_tag_escape_entities(self):
        context_instance = Context()
        tpl = Template('{% load js_reverse %}{% js_reverse_inline %}')
        js = tpl.render(context_instance)
        self.assertIn(
            '\\u003C/script\\u003E\\u003Cscript\\u003Econsole.log(\\u0026amp;)'
            '\\u003C/script\\u003E\\u003C!--',
            js,
        )

if __name__ == '__main__':
    unittest.main()