def test_layabout_raises_type_error_with_string_connector(): layabout = Layabout() with pytest.raises(TypeError) as exc: layabout.run(connector='', until=lambda e: False) assert str(exc.value) == ('Use layabout.Token or layabout.EnvVar ' 'instead of str')
def test_layabout_can_connect_to_slack_with_existing_slack_client(): """ Test that layabout can use an existing SlackClient as a connector. """ layabout = Layabout() _, slack = mock_slack(connections=(True, )) layabout.run(connector=slack, until=lambda e: False)
def test_layabout_raises_missing_token_with_empty_token(): """ Test that layabout raises a MissingToken if given an empty Slack API token. """ layabout = Layabout() with pytest.raises(MissingToken) as exc: # until will exit early here just to be safe. layabout.run(connector=Token(''), until=lambda e: False) assert str(exc.value) == 'The empty string is an invalid Slack API token'
def test_layabout_raises_type_error_with_invalid_connector(): """ Test that layabout cannot connect to Slack with a pineapple. """ layabout = Layabout() class Pineapple: pass with pytest.raises(TypeError): # Turns out you can't connect to Slack with a Pineapple. layabout.run(connector=Pineapple)
def test_layabout_can_connect_to_slack_with_token(monkeypatch): """ Test that layabout can connect to the Slack API when given a valid Slack API token. """ layabout = Layabout() SlackClient, slack = mock_slack(connections=(True, )) monkeypatch.setattr('layabout.SlackClient', SlackClient) layabout.run(connector=TOKEN, until=lambda e: False) # Verify we instantiated a SlackClient with the given token. SlackClient.assert_called_with(token=TOKEN)
def test_layabout_raises_missing_token_without_token(monkeypatch): """ Test that layabout raises a MissingToken if there is no Slack API token for it to use. """ environ = dict() layabout = Layabout() monkeypatch.setattr(os, 'environ', environ) with pytest.raises(MissingToken) as exc: # until will exit early here just to be safe. layabout.run(until=lambda e: False) assert str(exc.value) == 'Could not acquire token from LAYABOUT_TOKEN'
def test_layabout_can_handle_an_event(events, run_once, monkeypatch): """ Test that layabout can handle an event. """ layabout = Layabout() SlackClient, slack = mock_slack(connections=(True, ), reads=(events, [])) handle_hello = MagicMock() monkeypatch.setattr('layabout.SlackClient', SlackClient) layabout.handle('hello')(handle_hello) layabout.run(connector=TOKEN, interval=0, retries=0, backoff=lambda r: 0, until=run_once) handle_hello.assert_called_once_with(slack, events[0])
def test_layabout_can_continue_after_successful_reconnection(monkeypatch): """ Test that layabout can continue to handle events after successfully reconnecting to the Slack API. """ layabout = Layabout() # Succeed with the first connection and the subsequent reconnection. connections = (True, True) # Raise an exception on the first read and return empty events next. reads = (TimeoutError, []) SlackClient, _ = mock_slack(connections=connections, reads=reads) monkeypatch.setattr('layabout.SlackClient', SlackClient) layabout.run(connector=TOKEN, retries=1, backoff=lambda r: 0, until=lambda e: False)
def test_layabout_can_only_handle_events_that_happen(events, run_once, monkeypatch): """ Test that layabout only handles events that actually happen. """ layabout = Layabout() SlackClient, _ = mock_slack(connections=(True, ), reads=(events, [])) aint_happenin = MagicMock() monkeypatch.setattr('layabout.SlackClient', SlackClient) layabout.handle('this will never happen')(aint_happenin) layabout.run(connector=TOKEN, interval=0, retries=0, backoff=lambda r: 0, until=run_once) aint_happenin.assert_not_called()
def test_layabout_can_connect_to_slack_with_env_var(monkeypatch): """ Test that layabout can discover and use a Slack API token from an environment variable when not given one directly. """ env_var = EnvVar('_TEST_LAYABOUT_TOKEN') environ = {env_var: TOKEN} layabout = Layabout() SlackClient, slack = mock_slack(connections=(True, )) monkeypatch.setattr(os, 'environ', environ) monkeypatch.setattr('layabout.SlackClient', SlackClient) # Purposefully don't provide a connector so we have to use an env var. layabout.run(connector=env_var, until=lambda e: False) # Verify we instantiated a SlackClient with the given token and used it to # connect to the Slack API. SlackClient.assert_called_with(token=TOKEN)
def test_layabout_can_handle_all_events_with_a_splat_handler( events, run_once, monkeypatch): """ Test that layabout can handle all events with a splat handler. """ layabout = Layabout() SlackClient, slack = mock_slack(connections=(True, ), reads=(events, [])) splat = MagicMock() monkeypatch.setattr('layabout.SlackClient', SlackClient) layabout.handle('*')(splat) layabout.run(connector=TOKEN, interval=0, retries=0, backoff=lambda r: 0, until=run_once) splat.assert_has_calls([call(slack, e) for e in events])
def test_layabout_can_handle_multiple_events(events, run_once, monkeypatch): """ Test that layabout calls all handlers for their respective events. """ layabout = Layabout() SlackClient, slack = mock_slack(connections=(True, ), reads=(events, [])) handle_hello, handle_goodbye = MagicMock(), MagicMock() monkeypatch.setattr('layabout.SlackClient', SlackClient) layabout.handle('hello')(handle_hello) layabout.handle('goodbye')(handle_goodbye) layabout.run(connector=TOKEN, interval=0, retries=0, backoff=lambda r: 0, until=run_once) handle_hello.assert_called_once_with(slack, events[0]) handle_goodbye.assert_called_once_with(slack, events[1])
def test_layabout_can_handle_an_event_with_kwargs(events, run_once, monkeypatch): """ Test that layabout can call an event handler that requires kwargs. """ layabout = Layabout() SlackClient, slack = mock_slack(connections=(True, ), reads=(events, [])) kwargs = dict(caerbannog='🐰') handle_hello = MagicMock() monkeypatch.setattr('layabout.SlackClient', SlackClient) layabout.handle('hello', kwargs=kwargs)(handle_hello) layabout.run(connector=TOKEN, interval=0, retries=0, backoff=lambda r: 0, until=run_once) handle_hello.assert_called_once_with(slack, events[0], **kwargs)
def test_layabout_can_handle_one_event_multiple_times(events, run_once, monkeypatch): """ Test that layabout calls all handlers for a given event. """ layabout = Layabout() SlackClient, slack = mock_slack(connections=(True, ), reads=(events, [])) handle_hello1, handle_hello2 = MagicMock(), MagicMock() monkeypatch.setattr('layabout.SlackClient', SlackClient) layabout.handle('hello')(handle_hello1) layabout.handle('hello')(handle_hello2) layabout.run(connector=TOKEN, interval=0, retries=0, backoff=lambda r: 0, until=run_once) handle_hello1.assert_called_once_with(slack, events[0]) handle_hello2.assert_called_once_with(slack, events[0])
def test_layabout_can_handle_events_with_normal_and_splat_handlers( events, run_once, monkeypatch): """ Test that layabout can handle an event with normal handlers as well as a splat handler. """ layabout = Layabout() SlackClient, slack = mock_slack(connections=(True, ), reads=(events, [])) handle_hello, splat = MagicMock(), MagicMock() monkeypatch.setattr('layabout.SlackClient', SlackClient) layabout.handle('hello')(handle_hello) layabout.handle('*')(splat) layabout.run(connector=TOKEN, interval=0, retries=0, backoff=lambda r: 0, until=run_once) handle_hello.assert_called_once_with(slack, events[0]) splat.assert_has_calls([call(slack, e) for e in events])
def test_layabout_can_reuse_an_existing_client_to_reconnect(monkeypatch): """ Test that layabout can reuse an existing SlackClient instance to reconnect to the Slack API rather than needlessly instantiating a new one on each reconnection attempt. """ layabout = Layabout() # Fail initial connection, fail reconnection, succeed at last. connections = (False, False, True) SlackClient, _ = mock_slack(connections=connections) monkeypatch.setattr('layabout.SlackClient', SlackClient) # Retry connecting twice to verify reconnection logic was evaluated. # until will exit early just to be safe. layabout.run(connector=TOKEN, retries=2, backoff=lambda r: 0, until=lambda e: False) # Make sure the SlackClient was only instantiated once so we know that we # reused the existing instance. SlackClient.assert_called_once_with(token=TOKEN)
from pprint import pformat from layabout import Layabout app = Layabout() @app.handle('*') def print_all(slack, event): """ * is a special event type that allows you to handle all event types """ print(f"Got event:\n{pformat(event)}\n") # We don't need to pass anything to run. By default the API token will # be fetched from the LAYABOUT_TOKEN environment variable. if __name__ == "__main__": print('Printing all events. Press Ctrl-C to quit.\n') app.run()