Isaiah Odhner
06344fb8de
Silence type checker warnings (reportOptionalMemberAccess)
2023-09-16 23:31:08 -04:00
Isaiah Odhner
0791b1c080
Satisfy the type checker
...
`PYRIGHT_PYTHON_FORCE_VERSION=1.1.327 pyright` now gives 0 errors
(before this commit it was 16 errors)
2023-09-16 23:31:08 -04:00
Isaiah Odhner
a6b5cb31be
Clean up mocked method FigletFont.preloadFont
2023-09-16 23:31:08 -04:00
Isaiah Odhner
0f617dd8c4
Dynamically theme message box icons
2023-09-15 22:03:34 -04:00
Isaiah Odhner
7a13659d48
Fix "Show Details" not changing to "Hide Details" when expanding error
2023-09-15 20:44:40 -04:00
Isaiah Odhner
fc1baa9815
Move imports so that Organize Imports doesn't break it
...
Before, if I ran Organize Imports in VS Code, it reordered things such that `sys.path.insert` was after the import that needed it.
Now it's stable.
2023-09-15 19:56:27 -04:00
Isaiah Odhner
857e459b2d
Get tests running, if not passing, on Windows
2023-09-15 17:08:13 -04:00
Isaiah Odhner
40291f29fd
Add fake folders to mask OS differences in snapshot tests
...
Now the tests pass on macOS, not just Ubuntu. Not sure about Windows.
2023-09-15 17:08:13 -04:00
Isaiah Odhner
7fa80b853c
Fix flaky test due to pressed button style
2023-09-14 20:22:48 -04:00
Isaiah Odhner
91b2c285fe
Re-color in-progress polygon/curve immediately
2023-09-14 20:04:31 -04:00
Isaiah Odhner
ad39f34084
Add Polygon test with dragging
2023-09-14 16:58:47 -04:00
Isaiah Odhner
3f1c6c964a
Fix Polygon tool detecting double clicks despite distance
2023-09-14 16:32:40 -04:00
Isaiah Odhner
b6d0d2cc7b
Delete debug scratchpad for polygon test
2023-09-14 15:09:22 -04:00
Isaiah Odhner
bf8e445f69
Make palette state local to the app instance
2023-09-14 02:31:49 -04:00
Isaiah Odhner
faa9c76ba8
Test file drag-and-drop handling
2023-09-14 02:03:52 -04:00
Isaiah Odhner
070e253394
Move fixtures to conftest.py
2023-09-14 01:17:01 -04:00
Isaiah Odhner
5a7ba995c0
Accept super trivial change to About dialog snapshots
...
The scrollbar handle is slightly taller now because I removed the `--recode-samples` option.
2023-09-13 02:37:37 -04:00
Isaiah Odhner
c538787ff2
Recurse into subfolders for re-encoding round trip test
...
There are many more failures now, which I should probably take a look at
at some point, but I don't know how to best inspect the changes yet.
I'll mark these as xfail (expected to fail) for now.
2023-09-13 02:24:25 -04:00
Isaiah Odhner
bb047c04e7
Move --recode-samples to an automated test
2023-09-12 21:54:19 -04:00
Isaiah Odhner
6f13a5a302
Clean up
2023-09-12 21:23:36 -04:00
Isaiah Odhner
1f1bf577f2
Disable tool icon swaps when running in pytest
2023-09-12 21:08:24 -04:00
Isaiah Odhner
08847ca91b
Fix Free-Form Select behavior when melding with negative coordinates
2023-09-12 20:16:55 -04:00
Isaiah Odhner
96fe28269d
Accept changes to file dialog snapshots
...
...but NOT the Free-Form Select test! I'm noticing that when marked
as skipped, running with --snapshot-update deletes the snapshot.
So neither xfail or skip (or xfail with run=False) is a good solution.
It's almost as if people don't normally do TDD with snapshots.
Anyways, HOPEFULLY I can move on now, to actually fixing things,
like the Polygon tool, and new bugs I've found while adding tests.
2023-09-12 19:45:41 -04:00
Isaiah Odhner
d6705912b3
Fix DirectoryTree retaining real pathlib access
...
This fixes the following error:
----------------------------------------------- Captured stderr call -----------------------------------------------
╭───────────────────── Traceback (most recent call last) ──────────────────────╮
│ /home/io/Projects/textual-paint/src/textual_paint/file_dialogs.py:86 in │
│ on_mount │
│ │
│ 83 │ def on_mount(self) -> None: │
│ 84 │ │ """Called when the window is mounted.""" │
│ 85 │ │ self.content.mount( │
│ ❱ 86 │ │ │ EnhancedDirectoryTree(path="/"), │
│ 87 │ │ │ Horizontal( │
│ 88 │ │ │ │ Label(_("File name:")), │
│ 89 │ │ │ │ Input(classes="filename_input autofocus", value=self._ │
│ │
│ ╭──────────────────── locals ────────────────────╮ │
│ │ self = OpenDialogWindow(id='window_auto_id_0') │ │
│ ╰────────────────────────────────────────────────╯ │
│ │
│ in __init__:119 │
│ │
│ 116 │ │ self._load_queue: Queue[TreeNode[DirEntry]] = Queue() │
│ 117 │ │ super().__init__( │
│ 118 │ │ │ str(path), │
│ ❱ 119 │ │ │ data=DirEntry(self.PATH(path)), │
│ 120 │ │ │ name=name, │
│ 121 │ │ │ id=id, │
│ 122 │ │ │ classes=classes, │
│ │
│ ╭───────────────── locals ──────────────────╮ │
│ │ classes = None │ │
│ │ disabled = False │ │
│ │ id = None │ │
│ │ name = None │ │
│ │ path = '/' │ │
│ │ self = EnhancedDirectoryTree( │ │
│ │ │ id='some fake shit', │ │
│ │ │ name='some more fake shit' │ │
│ │ ) │ │
│ ╰───────────────────────────────────────────╯ │
│ │
│ in __new__:960 │
│ │
│ 957 │ def __new__(cls, *args, **kwargs): │
│ 958 │ │ if cls is Path: │
│ 959 │ │ │ cls = WindowsPath if os.name == 'nt' else PosixPath │
│ ❱ 960 │ │ self = cls._from_parts(args) │
│ 961 │ │ if not self._flavour.is_supported: │
│ 962 │ │ │ raise NotImplementedError("cannot instantiate %r on your │
│ 963 │ │ │ │ │ │ │ │ │ % (cls.__name__,)) │
│ │
│ ╭──────────── locals ─────────────╮ │
│ │ args = ('/',) │ │
│ │ cls = <class 'pathlib.Path'> │ │
│ │ kwargs = {} │ │
│ ╰─────────────────────────────────╯ │
│ │
│ in _from_parts:594 │
│ │
│ 591 │ │ # We need to call _parse_args on the instance, so as to get t │
│ 592 │ │ # right flavour. │
│ 593 │ │ self = object.__new__(cls) │
│ ❱ 594 │ │ drv, root, parts = self._parse_args(args) │
│ 595 │ │ self._drv = drv │
│ 596 │ │ self._root = root │
│ 597 │ │ self._parts = parts │
│ │
│ ╭──────────────────────────── locals ─────────────────────────────╮ │
│ │ args = ('/',) │ │
│ │ cls = <class 'pathlib.Path'> │ │
│ │ self = <repr-error "'Path' object has no attribute '_flavour'"> │ │
│ ╰─────────────────────────────────────────────────────────────────╯ │
│ │
│ in _parse_args:587 │
│ │
│ 584 │ │ │ │ │ │ "argument should be a str object or an os.Pat │
│ 585 │ │ │ │ │ │ "object returning str, not %r" │
│ 586 │ │ │ │ │ │ % type(a)) │
│ ❱ 587 │ │ return cls._flavour.parse_parts(parts) │
│ 588 │ │
│ 589 │ @classmethod │
│ 590 │ def _from_parts(cls, args): │
│ │
│ ╭──────────── locals ────────────╮ │
│ │ a = '/' │ │
│ │ args = ('/',) │ │
│ │ cls = <class 'pathlib.Path'> │ │
│ │ parts = ['/'] │ │
│ ╰────────────────────────────────╯ │
╰──────────────────────────────────────────────────────────────────────────────╯
AttributeError: type object 'Path' has no attribute '_flavour'
...which was itself masked by an error:
/home/io/Projects/textual-paint/.venv/lib/python3.10/site-packages/textual/_doc.py:136: in take_svg_screenshot
app.run(
/home/io/Projects/textual-paint/.venv/lib/python3.10/site-packages/textual/app.py:1207: in run
asyncio.run(run_app())
/usr/lib/python3.10/asyncio/runners.py:44: in run
return loop.run_until_complete(main)
/usr/lib/python3.10/asyncio/base_events.py:649: in run_until_complete
return future.result()
/home/io/Projects/textual-paint/.venv/lib/python3.10/site-packages/textual/app.py:1196: in run_app
await self.run_async(
/home/io/Projects/textual-paint/.venv/lib/python3.10/site-packages/textual/app.py:1168: in run_async
await app._shutdown()
/home/io/Projects/textual-paint/.venv/lib/python3.10/site-packages/textual/app.py:2186: in _shutdown
await self._close_all()
/home/io/Projects/textual-paint/.venv/lib/python3.10/site-packages/textual/app.py:2166: in _close_all
await self._prune_node(stack_screen)
/home/io/Projects/textual-paint/.venv/lib/python3.10/site-packages/textual/app.py:2656: in _prune_node
await asyncio.gather(*close_messages)
/home/io/Projects/textual-paint/.venv/lib/python3.10/site-packages/textual/message_pump.py:453: in _close_messages
await self._task
/home/io/Projects/textual-paint/.venv/lib/python3.10/site-packages/textual/message_pump.py:469: in _process_messages
await self._pre_process()
/home/io/Projects/textual-paint/.venv/lib/python3.10/site-packages/textual/message_pump.py:490: in _pre_process
self.app._handle_exception(error)
/home/io/Projects/textual-paint/.venv/lib/python3.10/site-packages/textual/app.py:1822: in _handle_exception
self._fatal_error()
/home/io/Projects/textual-paint/.venv/lib/python3.10/site-packages/textual/app.py:1827: in _fatal_error
traceback = Traceback(
/home/io/Projects/textual-paint/.venv/lib/python3.10/site-packages/rich/traceback.py:264: in __init__
trace = self.extract(
/home/io/Projects/textual-paint/.venv/lib/python3.10/site-packages/rich/traceback.py:449: in extract
locals={
/home/io/Projects/textual-paint/.venv/lib/python3.10/site-packages/rich/traceback.py:450: in <dictcomp>
key: pretty.traverse(
/home/io/Projects/textual-paint/.venv/lib/python3.10/site-packages/rich/pretty.py:852: in traverse
node = _traverse(_object, root=True)
/home/io/Projects/textual-paint/.venv/lib/python3.10/site-packages/rich/pretty.py:647: in _traverse
args = list(iter_rich_args(rich_repr_result))
/home/io/Projects/textual-paint/.venv/lib/python3.10/site-packages/rich/pretty.py:614: in iter_rich_args
for arg in rich_args:
/home/io/Projects/textual-paint/.venv/lib/python3.10/site-packages/textual/widget.py:2516: in __rich_repr__
yield "id", self.id, None
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <[AttributeError("'EnhancedDirectoryTree' object has no attribute '_id'") raised in repr()] EnhancedDirectoryTree object at 0x7f06b38c89d0>
@property
def id(self) -> str | None:
"""The ID of this node, or None if the node has no ID."""
> return self._id
E AttributeError: 'EnhancedDirectoryTree' object has no attribute '_id'. Did you mean: 'id'?
/home/io/Projects/textual-paint/.venv/lib/python3.10/site-packages/textual/dom.py:483: AttributeError
...which I worked around by adding class vars to EnhancedDirectoryTree:
_id = "some fake shit"
_name = "some more fake shit"
It was also a heisenbug. I was able to run the tests, even update snapshots, running in debug mode in VS Code.
2023-09-12 19:45:41 -04:00
Isaiah Odhner
dce55cd833
Fix further errors with pyfakefs
2023-09-12 19:45:41 -04:00
Isaiah Odhner
7f91138a63
Use pyfakefs for file dialog tests
...
- The app's directory structure is not a constant, and shouldn't play into this test. Aside from codebase restructuring, directories like `__pycache__` can come and go.
- Even if a temporary directory were created with files enough to fill the view, the scrollbar would still change based on the folder structure outside of the temporary folder.
- pyfakefs is one way to ensure a consistent view of a folder structure for testing. It allows adding real folders in a readonly way. It's more complicated than I thought it would be going in, since I had to add workarounds for pyfiglet and pytest-textual-snapshot, and handle an edge case in my EnhancedDirectoryTree (which got an error which seems to be swallowed?), not to mention pyfakefs raises an error saying "No such file or directory in the fake filesystem" when actually it's the real directory not existing when trying to add it to the fake filesystem, and VS Code was hiding stack frames and refusing to step into library code, and it turned out that I was resolving the absolute path wrong, but it looked right to me because the only part that was missing was "textual-paint", when, at a glance it seemed present, since the "textual_paint" part was present. Ay-ay-ay!
- I don't know if this will fix the problem I saw where these tests' snapshots all changed with no visual or even structural changes, just the IDs of elements changing. I don't know what caused that.
Oh yeah and this is still actually a problem:
============================================= short test summary info ==============================================
FAILED tests/test_snapshots.py::test_paint_open_dialog[light_unicode] - AttributeError: 'EnhancedDirectoryTree' object has no attribute '_id'. Did you mean: 'id'?
FAILED tests/test_snapshots.py::test_paint_open_dialog[dark_unicode] - AttributeError: 'EnhancedDirectoryTree' object has no attribute '_id'. Did you mean: 'id'?
FAILED tests/test_snapshots.py::test_paint_open_dialog[light_ascii] - AttributeError: 'EnhancedDirectoryTree' object has no attribute '_id'. Did you mean: 'id'?
FAILED tests/test_snapshots.py::test_paint_open_dialog[dark_ascii] - AttributeError: 'EnhancedDirectoryTree' object has no attribute '_id'. Did you mean: 'id'?
FAILED tests/test_snapshots.py::test_paint_save_dialog[light_unicode] - AttributeError: 'EnhancedDirectoryTree' object has no attribute '_id'. Did you mean: 'id'?
FAILED tests/test_snapshots.py::test_paint_save_dialog[dark_unicode] - AttributeError: 'EnhancedDirectoryTree' object has no attribute '_id'. Did you mean: 'id'?
FAILED tests/test_snapshots.py::test_paint_save_dialog[light_ascii] - AttributeError: 'EnhancedDirectoryTree' object has no attribute '_id'. Did you mean: 'id'?
FAILED tests/test_snapshots.py::test_paint_save_dialog[dark_ascii] - AttributeError: 'EnhancedDirectoryTree' object has no attribute '_id'. Did you mean: 'id'?
========================== 8 failed, 56 passed, 1 xfailed, 1 warning in 152.86s (0:02:32) ==========================
It worked when running in debug, but not when running normally.
2023-09-12 19:45:41 -04:00
Isaiah Odhner
bb8e968f6c
Test Free-Form Select off-screen melding bug
2023-09-12 19:45:41 -04:00
Isaiah Odhner
48b15319da
Test Select tool
2023-09-11 22:42:10 -04:00
Isaiah Odhner
2206df20bd
Test Free-Form Select tool
2023-09-11 22:37:30 -04:00
Isaiah Odhner
ad86491ada
Shorten Offset arguments
2023-09-11 22:36:31 -04:00
Isaiah Odhner
42e3104c7e
Tighten Polygon test timing
...
and find the tool button by tooltip text
2023-09-11 22:25:38 -04:00
Isaiah Odhner
ec774c264a
Test Polygon tool!
2023-09-11 22:11:02 -04:00
Isaiah Odhner
e849af1dcd
Add to todos
2023-09-11 21:42:09 -04:00
Isaiah Odhner
304f18c3f4
Import helpers instead of including them in generated code
2023-09-11 21:42:09 -04:00
Isaiah Odhner
85d601b262
Refactor tests that click a tool button
2023-09-11 21:16:13 -04:00
Isaiah Odhner
6e7a3445e0
DRY widget clicking helpers (use one in the other)
2023-09-11 20:23:15 -04:00
Isaiah Odhner
95d89a6e7f
Move Pilot test helpers to a file
2023-09-11 19:40:20 -04:00
Isaiah Odhner
7f379103a6
Accept new Text tool test snapshots
2023-09-11 19:35:04 -04:00
Isaiah Odhner
0d9f62a4c3
Skip polygon test for now
2023-09-11 19:24:41 -04:00
Isaiah Odhner
6c108294b8
Add modifier options to click_by_index
(not recorded yet)
2023-09-11 19:12:26 -04:00
Isaiah Odhner
d6399022ee
Fix/cleanup test_text_tool_cursor_keys_and_color
...
- Fix `APP_PATH` reference error
- Hold Ctrl to set the foreground color (modifiers not recorded yet)
- DRY `pilot.press`
- Use same terminal size as many other tests
- Seven isn't spelt with a 2, but zero is! ;)
2023-09-11 19:10:18 -04:00
Isaiah Odhner
3b76ba0997
Accept mysterious ID changes to file dialog snapshots
...
WITHOUT accepting new WIP Polygon and Text tool tests
2023-09-11 18:45:21 -04:00
Isaiah Odhner
5426ed14a3
Use semantic key synonym
2023-09-11 18:02:20 -04:00
Isaiah Odhner
155b0e4c99
Wait only at start of playback, not before each drag/click in test
2023-09-11 18:02:20 -04:00
Isaiah Odhner
2b447a06d6
WIP: Polygon and Text tool tests
2023-09-11 18:02:20 -04:00
Isaiah Odhner
58ddc7e856
Add a word in docstring
...
I would've named the class `TestRecorder` if the file name `test_recorder.py` wouldn't be picked up by pytest as a test file...
2023-09-11 18:02:20 -04:00
Isaiah Odhner
2d03709565
Rename placeholders to sound less hand-wavy
2023-09-11 18:02:20 -04:00
Isaiah Odhner
a844cd7967
Make output_file
a parameter; add __init__
docstring
2023-09-11 18:02:20 -04:00
Isaiah Odhner
405cc1bf4e
Make test recorder generic to apps
...
The only mention of Paint is at construction time now.
2023-09-11 18:02:20 -04:00
Isaiah Odhner
c5e96ef580
Add todos to module-level docstring
2023-09-11 18:02:20 -04:00