Esempio n. 1
0
def test_lcfg(rf):
    two_thirds = int(LayoutCellGeneralInfoForm.CELL_FULL_WIDTH * 2 / 3)
    with plugin_override():
        with override_current_theme_class(None):
            theme = get_current_theme(get_default_shop())

            cell = LayoutCell(theme, "text", sizes={"md": two_thirds, "sm": two_thirds})
            lcfg = LayoutCellFormGroup(layout_cell=cell, theme=theme, request=apply_request_middleware(rf.get("/")))
            assert "general" in lcfg.forms
            assert "plugin" in lcfg.forms
            assert not lcfg.is_valid()  # Oh, we must've forgotten the text...
            lcfg = LayoutCellFormGroup(
                data={
                    "general-cell_width": "%d" % two_thirds,
                    "general-cell_align": " ",
                    "general-cell_extra_classes" : "newClass",
                    "plugin-text_*": "Hello, world!"
                },
                layout_cell=cell,
                theme=theme,
                request=apply_request_middleware(rf.get("/"))
            )
            assert lcfg.is_valid()  # Let's see now!
            lcfg.save()
            assert cell.sizes["md"] == two_thirds
            assert cell.extra_classes == "newClass"
            assert cell.config["text"] == {FALLBACK_LANGUAGE_CODE: "Hello, world!"}
Esempio n. 2
0
def get_view_config(context, global_type=False):
    """
    Get a view configuration object for a Jinja2 rendering context.

    :param context: Rendering context
    :type context: jinja2.runtime.Context
    :param global_type: Boolean indicating whether this is a global type
    :type global_type: bool|False
    :return: View config
    :rtype: shuup.xtheme.view_config.ViewConfig
    """
    # This uses the Jinja context's technically-immutable vars dict
    # to cache the view configuration. This is fine in our case, I'd say.
    request = context.get("request")
    config_key = "_xtheme_global_view_config" if global_type else "_xtheme_view_config"
    config = context.vars.get(config_key)
    if (config is None):
        view_object = context.get("view")
        if view_object:
            view_class = view_object.__class__
            view_name = view_class.__name__
        else:
            view_name = "UnknownView"
        config = ViewConfig(
            theme=get_current_theme(request),
            view_name=view_name,
            draft=is_edit_mode(request),
            global_type=global_type,
        )
        context.vars[config_key] = config
    return config
Esempio n. 3
0
def test_xtheme_wizard_pane(rf, admin_user, settings):
    settings.SHUUP_SETUP_WIZARD_PANE_SPEC = [
        "shuup.xtheme.admin_module.views.ThemeWizardPane"
    ]
    with override_current_theme_class():
        with override_provides("xtheme", [
            "shuup_tests.xtheme.utils:FauxTheme"
        ]):
            get_default_shop()
            assert get_current_theme() == None
            fields = _extract_fields(rf, admin_user)
            fields["theme-activate"] = FauxTheme.identifier
            request = rf.post("/", data=fields)
            response = WizardView.as_view()(request)
            assert isinstance(get_current_theme(), FauxTheme)
            assert_redirect_to_dashboard(rf)
Esempio n. 4
0
 def get_context_data(self, **kwargs):
     context = super(ThemeConfigView, self).get_context_data(**kwargs)
     context["theme_classes"] = sorted(
         [t for t in get_provide_objects("xtheme") if t.identifier], key=lambda t: (t.name or t.identifier)
     )
     context["current_theme"] = get_current_theme()
     return context
Esempio n. 5
0
    def _handle_xtheme_save(self):
        svc_pk = config.get(self.shop, CONTENT_FOOTER_KEY)
        svc = SavedViewConfig.objects.filter(pk=svc_pk).first()
        theme = get_current_theme(self.shop)

        if not svc and theme:
            context = {"shop": self.shop}
            rendered_content = template_loader.render_to_string(content_data.FOOTER_TEMPLATE, context).strip()
            layout = Layout(theme, "footer-bottom")
            # adds the footer template
            layout.begin_row()
            layout.begin_column({"md": 12})
            layout.add_plugin(SnippetsPlugin.identifier, {"in_place": rendered_content})

            svc = SavedViewConfig(
                theme_identifier=theme.identifier,
                shop=self.shop,
                view_name=XTHEME_GLOBAL_VIEW_NAME,
                status=SavedViewConfigStatus.CURRENT_DRAFT
            )
            svc.set_layout_data(layout.placeholder_name, layout)
            svc.save()
            svc.publish()

            config.set(self.shop, CONTENT_FOOTER_KEY, svc.pk)
Esempio n. 6
0
def test_pluginless_lcfg(rf):
    with plugin_override():
        with override_current_theme_class(None):
            theme = get_current_theme(get_default_shop())
            cell = LayoutCell(theme, None)
            assert not cell.instantiate_plugin()
            lcfg = LayoutCellFormGroup(layout_cell=cell, theme=theme, request=apply_request_middleware(rf.get("/")))
            assert "plugin" not in lcfg.forms
Esempio n. 7
0
def get_theme_context():
    return {
        "theme_classes": sorted(
            [t for t in get_provide_objects("xtheme") if t.identifier],
            key=lambda t: (t.name or t.identifier)
        ),
        "current_theme": get_current_theme()
    }
Esempio n. 8
0
def test_pluginless_lcfg():
    with plugin_override():
        with override_current_theme_class(None):
            request = get_request(edit=False)
            theme = get_current_theme(request)
            cell = LayoutCell(theme, None)
            assert not cell.instantiate_plugin()
            lcfg = LayoutCellFormGroup(layout_cell=cell, theme=theme)
            assert "plugin" not in lcfg.forms
Esempio n. 9
0
 def get_help_blocks(self, request, kind):
     theme = get_current_theme(request.shop)
     if kind == "quicklink" and theme:
         yield SimpleHelpBlock(
             text=_("Customize the look and feel of your shop"),
             actions=[{
                 "text": _("Customize theme"),
                 "url": reverse("shuup_admin:xtheme.config_detail", kwargs={"theme_identifier": theme.identifier})
             }],
             priority=200,
             category=HelpBlockCategory.STOREFRONT,
             icon_url="xtheme/theme.png"
         )
