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)
예제 #2
0
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
예제 #3
0
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)
예제 #4
0
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
예제 #5
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
예제 #6
0
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"
예제 #7
0
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
예제 #8
0
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)
예제 #9
0
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
예제 #10
0
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"
예제 #11
0
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"
예제 #12
0
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
예제 #13
0
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
예제 #14
0
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
예제 #15
0
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)
예제 #16
0
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
예제 #19
0
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)
예제 #20
0
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)
예제 #21
0
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
예제 #22
0
def setup_function(fn):
    cache.clear()
예제 #23
0
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
예제 #24
0
def setup_function(fn):
    activate("en")
    cache.clear()
예제 #25
0
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]