def test_global_snippet_resource_injection():
    request = get_request(edit=False)
    request.shop = get_default_shop()
    jeng = get_jinja2_engine()
    template = jeng.get_template("resinject.jinja")
    request.resolver_match = MagicMock(app_name="shuup")
    context = dict(view=FauxView, request=request)

    with override_provides("xtheme_resource_injection",
                           ["shuup.xtheme.resources:inject_global_snippet"]):
        with override_current_theme_class():
            output = template.render(context, request=request)
            assert "<div>1</div>" not in output

            Snippet.objects.create(
                shop=request.shop,
                location="body_end",
                snippet_type=SnippetType.InlineJinjaHTMLMarkup,
                snippet="""
                    {% set x = 1 %}
                    <div>{{- x -}}</div>
                """)

        cache.clear()

        with override_current_theme_class():
            output = template.render(context, request=request)
            assert "<div>1</div>" in output
Beispiel #2
0
def test_rendering(edit, injectable, theme_class, global_type):
    request = get_request(edit)
    request.resolver_match = mock.Mock()
    request.resolver_match.app_name = "shuup"

    with override_current_theme_class(theme_class):
        with plugin_override():
            jeng = get_jinja2_engine()
            if global_type:
                template = jeng.get_template("global_complex.jinja")
            else:
                template = jeng.get_template("complex.jinja")
            view = FauxView()
            view.xtheme_injection = bool(injectable)
            output = template.render(context={
                "view": view,
                "request": request
            }, request=request)

            # From now on we render placholders in views that
            # actually can be edited.
            if injectable and theme_class:
                assert "wider column" in output
                assert "less wide column" in output

            if edit and injectable and theme_class:
                assert "xt-ph-edit" in output
                assert "data-xt-placeholder-name" in output
                assert "data-xt-row" in output
                assert "data-xt-cell" in output
                assert "XthemeEditorConfig" in output
Beispiel #3
0
def test_rendering(edit, injectable, theme_class, global_type):
    request = get_request(edit)
    request.resolver_match = mock.Mock()
    request.resolver_match.app_name = "shuup"

    with override_current_theme_class(theme_class):
        with plugin_override():
            jeng = get_jinja2_engine()
            if global_type:
                template = jeng.get_template("global_complex.jinja")
            else:
                template = jeng.get_template("complex.jinja")
            view = FauxView()
            view.xtheme_injection = bool(injectable)
            output = template.render(context={
                "view": view,
                "request": request
            },
                                     request=request)

            # From now on we render placholders in views that
            # actually can be edited.
            if injectable and theme_class:
                assert "wider column" in output
                assert "less wide column" in output

            if edit and injectable and theme_class:
                assert "xt-ph-edit" in output
                assert "data-xt-placeholder-name" in output
                assert "data-xt-row" in output
                assert "data-xt-cell" in output
                assert "XthemeEditorConfig" in output
Beispiel #4
0
def test_layout_rendering_with_global_type(rf):
    request = get_request(edit=False)
    with override_current_theme_class(None):
        with plugin_override():
            jeng = get_jinja2_engine()
            template = jeng.from_string("")

            (template, layout, gibberish,
             ctx) = get_test_template_bits(request)

            global_class = "xt-global-ph"
            result = six.text_type(
                render_placeholder(ctx,
                                   "test",
                                   layout,
                                   template.template.name,
                                   global_type=True))
            assert global_class in result

            result = six.text_type(
                render_placeholder(ctx,
                                   "test",
                                   layout,
                                   template.template.name,
                                   global_type=False))
            assert global_class not in result
Beispiel #5
0
def test_render_custom_size_cell(rf):
    request = get_request(edit=False)
    with override_current_theme_class(None):
        with plugin_override():
            with layout_override():
                layout = Layout(FauxTheme, "test")
                gibberish = printable_gibberish()
                layout.begin_column({"md": None, "xs": None, "sm": None})
                layout.add_plugin("text", {"text": "<p>%s</p>" % gibberish})
                jeng = get_jinja2_engine()
                template = jeng.from_string("")
                template.template.name = "test"
                vars = {
                    "view": FauxView(),
                    "request": request
                }
                ctx = template.template.new_context(vars)

                result = six.text_type(render_placeholder(ctx, "test", layout, "test"))
                expect = """
                <div class="placeholder-edit-wrap">
                <div class="xt-ph" id="xt-ph-test">
                <div class="row xt-ph-row">
                <div class="xt-ph-cell"><p>%s</p></div>
                </div>
                </div>
                </div>
                """ % gibberish
                assert close_enough(result, expect)
Beispiel #6
0
def test_simple_addon_injection():
    request = get_request(edit=False)
    request.shop = get_default_shop()
    jeng = get_jinja2_engine()
    template = jeng.get_template("resinject.jinja")

    with override_current_theme_class():
        with override_provides(
                "xtheme_resource_injection",
            [
                "shuup_tests.xtheme.test_addon_injections:add_test_injection",
            ],
        ):
            # TestInjector should add alert to end of the body for every request
            output = template.render(request=request)
            head, body = output.split("</head>", 1)
            assert "window.injectedFromAddon=true;" in body

            with override_settings(
                    SHUUP_XTHEME_EXCLUDE_TEMPLATES_FROM_RESOUCE_INJECTION=[
                        "resinject.jinja"
                    ]):
                output = template.render(request=request)
                head, body = output.split("</head>", 1)
                assert "window.injectedFromAddon=true;" not in body
def test_theme_without_default_template_dir():
    get_default_shop()
    with override_current_theme_class(ShuupTestingTheme):
        c = SmartClient()
        soup = c.soup(reverse("shuup:index"))
        assert "Simple base for themes to use" not in soup
        assert "Welcome to test Shuup!" in soup.find("div", {"class": "page-content"}).text
def test_theme_with_default_template_dir():
    get_default_shop()
    with override_current_theme_class(ShuupTestingThemeWithCustomBase):
        c = SmartClient()
        soup = c.soup(reverse("shuup:index"))
        assert "Simple base for themes to use" in soup.find("h1").text
        assert "Welcome to test Shuup!" in soup.find("h1").text
