Example #1
0
def test_remove_unavailable_variants(checkout, product):
    variant = product.variants.get()
    add_variant_to_checkout(checkout, variant)
    variant.quantity = 0
    variant.save()
    utils.remove_unavailable_variants(checkout)
    assert len(checkout) == 0
Example #2
0
def test_checkout_lines_update_remove_shipping_if_removed_product_with_shipping(
        user_api_client, checkout_with_item, digital_content, address,
        shipping_method):
    checkout = checkout_with_item
    digital_variant = digital_content.product_variant
    checkout.shipping_address = address
    checkout.shipping_method = shipping_method
    checkout.save()
    add_variant_to_checkout(checkout, digital_variant, 1)
    line = checkout.lines.first()
    variant = line.variant

    variant_id = graphene.Node.to_global_id("ProductVariant", variant.pk)
    checkout_id = graphene.Node.to_global_id("Checkout", checkout.pk)

    variables = {
        "checkoutId": checkout_id,
        "lines": [{
            "variantId": variant_id,
            "quantity": 0
        }],
    }
    response = user_api_client.post_graphql(MUTATION_CHECKOUT_LINES_UPDATE,
                                            variables)
    content = get_graphql_content(response)

    data = content["data"]["checkoutLinesUpdate"]
    assert not data["checkoutErrors"]
    checkout.refresh_from_db()
    assert checkout.lines.count() == 1
    assert not checkout.shipping_method
def checkout_with_voucher(checkout, product, voucher):
    variant = product.variants.get()
    add_variant_to_checkout(checkout, variant, 3)
    checkout.voucher_code = voucher.code
    checkout.discount_amount = Money('20.00', 'USD')
    checkout.save()
    return checkout
Example #4
0
def test_calculate_checkout_subtotal(
    site_settings,
    vatlayer,
    checkout_with_item,
    address,
    shipping_zone,
    discount_info,
    with_discount,
    expected_net,
    expected_gross,
    taxes_in_prices,
    variant,
):
    site_settings.include_taxes_in_prices = taxes_in_prices
    site_settings.save()

    checkout_with_item.shipping_address = address
    checkout_with_item.shipping_method = shipping_zone.shipping_methods.get()
    checkout_with_item.save()

    manager = get_extensions_manager(
        plugins=["saleor.extensions.plugins.vatlayer.plugin.VatlayerPlugin"])

    product = variant.product
    manager.assign_tax_code_to_object_meta(product, "standard")
    product.save()

    discounts = [discount_info] if with_discount else None
    add_variant_to_checkout(checkout_with_item, variant, 2)
    total = manager.calculate_checkout_subtotal(checkout_with_item, discounts)
    total = quantize_price(total, total.currency)
    assert total == TaxedMoney(net=Money(expected_net, "USD"),
                               gross=Money(expected_gross, "USD"))
Example #5
0
def test_add_to_checkout_form(checkout, product):
    variant = product.variants.get()
    add_variant_to_checkout(checkout, variant, 3)
    data = {'quantity': 1}
    form = forms.AddToCheckoutForm(data=data,
                                   checkout=checkout,
                                   product=product)

    form.get_variant = Mock(return_value=variant)

    assert form.is_valid()
    form.save()
    assert checkout.lines.count() == 1
    assert checkout.lines.filter(variant=variant).exists()

    with pytest.raises(NotImplementedError):
        data = {'quantity': 1}
        form = forms.AddToCheckoutForm(data=data,
                                       checkout=checkout,
                                       product=product)
        form.is_valid()
    data = {}

    form = forms.AddToCheckoutForm(data=data,
                                   checkout=checkout,
                                   product=product)
    assert not form.is_valid()
Example #6
0
def test_remove_unavailable_variants(checkout, product):
    variant = product.variants.get()
    add_variant_to_checkout(checkout, variant)
    variant.quantity = 0
    variant.save()
    utils.remove_unavailable_variants(checkout)
    assert len(checkout) == 0
Example #7
0
def checkout_with_voucher_percentage(checkout, product, voucher_percentage):
    variant = product.variants.get()
    add_variant_to_checkout(checkout, variant, 3)
    checkout.voucher_code = voucher_percentage.code
    checkout.discount = Money("3.00", "USD")
    checkout.save()
    return checkout
