diff options
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/steamLaunchOptions.test.ts | 62 | ||||
| -rw-r--r-- | tests/test_flatpak_service.py | 174 |
2 files changed, 151 insertions, 85 deletions
diff --git a/tests/steamLaunchOptions.test.ts b/tests/steamLaunchOptions.test.ts index 3170fe8..215e3f7 100644 --- a/tests/steamLaunchOptions.test.ts +++ b/tests/steamLaunchOptions.test.ts @@ -37,6 +37,10 @@ test("normalizes blank and argument-only fields while refusing ambiguous launche options: `FOO=bar ${wrapper} %command% --windowed`, commandTokenAdded: true, }); + assert.deepEqual(installWrapperLaunchOption('FOO=bar "/home/deck/game.AppImage"', wrapper, true), { + options: 'FOO=bar ~/.lsfg %command% "/home/deck/game.AppImage"', + commandTokenAdded: true, + }); assert.throws(() => installWrapperLaunchOption("gamemoderun --windowed", wrapper), /refusing to guess/); assert.throws(() => installWrapperLaunchOption('"%command%"', wrapper), /refusing to guess/); }); @@ -122,11 +126,11 @@ test("reads the matching app-details field and installs/removes Steam integratio assert.equal(appWrites.length, 1); assert.equal(shortcutWrites.length, 0); - const shortcut = await installWrapperIntegration(43, true, wrapper); + const shortcut = await installWrapperIntegration(43, true, wrapper, false, "flatpak"); assert.equal(shortcut.originalExecutable, "/usr/bin/example-game"); assert.equal(shortcut.snapshot.target, wrapper); assert.deepEqual(targetWrites, [wrapper]); - const restored = await removeWrapperIntegration(43, true, wrapper, shortcut.originalExecutable); + const restored = await removeWrapperIntegration(43, true, wrapper, shortcut.originalExecutable, false, "flatpak"); assert.equal(restored.target, "/usr/bin/example-game"); assert.deepEqual(targetWrites, [wrapper, "/usr/bin/example-game"]); assert.equal(shortcutWrites.length, 0); @@ -143,6 +147,54 @@ test("reads the matching app-details field and installs/removes Steam integratio } }); +test("uses shortcut launch options for a host shortcut without changing its Target", async () => { + const previousWindow = (globalThis as Record<string, unknown>).window; + const previousSteamClient = (globalThis as Record<string, unknown>).SteamClient; + const originalOptions = 'DESKTOPINTEGRATION=1 "/home/deck/AppImages/dusk.appimage"'; + let shortcutOptions = originalOptions; + let shortcutTarget = "env"; + const shortcutWrites: string[] = []; + const targetWrites: string[] = []; + const apps = { + RegisterForAppDetails(_appId: number, callback: (details: SteamAppDetails) => void) { + callback({ strShortcutExe: shortcutTarget, strShortcutLaunchOptions: shortcutOptions }); + return { unregister() {} }; + }, + SetShortcutLaunchOptions(_appId: number, options: string) { + shortcutWrites.push(options); + shortcutOptions = options; + }, + SetShortcutExe(_appId: number, executable: string) { + targetWrites.push(executable); + shortcutTarget = executable; + }, + }; + (globalThis as Record<string, unknown>).window = { setTimeout, clearTimeout }; + (globalThis as Record<string, unknown>).SteamClient = { Apps: apps }; + try { + const installed = await installWrapperIntegration(44, true, wrapper, false, "host"); + assert.equal(installed.originalExecutable, undefined); + assert.equal(installed.snapshot.target, "env"); + assert.equal(installed.snapshot.options, 'DESKTOPINTEGRATION=1 ~/.lsfg %command% "/home/deck/AppImages/dusk.appimage"'); + assert.deepEqual(targetWrites, []); + assert.deepEqual(shortcutWrites, [installed.snapshot.options]); + + const secondInstall = await installWrapperIntegration(44, true, wrapper, false, "host"); + assert.equal(secondInstall.snapshot.options, installed.snapshot.options); + assert.deepEqual(shortcutWrites, [installed.snapshot.options]); + + const restored = await removeWrapperIntegration(44, true, wrapper, undefined, installed.commandTokenAdded, "host"); + assert.equal(restored.target, "env"); + assert.equal(restored.options, originalOptions); + assert.deepEqual(targetWrites, []); + } finally { + if (previousWindow === undefined) delete (globalThis as Record<string, unknown>).window; + else (globalThis as Record<string, unknown>).window = previousWindow; + if (previousSteamClient === undefined) delete (globalThis as Record<string, unknown>).SteamClient; + else (globalThis as Record<string, unknown>).SteamClient = previousSteamClient; + } +}); + test("fails closed when shortcut Target ownership or setters are unavailable", async () => { const previousWindow = (globalThis as Record<string, unknown>).window; const previousSteamClient = (globalThis as Record<string, unknown>).SteamClient; @@ -156,8 +208,8 @@ test("fails closed when shortcut Target ownership or setters are unavailable", a }, }; try { - await assert.rejects(installWrapperIntegration(99, true, wrapper), /Target API is unavailable/); - await assert.rejects(removeWrapperIntegration(99, true, wrapper, "/usr/bin/original"), /Target changed externally/); + await assert.rejects(installWrapperIntegration(99, true, wrapper, false, "flatpak"), /Target API is unavailable/); + await assert.rejects(removeWrapperIntegration(99, true, wrapper, "/usr/bin/original", false, "flatpak"), /Target changed externally/); } finally { if (previousWindow === undefined) delete (globalThis as Record<string, unknown>).window; else (globalThis as Record<string, unknown>).window = previousWindow; @@ -198,7 +250,7 @@ test("restores launch options and shortcut Target when a setter fails after chan assert.equal(appOptions, "FOO=bar %command%"); assert.deepEqual(appWrites, [`FOO=bar ${wrapper} %command%`, "FOO=bar %command%"]); - await assert.rejects(installWrapperIntegration(43, true, wrapper), /simulated Target write failure/); + await assert.rejects(installWrapperIntegration(43, true, wrapper, false, "flatpak"), /simulated Target write failure/); assert.equal(shortcutTarget, "/usr/bin/original"); assert.deepEqual(targetWrites, [wrapper, "/usr/bin/original"]); } finally { diff --git a/tests/test_flatpak_service.py b/tests/test_flatpak_service.py index 70ba228..d5baf61 100644 --- a/tests/test_flatpak_service.py +++ b/tests/test_flatpak_service.py @@ -26,7 +26,12 @@ class FlatpakServiceTests(unittest.TestCase): self.service.config_dir = self.home / ".config/lsfg-vk" self.service.config_file_path = self.service.config_dir / "conf.toml" self.service.check_flatpak_available = Mock(return_value=True) - self.service._run_flatpak_command = Mock() + self.service._run_flatpak_command = Mock(side_effect=self._run_flatpak_command) + self.runtime_ref = "org.freedesktop.Platform/x86_64/24.08" + self.runtime_metadata = "" + self.user_branches = set() + self.system_branches = set() + self.install_branch = "24.08" self.bundle = self.home / "lsfg-vk-24.08.flatpak" self.bundle.write_bytes(b"bundle") self.service._bundled_extension_path = Mock(return_value=self.bundle) @@ -42,6 +47,22 @@ class FlatpakServiceTests(unittest.TestCase): def _extension_line(branch): return f"org.freedesktop.Platform.VulkanLayer.lsfgvk\tx86_64\t{branch}\n" + def _run_flatpak_command(self, args, **_kwargs): + if args[0] == "info" and args[1] == "--show-runtime": + return self._result(self.runtime_ref + "\n") + if args[0] == "info" and args[1] == "--show-metadata": + return self._result(self.runtime_metadata) + if args[0] == "list": + branches = self.user_branches if "--user" in args else self.system_branches + return self._result("".join(self._extension_line(branch) for branch in sorted(branches))) + if args[0] == "install": + self.user_branches.add(self.install_branch) + return self._result() + if args[0] == "uninstall": + self.user_branches.discard(args[-1].rsplit("/", 1)[-1]) + return self._result() + raise AssertionError(f"Unexpected Flatpak command: {args}") + def test_runtime_branch_mapping_is_strict_and_branch_specific(self): self.assertEqual( FlatpakService.runtime_branch_from_ref( @@ -62,11 +83,20 @@ class FlatpakServiceTests(unittest.TestCase): "org.freedesktop.Platform/x86_64/26.08" ) + def test_runtime_branch_mapping_reads_documented_gl_metadata(self): + metadata = """ +[Extension org.freedesktop.Platform.GL] +versions=25.08;25.08-extra;1.4 +version=1.4 +""" + self.assertEqual(FlatpakService.runtime_branch_from_metadata(metadata), "25.08") + with self.assertRaises(ValueError): + FlatpakService.runtime_branch_from_metadata( + "[Extension org.freedesktop.Platform.GL]\nversions=26.08;26.08-extra;1.4\n" + ) + def test_resolve_reads_required_runtime_instead_of_any_installed_branch(self): - self.service._run_flatpak_command.side_effect = [ - self._result("org.freedesktop.Platform/x86_64/24.08\n"), - self._result(self._extension_line("23.08")), - ] + self.user_branches = {"23.08"} response = self.service.resolve_app_support("com.example.Game") @@ -80,22 +110,48 @@ class FlatpakServiceTests(unittest.TestCase): ) self.assertEqual( self.service._run_flatpak_command.call_args_list[1].args[0], - ["list", "--runtime", "--columns=application,arch,branch"], + ["list", "--user", "--runtime", "--columns=application,arch,branch"], + ) + self.assertEqual( + self.service._run_flatpak_command.call_args_list[2].args[0], + ["list", "--system", "--runtime", "--columns=application,arch,branch"], ) - def test_install_records_only_a_new_user_owned_branch(self): - self.service._run_flatpak_command.side_effect = [ - self._result(""), - self._result(""), - self._result(self._extension_line("24.08")), - ] + def test_resolve_maps_kde_and_gnome_runtimes_from_gl_metadata(self): + metadata = "[Extension org.freedesktop.Platform.GL]\nversions=25.08;25.08-extra;1.4\n" + for runtime in ("org.kde.Platform/x86_64/6.10", "org.gnome.Platform/x86_64/49"): + with self.subTest(runtime=runtime): + self.service._run_flatpak_command.reset_mock() + self.runtime_ref = runtime + self.runtime_metadata = metadata + response = self.service.resolve_app_support("com.example.Game") + self.assertEqual(response["runtime_branch"], "25.08") + self.assertEqual(response["support_status"], "needs-runtime") + self.assertEqual( + self.service._run_flatpak_command.call_args_list[1].args[0], + ["info", "--show-metadata", runtime], + ) + + def test_system_extension_is_ready_without_installing_a_user_copy(self): + self.system_branches = {"24.08"} + + response = self.service.ensure_app_support("com.example.Game") + + self.assertTrue(response["success"]) + self.assertEqual(response["support_status"], "ready") + self.assertEqual( + [call.args[0][0] for call in self.service._run_flatpak_command.call_args_list], + ["info", "list", "list"], + ) + self.assertFalse(any(call.args[0][0] == "install" for call in self.service._run_flatpak_command.call_args_list)) + def test_install_records_only_a_new_user_owned_branch(self): response = self.service.install_extension("24.08") self.assertTrue(response["success"]) self.assertTrue(response["enabled"]) self.assertTrue(response["installed"]) - install_args = self.service._run_flatpak_command.call_args_list[1].args[0] + install_args = self.service._run_flatpak_command.call_args_list[2].args[0] self.assertEqual(install_args[:4], ["install", "--user", "--noninteractive", "--or-update"]) self.assertEqual( json.loads(self.service.ownership_path.read_text(encoding="utf-8")), @@ -103,9 +159,7 @@ class FlatpakServiceTests(unittest.TestCase): ) def test_preexisting_branch_is_not_claimed_or_removed(self): - self.service._run_flatpak_command.return_value = self._result( - self._extension_line("24.08") - ) + self.user_branches = {"24.08"} install_response = self.service.install_extension("24.08") cleanup_response = self.service.remove_plugin_owned_extensions() @@ -115,15 +169,10 @@ class FlatpakServiceTests(unittest.TestCase): self.assertTrue(install_response["installed"]) self.assertFalse(self.service.ownership_path.exists()) self.assertTrue(cleanup_response["success"]) - self.assertEqual(self.service._run_flatpak_command.call_count, 1) - - def test_extension_toggle_installs_and_uninstalls_preexisting_branch(self): - self.service._run_flatpak_command.side_effect = [ - self._result(self._extension_line("24.08")), - self._result(self._extension_line("24.08")), - self._result(""), - self._result(""), - ] + self.assertEqual(self.service._run_flatpak_command.call_count, 2) + + def test_extension_toggle_preserves_preexisting_branch(self): + self.user_branches = {"24.08"} enable_response = self.service.set_extension_enabled("24.08", True) disable_response = self.service.set_extension_enabled("24.08", False) @@ -132,36 +181,36 @@ class FlatpakServiceTests(unittest.TestCase): self.assertTrue(enable_response["enabled"]) self.assertTrue(enable_response["installed"]) self.assertTrue(disable_response["success"]) - self.assertFalse(disable_response["enabled"]) - self.assertFalse(disable_response["installed"]) - self.assertTrue(disable_response["removed"]) + self.assertTrue(disable_response["enabled"]) + self.assertTrue(disable_response["installed"]) + self.assertFalse(disable_response["removed"]) + self.assertEqual(self.user_branches, {"24.08"}) self.assertEqual( [call.args[0][0] for call in self.service._run_flatpak_command.call_args_list], - ["list", "list", "uninstall", "list"], + ["list", "list", "list", "list"], ) - def test_extension_toggle_removes_owned_branch_and_can_repeat_disable(self): + def test_extension_toggle_removes_owned_user_branch_but_preserves_system_branch(self): self.service.ownership_path.parent.mkdir(parents=True, exist_ok=True) self.service.ownership_path.write_text( json.dumps({"version": 1, "plugin_owned_branches": ["24.08"]}), encoding="utf-8", ) - self.service._run_flatpak_command.side_effect = [ - self._result(self._extension_line("24.08")), - self._result(""), - self._result(""), - self._result(""), - ] + self.user_branches = {"24.08"} + self.system_branches = {"24.08"} disable_response = self.service.set_extension_enabled("24.08", False) repeat_response = self.service.set_extension_enabled("24.08", False) self.assertTrue(disable_response["success"]) - self.assertFalse(disable_response["enabled"]) + self.assertTrue(disable_response["enabled"]) self.assertTrue(disable_response["removed"]) self.assertTrue(repeat_response["success"]) - self.assertFalse(repeat_response["enabled"]) - self.assertFalse(repeat_response["installed"]) + self.assertTrue(repeat_response["enabled"]) + self.assertTrue(repeat_response["installed"]) + self.assertEqual(self.user_branches, set()) + self.assertEqual(self.system_branches, {"24.08"}) + self.assertFalse(self.service.ownership_path.exists()) uninstall_commands = [ call.args[0] for call in self.service._run_flatpak_command.call_args_list @@ -190,23 +239,16 @@ class FlatpakServiceTests(unittest.TestCase): self.assertEqual(self.service._run_flatpak_command.call_count, 0) def test_ensure_app_support_installs_only_the_app_runtime_branch(self): - self.service._run_flatpak_command.side_effect = [ - self._result("org.freedesktop.Platform/x86_64/24.08\n"), - self._result(""), - self._result(""), - self._result(""), - self._result(""), - self._result(self._extension_line("24.08")), - self._result("org.freedesktop.Platform/x86_64/24.08\n"), - self._result(self._extension_line("24.08")), - ] - response = self.service.ensure_app_support("com.example.Game") self.assertTrue(response["success"]) self.assertEqual(response["support_status"], "ready") self.assertEqual(response["runtime_branch"], "24.08") - install_args = self.service._run_flatpak_command.call_args_list[4].args[0] + install_args = next( + call.args[0] + for call in self.service._run_flatpak_command.call_args_list + if call.args[0][0] == "install" + ) self.assertEqual(install_args[0], "install") self.assertIn("--user", install_args) self.assertNotIn("23.08", install_args) @@ -216,19 +258,6 @@ class FlatpakServiceTests(unittest.TestCase): ) def test_two_shortcuts_using_one_flatpak_share_one_extension_branch(self): - self.service._run_flatpak_command.side_effect = [ - self._result("org.freedesktop.Platform/x86_64/24.08\n"), - self._result(""), - self._result(""), - self._result(""), - self._result(""), - self._result(self._extension_line("24.08")), - self._result("org.freedesktop.Platform/x86_64/24.08\n"), - self._result(self._extension_line("24.08")), - self._result("org.freedesktop.Platform/x86_64/24.08\n"), - self._result(self._extension_line("24.08")), - ] - first = self.service.ensure_app_support("net.pcsx2.PCSX2") second = self.service.ensure_app_support("net.pcsx2.PCSX2.Dev") @@ -251,22 +280,7 @@ class FlatpakServiceTests(unittest.TestCase): json.dumps({"version": 1, "plugin_owned_branches": ["23.08", "24.08"]}), encoding="utf-8", ) - self.service._run_flatpak_command.side_effect = [ - self._result( - "\n".join( - [ - "\t".join([FlatpakService.EXTENSION_ID, "x86_64", "23.08"]), - "\t".join([FlatpakService.EXTENSION_ID, "x86_64", "24.08"]), - ] - ) - + "\n" - ), - self._result(""), - self._result("\t".join([FlatpakService.EXTENSION_ID, "x86_64", "24.08"]) + "\n"), - self._result("\t".join([FlatpakService.EXTENSION_ID, "x86_64", "24.08"]) + "\n"), - self._result(""), - self._result(""), - ] + self.user_branches = {"23.08", "24.08"} response = self.service.remove_plugin_owned_extensions() |
