Projet

Général

Profil

0002-misc-faster-tests-for-api-booking-endpoints.patch

Lauréline Guérin, 08 février 2022 10:13

Télécharger (12,2 ko)

Voir les différences:

Subject: [PATCH 2/2] misc: faster tests for api booking endpoints

 chrono/agendas/models.py  |   2 +-
 tests/api/test_booking.py | 174 ++++++++++++--------------------------
 2 files changed, 55 insertions(+), 121 deletions(-)
chrono/agendas/models.py
1962 1962
            vevent.add('dtend').value = self.event.end_datetime
1963 1963

  
1964 1964
        for field in ('description', 'location', 'comment', 'url'):
1965
            field_value = request and request.GET.get(field) or self.extra_data.get(field)
1965
            field_value = request and request.GET.get(field) or (self.extra_data or {}).get(field)
1966 1966
            if field_value:
1967 1967
                vevent.add(field).value = field_value
1968 1968
        ics.add(vevent)
tests/api/test_booking.py
1 1
import datetime
2
import urllib.parse as urlparse
3 2
from unittest import mock
4 3

  
5 4
import pytest
......
24 23
def test_booking_ics(app, some_data, meetings_agenda, user):
25 24
    agenda = Agenda.objects.filter(label='Foo bar')[0]
26 25
    event = [x for x in Event.objects.filter(agenda=agenda) if x.in_bookable_period()][0]
27
    app.authorization = ('Basic', ('john.doe', 'password'))
28
    resp = app.post('/api/agenda/%s/fillslot/%s/' % (agenda.slug, event.id))
29 26

  
30
    assert Booking.objects.count() == 1
31
    assert 'ics_url' in resp.json['api']
32
    assert urlparse.urlparse(resp.json['api']['cancel_url']).netloc
33
    assert urlparse.urlparse(resp.json['api']['ics_url']).netloc
27
    booking = Booking.objects.create(event=event)
34 28

  
35 29
    formatted_start_date = event.start_datetime.strftime('%Y%m%dT%H%M%S')
36
    booking_ics = Booking.objects.get(id=resp.json['booking_id']).get_ics()
37
    assert (
38
        'UID:%s-%s-%s\r\n' % (event.start_datetime.isoformat(), agenda.pk, resp.json['booking_id'])
39
        in booking_ics
40
    )
30
    booking_ics = booking.get_ics()
31
    assert 'UID:%s-%s-%s\r\n' % (event.start_datetime.isoformat(), agenda.pk, booking.pk) in booking_ics
41 32
    assert 'SUMMARY:\r\n' in booking_ics
42 33
    assert 'DTSTART:%sZ\r\n' % formatted_start_date in booking_ics
43 34
    assert 'DTEND:' not in booking_ics
44 35

  
45 36
    # test with additional data
46
    resp = app.post_json(
47
        '/api/agenda/%s/fillslot/%s/' % (agenda.id, event.id),
48
        params={
49
            'label': 'foo',
50
            'user_name': 'bar',
51
            'backoffice_url': 'http://example.net/',
52
            'url': 'http://example.com/booking',
53
        },
54
    )
55
    assert Booking.objects.count() == 2
56
    booking_ics = Booking.objects.get(id=resp.json['booking_id']).get_ics()
37
    booking.label = 'foo'
38
    booking.user_last_name = 'bar'
39
    booking.backoffice_url = 'http://example.net/'
40
    booking.extra_data = {'url': 'http://example.com/booking'}
41
    booking.save()
42
    booking_ics = booking.get_ics()
57 43
    assert 'SUMMARY:foo\r\n' in booking_ics
58 44
    assert 'ATTENDEE:bar\r\n' in booking_ics
59 45
    assert 'URL:http://example.com/booking\r\n' in booking_ics
60 46

  
61 47
    # test with user_label in additionnal data
62
    resp = app.post_json(
63
        '/api/agenda/%s/fillslot/%s/' % (agenda.id, event.id),
64
        params={
65
            'label': 'foo',
66
            'user_first_name': 'foo',
67
            'user_last_name': 'bar',
68
            'backoffice_url': 'http://example.net/',
69
            'url': 'http://example.com/booking',
70
            'user_display_label': 'your booking',
71
        },
72
    )
73
    assert Booking.objects.count() == 3
74
    booking_ics = Booking.objects.get(id=resp.json['booking_id']).get_ics()
48
    booking.user_first_name = 'foo'
49
    booking.user_last_name = 'bar'
50
    booking.user_display_label = 'your booking'
51
    booking.save()
52
    booking_ics = booking.get_ics()
75 53
    assert 'SUMMARY:your booking\r\n' in booking_ics
76 54
    assert 'ATTENDEE:foo bar\r\n' in booking_ics
