def test_maybe_add_or_delete_source(self): auth_entity = FakeAuthEntity(id='x', user_json=json_dumps({ 'url': 'http://foo.com/', 'name': UNICODE_STR })) auth_entity.put() key = FakeSource.next_key() with app.test_request_context(), self.assertRaises( RequestRedirect) as rr: state = util.construct_state_param_for_add(feature='publish') util.maybe_add_or_delete_source(FakeSource, auth_entity, state) self.assertIn(UNICODE_STR, get_flashed_messages()[0]) self.assertEqual(302, rr.exception.code) self.assertEqual(['publish'], key.get().features) name = urllib.parse.quote_plus(UNICODE_STR.encode()) self.assertIn(f'logins="/fake/{key.id()}?{name}";', rr.exception.get_response().headers['Set-Cookie']) for feature in None, '': key = FakeSource.next_key() with app.test_request_context(), self.assertRaises( RequestRedirect) as rr: state = util.construct_state_param_for_add(feature) util.maybe_add_or_delete_source(FakeSource, auth_entity, state) self.assertEqual([], key.get().features)
def test_maybe_add_or_delete_source_delete_declined(self): state = { 'feature': 'webmention', 'operation': 'delete', } msg = 'If you want to disable, please approve the FakeSource prompt.' # no source with app.test_request_context(): with self.assertRaises(RequestRedirect) as rr: util.maybe_add_or_delete_source(FakeSource, None, util.encode_oauth_state(state)) self.assert_equals(302, rr.exception.code) self.assert_equals('http://localhost/', rr.exception.new_url) self.assertEqual([msg], get_flashed_messages()) # source state['source'] = self.sources[0].key.urlsafe().decode() with app.test_request_context(), self.assertRaises( RequestRedirect) as rr: util.maybe_add_or_delete_source(FakeSource, None, util.encode_oauth_state(state)) self.assert_equals(302, rr.exception.code) self.assert_equals(self.source_bridgy_url, rr.exception.new_url) self.assertEqual([msg], get_flashed_messages())
def test_host_url(self): with app.test_request_context(): self.assertEqual('http://localhost/', util.host_url()) self.assertEqual('http://localhost/asdf', util.host_url('asdf')) self.assertEqual('http://localhost/foo/bar', util.host_url('/foo/bar')) with app.test_request_context(base_url='https://a.xyz', path='/foo'): self.assertEqual('https://a.xyz/', util.host_url()) self.assertEqual('https://a.xyz/asdf', util.host_url('asdf')) self.assertEqual('https://a.xyz/foo/bar', util.host_url('/foo/bar'))
def test_bad_logins_cookies(self): """https://github.com/snarfed/bridgy/issues/601""" with app.test_request_context( headers={ 'Cookie': 'OAMAuthnCookie_www.arbeitsagentur.de:443=xyz', }): self.assertEqual([], util.get_logins())
def test_logins_cookie_url_decode(self): """https://console.cloud.google.com/errors/10588536940780707768?project=brid-gy""" with app.test_request_context( headers={'Cookie': 'logins="/fake/123?question%3Fmark"'}): self.assertEqual( [Login(site='fake', name='question?mark', path='/fake/123')], util.get_logins())
def test_login_helper_scopes(self): with app.test_request_context(): result = login_helper('scopes') self.assertIsInstance(result, werkzeug.wrappers.Response) self.assertEqual(result.status_code, 302) redirect_location = result.headers['Location'] self.assertTrue('scopes' in redirect_location)
class JwtTestUtils(DbTestUtils): with app.test_request_context(): LOGIN_URL = url_for('login') TEST_NAME = 'test_user' TEST_PASSWORD = '******' @tools.nottest def create_test_data(self, name=TEST_NAME): return { 'username': name, 'password': self.TEST_PASSWORD } @tools.nottest def create_jwt_test_user(self, name=TEST_NAME): user = self.create_test_user(name, self.TEST_PASSWORD) data = self.create_test_data(name=name) response = self.client.post(self.LOGIN_URL, content_type='application/json', data=json.dumps(data)) access_token = response.json['access_token'] refresh_token = response.json['refresh_token'] auth_value = 'Bearer {}'.format(access_token) headers = {'Authorization': auth_value} auth_value = 'Bearer {}'.format(refresh_token) refresh_headers = {'Authorization': auth_value} return user, headers, refresh_headers
def test_maybe_add_or_delete_source_username_key_id_disables_other_source( self): class UKISource(Source): USERNAME_KEY_ID = True GR_CLASS = FakeGrSource @classmethod def new(cls, **kwargs): del kwargs['auth_entity'] return UKISource(username='******', domain_urls=['http://foo/'], **kwargs) # original entity with capitalized key name orig_key = UKISource(id='FoO', features=['listen']).put() with app.test_request_context(), self.assertRaises( RequestRedirect) as rr: state = util.construct_state_param_for_add(feature='publish') util.maybe_add_or_delete_source(UKISource, FakeAuthEntity(id='x'), state) self.assertEqual(302, rr.exception.code) got = UKISource.get_by_id('foo') self.assertEqual('FoO', got.username) self.assertEqual(['publish'], got.features) # original entity with capitalized key should be disabled self.assertEqual([], orig_key.get().features)
def test_choose_blog_decline(self): with app.test_request_context(): with self.assertRaises(RequestRedirect) as rr: ChooseBlog('/unused').finish(None) self.assertEqual(0, Medium.query().count()) self.assertEqual(302, rr.exception.code) self.assertEqual('http://localhost/', rr.exception.new_url) self.assertEqual( ["OK, you're not signed up. Hope you reconsider!"], get_flashed_messages())
def test_choose_blog_no_publications(self): self.expect_get_publications({}) with app.test_request_context(): with self.assertRaises(RequestRedirect) as rr: ChooseBlog('/unused').finish(self.auth_entity) self.assertEqual(302, rr.exception.code) self.assertEqual('http://localhost/medium/@ry', rr.exception.new_url) self.assert_created_profile()
def test_site_lookup_api_disabled_error_start(self): self.expect_urlopen( 'https://public-api.wordpress.com/rest/v1/sites/123?pretty=true', '{"error": "unauthorized", "message": "API calls to this blog have been disabled."}', status=403) self.mox.ReplayAll() with app.test_request_context(): with self.assertRaises(RequestRedirect): self.assertIsNone(WordPress.new(auth_entity=self.auth_entity)) self.assertIsNone(WordPress.query().get()) self.assertIn('enable the Jetpack JSON API', get_flashed_messages()[0])
def test_protected(self): with app.test_request_context(): protected_url = url_for('test_protected') response = self.client.get(protected_url) self.assert_401(response) self.assertIsNotNone(response.data) user_, headers, refresh_headers_ = self.create_jwt_test_user() response = self.client.get(protected_url, headers=headers) self.assert_200(response) self.assertIsNotNone(response.data)
def test_choose_blog_publications(self): self.expect_get_publications(PUBLICATIONS) with app.test_request_context(): resp = ChooseBlog('/unused').finish(self.auth_entity) for expected in ( 'action="/medium/add" method="post"', '<input type="radio" name="blog" id="@RY"', '<input type="radio" name="blog" id="b969ac62a46b"', '<input type="radio" name="blog" id="b45573563f5a"', ): self.assertIn(expected, resp) self.assertEqual(0, Medium.query().count())
def test_is_admin(self): with app.test_request_context(): protected_url = url_for('test_admin_protected') user, headers, refresh_headers_ = self.create_jwt_test_user() response = self.client.get(protected_url, headers=headers) self.assert_401(response) self.assertIsNotNone(response.data) user.is_admin = True db.session.commit() response = self.client.get(protected_url, headers=headers) self.assert_200(response) self.assertIsNotNone(response.data)
def test_maybe_add_or_delete_without_web_site_redirects_to_edit_websites( self): for bad_url in None, 'not>a<url', 'http://fa.ke/xyz': auth_entity = FakeAuthEntity(id='x', user_json=json_dumps({'url': bad_url})) auth_entity.put() key = FakeSource.next_key().urlsafe().decode() with app.test_request_context(), self.assertRaises( RequestRedirect) as rr: util.maybe_add_or_delete_source(FakeSource, auth_entity, '{}') self.assertEqual(302, rr.exception.code) self.assert_equals( f'http://localhost/edit-websites?source_key={key}', rr.exception.new_url)
def test_get_logins(self): for cookie, expected in ( ('', []), ('abc=xyz', []), ('logins=', []), ('logins=|', []), ('logins=/fake/123', [Login('fake', '', '/fake/123')]), ('logins=/fake/123?Name', [Login('fake', 'Name', '/fake/123')]), ('logins=/fake/123?a%E2%98%95b', [Login('fake', 'a☕b', '/fake/123')]), ('logins=/fake/123?Name|/blogger/456?Nombre', [ Login('fake', 'Name', '/fake/123'), Login('blogger', 'Nombre', '/blogger/456'), ]), ): with app.test_request_context(headers={'Cookie': cookie}): self.assertCountEqual(expected, util.get_logins())
def test_delete_removes_from_logins_cookie(self): self.client.set_cookie( 'localhost', 'logins', f'/fake/{self.sources[0].key.id()}?Fake%20User|/other/1?bob') with app.test_request_context(): state = util.construct_state_param_for_add( feature='listen', operation='delete', source=self.sources[0].key.urlsafe().decode()) self.auth_entities[0].put() auth_entity_key = self.sources[0].auth_entity.urlsafe().decode() resp = self.client.get( f'/delete/finish?auth_entity={auth_entity_key}&state={state}') self.assertEqual(302, resp.status_code) location = resp.headers['Location'] self.assertEqual('http://localhost/', location) self.assertIn('logins="/other/1?bob";', resp.headers['Set-Cookie'].split(' '))
def test_add_to_logins_cookie(self): with app.test_request_context( headers={'Cookie': 'logins=/other/1?bob'}): listen = util.construct_state_param_for_add(feature='listen') auth_entity = FakeAuthEntity(id='x', user_json='{}') auth_entity.put() id = FakeSource.next_key().id() with self.assertRaises(RequestRedirect) as rr: util.maybe_add_or_delete_source(FakeSource, auth_entity, listen) cookie = 'logins="/fake/{id}?fake|/other/1?bob";' self.assertIn(cookie.format(id=id), rr.exception.get_response().headers['Set-Cookie']) id = FakeSource.next_key().id() with self.assertRaises(RequestRedirect) as rr: util.maybe_add_or_delete_source(FakeSource, auth_entity, listen) self.assertIn(cookie.format(id=id), rr.exception.get_response().headers['Set-Cookie'])
#!/usr/bin/env python from flask import url_for from flask_app import app from routes import * from dotenv import load_dotenv # Utilize .env environment variables for GoogleAPI # Citation: July 28th, 2019. https://pypi.org/project/python-dotenv/ load_dotenv() with app.test_request_context(): print(url_for('Landing')) print(url_for('CategoryListing', category_id=1)) app.secret_key = 'non-production-ready-secret'
def test_new_no_primary_blog(self): self.auth_entity.user_json = json_dumps({'user': {'blogs': [{'url': 'foo'}]}}) with app.test_request_context(): self.assertIsNone(Tumblr.new(auth_entity=self.auth_entity)) self.assertIn('Tumblr blog not found', get_flashed_messages()[0])
def test_new_no_blogs(self): self.auth_entity.blog_hostnames = [] with app.test_request_context(): self.assertIsNone(Blogger.new(auth_entity=self.auth_entity)) self.assertIn('Blogger blog not found', get_flashed_messages()[0])
def get_expense_url(self, expense_id): with app.test_request_context(): return url_for('expenseitem', expense_id=expense_id)
class ExpenseApiTest(ExpenseTestUtils): with app.test_request_context(): EXPENSE_LIST_URL = url_for('expense') @tools.nottest def get_expense_url(self, expense_id): with app.test_request_context(): return url_for('expenseitem', expense_id=expense_id) def test_expenses_get(self): # GET - without authentication response = self.client.get(self.EXPENSE_LIST_URL) self.assert_401(response) self.assertIsNotNone(response.data) # GET - with authentication - no expenses user, headers, refresh_headers_ = self.create_jwt_test_user() response = self.client.get(self.EXPENSE_LIST_URL, headers=headers) self.assert_200(response) self.assertIsNotNone(response.json) expenses = response.json['expenses'] self.assertEqual(len(expenses), 0) # GET - several expenses num_expenses = 10 expense_ids = [] for x in range(0, num_expenses): expense = self.insert_test_expense(user=user) expense_ids.append(expense.id) response = self.client.get(self.EXPENSE_LIST_URL, headers=headers) self.assertIsNotNone(response.json) response_expenses = response.json['expenses'] self.assertEqual(len(response_expenses), num_expenses) def test_expense_get(self): user_1, headers_1, refresh_headers_ = self.create_jwt_test_user(name='test_user_1') user_2, headers_2, refresh_headers_ = self.create_jwt_test_user(name='test_user_2') # GET - without authentication response = self.client.get(self.get_expense_url(1)) self.assert_401(response) self.assertIsNotNone(response.data) # GET - expense_id does not belong to user expense = self.insert_test_expense(user=user_1) expense_url = self.get_expense_url(expense.id) response = self.client.get(expense_url, headers=headers_2) self.assert_401(response) # GET - expense_id belongs to user response = self.client.get(expense_url, headers=headers_1) self.assert_200(response) self.assertIsNotNone(response.json) # GET - expense_id does not belong to user, but user is an admin user_2.is_admin = True db.session.commit() response = self.client.get(expense_url, headers=headers_2) self.assert_200(response) self.assertIsNotNone(response.json) def test_expense_post(self): # POST - without authentication response = self.client.post(self.EXPENSE_LIST_URL, content_type='application/json') self.assert_401(response) # POST - missing data user, headers, refresh_headers_ = self.create_jwt_test_user() response = self.client.post(self.EXPENSE_LIST_URL, content_type='application/json', headers=headers, data=json.dumps({})) self.assert_422(response) # POST - data included dt = pendulum.now().subtract() timestamp = dt.to_iso8601_string() data = { 'timestamp': timestamp, 'amount': 10.5, 'description': 'Test description' } response = self.client.post(self.EXPENSE_LIST_URL, content_type='application/json', headers=headers, data=json.dumps(data)) self.assert_200(response) self.assertSuccessIsTrue(response) expense_json = response.json['expense'] self.assertEqual(expense_json['user_id'], user.id) def test_expense_put(self): dt = pendulum.now().subtract() timestamp = dt.to_iso8601_string() data = { 'timestamp': timestamp, 'amount': 15.0, 'description': 'Updated test description' } # PUT - without authentication response = self.client.put(self.get_expense_url(1)) self.assert_401(response) self.assertIsNotNone(response.data) user_1, headers_1, refresh_headers_ = self.create_jwt_test_user(name='test_user_1') user_2, headers_2, refresh_headers_ = self.create_jwt_test_user(name='test_user_2') # PUT - missing data expense = self.insert_test_expense(user=user_1) expense_url = self.get_expense_url(expense.id) response = self.client.put(expense_url, headers=headers_1) self.assert_422(response) # PUT - expense does not exist expense = self.insert_test_expense(user=user_1) expense_url = self.get_expense_url(expense.id) db.session.delete(expense) db.session.commit() response = self.client.put(expense_url, headers=headers_1, content_type='application/json', data=json.dumps(data)) self.assert_401(response) # PUT - wrong user expense = self.insert_test_expense(user=user_1) expense_url = self.get_expense_url(expense.id) response = self.client.put(expense_url, headers=headers_2, content_type='application/json', data=json.dumps(data)) self.assert_401(response) # PUT - good request expense = self.insert_test_expense(user=user_1) expense_url = self.get_expense_url(expense.id) response = self.client.put(expense_url, headers=headers_1, content_type='application/json', data=json.dumps(data)) self.assert_200(response) self.assertSuccessIsTrue(response) self.assertEqual(expense.amount, data['amount']) self.assertEqual(expense.description, data['description']) def test_expense_delete(self): # DELETE - without authentication response = self.client.delete(self.get_expense_url(1)) self.assert_401(response) self.assertIsNotNone(response.data) user_1, headers_1, refresh_headers_ = self.create_jwt_test_user(name='test_user_1') user_2, headers_2, refresh_headers_ = self.create_jwt_test_user(name='test_user_2') # DELETE - with authentication, but wrong user expense = self.insert_test_expense(user=user_1) expense_url = self.get_expense_url(expense.id) response = self.client.delete(expense_url, headers=headers_2) self.assert_401(response) # DELETE - with authentication, but expense does not exist expense = self.insert_test_expense(user=user_1) expense_url = self.get_expense_url(expense.id) db.session.delete(expense) db.session.commit() response = self.client.delete(expense_url, headers=headers_1) self.assert_401(response) # DELETE - successful request expense = self.insert_test_expense(user=user_1) expense_url = self.get_expense_url(expense.id) response = self.client.delete(expense_url, headers=headers_1) self.assert_200(response) self.assertSuccessIsTrue(response)