Esempio n. 1
0
def test_basic_order_flow(with_company):
    create_default_order_statuses()
    n_orders_pre = Order.objects.count()
    populate_if_required()
    c = SmartClient()
    _populate_client_basket(c)

    addresses_path = reverse("shoop:checkout", kwargs={"phase": "addresses"})
    addresses_soup = c.soup(addresses_path)
    inputs = fill_address_inputs(addresses_soup, with_company=with_company)
    response = c.post(addresses_path, data=inputs)
    assert response.status_code == 302  # Should redirect forth

    methods_path = reverse("shoop:checkout", kwargs={"phase": "methods"})
    methods_soup = c.soup(methods_path)
    assert c.post(methods_path, data=extract_form_fields(
        methods_soup)).status_code == 302  # Should redirect forth

    confirm_path = reverse("shoop:checkout", kwargs={"phase": "confirm"})
    confirm_soup = c.soup(confirm_path)
    assert c.post(confirm_path, data=extract_form_fields(
        confirm_soup)).status_code == 302  # Should redirect forth

    n_orders_post = Order.objects.count()
    assert n_orders_post > n_orders_pre, "order was created"
Esempio n. 2
0
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
Esempio n. 3
0
def fill_address_inputs(soup, with_company=False):
    inputs = {}
    test_address = get_address()
    for key, value in extract_form_fields(soup.find('form',
                                                    id='addresses')).items():
        if not value:
            if key in ("order-tax_number", "order-company_name"):
                continue
            if key.startswith("shipping-") or key.startswith("billing-"):
                bit = key.split("-")[1]
                value = getattr(test_address, bit, None)
            if not value and "email" in key:
                value = "*****@*****.**" % random.random()
            if not value:
                value = "test"
        inputs[key] = value

    if with_company:
        inputs["company-tax_number"] = "FI1234567-1"
        inputs["company-company_name"] = "Example Oy"
    else:
        inputs = dict((k, v) for (k, v) in inputs.items()
                      if not k.startswith("company-"))

    return inputs
Esempio n. 4
0
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
Esempio n. 6
0
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
Esempio n. 7
0
def test_basic_order_flow(with_company):
    create_default_order_statuses()
    n_orders_pre = Order.objects.count()
    populate_if_required()
    c = SmartClient()
    _populate_client_basket(c)

    addresses_path = reverse("shoop:checkout", kwargs={"phase": "addresses"})
    addresses_soup = c.soup(addresses_path)
    inputs = fill_address_inputs(addresses_soup, with_company=with_company)
    response = c.post(addresses_path, data=inputs)
    assert response.status_code == 302  # Should redirect forth

    methods_path = reverse("shoop:checkout", kwargs={"phase": "methods"})
    methods_soup = c.soup(methods_path)
    assert c.post(methods_path, data=extract_form_fields(methods_soup)).status_code == 302  # Should redirect forth

    confirm_path = reverse("shoop:checkout", kwargs={"phase": "confirm"})
    confirm_soup = c.soup(confirm_path)
    assert c.post(confirm_path, data=extract_form_fields(confirm_soup)).status_code == 302  # Should redirect forth

    n_orders_post = Order.objects.count()
    assert n_orders_post > n_orders_pre, "order was created"
Esempio n. 8
0
def _populate_client_basket(client):
    index = client.soup("/")
    product_links = index.find_all("a", rel="product-detail")
    assert product_links
    product_detail_path = product_links[0]["href"]
    assert product_detail_path
    product_detail_soup = client.soup(product_detail_path)
    inputs = extract_form_fields(product_detail_soup)
    basket_path = reverse("shoop:basket")
    for i in range(3):  # Add the same product thrice
        add_to_basket_resp = client.post(basket_path, data={
            "command": "add",
            "product_id": inputs["product_id"],
            "quantity": 1,
            "supplier": get_default_supplier().pk
        })
        assert add_to_basket_resp.status_code < 400
    basket_soup = client.soup(basket_path)
    assert b'no such element' not in basket_soup.renderContents(), 'All product details are not rendered correctly'
Esempio n. 9
0
def _populate_client_basket(client):
    index = client.soup("/")
    product_links = index.find_all("a", rel="product-detail")
    assert product_links
    product_detail_path = product_links[0]["href"]
    assert product_detail_path
    product_detail_soup = client.soup(product_detail_path)
    inputs = extract_form_fields(product_detail_soup)
    basket_path = reverse("shoop:basket")
    for i in range(3):  # Add the same product thrice
        add_to_basket_resp = client.post(basket_path, data={
            "command": "add",
            "product_id": inputs["product_id"],
            "quantity": 1,
            "supplier": get_default_supplier().pk
        })
        assert add_to_basket_resp.status_code < 400
    basket_soup = client.soup(basket_path)
    assert b'no such element' not in basket_soup.renderContents(), 'All product details are not rendered correctly'
