Source code for search.routes.api.tests.test_api

"""Tests for API routes."""

import os
import json
from datetime import datetime
from unittest import TestCase, mock

import jsonschema

from arxiv.users import helpers, auth
from arxiv.users.domain import Scope
from arxiv import status

from search import factory
from search import domain


[docs]class TestAPISearchRequests(TestCase): """Requests against the main search API.""" SCHEMA_PATH = os.path.abspath('schema/resources/DocumentSet.json')
[docs] def setUp(self): """Instantiate and configure an API app.""" jwt_secret = 'foosecret' os.environ['JWT_SECRET'] = jwt_secret self.app = factory.create_api_web_app() self.app.config['JWT_SECRET'] = jwt_secret self.client = self.app.test_client() with open(self.SCHEMA_PATH) as f: self.schema = json.load(f)
[docs] def test_request_without_token(self): """No auth token is provided on the request.""" response = self.client.get('/') self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
[docs] def test_with_token_lacking_scope(self): """Client auth token lacks required public read scope.""" token = helpers.generate_token('1234', 'foo@bar.com', 'foouser', scope=[Scope('something', 'read')]) response = self.client.get('/', headers={'Authorization': token}) self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
[docs] @mock.patch(f'{factory.__name__}.api.api') def test_with_valid_token(self, mock_controller): """Client auth token has required public read scope.""" document = domain.Document( submitted_date=datetime.now(), submitted_date_first=datetime.now(), announced_date_first=datetime.now(), id='1234.5678', abstract='very abstract', authors=[ domain.Person(full_name='F. Bar', orcid='1234-5678-9012-3456') ], submitter=domain.Person(full_name='S. Ubmitter', author_id='su_1'), modified_date=datetime.now(), updated_date=datetime.now(), is_current=True, is_withdrawn=False, license={ 'uri': 'http://foo.license/1', 'label': 'Notalicense 5.4' }, paper_id='1234.5678', paper_id_v='1234.5678v6', title='tiiiitle', source={ 'flags': 'A', 'format': 'pdftotex', 'size_bytes': 2 }, version=6, latest='1234.5678v6', latest_version=6, report_num='somenum1', msc_class=['c1'], acm_class=['z2'], journal_ref='somejournal (1991): 2-34', doi='10.123456/7890', comments='very science', abs_categories='astro-ph.CO foo.BR', formats=['pdf', 'other'], primary_classification=domain.Classification( group={'id': 'foo', 'name': 'Foo Group'}, archive={'id': 'foo', 'name': 'Foo Archive'}, category={'id': 'foo.BR', 'name': 'Foo Category'}, ), secondary_classification=[ domain.Classification( group={'id': 'foo', 'name': 'Foo Group'}, archive={'id': 'foo', 'name': 'Foo Archive'}, category={'id': 'foo.BZ', 'name': 'Baz Category'}, ) ] ) docs = domain.DocumentSet( results=[document], metadata={'start': 0, 'end': 1, 'size': 50, 'total': 1} ) r_data = {'results': docs, 'query': domain.APIQuery()} mock_controller.search.return_value = r_data, status.HTTP_200_OK, {} token = helpers.generate_token('1234', 'foo@bar.com', 'foouser', scope=[auth.scopes.READ_PUBLIC]) response = self.client.get('/', headers={'Authorization': token}) self.assertEqual(response.status_code, status.HTTP_200_OK) data = json.loads(response.data) res = jsonschema.RefResolver( 'file://%s/' % os.path.abspath(os.path.dirname(self.SCHEMA_PATH)), None ) self.assertIsNone(jsonschema.validate(data, self.schema, resolver=res), 'Response content is valid per schema') for field in domain.api.get_required_fields(): self.assertIn(field, data['results'][0])
[docs] @mock.patch(f'{factory.__name__}.api.api') def test_with_valid_token_limit_fields(self, mock_controller): """Client auth token has required public read scope.""" document = domain.Document( submitted_date=datetime.now(), submitted_date_first=datetime.now(), announced_date_first=datetime.now(), id='1234.5678', abstract='very abstract', authors=[ domain.Person(full_name='F. Bar', orcid='1234-5678-9012-3456') ], submitter=domain.Person(full_name='S. Ubmitter', author_id='su_1'), modified_date=datetime.now(), updated_date=datetime.now(), is_current=True, is_withdrawn=False, license={ 'uri': 'http://foo.license/1', 'label': 'Notalicense 5.4' }, paper_id='1234.5678', paper_id_v='1234.5678v6', title='tiiiitle', source={ 'flags': 'A', 'format': 'pdftotex', 'size_bytes': 2 }, version=6, latest='1234.5678v6', latest_version=6, report_num='somenum1', msc_class=['c1'], acm_class=['z2'], journal_ref='somejournal (1991): 2-34', doi='10.123456/7890', comments='very science', abs_categories='astro-ph.CO foo.BR', formats=['pdf', 'other'], primary_classification=domain.Classification( group={'id': 'foo', 'name': 'Foo Group'}, archive={'id': 'foo', 'name': 'Foo Archive'}, category={'id': 'foo.BR', 'name': 'Foo Category'}, ), secondary_classification=[ domain.Classification( group={'id': 'foo', 'name': 'Foo Group'}, archive={'id': 'foo', 'name': 'Foo Archive'}, category={'id': 'foo.BZ', 'name': 'Baz Category'}, ) ] ) docs = domain.DocumentSet( results=[document], metadata={'start': 0, 'end': 1, 'size': 50, 'total': 1} ) query = domain.APIQuery(include_fields=['abstract', 'license']) r_data = {'results': docs, 'query': query} mock_controller.search.return_value = r_data, status.HTTP_200_OK, {} token = helpers.generate_token('1234', 'foo@bar.com', 'foouser', scope=[auth.scopes.READ_PUBLIC]) response = self.client.get('/', headers={'Authorization': token}) self.assertEqual(response.status_code, status.HTTP_200_OK) data = json.loads(response.data) res = jsonschema.RefResolver( 'file://%s/' % os.path.abspath(os.path.dirname(self.SCHEMA_PATH)), None ) self.assertIsNone(jsonschema.validate(data, self.schema, resolver=res), 'Response content is valid per schema') for field in domain.api.get_required_fields(): self.assertEqual( set(data['results'][0].keys()), set(query.include_fields) )