async def test_get_dog_image_url(response_mock): response_mock.get( "https://dog.ceo/api/breeds/image/random", body="", status=500, ) response_mock.get( "https://dog.ceo/api/breeds/image/random", exception=aiohttp.client_exceptions.ServerDisconnectedError(), ) response_mock.get( "https://dog.ceo/api/breeds/image/random", body=json.dumps({ "status": "success", "message": "http://dog.com/404.jpg" }), headers={"Content-Type": "application/json"}, ) response_mock.get( "https://dog.ceo/api/breeds/image/random", body=json.dumps({ "status": "success", "message": "http://cannotresolve.com/200.jpg", }), headers={"Content-Type": "application/json"}, ) response_mock.get( "https://dog.ceo/api/breeds/image/random", body=json.dumps({ "status": "success", "message": "http://timeout.com/200.jpg" }), headers={"Content-Type": "application/json"}, ) response_mock.get( "https://dog.ceo/api/breeds/image/random", body=json.dumps({ "status": "success", "message": "http://dog.com/200.jpg" }), headers={"Content-Type": "application/json"}, ) response_mock.get( "http://cannotresolve.com/200.jpg", exception=aiohttp.ClientConnectorError(None, OSError()), ) response_mock.get( "http://timeout.com/200.jpg", exception=asyncio.TimeoutError(), ) response_mock.get("http://dog.com/404.jpg", status=404) response_mock.get("http://dog.com/200.jpg", status=200) with pytest.raises(APIServerError): await get_dog_image_url(0.001) url = await get_dog_image_url(0.001) assert url == "http://dog.com/200.jpg"
async def test_get_dog_image_url(response_mock): response_mock.get( 'https://dog.ceo/api/breeds/image/random', body='', status=500, ) response_mock.get( 'https://dog.ceo/api/breeds/image/random', exception=aiohttp.client_exceptions.ServerDisconnectedError(), ) response_mock.get( 'https://dog.ceo/api/breeds/image/random', body=json.dumps({ 'status': 'success', 'message': 'http://dog.com/404.jpg', }), headers={'Content-Type': 'application/json'}, ) response_mock.get( 'https://dog.ceo/api/breeds/image/random', body=json.dumps({ 'status': 'success', 'message': 'http://cannotresolve.com/200.jpg', }), headers={'Content-Type': 'application/json'}, ) response_mock.get( 'https://dog.ceo/api/breeds/image/random', body=json.dumps({ 'status': 'success', 'message': 'http://timeout.com/200.jpg', }), headers={'Content-Type': 'application/json'}, ) response_mock.get( 'https://dog.ceo/api/breeds/image/random', body=json.dumps({ 'status': 'success', 'message': 'http://dog.com/200.jpg', }), headers={'Content-Type': 'application/json'}, ) response_mock.get( 'http://cannotresolve.com/200.jpg', exception=aiohttp.ClientConnectorError(None, OSError()), ) response_mock.get( 'http://timeout.com/200.jpg', exception=asyncio.TimeoutError(), ) response_mock.get('http://dog.com/404.jpg', status=404) response_mock.get('http://dog.com/200.jpg', status=200) with pytest.raises(APIServerError): await get_dog_image_url(0.001) url = await get_dog_image_url(0.001) assert url == 'http://dog.com/200.jpg'
async def test_aqi_error2(bot_config, cache, response_mock): response_mock.get( 'https://maps.googleapis.com/maps/api/geocode/json?' + urlencode({ 'region': 'kr', 'address': addr1, 'key': 'qwer' }), body=json.dumps({ 'results': [ { 'formatted_address': '대한민국 경기도 부천시', 'geometry': { 'location': { 'lat': 37.5034138, 'lng': 126.7660309, }, }, }, ], }), headers={'Content-Type': 'application/json'}, ) response_mock.get( 'https://api.waqi.info/feed/geo:' '37.5034138;126.7660309/?token=asdf', body=json.dumps({'data': { 'idx': '5511' }}), headers={'Content-Type': 'application/json'}, ) response_mock.post( 'https://api.waqi.info/api/feed/@5511/obs.en.json', body=json.dumps({'rxs': { 'obs': [{ 'status': '404' }] }}), headers={'Content-Type': 'application/json'}, ) bot_config.AQI_API_TOKEN = 'asdf' bot_config.GOOGLE_API_KEY = 'qwer' bot = FakeBot(bot_config, cache=cache) bot.add_channel('C1', 'general') bot.add_user('U1', 'item4') event = bot.create_message('C1', 'U1', '1234.5678') async with bot.begin(): await aqi(bot, event, addr1) said = bot.call_queue.pop(0) assert said.method == 'chat.postMessage' assert said.data['channel'] == 'C1' assert said.data['text'] == '현재 AQI 서버의 상태가 좋지 않아요! 나중에 다시 시도해주세요!'
async def test_aqi_error2(bot_config, cache, response_mock): response_mock.get( "https://maps.googleapis.com/maps/api/geocode/json?" + urlencode({ "region": "kr", "address": addr1, "key": "qwer" }), body=json.dumps({ "results": [ { "formatted_address": "대한민국 경기도 부천시", "geometry": { "location": { "lat": 37.5034138, "lng": 126.7660309, }, }, }, ], }), headers={"Content-Type": "application/json"}, ) response_mock.get( "https://api.waqi.info/feed/geo:" "37.5034138;126.7660309/?token=asdf", body=json.dumps({"data": { "idx": "5511" }}), headers={"Content-Type": "application/json"}, ) response_mock.post( "https://api.waqi.info/api/feed/@5511/obs.en.json", body=json.dumps({"rxs": { "obs": [{ "status": "404" }] }}), headers={"Content-Type": "application/json"}, ) bot_config.AQI_API_TOKEN = "asdf" bot_config.GOOGLE_API_KEY = "qwer" bot = FakeBot(bot_config, cache=cache) bot.add_channel("C1", "general") bot.add_user("U1", "item4") event = bot.create_message("C1", "U1", "1234.5678") async with bot.begin(): await aqi(bot, event, addr1) said = bot.call_queue.pop(0) assert said.method == "chat.postMessage" assert said.data["channel"] == "C1" assert said.data["text"] == "현재 AQI 서버의 상태가 좋지 않아요! 나중에 다시 시도해주세요!"
async def test_get_aqi_wrong_idx(response_mock): response_mock.get( 'https://api.waqi.info/feed/geo:123;456/?token=asdf', body=json.dumps({'data': {'idx': 'wrong'}}), headers={'Content-Type': 'application/json'}, ) response_mock.get( 'https://api.waqi.info/api/feed/@wrong/obs.en.json', body=json.dumps({'rxs': {'obs': [{'status': '404'}]}}), headers={'Content-Type': 'application/json'}, ) result = await get_aqi_idx(123, 456, 'asdf') assert result == 'wrong'
async def test_auto_packtpub_dotd(response_mock, fx_config): assert auto_packtpub_dotd.cron.spec == '5 9 * * *' product_id = '11223344' title = 'test book' image_url = 'test url' response_mock.get( 'https://services.packtpub.com/free-learning-v1/offers' f'?dateFrom=2018-10-07T00:00:00.000Z&dateTo=2018-10-08T00:00:00.000Z', body=json.dumps({ 'data': [{'productId': product_id}], }), headers={'Content-Type': 'application/json'}, ) response_mock.get( f'https://static.packt-cdn.com/products/{product_id}/summary', body=json.dumps({ 'title': title, 'coverImage': image_url, }), headers={'Content-Type': 'application/json'}, ) fx_config.CHANNELS = { 'general': 'general', } bot = FakeBot(fx_config) bot.add_channel('C1', 'general') await auto_packtpub_dotd(bot) said = bot.call_queue.pop(0) assert said.method == 'chat.postMessage' assert said.data['channel'] == 'C1' assert said.data['text'] == '오늘자 PACKT Book의 무료책이에요!' attachments = json.loads(said.data['attachments']) assert len(attachments) == 1 assert attachments[0]['fallback'] == f'{title} - {PACKTPUB_URL}' assert attachments[0]['title'] == title assert attachments[0]['title_link'] == PACKTPUB_URL assert attachments[0]['text'] == ( f'오늘의 Packt Book Deal of The Day: {title} - {PACKTPUB_URL}' ) assert attachments[0]['image_url'] == image_url
async def test_auto_packtpub_dotd(bot_config, response_mock): assert auto_packtpub_dotd.cron.spec == "5 9 * * *" product_id = "11223344" title = "test book" image_url = "test url" response_mock.get( "https://services.packtpub.com/free-learning-v1/offers" "?dateFrom=2018-10-07T00:00:00.000Z&dateTo=2018-10-08T00:00:00.000Z", body=json.dumps({"data": [{ "productId": product_id }]}), headers={"Content-Type": "application/json"}, ) response_mock.get( f"https://static.packt-cdn.com/products/{product_id}/summary", body=json.dumps({ "title": title, "coverImage": image_url }), headers={"Content-Type": "application/json"}, ) bot_config.CHANNELS = { "general": "C1", } bot = FakeBot(bot_config) bot.add_channel("C1", "general") await auto_packtpub_dotd(bot) said = bot.call_queue.pop(0) assert said.method == "chat.postMessage" assert said.data["channel"] == "C1" assert said.data["text"] == "오늘자 PACKT Book의 무료책이에요!" attachments = said.data["attachments"] assert len(attachments) == 1 assert attachments[0]["fallback"] == f"{title} - {PACKTPUB_URL}" assert attachments[0]["title"] == title assert attachments[0]["title_link"] == PACKTPUB_URL assert attachments[0]["text"] == ( f"오늘의 Packt Book Deal of The Day: {title} - {PACKTPUB_URL}") assert attachments[0]["image_url"] == image_url
async def test_get_aqi_wrong_idx(response_mock): response_mock.get( "https://api.waqi.info/feed/geo:123;456/?token=asdf", body=json.dumps({"data": { "idx": "wrong" }}), headers={"Content-Type": "application/json"}, ) response_mock.get( "https://api.waqi.info/api/feed/@wrong/obs.en.json", body=json.dumps({"rxs": { "obs": [{ "status": "404" }] }}), headers={"Content-Type": "application/json"}, ) result = await get_aqi_idx(123, 456, "asdf") assert result == "wrong"
async def test_packtpub_dotd(bot, response_mock): product_id = '11223344' title = 'test book' image_url = 'test url' response_mock.get( 'https://services.packtpub.com/free-learning-v1/offers' '?dateFrom=2018-10-07T00:00:00.000Z&dateTo=2018-10-08T00:00:00.000Z', body=json.dumps({'data': [{'productId': product_id}]}), headers={'Content-Type': 'application/json'}, ) response_mock.get( f'https://static.packt-cdn.com/products/{product_id}/summary', body=json.dumps({'title': title, 'coverImage': image_url}), headers={'Content-Type': 'application/json'}, ) bot.add_channel('C1', 'general') bot.add_user('U1', 'item4') event = bot.create_message('C1', 'U1') await packtpub_dotd(bot, event) said = bot.call_queue.pop(0) assert said.method == 'chat.postMessage' assert said.data['channel'] == 'C1' assert said.data['text'] == '오늘자 PACKT Book의 무료책이에요!' attachments = said.data['attachments'] assert len(attachments) == 1 assert attachments[0]['fallback'] == f'{title} - {PACKTPUB_URL}' assert attachments[0]['title'] == title assert attachments[0]['title_link'] == PACKTPUB_URL assert attachments[0]['text'] == ( f'오늘의 Packt Book Deal of The Day: {title} - {PACKTPUB_URL}' ) assert attachments[0]['image_url'] == image_url
async def test_get_aqi_wrong_geometric_info(response_mock): addr = "WRONG" key = "XXX" response_mock.get( "https://maps.googleapis.com/maps/api/geocode/json" f"?region=kr&address={addr}&key=XXX", body=json.dumps({ "results": [], }), headers={"Content-Type": "application/json"}, ) with pytest.raises(IndexError): await get_geometric_info_by_address( addr, key, )
async def test_exchange_error(bot, response_mock): response_mock.get( "https://api.manana.kr/exchange/rate.json?base=KRW&code=JPY", body=json.dumps([False]), headers={"Content-Type": "application/json"}, ) bot.add_channel("C1", "test") bot.add_user("U1", "tester") event = bot.create_message("C1", "U1") await exchange(bot, event, "100엔") said = bot.call_queue.pop(0) assert said.method == "chat.postMessage" assert said.data["channel"] == "C1" assert said.data["text"] == "알 수 없는 에러가 발생했어요! 아빠에게 문의해주세요!"
async def test_get_aqi_wrong_geometric_info(response_mock): addr = 'WRONG' key = 'XXX' response_mock.get( 'https://maps.googleapis.com/maps/api/geocode/json' f'?region=kr&address={addr}&key=XXX', body=json.dumps({ 'results': [], }), headers={'Content-Type': 'application/json'}, ) with pytest.raises(IndexError): await get_geometric_info_by_address( addr, key, )
async def test_exchange_error(bot, response_mock): response_mock.get( 'https://api.manana.kr/exchange/rate.json?base=KRW&code=JPY', body=json.dumps([False]), headers={'Content-Type': 'application/json'}, ) bot.add_channel('C1', 'test') bot.add_user('U1', 'tester') event = bot.create_message('C1', 'U1') await exchange(bot, event, '100엔') said = bot.call_queue.pop(0) assert said.method == 'chat.postMessage' assert said.data['channel'] == 'C1' assert said.data['text'] == '알 수 없는 에러가 발생했어요! 아빠에게 문의해주세요!'
async def test_aqi_error1(fx_config, response_mock): response_mock.get( 'https://maps.googleapis.com/maps/api/geocode/json?' + urlencode({ 'region': 'kr', 'address': '부천1', 'key': 'qwer', }), body=json.dumps({ 'results': [ { 'formatted_address': '대한민국 경기도 부천시', 'geometry': { 'location': { 'lat': 9937.5034138, 'lng': 99126.7660309, }, }, }, ], }), headers={'Content-Type': 'application/json'}, ) response_mock.get( 'https://api.waqi.info/feed/geo:' '9937.5034138;99126.7660309/?token=asdf', body='null', headers={'Content-Type': 'application/json'}, ) fx_config.AQI_API_TOKEN = 'asdf' fx_config.GOOGLE_API_KEY = 'qwer' bot = FakeBot(fx_config) bot.add_channel('C1', 'general') bot.add_user('U1', 'item4') event = bot.create_message('C1', 'U1', '1234.5678') await aqi(bot, event, '부천1') said = bot.call_queue.pop(0) assert said.method == 'chat.postMessage' assert said.data['channel'] == 'C1' assert said.data['text'] == ( '해당 지역의 AQI 정보를 받아올 수 없어요!' )
async def test_no_packtpub_dotd(bot, response_mock): response_mock.get( 'https://services.packtpub.com/free-learning-v1/offers' '?dateFrom=2018-10-07T00:00:00.000Z&dateTo=2018-10-08T00:00:00.000Z', body=json.dumps({'data': []}), headers={'Content-Type': 'application/json'}, ) bot.add_channel('C1', 'general') bot.add_user('U1', 'item4') event = bot.create_message('C1', 'U1') await packtpub_dotd(bot, event) said = bot.call_queue.pop(0) assert said.method == 'chat.postMessage' assert said.data['channel'] == 'C1' assert said.data['text'] == '오늘은 PACKT Book의 무료책이 없는 것 같아요'
async def test_no_packtpub_dotd(bot, response_mock): response_mock.get( "https://services.packtpub.com/free-learning-v1/offers" "?dateFrom=2018-10-07T00:00:00.000Z&dateTo=2018-10-08T00:00:00.000Z", body=json.dumps({"data": []}), headers={"Content-Type": "application/json"}, ) bot.add_channel("C1", "general") bot.add_user("U1", "item4") event = bot.create_message("C1", "U1") await packtpub_dotd(bot, event) said = bot.call_queue.pop(0) assert said.method == "chat.postMessage" assert said.data["channel"] == "C1" assert said.data["text"] == "오늘은 PACKT Book의 무료책이 없는 것 같아요"
async def test_dog_command(response_mock): response_mock.get( 'https://dog.ceo/api/breeds/image/random', body='', status=500, ) response_mock.get( 'https://dog.ceo/api/breeds/image/random', body=json.dumps({ 'status': 'success', 'message': 'http://dog.com/200.jpg', }), headers={'Content-Type': 'application/json'}, ) response_mock.get( 'https://dog.ceo/api/breeds/image/random', body='', status=500, ) response_mock.get( 'https://dog.ceo/api/breeds/image/random', body=json.dumps({ 'status': 'success', 'message': 'http://dog.com/200.jpg', }), headers={'Content-Type': 'application/json'}, ) response_mock.get('http://dog.com/200.jpg', status=200) response_mock.get('http://dog.com/200.jpg', status=200) bot = FakeBot() bot.add_channel('C1', 'general') user = bot.add_user('U1', 'kirito') bot.add_dm('D1', user) event = bot.create_message('C1', 'U1') assert dog.last_call.get('C1') is None await dog(bot, event, 0.001) said = bot.call_queue.pop() assert said.method == 'chat.postMessage' assert said.data['channel'] == 'C1' assert said.data['text'] == ('멍멍이 API 서버의 상태가 좋지 않다멍! 나중에 다시 시도해보라멍!') assert said.data['as_user'] == '0' assert said.data['username'] == '멍짤의 요정' assert said.data['icon_url'] == 'https://i.imgur.com/Q9FKplO.png' assert dog.last_call.get('C1') is None await dog(bot, event, 0.001) said = bot.call_queue.pop() assert said.method == 'chat.postMessage' assert said.data['channel'] == 'C1' assert said.data['text'] == 'http://dog.com/200.jpg' assert said.data['as_user'] == '0' assert said.data['username'] == '멍짤의 요정' assert said.data['icon_url'] == 'https://i.imgur.com/Q9FKplO.png' assert dog.last_call['C1'] await dog(bot, event, 0.001) said = bot.call_queue.pop() assert said.method == 'chat.postMessage' assert said.data['channel'] == 'C1' assert dog_cooltime_re.match(said.data['text']) assert said.data['as_user'] == '0' assert said.data['username'] == '멍짤의 요정' assert said.data['icon_url'] == 'https://i.imgur.com/Q9FKplO.png' event = bot.create_message('D1', 'U1') assert dog.last_call.get('D1') is None await dog(bot, event, 0.001) said = bot.call_queue.pop() assert said.method == 'chat.postMessage' assert said.data['channel'] == 'D1' assert said.data['text'] == ('멍멍이 API 서버의 상태가 좋지 않다멍! 나중에 다시 시도해보라멍!') assert said.data['as_user'] == '0' assert said.data['username'] == '멍짤의 요정' assert said.data['icon_url'] == 'https://i.imgur.com/Q9FKplO.png' assert dog.last_call.get('D1') is None await dog(bot, event, 0.001) said = bot.call_queue.pop() assert said.method == 'chat.postMessage' assert said.data['channel'] == 'D1' assert said.data['text'] == 'http://dog.com/200.jpg' assert said.data['as_user'] == '0' assert said.data['username'] == '멍짤의 요정' assert said.data['icon_url'] == 'https://i.imgur.com/Q9FKplO.png' assert dog.last_call['D1'] await dog(bot, event, 0.001) said = bot.call_queue.pop() assert said.method == 'chat.postMessage' assert said.data['channel'] == 'D1' assert dog_cooltime_re.match(said.data['text']) assert said.data['as_user'] == '0' assert said.data['username'] == '멍짤의 요정' assert said.data['icon_url'] == 'https://i.imgur.com/Q9FKplO.png'
async def test_dog_command(bot, response_mock): response_mock.get( "https://dog.ceo/api/breeds/image/random", body="", status=500, ) response_mock.get( "https://dog.ceo/api/breeds/image/random", body=json.dumps({ "status": "success", "message": "http://dog.com/200.jpg" }), headers={"Content-Type": "application/json"}, ) response_mock.get( "https://dog.ceo/api/breeds/image/random", body="", status=500, ) response_mock.get( "https://dog.ceo/api/breeds/image/random", body=json.dumps({ "status": "success", "message": "http://dog.com/200.jpg" }), headers={"Content-Type": "application/json"}, ) response_mock.get("http://dog.com/200.jpg", status=200) response_mock.get("http://dog.com/200.jpg", status=200) bot.add_channel("C1", "general") user = bot.add_user("U1", "kirito") bot.add_dm("D1", user) event = bot.create_message("C1", "U1") assert dog.last_call.get("C1") is None await dog(bot, event, 0.001) said = bot.call_queue.pop() assert said.method == "chat.postMessage" assert said.data["channel"] == "C1" assert said.data["text"] == ("멍멍이 API 서버의 상태가 좋지 않다멍! 나중에 다시 시도해보라멍!") assert not said.data["as_user"] assert said.data["username"] == "멍짤의 요정" assert said.data["icon_url"] == "https://i.imgur.com/Q9FKplO.png" assert dog.last_call.get("C1") is None await dog(bot, event, 0.001) said = bot.call_queue.pop() assert said.method == "chat.postMessage" assert said.data["channel"] == "C1" assert said.data["text"] == "http://dog.com/200.jpg" assert not said.data["as_user"] assert said.data["username"] == "멍짤의 요정" assert said.data["icon_url"] == "https://i.imgur.com/Q9FKplO.png" assert dog.last_call["C1"] await dog(bot, event, 0.001) said = bot.call_queue.pop() assert said.method == "chat.postMessage" assert said.data["channel"] == "C1" assert dog_cooltime_re.match(said.data["text"]) assert not said.data["as_user"] assert said.data["username"] == "멍짤의 요정" assert said.data["icon_url"] == "https://i.imgur.com/Q9FKplO.png" event = bot.create_message("D1", "U1") assert dog.last_call.get("D1") is None await dog(bot, event, 0.001) said = bot.call_queue.pop() assert said.method == "chat.postMessage" assert said.data["channel"] == "D1" assert said.data["text"] == ("멍멍이 API 서버의 상태가 좋지 않다멍! 나중에 다시 시도해보라멍!") assert not said.data["as_user"] assert said.data["username"] == "멍짤의 요정" assert said.data["icon_url"] == "https://i.imgur.com/Q9FKplO.png" assert dog.last_call.get("D1") is None await dog(bot, event, 0.001) said = bot.call_queue.pop() assert said.method == "chat.postMessage" assert said.data["channel"] == "D1" assert said.data["text"] == "http://dog.com/200.jpg" assert not said.data["as_user"] assert said.data["username"] == "멍짤의 요정" assert said.data["icon_url"] == "https://i.imgur.com/Q9FKplO.png" assert dog.last_call["D1"] await dog(bot, event, 0.001) said = bot.call_queue.pop() assert said.method == "chat.postMessage" assert said.data["channel"] == "D1" assert dog_cooltime_re.match(said.data["text"]) assert not said.data["as_user"] assert said.data["username"] == "멍짤의 요정" assert said.data["icon_url"] == "https://i.imgur.com/Q9FKplO.png"
async def test_call(fx_config, response_mock): token = 'asdf1234' response_mock.post( 'https://slack.com/api/test11', body=json.dumps({'res': 'hello world!'}), headers={'content-type': 'application/json'}, status=200, ) response_mock.post( 'https://slack.com/api/test12', body=json.dumps({ 'res': 'hello world!', 'data': { 'extra': 'wow' } }), headers={'content-type': 'application/json'}, status=200, ) response_mock.post( 'https://slack.com/api/test21', body=json.dumps({'error': 'aaa'}), headers={'content-type': 'application/json'}, status=404, ) response_mock.post( 'https://slack.com/api/test22', body=json.dumps({'error': 'aaa'}), headers={'content-type': 'application/json'}, status=404, ) response_mock.post( 'https://slack.com/api/test3', body=json.dumps({'res': 'hello world!'}), headers={'content-type': 'application/json'}, status=200, ) box = Box() bot = Bot(fx_config, using_box=box) res = await bot.call('test11') assert res == APIResponse( body={'res': 'hello world!'}, status=200, headers={'content-type': 'application/json'}, ) res = await bot.call('test12', data={'extra': 'wow'}) assert res == APIResponse( body={ 'res': 'hello world!', 'data': { 'extra': 'wow' } }, status=200, headers={'content-type': 'application/json'}, ) res = await bot.call('test21') assert res == APIResponse( body={'error': 'aaa'}, status=404, headers={'content-type': 'application/json'}, ) res = await bot.call('test22', data={'extra': 'wow'}) assert res == APIResponse( body={'error': 'aaa'}, status=404, headers={'content-type': 'application/json'}, ) res = await bot.call('test3', token=token) assert res == APIResponse( body={'res': 'hello world!'}, status=200, headers={'content-type': 'application/json'}, )
async def test_aws(response_mock): response_mock.get( # 1 API_URL, exception=client_exceptions.ClientPayloadError(), ) response_mock.get( # 2 API_URL, body=json.dumps({ 'observed_at': '2019-12-31T00:00:00+0900', 'records': [ { 'id': 433, 'name': '부천', 'height': 29, 'rain': { 'is_raining': 'Clear', 'rain15': 0.0, 'rain60': 0.0, 'rain3h': 0.0, 'rain6h': 0.0, 'rain12h': 0.0, 'rainday': 0.0, }, 'temperature': -9.0, 'wind1': { 'direction_code': 320.5, 'direction_text': 'NW', 'velocity': 1.5, }, 'wind10': { 'direction_code': 298.0, 'direction_text': 'WNW', 'velocity': 1.3, }, 'humidity': None, 'atmospheric': None, 'address': '경기도 부천시 중동', }, ] }), headers={'Content-Type': 'application/json'}, ) response_mock.get( # 3 API_URL, body=json.dumps({ 'observed_at': '2019-12-31T00:00:00+0900', 'records': [ { 'id': 433, 'name': '부천', 'height': 29, 'rain': { 'is_raining': 'Clear', 'rain15': 0.0, 'rain60': 0.0, 'rain3h': 0.0, 'rain6h': 0.0, 'rain12h': 0.0, 'rainday': 0.0, }, 'temperature': -9.0, 'wind1': { 'direction_code': 320.5, 'direction_text': 'NW', 'velocity': 1.5, }, 'wind10': { 'direction_code': 298.0, 'direction_text': 'WNW', 'velocity': 1.3, }, 'humidity': None, 'atmospheric': None, 'address': '경기도 부천시 중동', }, { 'id': 429, 'name': '부천원미', 'height': 16, 'rain': { 'is_raining': 'Unknown', 'rain15': None, 'rain60': None, 'rain3h': None, 'rain6h': None, 'rain12h': None, 'rainday': None, }, 'temperature': None, 'wind1': { 'direction_code': None, 'direction_text': 'Unavailable', 'velocity': None, }, 'wind10': { 'direction_code': None, 'direction_text': 'Unavailable', 'velocity': None, }, 'humidity': None, 'atmospheric': None, 'address': '경기도 부천시 중동', }, ] }), headers={'Content-Type': 'application/json'}, ) response_mock.get( # 4 API_URL, body=json.dumps({ 'observed_at': '2019-12-31T13:00:00+0900', 'records': [ { 'id': 433, 'name': '가상', 'height': 100, 'rain': { 'is_raining': 'Rain', 'rain15': 10.0, 'rain60': 20.0, 'rain3h': 40.0, 'rain6h': 80.0, 'rain12h': 160.0, 'rainday': 320.0, }, 'temperature': 15.0, 'wind1': { 'direction_code': 320.5, 'direction_text': 'NW', 'velocity': 1.5, }, 'wind10': { 'direction_code': 298.0, 'direction_text': 'WNW', 'velocity': 1.3, }, 'humidity': 43, 'atmospheric': 1035.1, 'address': '가상시 가상구', }, ] }), headers={'Content-Type': 'application/json'}, ) response_mock.get( # 5 API_URL, body=json.dumps({ 'observed_at': '2019-12-31T13:00:00+0900', 'records': [ { 'id': 433, 'name': '가상', 'height': 100, 'rain': { 'is_raining': 'Rain', 'rain15': 10.0, 'rain60': 20.0, 'rain3h': 40.0, 'rain6h': 80.0, 'rain12h': 160.0, 'rainday': 320.0, }, 'temperature': -15.0, 'wind1': { 'direction_code': 320.5, 'direction_text': 'NW', 'velocity': 1.5, }, 'wind10': { 'direction_code': 298.0, 'direction_text': 'WNW', 'velocity': 1.3, }, 'humidity': 43, 'atmospheric': 1035.1, 'address': '가상시 가상구', }, ] }), headers={'Content-Type': 'application/json'}, ) response_mock.get( # 6 API_URL, body=json.dumps({ 'observed_at': '2019-12-31T13:00:00+0900', 'records': [ { 'id': 433, 'name': '가상', 'height': 100, 'rain': { 'is_raining': 'Clear', 'rain15': 0.0, 'rain60': 0.0, 'rain3h': 0.0, 'rain6h': 0.0, 'rain12h': 0.0, 'rainday': 0.0, }, 'temperature': -15.0, 'wind1': { 'direction_code': 320.5, 'direction_text': 'NW', 'velocity': 1.5, }, 'wind10': { 'direction_code': 298.0, 'direction_text': 'WNW', 'velocity': 1.3, }, 'humidity': 43, 'atmospheric': 1035.1, 'address': '가상시 가상구', }, ] }), headers={'Content-Type': 'application/json'}, ) response_mock.get( # 7 API_URL, body=json.dumps({ 'observed_at': '2019-12-31T13:00:00+0900', 'records': [{ 'id': 433, 'name': f'가상{i}', 'height': 100, 'rain': { 'is_raining': 'Clear', 'rain15': 0.0, 'rain60': 0.0, 'rain3h': 0.0, 'rain6h': 0.0, 'rain12h': 0.0, 'rainday': 0.0, }, 'temperature': -15.0, 'wind1': { 'direction_code': 320.5, 'direction_text': 'NW', 'velocity': 1.5, }, 'wind10': { 'direction_code': 298.0, 'direction_text': 'WNW', 'velocity': 1.3, }, 'humidity': 43, 'atmospheric': 1035.1, 'address': '가상시 가상구', } for i in range(10)] }), headers={'Content-Type': 'application/json'}, ) bot = FakeBot() bot.add_channel('C1', 'general') bot.add_user('U1', 'item4') event = bot.create_message('C1', 'U1', ts='1234.56') # too short keyword await aws(bot, event, False, '1') said = bot.call_queue.pop(0) assert said.method == 'chat.postMessage' assert said.data['channel'] == 'C1' assert said.data['text'] == ('검색어가 너무 짧아요! 2글자 이상의 검색어를 사용해주세요!') assert 'thread_ts' not in said.data # 1 API error await aws(bot, event, False, '부천') said = bot.call_queue.pop(0) assert said.method == 'chat.postMessage' assert said.data['channel'] == 'C1' assert said.data['text'] == '날씨 API 접근 중 에러가 발생했어요!' assert 'thread_ts' not in said.data # 2 match first mode await aws(bot, event, False, '부천') said = bot.call_queue.pop(0) assert said.method == 'chat.postMessage' assert said.data['channel'] == 'C1' assert said.data['text'] == ('[2019년 12월 31일 00시 00분@부천/경기도 부천시 중동]' ' 강수: 아니오 / -9℃ / 바람: 북서 1.5㎧' '\n\n추천 의상: 패딩, 두꺼운 코트, 목도리, 기모제품') assert said.data['username'] == '부천 날씨' assert said.data['icon_emoji'] == ':crescent_moon:' assert 'thread_ts' not in said.data # 3 fuzzy togather mode await aws(bot, event, True, '부천') said = bot.call_queue.pop(0) assert said.method == 'chat.postMessage' assert said.data['channel'] == 'C1' assert said.data['text'] == ('[2019년 12월 31일 00시 00분@부천/경기도 부천시 중동]' ' 강수: 아니오 / -9℃ / 바람: 북서 1.5㎧' '\n\n추천 의상: 패딩, 두꺼운 코트, 목도리, 기모제품') assert said.data['username'] == '부천 날씨' assert said.data['icon_emoji'] == ':crescent_moon:' assert said.data['thread_ts'] == event.ts said = bot.call_queue.pop(0) assert said.method == 'chat.postMessage' assert said.data['channel'] == 'C1' assert said.data['text'] == ('[2019년 12월 31일 00시 00분@부천원미/경기도 부천시 중동]' ' 강수: 모름') assert said.data['username'] == '부천원미 날씨' assert said.data['icon_emoji'] == ':crescent_moon:' assert said.data['thread_ts'] == event.ts # 4 test rain await aws(bot, event, False, '가상') said = bot.call_queue.pop(0) assert said.method == 'chat.postMessage' assert said.data['channel'] == 'C1' assert said.data['text'] == ( '[2019년 12월 31일 13시 00분@가상/가상시 가상구]' ' 강수: 예(15min: 10/일일: 320) / 15℃ / 바람: 북서 1.5㎧' ' / 습도: 43% / 해면기압: 1035.1hPa' '\n\n추천 의상: 얇은 재킷, 가디건, 간절기 야상, 맨투맨, 니트, 살구색 스타킹') assert said.data['username'] == '가상 날씨' assert said.data['icon_emoji'] == ':umbrella_with_rain_drops:' assert 'thread_ts' not in said.data # 5 test snow await aws(bot, event, False, '가상') said = bot.call_queue.pop(0) assert said.method == 'chat.postMessage' assert said.data['channel'] == 'C1' assert said.data['text'] == ( '[2019년 12월 31일 13시 00분@가상/가상시 가상구]' ' 강수: 예(15min: 10/일일: 320) / -15℃ / 바람: 북서 1.5㎧' ' / 습도: 43% / 해면기압: 1035.1hPa' '\n\n추천 의상: 패딩, 두꺼운 코트, 목도리, 기모제품') assert said.data['username'] == '가상 날씨' assert said.data['icon_emoji'] == ':snowflake:' assert 'thread_ts' not in said.data # 6 test sunny await aws(bot, event, False, '가상') said = bot.call_queue.pop(0) assert said.method == 'chat.postMessage' assert said.data['channel'] == 'C1' assert said.data['text'] == ('[2019년 12월 31일 13시 00분@가상/가상시 가상구]' ' 강수: 아니오 / -15℃ / 바람: 북서 1.5㎧' ' / 습도: 43% / 해면기압: 1035.1hPa' '\n\n추천 의상: 패딩, 두꺼운 코트, 목도리, 기모제품') assert said.data['username'] == '가상 날씨' assert said.data['icon_emoji'] == ':sunny:' assert 'thread_ts' not in said.data # 7 hit cooltime await aws(bot, event, True, '가상') assert len(bot.call_queue) == 10 for i in range(10): said = bot.call_queue.pop(0) assert said.method == 'chat.postMessage' assert said.data['channel'] == 'C1' assert said.data['text'] == (f'[2019년 12월 31일 13시 00분@가상{i}/가상시 가상구]' ' 강수: 아니오 / -15℃ / 바람: 북서 1.5㎧' ' / 습도: 43% / 해면기압: 1035.1hPa' '\n\n추천 의상: 패딩, 두꺼운 코트, 목도리, 기모제품') assert said.data['username'] == f'가상{i} 날씨' assert said.data['icon_emoji'] == ':sunny:' assert said.data['thread_ts'] == event.ts assert aws.last_call['C1'] # block by cooltime await aws(bot, event, False, '가상') assert len(bot.call_queue) == 1 said = bot.call_queue.pop(0) assert said.method == 'chat.postMessage' assert said.data['channel'] == 'C1' assert COOLTIME.match(said.data['text']) assert 'thread_ts' not in said.data
async def test_call(event_loop, bot_config, response_mock): token = 'asdf1234' response_mock.post( 'https://slack.com/api/test11', body=json.dumps({'res': 'hello world!'}), headers={'content-type': 'application/json'}, status=200, ) response_mock.post( 'https://slack.com/api/test12', body=json.dumps({ 'res': 'hello world!', 'data': { 'extra': 'wow' } }), headers={'content-type': 'application/json'}, status=200, ) response_mock.post( 'https://slack.com/api/test21', body=json.dumps({'error': 'aaa'}), headers={'content-type': 'application/json'}, status=404, ) response_mock.post( 'https://slack.com/api/test22', body=json.dumps({'error': 'aaa'}), headers={'content-type': 'application/json'}, status=404, ) response_mock.post( 'https://slack.com/api/test3', body=json.dumps({'res': 'hello world!'}), headers={'content-type': 'application/json'}, status=200, ) box = Box() bot = Bot(bot_config, event_loop, using_box=box) bot.api.throttle_interval = defaultdict(lambda: timedelta(0)) res = await bot.call('test11') assert res == APIResponse( body={'res': 'hello world!'}, status=200, headers={'content-type': 'application/json'}, ) res = await bot.call('test12', data={'extra': 'wow'}) assert res == APIResponse( body={ 'res': 'hello world!', 'data': { 'extra': 'wow' } }, status=200, headers={'content-type': 'application/json'}, ) res = await bot.call('test21') assert res == APIResponse( body={'error': 'aaa'}, status=404, headers={'content-type': 'application/json'}, ) res = await bot.call('test22', data={'extra': 'wow'}) assert res == APIResponse( body={'error': 'aaa'}, status=404, headers={'content-type': 'application/json'}, ) res = await bot.call('test3', token=token) assert res == APIResponse( body={'res': 'hello world!'}, status=200, headers={'content-type': 'application/json'}, )
async def test_aws(bot, response_mock): response_mock.get( # 1 API_URL, exception=client_exceptions.ClientPayloadError(), ) response_mock.get( # 2 API_URL, body=json.dumps({ "observed_at": "2019-12-31T00:00:00+0900", "records": [ { "id": 433, "name": "부천", "height": 29, "rain": { "is_raining": "Clear", "rain15": 0.0, "rain60": 0.0, "rain3h": 0.0, "rain6h": 0.0, "rain12h": 0.0, "rainday": 0.0, }, "temperature": -9.0, "wind1": { "direction_code": 320.5, "direction_text": "NW", "velocity": 1.5, }, "wind10": { "direction_code": 298.0, "direction_text": "WNW", "velocity": 1.3, }, "humidity": None, "atmospheric": None, "address": "경기도 부천시 중동", }, ], }), headers={"Content-Type": "application/json"}, ) response_mock.get( # 3 API_URL, body=json.dumps({ "observed_at": "2019-12-31T00:00:00+0900", "records": [ { "id": 433, "name": "부천", "height": 29, "rain": { "is_raining": "Clear", "rain15": 0.0, "rain60": 0.0, "rain3h": 0.0, "rain6h": 0.0, "rain12h": 0.0, "rainday": 0.0, }, "temperature": -9.0, "wind1": { "direction_code": 320.5, "direction_text": "NW", "velocity": 1.5, }, "wind10": { "direction_code": 298.0, "direction_text": "WNW", "velocity": 1.3, }, "humidity": None, "atmospheric": None, "address": "경기도 부천시 중동", }, { "id": 429, "name": "부천원미", "height": 16, "rain": { "is_raining": "Unknown", "rain15": None, "rain60": None, "rain3h": None, "rain6h": None, "rain12h": None, "rainday": None, }, "temperature": None, "wind1": { "direction_code": None, "direction_text": "Unavailable", "velocity": None, }, "wind10": { "direction_code": None, "direction_text": "Unavailable", "velocity": None, }, "humidity": None, "atmospheric": None, "address": "경기도 부천시 중동", }, ], }), headers={"Content-Type": "application/json"}, ) response_mock.get( # 4 API_URL, body=json.dumps({ "observed_at": "2019-12-31T13:00:00+0900", "records": [ { "id": 433, "name": "가상", "height": 100, "rain": { "is_raining": "Rain", "rain15": 10.0, "rain60": 20.0, "rain3h": 40.0, "rain6h": 80.0, "rain12h": 160.0, "rainday": 320.0, }, "temperature": 15.0, "wind1": { "direction_code": 320.5, "direction_text": "NW", "velocity": 1.5, }, "wind10": { "direction_code": 298.0, "direction_text": "WNW", "velocity": 1.3, }, "humidity": 43, "atmospheric": 1035.1, "address": "가상시 가상구", }, ], }), headers={"Content-Type": "application/json"}, ) response_mock.get( # 5 API_URL, body=json.dumps({ "observed_at": "2019-12-31T13:00:00+0900", "records": [ { "id": 433, "name": "가상", "height": 100, "rain": { "is_raining": "Rain", "rain15": 10.0, "rain60": 20.0, "rain3h": 40.0, "rain6h": 80.0, "rain12h": 160.0, "rainday": 320.0, }, "temperature": -15.0, "wind1": { "direction_code": 320.5, "direction_text": "NW", "velocity": 1.5, }, "wind10": { "direction_code": 298.0, "direction_text": "WNW", "velocity": 1.3, }, "humidity": 43, "atmospheric": 1035.1, "address": "가상시 가상구", }, ], }), headers={"Content-Type": "application/json"}, ) response_mock.get( # 6 API_URL, body=json.dumps({ "observed_at": "2019-12-31T13:00:00+0900", "records": [ { "id": 433, "name": "가상", "height": 100, "rain": { "is_raining": "Clear", "rain15": 0.0, "rain60": 0.0, "rain3h": 0.0, "rain6h": 0.0, "rain12h": 0.0, "rainday": 0.0, }, "temperature": -15.0, "wind1": { "direction_code": 320.5, "direction_text": "NW", "velocity": 1.5, }, "wind10": { "direction_code": 298.0, "direction_text": "WNW", "velocity": 1.3, }, "humidity": 43, "atmospheric": 1035.1, "address": "가상시 가상구", }, ], }), headers={"Content-Type": "application/json"}, ) response_mock.get( # 7 API_URL, body=json.dumps({ "observed_at": "2019-12-31T13:00:00+0900", "records": [{ "id": 433, "name": f"가상{i}", "height": 100, "rain": { "is_raining": "Clear", "rain15": 0.0, "rain60": 0.0, "rain3h": 0.0, "rain6h": 0.0, "rain12h": 0.0, "rainday": 0.0, }, "temperature": -15.0, "wind1": { "direction_code": 320.5, "direction_text": "NW", "velocity": 1.5, }, "wind10": { "direction_code": 298.0, "direction_text": "WNW", "velocity": 1.3, }, "humidity": 43, "atmospheric": 1035.1, "address": "가상시 가상구", } for i in range(10)], }), headers={"Content-Type": "application/json"}, ) bot.add_channel("C1", "general") bot.add_user("U1", "item4") event = bot.create_message("C1", "U1", ts="1234.56") # too short keyword await aws(bot, event, False, "1") said = bot.call_queue.pop(0) assert said.method == "chat.postMessage" assert said.data["channel"] == "C1" assert said.data["text"] == ("검색어가 너무 짧아요! 2글자 이상의 검색어를 사용해주세요!") assert "thread_ts" not in said.data # 1 API error await aws(bot, event, False, "부천") said = bot.call_queue.pop(0) assert said.method == "chat.postMessage" assert said.data["channel"] == "C1" assert said.data["text"] == "날씨 API 접근 중 에러가 발생했어요!" assert "thread_ts" not in said.data # 2 match first mode await aws(bot, event, False, "부천") said = bot.call_queue.pop(0) assert said.method == "chat.postMessage" assert said.data["channel"] == "C1" assert said.data["text"] == ("[2019년 12월 31일 00시 00분@부천/경기도 부천시 중동]" " 강수: 아니오 / -9℃ / 바람: 북서 1.5㎧" "\n\n추천 의상: 패딩, 두꺼운 코트, 목도리, 기모제품") assert said.data["username"] == "부천 날씨" assert said.data["icon_emoji"] == ":crescent_moon:" assert "thread_ts" not in said.data # 3 fuzzy togather mode await aws(bot, event, True, "부천") said = bot.call_queue.pop(0) assert said.method == "chat.postMessage" assert said.data["channel"] == "C1" assert said.data["text"] == ("[2019년 12월 31일 00시 00분@부천/경기도 부천시 중동]" " 강수: 아니오 / -9℃ / 바람: 북서 1.5㎧" "\n\n추천 의상: 패딩, 두꺼운 코트, 목도리, 기모제품") assert said.data["username"] == "부천 날씨" assert said.data["icon_emoji"] == ":crescent_moon:" assert said.data["thread_ts"] == event.ts said = bot.call_queue.pop(0) assert said.method == "chat.postMessage" assert said.data["channel"] == "C1" assert said.data["text"] == ("[2019년 12월 31일 00시 00분@부천원미/경기도 부천시 중동]" " 강수: 모름") assert said.data["username"] == "부천원미 날씨" assert said.data["icon_emoji"] == ":crescent_moon:" assert said.data["thread_ts"] == event.ts # 4 test rain await aws(bot, event, False, "가상") said = bot.call_queue.pop(0) assert said.method == "chat.postMessage" assert said.data["channel"] == "C1" assert said.data["text"] == ( "[2019년 12월 31일 13시 00분@가상/가상시 가상구]" " 강수: 예(15min: 10/일일: 320) / 15℃ / 바람: 북서 1.5㎧" " / 습도: 43% / 해면기압: 1035.1hPa" "\n\n추천 의상: 얇은 재킷, 가디건, 간절기 야상, 맨투맨, 니트, 살구색 스타킹") assert said.data["username"] == "가상 날씨" assert said.data["icon_emoji"] == ":umbrella_with_rain_drops:" assert "thread_ts" not in said.data # 5 test snow await aws(bot, event, False, "가상") said = bot.call_queue.pop(0) assert said.method == "chat.postMessage" assert said.data["channel"] == "C1" assert said.data["text"] == ( "[2019년 12월 31일 13시 00분@가상/가상시 가상구]" " 강수: 예(15min: 10/일일: 320) / -15℃ / 바람: 북서 1.5㎧" " / 습도: 43% / 해면기압: 1035.1hPa" "\n\n추천 의상: 패딩, 두꺼운 코트, 목도리, 기모제품") assert said.data["username"] == "가상 날씨" assert said.data["icon_emoji"] == ":snowflake:" assert "thread_ts" not in said.data # 6 test sunny await aws(bot, event, False, "가상") said = bot.call_queue.pop(0) assert said.method == "chat.postMessage" assert said.data["channel"] == "C1" assert said.data["text"] == ("[2019년 12월 31일 13시 00분@가상/가상시 가상구]" " 강수: 아니오 / -15℃ / 바람: 북서 1.5㎧" " / 습도: 43% / 해면기압: 1035.1hPa" "\n\n추천 의상: 패딩, 두꺼운 코트, 목도리, 기모제품") assert said.data["username"] == "가상 날씨" assert said.data["icon_emoji"] == ":sunny:" assert "thread_ts" not in said.data # 7 hit cooltime await aws(bot, event, True, "가상") assert len(bot.call_queue) == 10 for i in range(10): said = bot.call_queue.pop(0) assert said.method == "chat.postMessage" assert said.data["channel"] == "C1" assert said.data["text"] == (f"[2019년 12월 31일 13시 00분@가상{i}/가상시 가상구]" " 강수: 아니오 / -15℃ / 바람: 북서 1.5㎧" " / 습도: 43% / 해면기압: 1035.1hPa" "\n\n추천 의상: 패딩, 두꺼운 코트, 목도리, 기모제품") assert said.data["username"] == f"가상{i} 날씨" assert said.data["icon_emoji"] == ":sunny:" assert said.data["thread_ts"] == event.ts assert aws.last_call["C1"] # block by cooltime await aws(bot, event, False, "가상") assert len(bot.call_queue) == 1 said = bot.call_queue.pop(0) assert said.method == "chat.postMessage" assert said.data["channel"] == "C1" assert COOLTIME.match(said.data["text"]) assert "thread_ts" not in said.data
async def test_call(bot_config, response_mock): token = "asdf1234" response_mock.post( "https://slack.com/api/test11", body=json.dumps({"res": "hello world!"}), headers={"content-type": "application/json"}, status=200, ) response_mock.post( "https://slack.com/api/test12", body=json.dumps({ "res": "hello world!", "data": { "extra": "wow" } }), headers={"content-type": "application/json"}, status=200, ) response_mock.post( "https://slack.com/api/test21", body=json.dumps({"error": "aaa"}), headers={"content-type": "application/json"}, status=404, ) response_mock.post( "https://slack.com/api/test22", body=json.dumps({"error": "aaa"}), headers={"content-type": "application/json"}, status=404, ) response_mock.post( "https://slack.com/api/test3", body=json.dumps({"res": "hello world!"}), headers={"content-type": "application/json"}, status=200, ) box = Box() bot = Bot(bot_config, using_box=box) bot.api.throttle_interval = defaultdict(lambda: timedelta(0)) res = await bot.call("test11") assert res == APIResponse( body={"res": "hello world!"}, status=200, headers={"content-type": "application/json"}, ) res = await bot.call("test12", data={"extra": "wow"}) assert res == APIResponse( body={ "res": "hello world!", "data": { "extra": "wow" } }, status=200, headers={"content-type": "application/json"}, ) res = await bot.call("test21") assert res == APIResponse( body={"error": "aaa"}, status=404, headers={"content-type": "application/json"}, ) res = await bot.call("test22", data={"extra": "wow"}) assert res == APIResponse( body={"error": "aaa"}, status=404, headers={"content-type": "application/json"}, ) res = await bot.call("test3", token=token) assert res == APIResponse( body={"res": "hello world!"}, status=200, headers={"content-type": "application/json"}, )