
    מiF                       d Z ddlmZ ddlZddlmc mZ ddl	Z	ddl
Z
ddlZddlmZmZ ddlZd ZdddZ G d d      Z G d	 d
      Z G d d      Z G d d      Z G d d      Z G d d      Z G d d      Z G d d      Zy)uL  
tests/infra/test_email.py
Test suite for core/email — GenesisEmail client + templates.

Coverage breakdown:
  BB1  GenesisEmail initialises without resend package (graceful degradation)
  BB2  send() returns correct structure on success (mocked API)
  BB3  send() returns error dict on API failure (mocked)
  BB4  batch_send() processes multiple messages (mocked)
  BB5  All templates render without missing variables
  WB1  render_template handles missing variables gracefully (no KeyError)
  WB2  send_template calls render then send correctly
  WB3  Templates contain no banned Australian slang

Run:
    cd /mnt/e/genesis-system && python3 -m pytest tests/infra/test_email.py -v

# VERIFICATION_STAMP
# Story: M10.04 — tests/infra/test_email.py
# Verified By: parallel-builder
# Verified At: 2026-02-25
# Tests: 10/10
# Coverage: 100%
    )annotationsN)	MagicMockpatchc                     t        t        j                  j                               D ]%  } | j	                  d      st        j                  | = ' y)zBForce a fresh import of core.email.* to clear cached module state.z
core.emailN)listsysmoduleskeys
startswith)mod_names    //mnt/e/genesis-system/tests/infra/test_email.py_reload_email_modulesr   '   s=    ))+, &|,H%&    c                j     t        j                  d      }d|_         G  fdd      }||_        |S )z$Build a minimal resend-library stub.resendNc                  $    e Zd Ze fd       Zy)"_make_resend_stub.<locals>._Emailsc                p    t               }xs i j                  dd      |_        dfd	|_        |S )Nidztest-email-id-123c                0    xs i j                  | |      S N)get)kdsend_returns     r   <lambda>z9_make_resend_stub.<locals>._Emails.send.<locals>.<lambda>:   s    +*;)@)@A)F r   r   )r   r   r   )paramsresp	raise_excr   s     r   sendz'_make_resend_stub.<locals>._Emails.send4   s;    $;D"(b--d4GHDGFDHKr   N__name__
__module____qualname__staticmethodr    )r   r   s   r   _Emailsr   3   s    		 
	r   r&   )types
ModuleTypeapi_keyEmails)r   r   stubr&   s   ``  r   _make_resend_stubr,   .   s2    H%DDL  DKKr   c                      e Zd ZdZd Zd Zy)TestBB1GracefulDegradationz9Client must not crash when the resend package is missing.c                L   t                |j                  t        j                  dd       t                t	        j
                  t        j                  ddi      5  ddlm}  |d      }ddd       d}|u}|st        j                  d|fd||f      d	t        j                         v st        j                  |      rt        j                  |      nd	t        j                  |      d
z  }dd|iz  }t        t        j                  |            dx}}y# 1 sw Y   xY w)z;GenesisEmail() succeeds even when resend is not importable.r   Nr   GenesisEmailtest-keyr)   )is not)z%(py0)s is not %(py3)sclient)py0py3assert %(py5)spy5)r   setitemr   r	   r   dictcore.email.clientr1   
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanation)selfmonkeypatchr1   r5   @py_assert2@py_assert1@py_format4@py_format6s           r   $test_bb1_init_without_resend_packagez?TestBB1GracefulDegradation.test_bb1_init_without_resend_packageH   s    CKK48 	ZZh%56 	66!*5F	6 "!vT!!!!vT!!!!!!v!!!v!!!T!!!!!!!		6 	6s   DD#c                    t                t        j                  t        j                  ddi      5  ddlm}  |d      }|j                  ddd	
      }ddd       d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}d}||v }|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }	dd|	iz  }
