def test_edit_bootstrap_row(rf, bootstrap_row):
    row_plugin, row_model = bootstrap_row
    request = rf.get('/')
    ModelForm = row_plugin.get_form(request, row_model)
    data = {'num_children': 3}
    form = ModelForm(data, None, instance=row_model)
    assert form.is_valid()
    row_plugin.save_model(request, row_model, form, False)

    container_model, container_plugin = row_model.parent.get_plugin_instance()
    plugin_list = [container_model, row_model]

    # we now should have three columns attached to the row
    assert row_model.get_descendant_count() == 3
    for cms_plugin in row_model.get_descendants():
        column_model, column_plugin = cms_plugin.get_plugin_instance()
        assert isinstance(column_model, CascadeElement)
        assert isinstance(column_plugin, BootstrapColumnPlugin)
        assert column_model.parent.id == row_model.id
        plugin_list.append(column_model)

    # change data inside the first column
    cms_plugin = row_model.get_descendants().first()
    column_model, column_plugin = cms_plugin.get_plugin_instance()
    data = {
        'xs-column-width': 'col',
        'sm-column-offset': 'offset-sm-1',
        'sm-column-width': 'col-sm-3'
    }
    ModelForm = column_plugin.get_form(request, column_model)
    form = ModelForm(data, None, instance=column_model)
    assert form.is_valid()
    column_plugin.save_model(request, column_model, form, True)

    # change data inside the last column
    cms_plugin = row_model.get_descendants().last()
    column_model, column_plugin = cms_plugin.get_plugin_instance()
    data = {
        'xs-column-width': 'col',
        'sm-responsive-utils': 'hidden-sm',
        'sm-column-width': 'col-sm-4'
    }
    ModelForm = column_plugin.get_form(request, column_model)
    form = ModelForm(data, None, instance=column_model)
    assert form.is_valid()
    column_plugin.save_model(request, column_model, form, False)

    # render the plugin and check the output
    context = {
        'request': request,
    }
    content_renderer = ContentRenderer(request)
    row_model.parent.child_plugin_instances
    for plugin in plugin_list:
        plugin.refresh_from_db()
    build_plugin_tree(plugin_list)
    html = content_renderer.render_plugin(container_model, context)
    html = strip_spaces_between_tags(html).strip()
    assert html == '<div class="container"><div class="row"><div class="col col-sm-3 offset-sm-1">' \
                   '</div><div class="col"></div><div class="col col-sm-4 hidden-sm"></div></div></div>'
Exemple #2
0
    def get_form_elements(self):
        from .utils import get_nested_plugins

        if self.child_plugin_instances is None:
            # 3.1 and 3.0 compatibility
            if CMS_31:
                # default ordering is by path
                ordering = ('path', )
            else:
                ordering = ('tree_id', 'level', 'position')

            descendants = self.get_descendants().order_by(*ordering)
            # Set parent_id to None in order to
            # fool the build_plugin_tree function.
            # This is sadly necessary to avoid getting all nodes
            # higher than the form.
            parent_id = self.parent_id
            self.parent_id = None
            # Important that this is a list in order to modify
            # the current instance
            descendants_with_self = [self] + list(descendants)
            # Let the cms build the tree
            build_plugin_tree(descendants_with_self)
            # Set back the original parent
            self.parent_id = parent_id

        if self._form_elements is None:
            children = get_nested_plugins(self)
            children_instances = downcast_plugins(children)
            self._form_elements = [
                p for p in children_instances if is_form_element(p)
            ]
        return self._form_elements
Exemple #3
0
    def get_form_elements(self):
        from .utils import get_nested_plugins

        if self.child_plugin_instances is None:
            # 3.1 and 3.0 compatibility
            if CMS_31:
                # default ordering is by path
                ordering = ('path',)
            else:
                ordering = ('tree_id', 'level', 'position')

            descendants = self.get_descendants().order_by(*ordering)
            # Set parent_id to None in order to
            # fool the build_plugin_tree function.
            # This is sadly necessary to avoid getting all nodes
            # higher than the form.
            parent_id = self.parent_id
            self.parent_id = None
            # Important that this is a list in order to modify
            # the current instance
            descendants_with_self = [self] + list(descendants)
            # Let the cms build the tree
            build_plugin_tree(descendants_with_self)
            # Set back the original parent
            self.parent_id = parent_id

        if self._form_elements is None:
            children = get_nested_plugins(self)
            children_instances = downcast_plugins(children)
            self._form_elements = [
                p for p in children_instances if is_form_element(p)]
        return self._form_elements
    def test_section(self):
        heading_model = add_plugin(self.placeholder, HeadingPlugin, 'en', target=self.column_model)
        self.assertIsInstance(heading_model, CascadeElement)
        heading_plugin = heading_model.get_plugin_class_instance(self.admin_site)
        self.assertIsInstance(heading_plugin, HeadingPlugin)
        ModelForm = heading_plugin.get_form(self.request, heading_model)
        post_data = QueryDict('', mutable=True)
        post_data.update(tag_type='h2', content="Hello", element_id='foo')
        form = ModelForm(post_data, None, instance=heading_model)
        html = form.as_p()
        needle = '<input id="id_glossary_element_id" name="element_id" type="text" value="foo" />'
        self.assertInHTML(needle, html)
        self.assertTrue(form.is_valid())
        heading_plugin.save_model(self.request, heading_model, form, False)

        # check identifier
        html = heading_plugin.get_identifier(heading_model)
        expected = '<code>h2</code>: Hello <code>id="foo"</code>'
        self.assertHTMLEqual(html, expected)

        # render the Container Plugin with the Heading Plgin as a child
        self.plugin_list.append(heading_model)
        build_plugin_tree(self.plugin_list)
        # context = get_request_context(self.request)
        # html = heading_model.render_plugin(context)
        html = self.get_html(heading_model, self.get_request_context())
        expected = '<h2 id="foo">Hello</h2>'
        self.assertHTMLEqual(html, expected)

        # add another heading model with the same id
        heading_model = add_plugin(self.placeholder, HeadingPlugin, 'en', target=self.column_model)
        form = ModelForm(post_data, None, instance=heading_model)
        self.assertFalse(form.is_valid())
        expected = '<ul class="errorlist"><li>glossary<ul class="errorlist"><li>The element ID &#39;foo&#39; is not unique for this page.</li></ul></li></ul>'
        self.assertHTMLEqual(str(form.errors), expected)
def test_edit_accordion_group(rf, admin_site, bootstrap_accordion):
    request = rf.get('/')
    accordion_plugin, accordion_model = bootstrap_accordion
    first_group = accordion_model.get_first_child()
    group_model, group_plugin = first_group.get_plugin_instance(admin_site)
    data = {'heading': "Hello", 'body_padding': 'on'}
    ModelForm = group_plugin.get_form(request, group_model)
    form = ModelForm(data, None, instance=group_model)
    assert form.is_valid()
    group_plugin.save_model(request, group_model, form, False)
    assert group_model.glossary['heading'] == "Hello"
    assert group_model.glossary['body_padding'] is True

    # render the plugin
    build_plugin_tree([accordion_model, group_model])
    context = RequestContext(request)
    content_renderer = ContentRenderer(request)
    html = content_renderer.render_plugin(accordion_model, context).strip()
    html = html.replace('\n', '').replace('\t', '')
    expected = """<div id="cmsplugin_{accordion_id}" class="accordion"><div class="card">
<div class="card-header" id="heading_{group_id}"><h5 class="mb-0">
<button class="btn btn-link" type="button" data-toggle="collapse" data-target="#collapse_{group_id}" aria-expanded="true" aria-controls="collapse_{group_id}">
Hello</button></h5></div>
<div id="collapse_{group_id}" class="collapse" aria-labelledby="heading_{group_id}" data-parent="#cmsplugin_{accordion_id}">
<div class="card-body"></div></div></div></div>""".format(
        accordion_id=accordion_model.id, group_id=group_model.id)
    expected = expected.replace('\n', '').replace('\t', '')
    assert html == expected
Exemple #6
0
    def get_form_elements(self):
        from .utils import get_nested_plugins

        if self.child_plugin_instances is None:
            descendants = self.get_descendants().order_by('path')
            # Set parent_id to None in order to
            # fool the build_plugin_tree function.
            # This is sadly necessary to avoid getting all nodes
            # higher than the form.
            parent_id = self.parent_id
            self.parent_id = None
            # Important that this is a list in order to modify
            # the current instance
            descendants_with_self = [self] + list(descendants)
            # Let the cms build the tree
            build_plugin_tree(descendants_with_self)
            # Set back the original parent
            self.parent_id = parent_id

        if self._form_elements is None:
            children = get_nested_plugins(self)
            children_instances = downcast_plugins(children)
            self._form_elements = [
                p for p in children_instances if is_form_element(p)]
        return self._form_elements
    def test_plugin_context(self):
        # create container
        wrapper_model = add_plugin(self.placeholder, SimpleWrapperPlugin, 'en',
            glossary={'tag_type': 'naked'})
        wrapper_plugin = wrapper_model.get_plugin_class_instance(self.admin_site)
        self.assertIsInstance(wrapper_plugin, SimpleWrapperPlugin)

        # add an `if`-segment with some text as child
        if_segment_model = add_plugin(self.placeholder, SegmentPlugin, 'en', target=wrapper_model,
                               glossary={'open_tag': 'if', 'condition': 'user.is_superuser'})
        self.assertIsInstance(if_segment_model.get_plugin_class_instance(), SegmentPlugin)
        text_model_admin = add_plugin(self.placeholder, TextPlugin, 'en', target=if_segment_model,
            body='<p>User is admin</p>')
        self.assertIsInstance(text_model_admin.get_plugin_class_instance(), TextPlugin)

        # add an `elif`-segment with some text as child
        elif_segment_model = add_plugin(self.placeholder, SegmentPlugin, 'en', target=wrapper_model,
                               glossary={'open_tag': 'elif', 'condition': 'user.is_authenticated'})
        self.assertIsInstance(elif_segment_model.get_plugin_class_instance(), SegmentPlugin)
        text_model_staff = add_plugin(self.placeholder, TextPlugin, 'en', target=elif_segment_model,
            body='<p>User is staff</p>')
        self.assertIsInstance(text_model_staff.get_plugin_class_instance(), TextPlugin)

        # add an `else`-segment with some text as child
        else_segment_model = add_plugin(self.placeholder, SegmentPlugin, 'en', target=wrapper_model,
                               glossary={'open_tag': 'else'})
        self.assertIsInstance(else_segment_model.get_plugin_class_instance(), SegmentPlugin)
        text_model_anon = add_plugin(self.placeholder, TextPlugin, 'en', target=else_segment_model,
            body='<p>User is anonymous</p>')
        self.assertIsInstance(text_model_anon.get_plugin_class_instance(), TextPlugin)

        # build the DOM
        plugin_list = [wrapper_model, if_segment_model, text_model_admin, elif_segment_model,
                       text_model_staff, else_segment_model, text_model_anon]
        build_plugin_tree(plugin_list)

        # render the plugins as admin user
        context = get_request_context(self.request)
        html = wrapper_model.render_plugin(context)
        soup = BeautifulSoup(html)
        self.assertHTMLEqual(soup.p.text, 'User is admin')

        # render the plugins as staff user
        self.request.user = self.get_staff_user_with_no_permissions()
        context = get_request_context(self.request)
        html = wrapper_model.render_plugin(context)
        soup = BeautifulSoup(html)
        self.assertHTMLEqual(soup.p.text, 'User is staff')

        # render the plugins as anonymous user
        self.request.user = AnonymousUser
        context = get_request_context(self.request)
        html = wrapper_model.render_plugin(context)
        soup = BeautifulSoup(html)
        self.assertHTMLEqual(soup.p.text, 'User is anonymous')
