
    wg+                     D    d dl Z d dlmZ d dlmZ d dlmZ  G d d      Zy)    N)packet)PubSubManager)EnvironBuilderc                   R    e Zd ZdZi Z	 	 d
dZddZ	 	 ddZddZd Z	ddZ
dd	Zy)SocketIOTestClienta  
    This class is useful for testing a Flask-SocketIO server. It works in a
    similar way to the Flask Test Client, but adapted to the Socket.IO server.

    :param app: The Flask application instance.
    :param socketio: The application's ``SocketIO`` instance.
    :param namespace: The namespace for the client. If not provided, the client
                      connects to the server on the global namespace.
    :param query_string: A string with custom query string arguments.
    :param headers: A dictionary with custom HTTP headers.
    :param auth: Optional authentication data, given as a dictionary.
    :param flask_test_client: The instance of the Flask test client
                              currently in use. Passing the Flask test
                              client is optional, but is necessary if you
                              want the Flask user session and any other
                              cookies set in HTTP routes accessible from
                              Socket.IO events.
    Nc                    	
  fd
d 		
fd}| _         | _        t        j                         j                   _          j                   j
                  <   d _        | _        i  _	        g  _
        d  _        
|j                  _        ||j                  _        i |j                  j                   j
                  <   d|j                  _        d|j                  j"                  _        t%        |j                  j&                  t(              rt+        d      |j                  j&                  j-                           j/                  ||||       y )Nc                 B   |j                         }t        |t              st        j                  |      }n4t        j                  |d         }|dd  D ]  }|j                  |        j                  j                  |       }|sy |j                  t        j                  k(  s|j                  t        j                  k(  r|j                  d   dk(  s|j                  d   dk(  rH|j                  j                  |j                  d   |j                  d   |j                  xs dd       y |j                  j                  |j                  d   |j                  dd  |j                  xs dd       y |j                  t        j                  k(  s|j                  t        j                   k(  r#|j                  |j                  xs dd|_        y |j                  t        j$                  t        j&                  fv rd	|j(                  |j                  xs d<   y y )
Nencoded_packetr      messagejson/)nameargs	namespace)r   r   F)encode
isinstancelistr   Packetadd_attachmentclientsgetpacket_typeEVENTBINARY_EVENTdataqueueappendr   ACK
BINARY_ACKacks
DISCONNECTCONNECT_ERROR	connected)eio_sidpktepktattclientselfs        _/home/mcse/projects/flask/flask-venv/lib/python3.12/site-packages/flask_socketio/test_client.py_mock_send_packetz6SocketIOTestClient.__init__.<locals>._mock_send_packet   s   ::<DdD)mm48mm47;8 ,C&&s+,\\%%g.F&,,.OOv':'::88A;)+sxx{f/DLL'' # #%(]]%9c); <
 LL'' # #%(]]%9c); < FJJ.OOv'8'88'*xx,/MM,@SBV%6%68L8L$MM9>  !5#6 N    c                    Jj                  |j                         j                  t        j                        k(  r |        d y y t        j                  |j                        }|j                  dk(  r
 | |       y |y )Nr
   r   )r   r   attachment_countlenattachmentsr   r   )r&   eio_pktr'   _current_packetr-   s      r,   _mock_send_eio_packetz:SocketIOTestClient.__init__.<locals>._mock_send_eio_packet@   s|    *..w||<"33O7789%g?&*O9
 mm7<<@''1,%gs3&)Or.   r   Fz^Test client cannot be used with a message queue. Disable the queue on your test configuration.)r   query_stringheadersauth)appflask_test_clientuuiduuid4hexr&   r   callback_countersocketior%   r   r"   server_send_packet_send_eio_packetenvironasync_handlerseior   managerr   RuntimeError
