1+ from collections .abc import AsyncIterator
2+ from contextlib import asynccontextmanager
3+ from crystal .server import get_request_url
4+ from crystal .tests .util .server import assert_does_open_webbrowser_to , extracted_project
5+ from crystal .tests .util .windows import MainWindow , OpenOrCreateDialog
6+ from crystal .ui .log_drawer import LogDrawer
7+ from crystal .util .controls import click_button , TreeItem
18from unittest import skip
9+ import wx
10+ from wx .richtext import RichTextCtrl
211
3- # === Create ===
412
5- @skip ('not yet automated' )
6- def test_when_drawer_created_then_displays_inside_parent () -> None :
7- pass
13+ # === Test: Create ===
14+
15+ async def test_when_drawer_created_then_displays_inside_parent () -> None :
16+ async with _log_drawer_visible () as (mw , log_drawer ):
17+ # Verify the LogDrawer is maximized into the parent
18+ assert log_drawer ._is_maximized , \
19+ 'LogDrawer should be maximized into parent'
20+
21+ # Verify the LogDrawer's content (a RichTextCtrl) is inside the main window
22+ pcc = log_drawer ._parent_content_container
23+ assert pcc is not None
24+ assert isinstance (pcc , wx .SplitterWindow )
25+ assert pcc .Parent == mw .main_window , \
26+ 'LogDrawer content container should be a child of the main window'
827
28+ # Verify the splitter has two windows: the original content and the log textarea
29+ assert pcc .Window1 is not None , \
30+ 'Splitter should have the original content as Window1'
31+ assert pcc .Window2 is not None , \
32+ 'Splitter should have the log textarea as Window2'
33+ assert isinstance (pcc .Window2 , RichTextCtrl ), \
34+ 'Window2 of the splitter should be the log textarea (RichTextCtrl)'
935
10- # === Drawer Text ===
36+ # Verify the drawer is open and visible
37+ assert log_drawer .is_open , \
38+ 'LogDrawer should be open after creation'
39+
40+
41+ # === Test: Drawer Text ===
1142
1243@skip ('not yet automated' )
1344def test_when_write_colorized_text_to_writer_then_displays_colorized_text_in_drawer_and_in_stdout () -> None :
@@ -34,7 +65,7 @@ def test_always_displays_vertical_scrollbar_and_never_displays_horizontal_scroll
3465 pass
3566
3667
37- # === Drag or Double-Click Sash ===
68+ # === Test: Drag or Double-Click Sash ===
3869
3970@skip ('not yet automated' )
4071def test_when_sash_dragged_then_drawer_height_changes () -> None :
@@ -71,3 +102,33 @@ def test_given_drawer_closed_when_double_click_sash_then_drawer_opens_to_last_us
71102 # Case 2: Drawer was closed by dragging the sash far up
72103 # Case 3: Drawer was closed by dragging the drawer's south edge/corner far up
73104 pass
105+
106+
107+ # === Utility ===
108+
109+ @asynccontextmanager
110+ async def _log_drawer_visible () -> AsyncIterator [tuple [MainWindow , LogDrawer ]]:
111+ """
112+ Context manager that opens a test project, starts a server (which creates
113+ and displays the LogDrawer), and yields the MainWindow and LogDrawer.
114+ """
115+ with extracted_project ('testdata_xkcd.crystalproj.zip' ) as project_dirpath :
116+ async with (await OpenOrCreateDialog .wait_for ()).open (project_dirpath ) as (mw , _project ):
117+ # Start server by selecting a resource and clicking View
118+ root_ti = TreeItem .GetRootItem (mw .entity_tree .window )
119+ home_ti = root_ti .GetFirstChild ()
120+ assert home_ti is not None
121+ home_ti .SelectItem ()
122+ with assert_does_open_webbrowser_to (lambda : get_request_url ('https://xkcd.com/' )):
123+ click_button (mw .view_button )
124+
125+ # Find the LogDrawer among the top-level windows
126+ log_drawers = [
127+ w for w in wx .GetTopLevelWindows ()
128+ if isinstance (w , LogDrawer )
129+ ]
130+ assert len (log_drawers ) == 1 , \
131+ f'Expected exactly 1 LogDrawer, found { len (log_drawers )} '
132+ log_drawer = log_drawers [0 ]
133+
134+ yield (mw , log_drawer )
0 commit comments