lingo/tests/api/test_pricing.py

348 lines
11 KiB
Python

import datetime
from unittest import mock
import pytest
from lingo.agendas.chrono import ChronoError
from lingo.agendas.models import Agenda
from lingo.pricing.models import AgendaPricing, Pricing, PricingError
pytestmark = pytest.mark.django_db
def test_pricing_compute_params(app, user):
app.authorization = ('Basic', ('john.doe', 'password'))
# missing slots
resp = app.get(
'/api/pricing/compute/',
params={'user_external_id': 'user:1', 'adult_external_id': 'adult:1'},
status=400,
)
assert resp.json['err'] == 1
assert resp.json['err_desc'] == 'invalid payload'
assert resp.json['errors']['slots'] == ['This field is required.']
# missing user_external_id
resp = app.get(
'/api/pricing/compute/',
params={'slots': 'foo@foo', 'adult_external_id': 'adult:1'},
status=400,
)
assert resp.json['err'] == 1
assert resp.json['err_desc'] == 'invalid payload'
assert resp.json['errors']['user_external_id'] == ['This field is required.']
# missing adult_external_id
resp = app.get(
'/api/pricing/compute/',
params={'slots': 'foo@foo', 'user_external_id': 'user:1'},
status=400,
)
assert resp.json['err'] == 1
assert resp.json['err_desc'] == 'invalid payload'
assert resp.json['errors']['adult_external_id'] == ['This field is required.']
def test_pricing_compute_slots(app, user):
app.authorization = ('Basic', ('john.doe', 'password'))
# bad slot format
resp = app.get(
'/api/pricing/compute/',
params={
'slots': 'event-bar-slug',
'user_external_id': 'user:1',
'adult_external_id': 'adult:1',
},
status=400,
)
assert resp.json['err'] == 1
assert resp.json['err_desc'] == 'invalid payload'
assert resp.json['errors']['slots'] == ['Invalid format for slot event-bar-slug']
resp = app.get(
'/api/pricing/compute/',
params={
'slots': '@event-bar-slug',
'user_external_id': 'user:1',
'adult_external_id': 'adult:1',
},
status=400,
)
assert resp.json['err'] == 1
assert resp.json['err_desc'] == 'invalid payload'
assert resp.json['errors']['slots'] == ['Missing agenda slug in slot @event-bar-slug']
resp = app.get(
'/api/pricing/compute/',
params={
'slots': 'agenda@',
'user_external_id': 'user:1',
'adult_external_id': 'adult:1',
},
status=400,
)
assert resp.json['err'] == 1
assert resp.json['err_desc'] == 'invalid payload'
assert resp.json['errors']['slots'] == ['Missing event slug in slot agenda@']
# unknown agenda
resp = app.get(
'/api/pricing/compute/',
params={
'slots': 'agenda@event-bar-slug, agenda2@event-bar-slug',
'user_external_id': 'user:1',
'adult_external_id': 'adult:1',
},
status=400,
)
assert resp.json['err'] == 1
assert resp.json['err_desc'] == 'invalid payload'
assert resp.json['errors']['slots'] == ['Unknown agendas: agenda, agenda2']
@mock.patch('lingo.api.serializers.get_events')
def test_pricing_compute_events_error(mock_events, app, user):
Agenda.objects.create(label='Agenda')
app.authorization = ('Basic', ('john.doe', 'password'))
mock_events.side_effect = ChronoError('foo bar')
resp = app.get(
'/api/pricing/compute/',
params={
'slots': 'agenda@event-bar-slug',
'user_external_id': 'user:1',
'adult_external_id': 'adult:1',
},
status=400,
)
assert resp.json['err'] == 1
assert resp.json['err_desc'] == 'invalid payload'
assert resp.json['errors']['slots'] == ['foo bar']
@mock.patch('lingo.api.serializers.get_events')
@mock.patch('lingo.api.serializers.get_subscriptions')
def test_pricing_compute_subscriptions_error(mock_subscriptions, mock_events, app, user):
Agenda.objects.create(label='Agenda')
app.authorization = ('Basic', ('john.doe', 'password'))
mock_events.return_value = [
{'start_datetime': '2021-09-01T12:00:00+02:00', 'agenda': 'agenda', 'slug': 'event-bar-slug'}
]
mock_subscriptions.side_effect = ChronoError('foo baz')
resp = app.get(
'/api/pricing/compute/',
params={
'slots': 'agenda@event-bar-slug',
'user_external_id': 'user:1',
'adult_external_id': 'adult:1',
},
status=400,
)
assert resp.json['err'] == 1
assert resp.json['err_desc'] == 'invalid payload'
assert resp.json['errors']['user_external_id'] == ['foo baz']
@mock.patch('lingo.api.serializers.get_events')
@mock.patch('lingo.api.serializers.get_subscriptions')
@mock.patch('lingo.pricing.models.AgendaPricing.get_pricing_data_for_event')
def test_pricing_compute(mock_pricing_data_event, mock_subscriptions, mock_events, app, user):
agenda = Agenda.objects.create(label='Agenda')
agenda2 = Agenda.objects.create(label='Agenda2')
app.authorization = ('Basic', ('john.doe', 'password'))
# no subscription
mock_events.return_value = [
{'start_datetime': '2021-09-01T12:00:00+02:00', 'agenda': 'agenda', 'slug': 'event-bar-slug'}
]
mock_subscriptions.return_value = []
resp = app.get(
'/api/pricing/compute/',
params={
'slots': 'agenda@event-bar-slug',
'user_external_id': 'user:1',
'adult_external_id': 'adult:1',
},
status=400,
)
assert resp.json['err'] == 1
assert resp.json['err_desc'] == 'invalid payload'
assert resp.json['errors']['user_external_id'] == [
'No subscription found for event agenda@event-bar-slug'
]
assert mock_pricing_data_event.call_args_list == []
assert mock_subscriptions.call_args_list == [mock.call('agenda', 'user:1')]
# no matching subscription
mock_subscriptions.reset_mock()
mock_subscriptions.return_value = [
{
'date_start': '2021-08-01',
'date_end': '2021-09-01',
},
{
'date_start': '2021-09-02',
'date_end': '2021-09-03',
},
]
resp = app.get(
'/api/pricing/compute/',
params={
'slots': 'agenda@event-bar-slug',
'user_external_id': 'user:1',
'adult_external_id': 'adult:1',
},
status=400,
)
assert resp.json['err'] == 1
assert resp.json['err_desc'] == 'invalid payload'
assert resp.json['errors']['user_external_id'] == [
'No subscription found for event agenda@event-bar-slug'
]
assert mock_pricing_data_event.call_args_list == []
assert mock_subscriptions.call_args_list == [mock.call('agenda', 'user:1')]
# no matching subscription
mock_events.return_value = [
{'start_datetime': '2021-09-02T12:00:00+02:00', 'agenda': 'agenda', 'slug': 'event-bar-slug'},
{'start_datetime': '2021-09-01T12:00:00+02:00', 'agenda': 'agenda2', 'slug': 'event-baz-slug'},
]
mock_subscriptions.reset_mock()
mock_subscriptions.return_value = [
{
'date_start': '2021-08-01',
'date_end': '2021-09-01',
},
{
'date_start': '2021-09-02',
'date_end': '2021-09-03',
},
]
resp = app.get(
'/api/pricing/compute/',
params={
'slots': 'agenda@event-bar-slug, agenda2@event-baz-slug',
'user_external_id': 'user:1',
'adult_external_id': 'adult:1',
},
status=400,
)
assert resp.json['err'] == 1
assert resp.json['err_desc'] == 'invalid payload'
assert resp.json['errors']['user_external_id'] == [
'No subscription found for event agenda2@event-baz-slug'
]
assert mock_pricing_data_event.call_args_list == []
assert mock_subscriptions.call_args_list == [
mock.call('agenda', 'user:1'),
mock.call('agenda2', 'user:1'),
]
# no agenda_pricing found
mock_subscriptions.return_value = [
{
'date_start': '2021-08-01',
'date_end': '2021-09-01',
},
{
'date_start': '2021-09-01',
'date_end': '2021-09-02',
},
{
'date_start': '2021-09-02',
'date_end': '2021-09-03',
},
]
mock_pricing_data_event.side_effect = [
{'foo': 'baz'},
{'foo': 'bar'},
]
resp = app.get(
'/api/pricing/compute/',
params={
'slots': 'agenda@event-bar-slug, agenda2@event-baz-slug',
'user_external_id': 'user:1',
'adult_external_id': 'adult:1',
},
)
assert resp.json['data'] == [
{
'event': 'agenda2@event-baz-slug',
'error': 'No agenda pricing found for event agenda2@event-baz-slug',
},
{
'event': 'agenda@event-bar-slug',
'error': 'No agenda pricing found for event agenda@event-bar-slug',
},
]
# ok
pricing = Pricing.objects.create(label='Foo bar')
agenda_pricing = AgendaPricing.objects.create(
pricing=pricing,
date_start=datetime.date(year=2021, month=9, day=1),
date_end=datetime.date(year=2021, month=10, day=1),
)
agenda_pricing.agendas.add(agenda, agenda2)
resp = app.get(
'/api/pricing/compute/',
params={
'slots': 'agenda@event-bar-slug, agenda2@event-baz-slug',
'user_external_id': 'user:1',
'adult_external_id': 'adult:1',
},
)
assert resp.json['data'] == [
{'event': 'agenda2@event-baz-slug', 'pricing_data': {'foo': 'baz'}},
{'event': 'agenda@event-bar-slug', 'pricing_data': {'foo': 'bar'}},
]
assert mock_pricing_data_event.call_args_list == [
mock.call(
request=mock.ANY,
agenda=agenda2,
event={
'start_datetime': '2021-09-01T12:00:00+02:00',
'agenda': 'agenda2',
'slug': 'event-baz-slug',
},
subscription={'date_start': '2021-09-01', 'date_end': '2021-09-02'},
check_status={'status': 'presence', 'check_type': None},
booking={},
user_external_id='user:1',
adult_external_id='adult:1',
),
mock.call(
request=mock.ANY,
agenda=agenda,
event={
'start_datetime': '2021-09-02T12:00:00+02:00',
'agenda': 'agenda',
'slug': 'event-bar-slug',
},
subscription={'date_start': '2021-09-02', 'date_end': '2021-09-03'},
check_status={'status': 'presence', 'check_type': None},
booking={},
user_external_id='user:1',
adult_external_id='adult:1',
),
]
# get_pricing_data_for_event with error
mock_pricing_data_event.side_effect = [
PricingError(details={'foo': 'error'}),
{'foo': 'bar'},
]
resp = app.get(
'/api/pricing/compute/',
params={
'slots': 'agenda@event-bar-slug, agenda2@event-baz-slug',
'user_external_id': 'user:1',
'adult_external_id': 'adult:1',
},
)
assert resp.json['data'] == [
{'event': 'agenda2@event-baz-slug', 'error': {'foo': 'error'}},
{'event': 'agenda@event-bar-slug', 'pricing_data': {'foo': 'bar'}},
]