Esempio n. 10
0
def test_xtheme_wizard_pane(rf, admin_user):
    with override_settings(
        SHUUP_SETUP_WIZARD_PANE_SPEC = [
            "shuup.xtheme.admin_module.views.ThemeWizardPane"
        ],
        CACHES={
            'default': {
                'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
                'LOCATION': 'test_simple_set_and_get_with_shop',
            }
        }
    ):
        cache.init_cache()
        shop = get_default_shop()
        with override_provides("xtheme", ["shuup_tests.xtheme.utils:FauxTheme"]):
            from shuup_tests.xtheme.utils import FauxTheme
            assert get_current_theme(shop) is None
            fields = _extract_fields(rf, admin_user)
            fields["theme-activate"] = FauxTheme.identifier
            request = apply_request_middleware(rf.post("/", data=fields), user=admin_user)
            response = WizardView.as_view()(request)
            assert isinstance(get_current_theme(shop), FauxTheme)
            assert_redirect_to_dashboard(rf, admin_user, shop)
Esempio n. 11
0
def test_product_from_category_plugin(rf):
    shop = get_default_shop()
    category1 = get_default_category()
    category2 = CategoryFactory(status=CategoryStatus.VISIBLE)

    category1.shops.add(shop)
    category2.shops.add(shop)

    p1 = create_product("p1", shop, get_default_supplier(), "10")
    p2 = create_product("p2", shop, get_default_supplier(), "20")
    p3 = create_product("p3", shop, get_default_supplier(), "30")

    sp1 = p1.get_shop_instance(shop)
    sp2 = p2.get_shop_instance(shop)
    sp3 = p3.get_shop_instance(shop)

    sp1.categories.add(category1)
    sp2.categories.add(category1)
    sp3.categories.add(category2)

    context = get_context(rf)
    plugin = ProductsFromCategoryPlugin({
        "category": category1.pk
    })
    context_products = plugin.get_context_data(context)["products"]
    assert p1 in context_products
    assert p2 in context_products
    assert p3 not in context_products

    # test the plugin form
    with override_current_theme_class(None):
        theme = get_current_theme(get_default_shop())
        cell = LayoutCell(theme, ProductsFromCategoryPlugin.identifier, sizes={"md": 8})
        lcfg = LayoutCellFormGroup(layout_cell=cell, theme=theme, request=apply_request_middleware(rf.get("/")))
        assert not lcfg.is_valid()

        lcfg = LayoutCellFormGroup(
            data={
                "general-cell_width": "8",
                "general-cell_align": "pull-right",
                "plugin-count": 4,
                "plugin-category": category2.pk
            },
            layout_cell=cell,
            theme=theme,
            request=apply_request_middleware(rf.get("/"))
        )
        assert lcfg.is_valid()
        lcfg.save()
        assert cell.config["category"] == str(category2.pk)
Esempio n. 12
0
    def get_notifications(self, request):
        try:
            engine = engines["jinja2"]
        except KeyError:
            engine = None

        if engine and isinstance(engine, Jinja2):  # The engine is what we expect...
            if isinstance(engine.env, XthemeEnvironment):  # ... and it's capable of loading themes...
                if not get_current_theme(request.shop):  # ... but there's no theme active?!
                    # Panic!
                    yield Notification(
                        text=_("No theme is active. Click here to activate one."),
                        title=_("Theming"),
                        url="shuup_admin:xtheme.config"
                    )
Esempio n. 13
0
def test_formless_plugin_in_lcfg():
    two_thirds = int(LayoutCellGeneralInfoForm.CELL_FULL_WIDTH * 2 / 3)
    with plugin_override():
        with override_current_theme_class(None):
            request = get_request(edit=False)
            theme = get_current_theme(request)

            cell = LayoutCell(theme, "inject")
            assert cell.instantiate_plugin()
            lcfg = LayoutCellFormGroup(data={"general-cell_width": "%d" % two_thirds, "general-cell_align": "pull-right"}, layout_cell=cell, theme=theme)

            assert "plugin" not in lcfg.forms
            assert lcfg.is_valid()
            lcfg.save()
            assert cell.sizes["md"] == two_thirds  # Something got saved even if the plugin doesn't need config
Esempio n. 14
0
    def _create_sample_carousel(cls, shop, business_segment):
        """
        Create the sample carousel for the given business_segment
        and also injects it to the default theme currently being used in front
        """
        if business_segment not in BUSINESS_SEGMENTS:
            return None

        carousel_data = BUSINESS_SEGMENTS[business_segment]["carousel"]
        carousel = create_sample_carousel(carousel_data, business_segment, shop)

        # injects the carousel plugin with in the front_content placeholder
        # this will only works if the theme have this placeholder, we expect so
        if 'shuup.xtheme' in settings.INSTALLED_APPS:
            from shuup.front.apps.carousel.plugins import CarouselPlugin
            from shuup.xtheme.plugins.products import ProductHighlightPlugin

            from shuup.xtheme.models import SavedViewConfig, SavedViewConfigStatus
            from shuup.xtheme.layout import Layout
            from shuup.xtheme._theme import get_current_theme

            theme = get_current_theme(shop)

            if theme:
                layout = Layout(theme, "front_content")

                # adds the carousel
                layout.begin_row()
                layout.begin_column({"md": 12})
                layout.add_plugin(CarouselPlugin.identifier, {"carousel": carousel.pk})

                # adds some products
                layout.begin_row()
                layout.begin_column({"md": 12})
                layout.add_plugin(ProductHighlightPlugin.identifier, {})

                svc = SavedViewConfig(
                    theme_identifier=theme.identifier,
                    shop=shop,
                    view_name="IndexView",
                    status=SavedViewConfigStatus.CURRENT_DRAFT
                )
                svc.set_layout_data(layout.placeholder_name, layout)
                svc.save()
                svc.publish()

        return carousel
Esempio n. 15
0
def extra_view_dispatch(request, view):
    """
    Dispatch to an Xtheme extra view.

    :param request: A request
    :type request: django.http.HttpRequest
    :param view: View name
    :type view: str
    :return: A response of some ilk
    :rtype: django.http.HttpResponse
    """
    theme = get_current_theme(request)
    view_func = get_view_by_name(theme, view)
    if not view_func:
        msg = "%s/%s: Not found" % (getattr(theme, "identifier", None), view)
        return HttpResponseNotFound(msg)
    return view_func(request)
