Fixing tests

This commit is contained in:
rzuasti
2026-02-19 10:49:38 -05:00
parent 54e6dba496
commit e0e05823d1
6 changed files with 155 additions and 42 deletions
-22
View File
@@ -1,22 +0,0 @@
[database]
path="./oott.db"
[networking]
interface = "wlp3s0" # Network interface to use for scans
[log]
level = "debug" # off, error, warn, info, debug, trace
[timings]
wait_between_scans="30m" # Wait time between scans. This does not include the scan time
arp_sender_timeout="1m" # If the ARP sender process takes longer than this it will be stopped (for a class C network - 254 IPs - it should take less than a minute)
arp_scan_duration="2m" # How long to wait for response packets on each scan (5m to 10m is a good timeframe for a class B or C network)
[notifications]
# method="pushover" # For now just pushover, you can set this to "none" to avoid sending notifications (it will just log)
method="none"
notify_when_not_seen_for="1w" # Send a notification if a device comes back online after not being seen for this timeframe
[notifications.pushover]
token="a7vxi8b24ncdmuyt65x7zytkxaozi3" # Your pushover token goes here, just copy&paste from their website after creating the app
user_key="u872udy8xc8ceys9ee6iur229xs3fj" # User key goes here, this is the account wide code for pushover
+1
View File
@@ -1,4 +1,5 @@
pub mod devices; pub mod devices;
pub mod error;
pub mod notifications; pub mod notifications;
use include_dir::{Dir, include_dir}; use include_dir::{Dir, include_dir};
+28
View File
@@ -0,0 +1,28 @@
use std::{error, fmt};
#[derive(Debug)]
pub enum DbError {
Parse(rusqlite::Error),
}
impl fmt::Display for DbError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
DbError::Parse(..) => write!(f, "Database access error"),
}
}
}
impl error::Error for DbError {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match *self {
DbError::Parse(ref e) => Some(e),
}
}
}
impl From<rusqlite::Error> for DbError {
fn from(err: rusqlite::Error) -> DbError {
DbError::Parse(err)
}
}
+112 -17
View File
@@ -1,32 +1,127 @@
use chrono::Local; use crate::db;
use crate::db::error::DbError;
use log::debug; use log::debug;
use crate::model::{self, notifications::Notification}; use crate::model::notifications::Notification;
pub fn list() -> Vec<model::notifications::Notification> { pub fn list() -> Result<Vec<Notification>, DbError> {
debug!("Listing notifications"); debug!("Listing notifications");
let mut result = Vec::new(); let conn = db::get_db_connection();
result.push(Notification {
id: 1,
created_on: Local::now().to_utc(),
is_new: true,
notification_type: model::notifications::NotificationType::NewDeviceFound,
title: "title".to_string(),
body: "body".to_string(),
});
result let mut stmt = conn.prepare(
"SELECT id, created_on, notification_type, title, body FROM notifications WHERE is_new=1",
)?;
let notifications: Vec<Notification> = stmt
.query_map([], |row| {
Ok(Notification {
id: row.get(0)?,
created_on: row.get(1)?,
notification_type: row.get(2)?,
title: row.get(3)?,
body: row.get(4)?,
is_new: true,
})
})?
.collect::<Result<_, _>>()?;
Ok(notifications)
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use chrono::TimeZone;
use super::*; use super::*;
use crate::tests_common; use crate::{model::notifications::NotificationType, tests_common};
#[tokio::test] #[tokio::test]
async fn list_default() { async fn test_list_default() {
tests_common::setup().await; tests_common::setup().await;
let notifications = list(); let notifications = list().unwrap();
assert_eq!(notifications.len(), 1);
// There should be 3 unread notifications
assert_eq!(
notifications.len(),
3,
"There should be 3 notifications in the list"
);
// All notifications must be unread/new
for notification in notifications.iter() {
assert!(
notification.is_new,
"Notification {} is not new and there should only be new notifications in the list",
notification.id
);
}
// There should be only one of each type
assert_eq!(
1,
notifications
.iter()
.filter(|notification| notification.notification_type == NotificationType::Other)
.count(),
"There should be only one notification of type Other"
);
assert_eq!(
1,
notifications
.iter()
.filter(|notification| notification.notification_type
== NotificationType::DeviceOnlineAfterTime)
.count(),
"There should be only one notification of type Other"
);
assert_eq!(
1,
notifications
.iter()
.filter(|notification| notification.notification_type
== NotificationType::NewDeviceFound)
.count(),
"There should be only one notification of type Other"
);
// Check date of notification 1
let notification1 = notifications
.iter()
.filter(|notification| notification.id == 1)
.next()
.unwrap();
// 2026-01-03 14:13:12
assert_eq!(
notification1.created_on,
Local.with_ymd_and_hms(2026, 1, 3, 14, 13, 12).unwrap(),
"Incorrect created_on date/time for notification 1."
);
// Check title of notification 3
let notification3 = notifications
.iter()
.filter(|notification| notification.id == 3)
.next()
.unwrap();
assert_eq!(
notification3.title, "Unread device online after time",
"Notification 3 title incorrect: {}",
notification3.title
);
// Check body of notification 5
let notification5 = notifications
.iter()
.filter(|notification| notification.id == 5)
.next()
.unwrap();
assert_eq!(
notification5.body, "Body other",
"Notification 5 body incorrect: {}",
notification5.body
);
} }
} }
+8 -2
View File
@@ -5,7 +5,7 @@ use std::{error::Error, fmt, str::FromStr};
#[derive(Clone, Serialize, Deserialize)] #[derive(Clone, Serialize, Deserialize)]
pub struct Notification { pub struct Notification {
pub id: u64, pub id: i64,
#[serde(with = "ts_seconds")] #[serde(with = "ts_seconds")]
pub created_on: DateTime<Utc>, pub created_on: DateTime<Utc>,
pub notification_type: NotificationType, pub notification_type: NotificationType,
@@ -24,7 +24,13 @@ impl fmt::Display for Notification {
} }
} }
#[derive(Clone, Serialize, Deserialize)] impl PartialEq for Notification {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
}
}
#[derive(Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum NotificationType { pub enum NotificationType {
NewDeviceFound, NewDeviceFound,
DeviceOnlineAfterTime, DeviceOnlineAfterTime,
@@ -1 +1,6 @@
INSERT INTO NOTIFICATIONS (id, created_on, notification_type, title, body, is_new) VALUES (1, '2026-01-03 14:13:12', 'NewDeviceFound', 'Title new device found', 'Body new device found', 1); INSERT INTO NOTIFICATIONS (id, created_on, notification_type, title, body, is_new) VALUES (1, '2026-01-03 14:13:12', 'NewDeviceFound', 'Unread new device found', 'Body unread new device found', 1);
INSERT INTO NOTIFICATIONS (id, created_on, notification_type, title, body, is_new) VALUES (2, '2026-01-04 08:10:13', 'NewDeviceFound', 'Read new device found', 'Body read new device found', 0);
INSERT INTO NOTIFICATIONS (id, created_on, notification_type, title, body, is_new) VALUES (3, '2026-01-05 17:20:01', 'DeviceOnlineAfterTime', 'Unread device online after time', 'Body unread device online after time', 1);
INSERT INTO NOTIFICATIONS (id, created_on, notification_type, title, body, is_new) VALUES (4, '2026-01-06 02:11:12', 'DeviceOnlineAfterTime', 'Read device online after time', 'Body read device online after time', 0);
INSERT INTO NOTIFICATIONS (id, created_on, notification_type, title, body, is_new) VALUES (5, '2026-02-01 11:11:11', 'Other', 'Unread other', 'Body other', 1);
INSERT INTO NOTIFICATIONS (id, created_on, notification_type, title, body, is_new) VALUES (6, '2026-02-03 13:13:13', 'Other', 'Read other', 'Body other', 0);