1+ import pytest
2+ from unittest .mock import MagicMock , patch
3+
4+ from jupyter_server_documents .kernels .kernel_client import DocumentAwareKernelClient
5+ from jupyter_server_documents .kernels .message_cache import KernelMessageCache
6+ from jupyter_server_documents .outputs import OutputProcessor
7+
8+
9+ class TestDocumentAwareKernelClient :
10+ """Test cases for DocumentAwareKernelClient."""
11+
12+ def test_default_message_cache (self ):
13+ """Test that message cache is created by default."""
14+ client = DocumentAwareKernelClient ()
15+ assert isinstance (client .message_cache , KernelMessageCache )
16+
17+ def test_default_output_processor (self ):
18+ """Test that output processor is created by default."""
19+ client = DocumentAwareKernelClient ()
20+ assert isinstance (client .output_processor , OutputProcessor )
21+
22+ @pytest .mark .asyncio
23+ async def test_stop_listening_no_task (self ):
24+ """Test that stop_listening does nothing when no task exists."""
25+ client = DocumentAwareKernelClient ()
26+ client ._listening_task = None
27+
28+ # Should not raise an exception
29+ await client .stop_listening ()
30+
31+ def test_add_listener (self ):
32+ """Test adding a listener."""
33+ client = DocumentAwareKernelClient ()
34+
35+ def test_listener (channel , msg ):
36+ pass
37+
38+ client .add_listener (test_listener )
39+
40+ assert test_listener in client ._listeners
41+
42+ def test_remove_listener (self ):
43+ """Test removing a listener."""
44+ client = DocumentAwareKernelClient ()
45+
46+ def test_listener (channel , msg ):
47+ pass
48+
49+ client .add_listener (test_listener )
50+ client .remove_listener (test_listener )
51+
52+ assert test_listener not in client ._listeners
53+
54+ @pytest .mark .asyncio
55+ async def test_add_yroom (self ):
56+ """Test adding a YRoom."""
57+ client = DocumentAwareKernelClient ()
58+
59+ mock_yroom = MagicMock ()
60+ await client .add_yroom (mock_yroom )
61+
62+ assert mock_yroom in client ._yrooms
63+
64+ @pytest .mark .asyncio
65+ async def test_remove_yroom (self ):
66+ """Test removing a YRoom."""
67+ client = DocumentAwareKernelClient ()
68+
69+ mock_yroom = MagicMock ()
70+ client ._yrooms .add (mock_yroom )
71+
72+ await client .remove_yroom (mock_yroom )
73+
74+ assert mock_yroom not in client ._yrooms
75+
76+ def test_send_kernel_info_creates_message (self ):
77+ """Test that send_kernel_info creates a kernel info message."""
78+ client = DocumentAwareKernelClient ()
79+
80+ # Mock session
81+ from jupyter_client .session import Session
82+ client .session = Session ()
83+
84+ with patch .object (client , 'handle_incoming_message' ) as mock_handle :
85+ client .send_kernel_info ()
86+
87+ # Verify that handle_incoming_message was called with shell channel
88+ mock_handle .assert_called_once ()
89+ args , kwargs = mock_handle .call_args
90+ assert args [0 ] == "shell" # Channel name
91+ assert isinstance (args [1 ], list ) # Message list
92+
93+ @pytest .mark .asyncio
94+ async def test_handle_outgoing_message_control_channel (self ):
95+ """Test that control channel messages bypass document handling."""
96+ client = DocumentAwareKernelClient ()
97+
98+ msg = [b"test" , b"message" ]
99+
100+ with patch .object (client , 'handle_document_related_message' ) as mock_handle_doc :
101+ with patch .object (client , 'send_message_to_listeners' ) as mock_send :
102+ await client .handle_outgoing_message ("control" , msg )
103+
104+ mock_handle_doc .assert_not_called ()
105+ mock_send .assert_called_once_with ("control" , msg )
0 commit comments