t        t        j                  |
            dx}}y# 1 sw Y   0xY w)z:When resend is absent send() returns {"status": "failed"}.r   Nr   r0   r2   r3   ztest@example.comTest<p>Test</p>tosubjecthtmlstatusfailed==z%(py1)s == %(py4)spy1py4assert %(py6)spy6errorinz%(py1)s in %(py3)sresultrY   r7   r8   r9   )r   r   r;   r   r	   r<   r1   r    r=   r>   rB   rC   rD   r?   r@   rA   )rE   r1   r5   ra   @py_assert0@py_assert3rG   @py_format5@py_format7rI   rJ   s              r   /test_bb1_send_without_resend_returns_error_dictzJTestBB1GracefulDegradation.test_bb1_send_without_resend_returns_error_dictV   s
   ZZh%56 	6!*5F[[%" ! F	 h+8+8++++8++++++8+++++++ w&    w&   w      &   &       	 	s   $FFN)r"   r#   r$   __doc__rK   rg    r   r   r.   r.   E   s    C"!r   r.   c                      e Zd ZdZd Zd Zy)TestBB2SendSuccesszJsend() must return {"id": ..., "status": "sent"} on a successful API call.c                <   t                t        ddi      }t        j                  t        j
                  d|i      5  ddlm}  |d      }|j                  d	d
d      }ddd       d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }	t        t        j                  |	            dx}x}}d}||v }|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                   |      rt        j                  |      nddz  }
dd|
iz  }t        t        j                  |            dx}}|d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }	t        t        j                  |	            dx}x}}y# 1 sw Y   xY w)z+Happy-path send with mocked resend library.r   	re_abc123r   r   r   r0   ztest-resend-keyr3   customer@example.comWelcomez<p>Welcome</p>rO   NrS   sentrU   rW   rX   r[   r\   r^   r`   ra   rb   r8   r9   )r   r,   r   r;   r   r	   r<   r1   r    r=   r>   rB   rC   rD   r?   r@   rA   rE   r+   r1   r5   ra   rc   rd   rG   re   rf   rI   rJ   s               r   #test_bb2_send_returns_id_and_statusz6TestBB2SendSuccess.test_bb2_send_returns_id_and_statusl   sg    dK-@AZZh%56 	6!*;<F[[)!% ! F	 h)6)6))))6))))))6)))))))tv~tvtvvd|*{*|{****|{***|***{*******	 	s   $HHc                   t                t        ddi      }t        j                  t        j
                  d|i      5  ddlm}  |d      }|j                  d	d
gdd      }ddd       d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }	t        t        j                  |	            dx}x}}y# 1 sw Y   xY w)z.send() works when *to* is a list of addresses.r   re_multirn   r   r   r0   r2   r3   a@example.comb@example.comBatchz	<p>Hi</p>rO   NrS   rq   rU   rW   rX   r[   r\   )r   r,   r   r;   r   r	   r<   r1   r    r=   r>   rB   rC   rD   
rE   r+   r1   r5   ra   rc   rd   rG   re   rf   s
             r   (test_bb2_send_accepts_list_of_recipientsz;TestBB2SendSuccess.test_bb2_send_accepts_list_of_recipients~   s     dJ-?@ZZh%56 	6!*5F[[#_5  ! F	 h)6)6))))6))))))6)))))))	 	s   &C..C7N)r"   r#   r$   rh   rs   rz   ri   r   r   rk   rk   i   s    T+$*r   rk   c                      e Zd ZdZd Zd Zy)TestBB3SendFailurezJsend() must return {"error": ..., "status": "failed"} when the API raises.c                H   t                t        t        d            }t        j                  t
        j                  d|i      5  ddlm}  |d      }|j                  dd	d
      }ddd       d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }	t        t        j                  |	            dx}x}}d}||v }|st        j                  d|fd||f      t        j                  |      dt        j                          v st        j"                  |      rt        j                  |      nddz  }