Esempio n. 16
0
    def get(self, context, name, default=None):
        """
        Get a theme setting value.

        :param context: Implicit Jinja2 context
        :type context: jinja2.runtime.Context
        :param name: Setting name
        :type name: str
        :param default: Default value if setting is not found
        :type default: object
        :return: Value
        :rtype: object
        """
        request = context["request"]
        theme = get_current_theme(request)
        if theme:
            return theme.get_setting(name, default=default)
        return default
Esempio n. 17
0
def extra_view_dispatch(request, view):
    """
    Dispatch to an Xtheme extra view.

    :param request: A request.
    :type request: django.http.HttpRequest
    :param view: View name.
    :type view: str
    :return: A response of some kind.
    :rtype: django.http.HttpResponse
    """
    theme = get_current_theme(request.shop)
    view_func = get_view_by_name(theme, view)
    if not view_func:
        msg = "Error! %s/%s: Not found." % (getattr(theme, "identifier",
                                                    None), view)
        return HttpResponseNotFound(msg)
    return view_func(request)
Esempio n. 18
0
    def __getitem__(self, item):
        """
        Look for additional helper callables in the active theme.

        Callables marked with the Django standard `alters_data` attribute will not be honored.

        :param item: Template helper name
        :type item: str
        :return: Template helper, maybe
        :rtype: object|None
        """
        theme = get_current_theme()
        if theme:
            helper = getattr(theme, item, None)
            if helper and callable(helper) and not getattr(
                    helper, "alters_data", False):
                return helper
        raise KeyError("No such template helper: %s" % item)
Esempio n. 19
0
    def get(self, context, name, default=None):
        """
        Get a theme setting value.

        :param context: Implicit Jinja2 context
        :type context: jinja2.runtime.Context
        :param name: Setting name
        :type name: str
        :param default: Default value if setting is not found
        :type default: object
        :return: Value
        :rtype: object
        """
        request = context["request"]
        theme = get_current_theme(request.shop)
        if theme:
            return theme.get_setting(name, default=default)
        return default
Esempio n. 20
0
def test_product_selection_plugin(rf):
    shop = get_default_shop()
    p1 = create_product("p1", shop, get_default_supplier(), "10")
    p2 = create_product("p2", shop, get_default_supplier(), "20")
    p3 = create_product("p3", shop, get_default_supplier(), "30")
    p4 = create_product("p4", shop, get_default_supplier(), "40")

    sp1 = p1.get_shop_instance(shop)
    sp2 = p2.get_shop_instance(shop)
    sp3 = p3.get_shop_instance(shop)

    context = get_context(rf)
    plugin = ProductSelectionPlugin({"products": [sp1.pk, sp2.pk, sp3.pk]})
    context_products = plugin.get_context_data(context)["products"]
    assert p1 in context_products
    assert p2 in context_products
    assert p3 in context_products
    assert p4 not in context_products

    # test the plugin form
    with override_current_theme_class(None):
        theme = get_current_theme(get_default_shop())
        cell = LayoutCell(theme,
                          ProductSelectionPlugin.identifier,
                          sizes={"md": 8})
        lcfg = LayoutCellFormGroup(layout_cell=cell,
                                   theme=theme,
                                   request=apply_request_middleware(
                                       rf.get("/")))
        # not valid, products are required
        assert not lcfg.is_valid()

        lcfg = LayoutCellFormGroup(data={
            "general-cell_width": "8",
            "general-cell_align": "pull-right",
            "plugin-products": [p1.pk, p2.pk]
        },
                                   layout_cell=cell,
                                   theme=theme,
                                   request=apply_request_middleware(
                                       rf.get("/")))
        assert lcfg.is_valid()
        lcfg.save()
        assert cell.config["products"] == [str(p1.pk), str(p2.pk)]
Esempio n. 21
0
def test_formless_plugin_in_lcfg():
    two_thirds = int(LayoutCellGeneralInfoForm.CELL_FULL_WIDTH * 2 / 3)
    with plugin_override():
        with override_current_theme_class(None):
            request = get_request(edit=False)
            theme = get_current_theme(request)

            cell = LayoutCell(theme, "inject")
            assert cell.instantiate_plugin()
            lcfg = LayoutCellFormGroup(
                data={"general-cell_width": "%d" % two_thirds},
                layout_cell=cell,
                theme=theme)

            assert "plugin" not in lcfg.forms
            assert lcfg.is_valid()
            lcfg.save()
            assert cell.sizes[
                "md"] == two_thirds  # Something got saved even if the plugin doesn't need config
Esempio n. 22
0
def test_product_selection_plugin(rf):
    shop = get_default_shop()
    p1 = create_product("p1", shop, get_default_supplier(), "10")
    p2 = create_product("p2", shop, get_default_supplier(), "20")
    p3 = create_product("p3", shop, get_default_supplier(), "30")
    p4 = create_product("p4", shop, get_default_supplier(), "40")

    sp1 = p1.get_shop_instance(shop)
    sp2 = p2.get_shop_instance(shop)
    sp3 = p3.get_shop_instance(shop)

    context = get_context(rf)
    plugin = ProductSelectionPlugin({
        "products": [sp1.pk, sp2.pk, sp3.pk]
    })
    context_products = plugin.get_context_data(context)["products"]
    assert p1 in context_products
    assert p2 in context_products
    assert p3 in context_products
    assert p4 not in context_products

    # test the plugin form
    with override_current_theme_class(None):
        theme = get_current_theme(get_default_shop())
        cell = LayoutCell(theme, ProductSelectionPlugin.identifier, sizes={"md": 8})
        lcfg = LayoutCellFormGroup(layout_cell=cell, theme=theme, request=apply_request_middleware(rf.get("/")))
        # not valid, products are required
        assert not lcfg.is_valid()

        lcfg = LayoutCellFormGroup(
            data={
                "general-cell_width": "8",
                "general-cell_align": "pull-right",
                "plugin-products": [p1.pk, p2.pk]
            },
            layout_cell=cell,
            theme=theme,
            request=apply_request_middleware(rf.get("/"))
        )
        assert lcfg.is_valid()
        lcfg.save()
        assert cell.config["products"] == [str(p1.pk), str(p2.pk)]
