async def test_upload_image(): image_url = 'https://img.xiaoduanshijian.com/f28cc520be6ee16e8141-c66f9f10-27bb-1.png' endpoint_url = 'https://foo.com/api/image/v4/put/' get_token_url = 'https://foo.com/api/auth/v3/app_access_token/internal/' with pook.use(): pook.get(image_url, response_body=b'abc') pook.post(get_token_url, response_json={ 'code': 0, 'msg': 'OK', 'tenant_access_token': 'test' }) pook.post(endpoint_url, response_json={ 'code': 0, 'msg': 'OK', 'data': { 'image_key': 'test-image-key' } }) bot = FeishuBot('foo', 'bar', 'https://foo.com/api') image_key = await bot.upload_image(image_url) assert image_key == 'test-image-key'
async def test_update_group_name(): with pook.use(): get_token_mock_1 = pook.post( 'https://foo.com/api/auth/v3/app_access_token/internal/', response_json={ 'code': 0, 'msg': 'OK', 'tenant_access_token': 'test-token' }) pook.get('https://foo.com/api/chat/v4/list', response_json={ 'code': 0, 'msg': 'OK', 'data': { 'groups': [{ 'chat_id': 'test_chat_id' }] } }) new_name = f'#名片审核 {datetime.now().isoformat()}' update_mock = pook.post('https://foo.com/api/chat/v4/update/', response_json={ 'code': 0, 'msg': 'OK', }) bot = FeishuBot('foo', 'bar', 'https://foo.com/api') groups = await bot.get_groups() g = groups[0] await bot.update_group_name(g['chat_id'], new_name) assert update_mock.calls == 1
async def test_refresh_token(): with pook.use(): # Populate token with request get_token_mock_1 = pook.post( 'https://foo.com/api/auth/v3/app_access_token/internal/', response_json={ 'code': 0, 'msg': 'OK', 'tenant_access_token': 'test' }) pook.get('https://foo.com/api/chat/v4/list').\ header('Authorization', 'Bearer test').\ reply(200).\ json({'code': 0, 'msg': 'OK', 'data': { 'groups': [ {'chat_id': 'chat_id_1', 'name': 'group_1'}, {'chat_id': 'chat_id_2', 'name': 'group_2'} ] }}) # Pass the first send text send_text_mock_1 = pook.post('https://foo.com/api/message/v4/send/', headers={'Authorization': 'Bearer test'}, response_json={ 'code': 0, 'msg': 'OK', 'data': {} }) # Fail the second send text with token expired send_text_mock_2 = pook.post('https://foo.com/api/message/v4/send/', headers={'Authorization': 'Bearer test'}, response_json={ 'code': 99991663, 'msg': 'token expired', }) # Feed the valid token get_token_mock_2 = pook.post( 'https://foo.com/api/auth/v3/app_access_token/internal/', response_json={ 'code': 0, 'msg': 'OK', 'tenant_access_token': 'test2' }) # System would try again send_text_mock_3 = pook.post('https://foo.com/api/message/v4/send/', headers={'Authorization': 'Bearer test2'}, response_json={ 'code': 0, 'msg': 'OK', 'data': {} }) bot = FeishuBot('foo', 'bar', 'https://foo.com/api') resp = await bot.send_text('hello world')
def setup_fake_classroom_api( suffix_response_pairs: List[Tuple[str, str]]) -> Resource: """ Set up a fake Google Classroom/Admin SDK API using the pook HTTP traffic mocking library Parameters ---------- suffix_response_pairs: List[Tuple[str, str]] are pairs of endpoint suffixes and response jsons where endpoint suffixes are the suffixes of the endpoint being faked, for example: "courses" for the courses endpoint response jsons are the corresponding json response bodies to be returned. Returns ------- Resource a Google Classroom SDK Resource Notes ----- Requires pook to already be activated in a test """ fake_discovery_endpoint_json: str = Path( "tests/api/fake-classroom-discovery-endpoint.json").read_text() fake_credentials: Credentials = Credentials.from_service_account_file( "tests/api/fake-service-account.json", scopes=[], subject="*****@*****.**") pook.get( "http://www.googleapis.com:443/discovery/v1/apis/classroom/v1/rest", response_json=fake_discovery_endpoint_json, reply=200, ) pook.post( "http://oauth2.googleapis.com:443/token", response_json='{"access_token": "fake"}', reply=200, ) for suffix, response in suffix_response_pairs: pook.get( f"http://classroom.googleapis.com:443/v1/{suffix}", response_json=response, reply=200, ) return build("classroom", "v1", credentials=fake_credentials, cache_discovery=False)
async def test_me(bot): pook.post(f'https://api.telegram.org/bot{API_TOKEN}/getMe', response_json={ 'ok': True, 'result': { 'id': 1, 'is_bot': True, 'first_name': 'Test Bot', 'username': '******' } }) res = json.loads(str(await bot.me)) assert (res['username'] == 'test_bot')
def setup_fake_reports_api(endpoint_suffix: str, response_json: str) -> Resource: """ Set up a fake Google Reports SDK API using the pook HTTP traffic mocking library Parameters ---------- endpoint_suffix: string is the suffix of the endpoint being faked, for example: "courses" for the courses endpoint response_json: string is the json response body to be returned Returns ------- Resource a Google Reports SDK Resource Notes ----- Requires pook to already be activated in a test """ fake_discovery_endpoint_json: str = Path( "tests/api/fake-admin-discovery-endpoint.json").read_text() fake_credentials: Credentials = Credentials.from_service_account_file( "tests/api/fake-service-account.json", scopes=[], subject="*****@*****.**") pook.get( "http://www.googleapis.com:443/discovery/v1/apis/admin/reports_v1/rest", response_json=fake_discovery_endpoint_json, reply=200, ) pook.post( "http://oauth2.googleapis.com:443/token", response_json='{"access_token": "fake"}', reply=200, ) pook.get( f"http://www.googleapis.com:443/admin/reports/v1/{endpoint_suffix}", response_json=response_json, reply=200, ) return build("admin", "reports_v1", credentials=fake_credentials, cache_discovery=False)
def test_kong_gateway_add_api(): pook.get('http://kong:8001/apis/test-api', reply=404, response_json={'message': 'Not Found'}) (pook.post('http://kong:8001/apis/').json({ 'name': 'test-api', 'uris': '/test,/api/test', 'upstream_url': 'http://test.services.lan:8080' }).reply(201).json({ 'created_at': 1540213698704, 'strip_uri': False, 'id': '6af8aa24-b520-471a-bced-942e6cc023b6', 'name': 'test-api', 'http_if_terminated': True, 'https_only': False, 'upstream_url': 'http://test.services.lan:8080', 'uris': [ '/test', '/api/test' ], 'preserve_host': False, 'upstream_connect_timeout': 60000, 'upstream_read_timeout': 60000, 'upstream_send_timeout': 60000, 'retries': 5 })) reg = KongGatewayRegistrator(gw_admin_url='http://kong:8001') resp = reg.register(name='test-api', host='test.services.lan', port=8080, paths=['/test', '/api/test']) assert resp is not None
async def test_auto_invalidate_token_cache(): with pook.use(): get_token_mock_1 = pook.post( 'https://foo.com/api/auth/v3/app_access_token/internal/', response_json={ 'code': 0, 'msg': 'OK', 'tenant_access_token': 'test-token' }) get_user_detail_mock = pook.get( 'https://foo.com/api/contact/v1/user/batch_get', times=2, response_json={ 'code': 0, 'msg': 'OK', 'data': { 'user_infos': [{}] } }) get_token_mock_2 = pook.post( 'https://foo.com/api/auth/v3/app_access_token/internal/', response_json={ 'code': 0, 'msg': 'OK', 'tenant_access_token': 'test-token2' }) bot = FeishuBot('foo', 'bar', 'https://foo.com/api', token_ttl=0.1) resp = await bot.get_user_detail('test-user-id') # Wait for token expiry await asyncio.sleep(.1) resp = await bot.get_user_detail('test-user-id') matches = get_user_detail_mock.matches assert len(matches) == 2 assert matches[0].headers == {'Authorization': 'Bearer test-token'} assert matches[1].headers == {'Authorization': 'Bearer test-token2'}
async def test_send_text(): with pook.use(): get_token_mock = pook.post( 'https://foo.com/api/auth/v3/app_access_token/internal/', response_json={ 'code': 0, 'msg': 'OK', 'tenant_access_token': 'test' }) pook.get('https://foo.com/api/chat/v4/list').\ header('Authorization', 'Bearer test').\ reply(200).\ json({'code': 0, 'msg': 'OK', 'data': { 'groups': [ {'chat_id': 'chat_id_1', 'name': 'group_1'}, {'chat_id': 'chat_id_2', 'name': 'group_2'} ] }}) send_message_mock = pook.post('https://foo.com/api/message/v4/send/', times=2, headers={'Authorization': 'Bearer test'}, response_json={ 'code': 0, 'msg': 'OK', 'data': { 'groups': [{ 'chat_id': 'chat_id_1' }] } }) bot = FeishuBot('foo', 'bar', 'https://foo.com/api') resp = await bot.send_text('hello world') assert send_message_mock.calls == 2 assert get_token_mock.calls == 1
def testShouldThrowErrorWhenCannotRefreshToken(self): expired_token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVC" (pook.post(self.configuration.host + '/oauth2/token').times(1).reply(500).type('json').json( {'Error': "Unknown Error"})) (pook.get(self.configuration.host + '/v1/valid/url').header( 'Authorization', "Bearer " + expired_token ).times(0).reply(200).type('json').json({ 'message': "can't make this call since client could not refresh expired token" })) with self.assertRaises(ApiException) as cm: self.get_with_expired_token(expired_token) self.assertEqual(cm.exception.status, 500) self.assertIn("Cannot refresh token by calling", cm.exception.body["token_error"]) self.assertTrue(pook.isdone())
def testAlwaysSendValidBearerToken(self): expired_token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJjdHg6dXNlcjp1bXNJZCI6IjIyNjQyMSIsImN0eDp1c2VyOnVp" fresh_token = "kltTjBlKHAxYzJWIiwiY3" (pook.post(self.configuration.host + '/oauth2/token').header( "Content-Type", "application/x-www-form-urlencoded").body( 'client_id=%s&client_secret=%s&grant_type=client_credentials' % (self.configuration.username, self.configuration.password)). times(1).reply(200).type('json').json( dict(access_token=fresh_token, expires_in=299, token_type="bearer"))) (pook.get(self.configuration.host + '/v1/valid/url').header( 'Authorization', "Bearer " + fresh_token).times(1).reply(200).type('json').json( {'status': 'ok'})) res = self.get_with_expired_token(expired_token) self.assertTrue(pook.isdone()) self.assertEqual(res, {'status': 'ok'})
async def test_updates(bot): pook.post(f'https://api.telegram.org/bot{API_TOKEN}/getFile', response_json={ 'ok': True, 'result': { 'file_id': "id", 'file_size': 0, 'file_path': "path" } }) pook.post(f'https://api.telegram.org/bot{API_TOKEN}/sendMessage', times=3, response_json={ 'ok': True, 'result': { 'chat_id': 167777762, 'text': '...', 'reply_markup': { 'remove_keyboard': True, 'selective': False } } }) pook.post(f'https://api.telegram.org/bot{API_TOKEN}/getUpdates', response_json={ 'ok': True, 'result': [{ 'update_id': 919389466, 'message': get_mock_message('/start') }, { 'update_id': 919389467, 'message': get_mock_message('/help') }, { 'update_id': 919389468, 'message': get_mock_message('common phrase') }] }) res = await bot.get_updates() res = [json.loads(str(x))['update_id'] for x in res] assert (res == [919389466, 919389467, 919389468])
import json import pook import requests # Enable mock engine pook.on() (pook.post('httpbin.org/post') .json({'foo': 'bar'}) .type('json') .header('Client', 'requests') .reply(204) .headers({'server': 'pook'}) .json({'error': 'simulated'})) res = requests.post('http://httpbin.org/post', data=json.dumps({'foo': 'bar'}), headers={'Client': 'requests', 'Content-Type': 'application/json'}) print('Status:', res.status_code) print('Body:', res.json()) print('Is done:', pook.isdone()) print('Pending mocks:', pook.pending_mocks())
import json import pook import requests # Enable mock engine pook.on() (pook.post('httpbin.org/post').json({ 'foo': 'bar' }).reply(204).json({'error': 'simulated'})) res = requests.post('http://httpbin.org/post', data=json.dumps({'foo': 'bar'})) print('Status:', res.status_code) print('Body:', res.json()) print('Is done:', pook.isdone()) print('Pending mocks:', pook.pending_mocks())
import json import requests import pook pook.on() # Register a POST mock (pook.post('httpbin.org/post').json({ 'foo': 'bar' }).type('json').header('Client', 'requests').reply(204).headers({ 'server': 'pook' }).json({'body': 'FIRST'})) # Register with same URL but diff BODY (pook.post('httpbin.org/post').json({ 'foo': 'ha' }).type('json').header('Client', 'requests').reply(204).headers({ 'server': 'pook' }).json({'body': 'SECOND'})) res = requests.post('http://httpbin.org/post', data=json.dumps({'foo': 'bar'}), headers={ 'Client': 'requests', 'Content-Type': 'application/json' }) print(res.status_code) print(res.headers) print(res.content)
import json import pook import requests schema = { 'type': 'object', 'properties': { 'foo': { 'type': 'string' }, } } # Enable mock engine pook.on() (pook.post('httpbin.org/post').jsonschema(schema).reply(204).json( {'error': 'simulated'})) res = requests.post('http://httpbin.org/post', data=json.dumps({'foo': 'bar'})) print('Status:', res.status_code) print('Body:', res.json()) print('Is done:', pook.isdone()) print('Pending mocks:', pook.pending_mocks())