Esempio n. 10
0
def test_new_user_information_edit():
    client = SmartClient()
    get_default_shop()
    # create new user
    user_password = "******"
    user = get_user_model().objects.create_user(
        username="******",
        email="*****@*****.**",
        password=user_password,
        first_name="Niilo",
        last_name="Nyyppä",
    )

    client.login(username=user.username, password=user_password)

    # make sure all information matches in form
    customer_edit_url = reverse("shoop:customer_edit")
    soup = client.soup(customer_edit_url)

    assert soup.find(attrs={"name": "contact-email"})["value"] == user.email
    assert soup.find(
        attrs={"name": "contact-first_name"})["value"] == user.first_name
    assert soup.find(
        attrs={"name": "contact-last_name"})["value"] == user.last_name

    # Test POSTing
    form = extract_form_fields(soup)
    new_email = "*****@*****.**"
    form["contact-email"] = new_email
    form["contact-country"] = "FI"

    for prefix in ("billing", "shipping"):
        form["%s-city" % prefix] = "test-city"
        form["%s-email" % prefix] = new_email
        form["%s-street" % prefix] = "test-street"
        form["%s-country" % prefix] = "FI"

    response, soup = client.response_and_soup(customer_edit_url, form, "post")

    assert response.status_code == 302
    assert get_user_model().objects.get(pk=user.pk).email == new_email
Esempio n. 11
0
def test_new_user_information_edit():
    client = SmartClient()
    get_default_shop()
    # create new user
    user_password = "******"
    user = get_user_model().objects.create_user(
        username="******",
        email="*****@*****.**",
        password=user_password,
        first_name="Niilo",
        last_name="Nyyppä",
    )

    client.login(username=user.username, password=user_password)

    # make sure all information matches in form
    customer_edit_url = reverse("shoop:customer_edit")
    soup = client.soup(customer_edit_url)

    assert soup.find(attrs={"name": "contact-email"})["value"] == user.email
    assert soup.find(attrs={"name": "contact-first_name"})["value"] == user.first_name
    assert soup.find(attrs={"name": "contact-last_name"})["value"] == user.last_name

    # Test POSTing
    form = extract_form_fields(soup)
    new_email = "*****@*****.**"
    form["contact-email"] = new_email
    form["contact-country"] = "FI"

    for prefix in ("billing", "shipping"):
        form["%s-city" % prefix] = "test-city"
        form["%s-email" % prefix] = new_email
        form["%s-street" % prefix] = "test-street"
        form["%s-country" % prefix] = "FI"

    response, soup = client.response_and_soup(customer_edit_url, form, "post")

    assert response.status_code == 302
    assert get_user_model().objects.get(pk=user.pk).email == new_email
Esempio n. 12
0
def fill_address_inputs(soup, with_company=False):
    inputs = {}
    test_address = get_address()
    for key, value in extract_form_fields(soup.find(method="post")).items():
        if not value:
            if key in ("order-vat_code", "order-company_name"):
                continue
            if key.startswith("shipping-") or key.startswith("billing-"):
                bit = key.split("-")[1]
                value = getattr(test_address, bit, None)
            if not value and "email" in key:
                value = "*****@*****.**" % random.random()
            if not value:
                value = "test"
        inputs[key] = value

    if with_company:
        inputs["company-vat_code"] = "FI1234567-1"
        inputs["company-company_name"] = "Example Oy"
    else:
        inputs = dict((k, v) for (k, v) in inputs.items() if not k.startswith("company-"))

    return inputs