Esempio n. 23
0
def test_lcfg():
    two_thirds = int(LayoutCellGeneralInfoForm.CELL_FULL_WIDTH * 2 / 3)
    with plugin_override():
        with override_current_theme_class(None):
            theme = get_current_theme(get_default_shop())

            cell = LayoutCell(theme, "text", sizes={"md": two_thirds, "sm": two_thirds})
            lcfg = LayoutCellFormGroup(layout_cell=cell, theme=theme)
            assert "general" in lcfg.forms
            assert "plugin" in lcfg.forms
            assert not lcfg.is_valid()  # Oh, we must've forgotten the text...
            lcfg = LayoutCellFormGroup(data={
                "general-cell_width": "%d" % two_thirds,
                "general-cell_align": " ",
                "plugin-text_*": "Hello, world!"
            }, layout_cell=cell, theme=theme)
            assert lcfg.is_valid()  # Let's see now!
            lcfg.save()
            assert cell.sizes["md"] == two_thirds
            assert cell.config["text"] == {FALLBACK_LANGUAGE_CODE: "Hello, world!"}
Esempio n. 24
0
    def get_notifications(self, request):
        try:
            engine = engines["jinja2"]
        except KeyError:
            engine = None

        if engine and isinstance(engine,
                                 Jinja2):  # The engine is what we expect...
            if isinstance(engine.env, XthemeEnvironment
                          ):  # ... and it's capable of loading themes...
                if not (getattr(request, "theme", None)
                        or get_current_theme(request.shop)):
                    # ... but there's no theme active?!
                    # Panic!
                    yield Notification(
                        text=_(
                            "No theme is active. Click here to activate one."),
                        title=_("Theming"),
                        url="shuup_admin:xtheme.config",
                    )
Esempio n. 25
0
def test_lcfg():
    two_thirds = int(LayoutCellGeneralInfoForm.CELL_FULL_WIDTH * 2 / 3)
    with plugin_override():
        with override_current_theme_class(None):
            request = get_request(edit=False)
            theme = get_current_theme(request)

            cell = LayoutCell(theme, "text", sizes={"md": two_thirds, "sm": two_thirds})
            lcfg = LayoutCellFormGroup(layout_cell=cell, theme=theme)
            assert "general" in lcfg.forms
            assert "plugin" in lcfg.forms
            assert not lcfg.is_valid()  # Oh, we must've forgotten the text...
            lcfg = LayoutCellFormGroup(data={
                "general-cell_width": "%d" % two_thirds,
                "plugin-text": "Hello, world!"
            }, layout_cell=cell, theme=theme)
            assert lcfg.is_valid()  # Let's see now!
            lcfg.save()
            assert cell.sizes["md"] == two_thirds
            assert cell.config["text"] == {FALLBACK_LANGUAGE_CODE: "Hello, world!"}
Esempio n. 26
0
    def _get_themed_template_names(self, name):
        """
        Get theme-prefixed paths for the given template name.

        For instance, if the template_dir or identifier of the current theme is `mystery` and we're looking up
        `shuup/front/bar.jinja`, we'll look at `mystery/shuup/front/bar.jinja`, then at `shuup/front/bar.jinja`.

        :param name: Template name
        :type name: str
        :return: A template name or a list thereof
        :rtype: str|list[str]
        """
        if name.startswith("shuup/admin"):  # Ignore the admin.
            return name
        theme = get_current_theme()
        if not theme:
            return name
        return [
            "%s/%s" % ((theme.template_dir or theme.identifier), name), name
        ]
Esempio n. 27
0
    def _get_themed_template_names(self, name):
        """
        Get theme-prefixed paths for the given template name.

        For instance, if the template_dir or identifier of the current theme is `mystery` and we're looking up
        `shuup/front/bar.jinja`, we'll look at `mystery/shuup/front/bar.jinja`, then at `shuup/front/bar.jinja`.

        :param name: Template name
        :type name: str
        :return: A template name or a list thereof
        :rtype: str|list[str]
        """
        if name.startswith("shuup/admin"):  # Ignore the admin.
            return name
        theme = get_current_theme()
        if not theme:
            return name
        return [
            "%s/%s" % ((theme.template_dir or theme.identifier), name),
            name
        ]
Esempio n. 28
0
def test_formless_plugin_in_lcfg(rf):
    two_thirds = int(LayoutCellGeneralInfoForm.CELL_FULL_WIDTH * 2 / 3)
    with plugin_override():
        with override_current_theme_class(None):
            theme = get_current_theme(get_default_shop())

            cell = LayoutCell(theme, "inject")
            assert cell.instantiate_plugin()
            lcfg = LayoutCellFormGroup(data={
                "general-cell_width": "%d" % two_thirds,
                "general-cell_align": "pull-right"
            },
                                       layout_cell=cell,
                                       theme=theme,
                                       request=apply_request_middleware(
                                           rf.get("/")))

            assert "plugin" not in lcfg.forms
            assert lcfg.is_valid()
            lcfg.save()
            assert cell.sizes[
                "md"] == two_thirds  # Something got saved even if the plugin doesn't need config
Esempio n. 29
0
def test_custom_cell_size(rf):
    with plugin_override():
        with override_current_theme_class(None):
            theme = get_current_theme(get_default_shop())

            cell = LayoutCell(theme, "text", sizes={"md": None, "sm": None})
            lcfg = LayoutCellFormGroup(
                data={
                    "general-cell_width": None,
                    "general-cell_align": " ",
                    "general-cell_extra_classes": "newClass",
                    "plugin-text_*": "Hello, world!",
                },
                layout_cell=cell,
                theme=theme,
                request=apply_request_middleware(rf.get("/")),
            )
            assert lcfg.is_valid()
            lcfg.save()
            assert cell.sizes["md"] is None
            assert cell.sizes["sm"] is None
            assert cell.extra_classes == "newClass"
            assert cell.config["text"] == {FALLBACK_LANGUAGE_CODE: "Hello, world!"}
