2022-05-31 10:18:53 -04:00
|
|
|
# Copyright 2022 (c) Anna Schumaker.
|
|
|
|
"""Tests our application header."""
|
|
|
|
import emmental
|
|
|
|
import tests.util
|
2023-03-13 14:51:43 -04:00
|
|
|
import pathlib
|
2022-09-24 10:12:06 -04:00
|
|
|
import unittest.mock
|
2022-05-31 10:18:53 -04:00
|
|
|
from gi.repository import Gtk
|
|
|
|
from gi.repository import Adw
|
|
|
|
|
|
|
|
|
|
|
|
class TestHeader(tests.util.TestCase):
|
|
|
|
"""Test case for our custom Gtk.HeaderBar."""
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
"""Set up common variables."""
|
|
|
|
super().setUp()
|
|
|
|
self.header = emmental.header.Header(sql=self.sql, title="Test Title")
|
|
|
|
|
|
|
|
def test_constants(self):
|
|
|
|
"""Check that constants are set correctly."""
|
|
|
|
self.assertEqual(emmental.header.SUBTITLE, "The Cheesy Music Player")
|
|
|
|
|
|
|
|
def test_title(self):
|
|
|
|
"""Check that the title is set correctly."""
|
|
|
|
self.assertIsInstance(self.header, Gtk.HeaderBar)
|
|
|
|
self.assertIsInstance(self.header._title, Adw.WindowTitle)
|
|
|
|
|
|
|
|
self.assertEqual(self.header.get_title_widget(), self.header._title)
|
|
|
|
self.assertEqual(self.header.title, "Test Title")
|
|
|
|
self.assertEqual(self.header._title.get_title(), "Test Title")
|
|
|
|
|
|
|
|
self.assertEqual(self.header.subtitle, emmental.header.SUBTITLE)
|
|
|
|
self.assertEqual(self.header._title.get_subtitle(),
|
|
|
|
emmental.header.SUBTITLE)
|
2022-09-24 10:12:06 -04:00
|
|
|
|
2023-05-27 16:12:44 -04:00
|
|
|
self.assertEqual(self.header._title.get_tooltip_text(),
|
|
|
|
emmental.gsetup.env_string())
|
|
|
|
|
2023-10-24 11:04:09 -04:00
|
|
|
def test_show_sidebar(self):
|
|
|
|
"""Check that the show sidebar button works as expected."""
|
|
|
|
self.assertIsInstance(self.header._show_sidebar, Gtk.ToggleButton)
|
|
|
|
self.assertEqual(self.header._show_sidebar.props.icon_name,
|
|
|
|
"sidebar-show-symbolic")
|
|
|
|
self.assertFalse(self.header._show_sidebar.props.has_frame)
|
|
|
|
self.assertFalse(self.header._show_sidebar.props.active)
|
|
|
|
|
|
|
|
self.assertFalse(self.header.show_sidebar)
|
|
|
|
self.header.show_sidebar = True
|
|
|
|
self.assertTrue(self.header._show_sidebar.props.active)
|
|
|
|
|
|
|
|
self.header._show_sidebar.props.active = False
|
|
|
|
self.assertFalse(self.header.show_sidebar)
|
|
|
|
|
2023-03-13 14:51:43 -04:00
|
|
|
def test_open(self):
|
2024-01-24 20:38:41 -05:00
|
|
|
"""Check that the Open ActionRow works as expected."""
|
|
|
|
self.assertIsInstance(self.header._open, emmental.header.open.OpenRow)
|
|
|
|
self.assertEqual(self.header._menu_box.get_row_at_index(0),
|
|
|
|
self.header._open)
|
2023-03-13 14:51:43 -04:00
|
|
|
|
|
|
|
signal = unittest.mock.Mock()
|
|
|
|
self.header.connect("track-requested", signal)
|
|
|
|
self.header._open.emit("track-requested", pathlib.Path("/a/b/c/1.ogg"))
|
|
|
|
signal.assert_called_with(self.header, pathlib.Path("/a/b/c/1.ogg"))
|
|
|
|
|
2024-01-27 22:31:56 -05:00
|
|
|
def test_listenbrainz(self):
|
|
|
|
"""Check that the ListenBrainzRow is set up correctly."""
|
|
|
|
self.assertIsInstance(self.header._listenbrainz, Adw.PasswordEntryRow)
|
|
|
|
self.assertEqual(self.header._menu_box.get_row_at_index(1),
|
|
|
|
self.header._listenbrainz)
|
|
|
|
|
|
|
|
self.assertEqual(self.header.listenbrainz_token, "")
|
|
|
|
self.assertEqual(self.header._listenbrainz.props.text, "")
|
|
|
|
|
|
|
|
self.header.listenbrainz_token = "abcde"
|
|
|
|
self.assertEqual(self.header._listenbrainz.props.text, "abcde")
|
|
|
|
|
|
|
|
with unittest.mock.patch.object(self.header._menu_button,
|
|
|
|
"popdown") as mock_popdown:
|
|
|
|
self.header._listenbrainz.props.text = "fghij"
|
|
|
|
self.header._listenbrainz.emit("apply")
|
|
|
|
self.assertEqual(self.header.listenbrainz_token, "fghij")
|
|
|
|
mock_popdown.assert_called()
|
|
|
|
|
|
|
|
self.header._listenbrainz.props.text = "abcde"
|
|
|
|
self.header._menu_button.get_popover().emit("closed")
|
|
|
|
self.assertEqual(self.header._listenbrainz.props.text, "fghij")
|
|
|
|
|
|
|
|
def test_listenbrainz_token_valid(self):
|
|
|
|
"""Test the listenbrainz-token-valid property."""
|
|
|
|
win = Gtk.Window(titlebar=self.header)
|
|
|
|
win.post_toast = unittest.mock.Mock()
|
|
|
|
|
|
|
|
self.assertTrue(self.header.listenbrainz_token_valid)
|
|
|
|
|
|
|
|
self.header.listenbrainz_token_valid = False
|
|
|
|
self.assertTrue(self.header._menu_button.has_css_class("warning"))
|
|
|
|
self.assertTrue(self.header._listenbrainz.has_css_class("warning"))
|
|
|
|
self.assertFalse(self.header.listenbrainz_token_valid)
|
|
|
|
win.post_toast.assert_called_with(
|
|
|
|
"listenbrainz: user token is invalid")
|
|
|
|
|
|
|
|
win.post_toast.reset_mock()
|
|
|
|
self.header.listenbrainz_token_valid = True
|
|
|
|
self.assertFalse(self.header._menu_button.has_css_class("warning"))
|
|
|
|
self.assertFalse(self.header._listenbrainz.has_css_class("warning"))
|
|
|
|
self.assertTrue(self.header.listenbrainz_token_valid)
|
|
|
|
win.post_toast.assert_not_called()
|
|
|
|
|
2022-09-24 10:12:06 -04:00
|
|
|
def test_settings(self):
|
2024-01-26 09:25:00 -05:00
|
|
|
"""Check that the SettingsRow is set up correctly."""
|
|
|
|
self.assertIsInstance(self.header._settings,
|
|
|
|
emmental.header.settings.Row)
|
2024-01-27 22:31:56 -05:00
|
|
|
self.assertEqual(self.header._menu_box.get_row_at_index(2),
|
2024-01-26 09:25:00 -05:00
|
|
|
self.header._settings)
|
2022-05-31 10:18:53 -04:00
|
|
|
|
2024-01-24 10:13:11 -05:00
|
|
|
def test_menu_button(self):
|
|
|
|
"""Check that the menu popover button is set up properly."""
|
|
|
|
self.assertIsInstance(self.header._menu_button,
|
|
|
|
emmental.buttons.PopoverButton)
|
|
|
|
self.assertIsNotNone(self.header._menu_button.props.parent)
|
|
|
|
|
|
|
|
self.assertEqual(self.header._menu_button.props.icon_name,
|
|
|
|
"open-menu-symbolic")
|
|
|
|
self.assertEqual(self.header._menu_button.popover_child,
|
|
|
|
self.header._menu_box)
|
|
|
|
|
|
|
|
def test_menu_popover_child(self):
|
|
|
|
"""Check that the menu popover button child was set up correctly."""
|
|
|
|
self.assertIsInstance(self.header._menu_box, Gtk.ListBox)
|
|
|
|
self.assertEqual(self.header._menu_box.get_selection_mode(),
|
|
|
|
Gtk.SelectionMode.NONE)
|
|
|
|
self.assertTrue(self.header._menu_box.has_css_class("boxed-list"))
|
|
|
|
|
2024-01-24 20:38:41 -05:00
|
|
|
self.assertEqual(self.header._menu_box.get_row_at_index(0),
|
|
|
|
self.header._open)
|
|
|
|
|
2023-05-27 23:00:03 -04:00
|
|
|
def test_volume_icons(self):
|
|
|
|
"""Check that the volume icons box is set up properly."""
|
|
|
|
self.assertIsInstance(self.header._icons, Gtk.Box)
|
|
|
|
self.assertIsInstance(self.header._volume_icon, Gtk.Image)
|
|
|
|
self.assertIsInstance(self.header._background_icon, Gtk.Image)
|
|
|
|
|
|
|
|
self.assertEqual(self.header._icons.get_spacing(), 6)
|
|
|
|
|
|
|
|
self.assertEqual(self.header._icons.get_first_child(),
|
|
|
|
self.header._volume_icon)
|
|
|
|
self.assertEqual(self.header._volume_icon.get_next_sibling(),
|
|
|
|
self.header._background_icon)
|
|
|
|
|
2022-05-31 10:18:53 -04:00
|
|
|
def test_volume(self):
|
|
|
|
"""Check that volume widgets work as expected."""
|
|
|
|
self.assertIsInstance(self.header._volume,
|
2023-05-31 09:47:24 -04:00
|
|
|
emmental.header.volume.VolumeRow)
|
2022-05-31 10:18:53 -04:00
|
|
|
self.assertEqual(self.header.volume, 1.0)
|
|
|
|
|
|
|
|
for i, vol in [(x, x/10) for x in range(11)]:
|
|
|
|
with self.subTest(volume=vol):
|
|
|
|
widget = self.header if i % 2 else self.header._volume
|
|
|
|
match i:
|
|
|
|
case 0: icon = "muted"
|
|
|
|
case 1 | 2 | 3: icon = "low"
|
|
|
|
case 4 | 5 | 6: icon = "medium"
|
|
|
|
case _: icon = "high"
|
|
|
|
|
|
|
|
widget.volume = vol
|
|
|
|
self.assertEqual(self.header.volume, vol)
|
|
|
|
self.assertEqual(self.header._volume.volume, vol)
|
2023-05-27 23:00:03 -04:00
|
|
|
self.assertEqual(self.header._volume_icon.get_icon_name(),
|
2022-05-31 10:18:53 -04:00
|
|
|
f"audio-volume-{icon}-symbolic")
|
2024-01-24 09:06:00 -05:00
|
|
|
self.assertEqual(self.header._vol_button.get_tooltip_text(),
|
2023-05-27 23:00:03 -04:00
|
|
|
f"volume: {i*10}%\n"
|
|
|
|
"background listening: off\nnormalizing: off")
|
2022-05-31 10:18:53 -04:00
|
|
|
|
2023-05-31 16:30:00 -04:00
|
|
|
def test_background_listening(self):
|
|
|
|
"""Test the background listening mode."""
|
|
|
|
self.assertIsInstance(self.header._background,
|
|
|
|
emmental.header.volume.BackgroundRow)
|
2023-05-27 23:00:03 -04:00
|
|
|
self.assertEqual(self.header._background_icon.get_icon_name(),
|
|
|
|
"sound-wave")
|
2023-05-31 16:30:00 -04:00
|
|
|
|
|
|
|
self.assertFalse(self.header.bg_enabled)
|
2023-05-27 23:00:03 -04:00
|
|
|
self.assertEqual(self.header.bg_volume, 0.5)
|
|
|
|
|
2023-05-31 16:30:00 -04:00
|
|
|
self.header.bg_enabled = True
|
|
|
|
self.assertTrue(self.header._background.enabled)
|
2023-05-27 23:00:03 -04:00
|
|
|
self.assertEqual(self.header._background_icon.get_icon_name(),
|
|
|
|
"sound-wave-alt")
|
2024-01-24 09:06:00 -05:00
|
|
|
self.assertEqual(self.header._vol_button.get_tooltip_text(),
|
2023-05-27 23:00:03 -04:00
|
|
|
"volume: 100%\nbackground listening: 50%\n"
|
|
|
|
"normalizing: off")
|
2023-05-31 16:30:00 -04:00
|
|
|
|
|
|
|
self.header.bg_volume = 0.75
|
|
|
|
self.assertEqual(self.header._background.volume, 0.75)
|
2024-01-24 09:06:00 -05:00
|
|
|
self.assertEqual(self.header._vol_button.get_tooltip_text(),
|
2023-05-27 23:00:03 -04:00
|
|
|
"volume: 100%\nbackground listening: 75%\n"
|
|
|
|
"normalizing: off")
|
|
|
|
|
2023-05-31 16:30:00 -04:00
|
|
|
self.header._background.volume = 0.25
|
|
|
|
self.assertEqual(self.header.bg_volume, 0.25)
|
2024-01-24 09:06:00 -05:00
|
|
|
self.assertEqual(self.header._vol_button.get_tooltip_text(),
|
2023-05-27 23:00:03 -04:00
|
|
|
"volume: 100%\nbackground listening: 25%\n"
|
|
|
|
"normalizing: off")
|
|
|
|
|
|
|
|
self.header._background.enabled = False
|
|
|
|
self.assertFalse(self.header.bg_enabled)
|
|
|
|
self.assertEqual(self.header._background_icon.get_icon_name(),
|
|
|
|
"sound-wave")
|
2023-05-31 16:30:00 -04:00
|
|
|
|
2022-05-31 10:18:53 -04:00
|
|
|
def test_replaygain(self):
|
|
|
|
"""Test that we can configure ReplayGain as expected."""
|
|
|
|
self.assertIsInstance(self.header._replaygain,
|
2023-05-31 10:48:40 -04:00
|
|
|
emmental.header.replaygain.ReplayGainRow)
|
2022-05-31 10:18:53 -04:00
|
|
|
self.assertFalse(self.header.rg_enabled)
|
|
|
|
self.assertEqual(self.header.rg_mode, "auto")
|
|
|
|
|
|
|
|
self.header.rg_enabled = True
|
|
|
|
self.header.rg_mode = "track"
|
|
|
|
self.assertTrue(self.header._replaygain.enabled)
|
|
|
|
self.assertEqual(self.header._replaygain.mode, "track")
|
2024-01-24 09:06:00 -05:00
|
|
|
self.assertEqual(self.header._vol_button.get_tooltip_text(),
|
2023-05-27 23:00:03 -04:00
|
|
|
"volume: 100%\nbackground listening: off\n"
|
|
|
|
"normalizing: track mode")
|
2022-05-31 10:18:53 -04:00
|
|
|
|
|
|
|
self.header._replaygain.enabled = False
|
|
|
|
self.header._replaygain.mode = "album"
|
|
|
|
self.assertFalse(self.header.rg_enabled)
|
|
|
|
self.assertEqual(self.header.rg_mode, "album")
|
2024-01-24 09:06:00 -05:00
|
|
|
self.assertEqual(self.header._vol_button.get_tooltip_text(),
|
2023-05-27 23:00:03 -04:00
|
|
|
"volume: 100%\nbackground listening: off\n"
|
|
|
|
"normalizing: off")
|
2022-05-31 10:18:53 -04:00
|
|
|
|
2024-01-24 09:06:00 -05:00
|
|
|
def test_volume_popover_button(self):
|
|
|
|
"""Check that the volume popover button was set up correctly."""
|
|
|
|
self.assertIsInstance(self.header._vol_button,
|
2022-05-31 10:18:53 -04:00
|
|
|
emmental.buttons.PopoverButton)
|
2024-01-24 09:06:00 -05:00
|
|
|
self.assertEqual(self.header._vol_button.popover_child,
|
|
|
|
self.header._vol_box)
|
|
|
|
|
|
|
|
self.assertEqual(self.header._vol_button.get_child(),
|
|
|
|
self.header._icons)
|
|
|
|
self.assertEqual(self.header._vol_button.get_margin_end(), 6)
|
|
|
|
self.assertFalse(self.header._vol_button.get_has_frame())
|
|
|
|
|
|
|
|
def test_volume_popover_child(self):
|
|
|
|
"""Check that the volume popover button child was set up correctly."""
|
|
|
|
self.assertIsInstance(self.header._vol_box, Gtk.ListBox)
|
|
|
|
self.assertEqual(self.header._vol_box.get_selection_mode(),
|
2023-05-31 13:49:44 -04:00
|
|
|
Gtk.SelectionMode.NONE)
|
2024-01-24 09:06:00 -05:00
|
|
|
self.assertTrue(self.header._vol_box.has_css_class("boxed-list"))
|
2023-05-31 13:49:44 -04:00
|
|
|
|
2024-01-24 09:06:00 -05:00
|
|
|
self.assertEqual(self.header._vol_box.get_row_at_index(0),
|
2023-05-31 13:49:44 -04:00
|
|
|
self.header._volume)
|
2024-01-24 09:06:00 -05:00
|
|
|
self.assertEqual(self.header._vol_box.get_row_at_index(1),
|
2023-05-31 16:30:00 -04:00
|
|
|
self.header._background)
|
2024-01-24 09:06:00 -05:00
|
|
|
self.assertEqual(self.header._vol_box.get_row_at_index(2),
|
2023-05-31 13:49:44 -04:00
|
|
|
self.header._replaygain)
|
2023-06-04 10:29:28 -04:00
|
|
|
|
|
|
|
def test_accelerators(self):
|
|
|
|
"""Check that the accelerators list is set up properly."""
|
|
|
|
entries = [("open-file", self.header._open.activate, "<Control>o"),
|
|
|
|
("decrease-volume", self.header._volume.decrement,
|
2023-08-22 16:42:07 -04:00
|
|
|
"<Shift><Control>Down"),
|
2023-06-04 10:29:28 -04:00
|
|
|
("increase-volume", self.header._volume.increment,
|
2023-08-22 16:42:07 -04:00
|
|
|
"<Shift><Control>Up"),
|
2023-06-04 10:29:28 -04:00
|
|
|
("toggle-bg-mode", self.header._background.activate,
|
|
|
|
"<Shift><Control>b"),
|
2023-10-24 11:31:11 -04:00
|
|
|
("toggle-sidebar", self.header._show_sidebar.activate,
|
|
|
|
"<Control>bracketright"),
|
2023-06-04 10:29:28 -04:00
|
|
|
("edit-settings", self.header._settings.activate,
|
|
|
|
"<Shift><Control>s")]
|
|
|
|
|
|
|
|
accels = self.header.accelerators
|
|
|
|
self.assertIsInstance(accels, list)
|
|
|
|
|
|
|
|
for i, (name, func, accel) in enumerate(entries):
|
|
|
|
with self.subTest(name=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])
|
|
|
|
|
|
|
|
self.assertEqual(len(accels), i + 1)
|