From 180ddac37e91fc72925a5699e3d5d1c45c96386c Mon Sep 17 00:00:00 2001 From: yusufipk Date: Sun, 16 Aug 2026 15:54:44 +0300 Subject: [PATCH] Let the Windows job read the merged suite The merge put a Windows runner under tests master wrote for two systems, and 21 of them fell over on it. Two were the quoting: `command_for` goes through shlex now, so a Windows path comes back in quotes, and the two tests that read the command as a string were reading it as a Linux one. They ask through the same join instead. The other nineteen are `integrate.py`, which writes the menu entry and the login item a downloaded build installs for itself. There are two downloads, an AppImage and a disk image, so the module has a Linux half and a macOS half and nothing a Windows host would run: its tests hand the fake home over in $HOME, which Windows does not read, and compare paths that start at the root. They carry `@posix_only`, which comes off again the day there is a Windows build to integrate. --- CONTRIBUTING.md | 9 ++++++--- tests/support.py | 12 ++++++++++++ tests/test_integrate.py | 6 ++++++ tests/test_ipc.py | 8 +++++--- tests/test_ui.py | 7 ++++--- 5 files changed, 33 insertions(+), 9 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a3f85b2..c364c89 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -70,7 +70,7 @@ there can tell that apart from an empty device list, which only means the tool that lists them is not installed. The tests are split along the same line, and almost none of them are skipped. -1104 of the 1147 run on any machine, including every line of the Wayland, X11, +1084 of the 1147 run on any machine, including every line of the Wayland, X11, macOS and Windows backends: the programs are faked at `shutil.which`, the frameworks and system libraries at the one function that loads them (`paste._win_api`, `hotkey._win_input`). A test class says which system it is @@ -88,8 +88,11 @@ is sitting at. What the systems owe in common is written once as a contract class and subclassed by each of them. The 43 that do carry `@linux_only` are the ones that would need the real thing: -the `/dev/input` listener, KDE's shortcut file, GNOME's gsettings. Mark a test -that way only when faking it would leave nothing to test. A test that quietly +the `/dev/input` listener, KDE's shortcut file, GNOME's gsettings. The 20 with +`@posix_only` are `integrate.py`, the menu entry and the login item a downloaded +build writes for itself: there are two downloads, an AppImage and a disk image, +so that module has no Windows half for a Windows host to check. Mark a test +either way only when faking it would leave nothing to test. A test that quietly stops running on the platform you are porting to protects nothing. ## What a pull request should carry diff --git a/tests/support.py b/tests/support.py index 18c0a06..f6ec508 100644 --- a/tests/support.py +++ b/tests/support.py @@ -40,6 +40,18 @@ linux_only = unittest.skipUnless( "covers the Linux desktop stack (PipeWire, wl-clipboard, ydotool, KDE)", ) +# The launchers a downloaded build writes for itself. There are two downloads, +# an AppImage and a disk image, so `integrate` has a Linux half and a macOS half +# and no third one, and the tests that pin them stand in a home laid out the way +# those two systems lay one out: paths that start at the root, a $HOME the +# library reads, a symlink for the command. None of that is a Windows machine, +# where the same code never runs. A Windows build would add an entry there and +# take the mark off these. +posix_only = unittest.skipIf( + sys.platform == "win32", + "covers what an AppImage and a .app write into the desktop they landed on", +) + def _no_network(*args, **kwargs): raise AssertionError( diff --git a/tests/test_integrate.py b/tests/test_integrate.py index 6bc43b6..9721dd4 100644 --- a/tests/test_integrate.py +++ b/tests/test_integrate.py @@ -15,6 +15,7 @@ import unittest from unittest import mock from dikte import integrate +from tests.support import posix_only class Frozen: @@ -75,6 +76,7 @@ class WhatToStart(unittest.TestCase): def test_a_checkout_names_this_interpreter_and_the_entry_point(self): self.assertFalse(integrate.packaged()) + @posix_only def test_an_appimage_names_the_file_and_not_the_mount(self): """The mount is a fresh /tmp path every run; a shortcut written to it would work until the next login and never again.""" @@ -83,6 +85,7 @@ class WhatToStart(unittest.TestCase): self.assertEqual(str(integrate.target()), "/home/someone/Downloads/Dikte.AppImage") + @posix_only def test_a_mac_names_the_bundle_and_not_the_executable_inside_it(self): with Frozen("/Applications/Dikte.app/Contents/MacOS/Dikte", platform="darwin"): @@ -95,6 +98,7 @@ class WhatToStart(unittest.TestCase): class BundledTools(unittest.TestCase): """The ffmpeg the disk image carries, and how anything finds it.""" + @posix_only def test_a_mac_looks_beside_the_bundle_not_beside_the_executable(self): with Frozen("/Applications/Dikte.app/Contents/MacOS/Dikte", platform="darwin"): @@ -213,6 +217,7 @@ class Certificates(unittest.TestCase): self.assertIsNone(integrate.use_system_certificates()) +@posix_only class Linux(Home): def install(self, appimage, force=False): with Frozen("/tmp/.mount_x/usr/bin/dikte", appimage=str(appimage), @@ -348,6 +353,7 @@ class Linux(Home): self.assertEqual(integrate.ensure(), []) +@posix_only class MacOS(Home): def agent(self): return self.home / "Library/LaunchAgents/io.github.yusufipk.dikte.plist" diff --git a/tests/test_ipc.py b/tests/test_ipc.py index e58c06f..502574c 100644 --- a/tests/test_ipc.py +++ b/tests/test_ipc.py @@ -8,6 +8,7 @@ answers by saying nothing at all. import json import os import pathlib +import shlex import sys import unittest from unittest import mock @@ -65,9 +66,10 @@ class Paths(unittest.TestCase): self.assertTrue(os.path.exists(ipc.script_path())) def test_the_shortcut_command_runs_it_with_this_interpreter(self): - command = ipc.command_for("toggle") - self.assertTrue(command.startswith(sys.executable)) - self.assertTrue(command.endswith(" toggle")) + # Read back through the same quoting it went out with: a Windows path + # is spelled with backslashes and comes out of the join quoted. + self.assertEqual(shlex.split(ipc.command_for("toggle")), + [sys.executable, ipc.script_path(), "toggle"]) def test_a_packaged_build_names_itself_and_no_interpreter(self): """There is no __main__.py on disk in one, and sys.executable is the diff --git a/tests/test_ui.py b/tests/test_ui.py index b3a748d..6cd402c 100644 --- a/tests/test_ui.py +++ b/tests/test_ui.py @@ -21,6 +21,7 @@ from dikte import cleanup from dikte import config as cfg from dikte import ggml from dikte import hotkey +from dikte import ipc from dikte import overlay as overlay_module from dikte import paste from dikte import settings_ui @@ -283,7 +284,7 @@ class Settings(DikteTest): text = self.shortcut_tab_text(window) self.assertIn("i3 keeps no shortcut registry", text) self.assertNotIn("KWin", text) - self.assertIn("__main__.py toggle", text) + self.assertIn(ipc.command_for("toggle"), text) # Not a choice to offer where it is the only mechanism there is. self.assertTrue(window.evdev_enabled.isHidden()) self.assertFalse([button for button in @@ -460,7 +461,7 @@ class MacSettings(Settings): text = self.shortcut_tab_text(window) self.assertIn("Dikte asks macOS for these combinations", text) self.assertNotIn("KWin", text) - self.assertNotIn("__main__.py toggle", text) + self.assertNotIn(ipc.command_for("toggle"), text) def test_the_paste_keys_on_offer_are_the_ones_a_mac_uses(self): window = self.window(cfg.Config()) @@ -484,7 +485,7 @@ class KdeSettings(Settings): self.assertIn("KWin only reads shortcut settings at startup", text) self.assertIn("Install as a KDE shortcut", text) self.assertNotIn("keeps no shortcut registry", text) - self.assertNotIn("__main__.py toggle", text) + self.assertNotIn(ipc.command_for("toggle"), text) # Here it is a choice: the wait for the next login, or the key press # reaching the focused application as well. self.assertFalse(window.evdev_enabled.isHidden())