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.
This commit is contained in:
2026-08-16 15:54:44 +03:00
parent 80ff4ecade
commit 180ddac37e
5 changed files with 33 additions and 9 deletions
+6 -3
View File
@@ -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. that lists them is not installed.
The tests are split along the same line, and almost none of them are skipped. 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 macOS and Windows backends: the programs are faked at `shutil.which`, the
frameworks and system libraries at the one function that loads them 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 (`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. class and subclassed by each of them.
The 43 that do carry `@linux_only` are the ones that would need the real thing: 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 the `/dev/input` listener, KDE's shortcut file, GNOME's gsettings. The 20 with
that way only when faking it would leave nothing to test. A test that quietly `@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. stops running on the platform you are porting to protects nothing.
## What a pull request should carry ## What a pull request should carry
+12
View File
@@ -40,6 +40,18 @@ linux_only = unittest.skipUnless(
"covers the Linux desktop stack (PipeWire, wl-clipboard, ydotool, KDE)", "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): def _no_network(*args, **kwargs):
raise AssertionError( raise AssertionError(
+6
View File
@@ -15,6 +15,7 @@ import unittest
from unittest import mock from unittest import mock
from dikte import integrate from dikte import integrate
from tests.support import posix_only
class Frozen: class Frozen:
@@ -75,6 +76,7 @@ class WhatToStart(unittest.TestCase):
def test_a_checkout_names_this_interpreter_and_the_entry_point(self): def test_a_checkout_names_this_interpreter_and_the_entry_point(self):
self.assertFalse(integrate.packaged()) self.assertFalse(integrate.packaged())
@posix_only
def test_an_appimage_names_the_file_and_not_the_mount(self): 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 """The mount is a fresh /tmp path every run; a shortcut written to it
would work until the next login and never again.""" would work until the next login and never again."""
@@ -83,6 +85,7 @@ class WhatToStart(unittest.TestCase):
self.assertEqual(str(integrate.target()), self.assertEqual(str(integrate.target()),
"/home/someone/Downloads/Dikte.AppImage") "/home/someone/Downloads/Dikte.AppImage")
@posix_only
def test_a_mac_names_the_bundle_and_not_the_executable_inside_it(self): def test_a_mac_names_the_bundle_and_not_the_executable_inside_it(self):
with Frozen("/Applications/Dikte.app/Contents/MacOS/Dikte", with Frozen("/Applications/Dikte.app/Contents/MacOS/Dikte",
platform="darwin"): platform="darwin"):
@@ -95,6 +98,7 @@ class WhatToStart(unittest.TestCase):
class BundledTools(unittest.TestCase): class BundledTools(unittest.TestCase):
"""The ffmpeg the disk image carries, and how anything finds it.""" """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): def test_a_mac_looks_beside_the_bundle_not_beside_the_executable(self):
with Frozen("/Applications/Dikte.app/Contents/MacOS/Dikte", with Frozen("/Applications/Dikte.app/Contents/MacOS/Dikte",
platform="darwin"): platform="darwin"):
@@ -213,6 +217,7 @@ class Certificates(unittest.TestCase):
self.assertIsNone(integrate.use_system_certificates()) self.assertIsNone(integrate.use_system_certificates())
@posix_only
class Linux(Home): class Linux(Home):
def install(self, appimage, force=False): def install(self, appimage, force=False):
with Frozen("/tmp/.mount_x/usr/bin/dikte", appimage=str(appimage), with Frozen("/tmp/.mount_x/usr/bin/dikte", appimage=str(appimage),
@@ -348,6 +353,7 @@ class Linux(Home):
self.assertEqual(integrate.ensure(), []) self.assertEqual(integrate.ensure(), [])
@posix_only
class MacOS(Home): class MacOS(Home):
def agent(self): def agent(self):
return self.home / "Library/LaunchAgents/io.github.yusufipk.dikte.plist" return self.home / "Library/LaunchAgents/io.github.yusufipk.dikte.plist"
+5 -3
View File
@@ -8,6 +8,7 @@ answers by saying nothing at all.
import json import json
import os import os
import pathlib import pathlib
import shlex
import sys import sys
import unittest import unittest
from unittest import mock from unittest import mock
@@ -65,9 +66,10 @@ class Paths(unittest.TestCase):
self.assertTrue(os.path.exists(ipc.script_path())) self.assertTrue(os.path.exists(ipc.script_path()))
def test_the_shortcut_command_runs_it_with_this_interpreter(self): def test_the_shortcut_command_runs_it_with_this_interpreter(self):
command = ipc.command_for("toggle") # Read back through the same quoting it went out with: a Windows path
self.assertTrue(command.startswith(sys.executable)) # is spelled with backslashes and comes out of the join quoted.
self.assertTrue(command.endswith(" toggle")) 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): 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 """There is no __main__.py on disk in one, and sys.executable is the
+4 -3
View File
@@ -21,6 +21,7 @@ from dikte import cleanup
from dikte import config as cfg from dikte import config as cfg
from dikte import ggml from dikte import ggml
from dikte import hotkey from dikte import hotkey
from dikte import ipc
from dikte import overlay as overlay_module from dikte import overlay as overlay_module
from dikte import paste from dikte import paste
from dikte import settings_ui from dikte import settings_ui
@@ -283,7 +284,7 @@ class Settings(DikteTest):
text = self.shortcut_tab_text(window) text = self.shortcut_tab_text(window)
self.assertIn("i3 keeps no shortcut registry", text) self.assertIn("i3 keeps no shortcut registry", text)
self.assertNotIn("KWin", 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. # Not a choice to offer where it is the only mechanism there is.
self.assertTrue(window.evdev_enabled.isHidden()) self.assertTrue(window.evdev_enabled.isHidden())
self.assertFalse([button for button in self.assertFalse([button for button in
@@ -460,7 +461,7 @@ class MacSettings(Settings):
text = self.shortcut_tab_text(window) text = self.shortcut_tab_text(window)
self.assertIn("Dikte asks macOS for these combinations", text) self.assertIn("Dikte asks macOS for these combinations", text)
self.assertNotIn("KWin", 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): def test_the_paste_keys_on_offer_are_the_ones_a_mac_uses(self):
window = self.window(cfg.Config()) window = self.window(cfg.Config())
@@ -484,7 +485,7 @@ class KdeSettings(Settings):
self.assertIn("KWin only reads shortcut settings at startup", text) self.assertIn("KWin only reads shortcut settings at startup", text)
self.assertIn("Install as a KDE shortcut", text) self.assertIn("Install as a KDE shortcut", text)
self.assertNotIn("keeps no shortcut registry", 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 # Here it is a choice: the wait for the next login, or the key press
# reaching the focused application as well. # reaching the focused application as well.
self.assertFalse(window.evdev_enabled.isHidden()) self.assertFalse(window.evdev_enabled.isHidden())