Esempio n. 13
0
def test_order_flow_with_phases(get_shipping_method, shipping_data,
                                get_payment_method, payment_data):
    create_default_order_statuses()
    populate_if_required()
    c = SmartClient()
    _populate_client_basket(c)

    # Create methods
    shipping_method = get_shipping_method()
    payment_method = get_payment_method()

    # Resolve paths
    addresses_path = reverse("shoop:checkout", kwargs={"phase": "addresses"})
    methods_path = reverse("shoop:checkout", kwargs={"phase": "methods"})
    shipping_path = reverse("shoop:checkout", kwargs={"phase": "shipping"})
    payment_path = reverse("shoop:checkout", kwargs={"phase": "payment"})
    confirm_path = reverse("shoop:checkout", kwargs={"phase": "confirm"})

    # Phase: Addresses
    addresses_soup = c.soup(addresses_path)
    inputs = fill_address_inputs(addresses_soup, with_company=False)
    response = c.post(addresses_path, data=inputs)
    assert response.status_code == 302, "Address phase should redirect forth to methods"

    # Phase: Methods
    response = c.get(methods_path)
    assert response.status_code == 200
    response = c.post(methods_path,
                      data={
                          "shipping_method": shipping_method.pk,
                          "payment_method": payment_method.pk
                      })
    assert response.status_code == 302, "Methods phase should redirect forth"

    if isinstance(shipping_method.carrier, CarrierWithCheckoutPhase):
        # Phase: Shipping
        response = c.get(shipping_path)
        assert response.status_code == 200
        response = c.post(shipping_path, data=shipping_data)
        assert response.status_code == 302, "Payments phase should redirect forth"

    if isinstance(payment_method.payment_processor, PaymentWithCheckoutPhase):
        # Phase: payment
        response = c.get(payment_path)
        assert response.status_code == 200
        response = c.post(payment_path, data=payment_data)
        assert response.status_code == 302, "Payments phase should redirect forth"

    # Phase: Confirm
    assert Order.objects.count() == 0
    confirm_soup = c.soup(confirm_path)
    response = c.post(confirm_path, data=extract_form_fields(confirm_soup))
    assert response.status_code == 302, "Confirm should redirect forth"

    order = Order.objects.first()

    if isinstance(shipping_method.carrier, CarrierWithCheckoutPhase):
        assert order.shipping_data.get("input_value") == "20540"

    if isinstance(payment_method.payment_processor, PaymentWithCheckoutPhase):
        assert order.payment_data.get("input_value")
        assert order.payment_status == PaymentStatus.NOT_PAID
        # Resolve order specific paths (payment and complete)
        process_payment_path = reverse("shoop:order_process_payment",
                                       kwargs={
                                           "pk": order.pk,
                                           "key": order.key
                                       })
        process_payment_return_path = reverse(
            "shoop:order_process_payment_return",
            kwargs={
                "pk": order.pk,
                "key": order.key
            })
        order_complete_path = reverse("shoop:order_complete",
                                      kwargs={
                                          "pk": order.pk,
                                          "key": order.key
                                      })

        # Check confirm redirection to payment page
        assert response.url.endswith(process_payment_path), (
            "Confirm should have redirected to payment page")

        # Visit payment page
        response = c.get(process_payment_path)
        assert response.status_code == 302, "Payment page should redirect forth"
        assert response.url.endswith(process_payment_return_path)

        # Check payment return
        response = c.get(process_payment_return_path)
        assert response.status_code == 302, "Payment return should redirect forth"
        assert response.url.endswith(order_complete_path)

        # Check payment status has changed to DEFERRED
        order = Order.objects.get(pk=order.pk)  # reload
        assert order.payment_status == PaymentStatus.DEFERRED
