Skip to content

Commit

Permalink
Expand the integration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
rwood-moz committed Jan 17, 2025
1 parent 09478cb commit 85343cb
Show file tree
Hide file tree
Showing 6 changed files with 224 additions and 0 deletions.
52 changes: 52 additions & 0 deletions backend/test/integration/test_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,23 @@ def test_token_creates_user(self, with_db, with_client):
)
assert response.status_code == 403, response.text

def test_token_fails_due_to_invalid_auth_scheme(self, with_db, with_client, make_pro_subscriber):
"""Test that our username/password authentication fails when auth scheme is fxa"""
saved_scheme = os.environ['AUTH_SCHEME']
os.environ['AUTH_SCHEME'] = 'fxa'
password = 'test'
bad_password = 'test2'

subscriber = make_pro_subscriber(password=password)

# Test good credentials
response = with_client.post(
'/token',
data={'username': subscriber.email, 'password': password},
)
os.environ['AUTH_SCHEME'] = saved_scheme
assert response.status_code == 405, response.text


class TestFXA:
def test_fxa_login(self, with_client):
Expand Down Expand Up @@ -227,6 +244,18 @@ def test_fxa_with_allowlist_and_with_invite(self, with_client, with_l10n, make_i
assert 'url' in data
assert data.get('url') == FXA_CLIENT_PATCH.get('authorization_url')

def test_fxa_login_fail_with_invalid_auth_scheme(self, with_client):
saved_scheme = os.environ['AUTH_SCHEME']
os.environ['AUTH_SCHEME'] = 'NOT-fxa'
response = with_client.get(
'/fxa_login',
params={
'email': FXA_CLIENT_PATCH.get('subscriber_email'),
},
)
os.environ['AUTH_SCHEME'] = saved_scheme
assert response.status_code == 405, response.text

def test_fxa_callback_with_invite(self, with_db, with_client, monkeypatch, make_invite):
"""Test that our callback function correctly handles the session states, and creates a new subscriber"""
os.environ['AUTH_SCHEME'] = 'fxa'
Expand Down Expand Up @@ -460,6 +489,29 @@ def test_fxa_token_failed_due_to_empty_auth(self, make_basic_subscriber, with_cl

assert response.status_code == 401, response.text

def test_fxa_token_failed_due_to_invalid_auth_scheme(self, with_client, make_basic_subscriber):
saved_scheme = os.environ['AUTH_SCHEME']
os.environ['AUTH_SCHEME'] = 'NOT-fxa'

# Clear get_subscriber dep, so we can retrieve the real subscriber info later
del with_client.app.dependency_overrides[auth.get_subscriber]

subscriber = make_basic_subscriber(email='[email protected]')
access_token_expires = timedelta(minutes=float(10))
one_time_access_token = create_access_token(data={
'sub': f'uid-{subscriber.id}',
'jti': secrets.token_urlsafe(16)
}, expires_delta=access_token_expires)

# Exchange the one-time token with a long-living token
response = with_client.post(
'/fxa-token', headers={
'Authorization': f'Bearer {one_time_access_token}'
}
)
os.environ['AUTH_SCHEME'] = saved_scheme
assert response.status_code == 405, response.text


class TestCalDAV:
def test_auth(self, with_db, with_client):
Expand Down
82 changes: 82 additions & 0 deletions backend/test/integration/test_calendar.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,14 @@ def test_update_foreign_calendar(self, with_client, make_pro_subscriber, provide
)
assert response.status_code == 403, response.text

def test_update_invalid_calendar_id(self, with_client, request):
response = with_client.put(
f'/cal/{9999}',
json={'title': 'b', 'url': 'b', 'user': 'b', 'password': 'b'},
headers=auth_headers,
)
assert response.status_code == 404, response.text

@pytest.mark.parametrize('provider,factory_name', get_calendar_factory())
def test_connect_calendar(self, with_client, provider, factory_name, request):
generated_calendar = request.getfixturevalue(factory_name)()
Expand Down Expand Up @@ -321,6 +329,34 @@ def test_connect_more_calendars_than_tier_allows(
response = with_client.post(f'/cal/{cal[2].id}/connect', headers=auth_headers)
assert response.status_code == 403, response.text

def test_create_connection_failure(self, with_client, make_google_calendar, request):
"""Attempt to create google calendar connection without having external connection, expect failure"""
response = with_client.post(
'/cal',
json={
'title': 'A google calendar',
'color': '#123456',
'provider': CalendarProvider.google.value,
'url': 'test',
'user': 'test',
'password': 'test',
},
headers=auth_headers,
)
assert response.status_code == 400, response.text

@pytest.mark.parametrize('provider,factory_name', get_calendar_factory())
def test_disconnect_calendar(self, with_client, provider, factory_name, request):
new_calendar = request.getfixturevalue(factory_name)(connected=True)

response = with_client.post(f'/cal/{new_calendar.id}/disconnect', headers=auth_headers)
assert response.status_code == 200, response.text
data = response.json()
assert data['title'] == new_calendar.title
assert data['color'] == new_calendar.color
assert data['id'] == new_calendar.id
assert not data['connected']


class TestCaldav:
"""Tests for caldav specific functionality"""
Expand Down Expand Up @@ -414,3 +450,49 @@ def test_update_existing_caldav_calendar_without_password(self, with_client, wit
assert cal.url == os.getenv('CALDAV_TEST_CALENDAR_URL')
assert cal.user == os.getenv('CALDAV_TEST_USER')
assert cal.password == ''


class TestGoogle:
"""Tests for google specific functionality"""
def test_read_remote_google_calendar_connection_error(
self,
monkeypatch,
with_client,
make_pro_subscriber,
make_caldav_calendar,
make_schedule,
):
""" Attempt to read remote google calendar without having external connection first; expect error """
# Patch up the caldav constructor, and list_calendars (this test is for google only)
class MockGoogleConnector:
@staticmethod
def __init__(
self,
subscriber_id,
calendar_id,
redis_instance,
db,
remote_calendar_id,
google_client,
google_tkn: str = None,
):
pass

monkeypatch.setattr(GoogleConnector, '__init__', MockGoogleConnector.__init__)

test_url = 'https://caldav.thunderbird.net/'
test_user = 'thunderbird'

response = with_client.post(
'/rmt/calendars',
json={
'provider': CalendarProvider.google.value,
'url': test_url,
'user': test_user,
'password': 'caw',
},
headers=auth_headers,
)
assert response.status_code == 400, response.text
data = response.json()
assert data['detail']['id'] == 'REMOTE_CALENDAR_CONNECTION_ERROR'
46 changes: 46 additions & 0 deletions backend/test/integration/test_general.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ def test_health_for_locale(self, with_client):
def test_access_without_authentication_token(self, with_client):
# response = client.get("/login")
# assert response.status_code == 401
response = with_client.get('/me')
assert response.status_code == 401
response = with_client.put('/me')
assert response.status_code == 401
response = with_client.get('/me/calendars')
Expand All @@ -52,21 +54,65 @@ def test_access_without_authentication_token(self, with_client):
assert response.status_code == 401
response = with_client.delete('/cal/1')
assert response.status_code == 401
response = with_client.post('/caldav/auth')
assert response.status_code == 401
response = with_client.post('/caldav/disconnect')
assert response.status_code == 401
response = with_client.post('/rmt/calendars')
assert response.status_code == 401
response = with_client.get('/rmt/cal/1/' + DAY1 + '/' + DAY5)
assert response.status_code == 401
response = with_client.post('/rmt/sync')
assert response.status_code == 401
response = with_client.get('/account/available-emails')
assert response.status_code == 401
response = with_client.get('/account/download')
assert response.status_code == 401
response = with_client.get('/account/external-connections/')
assert response.status_code == 401
response = with_client.delete('/account/delete')
assert response.status_code == 401
response = with_client.get('/google/auth')
assert response.status_code == 401
response = with_client.post('/google/disconnect')
assert response.status_code == 401
response = with_client.post('/schedule')
assert response.status_code == 401
response = with_client.get('/schedule')
assert response.status_code == 401
response = with_client.get('/schedule/0')
assert response.status_code == 401
response = with_client.put('/schedule/0')
assert response.status_code == 401
response = with_client.get('/invite')
assert response.status_code == 401
response = with_client.post('/invite/generate/1')
assert response.status_code == 401
response = with_client.put('/invite/revoke/1')
assert response.status_code == 401
response = with_client.get('/subscriber')
assert response.status_code == 401
response = with_client.put('/subscriber/enable/[email protected]')
assert response.status_code == 401
response = with_client.put('/subscriber/disable/[email protected]')
assert response.status_code == 401
response = with_client.post('/subscriber/setup')
assert response.status_code == 401
response = with_client.post('/waiting-list/invite')
assert response.status_code == 401

def test_send_feedback(self, with_client):
response = with_client.post(
'/support', json={'topic': 'Hello World', 'details': 'Hello World but longer'}, headers=auth_headers
)
assert response.status_code == 200

def test_send_feedback_no_email_configured(self, with_client):
"""Attempt to send feedback with no support email configured; expect error"""
saved_email = os.environ['SUPPORT_EMAIL']
os.environ['SUPPORT_EMAIL'] = ''
response = with_client.post(
'/support', json={'topic': 'Hello World', 'details': 'Hello World but longer'}, headers=auth_headers
)
os.environ['SUPPORT_EMAIL'] = saved_email
assert response.status_code == 500
15 changes: 15 additions & 0 deletions backend/test/integration/test_profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,18 @@ def test_signed_short_link_refresh(self, with_client):
assert response.status_code == 200, response.text
url_new = response.json()['url']
assert url_old != url_new

def test_update_me_username_taken(self, with_db, with_client, make_pro_subscriber):
"""Attempt to update current subscriber's profile with already existing username"""
other_subscriber = make_pro_subscriber(username='thunderbird1')

response = with_client.put(
'/me',
json={
'username': 'thunderbird1',
'name': 'Changed Name',
'secondary_email': '[email protected]',
},
headers=auth_headers,
)
assert response.status_code == 403, response.text
14 changes: 14 additions & 0 deletions backend/test/integration/test_schedule.py
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,20 @@ def list_events(self, start, end):
else models.BookingStatus.booked.value
)

def test_public_availability_sched_not_active(self, with_client, make_pro_subscriber):
subscriber = make_pro_subscriber()
signed_url = signed_url_by_subscriber(subscriber)

# Check availability at the start of the schedule
response = with_client.post(
'/schedule/public/availability',
json={'url': signed_url},
headers=auth_headers,
)
assert response.status_code == 404, response.text
data = response.json()
assert data['detail']['id'] == 'SCHEDULE_NOT_ACTIVE'


class TestRequestScheduleAvailability:
@pytest.fixture
Expand Down
15 changes: 15 additions & 0 deletions backend/test/integration/test_waiting_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,21 @@ def test_bad_token_data_email_not_in_list(self, with_db, with_client):
with with_db() as db:
assert not db.query(models.WaitingList).filter(models.WaitingList.email == email).first()

def test_action_failed(self, with_db, with_client, make_waiting_list):
email = '[email protected]'

waiting_list = make_waiting_list(email='[email protected]')

serializer = URLSafeSerializer(os.getenv('SIGNED_SECRET'), 'waiting-list')
confirm_token = serializer.dumps({'email': email, 'action': WaitingListAction.CONFIRM_EMAIL.value})

response = with_client.post('/waiting-list/action', json={'token': confirm_token})

# expect the waiting list confirm email action to fail as email not on the list
assert response.status_code == 400, response.json()
data = response.json()
assert data['detail']['id'] == 'WAITING_LIST_FAIL'


class TestWaitingListActionLeave:
def assert_waiting_list_exists(self, db, waiting_list, success=True):
Expand Down

0 comments on commit 85343cb

Please sign in to comment.