Example #8
0
def checkout_with_items(checkout, product_list, product):
    variant = product.variants.get()
    add_variant_to_checkout(checkout, variant, 1)
    for prod in product_list:
        variant = prod.variants.get()
        add_variant_to_checkout(checkout, variant, 1)
    return checkout
Example #9
0
def checkout_with_digital_item(checkout, digital_content):
    """Create a checkout with a digital line."""
    variant = digital_content.product_variant
    add_variant_to_checkout(checkout, variant, 1)
    checkout.email = "*****@*****.**"
    checkout.save()
    return checkout
Example #10
0
def test_calculate_checkout_subtotal(
    with_discount,
    expected_net,
    expected_gross,
    taxes_in_prices,
    discount_info,
    checkout_with_item,
    variant,
    monkeypatch,
    site_settings,
    address_usa,
    shipping_zone,
    address,
):
    monkeypatch.setattr(
        "saleor.core.taxes.avatax.interface.get_cached_tax_codes_or_fetch",
        lambda: {"PC040156": "desc"},
    )

    site_settings.company_address = address_usa
    site_settings.include_taxes_in_prices = taxes_in_prices
    site_settings.save()

    checkout_with_item.address = address
    checkout_with_item.shipping_method = shipping_zone.shipping_methods.get()
    checkout_with_item.save()

    discounts = [discount_info] if with_discount else None
    add_variant_to_checkout(checkout_with_item, variant, 2)
    total = interface.calculate_checkout_subtotal(checkout_with_item,
                                                  discounts)
    total = quantize_price(total, total.currency)
    assert total == TaxedMoney(net=Money(expected_net, "USD"),
                               gross=Money(expected_gross, "USD"))
def test_calculate_checkout_total(
    reset_sequences,  # pylint: disable=unused-argument
    with_discount,
    expected_net,
    expected_gross,
    voucher_amount,
    taxes_in_prices,
    checkout_with_item,
    product_with_single_variant,
    discount_info,
    shipping_zone,
    address_usa_tx,
    address_usa,
    site_settings,
    monkeypatch,
    plugin_configuration,
    non_default_category,
):
    plugin_configuration()
    # Required ATE variant data
    metadata = {
        get_metadata_key("UnitQuantity"): 1,
    }
    ProductVariant.objects.filter(sku="SKU_SINGLE_VARIANT").update(
        sku="202127000", private_metadata=metadata)
    monkeypatch.setattr(
        "saleor.plugins.avatax.excise.plugin.AvataxExcisePlugin._skip_plugin",
        lambda *_: False,
    )
    manager = get_plugins_manager()
    checkout_with_item.shipping_address = address_usa_tx
    checkout_with_item.save()
    site_settings.company_address = address_usa
    site_settings.include_taxes_in_prices = taxes_in_prices
    site_settings.save()

    voucher_amount = Money(voucher_amount, "USD")
    checkout_with_item.shipping_method = shipping_zone.shipping_methods.get()
    checkout_with_item.discount = voucher_amount
    checkout_with_item.save()

    product_with_single_variant.charge_taxes = False
    product_with_single_variant.category = non_default_category
    product_with_single_variant.save()
    discounts = [discount_info] if with_discount else None
    discount_amount = Decimal("1.00") if with_discount else Decimal("0.00")
    checkout_with_item.discount_amount = discount_amount
    checkout_info = fetch_checkout_info(checkout_with_item, [], discounts,
                                        manager)

    add_variant_to_checkout(checkout_info,
                            product_with_single_variant.variants.get())

    lines = fetch_checkout_lines(checkout_with_item)
    total = manager.calculate_checkout_total(checkout_info, lines,
                                             address_usa_tx, discounts)
    total = quantize_price(total, total.currency)
    assert total == TaxedMoney(net=Money(expected_net, "USD"),
                               gross=Money(expected_gross, "USD"))
Example #12
0
def test_adding_same_variant(checkout, product):
    variant = product.variants.get()
    add_variant_to_checkout(checkout, variant, 1)
    add_variant_to_checkout(checkout, variant, 2)
    assert len(checkout) == 1
    assert checkout.quantity == 3
    subtotal = Money("30.00", "USD")
    assert checkout.get_subtotal() == subtotal
