U
    /e,                     @  s  d Z ddlmZ ddlZeeZddlZddlZddl	m
Z
 ddlmZ ddlmZmZmZmZmZ ddlZddlmZ ddlmZ dd	lmZ dd
lmZ ddlmZ ddlm Z  erddl!m"Z" ddl#m$Z$ ddl%m&Z& ddl'm(  m)  m*Z* ddl+m,Z,m-Z-m.Z. ddl/m0Z0 ddl1m2Z2 erLddl3m4Z4 ddl5m6Z6 ddl7m8Z8 dZ9dZ:ej;ddddddZ<ej;dddddd Z=G d!d" d"eZ>d#d$d%d&Z?G d'd( d(e Z@G d)d* d*e ZAej;dd+d(d,d-d.ZBG d/d0 d0ZCG d1d2 d2eCZDG d3d4 d4eCZEG d5d6 d6eEZFe; d+dd*d7d8d9d:ZGG d;d< d<eFeDZHe; d+dd*d=d8d>d?ZIG d@dA dAeEeDZJe; d+d(d*dBdCdDdEZKdS )Fz< Define a Pytest plugin for a Bokeh-specific testing tools

    )annotationsN)closing)Thread)TYPE_CHECKINGAnyCallableDictTuple)ActionChains)expected_conditions)WebDriverWait)IOLoop)RequestHandler)Protocol)_KeySeq)	WebDriver)
WebElement)INITRESULTSwait_for_canvas_resize)save)Server)SimpleWebServer)	ModifyDoc)	LayoutDOM)zbokeh._testing.plugins.projectz"bokeh._testing.plugins.file_serverzbokeh._testing.plugins.selenium)bokeh_app_infobokeh_model_pagebokeh_server_pagefind_free_portoutput_file_urlsingle_plot_pagetest_file_path_and_urlzpytest.FixtureRequestr   str)requestfile_serverreturnc                   sl   ddl m} | jjd }| j |  j}|dd}||dd dd	 fd
d}| 	| |
|S )Nr   )output_file.html\/inline)modeNoner%   c                     s      r   d S Nisfileremove Zfile_objr2   B/tmp/pip-unpacked-wheel-f5fndrjf/bokeh/_testing/plugins/project.py	tear_down_   s    z"output_file_url.<locals>.tear_down)bokeh.ior&   function__name__fspathdirpathjoinstrpathreplaceaddfinalizerwhere_is)r#   r$   r&   filename	file_pathurlr5   r2   r3   r4   r   U   s    
r   zTuple[str, str]c                   sX   | j jd }| j |  j}|dd}dd fdd}| | |||fS )Nr'   r(   r)   r,   r-   c                     s      r   d S r.   r/   r2   r3   r2   r4   r5   m   s    z)test_file_path_and_url.<locals>.tear_down)	r7   r8   r9   r:   r;   r<   r=   r>   r?   )r#   r$   r@   rA   rB   r5   r2   r3   r4   r!   f   s    
r!   c                   @  s.   e Zd ZdddddZdddddd	Zd
S )_ExitHandlerr   r,   )io_loopr%   c                 C  s
   || _ d S r.   rD   )selfrD   r2   r2   r4   
initializev   s    z_ExitHandler.initializer   )argskwargsr%   c                   s   | j   d S r.   )rD   stop)rF   rH   rI   r2   r2   r4   getx   s    z_ExitHandler.getN)r8   
__module____qualname__rG   rK   r2   r2   r2   r4   rC   u   s   rC   intr-   c               
   C  sB   t ttjtj$} | d |  d W  5 Q R  S Q R X d S )N) r      )r   socketAF_INETSOCK_STREAMbindgetsockname)sr2   r2   r4   r   |   s    
