# Copyright 2022 (c) Anna Schumaker. """Tests our autopause widgets.""" import unittest import emmental.nowplaying.autopause from gi.repository import Gtk from gi.repository import GLib class TestAutopauseEntry(unittest.TestCase): """Test our custom Autopause Entry.""" def setUp(self): """Set up common variables.""" self.entry = emmental.nowplaying.autopause.Entry() self.timeout_func = self.entry._Entry__change_value self.down_icon_pos = Gtk.EntryIconPosition.PRIMARY self.up_icon_pos = Gtk.EntryIconPosition.SECONDARY def tearDown(self): """Clean up.""" if self.entry._timeout[0] is not None: GLib.source_remove(self.entry._timeout[0]) def test_init(self): """Test that the Autopause Entry is configured correctly.""" self.assertIsInstance(self.entry, Gtk.Entry) self.assertTupleEqual(self.entry._timeout, (None, None)) self.assertEqual(self.entry.get_max_width_chars(), 20) self.assertTrue(self.entry.has_css_class("card")) def test_placeholder_text(self): """Test changing the placeholder text with the value.""" self.assertEqual(self.entry.value, -1) self.assertEqual(self.entry.get_placeholder_text(), "Keep playing") for (value, expected) in [(0, "Pause after this track"), (1, "Pause after the next track"), (99, "Pause after 99 tracks"), (-1, "Keep playing")]: with self.subTest(value=value, expected=expected): self.entry.value = value self.assertEqual(self.entry.get_placeholder_text(), expected) @unittest.mock.patch("gi.repository.GLib.source_remove", wraps=GLib.source_remove) @unittest.mock.patch("gi.repository.GLib.timeout_add", wraps=GLib.timeout_add) def test_down_icon(self, mock_tout_add: unittest.mock.Mock, mock_src_remove: unittest.mock.Mock): """Test that the down icon works as expected.""" self.assertEqual(self.entry.get_icon_name(self.down_icon_pos), "list-remove-symbolic") self.assertFalse(self.entry.get_icon_sensitive(self.down_icon_pos)) self.assertTrue(self.entry.get_icon_activatable(self.down_icon_pos)) self.entry.value = 5 self.entry.emit("icon-press", self.down_icon_pos) self.assertEqual(self.entry.value, 4) mock_tout_add.assert_called_with(500, self.timeout_func, "decrement") self.assertIsNotNone(self.entry._timeout[0]) self.assertEqual(self.entry._timeout[1], 500) timeout_id = self.entry._timeout[0] self.entry.emit("icon-release", self.down_icon_pos) mock_src_remove.assert_called_with(timeout_id) self.assertTupleEqual(self.entry._timeout, (None, None)) @unittest.mock.patch("gi.repository.GLib.timeout_add", wraps=GLib.timeout_add) def test_hold_down_icon(self, mock_timeout: unittest.mock.Mock): """Test holding down the down icon.""" self.entry.value = 99 self.assertEqual(self.timeout_func("decrement"), GLib.SOURCE_REMOVE) self.assertEqual(self.entry.value, 98) mock_timeout.assert_called_with(150, self.timeout_func, "decrement") self.assertTrue(self.entry.get_icon_sensitive(self.down_icon_pos)) self.assertIsNotNone(self.entry._timeout[0]) self.assertEqual(self.entry._timeout[1], 150) timeout_id = self.entry._timeout[0] mock_timeout.reset_mock() self.entry.value = 0 self.assertEqual(self.timeout_func("decrement"), GLib.SOURCE_CONTINUE) self.assertFalse(self.entry.get_icon_sensitive(self.down_icon_pos)) self.assertEqual(self.entry.value, -1) mock_timeout.assert_not_called() self.assertEqual(self.timeout_func("decrement"), GLib.SOURCE_REMOVE) GLib.source_remove(timeout_id) @unittest.mock.patch("gi.repository.GLib.source_remove", wraps=GLib.source_remove) @unittest.mock.patch("gi.repository.GLib.timeout_add", wraps=GLib.timeout_add) def test_up_icon(self, mock_tout_add: unittest.mock.Mock, mock_src_remove: unittest.mock.Mock): """Test that the down icon works as expected.""" self.assertEqual(self.entry.get_icon_name(self.up_icon_pos), "list-add-symbolic") self.assertTrue(self.entry.get_icon_sensitive(self.up_icon_pos)) self.assertTrue(self.entry.get_icon_activatable(self.up_icon_pos)) self.entry.emit("icon-press", self.up_icon_pos) self.assertEqual(self.entry.value, 0) mock_tout_add.assert_called_with(500, self.timeout_func, "increment") self.assertIsNotNone(self.entry._timeout[0]) self.assertEqual(self.entry._timeout[1], 500) timeout_id = self.entry._timeout[0] self.entry.emit("icon-release", self.up_icon_pos) self.assertTupleEqual(self.entry._timeout, (None, None)) mock_src_remove.assert_called_with(timeout_id) @unittest.mock.patch("gi.repository.GLib.timeout_add", wraps=GLib.timeout_add) def test_hold_up_icon(self, mock_timeout: unittest.mock.Mock): """Test holding down the up icon.""" self.assertEqual(self.timeout_func("increment"), GLib.SOURCE_REMOVE) self.assertEqual(self.entry.value, 0) mock_timeout.assert_called_with(150, self.timeout_func, "increment") self.assertTrue(self.entry.get_icon_sensitive(self.up_icon_pos)) self.assertIsNotNone(self.entry._timeout[0]) self.assertEqual(self.entry._timeout[1], 150) timeout_id = self.entry._timeout[0] mock_timeout.reset_mock() self.entry.value = 98 self.assertEqual(self.timeout_func("increment"), GLib.SOURCE_CONTINUE) self.assertFalse(self.entry.get_icon_sensitive(self.up_icon_pos)) self.assertEqual(self.entry.value, 99) mock_timeout.assert_not_called() self.assertEqual(self.timeout_func("increment"), GLib.SOURCE_REMOVE) GLib.source_remove(timeout_id) def test_parse_text(self): """Test setting a value through the entry.""" subtests = [(str(i), i) for i in [-3, -1, 99, 100]] for (text, value) in [("this", 0), ("NEXT", 1), ("", 1), ("", 1), ("cancel", -1)] + subtests: with self.subTest(text=text, value=value): value = min(99, max(-1, value)) self.entry.set_text(text) self.entry.emit("activate") self.assertEqual(self.entry.value, value, f"text=\"{text}\"") def test_decrement(self): """Test the decrement() function.""" self.entry.value = 1 self.entry.decrement() self.assertEqual(self.entry.value, 0) self.entry.decrement() self.assertEqual(self.entry.value, -1) self.entry.decrement() self.assertEqual(self.entry.value, -1) def test_increment(self): """Test the increment() function.""" self.entry.value = 97 self.entry.increment() self.assertEqual(self.entry.value, 98) self.entry.increment() self.assertEqual(self.entry.value, 99) self.entry.increment() self.assertEqual(self.entry.value, 99) class TestAutopauseButton(unittest.TestCase): """Test our Autopause Popover Button.""" def setUp(self): """Set up common variables.""" self.button = emmental.nowplaying.autopause.Button() def test_init(self): """Test the autopause button.""" self.assertIsInstance(self.button, emmental.buttons.PopoverButton) self.assertIsInstance(self.button._overlay, Gtk.Overlay) self.assertIsInstance(self.button.popover_child, emmental.nowplaying.autopause.Entry) self.assertEqual(self.button.get_child(), self.button._overlay) def test_arrow(self): """Test that the arrow image was set up properly.""" self.assertIsInstance(self.button._arrow, Gtk.Image) self.assertEqual(self.button._arrow.get_icon_name(), "pan-down-symbolic") self.assertEqual(self.button._arrow.get_margin_top(), 6) self.assertEqual(self.button._overlay.get_child(), self.button._arrow) def test_count(self): """Test that the count label was set up properly.""" self.assertIsInstance(self.button._count, Gtk.Label) self.assertEqual(self.button._count.get_yalign(), 0) self.assertEqual(self.button._count.get_halign(), Gtk.Align.CENTER) self.assertEqual(self.button._count.get_margin_top(), 3) self.assertEqual(self.button._count.get_text(), "") def test_value(self): """Test the value property.""" self.assertEqual(self.button.value, -1) self.button.value = 0 self.assertEqual(self.button.popover_child.value, 0) self.assertEqual(self.button._count.get_text(), "0") self.button.popover_child.value = 1 self.assertEqual(self.button.value, 1) self.assertEqual(self.button._count.get_text(), "1") self.button.value = -1 self.assertEqual(self.button._count.get_text(), "") def test_decrement(self): """Test the decrement() function.""" with unittest.mock.patch.object(self.button.popover_child, "decrement") as mock_decrement: self.button.decrement() mock_decrement.assert_called() def test_increment(self): """Test the increment() functions.""" with unittest.mock.patch.object(self.button.popover_child, "increment") as mock_increment: self.button.increment() mock_increment.assert_called()