diff --git a/tests/test_lite.py b/tests/test_lite.py index daea2a2..6bfb969 100644 --- a/tests/test_lite.py +++ b/tests/test_lite.py @@ -333,6 +333,9 @@ def test_the_foreground_is_never_asked_about_in_lite(self): self.assertIsNone(pill.paste_target) asked.assert_not_called() + @unittest.skipUnless(sys.platform == "win32", + "full mode resolves the foreground window through inject.py, " + "which binds user32 at import") def test_full_mode_still_tracks_it(self): import flow.ui as ui diff --git a/tests/test_main.py b/tests/test_main.py index c9fb850..7810b31 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -371,6 +371,7 @@ def launch(self, argv) -> int: import flow.asr import flow.diag import flow.profile + import flow.refine import flow.ui import flow.__main__ as mod @@ -445,7 +446,21 @@ def launch(self, hotkeys, argv=(), platform="win32") -> tuple[int, str]: path = self.dir / "profile.json" path.write_text(json.dumps({"schema": 1, "hotkeys": hotkeys}), encoding="utf-8") out = io.StringIO() + # `refine.resolve` is stubbed, and not only for speed. It calls + # `shutil.which`, and `shutil.which` reads `sys.platform` - which this + # helper has just lied about. On a real macOS runner that sends the stdlib + # down its Windows branch, where `_winapi` is None: `AttributeError: + # 'NoneType' object has no attribute 'NeedCurrentDirectoryForExePath'`, + # raised from a line no part of Flow wrote. Which agent CLI happens to be + # installed has nothing to do with what this class asserts. + # + # Stubbed at `resolve` rather than at its callers, which was the first + # attempt and was whack-a-mole: `main` reaches the same line through + # `available()` *and* `unverified()`, and patching one left the other. It is + # the single choke point - the only `shutil.which` in the module, and what + # every lookup goes through. with mock.patch.object(sys, "platform", platform), \ + mock.patch.object(flow.refine, "resolve", return_value=None), \ mock.patch.object(flow.profile, "DEFAULT_PATH", path), \ mock.patch.object(flow.diag, "Diag"), \ mock.patch.object(mod, "Session"), \ diff --git a/tests/test_pill.py b/tests/test_pill.py index e096a97..afdda73 100644 --- a/tests/test_pill.py +++ b/tests/test_pill.py @@ -111,6 +111,15 @@ def test_the_advance_is_the_one_the_real_font_measures(self): root.withdraw() ui._load_fonts() f = tkfont.Font(root=root, font=ui.FONT_TRACE) + # `_load_fonts` registers the bundled Plex weights through GDI and returns + # early off Windows, so anywhere else Tk quietly substitutes its own + # monospace and this measures *that* - 10 px on a macOS runner against the + # 7 the real face gives. Skipped on the substitution rather than on the + # platform, because the question is whether the font resolved, and a + # Windows machine missing the file deserves the same answer. + if f.actual("family") != ui.FONT_TRACE[0]: + self.skipTest(f"{ui.FONT_TRACE[0]} not installed; " + f"Tk substituted {f.actual('family')!r}") self.assertEqual(f.measure("M"), ui.LABEL_ADV) # Monospaced, which is the assumption behind one advance for every glyph — # including the space in `NO INPUT`.