# Copyright 2022 (c) Anna Schumaker. """Tests our sidebar row widgets.""" import unittest import tests.util import emmental.sidebar.icon import emmental.sidebar.row from gi.repository import Gio from gi.repository import Gtk from gi.repository import Adw class TestBaseRow(unittest.TestCase): """Test our BaseRow class.""" def setUp(self): """Set up common variables.""" self.row = emmental.sidebar.row.BaseRow() def test_init(self): """Test that the BaseRow is configured correctly.""" self.assertIsInstance(self.row, Gtk.Box) self.assertEqual(self.row.get_orientation(), Gtk.Orientation.HORIZONTAL) def test_name(self): """Test the name property.""" self.assertEqual(self.row.name, "") row2 = emmental.sidebar.row.BaseRow(name="Test Playlist") self.assertEqual(row2.name, "Test Playlist") def test_count(self): """Test the count property.""" self.assertEqual(self.row.count, 0) row2 = emmental.sidebar.row.BaseRow(count=42) self.assertEqual(row2.count, 42) def test_playlist(self): """Test the playlist property.""" plist = emmental.db.playlist.Playlist(Gio.ListStore(), 0, "Playlist Name") self.assertIsNone(self.row.playlist) row2 = emmental.sidebar.row.BaseRow(playlist=plist) self.assertEqual(row2.playlist, plist) class TestRow(unittest.TestCase): """Test a playlist Row.""" def setUp(self): """Set up common variables.""" self.row = emmental.sidebar.row.Row() def test_init(self): """Test that the Row is configured correctly.""" self.assertIsInstance(self.row, emmental.sidebar.row.BaseRow) self.assertEqual(self.row.get_spacing(), 12) def test_image(self): """Test the image property and icon widget.""" self.assertIsInstance(self.row._icon, emmental.sidebar.icon.Icon) self.assertEqual(self.row.get_first_child(), self.row._icon) self.assertIsNone(self.row.image) self.assertIsNone(self.row._icon.filepath) self.assertTrue(self.row._icon.show_initials) self.row.image = tests.util.COVER_JPG self.assertEqual(self.row._icon.filepath, tests.util.COVER_JPG) def test_name(self): """Test the name property and title widgets.""" self.assertIsInstance(self.row._title, emmental.sidebar.title.PlaylistTitle) self.assertEqual(self.row._icon.get_next_sibling(), self.row._title) self.row.name = "Test Playlist" self.assertEqual(self.row._title.title, "Test Playlist") self.assertEqual(self.row._icon.text, "Test Playlist") def test_count(self): """Test the count property.""" self.assertEqual(self.row.count, 0) self.assertEqual(self.row._title.count, 0) self.row.count = 1 self.assertEqual(self.row._title.count, 1) def test_year(self): """Test setting a year as the icon text.""" self.assertIsNone(self.row.year) self.row.year = 1985 self.assertEqual(self.row._icon.text, "8 5") self.row.year = 1988 self.assertEqual(self.row._icon.text, "8 8") self.row.year = 2000 self.assertEqual(self.row._icon.text, "0 0") class TestPlaylistRow(unittest.TestCase): """Test our playlist row with extra buttons.""" def setUp(self): """Set up common variables.""" self.row = emmental.sidebar.row.PlaylistRow() self.playlist = emmental.db.playlists.Playlist(table=Gio.ListStore(), propertyid=12345, playlistid=67890, name="Test Playlist") def test_init(self): """Test that the playlist row is configured properly.""" self.assertIsInstance(self.row, emmental.sidebar.row.BaseRow) def test_icon(self): """Test the settable icon widget and properties.""" self.assertIsInstance(self.row._icon, emmental.sidebar.icon.Settable) self.assertEqual(self.row.get_first_child(), self.row._icon) self.row.name = "Test Playlist" self.row.icon_name = "image-missing" self.row.filepath = tests.util.COVER_JPG self.assertEqual(self.row._icon.text, "Test Playlist") self.assertEqual(self.row._icon.icon_name, "image-missing") self.assertEqual(self.row._icon.filepath, tests.util.COVER_JPG) self.row._icon.filepath = None self.assertIsNone(self.row.filepath) def test_title(self): """Test the editable title widget and properties.""" self.assertIsInstance(self.row._title, emmental.sidebar.title.EditableTitle) self.assertEqual(self.row._icon.get_next_sibling(), self.row._title) self.assertEqual(self.row._title.get_margin_start(), 12) self.assertEqual(self.row._title.get_margin_end(), 12) self.row.name = "Test Playlist" self.row.count = 42 self.assertEqual(self.row._title.title, "Test Playlist") self.assertEqual(self.row._title.count, 42) def test_delete(self): """Test the delete button.""" self.assertIsInstance(self.row._delete, Gtk.Button) self.assertEqual(self.row._title.get_next_sibling(), self.row._delete) self.assertEqual(self.row._delete.get_icon_name(), "big-x-symbolic") self.assertEqual(self.row._delete.get_tooltip_text(), "delete playlist") self.assertEqual(self.row._delete.get_valign(), Gtk.Align.CENTER) self.assertFalse(self.row._delete.get_has_frame()) self.assertTrue(self.row._delete.has_css_class("emmental-delete")) self.row._delete.emit("clicked") self.playlist.delete = unittest.mock.Mock() self.row.playlist = self.playlist self.row._delete.emit("clicked") self.playlist.delete.assert_called() def test_modifiable(self): """Test the modifiable property.""" self.assertFalse(self.row.modifiable) self.assertFalse(self.row._icon.settable) self.assertFalse(self.row._title.editable) self.assertFalse(self.row._delete.get_visible()) self.row.modifiable = True self.assertTrue(self.row._icon.settable) self.assertTrue(self.row._title.editable) self.assertTrue(self.row._delete.get_visible()) def test_rename(self): """Test responding to the request-rename signal.""" self.row._title.emit("request-rename", "No Error Expected") self.playlist.rename = unittest.mock.Mock() self.row.playlist = self.playlist self.row._title.emit("request-rename", "New Name") self.playlist.rename.assert_called_with("New Name") class TestLibraryRow(unittest.TestCase): """Tests our library row with extra widgets.""" def setUp(self): """Set up common variables.""" super().setUp() self.row = emmental.sidebar.row.LibraryRow() self.playlist = emmental.db.playlist.Playlist(Gio.ListStore(), propertyid=12345, name="Test Playlist") def test_init(self): """Test that the library row is configured properly.""" self.assertIsInstance(self.row, emmental.sidebar.row.BaseRow) self.assertIsInstance(self.row._box, Gtk.Box) self.assertIsInstance(self.row._overlay, Gtk.Overlay) self.assertEqual(self.row.get_first_child(), self.row._overlay) self.assertEqual(self.row._overlay.get_child(), self.row._box) def test_switch(self): """Test the switch widget and enabled property.""" self.assertIsInstance(self.row._switch, Gtk.Switch) self.assertEqual(self.row._switch.get_valign(), Gtk.Align.CENTER) self.assertEqual(self.row._box.get_first_child(), self.row._switch) self.assertTrue(self.row.enabled) self.assertTrue(self.row._switch.get_active()) self.assertTrue(self.row._title.get_sensitive()) self.assertEqual(self.row._switch.get_tooltip_text(), "disable library path") self.row.enabled = False self.assertFalse(self.row._switch.get_active()) self.assertFalse(self.row._title.get_sensitive()) self.assertEqual(self.row._switch.get_tooltip_text(), "enable library path") self.row._switch.set_active(True) self.assertTrue(self.row.enabled) self.assertTrue(self.row._title.get_sensitive()) self.assertEqual(self.row._switch.get_tooltip_text(), "disable library path") def test_progress(self): """Test the progress bar widget and property.""" self.assertIsInstance(self.row._progress, Gtk.ProgressBar) self.assertEqual(self.row._progress.get_valign(), Gtk.Align.END) self.assertTrue(self.row._progress.has_css_class("osd")) self.assertIn(self.row._progress, self.row._overlay) self.assertEqual(self.row.progress, 0.0) self.row.progress = 0.42 self.assertEqual(self.row._progress.get_fraction(), 0.42) def test_title(self): """Test the title widget and properties.""" self.assertIsInstance(self.row._title, emmental.sidebar.title.PlaylistTitle) self.assertEqual(self.row._title.get_margin_start(), 12) self.assertEqual(self.row._title.get_margin_end(), 12) self.assertEqual(self.row._switch.get_next_sibling(), self.row._title) self.row.name = "/a/b/c" self.row.count = 42 self.assertEqual(self.row._title.title, "/a/b/c") self.assertEqual(self.row._title.count, 42) def test_scan(self): """Test the scan button.""" self.assertIsInstance(self.row._scan, Gtk.Button) self.assertEqual(self.row._scan.get_icon_name(), "update") self.assertEqual(self.row._scan.get_tooltip_text(), "update library path") self.assertEqual(self.row._scan.get_valign(), Gtk.Align.CENTER) self.assertFalse(self.row._scan.get_has_frame()) self.assertEqual(self.row._title.get_next_sibling(), self.row._scan) self.row._scan.emit("clicked") self.playlist.scan = unittest.mock.Mock() self.row.playlist = self.playlist self.row._scan.emit("clicked") self.playlist.scan.assert_called() def test_stop(self): """Test the stop button.""" self.assertIsInstance(self.row._stop, Gtk.Button) self.assertEqual(self.row._stop.get_icon_name(), "stop-sign-large") self.assertEqual(self.row._stop.get_tooltip_text(), "cancel update") self.assertEqual(self.row._stop.get_valign(), Gtk.Align.CENTER) self.assertFalse(self.row._stop.get_has_frame()) self.assertTrue(self.row._stop.has_css_class("emmental-stop")) self.assertEqual(self.row._scan.get_next_sibling(), self.row._stop) self.row._stop.emit("clicked") self.playlist.stop = unittest.mock.Mock() self.row.playlist = self.playlist self.row._stop.emit("clicked") self.playlist.stop.assert_called() def test_delete(self): """Test the delete button.""" self.assertIsInstance(self.row._delete, Gtk.Button) self.assertEqual(self.row._delete.get_icon_name(), "big-x-symbolic") self.assertEqual(self.row._delete.get_tooltip_text(), "delete library path") self.assertEqual(self.row._delete.get_valign(), Gtk.Align.CENTER) self.assertFalse(self.row._delete.get_has_frame()) self.assertTrue(self.row._delete.has_css_class("emmental-delete")) self.assertEqual(self.row._stop.get_next_sibling(), self.row._delete) self.row._delete.emit("clicked") self.playlist.delete = unittest.mock.Mock() self.row.playlist = self.playlist self.row._delete.emit("clicked") self.playlist.delete.assert_called() def test_online(self): """Test the online property.""" self.assertTrue(self.row.online) self.assertTrue(self.row._switch.get_sensitive()) self.assertTrue(self.row._title.get_sensitive()) self.row.online = False self.assertFalse(self.row._switch.get_sensitive()) self.assertFalse(self.row._title.get_sensitive()) def test_scaning(self): """Test the scanning property.""" self.assertFalse(self.row.scanning) self.assertFalse(self.row._progress.get_visible()) self.assertFalse(self.row._stop.get_visible()) self.assertTrue(self.row._scan.get_visible()) self.row.scanning = True self.assertTrue(self.row._progress.get_visible()) self.assertTrue(self.row._stop.get_visible()) self.assertFalse(self.row._scan.get_visible()) class TestTreeRow(unittest.TestCase): """Test the TreeRow widget used by the section factories.""" def setUp(self): """Set up common variables.""" self.playlist = emmental.db.playlist.Playlist(Gio.ListStore(), 0, "Playlist Name") self.treeitem = Gtk.TreeListRow() self.treeitem.get_item = unittest.mock.Mock(return_value=self.playlist) self.listitem = Gtk.ListItem() self.listitem.get_item = unittest.mock.Mock(return_value=self.treeitem) self.treerow = emmental.sidebar.row.TreeRow(self.listitem) self.adw_bin = Adw.Bin(child=self.listitem.get_child()) def test_init(self): """Test that the TreeRow was set up properly.""" self.assertIsInstance(self.treerow, emmental.factory.TreeRow) self.assertIsNone(self.treerow.child) def test_bind(self): """Test binding a Playlist to the TreeRow.""" self.treerow.child = emmental.sidebar.row.BaseRow() self.playlist.table.update = unittest.mock.Mock(return_value=True) self.playlist.active = True self.playlist.n_tracks = 42 self.playlist.children = Gtk.FilterListModel.new(Gio.ListStore(), None) self.treerow.bind() self.assertEqual(self.treerow.child.playlist, self.playlist) self.assertEqual(self.treerow.child.name, "Playlist Name") self.assertEqual(self.treerow.child.count, 42) self.assertEqual(self.treerow.n_children, 0) self.assertTrue(self.treerow.active) self.playlist.children.get_model().append(Gtk.Label()) self.assertEqual(self.treerow.n_children, 1) self.treerow.unbind() self.assertIsNone(self.treerow.child.playlist)