77 55
    assert 'URL:http://example.com/booking\r\n' in booking_ics
78 56

  
79 57
    # extra data stored in extra_data field
80
    resp = app.post_json(
81
        '/api/agenda/%s/fillslot/%s/' % (agenda.id, event.id),
82
        params={
83
            'label': 'l',
84
            'backoffice_url': '',
85
            'location': 'bar',
86
            'comment': 'booking comment',
87
            'description': 'booking description',
88
        },
89
    )
90
    assert Booking.objects.count() == 4
91
    booking_id = resp.json['booking_id']
92
    booking = Booking.objects.get(id=booking_id)
58
    booking.label = 'l'
59
    booking.extra_data = {
60
        'backoffice_url': '',
61
        'location': 'bar',
62
        'comment': 'booking comment',
63
        'description': 'booking description',
64
    }
65
    booking.save()
93 66
    booking_ics = booking.get_ics()
94 67
    assert 'COMMENT:booking comment\r\n' in booking_ics
95 68
    assert 'LOCATION:bar\r\n' in booking_ics
......
97 70

  
98 71
    # unauthenticated
99 72
    app.authorization = None
100
    app.get('/api/booking/%s/ics/' % resp.json['booking_id'], status=401)
73
    app.get('/api/booking/%s/ics/' % booking.pk, status=401)
101 74

  
102 75
    app.authorization = ('Basic', ('john.doe', 'password'))
103
    resp = app.get('/api/booking/%s/ics/' % resp.json['booking_id'])
76
    resp = app.get('/api/booking/%s/ics/' % booking.pk)
104 77
    assert resp.headers['Content-Type'] == 'text/calendar'
105 78

  
106 79
    params = {
......
109 82
        'comment': 'custom comment',
110 83
        'url': 'http://example.com/custom',
111 84
    }
112
    resp = app.get('/api/booking/%s/ics/' % booking_id, params=params)
85
    resp = app.get('/api/booking/%s/ics/' % booking.pk, params=params)
113 86
    assert 'DESCRIPTION:custom booking description\r\n' in resp.text
114 87
    assert 'LOCATION:custom booking location\r\n' in resp.text
115 88
    assert 'COMMENT:custom comment\r\n' in resp.text
116 89
    assert 'URL:http://example.com/custom\r\n' in resp.text
117 90

  
118
    meetings_agenda_id = Agenda.objects.filter(label='Foo bar Meeting')[0].id
119 91
    meeting_type = MeetingType.objects.get(agenda=meetings_agenda)
120 92
    resp = app.get('/api/agenda/meetings/%s/datetimes/' % meeting_type.id)
121 93
    event = resp.json['data'][2]
122
    resp = app.post('/api/agenda/%s/fillslot/%s/' % (meetings_agenda_id, event['id']))
123
    assert Booking.objects.count() == 5
124
    assert 'ics_url' in resp.json['api']
94
    resp = app.post('/api/agenda/%s/fillslot/%s/' % (meetings_agenda.pk, event['id']))
95
    assert Booking.objects.count() == 2
125 96
    booking = Booking.objects.get(id=resp.json['booking_id'])
126 97
    booking_ics = booking.get_ics()
127 98
    start = booking.event.start_datetime.strftime('%Y%m%dT%H%M%S')
......
693 664
    assert booking.extra_data == {'foo': None, 'foooo': 'baz'}  # not changed
694 665

  
695 666

  
696
def test_booking_cancellation_api(app, some_data, user):
697
    agenda = Agenda.objects.filter(label='Foo bar')[0]
698
    event = [x for x in Event.objects.filter(agenda=agenda) if x.in_bookable_period()][0]
699
    resp = app.post('/api/agenda/%s/fillslot/%s/' % (agenda.id, event.id), status=401)
700

  
701
    app.authorization = ('Basic', ('john.doe', 'password'))
702
    resp = app.post('/api/agenda/%s/fillslot/%s/' % (agenda.id, event.id))
703
    booking_id = resp.json['booking_id']
704
    assert Booking.objects.count() == 1
705
    resp = app.delete('/api/booking/%s/' % booking_id)
706
    assert Booking.objects.filter(cancellation_datetime__isnull=False).count() == 1
707

  
708

  
709
def test_booking_cancellation_post_api(app, some_data, user):
710
    agenda = Agenda.objects.filter(label='Foo bar')[0]
711
    event = [x for x in Event.objects.filter(agenda=agenda) if x.in_bookable_period()][0]
712
    resp = app.post('/api/agenda/%s/fillslot/%s/' % (agenda.id, event.id), status=401)
667
def test_booking_cancellation_api(app, user):
668
    agenda = Agenda.objects.create(kind='events')
669
    event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10)
670
    booking = Booking.objects.create(event=event)
