Attach proof of cover to a warranty
A provider lookup answers whether a unit is covered. It does not produce the invoice or the extended-warranty certificate, and a manually entered warranty had nowhere to keep one - so the proof stayed in somebody's mailbox until they left. Two columns rather than one: the served URL of the stored document, and the name the vendor sent it under, because "Dell invoice 4471.pdf" is what a person recognises a year later and "warranty-12.pdf" is not. The download route sends the original name back. Authenticated in both directions, unlike an asset photo: an invoice carries pricing and a service tag. One document per warranty, replacing any prior extension so a re-upload as .pdf does not leave the old .png behind claiming to be current. Capped at 25MB - a certificate is a document, not a disk image. Office formats are allowed because purchase records genuinely arrive as .msg and .xlsx, not only as PDFs.
This commit is contained in:
110
tests/test_plugins/test_warranty_proof.py
Normal file
110
tests/test_plugins/test_warranty_proof.py
Normal file
@@ -0,0 +1,110 @@
|
||||
"""Tests for the warranty proof-of-cover document.
|
||||
|
||||
A provider lookup answers whether a unit is covered; it does not produce the
|
||||
invoice or the extended-warranty certificate. Those had nowhere to live, so
|
||||
they stayed in somebody's mailbox. These pin the parts that are easy to get
|
||||
wrong: the document is authenticated on the way out, one per warranty, and the
|
||||
vendor's own filename survives so a download is recognisable.
|
||||
"""
|
||||
|
||||
import io
|
||||
|
||||
from plugins.warranty.models import Warranty
|
||||
|
||||
|
||||
def _warranty(db, vendor='Dell'):
|
||||
w = Warranty(vendor=vendor, servicetag='ABC123', provider='manual')
|
||||
db.session.add(w)
|
||||
db.session.commit()
|
||||
return w
|
||||
|
||||
|
||||
def test_upload_sets_url_and_keeps_the_original_filename(client, db, auth_headers):
|
||||
w = _warranty(db)
|
||||
|
||||
response = client.post(f'/api/warranty/{w.warrantyid}/proof',
|
||||
data={'file': (io.BytesIO(b'%PDF-1.4 invoice'),
|
||||
'Dell invoice 4471.pdf')},
|
||||
content_type='multipart/form-data',
|
||||
headers=auth_headers)
|
||||
|
||||
assert response.status_code == 200, response.get_json()
|
||||
body = response.get_json()['data']
|
||||
assert body['proofurl'] == f'/api/warranty/proof/warranty-{w.warrantyid}.pdf'
|
||||
assert body['prooffilename'] == 'Dell invoice 4471.pdf'
|
||||
|
||||
|
||||
def test_download_needs_a_token_and_uses_the_vendor_filename(client, db, auth_headers):
|
||||
"""An invoice carries pricing and a service tag - not open like an asset photo."""
|
||||
w = _warranty(db)
|
||||
client.post(f'/api/warranty/{w.warrantyid}/proof',
|
||||
data={'file': (io.BytesIO(b'%PDF-1.4 invoice'), 'Dell invoice 4471.pdf')},
|
||||
content_type='multipart/form-data', headers=auth_headers)
|
||||
path = f'/api/warranty/proof/warranty-{w.warrantyid}.pdf'
|
||||
|
||||
assert client.get(path).status_code == 401
|
||||
|
||||
authed = client.get(path, headers=auth_headers)
|
||||
assert authed.status_code == 200
|
||||
assert authed.data == b'%PDF-1.4 invoice'
|
||||
disposition = authed.headers.get('Content-Disposition', '')
|
||||
assert 'attachment' in disposition
|
||||
assert 'Dell invoice 4471.pdf' in disposition
|
||||
|
||||
|
||||
def test_rejects_an_unsupported_type(client, db, auth_headers):
|
||||
w = _warranty(db)
|
||||
|
||||
response = client.post(f'/api/warranty/{w.warrantyid}/proof',
|
||||
data={'file': (io.BytesIO(b'MZ'), 'setup.exe')},
|
||||
content_type='multipart/form-data',
|
||||
headers=auth_headers)
|
||||
|
||||
assert response.status_code == 400
|
||||
assert 'Unsupported document type' in response.get_data(as_text=True)
|
||||
|
||||
|
||||
def test_rejects_an_oversize_document(client, db, auth_headers, monkeypatch):
|
||||
from plugins.warranty.api import routes
|
||||
monkeypatch.setattr(routes, 'MAX_PROOF_BYTES', 512)
|
||||
w = _warranty(db)
|
||||
|
||||
response = client.post(f'/api/warranty/{w.warrantyid}/proof',
|
||||
data={'file': (io.BytesIO(b'x' * 2048), 'scan.pdf')},
|
||||
content_type='multipart/form-data',
|
||||
headers=auth_headers)
|
||||
|
||||
assert response.status_code == 400
|
||||
assert 'the limit is' in response.get_data(as_text=True)
|
||||
|
||||
|
||||
def test_replacing_keeps_one_document_per_warranty(client, db, auth_headers):
|
||||
import glob
|
||||
import os
|
||||
from flask import current_app
|
||||
w = _warranty(db)
|
||||
|
||||
client.post(f'/api/warranty/{w.warrantyid}/proof',
|
||||
data={'file': (io.BytesIO(b'first'), 'scan.png')},
|
||||
content_type='multipart/form-data', headers=auth_headers)
|
||||
client.post(f'/api/warranty/{w.warrantyid}/proof',
|
||||
data={'file': (io.BytesIO(b'%PDF second'), 'invoice.pdf')},
|
||||
content_type='multipart/form-data', headers=auth_headers)
|
||||
|
||||
proofdir = os.path.join(current_app.instance_path, 'warrantyproofs')
|
||||
files = glob.glob(os.path.join(proofdir, f'warranty-{w.warrantyid}.*'))
|
||||
assert len(files) == 1 and files[0].endswith('.pdf')
|
||||
|
||||
|
||||
def test_removing_clears_both_columns(client, db, auth_headers):
|
||||
w = _warranty(db)
|
||||
client.post(f'/api/warranty/{w.warrantyid}/proof',
|
||||
data={'file': (io.BytesIO(b'%PDF'), 'invoice.pdf')},
|
||||
content_type='multipart/form-data', headers=auth_headers)
|
||||
|
||||
response = client.delete(f'/api/warranty/{w.warrantyid}/proof',
|
||||
headers=auth_headers)
|
||||
|
||||
body = response.get_json()['data']
|
||||
assert body['proofurl'] is None
|
||||
assert body['prooffilename'] is None
|
||||
Reference in New Issue
Block a user