Beispiel #9
0
def pytest_runtest_call(item):
    # All tests are run with a theme override `shuup.themes.classic_gray.ClassicGrayTheme`.
    # To un-override, use `with override_current_theme_class()` (no arguments to re-enable database lookup)
    from shuup.themes.classic_gray.theme import ClassicGrayTheme
    item.session._theme_overrider = override_current_theme_class(
        ClassicGrayTheme, get_default_shop())
    item.session._theme_overrider.__enter__()
Beispiel #10
0
def test_xtheme_extra_view_exceptions(rf):
    with override_current_theme_class(H2G2Theme, get_default_shop()):
        request = rf.get("/")
        request.shop = get_default_shop()
        assert extra_view_dispatch(request, "vogons").status_code == 404
        with pytest.raises(ImproperlyConfigured):
            assert extra_view_dispatch(request, "true")
Beispiel #11
0
def pytest_runtest_call(item):
    # All tests are run with a theme override `shuup.themes.classic_gray.ClassicGrayTheme`.
    # To un-override, use `with override_current_theme_class()` (no arguments to re-enable database lookup)
    from shuup.themes.classic_gray.theme import ClassicGrayTheme

    item.session._theme_overrider = override_current_theme_class(ClassicGrayTheme)
    item.session._theme_overrider.__enter__()
def test_category_detail_multiselect_supplier_filters(client):
    shop = factories.get_default_shop()

    # Activate show supplier info for front
    assert ThemeSettings.objects.count() == 1
    theme_settings = ThemeSettings.objects.first()
    theme_settings.update_settings({"show_supplier_info": True})

    category = factories.get_default_category()

    # Important! Activate supplier filter.
    set_configuration(
        shop=shop,
        data={
            "filter_products_by_supplier": True,
            "filter_products_by_supplier_ordering": 1,
            "filter_products_by_supplier_multiselect_enabled": True,
        },
    )

    supplier_data = [
        ("Johnny Inc", 0.5),
        ("Mike Inc", 0.9),
        ("Simon Inc", 0.8),
    ]

    for name, percentage_from_original_price in supplier_data:
        supplier = Supplier.objects.create(name=name)
        supplier.shops.add(shop)
        sku = name
        price_value = 10
        product = factories.create_product(sku, shop=shop, default_price=price_value)
        shop_product = product.get_shop_instance(shop)
        shop_product.suppliers.add(supplier)
        shop_product.primary_category = category
        shop_product.categories.add(category)
        shop_product.save()

        supplier_price = percentage_from_original_price * price_value
        SupplierPrice.objects.create(supplier=supplier, shop=shop, product=product, amount_value=supplier_price)

    strategy = "shuup.testing.supplier_pricing.supplier_strategy:CheapestSupplierPriceSupplierStrategy"
    with override_settings(SHUUP_PRICING_MODULE="supplier_pricing", SHUUP_SHOP_PRODUCT_SUPPLIERS_STRATEGY=strategy):
        with override_current_theme_class(ClassicGrayTheme, shop):  # Ensure settings is refreshed from DB
            johnny_supplier = Supplier.objects.filter(name="Johnny Inc").first()
            mike_supplier = Supplier.objects.filter(name="Mike Inc").first()
            simon_supplier = Supplier.objects.filter(name="Simon Inc").first()

            soup = _get_category_detail_soup_multiselect(client, category, [johnny_supplier.pk])
            assert len(soup.findAll("div", {"class": "single-product"})) == 1

            soup = _get_category_detail_soup_multiselect(client, category, [johnny_supplier.pk, mike_supplier.pk])
            assert len(soup.findAll("div", {"class": "single-product"})) == 2

            soup = _get_category_detail_soup_multiselect(
                client, category, [johnny_supplier.pk, mike_supplier.pk, simon_supplier.pk]
            )
            assert len(soup.findAll("div", {"class": "single-product"})) == 3
Beispiel #13
0
def test_layout_edit_render():
    request = get_request(edit=True)
    with override_current_theme_class(None):
        with plugin_override():
            (template, layout, gibberish, ctx) = get_test_template_bits(request)
            result = six.text_type(render_placeholder(ctx, "test", layout, "test"))
            # Look for evidence of editing:
            assert "xt-ph-edit" in result
            assert "data-xt-placeholder-name" in result
            assert "data-xt-row" in result
            assert "data-xt-cell" in result
Beispiel #14
0
def test_xtheme_extra_views(rf):
    with override_current_theme_class(H2G2Theme):
        request = rf.get("/", {"name": "Arthur Dent"})
        # Simulate /xtheme/greeting
        response = extra_view_dispatch(request, "greeting")
        assert force_text(response.content) == "So long, and thanks for all the fish, Arthur Dent"
        # Try that again (to exercise the _VIEW_CACHE code path):
        response = extra_view_dispatch(request, "greeting")
        assert force_text(response.content) == "So long, and thanks for all the fish, Arthur Dent"
        # Now test that CBVs work
        assert not extra_view_dispatch(request, "faux").content
Beispiel #15
0
def test_layout_edit_render():
    request = get_request(edit=True)
    with override_current_theme_class(None):
        with plugin_override():
            (template, layout, gibberish, ctx) = get_test_template_bits(request)
            result = six.text_type(render_placeholder(ctx, "test", layout, "test"))
            # Look for evidence of editing:
            assert "xt-ph-edit" in result
            assert "data-xt-placeholder-name" in result
            assert "data-xt-row" in result
            assert "data-xt-cell" in result
def test_xtheme_extra_views(rf):
    with override_current_theme_class(H2G2Theme):
        request = rf.get("/", {"name": "Arthur Dent"})
        # Simulate /xtheme/greeting
        response = extra_view_dispatch(request, "greeting")
        assert force_text(response.content) == "So long, and thanks for all the fish, Arthur Dent"
        # Try that again (to exercise the _VIEW_CACHE code path):
        response = extra_view_dispatch(request, "greeting")
        assert force_text(response.content) == "So long, and thanks for all the fish, Arthur Dent"
        # Now test that CBVs work
        assert not extra_view_dispatch(request, "faux").content
