mirror of
https://github.com/JockeTF/fimfarchive.git
synced 2024-12-01 17:17:59 +01:00
189 lines
4.5 KiB
Python
189 lines
4.5 KiB
Python
|
"""
|
||
|
Signal tests.
|
||
|
"""
|
||
|
|
||
|
|
||
|
#
|
||
|
# Fimfarchive, preserves stories from Fimfiction.
|
||
|
# Copyright (C) 2015 Joakim Soderlund
|
||
|
#
|
||
|
# This program is free software: you can redistribute it and/or modify
|
||
|
# it under the terms of the GNU General Public License as published by
|
||
|
# the Free Software Foundation, either version 3 of the License, or
|
||
|
# (at your option) any later version.
|
||
|
#
|
||
|
# This program is distributed in the hope that it will be useful,
|
||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
# GNU General Public License for more details.
|
||
|
#
|
||
|
# You should have received a copy of the GNU General Public License
|
||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
#
|
||
|
|
||
|
|
||
|
from collections import OrderedDict
|
||
|
from unittest.mock import patch, Mock
|
||
|
|
||
|
import blinker
|
||
|
import pytest
|
||
|
|
||
|
from fimfarchive.signals import (
|
||
|
Signal, SignalBinder, SignalSender, SignalReceiver
|
||
|
)
|
||
|
|
||
|
|
||
|
@pytest.fixture
|
||
|
def params():
|
||
|
"""
|
||
|
Returns an ordered dict of parameters.
|
||
|
"""
|
||
|
data = (
|
||
|
('a', 1),
|
||
|
('b', 2),
|
||
|
('c', 3),
|
||
|
)
|
||
|
|
||
|
return OrderedDict(data)
|
||
|
|
||
|
|
||
|
@pytest.fixture
|
||
|
def signal(params):
|
||
|
"""
|
||
|
Returns an unbound signal instance.
|
||
|
"""
|
||
|
return Signal(*params.keys())
|
||
|
|
||
|
|
||
|
@pytest.fixture
|
||
|
def sender(signal):
|
||
|
"""
|
||
|
Returns a signal sender instance.
|
||
|
"""
|
||
|
class Sender(SignalSender):
|
||
|
on_signal = signal
|
||
|
|
||
|
return Sender()
|
||
|
|
||
|
|
||
|
@pytest.fixture
|
||
|
def receiver(sender):
|
||
|
"""
|
||
|
Returns a signal receiver instance.
|
||
|
"""
|
||
|
class Receiver(SignalReceiver):
|
||
|
on_signal = Mock('on_signal')
|
||
|
|
||
|
return Receiver(sender)
|
||
|
|
||
|
|
||
|
@pytest.fixture
|
||
|
def binder(sender):
|
||
|
"""
|
||
|
Returns a bound signal instance.
|
||
|
"""
|
||
|
return sender.on_signal
|
||
|
|
||
|
|
||
|
class TestSignal:
|
||
|
"""
|
||
|
Signal tests.
|
||
|
"""
|
||
|
|
||
|
def test_reserved_value_names(self):
|
||
|
"""
|
||
|
Tests `ValueError` is raised for reserved value names.
|
||
|
"""
|
||
|
with pytest.raises(ValueError):
|
||
|
Signal('sender')
|
||
|
|
||
|
def test_send_unbound_signal(self, params, signal):
|
||
|
"""
|
||
|
Tests `ValueError` is raised when calling unbound signals.
|
||
|
"""
|
||
|
with pytest.raises(ValueError):
|
||
|
signal(*params.values())
|
||
|
|
||
|
def test_parameter_mapping(self, params, signal, sender):
|
||
|
"""
|
||
|
Tests positional parameters maps to named parameters.
|
||
|
"""
|
||
|
with patch.object(blinker.Signal, 'send') as m:
|
||
|
signal.send(sender, *params.values())
|
||
|
m.assert_called_once_with(sender, **params)
|
||
|
|
||
|
def test_parameter_overflow(self, params, signal, sender):
|
||
|
"""
|
||
|
Tests `ValueError` is raised on too many parameters.
|
||
|
"""
|
||
|
with pytest.raises(ValueError):
|
||
|
signal.send(sender, *params.values(), 'alpaca')
|
||
|
|
||
|
def test_duplicate_parameter(self, params, signal, sender):
|
||
|
"""
|
||
|
Tests `ValueError` is raised on duplicate parameters.
|
||
|
"""
|
||
|
duplicate = dict(tuple(params.items())[:1])
|
||
|
|
||
|
with pytest.raises(ValueError):
|
||
|
signal.send(sender, *params.values(), **duplicate)
|
||
|
|
||
|
|
||
|
class TestSignalBinder:
|
||
|
"""
|
||
|
SignalBinder tests.
|
||
|
"""
|
||
|
|
||
|
def test_send(self, params, sender, binder):
|
||
|
"""
|
||
|
Tests sender is passed to signal.
|
||
|
"""
|
||
|
with patch.object(Signal, 'send') as m:
|
||
|
binder(*params.values())
|
||
|
m.assert_called_once_with(sender, *params.values())
|
||
|
|
||
|
|
||
|
class TestSignalSender:
|
||
|
"""
|
||
|
SignalSender tests.
|
||
|
"""
|
||
|
|
||
|
def test_bind(self, signal, sender, binder):
|
||
|
"""
|
||
|
Tests signal is bound on init.
|
||
|
"""
|
||
|
cls = type(sender)
|
||
|
|
||
|
assert isinstance(cls.on_signal, Signal)
|
||
|
assert isinstance(sender.on_signal, SignalBinder)
|
||
|
|
||
|
assert signal == cls.on_signal
|
||
|
assert binder == sender.on_signal
|
||
|
|
||
|
def test_send(self, params, sender):
|
||
|
"""
|
||
|
Tests sender is passed to signal
|
||
|
"""
|
||
|
with patch.object(Signal, 'send') as m:
|
||
|
sender.on_signal(*params.values())
|
||
|
m.assert_called_once_with(sender, *params.values())
|
||
|
|
||
|
|
||
|
class TestSignalReceiver:
|
||
|
"""
|
||
|
SignalReceiver tests.
|
||
|
"""
|
||
|
|
||
|
def test_connect(self, signal, receiver):
|
||
|
"""
|
||
|
Tests receiver connects to signal automatically.
|
||
|
"""
|
||
|
assert receiver.on_signal in signal.receivers
|
||
|
|
||
|
def test_send(self, params, sender, receiver):
|
||
|
"""
|
||
|
Tests receiver recives emitted singal.
|
||
|
"""
|
||
|
sender.on_signal(*params.values())
|
||
|
receiver.on_signal.assert_called_once_with(sender, **params)
|