140 lines
6.2 KiB
Python
140 lines
6.2 KiB
Python
from services import watchlist_service
|
|
from repositories.tenant_repository import tenant_repository
|
|
from repositories.seat_repository import seat_repository
|
|
from repositories.competitor_repository import competitor_repository
|
|
from repositories.watchlist_repository import watchlist_repository
|
|
|
|
|
|
def _make_tenant_and_seat(tier='analyse'):
|
|
tenant = tenant_repository.create({
|
|
'name': 'Wild Horizons Travel', 'domain': 'wildhorizons.com', 'tier': tier,
|
|
'status': 'active', 'max_seats': 5,
|
|
})
|
|
seat = seat_repository.create({'tenant_id': tenant['id'], 'email': 'pm@wildhorizons.com', 'active': True})
|
|
return tenant, seat
|
|
|
|
|
|
def _make_competitor(tenant_id):
|
|
return competitor_repository.create({
|
|
'tenant_id': tenant_id, 'name': 'Intrepid Travel', 'website': 'https://intrepidtravel.com',
|
|
'catalogue_url': 'https://intrepidtravel.com/adventures', 'primary_market': 'GB', 'active': True,
|
|
})
|
|
|
|
|
|
def test_add_to_watchlist_succeeds_under_cap():
|
|
tenant, seat = _make_tenant_and_seat()
|
|
competitor = _make_competitor(tenant['id'])
|
|
|
|
result = watchlist_service.add_to_watchlist(
|
|
tenant, seat, competitor['id'], 'https://intrepidtravel.com/peru-classic-15-days', 'Peru Classic'
|
|
)
|
|
|
|
assert result['success'] is True
|
|
assert result['item']['competitor_id'] == competitor['id']
|
|
assert result['item']['url'] == 'https://intrepidtravel.com/peru-classic-15-days'
|
|
assert watchlist_repository.count_for_seat(seat['id']) == 1
|
|
|
|
|
|
def test_add_to_watchlist_blocked_at_analyse_cap_of_one():
|
|
tenant, seat = _make_tenant_and_seat(tier='analyse')
|
|
competitor = _make_competitor(tenant['id'])
|
|
watchlist_service.add_to_watchlist(tenant, seat, competitor['id'], 'https://intrepidtravel.com/peru', 'Peru')
|
|
|
|
result = watchlist_service.add_to_watchlist(
|
|
tenant, seat, competitor['id'], 'https://intrepidtravel.com/vietnam', 'Vietnam'
|
|
)
|
|
|
|
assert result['success'] is False
|
|
assert '1/1' in result['reason']
|
|
assert watchlist_repository.count_for_seat(seat['id']) == 1 # unchanged — never silently overwrites
|
|
|
|
|
|
def test_add_to_watchlist_respects_higher_discover_cap():
|
|
tenant, seat = _make_tenant_and_seat(tier='discover')
|
|
competitor = _make_competitor(tenant['id'])
|
|
|
|
first = watchlist_service.add_to_watchlist(tenant, seat, competitor['id'], 'https://intrepidtravel.com/peru', 'Peru')
|
|
second = watchlist_service.add_to_watchlist(tenant, seat, competitor['id'], 'https://intrepidtravel.com/vietnam', 'Vietnam')
|
|
third = watchlist_service.add_to_watchlist(tenant, seat, competitor['id'], 'https://intrepidtravel.com/kenya', 'Kenya')
|
|
|
|
assert first['success'] is True
|
|
assert second['success'] is True
|
|
assert third['success'] is False # Discover cap is 2/seat
|
|
|
|
|
|
def test_add_to_watchlist_defaults_to_cap_of_one_for_unknown_tier():
|
|
tenant, seat = _make_tenant_and_seat(tier='unknown-future-tier')
|
|
competitor = _make_competitor(tenant['id'])
|
|
|
|
first = watchlist_service.add_to_watchlist(tenant, seat, competitor['id'], 'https://intrepidtravel.com/peru', 'Peru')
|
|
second = watchlist_service.add_to_watchlist(tenant, seat, competitor['id'], 'https://intrepidtravel.com/vietnam', 'Vietnam')
|
|
|
|
assert first['success'] is True
|
|
assert second['success'] is False
|
|
|
|
|
|
def test_two_seats_each_get_their_own_independent_slot():
|
|
tenant, seat_a = _make_tenant_and_seat()
|
|
seat_b = seat_repository.create({'tenant_id': tenant['id'], 'email': 'other@wildhorizons.com', 'active': True})
|
|
competitor = _make_competitor(tenant['id'])
|
|
|
|
result_a = watchlist_service.add_to_watchlist(tenant, seat_a, competitor['id'], 'https://intrepidtravel.com/peru', 'Peru')
|
|
result_b = watchlist_service.add_to_watchlist(tenant, seat_b, competitor['id'], 'https://intrepidtravel.com/vietnam', 'Vietnam')
|
|
|
|
assert result_a['success'] is True
|
|
assert result_b['success'] is True # seat_a being at cap doesn't block seat_b
|
|
|
|
|
|
def test_remove_from_watchlist_frees_the_slot():
|
|
tenant, seat = _make_tenant_and_seat()
|
|
competitor = _make_competitor(tenant['id'])
|
|
added = watchlist_service.add_to_watchlist(tenant, seat, competitor['id'], 'https://intrepidtravel.com/peru', 'Peru')
|
|
|
|
removed = watchlist_service.remove_from_watchlist(added['item']['id'])
|
|
|
|
assert removed is True
|
|
assert watchlist_repository.count_for_seat(seat['id']) == 0
|
|
second = watchlist_service.add_to_watchlist(tenant, seat, competitor['id'], 'https://intrepidtravel.com/vietnam', 'Vietnam')
|
|
assert second['success'] is True
|
|
|
|
|
|
def test_remove_from_watchlist_returns_false_for_unknown_item():
|
|
assert watchlist_service.remove_from_watchlist('does-not-exist') is False
|
|
|
|
|
|
def test_list_watchlist_for_tenant_enriches_with_seat_email():
|
|
tenant, seat = _make_tenant_and_seat()
|
|
competitor = _make_competitor(tenant['id'])
|
|
watchlist_service.add_to_watchlist(tenant, seat, competitor['id'], 'https://intrepidtravel.com/peru', 'Peru Classic')
|
|
|
|
items = watchlist_service.list_watchlist_for_tenant(tenant['id'])
|
|
|
|
assert len(items) == 1
|
|
assert items[0]['watched_by_email'] == 'pm@wildhorizons.com'
|
|
assert items[0]['trip_name'] == 'Peru Classic'
|
|
|
|
|
|
def test_list_watchlist_for_tenant_shows_items_from_every_seat():
|
|
tenant, seat_a = _make_tenant_and_seat()
|
|
seat_b = seat_repository.create({'tenant_id': tenant['id'], 'email': 'other@wildhorizons.com', 'active': True})
|
|
competitor = _make_competitor(tenant['id'])
|
|
watchlist_service.add_to_watchlist(tenant, seat_a, competitor['id'], 'https://intrepidtravel.com/peru', 'Peru')
|
|
watchlist_service.add_to_watchlist(tenant, seat_b, competitor['id'], 'https://intrepidtravel.com/vietnam', 'Vietnam')
|
|
|
|
items = watchlist_service.list_watchlist_for_tenant(tenant['id'])
|
|
|
|
emails = {item['watched_by_email'] for item in items}
|
|
assert emails == {'pm@wildhorizons.com', 'other@wildhorizons.com'}
|
|
|
|
|
|
def test_list_watchlist_for_tenant_handles_removed_seat_gracefully():
|
|
tenant, seat = _make_tenant_and_seat()
|
|
competitor = _make_competitor(tenant['id'])
|
|
watchlist_service.add_to_watchlist(tenant, seat, competitor['id'], 'https://intrepidtravel.com/peru', 'Peru')
|
|
seat_repository.delete(seat['id']) # seat later removed from the team
|
|
|
|
items = watchlist_service.list_watchlist_for_tenant(tenant['id'])
|
|
|
|
assert len(items) == 1
|
|
assert items[0]['watched_by_email'] is None
|