Beispiel #17
0
def initialize_editor_view(view_name, placeholder_name, request=None):
    if request is None:
        request = RequestFactory().get("/")
    request.user = SuperUser()
    if hasattr(request.GET, "_mutable"):
        request.GET._mutable = True  # Ahem
    request.GET.update({"theme": FauxTheme.identifier, "view": view_name, "ph": placeholder_name})

    with plugin_override():
        with override_provides("xtheme", ["shuup_tests.xtheme.utils:FauxTheme"]):
            with override_current_theme_class(FauxTheme):
                yield EditorView(request=request, args=(), kwargs={})
Beispiel #18
0
def test_view_config_caches_into_context(rf):
    # This is a silly test...
    request = get_request(edit=False)
    with override_current_theme_class(None):
        (template, layout, gibberish, ctx) = get_test_template_bits(request)
        cfg1 = get_view_config(ctx)
        cfg2 = get_view_config(ctx)
        assert cfg1 is cfg2
        (template, layout, gibberish, ctx) = get_test_template_bits(request, False)
        cfg1 = get_view_config(ctx)
        cfg2 = get_view_config(ctx)
        assert cfg1 is cfg2
def test_product_detail_theme_configs(client):
    shop = factories.get_default_shop()
    product = factories.create_product("sku", shop=shop, default_price=30)

    # Show only product description section
    assert ThemeSettings.objects.count() == 1
    theme_settings = ThemeSettings.objects.first()
    theme_settings.update_settings({"product_detail_tabs": ["description"]})

    with override_current_theme_class(ClassicGrayTheme, shop):  # Ensure settings is refreshed from DB
        soup = _get_product_detail_soup(client, product)
        assert soup.find("div", attrs={"class": "product-tabs"})
        tabs = soup.find_all("ul", attrs={"class": "nav-tabs"})[0].find_all("li")
        assert len(tabs) == 1
        assert "Description" in tabs[0].text

    # disable product details completely
    theme_settings.update_settings({"show_product_detail_section": False})
    with override_current_theme_class(ClassicGrayTheme, shop):
        soup = _get_product_detail_soup(client, product)
        assert not soup.find("div", attrs={"class": "product-tabs"})
Beispiel #20
0
def pytest_runtest_call(item):
    # All tests are run with a theme override `shuup.themes.classic_gray.ClassicGrayTheme`.
    # To un-override, use `with override_current_theme_class()` (no arguments to re-enable database lookup)
    from shuup.themes.classic_gray.theme import ClassicGrayTheme

    item.session._theme_overrider = override_current_theme_class(ClassicGrayTheme, get_default_shop())
    item.session._theme_overrider.__enter__()
    get_language_name.cache_clear()  # Clear language name lru_cache for each test
    get_setting.cache_clear()
    get_price_display_options.cache_clear()
    get_display_unit.cache_clear()
    get_groups_ids.cache_clear()
Beispiel #21
0
def test_simple_addon_injection():
    request = get_request(edit=False)
    jeng = get_jinja2_engine()
    template = jeng.get_template("resinject.jinja")

    with override_current_theme_class():
        with override_provides(
                "xtheme_resource_injection", ["shuup_tests.xtheme.test_addon_injections:add_test_injection",]):
            # TestInjector should add alert to end of the body for every request
            output = template.render(request=request)
            head, body = output.split("</head>", 1)
            assert "window.injectedFromAddon=true;" in body
Beispiel #22
0
def test_view_config_caches_into_context(rf):
    # This is a silly test...
    request = get_request(edit=False)
    with override_current_theme_class(None):
        (template, layout, gibberish, ctx) = get_test_template_bits(request)
        cfg1 = get_view_config(ctx)
        cfg2 = get_view_config(ctx)
        assert cfg1 is cfg2
        (template, layout, gibberish, ctx) = get_test_template_bits(request, False)
        cfg1 = get_view_config(ctx)
        cfg2 = get_view_config(ctx)
        assert cfg1 is cfg2
Beispiel #23
0
def test_product_detail(client):
    shop = factories.get_default_shop()
    product = factories.create_product("sku", shop=shop, default_price=30)
    shop_product = product.get_shop_instance(shop)

    # Activate show supplier info for front
    assert ThemeSettings.objects.count() == 1
    theme_settings = ThemeSettings.objects.first()
    theme_settings.update_settings({"show_supplier_info": True})

    supplier_data = [
        ("Johnny Inc", 30),
        ("Mike Inc", 20),
        ("Simon Inc", 10),
    ]
    for name, product_price in supplier_data:
        supplier = Supplier.objects.create(name=name)
        supplier.shops.add(shop)
        shop_product.suppliers.add(supplier)
        SupplierPrice.objects.create(supplier=supplier,
                                     shop=shop,
                                     product=product,
                                     amount_value=product_price)

    strategy = "shuup.testing.supplier_pricing.supplier_strategy:CheapestSupplierPriceSupplierStrategy"
    with override_settings(SHUUP_PRICING_MODULE="supplier_pricing",
                           SHUUP_SHOP_PRODUCT_SUPPLIERS_STRATEGY=strategy):

        # Ok so cheapest price should be default supplier
        expected_supplier = shop_product.get_supplier()
        assert expected_supplier.name == "Simon Inc"
        with override_current_theme_class(
                ClassicGrayTheme,
                shop):  # Ensure settings is refreshed from DB
            soup = _get_product_detail_soup(client, product)

            _assert_supplier_subtitle(soup, expected_supplier)
            _assert_add_to_basket_form(soup, expected_supplier, 10)

            # Bonus! Let's say Johnny gets mad and starts to supply this product for 5 euros
            johnny_the_supplier = Supplier.objects.filter(
                name="Johnny Inc").first()
            SupplierPrice.objects.filter(
                supplier=johnny_the_supplier, shop=shop,
                product=product).update(amount_value=5)

            # This means that product detail get new default supplier and new price
            assert shop_product.get_supplier() == johnny_the_supplier
            soup = _get_product_detail_soup(client, product)

            _assert_supplier_subtitle(soup, johnny_the_supplier)
            _assert_add_to_basket_form(soup, johnny_the_supplier, 5)
