Ejemplo n.º 1
0
def test_assopy_paypal(client):
    """
    This tests two views – paypal_feedback_ok and paypal_cancel.
    """
    user = auth_factories.UserFactory(email='*****@*****.**',
                                      is_active=True)
    assopy_user = AssopyUserFactory(user=user)

    order_code = 'asdf'
    order = Order(user=assopy_user, code=order_code, method='paypal')
    order.save()

    paypal_feedback_ok_url = reverse("assopy-paypal-feedback-ok",
                                     kwargs={'code': order_code})

    paypal_cancel_url = reverse("assopy-paypal-feedback-cancel",
                                kwargs={'code': order_code})

    response = client.get(paypal_cancel_url)

    make_sure_root_template_is_used(response, "assopy/paypal_cancel.html")
    make_sure_root_template_is_used(response, "assopy/base.html")
    make_sure_root_template_is_used(response, "p3/base.html")

    # @login_required is not enforced on any of those views, however feedback
    # has some manual checks builtin, so we need to to log in as a correct
    # user.
    client.login(email='*****@*****.**', password='******')
    response = client.get(paypal_feedback_ok_url)

    make_sure_root_template_is_used(response, "assopy/paypal_feedback_ok.html")
    make_sure_root_template_is_used(response, "assopy/base.html")
    make_sure_root_template_is_used(response, "p3/base.html")
Ejemplo n.º 2
0
    def setUp(self):
        self.conference = Conference.objects.create(
            code=settings.CONFERENCE_CONFERENCE,
            name=settings.CONFERENCE_CONFERENCE,
            # by default start with open CFP
            cfp_start=timezone.now() - timedelta(days=2),
            cfp_end=timezone.now() + timedelta(days=2))

        # default password is 'password123' per django_factory_boy
        admin = User.objects.create_superuser('admin', '*****@*****.**',
                                              'admin')
        AssopyUserFactory(user=admin)

        self.user = auth_factories.UserFactory(email='*****@*****.**',
                                               is_active=True)
        AssopyUserFactory(user=self.user)

        self.form_url = reverse("conference-paper-submission")
Ejemplo n.º 3
0
def test_change_password(client):
    """
    Testing full change password flow,

    1. Log in
    2. Look for change password url on the profile page
    3. Change the password.
    4. Log in with new password
    """

    # default password is 'password123' per django_factory_boy
    user = auth_factories.UserFactory(email='*****@*****.**',
                                      is_active=True)

    # both are required to access user profile page.
    AssopyUserFactory(user=user)
    AttendeeProfile.objects.create(user=user, slug='foobar')

    client.login(email='*****@*****.**', password='******')

    user_profile_url = reverse("assopy-profile")
    change_password_url = reverse("password_change")

    response = client.get(user_profile_url)
    assert "Change your password" in response.content.decode('utf-8')
    assert change_password_url in response.content.decode('utf-8')
    assert template_used(response, 'assopy/profile.html')

    response = client.get(change_password_url)
    assert template_used(response, "registration/password_change_form.html")
    assert 'Django Administration' not in response.content

    response = client.post(change_password_url, {
        'old_password': '******',
        'new_password1': 'pwd345',
        'new_password2': 'pwd345',
    },
                           follow=True)

    assert template_used(response, "registration/password_change_done.html")
    assert user_profile_url in response.content
    assert 'Password change successful' in response.content
    assert 'Go back to your profile' in response.content

    client.logout()

    can_log_in_with_new_password = client.login(email='*****@*****.**',
                                                password='******')
    assert can_log_in_with_new_password
Ejemplo n.º 4
0
 def setUp(self):
     self.conference = Conference.objects.create(
         code=settings.CONFERENCE_CONFERENCE,
         name=settings.CONFERENCE_CONFERENCE,
         # by default start with open CFP
         cfp_start=timezone.now() - timedelta(days=2),
         cfp_end=timezone.now()   + timedelta(days=2),
         voting_start=timezone.now() - timedelta(days=2),
         voting_end=timezone.now()   + timedelta(days=2)
     )
     self.user = auth_factories.UserFactory(
         email='*****@*****.**', is_active=True)
     AssopyUserFactory(user=self.user)
     self.talk = TalkFactory()
     TalkSpeakerFactory(speaker=SpeakerFactory(user=self.user))
     P3TalkFactory(talk=self.talk)