Example #13
0
def test_adding_same_variant(checkout, product):
    variant = product.variants.get()
    add_variant_to_checkout(checkout, variant, 1)
    add_variant_to_checkout(checkout, variant, 2)
    assert checkout.lines.count() == 1
    assert checkout.quantity == 3
    subtotal = TaxedMoney(Money("30.00", "USD"), Money("30.00", "USD"))
    assert calculations.checkout_subtotal(checkout) == subtotal
Example #14
0
def test_adding_same_variant(checkout, product, taxes):
    variant = product.variants.get()
    add_variant_to_checkout(checkout, variant, 1)
    add_variant_to_checkout(checkout, variant, 2)
    assert len(checkout) == 1
    assert checkout.quantity == 3
    checkout_total = TaxedMoney(net=Money("24.39", "USD"), gross=Money(30, "USD"))
    assert checkout.get_subtotal(taxes=taxes) == checkout_total
Example #15
0
def test_adding_same_variant(checkout, product, taxes):
    variant = product.variants.get()
    add_variant_to_checkout(checkout, variant, 1)
    add_variant_to_checkout(checkout, variant, 2)
    assert len(checkout) == 1
    assert checkout.quantity == 3
    checkout_total = TaxedMoney(net=Money('24.39', 'USD'), gross=Money(30, 'USD'))
    assert checkout.get_subtotal(taxes=taxes) == checkout_total
Example #16
0
def test_view_checkout_shipping_method_without_shipping(
        request_checkout, product_without_shipping, client):
    variant = product_without_shipping.variants.get()
    add_variant_to_checkout(request_checkout, variant)
    url = reverse("checkout:shipping-method")

    response = client.get(url)

    assert response.status_code == 302
    assert get_redirect_location(response) == reverse("checkout:summary")
Example #17
0
def test_replace_checkout_line_form(checkout, product):
    variant = product.variants.get()
    initial_quantity = 1
    replaced_quantity = 4

    add_variant_to_checkout(checkout, variant, initial_quantity)
    data = {"quantity": replaced_quantity}
    form = forms.ReplaceCheckoutLineForm(data=data, checkout=checkout, variant=variant)
    assert form.is_valid()
    form.save()
    assert checkout.quantity == replaced_quantity
Example #18
0
def test_view_checkout_shipping_method_without_shipping(
    request_checkout, product_without_shipping, client
):
    variant = product_without_shipping.variants.get()
    add_variant_to_checkout(request_checkout, variant)
    url = reverse("checkout:shipping-method")

    response = client.get(url)

    assert response.status_code == 302
    assert get_redirect_location(response) == reverse("checkout:summary")
def test_view_invalid_add_to_checkout(client, product, request_checkout):
    variant = product.variants.get()
    add_variant_to_checkout(request_checkout, variant, 2)
    response = client.post(
        reverse('product:add-to-checkout',
                kwargs={
                    'slug': product.get_slug(),
                    'product_id': product.pk
                }), {})
    assert response.status_code == 200
    assert request_checkout.quantity == 2
Example #20
0
def test_replace_checkout_line_form(checkout, product):
    variant = product.variants.get()
    initial_quantity = 1
    replaced_quantity = 4

    add_variant_to_checkout(checkout, variant, initial_quantity)
    data = {"quantity": replaced_quantity}
    form = forms.ReplaceCheckoutLineForm(data=data, checkout=checkout, variant=variant)
    assert form.is_valid()
    form.save()
    assert checkout.quantity == replaced_quantity
Example #21
0
def test_create_order_insufficient_stock(
    request_checkout, customer_user, product_without_shipping
):
    variant = product_without_shipping.variants.get()
    add_variant_to_checkout(request_checkout, variant, 10, check_quantity=False)
    request_checkout.user = customer_user
    request_checkout.billing_address = customer_user.default_billing_address
    request_checkout.shipping_address = customer_user.default_billing_address
    request_checkout.save()

    with pytest.raises(InsufficientStock):
        prepare_order_data(
            checkout=request_checkout, tracking_code="tracking_code", discounts=None
        )