Beispiel #24
0
def test_simple_addon_injection():
    request = get_request(edit=False)
    jeng = get_jinja2_engine()
    template = jeng.get_template("resinject.jinja")

    with override_current_theme_class():
        with override_provides("xtheme_resource_injection", [
                "shuup_tests.xtheme.test_addon_injections:add_test_injection",
        ]):
            # TestInjector should add alert to end of the body for every request
            output = template.render(request=request)
            head, body = output.split("</head>", 1)
            assert "window.injectedFromAddon=true;" in body
def test_product_view_prices_and_basket_visibility(rf):
    activate("en")
    product_sku = "test-123"
    shop = factories.get_default_shop()
    supplier = factories.get_default_supplier()
    default_price = 11
    product = factories.create_product(product_sku, shop=shop, supplier=supplier, default_price=default_price)

    assert ThemeSettings.objects.count() == 1
    theme_settings = ThemeSettings.objects.first()
    assert theme_settings.shop == shop
    assert theme_settings.theme_identifier == ClassicGrayTheme.identifier

    assert not theme_settings.get_setting("hide_prices")
    assert not theme_settings.get_setting("catalog_mode")

    with override_current_theme_class(ClassicGrayTheme, shop):  # Ensure settings is refreshed from DB
        c = SmartClient()
        soup = c.soup(reverse("shuup:product", kwargs={"pk": product.pk, "slug": product.slug}))
        assert _is_basket_in_soup(soup)
        assert _is_price_in_soup(soup, default_price)
        assert _is_add_to_basket_button_in_soup(soup)

    theme_settings.update_settings({"catalog_mode": True})
    with override_current_theme_class(ClassicGrayTheme, shop):  # Ensure settings is refreshed from DB
        c = SmartClient()
        soup = c.soup(reverse("shuup:product", kwargs={"pk": product.pk, "slug": product.slug}))
        assert not _is_basket_in_soup(soup)
        assert not _is_add_to_basket_button_in_soup(soup)
        assert _is_price_in_soup(soup, default_price)

    theme_settings.update_settings({"hide_prices": True, "catalog_mode": False})
    with override_current_theme_class(ClassicGrayTheme, shop):  # Ensure settings is refreshed from DB
        c = SmartClient()
        soup = c.soup(reverse("shuup:product", kwargs={"pk": product.pk, "slug": product.slug}))
        assert not _is_add_to_basket_button_in_soup(soup)
        assert not _is_basket_in_soup(soup)
        assert not _is_price_in_soup(soup, default_price)
def test_product_view_prices_and_basket_visibility(rf):
    activate("en")
    product_sku = "test-123"
    shop = factories.get_default_shop()
    supplier = factories.get_default_supplier()
    default_price = 11
    product = factories.create_product(product_sku, shop=shop, supplier=supplier, default_price=default_price)

    assert ThemeSettings.objects.count() == 1
    theme_settings = ThemeSettings.objects.first()
    assert theme_settings.shop == shop
    assert theme_settings.theme_identifier == ClassicGrayTheme.identifier

    assert not theme_settings.get_setting("hide_prices")
    assert not theme_settings.get_setting("catalog_mode")

    with override_current_theme_class(ClassicGrayTheme, shop):  # Ensure settings is refreshed from DB
        c = SmartClient()
        soup = c.soup(reverse("shuup:product", kwargs={"pk": product.pk, "slug": product.slug}))
        assert _is_basket_in_soup(soup)
        assert _is_price_in_soup(soup, default_price)
        assert _is_add_to_basket_button_in_soup(soup)

    theme_settings.update_settings({"catalog_mode": True})
    with override_current_theme_class(ClassicGrayTheme, shop):  # Ensure settings is refreshed from DB
        c = SmartClient()
        soup = c.soup(reverse("shuup:product", kwargs={"pk": product.pk, "slug": product.slug}))
        assert not _is_basket_in_soup(soup)
        assert not _is_add_to_basket_button_in_soup(soup)
        assert _is_price_in_soup(soup, default_price)

    theme_settings.update_settings({"hide_prices": True, "catalog_mode": False})
    with override_current_theme_class(ClassicGrayTheme, shop):  # Ensure settings is refreshed from DB
        c = SmartClient()
        soup = c.soup(reverse("shuup:product", kwargs={"pk": product.pk, "slug": product.slug}))
        assert not _is_add_to_basket_button_in_soup(soup)
        assert not _is_basket_in_soup(soup)
        assert not _is_price_in_soup(soup, default_price)
Beispiel #27
0
def test_xtheme_extra_view_exceptions(rf):
    with override_settings(CACHES={
        'default': {
            'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
            'LOCATION': 'test_configuration_cache',
        }
    }):
        cache.init_cache()
        with override_current_theme_class(H2G2Theme, get_default_shop()):
            request = rf.get("/")
            request.shop = get_default_shop()
            assert extra_view_dispatch(request, "vogons").status_code == 404
            with pytest.raises(ImproperlyConfigured):
                assert extra_view_dispatch(request, "true")
Beispiel #28
0
def test_theme_with_default_template_dir():
    with override_settings(CACHES={
        'default': {
            'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
            'LOCATION': 'test_configuration_cache',
        }
    }):
        cache.init_cache()
        get_default_shop()
        with override_current_theme_class(ShuupTestingThemeWithCustomBase, get_default_shop()):
            c = SmartClient()
            soup = c.soup(reverse("shuup:index"))
            assert "Simple base for themes to use" in soup.find("h1").text
            assert "Welcome to test Shuup!" in soup.find("h1").text
Beispiel #29
0
def test_theme_activation():
    with override_current_theme_class():
        with override_provides("xtheme", [
                "shuup_tests.xtheme.utils:FauxTheme",
                "shuup_tests.xtheme.utils:FauxTheme2"
        ]):
            ThemeSettings.objects.all().delete()
            assert not get_current_theme()
            set_current_theme(FauxTheme.identifier)
            assert isinstance(get_current_theme(), FauxTheme)
            set_current_theme(FauxTheme2.identifier)
            assert isinstance(get_current_theme(), FauxTheme2)
            with pytest.raises(ValueError):
                set_current_theme(printable_gibberish())
