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) => {
43                db.insert_or_merge_member(&member).await.unwrap();
44            }
45        }
46    }
47
48    // Return IDs for ease of use
49    ids
50}
51
52#[async_trait]
53pub trait FetchFixture {
54    async fn user(&self, db: &Database, d: usize) -> User;
55    async fn channel(&self, db: &Database, d: usize) -> Channel;
56    async fn server(&self, db: &Database, d: usize) -> Server;
57    async fn member(&self, db: &Database, d_server: usize, d_user: usize) -> Member;
58}
59
60#[async_trait]
61impl FetchFixture for HashMap<String, String> {
62    async fn user(&self, db: &Database, d: usize) -> User {
63        db.fetch_user(self.get(&d.to_string()).unwrap())
64            .await
65            .unwrap()
66    }
67
68    async fn channel(&self, db: &Database, d: usize) -> Channel {
69        db.fetch_channel(self.get(&d.to_string()).unwrap())
70            .await
71            .unwrap()
72    }
73
74    async fn server(&self, db: &Database, d: usize) -> Server {
75        db.fetch_server(self.get(&d.to_string()).unwrap())
76            .await
77            .unwrap()
78    }
79
80    async fn member(&self, db: &Database, d_server: usize, d_user: usize) -> Member {
81        db.fetch_member(
82            self.get(&d_server.to_string()).unwrap(),
83            self.get(&d_user.to_string()).unwrap(),
84        )
85        .await
86        .unwrap()
87    }
88}
89
90#[macro_export]
91macro_rules! fixture {
92    ( $database:expr, $name:expr, $( $variable:ident $type:ident $id: expr )+ ) => {
93        use $crate::util::test_fixtures::FetchFixture;
94
95        let fixtures = $crate::util::test_fixtures::load_fixture(
96            &$database,
97            include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/fixtures/", $name, ".json")),
98        )
99        .await;
100
101        $(
102            let $variable = fixtures.$type(&$database, $id).await;
103        )+
104    };
105}