dd|
iz  }t        t        j                  |            dx}}d}|d   }||v }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }	t        t        j                  |	            dx}x}}y# 1 sw Y   xY w)zARuntimeError from resend is caught and returned as an error dict.zAPI rate limit exceeded)r   r   r   r0   r2   r3   ro   rM   rN   rO   NrS   rT   rU   rW   rX   r[   r\   r]   r^   r`   ra   rb   r8   r9   z
rate limit)z%(py1)s in %(py4)s)r   r,   RuntimeErrorr   r;   r   r	   r<   r1   r    r=   r>   rB   rC   rD   r?   r@   rA   rr   s               r   )test_bb3_api_exception_returns_error_dictz<TestBB3SendFailure.test_bb3_api_exception_returns_error_dict   sh    <8Q+RSZZh%56 	6!*5F[[)" ! F	 h+8+8++++8++++++8+++++++ w&    w&   w      &   &       .vg.|....|...|..........	 	s   $HH!c                V   t                t               }|j                  dd       t        j                  t
        j                  d|i      5  ddlm}  |       }|j                  ddd	
      }ddd       d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            dx}x}}d}||v }|st        j                  d|fd||f      t        j                  |      dt        j                          v st        j"                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            dx}}y# 1 sw Y   0xY w)u/   No API key → error dict, no exception raised.RESEND_API_KEYF)raisingr   r   r0   ro   rM   rN   rO   NrS   rT   rU   rW   rX   r[   r\   r]   r^   r`   ra   rb   r8   r9   )r   r,   delenvr   r;   r   r	   r<   r1   r    r=   r>   rB   rC   rD   r?   r@   rA   )rE   rF   r+   r1   r5   ra   rc   rd   rG   re   rf   rI   rJ   s                r   +test_bb3_missing_api_key_returns_error_dictz>TestBB3SendFailure.test_bb3_missing_api_key_returns_error_dict   s#    "+U;ZZh%56 	6!^F[[)" ! F	 h+8+8++++8++++++8+++++++ w&    w&   w      &   &       	 	s   "FF(N)r"   r#   r$   rh   r   r   ri   r   r   r|   r|      s    T/$!r   r|   c                      e Zd ZdZd Zd Zy)TestBB4BatchSendz:batch_send() must return one result per message, in order.c                   t                ddifdt        j                  d      }d|_         G fdd      }||_        dd	d
dddddddddg}t        j                  t        j                  d|i      5  ddl	m
}  |d      }|j                  |      }ddd       t              }d}||k(  }	|	st        j                  d|	fd||f      dt        j                          v st        j"                  t              rt        j$                  t              nddt        j                          v st        j"                  |      rt        j$                  |      ndt        j$                  |      t        j$                  |      dz  }
dd|
iz  }t'        t        j(                  |            dx}x}	}|D ](  }|d   }d}||k(  }|slt        j                  d|fd||f      t        j$                  |      t        j$                  |      d z  }d!d"|iz  }
t'        t        j(                  |
            dx}x}}d#}||v }|st        j                  d$|fd%||f      t        j$                  |      d&t        j                          v st        j"                  |      rt        j$                  |      nd&d'z  }d(d)|iz  }t'        t        j(                  |            dx}}+ y# 1 sw Y   IxY w)*u&   Three messages → three result dicts.nr   c                h    dxx   dz  cc<   t               dd    _        dfd	_        S )Nr      	re_batch_c                *    | dk(  rj                   S |S Nr   r   r   r   r   s     r   r   zdTestBB4BatchSend.test_bb4_batch_returns_list_of_results.<locals>._send_side_effect.<locals>.<lambda>       AI 1 r   r   )r   r   r   )r   r   counters    @r   _send_side_effectzRTestBB4BatchSend.test_bb4_batch_returns_list_of_results.<locals>._send_side_effect   s6    CLAL;D!'#,0DGDDHKr   r   Nc                       e Zd Z eW        Zy)HTestBB4BatchSend.test_bb4_batch_returns_list_of_results.<locals>._EmailsNr!   r   s   r   r&   r           12Dr   r&   rv   One<p>1</p>rO   rw   Two<p>2</p>c@example.comThree<p>3</p>r0   r2   r3      rU   z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)slenresultsr6   rY   r7   r\   assert %(py8)spy8rS   rq   rW   rX   r[   r\   r   r^   r`   rrb   r8   r9   r   r'   r(   r)   r*   r   r;   r   r	   r<   r1   
