Add FCM device registration and Gitea bug reporter
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
import json
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
import httpx
|
||||
from starlette.requests import Request
|
||||
|
||||
from bug_reporter import browser_summary, issue_body, safe_route
|
||||
from gitea_service import GiteaConfig, GiteaError, GiteaService, redact
|
||||
|
||||
|
||||
class GiteaTests(unittest.TestCase):
|
||||
def service(self, handler):
|
||||
return GiteaService(GiteaConfig('http://gitea.invalid', 'test-secret-never-print', 'kai', 'pingu-concerts'), httpx.MockTransport(handler))
|
||||
|
||||
def test_existing_labels_bot_and_payload(self):
|
||||
requests = []
|
||||
def handler(request):
|
||||
requests.append(request)
|
||||
if request.url.path.endswith('/user'):
|
||||
return httpx.Response(200, json={'login': 'metalcircle-bot'})
|
||||
if request.url.path.endswith('/labels'):
|
||||
return httpx.Response(200, json=[{'id': 7, 'name': 'reported-from-metalcircle'}, {'id': 9, 'name': 'android'}, {'id': 99, 'name': 'unrelated'}])
|
||||
return httpx.Response(201, json={'number': 123, 'user': {'login': 'metalcircle-bot'}})
|
||||
self.assertEqual(self.service(handler).create_issue('A test title', 'A test body', 'android'), 123)
|
||||
payload = json.loads(requests[-1].content)
|
||||
self.assertEqual(payload['labels'], [7, 9])
|
||||
self.assertEqual(payload['title'], '[MetalCircle Bug] A test title')
|
||||
self.assertEqual(requests[-1].url.path, '/api/v1/repos/kai/pingu-concerts/issues')
|
||||
self.assertNotIn('test-secret', str(requests[-1].url))
|
||||
|
||||
def test_missing_or_inaccessible_labels_do_not_block(self):
|
||||
for response in (httpx.Response(200, json=[]), httpx.Response(403), httpx.Response(200, json={'invalid': True})):
|
||||
def handler(request):
|
||||
if request.url.path.endswith('/user'): return httpx.Response(200, json={'login': 'metalcircle-bot'})
|
||||
if request.url.path.endswith('/labels'): return response
|
||||
self.assertEqual(json.loads(request.content)['labels'], [])
|
||||
return httpx.Response(201, json={'number': 4, 'user': {'login': 'metalcircle-bot'}})
|
||||
self.assertEqual(self.service(handler).create_issue('Test title', 'body', 'general'), 4)
|
||||
|
||||
def test_personal_account_is_rejected_before_post(self):
|
||||
def handler(request):
|
||||
self.assertEqual(request.method, 'GET')
|
||||
return httpx.Response(200, json={'login': 'kai'})
|
||||
with self.assertRaisesRegex(GiteaError, 'wrong_account'):
|
||||
self.service(handler).create_issue('title', 'body', 'general')
|
||||
|
||||
def test_http_errors_and_secret_free_logs(self):
|
||||
for code in (401, 403, 404, 500, 502):
|
||||
def handler(request):
|
||||
if request.url.path.endswith('/user'): return httpx.Response(200, json={'login': 'metalcircle-bot'})
|
||||
if request.url.path.endswith('/labels'): return httpx.Response(200, json=[])
|
||||
return httpx.Response(code, text='test-secret-never-print')
|
||||
with self.subTest(code=code), self.assertLogs('gitea_service', 'WARNING') as logs:
|
||||
with self.assertRaises(GiteaError) as caught:
|
||||
self.service(handler).create_issue('title', 'body', 'general')
|
||||
self.assertEqual(caught.exception.uncertain, code >= 500)
|
||||
self.assertNotIn('test-secret-never-print', '\n'.join(logs.output))
|
||||
|
||||
def test_timeout_unreachable_and_invalid_response(self):
|
||||
for failure in ('timeout', 'unreachable', 'invalid_json', 'invalid_issue'):
|
||||
def handler(request):
|
||||
if failure == 'unreachable': raise httpx.ConnectError('test-secret-never-print')
|
||||
if request.url.path.endswith('/user'): return httpx.Response(200, json={'login': 'metalcircle-bot'})
|
||||
if request.url.path.endswith('/labels'): return httpx.Response(200, json=[])
|
||||
if failure == 'timeout': raise httpx.ReadTimeout('test-secret-never-print')
|
||||
if failure == 'invalid_json': return httpx.Response(201, text='not json')
|
||||
return httpx.Response(201, json={'number': 'x'})
|
||||
with self.subTest(failure=failure), self.assertLogs('gitea_service', 'WARNING') as logs:
|
||||
with self.assertRaises(GiteaError) as caught:
|
||||
self.service(handler).create_issue('title', 'body', 'general')
|
||||
self.assertEqual(caught.exception.uncertain, failure != 'unreachable')
|
||||
self.assertNotIn('test-secret', '\n'.join(logs.output))
|
||||
|
||||
def test_context_allowlist_and_redaction(self):
|
||||
secret = 'session-secret-never-send'
|
||||
request = Request({'type': 'http', 'headers': [
|
||||
(b'cookie', ('pingu_session='+secret).encode()),
|
||||
(b'authorization', b'Bearer authorization-secret'),
|
||||
(b'user-agent', b'Chrome/128.0 secret-header'),
|
||||
]})
|
||||
data = dict(description='This is '+secret, expected='Expected result', steps='', category='android',
|
||||
severity='normal', technical=True, platform='Android', app_version='1.1.0-debug',
|
||||
route='/concerts/1?token=secret-query')
|
||||
with patch.dict('os.environ', {'GITEA_TOKEN': 'bot-secret-never-send'}):
|
||||
body = issue_body(data, {'id': 12, 'username': 'real-user'}, request)
|
||||
for excluded in (secret, 'authorization-secret', 'secret-header', 'secret-query', 'bot-secret-never-send'):
|
||||
self.assertNotIn(excluded, body)
|
||||
self.assertIn('real-user', body)
|
||||
self.assertIn('12', body)
|
||||
self.assertIn('/concerts/1', body)
|
||||
self.assertIn('Chrome 128.0', body)
|
||||
self.assertEqual(safe_route('/password-reset/sensitive'), '/')
|
||||
self.assertEqual(safe_route('/register/sensitive'), '/')
|
||||
self.assertEqual(browser_summary('Cookie: evil'), 'Unknown')
|
||||
data['technical'] = False
|
||||
self.assertNotIn('Chrome', issue_body(data, {'id': 12, 'username': 'real-user'}, request))
|
||||
self.assertNotIn('/concerts/1', issue_body(data, {'id': 12, 'username': 'real-user'}, request))
|
||||
self.assertNotIn('super-secret', redact('password=super-secret'))
|
||||
self.assertNotIn('private bytes', redact('-----BEGIN PRIVATE KEY-----\nprivate bytes\n-----END PRIVATE KEY-----'))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user