from dbus_next import Variant from .mpris import setup_mpris from .playerctl import PlayerctlCli import pytest import asyncio # TODO: test missing function does not segv @pytest.mark.asyncio async def test_emoji(bus_address): [mpris] = await setup_mpris('emoji-format-test', bus_address=bus_address) mpris.metadata = {'mpris:length': Variant('x', 100000)} await mpris.ping() playerctl = PlayerctlCli(bus_address) status_emoji_cmd = 'metadata --format \'{{emoji(status)}}\'' mpris.playback_status = 'Playing' cmd = await playerctl.run(status_emoji_cmd) assert cmd.stdout == '▶️', cmd.stderr mpris.playback_status = 'Paused' cmd = await playerctl.run(status_emoji_cmd) assert cmd.stdout == '⏸️', cmd.stderr mpris.playback_status = 'Stopped' cmd = await playerctl.run(status_emoji_cmd) assert cmd.stdout == '⏹️', cmd.stderr volume_emoji_cmd = 'metadata --format \'{{emoji(volume)}}\'' mpris.volume = 0.0 cmd = await playerctl.run(volume_emoji_cmd) assert cmd.stdout == '🔈', cmd.stderr mpris.volume = 0.5 cmd = await playerctl.run(volume_emoji_cmd) assert cmd.stdout == '🔉', cmd.stderr mpris.volume = 1.0 cmd = await playerctl.run(volume_emoji_cmd) assert cmd.stdout == '🔊', cmd.stderr cmd = await playerctl.run('metadata --format \'{{emoji("hi")}}\'') assert cmd.returncode == 1, cmd.stderr cmd = await playerctl.run('metadata --format \'{{emoji(status, volume)}}\'' ) assert cmd.returncode == 1, cmd.stderr await mpris.disconnect() class MetadataTest: def __init__(self, playerctl): self.tests = [] self.playerctl = playerctl def add(self, fmt, expected, ret=0): fmt = fmt.replace("'", r"\'") self.tests.append((f"metadata --format '{fmt}'", expected, ret)) async def run(self): coros = [] for fmt, _, _ in self.tests: coros.append(self.playerctl.run(fmt)) results = await asyncio.gather(*coros) for i, cmd in enumerate(results): fmt, expected, ret = self.tests[i] assert cmd.returncode == ret, cmd.stderr if ret == 0: assert cmd.stdout == expected, cmd.stderr @pytest.mark.asyncio async def test_format(bus_address): title = 'A Title' artist = 'An Artist' album = 'An Album' player_name = 'format-test' player_instance = f'{player_name}.instance123' [mpris] = await setup_mpris(player_instance, bus_address=bus_address) mpris.metadata = { 'xesam:title': Variant('s', title), 'xesam:artist': Variant('as', [artist]), 'xesam:escapeme': Variant('s', ''), 'xesam:album': Variant('s', album), 'mpris:length': Variant('x', 100000) } mpris.volume = 2.0 playerctl = PlayerctlCli(bus_address) test = MetadataTest(playerctl) test.add('{{artist}} - {{title}}', f'{artist} - {title}') test.add("{{markup_escape(xesam:escapeme)}}", "<hi>") test.add("{{lc(artist)}}", artist.lower()) test.add("{{uc(title)}}", title.upper()) test.add("{{uc(lc(title))}}", title.upper()) test.add('{{uc("Hi")}}', "HI") test.add("{{mpris:length}}", "100000") test.add( '@{{ uc( "hi" ) }} - {{uc( lc( "HO" ) ) }} . {{lc( uc( title ) ) }}@', f'@HI - HO . {title.lower()}@') test.add("{{default(xesam:missing, artist)}}", artist) test.add("{{default(title, artist)}}", title) test.add('{{default("", "ok")}}', 'ok') test.add('{{default("ok", "not")}}', 'ok') test.add(' {{lc(album)}} ', album.lower()) test.add('{{playerName}} - {{playerInstance}}', f'{player_name} - {player_instance}') test.add("{{trunc(title, 10)}}", title) test.add("{{trunc(title, 5)}}", f"{title[:5]}…") test.add('{{trunc("", 0)}}', "") test.add('{{trunc("", 10)}}', "") await test.run() # numbers math = [ '10', '-10 + 20', '10 + 10', '10 * 10', '10 / 10', '10 + 10 * 10 + 10', '10 + 10 * -10 + 10', '10 + 10 * -10 + -10', '-10 * 10 + 10', '-10 * -10 * -1 + -10', '-10 * 10 + -10 * -10 + 20 / 10 * -20 + -10', '8+-+--++-4', '2 - 10 * 1 + 1', '2 / -2 + 2 * 2 * -2 - 2 - 2 * -2', '2 * (2 + 2)', '10 * (10 + 12) - 4', '-(10)', '-(10 + 12 * -2)', '14 - (10 * 2 + 5) * -6', '(14 - 2 * 3) * (14 * -2 - 6) + -(4 - 2) * 5', ] # variables math += [ 'volume', 'volume + 10', '-volume', '-volume * -1', '-volume + volume', 'volume * volume', 'volume * -volume', 'volume + volume * -volume * volume + -volume', 'volume / -volume + volume * volume * -volume - volume - volume * -volume', '-(volume + 3) * 5 * (volume + 2)', ] # functions math += [ 'default(5+5, None)', '-default(5 + 5, None)', '(-default(5 - 5, None) + 2) * 8', '2 + (5 * 4 + 3 * -default(5, default(6 * (3 + 4 * (6 + 2)) / 2, None)) + -56)', ] def default_shim(arg1, arg2): if arg1 is None: return arg2 return arg1 async def math_test(math): cmd = await playerctl.run("metadata --format '{{" + math + "}}'") assert cmd.returncode == 0, cmd.stderr assert float(cmd.stdout) == eval(math, { 'volume': mpris.volume, 'default': default_shim }), math await asyncio.gather(*[math_test(m) for m in math]) await mpris.disconnect()