Esempio n. 14
0
def test_order_flow_with_payment_phase():
    create_default_order_statuses()
    n_orders_pre = Order.objects.count()
    populate_if_required()
    c = SmartClient()
    _populate_client_basket(c)

    # Create methods
    shipping_method = get_default_shipping_method()
    processor = PaymentWithCheckoutPhase.objects.create(identifier="processor_with_phase", enabled=True)
    assert isinstance(processor, PaymentWithCheckoutPhase)
    payment_method = 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(),
    )

    # Resolve paths
    addresses_path = reverse("shoop:checkout", kwargs={"phase": "addresses"})
    methods_path = reverse("shoop:checkout", kwargs={"phase": "methods"})
    payment_path = reverse("shoop:checkout", kwargs={"phase": "payment"})
    confirm_path = reverse("shoop:checkout", kwargs={"phase": "confirm"})

    # Phase: Addresses
    addresses_soup = c.soup(addresses_path)
    inputs = fill_address_inputs(addresses_soup, with_company=False)
    response = c.post(addresses_path, data=inputs)
    assert response.status_code == 302, "Address phase should redirect forth"
    assert response.url.endswith(methods_path)

    # Phase: Methods
    assert Order.objects.filter(payment_method=payment_method).count() == 0
    response = c.post(methods_path, data={"payment_method": payment_method.pk, "shipping_method": shipping_method.pk})
    assert response.status_code == 302, "Methods phase should redirect forth"
    assert response.url.endswith(confirm_path)
    response = c.get(confirm_path)
    assert response.status_code == 302, "Confirm should first redirect forth"
    assert response.url.endswith(payment_path)

    # Phase: Payment
    c.soup(payment_path)
    response = c.post(payment_path, data={"will_pay": False})
    assert response.status_code == 200, "Invalid payment form should return error"
    response = c.post(payment_path, data={"will_pay": True})
    assert response.status_code == 302, "Valid payment form should redirect forth"
    assert response.url.endswith(confirm_path)

    # Phase: Confirm
    confirm_soup = c.soup(confirm_path)
    response = c.post(confirm_path, data=extract_form_fields(confirm_soup))
    assert response.status_code == 302, "Confirm should redirect forth"
    # response.url should point to payment, checked below

    # Check resulting order and its contents
    n_orders_post = Order.objects.count()
    assert n_orders_post > n_orders_pre, "order was created"
    order = Order.objects.filter(payment_method=payment_method).first()
    assert order.payment_data.get("promised_to_pay")
    assert order.payment_status == PaymentStatus.NOT_PAID

    # Resolve order specific paths (payment and complete)
    process_payment_path = reverse("shoop:order_process_payment", kwargs={"pk": order.pk, "key": order.key})
    process_payment_return_path = reverse(
        "shoop:order_process_payment_return", kwargs={"pk": order.pk, "key": order.key}
    )
    order_complete_path = reverse("shoop:order_complete", kwargs={"pk": order.pk, "key": order.key})

    # Check confirm redirection to payment page
    assert response.url.endswith(process_payment_path), "Confirm should have redirected to payment page"

    # Visit payment page
    response = c.get(process_payment_path)
    assert response.status_code == 302, "Payment page should redirect forth"
    assert response.url.endswith(process_payment_return_path)

    # Check payment return
    response = c.get(process_payment_return_path)
    assert response.status_code == 302, "Payment return should redirect forth"
    assert response.url.endswith(order_complete_path)

    # Check payment status has changed to DEFERRED
    order = Order.objects.get(pk=order.pk)  # reload
    assert order.payment_status == PaymentStatus.DEFERRED
Esempio n. 15
0
def test_order_flow_with_phases(get_shipping_method, shipping_data, get_payment_method, payment_data):
    create_default_order_statuses()
    populate_if_required()
    c = SmartClient()
    _populate_client_basket(c)

    # Create methods
    shipping_method = get_shipping_method()
    payment_method = get_payment_method()

    # Resolve paths
    addresses_path = reverse("shoop:checkout", kwargs={"phase": "addresses"})
    methods_path = reverse("shoop:checkout", kwargs={"phase": "methods"})
    shipping_path = reverse("shoop:checkout", kwargs={"phase": "shipping"})
    payment_path = reverse("shoop:checkout", kwargs={"phase": "payment"})
    confirm_path = reverse("shoop:checkout", kwargs={"phase": "confirm"})

    # Phase: Addresses
    addresses_soup = c.soup(addresses_path)
    inputs = fill_address_inputs(addresses_soup, with_company=False)
    response = c.post(addresses_path, data=inputs)
    assert response.status_code == 302, "Address phase should redirect forth to methods"

    # Phase: Methods
    response = c.get(methods_path)
    assert response.status_code == 200
    response = c.post(
        methods_path,
        data={
            "shipping_method": shipping_method.pk,
            "payment_method": payment_method.pk
        }
    )
    assert response.status_code == 302, "Methods phase should redirect forth"

    if isinstance(shipping_method.carrier, CarrierWithCheckoutPhase):
        # Phase: Shipping
        response = c.get(shipping_path)
        assert response.status_code == 200
        response = c.post(shipping_path, data=shipping_data)
        assert response.status_code == 302, "Payments phase should redirect forth"

    if isinstance(payment_method.payment_processor, PaymentWithCheckoutPhase):
        # Phase: payment
        response = c.get(payment_path)
        assert response.status_code == 200
        response = c.post(payment_path, data=payment_data)
        assert response.status_code == 302, "Payments phase should redirect forth"

    # Phase: Confirm
    assert Order.objects.count() == 0
    confirm_soup = c.soup(confirm_path)
    response = c.post(confirm_path, data=extract_form_fields(confirm_soup))
    assert response.status_code == 302, "Confirm should redirect forth"

    order = Order.objects.first()

    if isinstance(shipping_method.carrier, CarrierWithCheckoutPhase):
        assert order.shipping_data.get("input_value") == "20540"

    if isinstance(payment_method.payment_processor, PaymentWithCheckoutPhase):
        assert order.payment_data.get("input_value")
        assert order.payment_status == PaymentStatus.NOT_PAID
        # Resolve order specific paths (payment and complete)
        process_payment_path = reverse(
            "shoop:order_process_payment",
            kwargs={"pk": order.pk, "key": order.key})
        process_payment_return_path = reverse(
            "shoop:order_process_payment_return",
            kwargs={"pk": order.pk, "key": order.key})
        order_complete_path = reverse(
            "shoop:order_complete",
            kwargs={"pk": order.pk, "key": order.key})

        # Check confirm redirection to payment page
        assert response.url.endswith(process_payment_path), (
            "Confirm should have redirected to payment page")

        # Visit payment page
        response = c.get(process_payment_path)
        assert response.status_code == 302, "Payment page should redirect forth"
        assert response.url.endswith(process_payment_return_path)

        # Check payment return
        response = c.get(process_payment_return_path)
        assert response.status_code == 302, "Payment return should redirect forth"
        assert response.url.endswith(order_complete_path)

        # Check payment status has changed to DEFERRED
        order = Order.objects.get(pk=order.pk)  # reload
        assert order.payment_status == PaymentStatus.DEFERRED
