def test_create_services(): carrier = CorreiosCarrier.objects.create(name="Correios") pac_service = carrier.create_service( 'PAC', shop=get_default_shop(), enabled=True, tax_class=get_default_tax_class(), name="Correios PAC") assert pac_service.behavior_components.count() == 1 sedex_service = carrier.create_service( 'SEDEX', shop=get_default_shop(), enabled=True, tax_class=get_default_tax_class(), name="Correios SEDEX") assert sedex_service.behavior_components.count() == 1 strange_service = carrier.create_service( 'STRANGE', shop=get_default_shop(), enabled=True, tax_class=get_default_tax_class(), name="unknown") assert strange_service.behavior_components.count() == 0
def test_product_create(browser, admin_user, live_server, settings): activate("en") shop = get_default_shop() get_default_product_type() get_default_sales_unit() get_default_tax_class() configuration.set(None, "shuup_product_tour_complete", True) object_created.connect(_add_custom_product_created_message, sender=Product, dispatch_uid="object_created_signal_test") initialize_admin_browser_test(browser, live_server, settings) url = reverse("shuup_admin:shop_product.new") browser.visit("%s%s" % (live_server, url)) sku = "testsku" name = "Some product name" price_value = 10 short_description = "short but gold" browser.fill("base-sku", sku) browser.fill("base-name__en", name) browser.fill("base-short_description__en", short_description) browser.fill("shop%s-default_price_value" % shop.pk, price_value) configuration.set(None, "shuup_category_tour_complete", True) _add_primary_category(browser, shop) _add_additional_category(browser, shop) click_element(browser, "button[form='product_form']") wait_until_appeared(browser, "div[class='message success']") product = Product.objects.filter(sku=sku).first() assert product.log_entries.filter(identifier=OBJECT_CREATED_LOG_IDENTIFIER).count() == 1 object_created.disconnect(sender=Product, dispatch_uid="object_created_signal_test") shop_product = product.get_shop_instance(shop) assert shop_product.categories.count() == 2
def test_refunds_report(rf): shop = get_default_shop() get_default_tax_class() creator = OrderCreator() source1 = seed_source() source2 = seed_source() source3 = seed_source() source4 = seed_source() order1 = creator.create_order(source1) order2 = creator.create_order(source2) order3 = creator.create_order(source3) order4 = creator.create_order(source4) # pay orders [o.create_payment(o.taxful_total_price) for o in Order.objects.all()] order1.create_full_refund() order2.create_refund( [{"line": order2.lines.first(), "amount": order2.taxful_total_price.amount * Decimal(0.5), "quantity": 1}] ) order3.create_refund( [{"line": order3.lines.first(), "amount": order3.taxful_total_price.amount * Decimal(0.3), "quantity": 1}] ) order4.create_refund( [{"line": order4.lines.first(), "amount": order4.taxful_total_price.amount * Decimal(0.1), "quantity": 1}] ) total_refunded = (order1.get_total_refunded_amount() + order2.get_total_refunded_amount() + order3.get_total_refunded_amount() + order4.get_total_refunded_amount()) data = { "report": RefundedSalesReport.get_name(), "shop": shop.pk, "date_range": DateRangeChoices.ALL_TIME, "writer": "json", "force_download": 1, } report = RefundedSalesReport(**data) writer = get_writer_instance(data["writer"]) response = writer.get_response(report=report) if hasattr(response, "render"): response.render() json_data = json.loads(response.content.decode("utf-8")) assert force_text(RefundedSalesReport.title) in json_data.get("heading") data = json_data.get("tables")[0].get("data") assert len(data) == 1 data = data[0] expected_data = { "refunded_orders": "4", "total_refunded": str(total_refunded.value) } for k, v in expected_data.items(): assert data[k] == v
def test_wizard_pane(rf, admin_user, settings): with override_settings(SHUUP_SETUP_WIZARD_PANE_SPEC=["shuup.admin.modules.service_providers.views.PaymentWizardPane"]): factories.get_default_shop() factories.get_default_tax_class() request = apply_request_middleware(rf.get("/"), user=admin_user) response = WizardView.as_view()(request) assert response.status_code == 200
def test_quick_add(browser, admin_user, live_server, settings): shop = get_default_shop() get_default_product_type() get_default_sales_unit() get_default_tax_class() initialize_admin_browser_test(browser, live_server, settings) url = reverse("shuup_admin:shop_product.new") browser.visit("%s%s" % (live_server, url)) sku = "testsku" name = "Some product name" price_value = 10 short_description = "short but gold" browser.fill("base-sku", sku) browser.fill("base-name__en", name) browser.fill("base-short_description__en", short_description) browser.fill("shop%s-default_price_value" % shop.pk, price_value) wait_until_appeared(browser, "#id_shop%d-primary_category ~ .quick-add-btn a.btn" % shop.id) click_element(browser, "#id_shop%d-primary_category ~ .quick-add-btn a.btn" % shop.id) wait_until_appeared(browser, "#create-object-iframe") with browser.get_iframe('create-object-iframe') as iframe: assert Category.objects.count() == 0 wait_until_appeared(iframe, "input[name='base-name__en']") iframe.fill("base-name__en", "Test Category") time.sleep(3) # Let's just wait here to the iFrame to open fully (for Chrome and headless) wait_until_appeared(iframe, "button[form='category_form']") click_element(browser, "button[form='category_form']") wait_until_condition(browser, condition=lambda x: Category.objects.count() == 1, timeout=20) assert Category.objects.first().name == "Test Category" # click to edit the button click_element(browser, "#id_shop%d-primary_category ~ .edit-object-btn a.btn" % shop.id) with browser.get_iframe('create-object-iframe') as iframe: wait_until_appeared(iframe, "input[name='base-name__en']") new_cat_name = "Changed Name" iframe.fill("base-name__en", new_cat_name) time.sleep(3) # Let's just wait here to the iFrame to open fully (for Chrome and headless) wait_until_appeared(iframe, "button[form='category_form']") click_element(iframe, "button[form='category_form']") wait_until_condition(browser, condition=lambda x: Category.objects.first().name == new_cat_name, timeout=20) click_element(browser, "button[form='product_form']") wait_until_appeared(browser, "div[class='message success']")
def test_complex_import(): filename = "complex_import.xlsx" activate("en") shop = get_default_shop() get_default_tax_class() get_default_product_type() get_default_supplier() get_default_sales_unit() path = os.path.join(os.path.dirname(__file__), "data", "product", filename) transformed_data = transform_file(filename.split(".")[1], path) importer = ProductImporter(transformed_data, shop, "en") importer.process_data() assert len(importer.unmatched_fields) == 0 importer.do_import(ImportMode.CREATE_UPDATE) products = importer.new_objects assert len(products) == 6 assert ShopProduct.objects.count() == 6 assert Category.objects.count() == 11 assert Manufacturer.objects.count() == 4 for idx, product in enumerate(Product.objects.all().order_by("sku")): shop_product = product.get_shop_instance(shop) data = PRODUCT_DATA[idx] assert product.sku == data["sku"] assert product.name == data["name"] assert shop_product.default_price_value == Decimal(data["price"]) assert product.description == data["description"] if data.get("categories"): all_cats = set(data["categories"]) all_cats.add(data["category"]) for cat in shop_product.categories.all(): assert cat.name in all_cats assert shop_product.categories.count() == len(all_cats) # also add primary category if data.get("category"): assert shop_product.primary_category.name == data["category"] assert force_text(shop_product.visibility.label) == data["visibility"].lower() assert product.tax_class.name == data["tax_class"] if data.get("manufacturer"): assert product.manufacturer.name == data["manufacturer"]
def _get_template_engine_and_context(): engine = django.template.engines['jinja2'] assert isinstance(engine, django_jinja.backend.Jinja2) shop = get_default_shop() shop.currency = 'USD' shop.prices_include_tax = False shop.save() request = RequestFactory().get('/') request.shop = shop request.customer = AnonymousContact() request.person = request.customer PriceDisplayOptions(include_taxes=False).set_for_request(request) tax = get_default_tax() create_default_tax_rule(tax) tax_class = get_default_tax_class() order, order_line = _get_order_and_order_line(request) product = create_product(sku='6.0745', shop=shop, tax_class=tax_class) context = { 'request': request, 'prod': product, # TODO: Test also with variant products 'sline': _get_source_line(request), 'bline': _get_basket_line(request), 'oline': order_line, 'order': order } return (engine, context)
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_stripe_checkout_phase_with_saved_card(rf, stripe_payment_processor): shop = factories.get_default_shop() user = factories.create_random_user() contact = get_person_contact(user) request = apply_request_middleware(rf.post("/"), shop=shop, customer=contact) def return_stripe_mock_data(*args, **kwargs): return StripedData(**CUSTOMER_MOCK_DATA) with mock.patch("stripe.Customer.retrieve", new=return_stripe_mock_data): service = stripe_payment_processor.create_service( "stripe", shop=request.shop, tax_class=factories.get_default_tax_class(), enabled=True) StripeCustomer.objects.create(contact=contact, customer_token="123") checkout_phase = StripeCheckoutPhase(request=request, service=service) assert not checkout_phase.is_valid() context = checkout_phase.get_context_data() assert context["stripe"] request.method = "POST" request.POST = { "stripeCustomer": "1234" } checkout_phase.get_success_url = lambda: reverse("shuup_admin:home") checkout_phase.post(request) assert checkout_phase.is_valid() # We should be valid now assert request.session # And things should've been saved into the session checkout_phase.process() # And this should do things to the basket assert request.basket.payment_data["stripe"]["customer"]
def test_process_payment_return_request(rf): """ Order payment with default payment method with ``CustomPaymentProcessor`` should be deferred. Payment can't be processed if method doesn't have provider or provider is not enabled or payment method is not enabled. """ pm = PaymentMethod.objects.create( shop=get_default_shop(), name="Test method", enabled=False, tax_class=get_default_tax_class()) order = create_empty_order() order.payment_method = pm order.save() assert order.payment_status == PaymentStatus.NOT_PAID with pytest.raises(ValueError): # Can't process payment with unusable method order.payment_method.process_payment_return_request(order, rf.get("/")) assert order.payment_status == PaymentStatus.NOT_PAID pm.payment_processor = get_custom_payment_processor() pm.payment_processor.enabled = False pm.save() with pytest.raises(ValueError): # Can't process payment with unusable method order.payment_method.process_payment_return_request(order, rf.get("/")) assert order.payment_status == PaymentStatus.NOT_PAID pm.payment_processor.enabled = True pm.save() with pytest.raises(ValueError): # Can't process payment with unusable method order.payment_method.process_payment_return_request(order, rf.get("/")) assert order.payment_status == PaymentStatus.NOT_PAID pm.enabled = True pm.save() order.payment_method.process_payment_return_request(order, rf.get("/")) assert order.payment_status == PaymentStatus.DEFERRED
def test_stripe_checkout_phase(rf, stripe_payment_processor): request = rf.get("/") request.shop = get_default_shop() request.session = {} request.basket = get_basket(request) service = stripe_payment_processor.create_service( None, shop=request.shop, tax_class=get_default_tax_class(), enabled=True) checkout_phase = StripeCheckoutPhase( request=request, service=service) assert not checkout_phase.is_valid() # We can't be valid just yet context = checkout_phase.get_context_data() assert context["stripe"] request.method = "POST" token = get_stripe_token(stripe_payment_processor) request.POST = { "stripeToken": token["id"], "stripeTokenType": token["type"], "stripeTokenEmail": token.get("email"), } checkout_phase.post(request) assert checkout_phase.is_valid() # We should be valid now assert request.session # And things should've been saved into the session checkout_phase.process() # And this should do things to the basket assert request.basket.payment_data.get("stripe")
def test_method_creation(rf, admin_user, view, model, service_provider_attr, get_provider): """ To make things little bit more simple let's use only english as an language. """ with override_settings(LANGUAGES=[("en", "en")]): view = view.as_view() service_provider_field = "base-%s" % service_provider_attr data = { service_provider_field: get_provider().id, "base-choice_identifier": "manual", "base-name__en": "Custom method", "base-shop": get_default_shop().id, "base-tax_class": get_default_tax_class().id, "base-enabled": True, } # Default provider CustomCarrier/CustomPaymentProcessor should be set in form init methods_before = model.objects.count() url = "/?provider=%s" % get_provider().id request = apply_request_middleware(rf.post(url, data=data), user=admin_user) response = view(request, pk=None) if hasattr(response, "render"): response.render() assert response.status_code in [200, 302] assert model.objects.count() == (methods_before + 1)
def get_correios_carrier_2(): carrier = CorreiosCarrier.objects.create(name="Correios C2") pac_service2 = carrier.create_service( 'PAC', shop=get_default_shop(), enabled=True, tax_class=get_default_tax_class(), name="Correios - PAC #2") pac_service_bc2 = pac_service2.behavior_components.first() pac_service_bc2.cep_origem = '88220000' pac_service_bc2.max_weight = Decimal(40000.0) pac_service_bc2.max_width = Decimal(800.0) pac_service_bc2.max_length = Decimal(600.0) pac_service_bc2.max_height = Decimal(400.0) pac_service_bc2.min_width = Decimal(90.0) pac_service_bc2.min_length = Decimal(60.0) pac_service_bc2.min_height = Decimal(50.0) pac_service_bc2.max_edges_sum = Decimal(2000.0) pac_service_bc2.mao_propria = True pac_service_bc2.valor_declarado = True pac_service_bc2.aviso_recebimento = True pac_service_bc2.additional_delivery_time = 2 pac_service_bc2.additional_price = Decimal(13.3) pac_service_bc2.save() return carrier
def test_stripe_checkout_phase_with_saved_card_exception(rf, stripe_payment_processor): shop = factories.get_default_shop() user = factories.create_random_user() contact = get_person_contact(user) request = apply_request_middleware(rf.post("/"), shop=shop, customer=contact) def raise_stripe_exc(*args, **kwargs): raise stripe.StripeError("DUMMY") with mock.patch("stripe.Customer.retrieve", new=raise_stripe_exc): service = stripe_payment_processor.create_service( "stripe", shop=request.shop, tax_class=factories.get_default_tax_class(), enabled=True) StripeCustomer.objects.create(contact=contact, customer_token="123") checkout_phase = StripeCheckoutPhase(request=request, service=service) assert not checkout_phase.is_valid() context = checkout_phase.get_context_data() assert context["stripe"] assert not context.get("stripe_customer_data") request.method = "POST" request.POST = {} checkout_phase.get_success_url = lambda: reverse("shuup_admin:home") checkout_phase.post(request) assert not checkout_phase.is_valid()
def test_order_package_children_taxes(): """ Test OrderCreator creates package parent links for child lines. """ tax_class = get_default_tax_class() tax = Tax.objects.create(rate='0.25', name="Da Tax") TaxRule.objects.create(tax=tax).tax_classes.add(tax_class) source = get_order_source_with_a_package() assert source.get_lines()[0].tax_class == tax_class order = OrderCreator().create_order(source) lines_and_taxes = [] for line in order.lines.all(): lines_and_taxes.append(prettify_order_line(line)) for line_tax in line.taxes.all(): lines_and_taxes.append(' %s' % (line_tax,)) assert lines_and_taxes == [ '#0 10 x PackageParent', ' Da Tax: 20.000000000 EUR on 80.000000000 EUR', '#1 10 x PackageChild-0, child of #0', '#2 20 x PackageChild-1, child of #0', '#3 30 x PackageChild-2, child of #0', '#4 40 x PackageChild-3, child of #0', ]
def test_sample_import_all_match(filename): activate("en") shop = get_default_shop() tax_class = get_default_tax_class() product_type = get_default_product_type() path = os.path.join(os.path.dirname(__file__), "data", "product", filename) transformed_data = transform_file(filename.split(".")[1], path) importer = ProductImporter(transformed_data, shop, "en") importer.process_data() assert len(importer.unmatched_fields) == 0 importer.do_import(ImportMode.CREATE_UPDATE) products = importer.new_objects assert len(products) == 2 for product in products: shop_product = product.get_shop_instance(shop) assert shop_product.pk assert shop_product.pk == product.pk assert shop_product.default_price_value == 150 assert shop_product.default_price == shop.create_price(150) assert product.type == product_type # product type comes from importer defaults if product.pk == 1: assert product.tax_class.pk == 2 # new was created assert product.name == "Product English" assert product.description == "Description English" else: assert product.tax_class.pk == tax_class.pk # old was found as should assert product.name == "Product 2 English" assert product.description == "Description English 2" assert shop_product.primary_category.pk == 1 assert [c.pk for c in shop_product.categories.all()] == [1,2]
def test_method_creation_with_labels(rf, admin_user, view, model, service_provider_attr, get_provider): """ To make things little bit more simple let's use only english as an language. """ with override_settings(LANGUAGES=[("en", "en")]): for identifier, name in [("pickup", "Pickup"), ("delivery", "Delivery"), ("airmail", "Airmail")]: label = Label.objects.create(identifier=identifier, name=name) assert label.name == name assert "%s" % label == name view = view.as_view() service_provider_field = "base-%s" % service_provider_attr data = { service_provider_field: get_provider().id, "base-choice_identifier": "manual", "base-name__en": "Custom method", "base-shop": get_default_shop().id, "base-tax_class": get_default_tax_class().id, "base-enabled": True, "base-labels": Label.objects.values_list("pk", flat=True) } # Default provider CustomCarrier/CustomPaymentProcessor should be set in form init methods_before = model.objects.count() url = "/?provider=%s" % get_provider().id request = apply_request_middleware(rf.post(url, data=data), user=admin_user) response = view(request, pk=None) if hasattr(response, "render"): response.render() assert response.status_code in [200, 302] assert model.objects.count() == (methods_before + 1) assert model.objects.last().labels.count() == Label.objects.count()
def test_sample_ignore_column(): activate("en") shop = get_default_shop() get_default_tax_class() get_default_product_type() get_default_sales_unit() path = os.path.join(os.path.dirname(__file__), "data", "product", "sample_import_ignore.csv") transformed_data = transform_file("csv", path) importer = ProductImporter(transformed_data, shop, "en") importer.process_data() assert len(importer.unmatched_fields) == 0 importer.do_import(ImportMode.CREATE_UPDATE) products = importer.new_objects assert len(products) == 2
def test_sample_data_wizard_pane(rf, admin_user, settings): settings.SHUUP_SETUP_WIZARD_PANE_SPEC = [ "shuup.testing.modules.sample_data.views.SampleObjectsWizardPane" ] shop = get_default_shop() get_default_tax_class() data = { 'pane_id': 'sample', 'sample-business_segment': 'default', 'sample-categories': True, 'sample-products': True, 'sample-carousel': True } request = apply_request_middleware(rf.post("/", data=data), user=admin_user) response = WizardView.as_view()(request) assert response.status_code == 200 assert Product.objects.count() == len(BUSINESS_SEGMENTS["default"]["products"]) anon_contact = AnonymousContact() supplier = get_default_supplier() # check for the injected plugin using the carousel assert Carousel.objects.count() == 1 carousel = Carousel.objects.first() assert Slide.objects.count() == len(BUSINESS_SEGMENTS["default"]["carousel"]["slides"]) svc = SavedViewConfig.objects.first() assert svc.view_name == "IndexView" layout = svc.get_layout_data("front_content") assert layout['rows'][0]['cells'][0]['config']['carousel'] == carousel.pk assert layout['rows'][0]['cells'][0]['plugin'] == CarouselPlugin.identifier for product in Product.objects.all(): # all products must be orderable and have images assert product.get_shop_instance(shop).is_orderable(supplier=supplier, customer=anon_contact, quantity=1) assert product.primary_image is not None assert Category.objects.count() == len(BUSINESS_SEGMENTS["default"]["categories"]) request = apply_request_middleware(rf.get("/"), user=admin_user) response = WizardView.as_view()(request) assert response.status_code == 302 assert response["Location"] == reverse("shuup_admin:dashboard")
def test_sample_import_no_match(stock_managed): filename = "sample_import_nomatch.xlsx" if "shuup.simple_supplier" not in settings.INSTALLED_APPS: pytest.skip("Need shuup.simple_supplier in INSTALLED_APPS") from shuup_tests.simple_supplier.utils import get_simple_supplier activate("en") shop = get_default_shop() tax_class = get_default_tax_class() product_type = get_default_product_type() supplier = get_simple_supplier(stock_managed) sales_unit = get_default_sales_unit() Manufacturer.objects.create(name="manufctr") path = os.path.join(os.path.dirname(__file__), "data", "product", filename) transformed_data = transform_file(filename.split(".")[1], path) importer = ProductImporter(transformed_data, shop, "en") importer.process_data() assert len(importer.unmatched_fields) == 1 assert "gtiin" in importer.unmatched_fields importer.manually_match("gtiin", "shuup.core.models.Product:gtin") importer.do_remap() assert len(importer.unmatched_fields) == 0 importer.do_import(ImportMode.CREATE_UPDATE) products = importer.new_objects assert len(products) == 2 for product in products: assert product.gtin == "1280x720" shop_product = product.get_shop_instance(shop) assert shop_product.pk assert shop_product.default_price_value == 150 assert shop_product.default_price == shop.create_price(150) assert product.type == product_type # product type comes from importer defaults assert product.sales_unit == sales_unit if product.pk == 1: assert product.tax_class.pk == 2 # new was created assert product.name == "Product English" assert product.description == "Description English" else: assert product.tax_class.pk == tax_class.pk # old was found as should assert product.name == "Product 2 English" assert product.description == "Description English 2" assert shop_product.primary_category.pk == 1 assert [c.pk for c in shop_product.categories.all()] == [1,2] # stock was not managed since supplier doesn't like that for msg in importer.other_log_messages: assert "please set Stock Managed on" in msg supplier.stock_managed = True supplier.save() importer.do_import("create,update") assert len(importer.other_log_messages) == 0 for sa in StockAdjustment.objects.all(): assert sa.product.pk assert sa.delta == 20
def test_custom_payment_processor_defaults(choice_identifier, default_behavior_components): shop = get_default_shop() processor = CustomPaymentProcessor.objects.create() service = processor.create_service(choice_identifier, shop=shop, tax_class=get_default_tax_class()) assert service.behavior_components.count() == len(default_behavior_components) for behavior in default_behavior_components: assert ServiceBehaviorComponent.objects.instance_of(behavior).count() == 1
def test_service_methods_with_long_name(rf): """ Make sure that service methods with long names (up to the max length of shipping or payment method names) don't cause exceptions when creating an order. """ MAX_LENGTH = 100 long_name = "X" * MAX_LENGTH assert len(long_name) == MAX_LENGTH sm = ShippingMethod.objects.language("en").create( shop=get_default_shop(), name=long_name, enabled=True, tax_class=get_default_tax_class()) pm = PaymentMethod.objects.language("en").create( shop=get_default_shop(), name=long_name, enabled=True, tax_class=get_default_tax_class()) order = create_empty_order() order.shipping_method = sm order.payment_method = pm order.full_clean() order.save()
def test_payment_method_wizard_pane(rf, admin_user, settings): settings.SHUUP_SETUP_WIZARD_PANE_SPEC = [ "shuup.admin.modules.service_providers.views.PaymentWizardPane" ] shop = get_default_shop() get_default_tax_class() fields = _extract_fields(rf, admin_user) fields["payment_method_base-providers"] = "manual_payment" fields["manual_payment-service_name"] = "test" request = apply_request_middleware(rf.post("/", data=fields), user=admin_user) response = WizardView.as_view()(request) assert response.status_code == 200 assert ServiceProvider.objects.count() == 1 assert CustomPaymentProcessor.objects.count() == 1 assert CustomPaymentProcessor.objects.first().name == "Manual" assert PaymentMethod.objects.count() == 1 assert PaymentMethod.objects.first().name == "test" assert_redirect_to_dashboard(rf, admin_user, shop)
def test_shipping_method_wizard_pane(rf, admin_user, settings): settings.SHUUP_SETUP_WIZARD_PANE_SPEC = [ "shuup.admin.modules.service_providers.views.CarrierWizardPane" ] shop = get_default_shop() get_default_tax_class() fields = _extract_fields(rf, admin_user) fields["shipping_method_base-providers"] = "manual_shipping" fields["manual_shipping-service_name"] = "test" request = rf.post("/", data=fields) response = WizardView.as_view()(request) assert response.status_code == 200 assert ServiceProvider.objects.count() == 1 assert CustomCarrier.objects.count() == 1 assert CustomCarrier.objects.first().name == "Manual" assert ShippingMethod.objects.count() == 1 assert ShippingMethod.objects.first().name == "test" assert_redirect_to_dashboard(rf)
def test_product_create(browser, admin_user, live_server, settings): activate("en") shop = get_default_shop() get_default_product_type() get_default_sales_unit() get_default_tax_class() object_created.connect(_add_custom_product_created_message, sender=Product, dispatch_uid="object_created_signal_test") initialize_admin_browser_test(browser, live_server, settings) url = reverse("shuup_admin:shop_product.new") browser.visit("%s%s" % (live_server, url)) wait_until_condition(browser, condition=lambda x: x.is_text_present("New shop product")) sku = "testsku" name = "Some product name" price_value = 10 short_description = "short but gold" move_to_element(browser, "#id_base-sku") browser.fill("base-sku", sku) browser.fill("base-name__en", name) browser.fill("base-short_description__en", short_description) browser.fill("shop%s-default_price_value" % shop.pk, price_value) _add_primary_category(browser, shop) _add_additional_category(browser, shop) move_to_element(browser, "button[form='product_form']") try: click_element(browser, "button[form='product_form']") wait_until_appeared(browser, "div[class='message success']") except selenium.common.exceptions.WebDriverException as e: # TODO: Revise! # Give a product save second chance it seems that the save can # lag a little and the success message doesn't happen fast # enough every single time. click_element(browser, "button[form='product_form']") wait_until_appeared(browser, "div[class='message success']") product = Product.objects.filter(sku=sku).first() assert product.log_entries.filter(identifier=OBJECT_CREATED_LOG_IDENTIFIER).count() == 1 object_created.disconnect(sender=Product, dispatch_uid="object_created_signal_test") shop_product = product.get_shop_instance(shop) assert shop_product.categories.count() == 2
def _get_shipping_method_with_phase(): carrier = CarrierWithCheckoutPhase.objects.create( identifier="carrier_with_phase", enabled=True) assert isinstance(carrier, CarrierWithCheckoutPhase) return carrier.create_service( None, identifier="carrier_with_phase", shop=get_default_shop(), name="Test method with phase", enabled=True, tax_class=get_default_tax_class())
def test_admin(rf, admin_user): activate("en") shop = get_default_shop() shop.staff_members.add(admin_user) get_default_tax_class() get_default_product_type() get_default_sales_unit() client = do_importing("123", "test", "en", shop) # change import language and update product client = do_importing("123", "test-fi", "fi", shop, client=client) # update name in english client = do_importing("123", "test-en", "en", shop, client=client) # cannot update client = do_importing("123", "test", "en", shop, import_mode=ImportMode.CREATE, client=client) # can update do_importing("123", "test", "en", shop, import_mode=ImportMode.UPDATE, client=client)
def _get_payment_method_with_phase(): processor = PaymentWithCheckoutPhase.objects.create( identifier="processor_with_phase", enabled=True) assert isinstance(processor, PaymentWithCheckoutPhase) return processor.create_service( None, identifier="payment_with_phase", shop=get_default_shop(), name="Test method with phase", enabled=True, tax_class=get_default_tax_class())
def test_weight_limits(): carrier = CustomCarrier.objects.create() sm = carrier.create_service( None, shop=get_default_shop(), enabled=True, tax_class=get_default_tax_class()) sm.behavior_components.add( WeightLimitsBehaviorComponent.objects.create( min_weight=100, max_weight=500)) source = BasketishOrderSource(get_default_shop()) assert any(ve.code == "min_weight" for ve in sm.get_unavailability_reasons(source)) source.add_line(type=OrderLineType.PRODUCT, weight=600) assert any(ve.code == "max_weight" for ve in sm.get_unavailability_reasons(source))
def get_expensive_sweden_shipping_method(): carrier = CustomCarrier.objects.create(name="Sveede Sheep") sm = carrier.create_service( None, shop=get_default_shop(), enabled=True, tax_class=get_default_tax_class(), name="Expenseefe-a Svedee Sheepping") sm.behavior_components.add( ExpensiveSwedenBehaviorComponent.objects.create(), WeightLimitsBehaviorComponent.objects.create( min_weight="0.11", max_weight="3"), ) return sm
def test_views(rf): initialize() c = SmartClient() default_product = get_default_product() basket_path = reverse("shuup:basket") c.post(basket_path, data={ "command": "add", "product_id": default_product.pk, "quantity": 1, "supplier": get_default_supplier().pk }) shipping_method = get_default_shipping_method() processor = get_payment_provider() payment_method = processor.create_service( PagSeguroPaymentMethod.ONLINE_DEBIT.value, identifier="pagseguro_debit", shop=get_default_shop(), name="debit", enabled=True, tax_class=get_default_tax_class()) addresses_path = reverse("shuup:checkout", kwargs={"phase": "addresses"}) methods_path = reverse("shuup:checkout", kwargs={"phase": "methods"}) payment_path = reverse("shuup:checkout", kwargs={"phase": "payment"}) confirm_path = reverse("shuup:checkout", kwargs={"phase": "confirm"}) addresses_soup = c.soup(addresses_path) inputs = fill_address_inputs(addresses_soup, with_company=False) c.post(addresses_path, data=inputs) c.post(methods_path, data={ "payment_method": payment_method.pk, "shipping_method": shipping_method.pk }) c.get(confirm_path) c.soup(payment_path) c.post( payment_path, { "paymentMethod": PagSeguroPaymentMethodIdentifier.Debito, "bankOption": "{0}".format(PagSeguroPaymentMethodCode.DebitoOnlineBB.value), "senderHash": "J7E98Y37WEIRUHDIAI9U8RYE7UQE" }) transaction_code = "38490248UEHBU90-2342-324502221-442" confirm_soup = c.soup(confirm_path) c.post(confirm_path, data=extract_form_fields(confirm_soup)) order = Order.objects.filter(payment_method=payment_method).first() payment = PagSeguroPayment.objects.create( order=order, code=transaction_code, data={"transaction": { "status": "1" }}) payment.save() order.payment_data['pagseguro']['code'] = payment.code order.save() # Verifica: pagseguro_payment_return response = c.get(reverse("shuup:pagseguro_payment_return")) assert response.status_code == 302 assert reverse("shuup:checkout", kwargs={"phase": "payment"}) in response.url notify_path = reverse("shuup:pagseguro_notification") # Erro: notificationCode nao informado response = c.post(notify_path) assert response.status_code == 200 assert len(response.content.decode("utf-8")) == 0 assert response[ "Access-Control-Allow-Origin"] == 'https://sandbox.pagseguro.uol.com.br' # Sucesso 1 transaction_info = xmltodict.parse(""" <?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?> <transaction> <status>2</status> <code>{0}</code> </transaction> """.format(transaction_code).strip()) # altera retorno do get_notification_info with patch.object(PagSeguro, 'get_notification_info', return_value=transaction_info): response = c.post(notify_path, {"notificationCode": "it-does-not-mattter"}) assert response.status_code == 200 assert response[ "Access-Control-Allow-Origin"] == 'https://sandbox.pagseguro.uol.com.br' payment.refresh_from_db() order.refresh_from_db() assert payment.data['transaction']['status'] == "2" assert payment.data['transaction']['code'] == transaction_code assert order.payment_status == PaymentStatus.NOT_PAID # Sucesso 2 - PAGO, emite notificacao e bota o pedido como pago transaction_info = xmltodict.parse(""" <?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?> <transaction> <status>3</status> <code>{0}</code> </transaction> """.format(transaction_code).strip()) with patch.object(PagSeguro, 'get_notification_info', return_value=transaction_info): response = c.post(notify_path, {"notificationCode": "it-does-not-mattter"}) assert response.status_code == 200 payment.refresh_from_db() order.refresh_from_db() assert payment.data['transaction']['status'] == "3" assert order.payment_status == PaymentStatus.FULLY_PAID # volta o pedido ao estado de não pago order.payment_status = PaymentStatus.NOT_PAID order.save() # Sucesso 3 - CANCELADO, emite notificacao e bota o pedido como cancelado transaction_info = xmltodict.parse(""" <?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?> <transaction> <status>7</status> <code>{0}</code> </transaction> """.format(transaction_code).strip()) with patch.object(PagSeguro, 'get_notification_info', return_value=transaction_info): response = c.post(notify_path, {"notificationCode": "it-does-not-mattter"}) assert response.status_code == 200 payment.refresh_from_db() order.refresh_from_db() assert payment.data['transaction']['status'] == "7" assert order.status.role == OrderStatusRole.CANCELED
def test_pagseguro(): initialize() c = SmartClient() default_product = get_default_product() basket_path = reverse("shuup:basket") c.post(basket_path, data={ "command": "add", "product_id": default_product.pk, "quantity": 1, "supplier": get_default_supplier().pk }) shipping_method = get_default_shipping_method() processor = get_payment_provider() payment_method = processor.create_service( PagSeguroPaymentMethod.ONLINE_DEBIT.value, identifier="pagseguro_debit", shop=get_default_shop(), name="debit", enabled=True, tax_class=get_default_tax_class()) addr = MutableAddress.from_data( dict( name=u"Dog Hello", suffix=", Esq.", postal_code="89999-999", street="Woof Ave.", city="Dog Fort", country="GB", phone="47 98821-2231", )) patch("shuup.testing.factories.get_address", new_callable=lambda: addr) addresses_path = reverse("shuup:checkout", kwargs={"phase": "addresses"}) methods_path = reverse("shuup:checkout", kwargs={"phase": "methods"}) payment_path = reverse("shuup:checkout", kwargs={"phase": "payment"}) confirm_path = reverse("shuup:checkout", kwargs={"phase": "confirm"}) addresses_soup = c.soup(addresses_path) inputs = fill_address_inputs(addresses_soup, with_company=False) c.post(addresses_path, data=inputs) c.post(methods_path, data={ "payment_method": payment_method.pk, "shipping_method": shipping_method.pk }) c.get(confirm_path) c.soup(payment_path) c.post( payment_path, { "paymentMethod": PagSeguroPaymentMethodIdentifier.Debito, "bankOption": "{0}".format(PagSeguroPaymentMethodCode.DebitoOnlineBB.value), "senderHash": "J7E98Y37WEIRUHDIAI9U8RYE7UQE" }) confirm_soup = c.soup(confirm_path) c.post(confirm_path, data=extract_form_fields(confirm_soup)) order = Order.objects.filter(payment_method=payment_method).first() USER_MODEL = get_user_model() order.phone = "47 98821-2231" order.creator = get_user_model().objects.create_user( **{ USER_MODEL.USERNAME_FIELD: "*****@*****.**", "password": "******" }) order.save() pagseguro = PagSeguro.create_from_config(get_pagseguro_config()) # unpatch methods patch.stopall() # Test: get_session_id - SUCCESS session_xml_fake = """<session><id>WOEIFJE9IUREI29RU8</id></session>""" response = Mock() response.status_code = 200 response.content = session_xml_fake with patch.object(requests, 'post', return_value=response): session_id = xmltodict.parse(session_xml_fake)['session']['id'] assert pagseguro.get_session_id() == session_id # Test: get_session_id - EXCEPTION response = Mock() response.status_code = 500 response.content = ERROR_XML with patch.object(requests, 'post', return_value=response): with pytest.raises(PagSeguroException) as exc: pagseguro.get_session_id() assert exc.value.status_code == 500 assert exc.value.error == ERROR_XML # Test: get_notification_info - SUCCESS transaction_xml_fake = """<transaction><date>WOEIFJE9IUREI29RU8</date></transaction>""" response = Mock() response.status_code = 200 response.content = transaction_xml_fake with patch.object(requests, 'get', return_value=response): assert pagseguro.get_notification_info("XXXX") == xmltodict.parse( transaction_xml_fake) # Test: get_notification_info - EXCEPTION response = Mock() response.status_code = 500 response.content = ERROR_XML with patch.object(requests, 'get', return_value=response): with pytest.raises(PagSeguroException) as exc: pagseguro.get_notification_info("ZZZZ") assert exc.value.status_code == 500 assert exc.value.error == ERROR_XML # Test: get_transaction_info - SUCCESS transaction_xml_fake = """<transaction><date>WOEIFJE9IUREI29RU8</date></transaction>""" response = Mock() response.status_code = 200 response.content = transaction_xml_fake with patch.object(requests, 'get', return_value=response): assert pagseguro.get_transaction_info("XXXX") == xmltodict.parse( transaction_xml_fake) # Test: get_transaction_info - EXCEPTION response = Mock() response.status_code = 500 response.content = ERROR_XML with patch.object(requests, 'get', return_value=response): with pytest.raises(PagSeguroException) as exc: pagseguro.get_transaction_info("ZZZZ") assert exc.value.status_code == 500 assert exc.value.error == ERROR_XML # Test: pay - SUCCESS response = Mock() response.status_code = 200 response.content = TRANSACTION_XML with patch.object(requests, 'post', return_value=response): parsed_xml = xmltodict.parse(TRANSACTION_XML) result = pagseguro.pay(payment_method, order) assert isinstance(result, PagSeguroPaymentResult) assert result.error is False assert result._data == parsed_xml assert result.code == parsed_xml['transaction']['code'] assert result.payment_link == parsed_xml['transaction']['paymentLink'] # Test: pay - ERROR response = Mock() response.status_code = 400 response.content = ERROR_XML with patch.object(requests, 'post', return_value=response): parsed_xml = xmltodict.parse(ERROR_XML) result = pagseguro.pay(payment_method, order) assert isinstance(result, PagSeguroPaymentResult) assert result.error is True assert result._data == parsed_xml assert result.errors == parsed_xml['errors'] # Test: pay - EXCEPTION response = Mock() response.status_code = 500 response.content = "A BIG MISTAKE" with patch.object(requests, 'post', return_value=response): with pytest.raises(PagSeguroException) as exc: pagseguro.pay(payment_method, order) assert exc.value.status_code == 500 assert exc.value.error == "A BIG MISTAKE" def get_only_nums(value): return "".join([c for c in value if c.isdigit()]) # Test: _get_payment_xml with CPF order.creator.pf_person = PFPerson() payment_xml = xmltodict.parse( pagseguro._get_payment_xml(payment_method, order)) assert payment_xml['payment']['currency'] == 'BRL' assert payment_xml['payment'][ 'method'] == PagSeguroPaymentMethodIdentifier.Debito assert payment_xml['payment']['sender']['documents']['document'][ 'type'] == 'CPF' assert payment_xml['payment']['sender']['documents']['document'][ 'value'] == get_only_nums(PFPerson().cpf) # Test: _get_payment_xml with CNPJ delattr(order.creator, 'pf_person') order.creator.pj_person = PJPerson() payment_xml = xmltodict.parse( pagseguro._get_payment_xml(payment_method, order)) assert payment_xml['payment']['sender']['documents']['document'][ 'type'] == 'CNPJ' assert payment_xml['payment']['sender']['documents']['document'][ 'value'] == get_only_nums(PJPerson().cnpj) assert payment_xml['payment']['sender']['phone']['areaCode'] == "47" assert payment_xml['payment']['sender']['phone']['number'] == "988212231"
def test_tax_class_selector(admin_user): shop = get_default_shop() get_default_tax_class() assert get_object_selector_results(TaxClass, shop, admin_user, "Default")
def test_many_price_info_cache_bump(rf): initial_price = 10 shop = factories.get_default_shop() tax = factories.get_default_tax() tax_class = factories.get_default_tax_class() product = factories.create_product( "product", shop=shop, supplier=factories.get_default_supplier(), default_price=initial_price ) child1 = factories.create_product( "child1", shop=shop, supplier=factories.get_default_supplier(), default_price=5 ) child2 = factories.create_product( "child2", shop=shop, supplier=factories.get_default_supplier(), default_price=9 ) child1.link_to_parent(product, variables={"color": "red"}) child2.link_to_parent(product, variables={"color": "blue"}) request = apply_request_middleware(rf.get("/")) child1_pi = child1.get_price_info(request) child2_pi = child1.get_price_info(request) def assert_cache_products(): cache_many_price_info(request, product, 1, [child1_pi, child2_pi]) assert get_many_cached_price_info(request, product, 1)[0].price == child1_pi.price assert get_many_cached_price_info(request, product, 1)[1].price == child2_pi.price def assert_nothing_is_cached(): # nothing is cached assert get_many_cached_price_info(request, product, 1) is None # cache the item assert_nothing_is_cached() assert_cache_products() # cache bumped - the cache should be dropped - then, cache again tax.save() assert_nothing_is_cached() assert_cache_products() # cache bumped - the cache should be dropped - then, cache again tax_class.save() assert_nothing_is_cached() assert_cache_products() # cache bumped - the cache should be dropped - then, cache again product.save() assert_nothing_is_cached() assert_cache_products() shop_product = product.get_shop_instance(shop) # cache bumped - the cache should be dropped - then, cache again shop_product.save() assert_nothing_is_cached() assert_cache_products() category = factories.get_default_category() # cache bumped - the cache should be dropped - then, cache again shop_product.categories.add(category) assert_nothing_is_cached() assert_cache_products()
def test_payment_refresh(): """ Testa pagamentos """ initialize() c = SmartClient() default_product = get_default_product() basket_path = reverse("shuup:basket") c.post(basket_path, data={ "command": "add", "product_id": default_product.pk, "quantity": 1, "supplier": get_default_supplier().pk }) shipping_method = get_default_shipping_method() processor = get_payment_provider() payment_method = processor.create_service( PagSeguroPaymentMethod.ONLINE_DEBIT.value, identifier="pagseguro_debit", shop=get_default_shop(), name="debit", enabled=True, tax_class=get_default_tax_class()) service_choices = processor.get_service_choices() assert len(service_choices) == 2 assert service_choices[0].identifier == PagSeguroPaymentMethod.BOLETO.value assert service_choices[ 1].identifier == PagSeguroPaymentMethod.ONLINE_DEBIT.value addresses_path = reverse("shuup:checkout", kwargs={"phase": "addresses"}) methods_path = reverse("shuup:checkout", kwargs={"phase": "methods"}) payment_path = reverse("shuup:checkout", kwargs={"phase": "payment"}) confirm_path = reverse("shuup:checkout", kwargs={"phase": "confirm"}) addresses_soup = c.soup(addresses_path) inputs = fill_address_inputs(addresses_soup, with_company=False) c.post(addresses_path, data=inputs) c.post(methods_path, data={ "payment_method": payment_method.pk, "shipping_method": shipping_method.pk }) c.get(confirm_path) c.soup(payment_path) c.post( payment_path, { "paymentMethod": PagSeguroPaymentMethodIdentifier.Debito, "bankOption": "{0}".format(PagSeguroPaymentMethodCode.DebitoOnlineBB.value), "senderHash": "J7E98Y37WEIRUHDIAI9U8RYE7UQE" }) confirm_soup = c.soup(confirm_path) c.post(confirm_path, data=extract_form_fields(confirm_soup)) order = Order.objects.filter(payment_method=payment_method).first() process_payment_path = reverse("shuup:order_process_payment", kwargs={ "pk": order.pk, "key": order.key }) process_payment_return_path = reverse("shuup:order_process_payment_return", kwargs={ "pk": order.pk, "key": order.key }) order_complete_path = reverse("shuup:order_complete", kwargs={ "pk": order.pk, "key": order.key }) c.get(process_payment_path) c.get(process_payment_return_path) c.get(order_complete_path) # testa o refresh do pagamento payment = PagSeguroPayment.objects.get(order=order) transaction_info = xmltodict.parse(""" <?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?> <transaction> <status>2</status> </transaction> """.strip()) # altera o estado da transacao with patch.object(PagSeguro, 'get_transaction_info', return_value=transaction_info): assert payment.data['transaction']['status'] == "3" payment.refresh() assert payment.data['transaction']['status'] == "2" # format string "{0}".format(payment)
def test_sample_import_no_match(rf, stock_managed): filename = "sample_import_nomatch.xlsx" if "shuup.simple_supplier" not in settings.INSTALLED_APPS: pytest.skip("Need shuup.simple_supplier in INSTALLED_APPS") from shuup_tests.simple_supplier.utils import get_simple_supplier activate("en") shop = get_default_shop() tax_class = get_default_tax_class() product_type = get_default_product_type() supplier = get_simple_supplier(stock_managed) sales_unit = get_default_sales_unit() Manufacturer.objects.create(name="manufctr") path = os.path.join(os.path.dirname(__file__), "data", "product", filename) transformed_data = transform_file(filename.split(".")[1], path) importer = ProductImporter( transformed_data, ProductImporter.get_importer_context(rf.get("/"), shop=shop, language="en") ) importer.process_data() assert len(importer.unmatched_fields) == 1 assert "gtiin" in importer.unmatched_fields importer.manually_match("gtiin", "shuup.core.models.Product:gtin") importer.do_remap() assert len(importer.unmatched_fields) == 0 importer.do_import(ImportMode.CREATE_UPDATE) products = importer.new_objects assert len(products) == 2 for product in products: assert product.gtin == "1280x720" shop_product = product.get_shop_instance(shop) assert shop_product.pk assert shop_product.default_price_value == 150 assert shop_product.default_price == shop.create_price(150) assert product.type == product_type # product type comes from importer defaults assert product.sales_unit == sales_unit if product.pk == 1: assert product.tax_class.pk == 2 # new was created assert product.name == "Product English" assert product.description == "Description English" else: assert product.tax_class.pk == tax_class.pk # old was found as should assert product.name == "Product 2 English" assert product.description == "Description English 2" assert shop_product.primary_category.pk == 1 assert [c.pk for c in shop_product.categories.all()] == [1, 2] # stock was not managed since supplier doesn't like that for msg in importer.other_log_messages: assert "please set `Stock Managed` on" in msg supplier.stock_managed = True supplier.save() importer.do_import("create,update") assert len(importer.other_log_messages) == 0 for sa in StockAdjustment.objects.all(): assert sa.product.pk assert sa.delta == 20
def test_weight_limits(): carrier = CustomCarrier.objects.create() sm = carrier.create_service(None, shop=get_default_shop(), enabled=True, tax_class=get_default_tax_class()) sm.behavior_components.add(WeightLimitsBehaviorComponent.objects.create(min_weight=100, max_weight=500)) source = BasketishOrderSource(get_default_shop()) assert any(ve.code == "min_weight" for ve in sm.get_unavailability_reasons(source)) source.add_line(type=OrderLineType.PRODUCT, weight=600) assert any(ve.code == "max_weight" for ve in sm.get_unavailability_reasons(source))
def test_remap(rf, admin_user): lang = "en" import_mode = ImportMode.CREATE_UPDATE sku = "123" name = "test" import_path = reverse("shuup_admin:importer.import") process_path = reverse("shuup_admin:importer.import_process") tax_class = get_default_tax_class() product_type = get_default_product_type() activate("en") shop = get_default_shop() shop.staff_members.add(admin_user) client = SmartClient() client.login(username="******", password="******") csv_content = str.encode("sku;name;gtiin\n%s;%s;111" % (sku, name)) # show import view data = { "importer": "product_importer", "shop": shop.pk, "language": lang, "file": SimpleUploadedFile("file.csv", csv_content, content_type="text/csv") } response = client.post(import_path, data=data) assert response.status_code == 302 query_string = urlparse(response["location"]).query query = parse_qs(query_string) data = { # data with missing `n` "importer": "product_importer", "shop": shop.pk, "language": lang, "n": query.get("n") } soup = client.soup(process_path, data=data) assert "The following fields must be manually tied" in str(soup) for row in soup.findAll("tr"): first_td = row.find("td") if not first_td: continue tds = row.findAll("td") if len(tds) < 2: continue second_td = tds[1] if first_td.text.startswith("Connection"): # check that sku was connected badges = second_td.findAll("span", {"class": "badge"}) assert len(badges) == 1 assert badges[0].text == "sku" elif first_td.text.startswith("The following fields"): badges = second_td.findAll("span", {"class": "badge"}) assert len(badges) == 2 badge_texts = [] for b in badges: badge_texts.append(b.text) badge_texts.sort() assert badge_texts[0] == "name" assert badge_texts[1] == "sku" data = {} data["import_mode"] = import_mode.value data["remap[gtiin]"] = "Product:gtin" # map gtin process_submit_path = "%s?%s" % (process_path, query_string) client.soup(process_submit_path, data=data, method="post") assert Product.objects.count() == 1 product = Product.objects.first() assert product.gtin == "111"
def test_invalid_file_type(rf, admin_user): lang = "en" import_mode = ImportMode.CREATE_UPDATE sku = "123" name = "test" import_path = reverse("shuup_admin:importer.import.new") process_path = reverse("shuup_admin:importer.import_process") get_default_tax_class() get_default_product_type() get_default_sales_unit() activate("en") shop = get_default_shop() shop.staff_members.add(admin_user) client = SmartClient() client.login(username="******", password="******") csv_content = str.encode("sku;name\n%s;%s" % (sku, name)) # show import view data = { "importer": "product_importer", "shop": shop.pk, "language": lang, "file": SimpleUploadedFile("file.derp", csv_content, content_type="text/csv"), } response = client.post(import_path, data=data) assert response.status_code == 302 query_string = urlparse(response["location"]).query data = { # data with missing `n` "importer": "product_importer", "shop": shop.pk, "language": lang, } response, soup = client.response_and_soup(process_path, data=data) assert response.status_code == 400 for row in soup.findAll("tr"): first_td = row.find("td") if not first_td: continue tds = row.findAll("td") if len(tds) < 2: continue second_td = tds[1] if first_td.text.startswith("Connection"): # check that sku was connected badges = second_td.findAll("span", {"class": "badge"}) assert len(badges) == 1 assert badges[0].text == "sku" elif first_td.text.startswith("The following fields"): badges = second_td.findAll("span", {"class": "badge"}) assert len(badges) == 2 badge_texts = [] for b in badges: badge_texts.append(b.text) badge_texts.sort() assert badge_texts[0] == "name" assert badge_texts[1] == "sku" data = {} data["import_mode"] = import_mode.value process_submit_path = "%s?%s" % (process_path, query_string) response = client.post(process_submit_path, data=data) assert response.status_code == 302
def test_edit_button_no_permission(browser, admin_user, live_server, settings): shop = get_default_shop() manager_group = Group.objects.create(name="Managers") manager = create_random_user("en", is_staff=True) manager.username = "******" manager.set_password("password") manager.save() manager.groups.add(manager_group) shop.staff_members.add(manager) # add permissions for Product admin module manager_permissions = set(["dashboard", "Products", "shop_product.new"]) set_permissions_for_group(manager_group, manager_permissions) get_default_product_type() get_default_sales_unit() get_default_tax_class() initialize_admin_browser_test(browser, live_server, settings, username=manager.username) url = reverse("shuup_admin:shop_product.new") browser.visit("%s%s" % (live_server, url)) sku = "testsku" name = "Some product name" price_value = 10 short_description = "short but gold" browser.fill("base-sku", sku) browser.fill("base-name__en", name) browser.fill("base-short_description__en", short_description) browser.fill("shop%s-default_price_value" % shop.pk, price_value) wait_until_appeared( browser, "#id_shop%d-primary_category ~ .quick-add-btn a.btn" % shop.id) click_element( browser, "#id_shop%d-primary_category ~ .quick-add-btn a.btn" % shop.id) wait_until_appeared(browser, "#create-object-iframe") # no permission to add category with browser.get_iframe('create-object-iframe') as iframe: error = "Can't view this page. You do not have the required permissions: category.new" wait_until_condition(iframe, condition=lambda x: x.is_text_present(error)) # close iframe click_element(browser, "#create-object-overlay a.close-btn") # add permission to add category manager_permissions.add("category.new") manager_permissions.add("category.edit") set_permissions_for_group(manager_group, manager_permissions) # click to add category again click_element( browser, "#id_shop%d-primary_category ~ .quick-add-btn a.btn" % shop.id) wait_until_appeared(browser, "#create-object-iframe") # add the category with browser.get_iframe('create-object-iframe') as iframe: assert Category.objects.count() == 0 wait_until_appeared(iframe, "input[name='base-name__en']") iframe.fill("base-name__en", "Test Category") time.sleep( 3 ) # Let's just wait here to the iFrame to open fully (for Chrome and headless) wait_until_appeared(iframe, "button[form='category_form']") click_element(browser, "button[form='category_form']") wait_until_condition(browser, condition=lambda x: Category.objects.count() == 1, timeout=20) assert Category.objects.first().name == "Test Category" # remove the edit category permissions # add permission to add category manager_permissions.remove("category.edit") set_permissions_for_group(manager_group, manager_permissions) # click to edit the button click_element( browser, "#id_shop%d-primary_category ~ .edit-object-btn a.btn" % shop.id) # no permission to edit category with browser.get_iframe('create-object-iframe') as iframe: error = "Can't view this page. You do not have the required permission(s): category.edit" wait_until_condition(iframe, condition=lambda x: x.is_text_present(error)) # close iframe click_element(browser, "#create-object-overlay a.close-btn") manager_permissions.add("category.edit") set_permissions_for_group(manager_group, manager_permissions) click_element( browser, "#id_shop%d-primary_category ~ .edit-object-btn a.btn" % shop.id) wait_until_appeared(browser, "#create-object-iframe") new_cat_name = "Changed Name" with browser.get_iframe('create-object-iframe') as iframe: wait_until_appeared(iframe, "input[name='base-name__en']") iframe.fill("base-name__en", new_cat_name) time.sleep( 3 ) # Let's just wait here to the iFrame to open fully (for Chrome and headless) wait_until_appeared(iframe, "button[form='category_form']") click_element(browser, "button[form='category_form']") wait_until_condition( browser, condition=lambda x: Category.objects.first().name == new_cat_name, timeout=20)
def test_variatins_import(rf): filename = "product_sample_import_with_variations.xlsx" if "shuup.simple_supplier" not in settings.INSTALLED_APPS: pytest.skip("Need shuup.simple_supplier in INSTALLED_APPS") from shuup_tests.simple_supplier.utils import get_simple_supplier activate("en") shop = get_default_shop() product_type = get_default_product_type() sales_unit = get_default_sales_unit() tax_class = get_default_tax_class() # Create media _create_random_media_file(shop, "shirt1.jpeg") _create_random_media_file(shop, "shirt2.jpeg") _create_random_media_file(shop, "shirt3.jpeg") path = os.path.join(os.path.dirname(__file__), "data", "product", filename) transformed_data = transform_file(filename.split(".")[1], path) importer = ProductImporter( transformed_data, ProductImporter.get_importer_context(rf.get("/"), shop=shop, language="en")) importer.process_data() assert len(importer.unmatched_fields) == 0 importer.do_import(ImportMode.CREATE_UPDATE) products = importer.new_objects assert len(products) == 42 # 2 parents 20 variations each supplier = Supplier.objects.first() assert supplier and supplier.stock_managed and supplier.module_identifier == "simple_supplier" assert ShopProduct.objects.filter(suppliers=supplier).count() == 42 parent1 = Product.objects.filter(sku=1).first() assert parent1.mode == ProductMode.VARIABLE_VARIATION_PARENT assert parent1.variation_children.all().count() == 20 # Check product names child1 = Product.objects.filter(sku=10).first() assert child1.name == "T-Shirt - Pink - S" child2 = Product.objects.filter(sku=11).first() assert child2.name == "T-Shirt - Pink - XS" # Check stock counts assert supplier.get_stock_status(child1.pk).logical_count == Decimal(5) assert supplier.get_stock_status(child2.pk).logical_count == Decimal(10) parent2 = Product.objects.filter(sku=22).first() assert parent1.mode == ProductMode.VARIABLE_VARIATION_PARENT assert parent1.variation_children.all().count() == 20 # Check product names child1 = Product.objects.filter(sku=38).first() assert child1.name == "Custom T-Shirt - Black - XL" child2 = Product.objects.filter(sku=39).first() assert child2.name == "Custom T-Shirt - Black - L" # Check stock counts assert supplier.get_stock_status(child1.pk).logical_count == Decimal(5) assert supplier.get_stock_status(child2.pk).logical_count == Decimal(10) path = os.path.join(os.path.dirname(__file__), "data", "product", "product_sample_import_with_variations_update.xlsx") transformed_data = transform_file(filename.split(".")[1], path) importer = ProductImporter( transformed_data, ProductImporter.get_importer_context(rf.get("/"), shop=shop, language="en")) importer.process_data() assert len(importer.unmatched_fields) == 0 importer.do_import(ImportMode.CREATE_UPDATE) products = importer.new_objects assert len(products) == 0 updated_products = importer.updated_objects assert len(updated_products) == 4 # Check product names child1 = Product.objects.filter(sku=10).first() assert child1.name == "T-Shirt - Pink - S" child2 = Product.objects.filter(sku=11).first() assert child2.name == "Test" # Check stock counts assert supplier.get_stock_status(child1.pk).logical_count == Decimal(5) assert supplier.get_stock_status(child2.pk).logical_count == Decimal( 20) # Did not add 20 but made the logical to 20 parent2 = Product.objects.filter(sku=22).first() assert parent1.mode == ProductMode.VARIABLE_VARIATION_PARENT assert parent1.variation_children.all().count() == 20 # Check product names child1 = Product.objects.filter(sku=38).first() assert child1.name == "Custom T-Shirt - Black - XL" child2 = Product.objects.filter(sku=39).first() assert child2.name == "Custom T-Shirt - Black - L" # Check stock counts assert supplier.get_stock_status(child1.pk).logical_count == Decimal(15) assert supplier.get_stock_status(child2.pk).logical_count == Decimal(10) # Test file with missing variations path = os.path.join( os.path.dirname(__file__), "data", "product", "product_sample_import_with_variations_missing_variables.xlsx") transformed_data = transform_file(filename.split(".")[1], path) importer = ProductImporter( transformed_data, ProductImporter.get_importer_context(rf.get("/"), shop=shop, language="en")) importer.process_data() assert len(importer.unmatched_fields) == 0 importer.do_import(ImportMode.CREATE_UPDATE) products = importer.new_objects assert len(products) == 0 updated_products = importer.updated_objects assert len(updated_products) == 4 for log_message in importer.log_messages: assert "Parent SKU set for the row, but no variation" in log_message[ "messages"][0] # check that both variation products still looks correct parent1 = Product.objects.filter(sku=1).first() assert parent1.mode == ProductMode.VARIABLE_VARIATION_PARENT assert parent1.variation_children.all().count() == 20 parent2 = Product.objects.filter(sku=22).first() assert parent1.mode == ProductMode.VARIABLE_VARIATION_PARENT assert parent1.variation_children.all().count() == 20
def test_quick_add(browser, admin_user, live_server, settings): shop = get_default_shop() get_default_product_type() get_default_sales_unit() get_default_tax_class() initialize_admin_browser_test(browser, live_server, settings) url = reverse("shuup_admin:shop_product.new") browser.visit("%s%s" % (live_server, url)) sku = "testsku" name = "Some product name" price_value = 10 short_description = "short but gold" browser.fill("base-sku", sku) browser.fill("base-name__en", name) browser.fill("base-short_description__en", short_description) browser.fill("shop%s-default_price_value" % shop.pk, price_value) wait_until_appeared( browser, "#id_shop%d-primary_category ~ .quick-add-btn a.btn" % shop.id) click_element( browser, "#id_shop%d-primary_category ~ .quick-add-btn a.btn" % shop.id) wait_until_appeared(browser, "#create-object-iframe") with browser.get_iframe('create-object-iframe') as iframe: assert Category.objects.count() == 0 wait_until_appeared(iframe, "input[name='base-name__en']") iframe.fill("base-name__en", "Test Category") time.sleep( 3 ) # Let's just wait here to the iFrame to open fully (for Chrome and headless) wait_until_appeared(iframe, "button[form='category_form']") click_element(browser, "button[form='category_form']") wait_until_condition(browser, condition=lambda x: Category.objects.count() == 1, timeout=20) assert Category.objects.first().name == "Test Category" # click to edit the button click_element( browser, "#id_shop%d-primary_category ~ .edit-object-btn a.btn" % shop.id) with browser.get_iframe('create-object-iframe') as iframe: wait_until_appeared(iframe, "input[name='base-name__en']") new_cat_name = "Changed Name" iframe.fill("base-name__en", new_cat_name) time.sleep( 3 ) # Let's just wait here to the iFrame to open fully (for Chrome and headless) wait_until_appeared(iframe, "button[form='category_form']") click_element(iframe, "button[form='category_form']") wait_until_condition( browser, condition=lambda x: Category.objects.first().name == new_cat_name, timeout=20) click_element(browser, "button[form='product_form']") wait_until_appeared(browser, "div[class='message success']")
def test_postalcodeshipping(class_spec): with override_settings(SHIPPING_SIMULATOR_CLASS_SPEC=class_spec): get_default_shop() product = get_default_product() clear_load_cache() carrier = CustomCarrier.objects.create(name="Kustom Karrier") service = carrier.create_service(None, enabled=True, shop=get_default_shop(), tax_class=get_default_tax_class(), name="A Kustom Cervise", description="Nice!") path = reverse("shuup:simulate-product-shipping") client = Client() data = { "product_id": product.id, "command": "add", "quantity": "1", } if class_spec.endswith("PostalCodeShippingSimulator"): data["postal_code"] = "37128482" elif class_spec.endswith("CityStateCountryShippingSimulator"): data["city"] = "Plumenau" data["region"] = "SC" data["country"] = "BR" # First, the method does not return any price. it must be free cost = get_default_shop().create_price(0.00) response = client.post(path, data) json_response = json.loads(response.content.decode("utf-8")) method = json_response["methods"][0] assert method["name"] == service.name assert method["description"] == service.description assert method["cost"] == cost.value assert method["formatted_cost"] == format_money(cost) assert method.get("time") is None # now lets add some extra price and time behavior service.behavior_components.add(ExpensiveSwedenBehaviorComponent.objects.create()) cost = get_default_shop().create_price(1.00) duration = DurationRange(timedelta(days=5)) with patch.object(ExpensiveSwedenBehaviorComponent, 'get_costs', return_value=[ServiceCost(cost)]): with patch.object(ExpensiveSwedenBehaviorComponent, 'get_delivery_time', return_value=duration): response = client.post(path, data) json_response = json.loads(response.content.decode("utf-8")) method = json_response["methods"][0] assert method["name"] == service.name assert method["description"] == service.description assert method["cost"] == cost.value assert method["formatted_cost"] == format_money(cost) assert method["time"]["min"] == duration.min_duration.days assert not method["time"]["formatted"] is None assert method["time"].get("max") is None # now with duration range time cost = get_default_shop().create_price(3.0) duration = DurationRange(timedelta(days=2), timedelta(days=8)) with patch.object(ExpensiveSwedenBehaviorComponent, 'get_delivery_time', return_value=duration): with patch.object(ExpensiveSwedenBehaviorComponent, 'get_costs', return_value=[ServiceCost(cost)]): response = client.post(path, data) json_response = json.loads(response.content.decode("utf-8")) method = json_response["methods"][0] assert method["name"] == service.name assert method["description"] == service.description assert method["cost"] == cost.value assert method["formatted_cost"] == format_money(cost) assert method["time"]["min"] == duration.min_duration.days assert method["time"]["max"] == duration.max_duration.days # with suppier id data["supplier_id"] = get_default_supplier().pk response = client.post(path, data) json_response = json.loads(response.content.decode("utf-8")) method = json_response["methods"][0] assert method["name"] == service.name # with fractional quantity - internal error data["quantity"] = "1.321" response = client.post(path, data) assert response.status_code == 400 # invalid quantity - internal error data["quantity"] = "1.,32.,1" response = client.post(path, data) assert response.status_code == 400 # negative quantity - internal error data["quantity"] = "-1" response = client.post(path, data) assert response.status_code == 400 # invalid form data = {"produt_id": product.id} response = client.post(path, data) assert json.loads(response.content.decode("utf-8")) == {}
def test_refresh_transaction_view(rf, admin_user): initialize() c = SmartClient() default_product = get_default_product() ORDER_TOTAL = PRODUCT_PRICE * 1 basket_path = reverse("shuup:basket") c.post(basket_path, data={ "command": "add", "product_id": default_product.pk, "quantity": 1, "supplier": get_default_supplier().pk }) # Create methods shipping_method = get_default_shipping_method() processor = get_payment_provider() payment_method = processor.create_service( CIELO_SERVICE_CREDIT, identifier="cielo_phase_cc", shop=get_default_shop(), name="credit card", enabled=True, tax_class=get_default_tax_class()) # Resolve paths addresses_path = reverse("shuup:checkout", kwargs={"phase": "addresses"}) methods_path = reverse("shuup:checkout", kwargs={"phase": "methods"}) payment_path = reverse("shuup:checkout", kwargs={"phase": "payment"}) confirm_path = reverse("shuup:checkout", kwargs={"phase": "confirm"}) transaction_path = reverse("shuup:cielo_make_transaction") # Phase: Addresses addresses_soup = c.soup(addresses_path) inputs = fill_address_inputs(addresses_soup, with_company=False) c.post(addresses_path, data=inputs) c.post(methods_path, data={ "payment_method": payment_method.pk, "shipping_method": shipping_method.pk }) c.get(confirm_path) tid = uuid.uuid4().hex transacao = get_in_progress_transaction( numero=1, valor=decimal_to_int_cents(ORDER_TOTAL), produto=CieloProduct.Credit, bandeira=CieloCardBrand.Visa, parcelas=CC_VISA_1X_INFO['installments'], tid=tid) transacao = get_approved_transaction(transacao) with patch.object(CieloRequest, 'autorizar', return_value=transacao): with patch.object(CieloRequest, 'consultar', return_value=transacao): c.soup(payment_path) c.post(transaction_path, CC_VISA_1X_INFO) confirm_soup = c.soup(confirm_path) c.post(confirm_path, data=extract_form_fields(confirm_soup)) order = Order.objects.filter(payment_method=payment_method).first() process_payment_path = reverse("shuup:order_process_payment", kwargs={ "pk": order.pk, "key": order.key }) process_payment_return_path = reverse( "shuup:order_process_payment_return", kwargs={ "pk": order.pk, "key": order.key }) c.get(process_payment_path) c.get(process_payment_return_path) order.refresh_from_db() cielo_transaction = CieloTransaction.objects.get( order_transaction__order=order) # transacao nao capturada assert cielo_transaction.tid == tid assert cielo_transaction.total_captured.value == Decimal() view = load("shuup_cielo.admin.views.RefreshTransactionView").as_view() request = apply_request_middleware(rf.post("/"), user=admin_user) # request sem parametro - bad request response = view(request) assert response.status_code == 500 transacao = get_captured_transaction(transacao) with patch.object(CieloRequest, 'consultar', return_value=transacao): request = apply_request_middleware(rf.post( "/", {"id": cielo_transaction.pk}), user=admin_user) response = view(request) assert response.status_code == 200 cielo_transaction.refresh_from_db() assert cielo_transaction.total_captured_value == order.taxful_total_price_value
def test_refunds_report(rf): shop = get_default_shop() get_default_tax_class() creator = OrderCreator() source1 = seed_source() source2 = seed_source() source3 = seed_source() source4 = seed_source() order1 = creator.create_order(source1) order2 = creator.create_order(source2) order3 = creator.create_order(source3) order4 = creator.create_order(source4) # pay orders [o.create_payment(o.taxful_total_price) for o in Order.objects.all()] order1.create_full_refund() order2.create_refund([{ "line": order2.lines.first(), "amount": order2.taxful_total_price.amount * Decimal(0.5), "quantity": 1 }]) order3.create_refund([{ "line": order3.lines.first(), "amount": order3.taxful_total_price.amount * Decimal(0.3), "quantity": 1 }]) order4.create_refund([{ "line": order4.lines.first(), "amount": order4.taxful_total_price.amount * Decimal(0.1), "quantity": 1 }]) total_refunded = (order1.get_total_refunded_amount() + order2.get_total_refunded_amount() + order3.get_total_refunded_amount() + order4.get_total_refunded_amount()) data = { "report": RefundedSalesReport.get_name(), "shop": shop.pk, "date_range": DateRangeChoices.ALL_TIME, "writer": "json", "force_download": 1, } report = RefundedSalesReport(**data) writer = get_writer_instance(data["writer"]) response = writer.get_response(report=report) if hasattr(response, "render"): response.render() json_data = json.loads(response.content.decode("utf-8")) assert force_text(RefundedSalesReport.title) in json_data.get("heading") data = json_data.get("tables")[0].get("data") assert len(data) == 1 data = data[0] expected_data = { "refunded_orders": "4", "total_refunded": str(total_refunded.value) } for k, v in expected_data.items(): assert data[k] == v
def test_shipping_report(rf): shop = get_default_shop() tax_class = get_default_tax_class() creator = OrderCreator() carrier1 = CustomCarrier.objects.create(name="Carrier1") sm1 = carrier1.create_service(None, shop=get_default_shop(), enabled=True, tax_class=tax_class, name="SM #1") sm1.behavior_components.add( FixedCostBehaviorComponent.objects.create(price_value=Decimal(10))) sm2 = carrier1.create_service(None, shop=get_default_shop(), enabled=True, tax_class=tax_class, name="SM #2") sm2.behavior_components.add( FixedCostBehaviorComponent.objects.create(price_value=Decimal(99))) sm2.behavior_components.add( FixedCostBehaviorComponent.objects.create(price_value=Decimal(4))) carrier2 = CustomCarrier.objects.create(name="Carrier2") sm3 = carrier2.create_service(None, shop=get_default_shop(), enabled=True, tax_class=tax_class, name="SM #3") sm3.behavior_components.add( FixedCostBehaviorComponent.objects.create(price_value=Decimal(5))) source1 = seed_source(sm1) source2 = seed_source(sm1) source3 = seed_source(sm2) source4 = seed_source(sm3) creator.create_order(source1) creator.create_order(source2) creator.create_order(source3) creator.create_order(source4) # pay orders [o.create_payment(o.taxful_total_price) for o in Order.objects.all()] data = { "report": ShippingReport.get_name(), "shop": shop.pk, "date_range": DateRangeChoices.ALL_TIME, "writer": "json", "force_download": 1, } report = ShippingReport(**data) writer = get_writer_instance(data["writer"]) response = writer.get_response(report=report) if hasattr(response, "render"): response.render() json_data = json.loads(response.content.decode("utf-8")) assert force_text(ShippingReport.title) in json_data.get("heading") data = json_data.get("tables")[0].get("data") assert len(data) == 3 expected_result = [ { "carrier": carrier1.name, "shipping_method": sm1.name, "order_count": 2, "total_charged": sum([bc.price_value for bc in sm1.behavior_components.all()]) * 2 # 2 orders }, { "carrier": carrier1.name, "shipping_method": sm2.name, "order_count": 1, "total_charged": sum([bc.price_value for bc in sm2.behavior_components.all()]) }, { "carrier": carrier2.name, "shipping_method": sm3.name, "order_count": 1, "total_charged": sum([bc.price_value for bc in sm3.behavior_components.all()]) } ] for ix, shipping in enumerate(data): assert shipping["carrier"] == expected_result[ix]["carrier"] assert shipping["shipping_method"] == expected_result[ix][ "shipping_method"] assert shipping["order_count"] == str( expected_result[ix]["order_count"]) assert shipping["total_charged"] == str( expected_result[ix]["total_charged"].quantize(Decimal("0.01")))
def test_coupons_usage_report(rf): shop = get_default_shop() tax_class = get_default_tax_class() creator = OrderCreator() coupon1 = Coupon.objects.create(code="coupon1", active=True) coupon2 = Coupon.objects.create(code="coupon2", active=True) campaign1 = get_default_campaign(coupon1, "10") campaign2 = get_default_campaign(coupon2, "25") source1 = seed_source(coupon1) source2 = seed_source(coupon1) source3 = seed_source(coupon1) source4 = seed_source(coupon2) creator.create_order(source1) creator.create_order(source2) creator.create_order(source3) creator.create_order(source4) # pay orders [o.create_payment(o.taxful_total_price) for o in Order.objects.all()] data = { "report": CouponsUsageReport.get_name(), "shop": shop.pk, "date_range": DateRangeChoices.ALL_TIME, "writer": "json", "force_download": 1, } report = CouponsUsageReport(**data) writer = get_writer_instance(data["writer"]) response = writer.get_response(report=report) if hasattr(response, "render"): response.render() json_data = json.loads(response.content.decode("utf-8")) assert force_text(CouponsUsageReport.title) in json_data.get("heading") data = json_data.get("tables")[0].get("data") assert len(data) == Order.objects.count() expected_data = [] orders = Order.objects.all().order_by("order_date") for order in orders: discount = order.shop.create_price(0) for dt in order.lines.discounts(): discount += dt.taxful_price expected_data.append({ "date": format_date(order.order_date, locale=get_current_babel_locale()), "coupon": order.codes[0], "order": str(order), "taxful_total": str(order.taxful_total_price.as_rounded().value), "taxful_subtotal": str((order.taxful_total_price - discount).as_rounded().value), "total_discount": str(discount.as_rounded().value) }) assert len(expected_data) == len(data) for ix, d in enumerate(data): for k, v in d.items(): assert expected_data[ix][k] == v
def test_sample_import_all_match(filename): activate("en") shop = get_default_shop() tax_class = get_default_tax_class() product_type = get_default_product_type() sales_unit = get_default_sales_unit() path = os.path.join(os.path.dirname(__file__), "data", "product", filename) if filename == bom_file: import codecs bytes = min(32, os.path.getsize(path)) raw = open(path, 'rb').read(bytes) assert raw.startswith(codecs.BOM_UTF8) transformed_data = transform_file(filename.split(".")[1], path) importer = ProductImporter(transformed_data, shop, "en") importer.process_data() if filename == images_file: assert len(importer.unmatched_fields) == 2 _create_random_media_file(shop, "image1.jpeg") _create_random_media_file(shop, "products/images/image2.jpeg") _create_random_media_file(shop, "products/images/image3.jpeg") _create_random_media_file(shop, "image4.jpeg") _create_random_media_file(shop, "products2/images/image5.jpeg") _create_random_media_file(shop, "product1.jpeg") _create_random_media_file(shop, "products/images/product2.jpeg") _create_random_media_file(shop, "products/images2/product2.jpeg") else: assert len(importer.unmatched_fields) == 0 importer.do_import(ImportMode.CREATE_UPDATE) products = importer.new_objects if filename == images_file: assert len(products) == 3 else: assert len(products) == 2 for product in products: shop_product = product.get_shop_instance(shop) assert shop_product.pk assert shop_product.default_price_value == 150 assert shop_product.default_price == shop.create_price(150) assert product.type == product_type # product type comes from importer defaults assert product.sales_unit == sales_unit if product.pk == 1: assert product.tax_class.pk == 2 # new was created assert product.name == "Product English" assert product.description == "Description English" if filename == images_file: assert product.media.count() == 3 elif product.pk == 2: assert product.tax_class.pk == tax_class.pk # old was found as should assert product.name == "Product 2 English" assert product.description == "Description English 2" if filename == images_file: assert product.media.count() == 2 elif product.pk == 3 and filename == images_file: assert product.media.count() == 3 assert shop_product.primary_category.pk == 1 assert [c.pk for c in shop_product.categories.all()] == [1, 2]