Set up automated tests for the application Core #266
|
@ -1,5 +1,5 @@
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::{hash_map::Iter, HashMap},
|
||||||
fmt::{self, Display},
|
fmt::{self, Display},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ pub struct AssetId(String);
|
||||||
|
|
||||||
impl Display for AssetId {
|
impl Display for AssetId {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "AssetId({}", self.0)
|
write!(f, "AssetId({})", self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,8 +26,24 @@ impl From<&str> for AssetId {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<String> for AssetId {
|
||||||
|
fn from(s: String) -> Self {
|
||||||
|
AssetId(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct AssetIter<'a>(Iter<'a, AssetId, String>);
|
||||||
|
|
||||||
|
impl <'a> Iterator for AssetIter<'a> {
|
||||||
|
type Item = (&'a AssetId, &'a String);
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
self.0.next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait Assets {
|
pub trait Assets {
|
||||||
fn assets(&self) -> Vec<AssetId>;
|
fn assets<'a>(&'a self) -> AssetIter<'a>;
|
||||||
|
|
||||||
fn get(&self, asset_id: AssetId) -> Result<Vec<u8>, Error>;
|
fn get(&self, asset_id: AssetId) -> Result<Vec<u8>, Error>;
|
||||||
}
|
}
|
||||||
|
@ -49,8 +65,8 @@ impl FsAssets {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Assets for FsAssets {
|
impl Assets for FsAssets {
|
||||||
fn assets(&self) -> Vec<AssetId> {
|
fn assets<'a>(&'a self) -> AssetIter<'a> {
|
||||||
self.assets.keys().cloned().collect()
|
AssetIter(self.assets.iter())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get(&self, asset_id: AssetId) -> Result<Vec<u8>, Error> {
|
fn get(&self, asset_id: AssetId) -> Result<Vec<u8>, Error> {
|
||||||
|
@ -79,8 +95,8 @@ pub mod mocks {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Assets for MemoryAssets {
|
impl Assets for MemoryAssets {
|
||||||
fn assets(&self) -> Vec<AssetId> {
|
fn assets<'a>(&'a self) -> AssetIter<'a> {
|
||||||
self.assets.keys().cloned().collect()
|
AssetIter(self.assets.iter())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get(&self, asset_id: AssetId) -> Result<Vec<u8>, Error> {
|
fn get(&self, asset_id: AssetId) -> Result<Vec<u8>, Error> {
|
||||||
|
|
|
@ -20,7 +20,7 @@ struct WebsocketClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AppState {
|
pub struct AppState {
|
||||||
pub assets: Box<dyn Assets + Sync + Send + 'static>,
|
pub asset_db: Box<dyn Assets + Sync + Send + 'static>,
|
||||||
pub clients: HashMap<String, WebsocketClient>,
|
pub clients: HashMap<String, WebsocketClient>,
|
||||||
|
|
||||||
pub tabletop: Tabletop,
|
pub tabletop: Tabletop,
|
||||||
|
@ -35,7 +35,7 @@ impl Core {
|
||||||
A: Assets + Sync + Send + 'static,
|
A: Assets + Sync + Send + 'static,
|
||||||
{
|
{
|
||||||
Self(Arc::new(RwLock::new(AppState {
|
Self(Arc::new(RwLock::new(AppState {
|
||||||
assets: Box::new(assetdb),
|
asset_db: Box::new(assetdb),
|
||||||
clients: HashMap::new(),
|
clients: HashMap::new(),
|
||||||
tabletop: Tabletop {
|
tabletop: Tabletop {
|
||||||
background_color: RGB {
|
background_color: RGB {
|
||||||
|
@ -98,26 +98,19 @@ impl Core {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn available_images(&self) -> Vec<AssetId> {
|
pub fn available_images(&self) -> Vec<AssetId> {
|
||||||
self.0.read().unwrap().assets.assets()
|
self.0
|
||||||
/*
|
.read()
|
||||||
Ok(std::fs::read_dir(&self.0.read().unwrap().image_base)
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.filter_map(|entry| match entry {
|
.asset_db
|
||||||
Ok(entry_) => match mime_guess::from_path(entry_.path()).first() {
|
.assets()
|
||||||
Some(mime) if mime.type_() == mime::IMAGE => Some(
|
.filter_map(|(asset_id, value)| {
|
||||||
entry_
|
println!("[{:?}] {}", mime_guess::from_path(&value).first(), value);
|
||||||
.path()
|
match mime_guess::from_path(&value).first() {
|
||||||
.file_name()
|
Some(mime) if mime.type_() == mime::IMAGE => Some(asset_id.clone()),
|
||||||
.and_then(|filename| filename.to_str())
|
|
||||||
.and_then(|filename| Some(filename.to_owned()))
|
|
||||||
.unwrap(),
|
|
||||||
),
|
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
}
|
||||||
Err(_) => None,
|
|
||||||
})
|
})
|
||||||
.collect())
|
.collect()
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_background_image(&self, path: String) -> Result<(), AppError> {
|
pub fn set_background_image(&self, path: String) -> Result<(), AppError> {
|
||||||
|
@ -149,8 +142,8 @@ mod test {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn it_lists_available_images() {
|
async fn it_lists_available_images() {
|
||||||
let assets = MemoryAssets::new(vec![
|
let assets = MemoryAssets::new(vec![
|
||||||
(AssetId::from("asset_1"), "asset_1".to_owned()),
|
(AssetId::from("asset_1"), "asset_1.png".to_owned()),
|
||||||
(AssetId::from("asset_2"), "asset_2".to_owned()),
|
(AssetId::from("asset_2"), "asset_2.jpg".to_owned()),
|
||||||
(AssetId::from("asset_3"), "asset_3".to_owned()),
|
(AssetId::from("asset_3"), "asset_3".to_owned()),
|
||||||
(AssetId::from("asset_4"), "asset_4".to_owned()),
|
(AssetId::from("asset_4"), "asset_4".to_owned()),
|
||||||
(AssetId::from("asset_5"), "asset_5".to_owned()),
|
(AssetId::from("asset_5"), "asset_5".to_owned()),
|
||||||
|
@ -158,6 +151,6 @@ mod test {
|
||||||
let core = Core::new(assets);
|
let core = Core::new(assets);
|
||||||
|
|
||||||
let image_paths = core.available_images();
|
let image_paths = core.available_images();
|
||||||
assert_eq!(image_paths.len(), 5);
|
assert_eq!(image_paths.len(), 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
use std::{pin::Pin, time::Duration};
|
|
||||||
|
|
||||||
use futures::{SinkExt, StreamExt};
|
use futures::{SinkExt, StreamExt};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tokio_stream::wrappers::UnboundedReceiverStream;
|
|
||||||
use warp::{http::Response, reply::Reply, ws::Message};
|
use warp::{http::Response, reply::Reply, ws::Message};
|
||||||
|
|
||||||
use crate::core::Core;
|
use crate::core::Core;
|
||||||
|
@ -59,7 +56,7 @@ pub struct RegisterResponse {
|
||||||
url: String,
|
url: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn handle_register_client(core: Core, request: RegisterRequest) -> impl Reply {
|
pub async fn handle_register_client(core: Core, _request: RegisterRequest) -> impl Reply {
|
||||||
let client_id = core.register_client();
|
let client_id = core.register_client();
|
||||||
|
|
||||||
Response::builder()
|
Response::builder()
|
||||||
|
|
Loading…
Reference in New Issue