Example #22
0
def test_view_add_to_checkout(authorized_client, product, user_checkout):
    variant = product.variants.first()

    # Ignore stock
    variant.track_inventory = False
    variant.save()

    # Add the variant to the user checkout and retrieve the variant line
    add_variant_to_checkout(user_checkout, variant)
    checkout_line = user_checkout.lines.last()

    # Retrieve the test url
    checkout_url = reverse(
        "product:add-to-checkout",
        kwargs={
            "slug": product.get_slug(),
            "product_id": product.pk
        },
    )

    # Attempt to set the quantity to 50
    response = authorized_client.post(
        checkout_url,
        {
            "quantity": 49,
            "variant": variant.pk
        },
        HTTP_X_REQUESTED_WITH="XMLHttpRequest",
    )  # type: JsonResponse
    assert response.status_code == 200

    # Ensure the line quantity was updated to 50
    checkout_line.refresh_from_db(fields=["quantity"])
    assert checkout_line.quantity == 50

    # Attempt to increase the quantity to a too high count
    response = authorized_client.post(
        checkout_url,
        {
            "quantity": 1,
            "variant": variant.pk
        },
        HTTP_X_REQUESTED_WITH="XMLHttpRequest",
    )
    assert response.status_code == 400

    # Ensure the line quantity was not updated to 51
    checkout_line.refresh_from_db(fields=["quantity"])
    assert checkout_line.quantity == 50
Example #23
0
def test_calculate_checkout_subtotal(
    with_discount,
    expected_net,
    expected_gross,
    discount_info,
    checkout_with_item,
    variant,
):
    discounts = [discount_info] if with_discount else None
    add_variant_to_checkout(checkout_with_item, variant, 2)
    total = interface.calculate_checkout_subtotal(checkout_with_item, discounts)

    assert total == TaxedMoney(
        net=Money(expected_net, "USD"), gross=Money(expected_gross, "USD")
    )
Example #24
0
def test_create_order_insufficient_stock(
    request_checkout, customer_user, product_without_shipping
):
    variant = product_without_shipping.variants.get()
    add_variant_to_checkout(request_checkout, variant, 10, check_quantity=False)
    request_checkout.user = customer_user
    request_checkout.billing_address = customer_user.default_billing_address
    request_checkout.shipping_address = customer_user.default_billing_address
    request_checkout.save()

    with pytest.raises(InsufficientStock):
        create_order(
            request_checkout,
            "tracking_code",
            discounts=None,
            taxes=None,
            user=customer_user,
        )
Example #25
0
def test_replace_checkout_line_form_when_insufficient_stock(
        monkeypatch, checkout, product):
    variant = product.variants.get()
    initial_quantity = 1
    replaced_quantity = 4

    add_variant_to_checkout(checkout, variant, initial_quantity)
    exception_mock = InsufficientStock(Mock(quantity_available=2))
    monkeypatch.setattr('saleor.product.models.ProductVariant.check_quantity',
                        Mock(side_effect=exception_mock))
    data = {'quantity': replaced_quantity}
    form = forms.ReplaceCheckoutLineForm(data=data,
                                         checkout=checkout,
                                         variant=variant)
    assert not form.is_valid()
    with pytest.raises(KeyError):
        form.save()
    assert checkout.quantity == initial_quantity
Example #26
0
def test_get_prices_of_discounted_specific_product_only_product(
    checkout_with_item, voucher_specific_product_type, product_with_default_variant
):
    checkout = checkout_with_item
    voucher = voucher_specific_product_type
    line = checkout.lines.first()
    product = line.variant.product
    product2 = product_with_default_variant

    add_variant_to_checkout(checkout, product2.variants.get(), 1)
    voucher.products.add(product)

    prices = utils.get_prices_of_discounted_specific_product(checkout, voucher)

    excepted_value = [line.variant.get_price() for item in range(line.quantity)]

    assert checkout.lines.count() > 1
    assert prices == excepted_value
Example #27
0
def test_replace_checkout_line_form_when_insufficient_stock(
    monkeypatch, checkout, product
):
    variant = product.variants.get()
    initial_quantity = 1
    replaced_quantity = 4

    add_variant_to_checkout(checkout, variant, initial_quantity)
    exception_mock = InsufficientStock(Mock(quantity_available=2))
    monkeypatch.setattr(
        "saleor.product.models.ProductVariant.check_quantity",
        Mock(side_effect=exception_mock),
    )
    data = {"quantity": replaced_quantity}
    form = forms.ReplaceCheckoutLineForm(data=data, checkout=checkout, variant=variant)
    assert not form.is_valid()
    with pytest.raises(KeyError):
        form.save()
    assert checkout.quantity == initial_quantity
