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 get_initialized_test_event(): get_default_product() customer = create_random_person() order = create_random_order(customer) return ATestEvent( order_language=order.language, order=order, just_some_text=random_title() )
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_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).save()
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 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_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_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_report_writers(): """ Just check whether something breaks while writing differnt types of data """ shop = get_default_shop() product = get_default_product() supplier = get_default_supplier() order = create_order_with_product( product=product, supplier=supplier, quantity=1, taxless_base_unit_price=10, tax_rate=0, n_lines=2, shop=shop) order.create_payment(order.taxful_total_price.amount) data = { "report": SalesTestReport.get_name(), "shop": shop.pk, "date_range": DateRangeChoices.THIS_YEAR, "writer": "html", "force_download": 1, } report = SalesTestReport(**data) for writer_cls in [ExcelReportWriter, PDFReportWriter, PprintReportWriter, HTMLReportWriter, JSONReportWriter]: writer = writer_cls() report_data = [ { "date": order, "order_count": Decimal(2), "product_count": int(3), "taxless_total": lazy(lambda: order.taxless_total_price_value), "taxful_total": order.taxful_total_price, } ] writer.write_data_table(report, report_data) assert writer.get_rendered_output()
def test_simple_product_works(rf): product = get_default_product() request = rf.get("/") apply_request_middleware(request) assert product.get_child_price_range(request) == (None, None) assert product.get_cheapest_child_price_info(request) is None assert product.get_cheapest_child_price(request) is None
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_all_categories_view(rf, admin_user): shop = get_default_shop() supplier = get_default_supplier() category = get_default_category() product = get_default_product() request = apply_request_middleware(rf.get("/")) _check_product_count(request, 0) shop_product = product.get_shop_instance(shop) shop_product.categories.add(category) _check_product_count(request, 1) # Create few categories for better test results for i in range(10): cat = Category.objects.create(name=printable_gibberish()) cat.shops.add(shop) new_product_count = random.randint(1, 3) + 1 for i in range(1, new_product_count): product = create_product("sku-%s" % i, shop=shop, supplier=supplier, default_price=10) shop_product = product.get_shop_instance(shop) # Add random categories expect default category which we will make # hidden to make sure that products linked to hidden categories are # not listed shop_product.categories = Category.objects.exclude(id=category.pk).order_by("?")[:i] _check_product_count(request, new_product_count) category.status = CategoryStatus.INVISIBLE category.save() _check_product_count(request, new_product_count - 1)
def test_applied_attributes(): product = get_default_product() for spec in ATTR_SPECS: # This loop sets each attribute twice. That's okay. attr = Attribute.objects.get(identifier=spec["identifier"]) pa, _ = ProductAttribute.objects.get_or_create(product=product, attribute=attr) _populate_applied_attribute(pa) pa.save() if not attr.is_translated: product.set_attribute_value(attr.identifier, pa.value) assert product.get_attribute_value("bogomips") == 320, "integer attribute loaded neatly" product.set_attribute_value("bogomips", 480) assert product.get_attribute_value("bogomips") == 480, "integer attribute updated neatly" Product.cache_attributes_for_targets( applied_attr_cls=ProductAttribute, targets=[product], attribute_identifiers=[a["identifier"] for a in ATTR_SPECS], language=get_language() ) assert (get_language(), "bogomips",) in product._attr_cache, "integer attribute in cache" assert product.get_attribute_value("bogomips") == 480, "integer attribute value in cache" assert product.get_attribute_value("ba:gelmips", default="Britta") == "Britta", "non-existent attributes return default value" assert product._attr_cache[(get_language(), "ba:gelmips")] is NoSuchAttributeHere, "cache miss saved" attr_info = product.get_all_attribute_info(language=get_language(), visibility_mode=AttributeVisibility.SHOW_ON_PRODUCT_PAGE) assert set(attr_info.keys()) <= set(a["identifier"] for a in ATTR_SPECS), "get_all_attribute_info gets all attribute info"
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_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_mass_action_multishop(rf, admin_user): def create_shop(name): return Shop.objects.create( name="foobar", identifier=name, status=ShopStatus.ENABLED, public_name=name, currency=get_default_currency().code ) shop_one = get_default_shop() shop_two = create_shop("foobar") product = get_default_product() shop_product_one = product.get_shop_instance(shop_one) shop_product_two = ShopProduct.objects.create(shop=shop_two, product=product) shop_product_two.save() assert shop_product_one.visibility == ShopProductVisibility.ALWAYS_VISIBLE assert shop_product_two.visibility == ShopProductVisibility.ALWAYS_VISIBLE request = apply_request_middleware(rf.get("/"), user=admin_user, shop=shop_one) InvisibleMassAction().process(request, 'all') shop_product_one.refresh_from_db() shop_product_two.refresh_from_db() assert shop_product_one.visibility == ShopProductVisibility.NOT_VISIBLE assert shop_product_two.visibility == ShopProductVisibility.ALWAYS_VISIBLE request = apply_request_middleware(rf.get("/"), user=admin_user, shop=shop_one) VisibleMassAction().process(request, 'all') shop_product_one.refresh_from_db() shop_product_two.refresh_from_db() assert shop_product_two.visibility == ShopProductVisibility.ALWAYS_VISIBLE assert shop_product_one.visibility == ShopProductVisibility.ALWAYS_VISIBLE
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_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_delete_payment(admin_user, rf): product = get_default_product() shop_product = product.get_shop_instance(get_default_shop()) shop_product.default_price_value = 20 shop_product.save() order = create_random_order(customer=create_random_person(), products=(product,), completion_probability=0) payment_amount = order.taxful_total_price_value # create a payment view = OrderCreatePaymentView.as_view() request = apply_request_middleware(rf.post("/", {"amount": payment_amount}), user=admin_user) response = view(request, pk=order.pk) assert response.status_code == 302 order.refresh_from_db() assert order.is_paid() # delete the payment payment = order.payments.last() view = OrderDeletePaymentView.as_view() request = apply_request_middleware(rf.post("/", {"payment": payment.pk}), user=admin_user) response = view(request, pk=order.pk) assert response.status_code == 302 order.refresh_from_db() assert order.is_not_paid()
def test_edit_view_adding_messages_to_form_group(rf, admin_user): shop = get_default_shop() # obvious prerequisite product = get_default_product() shop_product = product.get_shop_instance(shop) view = ProductEditView.as_view() request = apply_request_middleware(rf.get("/"), user=admin_user) response = view(request, pk=shop_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, "lxml")) 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=shop_product.pk) errors = response.context_data["form"].errors assert "base" in errors assert "name__en" in errors["base"]
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_update_order_admin_comment(admin_user, rf): order = create_random_order(customer=create_random_person(), products=(get_default_product(),)) assert order.admin_comment == "" view = UpdateAdminCommentView.as_view() comment = "updated admin comment" request = apply_request_middleware(rf.post("/", {"comment": comment}), user=admin_user) response = view(request, pk=order.pk) assert response.status_code < 400 order.refresh_from_db() assert order.admin_comment == comment
def test_add_order_log_entry(admin_user, rf): order = create_random_order(customer=create_random_person(), products=(get_default_product(),)) assert not OrderLogEntry.objects.filter(target=order).exists() view = NewLogEntryView.as_view() test_message = "test_order" request = apply_request_middleware(rf.post("/", {"message": test_message}), user=admin_user) response = view(request, pk=order.pk) assert response.status_code < 400 assert OrderLogEntry.objects.filter(target=order).exists() assert OrderLogEntry.objects.filter(target=order).first().message == test_message
def test_product_price_without_shop_product(client): shop = get_default_shop() product = get_default_product() response = client.get( reverse('E-Commerce:xtheme_extra_view', kwargs={ 'view': 'product_price' } ) + "?id=%s" % (product.pk) ) assert response.context_data["product"] == product assert "Combination not available" in response.content.decode("utf-8")
def test_product_price(client): shop = get_default_shop() product = get_default_product() response = client.get( reverse('E-Commerce: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_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", [ "E-Commerce_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('E-Commerce: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 = [ "E-Commerce.front.forms.order_forms:VariableVariationProductOrderForm", "E-Commerce.front.forms.order_forms:SimpleVariationProductOrderForm", "E-Commerce.front.forms.order_forms:SimpleProductOrderForm", "E-Commerce.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('E-Commerce: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_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_order_set_status_canceled_works(admin_user, rf): order = create_random_order(customer=create_random_person(), products=(get_default_product(),)) assert order.shipping_status == ShippingStatus.NOT_SHIPPED assert order.status.role == OrderStatusRole.INITIAL canceled_status = OrderStatus.objects.get_default_canceled() view = OrderSetStatusView.as_view() request = apply_request_middleware(rf.post("/", {"status": canceled_status.pk}), user=admin_user) response = view(request, pk=order.pk) assert response.status_code < 400 order = Order.objects.get(pk=order.pk) assert order.status_id == canceled_status.id assert order.log_entries.filter(identifier="status_change").exists()
def test_order_set_status_completed_works(admin_user, rf): order = create_random_order(customer=create_random_person(), products=(get_default_product(),)) order.create_shipment_of_all_products() # Need to be shipped to set complete assert order.status.role == OrderStatusRole.INITIAL complete_status = OrderStatus.objects.get_default_complete() view = OrderSetStatusView.as_view() request = apply_request_middleware(rf.post("/", {"status": complete_status.pk}), user=admin_user) response = view(request, pk=order.pk) assert response.status_code < 400 order = Order.objects.get(pk=order.pk) assert order.status_id == complete_status.id assert order.log_entries.filter(identifier="status_change").exists()