426 lines
17 KiB
Python
426 lines
17 KiB
Python
# 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")
|