Coverage for tests / test_export_zenodo_csv.py: 100%

44 statements  

« prev     ^ index     » next       coverage.py v7.12.0, created at 2026-07-17 16:43 +0000

1# SPDX-FileCopyrightText: 2025-2026 Arcangelo Massari <arcangelo.massari@unibo.it> 

2# 

3# SPDX-License-Identifier: ISC 

4 

5import json 

6from unittest.mock import call, patch 

7 

8import pytest 

9import requests 

10 

11from changes_metadata_manager.export_zenodo_csv import export_zenodo_csv 

12 

13 

14def _draft(record_id: str) -> dict: 

15 return { 

16 "draft_id": record_id, 

17 "config_file": "/missing/stale-config.yaml", 

18 "title": "Stale local title", 

19 "zenodo_url": "https://zenodo.org/api", 

20 "access_token": "token", 

21 "user_agent": "agent", 

22 "status": "published", 

23 "doi": "stale-doi", 

24 "record_url": "stale-url", 

25 } 

26 

27 

28def _record(record_id: str, title: str, creators: list[dict]) -> dict: 

29 return { 

30 "metadata": { 

31 "title": title, 

32 "publication_date": "2026-07-17", 

33 "publisher": "Zenodo", 

34 "resource_type": {"id": "dataset", "title": {"en": "Dataset"}}, 

35 "creators": creators, 

36 "rights": [ 

37 { 

38 "title": { 

39 "en": "Creative Commons Zero v1.0 Universal (Metadata license)" 

40 }, 

41 "link": ("https://creativecommons.org/publicdomain/zero/1.0/"), 

42 }, 

43 { 

44 "title": { 

45 "en": "Creative Commons Attribution 4.0 International " 

46 "(Content license)" 

47 }, 

48 "link": "https://creativecommons.org/licenses/by/4.0/", 

49 }, 

50 ], 

51 }, 

52 "pids": {"doi": {"identifier": f"10.5281/zenodo.{record_id}"}}, 

53 "links": {"self_html": f"https://zenodo.org/records/{record_id}"}, 

54 } 

55 

56 

57GIRELLI = { 

58 "person_or_org": { 

59 "type": "personal", 

60 "family_name": "Girelli", 

61 "given_name": "Valentina Alena", 

62 "identifiers": [{"scheme": "orcid", "identifier": "0000-0001-9257-9803"}], 

63 } 

64} 

65 

66MANGANELLI = { 

67 "person_or_org": { 

68 "type": "personal", 

69 "family_name": "Manganelli Del Fà", 

70 "given_name": "Rachele", 

71 "identifiers": [{"scheme": "orcid", "identifier": "0009-0007-4401-9323"}], 

72 } 

73} 

74 

75 

76@patch("changes_metadata_manager.export_zenodo_csv.time.sleep") 

77@patch("changes_metadata_manager.export_zenodo_csv.fetch_latest_published_record") 

78def test_exports_latest_remote_versions_in_drafts_order( 

79 mock_fetch, mock_sleep, tmp_path 

80): 

81 drafts_path = tmp_path / "drafts.json" 

82 drafts = [ 

83 _draft("101"), 

84 { 

85 **_draft(""), 

86 "status": "failed", 

87 "zenodo_url": "", 

88 "access_token": "", 

89 "user_agent": "", 

90 }, 

91 _draft("102"), 

92 ] 

93 drafts_path.write_text(json.dumps(drafts)) 

94 mock_fetch.side_effect = [ 

95 _record("201", "Corrected remote title A", [GIRELLI, MANGANELLI]), 

96 _record("202", "Corrected remote title B", [MANGANELLI]), 

97 ] 

98 

99 csv_path = export_zenodo_csv(drafts_path) 

100 

101 assert csv_path == tmp_path / "doi_table.csv" 

102 assert csv_path.read_text() == ( 

103 "Numero su DMP,Caso di studio,Autore/i,Tipo,Titolo,Data pubblicazione," 

104 "DOI,URL,Repository,Licenza,Note\n" 

105 ',Aldrovandi,"Girelli, Valentina Alena [orcid:0000-0001-9257-9803]; ' 

106 'Manganelli Del Fà, Rachele [orcid:0009-0007-4401-9323]",Dataset,' 

107 "Corrected remote title A,2026-07-17,10.5281/zenodo.201," 

108 "https://zenodo.org/records/201,Zenodo," 

109 "cc0-1.0 (Metadata license); cc-by-4.0 (Content license),\n" 

110 ',Aldrovandi,"Manganelli Del Fà, Rachele ' 

111 '[orcid:0009-0007-4401-9323]",Dataset,Corrected remote title B,' 

112 "2026-07-17,10.5281/zenodo.202,https://zenodo.org/records/202," 

113 "Zenodo,cc0-1.0 (Metadata license); cc-by-4.0 (Content license),\n" 

114 ) 

115 assert mock_fetch.call_args_list == [ 

116 call("https://zenodo.org/api", "101", "token", "agent"), 

117 call("https://zenodo.org/api", "102", "token", "agent"), 

118 ] 

119 assert mock_sleep.call_args_list == [call(0.5), call(0.5)] 

120 

121 

122@patch("changes_metadata_manager.export_zenodo_csv.time.sleep") 

123@patch("changes_metadata_manager.export_zenodo_csv.fetch_latest_published_record") 

124def test_writes_to_requested_output(mock_fetch, mock_sleep, tmp_path): 

125 drafts_path = tmp_path / "drafts.json" 

126 drafts_path.write_text(json.dumps([_draft("101")])) 

127 mock_fetch.return_value = _record("201", "Remote title", [GIRELLI]) 

128 output_path = tmp_path / "silvio.csv" 

129 

130 result = export_zenodo_csv(drafts_path, output_path) 

131 

132 assert result == output_path 

133 assert output_path.exists() 

134 mock_sleep.assert_called_once_with(0.5) 

135 

136 

137@patch("changes_metadata_manager.export_zenodo_csv.fetch_latest_published_record") 

138def test_http_error_preserves_existing_csv(mock_fetch, tmp_path): 

139 drafts_path = tmp_path / "drafts.json" 

140 drafts_path.write_text(json.dumps([_draft("404")])) 

141 output_path = tmp_path / "doi_table.csv" 

142 output_path.write_text("previous export\n") 

143 mock_fetch.side_effect = requests.HTTPError("404 Client Error") 

144 

145 with pytest.raises(requests.HTTPError, match="404 Client Error"): 

146 export_zenodo_csv(drafts_path) 

147 

148 assert output_path.read_text() == "previous export\n"