revolt_database/util/
test_fixtures.rs

1use std::collections::HashMap;
2
3use once_cell::sync::Lazy;
4use regex::{Captures, Regex};
5use serde_json::from_str;
6
7use crate::{Channel, Database, Member, Server, User};
8
9static RE_ID: Lazy<Regex> = Lazy::new(|| Regex::new("__ID:(\\d+)__").unwrap());
10
11#[derive(Debug, Deserialize)]
12#[serde(tag = "_object_type")]
13enum LoadedFixture {
14    User(User),
15    Channel(Channel),
16    Server(Server),
17    ServerMember(Member),
18}
19
20pub async fn load_fixture(db: &Database, input: &str) -> HashMap<String, String> {
21    let mut ids = HashMap::<String, String>::new();
22    let input = RE_ID.replace_all(input, |cap: &Captures| {
23        let d = cap.get(1).unwrap().as_str();
24
25        if !ids.contains_key(d) {
26            ids.insert(d.to_string(), ulid::Ulid::new().to_string());
27        }
28
29        ids.get(d).unwrap().clone()
30    });
31
32    // Deserialise the fixtures
33    let items: Vec<LoadedFixture> = from_str(&input).expect("Failed to deserialise fixture");
34
35    // Load all of the items within
36    for item in items {
37        #[allow(clippy::disallowed_methods)]
38        match item {
39            LoadedFixture::User(user) => db.insert_user(&user).await.unwrap(),
40            LoadedFixture::Channel(channel) => db.insert_channel(&channel).await.unwrap(),
41            LoadedFixture::Server(server) => db.insert_server(&server).await.unwrap(),
42            LoadedFixture::ServerMember(member) => db.insert_member(&member).await.unwrap(),
43        }
44    }
45
46    // Return IDs for ease of use
47    ids
48}
49
50#[async_trait]
51pub trait FetchFixture {
52    async fn user(&self, db: &Database, d: usize) -> User;
53    async fn channel(&self, db: &Database, d: usize) -> Channel;
54    async fn server(&self, db: &Database, d: usize) -> Server;
55    async fn member(&self, db: &Database, d_server: usize, d_user: usize) -> Member;
56}
57
58#[async_trait]
59impl FetchFixture for HashMap<String, String> {
60    async fn user(&self, db: &Database, d: usize) -> User {
61        db.fetch_user(self.get(&d.to_string()).unwrap())
62            .await
63            .unwrap()
64    }
65
66    async fn channel(&self, db: &Database, d: usize) -> Channel {
67        db.fetch_channel(self.get(&d.to_string()).unwrap())
68            .await
69            .unwrap()
70    }
71
72    async fn server(&self, db: &Database, d: usize) -> Server {
73        db.fetch_server(self.get(&d.to_string()).unwrap())
74            .await
75            .unwrap()
76    }
77
78    async fn member(&self, db: &Database, d_server: usize, d_user: usize) -> Member {
79        db.fetch_member(
80            self.get(&d_server.to_string()).unwrap(),
81            self.get(&d_user.to_string()).unwrap(),
82        )
83        .await
84        .unwrap()
85    }
86}
87
88#[macro_export]
89macro_rules! fixture {
90    ( $database:expr, $name:expr, $( $variable:ident $type:ident $id: expr )+ ) => {
91        use $crate::util::test_fixtures::FetchFixture;
92
93        let fixtures = $crate::util::test_fixtures::load_fixture(
94            &$database,
95            include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/fixtures/", $name, ".json")),
96        )
97        .await;
98
99        $(
100            let $variable = fixtures.$type(&$database, $id).await;
101        )+
102    };
103}