batch_sendr   r=   r>   r?   r@   rA   rB   rC   rD   )rE   r+   r&   messagesr1   r5   r   rG   @py_assert5@py_assert4rf   @py_format9r   rc   rd   re   rI   rJ   r   r   s                     @@r   &test_bb4_batch_returns_list_of_resultsz7TestBB4BatchSend.test_bb4_batch_returns_list_of_results   s   (	 )	3 	3  #ujI"ujI"w
K
 ZZh%56 	26!*5F''1G	2
 7| q |q    |q      s   s      7   7   |   q        	AX;(&(;&((((;&(((;(((&(((((((41941411		2 	2s   <!K$$K.c                   t                ddifdt        j                  d      }d|_         G fdd      }||_        dd	d
dddddddddg}t        j                  t        j                  d|i      5  ddl	m
}  |d      }|j                  |      }ddd       t              }d}||k(  }	|	st        j                  d|	fd||f      dt        j                          v st        j"                  t              rt        j$                  t              nddt        j                          v st        j"                  |      rt        j$                  |      ndt        j$                  |      t        j$                  |      dz  }
dd|
iz  }t'        t        j(                  |            dx}x}	}|d   d   }d}||k(  }|slt        j                  d|fd||f      t        j$                  |      t        j$                  |      d z  }d!d"|iz  }
t'        t        j(                  |
            dx}x}}|d#   d   }d$}||k(  }|slt        j                  d|fd||f      t        j$                  |      t        j$                  |      d z  }d!d"|iz  }
t'        t        j(                  |
            dx}x}}|d%   d   }d}||k(  }|slt        j                  d|fd||f      t        j$                  |      t        j$                  |      d z  }d!d"|iz  }
t'        t        j(                  |
            dx}x}}y# 1 sw Y   xY w)&z9If one message fails, the rest should still be attempted.r   r   c                    dxx   dz  cc<   d   dk(  rt        d      t               dd    _        dfd	_        S )Nr   r      zSimulated failure on message 2re_ok_c                *    | dk(  rj                   S |S r   r   r   s     r   r   ziTestBB4BatchSend.test_bb4_batch_continues_on_partial_failure.<locals>._send_side_effect.<locals>.<lambda>   r   r   r   )
ValueErrorr   r   r   )r   r   
call_counts    @r   r   zWTestBB4BatchSend.test_bb4_batch_continues_on_partial_failure.<locals>._send_side_effect   sO    sOq O#!# !ABB;Dz#/0DGDDHKr   r   Nc                       e Zd Z eW        Zy)MTestBB4BatchSend.test_bb4_batch_continues_on_partial_failure.<locals>._EmailsNr!   r   s   r   r&   r      r   r   r&   rv   r   r   rO   rw   r   r   r   r   r   r0   r2   r3   r   rU   r   r   r   r   r   r   rS   rq   rW   rX   r[   r\   r   rT   r   r   )rE   r+   r&   r   r1   r5   r   rG   r   r   rf   r   rc   rd   re   r   r   s                  @@r   +test_bb4_batch_continues_on_partial_failurez<TestBB4BatchSend.test_bb4_batch_continues_on_partial_failure   sE   1X
	 )	3 	3  #ujI"ujI"w
K
 ZZh%56 	26!*5F''1G	2
 7| q |q    |q      s   s      7   7   |   q       qz(#-v-#v----#v---#---v-------qz(#/x/#x////#x///#///x///////qz(#-v-#v----#v---#---v-------	2 	2s   <!L??M	N)r"   r#   r$   rh   r   r   ri   r   r   r   r      s    D"H$.r   r   c                  0    e Zd ZdZddZd Zd Zd Zd Zy)	TestBB5TemplateRenderingzOEvery template must render completely when all required variables are supplied.c           
         i ddddddddd	d
dddddddddddddddddddddd d!d"d#d$d%d&d'd(d)d*d+S ),z;A superset of variables covering all template placeholders.
first_nameAlex	plan_nameProfessionaldashboard_urlz(https://app.sunaivadigital.com/dashboardweek_ending
2026-02-28total_sessions142tasks_completed318revenue_events7	new_leads23active_agents8
highlightsz!Strong lead generation this week.next_prioritiesz,1. Launch email campaign. 2. Review pricing.	lead_nameJordan Smithbusiness_nameSmith Plumbingphonez+61412345678emailzjordan@smithplumbing.com.ausourceWebsite Formmessagez*Interested in the AI receptionist package.z'https://app.sunaivadigital.com/leads/42Casey Brownz+61498765432z
2026-02-253m 42sAppointment bookedz0Caller enquired about pricing and booked a demo.z(Send follow-up email with pricing sheet.)crm_urlcaller_namecaller_phone	call_datecall_durationcall_outcometranscript_summaryaction_itemsri   )rE   s    r   
_full_varsz#TestBB5TemplateRendering._full_vars  s    
&
 
 G	
 <
 e
 u
 c
 
 S
 =
 M
 
  -!
" ^#
$ 2%
& n'
( C)
* A(*%%0"TF;
 	
r   c                V   t                ddlm}  |d| j                               \  }}d}||v }|st	        j
                  d|fd||f      t	        j                  |      dt        j                         v st	        j                  |      rt	        j                  |      nddz  }d	d
