def test_addWorkMeta(self): testWork = {} APIUtils.addWorkMeta(testWork, field1='value1', field2=['value2']) assert testWork['_meta']['field1'] == 'value1' assert testWork['_meta']['field2'] == ['value2']
def test_normalizeQueryParams(self, mocker): mockParams = mocker.MagicMock() mockParams.to_dict.return_value = {'test1': 1, 'test2': 2} testParams = APIUtils.normalizeQueryParams(mockParams) assert testParams == {'test1': 1, 'test2': 2}
def test_formatWorkOutput_multiple_works(self, mocker): mockFormat = mocker.patch.object(APIUtils, 'formatWork') mockFormat.side_effect = ['formattedWork1', 'formattedWork2'] mockAddMeta = mocker.patch.object(APIUtils, 'addWorkMeta') testWorks = [ mocker.MagicMock(uuid='uuid1'), mocker.MagicMock(uuid='uuid2') ] outWorks = APIUtils.formatWorkOutput(testWorks, [('uuid1', 1, 'highlight1'), ('uuid2', 2, 'highlight2'), ('uuid3', 3, 'highlight3')]) assert outWorks == ['formattedWork1', 'formattedWork2'] mockFormat.assert_has_calls([ mocker.call(testWorks[0], 1, True, formats=None, reader=None), mocker.call(testWorks[1], 2, True, formats=None, reader=None) ]) mockAddMeta.assert_has_calls([ mocker.call('formattedWork1', highlights='highlight1'), mocker.call('formattedWork2', highlights='highlight2') ])
def test_formatLanguages_no_counts(self, mocker): mockAggs = mocker.MagicMock() mockAggs.languages.languages.buckets = [ mocker.MagicMock(key='bLang'), mocker.MagicMock(key='aLang') ] assert APIUtils.formatLanguages(mockAggs) ==\ [{'language': 'aLang'}, {'language': 'bLang'}]
def test_formatWork_blocked_edition(self, testWork): testWork.editions[0].items = [] testWorkDict = APIUtils.formatWork(testWork, ['ed2'], True) assert testWorkDict['uuid'] == 'testUUID' assert testWorkDict['title'] == 'Test Title' assert len(testWorkDict['editions']) == 0 assert testWorkDict['edition_count'] == 1 assert testWorkDict['date_created'] == '2022-05-12T10:00:41' assert testWorkDict['date_modified'] == '2022-05-13T10:00:44'
def test_formatAggregationResult(self, testAggregationResp): testAggregations = APIUtils.formatAggregationResult( testAggregationResp) assert testAggregations['languages'][0] ==\ {'value': 'Lang1', 'count': 1} assert testAggregations['languages'][1] ==\ {'value': 'Lang2', 'count': 3} assert testAggregations['formats'][0] ==\ {'value': 'Format1', 'count': 5}
def test_formatPagingOptions_next_null(self): testPagingOptions = APIUtils.formatPagingOptions(6, 10, 55) assert testPagingOptions == { 'recordsPerPage': 10, 'firstPage': 1, 'previousPage': 5, 'currentPage': 6, 'nextPage': None, 'lastPage': 6 }
def test_formatLinkOutput(self, testLink, testWork, testEdition, testItem): testEdition.work = testWork testItem.edition = testEdition testLink.items = [testItem] testLink = APIUtils.formatLinkOutput(testLink) assert testLink['link_id'] == 'li1' assert testLink['work']['uuid'] == 'testUUID' assert testLink['work']['editions'][0]['edition_id'] == 'ed1' assert testLink['work']['editions'][0]['items'][0]['item_id'] == 'it1'
def test_formatEdition_v2_reader_flag(self, testEdition, testWebpubItem): testEdition.items.append(testWebpubItem) formattedEdition = APIUtils.formatEdition(testEdition, reader='v2') assert len(formattedEdition['items']) == 2 assert formattedEdition['items'][0]['item_id'] == 'it2' assert formattedEdition['items'][0]['links'][0]['mediaType'] ==\ 'application/webpub+json' assert formattedEdition['items'][1]['links'][0]['flags']['reader'] is\ False
def test_formatPipeDelimitedData_list(self): assert APIUtils.formatPipeDelimitedData( ['test|object', None, 'another|thing'], ['one', 'two']) == [{ 'one': 'test', 'two': 'object' }, { 'one': 'another', 'two': 'thing' }]
def test_formatEdition_w_records(self, testEdition, mocker): mockRecFormat = mocker.patch.object(APIUtils, 'formatRecord') mockRecFormat.side_effect = [{ 'id': 1, 'items': [] }, { 'id': 2, 'items': ['it1'] }] formattedEdition = APIUtils.formatEdition(testEdition, editionWorkTitle=None, editionWorkAuthors=None, records=['rec1', 'rec2'], showAll=False) assert len(formattedEdition['instances']) == 1 assert formattedEdition['instances'][0]['id'] == 2 assert formattedEdition.get('items', None) is None testItemDict = { 'id': 'it1', 'links': [{ 'link_id': 'li1', 'mediaType': 'application/epub+xml', 'url': 'testURI', 'flags': { 'test': True } }], 'rights': [{ 'source': 'test', 'license': 'testLicense', 'rightsStatement': 'testStatement' }], 'physical_location': { 'name': 'test' }, 'item_id': 'it1', 'location': 'test', 'source': 'hathitrust' } mockRecFormat.assert_has_calls([ mocker.call('rec1', {'testURI': testItemDict}), mocker.call('rec2', {'testURI': testItemDict}) ])
def test_formatWork_showAll_false(self, testWork, mocker): mockFormatEdition = mocker.patch.object(APIUtils, 'formatEdition') mockFormatEdition.return_value = { 'edition_id': 'ed1', 'items': ['it1'] } testWorkDict = APIUtils.formatWork(testWork, ['ed1'], False) assert testWorkDict['uuid'] == 'testUUID' assert testWorkDict['title'] == 'Test Title' assert len(testWorkDict['editions']) == 1 assert testWorkDict['edition_count'] == 1 assert testWorkDict['date_created'] == '2022-05-12T10:00:41' assert testWorkDict['date_modified'] == '2022-05-13T10:00:44'
def test_formatWork_ordered_editions(self, testWork, mocker): testWork.editions = [mocker.MagicMock(id=1), mocker.MagicMock(id=2)] mockFormatEdition = mocker.patch.object(APIUtils, 'formatEdition') mockFormatEdition.side_effect = [{ 'edition_id': 'ed1', 'items': ['it1'] }, { 'edition_id': 'ed2', 'items': ['it2'] }] testWorkDict = APIUtils.formatWork(testWork, [2, 1], True) assert testWorkDict['editions'][0]['edition_id'] == 'ed2' assert testWorkDict['editions'][1]['edition_id'] == 'ed1'
def test_formatResponseObject(self, mocker): mockDatetime = mocker.patch('api.utils.datetime') mockDatetime.utcnow.return_value = 'presentTimestamp' mockJsonify = mocker.patch('api.utils.jsonify') mockJsonify.return_value = 'jsonBlock' testResponse = APIUtils.formatResponseObject(200, 'test', 'testData') assert testResponse[0] == 'jsonBlock' assert testResponse[1] == 200 mockDatetime.utcnow.assert_called_once mockJsonify.assert_called_once_with({ 'status': 200, 'timestamp': 'presentTimestamp', 'responseType': 'test', 'data': 'testData' })
def test_formatLanguages_counts(self, mocker): mockAggs = mocker.MagicMock() mockAggs.languages.languages.buckets = [ mocker.MagicMock(key='bLang', work_totals=mocker.MagicMock(doc_count=10)), mocker.MagicMock(key='cLang', work_totals=mocker.MagicMock(doc_count=30)), mocker.MagicMock(key='aLang', work_totals=mocker.MagicMock(doc_count=20)) ] assert APIUtils.formatLanguages(mockAggs, True) == [{ 'language': 'cLang', 'work_total': 30 }, { 'language': 'aLang', 'work_total': 20 }, { 'language': 'bLang', 'work_total': 10 }]
def test_formatRecord(self, testRecord, mocker): testLinkItems = { 'url1': { 'item_id': 1, 'url': 'url1' }, 'url2': { 'item_id': 2, 'url': 'url2' } } mockFormatPipe = mocker.patch.object(APIUtils, 'formatPipeDelimitedData') mockFormatPipe.side_effect = [ 'testAuthors', 'testContribs', 'testPublishers', 'testDates', 'testLangs', 'testIDs' ] testFormatted = APIUtils.formatRecord(testRecord, testLinkItems) assert testFormatted['instance_id'] == 'rec1' assert testFormatted['title'] == 'Test Record' assert testFormatted['publication_place'] == 'Test Place' assert testFormatted['extent'] == 'Test Extent' assert testFormatted['summary'] == 'Test Summary' assert testFormatted['table_of_contents'] == 'Test TOC' assert testFormatted['authors'] == 'testAuthors' assert testFormatted['contributors'] == 'testContribs' assert testFormatted['publishers'] == 'testPublishers' assert testFormatted['dates'] == 'testDates' assert testFormatted['languages'] == 'testLangs' assert testFormatted['identifiers'] == 'testIDs' assert testFormatted['items'] == [{ 'item_id': 1, 'url': 'url1' }, { 'item_id': 2, 'url': 'url2' }]
def test_formatEditionOutput(self, mocker): mockFormatEdition = mocker.patch.object(APIUtils, 'formatEdition') mockFormatEdition.return_value = 'testEdition' mockDB = mocker.MagicMock() mockDBClient = mocker.patch('api.blueprints.drbEdition.DBClient') mockDBClient.return_value = mockDB mockEdition = mocker.MagicMock(dcdw_uuids='testUUID') mockDB.fetchSingleEdition.return_value = mockEdition assert APIUtils.formatEditionOutput(mockEdition, records='testRecords', showAll=True) == 'testEdition' mockFormatEdition.assert_called_once_with(mockEdition, mockEdition.work.title, mockEdition.work.authors, 'testRecords', showAll=True, reader=None)
def test_formatWorkOutput_single_work(self, mocker): mockFormat = mocker.patch.object(APIUtils, 'formatWork') mockFormat.return_value = { 'uuid': 1, 'editions': [{ 'id': 'ed1', 'publication_date': None }, { 'id': 'ed2', 'publication_date': 2000 }, { 'id': 'ed3', 'publication_date': 1900 }] } outWork = APIUtils.formatWorkOutput('testWork', None) assert outWork['uuid'] == 1 assert outWork['editions'][0]['id'] == 'ed3' assert outWork['editions'][2]['id'] == 'ed1' mockFormat.assert_called_once_with('testWork', None, True, reader=None)
def test_formatEdition_no_records(self, testEdition): formattedEdition = APIUtils.formatEdition(testEdition) assert formattedEdition['work_uuid'] == 'uuid1' assert formattedEdition['edition_id'] == 'ed1' assert formattedEdition['publication_date'] == 2000 assert formattedEdition['links'][0]['link_id'] == 'co1' assert formattedEdition['links'][0]['mediaType'] == 'image/png' assert formattedEdition['links'][0]['url'] == 'testCover' assert formattedEdition['items'][0]['item_id'] == 'it1' assert formattedEdition['items'][0]['location'] == 'test' assert formattedEdition['items'][0]['links'][0]['link_id'] == 'li1' assert formattedEdition['items'][0]['links'][0]['mediaType'] ==\ 'application/epub+xml' assert formattedEdition['items'][0]['links'][0]['url'] == 'testURI' assert formattedEdition['items'][0]['links'][0]['flags']['test'] is\ True assert formattedEdition['items'][0]['rights'][0]['source'] == 'test' assert formattedEdition['items'][0]['rights'][0]['license'] ==\ 'testLicense' assert formattedEdition['items'][0]['rights'][0]['rightsStatement'] ==\ 'testStatement' assert formattedEdition.get('instances', None) is None
def test_extractParamPairs_semicolon_no_field(self): testPairs = APIUtils.extractParamPairs('test', {'test': ['A Book: A Title']}) assert testPairs[0] == ('test', 'A Book: A Title')
def test_validatePassword_error(self): testHash = scrypt(b'testPswd', salt=b'testSalt', n=2**14, r=8, p=1) assert APIUtils.validatePassword('testError', testHash, b'testSalt')\ is False
def test_validatePassword_success(self): testHash = scrypt(b'testPswd', salt=b'testSalt', n=2**14, r=8, p=1) assert APIUtils.validatePassword('testPswd', testHash, b'testSalt')\ is True
def test_formatPipeDelimitedData_none(self): assert APIUtils.formatPipeDelimitedData(None, ['one', 'two']) is None
def test_extractParamPairs_dangling_quotation_multiple(self): testPairs = APIUtils.extractParamPairs( 'test', {'test': ['"A Title",keyword:"other']}) assert testPairs[0] == ('test', '"A Title"') assert testPairs[1] == ('keyword', 'other')
def test_formatPipeDelimitedData_string(self): assert APIUtils.formatPipeDelimitedData('test|object', ['one', 'two'])\ == {'one': 'test', 'two': 'object'}
def test_flatten_nested(self): flatArray = [i for i in APIUtils.flatten([[1, 2], 3, [4, [5]]])] assert flatArray == [1, 2, 3, 4, 5]
def test_flatten_already_flat(self): flatArray = [i for i in APIUtils.flatten([1, 2, 3, 4, 5])] assert flatArray == [1, 2, 3, 4, 5]
def test_formatTotals(self): assert APIUtils.formatTotals([('test', 3), ('other', 6)]) ==\ {'test': 3, 'other': 6}
def test_extractParamPairs_semantic_semicolon(self): testPairs = APIUtils.extractParamPairs( 'test', {'test': ['title:A Book: A Title']}) assert testPairs[0] == ('title', 'A Book: A Title')
def test_extractParamPairs_dangling_quotation(self): testPairs = APIUtils.extractParamPairs('test', {'test': ['"A Title']}) assert testPairs[0] == ('test', 'A Title')