darkwing/server/services/browser_profile_services/config/
geolocation.rsuse crate::server::{
dtos::{
browser_profile_dto::{BrowserProfileFullData, Mode},
start_dto::StartRequest,
},
error::Error,
};
use serde::{Deserialize, Serialize};
use tracing::debug;
use super::{FromStartRequest, Navigator, Screen};
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub struct Geolocation {
pub(super) install: bool,
pub(super) latitude: f64,
pub(super) longitude: f64,
pub(super) accuracy: i32,
}
impl FromStartRequest<Geolocation> for Geolocation {
fn from_start_request(
bp: &BrowserProfileFullData,
_request: &StartRequest,
_navigator: &Navigator,
_screen: &Screen,
_token: &str,
) -> Result<Self, Error> {
let connection_info = _request.connection_info.clone();
let (latitude, longitude, accuracy) = match (
bp.geolocation.mode,
bp.geolocation.latitude,
bp.geolocation.longitude,
) {
(Mode::Manual, Some(lat), Some(long)) => {
(lat, long, bp.geolocation.accuracy.unwrap_or(10.0) as i32)
}
_ => {
if connection_info.geo.len() != 2 {
return Err(Error::ConfigForming(
"not received exactly two coordinates".into(),
));
}
(connection_info.geo[0], connection_info.geo[1], 10)
}
};
let res = Self {
install: true,
latitude,
longitude,
accuracy,
};
debug!("res: {:?}", res);
Ok(res)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::server::dtos::browser_profile_dto::Geolocation as GeolocationConfig;
use crate::server::dtos::start_dto::ConnectionInfo;
use crate::server::services::browser_profile_services::config::consts::LINUX_MOCK_PROFILE;
fn create_base_profile() -> BrowserProfileFullData {
BrowserProfileFullData {
geolocation: GeolocationConfig {
mode: Mode::Auto,
latitude: None,
longitude: None,
accuracy: None,
},
..LINUX_MOCK_PROFILE.clone()
}
}
fn create_base_request() -> StartRequest {
StartRequest {
connection_info: ConnectionInfo::get_mock(),
..StartRequest::get_mock()
}
}
#[test]
fn test_manual_geolocation() -> Result<(), Error> {
let mut profile = create_base_profile();
profile.geolocation.mode = Mode::Manual;
profile.geolocation.latitude = Some(51.5074);
profile.geolocation.longitude = Some(-0.1278);
profile.geolocation.accuracy = Some(15.0);
let request = create_base_request();
let navigator = Navigator::default();
let screen = Screen::default();
let token = String::new();
let result = Geolocation::from_start_request(
&profile, &request, &navigator, &screen, &token,
)?;
assert!(result.install);
assert_eq!(result.latitude, 51.5074);
assert_eq!(result.longitude, -0.1278);
assert_eq!(result.accuracy, 15);
Ok(())
}
#[test]
fn test_manual_geolocation_default_accuracy() -> Result<(), Error> {
let mut profile = create_base_profile();
profile.geolocation.mode = Mode::Manual;
profile.geolocation.latitude = Some(51.5074);
profile.geolocation.longitude = Some(-0.1278);
let request = create_base_request();
let navigator = Navigator::default();
let screen = Screen::default();
let token = String::new();
let result = Geolocation::from_start_request(
&profile, &request, &navigator, &screen, &token,
)?;
assert!(result.install);
assert_eq!(result.latitude, 51.5074);
assert_eq!(result.longitude, -0.1278);
assert_eq!(result.accuracy, 10);
Ok(())
}
#[test]
fn test_auto_geolocation() -> Result<(), Error> {
let profile = create_base_profile();
let mut request = create_base_request();
request.connection_info = ConnectionInfo {
geo: vec![40.7128, -74.0060],
..ConnectionInfo::get_mock()
};
let navigator = Navigator::default();
let screen = Screen::default();
let token = String::new();
let result = Geolocation::from_start_request(
&profile, &request, &navigator, &screen, &token,
)?;
assert!(result.install);
assert_eq!(result.latitude, 40.7128);
assert_eq!(result.longitude, -74.0060);
assert_eq!(result.accuracy, 10);
Ok(())
}
#[test]
fn test_invalid_geo_coordinates() {
let profile = create_base_profile();
let mut request = create_base_request();
request.connection_info = ConnectionInfo {
geo: vec![40.7128], ..ConnectionInfo::get_mock()
};
let navigator = Navigator::default();
let screen = Screen::default();
let token = String::new();
let result = Geolocation::from_start_request(
&profile, &request, &navigator, &screen, &token,
);
assert!(matches!(
result,
Err(Error::ConfigForming(msg)) if msg == "not received exactly two coordinates"
));
}
#[test]
fn test_no_geolocation() -> Result<(), Error> {
let profile = create_base_profile();
let request = create_base_request();
let navigator = Navigator::default();
let screen = Screen::default();
let token = String::new();
let result = Geolocation::from_start_request(
&profile, &request, &navigator, &screen, &token,
)?;
assert!(!result.install);
assert_eq!(result.latitude, 1.0);
assert_eq!(result.longitude, 1.0);
assert_eq!(result.accuracy, 1);
Ok(())
}
}