|iz  }t        t	        j                  |            d x}}d}||v }|st	        j
                  d|fd||f      t	        j                  |      dt        j                         v st	        j                  |      rt	        j                  |      nddz  }d	d
|iz  }t        t	        j                  |            d x}}d}||v }|st	        j
                  d|fd||f      t	        j                  |      dt        j                         v st	        j                  |      rt	        j                  |      nddz  }d	d
|iz  }t        t	        j                  |            d x}}t        |      }d}||kD  }	|	st	        j
                  d|	fd||f      dt        j                         v st	        j                  t              rt	        j                  t              nddt        j                         v st	        j                  |      rt	        j                  |      ndt	        j                  |      t	        j                  |      dz  }
dd|
iz  }t        t	        j                  |            d x}x}	}y )Nr   render_templatewelcomer   r^   r`   rQ   rb   r8   r9   rR   r      )>)z/%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} > %(py6)sr   r   r   r   )r   core.email.templatesr   r   r=   r>   rB   r?   r@   rA   rC   rD   r   )rE   r   rQ   rR   rc   rG   rI   rJ   r   r   rf   r   s               r   test_bb5_welcome_rendersz1TestBB5TemplateRendering.test_bb5_welcome_renders6  s   8'	4??3DE v    v   v                v~vv%~%%%%~%%%~%%%%%%%%%%%%%%%%4y3y3y3ss44y3r   c                6   t                ddlm}  |d| j                               \  }}d}||v }|st	        j
                  d|fd||f      t	        j                  |      dt        j                         v st	        j                  |      rt	        j                  |      nddz  }d	d
|iz  }t        t	        j                  |            d x}}d}||v }|st	        j
                  d|fd||f      t	        j                  |      dt        j                         v st	        j                  |      rt	        j                  |      nddz  }d	d
|iz  }t        t	        j                  |            d x}}d}||v }|st	        j
                  d|fd||f      t	        j                  |      dt        j                         v st	        j                  |      rt	        j                  |      nddz  }d	d
|iz  }t        t	        j                  |            d x}}y )Nr   r   epoch_reportr   r^   r`   rQ   rb   r8   r9   r   rR   zStrong lead generationr   r   r   r   r=   r>   rB   r?   r@   rA   rC   rD   rE   r   rQ   rR   rc   rG   rI   rJ   s           r   test_bb5_epoch_report_rendersz6TestBB5TemplateRendering.test_bb5_epoch_report_renders?  s/   8'8IJ&|w&&&&|w&&&|&&&&&&w&&&w&&&&&&&u}uu'/'4////'4///'//////4///4///////r   c                6   t                ddlm}  |d| j                               \  }}d}||v }|st	        j
                  d|fd||f      t	        j                  |      dt        j                         v st	        j                  |      rt	        j                  |      nddz  }d	d
|iz  }t        t	        j                  |            d x}}d}||v }|st	        j
                  d|fd||f      t	        j                  |      dt        j                         v st	        j                  |      rt	        j                  |      nddz  }d	d
|iz  }t        t	        j                  |            d x}}d}||v }|st	        j
                  d|fd||f      t	        j                  |      dt        j                         v st	        j                  |      rt	        j                  |      nddz  }d	d
