import io from itertools import zip_longest import os import json import mock import boto from boto.s3.key import Key from moto import mock_s3 import openpyxl from app.logic import converter from app import config bucket_name = config.bucket_name + 'testbucketthatdoesntexist' owner_type = 'vendor' owner_id = '1236' filename = 'Perf_Rights_Test.xlsx' def test_open_fp(): file_type = 'xlsx' # Mock open to only return BytesIO file-like objects open_ = mock.MagicMock(return_value=io.BytesIO()) with mock.patch('builtins.open', open_): converter.open_fp(config.temp_dir, file_type, owner_type, owner_id, filename, 'wb') xlsx_fs_folder = converter.build_fs_path(config.temp_dir, 'xlsx', owner_type, owner_id) open_.assert_called_once_with(os.path.join(xlsx_fs_folder, filename), 'wb') def test_reopen_fp(): file_type = 'xlsx' # Mock open to only return BytesIO file-like objects open_ = mock.MagicMock(return_value=io.BytesIO()) with mock.patch('builtins.open', open_): temp_fp = converter.open_fp(config.temp_dir, file_type, owner_type, owner_id, filename, 'wb') # Mock open to only return BytesIO file-like objects open_ = mock.MagicMock(return_value=io.BytesIO()) with mock.patch('builtins.open', open_): converter.reopen_fp(config.temp_dir, file_type, owner_type, owner_id, filename, 'rb', temp_fp) xlsx_fs_folder = converter.build_fs_path(config.temp_dir, 'xlsx', owner_type, owner_id) open_.assert_called_once_with(os.path.join(xlsx_fs_folder, filename), 'rb') def test_build_s3_path(): xlsx_s3_folder = converter.build_s3_path(config.prefix, 'app', owner_type, owner_id) assert xlsx_s3_folder == 'ows-xlsx/app/vendor_1236' def test_build_s3_path_no_user(): xlsx_s3_folder = converter.build_s3_path(config.prefix, 'app', None, None) assert xlsx_s3_folder == 'ows-xlsx/app' def test_build_fs_path(): # build the folder xlsx_fs_folder = converter.build_fs_path(config.prefix, 'app', owner_type, owner_id) assert xlsx_fs_folder == 'ows-xlsx/app/vendor_1236/' def test_build_fs_path_no_user(): # build the folder xlsx_fs_folder = converter.build_fs_path(config.prefix, 'app', None, None) assert xlsx_fs_folder == 'ows-xlsx/app/' @mock_s3 def test_get_file_from_s3(): test_data = b'This is a test' # build the folder xlsx_s3_folder = converter.build_s3_path(config.prefix, 'app', owner_type, owner_id) # open a mock connection to s3 s3 = boto.connect_s3() # use an in-memory stream instead of a real file mock_fp = io.BytesIO() # create the mock file to download bucket = s3.create_bucket(bucket_name) k = Key(bucket) k.key = xlsx_s3_folder + '/' + filename # pass in the test data k.set_contents_from_string(test_data) # should download the file from s3 and save it to the mock filesystem converter.get_file_from_s3(s3, bucket, xlsx_s3_folder, filename, mock_fp) # at this point the mock file should be filled with the test data assert test_data == mock_fp.getvalue() def _convert_xlsx(xlsx_filename, row_offset): # create mock files json_fp = io.BytesIO() xlsx_fp = io.BytesIO() # open the xlsx fixture file full_path = os.path.join( os.path.dirname(__file__), 'fixtures', xlsx_filename) with open(full_path, 'rb') as xlsx_fixture_file: # populate the mock xlsx file with the # binary data from the fixture file xlsx_fp.write(xlsx_fixture_file.read()) # call the convert function converter.convert_xlsx_to_json(xlsx_fp, json_fp, filename, row_offset) # reset the stream pointer json_fp.seek(0) # read the output file's line delimited json contents actual_json_lines = [json.loads(line.decode('UTF-8')) for line in json_fp] return actual_json_lines def _convert_json(json_filename): # open the json fixture file full_path = os.path.join( os.path.dirname(__file__), 'fixtures', json_filename) with open(full_path, 'rb') as json_fixture_file: json_lines = [ json.loads(line.decode('UTF-8')) for line in json_fixture_file] return json_lines def test_convert_xlsx_to_json(): expected_json_lines = _convert_json('Perf_Rights_Test.json') actual_json_lines = _convert_xlsx('Perf_Rights_Test.xlsx', 0) assert actual_json_lines[0] == expected_json_lines[0] assert actual_json_lines[1] == expected_json_lines[1] assert actual_json_lines[2] == expected_json_lines[2] actual_json_lines = _convert_xlsx('Perf_Rights_Test_Offset.xlsx', 2) assert actual_json_lines[0] == expected_json_lines[0] assert actual_json_lines[1] == expected_json_lines[1] assert actual_json_lines[2] == expected_json_lines[2] actual_json_lines = _convert_xlsx('Perf_Rights_Test_Null_Rows.xlsx', 0) assert len(actual_json_lines) == 3 assert actual_json_lines[0] == expected_json_lines[0] assert actual_json_lines[1] == expected_json_lines[1] assert actual_json_lines[2] == expected_json_lines[2] def test_convert_valid_json_to_xlsx(): convert_json_to_xlsx( 'Perf_Rights_Template.xlsx', 'Perf_Rights_Test.json', 'Perf_Rights_Test.xlsx') def test_convert_invalid_json_to_xlsx(): convert_json_to_xlsx( 'Perf_Rights_Exception_Template.xlsx', 'Perf_Rights_Test_Invalid.json', 'Perf_Rights_Exception_Test.xlsx') def convert_json_to_xlsx(template, test_json, expected_excel): # create mock files xlsx_template_fp = io.BytesIO() xlsx_fp = io.BytesIO() # open the xlsx source fixture file with open(os.path.join( os.path.dirname(__file__), 'fixtures', template), 'rb') as xlsx_fixture_file: # populate the mock xlsx file with the # binary data from the fixture file xlsx_template_fp.write(xlsx_fixture_file.read()) xlsx_template_fp.seek(0) # open the json source fixture file json_fp = open(os.path.join( os.path.dirname(__file__), 'fixtures', test_json), 'r', encoding='utf-8') # open the xlsx expected fixture file expected_wb = openpyxl.load_workbook( os.path.join( os.path.dirname(__file__), 'fixtures', expected_excel)) expected_ws = expected_wb[expected_wb.sheetnames[0]] converter.convert_json_to_xlsx(json_fp, xlsx_fp, filename, xlsx_template_fp) json_fp.close() # reset the output stream pointer xlsx_fp.seek(0) # re-read the output into an Excel object for assertions output_wb = openpyxl.load_workbook(xlsx_fp) output_ws = output_wb[output_wb.sheetnames[0]] assert expected_ws.freeze_panes, 'Expected Row is not frozen' assert output_ws.freeze_panes, 'Actual Row is not frozen' assert expected_ws.freeze_panes == output_ws.freeze_panes # compare the generated spreadsheet to the expected fixture file for expected_row, actual_row in zip_longest( expected_ws.rows, output_ws.rows): # confirm that the current row is expected assert expected_row, 'Additional row found in output' assert actual_row, 'Row expected was not found in output' # check all of the values in each row for expected_cell, actual_cell in zip_longest( expected_row, actual_row): assert expected_cell, 'Additional cell found in output' assert actual_cell, 'Cell expected was not found in output' assert actual_cell.value == expected_cell.value actual_protection = actual_cell.protection.locked expected_protection = expected_cell.protection.locked assert actual_protection == expected_protection # check for comments if expected_cell.comment: assert actual_cell.comment, 'No comment found in actual' # check coordinates for non-empty cells if expected_cell.value is not None: assert actual_cell.coordinate == expected_cell.coordinate @mock_s3 def test_put_file_to_s3(): test_data = b'This is a test' # build the folder json_s3_folder = converter.build_s3_path(config.prefix, '/json/', owner_type, owner_id) # open a mock connection to s3 s3 = boto.connect_s3() # use an in-memory stream instead of a real file mock_fp = io.BytesIO() mock_fp.write(test_data) bucket = s3.create_bucket(config.bucket_name + 'testbucketthatdoesntexist') # reset the pointer mock_fp.seek(0) # will upload the mock file contenst to the mock s3 bucket k = converter.put_file_to_s3(s3, bucket, json_s3_folder, filename, mock_fp) # at this point the mock file should be filled with the test data assert test_data == k.get_contents_as_string()