Esempio n. 30
0
def test_ratings_plugin(show_recommenders, title):
    shop = factories.get_default_shop()
    product = factories.create_product(
        "product", shop=shop, supplier=factories.get_default_supplier())

    # create 15 reviews for the product
    [create_random_review_for_product(shop, product) for _ in range(15)]

    set_current_theme(ClassicGrayTheme.identifier, shop)
    svc = SavedViewConfig(theme_identifier=ClassicGrayTheme.identifier,
                          shop=shop,
                          view_name="ProductDetailView",
                          status=SavedViewConfigStatus.CURRENT_DRAFT)
    layout = Layout(get_current_theme(shop), "product_extra_2")
    layout.add_plugin(
        ProductReviewStarRatingsPlugin.identifier, {
            "customer_ratings_title": {
                "en": title
            },
            "show_recommenders": show_recommenders
        })
    svc.set_layout_data(layout.placeholder_name, layout)
    svc.save()
    svc.publish()

    client = Client()
    response = client.get(
        reverse("shuup:product", kwargs=dict(pk=product.pk,
                                             slug=product.slug)))
    assert response.status_code == 200
    response.render()
    content = response.content.decode("utf-8")

    assert "product-reviews-rating-star" in content
    assert 'class="rating"' in content
    assert ('class="recommend"' in content) == show_recommenders
    assert title in content
Esempio n. 31
0
    def _handle_xtheme_save(self):
        svc_pk = config.get(self.shop, CONTENT_FOOTER_KEY)
        svc = SavedViewConfig.objects.filter(pk=svc_pk).first()
        theme = get_current_theme()

        if not svc and theme:
            context = {"shop": self.shop}
            rendered_content = template_loader.render_to_string(content_data.FOOTER_TEMPLATE, context).strip()
            layout = Layout(theme, "footer-bottom")
            # adds the footer template
            layout.begin_row()
            layout.begin_column({"md": 12})
            layout.add_plugin(SnippetsPlugin.identifier, {"in_place": rendered_content})

            svc = SavedViewConfig(
                theme_identifier=theme.identifier,
                view_name=XTHEME_GLOBAL_VIEW_NAME,
                status=SavedViewConfigStatus.CURRENT_DRAFT
            )
            svc.set_layout_data(layout.placeholder_name, layout)
            svc.save()
            svc.publish()

            config.set(self.shop, CONTENT_FOOTER_KEY, svc.pk)
Esempio n. 32
0
def test_formless_plugin_in_lcfg(rf):
    two_thirds = int(LayoutCellGeneralInfoForm.CELL_FULL_WIDTH * 2 / 3)
    with plugin_override():
        with override_current_theme_class(None):
            theme = get_current_theme(get_default_shop())

            cell = LayoutCell(theme, "inject")
            assert cell.instantiate_plugin()
            lcfg = LayoutCellFormGroup(
                data={
                    "general-cell_width": "%d" % two_thirds,
                    "general-cell_align": "pull-right",
                    "general-cell_extra_classes" : "newClass",
                },
                layout_cell=cell,
                theme=theme,
                request=apply_request_middleware(rf.get("/"))
            )

            assert "plugin" not in lcfg.forms
            assert lcfg.is_valid()
            lcfg.save()
            assert cell.extra_classes == "newClass"
            assert cell.sizes["md"] == two_thirds  # Something got saved even if the plugin doesn't need config
Esempio n. 33
0
    def _get_themed_template_names(self, name):
        """
        Get theme-prefixed paths for the given template name.

        For instance, if the template_dir or identifier of the current theme is `mystery` and we're looking up
        `shuup/front/bar.jinja`, we'll look at `mystery/shuup/front/bar.jinja`, finally at `shuup/front/bar.jinja`.

        Mystery theme also can define default template dir let's say `pony`. In this scenario we're looking up
        `shuup/front/bar.jinja` from `mystery/shuup/front/bar.jinja` then at `pony/shuup/front/bar.jinja` and
        finally at the default `shuup/front/bar.jinja`.

        :param name: Template name
        :type name: str
        :return: A template name or a list thereof
        :rtype: str|list[str]
        """
        if name.startswith("shuup/admin"):  # Ignore the admin.
            return name
        theme = get_current_theme()
        if not theme:
            return name
        theme_template = "%s/%s" % ((theme.template_dir or theme.identifier), name)
        default_template = (("%s/%s" % (theme.default_template_dir, name)) if theme.default_template_dir else None)
        return [theme_template, default_template, name] if default_template else [theme_template, name]
Esempio n. 34
0
def test_carousel_custom_colors(rf):
    from shuup.front.apps.carousel.plugins import CarouselPlugin
    from shuup.utils.django_compat import reverse
    from shuup.xtheme._theme import get_current_theme
    from shuup.xtheme.layout import Layout
    from shuup.xtheme.models import SavedViewConfig, SavedViewConfigStatus

    shop = get_default_shop()
    shop.maintenance_mode = False
    shop.save()

    carousel = Carousel.objects.create(name="test")
    carousel.shops.add(shop)
    test_image = Image.objects.create(original_filename="slide.jpg")
    test_slide = Slide.objects.create(
        carousel=carousel,
        name="test",
        available_from=(datetime.now() - timedelta(days=1)),
        image=test_image,
        target=LinkTargetType.CURRENT,
    )

    theme = get_current_theme(shop)

    # adds the carousel to the front page
    layout = Layout(theme, "front_content")
    layout.begin_row()
    layout.begin_column({"md": 12})
    layout.add_plugin(CarouselPlugin.identifier, {"carousel": carousel.pk})
    svc = SavedViewConfig(
        theme_identifier=theme.identifier, shop=shop, view_name="IndexView", status=SavedViewConfigStatus.CURRENT_DRAFT
    )
    svc.set_layout_data(layout.placeholder_name, layout)
    svc.save()
    svc.publish()

    client = Client()

    # no customized color
    response = client.get(reverse("shuup:index"))
    content = response.content.decode("utf-8")
    assert "owl-carousel" in content
    assert ".owl-nav .owl-prev" not in content
    assert ".owl-nav .owl-next" not in content
    assert ".owl-dot:nth-child(" not in content

    # put colors in arrows
    carousel.arrows_color = "#ffaabb"
    carousel.save()
    response = client.get(reverse("shuup:index"))
    content = response.content.decode("utf-8")
    assert ".owl-nav .owl-prev" in content
    assert ".owl-nav .owl-next" in content
    assert "color: #ffaabb !important;" in content

    # put custom color in dots
    test_slide.inactive_dot_color = "#a1b2c3"
    test_slide.active_dot_color = "#d4e4f6"
    test_slide.save()
    response = client.get(reverse("shuup:index"))
    content = response.content.decode("utf-8")
    assert ".owl-dot:nth-child(1)" in content
    assert "border-color: #a1b2c3 !important" in content
    assert "background-color: #d4e4f6 !important;" in content
