+
    bdKj.  c                       R t ^ RIt^ RIHu Ht ^ RIHt ^ RI	H
t
 ^ RIHt ]
! ]4      t ! R R4      tR tR tR	 tR
 tR tR tR tR tR tR# )zSmoke tests wiring each endpoint against a FakeProvider (no real API key needed) -
these exist to prove the FastAPI routes, pydantic schemas, and error handling are
wired correctly, not to test any particular LLM's output quality.
N)patch)
TestClient)appc                   0   a  ] tR t^t o RR ltR tRtV tR# )FakeProviderNc                    Wn         W n        R # N)resulterror)selfr   r	   s   &&&<C:\xampp\htdocs\meridian\meridian-ai\tests\test_endpoints.py__init__FakeProvider.__init__   s    
    c                V    V P                   '       d   V P                   hV P                  # r   r	   r   )r
   system_promptmessagess   &&&r   complete_jsonFakeProvider.complete_json   s    :::**{{r   r   )NN)__name__
__module____qualname____firstlineno__r   r   __static_attributes____classdictcell__)__classdict__s   @r   r   r      s      r   r   c            	      :   \         P                  R 4      p V P                  p^q!V8H  q3'       g   \        P                  ! RV3RW34      RR\
        P                  ! 4       9   g   \        P                  ! V 4      '       d   \        P                  ! V 4      MRR\        P                  ! V4      R\        P                  ! V4      /,          pRRV/,          p\        \        P                  ! V4      4      hR;p;r2V P                  4       R,          pR	q6V8H  qw'       gy   \        P                  ! RV3RWc34      R
\        P                  ! V4      R\        P                  ! V4      /,          pRRV/,          p	\        \        P                  ! V	4      4      hR;p;rsR# )z/healthpy0responsepy2py5assert %(py7)spy7Nstatusokpy1py4assert %(py6)spy6==z3%(py2)s
{%(py2)s = %(py0)s.status_code
} == %(py5)sz%(py1)s == %(py4)s)clientgetstatus_code
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanationjson
r   @py_assert1@py_assert4@py_assert3@py_format6@py_format8@py_assert0@py_assert2@py_format5@py_format7s
             r   test_healthrC      s    zz)$H&3&3&&&&&&&&&&&8&&&&8&&&&&&3&&&&&&&&==?8$,,,,,,,$,,,$,,,,,,,,,,,r   c                     R RRRRRRRRR	R
RRRRR/RRRRRRRRR.RR
^PRRRR//////./p \        R\        V R7      R7      ;_uu_ 4        \        P                  RRRR^/R 7      pR!R!R!4       XP                  p^q2V8H  qD'       g   \
        P                  ! R,V3R-W#34      R"R#\        P                  ! 4       9   g   \
        P                  ! V4      '       d   \
        P                  ! V4      MR#R$\
        P                  ! V4      R%\
        P                  ! V4      /,          pR&R'V/,          p\        \
        P                  ! V4      4      hR!;p;rCVP                  4       pVR ,          ^ ,          R,          pRqHV8H  q'       gy   \
        P                  ! R,V	3R.W34      R(\
        P                  ! V4      R)\
        P                  ! V4      /,          p
R*R+V
/,          p\        \
        P                  ! V4      4      hR!;p;rVR ,          ^ ,          R,          pRqHVJ q'       gy   \
        P                  ! R/V	3R0W34      R(\
        P                  ! V4      R)\
        P                  ! V4      /,          p
R*R+V
/,          p\        \
        P                  ! V4      4      hR!;p;rVR ,          ^ ,          R,          R,          R,          R,          R,          pRR.qHV8H  q'       gy   \
        P                  ! R,V	3R.W34      R(\
        P                  ! V4      R)\
        P                  ! V4      /,          p
R*R+V
/,          p\        \
        P                  ! V4      4      hR!;p;rR!#   + '       g   i     EL; i)1optionsletterAnamezNairobi Wildlife Adventure
