Projet

Général

Profil

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

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

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')
......
685 656
    assert booking.extra_data == {'foo': None, 'foooo': 'baz'}  # not changed
686 657

  
687 658

  
688
def test_booking_cancellation_api(app, some_data, user):
689
    agenda = Agenda.objects.filter(label='Foo bar')[0]
690
    event = [x for x in Event.objects.filter(agenda=agenda) if x.in_bookable_period()][0]
691
    resp = app.post('/api/agenda/%s/fillslot/%s/' % (agenda.id, event.id), status=401)
692

  
693
    app.authorization = ('Basic', ('john.doe', 'password'))
694
    resp = app.post('/api/agenda/%s/fillslot/%s/' % (agenda.id, event.id))
695
    booking_id = resp.json['booking_id']
696
    assert Booking.objects.count() == 1
697
    resp = app.delete('/api/booking/%s/' % booking_id)
698
    assert Booking.objects.filter(cancellation_datetime__isnull=False).count() == 1
699

  
700

  
701
def test_booking_cancellation_post_api(app, some_data, user):
702
    agenda = Agenda.objects.filter(label='Foo bar')[0]
703
    event = [x for x in Event.objects.filter(agenda=agenda) if x.in_bookable_period()][0]
704
    resp = app.post('/api/agenda/%s/fillslot/%s/' % (agenda.id, event.id), status=401)
659
def test_booking_cancellation_api(app, user):
660
    agenda = Agenda.objects.create(kind='events')
661
    event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10)
662
    booking = Booking.objects.create(event=event)
705 663

  
706 664
    app.authorization = ('Basic', ('john.doe', 'password'))
707
    resp = app.post(
708
        '/api/agenda/%s/fillslot/%s/' % (agenda.id, event.id),
709
        params={
710
            'cancel_callback_url': 'http://example.net/jump/trigger/',
711
        },
712
    )
713
    booking_id = resp.json['booking_id']
714
    assert Booking.objects.count() == 1
715
    assert urlparse.urlparse(resp.json['api']['cancel_url']).path == '/api/booking/%s/cancel/' % booking_id
716
    with mock.patch('chrono.agendas.models.requests.post') as mocked_post:
717
        resp = app.post('/api/booking/%s/cancel/' % booking_id)
718
        assert not mocked_post.called
665
    app.delete('/api/booking/%s/' % booking.pk)
719 666
    assert Booking.objects.filter(cancellation_datetime__isnull=False).count() == 1
720 667

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

  
724
    # cancel an event that was already cancelled
725
    resp = app.post('/api/booking/%s/cancel/' % booking_id, status=200)
726
    assert resp.json['err'] == 1
727

  
728

  
729
def test_booking_cancellation_post_meeting_api(app, meetings_agenda, user):
730
    agenda_id = Agenda.objects.filter(label='Foo bar Meeting')[0].id
731
    meeting_type = MeetingType.objects.get(agenda=meetings_agenda)
732
    resp = app.get('/api/agenda/meetings/%s/datetimes/' % meeting_type.id)
733
    nb_events = len(resp.json['data'])
734
    event_id = resp.json['data'][2]['id']
735

  
736
    app.authorization = ('Basic', ('john.doe', 'password'))
737
    resp = app.post('/api/agenda/%s/fillslot/%s/' % (agenda_id, event_id))
738
    assert Booking.objects.count() == 1
739

  
740
    booking_id = resp.json['booking_id']
741
    assert Booking.objects.count() == 1
742
    resp = app.post('/api/booking/%s/cancel/' % booking_id)
743

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

  
747
    # book the same time slot
748
    resp = app.post('/api/agenda/%s/fillslot/%s/' % (agenda_id, event_id))
749
    assert resp.json['err'] == 0
750
    resp = app.get('/api/agenda/meetings/%s/datetimes/' % meeting_type.id)
751
    assert len([x for x in resp.json['data'] if not x.get('disabled')]) == nb_events - 1
752

  
753 668

  
754 669
def test_bookings(app, user):
755 670
    agenda = Agenda.objects.create(label='Foo bar', kind='events', minimal_booking_delay=0)
......
839 754
    )
840 755

  
841 756

  
842
def test_cancel_booking(app, some_data, user):
843
    agenda_id = Agenda.objects.filter(label='Foo bar')[0].pk
844
    event = Event.objects.filter(agenda_id=agenda_id).exclude(start_datetime__lt=now())[0]
757
def test_cancel_booking(app, user):
758
    agenda = Agenda.objects.create(kind='events')
759
    event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10)
845 760
    primary = Booking.objects.create(event=event)
846 761
    secondary = Booking.objects.create(event=event, primary_booking=primary)
847 762
    app.authorization = ('Basic', ('john.doe', 'password'))
......
859 774
    assert primary.cancellation_datetime is not None
860 775
    assert secondary.cancellation_datetime is not None
861 776

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

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

  
784

  
785
def test_cancel_booking_no_trigger(app, user):
786
    agenda = Agenda.objects.create(kind='events')
787
    event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10)
788
    booking = Booking.objects.create(event=event, cancel_callback_url='http://example.net/jump/trigger/')
789

  
790
    app.authorization = ('Basic', ('john.doe', 'password'))
791
    with mock.patch('chrono.agendas.models.requests.post') as mocked_post:
792
        app.post('/api/booking/%s/cancel/' % booking.pk)
793
        assert not mocked_post.called
794
    assert Booking.objects.filter(cancellation_datetime__isnull=False).count() == 1
795

  
862 796

  
863 797
def test_accept_booking(app, user):
864 798
    agenda = Agenda.objects.create(kind='events')
865
-