Esempio n. 35
0
 def visible(self):
     return not get_current_theme()
Esempio n. 36
0
def test_product_from_category_plugin(rf):
    shop = get_default_shop()
    category1 = get_default_category()
    category2 = CategoryFactory(status=CategoryStatus.VISIBLE)

    category1.shops.add(shop)
    category2.shops.add(shop)

    p1 = create_product("p1", shop, get_default_supplier(), "10")
    p2 = create_product("p2", shop, get_default_supplier(), "20")
    p3 = create_product("p3", shop, get_default_supplier(), "30")

    sp1 = p1.get_shop_instance(shop)
    sp2 = p2.get_shop_instance(shop)
    sp3 = p3.get_shop_instance(shop)

    sp1.categories.add(category1)
    sp2.categories.add(category1)
    sp3.categories.add(category2)

    plugin = ProductsFromCategoryPlugin({
        "category": category1.pk,
        "cache_timeout": 120
    })
    plugin_context = plugin.get_context_data(get_context(rf, is_ajax=False))
    context_products = plugin_context["products"]

    assert len(context_products) == 0

    plugin_context = plugin.get_context_data(get_context(rf))
    context_data_url = plugin_context["data_url"]
    context_products = plugin_context["products"]
    assert p1 in context_products
    assert p2 in context_products
    assert p3 not in context_products

    check_expected_product_count(context_data_url, 2)
    check_expected_product_count(context_data_url, 2)  # one for checking it is cached

    # test the plugin form
    with override_current_theme_class(None):
        theme = get_current_theme(get_default_shop())
        cell = LayoutCell(theme, ProductsFromCategoryPlugin.identifier, sizes={"md": 8})
        lcfg = LayoutCellFormGroup(layout_cell=cell, theme=theme, request=apply_request_middleware(rf.get("/")))
        assert not lcfg.is_valid()

        lcfg = LayoutCellFormGroup(
            data={
                "general-cell_width": "8",
                "general-cell_align": "pull-right",
                "plugin-count": 4,
                "plugin-category": category2.pk,
                "plugin-cache_timeout": 3600
            },
            layout_cell=cell,
            theme=theme,
            request=apply_request_middleware(rf.get("/"))
        )
        assert lcfg.is_valid()
        lcfg.save()
        assert cell.config["category"] == str(category2.pk)
Esempio n. 37
0
 def visible(self):
     return not get_current_theme()
Esempio n. 38
0
def test_product_selection_plugin(rf):
    shop = factories.get_default_shop()
    category1 = factories.CategoryFactory(status=CategoryStatus.VISIBLE)
    category2 = factories.CategoryFactory(status=CategoryStatus.VISIBLE)

    p1 = factories.create_product("p1", shop, factories.get_default_supplier(), "10")
    p2 = factories.create_product("p2", shop, factories.get_default_supplier(), "20")
    p3 = factories.create_product("p3", shop, factories.get_default_supplier(), "30")
    p4 = factories.create_product("p4", shop, factories.get_default_supplier(), "40")
    p5 = factories.create_product("p5", shop, factories.get_default_supplier(), "50")

    sp1 = p1.get_shop_instance(shop)
    sp2 = p2.get_shop_instance(shop)
    sp3 = p3.get_shop_instance(shop)
    sp4 = p4.get_shop_instance(shop)

    sp1.categories.add(category1, category2)
    sp2.categories.add(category1)
    sp3.categories.add(category2)
    sp4.categories.add(category2)

    # this discount should show products: p1, p2 and p5
    discount1 = Discount.objects.create(
        name="discount1",
        active=True,
        start_datetime=now() - timedelta(days=10),
        end_datetime=now() + timedelta(days=1),
        product=p5,
        category=category1
    )
    discount1.shops = [shop]

    # this discount should show products: p1, p3 and p4
    discount2 = Discount.objects.create(
        name="discount2",
        active=True,
        start_datetime=now() - timedelta(days=10),
        end_datetime=now() + timedelta(days=1),
        category=category2
    )
    discount2.shops = [shop]

    # this discount shouldn't be available for this shop
    discount3 = Discount.objects.create(
        name="discount3",
        active=True,
        start_datetime=now() - timedelta(days=10),
        end_datetime=now() + timedelta(days=1),
        category=category2
    )

    context = get_context(rf)

    # test only discount1
    plugin = DiscountedProductsPlugin({"discounts": [discount1.pk], "count": 10})
    context_products = plugin.get_context_data(context)["products"]
    assert p1 in context_products
    assert p2 in context_products
    assert p3 not in context_products
    assert p4 not in context_products
    assert p5 in context_products

    for status in range(2):
        if status == 1:
            discount2.active = False
            discount2.save()

        # test only discount2
        plugin = DiscountedProductsPlugin({"discounts": [discount2.pk], "count": 10})
        context_products = plugin.get_context_data(context)["products"]

        if status == 1:
            assert context_products == []
        else:
            assert p1 in context_products
            assert p2 not in context_products
            assert p3 in context_products
            assert p4 in context_products
            assert p5 not in context_products

    # test discount3
    plugin = DiscountedProductsPlugin({"discounts": [discount3.pk], "count": 10})
    assert plugin.get_context_data(context)["products"] == []

    discount2.active = True
    discount2.save()

    # test both discount1 and discount2
    plugin = DiscountedProductsPlugin({"discounts": [discount1.pk, discount2.pk], "count": 10})
    context_products = plugin.get_context_data(context)["products"]
    assert p1 in context_products
    assert p2 in context_products
    assert p3 in context_products
    assert p4 in context_products
    assert p5 in context_products

    # test the plugin form
    with override_current_theme_class(None):
        theme = get_current_theme(shop)
        cell = LayoutCell(theme, DiscountedProductsPlugin.identifier, sizes={"md": 8})
        lcfg = LayoutCellFormGroup(layout_cell=cell, theme=theme, request=apply_request_middleware(rf.get("/")))
        # not valid, products are required
        assert not lcfg.is_valid()

        lcfg = LayoutCellFormGroup(
            data={
                "general-cell_width": "8",
                "general-cell_align": "pull-right",
                "plugin-discounts": [discount1.pk, discount2.pk],
                "plugin-count": 6
            },
            layout_cell=cell,
            theme=theme,
            request=apply_request_middleware(rf.get("/"))
        )
        assert lcfg.is_valid()
        lcfg.save()
        assert cell.config["discounts"] == [discount1.pk, discount2.pk]