Ejemplo n.º 5
0
def test_assopy_profile(client):
    profile_url = reverse('assopy-profile')
    user = auth_factories.UserFactory(email='*****@*****.**',
                                      is_active=True)
    # both are required to access user profile page.
    AssopyUserFactory(user=user)
    AttendeeProfile.objects.create(user=user, slug='foobar')

    client.login(email='*****@*****.**', password='******')
    response = client.get(profile_url)

    make_sure_root_template_is_used(response, "assopy/profile.html")
    make_sure_root_template_is_used(response, "assopy/base.html")
    make_sure_root_template_is_used(response, "p3/base.html")

    # there are some includes used in this template, namely
    # profile_{email_contact,personal_data,spam_control}.html
    # those templates are also used in specific p3 views

    make_sure_root_template_is_used(response,
                                    "assopy/profile_email_contact.html")
    make_sure_root_template_is_used(response,
                                    "assopy/profile_personal_data.html")
    make_sure_root_template_is_used(response,
                                    "assopy/profile_spam_control.html")

    # also those templates are used in some p3 views, so adding some additional
    # checks for them.
    p3_account_spam_control_url = reverse('p3-account-spam-control')
    response = client.get(p3_account_spam_control_url)
    make_sure_root_template_is_used(response,
                                    "assopy/profile_spam_control.html")

    p3_account_email_url = reverse('p3-account-email')
    response = client.get(p3_account_email_url)
    make_sure_root_template_is_used(response,
                                    "assopy/profile_email_contact.html")

    p3_account_data_url = reverse('p3-account-data')
    response = client.get(p3_account_data_url)
    make_sure_root_template_is_used(response,
                                    "assopy/profile_personal_data.html")
Ejemplo n.º 6
0
def test_assopy_invoice(client):
    # default password is 'password123' per django_factory_boy
    user = auth_factories.UserFactory(email='*****@*****.**',
                                      is_active=True)
    assopy_user = AssopyUserFactory(user=user)
    client.login(email='*****@*****.**', password='******')

    # invoice_code must be validated via ASSOPY_IS_REAL_INVOICE
    invoice_code, order_code = 'I123', 'asdf'

    # FYI(artcz): Order.objects.create is overloaded method on OrderManager,
    # that sets up a lot of unused stuff, going with manual .save().
    order = Order(user=assopy_user, code=order_code)
    order.save()
    # create some random Vat instance to the invoice creation works
    vat_10 = Vat.objects.create(value=10)

    Invoice.objects.create(
        code=invoice_code,
        order=order,
        emit_date=timezone.now().date(),
        price=Decimal(1337),
        vat=vat_10,
        html='Here goes full html',
        exchange_rate_date=date.today(),
    )

    invoice_url = reverse('assopy-invoice-html',
                          kwargs={
                              'order_code': order_code,
                              'code': invoice_code,
                          })

    response = client.get(invoice_url)
    # TODO(artcz) after we changed to pre-rendering and storing full html of
    # the invoice we no longer use a template in this view.
    # TBD if we need that test here anymore, since it supposed to test
    # templates temporarily anyway.
    assert response.content == 'Here goes full html'