|iz  }t        t	        j                  |            d x}}y )Nr   r   lead_notificationr   r^   r`   rQ   rb   r8   r9   r   rR   r   r   r   s           r   "test_bb5_lead_notification_rendersz;TestBB5TemplateRendering.test_bb5_lead_notification_rendersG  s1   8'(;T__=NO(~((((~(((~(((((((((((((((('4''''4'''''''''4'''4'''''''%~%%%%~%%%~%%%%%%%%%%%%%%%%r   c                6   t                ddlm}  |d| j                               \  }}d}||v }|st	        j
                  d|fd||f      t	        j                  |      dt        j                         v st	        j                  |      rt	        j                  |      nddz  }d	d
|iz  }t        t	        j                  |            d x}}d}||v }|st	        j
                  d|fd||f      t	        j                  |      dt        j                         v st	        j                  |      rt	        j                  |      nddz  }d	d
|iz  }t        t	        j                  |            d x}}d}||v }|st	        j
                  d|fd||f      t	        j                  |      dt        j                         v st	        j                  |      rt	        j                  |      nddz  }d	d
|iz  }t        t	        j                  |            d x}}y )Nr   r   voice_summaryr   r^   r`   rQ   rb   r8   r9   r   rR   r   r   r   s           r   test_bb5_voice_summary_rendersz7TestBB5TemplateRendering.test_bb5_voice_summary_rendersO  s0   8'9JK'}''''}'''}''''''''''''''''#+#t++++#t+++#++++++t+++t+++++++x4x4x44r   N)returnr;   )	r"   r#   r$   rh   r   r   r   r   r   ri   r   r   r   r     s    Y 
D0& r   r   c                  "    e Zd ZdZd Zd Zd Zy)TestWB1MissingVariablesuP   Missing template variables must NOT raise KeyError — they return empty string.c                   t                ddlm}  |di       \  }}d}||v}|st        j                  d|fd||f      t        j
                  |      dt        j                         v st        j                  |      rt        j
                  |      nddz  }d	d
|iz  }t        t        j                  |            d x}}d}||v}|st        j                  d|fd||f      t        j
                  |      dt        j                         v st        j                  |      rt        j
                  |      nddz  }d	d
|iz  }t        t        j                  |            d x}}y )Nr   r   r   z{first_name}not inz%(py1)s not in %(py3)srQ   rb   r8   r9   rR   r   r   r   r=   r>   rB   r?   r@   rA   rC   rD   r   s           r   .test_wb1_missing_variable_returns_empty_stringzFTestWB1MissingVariables.test_wb1_missing_variable_returns_empty_string_  s    8'	26,~W,,,,~W,,,~,,,,,,W,,,W,,,,,,,)~T))))~T)))~))))))T)))T)))))))r   c                   t                ddlm}  |dddi      \  }}d}||v }|st        j                  d|fd||f      t        j
                  |      dt        j                         v st        j                  |      rt        j
                  |      ndd	z  }d
d|iz  }t        t        j                  |            d x}}d}||v}|st        j                  d|fd||f      t        j
                  |      dt        j                         v st        j                  |      rt        j
                  |      ndd	z  }d
d|iz  }t        t        j                  |            d x}}y )Nr   r   r   r   Taylorr^   r`   rQ   rb   r8   r9   z{business_name}r   r   rR   r   r   s           r   &test_wb1_partial_variables_no_keyerrorz>TestWB1MissingVariables.test_wb1_partial_variables_no_keyerrorh  s    8'(;k8=TU"x7""""x7"""x""""""7"""7""""""" , ,,,, ,,, ,,,,,,,,,,,,,,,,r   c                    t                ddlm} t        j                  t
              5   |di        d d d        y # 1 sw Y   y xY w)Nr   r   nonexistent_template_xyz)r   r   r   pytestraisesKeyError)rE   r   s     r   )test_wb1_unknown_template_raises_keyerrorzATestWB1MissingVariables.test_wb1_unknown_template_raises_keyerrorq  s7    8]]8$ 	<6;	< 	< 	<s	   
=AN)r"   r#   r$   rh   r   r   r  ri   r   r   r   r   \  s    Z*-<r   r   c                      e Zd ZdZd Zd Zy)TestWB2SendTemplatezEsend_template must render the template and pass the result to send().c           	        t                t        ddi      }t        j                  t        j
                  d|i      5  ddlm}  |d      }|j                  d	d
dddd      }d d d        d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }	t        t        j                  |	            d x}x}}|d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }	t        t        j                  |	            d x}x}}y # 1 sw Y   xY w)Nr   re_tmpl_001rn   r   r   r0   r2   r3   ro   r   SamStarterzhttps://app.sunaivadigital.com)r   r   r   rP   template_name	variablesrS   rq   rU   rW   rX   r[   r\   )r   r,   r   r;   r   r	   r<   r1   send_templater=   r>   rB   rC   rD   ry   s
             r   !test_wb2_send_template_happy_pathz5TestWB2SendTemplate.test_wb2_send_template_happy_path  s    dM-BCZZh%56 	6!*5F)))'"'!*%E * F	 h)6)6))))6))))))6)))))))d|,},|},,,,|},,,|,,,},,,,,,,	 	s   (E00E:c                4   t                t               }t        j                  t        j
                  d|i      5  ddlm}  |d      }|j                  ddi       }d d d        d	   }d
}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }	t        t        j                  |	            d x}x}}d}||v }|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                   |      rt        j                  |      nddz  }
dd|
iz  }t        t        j                  |            d x}}y # 1 sw Y   0xY w)Nr   r   r0   r2   r3   ro   does_not_existr  rS   rT   rU   rW   rX   r[   r\   r]   r^   r`   ra   rb   r8   r9   )r   r,   r   r;   r   r	   r<   r1   r  r=   r>   rB   rC   rD   r?   r@   rA   rr   s               r   5test_wb2_send_template_unknown_template_returns_errorzITestWB2SendTemplate.test_wb2_send_template_unknown_template_returns_error  s    "ZZh%56 	6!*5F))). * F	 h+8+8++++8++++++8+++++++ w&    w&   w      &   &       	 	s   $FFN)r"   r#   r$   rh   r  r  ri   r   r   r  r  |  s    O-(!r   r  c                  >    e Zd ZdZg dZd
dZd Zd Zd Zd Z	d Z
y	)TestWB3NoBannedSlangz8No template may contain banned Australian slang phrases.)g'dayz
g'day matetoo easyrightosweet asno worries matemazzac                    ddl m} d}|j                         D ]H  }||j                  dd      j	                         z  }||j                  dd      j	                         z  }J |S )Nr   )	TEMPLATES rQ   rR   )r   r  valuesr   lower)rE   r  all_texttmpls       r   _all_template_textz'TestWB3NoBannedSlang._all_template_text  se    2$$& 	5DB/5577H,2244H	5 r   c                   t                | j                         }d}||v}|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d x}}y )Nr  r   r   textrb   r8   r9   
r   r$  r=   r>   rB   r?   r@   rA   rC   rD   rE   r&  rc   rG   rI   rJ   s         r   test_wb3_no_gday_in_templatesz2TestWB3NoBannedSlang.test_wb3_no_gday_in_templates  so    &&("wd""""wd"""w""""""d"""d"""""""r   c                   t                | j                         }d}||v}|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d x}}y )Nr  r   r   r&  rb   r8   r9   r'  r(  s         r   test_wb3_no_mate_in_templatesz2TestWB3NoBannedSlang.test_wb3_no_mate_in_templates  st    &&( !, ,,,, ,,, ,,,,,,,,,,,,,,,,r   c                   t                | j                         }d}||v}|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d x}}y )Nr  r   r   r&  rb   r8   r9   r'  r(  s         r   test_wb3_no_righto_in_templatesz4TestWB3NoBannedSlang.test_wb3_no_righto_in_templates  so    &&(#xt####xt###x######t###t#######r   c                   t                | j                         }d}||v}|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d x}}y )Nr  r   r   r&  rb   r8   r9   r'  r(  s         r   !test_wb3_no_too_easy_in_templatesz6TestWB3NoBannedSlang.test_wb3_no_too_easy_in_templates  o    &&(%z%%%%z%%%z%%%%%%%%%%%%%%%%r   c                   t                | j                         }d}||v}|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d x}}y )Nr  r   r   r&  rb   r8   r9   r'  r(  s         r   !test_wb3_no_sweet_as_in_templatesz6TestWB3NoBannedSlang.test_wb3_no_sweet_as_in_templates  r0  r   N)r   str)r"   r#   r$   rh   _BANNEDr$  r)  r+  r-  r/  r2  ri   r   r   r  r    s*    BG#
-$
&
&r   r  )NN)r   zdict | Noner   zException | None)rh   
__future__r   builtinsr?   _pytest.assertion.rewrite	assertionrewriter=   	importlibr   r'   unittest.mockr   r   r  r   r,   r.   rk   r|   r   r   r   r  r  ri   r   r   <module>r<     s   0 #     
  * &.! !H#* #*T%! %!XK. K.dD  D V< <@%! %!X/& /&r   