Esempio n. 39
0
def test_theme_selection():
    cache.clear()

    shop = factories.get_default_shop()
    theme = get_current_theme(shop)

    test_js_script = 'console.log("this is JS snippet");'
    js_snippet = Snippet.objects.create(shop=shop,
                                        location="body_end",
                                        snippet_type=SnippetType.InlineJS,
                                        snippet=test_js_script,
                                        themes=theme.identifier)

    test_css_style = 'h1 { font-size: 3px; }'
    css_snippet = Snippet.objects.create(shop=shop,
                                         location="head_end",
                                         snippet_type=SnippetType.InlineCSS,
                                         snippet=test_css_style,
                                         themes=theme.identifier)

    test_html_code = '<p class="test-snippet">Test HTML snippet</p>'
    html_snippet = Snippet.objects.create(
        shop=shop,
        location="body_end",
        snippet_type=SnippetType.InlineHTMLMarkup,
        snippet=test_html_code,
        themes=theme.identifier)

    test_jinja_code = '<p class="test-snippet">Test Jinja snippet %s</p>'
    jinja_snippet = Snippet.objects.create(
        shop=shop,
        location="body_end",
        snippet_type=SnippetType.InlineJinjaHTMLMarkup,
        snippet=test_jinja_code % ('{{ request.shop.public_name}}'))

    html_that_should_not_exist = "<h1>-Hello world</h1>"
    snippet_for_other_theme = Snippet.objects.create(
        shop=shop,
        location="body_end",
        snippet_type=SnippetType.InlineHTMLMarkup,
        snippet=html_that_should_not_exist,
        themes="random.theme")
    with override_provides("xtheme_resource_injection",
                           ["shuup.xtheme.resources:inject_global_snippet"]):
        client = SmartClient()
        response, soup = client.response_and_soup("/")
        assert response.status_code == 200

        assert html_that_should_not_exist not in str(soup)

        body = str(soup.find("body"))
        assert "<script>%s</script>" % test_js_script in body
        assert test_html_code in body
        assert (test_jinja_code % shop.public_name) in body

        head = str(soup.find("head"))
        assert '<style type="text/css">%s</style>' % test_css_style in head

        # Admin views are not allowed to inject into
        client = SmartClient()
        response, soup = client.response_and_soup("/sa/login/")
        assert response.status_code == 200

        soup_str = str(soup)
        assert html_that_should_not_exist not in soup_str
        assert ('<style type="text/css">%s</style>' %
                test_css_style) not in soup_str
Esempio n. 40
0
def test_product_selection_plugin(rf, reindex_catalog):
    shop = factories.get_default_shop()
    shop2 = factories.get_shop(identifier="shop2")
    category1 = factories.CategoryFactory(status=CategoryStatus.VISIBLE)
    category2 = factories.CategoryFactory(status=CategoryStatus.VISIBLE)

    p1 = factories.create_product("p1", shop, factories.get_default_supplier(),
                                  "10")
    p2 = factories.create_product("p2", shop, factories.get_default_supplier(),
                                  "20")
    p3 = factories.create_product("p3", shop, factories.get_default_supplier(),
                                  "30")
    p4 = factories.create_product("p4", shop, factories.get_default_supplier(),
                                  "40")
    p5 = factories.create_product("p5", shop, factories.get_default_supplier(),
                                  "50")

    sp1 = p1.get_shop_instance(shop)
    sp2 = p2.get_shop_instance(shop)
    sp3 = p3.get_shop_instance(shop)
    sp4 = p4.get_shop_instance(shop)

    sp1.categories.add(category1, category2)
    sp2.categories.add(category1)
    sp3.categories.add(category2)
    sp4.categories.add(category2)

    # this discount should show products: p1, p2 and p5
    discount1 = Discount.objects.create(
        shop=shop,
        name="discount1",
        active=True,
        start_datetime=now() - timedelta(days=10),
        end_datetime=now() + timedelta(days=1),
        product=p5,
        category=category1,
    )

    # this discount should show products: p1, p3 and p4
    discount2 = Discount.objects.create(
        shop=shop,
        name="discount2",
        active=True,
        start_datetime=now() - timedelta(days=10),
        end_datetime=now() + timedelta(days=1),
        category=category2,
    )

    # this discount shouldn't be available for this shop
    discount3 = Discount.objects.create(
        shop=shop2,
        name="discount3",
        active=True,
        start_datetime=now() - timedelta(days=10),
        end_datetime=now() + timedelta(days=1),
        category=category2,
    )

    reindex_catalog()
    context = get_context(rf)

    # test only discount1
    plugin = DiscountedProductsPlugin({
        "discounts": [discount1.pk],
        "count": 10
    })
    context_products = plugin.get_context_data(context)["products"]
    assert p1 in context_products
    assert p2 in context_products
    assert p3 not in context_products
    assert p4 not in context_products
    assert p5 in context_products

    for status in range(2):
        if status == 1:
            discount2.active = False
            discount2.save()
            reindex_catalog()

        # test only discount2
        plugin = DiscountedProductsPlugin({
            "discounts": [discount2.pk],
            "count": 10
        })
        context_products = plugin.get_context_data(context)["products"]

        if status == 1:
            assert list(context_products) == []
        else:
            assert p1 in context_products
            assert p2 not in context_products
            assert p3 in context_products
            assert p4 in context_products
            assert p5 not in context_products

    # test discount3
    plugin = DiscountedProductsPlugin({
        "discounts": [discount3.pk],
        "count": 10
    })
    assert list(plugin.get_context_data(context)["products"]) == []

    discount2.active = True
    discount2.save()
    reindex_catalog()

    # test both discount1 and discount2
    plugin = DiscountedProductsPlugin({
        "discounts": [discount1.pk, discount2.pk],
        "count": 10
    })
    context_products = plugin.get_context_data(context)["products"]
    assert p1 in context_products
    assert p2 in context_products
    assert p3 in context_products
    assert p4 in context_products
    assert p5 in context_products

    # test the plugin form
    with override_current_theme_class(None):
        theme = get_current_theme(shop)
        cell = LayoutCell(theme,
                          DiscountedProductsPlugin.identifier,
                          sizes={"md": 8})
        lcfg = LayoutCellFormGroup(layout_cell=cell,
                                   theme=theme,
                                   request=apply_request_middleware(
                                       rf.get("/")))
        # not valid, products are required
        assert not lcfg.is_valid()

        lcfg = LayoutCellFormGroup(
            data={
                "general-cell_width": "8",
                "general-cell_align": "pull-right",
                "plugin-discounts": [discount1.pk, discount2.pk],
                "plugin-count": 6,
            },
            layout_cell=cell,
            theme=theme,
            request=apply_request_middleware(rf.get("/")),
        )
        assert lcfg.is_valid()
        lcfg.save()
        assert cell.config["discounts"] == [discount1.pk, discount2.pk]