Exemple #8
0
    def test_plugin_context(self):
        # create container
        wrapper_model = add_plugin(self.placeholder, SimpleWrapperPlugin, 'en',
            glossary={'tag_type': 'naked'})
        wrapper_plugin = wrapper_model.get_plugin_class_instance(self.admin_site)
        self.assertIsInstance(wrapper_plugin, SimpleWrapperPlugin)

        # add an `if`-segment with some text as child
        if_segment_model = add_plugin(self.placeholder, SegmentPlugin, 'en', target=wrapper_model,
                               glossary={'open_tag': 'if', 'condition': 'user.is_superuser'})
        self.assertIsInstance(if_segment_model.get_plugin_class_instance(), SegmentPlugin)
        text_model_admin = add_plugin(self.placeholder, TextPlugin, 'en', target=if_segment_model,
            body='<p>User is admin</p>')
        self.assertIsInstance(text_model_admin.get_plugin_class_instance(), TextPlugin)

        # add an `elif`-segment with some text as child
        elif_segment_model = add_plugin(self.placeholder, SegmentPlugin, 'en', target=wrapper_model,
                               glossary={'open_tag': 'elif', 'condition': 'user.is_authenticated'})
        self.assertIsInstance(elif_segment_model.get_plugin_class_instance(), SegmentPlugin)
        text_model_staff = add_plugin(self.placeholder, TextPlugin, 'en', target=elif_segment_model,
            body='<p>User is staff</p>')
        self.assertIsInstance(text_model_staff.get_plugin_class_instance(), TextPlugin)

        # add an `else`-segment with some text as child
        else_segment_model = add_plugin(self.placeholder, SegmentPlugin, 'en', target=wrapper_model,
                               glossary={'open_tag': 'else'})
        self.assertIsInstance(else_segment_model.get_plugin_class_instance(), SegmentPlugin)
        text_model_anon = add_plugin(self.placeholder, TextPlugin, 'en', target=else_segment_model,
            body='<p>User is anonymous</p>')
        self.assertIsInstance(text_model_anon.get_plugin_class_instance(), TextPlugin)

        # build the DOM
        plugin_list = [wrapper_model, if_segment_model, text_model_admin, elif_segment_model,
                       text_model_staff, else_segment_model, text_model_anon]
        build_plugin_tree(plugin_list)

        # render the plugins as admin user
        soup = BeautifulSoup(self.get_html(wrapper_model, self.get_request_context()), 'html.parser')
        self.assertHTMLEqual(soup.p.text, 'User is admin')

        # render the plugins as staff user
        self.request.user = self.staff_user
        soup = BeautifulSoup(self.get_html(wrapper_model, self.get_request_context()), 'html.parser')
        self.assertHTMLEqual(soup.p.text, 'User is staff')

        # render the plugins as anonymous user
        self.request.user = AnonymousUser
        soup = BeautifulSoup(self.get_html(wrapper_model, self.get_request_context()), 'html.parser')
        self.assertHTMLEqual(soup.p.text, 'User is anonymous')
    def render(self, context, instance, placeholder):
        from cms.utils.plugins import downcast_plugins, build_plugin_tree

        context = super(AliasPlugin, self).render(context, instance, placeholder)
        request = context.get('request')

        if not request or instance.is_recursive():
            return context

        if instance.plugin_id:
            plugins = instance.plugin.get_descendants().order_by('placeholder', 'path')
            plugins = [instance.plugin] + list(plugins)
            plugins = downcast_plugins(plugins, request=request)
            plugins = list(plugins)
            plugins[0].parent_id = None
            plugins = build_plugin_tree(plugins)
            context['plugins'] = plugins

        if instance.alias_placeholder_id:
            toolbar = get_toolbar_from_request(request)
            renderer = toolbar.content_renderer
            content = renderer.render_placeholder(
                placeholder=instance.alias_placeholder,
                context=context,
                editable=False,
            )
            context['content'] = mark_safe(content)
        return context
Exemple #10
0
    def get_children(self, obj):
        """
        Some plugins can contain children
        This method supposed to get children and
        prepare and return together with parent object
        :param obj:
        :return:
        """
        data = []
        plugin = obj.get_plugin_class()
        if not (getattr(plugin, 'allow_children', False)
                and getattr(plugin, 'child_classes', None)):
            return data
        children = obj.get_descendants().order_by('placeholder', 'path')
        children = [obj] + list(children)
        children = list(downcast_plugins(children))
        children[0].parent_id = None
        children = list(build_plugin_tree(children))

        def get_plugin_data(child_plugin):
            serializer = get_serializer(child_plugin,
                                        model=child_plugin._meta.model,
                                        context=self.context)
            plugin_data = serializer.data
            plugin_data['inlines'] = self.get_inlines(child_plugin)
            if child_plugin.child_plugin_instances:
                plugin_data['children'] = []
                for plug in child_plugin.child_plugin_instances:
                    plugin_data['children'].append(get_plugin_data(plug))
            return plugin_data

        for child in children[0].child_plugin_instances or []:
            data.append(get_plugin_data(child))
        return data
Exemple #11
0
    def render(self, context, instance, placeholder):
        from cms.utils.plugins import downcast_plugins, build_plugin_tree

        context = super(AliasPlugin, self).render(context, instance, placeholder)
        cms_content_renderer = context.get('cms_content_renderer')

        if not cms_content_renderer or instance.is_recursive():
            return context

        if instance.plugin_id:
            plugins = instance.plugin.get_descendants().order_by('placeholder', 'path')
            plugins = [instance.plugin] + list(plugins)
            plugins = downcast_plugins(plugins, request=cms_content_renderer.request)
            plugins = list(plugins)
            plugins[0].parent_id = None
            plugins = build_plugin_tree(plugins)
            context['plugins'] = plugins
        if instance.alias_placeholder_id:
            content = cms_content_renderer.render_placeholder(
                placeholder=instance.alias_placeholder,
                context=context,
                editable=False,
            )
            context['content'] = mark_safe(content)
        return context
    def _render_plugins(self, plugins, context):
        for plg in plugins:
            inst, name = plg.get_plugin_instance()

            if inst is None:
                # Ghost plugin
                continue

            # Get child plugins for this plugin instance, if any child plugins
            # exist
            try:
                # django CMS 3-
                plugins = (
                    inst
                    .get_descendants(include_self=True)
                    .order_by('placeholder', 'tree_id', 'level', 'position')
                )
            except (FieldError, TypeError):
                # django CMS 3.1+
                plugins = inst.get_descendants().order_by('path')

            plugins = [inst] + list(plugins)

            plugin_tree = downcast_plugins(plugins, select_placeholder=True)
            plugin_tree = list(plugin_tree)
            plugin_tree[0].parent_id = None
            plugin_tree = build_plugin_tree(plugin_tree)
            #  Replace plugin instance with plugin instance with correct
            #  child_plugin_instances set
            yield self._render_plugin(plugin_tree[0], context)
Exemple #13
0
    def get_children(self, obj):
        """
        Some plugins can contain children
        This method supposed to get children and
        prepare and return together with parent object
        :param obj:
        :return:
        """
        data = []
        plugin = obj.get_plugin_class()
        if not(getattr(plugin, 'allow_children', False) and getattr(plugin, 'child_classes', None)):
            return data
        children = obj.get_descendants().order_by('placeholder', 'path')
        children = [obj] + list(children)
        children = list(downcast_plugins(children))
        children[0].parent_id = None
        children = list(build_plugin_tree(children))

        def get_plugin_data(child_plugin):
            serializer = get_serializer(child_plugin, model=child_plugin._meta.model, context=self.context)
            plugin_data = serializer.data
            plugin_data['inlines'] = self.get_inlines(child_plugin)
            if child_plugin.child_plugin_instances:
                plugin_data['children'] = []
                for plug in child_plugin.child_plugin_instances:
                    plugin_data['children'].append(get_plugin_data(plug))
            return plugin_data

        for child in children[0].child_plugin_instances or []:
            data.append(get_plugin_data(child))
        return data
def render_alias_plugin(context, instance):
    renderer = context.get('cms_content_renderer')

    if instance.plugin:
        plugins = instance.plugin.get_descendants().order_by(
            'placeholder', 'path')
        plugins = [instance.plugin] + list(plugins)
        plugins = downcast_plugins(plugins, request=renderer.request)
        plugins = list(plugins)
        plugins[0].parent_id = None
        plugins = build_plugin_tree(plugins)
        content = renderer.render_plugin(
            instance=plugins[0],
            context=context,
            editable=False,
        )
        return mark_safe(content)

    if instance.alias_placeholder:
        content = renderer.render_placeholder(
            placeholder=instance.alias_placeholder,
            context=context,
            editable=False,
        )
        return mark_safe(content)
    return ''
    def _render_plugins(self, plugins, context):
        for plg in plugins:
            inst, name = plg.get_plugin_instance()

            if inst is None:
                # Ghost plugin
                continue

            # Get child plugins for this plugin instance, if any child plugins
            # exist
            try:
                # django CMS 3-
                plugins = (
                    inst
                    .get_descendants(include_self=True)
                    .order_by('placeholder', 'tree_id', 'level', 'position')
                )
            except (FieldError, TypeError):
                # django CMS 3.1+
                plugins = inst.get_descendants().order_by('path')

            plugins = [inst] + list(plugins)

            plugin_tree = downcast_plugins(plugins, select_placeholder=True)
            plugin_tree = list(plugin_tree)
            plugin_tree[0].parent_id = None
            plugin_tree = build_plugin_tree(plugin_tree)
            #  Replace plugin instance with plugin instance with correct
            #  child_plugin_instances set
            yield self._render_plugin(plugin_tree[0], context)
Exemple #16
0
    def render(self, context, instance, placeholder):
        template_vars = {
            'object': instance,
            'placeholder': placeholder,
        }
        lang = instance.from_language
        request = context.get('request', None)
        if not lang:
            if 'request' in context:
                lang = get_language_from_request(request)
            else:
                lang = settings.LANGUAGE_CODE
        page = instance.placeholder.page
        from_page = instance.from_page

        if page.publisher_is_draft:
            from_page = from_page.get_draft_object()
        else:
            from_page = from_page.get_public_object()

        plugins = get_cmsplugin_queryset(request).filter(
            placeholder__page=from_page,
            language=lang,
            placeholder__slot__iexact=placeholder,
            parent__isnull=True).order_by('position').select_related()

        plugin_output = []
        template_vars['parent_plugins'] = plugins

        for plg in plugins:
            tmpctx = copy.copy(context)
            tmpctx.update(template_vars)
            inst, name = plg.get_plugin_instance()
            if inst is None:
                continue
            # Get child plugins for this plugin instance, if any child plugins
            # exist
            try:
                # django CMS 3-
                plugins = [inst] + list(
                    inst.get_descendants(include_self=True).order_by(
                        'placeholder', 'tree_id', 'level', 'position'))
            except (FieldError, TypeError):
                # django CMS 3.1+
                plugins = [inst] + list(
                    inst.get_descendants().order_by('path'))
            plugin_tree = downcast_plugins(plugins)
            plugin_tree[0].parent_id = None
            plugin_tree = build_plugin_tree(plugin_tree)
            #  Replace plugin instance with plugin instance with correct
            #  child_plugin_instances set
            inst = plugin_tree[0]
            outstr = inst.render_plugin(tmpctx, placeholder)
            plugin_output.append(outstr)
        template_vars['parent_output'] = plugin_output
        context.update(template_vars)
        return context
Exemple #17
0
    def render(self, context, instance, placeholder):
        template_vars = {
            'object': instance,
            'placeholder': placeholder,
        }
        lang = instance.from_language
        request = context.get('request', None)
        if not lang:
            if 'request' in context:
                lang = get_language_from_request(request)
            else:
                lang = settings.LANGUAGE_CODE
        page = instance.placeholder.page
        from_page = instance.from_page

        if page.publisher_is_draft:
            from_page = from_page.get_draft_object()
        else:
            from_page = from_page.get_public_object()

        plugins = get_cmsplugin_queryset(request).filter(
            placeholder__page=from_page,
            language=lang,
            placeholder__slot__iexact=placeholder,
            parent__isnull=True
        ).order_by('position').select_related()

        plugin_output = []
        template_vars['parent_plugins'] = plugins

        for plg in plugins:
            tmpctx = copy.copy(context)
            tmpctx.update(template_vars)
            inst, name = plg.get_plugin_instance()
            if inst is None:
                continue
            # Get child plugins for this plugin instance, if any child plugins
            # exist
            try:
                # django CMS 3-
                plugins = [inst] + list(inst.get_descendants(include_self=True)
                                        .order_by('placeholder', 'tree_id',
                                                  'level', 'position'))
            except (FieldError, TypeError):
                # django CMS 3.1+
                plugins = [inst] + list(inst.get_descendants().order_by('path'))
            plugin_tree = downcast_plugins(plugins)
            plugin_tree[0].parent_id = None
            plugin_tree = build_plugin_tree(plugin_tree)
            #  Replace plugin instance with plugin instance with correct
            #  child_plugin_instances set
            inst = plugin_tree[0]
            outstr = inst.render_plugin(tmpctx, placeholder)
            plugin_output.append(outstr)
        template_vars['parent_output'] = plugin_output
        context.update(template_vars)
        return context
