def test_sticky_status_is_set(self): """A sticky status is set during moderation.""" # Client creates the submission. example = os.path.join(BASEPATH, 'examples/complete_submission.json') with open(example) as f: data = json.load(f) response = self.client.post('/', data=json.dumps(data), content_type='application/json', headers=self.headers) submission_id = json.loads(response.data)['submission_id'] # Moderator, admin, or other agent places the submission on hold, # and a sticky status is set. with self.app.app_context(): from arxiv.submission.services import classic session = classic.current_session() submission = session.query(classic.models.Submission)\ .get(submission_id) submission.status = submission.ON_HOLD submission.sticky_status = submission.ON_HOLD session.add(submission) session.commit() # Client gets submission state. response = self.client.get(f'/{submission_id}/', headers=self.headers) submission_data = json.loads(response.data) self.assertEqual(submission_data['status'], 'hold', "Status should be `hold`") # Client withdraws the submission from the queue. response = self.client.post(f'/{submission_id}/', data=json.dumps({"finalized": False}), content_type='application/json', headers=self.headers) submission_data = json.loads(response.data) self.assertFalse(submission_data['finalized'], "Should no longer be finalized") # Client gets submission state. response = self.client.get(f'/{submission_id}/', headers=self.headers) submission_data = json.loads(response.data) self.assertFalse(submission_data['finalized'], "Should no longer be finalized") self.assertEqual(submission_data['status'], 'working', "Status should be `working`") # Client finalizes the submission for moderation. response = self.client.post(f'/{submission_id}/', data=json.dumps({"finalized": True}), content_type='application/json', headers=self.headers) submission_data = json.loads(response.data) # Client gets submission state. response = self.client.get(f'/{submission_id}/', headers=self.headers) submission_data = json.loads(response.data) self.assertTrue(submission_data['finalized'], "Should be finalized") self.assertEqual(submission_data['status'], 'hold', "Status should be `hold`, as sticky_status was set")
def test_submission_placed_on_hold(self): """Before publication, a submission may be placed on hold.""" # Client creates the submission. example = os.path.join(BASEPATH, 'examples/complete_submission.json') with open(example) as f: data = json.load(f) response = self.client.post('/', data=json.dumps(data), content_type='application/json', headers=self.headers) submission_id = json.loads(response.data)['submission_id'] # Moderator, admin, or other agent places the submission on hold. with self.app.app_context(): from arxiv.submission.services import classic session = classic.current_session() submission = session.query(classic.models.Submission) \ .get(submission_id) submission.status = submission.ON_HOLD session.add(submission) session.commit() # Client gets submission state. response = self.client.get(f'/{submission_id}/', headers=self.headers) submission_data = json.loads(response.data) self.assertEqual(submission_data['status'], 'hold', "Status should be `hold`")
def test_request_withdrawal(self): """User requests withdrawal of a announced submission.""" # Get the JREF page. endpoint = f'/{self.submission_id}/withdraw' response = self.client.get(endpoint, headers=self.headers) self.assertEqual(response.status_code, status.OK) self.assertEqual(response.content_type, 'text/html; charset=utf-8') self.assertIn(b'Request withdrawal', response.data) token = self._parse_csrf_token(response) # Set the withdrawal reason, but make it huge. request_data = { 'withdrawal_reason': 'This is the reason' * 400, 'csrf_token': token } response = self.client.post(endpoint, data=request_data, headers=self.headers) self.assertEqual(response.status_code, status.BAD_REQUEST) token = self._parse_csrf_token(response) # Set the withdrawal reason to something reasonable (ha). request_data = { 'withdrawal_reason': 'This is the reason', 'csrf_token': token } response = self.client.post(endpoint, data=request_data, headers=self.headers) self.assertEqual(response.status_code, status.OK) self.assertEqual(response.content_type, 'text/html; charset=utf-8') self.assertIn(b'Confirm and Submit', response.data) token = self._parse_csrf_token(response) # Confirm the withdrawal request. request_data['confirmed'] = True request_data['csrf_token'] = token response = self.client.post(endpoint, data=request_data, headers=self.headers) self.assertEqual(response.status_code, status.SEE_OTHER) with self.app.app_context(): session = classic.current_session() # What happened. db_submissions = session.query(classic.models.Submission) \ .filter(classic.models.Submission.doc_paper_id == '1234.5678') self.assertEqual(db_submissions.count(), 2, "Creates a second row for the withdrawal") db_submission = db_submissions \ .order_by(classic.models.Submission.submission_id.desc()) \ .first() self.assertEqual(db_submission.type, classic.models.Submission.WITHDRAWAL)
def in_memory_db(): """Provide an in-memory sqlite database for testing purposes.""" app = Flask('foo') app.config['CLASSIC_DATABASE_URI'] = 'sqlite://' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False with app.app_context(): classic.init_app(app) classic.create_all() try: yield classic.current_session() except Exception: raise finally: classic.drop_all()
def test_publication_failed(self): """The submission was not announced successfully.""" with self.app.app_context(): from arxiv.submission.services import classic session = classic.current_session() # Publication agent publishes the paper. db_submission = session.query(classic.models.Submission)\ .get(self.submission_id) db_submission.status = db_submission.ERROR_STATE session.add(db_submission) session.commit() # Submission state should reflect scheduled status. response = self.client.get(f'/{self.submission_id}/', headers=self.headers) submission = json.loads(response.data) self.assertEqual(submission['status'], Submission.ERROR, "Submission should have error status.")
def test_scheduled_tomorrow_status_is_reflected(self): """The submission has been scheduled for publication tomorrow.""" with self.app.app_context(): from arxiv.submission.services import classic session = classic.current_session() # Publication agent publishes the paper. db_submission = session.query(classic.models.Submission)\ .get(self.submission_id) db_submission.status = db_submission.NEXT_PUBLISH_DAY session.add(db_submission) session.commit() # Submission state should reflect scheduled status. response = self.client.get(f'/{self.submission_id}/', headers=self.headers) submission = json.loads(response.data) self.assertEqual(submission['status'], Submission.SCHEDULED, "Submission should be scheduled for tomorrow.")
def test_scheduled_status_is_reflected_prior_to_announcement(self): """The submission is being announced; not yet announced.""" with self.app.app_context(): from arxiv.submission.services import classic session = classic.current_session() # Publication agent publishes the paper. db_submission = session.query(classic.models.Submission)\ .get(self.submission_id) db_submission.status = db_submission.NEEDS_EMAIL session.add(db_submission) session.commit() # Submission state should reflect scheduled status. response = self.client.get(f'/{self.submission_id}/', headers=self.headers) submission = json.loads(response.data) self.assertEqual(submission['status'], Submission.SCHEDULED, "Submission should have scheduled status.")
def test_deleted(self): """The submission was deleted.""" with self.app.app_context(): from arxiv.submission.services import classic session = classic.current_session() for classic_status in classic.models.Submission.DELETED: # Publication agent publishes the paper. db_submission = session.query(classic.models.Submission)\ .get(self.submission_id) db_submission.status = classic_status session.add(db_submission) session.commit() # Submission state should reflect scheduled status. response = self.client.get(f'/{self.submission_id}/', headers=self.headers) submission = json.loads(response.data) self.assertEqual(submission['status'], Submission.DELETED, "Submission should have deleted status.")
def test_create_submission(self): """User creates a new submission, and proceeds up to upload stage.""" # Get the JREF page. endpoint = f'/{self.submission_id}/jref' response = self.client.get(endpoint, headers=self.headers) self.assertEqual(response.status_code, status.OK) self.assertEqual(response.content_type, 'text/html; charset=utf-8') self.assertIn(b'Journal reference', response.data) token = self._parse_csrf_token(response) # Set the DOI, journal reference, report number. request_data = { 'doi': '10.1000/182', 'journal_ref': 'foo journal 1992', 'report_num': 'abc report 42', 'csrf_token': token } response = self.client.post(endpoint, data=request_data, headers=self.headers) self.assertEqual(response.status_code, status.OK) self.assertEqual(response.content_type, 'text/html; charset=utf-8') self.assertIn(b'Confirm and Submit', response.data) token = self._parse_csrf_token(response) request_data['confirmed'] = True request_data['csrf_token'] = token response = self.client.post(endpoint, data=request_data, headers=self.headers) self.assertEqual(response.status_code, status.SEE_OTHER) with self.app.app_context(): session = classic.current_session() # What happened. db_submission = session.query(classic.models.Submission) \ .filter(classic.models.Submission.doc_paper_id == '1234.5678') self.assertEqual(db_submission.count(), 2, "Creates a second row for the JREF")
def test_publication_status_is_reflected_after_files_expire(self): """The submission has been announced/announced, and files expired.""" with self.app.app_context(): from arxiv.submission.services import classic session = classic.current_session() # Publication agent publishes the paper. db_submission = session.query(classic.models.Submission)\ .get(self.submission_id) db_submission.status = db_submission.DELETED_ANNOUNCED dated = (datetime.now() - datetime.utcfromtimestamp(0)) primary = self.submission['primary_classification']['category'] db_submission.document = classic.models.Document( document_id=1, paper_id='1901.00123', title=self.submission['metadata']['title'], authors=self.submission['metadata']['authors_display'], dated=dated.total_seconds(), primary_subject_class=primary, created=datetime.now(UTC), submitter_email=self.submission['creator']['email'], submitter_id=self.submission['creator']['user_id']) session.add(db_submission) session.commit() # Submission state should reflect publication status. response = self.client.get(f'/{self.submission_id}/', headers=self.headers) submission = json.loads(response.data) self.assertEqual(submission['status'], Submission.ANNOUNCED, "Submission should have announced status.") self.assertEqual(submission['arxiv_id'], "1901.00123", "arXiv paper ID should be set") self.assertFalse( submission['active'], "Announced submission should no longer be active")
from arxiv.submission.services import classic from arxiv.submission.services.classic import bootstrap from arxiv.users.helpers import generate_token from arxiv.users.auth import scopes from submit.factory import create_ui_web_app logging.getLogger('arxiv.submission.services.classic.interpolate') \ .setLevel(logging.ERROR) logging.getLogger('arxiv.base.alerts').setLevel(logging.ERROR) logger = logging.getLogger(__name__) app = create_ui_web_app() with app.app_context(): session = classic.current_session() engine = classic.util.current_engine() logger.info('Waiting for database server to be available') logger.info(app.config['SQLALCHEMY_DATABASE_URI']) wait = 2 while True: try: session.execute('SELECT 1') break except Exception as e: logger.info(e) logger.info(f'...waiting {wait} seconds...') time.sleep(wait) wait *= 2 logger.info('Checking for database')
def setUp(self): """Create an application instance.""" self.app = create_ui_web_app() os.environ['JWT_SECRET'] = self.app.config.get('JWT_SECRET') _, self.db = tempfile.mkstemp(suffix='.db') self.app.config['CLASSIC_DATABASE_URI'] = f'sqlite:///{self.db}' self.user = User('1234', '*****@*****.**', endorsements=['astro-ph.GA', 'astro-ph.CO']) self.token = generate_token( '1234', '*****@*****.**', 'foouser', scope=[ scopes.CREATE_SUBMISSION, scopes.EDIT_SUBMISSION, scopes.VIEW_SUBMISSION, scopes.READ_UPLOAD, scopes.WRITE_UPLOAD, scopes.DELETE_UPLOAD_FILE ], endorsements=[ Category('astro-ph.GA'), Category('astro-ph.CO'), ]) self.headers = {'Authorization': self.token} self.client = self.app.test_client() # Create and announce a submission. with self.app.app_context(): classic.create_all() session = classic.current_session() cc0 = 'http://creativecommons.org/publicdomain/zero/1.0/' self.submission, _ = save( CreateSubmission(creator=self.user), ConfirmContactInformation(creator=self.user), ConfirmAuthorship(creator=self.user, submitter_is_author=True), SetLicense(creator=self.user, license_uri=cc0, license_name='CC0 1.0'), ConfirmPolicy(creator=self.user), SetPrimaryClassification(creator=self.user, category='astro-ph.GA'), SetUploadPackage( creator=self.user, checksum="a9s9k342900skks03330029k", source_format=SubmissionContent.Format.TEX, identifier=123, uncompressed_size=593992, compressed_size=59392, ), SetTitle(creator=self.user, title='foo title'), SetAbstract(creator=self.user, abstract='ab stract' * 20), SetComments(creator=self.user, comments='indeed'), SetReportNumber(creator=self.user, report_num='the number 12'), SetAuthors(creator=self.user, authors=[ Author(order=0, forename='Bob', surname='Paulson', email='*****@*****.**', affiliation='Fight Club') ]), FinalizeSubmission(creator=self.user)) # announced! db_submission = session.query(classic.models.Submission) \ .get(self.submission.submission_id) db_submission.status = classic.models.Submission.ANNOUNCED db_document = classic.models.Document(paper_id='1234.5678') db_submission.doc_paper_id = '1234.5678' db_submission.document = db_document session.add(db_submission) session.add(db_document) session.commit() self.submission_id = self.submission.submission_id