aboutsummaryrefslogtreecommitdiff
path: root/tests/test_sync.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_sync.py')
-rw-r--r--tests/test_sync.py280
1 files changed, 280 insertions, 0 deletions
diff --git a/tests/test_sync.py b/tests/test_sync.py
new file mode 100644
index 0000000..a09bf00
--- /dev/null
+++ b/tests/test_sync.py
@@ -0,0 +1,280 @@
+# -*- coding: utf-8 -*-
+from collections import OrderedDict
+
+from mock import Mock
+from pytest import raises
+
+from pyee import EventEmitter
+
+
+class PyeeTestException(Exception):
+ pass
+
+
+def test_emit_sync():
+ """Basic synchronous emission works"""
+
+ call_me = Mock()
+ ee = EventEmitter()
+
+ @ee.on("event")
+ def event_handler(data, **kwargs):
+ call_me()
+ assert data == "emitter is emitted!"
+
+ assert ee.event_names() == {"event"}
+
+ # Making sure data is passed propers
+ ee.emit("event", "emitter is emitted!", error=False)
+
+ call_me.assert_called_once()
+
+
+def test_emit_error():
+ """Errors raise with no event handler, otherwise emit on handler"""
+
+ call_me = Mock()
+ ee = EventEmitter()
+
+ test_exception = PyeeTestException("lololol")
+
+ with raises(PyeeTestException):
+ ee.emit("error", test_exception)
+
+ @ee.on("error")
+ def on_error(exc):
+ call_me()
+
+ assert ee.event_names() == {"error"}
+
+ # No longer raises and error instead return True indicating handled
+ assert ee.emit("error", test_exception) is True
+ call_me.assert_called_once()
+
+
+def test_emit_return():
+ """Emit returns True when handlers are registered on an event, and false
+ otherwise.
+ """
+
+ call_me = Mock()
+ ee = EventEmitter()
+
+ assert ee.event_names() == set()
+
+ # make sure emitting without a callback returns False
+ assert not ee.emit("data")
+
+ # add a callback
+ ee.on("data")(call_me)
+
+ # should return True now
+ assert ee.emit("data")
+
+
+def test_new_listener_event():
+ """The 'new_listener' event fires whenever a new listener is added."""
+
+ call_me = Mock()
+ ee = EventEmitter()
+
+ ee.on("new_listener", call_me)
+
+ # Should fire new_listener event
+ @ee.on("event")
+ def event_handler(data):
+ pass
+
+ assert ee.event_names() == {"new_listener", "event"}
+
+ call_me.assert_called_once_with("event", event_handler)
+
+
+def test_listener_removal():
+ """Removing listeners removes the correct listener from an event."""
+
+ ee = EventEmitter()
+
+ # Some functions to pass to the EE
+ def first():
+ return 1
+
+ ee.on("event", first)
+
+ @ee.on("event")
+ def second():
+ return 2
+
+ @ee.on("event")
+ def third():
+ return 3
+
+ def fourth():
+ return 4
+
+ ee.on("event", fourth)
+
+ assert ee.event_names() == {"event"}
+
+ assert ee._events["event"] == OrderedDict(
+ [(first, first), (second, second), (third, third), (fourth, fourth)]
+ )
+
+ ee.remove_listener("event", second)
+
+ assert ee._events["event"] == OrderedDict(
+ [(first, first), (third, third), (fourth, fourth)]
+ )
+
+ ee.remove_listener("event", first)
+ assert ee._events["event"] == OrderedDict([(third, third), (fourth, fourth)])
+
+ ee.remove_all_listeners("event")
+ assert "event" not in ee._events["event"]
+
+
+def test_listener_removal_on_emit():
+ """Test that a listener removed during an emit is called inside the current
+ emit cycle.
+ """
+
+ call_me = Mock()
+ ee = EventEmitter()
+
+ def should_remove():
+ ee.remove_listener("remove", call_me)
+
+ ee.on("remove", should_remove)
+ ee.on("remove", call_me)
+
+ assert ee.event_names() == {"remove"}
+
+ ee.emit("remove")
+
+ call_me.assert_called_once()
+
+ call_me.reset_mock()
+
+ # Also test with the listeners added in the opposite order
+ ee = EventEmitter()
+ ee.on("remove", call_me)
+ ee.on("remove", should_remove)
+
+ assert ee.event_names() == {"remove"}
+
+ ee.emit("remove")
+
+ call_me.assert_called_once()
+
+
+def test_once():
+ """Test that `once()` method works propers."""
+
+ # very similar to "test_emit" but also makes sure that the event
+ # gets removed afterwards
+
+ call_me = Mock()
+ ee = EventEmitter()
+
+ def once_handler(data):
+ assert data == "emitter is emitted!"
+ call_me()
+
+ # Tests to make sure that after event is emitted that it's gone.
+ ee.once("event", once_handler)
+
+ assert ee.event_names() == {"event"}
+
+ ee.emit("event", "emitter is emitted!")
+
+ call_me.assert_called_once()
+
+ assert ee.event_names() == set()
+
+ assert "event" not in ee._events
+
+
+def test_once_removal():
+ """Removal of once functions works"""
+
+ ee = EventEmitter()
+
+ def once_handler(data):
+ pass
+
+ handle = ee.once("event", once_handler)
+
+ assert handle == once_handler
+ assert ee.event_names() == {"event"}
+
+ ee.remove_listener("event", handle)
+
+ assert "event" not in ee._events
+ assert ee.event_names() == set()
+
+
+def test_listeners():
+ """`listeners()` returns a copied list of listeners."""
+
+ call_me = Mock()
+ ee = EventEmitter()
+
+ @ee.on("event")
+ def event_handler():
+ pass
+
+ @ee.once("event")
+ def once_handler():
+ pass
+
+ listeners = ee.listeners("event")
+
+ assert listeners[0] == event_handler
+ assert listeners[1] == once_handler
+
+ # listeners is a copy, you can't mutate the innards this way
+ listeners[0] = call_me
+
+ ee.emit("event")
+
+ call_me.assert_not_called()
+
+
+def test_listeners_does_work_with_unknown_listeners():
+ """`listeners()` should not throw."""
+ ee = EventEmitter()
+ listeners = ee.listeners("event")
+ assert listeners == []
+
+
+def test_properties_preserved():
+ """Test that the properties of decorated functions are preserved."""
+
+ call_me = Mock()
+ call_me_also = Mock()
+ ee = EventEmitter()
+
+ @ee.on("always")
+ def always_event_handler():
+ """An event handler."""
+ call_me()
+
+ @ee.once("once")
+ def once_event_handler():
+ """Another event handler."""
+ call_me_also()
+
+ assert always_event_handler.__doc__ == "An event handler."
+ assert once_event_handler.__doc__ == "Another event handler."
+
+ always_event_handler()
+ call_me.assert_called_once()
+
+ once_event_handler()
+ call_me_also.assert_called_once()
+
+ call_me_also.reset_mock()
+
+ # Calling the event handler directly doesn't clear the handler
+ ee.emit("once")
+ call_me_also.assert_called_once()