Ejemplo n.º 7
0
def test_invoices_from_buying_tickets(client):
    """
    This is an example of a full flow, of creating and buying a new ticket.
    """
    # because of 2018 we need to make sure that ECB rates are in place
    responses.add(responses.GET, DAILY_ECB_URL, body=EXAMPLE_ECB_DAILY_XML)
    fetch_and_store_latest_ecb_exrates()

    assert settings.P3_FARES_ENABLED

    # 1. First create a user with complete profile.
    # default password is 'password123' per django_factory_boy
    user = auth_factories.UserFactory(email='*****@*****.**',
                                      is_active=True)

    # both are required to access user profile page.
    AssopyUserFactory(user=user)
    AttendeeProfile.objects.create(user=user, slug='foobar')

    client.login(email='*****@*****.**', password='******')

    # 2. Let's start with checking if no tickets are available at first
    cart_url = reverse('p3-cart')
    response = client.get(cart_url)
    assert template_used(response, "p3/cart.html")
    assert 'Sorry, no tickets are available' in response.content

    # 3. p3/cart.html is using {% fares_available %} assignment tag to display
    # fares.  For more details about fares check conference/fares.py

    ticket_price = Decimal(100)
    ticket_amount = 20
    social_event_price = Decimal(10)
    social_event_amount = 5

    vat_rate_10, _ = Vat.objects.get_or_create(value=10)
    vat_rate_20, _ = Vat.objects.get_or_create(value=20)

    today = date.today()
    yesterday, tomorrow = today - timedelta(days=1), today + timedelta(days=1)

    CONFERENCE = settings.CONFERENCE_CONFERENCE

    create_fare_for_conference(
        code="TRSP",  # Ticket Regular Standard Personal
        conference=CONFERENCE,
        price=ticket_price,
        start_validity=yesterday,
        end_validity=tomorrow,
        vat_rate=vat_rate_10)

    create_fare_for_conference(code=SOCIAL_EVENT_FARE_CODE,
                               conference=CONFERENCE,
                               price=social_event_price,
                               start_validity=yesterday,
                               end_validity=tomorrow,
                               vat_rate=vat_rate_20)

    # 4. If Fare is created we should have one input on the cart.
    response = client.get(cart_url)
    assert template_used(response, "p3/cart.html")
    _response_content = response.content.decode('utf-8')

    assert 'Sorry, no tickets are available' not in _response_content
    assert 'Buy tickets (1 of 2)' in _response_content

    # There are plenty of tds but only TRSP should have data-fare set
    assert 'td class="fare" data-fare="TRSP">' in _response_content
    assert 'td class="fare" data-fare="TDCP">' not in _response_content
    assert 'td class="fare" data-fare="">' in _response_content
    # social events
    assert 'td class="fare" data-fare="VOUPE03">' in _response_content

    # and one input for TRSP where you can specify how many tickets
    # TODO: maybe it should have a different type than text?
    assert '<input type="text" size="2" name="TRSP"' in _response_content

    # 5. Try buying some tickets
    # FIXME: looks like the max_tickets is enforced only with javascript
    assert ticket_amount > conference_settings.MAX_TICKETS

    response = client.post(
        cart_url,
        {
            'order_type': 'non-deductible',  # == Personal
            'TRSP': ticket_amount,
            'VOUPE03': social_event_amount,
        },
        follow=True)

    billing_url = reverse('p3-billing')
    assert response.status_code == 200
    assert response.request['PATH_INFO'] == billing_url

    assert 'Buy tickets (2 of 2)' in response.content.decode('utf-8')

    # unless you POST to the billing page the Order is not created
    assert Order.objects.count() == 0

    Country.objects.create(iso='PL', name='Poland')
    response = client.post(billing_url, {
        'card_name': 'Joe Doe',
        'payment': 'cc',
        'country': 'PL',
        'address': 'Random 42',
        'cf_code': '31447',
        'code_conduct': True,
    },
                           follow=True)
    assert response.status_code == 200
    assert response.request['PATH_INFO'] == '/accounts/stripe/checkout/1/'

    order = Order.objects.get()
    # FIXME: confirming that max_tickets is only enforced in javascript
    assert order.orderitem_set.all().count() ==\
        ticket_amount + social_event_amount

    # need to create an email template that's used in the purchasing process
    Email.objects.create(code='purchase-complete')

    # no invoices
    assert Invoice.objects.all().count() == 0
    # static date, because of #592 choosing something in 2018
    SOME_RANDOM_DATE = date(2018, 1, 1)
    order.confirm_order(SOME_RANDOM_DATE)
    assert order.payment_date == SOME_RANDOM_DATE

    # # multiple items per invoice, one invoice per vat rate.
    # # 2 invoices but they are both placeholders
    assert Invoice.objects.all().count() == 2
    assert Invoice.objects.filter(
        html=VAT_NOT_AVAILABLE_PLACEHOLDER).count() == 2

    # # and we can then upgrade all invoices to non-placeholders
    for _invoice in Invoice.objects.all():
        upgrade_invoice_placeholder_to_real_invoice(_invoice)

    assert Invoice.objects.all().count() == 2
    assert Invoice.objects.filter(
        html=VAT_NOT_AVAILABLE_PLACEHOLDER).count() == 0

    invoice_vat_10 = Invoice.objects.get(vat__value=10)
    invoice_vat_20 = Invoice.objects.get(vat__value=20)

    # only one orderitem_set instance because they are grouped by fare_code
    # items are ordered desc by price.
    expected_invoice_items_vat_10 = [
        {
            'count': ticket_amount,
            'price': ticket_price * ticket_amount,
            'code': u'TRSP',
            'description': u'ep2018 - Regular Standard Personal'
        },
    ]

    expected_invoice_items_vat_20 = [
        {
            'count': social_event_amount,
            'price': social_event_price * social_event_amount,
            'code': SOCIAL_EVENT_FARE_CODE,
            'description': u'ep2018 - Social Event'
        },
    ]

    assert sequence_equals(invoice_vat_10.invoice_items(),
                           expected_invoice_items_vat_10)

    assert sequence_equals(invoice_vat_20.invoice_items(),
                           expected_invoice_items_vat_20)

    # check numbers for vat 10%
    gross_price_vat_10 = ticket_price * ticket_amount

    net_price_vat_10 = normalize_price(gross_price_vat_10 / Decimal('1.1'))
    vat_value_vat_10 = gross_price_vat_10 - net_price_vat_10

    assert invoice_vat_10.price == gross_price_vat_10
    assert invoice_vat_10.net_price() == net_price_vat_10
    assert invoice_vat_10.vat_value() == vat_value_vat_10
    assert invoice_vat_10.html.startswith('<!DOCTYPE')
    assert len(invoice_vat_10.html) > 1000  # large html blob

    # check numbers for vat 20%
    gross_price_vat_20 = social_event_price * social_event_amount

    net_price_vat_20 = normalize_price(gross_price_vat_20 / Decimal('1.2'))
    vat_value_vat_20 = gross_price_vat_20 - net_price_vat_20

    assert invoice_vat_20.price == gross_price_vat_20
    assert invoice_vat_20.net_price() == net_price_vat_20
    assert invoice_vat_20.vat_value() == vat_value_vat_20
    assert invoice_vat_20.html.startswith('<!DOCTYPE')
    assert len(invoice_vat_20.html) > 1000  # large html blob

    # each OrderItem should have a corresponding Ticket
    assert Ticket.objects.all().count() == ticket_amount + social_event_amount

    # Check if user profile has the tickets and invoices available
    profile_url = reverse('assopy-profile')
    response = client.get(profile_url)

    # order code depends on when this test is run, but invoice code should
    # default to whatever payment_date is (in this case 2018, 1, 1)
    # TODO: currently this test is under freezegun, but we may want to remove
    # it later and replace with APIs that allows to control/specify date for
    # order and invoice.
    assert 'O/18.0001' in response.content.decode('utf-8')
    # there is only one order but two invoices
    assert 'I/18.0001' in response.content.decode('utf-8')
    assert 'I/18.0002' in response.content.decode('utf-8')