is_ai_pickTsummaryzA wildlife-focused trip.
total_costamounti`	  currencyUSDis_estimatedays1titleArrivaldestinationsNairobi
activitieszevening clubbingdinnerestimated_cost#app.services.itinerary.get_providerr   return_value/generate_itinerary
trip_briefz4-day wildlife trip to Kenyanum_optionsr8   Nr   r   r   r    r!   r"   r%   r&   r'   r(   r)   r+   r,   )is)z%(py1)s is %(py4)sr   r   r-   postr/   r0   r1   r2   r3   r4   r5   r6   r7   r8   )fake_resultr   r:   r;   r<   r=   r>   bodyr?   r@   rA   rB   s               r   test_generate_itinerary_successrf       s   #4d5xz5-QUV&% ,/A8.L 08RUTacg2h()

K, 
4<WbCc	d	d;;! >qQ  
 
e
 &3&3&&&&&&&&&&&8&&&&8&&&&&&3&&&&&&&&==?D	?1h'.3.3.....'...'...3........	?1l+3t3t33333+333+333t33333333	?1f%c*>:9ElS X  X    S   S    X         
e	d	ds   M%%M6	c            	         \        R \        \        R4      R7      R7      ;_uu_ 4        \        P	                  RRR/R7      p RRR4       X P
                  pR	q!V8H  q3'       g   \        P                  ! RV3RW34      R
R\        P                  ! 4       9   g   \        P                  ! V 4      '       d   \        P                  ! V 4      MRR\        P                  ! V4      R\        P                  ! V4      /,          pRRV/,          p\        \        P                  ! V4      4      hR;p;r2V P                  4       R,          R,          pRq6V8H  qw'       gy   \        P                  ! RV3RWc34      R\        P                  ! V4      R\        P                  ! V4      /,          pRRV/,          p	\        \        P                  ! V	4      4      hR;p;rsR#   + '       g   i     EL; i)rY   boom)r	   r[   r]   r^   tripr`   N  r   r   r   r    r!   r"   r	   codeLLM_GENERATION_FAILEDr%   r&   r'   r(   r)   r+   r,   )r   r   RuntimeErrorr-   rc   r/   r0   r1   r2   r3   r4   r5   r6   r7   r8   r9   s
             r   4test_generate_itinerary_provider_failure_returns_502rn   F   s   	4<VbciVjCk	l	l;;4L&;Q;R 
m&3&3&&&&&&&&&&&8&&&&8&&&&&&3&&&&&&&&==?7#F+F/FF/FFFFFF+FFF+FFF/FFFFFFFFF 
m	l	ls   GG*	c            	         \        R \        RRR/./R7      R7      ;_uu_ 4        \        P                  RRR/R	7      p R
R
R
4       X P                  pRq!V8H  q3'       g   \
        P                  ! RV3RW34      RR\        P                  ! 4       9   g   \
        P                  ! V 4      '       d   \
        P                  ! V 4      MRR\
        P                  ! V4      R\
        P                  ! V4      /,          pRRV/,          p\        \
        P                  ! V4      4      hR
;p;r2V P                  4       R,          R,          pRq6V8H  qw'       gy   \
        P                  ! RV3RWc34      R\
        P                  ! V4      R\
        P                  ! V4      /,          pRRV/,          p	\        \
        P                  ! V	4      4      hR
;p;rsR
#   + '       g   i     EL; i)rY   rE   rF   rG   rZ   r[   r]   r^   ri   r`   Nrj   r   r   r   r    r!   r"   r	   rk   LLM_RESPONSE_INVALIDr%   r&   r'   r(   r)   r+   r,   rb   r9   s
             r   6test_generate_itinerary_malformed_response_returns_502rq   M   s'   	4<XaemordsctWuCv	w	w;;4L&;Q;R 
x&3&3&&&&&&&&&&&8&&&&8&&&&&&3&&&&&&&&==?7#F+E/EE/EEEEEE+EEE+EEE/EEEEEEEEE 
x	w	ws   GG&	c            
         R RRRRRRRRR	././p \        R