Esempio n. 16
0
def test_order_flow_with_payment_phase():
    create_default_order_statuses()
    n_orders_pre = Order.objects.count()
    populate_if_required()
    c = SmartClient()
    _populate_client_basket(c)

    # Create methods
    shipping_method = get_default_shipping_method()
    processor = PaymentWithCheckoutPhase.objects.create(
        identifier="processor_with_phase", enabled=True)
    assert isinstance(processor, PaymentWithCheckoutPhase)
    payment_method = 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())

    # Resolve paths
    addresses_path = reverse("shoop:checkout", kwargs={"phase": "addresses"})
    methods_path = reverse("shoop:checkout", kwargs={"phase": "methods"})
    payment_path = reverse("shoop:checkout", kwargs={"phase": "payment"})
    confirm_path = reverse("shoop:checkout", kwargs={"phase": "confirm"})

    # Phase: Addresses
    addresses_soup = c.soup(addresses_path)
    inputs = fill_address_inputs(addresses_soup, with_company=False)
    response = c.post(addresses_path, data=inputs)
    assert response.status_code == 302, "Address phase should redirect forth"
    assert response.url.endswith(methods_path)

    # Phase: Methods
    assert Order.objects.filter(payment_method=payment_method).count() == 0
    response = c.post(methods_path,
                      data={
                          "payment_method": payment_method.pk,
                          "shipping_method": shipping_method.pk
                      })
    assert response.status_code == 302, "Methods phase should redirect forth"
    assert response.url.endswith(confirm_path)
    response = c.get(confirm_path)
    assert response.status_code == 302, "Confirm should first redirect forth"
    assert response.url.endswith(payment_path)

    # Phase: Payment
    c.soup(payment_path)
    response = c.post(payment_path, data={"will_pay": False})
    assert response.status_code == 200, "Invalid payment form should return error"
    response = c.post(payment_path, data={"will_pay": True})
    assert response.status_code == 302, "Valid payment form should redirect forth"
    assert response.url.endswith(confirm_path)

    # Phase: Confirm
    confirm_soup = c.soup(confirm_path)
    response = c.post(confirm_path, data=extract_form_fields(confirm_soup))
    assert response.status_code == 302, "Confirm should redirect forth"
    # response.url should point to payment, checked below

    # Check resulting order and its contents
    n_orders_post = Order.objects.count()
    assert n_orders_post > n_orders_pre, "order was created"
    order = Order.objects.filter(payment_method=payment_method).first()
    assert order.payment_data.get("promised_to_pay")
    assert order.payment_status == PaymentStatus.NOT_PAID

    # Resolve order specific paths (payment and complete)
    process_payment_path = reverse("shoop:order_process_payment",
                                   kwargs={
                                       "pk": order.pk,
                                       "key": order.key
                                   })
    process_payment_return_path = reverse("shoop:order_process_payment_return",
                                          kwargs={
                                              "pk": order.pk,
                                              "key": order.key
                                          })
    order_complete_path = reverse("shoop:order_complete",
                                  kwargs={
                                      "pk": order.pk,
                                      "key": order.key
                                  })

    # Check confirm redirection to payment page
    assert response.url.endswith(process_payment_path), (
        "Confirm should have redirected to payment page")

    # Visit payment page
    response = c.get(process_payment_path)
    assert response.status_code == 302, "Payment page should redirect forth"
    assert response.url.endswith(process_payment_return_path)

    # Check payment return
    response = c.get(process_payment_return_path)
    assert response.status_code == 302, "Payment return should redirect forth"
    assert response.url.endswith(order_complete_path)

    # Check payment status has changed to DEFERRED
    order = Order.objects.get(pk=order.pk)  # reload
    assert order.payment_status == PaymentStatus.DEFERRED