281 lines
5.9 KiB
Python
281 lines
5.9 KiB
Python
# -*- 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()
|