\        V R7      R7      ;_uu_ 4        \        P                  RRR/R7      pRRR4       XP                  p^q2V8H  qD'       g   \
        P                  ! RV3RW#34      RR\        P                  ! 4       9   g   \
        P                  ! V4      '       d   \
        P                  ! V4      MRR\
        P                  ! V4      R\
        P                  ! V4      /,          pRRV/,          p\        \
        P                  ! V4      4      hR;p;rCVP                  4       R ,          ^ ,          R,          pRqGV8H  q'       gy   \
        P                  ! RV3RWt34      R\
        P                  ! V4      R\
        P                  ! V4      /,          p	RRV	/,          p
\        \
        P                  ! V
4      4      hR;p;rR#   + '       g   i     EL; i)	questionsidq_01textzWhat's your budget?typesingle_choicerE   LowHigh#app.services.questions.get_providerrZ   r[   /suggest_questionsr^   zTrip to Japanr`   Nr   r   r   r    r!   r"   r%   r&   r'   r(   r)   r+   r,   rb   rd   r   r:   r;   r<   r=   r>   r?   r@   rA   rB   s              r   test_suggest_questionsr~   U   sH   66#8&/S\_dfl^mn
K
 
4<WbCc	d	d;;3<:Y;Z 
e&3&3&&&&&&&&&&&8&&&&8&&&&&&3&&&&&&&&==?;'*40:F:F:::::0:::0:::F:::::::: 
e	d	ds   G&&G7	c            
         R RRRR/.RR./p \        R\        V R7      R	7      ;_uu_ 4        \        P                  R
RRRRR/./R7      pRRR4       XP                  p^q2V8H  qD'       g   \
        P                  ! RV3RW#34      RR\        P                  ! 4       9   g   \
        P                  ! V4      '       d   \
        P                  ! V4      MRR\
        P                  ! V4      R\
        P                  ! V4      /,          pRRV/,          p\        \
        P                  ! V4      4      hR;p;rCVP                  4       R ,          ^ ,          R,          pRqGV8H  q'       gy   \
        P                  ! RV3RWt34      R\
        P                  ! V4      R\
        P                  ! V4      /,          p	RRV	/,          p
\        \
        P                  ! V
4      4      hR;p;rR#   + '       g   i     EL; i)suggestionsrv   zYes, breakfast is included!tonefriendlycontext_usedztrip: Santorinizapp.services.reply.get_providerrZ   r[   z/suggest_responseconversation_historyroleusercontentz Does option A include breakfast?r`   Nr   r   r   r    r!   r"   r%   r&   r'   r(   r)   r+   r,   rb   r}   s              r   test_suggest_responser   a   sS   !>
ST*+K 
0|S^?_	`	`;;(FFIGi+j*kl  
 
a
 &3&3&&&&&&&&&&&8&&&&8&&&&&&3&&&&&&&&==?=)!,V4B
B
BBBBB4BBB4BBB
BBBBBBBB 
a	`	`s   G((G9	c                     ^ RI Hp  ^ RIHp V ! RRR7      V ! RRR7      V ! RRR7      .pV! V4      pV Uu. uF  qDR	,          NK  	  ppRR.qeV8H  qw'       gy   \        P
                  ! RV3RWV34      R
\        P                  ! V4      R\        P                  ! V4      /,          pRRV/,          p	\        \        P                  ! V	4      4      hR;p;rvV^ ,          R,          pRqeV8H  qw'       gy   \        P
                  ! RV3RWV34      R
\        P                  ! V4      R\        P                  ! V4      /,          pRRV/,          p	\        \        P                  ! V	4      4      hR;p;rvR# u upi )    )ChatMessage)_to_alternating_messagesr   Hi)r   r   zAre you there?	assistantzYes!r   r%   r&   r'   r(   Nr   zHi
Are you there?r)   r,   )	app.schemasr   app.services.replyr   r0   r1   r5   r6   r7   )
r   r   historymergedmr?   r<   r@   rA   rB   s
             r   ;test_suggest_response_collapses_consecutive_same_role_turnsr   o   s   '; 	.)9:f5G
 &g.F%&v!fIIv?&6;*??*??????&???&???*?????????!9Y7#77#777777777777#777777777 's   E1c                     R RRRRRRRRR	R