Exemple #18
0
    def test_section(self):
        heading_model = add_plugin(self.placeholder,
                                   HeadingPlugin,
                                   'en',
                                   target=self.column_model)
        self.assertIsInstance(heading_model, CascadeElement)
        heading_plugin = heading_model.get_plugin_class_instance(
            self.admin_site)
        self.assertIsInstance(heading_plugin, HeadingPlugin)
        ModelForm = heading_plugin.get_form(self.request, heading_model)
        post_data = QueryDict('', mutable=True)
        post_data.update(tag_type='h2', content="Hello", element_id='foo')
        form = ModelForm(post_data, None, instance=heading_model)
        html = form.as_p()
        needle = '<input id="id_glossary_element_id" name="element_id" type="text" value="foo" />'
        self.assertInHTML(needle, html)
        self.assertTrue(form.is_valid())
        heading_plugin.save_model(self.request, heading_model, form, False)

        # check identifier
        html = heading_plugin.get_identifier(heading_model)
        expected = '<code>h2</code>: Hello <code>id="foo"</code>'
        self.assertHTMLEqual(html, expected)

        # render the Container Plugin with the Heading Plgin as a child
        self.plugin_list.append(heading_model)
        build_plugin_tree(self.plugin_list)
        # context = get_request_context(self.request)
        # html = heading_model.render_plugin(context)
        html = self.get_html(heading_model, self.get_request_context())
        expected = '<h2 id="foo">Hello</h2>'
        self.assertHTMLEqual(html, expected)

        # add another heading model with the same id
        heading_model = add_plugin(self.placeholder,
                                   HeadingPlugin,
                                   'en',
                                   target=self.column_model)
        form = ModelForm(post_data, None, instance=heading_model)
        self.assertFalse(form.is_valid())
        expected = '<ul class="errorlist"><li>glossary<ul class="errorlist"><li>The element ID `foo` is not unique for this page.</li></ul></li></ul>'
        print(str(form.errors))
        self.assertHTMLEqual(str(form.errors), expected)
    def build_accordion_plugins(self):
        # create container
        container_model = add_plugin(self.placeholder, BootstrapContainerPlugin, 'en',
            glossary={'breakpoints': BS3_BREAKPOINT_KEYS})
        container_plugin = container_model.get_plugin_class_instance(self.admin_site)
        self.assertIsInstance(container_plugin, BootstrapContainerPlugin)

        # add one row
        row_model = add_plugin(self.placeholder, BootstrapRowPlugin, 'en', target=container_model,
                               glossary={})
        row_plugin = row_model.get_plugin_class_instance()
        self.assertIsInstance(row_plugin, BootstrapRowPlugin)

        # add one column
        column_model = add_plugin(self.placeholder, BootstrapColumnPlugin, 'en', target=row_model,
            glossary={'xs-column-width': 'col-xs-12', 'sm-column-width': 'col-sm-6',
                      'md-column-width': 'col-md-4', 'lg-column-width': 'col-lg-3'})
        column_plugin = column_model.get_plugin_class_instance()
        self.assertIsInstance(column_plugin, BootstrapColumnPlugin)

        # add accordion plugin
        accordion_model = add_plugin(self.placeholder, BootstrapAccordionPlugin, 'en', target=column_model)
        accordion_plugin = accordion_model.get_plugin_class_instance(self.admin_site)
        self.assertIsInstance(accordion_plugin, BootstrapAccordionPlugin)
        accordion_plugin.cms_plugin_instance = accordion_model.cmsplugin_ptr

        # add accordion panel
        panel_model = add_plugin(self.placeholder, BootstrapAccordionPanelPlugin, 'en',
            target=accordion_model, glossary={'panel_type': "panel-danger", 'panel_title': "Foo"})
        panel_plugin = panel_model.get_plugin_class_instance(self.admin_site)
        self.assertIsInstance(panel_plugin, BootstrapAccordionPanelPlugin)
        panel_plugin.cms_plugin_instance = panel_model.cmsplugin_ptr

        # render the plugins
        plugin_list = [container_model, row_model, column_model, accordion_model, panel_model]
        build_plugin_tree(plugin_list)
        context = get_request_context(self.request)

        self.assertEqual(accordion_plugin.get_identifier(accordion_model), 'with 1 panel')
        self.assertEqual(panel_plugin.get_identifier(panel_model), 'Foo')

        return container_model.render_plugin(context)
    def build_accordion_plugins(self):
        # create container
        container_model = add_plugin(self.placeholder, BootstrapContainerPlugin, 'en',
            glossary={'breakpoints': BS3_BREAKPOINT_KEYS})
        container_plugin = container_model.get_plugin_class_instance()
        self.assertIsInstance(container_plugin, BootstrapContainerPlugin)

        # add one row
        row_model = add_plugin(self.placeholder, BootstrapRowPlugin, 'en', target=container_model,
                               glossary={})
        row_plugin = row_model.get_plugin_class_instance()
        self.assertIsInstance(row_plugin, BootstrapRowPlugin)

        # add one column
        column_model = add_plugin(self.placeholder, BootstrapColumnPlugin, 'en', target=row_model,
            glossary={'xs-column-width': 'col-xs-12', 'sm-column-width': 'col-sm-6',
                      'md-column-width': 'col-md-4', 'lg-column-width': 'col-lg-3'})
        column_plugin = column_model.get_plugin_class_instance()
        self.assertIsInstance(column_plugin, BootstrapColumnPlugin)

        # add accordion plugin
        accordion_model = add_plugin(self.placeholder, BootstrapAccordionPlugin, 'en', target=column_model)
        accordion_plugin = accordion_model.get_plugin_class_instance()
        self.assertIsInstance(accordion_plugin, BootstrapAccordionPlugin)
        accordion_plugin.cms_plugin_instance = accordion_model.cmsplugin_ptr

        # add accordion panel
        panel_model = add_plugin(self.placeholder, BootstrapAccordionPanelPlugin, 'en',
            target=accordion_model, glossary={'panel_type': "panel-danger", 'panel_title': "Foo"})
        panel_plugin = panel_model.get_plugin_class_instance()
        self.assertIsInstance(panel_plugin, BootstrapAccordionPanelPlugin)
        panel_plugin.cms_plugin_instance = panel_model.cmsplugin_ptr

        # render the plugins
        plugin_list = [container_model, row_model, column_model, accordion_model, panel_model]
        build_plugin_tree(plugin_list)

        self.assertEqual(accordion_plugin.get_identifier(accordion_model), 'with 1 panel')
        self.assertEqual(panel_plugin.get_identifier(panel_model), 'Foo')

        return self.get_html(container_model, self.get_request_context())
Exemple #21
0
def get_plugin_tree_as_json(request, plugins):
    from cms.utils.plugins import (
        build_plugin_tree,
        downcast_plugins,
        get_plugin_restrictions,
    )

    tree_data = []
    tree_structure = []
    restrictions = {}
    toolbar = get_toolbar_from_request(request)
    template = toolbar.templates.drag_item_template
    placeholder = plugins[0].placeholder
    host_page = placeholder.page
    copy_to_clipboard = placeholder.pk == toolbar.clipboard.pk
    plugins = downcast_plugins(plugins, select_placeholder=True)
    plugin_tree = build_plugin_tree(plugins)
    get_plugin_info = get_plugin_toolbar_info

    def collect_plugin_data(plugin):
        child_classes, parent_classes = get_plugin_restrictions(
            plugin=plugin,
            page=host_page,
            restrictions_cache=restrictions,
        )
        plugin_info = get_plugin_info(
            plugin,
            children=child_classes,
            parents=parent_classes,
        )

        tree_data.append(plugin_info)

        for plugin in plugin.child_plugin_instances or []:
            collect_plugin_data(plugin)

    with force_language(toolbar.toolbar_language):
        for root_plugin in plugin_tree:
            collect_plugin_data(root_plugin)
            context = {
                'plugin': root_plugin,
                'request': request,
                'clipboard': copy_to_clipboard,
                'cms_toolbar': toolbar,
            }
            tree_structure.append(template.render(context))
    tree_data.reverse()
    return json.dumps({
        'html': '\n'.join(tree_structure),
        'plugins': tree_data
    })
Exemple #22
0
 def render(self, context, instance, placeholder):
     context['instance'] = instance
     context['placeholder'] = placeholder
     if instance.plugin_id:
         plugins = instance.plugin.get_descendants(include_self=True).order_by('placeholder', 'tree_id', 'level',
                                                                               'position')
         plugins = downcast_plugins(plugins)
         plugins[0].parent_id = None
         plugins = build_plugin_tree(plugins)
         context['plugins'] = plugins
     if instance.alias_placeholder_id:
         content = render_placeholder(instance.alias_placeholder, context)
         context['content'] = mark_safe(content)
     return context
Exemple #23
0
 def render(self, context, instance, placeholder):
     context['instance'] = instance
     context['placeholder'] = placeholder
     if instance.plugin_id:
         plugins = instance.plugin.get_descendants().order_by('placeholder', 'path')
         plugins = [instance.plugin] + list(plugins)
         plugins = downcast_plugins(plugins)
         plugins[0].parent_id = None
         plugins = build_plugin_tree(plugins)
         context['plugins'] = plugins
     if instance.alias_placeholder_id:
         content = render_placeholder(instance.alias_placeholder, context)
         context['content'] = mark_safe(content)
     return context
Exemple #24
0
 def render(self, context, instance, placeholder):
     from cms.utils.plugins import downcast_plugins, build_plugin_tree
     context['instance'] = instance
     context['placeholder'] = placeholder
     if instance.plugin_id:
         plugins = instance.plugin.get_descendants().order_by(
             'placeholder', 'path')
         plugins = [instance.plugin] + list(plugins)
         plugins = downcast_plugins(plugins)
         plugins[0].parent_id = None
         plugins = build_plugin_tree(plugins)
         context['plugins'] = plugins
     if instance.alias_placeholder_id:
         content = render_placeholder(instance.alias_placeholder, context)
         context['content'] = mark_safe(content)
     return context
Exemple #25
0
def get_plugin_tree(model, **kwargs):
    """
    Plugins in django CMS are highly related to a placeholder.

    This function builds a plugin tree for a plugin with no placeholder context.

    Makes as many database queries as many levels are in the tree.

    This is ok as forms shouldn't form very deep trees.
    """
    plugin = model.objects.get(**kwargs)
    plugin.parent = None
    current_level = [plugin]
    plugin_list = [plugin]
    while get_next_level(current_level).exists():
        current_level = get_next_level(current_level)
        current_level = downcast_plugins(queryset=current_level)
        plugin_list += current_level
    return build_plugin_tree(plugin_list)[0]
Exemple #26
0
def get_plugin_tree(model, **kwargs):
    """
    Plugins in django CMS are highly related to a placeholder.

    This function builds a plugin tree for a plugin with no placeholder context.

    Makes as many database queries as many levels are in the tree.

    This is ok as forms shouldn't form very deep trees.
    """
    plugin = model.objects.get(**kwargs)
    plugin.parent = None
    current_level = [plugin]
    plugin_list = [plugin]
    while get_next_level(current_level).exists():
        current_level = get_next_level(current_level)
        current_level = downcast_plugins(queryset=current_level)
        plugin_list += current_level
    return build_plugin_tree(plugin_list)[0]
def render_plugin(request, plugin_id, template_name='responsive_wrapper/render_plugin.html'):
    try:
        instance = CMSPlugin.objects.get(pk=hashid_to_int(plugin_id))
    except CMSPlugin.DoesNotExist:
        msg = _('Plugin not found.')
        return HttpResponseNotFound(force_text(msg))

    try:
        # django CMS 3-
        descendants = instance.get_descendants(include_self=True) \
            .order_by('placeholder', 'tree_id', 'level', 'position')
    except (FieldError, TypeError):
        # django CMS 3.1+
        descendants = instance.get_descendants().order_by('path')

    plugins = [instance] + list(descendants)
    plugins = downcast_plugins(plugins)
    plugins[0].parent_id = None
    plugins = build_plugin_tree(plugins)

    context = RequestContext(request)
    context['plugins'] = plugins
    return render_to_response(template_name, {}, context)
