PageRenderTime 47ms CodeModel.GetById 2ms app.highlight 38ms RepoModel.GetById 1ms app.codeStats 1ms

/tests/regressiontests/forms/tests/media.py

https://code.google.com/p/mango-py/
Python | 920 lines | 913 code | 4 blank | 3 comment | 0 complexity | c3ecf15f6dd23e7f4441ab935c7db1dc MD5 | raw file
  1# -*- coding: utf-8 -*-
  2from django.conf import settings
  3from django.forms import TextInput, Media, TextInput, CharField, Form, MultiWidget
  4from django.utils.unittest import TestCase
  5
  6
  7class FormsMediaTestCase(TestCase):
  8    # Tests for the media handling on widgets and forms
  9    def setUp(self):
 10        super(FormsMediaTestCase, self).setUp()
 11        self.original_media_url = settings.MEDIA_URL
 12        settings.MEDIA_URL = 'http://media.example.com/media/'
 13
 14    def tearDown(self):
 15        settings.MEDIA_URL = self.original_media_url
 16        super(FormsMediaTestCase, self).tearDown()
 17
 18    def test_construction(self):
 19        # Check construction of media objects
 20        m = Media(css={'all': ('path/to/css1','/path/to/css2')}, js=('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3'))
 21        self.assertEqual(str(m), """<link href="http://media.example.com/media/path/to/css1" type="text/css" media="all" rel="stylesheet" />
 22<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
 23<script type="text/javascript" src="/path/to/js1"></script>
 24<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
 25<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>""")
 26
 27        class Foo:
 28            css = {
 29               'all': ('path/to/css1','/path/to/css2')
 30            }
 31            js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
 32
 33        m3 = Media(Foo)
 34        self.assertEqual(str(m3), """<link href="http://media.example.com/media/path/to/css1" type="text/css" media="all" rel="stylesheet" />
 35<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
 36<script type="text/javascript" src="/path/to/js1"></script>
 37<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
 38<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>""")
 39
 40        # A widget can exist without a media definition
 41        class MyWidget(TextInput):
 42            pass
 43
 44        w = MyWidget()
 45        self.assertEqual(str(w.media), '')
 46
 47    def test_media_dsl(self):
 48        ###############################################################
 49        # DSL Class-based media definitions
 50        ###############################################################
 51
 52        # A widget can define media if it needs to.
 53        # Any absolute path will be preserved; relative paths are combined
 54        # with the value of settings.MEDIA_URL
 55        class MyWidget1(TextInput):
 56            class Media:
 57                css = {
 58                   'all': ('path/to/css1','/path/to/css2')
 59                }
 60                js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
 61
 62        w1 = MyWidget1()
 63        self.assertEqual(str(w1.media), """<link href="http://media.example.com/media/path/to/css1" type="text/css" media="all" rel="stylesheet" />
 64<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
 65<script type="text/javascript" src="/path/to/js1"></script>
 66<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
 67<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>""")
 68
 69        # Media objects can be interrogated by media type
 70        self.assertEqual(str(w1.media['css']), """<link href="http://media.example.com/media/path/to/css1" type="text/css" media="all" rel="stylesheet" />
 71<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />""")
 72
 73        self.assertEqual(str(w1.media['js']), """<script type="text/javascript" src="/path/to/js1"></script>
 74<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
 75<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>""")
 76
 77    def test_combine_media(self):
 78        # Media objects can be combined. Any given media resource will appear only
 79        # once. Duplicated media definitions are ignored.
 80        class MyWidget1(TextInput):
 81            class Media:
 82                css = {
 83                   'all': ('path/to/css1','/path/to/css2')
 84                }
 85                js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
 86
 87        class MyWidget2(TextInput):
 88            class Media:
 89                css = {
 90                   'all': ('/path/to/css2','/path/to/css3')
 91                }
 92                js = ('/path/to/js1','/path/to/js4')
 93
 94        class MyWidget3(TextInput):
 95            class Media:
 96                css = {
 97                   'all': ('/path/to/css3','path/to/css1')
 98                }
 99                js = ('/path/to/js1','/path/to/js4')