713 671

  
714 672
    app.authorization = ('Basic', ('john.doe', 'password'))
715
    resp = app.post(
716
        '/api/agenda/%s/fillslot/%s/' % (agenda.id, event.id),
717
        params={
718
            'cancel_callback_url': 'http://example.net/jump/trigger/',
719
        },
720
    )
721
    booking_id = resp.json['booking_id']
722
    assert Booking.objects.count() == 1
723
    assert urlparse.urlparse(resp.json['api']['cancel_url']).path == '/api/booking/%s/cancel/' % booking_id
724
    with mock.patch('chrono.agendas.models.requests.post') as mocked_post:
725
        resp = app.post('/api/booking/%s/cancel/' % booking_id)
726
        assert not mocked_post.called
673
    app.delete('/api/booking/%s/' % booking.pk)
727 674
    assert Booking.objects.filter(cancellation_datetime__isnull=False).count() == 1
728 675

  
729
    # cancel an object that doesn't exist
730
    resp = app.post('/api/booking/%s/cancel/' % 0, status=404)
731

  
732
    # cancel an event that was already cancelled
733
    resp = app.post('/api/booking/%s/cancel/' % booking_id, status=200)
734
    assert resp.json['err'] == 1
735

  
736

  
737
def test_booking_cancellation_post_meeting_api(app, meetings_agenda, user):
738
    agenda_id = Agenda.objects.filter(label='Foo bar Meeting')[0].id
739
    meeting_type = MeetingType.objects.get(agenda=meetings_agenda)
740
    resp = app.get('/api/agenda/meetings/%s/datetimes/' % meeting_type.id)
741
    nb_events = len(resp.json['data'])
742
    event_id = resp.json['data'][2]['id']
743

  
744
    app.authorization = ('Basic', ('john.doe', 'password'))
745
    resp = app.post('/api/agenda/%s/fillslot/%s/' % (agenda_id, event_id))
746
    assert Booking.objects.count() == 1
747

  
748
    booking_id = resp.json['booking_id']
749
    assert Booking.objects.count() == 1
750
    resp = app.post('/api/booking/%s/cancel/' % booking_id)
751

  
752
    resp = app.get('/api/agenda/meetings/%s/datetimes/' % meeting_type.id)
753
    assert len(resp.json['data']) == nb_events
754

  
755
    # book the same time slot
756
    resp = app.post('/api/agenda/%s/fillslot/%s/' % (agenda_id, event_id))
757
    assert resp.json['err'] == 0
758
    resp = app.get('/api/agenda/meetings/%s/datetimes/' % meeting_type.id)
759
    assert len([x for x in resp.json['data'] if not x.get('disabled')]) == nb_events - 1
760

  
761 676

  
762 677
def test_bookings(app, user):
763 678
    agenda = Agenda.objects.create(label='Foo bar', kind='events', minimal_booking_delay=0)
......
847 762
    )
848 763

  
849 764

  
850
def test_cancel_booking(app, some_data, user):
851
    agenda_id = Agenda.objects.filter(label='Foo bar')[0].pk
852
    event = Event.objects.filter(agenda_id=agenda_id).exclude(start_datetime__lt=now())[0]
765
def test_cancel_booking(app, user):
766
    agenda = Agenda.objects.create(kind='events')
767
    event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10)
853 768
    primary = Booking.objects.create(event=event)
854 769
    secondary = Booking.objects.create(event=event, primary_booking=primary)
855 770
    app.authorization = ('Basic', ('john.doe', 'password'))
......
867 782
    assert primary.cancellation_datetime is not None
868 783
    assert secondary.cancellation_datetime is not None
869 784

  
785
    # cancel an object that doesn't exist
786
    resp = app.post('/api/booking/%s/cancel/' % 0, status=404)
787

  
788
    # cancel an event that was already cancelled
789
    resp = app.post('/api/booking/%s/cancel/' % primary.pk, status=200)
790
    assert resp.json['err'] == 1
791

  
792

  
793
def test_cancel_booking_no_trigger(app, user):
794
    agenda = Agenda.objects.create(kind='events')
795
    event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10)
796
    booking = Booking.objects.create(event=event, cancel_callback_url='http://example.net/jump/trigger/')
797

  
798
    app.authorization = ('Basic', ('john.doe', 'password'))
799
    with mock.patch('chrono.agendas.models.requests.post') as mocked_post:
800
        app.post('/api/booking/%s/cancel/' % booking.pk)
801
        assert not mocked_post.called
802
    assert Booking.objects.filter(cancellation_datetime__isnull=False).count() == 1
803

  
870 804

  
871 805
def test_accept_booking(app, user):
872 806
    agenda = Agenda.objects.create(kind='events')
873
-