# Copyright 2022 (c) Anna Schumaker. """Tests our Tracklist card.""" import unittest.mock import emmental.tracklist import tests.util from gi.repository import GLib from gi.repository import Gtk class TestTracklist(tests.util.TestCase): """Tests the Tracklist card.""" def setUp(self): """Set up common variables.""" super().setUp() self.sql.playlists.load(now=True) self.tracklist = emmental.tracklist.Card(self.sql) self.db_plist = self.sql.playlists.create("Test Playlist") self.playlist = emmental.playlist.playlist.Playlist(self.sql, self.db_plist) def test_init(self): """Test that the Tracklist has been set up correctly.""" self.assertIsInstance(self.tracklist, Gtk.Box) self.assertIsInstance(self.tracklist._top_box, Gtk.CenterBox) self.assertIsInstance(self.tracklist._top_left, Gtk.Box) self.assertIsInstance(self.tracklist._top_right, Gtk.Box) self.assertEqual(self.tracklist.sql, self.sql) self.assertEqual(self.tracklist.get_orientation(), Gtk.Orientation.VERTICAL) self.assertEqual(self.tracklist._top_box.get_margin_start(), 6) self.assertEqual(self.tracklist._top_box.get_margin_end(), 6) self.assertEqual(self.tracklist._top_box.get_orientation(), Gtk.Orientation.HORIZONTAL) self.assertEqual(self.tracklist.get_first_child(), self.tracklist._top_box) self.assertEqual(self.tracklist._top_box.get_start_widget(), self.tracklist._top_left) self.assertEqual(self.tracklist._top_box.get_end_widget(), self.tracklist._top_right) self.assertTrue(self.tracklist._top_box.has_css_class("toolbar")) self.assertTrue(self.tracklist.has_css_class("card")) def test_visible_columns(self): """Test the visible columns button.""" self.assertIsInstance(self.tracklist._visible_cols, emmental.tracklist.buttons.VisibleColumns) self.assertEqual(self.tracklist._visible_cols.columns, self.tracklist._trackview.columns) self.assertEqual(self.tracklist._top_left.get_first_child(), self.tracklist._visible_cols) def test_unselect(self): """Test the unselect button.""" self.assertIsInstance(self.tracklist._unselect, Gtk.Button) self.assertEqual(self.tracklist._unselect.get_icon_name(), "edit-select-none-symbolic") self.assertEqual(self.tracklist._unselect.get_tooltip_text(), "unselect all tracks") self.assertFalse(self.tracklist._unselect.get_has_frame()) self.assertFalse(self.tracklist._unselect.get_sensitive()) self.tracklist._trackview.have_selected = True self.assertTrue(self.tracklist._unselect.get_sensitive()) with unittest.mock.patch.object(self.tracklist._osd.selection, "unselect_all") as mock_clear: self.tracklist._unselect.emit("clicked") mock_clear.assert_called() self.assertEqual(self.tracklist._visible_cols.get_next_sibling(), self.tracklist._unselect) def test_filter(self): """Test the Tracklist Filter entry.""" self.assertIsInstance(self.tracklist._filter, emmental.entry.Filter) self.assertEqual(self.tracklist._top_box.get_center_widget(), self.tracklist._filter) self.assertEqual(self.tracklist._filter.get_margin_start(), 100) self.assertEqual(self.tracklist._filter.get_margin_end(), 100) self.assertEqual(self.tracklist._filter.get_placeholder_text(), "type to filter tracks") self.assertTrue(self.tracklist._filter.get_hexpand()) with unittest.mock.patch.object(self.sql.tracks, "filter") as mock_filter: self.tracklist._filter.set_text("test text") self.tracklist._filter.emit("search-changed") mock_filter.assert_called_with("*test text*") def test_loop_button(self): """Test the loop button.""" self.assertIsInstance(self.tracklist._loop, emmental.tracklist.buttons.LoopButton) self.assertEqual(self.tracklist._top_right.get_first_child(), self.tracklist._loop) self.tracklist._loop.can_disable = False self.playlist.loop = "Track" self.tracklist.playlist = self.playlist self.assertTrue(self.tracklist._loop.can_disable) self.assertEqual(self.tracklist._loop.state, "Track") self.playlist.playlist = self.sql.playlists.collection self.assertFalse(self.tracklist._loop.can_disable) self.assertEqual(self.tracklist._loop.state, "Playlist") self.playlist.loop = "Track" self.assertEqual(self.tracklist._loop.state, "Track") self.tracklist._loop.state = "Playlist" self.assertEqual(self.playlist.loop, "Playlist") def test_shuffle_button(self): """Test the shuffle button.""" self.assertIsInstance(self.tracklist._shuffle, emmental.tracklist.buttons.ShuffleButton) self.assertEqual(self.tracklist._loop.get_next_sibling(), self.tracklist._shuffle) self.playlist.shuffle = True self.tracklist.playlist = self.playlist self.assertTrue(self.tracklist._shuffle.active) self.playlist.playlist = self.sql.playlists.collection self.assertFalse(self.tracklist._shuffle.active) self.playlist.shuffle = True self.assertTrue(self.tracklist._shuffle.active) self.tracklist._shuffle.active = False self.assertFalse(self.playlist.shuffle) def test_sort_button(self): """Test the sort button.""" self.assertIsInstance(self.tracklist._sort, emmental.tracklist.buttons.SortButton) self.assertEqual(self.tracklist._shuffle.get_next_sibling(), self.tracklist._sort) self.tracklist.playlist = self.playlist self.assertEqual(self.tracklist._sort.sort_order, self.playlist.sort_order) self.playlist.playlist = self.sql.playlists.collection self.assertEqual(self.tracklist._sort.sort_order, self.sql.playlists.collection.sort_order) self.playlist.sort_order = "album" self.assertEqual(self.tracklist._sort.sort_order, "album") self.tracklist._sort.sort_order = "artist" self.assertEqual(self.playlist.sort_order, "artist") def test_trackview(self): """Test the Trackview widget.""" self.assertIsInstance(self.tracklist._trackview, emmental.tracklist.trackview.TrackView) self.assertEqual(self.tracklist.columns, self.tracklist._trackview.columns) sep = self.tracklist._top_box.get_next_sibling() self.assertIsInstance(sep, Gtk.Separator) self.assertEqual(sep.get_orientation(), Gtk.Orientation.HORIZONTAL) self.assertEqual(sep.get_next_sibling(), self.tracklist._osd) self.assertEqual(self.tracklist._osd.get_child(), self.tracklist._trackview) def test_osd(self): """Test the OSD widget.""" self.assertIsInstance(self.tracklist._osd, emmental.tracklist.selection.OSD) self.assertEqual(self.tracklist._osd.sql, self.sql) self.assertEqual(self.tracklist._osd.selection, self.tracklist._trackview.selection_model) self.assertFalse(self.tracklist._trackview.have_selected) self.tracklist._osd.have_selected = True self.assertTrue(self.tracklist._trackview.have_selected) self.assertEqual(self.tracklist._trackview.n_selected, 0) self.tracklist._osd.n_selected = 4 self.assertEqual(self.tracklist._trackview.n_selected, 4) def test_footer(self): """Test that the footer is wired up properly.""" self.assertIsInstance(self.tracklist._footer, emmental.tracklist.footer.Footer) self.assertEqual(self.tracklist._footer.get_margin_start(), 6) self.assertEqual(self.tracklist._footer.get_margin_end(), 6) self.assertEqual(self.tracklist._footer.get_margin_top(), 6) self.assertEqual(self.tracklist._footer.get_margin_bottom(), 6) sep = self.tracklist._osd.get_next_sibling() self.assertIsInstance(sep, Gtk.Separator) self.assertEqual(sep.get_orientation(), Gtk.Orientation.HORIZONTAL) self.assertEqual(sep.get_next_sibling(), self.tracklist._footer) self.tracklist._trackview.n_tracks = 5 self.tracklist._trackview.n_selected = 3 self.tracklist._trackview.runtime = 12345 self.assertEqual(self.tracklist._footer.count, 5) self.assertEqual(self.tracklist._footer.selected, 3) self.assertEqual(self.tracklist._footer.runtime, 12345) def test_playlist(self): """Test the playlist property.""" self.assertIsNone(self.tracklist.playlist) self.assertFalse(self.tracklist._top_right.get_sensitive()) with unittest.mock.patch.object(self.tracklist._osd, "reset") as mock_reset_osd: self.tracklist.playlist = self.playlist self.assertEqual(self.tracklist.playlist, self.playlist) self.assertEqual(self.tracklist._trackview.playlist, self.playlist) self.assertEqual(self.tracklist._osd.playlist, self.playlist) self.assertTrue(self.tracklist._top_right.get_sensitive()) mock_reset_osd.assert_called() mock_reset_osd.reset_mock() db_prev = self.sql.playlists.previous previous = emmental.playlist.previous.Previous(self.sql, db_prev) self.tracklist.playlist = previous self.assertFalse(self.tracklist._top_right.get_sensitive()) mock_reset_osd.assert_called() self.tracklist.playlist.playlist = None self.tracklist.playlist = None @unittest.mock.patch("gi.repository.GLib.idle_add") def test_scroll_to_track(self, mock_idle_add: unittest.mock.Mock): """Test the scroll_to_track() function.""" self.tracklist.scroll_to_track(None) mock_idle_add.assert_not_called() self.tracklist.playlist = self.playlist self.tracklist.scroll_to_track(None) mock_idle_add.assert_called_with(self.tracklist._Card__scroll_idle, None) with unittest.mock.patch.object(self.tracklist._trackview, "scroll_to_track") as mock_scroll: self.assertEqual(self.tracklist._Card__scroll_idle(None), GLib.SOURCE_REMOVE) mock_scroll.assert_called_with(None) def test_accelerators(self): """Check that the accelerators list is set up properly.""" entries = [("focus-search-track", self.tracklist._filter.grab_focus, ["slash"], None, None), ("clear-selected-tracks", self.tracklist._unselect.activate, ["Escape"], self.tracklist._unselect, "sensitive"), ("cycle-loop", self.tracklist._loop.activate, ["l"], self.tracklist._top_right, "sensitive"), ("toggle-shuffle", self.tracklist._shuffle.activate, ["s"], self.tracklist._top_right, "sensitive")] accels = self.tracklist.accelerators self.assertIsInstance(accels, list) for i, (name, func, accel, gobject, prop) in enumerate(entries): with self.subTest(action=name): self.assertIsInstance(accels[i], emmental.action.ActionEntry) self.assertEqual(accels[i].name, name) self.assertEqual(accels[i].func, func) self.assertListEqual(accels[i].accels, accel) if gobject and prop: enabled = gobject.get_property(prop) self.assertEqual(accels[i].enabled, enabled) gobject.set_property(prop, not enabled) self.assertEqual(accels[i].enabled, not enabled) start = len(entries) osd_accels = self.tracklist._osd.accelerators for i, accel in enumerate(osd_accels): with self.subTest(name=accel.name): self.assertIsInstance(accels[start + i], emmental.action.ActionEntry) self.assertEqual(accels[start + i].name, accel.name) self.assertEqual(accels[start + i].func, accel.func) self.assertListEqual(accels[start + i].accels, accel.accels)