100
101        w1 = MyWidget1()
102        w2 = MyWidget2()
103        w3 = MyWidget3()
104        self.assertEqual(str(w1.media + w2.media + w3.media), """<link href="http://media.example.com/media/path/to/css1" type="text/css" media="all" rel="stylesheet" />
105<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
106<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
107<script type="text/javascript" src="/path/to/js1"></script>
108<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
109<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
110<script type="text/javascript" src="/path/to/js4"></script>""")
111
112        # Check that media addition hasn't affected the original objects
113        self.assertEqual(str(w1.media), """<link href="http://media.example.com/media/path/to/css1" type="text/css" media="all" rel="stylesheet" />
114<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
115<script type="text/javascript" src="/path/to/js1"></script>
116<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
117<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>""")
118
119        # Regression check for #12879: specifying the same CSS or JS file
120        # multiple times in a single Media instance should result in that file
121        # only being included once.
122        class MyWidget4(TextInput):
123            class Media:
124                css = {'all': ('/path/to/css1', '/path/to/css1')}
125                js = ('/path/to/js1', '/path/to/js1')
126
127        w4 = MyWidget4()
128        self.assertEqual(str(w4.media), """<link href="/path/to/css1" type="text/css" media="all" rel="stylesheet" />
129<script type="text/javascript" src="/path/to/js1"></script>""")
130
131    def test_media_property(self):
132        ###############################################################
133        # Property-based media definitions
134        ###############################################################
135
136        # Widget media can be defined as a property
137        class MyWidget4(TextInput):
138            def _media(self):
139                return Media(css={'all': ('/some/path',)}, js = ('/some/js',))
140            media = property(_media)
141
142        w4 = MyWidget4()
143        self.assertEqual(str(w4.media), """<link href="/some/path" type="text/css" media="all" rel="stylesheet" />
144<script type="text/javascript" src="/some/js"></script>""")
145
146        # Media properties can reference the media of their parents
147        class MyWidget5(MyWidget4):
148            def _media(self):
149                return super(MyWidget5, self).media + Media(css={'all': ('/other/path',)}, js = ('/other/js',))
150            media = property(_media)
151
152        w5 = MyWidget5()
153        self.assertEqual(str(w5.media), """<link href="/some/path" type="text/css" media="all" rel="stylesheet" />
154<link href="/other/path" type="text/css" media="all" rel="stylesheet" />
155<script type="text/javascript" src="/some/js"></script>
156<script type="text/javascript" src="/other/js"></script>""")
157
158    def test_media_property_parent_references(self):
159        # Media properties can reference the media of their parents,
160        # even if the parent media was defined using a class
161        class MyWidget1(TextInput):
162            class Media:
163                css = {
164                   'all': ('path/to/css1','/path/to/css2')
165                }
166                js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
167
168        class MyWidget6(MyWidget1):
169            def _media(self):
170                return super(MyWidget6, self).media + Media(css={'all': ('/other/path',)}, js = ('/other/js',))
171            media = property(_media)
172
173        w6 = MyWidget6()
174        self.assertEqual(str(w6.media), """<link href="http://media.example.com/media/path/to/css1" type="text/css" media="all" rel="stylesheet" />
175<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
176<link href="/other/path" type="text/css" media="all" rel="stylesheet" />
177<script type="text/javascript" src="/path/to/js1"></script>
178<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
179<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
180<script type="text/javascript" src="/other/js"></script>""")
181
182    def test_media_inheritance(self):
183        ###############################################################
184        # Inheritance of media
185        ###############################################################
186
187        # If a widget extends another but provides no media definition, it inherits the parent widget's media
188        class MyWidget1(TextInput):
189            class Media:
190                css = {
191                   'all': ('path/to/css1','/path/to/css2')
192                }
193                js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
194
195        class MyWidget7(MyWidget1):
196            pass
197
198        w7 = MyWidget7()
199        self.assertEqual(str(w7.media), """<link href="http://media.example.com/media/path/to/css1" type="text/css" media="all" rel="stylesheet" />
200<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
201<script type="text/javascript" src="/path/to/js1"></script>
202<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
203<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>""")
204
205        # If a widget extends another but defines media, it extends the parent widget's media by default
206        class MyWidget8(MyWidget1):
207            class Media:
208                css = {
209                   'all': ('/path/to/css3','path/to/css1')
210                }
211                js = ('/path/to/js1','/path/to/js4')
212
213        w8 = MyWidget8()
214        self.assertEqual(str(w8.media), """<link href="http://media.example.com/media/path/to/css1" type="text/css" media="all" rel="stylesheet" />
215<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
216<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
217<script type="text/javascript" src="/path/to/js1"></script>
218<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
219<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
220<script type="text/javascript" src="/path/to/js4"></script>""")
221
222    def test_media_inheritance_from_property(self):
223        # If a widget extends another but defines media, it extends the parents widget's media,
224        # even if the parent defined media using a property.
225        class MyWidget1(TextInput):
226            class Media:
227                css = {
228                   'all': ('path/to/css1','/path/to/css2')
229                }
230                js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
231
232        class MyWidget4(TextInput):
233            def _media(self):
234                return Media(css={'all': ('/some/path',)}, js = ('/some/js',))
235            media = property(_media)
236
237        class MyWidget9(MyWidget4):
238            class Media:
239                css = {
240                    'all': ('/other/path',)
241                }
242                js = ('/other/js',)
243
244        w9 = MyWidget9()
245        self.assertEqual(str(w9.media), """<link href="/some/path" type="text/css" media="all" rel="stylesheet" />
246<link href="/other/path" type="text/css" media="all" rel="stylesheet" />
247<script type="text/javascript" src="/some/js"></script>
248<script type="text/javascript" src="/other/js"></script>""")
249
250        # A widget can disable media inheritance by specifying 'extend=False'
251        class MyWidget10(MyWidget1):
252            class Media:
253                extend = False
254                css = {
255                   'all': ('/path/to/css3','path/to/css1')
256                }
257                js = ('/path/to/js1','/path/to/js4')
258
259        w10 = MyWidget10()
260        self.assertEqual(str(w10.media), """<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
261<link href="http://media.example.com/media/path/to/css1" type="text/css" media="all" rel="stylesheet" />
262<script type="text/javascript" src="/path/to/js1"></script>
263<script type="text/javascript" src="/path/to/js4"></script>""")
264
265    def test_media_inheritance_extends(self):
266        # A widget can explicitly enable full media inheritance by specifying 'extend=True'
267        class MyWidget1(TextInput):
268            class Media:
269                css = {
270                   'all': ('path/to/css1','/path/to/css2')
271                }
272                js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
273
274        class MyWidget11(MyWidget1):
275            class Media:
276                extend = True
277                css = {
278                   'all': ('/path/to/css3','path/to/css1')
279                }
280                js = ('/path/to/js1','/path/to/js4')
281
282        w11 = MyWidget11()
283        self.assertEqual(str(w11.media), """<link href="http://media.example.com/media/path/to/css1" type="text/css" media="all" rel="stylesheet" />
284<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
285<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
286<script type="text/javascript" src="/path/to/js1"></script>
287<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
288<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
289<script type="text/javascript" src="/path/to/js4"></script>""")
290
291    def test_media_inheritance_single_type(self):
292        # A widget can enable inheritance of one media type by specifying extend as a tuple
293        class MyWidget1(TextInput):
294            class Media:
295                css = {
296                   'all': ('path/to/css1','/path/to/css2')
297                }
298                js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
299
300        class MyWidget12(MyWidget1):
301            class Media:
302                extend = ('css',)
303                css = {
304                   'all': ('/path/to/css3','path/to/css1')
305                }
306                js = ('/path/to/js1','/path/to/js4')
307
308        w12 = MyWidget12()
309        self.assertEqual(str(w12.media), """<link href="http://media.example.com/media/path/to/css1" type="text/css" media="all" rel="stylesheet" />
310<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
311<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
312<script type="text/javascript" src="/path/to/js1"></script>
313<script type="text/javascript" src="/path/to/js4"></script>""")
314
315    def test_multi_media(self):
316        ###############################################################
317        # Multi-media handling for CSS
318        ###############################################################
319
320        # A widget can define CSS media for multiple output media types
321        class MultimediaWidget(TextInput):
322            class Media:
323                css = {
324                   'screen, print': ('/file1','/file2'),
325                   'screen': ('/file3',),
326                   'print': ('/file4',)
327                }
328                js = ('/path/to/js1','/path/to/js4')
329
330        multimedia = MultimediaWidget()
331        self.assertEqual(str(multimedia.media), """<link href="/file4" type="text/css" media="print" rel="stylesheet" />
332<link href="/file3" type="text/css" media="screen" rel="stylesheet" />
333<link href="/file1" type="text/css" media="screen, print" rel="stylesheet" />
334<link href="/file2" type="text/css" media="screen, print" rel="stylesheet" />
335<script type="text/javascript" src="/path/to/js1"></script>
336<script type="text/javascript" src="/path/to/js4"></script>""")
337
338    def test_multi_widget(self):
339        ###############################################################
340        # Multiwidget media handling
341        ###############################################################
342
343        class MyWidget1(TextInput):
344            class Media:
345                css = {
346                   'all': ('path/to/css1','/path/to/css2')
347                }
348                js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
349
350        class MyWidget2(TextInput):
351            class Media:
352                css = {
353                   'all': ('/path/to/css2','/path/to/css3')
354                }
355                js = ('/path/to/js1','/path/to/js4')
356
357        class MyWidget3(TextInput):
358            class Media:
359                css = {
360                   'all': ('/path/to/css3','path/to/css1')
361                }
362                js = ('/path/to/js1','/path/to/js4')
363
364        # MultiWidgets have a default media definition that gets all the
365        # media from the component widgets
366        class MyMultiWidget(MultiWidget):
367            def __init__(self, attrs=None):
368                widgets = [MyWidget1, MyWidget2, MyWidget3]
369                super(MyMultiWidget, self).__init__(widgets, attrs)
370
371        mymulti = MyMultiWidget()
372        self.assertEqual(str(mymulti.media), """<link href="http://media.example.com/media/path/to/css1" type="text/css" media="all" rel="stylesheet" />
373<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
374<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
375<script type="text/javascript" src="/path/to/js1"></script>
376<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
377<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
378<script type="text/javascript" src="/path/to/js4"></script>""")
379
380    def test_form_media(self):
381        ###############################################################
382        # Media processing for forms
383        ###############################################################
384
385        class MyWidget1(TextInput):
386            class Media:
387                css = {
388                   'all': ('path/to/css1','/path/to/css2')
389                }
390                js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
391
392        class MyWidget2(TextInput):
393            class Media:
394                css = {
395                   'all': ('/path/to/css2','/path/to/css3')
396                }
397                js = ('/path/to/js1','/path/to/js4')
398
399        class MyWidget3(TextInput):
400            class Media:
401                css = {
402                   'all': ('/path/to/css3','path/to/css1')
403                }
404                js = ('/path/to/js1','/path/to/js4')
405
406        # You can ask a form for the media required by its widgets.
407        class MyForm(Form):
408            field1 = CharField(max_length=20, widget=MyWidget1())
409            field2 = CharField(max_length=20, widget=MyWidget2())
410        f1 = MyForm()
411        self.assertEqual(str(f1.media), """<link href="http://media.example.com/media/path/to/css1" type="text/css" media="all" rel="stylesheet" />
412<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
413<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
414<script type="text/javascript" src="/path/to/js1"></script>
415<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
416<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
417<script type="text/javascript" src="/path/to/js4"></script>""")
418
419        # Form media can be combined to produce a single media definition.
420        class AnotherForm(Form):
421            field3 = CharField(max_length=20, widget=MyWidget3())
422        f2 = AnotherForm()
423        self.assertEqual(str(f1.media + f2.media), """<link href="http://media.example.com/media/path/to/css1" type="text/css" media="all" rel="stylesheet" />
424<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
425<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
426<script type="text/javascript" src="/path/to/js1"></script>
427<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
428<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
429<script type="text/javascript" src="/path/to/js4"></script>""")
430
431        # Forms can also define media, following the same rules as widgets.
432        class FormWithMedia(Form):
433            field1 = CharField(max_length=20, widget=MyWidget1())
434            field2 = CharField(max_length=20, widget=MyWidget2())
435            class Media:
436                js = ('/some/form/javascript',)
437                css = {
438                    'all': ('/some/form/css',)
439                }
440        f3 = FormWithMedia()
441        self.assertEqual(str(f3.media), """<link href="http://media.example.com/media/path/to/css1" type="text/css" media="all" rel="stylesheet" />
442<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
443<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
444<link href="/some/form/css" type="text/css" media="all" rel="stylesheet" />
445<script type="text/javascript" src="/path/to/js1"></script>
446<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
447<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
448<script type="text/javascript" src="/path/to/js4"></script>
449<script type="text/javascript" src="/some/form/javascript"></script>""")
450
451        # Media works in templates
452        from django.template import Template, Context
453        self.assertEqual(Template("{{ form.media.js }}{{ form.media.css }}").render(Context({'form': f3})), """<script type="text/javascript" src="/path/to/js1"></script>
454<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
455<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
456<script type="text/javascript" src="/path/to/js4"></script>
457<script type="text/javascript" src="/some/form/javascript"></script><link href="http://media.example.com/media/path/to/css1" type="text/css" media="all" rel="stylesheet" />
458<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
459<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
460<link href="/some/form/css" type="text/css" media="all" rel="stylesheet" />""")
461
462
463class StaticFormsMediaTestCase(TestCase):
464    # Tests for the media handling on widgets and forms
465    def setUp(self):
466        super(StaticFormsMediaTestCase, self).setUp()
467        self.original_media_url = settings.MEDIA_URL
468        self.original_static_url = settings.STATIC_URL
469        settings.MEDIA_URL = 'http://media.example.com/static/'
470        settings.STATIC_URL = 'http://media.example.com/static/'
471
472    def tearDown(self):
473        settings.MEDIA_URL = self.original_media_url
474        settings.STATIC_URL = self.original_static_url
475        super(StaticFormsMediaTestCase, self).tearDown()
476
477    def test_construction(self):
478        # Check construction of media objects
479        m = Media(css={'all': ('path/to/css1','/path/to/css2')}, js=('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3'))
480        self.assertEqual(str(m), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
481<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
482<script type="text/javascript" src="/path/to/js1"></script>
483<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
484<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>""")
485
486        class Foo:
487            css = {
488               'all': ('path/to/css1','/path/to/css2')
489            }
490            js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
491
492        m3 = Media(Foo)
493        self.assertEqual(str(m3), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
494<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
495<script type="text/javascript" src="/path/to/js1"></script>
496<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
497<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>""")
498
499        # A widget can exist without a media definition
500        class MyWidget(TextInput):
501            pass
502
503        w = MyWidget()
504        self.assertEqual(str(w.media), '')
505
506    def test_media_dsl(self):
507        ###############################################################
508        # DSL Class-based media definitions
509        ###############################################################
510
511        # A widget can define media if it needs to.
512        # Any absolute path will be preserved; relative paths are combined
513        # with the value of settings.MEDIA_URL
514        class MyWidget1(TextInput):
515            class Media:
516                css = {
517                   'all': ('path/to/css1','/path/to/css2')
518                }
519                js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
520
521        w1 = MyWidget1()
522        self.assertEqual(str(w1.media), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
523<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
524<script type="text/javascript" src="/path/to/js1"></script>
525<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
526<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>""")
527
528        # Media objects can be interrogated by media type
529        self.assertEqual(str(w1.media['css']), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
530<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />""")
531
532        self.assertEqual(str(w1.media['js']), """<script type="text/javascript" src="/path/to/js1"></script>
533<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
534<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>""")
535
536    def test_combine_media(self):
537        # Media objects can be combined. Any given media resource will appear only
538        # once. Duplicated media definitions are ignored.
539        class MyWidget1(TextInput):
540            class Media:
541                css = {
542                   'all': ('path/to/css1','/path/to/css2')
543                }
544                js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
545
546        class MyWidget2(TextInput):
547            class Media:
548                css = {
549                   'all': ('/path/to/css2','/path/to/css3')
550                }
551                js = ('/path/to/js1','/path/to/js4')
552
553        class MyWidget3(TextInput):
554            class Media:
555                css = {
556                   'all': ('/path/to/css3','path/to/css1')
557                }
558                js = ('/path/to/js1','/path/to/js4')
559
560        w1 = MyWidget1()
561        w2 = MyWidget2()
562        w3 = MyWidget3()
563        self.assertEqual(str(w1.media + w2.media + w3.media), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
564<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
565<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
566<script type="text/javascript" src="/path/to/js1"></script>
567<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
568<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
569<script type="text/javascript" src="/path/to/js4"></script>""")
570
571        # Check that media addition hasn't affected the original objects
572        self.assertEqual(str(w1.media), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
573<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
574<script type="text/javascript" src="/path/to/js1"></script>
575<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
576<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>""")
577
578        # Regression check for #12879: specifying the same CSS or JS file
579        # multiple times in a single Media instance should result in that file
580        # only being included once.
581        class MyWidget4(TextInput):
582            class Media:
583                css = {'all': ('/path/to/css1', '/path/to/css1')}
584                js = ('/path/to/js1', '/path/to/js1')
585
586        w4 = MyWidget4()
587        self.assertEqual(str(w4.media), """<link href="/path/to/css1" type="text/css" media="all" rel="stylesheet" />
588<script type="text/javascript" src="/path/to/js1"></script>""")
589
590    def test_media_property(self):
591        ###############################################################
592        # Property-based media definitions
593        ###############################################################
594
595        # Widget media can be defined as a property
596        class MyWidget4(TextInput):
597            def _media(self):
598                return Media(css={'all': ('/some/path',)}, js = ('/some/js',))
599            media = property(_media)
600
601        w4 = MyWidget4()
602        self.assertEqual(str(w4.media), """<link href="/some/path" type="text/css" media="all" rel="stylesheet" />
603<script type="text/javascript" src="/some/js"></script>""")
604
605        # Media properties can reference the media of their parents
606        class MyWidget5(MyWidget4):
607            def _media(self):
608                return super(MyWidget5, self).media + Media(css={'all': ('/other/path',)}, js = ('/other/js',))
609            media = property(_media)
610
611        w5 = MyWidget5()
612        self.assertEqual(str(w5.media), """<link href="/some/path" type="text/css" media="all" rel="stylesheet" />
613<link href="/other/path" type="text/css" media="all" rel="stylesheet" />
614<script type="text/javascript" src="/some/js"></script>
615<script type="text/javascript" src="/other/js"></script>""")
616
617    def test_media_property_parent_references(self):
618        # Media properties can reference the media of their parents,
619        # even if the parent media was defined using a class
620        class MyWidget1(TextInput):
621            class Media:
622                css = {
623                   'all': ('path/to/css1','/path/to/css2')
624                }
625                js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
626
627        class MyWidget6(MyWidget1):
628            def _media(self):
629                return super(MyWidget6, self).media + Media(css={'all': ('/other/path',)}, js = ('/other/js',))
630            media = property(_media)
631
632        w6 = MyWidget6()
633        self.assertEqual(str(w6.media), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
634<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
635<link href="/other/path" type="text/css" media="all" rel="stylesheet" />
636<script type="text/javascript" src="/path/to/js1"></script>
637<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
638<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
639<script type="text/javascript" src="/other/js"></script>""")
640
641    def test_media_inheritance(self):
642        ###############################################################
643        # Inheritance of media
644        ###############################################################
645
646        # If a widget extends another but provides no media definition, it inherits the parent widget's media
647        class MyWidget1(TextInput):
648            class Media:
649                css = {
650                   'all': ('path/to/css1','/path/to/css2')
651                }
652                js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
653
654        class MyWidget7(MyWidget1):
655            pass
656
657        w7 = MyWidget7()
658        self.assertEqual(str(w7.media), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
659<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
660<script type="text/javascript" src="/path/to/js1"></script>
661<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
662<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>""")
663
664        # If a widget extends another but defines media, it extends the parent widget's media by default
665        class MyWidget8(MyWidget1):
666            class Media:
667                css = {
668                   'all': ('/path/to/css3','path/to/css1')
669                }
670                js = ('/path/to/js1','/path/to/js4')
671
672        w8 = MyWidget8()
673        self.assertEqual(str(w8.media), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
674<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
675<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
676<script type="text/javascript" src="/path/to/js1"></script>
677<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
678<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
679<script type="text/javascript" src="/path/to/js4"></script>""")
680
681    def test_media_inheritance_from_property(self):
682        # If a widget extends another but defines media, it extends the parents widget's media,
683        # even if the parent defined media using a property.
684        class MyWidget1(TextInput):
685            class Media:
686                css = {
687                   'all': ('path/to/css1','/path/to/css2')
688                }
689                js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
690
691        class MyWidget4(TextInput):
692            def _media(self):
693                return Media(css={'all': ('/some/path',)}, js = ('/some/js',))
694            media = property(_media)
695
696        class MyWidget9(MyWidget4):
697            class Media:
698                css = {
699                    'all': ('/other/path',)
700                }
701                js = ('/other/js',)
702
703        w9 = MyWidget9()
704        self.assertEqual(str(w9.media), """<link href="/some/path" type="text/css" media="all" rel="stylesheet" />
705<link href="/other/path" type="text/css" media="all" rel="stylesheet" />
706<script type="text/javascript" src="/some/js"></script>
707<script type="text/javascript" src="/other/js"></script>""")
708
709        # A widget can disable media inheritance by specifying 'extend=False'
710        class MyWidget10(MyWidget1):
711            class Media:
712                extend = False
713                css = {
714                   'all': ('/path/to/css3','path/to/css1')
715                }
716                js = ('/path/to/js1','/path/to/js4')
717
718        w10 = MyWidget10()
719        self.assertEqual(str(w10.media), """<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
720<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
721<script type="text/javascript" src="/path/to/js1"></script>
722<script type="text/javascript" src="/path/to/js4"></script>""")
723
724    def test_media_inheritance_extends(self):
725        # A widget can explicitly enable full media inheritance by specifying 'extend=True'
726        class MyWidget1(TextInput):
727            class Media:
728                css = {
729                   'all': ('path/to/css1','/path/to/css2')
730                }
731                js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
732
733        class MyWidget11(MyWidget1):
734            class Media:
735                extend = True
736                css = {
737                   'all': ('/path/to/css3','path/to/css1')
738                }
739                js = ('/path/to/js1','/path/to/js4')
740
741        w11 = MyWidget11()
742        self.assertEqual(str(w11.media), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
743<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
744<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
745<script type="text/javascript" src="/path/to/js1"></script>
746<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
747<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
748<script type="text/javascript" src="/path/to/js4"></script>""")
749
750    def test_media_inheritance_single_type(self):
751        # A widget can enable inheritance of one media type by specifying extend as a tuple
752        class MyWidget1(TextInput):
753            class Media:
754                css = {
755                   'all': ('path/to/css1','/path/to/css2')
756                }
757                js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
758
759        class MyWidget12(MyWidget1):
760            class Media:
761                extend = ('css',)
762                css = {
763                   'all': ('/path/to/css3','path/to/css1')
764                }
765                js = ('/path/to/js1','/path/to/js4')
766
767        w12 = MyWidget12()
768        self.assertEqual(str(w12.media), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
769<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
770<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
771<script type="text/javascript" src="/path/to/js1"></script>
772<script type="text/javascript" src="/path/to/js4"></script>""")
773
774    def test_multi_media(self):
775        ###############################################################
776        # Multi-media handling for CSS
777        ###############################################################
778
779        # A widget can define CSS media for multiple output media types
780        class MultimediaWidget(TextInput):
781            class Media:
782                css = {
783                   'screen, print': ('/file1','/file2'),
784                   'screen': ('/file3',),
785                   'print': ('/file4',)
786                }
787                js = ('/path/to/js1','/path/to/js4')
788
789        multimedia = MultimediaWidget()
790        self.assertEqual(str(multimedia.media), """<link href="/file4" type="text/css" media="print" rel="stylesheet" />
791<link href="/file3" type="text/css" media="screen" rel="stylesheet" />
792<link href="/file1" type="text/css" media="screen, print" rel="stylesheet" />
793<link href="/file2" type="text/css" media="screen, print" rel="stylesheet" />
794<script type="text/javascript" src="/path/to/js1"></script>
795<script type="text/javascript" src="/path/to/js4"></script>""")
796
797    def test_multi_widget(self):
798        ###############################################################
799        # Multiwidget media handling
800        ###############################################################
801
802        class MyWidget1(TextInput):
803            class Media:
804                css = {
805                   'all': ('path/to/css1','/path/to/css2')
806                }
807                js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
808
809        class MyWidget2(TextInput):
810            class Media:
811                css = {
812                   'all': ('/path/to/css2','/path/to/css3')
813                }
814                js = ('/path/to/js1','/path/to/js4')
815
816        class MyWidget3(TextInput):
817            class Media:
818                css = {
819                   'all': ('/path/to/css3','path/to/css1')
820                }
821                js = ('/path/to/js1','/path/to/js4')
822
823        # MultiWidgets have a default media definition that gets all the
824        # media from the component widgets
825        class MyMultiWidget(MultiWidget):
826            def __init__(self, attrs=None):
827                widgets = [MyWidget1, MyWidget2, MyWidget3]
828                super(MyMultiWidget, self).__init__(widgets, attrs)
829
830        mymulti = MyMultiWidget()
831        self.assertEqual(str(mymulti.media), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
832<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
833<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
834<script type="text/javascript" src="/path/to/js1"></script>
835<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
836<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
837<script type="text/javascript" src="/path/to/js4"></script>""")
838
839    def test_form_media(self):
840        ###############################################################
841        # Media processing for forms
842        ###############################################################
843
844        class MyWidget1(TextInput):
845            class Media:
846                css = {
847                   'all': ('path/to/css1','/path/to/css2')
848                }
849                js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
850
851        class MyWidget2(TextInput):
852            class Media:
853                css = {
854                   'all': ('/path/to/css2','/path/to/css3')
855                }
856                js = ('/path/to/js1','/path/to/js4')
857
858        class MyWidget3(TextInput):
859            class Media:
860                css = {
861                   'all': ('/path/to/css3','path/to/css1')
862                }
863                js = ('/path/to/js1','/path/to/js4')
864
865        # You can ask a form for the media required by its widgets.
866        class MyForm(Form):
867            field1 = CharField(max_length=20, widget=MyWidget1())
868            field2 = CharField(max_length=20, widget=MyWidget2())
869        f1 = MyForm()
870        self.assertEqual(str(f1.media), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
871<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
872<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
873<script type="text/javascript" src="/path/to/js1"></script>
874<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
875<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
876<script type="text/javascript" src="/path/to/js4"></script>""")
877
878        # Form media can be combined to produce a single media definition.
879        class AnotherForm(Form):
880            field3 = CharField(max_length=20, widget=MyWidget3())
881        f2 = AnotherForm()
882        self.assertEqual(str(f1.media + f2.media), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
883<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
884<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
885<script type="text/javascript" src="/path/to/js1"></script>
886<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
887<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
888<script type="text/javascript" src="/path/to/js4"></script>""")
889
890        # Forms can also define media, following the same rules as widgets.
891        class FormWithMedia(Form):
892            field1 = CharField(max_length=20, widget=MyWidget1())
893            field2 = CharField(max_length=20, widget=MyWidget2())
894            class Media:
895                js = ('/some/form/javascript',)
896                css = {
897                    'all': ('/some/form/css',)
898                }
899        f3 = FormWithMedia()
900        self.assertEqual(str(f3.media), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
901<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
902<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
903<link href="/some/form/css" type="text/css" media="all" rel="stylesheet" />
904<script type="text/javascript" src="/path/to/js1"></script>
905<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
906<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
907<script type="text/javascript" src="/path/to/js4"></script>
908<script type="text/javascript" src="/some/form/javascript"></script>""")
909
910        # Media works in templates
911        from django.template import Template, Context
912        self.assertEqual(Template("{{ form.media.js }}{{ form.media.css }}").render(Context({'form': f3})), """<script type="text/javascript" src="/path/to/js1"></script>
913<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
914<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
915<script type="text/javascript" src="/path/to/js4"></script>
916<script type="text/javascript" src="/some/form/javascript"></script><link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
917<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
918<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
919<link href="/some/form/css" type="text/css" media="all" rel="stylesheet" />""")
920