def test_user_detail_contact_seed(rf): get_default_shop() contact = create_random_person() view_func = UserDetailView.as_view() # Check that fields populate . . . request = apply_request_middleware(rf.get("/", {"contact_id": contact.pk})) response = view_func(request) response.render() content = force_text(response.content) assert force_text(contact.first_name) in content assert force_text(contact.last_name) in content assert force_text(contact.email) in content # POST the password too to create the user . . . post = extract_form_fields(BeautifulSoup(content)) post["password"] = "******" request.method = "POST" request.POST = post response = view_func(request) assert response.status_code < 500 # Check this new user is visible in the details now user = Contact.objects.get(pk=contact.pk).user request = apply_request_middleware(rf.get("/", {"contact_id": contact.pk})) response = view_func(request, pk=user.pk) response.render() content = force_text(response.content) assert force_text(contact.first_name) in content assert force_text(contact.last_name) in content assert force_text(contact.email) in content
def test_user_detail_contact_seed(rf): get_default_shop() contact = create_random_person() # Using random data for name and email would need escaping when # checking if it is rendered, therefore use something very basic instead contact.name = "Matti Perustyyppi" contact.email = "*****@*****.**" contact.save() view_func = UserDetailView.as_view() # Check that fields populate . . . request = apply_request_middleware(rf.get("/", {"contact_id": contact.pk})) response = view_func(request) response.render() content = force_text(response.content) assert force_text(contact.first_name) in content assert force_text(contact.last_name) in content assert force_text(contact.email) in content # POST the password too to create the user . . . post = extract_form_fields(BeautifulSoup(content)) post["password"] = "******" request.method = "POST" request.POST = post response = view_func(request) assert response.status_code < 500 # Check this new user is visible in the details now user = Contact.objects.get(pk=contact.pk).user request = apply_request_middleware(rf.get("/", {"contact_id": contact.pk})) response = view_func(request, pk=user.pk) response.render() content = force_text(response.content) assert force_text(contact.first_name) in content assert force_text(contact.last_name) in content assert force_text(contact.email) in content
def test_simple_search_no_results(rf): with translation.override("xx"): # use built-in translation get_default_shop() view = SearchView.as_view() resp = view(apply_request_middleware(rf.get("/", {"q": UNLIKELY_STRING}))) assert NO_RESULTS_FOUND_STRING in resp.rendered_content resp = view(apply_request_middleware(rf.get("/"))) assert NO_RESULTS_FOUND_STRING not in resp.rendered_content
def test_modules_in_core_admin_work(rf, admin_user): get_default_shop() request = rf.get("/") apply_request_middleware(request, user=admin_user) request = apply_request_middleware(rf.get("/"), user=admin_user) with replace_modules(ShoopAdminAppConfig.provides["admin_module"]): assert all(get_module_urls()) assert get_menu_entry_categories(request)
def test_simple_search_no_results(rf): with translation.override("xx"): # use built-in translation get_default_shop() view = SearchView.as_view() resp = view( apply_request_middleware(rf.get("/", {"q": UNLIKELY_STRING}))) assert NO_RESULTS_FOUND_STRING in resp.rendered_content resp = view(apply_request_middleware(rf.get("/"))) assert NO_RESULTS_FOUND_STRING not in resp.rendered_content
def test_simple_search_view_works(rf): view = SearchView.as_view() prod = create_product(sku=UNLIKELY_STRING, shop=get_default_shop()) query = prod.name[:8] # This test is pretty cruddy. TODO: Un-cruddify this test. resp = view(apply_request_middleware(rf.get("/"))) assert query not in resp.rendered_content resp = view(apply_request_middleware(rf.get("/", {"q": query}))) assert query in resp.rendered_content
def create_order_with_product(product, supplier, quantity, taxless_base_unit_price, tax_rate=0, n_lines=1, shop=None): order = create_empty_order(shop=shop) order.full_clean() order.save() request = apply_request_middleware(RequestFactory().get("/")) request.shop = order.shop for x in range(n_lines): product_order_line = OrderLine(order=order) update_order_line_from_product(request=request, order_line=product_order_line, product=product, quantity=quantity, supplier=supplier) product_order_line.base_unit_price = order.shop.create_price( taxless_base_unit_price) product_order_line.save() product_order_line.taxes.add( OrderLineTax.from_tax( get_test_tax(tax_rate), product_order_line.taxless_total_price.amount, order_line=product_order_line, )) assert order.get_product_ids_and_quantities()[product.pk] == ( quantity * n_lines), "Things got added" return order
def test_order_source_parentage(rf, admin_user): source = seed_source(admin_user) product = get_default_product() source.add_line( type=OrderLineType.PRODUCT, product=product, supplier=get_default_supplier(), quantity=1, base_unit_price=source.create_price(10), line_id="parent" ) source.add_line( type=OrderLineType.OTHER, text="Child Line", sku="KIDKIDKID", quantity=1, base_unit_price=source.create_price(5), parent_line_id="parent" ) request = apply_request_middleware(rf.get("/")) creator = OrderCreator(request) order = Order.objects.get(pk=creator.create_order(source).pk) kid_line = order.lines.filter(sku="KIDKIDKID").first() assert kid_line assert kid_line.parent_line.product_id == product.pk
def test_order_creator(rf, admin_user): source = seed_source(admin_user) source.add_line( type=OrderLineType.PRODUCT, product=get_default_product(), supplier=get_default_supplier(), quantity=1, base_unit_price=source.create_price(10), ) source.add_line( type=OrderLineType.OTHER, quantity=1, base_unit_price=source.create_price(10), require_verification=True, ) request = apply_request_middleware(rf.get("/")) creator = OrderCreator(request) order = creator.create_order(source) assert get_data_dict(source.billing_address) == get_data_dict( order.billing_address) assert get_data_dict(source.shipping_address) == get_data_dict( order.shipping_address) assert source.customer == order.customer assert source.payment_method == order.payment_method assert source.shipping_method == order.shipping_method assert order.pk
def test_order_source_parentage(rf, admin_user): source = seed_source(admin_user) product = get_default_product() source.lines.append(SourceLine( type=OrderLineType.PRODUCT, product=product, supplier=get_default_supplier(), quantity=1, unit_price=TaxlessPrice(10), line_id="parent" )) source.lines.append(SourceLine( type=OrderLineType.OTHER, text="Child Line", sku="KIDKIDKID", quantity=1, unit_price=TaxlessPrice(5), parent_line_id="parent" )) request = apply_request_middleware(rf.get("/")) creator = OrderCreator(request) order = Order.objects.get(pk=creator.create_order(source).pk) kid_line = order.lines.filter(sku="KIDKIDKID").first() assert kid_line assert kid_line.parent_line.product_id == product.pk
def create_random_order(customer=None, products=(), completion_probability=0): if not customer: customer = Contact.objects.all().order_by("?").first() if not customer: raise ValueError("No valid contacts") shop = get_default_shop() request = apply_request_middleware(RequestFactory().get("/"), customer=customer) context = PriceTaxContext.from_request(request) source = OrderSource() source.customer = customer source.customer_comment = "Mock Order" if customer.default_billing_address and customer.default_shipping_address: source.billing_address = customer.default_billing_address source.shipping_address = customer.default_shipping_address else: source.billing_address = create_random_address() source.shipping_address = create_random_address() source.order_date = now() - datetime.timedelta(days=random.uniform(0, 400)) source.shop = shop source.language = customer.language source.status = get_initial_order_status() if not products: products = list(Product.objects.list_visible(source.shop, customer).order_by("?")[:40]) source.lines = [] for i in range(random.randint(3, 10)): product = random.choice(products) quantity = random.randint(1, 5) price_info = product.get_price_info(context, quantity=quantity) shop_product = product.get_shop_instance(source.shop) supplier = shop_product.suppliers.first() line = SourceLine( type=OrderLineType.PRODUCT, product=product, supplier=supplier, quantity=quantity, unit_price=price_info.unit_base_price, total_discount=price_info.discount_amount, sku=product.sku, text=product.safe_translation_getter("name", any_language=True) ) assert line.total_price == price_info.price source.lines.append(line) with atomic(): oc = OrderCreator(request) order = oc.create_order(source) if random.random() < completion_probability: order.create_shipment_of_all_products() # also set complete order.status = OrderStatus.objects.get_default_complete() order.save(update_fields=("status",)) return order
def create_order_with_product( product, supplier, quantity, taxless_base_unit_price, tax_rate=0, n_lines=1, shop=None): order = create_empty_order(shop=shop) order.full_clean() order.save() request = apply_request_middleware(RequestFactory().get("/")) request.shop = order.shop for x in range(n_lines): product_order_line = OrderLine(order=order) update_order_line_from_product(request=request, order_line=product_order_line, product=product, quantity=quantity, supplier=supplier) product_order_line.base_unit_price = order.shop.create_price(taxless_base_unit_price) product_order_line.save() product_order_line.taxes.add(OrderLineTax.from_tax( get_test_tax(tax_rate), product_order_line.taxless_total_price.amount, order_line=product_order_line, )) assert order.get_product_ids_and_quantities()[product.pk] == (quantity * n_lines), "Things got added" return order
def test_order_creator(rf, admin_user): source = seed_source(admin_user) source.add_line( type=OrderLineType.PRODUCT, product=get_default_product(), supplier=get_default_supplier(), quantity=1, base_unit_price=source.create_price(10), ) source.add_line( type=OrderLineType.OTHER, quantity=1, base_unit_price=source.create_price(10), require_verification=True, ) request = apply_request_middleware(rf.get("/")) creator = OrderCreator(request) order = creator.create_order(source) assert get_data_dict(source.billing_address) == get_data_dict(order.billing_address) assert get_data_dict(source.shipping_address) == get_data_dict(order.shipping_address) assert source.customer == order.customer assert source.payment_method == order.payment_method assert source.shipping_method == order.shipping_method assert order.pk
def create_random_order(customer=None, products=(), completion_probability=0): if not customer: customer = Contact.objects.all().order_by("?").first() if not customer: raise ValueError("No valid contacts") shop = get_default_shop() request = apply_request_middleware(RequestFactory().get("/"), customer=customer) context = PriceTaxContext.from_request(request) source = OrderSource() source.customer = customer source.customer_comment = "Mock Order" if customer.default_billing_address and customer.default_shipping_address: source.billing_address = customer.default_billing_address source.shipping_address = customer.default_shipping_address else: source.billing_address = create_random_address() source.shipping_address = create_random_address() source.order_date = now() - datetime.timedelta(days=random.uniform(0, 400)) source.shop = shop source.language = customer.language source.status = get_initial_order_status() if not products: products = list( Product.objects.list_visible(source.shop, customer).order_by("?")[:40]) source.lines = [] for i in range(random.randint(3, 10)): product = random.choice(products) quantity = random.randint(1, 5) price = product.get_price(context, quantity=quantity) shop_product = product.get_shop_instance(source.shop) supplier = shop_product.suppliers.first() line = SourceLine(type=OrderLineType.PRODUCT, product=product, supplier=supplier, quantity=quantity, unit_price=price, sku=product.sku, text=product.safe_translation_getter( "name", any_language=True)) source.lines.append(line) with atomic(): oc = OrderCreator(request) order = oc.create_order(source) if random.random() < completion_probability: order.create_shipment_of_all_products() # also set complete order.status = OrderStatus.objects.get_default_complete() order.save(update_fields=("status", )) return order
def test_superuser_can_see_invisible_page(rf, admin_user): page = create_page() get_default_shop() view_func = PageView.as_view() request = apply_request_middleware(rf.get("/"), user=admin_user) response = view_func(request, url=page.url) response.render() assert "<h1>Bacon ipsum" in response.rendered_content
def test_anon_cant_see_invisible_page(rf): page = create_page() get_default_shop() view_func = PageView.as_view() request = apply_request_middleware(rf.get("/")) assert request.user.is_anonymous() with pytest.raises(Http404): response = view_func(request, url=page.url)
def test_user_detail_works_at_all(rf, admin_user): get_default_shop() user = get_user_model().objects.create( username=printable_gibberish(20), first_name=printable_gibberish(10), last_name=printable_gibberish(10), password="******" ) view_func = UserDetailView.as_view() response = view_func(apply_request_middleware(rf.get("/"), user=admin_user), pk=user.pk) assert response.status_code == 200 response.render() assert force_text(user) in force_text(response.content) response = view_func(apply_request_middleware(rf.post("/", {"set_is_active": "0"}), user=admin_user), pk=user.pk) assert response.status_code < 500 and not get_user_model().objects.get(pk=user.pk).is_active with pytest.raises(Problem): view_func(apply_request_middleware(rf.post("/", {"set_is_active": "0"}), user=admin_user), pk=admin_user.pk)
def test_visible_page_has_right_content(rf): page = create_page(available_from=datetime.date(1988, 1, 1)) get_default_shop() view_func = PageView.as_view() request = apply_request_middleware(rf.get("/")) assert request.user.is_anonymous() response = view_func(request, url=page.url) response.render() assert "<h1>Bacon ipsum" in response.rendered_content
def test_intra_request_user_changing(rf, regular_user): get_default_shop() # Create a shop mw = ShoopFrontMiddleware() request = apply_request_middleware(rf.get("/"), user=regular_user) mw.process_request(request) assert request.person == shoop.core.models.get_person_contact(regular_user) logout(request) assert request.user == AnonymousUser() assert request.person == shoop.core.models.AnonymousContact() assert request.customer == shoop.core.models.AnonymousContact()
def test_detail_view(rf, admin_user, model_and_class): get_default_shop() # obvious prerequisite model_func, class_spec = model_and_class model = model_func() view = load(class_spec).as_view() request = apply_request_middleware(rf.get("/"), user=admin_user) response = view(request, pk=model.pk) if hasattr(response, "render"): response.render() assert 200 <= response.status_code < 300
def test_product_edit_view_works_at_all(rf, admin_user): get_default_shop() request = apply_request_middleware(rf.get("/"), user=admin_user) with replace_modules([ProductModule]): with admin_only_urls(): default_product = get_default_product() view_func = ProductEditView.as_view() response = view_func(request, pk=default_product.pk) assert (default_product.sku in response.rendered_content) # it's probable the SKU is there response = view_func(request, pk=None) # "new mode" assert response.rendered_content # yeah, something gets rendered
def test_order_set_status_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()
def test_product_edit_view_with_params(rf, admin_user): get_default_shop() sku = "test-sku" name = "test name" request = apply_request_middleware(rf.get("/", {"name": name, "sku": sku}), user=admin_user) with replace_modules([ProductModule]): with admin_only_urls(): view_func = ProductEditView.as_view() response = view_func(request) assert (sku in response.rendered_content) # it's probable the SKU is there assert (name in response.rendered_content) # it's probable the name is there
def test_multilanguage_page_404_no_xlate(rf): # https://github.com/edoburu/django-parler/issues/50 cache.clear() # this is here, because parler cache is enabled and tests use same pk with page page = create_multilanguage_page(eternal=True, url="no_content", languages=("udm",)) # create page with udm language get_default_shop() request = apply_request_middleware(rf.get("/")) with translation.override("fi"): # change language of the page to fi view_func = PageView.as_view() with pytest.raises(Http404): response = view_func(request, url="no_content-udm") # Using Udmurt URL, but xlate is Finnish . . . assert response.status_code == 404 # ... should 404
def test_product_module_search(rf, admin_user): get_default_shop() request = apply_request_middleware(rf.get("/"), user=admin_user) with replace_modules([ProductModule]): with admin_only_urls(): default_product = get_default_product() model_url = get_model_url(default_product) sku = default_product.sku assert any(sr.url == model_url for sr in get_search_results(request, query=sku)) # Queries work assert any(sr.is_action for sr in get_search_results(request, query=sku[:5])) # Actions work assert empty_iterable(get_search_results(request, query=sku[:2])) # Short queries don't
def test_maintenance_mode(rf, regular_user, admin_user): shop = get_default_shop() shop.maintenance_mode = True shop.save() mw = ShoopFrontMiddleware() request = apply_request_middleware(rf.get("/"), user=regular_user) maintenance_response = mw.process_view(request, IndexView) assert maintenance_response is not None assert maintenance_response.status_code == 503 assert mw._get_maintenance_response(request, IndexView).content == maintenance_response.content login_response = mw.process_view(request, login) assert login_response is None request = apply_request_middleware(rf.get("/"), user=admin_user) admin_response = mw.process_view(request, IndexView) assert admin_response is None shop.maintenance_mode = False shop.save()
def test_multishop_edit_view(rf, admin_user): get_default_shop() request = apply_request_middleware(rf.get("/"), user=admin_user) view = ShopEditView(request=request, kwargs={"pk": None}) with override_settings(SHOOP_ENABLE_MULTIPLE_SHOPS=False): with pytest.raises(Problem): view.get_object() # Now view object should throw Problem with override_settings(SHOOP_ENABLE_MULTIPLE_SHOPS=True): new_shop = view.get_object() assert new_shop.pk is None
def test_admin_recovers_clients_password(rf, admin_user): get_default_shop() person = create_random_person() person.user = get_user_model().objects.create_user( username="******", password="******", email="*****@*****.**" ) person.save() request = apply_request_middleware(rf.post("/"), user=admin_user) view_func = ContactResetPasswordView.as_view() n_outbox_pre = len(mail.outbox) view_func(request, pk=person.pk) # The response doesn't actually matter. assert (len(mail.outbox) == n_outbox_pre + 1), "Sending recovery email has failed"
def test_media_view_images(rf): get_default_shop() folder = Folder.objects.create(name="Root") file = File.objects.create(name="normalfile", folder=folder) img = Image.objects.create(name="imagefile", folder=folder) request = apply_request_middleware(rf.get("/sa/media", {"filter": "images", "action": "folder", "id": folder.id})) view_func = MediaBrowserView.as_view() response = view_func(request) assert isinstance(response, JsonResponse) content = json.loads(response.content.decode("utf-8")) assert len(content["folder"]["files"]) == 1 filedata = content["folder"]["files"][0] assert filedata["name"] == img.name
def test_multilanguage_page_redirect(rf): page = create_multilanguage_page(eternal=True, url="redirector") get_default_shop() view_func = PageView.as_view() request = apply_request_middleware(rf.get("/")) with translation.override("fi"): page.set_current_language("fi") finnish_url = page.url response = view_func(request, url=finnish_url) assert response.status_code == 200 # Using the Finnish URL works page.set_current_language("en") english_url = page.url response = view_func(request, url=english_url) assert response.status_code == 302 # Using the English URL - redirect to finnish assert finnish_url in response["location"]
def test_user_detail_works_at_all(rf, admin_user): get_default_shop() user = get_user_model().objects.create(username=printable_gibberish(20), first_name=printable_gibberish(10), last_name=printable_gibberish(10), password="******") view_func = UserDetailView.as_view() response = view_func(apply_request_middleware(rf.get("/"), user=admin_user), pk=user.pk) assert response.status_code == 200 response.render() assert force_text(user) in force_text(response.content) response = view_func(apply_request_middleware(rf.post( "/", {"set_is_active": "0"}), user=admin_user), pk=user.pk) assert response.status_code < 500 and not get_user_model().objects.get( pk=user.pk).is_active with pytest.raises(Problem): view_func(apply_request_middleware(rf.post("/", {"set_is_active": "0"}), user=admin_user), pk=admin_user.pk)
def test_product_edit_view_works_at_all(rf, admin_user): shop = get_default_shop() product = create_product("test-product", shop, default_price=200) shop_product = product.get_shop_instance(shop) shop_product.visibility_limit = ProductVisibility.VISIBLE_TO_GROUPS shop_product.save() request = apply_request_middleware(rf.get("/"), user=admin_user) with replace_modules([ProductModule]): with admin_only_urls(): view_func = ProductEditView.as_view() response = view_func(request, pk=product.pk) assert (product.sku in response.rendered_content) # it's probable the SKU is there response = view_func(request, pk=None) # "new mode" assert response.rendered_content # yeah, something gets rendered
def test_order_creator_supplierless_product_line_conversion_should_fail(rf, admin_user): source = seed_source(admin_user) source.add_line( type=OrderLineType.PRODUCT, product=get_default_product(), supplier=None, quantity=1, base_unit_price=source.create_price(10), ) request = apply_request_middleware(rf.get("/")) creator = OrderCreator(request) with pytest.raises(ValueError): order = creator.create_order(source)
def test_order_creator_supplierless_product_line_conversion_should_fail(rf, admin_user): source = seed_source(admin_user) source.lines.append(SourceLine( type=OrderLineType.PRODUCT, product=get_default_product(), supplier=None, quantity=1, unit_price=TaxlessPrice(10), )) request = apply_request_middleware(rf.get("/")) creator = OrderCreator(request) with pytest.raises(ValueError): order = creator.create_order(source)
def test_product_edit_view_works_at_all(rf, admin_user): shop = get_default_shop() product = create_product("test-product", shop, default_price=200) shop_product = product.get_shop_instance(shop) shop_product.visibility_limit = ProductVisibility.VISIBLE_TO_GROUPS shop_product.save() request = apply_request_middleware(rf.get("/"), user=admin_user) with replace_modules([ProductModule]): with admin_only_urls(): view_func = ProductEditView.as_view() response = view_func(request, pk=product.pk) assert (product.sku in response.rendered_content ) # it's probable the SKU is there response = view_func(request, pk=None) # "new mode" assert response.rendered_content # yeah, something gets rendered
def test_multilanguage_page_404_no_xlate(rf): # https://github.com/edoburu/django-parler/issues/50 cache.clear( ) # this is here, because parler cache is enabled and tests use same pk with page page = create_multilanguage_page( eternal=True, url="no_content", languages=("udm", )) # create page with udm language get_default_shop() request = apply_request_middleware(rf.get("/")) with translation.override("fi"): # change language of the page to fi view_func = PageView.as_view() with pytest.raises(Http404): response = view_func( request, url="no_content-udm" ) # Using Udmurt URL, but xlate is Finnish . . . assert response.status_code == 404 # ... should 404
def test_tax_edit_view_works_at_all(rf, admin_user): get_default_shop() # We need a shop to exists request = apply_request_middleware(rf.get("/")) request.user = admin_user default_tax_class = get_default_tax_class() with replace_modules([TaxModule]): with admin_only_urls(): view_func = TaxClassEditView.as_view() response = view_func(request, pk=default_tax_class.pk) response.render() assert (default_tax_class.name in force_text(response.content)) response = view_func(request, pk=None) # "new mode" response.render() assert response.content
def test_package(): shop = get_default_shop() supplier = get_default_supplier() package_product = create_product("PackageParent", shop=shop, supplier=supplier) assert not package_product.get_package_child_to_quantity_map() children = [ create_product("PackageChild-%d" % x, shop=shop, supplier=supplier) for x in range(4) ] package_def = {child: 1 + i for (i, child) in enumerate(children)} package_product.make_package(package_def) assert package_product.is_package_parent() package_product.save() sp = package_product.get_shop_instance(shop) assert not list( sp.get_orderability_errors( supplier=supplier, quantity=1, customer=AnonymousContact())) with pytest.raises(ValueError): # Test re-packaging fails package_product.make_package(package_def) # Check that OrderCreator can deal with packages source = BasketishOrderSource() source.lines.append( SourceLine( type=OrderLineType.PRODUCT, product=package_product, supplier=get_default_supplier(), quantity=10, unit_price=TaxlessPrice(10), )) source.shop = get_default_shop() source.status = get_initial_order_status() request = apply_request_middleware(RequestFactory().get("/")) creator = OrderCreator(request) order = creator.create_order(source) pids_to_quantities = order.get_product_ids_and_quantities() for child, quantity in six.iteritems(package_def): assert pids_to_quantities[child.pk] == 10 * quantity
def test_media_view_images(rf): get_default_shop() folder = Folder.objects.create(name="Root") file = File.objects.create(name="normalfile", folder=folder) img = Image.objects.create(name="imagefile", folder=folder) request = apply_request_middleware( rf.get("/", { "filter": "images", "action": "folder", "id": folder.id })) view_func = MediaBrowserView.as_view() response = view_func(request) assert isinstance(response, JsonResponse) content = json.loads(response.content.decode("utf-8")) assert len(content["folder"]["files"]) == 1 filedata = content["folder"]["files"][0] assert filedata["name"] == img.name
def test_package(): shop = get_default_shop() supplier = get_default_supplier() package_product = create_product("PackageParent", shop=shop, supplier=supplier) assert not package_product.get_package_child_to_quantity_map() children = [create_product("PackageChild-%d" % x, shop=shop, supplier=supplier) for x in range(4)] package_def = {child: 1 + i for (i, child) in enumerate(children)} package_product.make_package(package_def) assert package_product.is_package_parent() package_product.save() sp = package_product.get_shop_instance(shop) assert not list(sp.get_orderability_errors(supplier=supplier, quantity=1, customer=AnonymousContact())) with pytest.raises(ValueError): # Test re-packaging fails package_product.make_package(package_def) # Check that OrderCreator can deal with packages source = BasketishOrderSource() source.lines.append(SourceLine( type=OrderLineType.PRODUCT, product=package_product, supplier=get_default_supplier(), quantity=10, unit_price=TaxlessPrice(10), )) source.shop = get_default_shop() source.status = get_initial_order_status() request = apply_request_middleware(RequestFactory().get("/")) creator = OrderCreator(request) order = creator.create_order(source) pids_to_quantities = order.get_product_ids_and_quantities() for child, quantity in six.iteritems(package_def): assert pids_to_quantities[child.pk] == 10 * quantity