def test_single_page_checkout_with_login_and_register(browser, live_server, settings): cache.clear() # Avoid caches from past tests # initialize product_name = "Test Product" get_default_shop() get_default_payment_method() get_default_shipping_method() product = create_orderable_product(product_name, "test-123", price=100) OrderStatus.objects.create(identifier="initial", role=OrderStatusRole.INITIAL, name="initial", default=True) # Initialize test and go to front page browser = initialize_front_browser_test(browser, live_server) wait_until_condition(browser, lambda x: x.is_text_present("Welcome to Default!")) navigate_to_checkout(browser, product) # Let's assume that after addresses the checkout is normal wait_until_condition(browser, lambda x: x.is_text_present("Checkout Method")) test_username = "******" test_email = "*****@*****.**" test_password = "******" register_test(browser, live_server, test_username, test_email, test_password) login_and_finish_up_the_checkout(browser, live_server, test_username, test_email, test_password)
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_category_product_filters_1(browser, live_server, settings): cache.clear() # Avoid cache from past tests shop, first_cat, second_cat, third_cat, first_manufacturer = initialize_db( ) # initialize test and go to front page browser = initialize_front_browser_test(browser, live_server) # check that front page actually loaded wait_until_condition(browser, lambda x: x.is_text_present("Welcome to Default!")) url = reverse("wshop:category", kwargs={ "pk": first_cat.pk, "slug": first_cat.slug }) browser.visit("%s%s" % (live_server, url)) wait_until_condition(browser, lambda x: x.is_text_present("First Category")) wait_until_condition(browser, lambda x: x.is_text_present("Sort")) assert not browser.is_text_present( "Manufacturers") # Since not in default configuration hide_sorts_for_shop(browser, shop) show_sorts_for_the_category_only(browser, first_cat) second_category_page_change(browser, live_server, shop, second_cat)
def test_get_best_selling_products(): context = get_jinja_context() cache.clear() # No products sold assert len(list(general.get_best_selling_products(context, n_products=2))) == 0 supplier = get_default_supplier() shop = get_default_shop() product = get_default_product() create_order_with_product(product, supplier, quantity=1, taxless_base_unit_price=10, shop=shop) cache.clear() # One product sold assert len(list(general.get_best_selling_products(context, n_products=2))) == 1 # Make order unorderable shop_product = product.get_shop_instance(shop) shop_product.visibility = ShopProductVisibility.NOT_VISIBLE shop_product.save() assert len(list(general.get_best_selling_products(context, n_products=2))) == 0
def test_simple_search_word_finder(rf): cache.clear() view = SearchView.as_view() name = "Savage Garden" sku = UNLIKELY_STRING prod = create_product( sku=sku, name=name, keywords="truly, madly, deeply", description="Descriptive text", shop=get_default_shop() ) resp = view(apply_request_middleware(rf.get("/"))) assert prod not in resp.context_data["object_list"], "No query no results" partial_sku = sku[:int(len(sku)/2)] valid_searches = ["Savage", "savage", "truly", "madly", "truly madly", "truly garden", "text", sku, partial_sku] for query in valid_searches: resp = view(apply_request_middleware(rf.get("/", {"q": query}))) assert name in resp.rendered_content invalid_searches = ["saavage", "", sku[::-1]] for query in invalid_searches: resp = view(apply_request_middleware(rf.get("/", {"q": query}))) assert name not in resp.rendered_content
def test_basic_order_flow(with_company): cache.clear() create_default_order_statuses() n_orders_pre = Order.objects.count() populate_if_required() c = SmartClient() product_ids = _populate_client_basket(c) addresses_path = reverse("wshop:checkout", kwargs={"phase": "addresses"}) addresses_soup = c.soup(addresses_path) inputs = fill_address_inputs(addresses_soup, with_company=with_company) response = c.post(addresses_path, data=inputs) assert response.status_code == 302 # Should redirect forth methods_path = reverse("wshop:checkout", kwargs={"phase": "methods"}) methods_soup = c.soup(methods_path) assert c.post(methods_path, data=extract_form_fields( methods_soup)).status_code == 302 # Should redirect forth confirm_path = reverse("wshop:checkout", kwargs={"phase": "confirm"}) confirm_soup = c.soup(confirm_path) Product.objects.get(pk=product_ids[0]).soft_delete() assert c.post(confirm_path, data=extract_form_fields( confirm_soup)).status_code == 200 # user needs to reconfirm data = extract_form_fields(confirm_soup) data['product_ids'] = ','.join(product_ids[1:]) assert c.post(confirm_path, data=data).status_code == 302 # Should redirect forth n_orders_post = Order.objects.count() assert n_orders_post > n_orders_pre, "order was created"
def test_simple_search_get_ids_works(rf): cache.clear() prod = get_default_product() bit = prod.name[:5] request = apply_request_middleware(rf.get("/")) assert prod.pk in get_search_product_ids(request, bit) assert prod.pk in get_search_product_ids(request, bit) # Should use cache
def test_category_product_filters_2(browser, live_server, settings): cache.clear() # Avoid cache from past tests shop, first_cat, second_cat, third_cat, first_manufacturer = initialize_db( ) # Activate limit page size changer for the shop set_configuration(shop=shop, data={ "sort_products_by_name": True, "sort_products_by_name_ordering": 1, "sort_products_by_price": True, "sort_products_by_price_ordering": 2, "limit_product_list_page_size": True }) # initialize test and go to front page browser = initialize_front_browser_test(browser, live_server) # check that front page actually loaded wait_until_condition(browser, lambda x: x.is_text_present("Welcome to Default!")) url = reverse("wshop:category", kwargs={ "pk": first_cat.pk, "slug": first_cat.slug }) browser.visit("%s%s" % (live_server, url)) wait_until_condition(browser, lambda x: x.is_text_present("First Category")) wait_until_condition(browser, lambda x: x.is_text_present("Sort")) assert not browser.is_text_present( "Manufacturers") # Since not in default configuration second_category_sort_test(browser, live_server, shop, second_cat) second_category_sort_with_price_filter(browser, second_cat)
def initialize_db(): activate("en") # initialize cache.clear() shop = get_default_shop() for name, identifier in CATEGORY_DATA: category = Category() category.name = name category.identifier = identifier category.status = CategoryStatus.VISIBLE category.save() category.shops.add(shop) for name, identifier in MANUFACTURER_DATA: Manufacturer.objects.create(name=name, identifier=identifier) first_cat = Category.objects.filter(identifier="cat-1").first() second_cat = Category.objects.filter(identifier="cat-2").first() third_cat = Category.objects.filter(identifier="cat-3").first() assert first_cat.pk != second_cat.pk for name, sku, price in FIRST_CATEGORY_PRODUCT_DATA: product = create_orderable_product(name, sku, price=price) shop_product = product.get_shop_instance(shop) cat = Category.objects.first() shop_product.primary_category = first_cat shop_product.save() shop_product.categories.add(first_cat) # Add some variation products add_variations(shop, Product.objects.filter(sku="test-sku-1").first(), ["Black", "Yellow"], ["Big", "Small"]) add_variations(shop, Product.objects.filter(sku="test-sku-2").first(), ["Brown", "Pink"], ["S", "L", "XL"]) add_variations(shop, Product.objects.filter(sku="test-sku-3").first(), ["Brown", "Black"], ["S", "L", "XL", "Big"]) for i in range(1, 14): product = create_orderable_product("Test product", "sku-%s" % i, price=i) shop_product = product.get_shop_instance(shop) cat = Category.objects.first() shop_product.primary_category = second_cat shop_product.save() shop_product.categories.add(second_cat) # Set manufacturer for first product only first_manufacturer = Manufacturer.objects.first() Product.objects.filter(sku="test-sku-1").update( manufacturer_id=first_manufacturer.id) return shop, first_cat, second_cat, third_cat, first_manufacturer
def test_simple_search_no_results(rf): cache.clear() with translation.override("xx"): # use built-in translation get_default_shop() view = SearchView.as_view() resp = view(apply_request_middleware(rf.get("/", {"q": UNLIKELY_STRING}))) assert NO_RESULTS_FOUND_STRING in resp.rendered_content resp = view(apply_request_middleware(rf.get("/"))) assert NO_RESULTS_FOUND_STRING in resp.rendered_content, "No query string no results"
def test_basic_order_flow_registered(regular_user): cache.clear() create_default_order_statuses() n_orders_pre = Order.objects.count() populate_if_required() get_test_script("test script", "order_received") # paths addresses_path = reverse("wshop:checkout", kwargs={"phase": "addresses"}) methods_path = reverse("wshop:checkout", kwargs={"phase": "methods"}) confirm_path = reverse("wshop:checkout", kwargs={"phase": "confirm"}) template_data = STEP_DATA[0]["actions"][0]["template_data"] LANG_CODE = {"en": "US", "fi": "FI"} for lang in ["en", "fi"]: n_outbox_pre = len(mail.outbox) contact = get_person_contact(regular_user) contact.language = lang contact.save() c = SmartClient() c.login(username=REGULAR_USER_USERNAME, password=REGULAR_USER_PASSWORD) product_ids = _populate_client_basket(c) addresses_soup = c.soup(addresses_path) address = get_address(country=LANG_CODE[lang]) inputs = fill_address_inputs(addresses_soup, address) response = c.post(addresses_path, data=inputs) assert response.status_code == 302 # Should redirect forth methods_soup = c.soup(methods_path) assert c.post(methods_path, data=extract_form_fields( methods_soup)).status_code == 302 # Should redirect forth confirm_soup = c.soup(confirm_path) Product.objects.get(pk=product_ids[0]).soft_delete() assert c.post(confirm_path, data=extract_form_fields( confirm_soup)).status_code == 200 # user needs to reconfirm data = extract_form_fields(confirm_soup) data['product_ids'] = ','.join(product_ids[1:]) assert c.post(confirm_path, data=data).status_code == 302 # Should redirect forth n_orders_post = Order.objects.count() assert n_orders_post > n_orders_pre, "order was created" assert (len(mail.outbox) == n_outbox_pre + 1), "Sending email failed" latest_mail = mail.outbox[-1] # mail is always sent in fallback language since user is not registered assert latest_mail.subject == template_data[lang][ "subject"], "Subject doesn't match" assert latest_mail.body == template_data[lang][ "body"], "Body doesn't match"
def test_normalize_spaces(rf): cache.clear() view = SearchView.as_view() create_product(sku=UNLIKELY_STRING, name="Savage Garden", shop=get_default_shop()) query = "\t Savage \t \t \n \r Garden \n" resp = view(apply_request_middleware(rf.get("/"))) assert query not in resp.rendered_content resp = view(apply_request_middleware(rf.get("/", {"q": query}))) assert query in resp.rendered_content
def test_simple_search_view_works(rf): cache.clear() view = SearchView.as_view() prod = create_product(sku=UNLIKELY_STRING, shop=get_default_shop()) query = prod.name[:8] # This test is pretty cruddy. TODO: Un-cruddify this test. resp = view(apply_request_middleware(rf.get("/"))) assert query not in resp.rendered_content resp = view(apply_request_middleware(rf.get("/", {"q": query}))) assert query in resp.rendered_content
def test_product_searchability(rf, visibility, show_in_search): cache.clear() view = SearchView.as_view() name = "Savage Garden" sku = UNLIKELY_STRING shop = get_default_shop() product = create_product(sku, name=name, shop=shop) shop_product = product.get_shop_instance(shop) shop_product.visibility = visibility shop_product.save() resp = view(apply_request_middleware(rf.get("/", {"q": "savage"}))) assert (name in resp.rendered_content) == show_in_search
def test_simple_search_with_non_public_products(rf): cache.clear() shop = get_default_shop() name = "Some Test Name For Product" product = create_product("sku", name=name, shop=shop) shop_product = product.get_shop_instance(shop) shop_product.visibility = ShopProductVisibility.SEARCHABLE shop_product.visibility_limit = ProductVisibility.VISIBLE_TO_LOGGED_IN shop_product.save() view = SearchView.as_view() request = apply_request_middleware(rf.get("/", {"q": "Test name"})) request.customer = create_random_person() resp = view(request) assert bool(name in resp.rendered_content)
def test_checkout_empty_basket(rf): cache.clear() create_default_order_statuses() n_orders_pre = Order.objects.count() populate_if_required() c = SmartClient() product_ids = _populate_client_basket(c) addresses_path = reverse("wshop:checkout", kwargs={"phase": "addresses"}) addresses_soup = c.soup(addresses_path) inputs = fill_address_inputs(addresses_soup) for product_id in product_ids: Product.objects.get(pk=product_id).soft_delete() response, soup = c.response_and_soup(addresses_path, data=inputs, method="post") assert response.status_code == 200 # Should redirect forth assert b"Your shopping cart is empty." in soup.renderContents()
def test_sorts_and_filter_in_shop_edit(rf, admin_user): cache.clear() activate("en") with override_settings(WSHOP_ENABLE_MULTIPLE_SHOPS=False): with override_provides("front_extend_product_list_form", DEFAULT_FORM_MODIFIERS): shop = get_default_shop() view = ShopEditView.as_view() assert get_configuration( shop=shop) == settings.WSHOP_FRONT_DEFAULT_SORT_CONFIGURATION data = { "base-name__en": shop.name, "base-public_name__en": shop.public_name, "base-status": shop.status.value, "base-currency": shop.currency, "base-prices_include_tax": shop.prices_include_tax, "base-languages": "en", "order_configuration-order_min_total": 0, "order_configuration-order_reference_number_length": 18, "product_list_facets-sort_products_by_name": True, "product_list_facets-sort_products_by_name_ordering": 11, "product_list_facets-sort_products_by_price": False, "product_list_facets-sort_products_by_price_ordering": 32, "product_list_facets-filter_products_by_manufacturer": False, "product_list_facets-filter_products_by_manufacturer_ordering": 1, } request = apply_request_middleware(rf.post("/", data=data), user=admin_user) response = view(request, pk=shop.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": 11, "sort_products_by_price": False, "sort_products_by_price_ordering": 32, "filter_products_by_manufacturer": False, "filter_products_by_manufacturer_ordering": 1 } assert get_configuration(shop=shop) == expected_configurations
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_coupon(browser, live_server, settings): activate("en") # initialize cache.clear() shop = get_default_shop() get_default_payment_method() get_default_shipping_method() first_category = Category.objects.create(identifier="cat-1", status=CategoryStatus.VISIBLE, name="First Category") first_category.shops.add(shop) _populate_products_form_data(CATEGORY_PRODUCT_DATA, shop, first_category) # initialize test and go to front page browser = initialize_front_browser_test(browser, live_server) _add_product_to_basket_from_category(live_server, browser, first_category, shop) _activate_basket_campaign_through_coupon(browser, first_category, shop)
def test_search_product_list(browser, live_server, settings): activate("en") # initialize cache.clear() shop = get_default_shop() for name, sku, price in PRODUCT_DATA: create_orderable_product(name, sku, price=price) # initialize test and go to front page browser = initialize_front_browser_test(browser, live_server) # check that front page actually loaded wait_until_condition(browser, lambda x: x.is_text_present("Welcome to Default!")) url = reverse("wshop:product_search") browser.visit("%s%s?q=test product" % (live_server, url)) wait_until_condition(browser, lambda x: len(x.find_by_css(".product-card")) == 9) check_default_ordering(browser) # basic_sorting_test(browser) second_test_query(browser, live_server, url)
def test_order_flow_with_phases(get_shipping_method, shipping_data, get_payment_method, payment_data): cache.clear() create_default_order_statuses() populate_if_required() c = SmartClient() _populate_client_basket(c) # Create methods shipping_method = get_shipping_method() payment_method = get_payment_method() # Resolve paths addresses_path = reverse("wshop:checkout", kwargs={"phase": "addresses"}) methods_path = reverse("wshop:checkout", kwargs={"phase": "methods"}) shipping_path = reverse("wshop:checkout", kwargs={"phase": "shipping"}) payment_path = reverse("wshop:checkout", kwargs={"phase": "payment"}) confirm_path = reverse("wshop:checkout", kwargs={"phase": "confirm"}) # Phase: Addresses addresses_soup = c.soup(addresses_path) inputs = fill_address_inputs(addresses_soup, with_company=False) response = c.post(addresses_path, data=inputs) assert response.status_code == 302, "Address phase should redirect forth to methods" # Phase: Methods response = c.get(methods_path) assert response.status_code == 200 response = c.post(methods_path, data={ "shipping_method": shipping_method.pk, "payment_method": payment_method.pk }) assert response.status_code == 302, "Methods phase should redirect forth" if isinstance(shipping_method.carrier, CarrierWithCheckoutPhase): # Phase: Shipping response = c.get(shipping_path) assert response.status_code == 200 response = c.post(shipping_path, data=shipping_data) assert response.status_code == 302, "Payments phase should redirect forth" if isinstance(payment_method.payment_processor, PaymentWithCheckoutPhase): # Phase: payment response = c.get(payment_path) assert response.status_code == 200 response = c.post(payment_path, data=payment_data) assert response.status_code == 302, "Payments phase should redirect forth" # Phase: Confirm assert Order.objects.count() == 0 confirm_soup = c.soup(confirm_path) response = c.post(confirm_path, data=extract_form_fields(confirm_soup)) assert response.status_code == 302, "Confirm should redirect forth" order = Order.objects.first() if isinstance(shipping_method.carrier, CarrierWithCheckoutPhase): assert order.shipping_data.get("input_value") == "20540" if isinstance(payment_method.payment_processor, PaymentWithCheckoutPhase): assert order.payment_data.get("input_value") assert order.payment_status == PaymentStatus.NOT_PAID # Resolve order specific paths (payment and complete) process_payment_path = reverse("wshop:order_process_payment", kwargs={ "pk": order.pk, "key": order.key }) process_payment_return_path = reverse( "wshop:order_process_payment_return", kwargs={ "pk": order.pk, "key": order.key }) order_complete_path = reverse("wshop:order_complete", kwargs={ "pk": order.pk, "key": order.key }) # Check confirm redirection to payment page assert response.url.endswith(process_payment_path), ( "Confirm should have redirected to payment page") # Visit payment page response = c.get(process_payment_path) assert response.status_code == 302, "Payment page should redirect forth" assert response.url.endswith(process_payment_return_path) # Check payment return response = c.get(process_payment_return_path) assert response.status_code == 302, "Payment return should redirect forth" assert response.url.endswith(order_complete_path) # Check payment status has changed to DEFERRED order = Order.objects.get(pk=order.pk) # reload assert order.payment_status == PaymentStatus.DEFERRED
def setup_function(fn): cache.clear()
def test_get_best_selling_products(admin_user): shop1 = get_default_shop() shop2 = get_shop(True) person1 = create_random_person() person1.user = admin_user person1.save() supplier = create_simple_supplier("supplier1") client = _get_client(admin_user) # list best selling products response = client.get("/api/wshop/front/shop_products/best_selling/", {"shop": shop2.pk, "limit": 20}) assert response.status_code == status.HTTP_200_OK products = json.loads(response.content.decode("utf-8")) assert len(products["results"]) == 0 # THIS IS IMPORTANT! cache.clear() products = [create_product("Standard-%d" % x, supplier=supplier, shop=shop2) for x in range(10)] # create 1 product with 4 variations parent_product = create_product("ParentProduct1", supplier=supplier, shop=shop2) children = [create_product("SimpleVarChild-%d" % x, supplier=supplier, shop=shop2) for x in range(4)] for child in children: child.link_to_parent(parent_product) best_selling = defaultdict(int) # create orders with standard products for p_index in range(len(products)): order = create_empty_order(shop=shop2) order.save() qty = (len(products)-p_index) add_product_to_order(order, supplier, products[p_index], qty, Decimal(1.0)) order.create_shipment_of_all_products() order.status = OrderStatus.objects.get_default_complete() order.save(update_fields=("status",)) best_selling[products[p_index].id] = qty # create orders with variation products - the parent product is counted instead of its children for p_index in range(2): variation = random.choice(children) qty = 5 order = create_empty_order(shop=shop2) order.save() add_product_to_order(order, supplier, variation, qty, Decimal(1.0)) order.create_shipment_of_all_products() order.status = OrderStatus.objects.get_default_complete() order.save(update_fields=("status",)) best_selling[parent_product.id] = best_selling[parent_product.id] + qty # get the top 100 best selling products response = client.get("/api/wshop/front/shop_products/best_selling/", {"shop": shop2.pk, "limit": 100}) assert response.status_code == status.HTTP_200_OK products = json.loads(response.content.decode("utf-8")) assert len(products["results"]) == len(best_selling) # as we added less then 100, this must be true assert products["next"] is None # check the if all IDS are part of best selling for ix in range(len(products)): assert products["results"][ix]["product_id"] in best_selling.keys() # get the top 5 best selling products (we should get paginated results) response = client.get("/api/wshop/front/shop_products/best_selling/", {"shop": shop2.pk, "limit": 5}) assert response.status_code == status.HTTP_200_OK products = json.loads(response.content.decode("utf-8")) assert len(products["results"]) == 5 assert products["count"] == len(best_selling) assert products["next"] is not None sorted_best_selling_ids = [prod[0] for prod in sorted(best_selling.items(), key=lambda prod: -prod[1])][:5] # check the if all the 5 best sellers are part of best selling for ix in range(len(products)): assert products["results"][ix]["product_id"] in sorted_best_selling_ids
def setup_function(fn): activate("en") cache.clear()
def test_best_selling_products_with_multiple_orders(): context = get_jinja_context() supplier = get_default_supplier() shop = get_default_shop() n_products = 2 price = 10 product_1 = create_product("test-sku-1", supplier=supplier, shop=shop) product_2 = create_product("test-sku-2", supplier=supplier, shop=shop) create_order_with_product(product_1, supplier, quantity=1, taxless_base_unit_price=price, shop=shop) create_order_with_product(product_2, supplier, quantity=1, taxless_base_unit_price=price, shop=shop) cache.clear() # Two initial products sold assert product_1 in general.get_best_selling_products( context, n_products=n_products) assert product_2 in general.get_best_selling_products( context, n_products=n_products) product_3 = create_product("test-sku-3", supplier=supplier, shop=shop) create_order_with_product(product_3, supplier, quantity=2, taxless_base_unit_price=price, shop=shop) cache.clear() # Third product sold in greater quantity assert product_3 in general.get_best_selling_products( context, n_products=n_products) create_order_with_product(product_1, supplier, quantity=4, taxless_base_unit_price=price, shop=shop) create_order_with_product(product_2, supplier, quantity=4, taxless_base_unit_price=price, shop=shop) cache.clear() # Third product outsold by first two products assert product_3 not in general.get_best_selling_products( context, n_products=n_products) children = [ create_product("SimpleVarChild-%d" % x, supplier=supplier, shop=shop) for x in range(5) ] for child in children: child.link_to_parent(product_3) create_order_with_product(child, supplier, quantity=1, taxless_base_unit_price=price, shop=shop) cache.clear() # Third product now sold in greatest quantity assert product_3 == general.get_best_selling_products( context, n_products=n_products)[0]