Ejemplo n.º 8
0
def test_592_dont_display_invoices_for_years_before_2018(client):
    """
    https://github.com/EuroPython/epcon/issues/592

    Temporary(?) test for #592, until #591 is fixed.
    """

    # default password is 'password123' per django_factory_boy
    user = auth_factories.UserFactory(email='*****@*****.**',
                                      is_active=True)

    # both are required to access user profile page.
    assopy_user = AssopyUserFactory(user=user)
    AttendeeProfile.objects.create(user=user, slug='foobar')

    client.login(email='*****@*****.**', password='******')

    # create some random Vat instance to the invoice creation works
    vat_10 = Vat.objects.create(value=10)

    # invoice_code must be validated via ASSOPY_IS_REAL_INVOICE
    invoice_code_2017, order_code_2017 = 'I2017', 'O2017'
    invoice_code_2018, order_code_2018 = 'I2018', 'O2018'

    order2017 = Order(user=assopy_user, code=order_code_2017)
    order2017.save()
    order2017.created = date(2017, 12, 31)
    order2017.save()

    order2018 = Order(user=assopy_user, code=order_code_2018)
    order2018.save()
    order2018.created = date(2018, 1, 1)
    order2018.save()

    Invoice.objects.create(
        code=invoice_code_2017,
        order=order2017,
        emit_date=date(2017, 3, 13),
        price=Decimal(1337),
        vat=vat_10,
        exchange_rate_date=date.today(),
    )

    # Doesn't matter when the invoice was issued (invoice.emit_date),
    # it only matters what's the Order.created date
    Invoice.objects.create(
        code=invoice_code_2018,
        order=order2018,
        emit_date=date(2017, 3, 13),
        price=Decimal(1337),
        vat=vat_10,
        exchange_rate_date=date.today(),
    )

    user_profile_url = reverse("assopy-profile")
    response = client.get(user_profile_url)

    assert invoice_code_2017 not in response.content.decode('utf-8')
    assert order_code_2017 not in response.content.decode('utf-8')

    assert invoice_code_2018 in response.content.decode('utf-8')
    assert order_code_2018 in response.content.decode('utf-8')

    assert reverse("assopy-invoice-pdf",
                   kwargs={
                       'code': invoice_code_2018,
                       'order_code': order_code_2018,
                   }) in response.content.decode('utf-8')

    assert template_used(response, 'assopy/profile.html')
Ejemplo n.º 9
0
def make_user(email='*****@*****.**', **kwargs):
    user = auth_factories.UserFactory(email=email, is_active=True, **kwargs)
    AssopyUserFactory(user=user)
    AttendeeProfile.objects.getOrCreateForUser(user=user)
    return user