"""Put file attachment tests.""" import json import unittest import boto3 from httmock import all_requests from httmock import HTTMock from moto import mock_aws import application from manualadjustment import config from manualadjustment.models.manual_adjustment import ManualAdjustment from utils import db_ops class TestPutAttachment(unittest.TestCase): """Test various scenarios of PUT with file attachment.""" def setUp(self): """Test setup procedure.""" self.app = application.app.test_client() db_ops.create_tables() db_ops.seed_art_relations() self.filename = 'test_put_attachment.csv' self.request_json = { 'attachment_url': 'http://mock_url/{}'.format(self.filename)} self.headers = [('Content-Type', 'application/json')] ma_id = db_ops.ar_session.query(ManualAdjustment).first().id self.url = '/manual_adjustment/{}'.format(ma_id) self.attachment_text = 'test_put_attachment data' def tearDown(self): """Test teardown procedure.""" db_ops.create_tables() @all_requests def attachment_url_success(self, url, request): """Mock response from requests lib for attachment_url.""" return {'status_code': 200, 'content': self.attachment_text} @all_requests def attachment_url_unknown(self, url, request): """Mock response from requests lib for attachment_url.""" return {'status_code': 404} @mock_aws def test_attachment_url_success(self): """Assert updating filename updates db and s3, then delete the file.""" with HTTMock(self.attachment_url_success): sqs_conn = boto3.client('sqs', region_name=config.AWS_REGION) sqs_conn.create_queue(QueueName=config.queue_name) resource = boto3.resource('s3') resource.create_bucket(Bucket=config.bucket_name) res = self.app.put( self.url, data=json.dumps(self.request_json), headers=self.headers) # verify PUT response contains new file self.assertEqual(res.status_code, 200) json_response = json.loads(res.data.decode('utf-8')) self.assertIn( self.filename, json_response['attachment_location']) # verify db record was updated with new file db_rec = db_ops.ar_session.query(ManualAdjustment).first() self.assertIn(self.filename, db_rec.attachment_location) # verify S3 contains new file bucket = resource.Bucket(config.bucket_name) for obj in bucket.objects.all(): body = obj.get()['Body'].read() assert self.attachment_text == body.decode('utf-8') # test deleting the file after it was created res = self.app.put( self.url, data='{"attachment_url": null}', headers=self.headers) # verify PUT response shows null attachment_location self.assertEqual(res.status_code, 200) json_response = json.loads(res.data.decode('utf-8')) self.assertIsNone(json_response['attachment_location']) # verify db record has NULL attachment_location db_ops.ar_session.refresh(db_rec) self.assertIsNone(db_rec.attachment_location) # verify file was removed from S3 bucket = resource.Bucket(config.bucket_name) body = '' for obj in bucket.objects.all(): body = obj.get()['Body'].read() assert len(body) == 0 @mock_aws def test_bad_attachment_url(self): """Assert that service returns error for bad attachment_url.""" with HTTMock(self.attachment_url_unknown): resource = boto3.resource('s3') resource.create_bucket(Bucket=config.bucket_name) res = self.app.put( self.url, data=json.dumps(self.request_json), headers=self.headers) self.assertEqual(res.status_code, 500) json_response = json.loads(res.data.decode('utf-8')) self.assertEqual('could not upload to s3', json_response['error'])