Exemple #28
0
def render_alias_plugin(context, instance):
    request = context['request']
    toolbar = get_toolbar_from_request(request)
    renderer = toolbar.content_renderer
    source = (instance.plugin or instance.alias_placeholder)

    # In edit mode, content is shown regardless of the source page publish status.
    # In published mode, content is shown only if the source page is published.
    if not (toolbar.edit_mode_active) and source and source.page:
        # this is bad but showing unpublished content is worse
        can_see_content = source.page.is_published(instance.language)
    else:
        can_see_content = True

    if can_see_content and instance.plugin:
        plugins = instance.plugin.get_descendants().order_by(
            'placeholder', 'path')
        plugins = [instance.plugin] + list(plugins)
        plugins = downcast_plugins(plugins, request=request)
        plugins = list(plugins)
        plugins[0].parent_id = None
        plugins = build_plugin_tree(plugins)
        content = renderer.render_plugin(
            instance=plugins[0],
            context=context,
            editable=False,
        )
        return mark_safe(content)

    if can_see_content and instance.alias_placeholder:
        content = renderer.render_placeholder(
            placeholder=instance.alias_placeholder,
            context=context,
            editable=False,
        )
        return mark_safe(content)
    return ''
    def test_jumbotron_plugin(self):
        # create container
        container_model = add_plugin(self.placeholder, BootstrapContainerPlugin, 'en',
            glossary={'breakpoints': BS3_BREAKPOINT_KEYS})
        container_plugin = container_model.get_plugin_class_instance(self.admin_site)
        self.assertIsInstance(container_plugin, BootstrapContainerPlugin)

        # add one row
        row_model = add_plugin(self.placeholder, BootstrapRowPlugin, 'en', target=container_model,
                               glossary={})
        row_plugin = row_model.get_plugin_class_instance()
        self.assertIsInstance(row_plugin, BootstrapRowPlugin)

        # add one column
        column_model = add_plugin(self.placeholder, BootstrapColumnPlugin, 'en', target=row_model,
            glossary={'xs-column-width': 'col-xs-12', 'sm-column-width': 'col-sm-6',
                      'md-column-width': 'col-md-4', 'lg-column-width': 'col-lg-3'})
        column_plugin = column_model.get_plugin_class_instance()
        self.assertIsInstance(column_plugin, BootstrapColumnPlugin)

        # add Jumbotron plugin
        jumbotron_model = add_plugin(self.placeholder, BootstrapJumbotronPlugin, 'en', target=column_model)
        self.assertIsInstance(jumbotron_model, ImagePropertyMixin)
        self.assertIsInstance(jumbotron_model, ImageBackgroundMixin)
        jumbotron_plugin = jumbotron_model.get_plugin_class_instance(self.admin_site)
        self.assertIsInstance(jumbotron_plugin, BootstrapJumbotronPlugin)
        jumbotron_plugin.cms_plugin_instance = jumbotron_model.cmsplugin_ptr

        # edit jumbotron model
        post_data = QueryDict('', mutable=True)
        post_data.update({
            'background-size': 'auto',
            'background-repeat': 'no-repeat',
            'background-width-height-width': '',
            'background-attachment': 'fixed',
            'background-color_color': '#aabbcc',
            'background-color_disabled': '',
            'background-vertical-position': 'center',
            'background-horizontal-position': 'center',
            'breakpoints': ['xs', 'sm', 'md', 'lg'],
            'extra_inline_styles:Paddings-padding-bottom': '',
            'background-width-height-height': '',
            'container_max_heights-xs': '100%',
            'container_max_heights-sm': '100%',
            'container_max_heights-md': '100%',
            'container_max_heights-lg': '100%',
            'extra_inline_styles:Paddings-padding-top': '200px',
            'resize-options': ['crop', 'subject_location', 'high_resolution'],
            'image_file': str(self.image.pk),
        })

        ModelForm = jumbotron_plugin.get_form(self.request, jumbotron_model)
        form = ModelForm(post_data, None, instance=jumbotron_model)
        self.assertTrue(form.is_valid())
        jumbotron_plugin.save_model(self.request, jumbotron_model, form, False)

        del jumbotron_model._image_model  # invalidate cache
        self.assertEqual(jumbotron_plugin.get_identifier(jumbotron_model), 'Demo Image')

        # render the plugins
        plugin_list = [container_model, row_model, column_model, jumbotron_model]
        build_plugin_tree(plugin_list)
        context = get_request_context(self.request)

        html = container_model.render_plugin(context)
        print(html)
        self.assertHTMLEqual("""
<div class="container"><div class="row"><div class="col-xs-12 col-sm-6 col-md-4 col-lg-3">
  <div id="cascadeelement_id-{}" class="jumbotron"></div>
</div></div></div>""".format(jumbotron_model.pk), html)
        self.assertEqual('background-color: #aabbcc;', jumbotron_model.background_color)
        self.assertEqual('background-position: center center;', jumbotron_model.background_position)
        self.assertEqual('background-repeat: no-repeat;', jumbotron_model.background_repeat)
        self.assertEqual('background-attachment: fixed;', jumbotron_model.background_attachment)
        self.assertEqual('background-size: auto;', jumbotron_model.background_size)
    def test_plugin_context(self):
        # create container
        container_model = add_plugin(
            self.placeholder,
            BootstrapContainerPlugin,
            'en',
            glossary={'breakpoints': CASCADE_BREAKPOINTS_LIST})
        container_plugin = container_model.get_plugin_class_instance(
            self.admin_site)
        self.assertIsInstance(container_plugin, BootstrapContainerPlugin)

        # add one row
        row_model = add_plugin(self.placeholder,
                               BootstrapRowPlugin,
                               'en',
                               target=container_model,
                               glossary={})
        row_plugin = row_model.get_plugin_class_instance()
        self.assertIsInstance(row_plugin, BootstrapRowPlugin)

        # add one column
        column_model = add_plugin(self.placeholder,
                                  BootstrapColumnPlugin,
                                  'en',
                                  target=row_model,
                                  glossary={
                                      'xs-column-width': 'col-xs-12',
                                      'sm-column-width': 'col-sm-6',
                                      'md-column-width': 'col-md-4',
                                      'lg-column-width': 'col-lg-3'
                                  })
        column_plugin = column_model.get_plugin_class_instance()
        self.assertIsInstance(column_plugin, BootstrapColumnPlugin)

        # add an image
        image_model = add_plugin(self.placeholder,
                                 BootstrapImagePlugin,
                                 'en',
                                 target=column_model)
        self.assertIsInstance(image_model, SharableCascadeElement)
        image_plugin = image_model.get_plugin_class_instance(self.admin_site)
        self.assertIsInstance(image_plugin, BootstrapImagePlugin)
        image_plugin.cms_plugin_instance = image_model.cmsplugin_ptr

        # upload an image and change the form
        ModelForm = image_plugin.get_form(self.request, image_model)
        image = self.upload_demo_image()
        post_data = QueryDict('', mutable=True)
        post_data.update({
            'image_file': image.pk,
            'link_type': 'none',
            'image-width-fixed': '300px'
        })
        image_model._image_model = image
        form = ModelForm(post_data, None, instance=image_model)
        self.assertTrue(form.is_valid())
        image_plugin.save_model(self.request, image_model, form, False)

        # render the plugins
        plugin_list = [container_model, row_model, column_model, image_model]
        build_plugin_tree(plugin_list)
        context = get_request_context(self.request)
        html = container_model.render_plugin(context)
        soup = BeautifulSoup(html)
        self.assertEqual(soup.img['height'], '100')
        self.assertEqual(soup.img['width'], '300')
        self.assertTrue(
            'demo_image.png__300x100_q85_subsampling-2' in str(soup.img))

        # use a responsive image
        post_data.setlist('image-shapes', ['img-responsive'])
        form = ModelForm(post_data, None, instance=image_model)
        self.assertTrue(form.is_valid())
        image_plugin.save_model(self.request, image_model, form, False)
        html = container_model.render_plugin(context)
        soup = BeautifulSoup(html)
        self.assertTrue('img-responsive' in soup.img['class'])
        sizes = [s.strip() for s in soup.img['sizes'].split(',')]
        self.assertTrue('(max-width: 768px) 720px' in sizes)
        self.assertTrue(
            '(min-width: 768px) and (max-width: 992px) 345px' in sizes)
        self.assertTrue(
            '(min-width: 992px) and (max-width: 1200px) 293px' in sizes)
        self.assertTrue('(min-width: 1200px) 262px' in sizes)
        srcsets = [s.strip() for s in soup.img['srcset'].split(',')]
        self.assertEqual(
            len([
                s for s in srcsets if s.endswith(
                    'demo_image.png__293x98_q85_subsampling-2.jpg 293w')
            ]), 1)
        self.assertEqual(
            len([
                s for s in srcsets if s.endswith(
                    'demo_image.png__720x240_q85_subsampling-2.jpg 720w')
            ]), 1)
        self.assertEqual(
            len([
                s for s in srcsets if s.endswith(
                    'demo_image.png__345x115_q85_subsampling-2.jpg 345w')
            ]), 1)
        self.assertEqual(
            len([
                s for s in srcsets if s.endswith(
                    'demo_image.png__262x87_q85_subsampling-2.jpg 262w')
            ]), 1)
        self.assertTrue(soup.img['src'].endswith(
            'demo_image.png__720x240_q85_subsampling-2.jpg'))
