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")
Beispiel #2
0
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()
Beispiel #3
0
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")
Beispiel #4
0
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()