Solaar/tests/solaar/ui/test_pair_window.py

212 lines
7.6 KiB
Python

from dataclasses import dataclass
from dataclasses import field
from typing import Any
from typing import List
from typing import Optional
import gi
import pytest
from logitech_receiver import receiver
from solaar.ui import pair_window
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk # NOQA: E402
gtk_init = Gtk.init_check()[0]
@dataclass
class Device:
name: str = "test device"
kind: str = "test kind"
@dataclass
class Receiver:
name: str
receiver_kind: str
_set_lock: bool = True
pairing: receiver.Pairing = field(default_factory=receiver.Pairing)
pairable: bool = True
_remaining_pairings: Optional[int] = None
def reset_pairing(self):
self.receiver = receiver.Pairing()
def remaining_pairings(self, cache=True):
return self._remaining_pairings
def set_lock(self, value=False, timeout=0):
self.pairing.lock_open = self._set_lock
return self._set_lock
def discover(self, cancel=False, timeout=30):
self.pairing.discovering = self._set_lock
return self._set_lock
def pair_device(self, pair=True, slot=0, address=b"\0\0\0\0\0\0", authentication=0x00, entropy=20, force=False):
print("PD", self.pairable)
return self.pairable
@dataclass
class Assistant:
drawable: bool = True
pages: List[Any] = field(default_factory=list)
def is_drawable(self):
return self.drawable
def next_page(self):
return True
def set_page_complete(self, page, b):
return True
def commit(self):
return True
def append_page(self, page):
self.pages.append(page)
def remove_page(self, page):
return True
def set_page_type(self, page, type):
return True
def destroy(self):
pass
@pytest.mark.skipif(not gtk_init, reason="requires Gtk")
@pytest.mark.parametrize(
"receiver, lock_open, discovering, page_type",
[
(Receiver("unifying", "unifying", True), True, False, Gtk.AssistantPageType.PROGRESS),
(Receiver("unifying", "unifying", False), False, False, Gtk.AssistantPageType.SUMMARY),
(Receiver("nano", "nano", True, _remaining_pairings=5), True, False, Gtk.AssistantPageType.PROGRESS),
(Receiver("nano", "nano", False), False, False, Gtk.AssistantPageType.SUMMARY),
(Receiver("bolt", "bolt", True), False, True, Gtk.AssistantPageType.PROGRESS),
(Receiver("bolt", "bolt", False), False, False, Gtk.AssistantPageType.SUMMARY),
],
)
def test_create(receiver, lock_open, discovering, page_type):
assistant = pair_window.create(receiver)
assert assistant is not None
assert assistant.get_page_type(assistant.get_nth_page(0)) == page_type
assert receiver.pairing.lock_open == lock_open
assert receiver.pairing.discovering == discovering
@pytest.mark.parametrize(
"receiver, expected_result, expected_error",
[
(Receiver("unifying", "unifying", True), True, False),
(Receiver("unifying", "unifying", False), False, True),
(Receiver("bolt", "bolt", True), True, False),
(Receiver("bolt", "bolt", False), False, True),
],
)
def test_prepare(receiver, expected_result, expected_error):
result = pair_window.prepare(receiver)
assert result == expected_result
assert bool(receiver.pairing.error) == expected_error
@pytest.mark.parametrize("assistant, expected_result", [(Assistant(True), True), (Assistant(False), False)])
def test_check_lock_state_drawable(assistant, expected_result):
r = Receiver("succeed", "unifying", True, receiver.Pairing(lock_open=True))
result = pair_window.check_lock_state(assistant, r, 2)
assert result == expected_result
@pytest.mark.skipif(not gtk_init, reason="requires Gtk")
@pytest.mark.parametrize(
"receiver, count, expected_result",
[
(Receiver("fail", "unifying", False, receiver.Pairing(lock_open=False)), 2, False),
(Receiver("succeed", "unifying", True, receiver.Pairing(lock_open=True)), 1, True),
(Receiver("error", "unifying", True, receiver.Pairing(error="error")), 0, False),
(Receiver("new device", "unifying", True, receiver.Pairing(new_device=Device())), 2, False),
(Receiver("closed", "unifying", True, receiver.Pairing()), 2, False),
(Receiver("closed", "unifying", True, receiver.Pairing()), 1, False),
(Receiver("closed", "unifying", True, receiver.Pairing()), 0, False),
(Receiver("fail bolt", "bolt", False), 1, False),
(Receiver("succeed bolt", "bolt", True, receiver.Pairing(lock_open=True)), 0, True),
(Receiver("error bolt", "bolt", True, receiver.Pairing(error="error")), 2, False),
(Receiver("new device", "bolt", True, receiver.Pairing(lock_open=True, new_device=Device())), 1, False),
(Receiver("discovering", "bolt", True, receiver.Pairing(lock_open=True)), 1, True),
(Receiver("closed", "bolt", True, receiver.Pairing()), 2, False),
(Receiver("closed", "bolt", True, receiver.Pairing()), 1, False),
(Receiver("closed", "bolt", True, receiver.Pairing()), 0, False),
(
Receiver("pass1", "bolt", True, receiver.Pairing(lock_open=True, device_passkey=50, device_authentication=0x01)),
0,
True,
),
(
Receiver("pass2", "bolt", True, receiver.Pairing(lock_open=True, device_passkey=50, device_authentication=0x02)),
0,
True,
),
(
Receiver("adt", "bolt", True, receiver.Pairing(discovering=True, device_address=2, device_name=5), pairable=True),
2,
True,
),
(
Receiver("adf", "bolt", True, receiver.Pairing(discovering=True, device_address=2, device_name=5), pairable=False),
2,
False,
),
(Receiver("add fail", "bolt", False, receiver.Pairing(device_address=2, device_passkey=5)), 2, False),
],
)
def test_check_lock_state(receiver, count, expected_result):
assistant = Assistant(True)
check_state = pair_window._check_lock_state(assistant, receiver, count)
assert check_state == expected_result
@pytest.mark.parametrize(
"receiver, pair_device, set_lock, discover, error",
[
(Receiver("unifying", "unifying", pairing=receiver.Pairing(lock_open=False, error="error")), 0, 0, 0, None),
(Receiver("unifying", "unifying", pairing=receiver.Pairing(lock_open=True, error="error")), 0, 1, 0, "error"),
(Receiver("bolt", "bolt", pairing=receiver.Pairing(lock_open=False, error="error")), 0, 0, 0, None),
(Receiver("bolt", "bolt", pairing=receiver.Pairing(lock_open=True, error="error")), 1, 0, 0, "error"),
(Receiver("bolt", "bolt", pairing=receiver.Pairing(discovering=True, error="error")), 0, 0, 1, "error"),
],
)
def test_finish(receiver, pair_device, set_lock, discover, error, mocker):
spy_pair_device = mocker.spy(receiver, "pair_device")
spy_set_lock = mocker.spy(receiver, "set_lock")
spy_discover = mocker.spy(receiver, "discover")
assistant = Assistant(True)
pair_window._finish(assistant, receiver)
assert spy_pair_device.call_count == pair_device
assert spy_set_lock.call_count == set_lock
assert spy_discover.call_count == discover
assert receiver.pairing.error == error
@pytest.mark.skipif(not gtk_init, reason="requires Gtk")
@pytest.mark.parametrize("error", ["timeout", "device not supported", "too many devices"])
def test_create_failure_page(error, mocker):
spy_create = mocker.spy(pair_window, "_create_page")
pair_window._pairing_failed(Assistant(True), Receiver("nano", "nano"), error)
assert spy_create.call_count == 1