Exemple #31
0
    def test_jumbotron_plugin(self):
        # create container
        container_model = add_plugin(self.placeholder, BootstrapContainerPlugin, 'en',
            glossary={'breakpoints': BS3_BREAKPOINT_KEYS})
        container_plugin = container_model.get_plugin_class_instance(self.admin_site)
        self.assertIsInstance(container_plugin, BootstrapContainerPlugin)

        # add one row
        row_model = add_plugin(self.placeholder, BootstrapRowPlugin, 'en', target=container_model,
                               glossary={})
        row_plugin = row_model.get_plugin_class_instance()
        self.assertIsInstance(row_plugin, BootstrapRowPlugin)

        # add one column
        column_model = add_plugin(self.placeholder, BootstrapColumnPlugin, 'en', target=row_model,
            glossary={'xs-column-width': 'col-xs-12', 'sm-column-width': 'col-sm-6',
                      'md-column-width': 'col-md-4', 'lg-column-width': 'col-lg-3'})
        column_plugin = column_model.get_plugin_class_instance()
        self.assertIsInstance(column_plugin, BootstrapColumnPlugin)

        # add Jumbotron plugin
        jumbotron_model = add_plugin(self.placeholder, BootstrapJumbotronPlugin, 'en', target=column_model)
        self.assertIsInstance(jumbotron_model, ImagePropertyMixin)
        self.assertIsInstance(jumbotron_model, ImageBackgroundMixin)
        jumbotron_plugin = jumbotron_model.get_plugin_class_instance(self.admin_site)
        self.assertIsInstance(jumbotron_plugin, BootstrapJumbotronPlugin)
        jumbotron_plugin.cms_plugin_instance = jumbotron_model.cmsplugin_ptr

        # edit jumbotron model
        post_data = QueryDict('', mutable=True)
        post_data.update({
            'background_size': 'auto',
            'background_repeat': 'no-repeat',
            'background_width-height-width': '',
            'background_attachment': 'fixed',
            'background_color_color': '#aabbcc',
            'background_color_disabled': '',
            'background_vertical_position': 'center',
            'background_horizontal_position': 'center',
            'breakpoints': ['xs', 'sm', 'md', 'lg'],
            'extra_inline_styles:Paddings-padding-bottom': '',
            'background-width-height-height': '',
            'container_max_heights-xs': '100%',
            'container_max_heights-sm': '100%',
            'container_max_heights-md': '100%',
            'container_max_heights-lg': '100%',
            'extra_inline_styles:Paddings-padding-top': '200px',
            'resize_options': ['crop', 'subject_location', 'high_resolution'],
            'image_file': str(self.image.pk),
        })

        ModelForm = jumbotron_plugin.get_form(self.request, jumbotron_model)
        form = ModelForm(post_data, None, instance=jumbotron_model)
        self.assertTrue(form.is_valid())
        jumbotron_plugin.save_model(self.request, jumbotron_model, form, False)

        del jumbotron_model._image_model  # invalidate cache
        self.assertEqual(jumbotron_plugin.get_identifier(jumbotron_model), 'Demo Image')

        # render the plugins
        plugin_list = [container_model, row_model, column_model, jumbotron_model]
        build_plugin_tree(plugin_list)

        html = self.get_html(container_model, self.get_request_context())
        # print(html)
        self.assertHTMLEqual("""
<div class="container"><div class="row"><div class="col-xs-12 col-sm-6 col-md-4 col-lg-3">
  <div id="cascadeelement_id-{}" class="jumbotron"></div>
</div></div></div>""".format(jumbotron_model.pk), html)
        self.assertEqual('background-color: #aabbcc;', jumbotron_model.background_color)
        self.assertEqual('background-position: center center;', jumbotron_model.background_position)
        self.assertEqual('background-repeat: no-repeat;', jumbotron_model.background_repeat)
        self.assertEqual('background-attachment: fixed;', jumbotron_model.background_attachment)
        self.assertEqual('background-size: auto;', jumbotron_model.background_size)
    def test_add_font(self):
        with self.login_user_context(self.admin_user):
            # upload the zipfile into the filer's clipboard
            filename = os.path.join(os.path.dirname(__file__), 'assets/fontello-b504201f.zip')
            with open(filename, 'rb') as zipfile:
                uploaded_file = SimpleUploadedFile('fontello-b504201f.zip', zipfile.read(), content_type='application/zip')
            request = self.get_request(reverse('admin:filer-ajax_upload'))
            self.assertTrue(request.user.is_staff, "User is not a staff user")
            request.FILES.update(file=uploaded_file)
            response = ajax_upload(request)
            self.assertEqual(response.status_code, 200)
            content = json.loads(response.content.decode('utf-8'))
            self.assertDictContainsSubset({'label': 'fontello-b504201f.zip'}, content)

            # save the form and submit the remaining fields
            add_iconfont_url = reverse('admin:cmsplugin_cascade_iconfont_add')
            data = {
                'identifier': "Fontellico",
                'zip_file': content['file_id'],
                '_continue': "Save and continue editing",
            }
            response = self.client.post(add_iconfont_url, data)
            self.assertEqual(response.status_code, 302)
            resolver_match = resolve(response.url)
            self.assertEqual(resolver_match.url_name, 'cmsplugin_cascade_iconfont_change')

            # check the content of the uploaded file
            icon_font = IconFont.objects.get(pk=resolver_match.args[0])
            self.assertEqual(icon_font.identifier, "Fontellico")
            self.assertEqual(icon_font.config_data['name'], 'fontelico')
            self.assertEqual(len(icon_font.config_data['glyphs']), 34)

            # check if the uploaded fonts are rendered inside Preview Icons
            response = self.client.get(response.url)
            self.assertEqual(response.status_code, 200)
            soup = BeautifulSoup(response.content, 'lxml')
            preview_iconfont = soup.find('div', class_="preview-iconfont")
            icon_items = preview_iconfont.ul.find_all('li')
            self.assertEqual(len(icon_items), 34)
            self.assertListEqual(icon_items[0].i.attrs['class'], ['icon-emo-happy'])
            self.assertListEqual(icon_items[33].i.attrs['class'], ['icon-marquee'])

            # select icon font from toolbar
            self.placeholder.page.cascadepage.icon_font = icon_font
            self.placeholder.page.cascadepage.save()

            # create container
            container_model = add_plugin(self.placeholder, BootstrapContainerPlugin, 'en',
                                         glossary={'breakpoints': BS3_BREAKPOINT_KEYS})
            container_plugin = container_model.get_plugin_class_instance()
            self.assertIsInstance(container_plugin, BootstrapContainerPlugin)

            # add icon as child to this container
            glossary = {"font_size": "10em", "color": ["","#88258e"], "background_color": ["on","#c8ffcd"],
                        "symbol": "emo-wink", "icon_font": icon_font.pk,
                        "border_radius":"50%","border":["","solid","#000000"]}
            icon_model = add_plugin(self.placeholder, FramedIconPlugin, 'en', target=container_model,
                                    glossary=glossary)
            icon_plugin = icon_model.get_plugin_class_instance()
            self.assertIsInstance(icon_plugin, FramedIconPlugin)

            # render the plugins
            plugin_list = [container_model, icon_model]
            build_plugin_tree(plugin_list)
            html = self.get_html(container_model, self.get_request_context())
            soup = BeautifulSoup(html, 'lxml')

            # look for the icon symbol
            style = soup.find('span', class_='icon-emo-wink').attrs['style'].split(';')
            self.assertIn('color:#88258e', style)
            self.assertIn('display:inline-block', style)

            # look for the CSS file
            response = self.client.get(container_model.placeholder.page.get_absolute_url() + '?edit')
            self.assertEqual(response.status_code, 200)
            soup = BeautifulSoup(response.content, 'lxml')
            links = soup.head.find_all('link')
            for link in links:
                if link.attrs['href'].endswith('fontelico.css'):
                    break
            else:
                self.fail("No CSS file with font definition found")
    def test_container_context(self):
        # add a Bootstrap Container Plugin
        container_model = add_plugin(
            self.placeholder,
            BootstrapContainerPlugin,
            'en',
            glossary={'breakpoints': BS3_BREAKPOINT_KEYS})
        self.assertIsInstance(container_model, CascadeElement)
        container_plugin = container_model.get_plugin_class_instance(
            self.admin_site)
        self.assertIsInstance(container_plugin, BootstrapContainerPlugin)
        ModelForm = container_plugin.get_form(self.request, container_model)
        post_data = QueryDict('', mutable=True)
        post_data.setlist('breakpoints', ['sm', 'md'])
        form = ModelForm(post_data, None, instance=container_model)
        html = form.as_p()
        self.assertInHTML(
            '<input id="id_glossary_breakpoints_0" name="breakpoints" type="checkbox" value="xs" />',
            html)
        self.assertInHTML(
            '<input checked="checked" id="id_glossary_breakpoints_2" name="breakpoints" type="checkbox" value="md" />',
            html)
        self.assertInHTML(
            '<input id="id_glossary_fluid" name="fluid" type="checkbox" />',
            html)
        container_plugin.save_model(self.request, container_model, form, False)
        self.assertListEqual(container_model.glossary['breakpoints'],
                             ['sm', 'md'])
        self.assertTrue('fluid' in container_model.glossary)
        self.assertEqual(str(container_model), 'for tablets, laptops')

        # add a RowPlugin with 3 Columns
        row_model = add_plugin(self.placeholder,
                               BootstrapRowPlugin,
                               'en',
                               target=container_model)
        row_plugin = row_model.get_plugin_class_instance()
        row_change_form = BootstrapRowForm({'num_children': 3})
        row_change_form.full_clean()
        row_plugin.save_model(self.request, row_model, row_change_form, False)
        self.assertDictEqual(row_model.glossary, {})
        self.assertIsInstance(row_model, CascadeElement)
        self.assertEqual(str(row_model), 'with 3 columns')
        plugin_list = [container_model, row_model]
        columns_qs = CascadeElement.objects.filter(parent_id=row_model.id)
        self.assertEqual(columns_qs.count(), 3)
        for column_model in columns_qs:
            self.assertIsInstance(column_model, CascadeElement)
            column_plugin = column_model.get_plugin_class_instance()
            self.assertIsInstance(column_plugin, BootstrapColumnPlugin)
            self.assertEqual(column_model.parent.id, row_model.id)
            self.assertEqual(str(column_model), 'default width: 4 units')
            plugin_list.append(column_model)

        # Render the Container Plugin with all of its children
        build_plugin_tree(plugin_list)
        context = get_request_context(self.request)
        html = container_model.render_plugin(context)
        self.assertHTMLEqual(
            html, '<div class="container"><div class="row">' +
            '<div class="col-sm-4"></div><div class="col-sm-4"></div><div class="col-sm-4"></div>'
            + '</div></div>')

        # change data inside the first column
        column_model = columns_qs[0]
        delattr(column_model, '_inst')
        column_plugin = column_model.get_plugin_class_instance(self.admin_site)
        column_plugin.cms_plugin_instance = column_model
        post_data = QueryDict('', mutable=True)
        post_data.update({
            'sm-column-offset': 'col-sm-offset-1',
            'sm-column-width': 'col-sm-3'
        })
        ModelForm = column_plugin.get_form(self.request, column_model)
        form = ModelForm(post_data, None, instance=column_model)
        self.assertTrue(form.is_valid())
        column_plugin.save_model(self.request, column_model, form, True)

        # change data inside the second column
        column_model = columns_qs[1]
        delattr(column_model, '_inst')
        column_plugin = column_model.get_plugin_class_instance(self.admin_site)
        column_plugin.cms_plugin_instance = column_model
        post_data = QueryDict('', mutable=True)
        post_data.update({
            'sm-responsive-utils': 'hidden-sm',
            'sm-column-width': 'col-sm-4'
        })
        ModelForm = column_plugin.get_form(self.request, column_model)
        form = ModelForm(post_data, None, instance=column_model)
        self.assertTrue(form.is_valid())
        column_plugin.save_model(self.request, column_model, form, False)
        html = container_model.render_plugin(context)
        self.assertHTMLEqual(
            html, '<div class="container"><div class="row">' +
            '<div class="col-sm-3 col-sm-offset-1"></div><div class="col-sm-4 hidden-sm"></div><div class="col-sm-4"></div>'
            + '</div></div>')
    def test_plugin_context(self):
        # create container
        container_model = add_plugin(self.placeholder, BootstrapContainerPlugin, 'en',
            glossary={'breakpoints': CASCADE_BREAKPOINTS_LIST})
        container_plugin = container_model.get_plugin_class_instance(self.admin_site)
        self.assertIsInstance(container_plugin, BootstrapContainerPlugin)

        # add one row
        row_model = add_plugin(self.placeholder, BootstrapRowPlugin, 'en', target=container_model,
                               glossary={})
        row_plugin = row_model.get_plugin_class_instance()
        self.assertIsInstance(row_plugin, BootstrapRowPlugin)

        # add one column
        column_model = add_plugin(self.placeholder, BootstrapColumnPlugin, 'en', target=row_model,
            glossary={'xs-column-width': 'col-xs-12', 'sm-column-width': 'col-sm-6',
                      'md-column-width': 'col-md-4', 'lg-column-width': 'col-lg-3'})
        column_plugin = column_model.get_plugin_class_instance()
        self.assertIsInstance(column_plugin, BootstrapColumnPlugin)

        # add an image
        image_model = add_plugin(self.placeholder, BootstrapImagePlugin, 'en', target=column_model)
        self.assertIsInstance(image_model, SharableCascadeElement)
        image_plugin = image_model.get_plugin_class_instance(self.admin_site)
        self.assertIsInstance(image_plugin, BootstrapImagePlugin)
        image_plugin.cms_plugin_instance = image_model.cmsplugin_ptr

        # upload an image and change the form
        ModelForm = image_plugin.get_form(self.request, image_model)
        image = self.upload_demo_image()
        post_data = QueryDict('', mutable=True)
        post_data.update({'image_file': image.pk, 'link_type': 'none', 'image-width-fixed': '300px'})
        image_model._image_model = image
        form = ModelForm(post_data, None, instance=image_model)
        self.assertTrue(form.is_valid())
        image_plugin.save_model(self.request, image_model, form, False)

        # render the plugins
        plugin_list = [container_model, row_model, column_model, image_model]
        build_plugin_tree(plugin_list)
        context = get_request_context(self.request)
        html = container_model.render_plugin(context)
        soup = BeautifulSoup(html)
        self.assertEqual(soup.img['height'], '100')
        self.assertEqual(soup.img['width'], '300')
        self.assertTrue('demo_image.png__300x100_q85_subsampling-2' in str(soup.img))

        # use a responsive image
        post_data.setlist('image-shapes', ['img-responsive'])
        form = ModelForm(post_data, None, instance=image_model)
        self.assertTrue(form.is_valid())
        image_plugin.save_model(self.request, image_model, form, False)
        html = container_model.render_plugin(context)
        soup = BeautifulSoup(html)
        self.assertTrue('img-responsive' in soup.img['class'])
        sizes = [s.strip() for s in soup.img['sizes'].split(',')]
        self.assertTrue('(max-width: 768px) 720px' in sizes)
        self.assertTrue('(min-width: 768px) and (max-width: 992px) 345px' in sizes)
        self.assertTrue('(min-width: 992px) and (max-width: 1200px) 293px' in sizes)
        self.assertTrue('(min-width: 1200px) 262px' in sizes)
        srcsets = [s.strip() for s in soup.img['srcset'].split(',')]
        self.assertEqual(len([s for s in srcsets if s.endswith('demo_image.png__293x98_q85_subsampling-2.jpg 293w')]), 1)
        self.assertEqual(len([s for s in srcsets if s.endswith('demo_image.png__720x240_q85_subsampling-2.jpg 720w')]), 1)
        self.assertEqual(len([s for s in srcsets if s.endswith('demo_image.png__345x115_q85_subsampling-2.jpg 345w')]), 1)
        self.assertEqual(len([s for s in srcsets if s.endswith('demo_image.png__262x87_q85_subsampling-2.jpg 262w')]), 1)
        self.assertTrue(soup.img['src'].endswith('demo_image.png__720x240_q85_subsampling-2.jpg'))
