async def test_gift_subscription_event(opsdroid, caplog): caplog.set_level(logging.DEBUG) connector = ConnectorTwitch(connector_config, opsdroid=opsdroid) connector.validate_request = amock.CoroutineMock(return_value=True) mock_request = amock.CoroutineMock() mock_request.json = amock.CoroutineMock() mock_request.json.return_value = { "data": [{ "event_type": "subscriptions.subscribe", "event_data": { "user_name": "lucky_mc_luck", "gifter_name": "Awesome gifter", "is_gift": True, }, }] } twitch_event.UserSubscribed = amock.Mock() resp = await connector.twitch_webhook_handler(mock_request) assert "Gifted subscriber event received by Twitch." in caplog.text assert resp.status == 200 assert twitch_event.UserSubscribed.called
async def test_stream_started_event(opsdroid, caplog): caplog.set_level(logging.DEBUG) connector = ConnectorTwitch(connector_config, opsdroid=opsdroid) connector.validate_request = amock.CoroutineMock(return_value=True) connector.listen = amock.CoroutineMock() mock_request = amock.CoroutineMock() mock_request.json = amock.CoroutineMock() mock_request.json.return_value = { "data": [{ "started_at": "just now", "title": "Testing with pytest!", "viewer_count": 1, }] } stream_start_event = twitch_event.StreamStarted("Testing with pytest", 1, "just now") twitch_event.StreamStarted = amock.Mock() resp = await connector.twitch_webhook_handler(mock_request) assert "Broadcaster went live event received by Twitch." in caplog.text assert connector.is_live assert resp.status == 200 assert twitch_event.StreamStarted.called assert connector.listen.called assert "Testing with pytest" in stream_start_event.title assert 1 == stream_start_event.viewers assert "just now" in stream_start_event.started_at
async def test_create_clip_failure(opsdroid, caplog): caplog.set_level(logging.DEBUG) connector = ConnectorTwitch(connector_config, opsdroid=opsdroid) connector.send_message = amock.CoroutineMock() post_response = amock.Mock() post_response.status = 200 post_response.json = amock.CoroutineMock() post_response.json.return_value = {"data": [{"id": "clip123"}]} get_response = amock.Mock() get_response.status = 404 with amock.patch("aiohttp.ClientSession.post", new=amock.CoroutineMock()) as mocked_post, amock.patch( "aiohttp.ClientSession.get", new=amock.CoroutineMock()) as mocked_get: mocked_post.return_value = asyncio.Future() mocked_post.return_value.set_result(post_response) mocked_get.return_value = asyncio.Future() mocked_get.return_value.set_result(get_response) await connector.create_clip() assert "Failed to create Twitch clip" in caplog.text
async def test_connect_no_auth_data(opsdroid, caplog, tmpdir): caplog.set_level(logging.INFO) get_response = amock.Mock() get_response.status = 200 get_response.json = amock.CoroutineMock() get_response.json.return_value = {"data": [{"id": "test-bot"}]} connector = ConnectorTwitch(connector_config, opsdroid=opsdroid) connector.auth_file = AUTH_FILE connector.webhook = amock.CoroutineMock() connector.request_oauth_token = amock.CoroutineMock() opsdroid.web_server = amock.Mock() with amock.patch( "aiohttp.ClientSession.get", new=amock.CoroutineMock()) as patched_request, amock.patch( "os.path") as mocked_file: patched_request.return_value = asyncio.Future() patched_request.return_value.set_result(get_response) mocked_file.isfile = amock.Mock(return_value=False) await connector.connect() assert "No previous authorization data found" in caplog.text assert connector.request_oauth_token.called assert opsdroid.web_server.web_app.router.add_get.called assert connector.webhook.called
async def test_send_handshake(opsdroid): connector = ConnectorTwitch(connector_config, opsdroid=opsdroid) connector.websocket = amock.Mock() connector.websocket.send_str = amock.CoroutineMock() await connector.send_handshake() assert connector.websocket.send_str.called
async def test_disconnect_websockets(opsdroid): connector = ConnectorTwitch(connector_config, opsdroid=opsdroid) connector.websocket = web.WebSocketResponse() resp = await connector.disconnect_websockets() assert not connector.websocket assert not connector.is_live assert not resp
async def test_send_message_event(opsdroid, caplog): caplog.set_level(logging.DEBUG) connector = ConnectorTwitch(connector_config, opsdroid=opsdroid) message_event = opsdroid_events.Message(text="Hello world!") connector.send_message = amock.CoroutineMock() await connector._send_message(message_event) assert connector.send_message.called assert "Hello world!" in caplog.text
async def test_handle_message_authentication_failed(opsdroid): message = ":tmi.twitch.tv NOTICE * :Login authentication failed" connector = ConnectorTwitch(connector_config, opsdroid=opsdroid) connector.refresh_token = amock.CoroutineMock() with pytest.raises(ConnectionError): await connector._handle_message(message) assert connector.refresh_token.called
async def test_ban_user(opsdroid, caplog): caplog.set_level(logging.DEBUG) connector = ConnectorTwitch(connector_config, opsdroid=opsdroid) ban_event = opsdroid_events.BanUser(user="******") connector.send_message = amock.CoroutineMock() await connector.ban_user(ban_event) assert connector.send_message.called assert "bot_mc_spam_bot" in caplog.text
async def test_disconnect(opsdroid): connector_config["always-listening"] = True connector = ConnectorTwitch(connector_config, opsdroid=opsdroid) connector.disconnect_websockets = amock.CoroutineMock() connector.webhook = amock.CoroutineMock() await connector.disconnect() assert connector.is_live is True assert connector.disconnect_websockets.called assert connector.webhook.called
async def test_invalid_post_request_webhook(opsdroid): connector = ConnectorTwitch(connector_config, opsdroid=opsdroid) connector.validate_request = amock.CoroutineMock(return_value=False) mock_request = amock.CoroutineMock() mock_request.json = amock.CoroutineMock() mock_request.json.return_value = {"data": [{"test": "test"}]} resp = await connector.twitch_webhook_handler(mock_request) assert "Unauthorized" in resp.text assert resp.status == 401
async def test_stream_ended_event(opsdroid): connector = ConnectorTwitch(connector_config, opsdroid=opsdroid) connector.validate_request = amock.CoroutineMock(return_value=True) connector.disconnect_websockets = amock.CoroutineMock() mock_request = amock.CoroutineMock() mock_request.json = amock.CoroutineMock() mock_request.json.return_value = {"data": []} twitch_event.StreamEnded = amock.Mock() resp = await connector.twitch_webhook_handler(mock_request) assert not connector.is_live assert resp.status == 200 assert twitch_event.StreamEnded.called
async def test_connect_websocket(opsdroid, caplog): connector = ConnectorTwitch(connector_config, opsdroid=opsdroid) caplog.set_level(logging.INFO) with amock.patch("aiohttp.ClientSession") as mocked_session: mocked_session.ws_connect = amock.CoroutineMock() connector.send_handshake = amock.CoroutineMock() connector.get_messages_loop = amock.CoroutineMock() await connector.connect_websocket() assert "Connecting to Twitch IRC Server." in caplog.text assert connector.websocket assert connector.send_handshake.called assert connector.get_messages_loop.called
def test_init(opsdroid): connector = ConnectorTwitch(connector_config, opsdroid=opsdroid) assert connector.default_target == "test" assert connector.name == "twitch" assert connector.token is None assert connector.websocket is None assert connector.user_id is None assert connector.reconnections == 0
async def test_listen_reconnect(opsdroid, caplog): caplog.set_level(logging.DEBUG) connector = ConnectorTwitch(connector_config, opsdroid=opsdroid) connector.connect_websocket = amock.CoroutineMock( side_effect=ConnectionError) with amock.patch( "aiohttp.ClientSession.ws_connect", new=amock.CoroutineMock()) as mocked_websocket, amock.patch( "asyncio.sleep") as mocked_sleep: mocked_websocket.side_effect = Exception() with contextlib.suppress((Exception)): await connector.listen() assert mocked_sleep.called assert None in caplog.text assert connector.reconnections == 1
async def test_listen(opsdroid): connector = ConnectorTwitch(connector_config, opsdroid=opsdroid) with amock.patch("aiohttp.ClientSession.ws_connect", new=amock.CoroutineMock()) as mocked_websocket: mocked_websocket.side_effect = Exception() with contextlib.suppress(Exception): await connector.listen()
async def test_remove_message(opsdroid, caplog): caplog.set_level(logging.DEBUG) connector = ConnectorTwitch(connector_config, opsdroid=opsdroid) message_event = opsdroid_events.Message( user="******", text="spammy message", user_id="123", event_id="messageid123", ) remove_event = opsdroid_events.DeleteMessage(linked_event=message_event) connector.send_message = amock.CoroutineMock() await connector.remove_message(remove_event) assert connector.send_message.called assert "messageid123" in caplog.text
async def test_handle_challenge_error(opsdroid, caplog): caplog.set_level(logging.DEBUG) connector = ConnectorTwitch(connector_config, opsdroid=opsdroid) req = make_mocked_request("GET", "/connector/twitch") resp = await connector.handle_challenge(req) assert "Failed to get challenge" in caplog.text assert resp.status == 500
def test_base_url_twitch_config(opsdroid): config = { "code": "yourcode", "channel": "test", "client-id": "client-id", "client-secret": "client-secret", "forward-url": "http://my-awesome-url", } connector = ConnectorTwitch(config, opsdroid=opsdroid) assert connector.base_url == "http://my-awesome-url"
async def test_handle_message_left_event(opsdroid): message = ":[email protected] PART #channel" left_event = opsdroid_events.LeaveRoom(user="******") connector = ConnectorTwitch(connector_config, opsdroid=opsdroid) opsdroid.parse = amock.CoroutineMock() await connector._handle_message(message) assert opsdroid.parse.called assert "username" in left_event.user
async def test_handle_message_chat_message(opsdroid, caplog): caplog.set_level(logging.DEBUG) message = "@badge-info=;badges=;client-nonce=jiwej12;color=;display-name=user;emotes=;flags=0-81:;id=jdias-9212;mod=0;room-id=123;subscriber=0;tmi-sent-ts=1592943868712;turbo=0;user-id=123;user-type= :[email protected] PRIVMSG #channel :Hello world!" connector = ConnectorTwitch(connector_config, opsdroid=opsdroid) opsdroid.parse = amock.CoroutineMock() await connector._handle_message(message) assert "Got message from Twitch" in caplog.text assert opsdroid.parse.called
async def test_handle_challenge(opsdroid, caplog): caplog.set_level(logging.DEBUG) connector = ConnectorTwitch(connector_config, opsdroid=opsdroid) req = make_mocked_request( "GET", "/connector/twitch?hub.challenge=testchallenge123") resp = await connector.handle_challenge(req) assert "Failed to get challenge" not in caplog.text assert "testchallenge123" in resp.text
async def test_get_message_loop(opsdroid): connector = ConnectorTwitch(connector_config, opsdroid=opsdroid) connector.websocket = amock.MagicMock() connector.websocket.__aiter__.return_value = [ WSMessage(WSMsgType.TEXT, "PING", b""), WSMessage(WSMsgType.TEXT, ":[email protected]! JOIN #channel", b""), WSMessage(WSMsgType.CLOSED, "CLOSE", ""), ] connector.websocket.send_str = amock.CoroutineMock() connector.websocket.close = amock.CoroutineMock() connector._handle_message = amock.CoroutineMock() with pytest.raises(ConnectionError): await connector.get_messages_loop() assert connector.is_live assert connector.send_str.called assert connector.websocket.close.called assert connector._handle_message.called
def test_base_url_web_config(opsdroid): config = { "code": "yourcode", "channel": "test", "client-id": "client-id", "client-secret": "client-secret", } opsdroid.config["web"] = {"base-url": "http://my-awesome-url"} connector = ConnectorTwitch(config, opsdroid=opsdroid) assert connector.base_url == "http://my-awesome-url"
async def test_get_user_id_unauthorized(opsdroid): connector = ConnectorTwitch(connector_config, opsdroid=opsdroid) get_response = amock.Mock() get_response.status = 401 with amock.patch("aiohttp.ClientSession.get", new=amock.CoroutineMock()) as patched_request: patched_request.return_value = asyncio.Future() patched_request.return_value.set_result(get_response) with pytest.raises(ConnectionError) as exception: await connector.get_user_id("theflyingdev", "token", "client-id") assert "Unauthorized" in exception.message
async def test_get_user_id_failure(opsdroid, caplog): connector = ConnectorTwitch(connector_config, opsdroid=opsdroid) get_response = amock.Mock() get_response.status = 404 get_response.json = amock.CoroutineMock() with amock.patch("aiohttp.ClientSession.get", new=amock.CoroutineMock()) as patched_request: patched_request.return_value = asyncio.Future() patched_request.return_value.set_result(get_response) await connector.get_user_id("theflyingdev", "token", "client-id") assert "Unable to receive broadcaster id - Error" in caplog.text
async def test_followed_event(opsdroid, caplog): caplog.set_level(logging.DEBUG) connector = ConnectorTwitch(connector_config, opsdroid=opsdroid) connector.validate_request = amock.CoroutineMock(return_value=True) mock_request = amock.CoroutineMock() mock_request.json = amock.CoroutineMock() mock_request.json.return_value = { "data": [{ "from_name": "awesome_follower", "followed_at": "today" }] } follow_event = twitch_event.UserFollowed("awesome_follower", "today") twitch_event.UserFollowed = amock.Mock() resp = await connector.twitch_webhook_handler(mock_request) assert "Follower event received by Twitch." in caplog.text assert resp.status == 200 assert twitch_event.UserFollowed.called assert "awesome_follower" in follow_event.follower assert "today" in follow_event.followed_at
async def test_validate_request(opsdroid): connector = ConnectorTwitch(connector_config, opsdroid=opsdroid) request = amock.CoroutineMock() request.headers = { "x-hub-signature": "sha256=fcfa24b327e3467f1586cc1ace043c016cabfe9c15dabc0020aca45440338be9" } request.read = amock.CoroutineMock() request.read.return_value = b'{"test": "test"}' validation = await connector.validate_request(request, "test") assert validation
async def test_create_clip(opsdroid, caplog): caplog.set_level(logging.DEBUG) connector = ConnectorTwitch(connector_config, opsdroid=opsdroid) connector.send_message = amock.CoroutineMock() post_response = amock.Mock() post_response.status = 200 post_response.json = amock.CoroutineMock() post_response.json.return_value = {"data": [{"id": "clip123"}]} get_response = amock.Mock() get_response.status = 200 get_response.json = amock.CoroutineMock() get_response.json.return_value = { "data": [{ "id": "clip123", "embed_url": "localhost" }] } with amock.patch("aiohttp.ClientSession.post", new=amock.CoroutineMock()) as mocked_post, amock.patch( "aiohttp.ClientSession.get", new=amock.CoroutineMock()) as mocked_get: mocked_post.return_value = asyncio.Future() mocked_post.return_value.set_result(post_response) mocked_get.return_value = asyncio.Future() mocked_get.return_value.set_result(get_response) clip_event = twitch_event.CreateClip(id="broadcaster123") await connector.create_clip() assert "Twitch clip created successfully." in caplog.text assert "broadcaster123" in clip_event.id
async def test_subscription_event(opsdroid, caplog): caplog.set_level(logging.DEBUG) connector = ConnectorTwitch(connector_config, opsdroid=opsdroid) connector.validate_request = amock.CoroutineMock(return_value=True) mock_request = amock.CoroutineMock() mock_request.json = amock.CoroutineMock() mock_request.json.return_value = { "data": [{ "event_type": "subscriptions.notification", "event_data": { "user_name": "awesome_subscriber!", "message": "Best channel ever!", }, }] } twitch_event.UserSubscribed = amock.Mock() resp = await connector.twitch_webhook_handler(mock_request) assert "Subscriber event received by Twitch." in caplog.text assert resp.status == 200 assert twitch_event.UserSubscribed.called