# -*- coding: utf-8 -*-
from __future__ import with_statement
import datetime
import re

from django.contrib import admin
from django.contrib.auth.models import AnonymousUser, Permission
from django.template.defaultfilters import truncatewords
from django.test import TestCase
from django.test.client import RequestFactory
from django.test.utils import override_settings
from django.utils.functional import lazy
from django.utils.translation import ugettext_lazy as _, override
from django.core.urlresolvers import reverse

from cms.api import create_page, create_title, add_plugin
from cms.cms_toolbar import ADMIN_MENU_IDENTIFIER, ADMINISTRATION_BREAK
from cms.middleware.toolbar import ToolbarMiddleware
from cms.models import Page, UserSettings, PagePermission
from cms.toolbar.items import (ToolbarAPIMixin, LinkItem, ItemSearchResult,
                               Break, SubMenu, AjaxItem)
from cms.toolbar.toolbar import CMSToolbar
from cms.test_utils.project.placeholderapp.models import (Example1, CharPksExample,
                                                          MultilingualExample1)
from cms.test_utils.project.placeholderapp.views import (detail_view, detail_view_char,
                                                         detail_view_multi,
                                                         detail_view_multi_unfiltered)
from cms.test_utils.testcases import (CMSTestCase,
                                      URL_CMS_PAGE_ADD, URL_CMS_PAGE_CHANGE)
from cms.test_utils.util.context_managers import UserLoginContext
from cms.utils.conf import get_cms_setting
from cms.utils.urlutils import admin_reverse
from cms.views import details


class ToolbarTestBase(CMSTestCase):
    def get_page_request(self, page, user, path=None, edit=False, lang_code='en'):
        path = path or page and page.get_absolute_url()
        if edit:
            path += '?%s' % get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON')
        request = RequestFactory().get(path)
        request.session = {}
        request.user = user
        request.LANGUAGE_CODE = lang_code
        if edit:
            request.GET = {'edit': None}
        else:
            request.GET = {'edit_off': None}
        request.current_page = page
        mid = ToolbarMiddleware()
        mid.process_request(request)
        request.toolbar.populate()
        return request

    def get_anon(self):
        return AnonymousUser()

    def get_staff(self):
        staff = self._create_user('staff', True, False)
        staff.user_permissions.add(Permission.objects.get(codename='change_page'))
        return staff

    def get_nonstaff(self):
        nonstaff = self._create_user('nonstaff')
        nonstaff.user_permissions.add(Permission.objects.get(codename='change_page'))
        return nonstaff

    def get_superuser(self):
        superuser = self._create_user('superuser', True, True)
        return superuser


