156 lines
6.5 KiB
Python
156 lines
6.5 KiB
Python
"""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
|
|
|
|
|
|
# --- a date that is not a date -----------------------------------------------
|
|
#
|
|
# PUT /api/warranty/<id> with an unparseable enddate answered 200 "Warranty
|
|
# updated" and stored NULL, which drops the record out of every expiry surface
|
|
# it feeds. The local _parse_date swallowed the ValueError, so a typo and a
|
|
# deliberate clear produced the same write.
|
|
|
|
def _warranty_via_api(client, auth_headers, **fields):
|
|
payload = {'vendor': 'Acme', 'servicetag': 'WD-1', 'enddate': '2027-06-30'}
|
|
payload.update(fields)
|
|
created = client.post('/api/warranty', headers=auth_headers, json=payload)
|
|
assert created.status_code == 201, created.get_json()
|
|
return created.get_json()['data']['warrantyid']
|
|
|
|
|
|
def test_a_mistyped_end_date_is_refused_not_stored_as_null(client, db,
|
|
auth_headers):
|
|
warrantyid = _warranty_via_api(client, auth_headers)
|
|
|
|
refused = client.put(f'/api/warranty/{warrantyid}', headers=auth_headers,
|
|
json={'enddate': '30-06-2027'})
|
|
assert refused.status_code == 400, refused.get_json()
|
|
assert 'enddate' in refused.get_json()['data']['error']['message']
|
|
|
|
kept = db.session.get(Warranty, warrantyid)
|
|
assert kept.enddate is not None, 'the stored cover date must survive a typo'
|
|
assert str(kept.enddate) == '2027-06-30'
|
|
|
|
|
|
def test_an_explicitly_empty_end_date_still_clears_it(client, db, auth_headers):
|
|
warrantyid = _warranty_via_api(client, auth_headers, servicetag='WD-2')
|
|
cleared = client.put(f'/api/warranty/{warrantyid}', headers=auth_headers,
|
|
json={'enddate': ''})
|
|
assert cleared.status_code == 200, cleared.get_json()
|
|
assert db.session.get(Warranty, warrantyid).enddate is None
|
|
|
|
|
|
def test_a_mistyped_date_is_refused_at_create_too(client, db, auth_headers):
|
|
refused = client.post('/api/warranty', headers=auth_headers,
|
|
json={'vendor': 'Acme', 'servicetag': 'WD-3',
|
|
'startdate': 'yesterday'})
|
|
assert refused.status_code == 400, refused.get_json()
|
|
assert Warranty.query.filter_by(servicetag='WD-3').first() is None
|