Example #28
0
def test_check_product_availability_and_warn(monkeypatch, checkout, product):
    variant = product.variants.get()
    add_variant_to_checkout(checkout, variant)
    monkeypatch.setattr('django.contrib.messages.warning',
                        Mock(warning=Mock()))
    monkeypatch.setattr('saleor.checkout.utils.contains_unavailable_variants',
                        Mock(return_value=False))

    utils.check_product_availability_and_warn(MagicMock(), checkout)
    assert len(checkout) == 1

    monkeypatch.setattr('saleor.checkout.utils.contains_unavailable_variants',
                        Mock(return_value=True))
    monkeypatch.setattr(
        'saleor.checkout.utils.remove_unavailable_variants',
        lambda c: add_variant_to_checkout(checkout, variant, 0, replace=True))

    utils.check_product_availability_and_warn(MagicMock(), checkout)
    assert len(checkout) == 0
Example #29
0
def test_add_to_checkout_form(checkout, product):
    variant = product.variants.get()
    add_variant_to_checkout(checkout, variant, 3)
    data = {"quantity": 1}
    form = forms.AddToCheckoutForm(data=data, checkout=checkout, product=product)

    form.get_variant = Mock(return_value=variant)

    assert form.is_valid()
    form.save()
    assert checkout.lines.count() == 1
    assert checkout.lines.filter(variant=variant).exists()

    with pytest.raises(NotImplementedError):
        data = {"quantity": 1}
        form = forms.AddToCheckoutForm(data=data, checkout=checkout, product=product)
        form.is_valid()
    data = {}

    form = forms.AddToCheckoutForm(data=data, checkout=checkout, product=product)
    assert not form.is_valid()
Example #30
0
def test_check_product_availability_and_warn(monkeypatch, checkout, product):
    variant = product.variants.get()
    add_variant_to_checkout(checkout, variant)
    monkeypatch.setattr("django.contrib.messages.warning", Mock(warning=Mock()))
    monkeypatch.setattr(
        "saleor.checkout.utils.contains_unavailable_variants", Mock(return_value=False)
    )

    utils.check_product_availability_and_warn(MagicMock(), checkout)
    assert len(checkout) == 1

    monkeypatch.setattr(
        "saleor.checkout.utils.contains_unavailable_variants", Mock(return_value=True)
    )
    monkeypatch.setattr(
        "saleor.checkout.utils.remove_unavailable_variants",
        lambda c: add_variant_to_checkout(checkout, variant, 0, replace=True),
    )

    utils.check_product_availability_and_warn(MagicMock(), checkout)
    assert len(checkout) == 0
Example #31
0
def test_get_prices_of_discounted_specific_product_only_category(
    checkout_with_item, voucher_specific_product_type, product_with_default_variant
):
    checkout = checkout_with_item
    voucher = voucher_specific_product_type
    line = checkout.lines.first()
    product = line.variant.product
    product2 = product_with_default_variant
    category = product.category
    category2 = Category.objects.create(name="Cat", slug="cat")

    product2.category = category2
    product2.save()
    add_variant_to_checkout(checkout, product2.variants.get(), 1)
    voucher.categories.add(category)

    prices = utils.get_prices_of_discounted_specific_product(checkout, voucher)

    excepted_value = [line.variant.get_price() for item in range(line.quantity)]

    assert checkout.lines.count() > 1
    assert prices == excepted_value
Example #32
0
def test_calculate_checkout_subtotal(
    with_discount,
    expected_net,
    expected_gross,
    taxes_in_prices,
    discount_info,
    checkout_with_item,
    stock,
    monkeypatch,
    site_settings,
    address_usa,
    shipping_zone,
    address,
    plugin_configuration,
):
    plugin_configuration()
    variant = stock.product_variant
    monkeypatch.setattr(
        "saleor.plugins.avatax.plugin.get_cached_tax_codes_or_fetch",
        lambda _: {"PC040156": "desc"},
    )
    manager = get_plugins_manager(
        plugins=["saleor.plugins.avatax.plugin.AvataxPlugin"])
    site_settings.company_address = address_usa
    site_settings.include_taxes_in_prices = taxes_in_prices
    site_settings.save()

    checkout_with_item.shipping_address = address
    checkout_with_item.shipping_method = shipping_zone.shipping_methods.get()
    checkout_with_item.save()

    discounts = [discount_info] if with_discount else None
    add_variant_to_checkout(checkout_with_item, variant, 2)
    total = manager.calculate_checkout_subtotal(checkout_with_item,
                                                list(checkout_with_item),
                                                discounts)
    total = quantize_price(total, total.currency)
    assert total == TaxedMoney(net=Money(expected_net, "USD"),
                               gross=Money(expected_gross, "USD"))
