Пример #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!"}
Пример #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: E-Commerce.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.shop),
            shop=request.shop,
            view_name=view_name,
            draft=is_edit_mode(request),
            global_type=global_type,
        )
        context.vars[config_key] = config
    return config
Пример #3
0
def inject_global_snippet(context, content):
    if not valid_view(context):
        return

    from E-Commerce.xtheme import get_current_theme
    from E-Commerce.xtheme.models import Snippet, SnippetType
    shop = get_shop(context["request"])

    cache_key = GLOBAL_SNIPPETS_CACHE_KEY.format(shop_id=shop.id)
    snippets = cache.get(cache_key)

    if snippets is None:
        snippets = Snippet.objects.filter(shop=shop)
        cache.set(cache_key, snippets)

    for snippet in snippets:
        if snippet.themes:
            current_theme = get_current_theme(shop)
            if current_theme and current_theme.identifier not in snippet.themes:
                continue

        content = snippet.snippet
        if snippet.snippet_type == SnippetType.InlineJS:
            content = InlineScriptResource(content)
        elif snippet.snippet_type == SnippetType.InlineCSS:
            content = InlineStyleResource(content)
        elif snippet.snippet_type == SnippetType.InlineHTMLMarkup:
            content = InlineMarkupResource(content)

        add_resource(context, snippet.location, content)
Пример #4
0
 def process_request(self, request):
     shop = getattr(request, "shop", Shop.objects.first())
     theme = get_current_theme(shop)
     if theme:
         theme.set_current()
     else:
         log.error((_("Shop '{}' has no active theme")).format(shop))
Пример #5
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
Пример #6
0
def test_xtheme_snippet_injection(browser, admin_user, live_server, settings):
    shop = factories.get_default_shop()
    initialize_admin_browser_test(browser, live_server, settings)

    url = reverse("E-Commerce_admin:xtheme_snippet.new")
    browser.visit("%s%s" % (live_server, url))
    wait_until_condition(browser, lambda x: x.is_text_present("New Snippet"))
    browser.execute_script("$(\"[name='location']\").val('body_end').trigger('change')")
    browser.execute_script("$(\"[name='snippet_type']\").val('inline_js').trigger('change')")
    browser.execute_script("window.CodeMirror.editors['id_snippet-snippet'].setValue('alert(\"works\")');")
    click_element(browser, "button[type='submit']")
    wait_until_appeared(browser, "div[class='message success']")

    url = reverse("E-Commerce:index")
    browser.visit("%s%s" % (live_server, url))

    def has_alert(browser):
        try:
            return browser.get_alert().text == "works"
        except:
            return False

    wait_until_condition(browser, has_alert)
    browser.get_alert().accept()

    theme = get_current_theme(shop)
    snippet = Snippet.objects.filter(shop=shop).first()
    snippet.themes = [theme.identifier]
    snippet.save()

    cache.clear()
    browser.visit("%s%s" % (live_server, url))
    wait_until_condition(browser, has_alert)
    browser.get_alert().accept()

    snippet.themes = ["doesnt-exist"]
    snippet.save()

    cache.clear()
    browser.visit("%s%s" % (live_server, url))
    wait_until_condition(browser, lambda x: x.is_text_present("Welcome to Default!"))

    with pytest.raises(Exception):
        browser.get_alert()

    # delete the snippet
    url = reverse("E-Commerce_admin:xtheme_snippet.edit", kwargs=dict(pk=snippet.pk))
    browser.visit("%s%s" % (live_server, url))
    assert Snippet.objects.filter(shop=shop).exists()

    click_element(browser, ".E-Commerce-toolbar button.btn.btn-danger")
    browser.get_alert().accept()
    wait_until_condition(browser, lambda x: not Snippet.objects.filter(shop=shop).exists())
Пример #7
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("E-Commerce_admin:xtheme.config_detail", kwargs={"theme_identifier": theme.identifier})
             }],
             priority=200,
             category=HelpBlockCategory.STOREFRONT,
             icon_url="xtheme/theme.png"
         )
Пример #8
0
def test_xtheme_wizard_pane(rf, admin_user):
    with override_settings(
        E-Commerce_SETUP_WIZARD_PANE_SPEC = [
            "E-Commerce.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", ["E-Commerce_tests.xtheme.utils:FauxTheme"]):
            from E-Commerce_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)
Пример #9
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)
Пример #10
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="E-Commerce_admin:xtheme.config"
                    )
Пример #11
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 'E-Commerce.xtheme' in settings.INSTALLED_APPS:
            from E-Commerce.front.apps.carousel.plugins import CarouselPlugin
            from E-Commerce.xtheme.plugins.products import ProductHighlightPlugin

            from E-Commerce.xtheme.models import SavedViewConfig, SavedViewConfigStatus
            from E-Commerce.xtheme.layout import Layout
            from E-Commerce.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
Пример #12
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.shop)
    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)
Пример #13
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
Пример #14
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)]
Пример #15
0
def test_page_layout():
    if "E-Commerce.xtheme" not in settings.INSTALLED_APPS:
        pytest.skip("Need E-Commerce.xtheme in INSTALLED_APPS")

    shop = factories.get_default_shop()
    theme = get_current_theme(shop)
    view_config = ViewConfig(theme=theme, shop=shop, view_name="PageView", draft=True)
    page1_content = printable_gibberish()
    page1 = create_page(available_from=datetime.date(1917, 12, 6), content=page1_content, shop=shop, url="test1")
    page2_content = printable_gibberish()
    page2 = create_page(available_from=datetime.date(1917, 12, 6), content=page2_content, shop=shop, url="test2")

    placeholder_name = "cms_page"
    context = {"page": page1}
    layout = view_config.get_placeholder_layout(PageLayout, placeholder_name, context=context)
    assert isinstance(layout, PageLayout)
    assert layout.get_help_text({}) == ""  # Invalid context for help text
    assert page1.title in layout.get_help_text(context)

    # Make sure layout is empty
    serialized = layout.serialize()
    assert len(serialized["rows"]) == 0
    assert serialized["name"] == placeholder_name

    # Add custom plugin to page
    layout.begin_column({"md": 8})
    plugin_text = printable_gibberish()
    layout.add_plugin("text", {"text": plugin_text})
    view_config.save_placeholder_layout(get_layout_data_key(placeholder_name, layout, context), layout)
    view_config.publish()

    c = SmartClient()
    soup = c.soup(reverse("E-Commerce:cms_page", kwargs={"url": page1.url}))
    page_content = soup.find("div", {"class": "page-content"})
    assert page1_content in page_content.text
    assert plugin_text in page_content.text

    c = SmartClient()
    soup = c.soup(reverse("E-Commerce:cms_page", kwargs={"url": page2.url}))
    page_content = soup.find("div", {"class": "page-content"})
    assert page2_content in page_content.text
    assert plugin_text not in page_content.text
Пример #16
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
Пример #17
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]
Пример #18
0
def _get_basic_view_config(view_name="pow"):
    shop = factories.get_default_shop()
    theme = get_current_theme(shop)
    return ViewConfig(theme=theme, shop=shop, view_name=view_name, draft=True)