def test_product_detail_theme_configs(client):
    shop = factories.get_default_shop()
    product = factories.create_product("sku", shop=shop, default_price=30)

    # Show only product description section
    assert ThemeSettings.objects.count() == 1
    theme_settings = ThemeSettings.objects.first()
    theme_settings.update_settings({"product_detail_tabs": ["description"]})

    with override_current_theme_class(
            ClassicGrayTheme, shop):  # Ensure settings is refreshed from DB
        soup = _get_product_detail_soup(client, product)
        assert soup.find("div", attrs={"class": "product-tabs"})
        tabs = soup.find_all("ul", attrs={"class":
                                          "nav-tabs"})[0].find_all("li")
        assert len(tabs) == 1
        assert "Description" in tabs[0].text

    # disable product details completely
    theme_settings.update_settings({"show_product_detail_section": False})
    with override_current_theme_class(ClassicGrayTheme, shop):
        soup = _get_product_detail_soup(client, product)
        assert not soup.find("div", attrs={"class": "product-tabs"})
Beispiel #31
0
def test_theme_activation():
    with override_current_theme_class():
        with override_provides("xtheme", [
            "shuup_tests.xtheme.utils:FauxTheme",
            "shuup_tests.xtheme.utils:FauxTheme2"
        ]):
            ThemeSettings.objects.all().delete()
            assert not get_current_theme()
            set_current_theme(FauxTheme.identifier)
            assert isinstance(get_current_theme(), FauxTheme)
            set_current_theme(FauxTheme2.identifier)
            assert isinstance(get_current_theme(), FauxTheme2)
            with pytest.raises(ValueError):
                set_current_theme(printable_gibberish())
Beispiel #32
0
def test_resources():
    request = get_request(edit=False)
    with override_current_theme_class(None):
        with plugin_override():
            jeng = get_jinja2_engine()
            template = jeng.get_template("resinject.jinja")
            output = template.render(request=request)
            head, body = output.split("</head>", 1)
            assert "alert('xss')" in body  # the inline script
            assert '"bars": [1, 2, 3]' in head  # the script vars
            assert '(unknown resource type:' in body  # the png
            assert 'href="://example.com/css.css"' in head  # the css
            assert 'src="://example.com/js.js"' in body  # the js
            assert head.count(ResourceInjectorPlugin.meta_markup) == 1  # the duplicate meta
            assert ResourceInjectorPlugin.message in output  # the actual message
Beispiel #33
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)
Beispiel #34
0
def test_xtheme_extra_view_exceptions(rf):
    with override_settings(
            CACHES={
                'default': {
                    'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
                    'LOCATION': 'test_configuration_cache',
                }
            }):
        cache.init_cache()
        with override_current_theme_class(H2G2Theme, get_default_shop()):
            request = rf.get("/")
            request.shop = get_default_shop()
            assert extra_view_dispatch(request, "vogons").status_code == 404
            with pytest.raises(ImproperlyConfigured):
                assert extra_view_dispatch(request, "true")
Beispiel #35
0
def test_layout_rendering_with_global_type(rf):
    request = get_request(edit=False)
    with override_current_theme_class(None):
        with plugin_override():
            jeng = get_jinja2_engine()
            template = jeng.from_string("")

            (template, layout, gibberish, ctx) = get_test_template_bits(request)

            global_class = "xt-global-ph"
            result = six.text_type(render_placeholder(ctx, "test", layout, template.template.name, global_type=True))
            assert global_class in result

            result = six.text_type(render_placeholder(ctx, "test", layout, template.template.name, global_type=False))
            assert global_class not in result
Beispiel #36
0
def test_layout_rendering(rf):
    request = get_request(edit=False)
    with override_current_theme_class(None):
        with plugin_override():
            (template, layout, gibberish, ctx) = get_test_template_bits(request)

            result = six.text_type(render_placeholder(ctx, "test", layout, "test"))
            expect = """
            <div class="xt-ph" id="xt-ph-test">
            <div class="row xt-ph-row">
            <div class="col-md-12 hidden-xs xt-ph-cell"><p>%s</p></div>
            </div>
            </div>
            """ % gibberish
            assert close_enough(result, expect)
Beispiel #37
0
def test_layout_rendering(rf):
    request = get_request(edit=False)
    with override_current_theme_class(None):
        with plugin_override():
            (template, layout, gibberish, ctx) = get_test_template_bits(request)

            result = six.text_type(render_placeholder(ctx, "test", layout, "test"))
            expect = """
            <div class="xt-ph" id="xt-ph-test">
            <div class="row xt-ph-row">
            <div class="col-md-12 hidden-xs xt-ph-cell"><p>%s</p></div>
            </div>
            </div>
            """ % gibberish
            assert close_enough(result, expect)
Beispiel #38
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)
Beispiel #39
0
def initialize_editor_view(view_name, placeholder_name, request=None):
    if request is None:
        request = RequestFactory().get("/")
    request.user = SuperUser()
    if hasattr(request.GET, "_mutable"):
        request.GET._mutable = True  # Ahem
    request.GET.update({
        "theme": FauxTheme.identifier,
        "view": view_name,
        "ph": placeholder_name
    })

    with plugin_override():
        with override_provides("xtheme", ["shuup_tests.xtheme.utils:FauxTheme"]):
            with override_current_theme_class(FauxTheme):
                yield EditorView(request=request, args=(), kwargs={})
Beispiel #40
0
def test_resources():
    request = get_request(edit=False)
    with override_current_theme_class(None):
        with plugin_override():
            jeng = get_jinja2_engine()
            template = jeng.get_template("resinject.jinja")
            output = template.render(request=request)
            head, body = output.split("</head>", 1)
            assert "alert('xss')" in body  # the inline script
            assert '"bars": [1, 2, 3]' in head  # the script vars
            assert '(unknown resource type:' in body  # the png
            assert 'href="://example.com/css.css"' in head  # the css
            assert 'src="://example.com/js.js"' in body  # the js
            assert head.count(
                ResourceInjectorPlugin.meta_markup) == 1  # the duplicate meta
            assert ResourceInjectorPlugin.message in output  # the actual message
