• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pulibrary / bibdata / 3165b919-56f4-4faa-baf4-b5a08621230c

18 Sep 2025 03:08PM UTC coverage: 90.866% (+0.2%) from 90.675%
3165b919-56f4-4faa-baf4-b5a08621230c

Pull #2927

circleci

Ryan Laddusaw
Add QA DSpace config
Pull Request #2927: Index theses from dspace 7+

1411 of 1519 new or added lines in 16 files covered. (92.89%)

41 existing lines in 7 files now uncovered.

8874 of 9766 relevant lines covered (90.87%)

338.18 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.53
/lib/bibdata_rs/src/theses/dataspace/community.rs
1
// This module is responsible for interacting with Dataspace communities.
2
// using the Dataspace JSON API.  Our Dataspace has a single community dedicated
3
// to senior theses.
4

5
use anyhow::{anyhow, Result};
6
use log::info;
7
use serde::Deserialize;
8

9
#[derive(Debug, Default, Deserialize)]
10
struct CommunitiesResponse {
11
    pub _embedded: CommunitiesEmbedded,
12
}
13

14
#[derive(Debug, Default, Deserialize)]
15
struct CommunitiesEmbedded {
16
    pub communities: Vec<Community>,
17
}
18

19
#[derive(Debug, Default, Deserialize)]
20
struct CollectionsResponse {
21
    pub _embedded: CollectionsEmbedded,
22
}
23

24
#[derive(Debug, Default, Deserialize)]
25
struct CollectionsEmbedded {
26
    pub collections: Vec<Collection>,
27
}
28

29
#[derive(Debug, Default, Deserialize)]
30
struct Community {
31
    pub id: Option<String>,
32
    pub handle: String,
33
}
34

35
#[derive(Debug, Default, Deserialize)]
36
struct Collection {
37
    pub id: Option<String>,
38
}
39

40
/// The DSpace id of the community we're fetching content for.
41
/// E.g., for handle '88435/dsp019c67wm88m', the DSpace id is 267
42
pub fn get_community_id(server: &str, community_handle: &str) -> Result<Option<String>> {
3✔
43
    let communities: CommunitiesResponse = reqwest::blocking::get(format!("{}/core/communities/", server))?
3✔
44
        .json()
3✔
45
        .map_err(|e| anyhow!("Could not parse json: {e:?}"))?;
3✔
46
    let theses_community = communities
1✔
47
        ._embedded
1✔
48
        .communities
1✔
49
        .iter()
1✔
50
        .find(|community| community.handle == community_handle)
1✔
51
        .ok_or(anyhow!(format!(
1✔
52
            "The senior theses handle {} is not available at {}",
1✔
53
            community_handle, server
UNCOV
54
        )))?;
×
55
    Ok(theses_community.id.clone())
1✔
56
}
3✔
57

58
type CommunityIdSelector = fn(&str, &str) -> Result<Option<String>>;
59
pub fn get_collection_list(
2✔
60
    server: &str,
2✔
61
    community_handle: &str,
2✔
62
    id_selector: CommunityIdSelector, // A closure that returns the ID of the dspace community that contains the collections we need
2✔
63
) -> Result<Vec<String>> {
2✔
64
    let url = format!(
2✔
65
        "{}/core/communities/{}/collections?size=100",
1✔
66
        server,
67
        id_selector(server, community_handle)?.unwrap_or_default()
2✔
68
    );
69
    info!("Querying {} for the collections", url);
1✔
70
    let collections: CollectionsResponse = reqwest::blocking::get(url)?
1✔
71
        .json()
1✔
72
        .map_err(|e| anyhow!("Could not parse json: {e:?}"))?;
1✔
73
    Ok(collections
1✔
74
        ._embedded
1✔
75
        .collections
1✔
76
        .iter()
1✔
77
        .filter_map(|collection| collection.id.clone())
20✔
78
        .collect())
1✔
79
}
2✔
80

81
#[cfg(test)]
82
mod tests {
83
    use super::*;
84

85
    #[test]
86
    fn it_gets_the_id_for_the_theses_community_from_the_api() {
1✔
87
        let mut server = mockito::Server::new();
1✔
88
        let mock = server
1✔
89
            .mock("GET", "/core/communities/")
1✔
90
            .with_status(200)
1✔
91
            .with_body_from_file("../../spec/fixtures/files/theses/communities.json")
1✔
92
            .create();
1✔
93

94
        let id = get_community_id(&server.url(), "88435/dsp019c67wm88m")
1✔
95
            .unwrap()
1✔
96
            .unwrap();
1✔
97
        assert_eq!(id, "c5839e02-b833-4db1-a92f-92a1ffd286b9");
1✔
98

99
        mock.assert();
1✔
100
    }
1✔
101

102
    #[test]
103
    fn it_returns_error_if_the_api_does_not_return_the_id_for_the_theses_community() {
1✔
104
        let mut server = mockito::Server::new();
1✔
105
        let mock = server
1✔
106
            .mock("GET", "/core/communities/")
1✔
107
            .with_status(200)
1✔
108
            .with_body(r#"[{"id":1,"handle":"bad-bad-bad"}]"#)
1✔
109
            .create();
1✔
110
        assert!(get_community_id(&server.url(), "88435/dsp019c67wm88m").is_err());
1✔
111
        mock.assert();
1✔
112
    }
1✔
113

114
    #[test]
115
    fn it_fetches_the_list_of_collections_in_the_community() {
1✔
116
        let mut server = mockito::Server::new();
1✔
117
        let mock = server
1✔
118
            .mock("GET", "/core/communities/c5839e02-b833-4db1-a92f-92a1ffd286b9/collections?size=100")
1✔
119
            .with_status(200)
1✔
120
            .with_body_from_file("../../spec/fixtures/files/theses/api_collections.json")
1✔
121
            .create();
1✔
122

123
        let id_selector: CommunityIdSelector = |_server: &str, _handle: &str| Ok(Some("c5839e02-b833-4db1-a92f-92a1ffd286b9".to_string()));
1✔
124
        let ids = get_collection_list(&server.url(), "88435/dsp019c67wm88m", id_selector).unwrap();
1✔
125
        assert!(ids.contains(&"894dd444-031f-4adf-8ea6-4e9cb6ef7334".to_string()));
1✔
126

127
        mock.assert();
1✔
128
    }
1✔
129
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc