# Copyright 2022 (c) Anna Schumaker """Tests extra buttons for the TrackList.""" import unittest import unittest.mock import emmental.tracklist.buttons from gi.repository import Gio from gi.repository import Gtk class TestVisibleColumnRow(unittest.TestCase): """Test the Visible Column ListBoxRow.""" def setUp(self): """Set up common variables.""" self.row = emmental.tracklist.buttons.VisibleRow("title", True) def test_init(self): """Test that the VisibleRow was set up properly.""" self.assertIsInstance(self.row, Gtk.ListBoxRow) self.assertIsInstance(self.row.props.child, Gtk.Box) self.assertEqual(self.row.title, "title") self.assertTrue(self.row.active) self.assertEqual(self.row.props.child.props.margin_start, 6) self.assertEqual(self.row.props.child.props.margin_end, 6) self.assertEqual(self.row.props.child.props.margin_top, 6) self.assertEqual(self.row.props.child.props.margin_bottom, 6) self.assertEqual(self.row.props.child.props.spacing, 6) row2 = emmental.tracklist.buttons.VisibleRow("title2", False) self.assertEqual(row2.title, "title2") self.assertFalse(row2.active) def test_switch(self): """Test the VisibleRow switch.""" self.assertIsInstance(self.row._switch, Gtk.Switch) self.assertEqual(self.row._switch.props.parent, self.row.props.child) self.assertTrue(self.row._switch.props.active) self.row.active = False self.assertFalse(self.row._switch.props.active) self.row._switch.props.active = True self.assertTrue(self.row.active) row2 = emmental.tracklist.buttons.VisibleRow("title2", False) self.assertFalse(row2._switch.props.active) def test_label(self): """Test the VisibleRow title label.""" self.assertIsInstance(self.row._label, Gtk.Label) self.assertEqual(self.row._label.props.label, "title") self.assertEqual(self.row._switch.get_next_sibling(), self.row._label) class TestVisibleColumns(unittest.TestCase): """Test the Visible Columns button.""" def setUp(self): """Set up common variables.""" self.columns = Gio.ListStore() self.columns.append(Gtk.ColumnViewColumn(title="title", visible=True)) self.columns.append(Gtk.ColumnViewColumn(title="title2", visible=False)) self.button = emmental.tracklist.buttons.VisibleColumns(self.columns) def test_init(self): """Test that the Visible Columns button is set up properly.""" self.assertIsInstance(self.button, emmental.buttons.PopoverButton) self.assertFalse(self.button.get_has_frame()) self.assertEqual(self.button.get_icon_name(), "columns-symbolic") self.assertEqual(self.button.get_tooltip_text(), "configure visible columns") self.assertEqual(self.button.columns, self.columns) def test_popover_child(self): """Test that the popover_child was set up properly.""" self.assertIsInstance(self.button.popover_child, Gtk.ListBox) self.assertEqual(self.button.popover_child.props.selection_mode, Gtk.SelectionMode.NONE) self.assertTrue(self.button.popover_child.has_css_class("boxed-list")) def test_create_func(self): """Test that the Gtk.ListBox creates VisibleRows correctly.""" row = self.button.popover_child.get_row_at_index(0) self.assertIsInstance(row, emmental.tracklist.buttons.VisibleRow) self.assertEqual(row.title, "title") self.assertTrue(row.active) row.active = False self.assertFalse(self.columns[0].get_visible()) row.active = True self.assertTrue(self.columns[0].get_visible()) self.columns[0].set_visible(False) self.assertFalse(row.active) row = self.button.popover_child.get_row_at_index(1) self.assertIsInstance(row, emmental.tracklist.buttons.VisibleRow) self.assertEqual(row.title, "title2") self.assertFalse(row.active) def test_activate(self): """Test activating a Gtk.ListBox row.""" row = self.button.popover_child.get_row_at_index(0) self.button.popover_child.emit("row-activated", row) self.assertFalse(row.active) self.button.popover_child.emit("row-activated", row) self.assertTrue(row.active) class TestLoopButton(unittest.TestCase): """Test the LoopButton.""" def setUp(self): """Set up common variables.""" self.loop = emmental.tracklist.buttons.LoopButton() def test_init(self): """Test that the loop button is set up properly.""" self.assertIsInstance(self.loop, emmental.buttons.ImageToggle) self.assertEqual(self.loop.active_icon_name, "media-playlist-repeat-song") self.assertEqual(self.loop.active_tooltip_text, "loop: track") self.assertEqual(self.loop.inactive_icon_name, "media-playlist-repeat") self.assertEqual(self.loop.inactive_tooltip_text, "loop: disabled") self.assertFalse(self.loop.large_icon) self.assertFalse(self.loop.get_has_frame()) def test_state(self): """Test changing the state property.""" self.assertTrue(self.loop.can_disable) self.assertEqual(self.loop.state, "None") self.assertAlmostEqual(self.loop.icon_opacity, 0.5, delta=0.005) self.assertEqual(self.loop.props.tooltip_text, "loop: disabled") self.assertFalse(self.loop.active) self.loop.state = "Playlist" self.assertEqual(self.loop.state, "Playlist") self.assertEqual(self.loop.icon_opacity, 1.0) self.assertEqual(self.loop.props.tooltip_text, "loop: playlist") self.assertFalse(self.loop.active) self.loop.state = "Track" self.assertEqual(self.loop.state, "Track") self.assertEqual(self.loop.icon_opacity, 1.0) self.assertEqual(self.loop.props.tooltip_text, "loop: track") self.assertTrue(self.loop.active) self.loop.can_disable = False self.loop.state = "None" self.assertEqual(self.loop.state, "Track") self.assertEqual(self.loop.props.tooltip_text, "loop: track") self.assertTrue(self.loop.active) self.loop.can_disable = True self.loop.state = "None" self.assertAlmostEqual(self.loop.icon_opacity, 0.5, delta=0.005) self.assertEqual(self.loop.inactive_tooltip_text, "loop: disabled") self.assertFalse(self.loop.active) def test_click(self): """Test cycling through states when clicked.""" self.assertEqual(self.loop.state, "None") self.loop.emit("clicked") self.assertEqual(self.loop.state, "Playlist") self.loop.emit("clicked") self.assertEqual(self.loop.state, "Track") self.loop.emit("clicked") self.assertEqual(self.loop.state, "None") self.loop.state = "Playlist" self.loop.can_disable = False self.loop.emit("clicked") self.assertEqual(self.loop.state, "Track") self.loop.emit("clicked") self.assertEqual(self.loop.state, "Playlist") class TestShuffleButtons(unittest.TestCase): """Test the Shuffle button.""" def setUp(self): """Set up common variables.""" self.shuffle = emmental.tracklist.buttons.ShuffleButton() def test_init(self): """Test that the shuffle button is configured correctly.""" self.assertIsInstance(self.shuffle, emmental.buttons.ImageToggle) self.assertFalse(self.shuffle.large_icon) self.assertFalse(self.shuffle.get_has_frame()) self.assertEqual(self.shuffle.active_icon_name, "media-playlist-shuffle") self.assertEqual(self.shuffle.active_tooltip_text, "shuffle: enabled") self.assertEqual(self.shuffle.inactive_tooltip_text, "shuffle: disabled") self.assertAlmostEqual(self.shuffle.icon_opacity, 0.5, delta=0.005) @unittest.mock.patch("emmental.gsetup.has_icon") def test_get_inactive_icon(self, mock_has_icon: unittest.mock.Mock): """Test the get_inactive_icon() function.""" mock_has_icon.return_value = True self.assertEqual(self.shuffle.get_inactive_icon(), "media-playlist-normal") mock_has_icon.assert_called() mock_has_icon.return_value = False self.assertEqual(self.shuffle.get_inactive_icon(), "media-playlist-consecutive") @unittest.mock.patch("emmental.gsetup.has_icon") def test_inactive_icon_name(self, mock_has_icon: unittest.mock.Mock): """Test setting the inactive icon name.""" mock_has_icon.return_value = True button = emmental.tracklist.buttons.ShuffleButton() mock_has_icon.assert_called_with("media-playlist-normal") self.assertEqual(button.inactive_icon_name, "media-playlist-normal") mock_has_icon.return_value = False button = emmental.tracklist.buttons.ShuffleButton() self.assertEqual(button.inactive_icon_name, "media-playlist-consecutive") @unittest.mock.patch("emmental.gsetup.has_icon") def test_toggled(self, mock_has_icon: unittest.mock.Mock): """Test changing the icon when toggled.""" mock_has_icon.return_value = True self.shuffle.active = True self.assertEqual(self.shuffle.inactive_icon_name, "media-playlist-normal") mock_has_icon.assert_called() mock_has_icon.return_value = False self.shuffle.active = False self.assertEqual(self.shuffle.inactive_icon_name, "media-playlist-consecutive") def test_opacity(self): """Test adjusting the opacity based on active state.""" self.shuffle.active = True self.assertEqual(self.shuffle.icon_opacity, 1.0) self.shuffle.active = False self.assertEqual(self.shuffle.icon_opacity, 0.5) class TestSortRow(unittest.TestCase): """Test the Sort Row ListBoxRow.""" def setUp(self): """Set up common variables.""" self.model = emmental.tracklist.sorter.SortOrderModel() self.model[0].enable() self.model[1].reverse() self.row1 = emmental.tracklist.buttons.SortRow(self.model[0]) self.row2 = emmental.tracklist.buttons.SortRow(self.model[1]) def test_init(self): """Test that the Sort Field Widget is configured correctly.""" self.assertIsInstance(self.row1, Gtk.ListBoxRow) self.assertIsInstance(self.row1.props.child, Gtk.Box) self.assertEqual(self.row1.props.child.props.margin_start, 6) self.assertEqual(self.row1.props.child.props.margin_end, 6) self.assertEqual(self.row1.props.child.props.margin_top, 6) self.assertEqual(self.row1.props.child.props.margin_bottom, 6) self.assertEqual(self.row1.props.child.props.spacing, 6) self.assertEqual(self.row1.sort_field, self.model[0]) self.assertTrue(self.row1.active) self.assertEqual(self.row2.sort_field, self.model[1]) self.assertFalse(self.row2.active) def test_switch(self): """Test the SortRow switch.""" self.assertIsInstance(self.row1._switch, Gtk.Switch) self.assertEqual(self.row1._switch.props.valign, Gtk.Align.CENTER) self.assertEqual(self.row1._switch.props.parent, self.row1.props.child) self.assertTrue(self.row1._switch.props.active) self.assertFalse(self.row2._switch.props.active) with unittest.mock.patch.object(self.model[0], "disable") as mock_disable: self.row1._switch.props.active = False mock_disable.assert_called() with unittest.mock.patch.object(self.model[0], "enable") as mock_enable: self.row1._switch.props.active = True mock_enable.assert_called() def test_label(self): """Test the SortRow title label.""" self.assertIsInstance(self.row1._label, Gtk.Label) self.assertEqual(self.row1._switch.get_next_sibling(), self.row1._label) self.assertEqual(self.row1._label.props.label, self.model[0].name) self.assertEqual(self.row1._label.props.xalign, 0.0) self.assertTrue(self.row1._label.props.hexpand) self.assertTrue(self.row1._label.props.sensitive) self.assertFalse(self.row2._label.props.sensitive) def test_reverse(self): """Test the SortRow reverse button.""" self.assertIsInstance(self.row1._reverse, emmental.buttons.ImageToggle) self.assertEqual(self.row1._label.get_next_sibling(), self.row1._reverse) self.assertEqual(self.row1._reverse.active_icon_name, "arrow1-up") self.assertEqual(self.row1._reverse.inactive_icon_name, "arrow1-down") self.assertFalse(self.row1._reverse.props.has_frame) self.assertFalse(self.row1._reverse.large_icon) self.assertFalse(self.row1._reverse.props.active) self.assertTrue(self.row1._reverse.props.sensitive) self.assertTrue(self.row2._reverse.props.active) self.assertFalse(self.row2._reverse.props.sensitive) with unittest.mock.patch.object(self.model[0], "reverse") as mock_reverse: self.row1._reverse.emit("toggled") mock_reverse.assert_called() def test_move_box(self): """Test the box containing the move up & down buttons.""" self.assertIsInstance(self.row1._move_box, Gtk.Box) self.assertEqual(self.row1._reverse.get_next_sibling(), self.row1._move_box) self.assertTrue(self.row1._move_box.has_css_class("linked")) self.assertTrue(self.row1._move_box.props.sensitive) self.assertFalse(self.row2._move_box.props.sensitive) def test_move_up(self): """Test the move up button.""" self.assertIsInstance(self.row1._move_up, Gtk.Button) self.assertEqual(self.row1._move_up.get_icon_name(), "go-up-symbolic") self.assertEqual(self.row1._move_up.props.parent, self.row1._move_box) with unittest.mock.patch.object(self.model[0], "move_up") as mock_move_up: self.row1._move_up.emit("clicked") mock_move_up.assert_called() def test_move_down(self): """Test the move down button.""" self.assertIsInstance(self.row1._move_down, Gtk.Button) self.assertEqual(self.row1._move_down.get_icon_name(), "go-down-symbolic") self.assertEqual(self.row1._move_up.get_next_sibling(), self.row1._move_down) with unittest.mock.patch.object(self.model[0], "move_down") as mock_move_down: self.row1._move_down.emit("clicked") mock_move_down.assert_called() class TestSortButton(unittest.TestCase): """Test the Sort button.""" def setUp(self): """Set up common variables.""" self.sort = emmental.tracklist.buttons.SortButton() def test_init(self): """Test that the Sort button is configured correctly.""" self.assertIsInstance(self.sort, emmental.buttons.PopoverButton) self.assertEqual(self.sort.get_icon_name(), "list-compact-symbolic") self.assertEqual(self.sort.get_tooltip_text(), "configure playlist sort order") self.assertFalse(self.sort.get_has_frame()) def test_popover_child(self): """Test that the popover_child is configured correctly.""" self.assertIsInstance(self.sort.popover_child, Gtk.ListBox) self.assertEqual(self.sort.popover_child.props.selection_mode, Gtk.SelectionMode.NONE) self.assertTrue(self.sort.popover_child.has_css_class("boxed-list")) def test_create_func(self): """Test that the Gtk.ListBox creates SortRows correctly.""" row = self.sort.popover_child.get_row_at_index(0) self.assertIsInstance(row, emmental.tracklist.buttons.SortRow) self.assertEqual(row.sort_field, self.sort.model[0]) def test_activate(self): """Test activating a Gtk.ListBox sort row.""" row = self.sort.popover_child.get_row_at_index(0) field = row.sort_field self.assertFalse(field.enabled) self.assertFalse(field.reversed) with unittest.mock.patch.object(field, "enable") as mock_enable: self.sort.popover_child.emit("row-activated", row) mock_enable.assert_called() mock_enable.reset_mock() row.active = True with unittest.mock.patch.object(field, "reverse") as mock_reverse: self.sort.popover_child.emit("row-activated", row) self.assertTrue(row._reverse.active) mock_enable.assert_not_called() mock_reverse.assert_called() def test_sort_order(self): """Test the sort-order property.""" self.assertEqual(self.sort.sort_order, "") self.sort.model[0].enable() self.assertEqual(self.sort.sort_order, self.sort.model.sort_order) self.sort.set_sort_order("artist") self.assertEqual(self.sort.model.sort_order, "artist")