# Copyright 2022 (c) Anna Schumaker. """Test as much as we can of the Emmental Application.""" import io import unittest import unittest.mock import gi import emmental class TestEmmental(unittest.TestCase): """Emmental Application test case.""" def setUp(self): """Set up common variables.""" self.application = emmental.Application() def tearDown(self): """Clean up.""" self.application.do_shutdown() def test_version(self): """Check that version constants have been set properly.""" self.assertEqual(emmental.MAJOR_VERSION, 3) self.assertEqual(emmental.MINOR_VERSION, 1) self.assertEqual(emmental.MICRO_VERSION, 0) self.assertEqual(emmental.VERSION_NUMBER, "3.1.0") self.assertEqual(emmental.VERSION_STRING, "Emmental 3.1.0-debug") def test_application(self): """Check that the application instance is initialized properly.""" self.assertIsInstance(self.application, gi.repository.Adw.Application) self.assertEqual(self.application.get_application_id(), "com.nowheycreamery.emmental-debug") self.assertEqual(self.application.get_property("resource-base-path"), "/com/nowheycreamery/emmental") @unittest.mock.patch("musicbrainzngs.set_useragent") @unittest.mock.patch("sys.stdout") @unittest.mock.patch("gi.repository.Adw.Application.add_window") @unittest.mock.patch("emmental.db.Connection.load") @unittest.mock.patch("gi.repository.Adw.Application.do_startup") def test_startup(self, mock_startup: unittest.mock.Mock, mock_load: unittest.mock.Mock, mock_add_window: unittest.mock.Mock, mock_stdout: unittest.mock.Mock, mock_set_useragent: unittest.mock.Mock): """Test that the startup signal works as expected.""" self.assertIsNone(self.application.db) self.assertIsNone(self.application.mpris) self.assertIsNone(self.application.factory) self.assertIsNone(self.application.player) self.assertIsNone(self.application.win) self.application.emit("startup") self.assertIsInstance(self.application.db, emmental.db.Connection) self.assertIsInstance(self.application.mpris, emmental.mpris2.Connection) self.assertIsInstance(self.application.player, emmental.audio.Player) self.assertIsInstance(self.application.factory, emmental.playlist.Factory) self.assertIsInstance(self.application.win, emmental.window.Window) mock_startup.assert_called() mock_load.assert_called() mock_add_window.assert_called_with(self.application.win) mock_set_useragent.assert_called_with("emmental-debug", "3.1.0") @unittest.mock.patch("sys.stdout") @unittest.mock.patch("gi.repository.Adw.Application.add_window") @unittest.mock.patch("gi.repository.Adw.Application.do_startup") def test_activate(self, mock_startup: unittest.mock.Mock, mock_add_window: unittest.mock.Mock, mock_stdout: unittest.mock.Mock): """Test activating the application.""" self.application.emit("startup") with unittest.mock.patch.object(self.application.win, "present") as mock_present: self.application.emit("activate") mock_present.assert_called() @unittest.mock.patch("gi.repository.Adw.Window.close") def test_shutdown(self, mock_close: unittest.mock.Mock): """Test that the shutdown signal works as expected.""" db = self.application.db = emmental.db.Connection() mpris = self.application.mpris = emmental.mpris2.Connection() self.application.win = emmental.window.Window("Test 1.2.3") player = self.application.player = emmental.audio.Player() self.application.emit("shutdown") self.assertIsNone(self.application.db) self.assertIsNone(self.application.mpris) self.assertIsNone(self.application.player) self.assertIsNone(self.application.win) self.assertIsNone(mpris.dbus) self.assertFalse(db.connected) self.assertEqual(player.get_state(), gi.repository.Gst.State.NULL) mock_close.assert_called() @unittest.mock.patch("sys.stdout", new_callable=io.StringIO) def test_window_widgets(self, mock_stdout: io.StringIO): """Check that the window widgets are added properly.""" self.application.db = emmental.db.Connection() self.application.factory = emmental.playlist.Factory( self.application.db) self.application.player = emmental.audio.Player() win = self.application.build_window() self.assertIsInstance(win, emmental.window.Window) self.assertIsInstance(win.header, emmental.header.Header) self.assertIsInstance(win.now_playing, emmental.nowplaying.Card) self.assertIsInstance(win.sidebar, emmental.sidebar.Card) self.assertIsInstance(win.tracklist, emmental.tracklist.Card) self.assertEqual(win.header.title, emmental.VERSION_STRING) self.assertEqual(self.application.get_accels_for_action( "app.reset-focus"), ["Escape"]) @unittest.mock.patch("sys.stdout", new_callable=io.StringIO) def test_header_accels(self, mock_stdout: io.StringIO): """Check that accelerators have been added for header actions.""" self.application.db = emmental.db.Connection() self.application.factory = emmental.playlist.Factory( self.application.db) self.application.player = emmental.audio.Player() self.application.build_window() for action, accel in [("app.open-file", "o"), ("app.decrease-volume", "Down"), ("app.increase-volume", "Up"), ("app.toggle-bg-mode", "b"), ("app.toggle-sidebar", "bracketright"), ("app.edit-settings", "s")]: self.assertEqual(self.application.get_accels_for_action(action), [accel]) @unittest.mock.patch("emmental.audio.Player.pause") @unittest.mock.patch("emmental.audio.Player.play") @unittest.mock.patch("sys.stdout", new_callable=io.StringIO) def test_nowplaying(self, mock_stdout: io.StringIO, play_func: unittest.mock.Mock, pause_func: unittest.mock.Mock): """Check that the nowplaying widget is wired up properly.""" self.application.db = emmental.db.Connection() self.application.factory = emmental.playlist.Factory( self.application.db) self.application.player = emmental.audio.Player() win = self.application.build_window() for action, accel in [("app.toggle-favorite", ["f"]), ("app.goto-current-track", ["g"]), ("app.next-track", ["Return"]), ("app.previous-track", ["BackSpace"]), ("app.play-pause", ["space"]), ("app.inc-autopause", ["plus", "KP_Add"]), ("app.dec-autopause", ["minus", "KP_Subtract"])]: with self.subTest(action=action): accels = self.application.get_accels_for_action(action) self.assertListEqual(accels, accel) for (property, value) in [("have-track", True), ("playing", True), ("duration", 10), ("position", 5), ("artwork", "/a/b/c.jpg")]: with self.subTest(property=property, value=value): self.application.player.set_property(property, value) self.assertEqual(win.now_playing.get_property(property), value) self.application.db.tracks.have_current_track = True self.assertTrue(win.now_playing.have_db_track) self.application.factory.can_go_next = True self.assertTrue(win.now_playing.have_next) self.application.factory.can_go_previous = True self.assertTrue(win.now_playing.have_previous) win.user_editing = True self.assertTrue(win.now_playing.editing) win.now_playing.emit("play") play_func.assert_called() win.now_playing.emit("pause") pause_func.assert_called() for tag in ["title", "album", "artist", "album-artist"]: with self.subTest(tag=tag): self.assertEqual(win.now_playing.get_property(tag), "") self.application.player.set_property(tag, "Test Tag") self.assertEqual(win.now_playing.get_property(tag), "Test Tag") self.assertEqual(self.application.autopause, -1) win.now_playing.autopause = 1 self.assertEqual(self.application.autopause, 1) self.application.autopause = 2 self.assertEqual(win.now_playing.autopause, 2) @unittest.mock.patch("sys.stdout", new_callable=io.StringIO) def test_sidebar(self, mock_stdout: io.StringIO): """Check that the sidebar widget is wired up properly.""" self.application.db = emmental.db.Connection() self.application.factory = emmental.playlist.Factory( self.application.db) self.application.player = emmental.audio.Player() win = self.application.build_window() for action, accel in [("app.focus-search-playlist", "question"), ("app.goto-active-playlist", "g"), ("app.goto-playlists", "p"), ("app.goto-artists", "a"), ("app.goto-genres", "g"), ("app.goto-decades", "d"), ("app.goto-libraries", "l")]: self.assertEqual(self.application.get_accels_for_action(action), [accel]) self.assertEqual(win.sidebar.sql, self.application.db) @unittest.mock.patch("sys.stdout", new_callable=io.StringIO) def test_tracklist(self, new_callable: io.StringIO): """Check that the tracklist widget is wired up properly.""" self.application.db = emmental.db.Connection() self.application.factory = emmental.playlist.Factory( self.application.db) self.application.player = emmental.audio.Player() win = self.application.build_window() for action, accel in [("app.focus-search-track", "slash"), ("app.clear-selected-tracks", "Escape"), ("app.cycle-loop", "l"), ("app.toggle-shuffle", "s"), ("app.remove-selected-tracks", "Delete"), ("app.move-track-up", "Up"), ("app.move-track-down", "Down")]: self.assertEqual(self.application.get_accels_for_action(action), [accel]) self.assertEqual(win.tracklist.sql, self.application.db) playlist = self.application.db.playlists.create("Test Playlist") self.application.factory.db_visible = playlist self.assertEqual(win.tracklist.playlist, self.application.factory.visible_playlist) @unittest.mock.patch("sys.stdout", new_callable=io.StringIO) def test_playlist_factory(self, mock_stdout: io.StringIO): """Test that the Playlist Factory is wired up properly.""" self.application.db = emmental.db.Connection() self.application.player = emmental.audio.Player() self.application.factory = emmental.playlist.Factory( self.application.db) self.application.win = self.application.build_window() self.application.connect_playlist_factory() self.application.db.playlists.load(now=True) playlist = self.application.db.playlists.create("Test Playlist") self.application.win.sidebar.selected_playlist = playlist self.assertEqual(self.application.factory.db_visible, playlist) self.assertEqual(self.application.factory.db_previous, self.application.db.playlists.previous) @unittest.mock.patch("sys.stdout", new_callable=io.StringIO) def test_replaygain(self, mock_stdout: io.StringIO): """Test setting replaygain modes.""" self.application.db = emmental.db.Connection() self.application.factory = emmental.playlist.Factory( self.application.db) self.application.player = emmental.audio.Player() win = self.application.build_window() player = self.application.player win.header.rg_enabled = True self.assertEqual(player.get_replaygain(), (True, "track")) win.header.rg_mode = "album" self.assertEqual(player.get_replaygain(), (True, "album")) @unittest.mock.patch("sys.stdout", new_callable=io.StringIO) def test_background_mode(self, mock_stdout: io.StringIO): """Test setting background mode.""" self.application.db = emmental.db.Connection() self.application.factory = emmental.playlist.Factory( self.application.db) self.application.player = emmental.audio.Player() win = self.application.build_window() player = self.application.player win.header.bg_enabled = True win.header.bg_volume = 0.5 self.assertTrue(player.bg_enabled) self.assertEqual(player.bg_volume, 0.5) @unittest.mock.patch("sys.stdout", new_callable=io.StringIO) def test_show_sidebar(self, mock_stdout: io.StringIO): """Test showing the sidebar.""" self.application.db = emmental.db.Connection() self.application.factory = emmental.playlist.Factory( self.application.db) self.application.player = emmental.audio.Player() win = self.application.build_window() win.show_sidebar = True self.assertTrue(win.header.show_sidebar) win.header.show_sidebar = False self.assertFalse(win.show_sidebar)