Skip to content

Commit

Permalink
Merge pull request #10840 from bodintsov/feature/crossref_and_doi_tests
Browse files Browse the repository at this point in the history
[ENG-6620] [ENG-6732] Added tests for versioned DOI and CrossRef metadata + Update Preprint Factory
  • Loading branch information
cslzchen authored Dec 14, 2024
2 parents 2396c7e + 5a842c0 commit 93997e5
Show file tree
Hide file tree
Showing 2 changed files with 142 additions and 1 deletion.
88 changes: 87 additions & 1 deletion osf_tests/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
from django.db.utils import IntegrityError
from faker import Factory, Faker
from waffle.models import Flag, Sample, Switch

from website.notifications.constants import NOTIFICATION_TYPES
from osf.utils import permissions
from website.archiver import ARCHIVER_SUCCESS
Expand Down Expand Up @@ -795,6 +794,93 @@ def _create(cls, target_class, *args, **kwargs):
instance.save()
return instance

@classmethod
def create_version(cls, *args, **kwargs):

update_task_patcher = mock.patch('website.preprints.tasks.on_preprint_updated.si')
update_task_patcher.start()

source_preprint = kwargs.pop('preprint')
# TODO: assert not source_preprint.has_unpublished_pending_version()
guid_obj = source_preprint.guids.first()
latest_version = guid_obj.versions.filter(is_rejected=False).order_by('-version').first().referent
assert latest_version.is_latest_version
last_version_number = guid_obj.versions.order_by('-version').first().version

finish = kwargs.pop('finish', True)
set_doi = kwargs.pop('set_doi', True)
is_published = kwargs.pop('is_published', True)
# TODO: machine_state = kwargs.pop('machine_state', 'initial')
license_details = None
if latest_version.license:
license_details = {
'id': latest_version.license.node_license.license_id,
'copyrightHolders': latest_version.license.copyright_holders,
'year': latest_version.license.year
}
subjects = [[el] for el in latest_version.subjects.all().values_list('_id', flat=True)]

target_class = cls._meta.model
instance = cls._build(target_class, *args, **kwargs)
instance.article_doi = latest_version.article_doi
instance.date_published = timezone.now()
user = kwargs.pop('creator', None) or instance.creator
instance.machine_state = 'initial'
instance.provider = latest_version.provider
instance.save()

models.GuidVersionsThrough.objects.create(
referent=instance,
content_type=ContentType.objects.get_for_model(instance),
object_id=instance.pk,
guid=guid_obj,
version=last_version_number + 1
)

filename = kwargs.pop('filename', None) or f'preprint_file_{last_version_number + 1}_file.txt'
file_size = kwargs.pop('file_size', 1337)
preprint_file = OsfStorageFile.create(
target_object_id=instance.id,
target_content_type=ContentType.objects.get_for_model(instance),
path=f'/{filename}',
name=filename,
materialized_path=f'/{filename}'
)
preprint_file.save()
# TODO: why setting machine state here? it should happen in `if finish`
# TODO: instance.machine_state = machine_state
from addons.osfstorage import settings as osfstorage_settings
preprint_file.create_version(user, {
'object': '06d80e',
'service': 'cloud',
osfstorage_settings.WATERBUTLER_RESOURCE: 'osf',
}, {
'size': file_size,
'contentType': 'img/png'
}).save()
update_task_patcher.stop()

if finish:
auth = Auth(user)
# TODO: make sure user is an admin contributor
instance.set_primary_file(preprint_file, auth=auth, save=True)
instance.set_subjects(subjects, auth=auth)
if license_details:
instance.set_preprint_license(license_details, auth=auth)
instance.set_published(is_published, auth=auth)
create_task_patcher = mock.patch('website.identifiers.utils.request_identifiers')
mock_create_identifier = create_task_patcher.start()
if is_published and set_doi:
mock_create_identifier.side_effect = sync_set_identifiers(instance)
guid_obj.referent = instance
guid_obj.object_id = instance.pk
guid_obj.save()
# TODO: instance.machine_state = machine_state
create_task_patcher.stop()

instance.save()
return instance

class TagFactory(DjangoModelFactory):
class Meta:
model = models.Tag
Expand Down
55 changes: 55 additions & 0 deletions tests/identifiers/test_crossref.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ def preprint():
preprint.license.node_license.url = 'https://creativecommons.org/licenses/by/4.0/legalcode'
return preprint

@pytest.fixture()
def preprint_version(preprint):
versioned_preprint = PreprintFactory.create_version(preprint=preprint)
return versioned_preprint

