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
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
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
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
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)
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
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__()
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")
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
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
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
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={})
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"})
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()
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_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(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)
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)
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")
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
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"})
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_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
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)
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")
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
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)
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)
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)
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={})
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
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", " ")
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
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
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
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)
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
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_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)
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!
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")
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")