def test_product_descriptions(browser, live_server, settings): activate("en") cache.clear() shop = get_default_shop() product = create_product("product1", shop=shop, description="<b>My HTML description</b>", short_description="some short of description instead", supplier=get_default_supplier()) sp = ShopProduct.objects.get(product=product, shop=shop) sp.primary_category = get_default_category() sp.categories.add(get_default_category()) sp.save() # initialize test and go to front page browser = initialize_front_browser_test(browser, live_server) # view product detail page url = reverse("wshop:product", kwargs={"pk": product.pk, "slug": product.slug}) browser.visit("%s%s" % (live_server, url)) wait_until_condition(browser, lambda x: x.is_text_present(product.short_description)) assert product.description in browser.html # product preview url = reverse("wshop:xtheme_extra_view", kwargs={"view": "products"}) browser.visit("%s%s" % (live_server, url)) product_div_name = "product-{}".format(product.pk) wait_until_condition(browser, lambda x: x.find_by_css("#{} button.btn".format(product_div_name))) browser.execute_script("$('#{} button.btn').click();".format(product_div_name)) assert product.short_description == browser.find_by_css("#{} p.description".format(product_div_name))[0].html
def test_products_form_add_multiple_products(): shop = get_default_shop() category = get_default_category() category.shops.add(shop) product_ids = [] for x in range(0, 15): product = create_product("%s" % x, shop=shop) product_ids.append(product.id) for x in range(0, 5): product = create_product("parent_%s" % x, shop=shop, mode=ProductMode.SIMPLE_VARIATION_PARENT) for y in range(0, 3): child_product = create_product("child_%s_%s" % (x, y), shop=shop) child_product.link_to_parent(product) product_ids.append(product.id) assert (category.shop_products.count() == 0) data = { "additional_products": ["%s" % product_id for product_id in product_ids] } form = CategoryProductForm(shop=shop, category=category, data=data) form.full_clean() form.save() category.refresh_from_db() assert (category.shop_products.count() == 35 ) # 15 normal products and 5 parents with 3 children each
def test_mass_edit_products(rf, admin_user): shop = get_default_shop() supplier = get_default_supplier() product1 = create_product(printable_gibberish(), shop=shop, supplier=supplier, default_price="50") product2 = create_product(printable_gibberish(), shop=shop, supplier=supplier, default_price="501") category = get_default_category() shop_product1 = product1.get_shop_instance(shop) shop_product2 = product2.get_shop_instance(shop) # ensure no categories set assert shop_product1.primary_category is None assert shop_product2.primary_category is None request = apply_request_middleware(rf.post( "/", data={"primary_category": category.pk}), user=admin_user) request.session["mass_action_ids"] = [product1.pk, product2.pk] view = ProductMassEditView.as_view() response = view(request=request) assert response.status_code == 302 for product in Product.objects.all(): assert product.get_shop_instance(shop).primary_category == category
def test_category_create_with_parent(rf, admin_user): shop = get_default_shop() default_category = get_default_category() default_category.shops.clear() assert shop not in default_category.shops.all() with override_settings(LANGUAGES=[("en", "en")]): view = CategoryEditView.as_view() cat_name = "Random name" data = { "base-name__en": cat_name, "base-status": CategoryStatus.VISIBLE.value, "base-visibility": CategoryVisibility.VISIBLE_TO_ALL.value, "base-ordering": 1, "base-parent": default_category.pk } assert Category.objects.count() == 1 request = apply_request_middleware(rf.post("/", data=data), user=admin_user, shop=shop) response = view(request, pk=None) if hasattr(response, "render"): response.render() assert response.status_code in [200, 302] assert Category.objects.count() == 1 default_category.shops.add(shop) request = apply_request_middleware(rf.post("/", data=data), user=admin_user, shop=shop) response = view(request, pk=None) if hasattr(response, "render"): response.render() assert response.status_code in [200, 302] assert Category.objects.count() == 2
def test_category_links_plugin_with_customer(rf, show_all_categories): """ Test plugin for categories that is visible for certain group """ shop = get_default_shop() group = get_default_customer_group() customer = create_random_person() customer.groups.add(group) customer.save() request = rf.get("/") request.shop = get_default_shop() apply_request_middleware(request) request.customer = customer category = get_default_category() category.status = CategoryStatus.VISIBLE category.visibility = CategoryVisibility.VISIBLE_TO_GROUPS category.visibility_groups.add(group) category.shops.add(shop) category.save() vars = {"request": request} context = get_jinja_context(**vars) plugin = CategoryLinksPlugin({"categories": [category.pk], "show_all_categories": show_all_categories}) assert category.is_visible(customer) assert category in plugin.get_context_data(context)["categories"] customer_without_groups = create_random_person() customer_without_groups.groups.clear() assert not category.is_visible(customer_without_groups) request.customer = customer_without_groups context = get_jinja_context(**vars) assert category not in plugin.get_context_data(context)["categories"]
def test_category_filter(rf): request, shop, group = initialize_test(rf, False) cat = get_default_category() cat_filter = CategoryFilter.objects.create() cat_filter.categories.add(cat) cat_filter.save() assert cat_filter.values.first() == cat category = Category.objects.create( parent=None, identifier="testcat", name="catcat", ) cat_filter.values = [cat, category] cat_filter.save() assert cat_filter.values.count() == 2 product = create_product("Just-A-Product-Too", shop, default_price="200") shop_product = product.get_shop_instance(shop) shop_product.categories.add(cat) shop_product.save() assert cat_filter.filter_queryset(ShopProduct.objects.all()).exists() # filter matches
def test_products_form_remove(): shop = get_default_shop() category = get_default_category() category.shops.add(shop) product = create_product("test_product", shop=shop) shop_product = product.get_shop_instance(shop) shop_product.primary_category = category shop_product.save() shop_product.categories.add(category) shop_product.refresh_from_db() assert (shop_product.primary_category == category) assert (shop_product.categories.count() == 1) assert (shop_product.categories.first() == category) data = {"remove_products": ["%s" % shop_product.id]} form = CategoryProductForm(shop=shop, category=category, data=data) form.full_clean() form.save() category.refresh_from_db() assert (category.shop_products.count() == 0) shop_product.refresh_from_db() assert (shop_product.primary_category is None) assert (shop_product.categories.count() == 0)
def test_category_deletion(admin_user): admin = get_person_contact(admin_user) category = get_default_category() category.children.create(identifier="foo") shop_product = get_default_shop_product() shop_product.categories.add(category) shop_product.primary_category = category shop_product.save() configuration.set(None, get_all_seeing_key(admin), True) assert category.status == CategoryStatus.VISIBLE assert category.children.count() == 1 with pytest.raises(NotImplementedError): category.delete() category.soft_delete() shop_product.refresh_from_db() shop_product.product.refresh_from_db() assert shop_product.categories.count() == 0 assert shop_product.primary_category is None assert category.status == CategoryStatus.DELETED assert category.children.count() == 0 # the child category still exists assert Category.objects.all_visible(customer=admin).count() == 1 assert Category.objects.all_except_deleted().count() == 1 configuration.set(None, get_all_seeing_key(admin), False)
def test_recently_viewed_products(browser, live_server, settings): shop = get_default_shop() category = get_default_category() category.shops.add(shop) category.status = CategoryStatus.VISIBLE category.save() category_url = reverse("wshop:category", kwargs={ "pk": category.pk, "slug": category.slug }) products = [] for i in range(1, 7): products.append(new_product(i, shop, category)) browser = initialize_front_browser_test(browser, live_server) for i, product in enumerate(products, 1): product_url = reverse("wshop:product", kwargs={ "pk": product.pk, "slug": product.slug }) browser.visit(live_server + product_url) wait_until_appeared(browser, ".product-main") browser.visit(live_server + category_url) wait_until_appeared(browser, ".categories-nav") items = browser.find_by_css(".recently-viewed li") assert items.first.text == product.name, "recently clicked product on top" assert len(items) == min(i, 5)
def test_shopproduct_primary_category_removal(): product = get_product() category = get_default_category() sp = product.get_shop_instance(get_default_shop()) sp.primary_category = category sp.save() with pytest.raises(NotImplementedError): category.delete() assert ShopProduct.objects.filter(pk=sp.pk).exists()
def test_category_products_effect_with_amount(rf): request, shop, group = initialize_test(rf, False) basket = get_basket(request) category = get_default_category() supplier = get_default_supplier() single_product_price = "50" discount_amount_value = "10" quantity = 5 product = create_product("The product", shop=shop, supplier=supplier, default_price=single_product_price) shop_product = product.get_shop_instance(shop) shop_product.categories.add(category) basket.add_product(supplier=supplier, shop=shop, product=product, quantity=quantity) basket.shipping_method = get_shipping_method(shop=shop) basket.save() rule = CategoryProductsBasketCondition.objects.create( operator=ComparisonOperator.EQUALS, quantity=quantity) rule.categories.add(category) campaign = BasketCampaign.objects.create(active=True, shop=shop, name="test", public_name="test") campaign.conditions.add(rule) DiscountFromCategoryProducts.objects.create( campaign=campaign, category=category, discount_amount=discount_amount_value) assert rule.matches(basket, []) basket.uncache() final_lines = basket.get_final_lines() assert len(final_lines ) == 2 # no new lines since the effect touches original lines expected_discount_amount = quantity * basket.create_price( discount_amount_value) original_price = basket.create_price(single_product_price) * quantity line = final_lines[0] assert line.discount_amount == expected_discount_amount assert basket.total_price == original_price - expected_discount_amount
def _get_shop_product_sample_data(): return { "shop": get_default_shop().id, "suppliers": [get_default_supplier().id], "visibility": ShopProductVisibility.ALWAYS_VISIBLE.value, "purchasable": False, "visibility_limit": ProductVisibility.VISIBLE_TO_ALL.value, "visibility_groups": [ create_random_contact_group().id, create_random_contact_group().id, ], "backorder_maximum": 0, "purchase_multiple": 1, "minimum_purchase_quantity": 1, "limit_shipping_methods": False, "limit_payment_methods": False, "shipping_methods": [], "payment_methods": [], "primary_category": get_default_category().id, "categories": [get_default_category().id, CategoryFactory().id], "default_price_value": 12.45, "minimum_price_value": 5.35 }
def test_slide_links(): test_carousel = Carousel.objects.create(name="test") test_image_1 = Image.objects.create(original_filename="slide1.jpg") with translation.override("en"): test_slide = Slide.objects.create(carousel=test_carousel, name="test", image=test_image_1) # Test external link assert len(test_carousel.slides.all()) == 1 test_link = "http://example.com" test_slide.external_link = test_link test_slide.save() assert test_slide.get_translated_field("external_link") == test_link assert test_slide.get_link_url() == test_link # Test Product url and link priorities test_product = get_default_product() test_slide.product_link = test_product test_slide.save() assert test_slide.get_link_url() == test_link test_slide.external_link = None test_slide.save() assert test_slide.get_link_url().startswith("/p/") # Close enough... # Test Category url and link priorities test_category = get_default_category() test_slide.category_link = test_category test_slide.save() assert test_slide.get_link_url().startswith("/p/") # Close enough... test_slide.product_link = None test_slide.save() assert test_slide.get_link_url().startswith("/c/") # Close enough... # Test CMS page url and link priorities attrs = {"url": "test", "shop": get_default_shop()} test_page = create_page(**attrs) test_slide.cms_page_link = test_page test_slide.save() assert test_slide.get_link_url().startswith("/c/") # Close enough... test_slide.category_link = None test_slide.save() assert test_slide.get_link_url().startswith("/test/") # Check that external link overrides everything test_slide.external_link = test_link test_slide.save() assert test_slide.get_link_url() == test_link
def test_category_links_plugin_show_all(rf): """ Test that show_all_categories forces plugin to return all visible categories """ category = get_default_category() category.status = CategoryStatus.VISIBLE category.shops.add(get_default_shop()) category.save() context = get_context(rf) plugin = CategoryLinksPlugin({"show_all_categories": False}) assert context["request"].customer.is_anonymous assert context["request"].shop in category.shops.all() assert not plugin.get_context_data(context)["categories"] plugin = CategoryLinksPlugin({"show_all_categories": True}) assert category in plugin.get_context_data(context)["categories"]
def test_products_form_update_default_category(): shop = get_default_shop() category = get_default_category() category.shops.add(shop) product = create_product("test_product", shop=shop) shop_product = product.get_shop_instance(shop) assert (category not in shop_product.categories.all()) data = { "primary_products": ["%s" % product.id], "update_product_category": True } form = CategoryProductForm(shop=shop, category=category, data=data) form.full_clean() form.save() shop_product.refresh_from_db() product.refresh_from_db() assert (shop_product.primary_category == category) assert (category in shop_product.categories.all())
def _get_order(prices_include_tax=False, include_basket_campaign=False, include_catalog_campaign=False): shop = get_shop(prices_include_tax=prices_include_tax) supplier = get_simple_supplier() if include_basket_campaign: _add_basket_campaign(shop) if include_catalog_campaign: _add_catalog_campaign(shop) _add_taxes() source = BasketishOrderSource(shop) source.status = get_initial_order_status() ctx = get_pricing_module().get_context_from_data(shop, AnonymousContact()) for product_data in _get_product_data(): quantity = product_data.pop("quantity") product = create_product( sku=product_data.pop("sku"), shop=shop, supplier=supplier, stock_behavior=StockBehavior.STOCKED, tax_class=get_default_tax_class(), **product_data) shop_product = product.get_shop_instance(shop) shop_product.categories.add(get_default_category()) shop_product.save() supplier.adjust_stock(product.id, INITIAL_PRODUCT_QUANTITY) pi = product.get_price_info(ctx) source.add_line( type=OrderLineType.PRODUCT, product=product, supplier=supplier, quantity=quantity, base_unit_price=pi.base_unit_price, discount_amount=pi.discount_amount ) oc = OrderCreator() order = oc.create_order(source) order.create_payment(Money("1", "EUR")) assert not order.has_refunds() assert order.can_create_refund() assert order.shipping_status == ShippingStatus.NOT_SHIPPED assert order.payment_status == PaymentStatus.PARTIALLY_PAID return order
def _get_custom_order(regular_user, **kwargs): prices_include_tax = kwargs.pop("prices_include_tax", False) include_basket_campaign = kwargs.pop("include_basket_campaign", False) include_catalog_campaign = kwargs.pop("include_catalog_campaign", False) shop = get_shop(prices_include_tax=prices_include_tax) supplier = get_simple_supplier() if include_basket_campaign: _add_basket_campaign(shop) if include_catalog_campaign: _add_catalog_campaign(shop) _add_taxes() contact = get_person_contact(regular_user) source = BasketishOrderSource(shop) source.status = get_initial_order_status() source.customer = contact ctx = get_pricing_module().get_context_from_data(shop, contact) for product_data in _get_product_data(): quantity = product_data.pop("quantity") product = create_product(sku=product_data.pop("sku"), shop=shop, supplier=supplier, stock_behavior=StockBehavior.STOCKED, tax_class=get_default_tax_class(), **product_data) shop_product = product.get_shop_instance(shop) shop_product.categories.add(get_default_category()) shop_product.save() supplier.adjust_stock(product.id, INITIAL_PRODUCT_QUANTITY) pi = product.get_price_info(ctx) source.add_line(type=OrderLineType.PRODUCT, product=product, supplier=supplier, quantity=quantity, base_unit_price=pi.base_unit_price, discount_amount=pi.discount_amount) oc = OrderCreator() order = oc.create_order(source) return order
def test_category_links_plugin(rf): """ Test that the plugin only displays visible categories with shop (since we can't have a request without shop or customer) """ category = get_default_category() category.shops.clear() context = get_context(rf) plugin = CategoryLinksPlugin({"show_all_categories": True}) assert context["request"].customer.is_anonymous assert category not in plugin.get_context_data(context)["categories"] category.status = CategoryStatus.VISIBLE category.shops.add(get_default_shop()) category.save() assert context["request"].customer.is_anonymous assert context["request"].shop in category.shops.all() assert category in plugin.get_context_data(context)["categories"]
def test_products_form_add(): shop = get_default_shop() category = get_default_category() category.visibility = CategoryVisibility.VISIBLE_TO_LOGGED_IN category.status = CategoryStatus.INVISIBLE category.shops.add(shop) category.save() product = create_product("test_product", shop=shop) shop_product = product.get_shop_instance(shop) assert (category not in shop_product.categories.all()) data = {"primary_products": ["%s" % product.id]} form = CategoryProductForm(shop=shop, category=category, data=data) form.full_clean() form.save() shop_product.refresh_from_db() product.refresh_from_db(()) assert (shop_product.primary_category == category) assert (category in shop_product.categories.all()) assert (shop_product.visibility_limit.value == category.visibility.value) assert (shop_product.visibility == ShopProductVisibility.NOT_VISIBLE)
def test_generate_slugs_for_category(): activate("en") category = get_default_category() assert category.slug == slugify(category.name) default_slug = category.slug # Test that slug is only generated when it's empty on save new_name = "Some new cat name" category.name = new_name category.save() assert category.slug == default_slug, "Old slug" category.slug = "" category.save() assert category.slug == slugify(new_name), "New slug generated" # Check that slug is not generated to other languages with pytest.raises(ObjectDoesNotExist): translation = category.get_translation("fi") translation.refresh_from_db( ) # If the translation object was returned from cache
def test_category_product_in_basket_condition(rf): request, shop, group = initialize_test(rf, False) basket = get_basket(request) supplier = get_default_supplier() category = get_default_category() product = create_product("The Product", shop=shop, default_price="200", supplier=supplier) basket.add_product(supplier=supplier, shop=shop, product=product, quantity=1) basket.shipping_method = get_shipping_method(shop=shop) shop_product = product.get_shop_instance(shop) assert category not in shop_product.categories.all() condition = CategoryProductsBasketCondition.objects.create( operator=ComparisonOperator.EQUALS, quantity=1) condition.categories.add(category) # No match the product does not have the category assert not condition.matches(basket, []) shop_product.categories.add(category) assert condition.matches(basket, []) basket.add_product(supplier=supplier, shop=shop, product=product, quantity=1) assert not condition.matches(basket, []) condition.operator = ComparisonOperator.GTE condition.save() assert condition.matches(basket, []) condition.excluded_categories.add(category) assert not condition.matches(basket, [])
def test_sorts_and_filter_in_category_edit(rf, admin_user): get_default_shop() cache.clear() activate("en") with override_settings(WSHOP_ENABLE_MULTIPLE_SHOPS=False): with override_provides("front_extend_product_list_form", DEFAULT_FORM_MODIFIERS): category = get_default_category() view = CategoryEditView.as_view() assert get_configuration( category=category ) == settings.WSHOP_FRONT_DEFAULT_SORT_CONFIGURATION data = { "base-name__en": category.name, "base-status": category.status.value, "base-visibility": category.visibility.value, "base-ordering": category.ordering, "product_list_facets-sort_products_by_name": True, "product_list_facets-sort_products_by_name_ordering": 6, "product_list_facets-sort_products_by_price": False, "product_list_facets-sort_products_by_price_ordering": 32, "product_list_facets-filter_products_by_manufacturer": True, "product_list_facets-filter_products_by_manufacturer_ordering": 1 } request = apply_request_middleware(rf.post("/", data=data), user=admin_user) response = view(request, pk=category.pk) if hasattr(response, "render"): response.render() assert response.status_code in [200, 302] expected_configurations = { "sort_products_by_name": True, "sort_products_by_name_ordering": 6, "sort_products_by_price": False, "sort_products_by_price_ordering": 32, "filter_products_by_manufacturer": True, "filter_products_by_manufacturer_ordering": 1 } assert get_configuration( category=category) == expected_configurations
def test_slug_is_generate_from_translation(): activate("en") category = get_default_category() assert category.slug == slugify(category.name) default_slug = category.slug activate("fi") category.set_current_language("fi") name_fi = "Joku nimi" category.name = name_fi category.save() assert category.slug == slugify(name_fi) # Make sure english still have default slug activate("en") category.set_current_language("en") assert category.slug == default_slug # Make sure Japanese does not have translations generated # Check that slug is not generated to other languages with pytest.raises(ObjectDoesNotExist): translation = category.get_translation("ja") translation.refresh_from_db( ) # If the translation object was returned from cache
def test_products_form_remove_with_parent(): shop = get_default_shop() category = get_default_category() category.shops.add(shop) product = create_product("test_product", shop=shop, mode=ProductMode.SIMPLE_VARIATION_PARENT) shop_product = product.get_shop_instance(shop) shop_product.primary_category = category shop_product.save() shop_product.categories.add(category) child_product = create_product("child_product", shop=shop) child_product.link_to_parent(product) child_shop_product = child_product.get_shop_instance(shop) child_shop_product.primary_category = category child_shop_product.save() child_shop_product.categories.add(category) shop_product.refresh_from_db() assert (shop_product.primary_category == category) assert (shop_product.categories.count() == 1) assert (shop_product.categories.first() == category) assert (category.shop_products.count() == 2) data = {"remove_products": ["%s" % shop_product.id]} form = CategoryProductForm(shop=shop, category=category, data=data) form.full_clean() form.save() category.refresh_from_db() assert (category.shop_products.count() == 0) shop_product.refresh_from_db() assert (shop_product.primary_category is None) assert (shop_product.categories.count() == 0)
def test_category_copy_visibility(rf, admin_user): shop = get_default_shop() group = get_default_customer_group() category = get_default_category() category.status = CategoryStatus.INVISIBLE category.visibility = CategoryVisibility.VISIBLE_TO_GROUPS category.shops.add(shop) category.visibility_groups.add(group) category.save() product = create_product("test_product", shop=shop) shop_product = product.get_shop_instance(shop) shop_product.primary_category = category shop_product.save() view = CategoryCopyVisibilityView.as_view() request = apply_request_middleware(rf.post("/"), user=admin_user) response = view(request, pk=category.pk) shop_product.refresh_from_db() assert response.status_code == 200 assert shop_product.visibility == ShopProductVisibility.NOT_VISIBLE assert shop_product.visibility_limit.value == category.visibility.value assert shop_product.visibility_groups.count( ) == category.visibility_groups.count() assert set(shop_product.visibility_groups.all()) == set( category.visibility_groups.all())
def _add_catalog_campaign(shop): campaign = CatalogCampaign.objects.create(shop=shop, name="test", public_name="test", active=True) category_filter = CategoryFilter.objects.create() category_filter.categories.add(get_default_category()) category_filter.save() ProductDiscountAmount.objects.create(campaign=campaign, discount_amount=5)
def test_multiple_campaigns_cheapest_price(rf): request, shop, group = initialize_test(rf, False) price = shop.create_price product_price = "100" discount_percentage = "0.30" discount_amount_value = "10" total_discount_amount = "50" expected_total = price(product_price) - (Decimal(discount_percentage) * price(product_price)) matching_expected_total = price(product_price) - price(total_discount_amount) category = get_default_category() supplier = get_default_supplier() product = create_product(printable_gibberish(), shop=shop, supplier=supplier, default_price=product_price) shop_product = product.get_shop_instance(shop) shop_product.categories.add(category) # create catalog campaign catalog_filter = ProductFilter.objects.create() catalog_filter.products.add(product) catalog_campaign = CatalogCampaign.objects.create(shop=shop, active=True, name="test") catalog_campaign.filters.add(catalog_filter) cdp = ProductDiscountPercentage.objects.create(campaign=catalog_campaign, discount_percentage=discount_percentage) # create basket campaign condition = CategoryProductsBasketCondition.objects.create(operator=ComparisonOperator.EQUALS, quantity=1) condition.categories.add(category) basket_campaign = BasketCampaign.objects.create(shop=shop, public_name="test", name="test", active=True) basket_campaign.conditions.add(condition) effect = DiscountFromProduct.objects.create(campaign=basket_campaign, discount_amount=discount_amount_value) effect.products.add(product) # add product to basket basket = get_basket(request) basket.add_product(supplier=supplier, shop=shop, product=product, quantity=1) basket.shipping_method = get_shipping_method(shop=shop) final_lines = basket.get_final_lines() assert len(final_lines) == 2 assert basket.total_price == expected_total effect.discount_amount = total_discount_amount effect.save() basket.uncache() catalog_campaign.save() # save to bump caches basket_campaign.save() # save to bump caches assert basket.total_price == matching_expected_total # discount is now bigger than the original effect.delete() # remove effect basket.uncache() catalog_campaign.save() # save to bump caches basket_campaign.save() # save to bump caches assert BasketLineEffect.objects.count() == 0 assert basket.total_price == expected_total # add new effect effect = DiscountFromCategoryProducts.objects.create(category=category, campaign=basket_campaign, discount_amount=discount_amount_value) assert basket.total_price == expected_total effect.discount_amount = total_discount_amount effect.save() basket.uncache() catalog_campaign.save() # save to bump caches basket_campaign.save() # save to bump caches assert basket.total_price == matching_expected_total # discount is now bigger than the original