mirror of
https://github.com/rzuasti/oott.git
synced 2026-07-08 19:21:54 +02:00
Add a "Send test notification" button to verify push delivery
Adds POST /api/notifications/test, which delivers a canned test push to every registered device through the existing relay path (not persisted to the notifications list), wired into the router and OpenAPI. In Settings, a "Send test notification" button appears under the push toggle, only when push is enabled on this device, so the full backend -> relay -> FCM -> APNs -> device path can be verified on demand without waiting for a real device event. Backend, API and widget tests added; clippy and dart analyze clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
c7c5b45ae8
commit
817ec5872c
@@ -15,6 +15,25 @@ use crate::model::devices::Device;
|
||||
use crate::model::notifications::{Notification, NotificationType};
|
||||
|
||||
pub use delivery::run_delivery;
|
||||
pub use error::DeliveryError;
|
||||
|
||||
/// Send a one-off test push to every registered device through the push relay. Used by the app's
|
||||
/// "Send test notification" button to verify end-to-end push delivery. Unlike scan-driven
|
||||
/// notifications it is not persisted to the notifications list, and it is a no-op (still `Ok`) when
|
||||
/// no devices are registered.
|
||||
pub async fn send_test_push() -> Result<(), DeliveryError> {
|
||||
let config = crate::settings::get_settings()
|
||||
.notifications
|
||||
.push
|
||||
.clone()
|
||||
.unwrap_or_default();
|
||||
push::send(
|
||||
&config,
|
||||
"OOTT test".to_string(),
|
||||
"Test notification — push is working on this device.".to_string(),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
/// Send notifications for the changes detected during a scan (or a single sighting). Changes are
|
||||
/// grouped by notification type: a type with exactly one change produces the usual single-device
|
||||
|
||||
@@ -60,6 +60,7 @@ pub mod utils;
|
||||
devices::update,
|
||||
devices::unregister,
|
||||
notifications::list,
|
||||
notifications::send_test,
|
||||
notifications::read,
|
||||
notifications::read_without_flagging,
|
||||
notifications::mark_as_new,
|
||||
@@ -186,6 +187,7 @@ pub async fn serve() -> Result<(), Box<dyn Error>> {
|
||||
.route("/api/dhcp_scanner/status", get(dhcp_scanner::status))
|
||||
.route("/api/snmp_scanner/status", get(snmp_scanner::status))
|
||||
.route("/api/notifications", get(notifications::list))
|
||||
.route("/api/notifications/test", post(notifications::send_test))
|
||||
.route(
|
||||
"/api/notifications/mark_all_as_old",
|
||||
post(notifications::mark_all_as_old),
|
||||
|
||||
@@ -9,7 +9,7 @@ use axum::{
|
||||
use log::error;
|
||||
|
||||
use crate::{
|
||||
db,
|
||||
db, notifications,
|
||||
model::notifications::{Notification, NotificationListResponse},
|
||||
web_server::utils,
|
||||
};
|
||||
@@ -118,6 +118,29 @@ pub async fn mark_all_as_old() -> impl IntoResponse {
|
||||
.await
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/api/notifications/test",
|
||||
tag = "notifications",
|
||||
responses(
|
||||
(status = 200, description = "Test notification dispatched to the push relay"),
|
||||
(status = 500, description = "Internal server error"),
|
||||
),
|
||||
security(("bearer_auth" = []))
|
||||
)]
|
||||
pub async fn send_test() -> impl IntoResponse {
|
||||
match notifications::send_test_push().await {
|
||||
Ok(()) => (StatusCode::OK, "Test notification sent"),
|
||||
Err(err) => {
|
||||
error!("Error sending test push notification: {err}");
|
||||
(
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
"Error sending test notification, check your logs",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/api/notifications",
|
||||
@@ -161,3 +184,29 @@ pub async fn list(
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::tests_common;
|
||||
|
||||
#[tokio::test]
|
||||
async fn send_test_succeeds_with_no_registered_devices() {
|
||||
tests_common::setup().await;
|
||||
|
||||
// Clear any tokens left by other tests so the relay is never contacted (the no-op path),
|
||||
// keeping this hermetic; actual relay delivery + pruning is covered in the
|
||||
// notifications::push tests with a mock relay.
|
||||
let tokens: Vec<String> = db::push_tokens::list()
|
||||
.unwrap()
|
||||
.into_iter()
|
||||
.map(|token| token.token)
|
||||
.collect();
|
||||
if !tokens.is_empty() {
|
||||
db::push_tokens::delete_many(&tokens).unwrap();
|
||||
}
|
||||
|
||||
let response = send_test().await.into_response();
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user