RRRRRR/./p \        R\        V R7      R7      ;_uu_ 4        \        P                  RRRRRR. ////RRRRR/./R7      pRRR4       XP                  p^q2V8H  qD'       g   \
        P                  ! R'V3R(W#34      RR\        P                  ! 4       9   g   \
        P                  ! V4      '       d   \
        P                  ! V4      MRR\
        P                  ! V4      R \
        P                  ! V4      /,          pR!R"V/,          p\        \
        P                  ! V4      4      hR;p;rCVP                  4       R ,          ^ ,          R,          pRqGV8H  q'       gy   \
        P                  ! R'V3R)Wt34      R#\
        P                  ! V4      R$\
        P                  ! V4      /,          p	R%R&V	/,          p
\        \
        P                  ! V
4      4      hR;p;rR#   + '       g   i     EL; i)*recommendationsrH   zCaldera View Suiteslocation	Santoriniprice_per_nightiT  rM   rN   whyzMatches sea view preference.is_top_pickTsourcesearch_candidate
source_refChIJ123zapp.services.stay.get_providerrZ   r[   z/recommend_stay	itineraryrQ   rT   rV   
candidatesproperty_tokenr`   Nr   r   r   r    r!   r"   r%   r&   r'   r(   r)   r+   r,   rb   r}   s              r   0test_recommend_stay_with_candidates_flags_sourcer   }   s   -K!3E5t,i	
K 
/lR]>^	_	_;;cN[<QSBT4U#VW 0)VEZ[\  
 
` &3&3&&&&&&&&&&&8&&&&8&&&&&&3&&&&&&&&==?,-a0:P>PP>PPPPPP:PPP:PPP>PPPPPPPPP 
`	_	_s   )G;;H	c                     \        R R4      ;_uu_ 4        \        P                  RRR/R7      p V P                  pRq!V8H  q3'       g   \        P
                  ! RV3RW34      RR\        P                  ! 4       9   g   \        P                  ! V 4      '       d   \        P                  ! V 4      MRR	\        P                  ! V4      R
\        P                  ! V4      /,          pRRV/,          p\        \        P                  ! V4      4      hR;p;r2\        R\        R. /R7      R7      ;_uu_ 4        \        P                  RRR/RR/R7      pRRR4       XP                  p^q!V8H  q3'       g   \        P
                  ! RV3RW34      RR\        P                  ! 4       9   g   \        P                  ! V4      '       d   \        P                  ! V4      MRR	\        P                  ! V4      R
\        P                  ! V4      /,          pRRV/,          p\        \        P                  ! V4      4      hR;p;r2RRR4       R#   + '       g   i     L; i  + '       g   i     R# ; i)zapp.main.settings.service_token	secret123r|   r^   Tripr`   i  r   unauthorizedr   r    r!   r"   Nr{   rs   rZ   r[   AuthorizationzBearer secret123)r8   headers
authorizedr)   r+   )r   r-   rc   r/   r0   r1   r2   r3   r4   r5   r6   r7   r   )r   r:   r;   r<   r=   r>   r   s          r   +test_service_token_required_when_configuredr      s{   	0+	>	>{{#7|V>T{U''.3.3.....'......|....|...'...3........8|\gik[lGmnn$"F+(*<= % J o %%,,,,,,,%,,,,,,z,,,,z,,,%,,,,,,,,,,, 
?	> on	 
?	>	>s3   BIBI4I	A1IA:IIII+	)__doc__builtinsr2   _pytest.assertion.rewrite	assertionrewriter0   unittest.mockr   fastapi.testclientr   app.mainr   r-   r   rC   rf   rn   rq   r~   r   r   r   r    r   r   <module>r      s_   
    ) 	C -#LGF	;C8Q6-r   