@override_settings(CMS_PERMISSION=False)
class ToolbarTests(ToolbarTestBase):

    def test_no_page_anon(self):
        request = self.get_page_request(None, self.get_anon(), '/')
        toolbar = CMSToolbar(request)
        toolbar.populate()
        toolbar.post_template_populate()
        items = toolbar.get_left_items() + toolbar.get_right_items()
        self.assertEqual(len(items), 0)

    def test_no_page_staff(self):
        request = self.get_page_request(None, self.get_staff(), '/')
        toolbar = CMSToolbar(request)
        toolbar.populate()
        toolbar.post_template_populate()
        items = toolbar.get_left_items() + toolbar.get_right_items()
        # Logo + admin-menu + logout
        self.assertEqual(len(items), 2, items)
        admin_items = toolbar.get_or_create_menu(ADMIN_MENU_IDENTIFIER, 'Test').get_items()
        self.assertEqual(len(admin_items), 7, admin_items)

    def test_no_page_superuser(self):
        request = self.get_page_request(None, self.get_superuser(), '/')
        toolbar = CMSToolbar(request)
        toolbar.populate()
        toolbar.post_template_populate()
        items = toolbar.get_left_items() + toolbar.get_right_items()
        # Logo + edit-mode + admin-menu + logout
        self.assertEqual(len(items), 2)
        admin_items = toolbar.get_or_create_menu(ADMIN_MENU_IDENTIFIER, 'Test').get_items()
        self.assertEqual(len(admin_items), 8, admin_items)

    def test_anon(self):
        page = create_page('test', 'nav_playground.html', 'en')
        request = self.get_page_request(page, self.get_anon())
        toolbar = CMSToolbar(request)

        items = toolbar.get_left_items() + toolbar.get_right_items()
        self.assertEqual(len(items), 0)

    def test_nonstaff(self):
        page = create_page('test', 'nav_playground.html', 'en', published=True)
        request = self.get_page_request(page, self.get_nonstaff())
        toolbar = CMSToolbar(request)
        items = toolbar.get_left_items() + toolbar.get_right_items()
        # Logo + edit-mode + logout
        self.assertEqual(len(items), 0)

    @override_settings(CMS_PERMISSIONS=True)
    def test_template_change_permission(self):
        page = create_page('test', 'nav_playground.html', 'en', published=True)
        request = self.get_page_request(page, self.get_nonstaff())
        toolbar = CMSToolbar(request)
        items = toolbar.get_left_items() + toolbar.get_right_items()
        self.assertEqual([item for item in items if item.css_class_suffix == 'templates'], [])

    def test_markup(self):
        create_page("toolbar-page", "nav_playground.html", "en", published=True)
        superuser = self.get_superuser()
        with self.login_user_context(superuser):
            response = self.client.get('/en/?%s' % get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON'))
        self.assertEqual(response.status_code, 200)
        self.assertTemplateUsed(response, 'nav_playground.html')
        self.assertContains(response, '<div id="cms_toolbar"')
        self.assertContains(response, 'cms.base.css')

    def test_markup_generic_module(self):
        create_page("toolbar-page", "col_two.html", "en", published=True)
        superuser = self.get_superuser()
        with self.login_user_context(superuser):
            response = self.client.get('/en/?%s' % get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON'))
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, '<div class="cms_submenu-item cms_submenu-item-title"><span>Generic</span>')

    def test_markup_flash_custom_module(self):
        superuser = self.get_superuser()
        create_page("toolbar-page", "col_two.html", "en", published=True)
        with self.login_user_context(superuser):
            response = self.client.get('/en/?%s' % get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON'))
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, 'href="LinkPlugin">')
        self.assertContains(response,
                            '<div class="cms_submenu-item cms_submenu-item-title"><span>Different Grouper</span>')

    def test_show_toolbar_to_staff(self):
        page = create_page("toolbar-page", "nav_playground.html", "en",
                           published=True)
        request = self.get_page_request(page, self.get_staff(), '/')
        toolbar = CMSToolbar(request)
        self.assertTrue(toolbar.show_toolbar)

    def test_show_toolbar_with_edit(self):
        page = create_page("toolbar-page", "nav_playground.html", "en",
                           published=True)
        request = self.get_page_request(page, AnonymousUser(), edit=True)
        toolbar = CMSToolbar(request)
        self.assertTrue(toolbar.show_toolbar)

    def test_show_toolbar_staff(self):
        page = create_page("toolbar-page", "nav_playground.html", "en",
                           published=True)
        request = self.get_page_request(page, self.get_staff(), edit=True)
        self.assertTrue(request.session.get('cms_build', True))
        self.assertTrue(request.session.get('cms_edit', False))

    def test_hide_toolbar_non_staff(self):
        page = create_page("toolbar-page", "nav_playground.html", "en",
                           published=True)
        request = self.get_page_request(page, self.get_nonstaff(), edit=True)
        self.assertFalse(request.session.get('cms_build', True))
        self.assertFalse(request.session.get('cms_edit', True))

    def test_show_toolbar_login_anonymous(self):
        create_page("toolbar-page", "nav_playground.html", "en", published=True)
        response = self.client.get('/en/?%s' % get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON'))
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, 'cms_form-login')

    def test_hide_toolbar_login_nonstaff(self):
        create_page("toolbar-page", "nav_playground.html", "en", published=True)
        with self.login_user_context(self.get_nonstaff()):
            response = self.client.get('/en/?%s' % get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON'))
        self.assertEqual(response.status_code, 200)
        self.assertNotContains(response, 'cms_form-login')
        self.assertNotContains(response, 'cms_toolbar')

    def test_admin_logout_staff(self):
        with override_settings(CMS_PERMISSION=True):
            with self.login_user_context(self.get_staff()):
                response = self.client.get('/en/admin/logout/?%s' % get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON'))
                self.assertTrue(response.status_code, 200)

    def test_show_toolbar_without_edit(self):
        page = create_page("toolbar-page", "nav_playground.html", "en",
                           published=True)
        request = self.get_page_request(page, AnonymousUser(), edit=False)
        toolbar = CMSToolbar(request)
        self.assertFalse(toolbar.show_toolbar)

    def test_publish_button(self):
        page = create_page('test', 'nav_playground.html', 'en', published=True)
        request = self.get_page_request(page, self.get_superuser(), edit=True)
        toolbar = CMSToolbar(request)
        toolbar.populate()
        toolbar.post_template_populate()
        self.assertTrue(toolbar.edit_mode)
        items = toolbar.get_left_items() + toolbar.get_right_items()
        self.assertEqual(len(items), 7)

    def test_no_publish_button(self):
        page = create_page('test', 'nav_playground.html', 'en', published=True)
        request = self.get_page_request(page, self.get_staff(), edit=True)
        toolbar = CMSToolbar(request)
        toolbar.populate()
        toolbar.post_template_populate()
        self.assertTrue(page.has_change_permission(request))
        self.assertFalse(page.has_publish_permission(request))
        self.assertTrue(toolbar.edit_mode)
        items = toolbar.get_left_items() + toolbar.get_right_items()
        # Logo + edit-mode + templates + page-menu + admin-menu + logout
        self.assertEqual(len(items), 6)

    def test_no_change_button(self):
        page = create_page('test', 'nav_playground.html', 'en', published=True)
        user = self.get_staff()
        user.user_permissions.all().delete()
        request = self.get_page_request(page, user, edit=True)
        toolbar = CMSToolbar(request)
        toolbar.populate()
        toolbar.post_template_populate()
        self.assertFalse(page.has_change_permission(request))
        self.assertFalse(page.has_publish_permission(request))

        items = toolbar.get_left_items() + toolbar.get_right_items()
        # Logo + page-menu + admin-menu + logout
        self.assertEqual(len(items), 3, items)
        admin_items = toolbar.get_or_create_menu(ADMIN_MENU_IDENTIFIER, 'Test').get_items()
        self.assertEqual(len(admin_items), 7, admin_items)

    def test_button_consistency_staff(self):
        """
        Tests that the buttons remain even when the language changes.
        """
        user = self.get_staff()
        cms_page = create_page('test-en', 'nav_playground.html', 'en', published=True)
        create_title('de', 'test-de', cms_page)
        cms_page.publish('de')
        en_request = self.get_page_request(cms_page, user, edit=True)
        en_toolbar = CMSToolbar(en_request)
        en_toolbar.populate()
        en_toolbar.post_template_populate()
        self.assertEqual(len(en_toolbar.get_left_items() + en_toolbar.get_right_items()), 6)
        de_request = self.get_page_request(cms_page, user, path='/de/', edit=True, lang_code='de')
        de_toolbar = CMSToolbar(de_request)
        de_toolbar.populate()
        de_toolbar.post_template_populate()
        self.assertEqual(len(de_toolbar.get_left_items() + de_toolbar.get_right_items()), 6)

    @override_settings(CMS_PLACEHOLDER_CONF={'col_left': {'name': 'PPPP'}})
    def test_placeholder_name(self):
        superuser = self.get_superuser()
        create_page("toolbar-page", "col_two.html", "en", published=True)
        with self.login_user_context(superuser):
            response = self.client.get('/en/?%s' % get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON'))
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, 'PPPP')

    def test_user_settings(self):
        superuser = self.get_superuser()
        with self.login_user_context(superuser):
            response = self.client.get('/en/admin/cms/usersettings/')
            self.assertEqual(response.status_code, 200)

    def test_remove_lang(self):
        create_page('test', 'nav_playground.html', 'en', published=True)
        superuser = self.get_superuser()
        with self.login_user_context(superuser):
            response = self.client.get('/en/?%s' % get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON'))
            self.assertEqual(response.status_code, 200)
            setting = UserSettings.objects.get(user=superuser)
            setting.language = 'it'
            setting.save()
            with self.settings(LANGUAGES=(('en', 'english'),)):
                response = self.client.get('/en/?%s' % get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON'))
                self.assertEqual(response.status_code, 200)
                self.assertNotContains(response, '/it/')

    def test_get_alphabetical_insert_position(self):
        page = create_page("toolbar-page", "nav_playground.html", "en",
                           published=True)
        request = self.get_page_request(page, self.get_staff(), '/')
        toolbar = CMSToolbar(request)
        toolbar.get_left_items()
        toolbar.get_right_items()

        admin_menu = toolbar.get_or_create_menu(ADMIN_MENU_IDENTIFIER, 'TestAppMenu')

        # Insert alpha
        alpha_position = admin_menu.get_alphabetical_insert_position('menu-alpha', SubMenu, None)

        # As this will be the first item added to this, this use should return the default, or namely None
        if not alpha_position:
            alpha_position = admin_menu.find_first(Break, identifier=ADMINISTRATION_BREAK) + 1
        admin_menu.get_or_create_menu('menu-alpha', 'menu-alpha', position=alpha_position)

        # Insert gamma (should return alpha_position + 1)
        gamma_position = admin_menu.get_alphabetical_insert_position('menu-gamma', SubMenu)
        self.assertEqual(int(gamma_position), int(alpha_position) + 1)
        admin_menu.get_or_create_menu('menu-gamma', 'menu-gamma', position=gamma_position)

        # Where should beta go? It should go right where gamma is now...
        beta_position = admin_menu.get_alphabetical_insert_position('menu-beta', SubMenu)
        self.assertEqual(beta_position, gamma_position)

    def test_out_of_order(self):
        page = create_page("toolbar-page", "nav_playground.html", "en",
                           published=True)
        request = self.get_page_request(page, self.get_staff(), '/')
        toolbar = CMSToolbar(request)
        menu1 = toolbar.get_or_create_menu("test")
        menu2 = toolbar.get_or_create_menu("test", "Test", side=toolbar.RIGHT, position=2)

        self.assertEqual(menu1, menu2)
        self.assertEqual(menu1.name, 'Test')
        self.assertEqual(len(toolbar.get_right_items()), 1)

    def test_page_create_redirect(self):
        superuser = self.get_superuser()
        create_page("home", "nav_playground.html", "en",
                           published=True)
        resolve_url = admin_reverse('cms_page_resolve')
        with self.login_user_context(superuser):
            response = self.client.post(resolve_url, {'pk': '', 'model': 'cms.page'})
            self.assertEqual(response.content.decode('utf-8'), '')
            page_data = self.get_new_page_data()
            self.client.post(URL_CMS_PAGE_ADD, page_data)

            response = self.client.post(resolve_url, {'pk': Page.objects.all()[2].pk, 'model': 'cms.page'})
            self.assertEqual(response.content.decode('utf-8'), '/en/test-page-1/')

    def test_page_edit_redirect(self):
        page1 = create_page("home", "nav_playground.html", "en",
                            published=True)
        page2 = create_page("test", "nav_playground.html", "en",
                            published=True)
        superuser = self.get_superuser()
        with self.login_user_context(superuser):
            page_data = self.get_new_page_data()
            self.client.post(URL_CMS_PAGE_CHANGE % page2.pk, page_data)
            url = admin_reverse('cms_page_resolve')
            response = self.client.post(url, {'pk': page1.pk, 'model': 'cms.page'})
            self.assertEqual(response.content.decode('utf-8'), '/en/test-page-1/')
            response = self.client.post(url, {'pk': page1.pk, 'model': 'cms.page'})
            self.assertEqual(response.content.decode('utf-8'), '/en/')
        response = self.client.post(url, {'pk': page1.pk, 'model': 'cms.page'})
        self.assertEqual(response.content.decode('utf-8'), '')

    def get_username(self, user=None, default=''):
        user = user or self.request.user
        try:
            name = user.get_full_name()
            if name:
                return name
            else:
                return user.get_username()
        except (AttributeError, NotImplementedError):
            return default

    def test_toolbar_logout(self):
        '''
        Tests that the Logout menu item includes the user's full name, if the
        relevant fields were populated in auth.User, else the user's username.
        '''
        superuser = self.get_superuser()

        # Ensure that some other test hasn't set the name fields
        if superuser.get_full_name():
            # Looks like it has been set, clear them
            superuser.first_name = ''
            superuser.last_name = ''
            superuser.save()

        page = create_page("home", "nav_playground.html", "en",
                            published=True)
        page.publish('en')
        self.get_page_request(page, superuser, '/')
        #
        # Test that the logout shows the username of the logged-in user if
        # first_name and last_name haven't been provided.
        #
        with self.login_user_context(superuser):
            response = self.client.get(page.get_absolute_url('en') + '?%s' % get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON'))
            toolbar = response.context['request'].toolbar
            admin_menu = toolbar.get_or_create_menu(ADMIN_MENU_IDENTIFIER)
            self.assertTrue(admin_menu.find_first(AjaxItem, name=_(u'Logout %s') % self.get_username(superuser)))

        #
        # Test that the logout shows the logged-in user's name, if it was
        # populated in auth.User.
        #
        superuser.first_name = 'Super'
        superuser.last_name = 'User'
        superuser.save()
        # Sanity check...
        self.get_page_request(page, superuser, '/')
        with self.login_user_context(superuser):
            response = self.client.get(page.get_absolute_url('en') + '?%s' % get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON'))
            toolbar = response.context['request'].toolbar
            admin_menu = toolbar.get_or_create_menu(ADMIN_MENU_IDENTIFIER)
            self.assertTrue(admin_menu.find_first(AjaxItem, name=_(u'Logout %s') % self.get_username(superuser)))

    def test_toolbar_logout_redirect(self):
        """
        Tests the logount AjaxItem on_success parameter in four different conditions:

         * published page: no redirect
         * unpublished page: redirect to the home page
         * published page with login_required: redirect to the home page
         * published page with view permissions: redirect to the home page
        """
        superuser = self.get_superuser()
        page0 = create_page("home", "nav_playground.html", "en",
                            published=True)
        page1 = create_page("internal", "nav_playground.html", "en",
                            published=True, parent=page0)
        page2 = create_page("unpublished", "nav_playground.html", "en",
                            published=False, parent=page0)
        page3 = create_page("login_restricted", "nav_playground.html", "en",
                            published=True, parent=page0, login_required=True)
        page4 = create_page("view_restricted", "nav_playground.html", "en",
                            published=True, parent=page0)
        PagePermission.objects.create(page=page4, can_view=True,
                                      user=superuser)
        page4.publish('en')
        page4 = page4.get_public_object()
        self.get_page_request(page4, superuser, '/')

        with self.login_user_context(superuser):
            # Published page, no redirect
            response = self.client.get(page1.get_absolute_url('en') + '?%s' % get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON'))
            toolbar = response.context['request'].toolbar
            menu_name = _(u'Logout %s') % self.get_username(superuser)
            admin_menu = toolbar.get_or_create_menu(ADMIN_MENU_IDENTIFIER)
            self.assertTrue(admin_menu.find_first(AjaxItem, name=menu_name).item.on_success)

            # Unpublished page, redirect
            response = self.client.get(page2.get_absolute_url('en') + '?%s' % get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON'))
            toolbar = response.context['request'].toolbar
            admin_menu = toolbar.get_or_create_menu(ADMIN_MENU_IDENTIFIER)

            self.assertEquals(admin_menu.find_first(AjaxItem, name=menu_name).item.on_success, '/')

            # Published page with login restrictions, redirect
            response = self.client.get(page3.get_absolute_url('en') + '?%s' % get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON'))
            toolbar = response.context['request'].toolbar
            admin_menu = toolbar.get_or_create_menu(ADMIN_MENU_IDENTIFIER)
            self.assertEquals(admin_menu.find_first(AjaxItem, name=menu_name).item.on_success, '/')

            # Published page with view permissions, redirect
            response = self.client.get(page4.get_absolute_url('en') + '?%s' % get_cms_setting('CMS_TOOLBAR_URL__EDIT_ON'))
            toolbar = response.context['request'].toolbar
            admin_menu = toolbar.get_or_create_menu(ADMIN_MENU_IDENTIFIER)
            self.assertEquals(admin_menu.find_first(AjaxItem, name=menu_name).item.on_success, '/')


class EditModelTemplateTagTest(ToolbarTestBase):
    urls = 'cms.test_utils.project.placeholderapp_urls'
    edit_fields_rx = "(\?|&amp;)edit_fields=%s"

    def tearDown(self):
        Example1.objects.all().delete()
        MultilingualExample1.objects.all().delete()
        super(EditModelTemplateTagTest, self).tearDown()

    def test_anon(self):
        user = self.get_anon()
        page = create_page('Test', 'col_two.html', 'en', published=True)
        ex1 = Example1(char_1="char_1", char_2="char_2", char_3="char_3",
                       char_4="char_4")
        ex1.save()
        request = self.get_page_request(page, user, edit=False)
        response = detail_view(request, ex1.pk)
        self.assertContains(response, "<h1>char_1</h1>")
        self.assertNotContains(response, "CMS.API")

    def test_noedit(self):
        user = self.get_staff()
        page = create_page('Test', 'col_two.html', 'en', published=True)
        ex1 = Example1(char_1="char_1", char_2="char_2", char_3="char_3",
                       char_4="char_4")
        ex1.save()
        request = self.get_page_request(page, user, edit=False)
        response = detail_view(request, ex1.pk)
        self.assertContains(response, "<h1>char_1</h1>")
        self.assertContains(response, "CMS.API")

    def test_edit(self):
        user = self.get_staff()
        page = create_page('Test', 'col_two.html', 'en', published=True)
        ex1 = Example1(char_1="char_1", char_2="char_2", char_3="char_3",
                       char_4="char_4")
        ex1.save()
        request = self.get_page_request(page, user, edit=True)
        response = detail_view(request, ex1.pk)
        self.assertContains(
            response,
            '<h1><div class="cms_plugin cms_plugin-%s-%s-%s-%s cms_render_model">char_1</div></h1>' % (
                'placeholderapp', 'example1', 'char_1', ex1.pk))

    def test_invalid_item(self):
        user = self.get_staff()
        page = create_page('Test', 'col_two.html', 'en', published=True)
        ex1 = Example1(char_1="char_1", char_2="char_2", char_3="char_3",
                       char_4="char_4")
        ex1.save()
        template_text = '''{% extends "base.html" %}
{% load cms_tags %}

{% block content %}
<h1>{% render_model fake "char_1" %}</h1>
{% endblock content %}
'''
        request = self.get_page_request(page, user, edit=True)
        response = detail_view(request, ex1.pk, template_string=template_text)
        self.assertContains(
            response,
            '<div class="cms_plugin cms_plugin-%s cms_render_model"></div>' % ex1.pk)

    def test_as_varname(self):
        user = self.get_staff()
        page = create_page('Test', 'col_two.html', 'en', published=True)
        ex1 = Example1(char_1="char_1", char_2="char_2", char_3="char_3",
                       char_4="char_4")
        ex1.save()
        template_text = '''{% extends "base.html" %}
{% load cms_tags %}

{% block content %}
<h1>{% render_model instance "char_1" as tempvar %}</h1>
{% endblock content %}
'''
        request = self.get_page_request(page, user, edit=True)
        response = detail_view(request, ex1.pk, template_string=template_text)
        self.assertNotContains(
            response,
            '<div class="cms_plugin cms_plugin-%s cms_render_model"></div>' % ex1.pk)

    def test_edit_render_placeholder(self):
        """
        Tests the {% render_placeholder %} templatetag.
        """
        user = self.get_staff()
        page = create_page('Test', 'col_two.html', 'en', published=True)
        ex1 = Example1(char_1="char_1", char_2="char_2", char_3="char_3",
                       char_4="char_4")
        ex1.save()

        render_placeholder_body = "I'm the render placeholder body"

        plugin = add_plugin(ex1.placeholder, u"TextPlugin", u"en", body=render_placeholder_body)

        template_text = '''{% extends "base.html" %}
{% load cms_tags %}

{% block content %}
<h1>{% render_placeholder instance.placeholder %}</h1>
<h2>{% render_placeholder instance.placeholder as tempvar %}</h2>
<h3>{{ tempvar }}</h3>
{% endblock content %}
'''
        request = self.get_page_request(page, user, edit=True)
        response = detail_view(request, ex1.pk, template_string=template_text)
        self.assertContains(
            response,
            '<h1><div class="cms_placeholder cms_placeholder-{0}"></div>\n'
            '<div class="cms_plugin cms_plugin-{1}">{2}</div></h1>'.format(ex1.placeholder.pk,
                                                                           plugin.pk, render_placeholder_body)
            )

        self.assertContains(
            response,
            '<h2></h2>',
        )

        #
        # NOTE: Using the render_placeholder "as" form should /not/ render
        # frontend placeholder editing support.
        #
        self.assertContains(
            response,
            '<h3>{0}</h3>'.format(render_placeholder_body)
            )

        self.assertContains(
            response,
            'CMS.Plugin(\'cms_plugin-{0}\''.format(plugin.pk)
        )

        self.assertContains(
            response,
            'CMS.Plugin(\'cms_placeholder-{0}\''.format(ex1.placeholder.pk)
        )

    def test_filters(self):
        user = self.get_staff()
        page = create_page('Test', 'col_two.html', 'en', published=True)
        ex1 = Example1(char_1="char_1, <p>hello</p>, <p>hello</p>, <p>hello</p>, <p>hello</p>", char_2="char_2",
                       char_3="char_3",
                       char_4="char_4")
        ex1.save()
        template_text = '''{% extends "base.html" %}
{% load cms_tags %}

{% block content %}
<h1>{% render_model instance "char_1" "" "" 'truncatewords:2' %}</h1>
{% endblock content %}
'''
        request = self.get_page_request(page, user, edit=True)
        response = detail_view(request, ex1.pk, template_string=template_text)
        self.assertContains(
            response,
            '<h1><div class="cms_plugin cms_plugin-%s-%s-%s-%s cms_render_model">%s</div></h1>' % (
                'placeholderapp', 'example1', 'char_1', ex1.pk, truncatewords(ex1.char_1, 2)))

    def test_filters_date(self):
        user = self.get_staff()
        page = create_page('Test', 'col_two.html', 'en', published=True)
        ex1 = Example1(char_1="char_1, <p>hello</p>, <p>hello</p>, <p>hello</p>, <p>hello</p>", char_2="char_2",
                       char_3="char_3",
                       char_4="char_4", date_field=datetime.date(2012, 1, 1))
        ex1.save()
        template_text = '''{% extends "base.html" %}
{% load cms_tags %}

{% block content %}
<h1>{% render_model instance "date_field" %}</h1>
{% endblock content %}
'''
        request = self.get_page_request(page, user, edit=True)

        response = detail_view(request, ex1.pk, template_string=template_text)
        self.assertContains(
            response,
            '<h1><div class="cms_plugin cms_plugin-%s-%s-%s-%s cms_render_model">%s</div></h1>' % (
                'placeholderapp', 'example1', 'date_field', ex1.pk,
                ex1.date_field.strftime("%Y-%m-%d")))

        template_text = '''{% extends "base.html" %}
{% load cms_tags %}

{% block content %}
<h1>{% render_model instance "date_field" "" "" 'date:"Y m d"' %}</h1>
{% endblock content %}
'''
        response = detail_view(request, ex1.pk, template_string=template_text)
        self.assertContains(
            response,
            '<h1><div class="cms_plugin cms_plugin-%s-%s-%s-%s cms_render_model">%s</div></h1>' % (
                'placeholderapp', 'example1', 'date_field', ex1.pk,
                ex1.date_field.strftime("%Y %m %d")))

    def test_filters_notoolbar(self):
        user = self.get_staff()
        page = create_page('Test', 'col_two.html', 'en', published=True)
        ex1 = Example1(char_1="char_1, <p>hello</p>, <p>hello</p>, <p>hello</p>, <p>hello</p>", char_2="char_2",
                       char_3="char_3",
                       char_4="char_4")
        ex1.save()
        template_text = '''{% extends "base.html" %}
{% load cms_tags %}

{% block content %}
<h1>{% render_model instance "char_1" "" "" 'truncatewords:2'  %}</h1>
{% endblock content %}
'''
        request = self.get_page_request(page, user, edit=False)
        response = detail_view(request, ex1.pk, template_string=template_text)
        self.assertContains(response,
                            '<h1>%s</h1>' % truncatewords(ex1.char_1, 2))

    def test_no_cms(self):
        user = self.get_staff()
        ex1 = Example1(char_1="char_1", char_2="char_2", char_3="char_3",
                       char_4="char_4")
        ex1.save()
        template_text = '''{% extends "base.html" %}
{% load cms_tags %}

{% block content %}
{% render_model_icon instance %}
{% endblock content %}
'''
        request = self.get_page_request('', user, edit=True)
        response = detail_view(request, ex1.pk, template_string=template_text)
        self.assertContains(
            response,
            '<div class="cms_plugin cms_plugin-%s-%s-%s cms_render_model_icon"><img src="/static/cms/img/toolbar/render_model_placeholder.png"></div>' % (
                'placeholderapp', 'example1', ex1.pk))
        self.assertContains(response, "'onClose': 'REFRESH_PAGE',")

    def test_icon_tag(self):
        user = self.get_staff()
        page = create_page('Test', 'col_two.html', 'en', published=True)
        ex1 = Example1(char_1="char_1", char_2="char_2", char_3="char_3",
                       char_4="char_4")
        ex1.save()
        template_text = '''{% extends "base.html" %}
{% load cms_tags %}

{% block content %}
{% render_model_icon instance %}
{% endblock content %}
'''
        request = self.get_page_request(page, user, edit=True)
        response = detail_view(request, ex1.pk, template_string=template_text)
        self.assertContains(
            response,
            '<div class="cms_plugin cms_plugin-%s-%s-%s cms_render_model_icon"><img src="/static/cms/img/toolbar/render_model_placeholder.png"></div>' % (
                'placeholderapp', 'example1', ex1.pk))

    def test_icon_followed_by_render_model_block_tag(self):
        user = self.get_staff()
        page = create_page('Test', 'col_two.html', 'en', published=True)
        ex1 = Example1(char_1="char_1", char_2="char_2", char_3="char_3",
                       char_4="char_4", date_field=datetime.date(2012, 1, 1))
        ex1.save()
        template_text = '''{% extends "base.html" %}
{% load cms_tags %}{% load url from future %}

{% block content %}
{% render_model_icon instance "char_1" %}