def test_parallel_baskets(rf): request = get_request_with_basket() shop = get_default_shop() customer = create_random_person() request = rf.get("/") request.shop = shop apply_request_middleware(request) request.customer = customer basket_one = get_basket(request, basket_name="basket_one") basket_two = get_basket(request, basket_name="basket_two") product_one = get_default_product() product_two = get_default_product() product_two.sku = "derpy-hooves" sales_unit = SalesUnit.objects.create(identifier="test-sales-partial", decimals=2, name="Partial unit") product_two.sales_unit = sales_unit # Set the sales unit for the product product_two.save() basket_commands.handle_add(request, basket_one, product_id=product_one.pk, quantity=1) basket_commands.handle_add(request, basket_two, product_id=product_two.pk, quantity=3.5) assert basket_one.product_count == 1 assert basket_two.product_count == 3.5
def test_order_creator_account_manager(): company = create_random_company() shop = get_shop(identifier="random-shop", enabled=True) source = seed_source(create_random_user(), shop) source.customer = company source.add_line( type=OrderLineType.PRODUCT, product=get_default_product(), supplier=get_default_supplier(), quantity=1, base_unit_price=source.create_price(10), ) creator = OrderCreator() order = creator.create_order(source) assert order.account_manager is None # Company contact doesn't have account manager field person = create_random_person() person.account_manager = create_random_person() person.save() source = seed_source(create_random_user(), shop) source.customer = person source.add_line( type=OrderLineType.PRODUCT, product=get_default_product(), supplier=get_default_supplier(), quantity=1, base_unit_price=source.create_price(10), ) creator = OrderCreator() order = creator.create_order(source) assert order.account_manager is not None assert order.account_manager == person.account_manager with pytest.raises(ProtectedError): person.account_manager.delete()
def test_fixed_cost_with_waiving_costs(): sm = get_shipping_method(name="Fixed and waiving", price=5) sm.behavior_components.add(*[ WaivingCostBehaviorComponent.objects.create(price_value=p, waive_limit_value=w) for (p, w) in [(3, 5), (7, 10), (10, 30)] ]) source = BasketishOrderSource(get_default_shop()) source.shipping_method = sm def pricestr(pi): assert pi.price.unit_matches_with(source.create_price(0)) return "%.0f EUR (%.0f EUR)" % (pi.price.value, pi.base_price.value) assert pricestr(sm.get_total_cost(source)) == "25 EUR (25 EUR)" assert source.total_price.value == 25 source.add_line(type=OrderLineType.PRODUCT, product=get_default_product(), base_unit_price=source.create_price(2), quantity=1) assert pricestr(sm.get_total_cost(source)) == "25 EUR (25 EUR)" assert source.total_price.value == 27 source.add_line(type=OrderLineType.PRODUCT, product=get_default_product(), base_unit_price=source.create_price(3), quantity=1) assert pricestr(sm.get_total_cost(source)) == "22 EUR (25 EUR)" assert source.total_price.value == 27 source.add_line(type=OrderLineType.PRODUCT, product=get_default_product(), base_unit_price=source.create_price(10), quantity=1) assert pricestr(sm.get_total_cost(source)) == "15 EUR (25 EUR)" assert source.total_price.value == 30 source.add_line(type=OrderLineType.PRODUCT, product=get_default_product(), base_unit_price=source.create_price(10), quantity=1) assert pricestr(sm.get_total_cost(source)) == "15 EUR (25 EUR)" assert source.total_price.value == 40 source.add_line(type=OrderLineType.PRODUCT, product=get_default_product(), base_unit_price=source.create_price(10), quantity=1) assert pricestr(sm.get_total_cost(source)) == "5 EUR (25 EUR)" assert source.total_price.value == 40
def test_broken_order_lines(): with pytest.raises(ValidationError): OrderLine(type=OrderLineType.PRODUCT).save() with pytest.raises(ValidationError): OrderLine(product=get_default_product(), type=OrderLineType.PRODUCT, supplier=None).save() with pytest.raises(ValidationError): OrderLine(product=get_default_product(), type=OrderLineType.OTHER).save() with pytest.raises(ValidationError): OrderLine(product=get_default_product(), type=OrderLineType.OTHER, tax_rate=3).save()
def test_tracking_codes(): product = get_default_product() supplier = get_default_supplier() order = create_order_with_product(product, supplier=supplier, quantity=1, taxless_base_unit_price=10, tax_rate=decimal.Decimal("0.5")) _add_product_to_order(order, "duck-tape-1", 3, order.shop, supplier) _add_product_to_order(order, "water-1", 2, order.shop, supplier) order.cache_prices() order.check_all_verified() order.save() # Create shipment with tracking code for every product line. product_lines = order.lines.exclude(product_id=None) assert len(product_lines) == 3 for line in product_lines: shipment = order.create_shipment({line.product: line.quantity}, supplier=supplier) if line.quantity != 3: shipment.tracking_code = "123FI" shipment.save() tracking_codes = order.get_tracking_codes() code_count = (len(product_lines) - 1) # We skipped that one assert len(tracking_codes) == code_count assert len([ tracking_code for tracking_code in tracking_codes if tracking_code == "123FI" ]) == code_count
def test_custom_payment_processor_cash_service(choice_identifier, expected_payment_status): shop = get_default_shop() product = get_default_product() supplier = get_default_supplier() processor = CustomPaymentProcessor.objects.create() payment_method = PaymentMethod.objects.create( shop=shop, payment_processor=processor, choice_identifier=choice_identifier, tax_class=get_default_tax_class()) order = create_order_with_product( product=product, supplier=supplier, quantity=1, taxless_base_unit_price=Decimal('5.55'), shop=shop) order.taxful_total_price = TaxfulPrice(Decimal('5.55'), u'EUR') order.payment_method = payment_method order.save() assert order.payment_status == PaymentStatus.NOT_PAID processor.process_payment_return_request(choice_identifier, order, None) assert order.payment_status == expected_payment_status processor.process_payment_return_request(choice_identifier, order, None) assert order.payment_status == expected_payment_status
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_basket_partial_quantity_update(): request = get_request_with_basket() basket = request.basket product = get_default_product() sales_unit = SalesUnit.objects.create(identifier="test-sales-partial", decimals=2, name="Partial unit") product.sales_unit = sales_unit # Set the sales unit for the product product.save() basket_commands.handle_add(request, basket, product_id=product.pk, quantity=1.5) assert basket.product_count == 1.5 line_id = basket.get_lines()[0].line_id basket_commands.handle_update(request, basket, **{"q_%s" % line_id: "1.5"}) assert basket.product_count == 1.5 basket_commands.handle_update(request, basket, **{"q_%s" % line_id: "3.5"}) assert basket.product_count == 3.5 basket_commands.handle_update(request, basket, **{"q_%s" % line_id: "3.0"}) assert basket.product_count == 3.0 basket_commands.handle_update(request, basket, **{"q_%s" % line_id: "4"}) assert basket.product_count == 4 basket_commands.handle_update(request, basket, **{"delete_%s" % line_id: "1"}) assert basket.product_count == 0
def test_order_statuses(admin_user): create_default_order_statuses() source = seed_source(admin_user) source.add_line( type=OrderLineType.PRODUCT, product=get_default_product(), supplier=get_default_supplier(), quantity=1, base_unit_price=source.create_price(10), ) source.add_line( type=OrderLineType.OTHER, quantity=1, base_unit_price=source.create_price(10), require_verification=True, ) creator = OrderCreator() order = creator.create_order(source) # new order, status/role is new/initial assert order.status.identifier == DefaultOrderStatus.INITIAL.value assert order.status.role == OrderStatusRole.INITIAL # FUTURE: order gets payment the status changes to processing/processing total = order.taxful_total_price.amount order.create_payment(total) assert order.status.identifier == DefaultOrderStatus.INITIAL.value assert order.status.role == OrderStatusRole.INITIAL # FUTURE: order is fully shipped the status changes to complete/complete order.create_shipment_of_all_products() assert order.status.identifier == DefaultOrderStatus.INITIAL.value assert order.status.role == OrderStatusRole.INITIAL
def test_shop_overview_block(rf, data, admin_user): (today, expected_today, expected_mtd, expected_ytd) = data product = get_default_product() sp = product.get_shop_instance(get_default_shop()) sp.default_price_value = "10" sp.save() get_order_for_date(today, product) o = get_order_for_date(today, product) o.customer = None o.save() get_order_for_date(date(today.year - 1, 12, 31), product) get_order_for_date(date(today.year, 1, 1), product) get_order_for_date(date(today.year, today.month, 1), product) request = apply_request_middleware(rf.get("/"), user=admin_user) block = get_shop_overview_block(request, currency=DEFAULT_CURRENCY, for_date=today) soup = BeautifulSoup(block.content) _, today_sales, mtd, ytd, totals = soup.find_all("tr") assert today_sales.find_all("td")[NUM_ORDERS_COLUMN_INDEX].string == str( expected_today) assert today_sales.find_all( "td")[NUM_CUSTOMERS_COLUMN_INDEX].string == str(expected_today) assert mtd.find_all("td")[NUM_ORDERS_COLUMN_INDEX].string == str( expected_mtd) assert mtd.find_all("td")[NUM_CUSTOMERS_COLUMN_INDEX].string == str( expected_mtd) assert ytd.find_all("td")[NUM_ORDERS_COLUMN_INDEX].string == str( expected_ytd) assert ytd.find_all("td")[NUM_CUSTOMERS_COLUMN_INDEX].string == str( expected_ytd) assert totals.find_all("td")[NUM_ORDERS_COLUMN_INDEX].string == "5" assert totals.find_all("td")[NUM_CUSTOMERS_COLUMN_INDEX].string == "5"
def test_order_creation_adds_usage(rf, admin_user): request, shop, group = initialize_test(rf, False) source = seed_source(admin_user, shop) source.add_line( type=OrderLineType.PRODUCT, product=get_default_product(), supplier=get_default_supplier(), quantity=1, base_unit_price=source.create_price(10), ) source.add_line( type=OrderLineType.OTHER, quantity=1, base_unit_price=source.create_price(10), require_verification=True, ) # add coupon coupon = Coupon.objects.create(active=True, code="asdf") campaign = BasketCampaign.objects.create( active=True, shop=shop, name="test", public_name="test", coupon=coupon) BasketDiscountPercentage.objects.create(campaign=campaign, discount_percentage="0.1") source.add_code(coupon.code) creator = OrderCreator() creator.create_order(source) assert CouponUsage.objects.count() == 1
def test_model_url(): with admin_only_urls(): with pytest.raises(NoModelUrl): get_model_url(Counter) # That's silly! p = get_default_product() assert get_model_url(p, shop=get_default_shop())
def test_order_creator(rf, admin_user): source = seed_source(admin_user) source.add_line( type=OrderLineType.PRODUCT, product=get_default_product(), supplier=get_default_supplier(), quantity=1, base_unit_price=source.create_price(10), ) source.add_line( type=OrderLineType.OTHER, quantity=1, base_unit_price=source.create_price(10), require_verification=True, ) creator = OrderCreator() order = creator.create_order(source) assert get_data_dict(source.billing_address) == get_data_dict( order.billing_address) assert get_data_dict(source.shipping_address) == get_data_dict( order.shipping_address) customer = source.customer assert customer == order.customer assert customer.groups.count() == 1 assert customer.groups.first() == order.customer_groups.first() assert customer.tax_group is not None assert customer.tax_group == order.tax_group assert source.payment_method == order.payment_method assert source.shipping_method == order.shipping_method assert order.pk
def test_processor_orderability(admin_user): source = OrderSource(Shop()) processor = OrderProcessor() line = source.add_line( type=OrderLineType.PRODUCT, product=get_default_product(), supplier=get_default_supplier(), quantity=1, shop=get_default_shop(), base_unit_price=source.create_price(10), ) line.order = Order(shop=get_default_shop()) assert processor._check_orderability(line) is None unorderable_line = source.add_line( type=OrderLineType.PRODUCT, product=create_product("no-shop"), supplier=get_default_supplier(), quantity=1, shop=get_default_shop(), base_unit_price=source.create_price(20), ) unorderable_line.order = Order(shop=get_default_shop()) with pytest.raises(ValidationError) as exc: processor._check_orderability(unorderable_line) assert "Not available in" in exc.value.message
def test_complex_order_tax(include_taxes): tax = get_default_tax() quantities = [44, 23, 65] product = get_default_product() supplier = get_default_supplier() shop = get_default_shop() shop.prices_include_tax = include_taxes shop.save() order = create_empty_order(shop=shop) order.full_clean() order.save() pricing_context = get_pricing_module().get_context_from_data( shop=shop, customer=order.customer or AnonymousContact(), ) total_price = Decimal("0") price = Decimal("50") for quantity in quantities: total_price += quantity * price add_product_to_order(order, supplier, product, quantity, price, tax.rate, pricing_context) order.cache_prices() order.save() currency = "EUR" summary = order.get_tax_summary()[0] assert summary.tax_rate == tax.rate assert summary.based_on == Money(total_price, currency) assert summary.tax_amount == Money(total_price * tax.rate, currency) assert summary.taxful == summary.based_on + summary.tax_amount assert order.get_total_tax_amount() == Money(total_price * tax.rate, currency)
def test_model_url_with_permissions(): permissions = set( ["wshop.add_product", "wshop.delete_product", "wshop.change_product"]) shop = get_default_shop() p = get_default_product() # If no user is given, don't check for permissions assert get_model_url(p, shop=shop) # If a user is given and no permissions are provided, check for default model permissions user = StaffUser() with pytest.raises(NoModelUrl): assert get_model_url(p, user=user, shop=shop) # If a user is given and permissions are provided, check for those permissions assert get_model_url(p, user=user, required_permissions=(), shop=shop) with pytest.raises(NoModelUrl): assert get_model_url(p, user=user, required_permissions=["wshop.add_product"], shop=shop) # Confirm that url is returned with correct permissions user.permissions = permissions assert get_model_url(p, user=user, shop=shop) assert get_model_url(p, user=user, required_permissions=permissions, shop=shop)
def test_order_chart_works(rf, admin_user): get_default_shop() order = create_random_order(customer=create_random_person(), products=(get_default_product(), )) request = apply_request_middleware(rf.get("/"), user=admin_user) chart = OrderValueChartDashboardBlock("test", request=request).get_chart() assert len(chart.datasets[0]) > 0
def test_edit_view_adding_messages_to_form_group(rf, admin_user): get_default_shop() # obvious prerequisite product = get_default_product() view = ProductEditView.as_view() request = apply_request_middleware(rf.get("/"), user=admin_user) response = view(request, pk=product.pk) response.render() assert 200 <= response.status_code < 300 assert ProductEditView.add_form_errors_as_messages content = force_text(response.content) post = extract_form_fields(BeautifulSoup(content)) post_data = { # Error in the base form part "base-name__en": "", } post.update(post_data) request = apply_request_middleware(rf.post("/", post), user=admin_user) response = view(request, pk=product.pk) errors = response.context_data["form"].errors assert "base" in errors assert "name__en" in errors["base"]
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_product_price(client): shop = get_default_shop() product = get_default_product() response = client.get( reverse('wshop:xtheme_extra_view', kwargs={'view': 'product_price'}) + "?id=%s&quantity=%s" % (product.pk, 1)) assert response.context_data["product"] == product assert b"form" in response.content
def test_ajax(): product = get_default_product() commands = get_basket_command_dispatcher(get_request_with_basket()) commands.ajax = True rv = commands.handle("add", kwargs=dict(product_id=product.pk, quantity=-3)) assert isinstance(rv, JsonResponse) assert commands.basket.product_count == 0
def test_order_received(rf, regular_user): activate("en") get_default_product() get_default_supplier() get_test_script("test script", "order_received") template_data = STEP_DATA[0]["actions"][0]["template_data"] for lang in ["en", "fi"]: n_outbox_pre = len(mail.outbox) customer = create_random_person(locale=lang) create_random_order(customer) assert (len(mail.outbox) == n_outbox_pre + 1), "Sending email failed" latest_mail = mail.outbox[-1] 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 _create_order(shop, customer): p1 = factories.create_product("test", shop=shop, supplier=factories.get_default_supplier()) order = factories.create_order_with_product(factories.get_default_product(), factories.get_default_supplier(), 2, 10, shop=shop) factories.add_product_to_order(order, factories.get_default_supplier(), p1, 2, 5) order.customer = customer order.save() return order
def test_refunds(browser, admin_user, live_server, settings): order = create_order_with_product(get_default_product(), get_default_supplier(), 10, decimal.Decimal("10"), n_lines=10, shop=get_default_shop()) order2 = create_order_with_product(get_default_product(), get_default_supplier(), 10, decimal.Decimal("10"), n_lines=10, shop=get_default_shop()) order2.create_payment(order2.taxful_total_price) initialize_admin_browser_test(browser, live_server, settings) _test_toolbar_visibility(browser, live_server, order) _test_create_full_refund(browser, live_server, order) _test_refund_view(browser, live_server, order2)
def test_waiver(): sm = get_shipping_method(name="Waivey", price=100, waive_at=370) source = BasketishOrderSource(get_default_shop()) assert sm.get_effective_name(source) == u"Waivey" assert sm.get_total_cost(source).price == source.create_price(100) source.add_line(type=OrderLineType.PRODUCT, product=get_default_product(), base_unit_price=source.create_price(400), quantity=1) assert sm.get_total_cost(source).price == source.create_price(0)
def test_product_view_extra_context(rf, admin_user): product = get_default_product() request = apply_request_middleware(rf.get("/"), user=admin_user) view_func = ProductDetailView.as_view() # Test that we can insert extra information into ProductDetailView context with override_provides("product_context_extra", [ "wshop_tests.front.test_product:ExtraContextTest", ]): response = view_func(request, pk=product.pk) assert response.context_data['product_sku'] == product.sku
def test_product_page(client): get_default_shop() product = get_default_product() response = client.get( reverse('wshop:product', kwargs={ 'pk': product.pk, 'slug': product.slug } ) ) assert b'no such element' not in response.content, 'All items are not rendered correctly' # TODO test purchase_multiple and sales_unit.allow_fractions product_mode_forms = [ "wshop.front.forms.order_forms:VariableVariationProductOrderForm", "wshop.front.forms.order_forms:SimpleVariationProductOrderForm", "wshop.front.forms.order_forms:SimpleProductOrderForm", "wshop.testing.extend_classes:DifferentProductOrderForm" ] with override_provides("front_product_order_form", product_mode_forms): get_default_shop() product = get_default_product() product_modes = [ProductMode.NORMAL, ProductMode.PACKAGE_PARENT, ProductMode.VARIABLE_VARIATION_PARENT, ProductMode.SIMPLE_VARIATION_PARENT, ProductMode.SUBSCRIPTION] for product_mode in product_modes: product.mode = product_mode product.save() response = client.get( reverse('wshop:product', kwargs={ 'pk': product.pk, 'slug': product.slug } ) ) assert b'no such element' not in response.content, 'All items are not rendered correctly' if product_mode == ProductMode.SUBSCRIPTION: assert b'This is different' in response.content, 'DifferentProductOrderForm not rendered properly'
def test_order_verification(): product = get_default_product() supplier = get_default_supplier() order = create_order_with_product(product, supplier=supplier, quantity=3, n_lines=10, taxless_base_unit_price=10) order.require_verification = True order.save() assert not order.check_all_verified(), "Nothing is verified by default" order.lines.filter(pk=order.lines.filter(verified=False).first().pk).update(verified=True) assert not order.check_all_verified(), "All is not verified even if something is" order.lines.all().update(verified=True) assert order.check_all_verified(), "All is now verified" assert not order.require_verification, "Verification complete"
def test_basic_order(rf, admin_user, mode): prices_include_tax = (mode == "taxful") shop = get_shop(prices_include_tax=prices_include_tax) request = rf.get('/') request.shop = shop apply_request_middleware(request) product = get_default_product() customer = get_person_contact(admin_user) for x in range(10): create_order(request, creator=admin_user, customer=customer, product=product) assert Order.objects.filter(customer=customer).count() == 10
def test_product_module_search(rf, admin_user): get_default_shop() request = apply_request_middleware(rf.get("/"), user=admin_user) with replace_modules([CategoryModule, ImportAdminModule, ProductModule, ProductTypeModule, ManufacturerModule, PaymentMethodModule, ShippingMethodModule]): with admin_only_urls(): default_product = get_default_product() model_url = get_model_url(default_product, shop=get_shop(request)) sku = default_product.sku assert any(sr.url == model_url for sr in get_search_results(request, query=sku)) # Queries work assert any(sr.is_action for sr in get_search_results(request, query=sku[:5])) # Actions work assert empty_iterable(get_search_results(request, query=sku[:2])) # Short queries don't