Beispiel #41
0
def test_theme_activation():
    shop = get_default_shop()
    with override_current_theme_class():
        with override_provides("xtheme", [
                "shuup_tests.xtheme.utils:FauxTheme",
                "shuup_tests.xtheme.utils:FauxTheme2"
        ]):
            ThemeSettings.objects.all().delete()
            # ThemeSettings will be created on the fly
            theme = get_current_theme(shop)
            assert theme
            assert theme.settings_obj
            set_current_theme(FauxTheme.identifier, shop)
            assert isinstance(get_current_theme(shop), FauxTheme)
            set_current_theme(FauxTheme2.identifier, shop)
            assert isinstance(get_current_theme(shop), FauxTheme2)
            with pytest.raises(ValueError):
                set_current_theme(printable_gibberish(), shop)
def test_theme_selection():
    """
    Test that a theme with a `template_dir` actually affects template directory selection.
    """
    with override_current_theme_class(), override_provides("xtheme", [
        "shuup_tests.xtheme.utils:FauxTheme",
        "shuup_tests.xtheme.utils:FauxTheme2",
        "shuup_tests.xtheme.utils:H2G2Theme",
    ]):
        ThemeSettings.objects.all().delete()
        for theme in get_provide_objects("xtheme"):
            set_current_theme(theme.identifier)
            je = get_jinja2_engine()
            wrapper = (noop() if theme.identifier == "h2g2" else pytest.raises(TemplateDoesNotExist))
            with wrapper:
                t = je.get_template("42.jinja")
                content = t.render().strip()
                assert "a slice of lemon wrapped around a large gold brick" in content.replace("\n", " ")
Beispiel #43
0
def test_product_detail(client):
    shop = factories.get_default_shop()
    product = factories.create_product("sku", shop=shop, default_price=30)
    shop_product = product.get_shop_instance(shop)

    # Activate show supplier info for front
    assert ThemeSettings.objects.count() == 1
    theme_settings = ThemeSettings.objects.first()
    theme_settings.update_settings({"show_supplier_info": True})

    supplier_data = [
        ("Johnny Inc", 30),
        ("Mike Inc", 20),
        ("Simon Inc", 10),
    ]
    for name, product_price in supplier_data:
        supplier = Supplier.objects.create(name=name)
        shop_product.suppliers.add(supplier)
        SupplierPrice.objects.create(supplier=supplier, shop=shop, product=product, amount_value=product_price)

    strategy = "shuup.testing.supplier_pricing.supplier_strategy:CheapestSupplierPriceSupplierStrategy"
    with override_settings(SHUUP_PRICING_MODULE="supplier_pricing", SHUUP_SHOP_PRODUCT_SUPPLIERS_STRATEGY=strategy):

        # Ok so cheapest price should be default supplier
        expected_supplier = shop_product.get_supplier()
        assert expected_supplier.name == "Simon Inc"
        with override_current_theme_class(ClassicGrayTheme, shop):  # Ensure settings is refreshed from DB
            soup = _get_product_detail_soup(client, product)

            _assert_supplier_subtitle(soup, expected_supplier)
            _assert_add_to_basket_form(soup, expected_supplier, 10)

            # Bonus! Let's say Johnny gets mad and starts to supply this product for 5 euros
            johnny_the_supplier = Supplier.objects.filter(name="Johnny Inc").first()
            SupplierPrice.objects.filter(
                supplier=johnny_the_supplier, shop=shop, product=product
            ).update(amount_value=5)

            # This means that product detail get new default supplier and new price
            assert shop_product.get_supplier() == johnny_the_supplier
            soup = _get_product_detail_soup(client, product)

            _assert_supplier_subtitle(soup, johnny_the_supplier)
            _assert_add_to_basket_form(soup, johnny_the_supplier, 5)
def test_theme_without_default_template_dir():
    with override_settings(
            CACHES={
                "default": {
                    "BACKEND": "django.core.cache.backends.locmem.LocMemCache",
                    "LOCATION": "test_configuration_cache",
                }
            }):
        cache.init_cache()

        with override_current_theme_class(ShuupTestingTheme,
                                          get_default_shop()):
            c = SmartClient()
            soup = c.soup(reverse("shuup:index"))
            assert "Simple base for themes to use" not in soup
            assert "Welcome to test Shuup!" in soup.find(
                "div", {
                    "class": "page-content"
                }).text
Beispiel #45
0
def test_templated_plugin():
    jeng = get_jinja2_engine()

    my_plugin_class = templated_plugin_factory(
        "MyPlugin",
        "templated_plugin.jinja",
        inherited_variables=("name", ),
        config_copied_variables=("greeting", ),
        engine=jeng)
    top_context = {
        "name": printable_gibberish(),
    }
    config = {"greeting": "Good day"}
    plugin = my_plugin_class(config=config)
    assert isinstance(plugin, TemplatedPlugin)
    with override_current_theme_class(None):
        rendered_content = plugin.render(top_context)
        expected_content = "Good day %s" % top_context["name"]
        assert rendered_content == expected_content
Beispiel #46
0
def test_xtheme_extra_views(rf):
    with override_settings(CACHES={
        'default': {
            'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
            'LOCATION': 'test_configuration_cache',
        }
    }):
        cache.init_cache()
        with override_current_theme_class(H2G2Theme, get_default_shop()):
            request = rf.get("/", {"name": "Arthur Dent"})
            request.shop = get_default_shop()
            # Simulate /xtheme/greeting
            response = extra_view_dispatch(request, "greeting")
            assert force_text(response.content) == "So long, and thanks for all the fish, Arthur Dent"
            # Try that again (to exercise the _VIEW_CACHE code path):
            response = extra_view_dispatch(request, "greeting")
            assert force_text(response.content) == "So long, and thanks for all the fish, Arthur Dent"
            # Now test that CBVs work
            assert not extra_view_dispatch(request, "faux").content