Exemple #35
0
    def test_plugin_context(self):
        # create container
        container_model = add_plugin(
            self.placeholder,
            BootstrapContainerPlugin,
            'en',
            glossary={'breakpoints': BS3_BREAKPOINT_KEYS})
        container_plugin = container_model.get_plugin_class_instance(
            self.admin_site)
        self.assertIsInstance(container_plugin, BootstrapContainerPlugin)

        # add one row
        row_model = add_plugin(self.placeholder,
                               BootstrapRowPlugin,
                               'en',
                               target=container_model,
                               glossary={})
        row_plugin = row_model.get_plugin_class_instance()
        self.assertIsInstance(row_plugin, BootstrapRowPlugin)

        # add one column
        column_model = add_plugin(self.placeholder,
                                  BootstrapColumnPlugin,
                                  'en',
                                  target=row_model,
                                  glossary={
                                      'xs-column-width': 'col-xs-12',
                                      'sm-column-width': 'col-sm-6',
                                      'md-column-width': 'col-md-4',
                                      'lg-column-width': 'col-lg-3'
                                  })
        column_plugin = column_model.get_plugin_class_instance()
        self.assertIsInstance(column_plugin, BootstrapColumnPlugin)

        # add a picture
        picture_model = add_plugin(self.placeholder,
                                   BootstrapPicturePlugin,
                                   'en',
                                   target=column_model)
        self.assertIsInstance(picture_model, SharableCascadeElement)
        picture_plugin = picture_model.get_plugin_class_instance(
            self.admin_site)
        self.assertIsInstance(picture_plugin, BootstrapPicturePlugin)
        picture_plugin.cms_plugin_instance = picture_model.cmsplugin_ptr

        # upload an image and change the form
        ModelForm = picture_plugin.get_form(self.request, picture_model)
        image = self.upload_demo_image()
        post_data = QueryDict('', mutable=True)
        post_data.update({
            'image_file': image.pk,
            'link_type': 'none',
            'responsive_heights-xs': '50%',
            'responsive_heights-sm': '66%',
            'responsive_heights-md': '75%',
            'responsive_heights-lg': '100%',
            'responsive_zoom-lg': '40%',
            'responsive_zoom-lg': '25%',
            'responsive_zoom-lg': '15%',
            'responsive_zoom-lg': '0%'
        })
        post_data.setlist('resize_options', ['crop'])
        picture_model._image_model = image
        form = ModelForm(post_data, None, instance=picture_model)
        self.assertTrue(form.is_valid())
        picture_plugin.save_model(self.request, picture_model, form, False)

        # render the plugins
        plugin_list = [container_model, row_model, column_model, picture_model]
        build_plugin_tree(plugin_list)
        soup = BeautifulSoup(
            self.get_html(container_model, self.get_request_context()))
        self.assertEqual(soup.img['height'], '240')
        self.assertEqual(soup.img['width'], '720')
        self.assertTrue('demo_image.png__720x240_q85_crop_subsampling-2.jpg' in
                        str(soup.img))
        sources = dict(
            (s['media'], s['srcset']) for s in soup.picture.find_all('source'))
        self.assertTrue('demo_image.png__720x120_q85_crop_subsampling-2.jpg' in
                        sources['(max-width: 768px)'])
        self.assertTrue('demo_image.png__345x76_q85_crop_subsampling-2.jpg' in
                        sources['(min-width: 768px) and (max-width: 992px)'])
        self.assertTrue('demo_image.png__293x73_q85_crop_subsampling-2.jpg' in
                        sources['(min-width: 992px) and (max-width: 1200px)'])
        # Due to an different round implimentation in python3 height can vary by 1 to 2 pixels
        self.assertTrue(
            bool(
                re.search(
                    r'demo_image.png__262x8\d_q85_crop_subsampling-2.jpg$',
                    sources['(min-width: 1200px)'])))

        # with Retina images
        post_data.setlist('resize_options', ['crop', 'high_resolution'])
        form = ModelForm(post_data, None, instance=picture_model)
        self.assertTrue(form.is_valid())
        picture_plugin.save_model(self.request, picture_model, form, False)
        soup = BeautifulSoup(
            self.get_html(container_model, self.get_request_context()))
        self.assertEqual(soup.img['height'], '240')
        self.assertEqual(soup.img['width'], '720')
        self.assertTrue('demo_image.png__720x240_q85_crop_subsampling-2.jpg' in
                        soup.img['src'])
        sources = dict(
            (s['media'], s['srcset']) for s in soup.picture.find_all('source'))
        self.assertTrue(
            'demo_image.png__720x120_q85_crop_subsampling-2.jpg' in sources[
                '(max-width: 768px) and (max-resolution: 1.5dppx), (max-resolution: 144dpi), (-webkit-max-device-pixel-ratio: 1.5), (-o-max-device-pixel-ratio: 3)']
        )
        self.assertTrue(
            'demo_image.png__1440x240_q85_crop_subsampling-2.jpg' in sources[
                '(max-width: 768px) and (min-resolution: 1.5dppx), (min-resolution: 144dpi), (-webkit-min-device-pixel-ratio: 1.5), (-o-min-device-pixel-ratio: 3)']
        )
        self.assertTrue(
            'demo_image.png__345x76_q85_crop_subsampling-2.jpg' in sources[
                '(min-width: 768px) and (max-width: 992px) and (max-resolution: 1.5dppx), (max-resolution: 144dpi), (-webkit-max-device-pixel-ratio: 1.5), (-o-max-device-pixel-ratio: 3)']
        )
        self.assertTrue(
            'demo_image.png__690x152_q85_crop_subsampling-2.jpg' in sources[
                '(min-width: 768px) and (max-width: 992px) and (min-resolution: 1.5dppx), (min-resolution: 144dpi), (-webkit-min-device-pixel-ratio: 1.5), (-o-min-device-pixel-ratio: 3)']
        )
        self.assertTrue(
            'demo_image.png__293x73_q85_crop_subsampling-2.jpg' in sources[
                '(min-width: 992px) and (max-width: 1200px) and (max-resolution: 1.5dppx), (max-resolution: 144dpi), (-webkit-max-device-pixel-ratio: 1.5), (-o-max-device-pixel-ratio: 3)']
        )
        self.assertTrue(
            'demo_image.png__586x146_q85_crop_subsampling-2.jpg' in sources[
                '(min-width: 992px) and (max-width: 1200px) and (min-resolution: 1.5dppx), (min-resolution: 144dpi), (-webkit-min-device-pixel-ratio: 1.5), (-o-min-device-pixel-ratio: 3)']
        )
        # Due to an different round implimentation in python3 height can vary by 1 to 2 pixels
        self.assertTrue(
            bool(
                re.search(
                    r'demo_image.png__262x8\d_q85_crop_subsampling-2.jpg$',
                    sources[
                        '(min-width: 1200px) and (max-resolution: 1.5dppx), (max-resolution: 144dpi), (-webkit-max-device-pixel-ratio: 1.5), (-o-max-device-pixel-ratio: 3)']
                )))
        self.assertTrue(
            bool(
                re.search(
                    r'demo_image.png__524x17\d_q85_crop_subsampling-2.jpg$',
                    sources[
                        '(min-width: 1200px) and (min-resolution: 1.5dppx), (min-resolution: 144dpi), (-webkit-min-device-pixel-ratio: 1.5), (-o-min-device-pixel-ratio: 3)']
                )))
    def setUp(self):
        super(ClipboardPluginTest, self).setUp()
        UserModel = get_user_model()
        self.admin_user = UserModel.objects.get(username='******')

        # add a Bootstrap Container Plugin
        container_model = add_plugin(
            self.placeholder,
            BootstrapContainerPlugin,
            'en',
            glossary={'breakpoints': BS3_BREAKPOINT_KEYS})
        self.assertIsInstance(container_model, CascadeElement)
        container_plugin = container_model.get_plugin_class_instance(
            self.admin_site)
        self.assertIsInstance(container_plugin, BootstrapContainerPlugin)
        ModelForm = container_plugin.get_form(self.request, container_model)
        post_data = QueryDict('', mutable=True)
        post_data.setlist('breakpoints', ['sm', 'md'])
        form = ModelForm(post_data, None, instance=container_model)
        soup = BeautifulSoup(form.as_p(), features='lxml')
        input_element = soup.find(id="id_glossary_breakpoints_0")
        self.assertDictContainsSubset(
            {
                'type': 'checkbox',
                'name': 'breakpoints',
                'value': 'xs'
            }, input_element.attrs)
        input_element = soup.find(id="id_glossary_breakpoints_2")
        self.assertDictContainsSubset(
            {
                'type': 'checkbox',
                'name': 'breakpoints',
                'value': 'md',
                'checked': ''
            }, input_element.attrs)
        input_element = soup.find(id="id_glossary_fluid")
        self.assertDictContainsSubset({
            'type': 'checkbox',
            'name': 'fluid'
        }, input_element.attrs)
        container_plugin.save_model(self.request, container_model, form, False)
        self.assertListEqual(container_model.glossary['breakpoints'],
                             ['sm', 'md'])
        self.assertTrue('fluid' in container_model.glossary)
        self.assertEqual(str(container_model), 'for tablets, laptops')

        # add a RowPlugin with 3 Columns
        row_model = add_plugin(self.placeholder,
                               BootstrapRowPlugin,
                               'en',
                               target=container_model)
        row_plugin = row_model.get_plugin_class_instance()
        row_change_form = BootstrapRowForm({'num_children': 3})
        row_change_form.full_clean()
        row_plugin.save_model(self.request, row_model, row_change_form, False)
        self.assertDictEqual(row_model.glossary, {})
        self.assertIsInstance(row_model, CascadeElement)
        self.assertEqual(str(row_model), 'with 3 columns')
        plugin_list = [container_model, row_model]
        columns_qs = CascadeElement.objects.filter(parent_id=row_model.id)
        self.assertEqual(columns_qs.count(), 3)
        row_data = []
        for column_model in columns_qs:
            self.assertIsInstance(column_model, CascadeElement)
            column_plugin = column_model.get_plugin_class_instance()
            self.assertIsInstance(column_plugin, BootstrapColumnPlugin)
            self.assertEqual(column_model.parent.id, row_model.id)
            self.assertEqual(str(column_model), 'default width: 4 units')
            plugin_list.append(column_model)
            row_data.append([
                'BootstrapColumnPlugin', {
                    'glossary': column_model.glossary
                }, []
            ])
        # container_data = ['BootstrapRowPlugin', {'glossary': row_model.glossary}, row_data]

        # Render the Container Plugin with all of its children
        build_plugin_tree(plugin_list)
        html = self.get_html(container_model, self.get_request_context())
        self.assertHTMLEqual(
            html, '<div class="container"><div class="row">' +
            '<div class="col-sm-4"></div><div class="col-sm-4"></div>' +
            '<div class="col-sm-4"></div>' + '</div></div>')

        # change data inside the first column
        column_model = columns_qs[0]
        delattr(column_model, '_inst')
        column_plugin = column_model.get_plugin_class_instance(self.admin_site)
        column_plugin.cms_plugin_instance = column_model
        post_data = QueryDict('', mutable=True)
        post_data.update({
            'sm-column-offset': 'col-sm-offset-1',
            'sm-column-width': 'col-sm-3'
        })
        ModelForm = column_plugin.get_form(self.request, column_model)
        form = ModelForm(post_data, None, instance=column_model)
        self.assertTrue(form.is_valid())
        column_plugin.save_model(self.request, column_model, form, True)

        # change data inside the second column
        column_model = columns_qs[1]
        delattr(column_model, '_inst')
        column_plugin = column_model.get_plugin_class_instance(self.admin_site)
        column_plugin.cms_plugin_instance = column_model
        post_data = QueryDict('', mutable=True)
        post_data.update({
            'sm-responsive-utils': 'hidden-sm',
            'sm-column-width': 'col-sm-4'
        })
        ModelForm = column_plugin.get_form(self.request, column_model)
        form = ModelForm(post_data, None, instance=column_model)
        self.assertTrue(form.is_valid())
        column_plugin.save_model(self.request, column_model, form, False)
        html = self.get_html(container_model, self.get_request_context())
        self.assertHTMLEqual(
            html, '<div class="container"><div class="row">' +
            '<div class="col-sm-3 col-sm-offset-1"></div>' +
            '<div class="col-sm-4 hidden-sm"></div><div class="col-sm-4"></div>'
            + '</div></div>')
    def test_plugin_context(self):
        # create container
        container_model = add_plugin(self.placeholder, BootstrapContainerPlugin, 'en',
            glossary={'breakpoints': BS3_BREAKPOINT_KEYS})
        container_plugin = container_model.get_plugin_class_instance()
        self.assertIsInstance(container_plugin, BootstrapContainerPlugin)

        # add one row
        row_model = add_plugin(self.placeholder, BootstrapRowPlugin, 'en', target=container_model,
                               glossary={})
        row_plugin = row_model.get_plugin_class_instance()
        self.assertIsInstance(row_plugin, BootstrapRowPlugin)

        # add one column
        column_model = add_plugin(self.placeholder, BootstrapColumnPlugin, 'en', target=row_model,
            glossary={'xs-column-width': 'col-xs-12', 'sm-column-width': 'col-sm-6',
                      'md-column-width': 'col-md-4', 'lg-column-width': 'col-lg-3'})
        column_plugin = column_model.get_plugin_class_instance()
        self.assertIsInstance(column_plugin, BootstrapColumnPlugin)

        # add a picture
        picture_model = add_plugin(self.placeholder, BootstrapPicturePlugin, 'en', target=column_model)
        self.assertIsInstance(picture_model, SharableCascadeElement)
        picture_plugin = picture_model.get_plugin_class_instance()
        self.assertIsInstance(picture_plugin, BootstrapPicturePlugin)
        picture_plugin.cms_plugin_instance = picture_model.cmsplugin_ptr

        # upload an image and change the form
        ModelForm = picture_plugin.get_form(self.request, picture_model)
        image = self.upload_demo_image()
        post_data = QueryDict('', mutable=True)
        post_data.update({'image_file': image.pk, 'link_type': 'none',
            'responsive_heights-xs': '50%', 'responsive_heights-sm': '66%',
            'responsive_heights-md': '75%', 'responsive_heights-lg': '100%',
            'responsive_zoom-lg': '40%', 'responsive_zoom-lg': '25%',
            'responsive_zoom-lg': '15%', 'responsive_zoom-lg': '0%'})
        post_data.setlist('resize_options', ['crop'])
        picture_model._image_model = image
        form = ModelForm(post_data, None, instance=picture_model)
        self.assertTrue(form.is_valid())
        picture_plugin.save_model(self.request, picture_model, form, False)

        # render the plugins
        plugin_list = [container_model, row_model, column_model, picture_model]
        build_plugin_tree(plugin_list)
        soup = BeautifulSoup(self.get_html(container_model, self.get_request_context()), features="lxml")
        self.assertEqual(soup.img['height'], '240')
        self.assertEqual(soup.img['width'], '720')
        self.assertTrue('demo_image.png__720x240_q85_crop_subsampling-2.jpg' in str(soup.img))
        sources = dict((s['media'], s['srcset']) for s in soup.picture.find_all('source'))
        self.assertTrue('demo_image.png__720x120_q85_crop_subsampling-2.jpg' in sources['(max-width: 768px)'])
        self.assertTrue('demo_image.png__345x76_q85_crop_subsampling-2.jpg' in sources['(min-width: 768px) and (max-width: 992px)'])
        self.assertTrue('demo_image.png__293x73_q85_crop_subsampling-2.jpg' in sources['(min-width: 992px) and (max-width: 1200px)'])
        # Due to an different round implimentation in python3 height can vary by 1 to 2 pixels
        self.assertTrue(bool(re.search(r'demo_image.png__262x8\d_q85_crop_subsampling-2.jpg$', sources['(min-width: 1200px)'])))

        # with Retina images
        post_data.setlist('resize_options', ['crop', 'high_resolution'])
        form = ModelForm(post_data, None, instance=picture_model)
        self.assertTrue(form.is_valid())
        picture_plugin.save_model(self.request, picture_model, form, False)
        soup = BeautifulSoup(self.get_html(container_model, self.get_request_context()), features="lxml")
        self.assertEqual(soup.img['height'], '240')
        self.assertEqual(soup.img['width'], '720')
        self.assertTrue('demo_image.png__720x240_q85_crop_subsampling-2.jpg' in soup.img['src'])
        sources = dict((s['media'], s['srcset']) for s in soup.picture.find_all('source'))

        self.assertTrue('demo_image.png__720x120_q85_crop_subsampling-2.jpg 1x' in sources['(max-width: 768px)'])
        self.assertTrue('demo_image.png__1440x240_q85_crop_subsampling-2.jpg 2x' in sources['(max-width: 768px)'])
        self.assertTrue('demo_image.png__345x76_q85_crop_subsampling-2.jpg 1x' in sources['(min-width: 768px) and (max-width: 992px)'])
        self.assertTrue('demo_image.png__690x152_q85_crop_subsampling-2.jpg 2x' in sources['(min-width: 768px) and (max-width: 992px)'])
        self.assertTrue('demo_image.png__293x73_q85_crop_subsampling-2.jpg 1x' in sources['(min-width: 992px) and (max-width: 1200px)'])
        self.assertTrue('demo_image.png__586x146_q85_crop_subsampling-2.jpg 2x' in sources['(min-width: 992px) and (max-width: 1200px)'])

        # Due to an different round implimentation in python3 height can vary by 1 to 2 pixels
        self.assertTrue(bool(re.search(r'demo_image.png__262x8\d_q85_crop_subsampling-2.jpg\s1x', sources['(min-width: 1200px)'])))
        self.assertTrue(bool(re.search(r'demo_image.png__524x17\d_q85_crop_subsampling-2.jpg\s2x', sources['(min-width: 1200px)'])))