@pytest.fixture()
def crossref_success_response():
return b"""
Expand Down Expand Up @@ -88,6 +93,11 @@ def test_crossref_build_doi(self, crossref_client, preprint):

assert crossref_client.build_doi(preprint) == settings.DOI_FORMAT.format(prefix=doi_prefix, guid=preprint._id)

def test_crossref_build_doi_versioned(self, crossref_client, preprint_version):
doi_prefix = preprint_version.provider.doi_prefix

assert crossref_client.build_doi(preprint_version) == settings.DOI_FORMAT.format(prefix=doi_prefix, guid=preprint_version._id)

def test_crossref_build_metadata(self, crossref_client, preprint):
test_email = '[email protected]'
with mock.patch('website.settings.CROSSREF_DEPOSITOR_EMAIL', test_email):
Expand All @@ -113,11 +123,56 @@ def test_crossref_build_metadata(self, crossref_client, preprint):
assert root.find('.//{%s}intra_work_relation' % crossref.CROSSREF_RELATIONS).text == preprint.article_doi
assert root.find('.//{%s}doi' % crossref.CROSSREF_NAMESPACE).text == settings.DOI_FORMAT.format(prefix=preprint.provider.doi_prefix, guid=preprint._id)
assert root.find('.//{%s}resource' % crossref.CROSSREF_NAMESPACE).text == settings.DOMAIN + preprint._id
assert root.find('.//{%s}doi_relations' % crossref.CROSSREF_NAMESPACE) is None

metadata_date_parts = [elem.text for elem in root.find('.//{%s}posted_date' % crossref.CROSSREF_NAMESPACE)]
preprint_date_parts = preprint.date_published.strftime('%Y-%m-%d').split('-')
assert set(metadata_date_parts) == set(preprint_date_parts)

def test_crossref_build_metadata_versioned(self, crossref_client, preprint_version, preprint):
test_email = '[email protected]'
with mock.patch('website.settings.CROSSREF_DEPOSITOR_EMAIL', test_email):
crossref_xml = crossref_client.build_metadata(preprint_version)
root = lxml.etree.fromstring(crossref_xml)

# header
assert root.find('.//{%s}doi_batch_id' % crossref.CROSSREF_NAMESPACE).text == preprint_version._id
assert root.find('.//{%s}depositor_name' % crossref.CROSSREF_NAMESPACE).text == crossref.CROSSREF_DEPOSITOR_NAME
assert root.find('.//{%s}email_address' % crossref.CROSSREF_NAMESPACE).text == test_email

# body
contributors = root.find('.//{%s}contributors' % crossref.CROSSREF_NAMESPACE)
assert len(contributors.getchildren()) == len(preprint_version.visible_contributors)

assert root.find('.//{%s}group_title' % crossref.CROSSREF_NAMESPACE).text == preprint_version.provider.name
assert root.find('.//{%s}title' % crossref.CROSSREF_NAMESPACE).text == preprint_version.title
assert root.find('.//{%s}item_number' % crossref.CROSSREF_NAMESPACE).text == f'osf.io/{preprint_version._id}'
assert root.find('.//{%s}abstract/' % crossref.JATS_NAMESPACE).text == preprint_version.description
assert root.find(
'.//{%s}license_ref' % crossref.CROSSREF_ACCESS_INDICATORS).text == 'https://creativecommons.org/licenses/by/4.0/legalcode'
assert root.find('.//{%s}license_ref' % crossref.CROSSREF_ACCESS_INDICATORS).get(
'start_date') == preprint_version.date_published.strftime('%Y-%m-%d')

doi_relations = root.find('.//{%s}doi_relations' % crossref.CROSSREF_NAMESPACE)
assert doi_relations is not None

doi = doi_relations.find('.//{%s}doi' % crossref.CROSSREF_NAMESPACE)
assert doi is not None
assert doi.text == settings.DOI_FORMAT.format(prefix=preprint_version.provider.doi_prefix, guid=preprint_version._id)

related_item = doi_relations.find('.//{%s}related_item' % crossref.CROSSREF_RELATIONS)
assert related_item is not None

description = related_item.find('.//{%s}description' % crossref.CROSSREF_RELATIONS)
assert description is not None
assert description.text == "Updated version"

intra_work_relation = related_item.find('.//{%s}intra_work_relation' % crossref.CROSSREF_RELATIONS)
assert intra_work_relation is not None
assert intra_work_relation.get('relationship-type') == "isVersionOf"
assert intra_work_relation.get('identifier-type') == "doi"
assert intra_work_relation.text == settings.DOI_FORMAT.format(prefix=preprint.provider.doi_prefix, guid=preprint._id)

@responses.activate
@mock.patch('osf.models.preprint.update_or_enqueue_on_preprint_updated', mock.Mock())
def test_metadata_for_deleted_node(self, crossref_client, preprint):
Expand Down

0 comments on commit 93997e5

Please sign in to comment.