Beispiel #47
0
def test_supplier_product_detail(client):
    shop = factories.get_default_shop()
    product = factories.create_product("sku", shop=shop, default_price=30)
    shop_product = product.get_shop_instance(shop)

    # Activate show supplier info for front
    assert ThemeSettings.objects.count() == 1
    theme_settings = ThemeSettings.objects.first()
    theme_settings.update_settings({"show_supplier_info": True})

    supplier_data = [
        ("Johnny Inc", 30),
        ("Mike Inc", 20),
        ("Simon Inc", 10),
    ]
    for name, product_price in supplier_data:
        supplier = Supplier.objects.create(name=name)
        supplier.shops.add(shop)
        shop_product.suppliers.add(supplier)
        SupplierPrice.objects.create(supplier=supplier, shop=shop, product=product, amount_value=product_price)

    strategy = "shuup.testing.supplier_pricing.supplier_strategy:CheapestSupplierPriceSupplierStrategy"
    with override_settings(SHUUP_PRICING_MODULE="supplier_pricing", SHUUP_SHOP_PRODUCT_SUPPLIERS_STRATEGY=strategy):

        # Ok so cheapest price should be default supplier
        expected_supplier = shop_product.get_supplier()
        assert expected_supplier.name == "Simon Inc"
        with override_current_theme_class(ClassicGrayTheme, shop):  # Ensure settings is refreshed from DB
            johnny = Supplier.objects.filter(name="Johnny Inc").first()
            soup = _get_supplier_product_detail_soup(client, product, johnny)
            _assert_supplier_subtitle(soup, johnny)
            _assert_add_to_basket_form(soup, johnny, 30)

            mike = Supplier.objects.filter(name="Mike Inc").first()
            soup = _get_supplier_product_detail_soup(client, product, mike)
            _assert_supplier_subtitle(soup, mike)
            _assert_add_to_basket_form(soup, mike, 20)

            simon = Supplier.objects.filter(name="Simon Inc").first()
            soup = _get_supplier_product_detail_soup(client, product, simon)
            _assert_supplier_subtitle(soup, simon)
            _assert_add_to_basket_form(soup, simon, 10)
Beispiel #48
0
def test_templated_plugin():
    jeng = get_jinja2_engine()

    my_plugin_class = templated_plugin_factory("MyPlugin", "templated_plugin.jinja",
        inherited_variables=("name",),
        config_copied_variables=("greeting",),
        engine=jeng
    )
    top_context = {
        "name": printable_gibberish(),
    }
    config = {
        "greeting": "Good day"
    }
    plugin = my_plugin_class(config=config)
    assert isinstance(plugin, TemplatedPlugin)
    with override_current_theme_class(None):
        rendered_content = plugin.render(top_context)
        expected_content = "Good day %s" % top_context["name"]
        assert rendered_content == expected_content
Beispiel #49
0
def test_rendering(edit, injectable, theme_class, global_type):
    request = get_request(edit)
    with override_current_theme_class(theme_class):
        with plugin_override():
            jeng = get_jinja2_engine()
            if global_type:
                template = jeng.get_template("global_complex.jinja")
            else:
                template = jeng.get_template("complex.jinja")
            view = FauxView()
            view.xtheme_injection = bool(injectable)
            output = template.render(context={
                "view": view,
            }, request=request)
            assert "wider column" in output
            assert "less wide column" in output
            if edit and injectable and theme_class:
                assert "xt-ph-edit" in output
                assert "data-xt-placeholder-name" in output
                assert "data-xt-row" in output
                assert "data-xt-cell" in output
                assert "XthemeEditorConfig" in output
Beispiel #50
0
def test_rendering(edit, injectable, theme_class, global_type):
    request = get_request(edit)
    with override_current_theme_class(theme_class):
        with plugin_override():
            jeng = get_jinja2_engine()
            if global_type:
                template = jeng.get_template("global_complex.jinja")
            else:
                template = jeng.get_template("complex.jinja")
            view = FauxView()
            view.xtheme_injection = bool(injectable)
            output = template.render(context={
                "view": view,
            }, request=request)
            assert "wider column" in output
            assert "less wide column" in output
            if edit and injectable and theme_class:
                assert "xt-ph-edit" in output
                assert "data-xt-placeholder-name" in output
                assert "data-xt-row" in output
                assert "data-xt-cell" in output
                assert "XthemeEditorConfig" in output
