59 lines
3.4 KiB
Python
59 lines
3.4 KiB
Python
|
|
import asyncio
|
||
|
|
import json
|
||
|
|
from io import BytesIO
|
||
|
|
from unittest.mock import MagicMock
|
||
|
|
import pytest
|
||
|
|
from fastapi import HTTPException, UploadFile
|
||
|
|
from app.modules.sag.backend import mail_templates as mail
|
||
|
|
|
||
|
|
CASE={'id':186,'titel':'Router','customer_id':8,'customer_name':'Testkunde'}
|
||
|
|
|
||
|
|
def test_tag_ranking_and_customer_scope():
|
||
|
|
rows=[{'name':'Global','customer_id':None,'match_tags':['MOBIL']},{'name':'Kunde','customer_id':8,'match_tags':['mobil','portering']},{'name':'Andet','customer_id':None,'match_tags':[]}]
|
||
|
|
result=mail.rank_templates(rows,[' mobil ','portering'])
|
||
|
|
assert [r['name'] for r in result]==['Kunde','Global','Andet']
|
||
|
|
assert result[0]['recommended'] and not result[-1]['recommended']
|
||
|
|
assert mail.available(rows[0],CASE)
|
||
|
|
assert not mail.available({'customer_id':9},CASE)
|
||
|
|
|
||
|
|
def test_variables_and_unknown_placeholder():
|
||
|
|
assert mail.render_text('{sag_id} {{kunde_navn}} {kontakt_navn} {{customer_name}} {andet}',CASE,{'name':'Anne'})=='186 Testkunde Anne Testkunde {andet}'
|
||
|
|
|
||
|
|
def connection(monkeypatch,fetches,rows):
|
||
|
|
conn=MagicMock();cur=conn.cursor.return_value.__enter__.return_value
|
||
|
|
cur.fetchone.side_effect=fetches;cur.fetchall.return_value=rows
|
||
|
|
monkeypatch.setattr(mail,'get_db_connection',lambda:conn)
|
||
|
|
monkeypatch.setattr(mail,'release_db_connection',lambda c:None)
|
||
|
|
return conn,cur
|
||
|
|
|
||
|
|
@pytest.mark.parametrize('rows',[[],[{'customer_id':9}]])
|
||
|
|
def test_attachment_cannot_escape_customer(monkeypatch,rows):
|
||
|
|
conn,_=connection(monkeypatch,[CASE],rows)
|
||
|
|
with pytest.raises(HTTPException):mail.send_attachments(186,[1])
|
||
|
|
conn.rollback.assert_called();conn.commit.assert_not_called()
|
||
|
|
|
||
|
|
def test_attachment_bytes_for_existing_sender(monkeypatch):
|
||
|
|
connection(monkeypatch,[CASE],[{'customer_id':8,'filename':'ark.pdf','content_type':'application/pdf','content':memoryview(b'PDF'),'size_bytes':3}])
|
||
|
|
assert mail.send_attachments(186,[1])==[{'filename':'ark.pdf','content_type':'application/pdf','content':b'PDF','size':3}]
|
||
|
|
|
||
|
|
@pytest.mark.parametrize('payload',[{},[],{'request_id':'invalid'}, {'request_id':'11111111-1111-1111-1111-111111111111','name':'','subject':'X','body':'X'}])
|
||
|
|
def test_invalid_input_rejected_before_db(payload):
|
||
|
|
with pytest.raises(HTTPException):asyncio.run(mail.create_template(186,json.dumps(payload),[]))
|
||
|
|
|
||
|
|
def test_create_template_keeps_scope_and_files(monkeypatch):
|
||
|
|
conn,cur=connection(monkeypatch,[CASE,None,{'id':123}],[])
|
||
|
|
payload={'request_id':'11111111-1111-1111-1111-111111111111','name':'Mobil','subject':'Portering','body':'Hej','scope':'customer','match_tags':['mobil']}
|
||
|
|
assert asyncio.run(mail.create_template(186,json.dumps(payload),[UploadFile(filename='../ark.pdf',file=BytesIO(b'PDF'))]))=={'id':123}
|
||
|
|
inserts=[call.args for call in cur.execute.call_args_list if 'INSERT INTO' in call.args[0]]
|
||
|
|
assert inserts[0][1][4]==8
|
||
|
|
assert inserts[1][1]==(123,'ark.pdf','application/octet-stream',b'PDF',3)
|
||
|
|
conn.commit.assert_called_once()
|
||
|
|
|
||
|
|
def test_replay_rejects_changed_files(monkeypatch):
|
||
|
|
payload={'request_id':'11111111-1111-1111-1111-111111111111','name':'Mobil','subject':'Portering','body':'Hej','scope':'customer','match_tags':[]}
|
||
|
|
previous=dict(payload,id=123,customer_id=8)
|
||
|
|
conn,_=connection(monkeypatch,[CASE,previous],[{'filename':'old','content_type':'x','content':b'old','size_bytes':3}])
|
||
|
|
with pytest.raises(HTTPException) as exc:asyncio.run(mail.create_template(186,json.dumps(payload),[]))
|
||
|
|
assert exc.value.status_code==409
|
||
|
|
conn.commit.assert_not_called()
|