atmosphere_core/
testing.rs

1//! Provides functions for automated database testing.
2//!
3//! This module contains asynchronous functions to test the basic CRUD (Create, Read, Update, Delete)
4//! operations on database entities. It ensures that these operations are executed correctly and that
5//! the data integrity is maintained throughout the process.
6
7use crate::Entity;
8use std::fmt::Debug;
9
10/// Tests entity creation in the database.
11///
12/// Verifies that an entity can be created and retrieved correctly. It asserts the non-existence of
13/// the entity before creation and checks for equality between the created and retrieved instances.
14pub async fn create<E>(pool: &crate::Pool, mut instance: E)
15where
16    E: Entity + Clone + Debug + Eq + Send,
17{
18    assert!(
19        E::read(pool, instance.pk()).await.is_err(),
20        "instance was found (read) before it was created"
21    );
22
23    assert!(
24        E::find(pool, instance.pk()).await.unwrap().is_none(),
25        "instance was found (find) before it was created"
26    );
27
28    instance.create(pool).await.expect("insertion did not work");
29
30    let retrieved = E::read(pool, instance.pk())
31        .await
32        .expect("instance not found after insertion");
33
34    assert_eq!(instance, retrieved);
35}
36
37/// Tests reading of an entity from the database.
38///
39/// Validates that an entity, once created, can be correctly read from the database. It ensures
40/// that the entity does not exist prior to creation and that the retrieved instance matches the
41/// created one.
42pub async fn read<E>(pool: &crate::Pool, mut instance: E)
43where
44    E: Entity + Clone + Debug + Eq + Send,
45{
46    assert!(
47        E::read(pool, instance.pk()).await.is_err(),
48        "instance was found (read) after deletion"
49    );
50
51    assert!(
52        E::find(pool, instance.pk()).await.unwrap().is_none(),
53        "instance was found (find) after deletion"
54    );
55
56    assert!(
57        E::read_all(pool).await.unwrap().is_empty(),
58        "there was an instance found in the database before creating"
59    );
60
61    instance.create(pool).await.expect("insertion did not work");
62
63    let retrieved = E::read(pool, instance.pk())
64        .await
65        .expect("instance not found after insertion");
66
67    assert_eq!(instance, retrieved);
68
69    assert_eq!(E::read_all(pool).await.unwrap(), vec![instance.clone()]);
70}
71
72/// Tests updating of an entity in the database.
73///
74/// Checks that an entity can be updated and the changes are correctly reflected. Each update is
75/// verified by reloading and comparing it with the original instance.
76pub async fn update<E>(pool: &crate::Pool, mut instance: E, updates: Vec<E>)
77where
78    E: Entity + Clone + Debug + Eq + Send,
79{
80    instance.upsert(pool).await.expect("insertion did not work");
81
82    for mut update in updates {
83        update
84            .update(pool)
85            .await
86            .expect("updating the instance did not work");
87
88        instance
89            .reload(pool)
90            .await
91            .expect("reloading the instance did not work");
92
93        assert_eq!(instance, update);
94
95        let retrieved = E::read(pool, instance.pk())
96            .await
97            .expect("instance not found after update");
98
99        assert_eq!(instance, retrieved);
100
101        let retrieved = E::find(pool, instance.pk())
102            .await
103            .unwrap()
104            .expect("instance not found (find) after update");
105
106        assert_eq!(instance, retrieved);
107    }
108}
109
110/// Tests deletion of an entity from the database.
111///
112/// Ensures that an entity can be deleted and is no longer retrievable post-deletion. It also
113/// confirms the non-existence of the entity after a delete operation.
114pub async fn delete<E>(pool: &crate::Pool, mut instance: E)
115where
116    E: Entity + Clone + Debug + Eq + Send,
117{
118    instance.create(pool).await.expect("insertion did not work");
119
120    instance.delete(pool).await.expect("deletion did not work");
121
122    instance
123        .reload(pool)
124        .await
125        .expect_err("instance could be reloaded from db after deletion");
126
127    assert!(
128        E::read(pool, instance.pk()).await.is_err(),
129        "instance was found (read) after deletion"
130    );
131
132    assert!(
133        E::find(pool, instance.pk()).await.unwrap().is_none(),
134        "instance was found (find) after deletion"
135    );
136
137    instance.create(pool).await.expect("insertion did not work");
138
139    E::delete_by(pool, instance.pk())
140        .await
141        .expect("deletion did not work");
142
143    instance
144        .reload(pool)
145        .await
146        .expect_err("instance could be reloaded from db after deletion");
147}
148
149// TODO: provide helpers to autogenerate uuids, pks, strings, emails, etc – maybe reexport another
150// crate?