|
2 | 2 | """InvenioRDM reader tests""" |
3 | 3 |
|
4 | 4 | from os import path |
| 5 | +from unittest.mock import MagicMock, patch |
5 | 6 |
|
6 | 7 | import pytest |
7 | 8 |
|
8 | 9 | from commonmeta import Metadata |
| 10 | +from commonmeta.readers.inveniordm_reader import search_by_doi, search_by_guid |
9 | 11 |
|
10 | 12 |
|
11 | 13 | @pytest.mark.vcr |
@@ -592,3 +594,95 @@ def test_subfield_classification(): |
592 | 594 | {"subject": "SSP"}, |
593 | 595 | {"subject": "Stinkin' Publishers"}, |
594 | 596 | ] |
| 597 | + |
| 598 | + |
| 599 | +# --- Unit tests for search_by_guid / search_by_doi --- |
| 600 | + |
| 601 | + |
| 602 | +def _mock_response(status_code: int, payload: dict) -> MagicMock: |
| 603 | + """Build a minimal mock requests.Response.""" |
| 604 | + response = MagicMock() |
| 605 | + response.status_code = status_code |
| 606 | + response.json.return_value = payload |
| 607 | + if status_code >= 400: |
| 608 | + from requests.exceptions import HTTPError |
| 609 | + |
| 610 | + response.raise_for_status.side_effect = HTTPError(response=response) |
| 611 | + else: |
| 612 | + response.raise_for_status.return_value = None |
| 613 | + return response |
| 614 | + |
| 615 | + |
| 616 | +def test_search_by_guid_returns_id_when_found(): |
| 617 | + """search_by_guid returns the record id from the first hit.""" |
| 618 | + hit_id = "abc12-def34" |
| 619 | + payload = {"hits": {"total": 1, "hits": [{"id": hit_id}]}} |
| 620 | + with patch( |
| 621 | + "commonmeta.readers.inveniordm_reader.http.get", |
| 622 | + return_value=_mock_response(200, payload), |
| 623 | + ) as mock_get: |
| 624 | + result = search_by_guid( |
| 625 | + "https://ideophone.org/?p=5639", "rogue-scholar.org", "token" |
| 626 | + ) |
| 627 | + |
| 628 | + assert result == hit_id |
| 629 | + # The query must phrase-quote the GUID so partial URLs don't match |
| 630 | + called_params = mock_get.call_args.kwargs["params"] |
| 631 | + assert ( |
| 632 | + called_params["q"] |
| 633 | + == 'metadata.identifiers.identifier:"https://ideophone.org/?p=5639"' |
| 634 | + ) |
| 635 | + |
| 636 | + |
| 637 | +def test_search_by_guid_returns_none_when_not_found(): |
| 638 | + """search_by_guid returns None when no record matches the GUID.""" |
| 639 | + payload = {"hits": {"total": 0, "hits": []}} |
| 640 | + with patch( |
| 641 | + "commonmeta.readers.inveniordm_reader.http.get", |
| 642 | + return_value=_mock_response(200, payload), |
| 643 | + ): |
| 644 | + result = search_by_guid( |
| 645 | + "https://ideophone.org/?p=9999", "rogue-scholar.org", "token" |
| 646 | + ) |
| 647 | + |
| 648 | + assert result is None |
| 649 | + |
| 650 | + |
| 651 | +def test_search_by_guid_returns_none_on_rate_limit(): |
| 652 | + """search_by_guid returns None when the API responds with 429.""" |
| 653 | + with patch( |
| 654 | + "commonmeta.readers.inveniordm_reader.http.get", |
| 655 | + return_value=_mock_response(429, {}), |
| 656 | + ): |
| 657 | + result = search_by_guid( |
| 658 | + "https://ideophone.org/?p=5639", "rogue-scholar.org", "token" |
| 659 | + ) |
| 660 | + |
| 661 | + assert result is None |
| 662 | + |
| 663 | + |
| 664 | +def test_search_by_doi_returns_id_when_found(): |
| 665 | + """search_by_doi returns the record id from the first hit.""" |
| 666 | + hit_id = "xyz98-uvw76" |
| 667 | + payload = {"hits": {"total": 1, "hits": [{"id": hit_id}]}} |
| 668 | + with patch( |
| 669 | + "commonmeta.readers.inveniordm_reader.http.get", |
| 670 | + return_value=_mock_response(200, payload), |
| 671 | + ) as mock_get: |
| 672 | + result = search_by_doi("10.59350/dn2mm-m9q51", "rogue-scholar.org", "token") |
| 673 | + |
| 674 | + assert result == hit_id |
| 675 | + called_params = mock_get.call_args.kwargs["params"] |
| 676 | + assert called_params["q"] == "doi:10.59350/dn2mm-m9q51" |
| 677 | + |
| 678 | + |
| 679 | +def test_search_by_doi_returns_none_when_not_found(): |
| 680 | + """search_by_doi returns None when no record matches the DOI.""" |
| 681 | + payload = {"hits": {"total": 0, "hits": []}} |
| 682 | + with patch( |
| 683 | + "commonmeta.readers.inveniordm_reader.http.get", |
| 684 | + return_value=_mock_response(200, payload), |
| 685 | + ): |
| 686 | + result = search_by_doi("10.59350/nonexistent", "rogue-scholar.org", "token") |
| 687 | + |
| 688 | + assert result is None |
0 commit comments