class TFIFOControl(TestCase): def setUp(self): config.init() self.p = NullPlayer() self.l = SongFileLibrary() self.w = gtk.Window() self.fifo = FIFOControl(self.l, self.w, self.p) def tearDown(self): self.p.destroy() self.l.destroy() self.w.destroy() config.quit() def __send(self, command): f = open(const.CONTROL, "wb") f.write(command) f.close() while gtk.events_pending(): gtk.main_iteration() def test_player(self): self.__send("previous") self.__send("force_previous") self.__send("next") self.__send("pause") self.__send("play-pause") self.__send("stop") self.__send("volume +1000") self.__send("volume 40") self.__send("volume -10") #self.__send("seek -10") #self.__send("seek +10") #self.__send("seek 0") def test_misc(self): #self.__send("add-directory /dev/null") self.__send("add-file /dev/null") #self.__send("dump-playlist /dev/null") #self.__send("dump_queue /dev/null") #self.__send("enqueue /dev/null") self.__send("enqueue-files /dev/null") #self.__send("filter album=test") #self.__send("focus") #self.__send("hide-window") #self.__send("open-browser 1") #self.__send("order shuffle") self.__send("properties") #self.__send("queue 1") self.__send("quit") #self.__send("random album") #self.__send("refresh") #self.__send("repeat 0") #self.__send("set-browser 1") self.__send("set-rating 0.5")
class TSongsMenu(TestCase): def _confirmer(self, *args): self.confirmed = True return False def setUp(self): config.init() self.library = SongFileLibrary() backend = quodlibet.player.init_backend("nullbe") self.device = backend.init(self.library) self.songs = [AudioFile({"title": x}) for x in ["song1", "song2", "song3"]] for song in self.songs: song.sanitize(fsnative(str(song["title"]))) self.confirmed = False def test_empty(self): self.menu = self.empty_menu_with() self.failIf(len(self.menu)) def test_simple(self): self.menu = SongsMenu(self.library, self.songs, plugins=False) def test_playlists(self): self.menu = self.empty_menu_with(playlists=True) self.failUnlessEqual(len(self.menu), 1) self.failUnless(self.menu.get_children()[0].props.sensitive) self.songs[0].can_add = False self.menu = self.empty_menu_with(playlists=True) self.failUnlessEqual(len(self.menu), 1) self.failIf(self.menu.get_children()[0].props.sensitive) def test_queue(self): self.menu = self.empty_menu_with(queue=True) self.failUnlessEqual(len(self.menu), 1) self.failUnless(self.menu.get_children()[0].props.sensitive) self.songs[0].can_add = False self.menu = self.empty_menu_with(queue=True) self.failUnlessEqual(len(self.menu), 1) self.failIf(self.menu.get_children()[0].props.sensitive) def test_remove(self): self.menu = self.empty_menu_with(remove=True, removal_confirmer=self._confirmer) self.failUnlessEqual(len(self.menu), 1) item = self.menu.get_children()[0] self.failIf(item.props.sensitive) item.activate() self.failUnless(self.confirmed, "Should have confirmed song removal") def test_remove_sensitive(self): self.library.add(self.songs) self.menu = self.empty_menu_with(remove=True) self.failUnlessEqual(len(self.menu), 1) self.failUnless(self.menu.get_children()[0].props.sensitive) def test_delete(self): self.menu = self.empty_menu_with(delete=True) self.failUnlessEqual(len(self.menu), 1) self.failUnless(self.menu.get_children()[0].props.sensitive) self.songs[0].is_file = False self.menu = self.empty_menu_with(delete=True) self.failIf(self.menu.get_children()[0].props.sensitive) def test_show_files(self): self.menu = self.empty_menu_with(show_files=True) self.failUnlessEqual(len(self.menu), 1) self.failUnless(self.menu.get_children()[0].props.sensitive) item = self.menu.get_children()[0] self.failUnless(item.props.sensitive) def test_show_files_remote_songs(self): self.songs = self.library.songs = [an_rf(1)] self.menu = self.empty_menu_with(show_files=True) self.failIf(len(self.menu)) def test_show_files_too_many_songs(self): self.songs = self.library.songs = [an_af(i) for i in range(50)] self.menu = self.empty_menu_with(show_files=True) item = self.menu.get_children()[0] self.failIf(item.props.sensitive, msg="Should have disabled show files for 50 files") def test_download(self): def choose(*args, **kwargs): return [mkdtemp()] self.songs = self.library.songs = [an_rf(i) for i in range(3)] self.menu = self.empty_menu_with(download=True, folder_chooser=choose) last = self.menu.get_children()[-1] assert last.props.sensitive, "should have enabled download for remotes" # TODO: some useful assertions, without needing a UI def empty_menu_with(self, plugins=False, playlists=False, queue=False, remove=False, delete=False, edit=False, ratings=False, show_files=False, download=False, removal_confirmer=None, folder_chooser=None): return SongsMenu(self.library, self.songs, plugins=plugins, playlists=playlists, queue=queue, remove=remove, delete=delete, edit=edit, ratings=ratings, show_files=show_files, removal_confirmer=removal_confirmer, download=download, folder_chooser=folder_chooser) def tearDown(self): self.device.destroy() self.library.destroy() try: self.menu.destroy() except AttributeError: pass else: del(self.menu) config.quit()
class TPlaylistUtil(TestCase): PLAYLIST_FILE_PATH = get_data_path('test.m3u8') sfLib: SongFileLibrary = None plLib: PlaylistLibrary = None def setUp(self): self.sfLib = SongFileLibrary() self.plLib = PlaylistLibrary(self.sfLib) def tearDown(self): self.plLib.destroy() self.sfLib.destroy() def test_dir_for(self): # uri format of files added via drag and drop or add button # (Gtk.SelectionData.get_uris()): file:///path/to/file.ext url_based_file: addinfourl = urlopen("file:///" + self.PLAYLIST_FILE_PATH) reader_based_file: BufferedReader = open(self.PLAYLIST_FILE_PATH, "rb") try: dir_of_url_based_file: str = _dir_for(url_based_file) self.assertEqual( os.path.realpath(os.path.dirname(self.PLAYLIST_FILE_PATH)), os.path.realpath(dir_of_url_based_file), "determining the directory of url based files" " should result in a correct path") dir_of_reader_based_file: str = _dir_for(reader_based_file) self.assertEqual( os.path.realpath(os.path.dirname(self.PLAYLIST_FILE_PATH)), os.path.realpath(dir_of_reader_based_file, ), "determining the directory of reader based files" " should result in a correct path") finally: url_based_file.close() reader_based_file.close() def test_parse_m3u8(self): fileName = os.path.basename(self.PLAYLIST_FILE_PATH) playlist: Playlist = None with open(self.PLAYLIST_FILE_PATH, "rb") as file: try: playlist = parse_m3u(file, fileName, self.sfLib, self.plLib) except: assert False, ("parsing m3u8 playlists in correct format" " should not cause errors") self.assertIsNotNone(playlist, ("parsing an m3u8 playlist in the correct format" " should result in a playlist")) # the test.m3u8 contains: # - 3 existing and supported audio files from the tests/data folder: # lame.mp3, test.wav, sine-110hz.flac # - 1 non existing file: non_existing_audio_file.mp3 # - 1 not supported file: test.jpg # parsing the file correctly should result in a playlist with 3 entries self.assertEqual( 3, len(playlist), "only existing files should be added to the playlist")
class TSongList(TestCase): HEADERS = [ "acolumn", "~#lastplayed", "~foo~bar", "~#rating", "~#length", "~dirname", "~#track" ] def setUp(self): config.init() self.lib = SongFileLibrary() self.songlist = SongList(self.lib) assert not self.lib.librarian, "not expecting a librarian - leaky test?" self.orders_changed = 0 self.songs_removed: List[Set] = [] def orders_changed_cb(*args): self.orders_changed += 1 def orders_removed_cb(songlist, removed): self.songs_removed.append(removed) self.__sigs = [ self.songlist.connect("orders-changed", orders_changed_cb), self.songlist.connect("songs-removed", orders_removed_cb) ] def test_set_all_column_headers(self): SongList.set_all_column_headers(self.HEADERS) headers = [col.header_name for col in self.songlist.get_columns()] self.failUnlessEqual(headers, self.HEADERS) def test_set_column_headers(self): self.songlist.set_column_headers(self.HEADERS) headers = [col.header_name for col in self.songlist.get_columns()] self.failUnlessEqual(headers, self.HEADERS) def test_drop(self): self.songlist.enable_drop() self.songlist.disable_drop() def test_sort_by(self): self.songlist.set_column_headers(["one", "two", "three"]) for key, order in [("one", True), ("two", False), ("three", False)]: self.songlist.set_sort_orders([(key, order)]) self.failUnlessEqual(self.songlist.get_sort_orders(), [(key, order)]) self.songlist.toggle_column_sort(self.songlist.get_columns()[-1]) self.failUnlessEqual(self.songlist.get_sort_orders(), [("three", True)]) def test_sort_orders(self): s = self.songlist s.set_column_headers(["foo", "quux", "bar"]) values = [("foo", True), ("bar", False)] s.set_sort_orders(values) self.assertEqual(s.get_sort_orders(), values) s.toggle_column_sort(s.get_columns()[1], replace=False) self.assertEqual(s.get_sort_orders(), values + [("quux", False)]) s.toggle_column_sort(s.get_columns()[1], replace=True) self.assertEqual(s.get_sort_orders(), [("quux", False)]) def test_toggle_sort(self): s = self.songlist s.set_column_headers(["foo"]) self.assertEqual(self.orders_changed, 1) s.toggle_column_sort(s.get_columns()[0], replace=True) self.assertEqual(self.orders_changed, 2) self.assertEqual(s.get_sort_orders(), [("foo", False)]) s.toggle_column_sort(s.get_columns()[0], replace=True) self.assertEqual(self.orders_changed, 3) self.assertEqual(s.get_sort_orders(), [("foo", True)]) def test_clear_sort(self): s = self.songlist s.set_column_headers(["foo"]) s.toggle_column_sort(s.get_columns()[0], replace=True) self.assertTrue(s.get_sort_orders()) s.clear_sort() self.assertFalse(s.get_sort_orders()) def test_not_sortable(self): s = self.songlist s.sortable = False s.set_column_headers(["foo"]) s.toggle_column_sort(s.get_columns()[0]) self.assertEqual(self.orders_changed, 0) self.assertFalse(s.get_sort_orders()) def test_find_default_sort_column(self): s = self.songlist self.assertTrue(s.find_default_sort_column() is None) s.set_column_headers(["~#track"]) self.assertTrue(s.find_default_sort_column()) def test_inline_search_state(self): self.assertEqual(self.songlist.get_search_column(), 0) self.assertTrue(self.songlist.get_enable_search()) def test_set_songs(self): self.songlist.set_songs([], sorted=True) self.songlist.set_songs([], sorted=False) self.songlist.set_songs([], scroll_select=True) self.songlist.set_songs([], scroll_select=False) self.songlist.set_songs([], scroll=True) self.songlist.set_songs([], scroll=False) def test_set_songs_restore_select(self): song = AudioFile({"~filename": "/dev/null"}) self.songlist.add_songs([song]) sel = self.songlist.get_selection() sel.select_path(Gtk.TreePath.new_first()) self.songlist.set_songs([song], scroll_select=True) self.assertEqual(self.songlist.get_selected_songs(), [song]) song2 = AudioFile({"~filename": "/dev/null"}) self.songlist.set_songs([song2], scroll_select=True) self.assertEqual(self.songlist.get_selected_songs(), []) def test_set_songs_no_restore_select(self): song = AudioFile({"~filename": "/dev/null"}) self.songlist.add_songs([song]) model = self.songlist.get_model() model.go_to(song) self.assertIs(model.current, song) # only restore if there was a selected one self.songlist.set_songs([song], scroll_select=True) self.assertEqual(self.songlist.get_selected_songs(), []) def test_get_selected_songs(self): song = AudioFile({"~filename": "/dev/null"}) self.songlist.add_songs([song]) sel = self.songlist.get_selection() sel.select_path(Gtk.TreePath.new_first()) self.assertEqual(self.songlist.get_selected_songs(), [song]) self.assertEqual(self.songlist.get_first_selected_song(), song) sel.unselect_all() self.assertEqual(self.songlist.get_selected_songs(), []) self.assertIs(self.songlist.get_first_selected_song(), None) def test_add_songs(self): song = AudioFile({"~filename": "/dev/null"}) # unsorted self.songlist.add_songs([song]) self.songlist.add_songs([song]) # sorted self.songlist.set_column_headers(["foo"]) self.songlist.toggle_column_sort(self.songlist.get_columns()[0]) self.songlist.add_songs([]) self.songlist.add_songs([song]) self.songlist.add_songs([song]) self.assertEqual(self.songlist.get_songs(), [song] * 4) def test_remove_songs(self): song = AudioFile({"~filename": "/dev/null"}) song.sanitize() self.lib.add([song]) assert song in self.lib, "Broken library?" self.songlist.add_songs([song]) assert set(self.songlist.get_songs()) == {song} self.lib.remove([song]) assert not list(self.lib), "Didn't get removed" run_gtk_loop() assert self.songs_removed == [{song} ], f"Signal not emitted: {self.__sigs}" def test_header_menu(self): song = AudioFile({"~filename": fsnative(u"/dev/null")}) song.sanitize() self.songlist.set_songs([song]) library = self.lib librarian = SongLibrarian() librarian.register(self.lib, "test") self.lib.librarian = librarian browser = TrackList(library) self.songlist.set_column_headers(["foo"]) self.assertFalse(self.songlist.Menu("foo", browser, library)) sel = self.songlist.get_selection() sel.select_all() self.assertTrue(self.songlist.Menu("foo", browser, library)) librarian.destroy() self.lib.librarian = None def test_get_columns_migrated(self): self.failIf(config.get("settings", "headers", None)) columns = "~album,~#replaygain_track_gain,foobar" config.set("settings", "columns", columns) self.failUnlessEqual(get_columns(), ["~album", "~#replaygain_track_gain", "foobar"]) self.failIf(config.get("settings", "headers", None)) def test_get_set_columns(self): self.failIf(config.get("settings", "headers", None)) self.failIf(config.get("settings", "columns", None)) columns = ["first", "won't", "two words", "4"] set_columns(columns) self.failUnlessEqual(columns, get_columns()) columns += ["~~another~one"] set_columns(columns) self.failUnlessEqual(columns, get_columns()) self.failIf(config.get("settings", "headers", None)) def test_header_tag_split(self): self.assertEqual(header_tag_split("foo"), ["foo"]) self.assertEqual(header_tag_split("~foo~bar"), ["foo", "bar"]) self.assertEqual(header_tag_split("<foo>"), ["foo"]) self.assertEqual(header_tag_split("<~foo~bar>"), ["foo", "bar"]) self.assertEqual(header_tag_split("pattern <~foo~bar>"), ["foo", "bar"]) def test_get_sort_tag(self): self.assertEqual(get_sort_tag("~#track"), "") self.assertEqual(get_sort_tag("artist"), "artistsort") self.assertEqual(get_sort_tag("date"), "date") self.assertEqual(get_sort_tag("~artist~date"), "~artistsort~date") self.assertEqual(get_sort_tag("~date~artist"), "~date~artistsort") self.assertEqual(get_sort_tag("composer"), "composersort") self.assertEqual(get_sort_tag("originalartist"), "originalartistsort") def test_check_sensible_menu_items(self): col = SongListColumn("title") menu = self.songlist._menu(col) submenus = [item.get_submenu() for item in menu.get_children()] names = { item.get_label() for child in submenus if child and not isinstance(child, Gtk.SeparatorMenuItem) for item in child.get_children() } assert {"Title", "Genre", "Comment", "Artist"} < names def tearDown(self): for sig in self.__sigs: self.songlist.disconnect(sig) self.songlist.destroy() self.lib.destroy() config.quit()