r   c                   @  s   e Zd ZdddddZdS )BokehAppInfor   Tuple[str, ws.MessageTestPort]
modify_docr%   c                 C  s   d S r.   r2   )rF   rZ   r2   r2   r4   __call__       zBokehAppInfo.__call__Nr8   rL   rM   r[   r2   r2   r2   r4   rW      s   rW   c                   @  s   e Zd ZdddddZdS )HasNoConsoleErrorsr   bool)	webdriverr%   c                 C  s   d S r.   r2   )rF   r`   r2   r2   r4   r[      r\   zHasNoConsoleErrors.__call__Nr]   r2   r2   r2   r4   r^      s   r^   r   )r#   driverr%   c                   s   ddd fdd}|S )a$   Start a Bokeh server app and return information needed to test it.

    Returns a tuple (url, message_test_port), where the latter is an instance of
    ``MessageTestPort`` dataclass, and will contain all messages that the Bokeh
    Server sends/receives while running during the test.

    r   rX   rY   c                   sn   t jg g dt _t dd fdd}t|d  ddfdd}| d	 d
t jfS )N)sentZreceivedr,   r-   c               	     s>   t  } td i| dtt| dfgd}|  |j  d S )Nr)   /exitrE   )portrD   Zextra_patterns)r   r   rC   dictstartrD   )rD   server)rZ   rd   r2   r4   worker   s    z,bokeh_app_info.<locals>.func.<locals>.worker)targetc                     s.     d d  d d t_  d S )Nhttp://localhost:rc   Zbrowser)rK   Zget_logws_message_test_portr;   r2   )ra   rd   tr2   r4   cleanup   s    
z-bokeh_app_info.<locals>.func.<locals>.cleanuprj   r)   )rk   ZMessageTestPortrl   r   r   rf   r>   )rZ   rh   rn   ra   r#   )rZ   rd   rm   r4   func   s    	


zbokeh_app_info.<locals>.funcr2   )r#   ra   rp   r2   ro   r4   r      s    
r   c                	   @  sj   e Zd ZU ded< dddddddZdddddd	d
ZdddddddddddZdddddZdS )_ElementMixinr   _driverr   rN   r,   )elementxyr%   c                 C  s,   t | j}|||| |  |  d S r.   r
   rr   move_to_element_with_offsetclickperformrF   rs   rt   ru   actionsr2   r2   r4   click_element_at_position   s    
z'_ElementMixin.click_element_at_positionc                 C  s4   t | j}|||| |  |  |  d S r.   rv   rz   r2   r2   r4    double_click_element_at_position   s
    
z._ElementMixin.double_click_element_at_positionN_KeySeq | None)rs   rt   ru   dxdymodr%   c                 C  s\   t | j}|r|| |||| |  ||| |  |rP|| |  d S r.   )	r
   rr   Zkey_downrw   Zclick_and_holdZmove_by_offsetreleaseZkey_upry   )rF   rs   rt   ru   r   r   r   r{   r2   r2   r4   drag_element_at_position   s    


z&_ElementMixin.drag_element_at_positionr   )keysr%   c                 G  s    t | j}|j|  |  d S r.   )r
   rr   	send_keysry   )rF   r   r{   r2   r2   r4   r      s    

z_ElementMixin.send_keys)N)r8   rL   rM   __annotations__r|   r}   r   r   r2   r2   r2   r4   rq      s
   
rq   c                   @  sr   e Zd ZU ded< ddddddZdddddd	Zdd
ddZddddddddddZdddddZdS )_CanvasMixinr   canvasrN   r,   )rt   ru   r%   c                 C  s   |  | j|| d S r.   )r|   r   rF   rt   ru   r2   r2   r4   click_canvas_at_position   s    z%_CanvasMixin.click_canvas_at_positionc                 C  s   |  | j|| d S r.   )r}   r   r   r2   r2   r4   double_click_canvas_at_position   s    z,_CanvasMixin.double_click_canvas_at_positionr-   c                 C  s   | j d}|  d S )Nzbk-toolbar-button-custom-action)rr   find_element_by_class_namerx   )rF   buttonr2   r2   r4   click_custom_action   s    z _CanvasMixin.click_custom_actionNr~   )rt   ru   r   r   r   r%   c                 C  s   |  | j||||| d S r.   )r   r   )rF   rt   ru   r   r   r   r2   r2   r4   drag_canvas_at_position   s    z$_CanvasMixin.drag_canvas_at_positionr"   )namer%   c                 C  s   | j d| S )Nzbk-tool-icon-)rr   r   )rF   r   r2   r2   r4   get_toolbar_button   s    z_CanvasMixin.get_toolbar_button)N)	r8   rL   rM   r   r   r   r   r   r   r2   r2   r2   r4   r      s   
r   c                   @  sf   e Zd ZU ded< ded< ded< eddd	d
ZeddddZddddZddddZdS )_BokehPageMixinr   test_divr   rr   r^   _has_no_console_errorszDict[str, Any]r-   c                 C  s4   t | jdt| j | jd| _| jtS )N
   bokeh-test-div)	r   rr   ZuntilECZstaleness_ofr   r   execute_scriptr   rF   r2   r2   r4   results   s    z_BokehPageMixin.resultsc                 C  s   | j S r.   )rr   r   r2   r2   r4   ra      s    z_BokehPageMixin.driverr,   c                 C  s   | j t | j d| _d S )Nr   )rr   r   r   r   r   r   r2   r2   r4   init_results   s    z_BokehPageMixin.init_resultsr_   c                 C  s   |  | jS r.   )r   rr   r   r2   r2   r4   has_no_console_errors   s    z%_BokehPageMixin.has_no_console_errorsN)	r8   rL   rM   r   propertyr   ra   r   r   r2   r2   r2   r4   r      s   
r   c                   @  s"   e Zd ZddddddddZd	S )
_BokehModelPager   r   r"   r^   r,   modelra   r   r   r%   c                 C  s4   || _ || _|| _t| j | j | |   d S r.   )rr   _modelr   r   rK   r   rF   r   ra   r   r   r2   r2   r4   __init__   s    
z_BokehModelPage.__init__Nr8   rL   rM   r   r2   r2   r2   r4   r      s   r   z&Callable[[LayoutDOM], _BokehModelPage])ra   r   r   r%   c                   s   ddd fdd}|S )Nr   r   r   r%   c                   s   t |  S r.   )r   r   ra   r   r   r2   r4   rp   	  s    zbokeh_model_page.<locals>.funcr2   ra   r   r   rp   r2   r   r4   r     s    r   c                      s*   e Zd Zdddddd fddZ  ZS )	_SinglePlotPager   r   r"   r^   r,   r   c                   s2   t  |||| | jd| _t| j| j d S )Nr   )superr   rr   find_element_by_tag_namer   r   r   	__class__r2   r4   r     s    z_SinglePlotPage.__init__)r8   rL   rM   r   __classcell__r2   r2   r   r4   r     s   r   z&Callable[[LayoutDOM], _SinglePlotPage]c                   s   ddd fdd}|S )Nr   r   r   c                   s   t |  S r.   )r   r   r   r2   r4   rp     s    zsingle_plot_page.<locals>.funcr2   r   r2   r   r4   r      s    r    c                   @  s"   e Zd ZddddddddZd	S )
_BokehServerPager   r   rW   r^   r,   )rZ   ra   r   r   r%   c                 C  s\   || _ || _||\| _| _td | j | j |   | j d| _	t
| j	| j  d S )Ng?r   )rr   r   Z_app_urlZmessage_test_porttimesleeprK   r   r   r   r   )rF   rZ   ra   r   r   r2   r2   r4   r     s    
z_BokehServerPage.__init__Nr   r2   r2   r2   r4   r     s   r   z'Callable[[ModifyDoc], _BokehServerPage])ra   r   r   r%   c                   s   ddd fdd}|S )Nr   r   rY   c                   s   t |  S r.   )r   )rZ   r   ra   r   r2   r4   rp   /  s    zbokeh_server_page.<locals>.funcr2   )ra   r   r   rp   r2   r   r4   r   ,  s    r   )L__doc__
__future__r   logging	getLoggerr8   logrQ   r   
contextlibr   	threadingr   typingr   r   r   r   r	   ZpytestZ'selenium.webdriver.common.action_chainsr
   Zselenium.webdriver.supportr   r   Zselenium.webdriver.support.waitr   Ztornado.ioloopr   Ztornado.webr   Ztyping_extensionsr   Zselenium.webdriver.common.keysr   Z#selenium.webdriver.remote.webdriverr   Z$selenium.webdriver.remote.webelementr   Zbokeh.server.views.wsrg   Zviewsrk   Zbokeh._testing.util.seleniumr   r   r   r6   r   Zbokeh.server.serverr   Z"bokeh._testing.plugins.file_serverr   Z#bokeh.application.handlers.functionr   Zbokeh.models.layoutsr   Zpytest_plugins__all__Zfixturer   r!   rC   r   rW   r^   r   rq   r   r   r   r   r   r    r   r   r2   r2   r2   r4   <module>   sf   
	(!	