Example #33
0
def test_calculate_checkout_subtotal(
    with_discount,
    expected_net,
    expected_gross,
    taxes_in_prices,
    discount_info,
    checkout_with_item,
    variant,
    monkeypatch,
    site_settings,
    address_usa,
    shipping_zone,
    address,
    settings,
):
    settings.AVATAX_USERNAME_OR_ACCOUNT = "test"
    settings.AVATAX_PASSWORD_OR_LICENSE = "test"
    settings.PLUGINS = ["saleor.extensions.plugins.avatax.plugin.AvataxPlugin"]
    monkeypatch.setattr(
        "saleor.extensions.plugins.avatax.plugin.get_cached_tax_codes_or_fetch",
        lambda _: {"PC040156": "desc"},
    )
    manager = get_extensions_manager(plugins=settings.PLUGINS)
    site_settings.company_address = address_usa
    site_settings.include_taxes_in_prices = taxes_in_prices
    site_settings.save()

    checkout_with_item.shipping_address = address
    checkout_with_item.shipping_method = shipping_zone.shipping_methods.get()
    checkout_with_item.save()

    discounts = [discount_info] if with_discount else None
    add_variant_to_checkout(checkout_with_item, variant, 2)
    total = manager.calculate_checkout_subtotal(checkout_with_item, discounts)
    total = quantize_price(total, total.currency)
    assert total == TaxedMoney(
        net=Money(expected_net, "USD"), gross=Money(expected_gross, "USD")
    )
Example #34
0
def test_adding_without_checking(checkout, product):
    variant = product.variants.get()
    add_variant_to_checkout(checkout, variant, 1000, check_quantity=False)
    assert len(checkout) == 1
Example #35
0
def test_getting_line(checkout, product):
    variant = product.variants.get()
    assert checkout.get_line(variant) is None
    add_variant_to_checkout(checkout, variant)
    assert checkout.lines.get() == checkout.get_line(variant)
Example #36
0
def test_adding_zero_quantity(checkout, product):
    variant = product.variants.get()
    add_variant_to_checkout(checkout, variant, 0)
    assert len(checkout) == 0
Example #37
0
def test_shipping_detection(checkout, product):
    assert not checkout.is_shipping_required()
    variant = product.variants.get()
    add_variant_to_checkout(checkout, variant, replace=True)
    assert checkout.is_shipping_required()
Example #38
0
def test_adding_invalid_quantity(checkout, product):
    variant = product.variants.get()
    with pytest.raises(ValueError):
        add_variant_to_checkout(checkout, variant, -1)
Example #39
0
def checkout_with_item(checkout, product):
    variant = product.variants.get()
    add_variant_to_checkout(checkout, variant, 3)
    checkout.save()
    return checkout
Example #40
0
def test_shipping_detection(checkout, product):
    assert not checkout.is_shipping_required()
    variant = product.variants.get()
    add_variant_to_checkout(checkout, variant, replace=True)
    assert checkout.is_shipping_required()
Example #41
0
def request_checkout_with_item(product, request_checkout):
    variant = product.variants.get()
    add_variant_to_checkout(request_checkout, variant)
    return request_checkout
Example #42
0
def test_adding_invalid_quantity(checkout, product):
    variant = product.variants.get()
    with pytest.raises(ValueError):
        add_variant_to_checkout(checkout, variant, -1)
Example #43
0
def test_getting_line(checkout, product):
    variant = product.variants.get()
    assert checkout.get_line(variant) is None
    add_variant_to_checkout(checkout, variant)
    assert checkout.lines.get() == checkout.get_line(variant)
Example #44
0
def test_replacing_same_variant(checkout, product):
    variant = product.variants.get()
    add_variant_to_checkout(checkout, variant, 1, replace=True)
    add_variant_to_checkout(checkout, variant, 2, replace=True)
    assert len(checkout) == 1
    assert checkout.quantity == 2