def test_category_detail_filters(client):
    shop = factories.get_default_shop()

    # Activate show supplier info for front
    assert ThemeSettings.objects.count() == 1
    theme_settings = ThemeSettings.objects.first()
    theme_settings.update_settings({"show_supplier_info": True})

    category = factories.get_default_category()

    # Important! Activate supplier filter.
    set_configuration(
        shop=shop,
        data={
            "filter_products_by_supplier": True,
            "filter_products_by_supplier_ordering": 1,
        }
    )

    product_data = [
        ("laptop", 1500),
        ("keyboard", 150),
        ("mouse", 150)
    ]
    products = []
    for sku, price_value in product_data:
        products.append(factories.create_product(sku, shop=shop, default_price=price_value))

    supplier_data = [
        ("Johnny Inc", 0.5),
        ("Mike Inc", 0.9),
        ("Simon Inc", 0.8),
    ]
    for name, percentage_from_original_price in supplier_data:
        supplier = Supplier.objects.create(name=name)
        supplier.shops.add(shop)

        for product in products:
            shop_product = product.get_shop_instance(shop)
            shop_product.suppliers.add(supplier)
            shop_product.primary_category = category
            shop_product.categories.add(category)
            shop_product.save()

            supplier_price = (
                percentage_from_original_price * [price for sku, price in product_data if product.sku == sku][0])
            SupplierPrice.objects.create(supplier=supplier, shop=shop, product=product, amount_value=supplier_price)

    strategy = "shuup.testing.supplier_pricing.supplier_strategy:CheapestSupplierPriceSupplierStrategy"
    with override_settings(SHUUP_PRICING_MODULE="supplier_pricing", SHUUP_SHOP_PRODUCT_SUPPLIERS_STRATEGY=strategy):
        with override_current_theme_class(ClassicGrayTheme, shop):  # Ensure settings is refreshed from DB

            laptop = [product for product in products if product.sku == "laptop"][0]
            keyboard = [product for product in products if product.sku == "keyboard"][0]
            mouse = [product for product in products if product.sku == "mouse"][0]
            # Let's get products for Johnny
            supplier_johnny = Supplier.objects.filter(name="Johnny Inc").first()
            soup = _get_category_detail_soup(client, category, supplier_johnny.pk)

            laptop_product_box = soup.find("div", {"id": "product-%s" % laptop.pk})
            _assert_supplier_info(laptop_product_box, "Johnny Inc")
            _assert_product_price(laptop_product_box, 750)

            # Now here when the category view is filtered based on supplier
            # the product urls should lead to supplier product url so we
            # can show details and prices for correct supplier.
            _assert_product_url(laptop_product_box, supplier_johnny, laptop)

            # Let's test rest of the products and suppliers
            keyboard_product_box = soup.find("div", {"id": "product-%s" % keyboard.pk})
            _assert_supplier_info(keyboard_product_box, "Johnny Inc")
            _assert_product_price(keyboard_product_box, 75)
            _assert_product_url(keyboard_product_box, supplier_johnny, keyboard)

            mike_supplier = Supplier.objects.filter(name="Mike Inc").first()
            soup = _get_category_detail_soup(client, category, mike_supplier.pk)
            keyboard_product_box = soup.find("div", {"id": "product-%s" % keyboard.pk})
            _assert_supplier_info(keyboard_product_box, "Mike Inc")
            _assert_product_price(keyboard_product_box, 135)
            _assert_product_url(keyboard_product_box, mike_supplier, keyboard)

            simon_supplier = Supplier.objects.filter(name="Simon Inc").first()
            soup = _get_category_detail_soup(client, category, simon_supplier.pk)
            mouse_product_box = soup.find("div", {"id": "product-%s" % mouse.pk})
            _assert_supplier_info(mouse_product_box, "Simon Inc")
            _assert_product_price(mouse_product_box, 120)
            _assert_product_url(mouse_product_box, simon_supplier, mouse)
Beispiel #52
0
def test_parsing():
    with override_current_theme_class(None):
        jeng = get_jinja2_engine()
        template = jeng.get_template("complex.jinja")
        assert template  # it'sa me! template!
Beispiel #53
0
def test_order_flow_with_multiple_suppliers():
    cache.clear()

    shop = factories.get_default_shop()
    factories.create_default_order_statuses()
    factories.get_default_payment_method()
    factories.get_default_shipping_method()

    n_orders_pre = Order.objects.count()
    product = factories.create_product("sku", shop=shop, default_price=30)
    shop_product = product.get_shop_instance(shop)

    # Activate show supplier info for front
    assert ThemeSettings.objects.count() == 1
    theme_settings = ThemeSettings.objects.first()
    theme_settings.update_settings({"show_supplier_info": True})

    supplier_data = [
        ("Johnny Inc", 30),
        ("Mike Inc", 10),
        ("Simon Inc", 20),
    ]
    for name, product_price in supplier_data:
        supplier = Supplier.objects.create(name=name)
        shop_product.suppliers.add(supplier)
        SupplierPrice.objects.create(supplier=supplier, shop=shop, product=product, amount_value=product_price)

    strategy = "shuup.testing.supplier_pricing.supplier_strategy:CheapestSupplierPriceSupplierStrategy"
    with override_settings(SHUUP_PRICING_MODULE="supplier_pricing", SHUUP_SHOP_PRODUCT_SUPPLIERS_STRATEGY=strategy):

        # Ok so cheapest price should be default supplier
        expected_supplier = shop_product.get_supplier()
        assert expected_supplier.name == "Mike Inc"
        with override_current_theme_class(ClassicGrayTheme, shop):  # Ensure settings is refreshed from DB
            c = SmartClient()

            # Case 1: use default supplier
            _add_to_basket(c, product.pk, 2)
            order = _complete_checkout(c, n_orders_pre + 1)
            assert order
            product_lines = order.lines.products()
            assert len(product_lines) == 1
            assert product_lines[0].supplier.pk == expected_supplier.pk
            assert product_lines[0].base_unit_price_value == decimal.Decimal("10")

            # Case 2: force supplier to Johnny Inc
            johnny_supplier = Supplier.objects.filter(name="Johnny Inc").first()
            _add_to_basket(c, product.pk, 3, johnny_supplier)
            order = _complete_checkout(c, n_orders_pre + 2)
            assert order
            product_lines = order.lines.products()
            assert len(product_lines) == 1
            assert product_lines[0].supplier.pk == johnny_supplier.pk
            assert product_lines[0].base_unit_price_value == decimal.Decimal("30")

            # Case 3: order 2 pcs from Mike and 3 pcs from Simon Inc
            mike_supplier = Supplier.objects.filter(name="Mike Inc").first()
            _add_to_basket(c, product.pk, 2, mike_supplier)

            simon_supplier = Supplier.objects.filter(name="Simon Inc").first()
            _add_to_basket(c, product.pk, 3, simon_supplier)

            order = _complete_checkout(c, n_orders_pre + 3)
            assert order
            assert order.taxful_total_price_value == decimal.Decimal("80")  # Math: 2x10e + 3x20e

            product_lines = order.lines.products()
            assert len(product_lines) == 2

            mikes_line = [line for line in product_lines if line.supplier.pk == mike_supplier.pk][0]
            assert mikes_line
            assert mikes_line.quantity == 2
            assert mikes_line.base_unit_price_value == decimal.Decimal("10")

            simon_line = [line for line in product_lines if line.supplier.pk == simon_supplier.pk][0]
            assert simon_line
            assert simon_line.quantity == 3
            assert simon_line.base_unit_price_value == decimal.Decimal("20")
Beispiel #54
0
def test_xtheme_extra_view_exceptions(rf):
    with override_current_theme_class(H2G2Theme):
        request = rf.get("/")
        assert extra_view_dispatch(request, "vogons").status_code == 404
        with pytest.raises(ImproperlyConfigured):
            assert extra_view_dispatch(request, "true")