1# -*- coding: utf-8 -*-
2
3import datetime
4import iptools
5import re
6
7from django.conf import settings
8from django.contrib import admin
9from django.contrib.admin.models import CHANGE, LogEntry
10from django.contrib.auth.models import AnonymousUser, Permission
11from django.contrib.contenttypes.models import ContentType
12from django.template.defaultfilters import truncatewords
13from django.test import TestCase
14from django.test.client import RequestFactory
15from django.test.utils import override_settings
16from django.urls import reverse
17from django.utils.encoding import force_text
18from django.utils.functional import lazy
19from django.utils.html import escape
20from django.utils.translation import ugettext_lazy as _
21
22from cms.api import create_page, create_title, add_plugin
23from cms.admin.forms import RequestToolbarForm
24from cms.cms_toolbars import (ADMIN_MENU_IDENTIFIER, ADMINISTRATION_BREAK, get_user_model,
25                              LANGUAGE_MENU_IDENTIFIER)
26from cms.middleware.toolbar import ToolbarMiddleware
27from cms.constants import PUBLISHER_STATE_DIRTY
28from cms.models import Page, UserSettings, PagePermission
29from cms.test_utils.project.placeholderapp.models import Example1, CharPksExample
30from cms.test_utils.project.placeholderapp.views import detail_view, detail_view_char, ClassDetail
31from cms.test_utils.testcases import (CMSTestCase,
32                                      URL_CMS_PAGE_ADD, URL_CMS_PAGE_CHANGE,
33                                      URL_CMS_USERSETTINGS)
34from cms.test_utils.util.context_managers import UserLoginContext
35from cms.toolbar_pool import toolbar_pool
36from cms.toolbar.items import (ToolbarAPIMixin, LinkItem, ItemSearchResult,
37                               Break, SubMenu, AjaxItem)
38from cms.toolbar.toolbar import CMSToolbar
39from cms.utils.conf import get_cms_setting
40from cms.utils.i18n import get_language_tuple
41from cms.utils.urlutils import admin_reverse
42from cms.views import details
43
44
45class ToolbarTestBase(CMSTestCase):
46
47    def get_page_request(self, page, user, path=None, edit=False,
48                         preview=False, structure=False, lang_code='en', disable=False):
49        if not path:
50            path = page.get_absolute_url()
51
52        if edit:
53            path += '?%s' % get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON')
54
55        if structure:
56            path += '?%s' % get_cms_setting('CMS_TOOLBAR_URL__BUILD')
57
58        if preview:
59            path += '?preview'
60
61        request = RequestFactory().get(path)
62        request.session = {}
63        request.user = user
64        request.LANGUAGE_CODE = lang_code
65        if edit:
66            request.GET = {'edit': None}
67        else:
68            request.GET = {'edit_off': None}
69        if disable:
70            request.GET[get_cms_setting('CMS_TOOLBAR_URL__DISABLE')] = None
71        request.current_page = page
72        mid = ToolbarMiddleware()
73        mid.process_request(request)
74        if hasattr(request,'toolbar'):
75            request.toolbar.populate()
76        return request
77
78    def get_anon(self):
79        return AnonymousUser()
80
81    def get_staff(self):
82        staff = self._create_user('staff', True, False)
83        staff.user_permissions.add(Permission.objects.get(codename='change_page'))
84        return staff
85
86    def get_nonstaff(self):
87        nonstaff = self._create_user('nonstaff')
88        nonstaff.user_permissions.add(Permission.objects.get(codename='change_page'))
89        return nonstaff
90
91    def get_superuser(self):
92        superuser = self._create_user('superuser', True, True)
93        return superuser
94
95    def _fake_logentry(self, instance_id, user, text, model=Page):
96        LogEntry.objects.log_action(
97            user_id=user.id,
98            content_type_id=ContentType.objects.get_for_model(model).pk,
99            object_id=instance_id,
100            object_repr=text,
101            action_flag=CHANGE,
102        )
103        entry = LogEntry.objects.filter(user=user, object_id=instance_id, action_flag__in=(CHANGE,))[0]
104        session = self.client.session
105        session['cms_log_latest'] = entry.pk
106        session.save()
107
108
109@override_settings(ROOT_URLCONF='cms.test_utils.project.nonroot_urls')
110class ToolbarMiddlewareTest(ToolbarTestBase):
111    @override_settings(CMS_TOOLBAR_HIDE=False)
112    def test_no_app_setted_show_toolbar_in_non_cms_urls(self):
113        request = self.get_page_request(None, self.get_anon(), '/en/example/')
114        self.assertTrue(hasattr(request, 'toolbar'))
115
116    @override_settings(CMS_TOOLBAR_HIDE=False)
117    def test_no_app_setted_show_toolbar_in_cms_urls(self):
118        page = create_page('foo', 'col_two.html', 'en', published=True)
119        request = self.get_page_request(page, self.get_anon())
120        self.assertTrue(hasattr(request, 'toolbar'))
121
122    @override_settings(CMS_TOOLBAR_HIDE=False)
123    def test_app_setted_hide_toolbar_in_non_cms_urls_toolbar_hide_unsetted(self):
124        request = self.get_page_request(None, self.get_anon(), '/en/example/')
125        self.assertTrue(hasattr(request, 'toolbar'))
126
127    @override_settings(CMS_TOOLBAR_HIDE=True)
128    def test_app_setted_hide_toolbar_in_non_cms_urls(self):
129        request = self.get_page_request(None, self.get_anon(), '/en/example/')
130        self.assertFalse(hasattr(request, 'toolbar'))
131
132    @override_settings(CMS_TOOLBAR_HIDE=False)
133    def test_app_setted_show_toolbar_in_cms_urls(self):
134        page = create_page('foo', 'col_two.html', 'en', published=True)
135        page = create_page('foo', 'col_two.html', 'en', published=True, parent=page)
136        request = self.get_page_request(page, self.get_anon())
137        self.assertTrue(hasattr(request, 'toolbar'))
138
139    @override_settings(CMS_TOOLBAR_HIDE=True)
140    def test_app_setted_show_toolbar_in_cms_urls_subpage(self):
141        page = create_page('foo', 'col_two.html', 'en', published=True)
142        page = create_page('foo', 'col_two.html', 'en', published=True, parent=page)
143        request = self.get_page_request(page, self.get_anon())
144        self.assertTrue(hasattr(request, 'toolbar'))
145
146    def test_cms_internal_ips_unset(self):
147        with self.settings(CMS_INTERNAL_IPS=[]):
148            request = self.get_page_request(None, self.get_staff(), '/en/example/')
149            self.assertTrue(hasattr(request, 'toolbar'))
150
151    def test_cms_internal_ips_set_no_match(self):
152        with self.settings(CMS_INTERNAL_IPS=['123.45.67.89', ]):
153            request = self.get_page_request(None, self.get_staff(), '/en/example/')
154            self.assertFalse(hasattr(request, 'toolbar'))
155
156    def test_cms_internal_ips_set_match(self):
157        with self.settings(CMS_INTERNAL_IPS=['127.0.0.0', '127.0.0.1', '127.0.0.2', ]):
158            request = self.get_page_request(None, self.get_staff(), '/en/example/')
159            self.assertTrue(hasattr(request, 'toolbar'))
160
161    def test_cms_internal_ips_iptools(self):
162        with self.settings(CMS_INTERNAL_IPS=iptools.IpRangeList(('127.0.0.0', '127.0.0.255'))):
163            request = self.get_page_request(None, self.get_staff(), '/en/example/')
164            self.assertTrue(hasattr(request, 'toolbar'))
165
166    def test_cms_internal_ips_iptools_bad_range(self):
167        with self.settings(CMS_INTERNAL_IPS=iptools.IpRangeList(('128.0.0.0', '128.0.0.255'))):
168            request = self.get_page_request(None, self.get_staff(), '/en/example/')
169            self.assertFalse(hasattr(request, 'toolbar'))
170
171
172@override_settings(CMS_PERMISSION=False)
173class ToolbarTests(ToolbarTestBase):
174
175    def get_page_item(self, toolbar):
176        items = toolbar.get_left_items() + toolbar.get_right_items()
177        page_item = [item for item in items if force_text(item.name) == 'Page']
178        self.assertEqual(len(page_item), 1)
179        return page_item[0]
180
181    def test_toolbar_login(self):
182        admin = self.get_superuser()
183        endpoint = reverse('cms_login') + '?next=/en/admin/'
184        username = getattr(admin, get_user_model().USERNAME_FIELD)
185        password = getattr(admin, get_user_model().USERNAME_FIELD)
186        response = self.client.post(endpoint, data={'username': username, 'password': password})
187        self.assertRedirects(response, '/en/admin/')
188        self.assertTrue(settings.SESSION_COOKIE_NAME in response.cookies)
189
190    def test_toolbar_login_non_staff(self):
191        admin = self.get_nonstaff()
192        endpoint = reverse('cms_login') + '?next=/en/admin/'
193        username = getattr(admin, get_user_model().USERNAME_FIELD)
194        password = getattr(admin, get_user_model().USERNAME_FIELD)
195        response = self.client.post(endpoint, data={'username': username, 'password': password})
196        self.assertRedirects(response, '/en/admin/?cms_toolbar_login_error=1', target_status_code=302)
197        self.assertFalse(settings.SESSION_COOKIE_NAME in response.cookies)
198
199    def test_toolbar_login_error(self):
200        admin = self.get_superuser()
201        endpoint = reverse('cms_login') + '?next=/en/admin/'
202        username = getattr(admin, get_user_model().USERNAME_FIELD)
203        response = self.client.post(endpoint, data={'username': username, 'password': 'invalid'})
204        self.assertRedirects(response, '/en/admin/?cms_toolbar_login_error=1', target_status_code=302)
205        self.assertFalse(settings.SESSION_COOKIE_NAME in response.cookies)
206
207    def test_toolbar_login_invalid_redirect_to(self):
208        admin = self.get_superuser()
209        endpoint = reverse('cms_login') + '?next=http://example.com'
210        username = getattr(admin, get_user_model().USERNAME_FIELD)
211        password = getattr(admin, get_user_model().USERNAME_FIELD)
212        response = self.client.post(endpoint, data={'username': username, 'password': password})
213        self.assertRedirects(response, '/en/')
214        self.assertTrue(settings.SESSION_COOKIE_NAME in response.cookies)
215
216    @override_settings(CMS_TOOLBARS=['cms.test_utils.project.sampleapp.cms_toolbars.ToolbarWithMedia'])
217    def test_toolbar_media(self):
218        """
219        Toolbar classes can declare a media class or property
220        to be rendered along with the toolbar.
221        """
222        old_pool = toolbar_pool.toolbars
223        toolbar_pool.clear()
224        cms_page = create_page("toolbar-page", "col_two.html", "en", published=True)
225
226        with self.login_user_context(self.get_superuser()):
227            endpoint = cms_page.get_absolute_url() + '?' + get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON')
228            response = self.client.get(endpoint)
229            self.assertContains(response, '<script type="text/javascript" src="/static/samplemap/js/sampleapp.js"></script>')
230            self.assertContains(response, '<link href="/static/samplemap/css/sampleapp.css"')
231        toolbar_pool.toolbars = old_pool
232        toolbar_pool._discovered = True
233
234    def test_toolbar_request_endpoint_validation(self):
235        endpoint = self.get_admin_url(UserSettings, 'get_toolbar')
236        cms_page = create_page("toolbar-page", "col_two.html", "en", published=True)
237        cms_page_2 = create_page("toolbar-page-2", "col_two.html", "en", published=True)
238
239        with self.login_user_context(self.get_superuser()):
240            response = self.client.get(
241                endpoint,
242                data={
243                    'obj_id': cms_page.pk,
244                    'obj_type': 'cms.page',
245                    'cms_path': cms_page.get_absolute_url('en')
246                },
247            )
248            self.assertEqual(response.status_code, 200)
249
250            # Invalid app / model
251            response = self.client.get(
252                endpoint,
253                data={
254                    'obj_id': cms_page.pk,
255                    'obj_type': 'cms.somemodel',
256                    'cms_path': cms_page.get_absolute_url('en')
257                },
258            )
259            self.assertEqual(response.status_code, 400)
260
261            # Page from path does not match attached toolbar obj
262            response = self.client.get(
263                endpoint,
264                data={
265                    'obj_id': cms_page.pk,
266                    'obj_type': 'cms.page',
267                    'cms_path': cms_page_2.get_absolute_url('en')
268                },
269            )
270            self.assertEqual(response.status_code, 400)
271
272    def test_toolbar_request_form(self):
273        cms_page = create_page("toolbar-page", "col_two.html", "en", published=True)
274        generic_obj = Example1.objects.create(
275            char_1="char_1",
276            char_2="char_2",
277            char_3="char_3",
278            char_4="char_4",
279        )
280
281        # Valid forms
282        form = RequestToolbarForm({
283            'obj_id': cms_page.pk,
284            'obj_type': 'cms.page',
285            'cms_path': cms_page.get_absolute_url('en'),
286        })
287        self.assertTrue(form.is_valid())
288        self.assertEqual(form.cleaned_data['attached_obj'], cms_page)
289
290        form = RequestToolbarForm({
291            'obj_id': generic_obj.pk,
292            'obj_type': 'placeholderapp.example1',
293            'cms_path': cms_page.get_absolute_url('en'),
294        })
295        self.assertTrue(form.is_valid())
296        self.assertEqual(form.cleaned_data['attached_obj'], generic_obj)
297
298        # Invalid forms
299        form = RequestToolbarForm({
300            'obj_id': 1000,
301            'obj_type': 'cms.page',
302            'cms_path': cms_page.get_absolute_url('en'),
303        })
304        self.assertFalse(form.is_valid())
305
306        form = RequestToolbarForm({
307            'obj_id': cms_page.pk,
308            'obj_type': 'cms.somemodel',
309            'cms_path': cms_page.get_absolute_url('en'),
310        })
311        self.assertFalse(form.is_valid())
312
313        form = RequestToolbarForm({
314            'obj_id': cms_page.pk,
315            'obj_type': 'cms.page',
316            'cms_path': 'https://example.com/some-path/',
317        })
318        self.assertFalse(form.is_valid())
319
320    def test_no_page_anon(self):
321        request = self.get_page_request(None, self.get_anon(), '/')
322        toolbar = CMSToolbar(request)
323        toolbar.populate()
324        toolbar.post_template_populate()
325        items = toolbar.get_left_items() + toolbar.get_right_items()
326        self.assertEqual(len(items), 0)
327
328    def test_no_page_staff(self):
329        request = self.get_page_request(None, self.get_staff(), '/')
330        toolbar = CMSToolbar(request)
331        toolbar.populate()
332        toolbar.post_template_populate()
333        items = toolbar.get_left_items() + toolbar.get_right_items()
334        # Logo + admin-menu + logout
335        self.assertEqual(len(items), 3, items)
336        admin_items = toolbar.get_or_create_menu(ADMIN_MENU_IDENTIFIER, 'Test').get_items()
337        self.assertEqual(len(admin_items), 12, admin_items)
338
339    def test_no_page_superuser(self):
340        request = self.get_page_request(None, self.get_superuser(), '/')
341        toolbar = CMSToolbar(request)
342        toolbar.populate()
343        toolbar.post_template_populate()
344        items = toolbar.get_left_items() + toolbar.get_right_items()
345        # Logo + edit-mode + admin-menu + logout
346        self.assertEqual(len(items), 3)
347        admin_items = toolbar.get_or_create_menu(ADMIN_MENU_IDENTIFIER, 'Test').get_items()
348        self.assertEqual(len(admin_items), 13, admin_items)
349
350    def test_anon(self):
351        page = create_page('test', 'nav_playground.html', 'en')
352        request = self.get_page_request(page, self.get_anon())
353        toolbar = CMSToolbar(request)
354
355        items = toolbar.get_left_items() + toolbar.get_right_items()
356        self.assertEqual(len(items), 0)
357
358    def test_nonstaff(self):
359        page = create_page('test', 'nav_playground.html', 'en', published=True)
360        request = self.get_page_request(page, self.get_nonstaff())
361        toolbar = CMSToolbar(request)
362        items = toolbar.get_left_items() + toolbar.get_right_items()
363        # Logo + edit-mode + logout
364        self.assertEqual(len(items), 0)
365
366    @override_settings(CMS_PERMISSION=True)
367    def test_template_change_permission(self):
368        page = create_page('test', 'nav_playground.html', 'en', published=True)
369
370        # Staff user with change page permissions only
371        staff_user = self.get_staff_user_with_no_permissions()
372        self.add_permission(staff_user, 'change_page')
373        global_permission = self.add_global_permission(staff_user, can_change=True, can_delete=True)
374
375        # User should not see "Templates" option because he only has
376        # "change" permission.
377        request = self.get_page_request(page, staff_user, edit=True)
378        toolbar = CMSToolbar(request)
379        page_item = self.get_page_item(toolbar)
380        template_item = [item for item in page_item.items
381                         if force_text(getattr(item, 'name', '')) == 'Templates']
382        self.assertEqual(len(template_item), 0)
383
384        # Give the user change advanced settings permission
385        global_permission.can_change_advanced_settings = True
386        global_permission.save()
387
388        # Reload user to avoid stale caches
389        staff_user = self.reload(staff_user)
390
391        # User should see "Templates" option because
392        # he has "change advanced settings" permission
393        request = self.get_page_request(page, staff_user, edit=True)
394        toolbar = CMSToolbar(request)
395        page_item = self.get_page_item(toolbar)
396        template_item = [item for item in page_item.items
397                         if force_text(getattr(item, 'name', '')) == 'Templates']
398        self.assertEqual(len(template_item), 1)
399
400    def test_markup(self):
401        page = create_page("toolbar-page", "nav_playground.html", "en", published=True)
402        page_edit_on_url = self.get_edit_on_url(page.get_absolute_url())
403        superuser = self.get_superuser()
404
405        with self.login_user_context(superuser):
406            response = self.client.get(page_edit_on_url)
407        self.assertEqual(response.status_code, 200)
408        self.assertTemplateUsed(response, 'nav_playground.html')
409        self.assertContains(response, '<div id="cms-top"')
410        self.assertContains(response, 'cms.base.css')
411
412    def test_live_draft_markup_on_app_page(self):
413        """
414        Checks that the "edit page" button shows up
415        on non-cms pages with app placeholders and no static placeholders.
416        """
417        superuser = self.get_superuser()
418
419        output = (
420            '<a class="cms-btn cms-btn-action cms-btn-switch-edit" '
421            'href="/en/example/latest/?{}">Edit</a>'
422        ).format(get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON'))
423
424        Example1.objects.create(
425            char_1="char_1",
426            char_2="char_2",
427            char_3="char_3",
428            char_4="char_4",
429        )
430
431        with self.login_user_context(superuser):
432            response = self.client.get('/en/example/latest/?%s' % get_cms_setting('CMS_TOOLBAR_URL__EDIT_OFF'))
433        self.assertEqual(response.status_code, 200)
434        self.assertContains(response, output, html=True)
435
436    def test_markup_generic_module(self):
437        page = create_page("toolbar-page", "col_two.html", "en", published=True)
438        page_structure_url = self.get_obj_structure_url(page.get_absolute_url())
439        superuser = self.get_superuser()
440
441        with self.login_user_context(superuser):
442            response = self.client.get(page_structure_url)
443
444        self.assertEqual(response.status_code, 200)
445        self.assertContains(response, '<div class="cms-submenu-item cms-submenu-item-title"><span>Generic</span>')
446
447    def test_markup_link_custom_module(self):
448        superuser = self.get_superuser()
449        page = create_page("toolbar-page", "col_two.html", "en", published=True)
450        page_structure_url = self.get_obj_structure_url(page.get_absolute_url())
451
452        with self.login_user_context(superuser):
453            response = self.client.get(page_structure_url)
454
455        self.assertEqual(response.status_code, 200)
456        self.assertContains(response, 'href="LinkPlugin">')
457        self.assertContains(response,
458                            '<div class="cms-submenu-item cms-submenu-item-title"><span>Different Grouper</span>')
459
460    def test_extra_placeholder_menu_items(self):
461        superuser = self.get_superuser()
462        page = create_page("toolbar-page", "col_two.html", "en", published=True)
463        page_structure_url = self.get_obj_structure_url(page.get_absolute_url())
464
465        with self.login_user_context(superuser):
466            response = self.client.get(page_structure_url)
467
468        self.assertEqual(response.status_code, 200)
469        self.assertContains(
470            response,
471            '<div class="cms-submenu-item"><a href="/some/url/" data-rel="ajax"'
472        )
473        self.assertContains(
474            response,
475            'data-on-success="REFRESH_PAGE" data-cms-icon="whatever" >Data item - not usable</a></div>'
476        )
477        self.assertContains(
478            response,
479            '<div class="cms-submenu-item"><a href="/some/other/url/" data-rel="ajax_add"'
480        )
481
482    def test_markup_toolbar_url_page(self):
483        superuser = self.get_superuser()
484        page_1 = create_page("top-page", "col_two.html", "en", published=True)
485        page_2 = create_page("sec-page", "col_two.html", "en", published=True, parent=page_1)
486        page_3 = create_page("trd-page", "col_two.html", "en", published=False, parent=page_1)
487
488        # page with publish = draft
489        # check when in draft mode
490        with self.login_user_context(superuser):
491            response = self.client.get('%s?%s' % (
492                page_2.get_absolute_url(), get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON')))
493        self.assertEqual(response.status_code, 200)
494        self.assertContains(response, 'href="%s?preview&amp;%s"' % (
495            page_2.get_public_url(), get_cms_setting('CMS_TOOLBAR_URL__EDIT_OFF')
496        ))
497        # check when in live mode
498        with self.login_user_context(superuser):
499            response = self.client.get('%s?preview&%s' % (
500                page_2.get_absolute_url(), get_cms_setting('CMS_TOOLBAR_URL__EDIT_OFF')))
501        self.assertEqual(response.status_code, 200)
502        self.assertContains(response, 'href="%s?%s"' % (
503            page_2.get_draft_url(), get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON')
504        ))
505        self.assertEqual(page_2.get_draft_url(), page_2.get_public_url())
506
507        # page with publish != draft
508        page_2.get_title_obj().slug = 'mod-page'
509        page_2.get_title_obj().path = 'top-page/mod-page'
510        page_2.get_title_obj().save()
511        # check when in draft mode
512        with self.login_user_context(superuser):
513            response = self.client.get('%s?%s' % (
514                page_2.get_absolute_url(), get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON')))
515        self.assertEqual(response.status_code, 200)
516        self.assertContains(response, 'href="%s?preview&amp;%s"' % (
517            page_2.get_public_url(), get_cms_setting('CMS_TOOLBAR_URL__EDIT_OFF')
518        ))
519        # check when in live mode
520        with self.login_user_context(superuser):
521            response = self.client.get('%s?preview&%s' % (
522                page_2.get_public_url(), get_cms_setting('CMS_TOOLBAR_URL__EDIT_OFF')))
523        self.assertEqual(response.status_code, 200)
524        self.assertContains(response, 'href="%s?%s"' % (
525            page_2.get_draft_url(), get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON')
526        ))
527        self.assertNotEqual(page_2.get_draft_url(), page_2.get_public_url())
528
529        # not published page
530        # check when in draft mode
531        with self.login_user_context(superuser):
532            response = self.client.get('%s?%s' % (
533                page_3.get_absolute_url(), get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON')))
534        self.assertEqual(response.status_code, 200)
535        self.assertNotContains(response, 'cms-toolbar-item-switch')
536        self.assertEqual(page_3.get_public_url(), '')
537        self.assertNotEqual(page_3.get_draft_url(), page_3.get_public_url())
538
539    def test_markup_plugin_template(self):
540        page = create_page("toolbar-page-1", "col_two.html", "en", published=True)
541        page_edit_on_url = self.get_edit_on_url(page.get_absolute_url())
542        plugin_1 = add_plugin(page.placeholders.get(slot='col_left'), language='en',
543                              plugin_type='TestPluginAlpha', alpha='alpha')
544        plugin_2 = add_plugin(page.placeholders.get(slot='col_left'), language='en',
545                              plugin_type='TextPlugin', body='text')
546        superuser = self.get_superuser()
547        with self.login_user_context(superuser):
548            response = self.client.get(page_edit_on_url)
549        self.assertEqual(response.status_code, 200)
550        response_text = response.render().rendered_content
551        self.assertTrue(re.search('edit_plugin.+/admin/custom/view/%s' % plugin_1.pk, response_text))
552        self.assertTrue(re.search('move_plugin.+/admin/custom/move/', response_text))
553        self.assertTrue(re.search('delete_plugin.+/admin/custom/delete/%s/' % plugin_1.pk, response_text))
554        self.assertTrue(re.search('add_plugin.+/admin/custom/view/', response_text))
555        self.assertTrue(re.search('copy_plugin.+/admin/custom/copy/', response_text))
556
557        self.assertTrue(re.search('edit_plugin.+/en/admin/cms/page/edit-plugin/%s' % plugin_2.pk, response_text))
558        self.assertTrue(re.search('delete_plugin.+/en/admin/cms/page/delete-plugin/%s/' % plugin_2.pk, response_text))
559
560    def test_show_toolbar_to_staff(self):
561        page = create_page("toolbar-page", "nav_playground.html", "en",
562                           published=True)
563        staff = self.get_staff()
564        assert staff.user_permissions.get().name == 'Can change page'
565        request = self.get_page_request(page, staff, '/')
566        toolbar = CMSToolbar(request)
567        self.assertTrue(toolbar.show_toolbar)
568
569    def test_show_toolbar_with_edit(self):
570        page = create_page("toolbar-page", "nav_playground.html", "en",
571                           published=True)
572        request = self.get_page_request(page, AnonymousUser(), edit=True)
573        toolbar = CMSToolbar(request)
574        self.assertTrue(toolbar.show_toolbar)
575
576    def test_show_toolbar_staff(self):
577        page = create_page("toolbar-page", "nav_playground.html", "en",
578                           published=True)
579        request = self.get_page_request(page, self.get_staff(), edit=True)
580        self.assertTrue(request.session.get('cms_edit', False))
581
582    def test_hide_toolbar_non_staff(self):
583        page = create_page("toolbar-page", "nav_playground.html", "en",
584                           published=True)
585        request = self.get_page_request(page, self.get_nonstaff(), edit=True)
586        self.assertNotIn('cms_edit', request.session)
587
588    def test_hide_toolbar_disabled(self):
589        page = create_page("toolbar-page", "nav_playground.html", "en",
590                           published=True)
591        # Edit mode should re-enable the toolbar in any case
592        request = self.get_page_request(page, self.get_staff(), edit=False, disable=True)
593        self.assertTrue(request.session.get('cms_toolbar_disabled'))
594        toolbar = CMSToolbar(request)
595        self.assertFalse(toolbar.show_toolbar)
596
597    def test_show_disabled_toolbar_with_edit(self):
598        page = create_page("toolbar-page", "nav_playground.html", "en",
599                           published=True)
600        request = self.get_page_request(page, self.get_staff(), edit=True, disable=True)
601        self.assertFalse(request.session.get('cms_toolbar_disabled'))
602        toolbar = CMSToolbar(request)
603        self.assertTrue(toolbar.show_toolbar)
604
605    def test_toolbar_login_redirect_validation(self):
606        user = self._create_user('toolbar', True, True)
607        username = getattr(user, user.USERNAME_FIELD)
608        page = create_page("toolbar-page", "nav_playground.html", "en", published=True)
609        page.set_as_homepage()
610        login_url = reverse('cms_login')
611        endpoint = '{}?next=https://notyourdomain.com'.format(login_url)
612        response = self.client.post(endpoint, {'username': username, 'password': username})
613        self.assertRedirects(response, page.get_absolute_url(), fetch_redirect_response=False)
614
615    def test_show_toolbar_login_anonymous(self):
616        page = create_page("toolbar-page", "nav_playground.html", "en", published=True)
617        page_edit_on_url = self.get_edit_on_url(page.get_absolute_url())
618        response = self.client.get(page_edit_on_url)
619        self.assertEqual(response.status_code, 200)
620        self.assertContains(response, 'cms-form-login')
621
622    @override_settings(CMS_TOOLBAR_ANONYMOUS_ON=False)
623    def test_hide_toolbar_login_anonymous_setting(self):
624        page = create_page("toolbar-page", "nav_playground.html", "en", published=True)
625        page_edit_on_url = self.get_edit_on_url(page.get_absolute_url())
626        response = self.client.get(page_edit_on_url)
627        self.assertEqual(response.status_code, 200)
628        self.assertNotContains(response, 'cms-form-login')
629
630    def test_hide_toolbar_login_nonstaff(self):
631        page = create_page("toolbar-page", "nav_playground.html", "en", published=True)
632        page_edit_on_url = self.get_edit_on_url(page.get_absolute_url())
633
634        with self.login_user_context(self.get_nonstaff()):
635            response = self.client.get(page_edit_on_url)
636        self.assertEqual(response.status_code, 200)
637        self.assertNotContains(response, 'cms-form-login')
638        self.assertNotContains(response, 'cms-toolbar')
639
640    def test_admin_logout_staff(self):
641        with override_settings(CMS_PERMISSION=True):
642            with self.login_user_context(self.get_staff()):
643                response = self.client.get('/en/admin/logout/?%s' % get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON'))
644                self.assertTrue(response.status_code, 200)
645
646    def test_show_toolbar_without_edit(self):
647        page = create_page("toolbar-page", "nav_playground.html", "en",
648                           published=True)
649        request = self.get_page_request(page, AnonymousUser(), edit=False)
650        toolbar = CMSToolbar(request)
651        self.assertFalse(toolbar.show_toolbar)
652
653    def test_publish_button(self):
654        page = create_page('test', 'nav_playground.html', 'en', published=True)
655        # Needed because publish button only shows if the page is dirty
656        page.set_publisher_state('en', state=PUBLISHER_STATE_DIRTY)
657
658        request = self.get_page_request(page, self.get_superuser(), edit=True)
659        toolbar = CMSToolbar(request)
660        toolbar.populate()
661        toolbar.post_template_populate()
662        self.assertTrue(toolbar.edit_mode_active)
663        items = toolbar.get_left_items() + toolbar.get_right_items()
664        self.assertEqual(len(items), 7)
665
666    def test_no_publish_button(self):
667        page = create_page('test', 'nav_playground.html', 'en', published=True)
668        user = self.get_staff()
669        request = self.get_page_request(page, user, edit=True)
670        toolbar = CMSToolbar(request)
671        toolbar.populate()
672        toolbar.post_template_populate()
673        self.assertTrue(page.has_change_permission(request.user))
674        self.assertFalse(page.has_publish_permission(request.user))
675        self.assertTrue(toolbar.edit_mode_active)
676        items = toolbar.get_left_items() + toolbar.get_right_items()
677        # Logo + templates + page-menu + admin-menu + logout
678        self.assertEqual(len(items), 5)
679
680        # adding back structure mode permission
681        permission = Permission.objects.get(codename='use_structure')
682        user.user_permissions.add(permission)
683
684        request.user = get_user_model().objects.get(pk=user.pk)
685        toolbar = CMSToolbar(request)
686        toolbar.populate()
687        toolbar.post_template_populate()
688        items = toolbar.get_left_items() + toolbar.get_right_items()
689        # Logo + edit mode + templates + page-menu + admin-menu + logout
690        self.assertEqual(len(items), 6)
691
692    def test_no_change_button(self):
693        page = create_page('test', 'nav_playground.html', 'en', published=True)
694        user = self.get_staff()
695        user.user_permissions.all().delete()
696        request = self.get_page_request(page, user, edit=True)
697        toolbar = CMSToolbar(request)
698        toolbar.populate()
699        toolbar.post_template_populate()
700        self.assertFalse(page.has_change_permission(request.user))
701        self.assertFalse(page.has_publish_permission(request.user))
702
703        items = toolbar.get_left_items() + toolbar.get_right_items()
704        # Logo + page-menu + admin-menu + logout
705        self.assertEqual(len(items), 4, items)
706        page_items = items[1].get_items()
707        # The page menu should only have the "Create page" item enabled.
708        self.assertFalse(page_items[0].disabled)
709        self.assertTrue(all(item.disabled for item in page_items[1:] if hasattr(item, 'disabled')))
710        admin_items = toolbar.get_or_create_menu(ADMIN_MENU_IDENTIFIER, 'Test').get_items()
711        self.assertEqual(len(admin_items), 14, admin_items)
712
713    def test_button_consistency_staff(self):
714        """
715        Tests that the buttons remain even when the language changes.
716        """
717        user = self.get_staff()
718        cms_page = create_page('test-en', 'nav_playground.html', 'en', published=True)
719        create_title('de', 'test-de', cms_page)
720        cms_page.publish('de')
721        en_request = self.get_page_request(cms_page, user, edit=True)
722        en_toolbar = CMSToolbar(en_request)
723        en_toolbar.populate()
724        en_toolbar.post_template_populate()
725        # Logo + templates + page-menu + admin-menu + logout
726        self.assertEqual(len(en_toolbar.get_left_items() + en_toolbar.get_right_items()), 5)
727        de_request = self.get_page_request(cms_page, user, path='/de/', edit=True, lang_code='de')
728        de_toolbar = CMSToolbar(de_request)
729        de_toolbar.populate()
730        de_toolbar.post_template_populate()
731        # Logo + templates + page-menu + admin-menu + logout
732        self.assertEqual(len(de_toolbar.get_left_items() + de_toolbar.get_right_items()), 5)
733
734    def test_double_menus(self):
735        """
736        Tests that even called multiple times, admin and language buttons are not duplicated
737        """
738        user = self.get_staff()
739        en_request = self.get_page_request(None, user, edit=True, path='/')
740        toolbar = CMSToolbar(en_request)
741        toolbar.populated = False
742        toolbar.populate()
743        toolbar.populated = False
744        toolbar.populate()
745        toolbar.populated = False
746        toolbar.post_template_populate()
747        admin = toolbar.get_left_items()[0]
748        lang = toolbar.get_left_items()[1]
749        self.assertEqual(len(admin.get_items()), 15)
750        self.assertEqual(len(lang.get_items()), len(get_language_tuple(1)))
751
752    @override_settings(CMS_PLACEHOLDER_CONF={'col_left': {'name': 'PPPP'}})
753    def test_placeholder_name(self):
754        superuser = self.get_superuser()
755        page = create_page("toolbar-page", "col_two.html", "en", published=True)
756        page_edit_on_url = self.get_edit_on_url(page.get_absolute_url())
757
758        with self.login_user_context(superuser):
759            response = self.client.get(page_edit_on_url)
760        self.assertEqual(response.status_code, 200)
761        self.assertContains(response, 'PPPP')
762
763    def test_user_settings(self):
764        superuser = self.get_superuser()
765        with self.login_user_context(superuser):
766            response = self.client.get(URL_CMS_USERSETTINGS)
767            self.assertEqual(response.status_code, 200)
768
769    def test_remove_lang(self):
770        page = create_page('test', 'nav_playground.html', 'en', published=True)
771        page_edit_on_url = self.get_edit_on_url(page.get_absolute_url())
772        superuser = self.get_superuser()
773        with self.login_user_context(superuser):
774            response = self.client.get(page_edit_on_url)
775            self.assertEqual(response.status_code, 200)
776            setting = UserSettings.objects.get(user=superuser)
777            setting.language = 'it'
778            setting.save()
779            with self.settings(LANGUAGES=(('en', 'english'),)):
780                response = self.client.get(page_edit_on_url)
781                self.assertEqual(response.status_code, 200)
782                self.assertNotContains(response, '/it/')
783
784    def test_get_alphabetical_insert_position(self):
785        page = create_page("toolbar-page", "nav_playground.html", "en",
786                           published=True)
787        request = self.get_page_request(page, self.get_staff(), '/')
788        toolbar = CMSToolbar(request)
789        toolbar.get_left_items()
790        toolbar.get_right_items()
791
792        admin_menu = toolbar.get_or_create_menu(ADMIN_MENU_IDENTIFIER, 'TestAppMenu')
793
794        # Insert alpha
795        alpha_position = admin_menu.get_alphabetical_insert_position('menu-alpha', SubMenu, None)
796
797        # As this will be the first item added to this, this use should return the default, or namely None
798        if not alpha_position:
799            alpha_position = admin_menu.find_first(Break, identifier=ADMINISTRATION_BREAK) + 1
800        admin_menu.get_or_create_menu('menu-alpha', 'menu-alpha', position=alpha_position)
801
802        # Insert gamma (should return alpha_position + 1)
803        gamma_position = admin_menu.get_alphabetical_insert_position('menu-gamma', SubMenu)
804        self.assertEqual(int(gamma_position), int(alpha_position) + 1)
805        admin_menu.get_or_create_menu('menu-gamma', 'menu-gamma', position=gamma_position)
806
807        # Where should beta go? It should go right where gamma is now...
808        beta_position = admin_menu.get_alphabetical_insert_position('menu-beta', SubMenu)
809        self.assertEqual(beta_position, gamma_position)
810
811    def test_out_of_order(self):
812        page = create_page("toolbar-page", "nav_playground.html", "en",
813                           published=True)
814        request = self.get_page_request(page, self.get_staff(), '/')
815        toolbar = CMSToolbar(request)
816        menu1 = toolbar.get_or_create_menu("test")
817        menu2 = toolbar.get_or_create_menu("test", "Test", side=toolbar.RIGHT, position=2)
818
819        self.assertEqual(menu1, menu2)
820        self.assertEqual(menu1.name, 'Test')
821        self.assertEqual(len(toolbar.get_right_items()), 1)
822
823    def test_negative_position_left(self):
824        page = create_page("toolbar-page", "nav_playground.html", "en", published=True)
825        request = self.get_page_request(page, self.get_staff(), '/')
826        toolbar = CMSToolbar(request)
827        # Starting point: [Menu:Example, Menu:Page, Menu:Language]
828        # Example @ 1, Page @ 2, Language @ -1
829        menu1 = toolbar.get_or_create_menu("menu1", "Menu1", side=toolbar.LEFT, position=-2)
830        menu2 = toolbar.get_or_create_menu("menu2", "Menu2", side=toolbar.LEFT, position=-3)
831        self.assertEqual(toolbar.get_left_items().index(menu1), 3)
832        self.assertEqual(toolbar.get_left_items().index(menu2), 2)
833
834    def test_negative_position_right(self):
835        page = create_page("toolbar-page", "nav_playground.html", "en", published=True)
836        request = self.get_page_request(page, self.get_staff(), '/')
837        toolbar = CMSToolbar(request)
838        # Starting point: [] (empty)
839        # Add a couple of "normal" menus
840        toolbar.get_or_create_menu("menu1", "Menu1", side=toolbar.RIGHT)
841        toolbar.get_or_create_menu("menu2", "Menu2", side=toolbar.RIGHT)
842        menu3 = toolbar.get_or_create_menu("menu3", "Menu3", side=toolbar.RIGHT, position=-1)
843        menu4 = toolbar.get_or_create_menu("menu4", "Menu4", side=toolbar.RIGHT, position=-2)
844        self.assertEqual(toolbar.get_right_items().index(menu3), 3)
845        self.assertEqual(toolbar.get_right_items().index(menu4), 2)
846
847    def test_page_create_redirect(self):
848        superuser = self.get_superuser()
849        page = self.create_homepage("home", "nav_playground.html", "en", published=True)
850        resolve_url_on = '%s?%s' % (admin_reverse('cms_page_resolve'),
851                                    get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON'))
852        resolve_url_off = '%s?%s' % (admin_reverse('cms_page_resolve'),
853                                     get_cms_setting('CMS_TOOLBAR_URL__EDIT_OFF'))
854        with self.login_user_context(superuser):
855            response = self.client.post(resolve_url_on, {'pk': '', 'model': 'cms.page'})
856            self.assertEqual(response.content.decode('utf-8'), '')
857            page_data = self.get_new_page_data(parent_id=page.node.pk)
858            response = self.client.post(self.get_admin_url(Page, 'add'), page_data)
859            self.assertRedirects(response, self.get_admin_url(Page, 'changelist'))
860
861            public_home = Page.objects.public().get(is_home=True)
862
863            # test redirection when toolbar is in edit mode
864            response = self.client.post(resolve_url_on, {'pk': public_home.pk,
865                                                         'model': 'cms.page'})
866            self.assertEqual(response.content.decode('utf-8'), '/en/test-page-1/')
867
868            self.client.post(URL_CMS_PAGE_ADD, page_data)
869
870            # test redirection when toolbar is not in edit mode
871            response = self.client.post(resolve_url_off, {'pk': public_home.pk,
872                                                          'model': 'cms.page'})
873            self.assertEqual(response.content.decode('utf-8'), '/en/')
874
875    def test_page_edit_redirect_editmode(self):
876        page1 = self.create_homepage("home", "nav_playground.html", "en", published=True)
877        page2 = create_page("test", "nav_playground.html", "en",
878                            published=True)
879        page3 = create_page("non-pub", "nav_playground.html", "en",
880                            published=False)
881        superuser = self.get_superuser()
882        with self.login_user_context(superuser):
883            page_data = self.get_new_page_data()
884            self.client.post(URL_CMS_PAGE_CHANGE % page2.pk, page_data)
885            url = '%s?%s' % (admin_reverse('cms_page_resolve'),
886                             get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON'))
887            # first call returns the latest modified page with updated slug even if a different
888            # page has been requested
889            response = self.client.post(url, {'pk': page1.pk, 'model': 'cms.page'})
890            self.assertEqual(response.content.decode('utf-8'), '/en/test-page-1/')
891            # following call returns the actual page requested
892            response = self.client.post(url, {'pk': page1.pk, 'model': 'cms.page'})
893            self.assertEqual(response.content.decode('utf-8'), '/en/')
894            # non published page - staff user can access it
895            response = self.client.post(url, {'pk': page3.pk, 'model': 'cms.page'})
896            self.assertEqual(response.content.decode('utf-8'), '/en/non-pub/')
897        # anonymous users should be redirected to the root page
898        response = self.client.post(url, {'pk': page3.pk, 'model': 'cms.page'})
899        self.assertEqual(response.content.decode('utf-8'), '/')
900
901    def test_page_edit_redirect_no_editmode(self):
902        page1 = create_page("home", "nav_playground.html", "en",
903                            published=True)
904        page2 = create_page("test", "nav_playground.html", "en",
905                            published=True, parent=page1)
906        page3 = create_page("non-pub-1", "nav_playground.html", "en",
907                            published=False, parent=page2)
908        page4 = create_page("non-pub-2", "nav_playground.html", "en",
909                            published=False, parent=page3)
910        superuser = self.get_superuser()
911        url = admin_reverse('cms_page_resolve')
912        with self.login_user_context(superuser):
913            # checking the redirect by passing URL parameters
914            # redirect to the same page
915            response = self.client.post(url, {'pk': page1.pk, 'model': 'cms.page'})
916            self.assertEqual(response.content.decode('utf-8'), page1.get_absolute_url())
917            # redirect to the same page
918            response = self.client.post(url, {'pk': page2.pk, 'model': 'cms.page'})
919            self.assertEqual(response.content.decode('utf-8'), page2.get_absolute_url())
920            # redirect to the first published ancestor
921            response = self.client.post(url, {'pk': page3.pk, 'model': 'cms.page'})
922            self.assertEqual(response.content.decode('utf-8'), '%s?%s' % (
923                page3.get_absolute_url(),
924                get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON'))
925            )
926            # redirect to the first published ancestor
927            response = self.client.post(url, {'pk': page4.pk, 'model': 'cms.page'})
928            self.assertEqual(response.content.decode('utf-8'), '%s?%s' % (
929                page4.get_absolute_url(),
930                get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON'))
931            )
932
933            # checking the redirect by setting the session data
934            self._fake_logentry(page1.get_draft_object().pk, superuser, 'test page')
935            response = self.client.post(url, {'pk': page2.pk, 'model': 'cms.page'})
936            self.assertEqual(response.content.decode('utf-8'), page1.get_public_object().get_absolute_url())
937
938            self._fake_logentry(page2.get_draft_object().pk, superuser, 'test page')
939            response = self.client.post(url, {'pk': page1.pk, 'model': 'cms.page'})
940            self.assertEqual(response.content.decode('utf-8'), page2.get_public_object().get_absolute_url())
941
942            self._fake_logentry(page3.get_draft_object().pk, superuser, 'test page')
943            response = self.client.post(url, {'pk': page1.pk, 'model': 'cms.page'})
944            self.assertEqual(response.content.decode('utf-8'), '%s?%s' % (
945                page3.get_absolute_url(),
946                get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON'))
947            )
948
949            self._fake_logentry(page4.get_draft_object().pk, superuser, 'test page')
950            response = self.client.post(url, {'pk': page1.pk, 'model': 'cms.page'})
951            self.assertEqual(response.content.decode('utf-8'), '%s?%s' % (
952                page4.get_absolute_url(),
953                get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON'))
954            )
955
956    def test_page_edit_redirect_errors(self):
957        page1 = create_page("home", "nav_playground.html", "en",
958                            published=True)
959        page2 = create_page("test", "nav_playground.html", "en",
960                            published=True, parent=page1)
961        create_page("non-pub", "nav_playground.html", "en",
962                    published=False, parent=page2)
963        superuser = self.get_superuser()
964        url = admin_reverse('cms_page_resolve')
965
966        with self.login_user_context(superuser):
967            # logentry - non existing id - parameter is used
968            self._fake_logentry(9999, superuser, 'test page')
969            response = self.client.post(url, {'pk': page2.pk, 'model': 'cms.page'})
970            self.assertEqual(response.content.decode('utf-8'), page2.get_public_object().get_absolute_url())
971            # parameters - non existing id - no redirection
972            response = self.client.post(url, {'pk': 9999, 'model': 'cms.page'})
973            self.assertEqual(response.content.decode('utf-8'), '')
974
975    def assertMenuItems(self, request, menu_id, name, items=None):
976        toolbar = CMSToolbar(request)
977        toolbar.populate()
978        menu = dict(
979            (force_text(getattr(item, 'name', '|')), item)
980            for item in toolbar.get_menu(menu_id).get_items()
981        )
982        self.assertIn(name, list(menu))
983        if items is not None:
984            sub_menu = list(
985                force_text(getattr(item, 'name', '|')) for item in menu[name].get_items()
986            )
987            self.assertEqual(sorted(sub_menu), sorted(items))
988
989    def test_remove_language(self):
990        page = create_page(
991            "toolbar-page", "nav_playground.html", "en", published=True
992        )
993        create_title(title="de page", language="de", page=page)
994        create_title(title="fr page", language="fr", page=page)
995
996        request = self.get_page_request(page, self.get_staff(), '/', edit=True)
997
998        self.assertMenuItems(
999            request, LANGUAGE_MENU_IDENTIFIER, 'Delete Translation',
1000            ['German...', 'English...', 'French...']
1001        )
1002
1003        reduced_langs = {
1004            1: [
1005                {
1006                    'code': 'en',
1007                    'name': 'English',
1008                    'fallbacks': ['fr', 'de'],
1009                    'public': True,
1010                },
1011                {
1012                    'code': 'fr',
1013                    'name': 'French',
1014                    'public': True,
1015                },
1016            ]
1017        }
1018
1019        with self.settings(CMS_LANGUAGES=reduced_langs):
1020            self.assertMenuItems(
1021                request, LANGUAGE_MENU_IDENTIFIER, 'Delete Translation',
1022                ['English...', 'French...']
1023            )
1024
1025    def test_add_language(self):
1026        page = create_page("tbp", "nav_playground.html", "en", published=True)
1027        request = self.get_page_request(page, self.get_staff(), '/', edit=True)
1028        self.assertMenuItems(
1029            request, LANGUAGE_MENU_IDENTIFIER, 'Add Translation',
1030            [u'German...', u'Brazilian Portuguese...', u'French...', u'Espa\xf1ol...']
1031        )
1032
1033        create_title(title="de page", language="de", page=page)
1034        create_title(title="fr page", language="fr", page=page)
1035        self.assertMenuItems(
1036            request, LANGUAGE_MENU_IDENTIFIER, 'Add Translation',
1037            [u'Brazilian Portuguese...', u'Espa\xf1ol...']
1038        )
1039
1040    def test_copy_plugins(self):
1041        page = create_page("tbp", "nav_playground.html", "en", published=True)
1042        create_title('de', 'de page', page)
1043        add_plugin(page.placeholders.get(slot='body'), "TextPlugin", "de", body='de body')
1044        create_title('fr', 'fr page', page)
1045        add_plugin(page.placeholders.get(slot='body'), "TextPlugin", "fr", body='fr body')
1046        page.publish('de')
1047        page.publish('fr')
1048
1049        staff = self.get_staff()
1050
1051        request = self.get_page_request(page, staff, '/', edit=True)
1052        self.assertMenuItems(
1053            request, LANGUAGE_MENU_IDENTIFIER, 'Copy all plugins',
1054            [u'from German', u'from French']
1055        )
1056
1057        request = self.get_page_request(page, staff, '/', edit=True, lang_code='de')
1058        self.assertMenuItems(
1059            request, LANGUAGE_MENU_IDENTIFIER, 'Copy all plugins',
1060            [u'from English', u'from French']
1061        )
1062
1063    def get_username(self, user=None, default=''):
1064        user = user or self.request.user
1065        try:
1066            name = user.get_full_name()
1067            if name:
1068                return name
1069            else:
1070                return user.get_username()
1071        except (AttributeError, NotImplementedError):
1072            return default
1073
1074    def test_toolbar_logout(self):
1075        '''
1076        Tests that the Logout menu item includes the user's full name, if the
1077        relevant fields were populated in auth.User, else the user's username.
1078        '''
1079        superuser = self.get_superuser()
1080
1081        # Ensure that some other test hasn't set the name fields
1082        if superuser.get_full_name():
1083            # Looks like it has been set, clear them
1084            superuser.first_name = ''
1085            superuser.last_name = ''
1086            superuser.save()
1087
1088        page = create_page("home", "nav_playground.html", "en",
1089                           published=True)
1090        page.publish('en')
1091        self.get_page_request(page, superuser, '/')
1092        #
1093        # Test that the logout shows the username of the logged-in user if
1094        # first_name and last_name haven't been provided.
1095        #
1096        with self.login_user_context(superuser):
1097            response = self.client.get(page.get_absolute_url('en') + '?%s' % get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON'))
1098            toolbar = response.context['request'].toolbar
1099            admin_menu = toolbar.get_or_create_menu(ADMIN_MENU_IDENTIFIER)
1100            self.assertTrue(admin_menu.find_first(AjaxItem, name=_(u'Logout %s') % self.get_username(superuser)))
1101
1102        #
1103        # Test that the logout shows the logged-in user's name, if it was
1104        # populated in auth.User.
1105        #
1106        superuser.first_name = 'Super'
1107        superuser.last_name = 'User'
1108        superuser.save()
1109        # Sanity check...
1110        self.get_page_request(page, superuser, '/')
1111        with self.login_user_context(superuser):
1112            response = self.client.get(page.get_absolute_url('en') + '?%s' % get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON'))
1113            toolbar = response.context['request'].toolbar
1114            admin_menu = toolbar.get_or_create_menu(ADMIN_MENU_IDENTIFIER)
1115            self.assertTrue(admin_menu.find_first(AjaxItem, name=_(u'Logout %s') % self.get_username(superuser)))
1116
1117    @override_settings(CMS_PERMISSION=True)
1118    def test_toolbar_logout_redirect(self):
1119        """
1120        Tests the logount AjaxItem on_success parameter in four different conditions:
1121
1122         * published page: no redirect
1123         * unpublished page: redirect to the home page
1124         * published page with login_required: redirect to the home page
1125         * published page with view permissions: redirect to the home page
1126        """
1127        superuser = self.get_superuser()
1128        page0 = create_page("home", "nav_playground.html", "en",
1129                            published=True)
1130        page1 = create_page("internal", "nav_playground.html", "en",
1131                            published=True, parent=page0)
1132        page2 = create_page("unpublished", "nav_playground.html", "en",
1133                            published=False, parent=page0)
1134        page3 = create_page("login_restricted", "nav_playground.html", "en",
1135                            published=True, parent=page0, login_required=True)
1136        page4 = create_page("view_restricted", "nav_playground.html", "en",
1137                            published=True, parent=page0)
1138        PagePermission.objects.create(page=page4, can_view=True,
1139                                      user=superuser)
1140        page4.publish('en')
1141        page4 = page4.get_public_object()
1142        self.get_page_request(page4, superuser, '/')
1143
1144        with self.login_user_context(superuser):
1145            # Published page, no redirect
1146            response = self.client.get(page1.get_absolute_url('en') + '?%s' % get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON'))
1147            toolbar = response.context['request'].toolbar
1148            menu_name = _(u'Logout %s') % self.get_username(superuser)
1149            admin_menu = toolbar.get_or_create_menu(ADMIN_MENU_IDENTIFIER)
1150            self.assertTrue(admin_menu.find_first(AjaxItem, name=menu_name).item.on_success)
1151
1152            # Unpublished page, redirect
1153            response = self.client.get(page2.get_absolute_url('en') + '?%s' % get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON'))
1154            toolbar = response.context['request'].toolbar
1155            admin_menu = toolbar.get_or_create_menu(ADMIN_MENU_IDENTIFIER)
1156
1157            self.assertEquals(admin_menu.find_first(AjaxItem, name=menu_name).item.on_success, '/')
1158
1159            # Published page with login restrictions, redirect
1160            response = self.client.get(page3.get_absolute_url('en') + '?%s' % get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON'))
1161            toolbar = response.context['request'].toolbar
1162            admin_menu = toolbar.get_or_create_menu(ADMIN_MENU_IDENTIFIER)
1163            self.assertEquals(admin_menu.find_first(AjaxItem, name=menu_name).item.on_success, '/')
1164
1165            # Published page with view permissions, redirect
1166            response = self.client.get(page4.get_absolute_url('en') + '?%s' % get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON'))
1167            toolbar = response.context['request'].toolbar
1168            admin_menu = toolbar.get_or_create_menu(ADMIN_MENU_IDENTIFIER)
1169            self.assertEquals(admin_menu.find_first(AjaxItem, name=menu_name).item.on_success, '/')
1170
1171
1172@override_settings(ROOT_URLCONF='cms.test_utils.project.placeholderapp_urls')
1173class EditModelTemplateTagTest(ToolbarTestBase):
1174    edit_fields_rx = "(\?|&amp;)edit_fields=%s"
1175
1176    def tearDown(self):
1177        Example1.objects.all().delete()
1178        super(EditModelTemplateTagTest, self).tearDown()
1179
1180    def test_markup_toolbar_url_model(self):
1181        superuser = self.get_superuser()
1182        page = create_page('Test', 'col_two.html', 'en', published=True)
1183        ex1 = Example1(char_1="char_1", char_2="char_2", char_3="char_3",
1184                       char_4="char_4")
1185        ex1.save()
1186        # object
1187        # check when in draft mode
1188        request = self.get_page_request(page, superuser, edit=True)
1189        response = detail_view(request, ex1.pk)
1190        self.assertEqual(response.status_code, 200)
1191        self.assertContains(response, 'href="%s?preview&amp;%s"' % (
1192            ex1.get_public_url(), get_cms_setting('CMS_TOOLBAR_URL__EDIT_OFF')
1193        ))
1194        # check when in live mode
1195        request = self.get_page_request(page, superuser, preview=True)
1196        response = detail_view(request, ex1.pk)
1197        self.assertEqual(response.status_code, 200)
1198        self.assertContains(response, 'href="%s?%s"' % (
1199            ex1.get_draft_url(), get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON')
1200        ))
1201        self.assertNotEqual(ex1.get_draft_url(), ex1.get_public_url())
1202
1203    def test_anon(self):
1204        user = self.get_anon()
1205        page = create_page('Test', 'col_two.html', 'en', published=True)
1206        ex1 = Example1(char_1="char_1", char_2="char_2", char_3="char_3",
1207                       char_4="char_4")
1208        ex1.save()
1209        request = self.get_page_request(page, user, edit=False)
1210        response = detail_view(request, ex1.pk)
1211        self.assertContains(response, "<h1>char_1</h1>")
1212        self.assertNotContains(response, "CMS.API")
1213
1214    def test_noedit(self):
1215        user = self.get_staff()
1216        page = create_page('Test', 'col_two.html', 'en', published=True)
1217        ex1 = Example1(char_1="char_1", char_2="char_2", char_3="char_3",
1218                       char_4="char_4")
1219        ex1.save()
1220        request = self.get_page_request(page, user, edit=False)
1221        response = detail_view(request, ex1.pk)
1222        self.assertContains(response, "<h1>char_1</h1>")
1223        self.assertContains(response, "CMS.API")
1224
1225    def test_edit(self):
1226        user = self.get_staff()
1227        page = create_page('Test', 'col_two.html', 'en', published=True)
1228        ex1 = Example1(char_1="char_1", char_2="char_2", char_3="char_3",
1229                       char_4="char_4")
1230        ex1.save()
1231        request = self.get_page_request(page, user, edit=True)
1232        response = detail_view(request, ex1.pk)
1233        self.assertContains(
1234            response,
1235            '<h1><template class="cms-plugin cms-plugin-start cms-plugin-{0}-{1}-{2}-{3} cms-render-model"></template>'
1236            'char_1'
1237            '<template class="cms-plugin cms-plugin-end cms-plugin-{0}-{1}-{2}-{3} cms-render-model"></template></h1>'.format(
1238                'placeholderapp', 'example1', 'char_1', ex1.pk))
1239
1240    def test_invalid_item(self):
1241        user = self.get_staff()
1242        page = create_page('Test', 'col_two.html', 'en', published=True)
1243        ex1 = Example1(char_1="char_1", char_2="char_2", char_3="char_3",
1244                       char_4="char_4")
1245        ex1.save()
1246        template_text = '''{% extends "base.html" %}
1247{% load cms_tags %}
1248
1249{% block content %}
1250<h1>{% render_model fake "char_1" %}</h1>
1251{% endblock content %}
1252'''
1253        request = self.get_page_request(page, user, edit=True)
1254        response = detail_view(request, ex1.pk, template_string=template_text)
1255        self.assertContains(
1256            response,
1257            '<template class="cms-plugin cms-plugin-start cms-plugin-%s cms-render-model"></template>' % ex1.pk)
1258        self.assertContains(
1259            response,
1260            '<template class="cms-plugin cms-plugin-end cms-plugin-%s cms-render-model"></template>' % ex1.pk)
1261
1262    def test_as_varname(self):
1263        user = self.get_staff()
1264        page = create_page('Test', 'col_two.html', 'en', published=True)
1265        ex1 = Example1(char_1="char_1", char_2="char_2", char_3="char_3",
1266                       char_4="char_4")
1267        ex1.save()
1268        template_text = '''{% extends "base.html" %}
1269{% load cms_tags %}
1270
1271{% block content %}
1272<h1>{% render_model instance "char_1" as tempvar %}</h1>
1273{% endblock content %}
1274'''
1275        request = self.get_page_request(page, user, edit=True)
1276        response = detail_view(request, ex1.pk, template_string=template_text)
1277        self.assertNotContains(
1278            response,
1279            '<template class="cms-plugin cms-plugin-start cms-plugin-%s cms-render-model"></template>' % ex1.pk)
1280        self.assertNotContains(
1281            response,
1282            '<template class="cms-plugin cms-plugin-end cms-plugin-%s cms-render-model"></template>' % ex1.pk)
1283
1284    def test_edit_render_placeholder(self):
1285        """
1286        Tests the {% render_placeholder %} templatetag.
1287        """
1288        user = self.get_staff()
1289        page = create_page('Test', 'col_two.html', 'en', published=True)
1290        ex1 = Example1(char_1="char_1", char_2="char_2", char_3="char_3",
1291                       char_4="char_4")
1292        ex1.save()
1293
1294        render_placeholder_body = "I'm the render placeholder body"
1295
1296        plugin = add_plugin(ex1.placeholder, u"TextPlugin", u"en", body=render_placeholder_body)
1297
1298        template_text = '''{% extends "base.html" %}
1299{% load cms_tags %}
1300
1301{% block content %}
1302<h1>{% render_placeholder instance.placeholder %}</h1>
1303<h2>{% render_placeholder instance.placeholder as tempvar %}</h2>
1304<h3>{{ tempvar }}</h3>
1305{% endblock content %}
1306'''
1307        request = self.get_page_request(page, user, edit=True)
1308        response = detail_view(request, ex1.pk, template_string=template_text)
1309        self.assertContains(
1310            response,
1311            '<div class="cms-placeholder cms-placeholder-{0}"></div>'.format(ex1.placeholder.pk))
1312
1313        self.assertContains(
1314            response,
1315            '<h1><template class="cms-plugin cms-plugin-start cms-plugin-{0}"></template>'
1316            '{1}'
1317            '<template class="cms-plugin cms-plugin-end cms-plugin-{0}"></template>'.format(
1318                                                                           plugin.pk, render_placeholder_body))
1319
1320        self.assertContains(
1321            response,
1322            '<h2></h2>',
1323        )
1324
1325        #
1326        # NOTE: Using the render_placeholder "as" form should /not/ render
1327        # frontend placeholder editing support.
1328        #
1329        self.assertContains(
1330            response,
1331            '<h3>{0}</h3>'.format(render_placeholder_body)
1332            )
1333
1334        self.assertContains(
1335            response,
1336            'CMS._plugins.push(["cms-plugin-{0}"'.format(plugin.pk)
1337        )
1338
1339        self.assertContains(
1340            response,
1341            'CMS._plugins.push(["cms-placeholder-{0}"'.format(ex1.placeholder.pk)
1342        )
1343
1344    def test_filters(self):
1345        user = self.get_staff()
1346        page = create_page('Test', 'col_two.html', 'en', published=True)
1347        ex1 = Example1(char_1="char_1, <p>hello</p>, <p>hello</p>, <p>hello</p>, <p>hello</p>", char_2="char_2",
1348                       char_3="char_3",
1349                       char_4="char_4")
1350        ex1.save()
1351        template_text = '''{% extends "base.html" %}
1352{% load cms_tags %}
1353
1354{% block content %}
1355<h1>{% render_model instance "char_1" "" "" 'truncatewords:2' %}</h1>
1356{% endblock content %}
1357'''
1358        request = self.get_page_request(page, user, edit=True)
1359        response = detail_view(request, ex1.pk, template_string=template_text)
1360        self.assertContains(
1361            response,
1362            '<h1>'
1363            '<template class="cms-plugin cms-plugin-start cms-plugin-{0}-{1}-{2}-{3} cms-render-model"></template>'
1364            '{4}'
1365            '<template class="cms-plugin cms-plugin-end cms-plugin-{0}-{1}-{2}-{3} cms-render-model"></template>'
1366            '</h1>'.format(
1367                'placeholderapp', 'example1', 'char_1', ex1.pk, truncatewords(escape(ex1.char_1), 2)))
1368
1369        template_text = '''{% extends "base.html" %}
1370{% load cms_tags %}
1371
1372{% block content %}
1373<h1>{% render_model instance "char_1" "" "" "truncatewords:2|safe" %}</h1>
1374{% endblock content %}
1375'''
1376        request = self.get_page_request(page, user, edit=True)
1377        response = detail_view(request, ex1.pk, template_string=template_text)
1378        self.assertContains(
1379            response,
1380            '<h1>'
1381            '<template class="cms-plugin cms-plugin-start cms-plugin-{0}-{1}-{2}-{3} cms-render-model"></template>'
1382            '{4}'
1383            '<template class="cms-plugin cms-plugin-end cms-plugin-{0}-{1}-{2}-{3} cms-render-model"></template>'
1384            '</h1>'.format(
1385                'placeholderapp', 'example1', 'char_1', ex1.pk, truncatewords(ex1.char_1, 2)))
1386
1387    def test_setting_override(self):
1388        template_text = '''{% extends "base.html" %}
1389{% load cms_tags %}
1390
1391{% block content %}
1392<h1>{% render_model instance "char_1" "" "" 'truncatewords:2' %}</h1>
1393{% endblock content %}
1394'''
1395        user = self.get_staff()
1396        page = create_page('Test', 'col_two.html', 'en', published=True)
1397        ex1 = Example1(char_1="char_1, <p>hello</p>, <p>hello</p>, <p>hello</p>, <p>hello</p>", char_2="char_2",
1398                       char_3="char_3",
1399                       char_4="char_4")
1400        ex1.save()
1401
1402        request = self.get_page_request(page, user, edit=True)
1403        response = detail_view(request, ex1.pk, template_string=template_text)
1404        self.assertContains(
1405            response,
1406            '<h1>'
1407            '<template class="cms-plugin cms-plugin-start cms-plugin-{0}-{1}-{2}-{3} cms-render-model"></template>'
1408            '{4}'
1409            '<template class="cms-plugin cms-plugin-end cms-plugin-{0}-{1}-{2}-{3} cms-render-model"></template>'
1410            '</h1>'.format(
1411                'placeholderapp', 'example1', 'char_1', ex1.pk, truncatewords(escape(ex1.char_1), 2)))
1412
1413    def test_filters_date(self):
1414        # Ensure we have a consistent testing env...
1415        with self.settings(USE_L10N=False, DATE_FORMAT="M. d, Y"):
1416            user = self.get_staff()
1417            page = create_page('Test', 'col_two.html', 'en', published=True)
1418            ex1 = Example1(char_1="char_1, <p>hello</p>, <p>hello</p>, <p>hello</p>, <p>hello</p>", char_2="char_2",
1419                           char_3="char_3",
1420                           char_4="char_4", date_field=datetime.date(2012, 1, 2))
1421            ex1.save()
1422            template_text = '''{% extends "base.html" %}
1423{% load cms_tags %}
1424
1425{% block content %}
1426<h1>{% render_model instance "date_field" %}</h1>
1427{% endblock content %}
1428'''
1429
1430            request = self.get_page_request(page, user, edit=True)
1431            response = detail_view(request, ex1.pk, template_string=template_text)
1432            self.assertContains(
1433                response,
1434                '<h1>'
1435                '<template class="cms-plugin cms-plugin-start cms-plugin-{0}-{1}-{2}-{3} cms-render-model"></template>'
1436                '{4}'
1437                '<template class="cms-plugin cms-plugin-end cms-plugin-{0}-{1}-{2}-{3} cms-render-model"></template>'
1438                '</h1>'.format(
1439                    'placeholderapp', 'example1', 'date_field', ex1.pk,
1440                    ex1.date_field.strftime("%b. %d, %Y")))
1441
1442            template_text = '''{% extends "base.html" %}
1443{% load cms_tags %}
1444
1445{% block content %}
1446<h1>{% render_model instance "date_field" "" "" "safe" %}</h1>
1447{% endblock content %}
1448'''
1449            request = self.get_page_request(page, user, edit=True)
1450            response = detail_view(request, ex1.pk, template_string=template_text)
1451            self.assertContains(
1452                response,
1453                '<h1>'
1454                '<template class="cms-plugin cms-plugin-start cms-plugin-{0}-{1}-{2}-{3} cms-render-model"></template>'
1455                '{4}'
1456                '<template class="cms-plugin cms-plugin-end cms-plugin-{0}-{1}-{2}-{3} cms-render-model"></template>'
1457                '</h1>'.format(
1458                    'placeholderapp', 'example1', 'date_field', ex1.pk,
1459                    ex1.date_field.strftime("%Y-%m-%d")))
1460
1461            template_text = '''{% extends "base.html" %}
1462{% load cms_tags %}
1463
1464{% block content %}
1465<h1>{% render_model instance "date_field" "" "" 'date:"Y m d"' %}</h1>
1466{% endblock content %}
1467'''
1468            response = detail_view(request, ex1.pk, template_string=template_text)
1469            self.assertContains(
1470                response,
1471                '<h1>'
1472                '<template class="cms-plugin cms-plugin-start cms-plugin-{0}-{1}-{2}-{3} cms-render-model"></template>'
1473                '{4}'
1474                '<template class="cms-plugin cms-plugin-end cms-plugin-{0}-{1}-{2}-{3} cms-render-model"></template>'
1475                '</h1>'.format(
1476                    'placeholderapp', 'example1', 'date_field', ex1.pk,
1477                    ex1.date_field.strftime("%Y %m %d")))
1478
1479    def test_filters_notoolbar(self):
1480        user = self.get_staff()
1481        page = create_page('Test', 'col_two.html', 'en', published=True)
1482        ex1 = Example1(char_1="char_1, <p>hello</p>, <p>hello</p>, <p>hello</p>, <p>hello</p>", char_2="char_2",
1483                       char_3="char_3",
1484                       char_4="char_4")
1485        ex1.save()
1486        template_text = '''{% extends "base.html" %}
1487{% load cms_tags %}
1488
1489{% block content %}
1490<h1>{% render_model instance "char_1" "" "" 'truncatewords:2' %}</h1>
1491{% endblock content %}
1492'''
1493
1494        request = self.get_page_request(page, user, edit=False)
1495        response = detail_view(request, ex1.pk, template_string=template_text)
1496        self.assertContains(response,
1497                            '<h1>%s</h1>' % truncatewords(escape(ex1.char_1), 2))
1498
1499        template_text = '''{% extends "base.html" %}
1500{% load cms_tags %}
1501
1502{% block content %}
1503<h1>{% render_model instance "char_1" "" "" 'truncatewords:2|safe' "" "" %}</h1>
1504{% endblock content %}
1505'''
1506        request = self.get_page_request(page, user, edit=False)
1507        response = detail_view(request, ex1.pk, template_string=template_text)
1508        self.assertContains(response,
1509                            '<h1>%s</h1>' % truncatewords(ex1.char_1, 2))
1510
1511    def test_no_cms(self):
1512        user = self.get_staff()
1513        ex1 = Example1(char_1="char_1", char_2="char_2", char_3="char_3",
1514                       char_4="char_4")
1515        ex1.save()
1516        template_text = '''{% extends "base.html" %}
1517{% load cms_tags %}
1518
1519{% block content %}
1520{% render_model_icon instance %}
1521{% endblock content %}
1522'''
1523        request = self.get_page_request(None, user, path='/', edit=True)
1524        response = detail_view(request, ex1.pk, template_string=template_text)
1525        self.assertContains(
1526            response,
1527            '<template class="cms-plugin cms-plugin-start cms-plugin-{0}-{1}-{2} cms-render-model-icon"></template>'
1528            '<img src="/static/cms/img/toolbar/render_model_placeholder.png">'
1529            '<template class="cms-plugin cms-plugin-end cms-plugin-{0}-{1}-{2} cms-render-model-icon"></template>'.format(
1530                'placeholderapp', 'example1', ex1.pk))
1531        self.assertContains(response, "onClose: 'REFRESH_PAGE',")
1532
1533    def test_icon_tag(self):
1534        user = self.get_staff()
1535        page = create_page('Test', 'col_two.html', 'en', published=True)
1536        ex1 = Example1(char_1="char_1", char_2="char_2", char_3="char_3",
1537                       char_4="char_4")
1538        ex1.save()
1539        template_text = '''{% extends "base.html" %}
1540{% load cms_tags %}
1541
1542{% block content %}
1543{% render_model_icon instance %}
1544{% endblock content %}
1545'''
1546        request = self.get_page_request(page, user, edit=True)
1547        response = detail_view(request, ex1.pk, template_string=template_text)
1548        self.assertContains(
1549            response,
1550            '<template class="cms-plugin cms-plugin-start cms-plugin-{0}-{1}-{2} cms-render-model-icon"></template>'
1551            '<img src="/static/cms/img/toolbar/render_model_placeholder.png">'
1552            '<template class="cms-plugin cms-plugin-end cms-plugin-{0}-{1}-{2} cms-render-model-icon"></template>'.format(
1553                'placeholderapp', 'example1', ex1.pk))
1554
1555    def test_icon_followed_by_render_model_block_tag(self):
1556        user = self.get_staff()
1557        page = create_page('Test', 'col_two.html', 'en', published=True)
1558        ex1 = Example1(char_1="char_1", char_2="char_2", char_3="char_3",
1559                       char_4="char_4", date_field=datetime.date(2012, 1, 1))
1560        ex1.save()
1561        template_text = '''{% extends "base.html" %}
1562{% load cms_tags %}
1563
1564{% block content %}
1565{% render_model_icon instance "char_1" %}
1566
1567{% render_model_block instance "char_2" %}
1568    {{ instance }}
1569    <h1>{{ instance.char_1 }} - {{  instance.char_2 }}</h1>
1570    <span class="date">{{ instance.date_field|date:"Y" }}</span>
1571    {% if instance.char_1 %}
1572    <a href="{% url 'detail' instance.pk %}">successful if</a>
1573    {% endif %}
1574{% endrender_model_block %}
1575{% endblock content %}
1576'''
1577        request = self.get_page_request(page, user, edit=True)
1578        response = detail_view(request, ex1.pk, template_string=template_text)
1579        self.assertContains(
1580            response,
1581            "CMS._plugins.push(['cms-plugin-{0}-{1}-{2}-{3}'".format('placeholderapp', 'example1', 'char_1', ex1.pk))
1582
1583        self.assertContains(
1584            response,
1585            "CMS._plugins.push(['cms-plugin-{0}-{1}-{2}-{3}'".format('placeholderapp', 'example1', 'char_2', ex1.pk))
1586
1587    def test_add_tag(self):
1588        user = self.get_staff()
1589        page = create_page('Test', 'col_two.html', 'en', published=True)
1590        ex1 = Example1(char_1="char_1", char_2="char_2", char_3="char_3",
1591                       char_4="char_4")
1592        ex1.save()
1593        template_text = '''{% extends "base.html" %}
1594{% load cms_tags %}
1595
1596{% block content %}
1597{% render_model_add instance %}
1598{% endblock content %}
1599'''
1600        request = self.get_page_request(page, user, edit=True)
1601        response = detail_view(request, ex1.pk, template_string=template_text)
1602        self.assertContains(
1603            response,
1604            '<template class="cms-plugin cms-plugin-start cms-plugin-{0}-{1}-add-{2} cms-render-model-add"></template>'
1605            '<img src="/static/cms/img/toolbar/render_model_placeholder.png">'
1606            '<template class="cms-plugin cms-plugin-end cms-plugin-{0}-{1}-add-{2} cms-render-model-add"></template>'.format(
1607                'placeholderapp', 'example1', ex1.pk)
1608            )
1609
1610    def test_add_tag_class(self):
1611        user = self.get_staff()
1612        page = create_page('Test', 'col_two.html', 'en', published=True)
1613        ex1 = Example1(char_1="char_1", char_2="char_2", char_3="char_3",
1614                       char_4="char_4")
1615        ex1.save()
1616        template_text = '''{% extends "base.html" %}
1617{% load cms_tags %}
1618
1619{% block content %}
1620{% render_model_add instance_class %}
1621{% endblock content %}
1622'''
1623        request = self.get_page_request(page, user, edit=True)
1624        response = detail_view(request, ex1.pk, template_string=template_text)
1625        self.assertContains(
1626            response,
1627            '<template class="cms-plugin cms-plugin-start cms-plugin-{0}-{1}-add-{2} cms-render-model-add"></template>'
1628            '<img src="/static/cms/img/toolbar/render_model_placeholder.png">'
1629            '<template class="cms-plugin cms-plugin-end cms-plugin-{0}-{1}-add-{2} cms-render-model-add"></template>'.format(
1630                'placeholderapp', 'example1', '0'))
1631
1632    def test_add_tag_classview(self):
1633        user = self.get_staff()
1634        page = create_page('Test', 'col_two.html', 'en', published=True)
1635        ex1 = Example1(char_1="char_1", char_2="char_2", char_3="char_3",
1636                       char_4="char_4")
1637        ex1.save()
1638        template_text = '''{% extends "base.html" %}
1639{% load cms_tags %}
1640
1641{% block content %}
1642{% render_model_add instance_class %}
1643{% endblock content %}
1644'''
1645        request = self.get_page_request(page, user, edit=True)
1646        view_func = ClassDetail.as_view(template_string=template_text)
1647        response = view_func(request, pk=ex1.pk, template_string=template_text)
1648        self.assertContains(
1649            response,
1650            '<template class="cms-plugin cms-plugin-start cms-plugin-{0}-{1}-add-{2} cms-render-model-add"></template>'
1651            '<img src="/static/cms/img/toolbar/render_model_placeholder.png">'
1652            '<template class="cms-plugin cms-plugin-end cms-plugin-{0}-{1}-add-{2} cms-render-model-add"></template>'.format(
1653                'placeholderapp', 'example1', '0'))
1654
1655    def test_block_tag(self):
1656        user = self.get_staff()
1657        page = create_page('Test', 'col_two.html', 'en', published=True)
1658        ex1 = Example1(char_1="char_1", char_2="char_2", char_3="char_3",
1659                       char_4="char_4", date_field=datetime.date(2012, 1, 1))
1660        ex1.save()
1661
1662        # This template does not render anything as content is saved in a
1663        # variable and never inserted in the page
1664        template_text = '''{% extends "base.html" %}
1665{% load cms_tags %}
1666
1667{% block content %}
1668{% render_model_block instance as rendered_model %}
1669    {{ instance }}
1670    <h1>{{ instance.char_1 }} - {{  instance.char_2 }}</h1>
1671    {{ instance.date_field|date:"Y" }}
1672    {% if instance.char_1 %}
1673    <a href="{% url 'detail' instance.pk %}">successful if</a>
1674    {% endif %}
1675{% endrender_model_block %}
1676{% endblock content %}
1677'''
1678        request = self.get_page_request(page, user, edit=True)
1679        response = detail_view(request, ex1.pk, template_string=template_text)
1680        self.assertNotContains(
1681            response,
1682            '<template class="cms-plugin cms-plugin-start cms-plugin-{0}-{1}-{2} cms-render-model-icon"></template>'
1683            '<img src="/static/cms/img/toolbar/render_model_icon.png">'
1684            '<template class="cms-plugin cms-plugin-end cms-plugin-{0}-{1}-{2} cms-render-model-icon"></template>'.format(
1685                'placeholderapp', 'example1', ex1.pk))
1686
1687        # This template does not render anything as content is saved in a
1688        # variable and inserted in the page afterwards
1689        template_text = '''{% extends "base.html" %}
1690{% load cms_tags %}
1691
1692{% block content %}
1693{% render_model_block instance as rendered_model %}
1694    {{ instance }}
1695    <h1>{{ instance.char_1 }} - {{  instance.char_2 }}</h1>
1696    <span class="date">{{ instance.date_field|date:"Y" }}</span>
1697    {% if instance.char_1 %}
1698    <a href="{% url 'detail' instance.pk %}">successful if</a>
1699    {% endif %}
1700{% endrender_model_block %}
1701{{ rendered_model }}
1702{% endblock content %}
1703'''
1704        request = self.get_page_request(page, user, edit=True)
1705        response = detail_view(request, ex1.pk, template_string=template_text)
1706        # Assertions on the content of the block tag
1707        self.assertContains(
1708            response,
1709            '<template class="cms-plugin cms-plugin-start cms-plugin-{0}-{1}-{2} cms-render-model cms-render-model-block">'.format(
1710                'placeholderapp', 'example1', ex1.pk))
1711        self.assertContains(response, '<h1>%s - %s</h1>' % (ex1.char_1, ex1.char_2))
1712        self.assertContains(response, '<span class="date">%s</span>' % (ex1.date_field.strftime("%Y")))
1713        self.assertContains(response, '<a href="%s">successful if</a>\n    \n<template' % (reverse('detail', args=(ex1.pk,))))
1714
1715        # This template is rendered directly
1716        template_text = '''{% extends "base.html" %}
1717{% load cms_tags %}
1718
1719{% block content %}
1720{% render_model_block instance %}
1721    {{ instance }}
1722    <h1>{{ instance.char_1 }} - {{  instance.char_2 }}</h1>
1723    <span class="date">{{ instance.date_field|date:"Y" }}</span>
1724    {% if instance.char_1 %}
1725    <a href="{% url 'detail' instance.pk %}">successful if</a>
1726    {% endif %}
1727{% endrender_model_block %}
1728{% endblock content %}
1729'''
1730        request = self.get_page_request(page, user, edit=True)
1731        response = detail_view(request, ex1.pk, template_string=template_text)
1732        # Assertions on the content of the block tag
1733        self.assertContains(
1734            response,
1735            '<template class="cms-plugin cms-plugin-start cms-plugin-{0}-{1}-{2} cms-render-model cms-render-model-block">'.format(
1736                'placeholderapp', 'example1', ex1.pk))
1737        self.assertContains(response, '<h1>%s - %s</h1>' % (ex1.char_1, ex1.char_2))
1738        self.assertContains(response, '<span class="date">%s</span>' % (ex1.date_field.strftime("%Y")))
1739        self.assertContains(response, '<a href="%s">successful if</a>\n    \n<template' % (reverse('detail', args=(ex1.pk,))))
1740
1741        # Changelist check
1742        template_text = '''{% extends "base.html" %}
1743{% load cms_tags %}
1744
1745{% block content %}
1746{% render_model_block instance 'changelist' %}
1747    {{ instance }}
1748{% endrender_model_block %}
1749{% endblock content %}
1750'''
1751        request = self.get_page_request(page, user, edit=True)
1752        response = detail_view(request, ex1.pk, template_string=template_text)
1753        # Assertions on the content of the block tag
1754        self.assertContains(
1755            response,
1756            '<template class="cms-plugin cms-plugin-start cms-plugin-{0}-{1}-changelist-{2} cms-render-model cms-render-model-block"></template>'.format(
1757                'placeholderapp', 'example1', ex1.pk))
1758        self.assertContains(
1759            response,
1760            "edit_plugin: '%s?language=%s&amp;edit_fields=changelist'" % (admin_reverse('placeholderapp_example1_changelist'), 'en'))
1761
1762    def test_invalid_attribute(self):
1763        user = self.get_staff()
1764        page = create_page('Test', 'col_two.html', 'en', published=True)
1765        ex1 = Example1(char_1="char_1", char_2="char_2", char_3="char_3",
1766                       char_4="char_4")
1767        ex1.save()
1768        template_text = '''{% extends "base.html" %}
1769{% load cms_tags %}
1770
1771{% block content %}
1772<h1>{% render_model instance "fake_field" %}</h1>
1773{% endblock content %}
1774'''
1775        request = self.get_page_request(page, user, edit=True)
1776        response = detail_view(request, ex1.pk, template_string=template_text)
1777        self.assertContains(
1778            response,
1779            '<template class="cms-plugin cms-plugin-start cms-plugin-{0}-{1}-{2}-{3} cms-render-model"></template>'.format(
1780                'placeholderapp', 'example1', 'fake_field', ex1.pk))
1781        self.assertContains(
1782            response,
1783            '<template class="cms-plugin cms-plugin-end cms-plugin-{0}-{1}-{2}-{3} cms-render-model"></template>'.format(
1784                'placeholderapp', 'example1', 'fake_field', ex1.pk))
1785
1786        # no attribute
1787        template_text = '''{% extends "base.html" %}
1788{% load cms_tags %}
1789
1790{% block content %}
1791<h1>{% render_model instance "" %}</h1>
1792{% endblock content %}
1793'''
1794        request = self.get_page_request(page, user, edit=True)
1795        response = detail_view(request, ex1.pk, template_string=template_text)
1796        self.assertContains(
1797            response,
1798            '<template class="cms-plugin cms-plugin-start cms-plugin-{0} cms-render-model"></template>'.format(ex1.pk))
1799        self.assertContains(
1800            response,
1801            '<template class="cms-plugin cms-plugin-end cms-plugin-{0} cms-render-model"></template>'.format(ex1.pk))
1802
1803    def test_callable_item(self):
1804        user = self.get_staff()
1805        page = create_page('Test', 'col_two.html', 'en', published=True)
1806        ex1 = Example1(char_1="char_1", char_2="char_2", char_3="char_3",
1807                       char_4="char_4")
1808        ex1.save()
1809        template_text = '''{% extends "base.html" %}
1810{% load cms_tags %}
1811
1812{% block content %}
1813<h1>{% render_model instance "callable_item" %}</h1>
1814{% endblock content %}
1815'''
1816        request = self.get_page_request(page, user, edit=True)
1817        response = detail_view(request, ex1.pk, template_string=template_text)
1818        self.assertContains(
1819            response,
1820            '<h1><template class="cms-plugin cms-plugin-start cms-plugin-{0}-{1}-{2}-{3} cms-render-model"></template>'
1821            'char_1'
1822            '<template class="cms-plugin cms-plugin-end cms-plugin-{0}-{1}-{2}-{3} cms-render-model"></template></h1>'.format(
1823                'placeholderapp', 'example1', 'callable_item', ex1.pk))
1824
1825    def test_view_method(self):
1826        user = self.get_staff()
1827        page = create_page('Test', 'col_two.html', 'en', published=True)
1828        ex1 = Example1(char_1="char_1", char_2="char_2", char_3="char_3",
1829                       char_4="char_4")
1830        ex1.save()
1831        template_text = '''{% extends "base.html" %}
1832{% load cms_tags %}
1833
1834{% block content %}
1835<h1>{% render_model instance "callable_item" "char_1,char_2" "en" "" "" "dynamic_url" %}</h1>
1836{% endblock content %}
1837'''
1838        request = self.get_page_request(page, user, edit=True)
1839        response = detail_view(request, ex1.pk, template_string=template_text)
1840        self.assertContains(
1841            response, "edit_plugin: '/admin/placeholderapp/example1/edit-field/%s/en/" % ex1.pk)
1842
1843    def test_view_url(self):
1844        user = self.get_staff()
1845        page = create_page('Test', 'col_two.html', 'en', published=True)
1846        ex1 = Example1(char_1="char_1", char_2="char_2", char_3="char_3",
1847                       char_4="char_4")
1848        ex1.save()
1849        template_text = '''{% extends "base.html" %}
1850{% load cms_tags %}
1851
1852{% block content %}
1853<h1>{% render_model instance "callable_item" "char_1,char_2" "en" "" "admin:placeholderapp_example1_edit_field" %}</h1>
1854{% endblock content %}
1855'''
1856        request = self.get_page_request(page, user, edit=True)
1857        response = detail_view(request, ex1.pk, template_string=template_text)
1858        self.assertContains(
1859            response, "edit_plugin: '/admin/placeholderapp/example1/edit-field/%s/en/" % ex1.pk)
1860
1861    def test_method_attribute(self):
1862        user = self.get_staff()
1863        page = create_page('Test', 'col_two.html', 'en', published=True)
1864        ex1 = Example1(char_1="char_1", char_2="char_2", char_3="char_3",
1865                       char_4="char_4")
1866        ex1.save()
1867        template_text = '''{% extends "base.html" %}
1868{% load cms_tags %}
1869
1870{% block content %}
1871<h1>{% render_model instance "callable_item" "char_1,char_2" "en" "" "" "static_admin_url" %}</h1>
1872{% endblock content %}
1873'''
1874        request = self.get_page_request(page, user, edit=True)
1875        ex1.set_static_url(request)
1876        response = detail_view(request, ex1.pk, template_string=template_text)
1877        self.assertContains(
1878            response,
1879            '<h1>'
1880            '<template class="cms-plugin cms-plugin-start cms-plugin-{0}-{1}-{2}-{3} cms-render-model"></template>'
1881            'char_1'
1882            '<template class="cms-plugin cms-plugin-end cms-plugin-{0}-{1}-{2}-{3} cms-render-model"></template>'
1883            '</h1>'.format(
1884                'placeholderapp', 'example1', 'callable_item', ex1.pk))
1885
1886    def test_admin_url(self):
1887        user = self.get_staff()
1888        page = create_page('Test', 'col_two.html', 'en', published=True)
1889        ex1 = Example1(char_1="char_1", char_2="char_2", char_3="char_3",
1890                       char_4="char_4")
1891        ex1.save()
1892        template_text = '''{% extends "base.html" %}
1893{% load cms_tags %}
1894
1895{% block content %}
1896<h1>{% render_model instance "callable_item" "char_1" "en" "" "admin:placeholderapp_example1_edit_field" %}</h1>
1897{% endblock content %}
1898'''
1899        request = self.get_page_request(page, user, edit=True)
1900        response = detail_view(request, ex1.pk, template_string=template_text)
1901        expected_output = (
1902            '<h1>'
1903            '<template class="cms-plugin cms-plugin-start cms-plugin-{0}-{1}-{2}-{3} cms-render-model"></template>'
1904            'char_1'
1905            '<template class="cms-plugin cms-plugin-end cms-plugin-{0}-{1}-{2}-{3} cms-render-model"></template>'
1906            '</h1>'
1907        ).format('placeholderapp', 'example1', 'callable_item', ex1.pk)
1908        self.assertContains(response, expected_output)
1909
1910    def test_admin_url_extra_field(self):
1911        user = self.get_staff()
1912        page = create_page('Test', 'col_two.html', 'en', published=True)
1913        ex1 = Example1(char_1="char_1", char_2="char_2", char_3="char_3",
1914                       char_4="char_4")
1915        ex1.save()
1916        template_text = '''{% extends "base.html" %}
1917{% load cms_tags %}
1918
1919{% block content %}
1920<h1>{% render_model instance "callable_item" "char_2" %}</h1>
1921{% endblock content %}
1922'''
1923        request = self.get_page_request(page, user, edit=True)
1924        response = detail_view(request, ex1.pk, template_string=template_text)
1925        self.assertContains(
1926            response,
1927            '<h1>'
1928            '<template class="cms-plugin cms-plugin-start cms-plugin-{0}-{1}-{2}-{3} cms-render-model"></template>'
1929            'char_1'
1930            '<template class="cms-plugin cms-plugin-end cms-plugin-{0}-{1}-{2}-{3} cms-render-model"></template>'
1931            '</h1>'.format(
1932                'placeholderapp', 'example1', 'callable_item', ex1.pk))
1933        self.assertContains(response, "/admin/placeholderapp/example1/edit-field/%s/en/" % ex1.pk)
1934        self.assertTrue(re.search(self.edit_fields_rx % "char_2", response.content.decode('utf8')))
1935
1936    def test_admin_url_multiple_fields(self):
1937        user = self.get_staff()
1938        page = create_page('Test', 'col_two.html', 'en', published=True)
1939        ex1 = Example1(char_1="char_1", char_2="char_2", char_3="char_3",
1940                       char_4="char_4")
1941        ex1.save()
1942        template_text = '''{% extends "base.html" %}
1943{% load cms_tags %}
1944
1945{% block content %}
1946<h1>{% render_model instance "callable_item" "char_1,char_2" "en" "" "admin:placeholderapp_example1_edit_field" %}</h1>
1947{% endblock content %}
1948'''
1949        request = self.get_page_request(page, user, edit=True)
1950        response = detail_view(request, ex1.pk, template_string=template_text)
1951        self.assertContains(
1952            response,
1953            '<h1>'
1954            '<template class="cms-plugin cms-plugin-start cms-plugin-{0}-{1}-{2}-{3} cms-render-model"></template>'
1955            'char_1'
1956            '<template class="cms-plugin cms-plugin-end cms-plugin-{0}-{1}-{2}-{3} cms-render-model"></template>'
1957            '</h1>'.format(
1958                'placeholderapp', 'example1', 'callable_item', ex1.pk))
1959        self.assertContains(response, "/admin/placeholderapp/example1/edit-field/%s/en/" % ex1.pk)
1960        self.assertTrue(re.search(self.edit_fields_rx % "char_1", response.content.decode('utf8')))
1961        self.assertTrue(re.search(self.edit_fields_rx % "char_1%2Cchar_2", response.content.decode('utf8')))
1962
1963    def test_instance_method(self):
1964        user = self.get_staff()
1965        page = create_page('Test', 'col_two.html', 'en', published=True)
1966        ex1 = Example1(char_1="char_1", char_2="char_2", char_3="char_3",
1967                       char_4="char_4")
1968        ex1.save()
1969        template_text = '''{% extends "base.html" %}
1970{% load cms_tags %}
1971
1972{% block content %}
1973<h1>{% render_model instance "callable_item" %}</h1>
1974{% endblock content %}
1975'''
1976        request = self.get_page_request(page, user, edit=True)
1977        response = detail_view(request, ex1.pk, template_string=template_text)
1978        self.assertContains(
1979            response,
1980            '<h1>'
1981            '<template class="cms-plugin cms-plugin-start cms-plugin-{0}-{1}-{2}-{3} cms-render-model"></template>'
1982            'char_1'
1983            '<template class="cms-plugin cms-plugin-end cms-plugin-{0}-{1}-{2}-{3} cms-render-model"></template>'
1984            '</h1>'.format(
1985                'placeholderapp', 'example1', 'callable_item', ex1.pk))
1986
1987    def test_item_from_context(self):
1988        user = self.get_staff()
1989        page = create_page('Test', 'col_two.html', 'en', published=True)
1990        ex1 = Example1(char_1="char_1", char_2="char_2", char_3="char_3",
1991                       char_4="char_4")
1992        ex1.save()
1993        template_text = '''{% extends "base.html" %}
1994{% load cms_tags %}
1995
1996{% block content %}
1997<h1>{% render_model instance item_name %}</h1>
1998{% endblock content %}
1999'''
2000        request = self.get_page_request(page, user, edit=True)
2001        response = detail_view(request, ex1.pk, template_string=template_text,
2002                               item_name="callable_item")
2003        self.assertContains(
2004            response,
2005            '<h1>'
2006            '<template class="cms-plugin cms-plugin-start cms-plugin-{0}-{1}-{2}-{3} cms-render-model"></template>'
2007            'char_1'
2008            '<template class="cms-plugin cms-plugin-end cms-plugin-{0}-{1}-{2}-{3} cms-render-model"></template>'
2009            '</h1>'.format(
2010                'placeholderapp', 'example1', 'callable_item', ex1.pk))
2011
2012    def test_edit_field(self):
2013        from django.contrib.admin import site
2014
2015        exadmin = site._registry[Example1]
2016
2017        user = self.get_superuser()
2018        page = create_page('Test', 'col_two.html', 'en', published=True)
2019        ex1 = Example1(char_1="char_1", char_2="char_2", char_3="char_3",
2020                       char_4="char_4")
2021        ex1.save()
2022
2023        request = self.get_page_request(page, user, edit=True)
2024        request.GET['edit_fields'] = 'char_1'
2025        response = exadmin.edit_field(request, ex1.pk, "en")
2026        self.assertContains(response, 'id="id_char_1"')
2027        self.assertContains(response, 'value="char_1"')
2028
2029    def test_edit_field_not_allowed(self):
2030        from django.contrib.admin import site
2031
2032        exadmin = site._registry[Example1]
2033
2034        user = self.get_superuser()
2035        page = create_page('Test', 'col_two.html', 'en', published=True)
2036        ex1 = Example1(char_1="char_1", char_2="char_2", char_3="char_3",
2037                       char_4="char_4")
2038        ex1.save()
2039
2040        request = self.get_page_request(page, user, edit=True)
2041        request.GET['edit_fields'] = 'char_3'
2042        response = exadmin.edit_field(request, ex1.pk, "en")
2043        self.assertEqual(response.status_code, 200)
2044        self.assertContains(response, 'Field char_3 not found')
2045
2046    def test_edit_page(self):
2047        language = "en"
2048        user = self.get_superuser()
2049        page = create_page('Test', 'col_two.html', language, published=True)
2050        title = page.get_title_obj(language)
2051        title.menu_title = 'Menu Test'
2052        title.page_title = 'Page Test'
2053        title.title = 'Main Test'
2054        title.save()
2055        page.publish('en')
2056        page.reload()
2057        request = self.get_page_request(page, user, edit=True)
2058        response = details(request, page.get_path())
2059        self.assertContains(
2060            response,
2061            '<template class="cms-plugin cms-plugin-start cms-plugin-cms-page-get_page_title-{0} cms-render-model"></template>'
2062            '{1}'
2063            '<template class="cms-plugin cms-plugin-end cms-plugin-cms-page-get_page_title-{0} cms-render-model"></template>'.format(
2064                page.pk, page.get_page_title(language)))
2065        self.assertContains(
2066            response,
2067            '<template class="cms-plugin cms-plugin-start cms-plugin-cms-page-get_menu_title-{0} cms-render-model"></template>'
2068            '{1}'
2069            '<template class="cms-plugin cms-plugin-end cms-plugin-cms-page-get_menu_title-{0} cms-render-model"></template>'.format(
2070                page.pk, page.get_menu_title(language)))
2071        self.assertContains(
2072            response,
2073            '<template class="cms-plugin cms-plugin-start cms-plugin-cms-page-get_title-{0} cms-render-model"></template>'
2074            '{1}'
2075            '<template class="cms-plugin cms-plugin-end cms-plugin-cms-page-get_title-{0} cms-render-model"></template>'.format(
2076                page.pk, page.get_title(language)))
2077        self.assertContains(
2078            response,
2079            '<template class="cms-plugin cms-plugin-start cms-plugin-cms-page-changelist-%s cms-render-model cms-render-model-block"></template>\n        <h3>Menu</h3>' % page.pk)
2080        self.assertContains(
2081            response,
2082            "edit_plugin: '%s?language=%s&amp;edit_fields=changelist'" % (admin_reverse('cms_page_changelist'), language))
2083
2084class CharPkFrontendPlaceholderAdminTest(ToolbarTestBase):
2085
2086    def get_admin(self):
2087        admin.autodiscover()
2088        return admin.site._registry[CharPksExample]
2089
2090    def test_url_char_pk(self):
2091        """
2092        Tests whether the frontend admin matches the edit_fields url with alphanumeric pks
2093        """
2094        ex = CharPksExample(
2095            char_1='one',
2096            slug='some-Special_slug_123',
2097        )
2098        ex.save()
2099        superuser = self.get_superuser()
2100        with UserLoginContext(self, superuser):
2101            response = self.client.get(admin_reverse('placeholderapp_charpksexample_edit_field', args=(ex.pk, 'en')),
2102                                       data={'edit_fields': 'char_1'})
2103            # if we get a response pattern matches
2104            self.assertEqual(response.status_code, 200)
2105
2106    def test_url_numeric_pk(self):
2107        """
2108        Tests whether the frontend admin matches the edit_fields url with numeric pks
2109        """
2110        ex = Example1(
2111            char_1='one',
2112            char_2='two',
2113            char_3='tree',
2114            char_4='four'
2115        )
2116        ex.save()
2117        superuser = self.get_superuser()
2118        with UserLoginContext(self, superuser):
2119            response = self.client.get(admin_reverse('placeholderapp_example1_edit_field', args=(ex.pk, 'en')),
2120                                       data={'edit_fields': 'char_1'})
2121            # if we get a response pattern matches
2122            self.assertEqual(response.status_code, 200)
2123
2124    def test_view_char_pk(self):
2125        """
2126        Tests whether the admin urls triggered when the toolbar is active works
2127        (i.e.: no NoReverseMatch is raised) with alphanumeric pks
2128        """
2129        page = create_page('Test', 'col_two.html', 'en', published=True)
2130        ex = CharPksExample(
2131            char_1='one',
2132            slug='some-Special_slug_123',
2133        )
2134        ex.save()
2135        superuser = self.get_superuser()
2136        request = self.get_page_request(page, superuser, edit=True)
2137        response = detail_view_char(request, ex.pk)
2138        # if we get a response pattern matches
2139        self.assertEqual(response.status_code, 200)
2140
2141    def test_view_numeric_pk(self):
2142        """
2143        Tests whether the admin urls triggered when the toolbar is active works
2144        (i.e.: no NoReverseMatch is raised) with numeric pks
2145        """
2146        page = create_page('Test', 'col_two.html', 'en', published=True)
2147        ex = Example1(
2148            char_1='one',
2149            char_2='two',
2150            char_3='tree',
2151            char_4='four'
2152        )
2153        ex.save()
2154        superuser = self.get_superuser()
2155        request = self.get_page_request(page, superuser, edit=True)
2156        response = detail_view(request, ex.pk)
2157        # if we get a response pattern matches
2158        self.assertEqual(response.status_code, 200)
2159
2160
2161class ToolbarAPITests(TestCase):
2162    def test_find_item(self):
2163        api = ToolbarAPIMixin()
2164        first = api.add_link_item('First', 'http://www.example.org')
2165        second = api.add_link_item('Second', 'http://www.example.org')
2166        all_links = api.find_items(LinkItem)
2167        self.assertEqual(len(all_links), 2)
2168        result = api.find_first(LinkItem, name='First')
2169        self.assertNotEqual(result, None)
2170        self.assertEqual(result.index, 0)
2171        self.assertEqual(result.item, first)
2172        result = api.find_first(LinkItem, name='Second')
2173        self.assertNotEqual(result, None)
2174        self.assertEqual(result.index, 1)
2175        self.assertEqual(result.item, second)
2176        no_result = api.find_first(LinkItem, name='Third')
2177        self.assertEqual(no_result, None)
2178
2179    def test_find_item_lazy(self):
2180        lazy_attribute = lazy(lambda x: x, str)('Test')
2181        api = ToolbarAPIMixin()
2182        api.add_link_item(lazy_attribute, None)
2183        result = api.find_first(LinkItem, name='Test')
2184        self.assertNotEqual(result, None)
2185        self.assertEqual(result.index, 0)
2186
2187    def test_not_is_staff(self):
2188        request = RequestFactory().get('/en/?%s' % get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON'))
2189        request.session = {}
2190        request.LANGUAGE_CODE = 'en'
2191        request.user = AnonymousUser()
2192        toolbar = CMSToolbar(request)
2193        self.assertEqual(len(toolbar.get_left_items()), 0)
2194        self.assertEqual(len(toolbar.get_right_items()), 0)
2195
2196    def test_item_search_result(self):
2197        item = object()
2198        result = ItemSearchResult(item, 2)
2199        self.assertEqual(result.item, item)
2200        self.assertEqual(int(result), 2)
2201        result += 2
2202        self.assertEqual(result.item, item)
2203        self.assertEqual(result.index, 4)
2204