initializeconnect)r+   r9   r?   r   r6   r7   r8   r:   r5   r4   r-   s   `        @@r,   __init__zSocketIOTestClient.__init__   s   	?> 	* !2zz|''%)T\\" ! 
	'8$+@(02-).&-2*hoo--}=  0 1 1 	**,y|$4 	 	1r.   c                 B    | j                   j                  |xs dd      S )zCheck if a namespace is connected.

        :param namespace: The namespace to check. The global namespace is
                         assumed if this argument is not provided.
        r   F)r%   r   )r+   r   s     r,   is_connectedzSocketIOTestClient.is_connectede   s      ~~!!)"2sE::r.   c                    d}|xs d}|r|d   dk7  rd|z   }||z  }t        ||      j                         }| j                  |d<   | j                  rWt	        | j                  d      r| j                  j                  |       n%| j                  j                  j                  |       | j                  j                  j                  | j                  |       t        j                  t        j                  ||      }| j                  j                  j                  | j                  |j!                                | j                  j                  j"                  j%                  | j                  |      }|rd	| j&                  |<   y
y
)a  Connect the client.

        :param namespace: The namespace for the client. If not provided, the
                          client connects to the server on the global
                          namespace.
        :param query_string: A string with custom query string arguments.
        :param headers: A dictionary with custom HTTP headers.
        :param auth: Optional authentication data, given as a dictionary.

        Note that it is usually not necessary to explicitly call this method,
        since a connection is automatically established when an instance of
        this class is created. An example where it this method would be useful
        is when the application accepts multiple namespace connections.
        z
/socket.ior   r   ?)r7   z	flask.app_add_cookies_to_wsgir   TN)r   get_environr9   r:   hasattrrO   
cookie_jarinject_wsgir?   r@   _handle_eio_connectr&   r   r   CONNECT_handle_eio_messager   rF   sid_from_eio_sidr%   )	r+   r   r6   r7   r8   urlrC   r'   sids	            r,   rI   zSocketIOTestClient.connectm   s;     $	A#%"\1<C g6BBD#xx!!t--/EF&&;;GD &&11==gF00wGmmFNNDIF00szz|Lmm""**;;DLL<EG(,DNN9% r.   c                 $   | j                  |      st        d      t        j                  t        j                  |      }| j
                  j                  j                  | j                  |j                                | j                  |xs d= y)zDisconnect the client.

        :param namespace: The namespace to disconnect. The global namespace is
                         assumed if this argument is not provided.
        not connectedrP   r   N)rL   rG   r   r   r#   r?   r@   rW   r&   r   r%   )r+   r   r'   s      r,   
disconnectzSocketIOTestClient.disconnect   sh       +//mmF--C00szz|LNN9+,r.   c                    |j                  dd      }| j                  |      st        d      |j                  dd      }d}|r!| xj                  dz  c_        | j                  }t	        j
                  t        j                  |gt        |      z   ||      }|j                         }t        |t              r8|D ]2  }	| j                  j                  j                  | j                  |	       4 n0| j                  j                  j                  | j                  |       | j                  1| j                  }
d| _        t        |
d         dk(  r|
d   d	   S |
d   S y)
a  Emit an event to the server.

        :param event: The event name.
        :param *args: The event arguments.
        :param callback: ``True`` if the client requests a callback, ``False``
                         if not. Note that client-side callbacks are not
                         implemented, a callback request will just tell the
                         server to provide the arguments to invoke the
                         callback, but no callback is invoked. Instead, the
                         arguments that the server provided for the callback
                         are returned by this function.
        :param namespace: The namespace of the event. The global namespace is
                          assumed if this argument is not provided.
        r   Nr\   callbackFr   )r   r   idr   r   )poprL   rG   r>   r   r   r   r   r   r   r?   r@   rW   r&   r"   r1   )r+   eventr   kwargsr   r_   r`   r'   encoded_pktr(   acks              r,   emitzSocketIOTestClient.emit   s6    JJ{D1	  +//::j%0!!Q&!&&BmmFLLwd/C&/B8jjlk4(# M$$88tLM MM  44T\\;O99 ))CDI%(V%5%:3v;q> ![! !r.   c                 :    |rd}nd}| j                  ||||      S )ax  Send a text or JSON message to the server.

        :param data: A string, dictionary or list to send to the server.
        :param json: ``True`` to send a JSON message, ``False`` to send a text
                     message.
        :param callback: ``True`` if the client requests a callback, ``False``
                         if not. Note that client-side callbacks are not
                         implemented, a callback request will just tell the
                         server to provide the arguments to invoke the
                         callback, but no callback is invoked. Instead, the
                         arguments that the server provided for the callback
                         are returned by this function.
        :param namespace: The namespace of the event. The global namespace is
                          assumed if this argument is not provided.
        r   r   )r_   r   )rf   )r+   r   r   r_   r   msgs         r,   sendzSocketIOTestClient.send   s(      CCyydXyKKr.   c                     | j                  |      st        d      |xs d}| j                  D cg c]  }|d   |k(  s| }}| j                  D cg c]	  }||vs| c}| _        |S c c}w c c}w )a  Return the list of messages received from the server.

        Since this is not a real client, any time the server emits an event,
        the event is simply stored. The test code can invoke this method to
        obtain the list of events that were received since the last call.

        :param namespace: The namespace to get events from. The global
                          namespace is assumed if this argument is not
                          provided.
        r\   r   r   )rL   rG   r   )r+   r   r'   rs       r,   get_receivedzSocketIOTestClient.get_received   st       +//$	 JJHS#k*:i*GSHH%)ZZ@c3a<c@
 I@s   A+A+	A0A0)NNNNN)N)NNNN)FFN)__name__
__module____qualname____doc__r   rJ   rL   rI   r]   rf   ri   rl    r.   r,   r   r      sF    $ GCG<@F1P; BF&-P
-#!JL,r.   r   )r;   r?   r   socketio.pubsub_managerr   werkzeug.testr   r   rq   r.   r,   <module>rt      s      1 (d dr.   