Esempio n. 41
0
def test_product_selection_plugin(rf, reindex_catalog):
    shop = get_default_shop()
    supplier = get_default_supplier()
    p1 = create_product("p1", shop, supplier, "10")
    p2 = create_product("p2", shop, supplier, "20")
    p3 = create_product("p3", shop, supplier, "30")
    p4 = create_product("p4", shop, supplier, "40")

    sp1 = p1.get_shop_instance(shop)
    sp2 = p2.get_shop_instance(shop)
    sp3 = p3.get_shop_instance(shop)

    reindex_catalog()
    plugin = ProductSelectionPlugin({
        "products": [sp1.product.pk, sp2.product.pk, sp3.product.pk],
        "cache_timeout":
        120
    })
    plugin_context = plugin.get_context_data(get_context(rf, is_ajax=False))
    context_products = plugin_context["products"]

    assert len(context_products) == 0

    plugin_context = plugin.get_context_data(get_context(rf))
    context_data_url = plugin_context["data_url"]
    context_products = plugin_context["products"]
    assert p1 in context_products
    assert p2 in context_products
    assert p3 in context_products
    assert p4 not in context_products

    check_expected_product_count(context_data_url, 3)
    check_expected_product_count(context_data_url,
                                 3)  # one for checking it is cached

    # test the plugin form
    with override_current_theme_class(None):
        theme = get_current_theme(get_default_shop())
        cell = LayoutCell(theme,
                          ProductSelectionPlugin.identifier,
                          sizes={"md": 8})
        lcfg = LayoutCellFormGroup(layout_cell=cell,
                                   theme=theme,
                                   request=apply_request_middleware(
                                       rf.get("/")))
        # not valid, products are required
        assert not lcfg.is_valid()

        lcfg = LayoutCellFormGroup(
            data={
                "general-cell_width": "8",
                "general-cell_align": "pull-right",
                "plugin-products": [p1.pk, p2.pk],
                "plugin-cache_timeout": 120,
            },
            layout_cell=cell,
            theme=theme,
            request=apply_request_middleware(rf.get("/")),
        )
        assert lcfg.is_valid()
        lcfg.save()
        assert cell.config["products"] == [str(p1.pk), str(p2.pk)]
Esempio n. 42
0
def test_carousel_custom_colors(rf):
    from shuup.front.apps.carousel.plugins import CarouselPlugin
    from shuup.xtheme.models import SavedViewConfig, SavedViewConfigStatus
    from shuup.xtheme.layout import Layout
    from shuup.xtheme._theme import get_current_theme
    from django.core.urlresolvers import reverse

    shop = get_default_shop()
    shop.maintenance_mode = False
    shop.save()

    carousel = Carousel.objects.create(name="test")
    carousel.shops.add(shop)
    test_image = Image.objects.create(original_filename="slide.jpg")
    test_slide = Slide.objects.create(
        carousel=carousel, name="test",
        available_from=(datetime.now() - timedelta(days=1)),
        image=test_image, target=LinkTargetType.CURRENT
    )

    theme = get_current_theme(shop)

    # adds the carousel to the front page
    layout = Layout(theme, "front_content")
    layout.begin_row()
    layout.begin_column({"md": 12})
    layout.add_plugin(CarouselPlugin.identifier, {"carousel": carousel.pk})
    svc = SavedViewConfig(
        theme_identifier=theme.identifier,
        shop=shop,
        view_name="IndexView",
        status=SavedViewConfigStatus.CURRENT_DRAFT
    )
    svc.set_layout_data(layout.placeholder_name, layout)
    svc.save()
    svc.publish()

    client = Client()

    # no customized color
    response = client.get(reverse("shuup:index"))
    content = response.content.decode("utf-8")
    assert "owl-carousel" in content
    assert ".owl-nav .owl-prev" not in content
    assert ".owl-nav .owl-next" not in content
    assert ".owl-dot:nth-child(" not in content

    # put colors in arrows
    carousel.arrows_color = "#ffaabb"
    carousel.save()
    response = client.get(reverse("shuup:index"))
    content = response.content.decode("utf-8")
    assert ".owl-nav .owl-prev" in content
    assert ".owl-nav .owl-next" in content
    assert "color: #ffaabb !important;" in content

    # put custom color in dots
    test_slide.inactive_dot_color = "#a1b2c3"
    test_slide.active_dot_color = "#d4e4f6"
    test_slide.save()
    response = client.get(reverse("shuup:index"))
    content = response.content.decode("utf-8")
    assert ".owl-dot:nth-child(1)" in content
    assert "border-color: #a1b2c3 !important" in content
    assert "background-color: #d4e4f6 !important;" in content