Exemple #38
0
    def test_add_font(self):
        with self.login_user_context(self.admin_user):
            # upload the zipfile into the filer's clipboard
            filename = os.path.join(os.path.dirname(__file__),
                                    'assets/fontello-b504201f.zip')
            with open(filename, 'rb') as zipfile:
                uploaded_file = SimpleUploadedFile(
                    'fontello-b504201f.zip',
                    zipfile.read(),
                    content_type='application/zip')
            request = self.get_request(reverse('admin:filer-ajax_upload'))
            self.assertTrue(request.user.is_staff, "User is not a staff user")
            request.FILES.update(file=uploaded_file)
            response = ajax_upload(request)
            self.assertEqual(response.status_code, 200)
            content = json.loads(response.content.decode('utf-8'))
            self.assertDictContainsSubset({'label': 'fontello-b504201f.zip'},
                                          content)

            # save the form and submit the remaining fields
            add_iconfont_url = reverse('admin:cmsplugin_cascade_iconfont_add')
            data = {
                'identifier': "Fontellico",
                'zip_file': content['file_id'],
                '_continue': "Save and continue editing",
            }
            response = self.client.post(add_iconfont_url, data)
            self.assertEqual(response.status_code, 302)
            resolver_match = resolve(response.url)
            self.assertEqual(resolver_match.url_name,
                             'cmsplugin_cascade_iconfont_change')

            # check the content of the uploaded file
            icon_font = IconFont.objects.get(pk=resolver_match.args[0])
            self.assertEqual(icon_font.identifier, "Fontellico")
            self.assertEqual(icon_font.config_data['name'], 'fontelico')
            self.assertEqual(len(icon_font.config_data['glyphs']), 34)

            # check if the uploaded fonts are rendered inside Preview Icons
            response = self.client.get(response.url)
            self.assertEqual(response.status_code, 200)
            soup = BeautifulSoup(response.content, 'lxml')
            preview_iconfont = soup.find('div', class_="preview-iconfont")
            icon_items = preview_iconfont.ul.find_all('li')
            self.assertEqual(len(icon_items), 34)
            self.assertListEqual(icon_items[0].i.attrs['class'],
                                 ['icon-emo-happy'])
            self.assertListEqual(icon_items[33].i.attrs['class'],
                                 ['icon-marquee'])

            # create container
            container_model = add_plugin(
                self.placeholder,
                BootstrapContainerPlugin,
                'en',
                glossary={'breakpoints': BS3_BREAKPOINT_KEYS})
            container_plugin = container_model.get_plugin_class_instance()
            self.assertIsInstance(container_plugin, BootstrapContainerPlugin)

            # add icon as child to this container
            glossary = {
                "font_size": "10em",
                "color": ["", "#88258e"],
                "background_color": ["on", "#c8ffcd"],
                "symbol": "emo-wink",
                "icon_font": icon_font.pk,
                "border_radius": "50%",
                "border": ["", "solid", "#000000"]
            }
            icon_model = add_plugin(self.placeholder,
                                    FramedIconPlugin,
                                    'en',
                                    target=container_model,
                                    glossary=glossary)
            icon_plugin = icon_model.get_plugin_class_instance()
            self.assertIsInstance(icon_plugin, FramedIconPlugin)

            # render the plugins
            plugin_list = [container_model, icon_model]
            build_plugin_tree(plugin_list)
            html = self.get_html(container_model, self.get_request_context())
            soup = BeautifulSoup(html, 'lxml')

            # look for the icon symbol
            style = soup.find('span',
                              class_='icon-emo-wink').attrs['style'].split(';')
            self.assertIn('color:#88258e', style)
            self.assertIn('display:inline-block', style)

            # look for the CSS file
            response = self.client.get(
                container_model.placeholder.page.get_absolute_url() + '?edit')
            self.assertEqual(response.status_code, 200)
            soup = BeautifulSoup(response.content, 'lxml')
            links = soup.head.find_all('link')
            for link in links:
                if link.attrs['href'].endswith('fontelico.css'):
                    break
            else:
                self.fail("No CSS file with font definition found")
    def test_plugin_context(self):
        # create container
        container_model = add_plugin(
            self.placeholder,
            BootstrapContainerPlugin,
            'en',
            glossary={'breakpoints': CASCADE_BREAKPOINTS_LIST})
        container_plugin = container_model.get_plugin_class_instance(
            self.admin_site)
        self.assertIsInstance(container_plugin, BootstrapContainerPlugin)

        # add one row
        row_model = add_plugin(self.placeholder,
                               BootstrapRowPlugin,
                               'en',
                               target=container_model,
                               glossary={})
        row_plugin = row_model.get_plugin_class_instance()
        self.assertIsInstance(row_plugin, BootstrapRowPlugin)

        # add one column
        column_model = add_plugin(self.placeholder,
                                  BootstrapColumnPlugin,
                                  'en',
                                  target=row_model,
                                  glossary={
                                      'xs-column-width': 'col-xs-12',
                                      'sm-column-width': 'col-sm-6',
                                      'md-column-width': 'col-md-4',
                                      'lg-column-width': 'col-lg-3'
                                  })
        column_plugin = column_model.get_plugin_class_instance()
        self.assertIsInstance(column_plugin, BootstrapColumnPlugin)

        # add a picture
        picture_model = add_plugin(self.placeholder,
                                   BootstrapPicturePlugin,
                                   'en',
                                   target=column_model)
        self.assertIsInstance(picture_model, SharableCascadeElement)
        picture_plugin = picture_model.get_plugin_class_instance(
            self.admin_site)
        self.assertIsInstance(picture_plugin, BootstrapPicturePlugin)
        picture_plugin.cms_plugin_instance = picture_model.cmsplugin_ptr

        # upload an image and change the form
        ModelForm = picture_plugin.get_form(self.request, picture_model)
        image = self.upload_demo_image()
        post_data = QueryDict('', mutable=True)
        post_data.update({
            'image_file': image.pk,
            'link_type': 'none',
            'responsive-heights-xs': '50%',
            'responsive-heights-sm': '66%',
            'responsive-heights-md': '75%',
            'responsive-heights-lg': '100%',
            'responsive-zoom-lg': '40%',
            'responsive-zoom-lg': '25%',
            'responsive-zoom-lg': '15%',
            'responsive-zoom-lg': '0%'
        })
        post_data.setlist('resize-options', ['crop'])
        form = ModelForm(post_data, None, instance=picture_model)
        self.assertTrue(form.is_valid())
        picture_plugin.save_model(self.request, picture_model, form, False)

        # render the plugins
        plugin_list = [container_model, row_model, column_model, picture_model]
        build_plugin_tree(plugin_list)
        context = RequestContext(self.request, {})
        html = container_model.render_plugin(context)
        soup = BeautifulSoup(html)
        self.assertEqual(soup.img['height'], '240')
        self.assertEqual(soup.img['width'], '720')
        self.assertTrue(soup.img['src'].endswith(
            'demo_image.png__720x240_q85_crop_subsampling-2.png'))
        sources = dict(
            (s['media'], s['srcset']) for s in soup.picture.find_all('source'))
        self.assertTrue(sources['(max-width: 768px)'].endswith(
            'demo_image.png__720x120_q85_crop_subsampling-2.png'))
        self.assertTrue(
            sources['(min-width: 768px) and (max-width: 992px)'].endswith(
                'demo_image.png__345x76_q85_crop_subsampling-2.png'))
        self.assertTrue(
            sources['(min-width: 992px) and (max-width: 1200px)'].endswith(
                'demo_image.png__293x73_q85_crop_subsampling-2.png'))
        self.assertTrue(sources['(min-width: 1200px)'].endswith(
            'demo_image.png__262x87_q85_crop_subsampling-2.png'))

        # with Retina images
        post_data.setlist('resize-options', ['crop', 'high_resolution'])
        form = ModelForm(post_data, None, instance=picture_model)
        self.assertTrue(form.is_valid())
        picture_plugin.save_model(self.request, picture_model, form, False)
        html = container_model.render_plugin(context)
        soup = BeautifulSoup(html)
        self.assertEqual(soup.img['height'], '240')
        self.assertEqual(soup.img['width'], '720')
        self.assertTrue(soup.img['src'].endswith(
            'demo_image.png__720x240_q85_crop_subsampling-2.png'))
        sources = dict(
            (s['media'], s['srcset']) for s in soup.picture.find_all('source'))
        self.assertTrue(
            sources['(max-width: 768px) and (max-resolution: 1.5dppx)'].
            endswith('demo_image.png__720x120_q85_crop_subsampling-2.png'))
        self.assertTrue(
            sources['(max-width: 768px) and (min-resolution: 1.5dppx)'].
            endswith('demo_image.png__1440x240_q85_crop_subsampling-2.png'))
        self.assertTrue(sources[
            '(min-width: 768px) and (max-width: 992px) and (max-resolution: 1.5dppx)']
                        .endswith(
                            'demo_image.png__345x76_q85_crop_subsampling-2.png'
                        ))
        self.assertTrue(sources[
            '(min-width: 768px) and (max-width: 992px) and (min-resolution: 1.5dppx)']
                        .endswith(
                            'demo_image.png__690x152_q85_crop_subsampling-2.png'
                        ))
        self.assertTrue(sources[
            '(min-width: 992px) and (max-width: 1200px) and (max-resolution: 1.5dppx)']
                        .endswith(
                            'demo_image.png__293x73_q85_crop_subsampling-2.png'
                        ))
        self.assertTrue(sources[
            '(min-width: 992px) and (max-width: 1200px) and (min-resolution: 1.5dppx)']
                        .endswith(
                            'demo_image.png__586x146_q85_crop_subsampling-2.png'
                        ))
        self.assertTrue(
            sources['(min-width: 1200px) and (max-resolution: 1.5dppx)'].
            endswith('demo_image.png__262x87_q85_crop_subsampling-2.png'))
        self.assertTrue(
            sources['(min-width: 1200px) and (min-resolution: 1.5dppx)'].
            endswith('demo_image.png__524x174_q85_crop_subsampling-2.png'))
    def test_container_context(self):
        # add a Bootstrap Container Plugin
        container_model = add_plugin(self.placeholder, BootstrapContainerPlugin, 'en',
            glossary={'breakpoints': BS3_BREAKPOINT_KEYS})
        self.assertIsInstance(container_model, CascadeElement)
        container_plugin = container_model.get_plugin_class_instance(self.admin_site)
        self.assertIsInstance(container_plugin, BootstrapContainerPlugin)
        ModelForm = container_plugin.get_form(self.request, container_model)
        post_data = QueryDict('', mutable=True)
        post_data.setlist('breakpoints', ['sm', 'md'])
        form = ModelForm(post_data, None, instance=container_model)
        html = form.as_p()
        self.assertInHTML('<input id="id_glossary_breakpoints_0" name="breakpoints" type="checkbox" value="xs" />', html)
        self.assertInHTML('<input checked="checked" id="id_glossary_breakpoints_2" name="breakpoints" type="checkbox" value="md" />', html)
        self.assertInHTML('<input id="id_glossary_fluid" name="fluid" type="checkbox" />', html)
        container_plugin.save_model(self.request, container_model, form, False)
        self.assertListEqual(container_model.glossary['breakpoints'], ['sm', 'md'])
        self.assertTrue('fluid' in container_model.glossary)
        self.assertEqual(str(container_model), 'for tablets, laptops')

        # add a RowPlugin with 3 Columns
        row_model = add_plugin(self.placeholder, BootstrapRowPlugin, 'en', target=container_model)
        row_plugin = row_model.get_plugin_class_instance()
        row_change_form = BootstrapRowForm({'num_children': 3})
        row_change_form.full_clean()
        row_plugin.save_model(self.request, row_model, row_change_form, False)
        self.assertDictEqual(row_model.glossary, {})
        self.assertIsInstance(row_model, CascadeElement)
        self.assertEqual(str(row_model), 'with 3 columns')
        plugin_list = [container_model, row_model]
        columns_qs = CascadeElement.objects.filter(parent_id=row_model.id)
        self.assertEqual(columns_qs.count(), 3)
        for column_model in columns_qs:
            self.assertIsInstance(column_model, CascadeElement)
            column_plugin = column_model.get_plugin_class_instance()
            self.assertIsInstance(column_plugin, BootstrapColumnPlugin)
            self.assertEqual(column_model.parent.id, row_model.id)
            self.assertEqual(str(column_model), 'default width: 4 units')
            plugin_list.append(column_model)

        # Render the Container Plugin with all of its children
        build_plugin_tree(plugin_list)
        html = self.get_html(container_model, self.get_request_context())
        self.assertHTMLEqual(html, '<div class="container"><div class="row">' +
            '<div class="col-sm-4"></div><div class="col-sm-4"></div><div class="col-sm-4"></div>' +
            '</div></div>')

        # change data inside the first column
        column_model = columns_qs[0]
        delattr(column_model, '_inst')
        column_plugin = column_model.get_plugin_class_instance(self.admin_site)
        column_plugin.cms_plugin_instance = column_model
        post_data = QueryDict('', mutable=True)
        post_data.update({'sm-column-offset': 'col-sm-offset-1', 'sm-column-width': 'col-sm-3'})
        ModelForm = column_plugin.get_form(self.request, column_model)
        form = ModelForm(post_data, None, instance=column_model)
        self.assertTrue(form.is_valid())
        column_plugin.save_model(self.request, column_model, form, True)

        # change data inside the second column
        column_model = columns_qs[1]
        delattr(column_model, '_inst')
        column_plugin = column_model.get_plugin_class_instance(self.admin_site)
        column_plugin.cms_plugin_instance = column_model
        post_data = QueryDict('', mutable=True)
        post_data.update({'sm-responsive-utils': 'hidden-sm', 'sm-column-width': 'col-sm-4'})
        ModelForm = column_plugin.get_form(self.request, column_model)
        form = ModelForm(post_data, None, instance=column_model)
        self.assertTrue(form.is_valid())
        column_plugin.save_model(self.request, column_model, form, False)
        html = self.get_html(container_model, self.get_request_context())
        self.assertHTMLEqual(html, '<div class="container"><div class="row">' +
            '<div class="col-sm-3 col-sm-offset-1"></div><div class="col-sm-4 hidden-sm"></div><div class="col-sm-4"></div>' +
            '</div></div>')
    def setUp(self):
        super(ClipboardPluginTest, self).setUp()
        UserModel = get_user_model()
        self.admin_user = UserModel.objects.get(username='******')

        # add a Bootstrap Container Plugin
        container_model = add_plugin(self.placeholder, BootstrapContainerPlugin, 'en',
                                     glossary={'breakpoints': BS3_BREAKPOINT_KEYS})
        self.assertIsInstance(container_model, CascadeElement)
        container_plugin = container_model.get_plugin_class_instance(self.admin_site)
        self.assertIsInstance(container_plugin, BootstrapContainerPlugin)
        ModelForm = container_plugin.get_form(self.request, container_model)
        post_data = QueryDict('', mutable=True)
        post_data.setlist('breakpoints', ['sm', 'md'])
        form = ModelForm(post_data, None, instance=container_model)
        soup = BeautifulSoup(form.as_p(), features='lxml')
        input_element = soup.find(id="id_glossary_breakpoints_0")
        self.assertDictContainsSubset({'type': 'checkbox', 'name': 'breakpoints', 'value': 'xs'},
                                      input_element.attrs)
        input_element = soup.find(id="id_glossary_breakpoints_2")
        self.assertDictContainsSubset({'type': 'checkbox', 'name': 'breakpoints', 'value': 'md', 'checked': ''},
                                      input_element.attrs)
        input_element = soup.find(id="id_glossary_fluid")
        self.assertDictContainsSubset({'type': 'checkbox', 'name': 'fluid'},
                                      input_element.attrs)
        container_plugin.save_model(self.request, container_model, form, False)
        self.assertListEqual(container_model.glossary['breakpoints'], ['sm', 'md'])
        self.assertTrue('fluid' in container_model.glossary)
        self.assertEqual(str(container_model), 'for tablets, laptops')

        # add a RowPlugin with 3 Columns
        row_model = add_plugin(self.placeholder, BootstrapRowPlugin, 'en', target=container_model)
        row_plugin = row_model.get_plugin_class_instance()
        row_change_form = BootstrapRowForm({'num_children': 3})
        row_change_form.full_clean()
        row_plugin.save_model(self.request, row_model, row_change_form, False)
        self.assertDictEqual(row_model.glossary, {})
        self.assertIsInstance(row_model, CascadeElement)
        self.assertEqual(str(row_model), 'with 3 columns')
        plugin_list = [container_model, row_model]
        columns_qs = CascadeElement.objects.filter(parent_id=row_model.id)
        self.assertEqual(columns_qs.count(), 3)
        row_data = []
        for column_model in columns_qs:
            self.assertIsInstance(column_model, CascadeElement)
            column_plugin = column_model.get_plugin_class_instance()
            self.assertIsInstance(column_plugin, BootstrapColumnPlugin)
            self.assertEqual(column_model.parent.id, row_model.id)
            self.assertEqual(str(column_model), 'default width: 4 units')
            plugin_list.append(column_model)
            row_data.append(['BootstrapColumnPlugin', {'glossary': column_model.glossary}, []])
        # container_data = ['BootstrapRowPlugin', {'glossary': row_model.glossary}, row_data]

        # Render the Container Plugin with all of its children
        build_plugin_tree(plugin_list)
        html = self.get_html(container_model, self.get_request_context())
        self.assertHTMLEqual(html, '<div class="container"><div class="row">' +
                             '<div class="col-sm-4"></div><div class="col-sm-4"></div>' +
                             '<div class="col-sm-4"></div>' +
                             '</div></div>')

        # change data inside the first column
        column_model = columns_qs[0]
        delattr(column_model, '_inst')
        column_plugin = column_model.get_plugin_class_instance(self.admin_site)
        column_plugin.cms_plugin_instance = column_model
        post_data = QueryDict('', mutable=True)
        post_data.update({'sm-column-offset': 'col-sm-offset-1', 'sm-column-width': 'col-sm-3'})
        ModelForm = column_plugin.get_form(self.request, column_model)
        form = ModelForm(post_data, None, instance=column_model)
        self.assertTrue(form.is_valid())
        column_plugin.save_model(self.request, column_model, form, True)

        # change data inside the second column
        column_model = columns_qs[1]
        delattr(column_model, '_inst')
        column_plugin = column_model.get_plugin_class_instance(self.admin_site)
        column_plugin.cms_plugin_instance = column_model
        post_data = QueryDict('', mutable=True)
        post_data.update({'sm-responsive-utils': 'hidden-sm', 'sm-column-width': 'col-sm-4'})
        ModelForm = column_plugin.get_form(self.request, column_model)
        form = ModelForm(post_data, None, instance=column_model)
        self.assertTrue(form.is_valid())
        column_plugin.save_model(self.request, column_model, form, False)
        html = self.get_html(container_model, self.get_request_context())
        self.assertHTMLEqual(html, '<div class="container"><div class="row">' +
                             '<div class="col-sm-3 col-sm-offset-1"></div>' +
                             '<div class="col-sm-4 hidden-sm"></div><div class="col-sm-4"></div>' +
                             '</div></div>')