Link user id to song queue (#159)

* Added initial code for endpoint to link user id with song queue #156

* Updated songQueue to have a user_id field #156

* Added function to link user_id with songQueue record #156

* Added useful constant #156

* Finished adding code #156

Need to make the endpoint available and then write a test. Might have to modify existing tests

* Made link user id endpoint available #156

* Added TODOs for later

* Changing location of test code

* Code formatting

* Added test #156

* Formatted code

* Added user_id to SongQueue and added more related code

* Code formatting

* Fixing possible nil user_id field in SongQueue when calling a function

* Fixed another issue

* Made changes to function to also return user_id

* Making use of user_id in test requests

* Code formatting

* Updated workflow

* Forgot to include port

* Docker changes for port change

* Reverting port changes

* Cleaning up Dockerfile

* Version bump
This commit was merged in pull request #159.
This commit is contained in:
KD
2025-07-22 21:36:29 -04:00
committed by GitHub
parent c9bcea5f98
commit 34e292bea9
7 changed files with 508 additions and 328 deletions
+5
View File
@@ -4,6 +4,7 @@ pub mod song;
pub mod endpoints {
pub const QUEUESONG: &str = "/api/v2/song/queue";
pub const QUEUESONGLINKUSERID: &str = "/api/v2/song/queue/link";
pub const QUEUESONGDATA: &str = "/api/v2/song/queue/{id}";
pub const QUEUESONGUPDATE: &str = "/api/v2/song/queue/{id}";
pub const NEXTQUEUESONG: &str = "/api/v2/song/queue/next";
@@ -17,3 +18,7 @@ pub mod endpoints {
pub const CREATESONG: &str = "/api/v2/song";
pub const CREATECOVERART: &str = "/api/v2/coverart";
}
pub mod response {
pub const SUCCESSFUL: &str = "SUCCESSFUL";
}
+123 -30
View File
@@ -84,6 +84,14 @@ pub mod request {
pub song_queue_id: uuid::Uuid,
}
}
pub mod link_user_id {
#[derive(Debug, serde::Deserialize, serde::Serialize)]
pub struct Request {
pub song_queue_id: uuid::Uuid,
pub user_id: uuid::Uuid,
}
}
}
pub mod response {
@@ -142,6 +150,14 @@ pub mod response {
pub data: Vec<uuid::Uuid>,
}
}
pub mod link_user_id {
#[derive(Debug, Default, serde::Deserialize, serde::Serialize)]
pub struct Response {
pub message: String,
pub data: Vec<uuid::Uuid>,
}
}
}
// TODO: Might make a distinction between year and date in a song's tag at some point
@@ -320,6 +336,7 @@ mod song_queue {
pub id: uuid::Uuid,
pub filename: String,
pub status: String,
pub user_id: uuid::Uuid,
}
pub async fn insert(
@@ -393,7 +410,7 @@ mod song_queue {
FOR UPDATE SKIP LOCKED
LIMIT 1
)
RETURNING id, filename, status;
RETURNING id, filename, status, user_id;
"#,
)
.bind(super::status::PROCESSING)
@@ -405,20 +422,29 @@ mod song_queue {
});
match result {
Ok(row) => Ok(SongQueue {
id: row
.try_get("id")
.map_err(|_e| sqlx::Error::RowNotFound)
.unwrap(),
filename: row
.try_get("filename")
.map_err(|_e| sqlx::Error::RowNotFound)
.unwrap(),
status: row
.try_get("status")
.map_err(|_e| sqlx::Error::RowNotFound)
.unwrap(),
}),
Ok(row) => {
let user_id_result = row.try_get("user_id");
let song_queue = SongQueue {
id: row
.try_get("id")
.map_err(|_e| sqlx::Error::RowNotFound)
.unwrap(),
filename: row
.try_get("filename")
.map_err(|_e| sqlx::Error::RowNotFound)
.unwrap(),
status: row
.try_get("status")
.map_err(|_e| sqlx::Error::RowNotFound)
.unwrap(),
user_id: match user_id_result {
Ok(id) => id,
Err(_) => uuid::Uuid::nil(),
},
};
Ok(song_queue)
}
Err(_err) => Err(sqlx::Error::RowNotFound),
}
}
@@ -475,13 +501,40 @@ mod song_queue {
}
}
pub async fn link_user_id(
pool: &sqlx::PgPool,
id: &uuid::Uuid,
user_id: &uuid::Uuid,
) -> Result<uuid::Uuid, sqlx::Error> {
let result = sqlx::query(
r#"
UPDATE "songQueue" SET user_id = $1 WHERE id = $2 RETURNING user_id;
"#,
)
.bind(user_id)
.bind(id)
.fetch_one(pool)
.await
.map_err(|e| {
eprintln!("Error updating record {e}");
});
match result {
Ok(row) => Ok(row
.try_get("user_id")
.map_err(|_e| sqlx::Error::RowNotFound)
.unwrap()),
Err(_) => Err(sqlx::Error::RowNotFound),
}
}
pub async fn get_song_queue(
pool: &sqlx::PgPool,
id: &uuid::Uuid,
) -> Result<SongQueue, sqlx::Error> {
let result = sqlx::query(
r#"
SELECT id, filename, status FROM "songQueue" WHERE id = $1
SELECT id, filename, status, user_id FROM "songQueue" WHERE id = $1
"#,
)
.bind(id)
@@ -492,20 +545,29 @@ mod song_queue {
});
match result {
Ok(row) => Ok(SongQueue {
id: row
.try_get("id")
.map_err(|_e| sqlx::Error::RowNotFound)
.unwrap(),
filename: row
.try_get("filename")
.map_err(|_e| sqlx::Error::RowNotFound)
.unwrap(),
status: row
.try_get("status")
.map_err(|_e| sqlx::Error::RowNotFound)
.unwrap(),
}),
Ok(row) => {
let user_id_result = row.try_get("user_id");
let song_queue = SongQueue {
id: row
.try_get("id")
.map_err(|_e| sqlx::Error::RowNotFound)
.unwrap(),
filename: row
.try_get("filename")
.map_err(|_e| sqlx::Error::RowNotFound)
.unwrap(),
status: row
.try_get("status")
.map_err(|_e| sqlx::Error::RowNotFound)
.unwrap(),
user_id: match user_id_result {
Ok(id) => id,
Err(_) => uuid::Uuid::nil(),
},
};
Ok(song_queue)
}
Err(_err) => Err(sqlx::Error::RowNotFound),
}
}
@@ -616,6 +678,37 @@ pub mod endpoint {
(StatusCode::OK, Json(response))
}
pub async fn link_user_id(
axum::Extension(pool): axum::Extension<sqlx::PgPool>,
axum::Json(payload): axum::Json<super::request::link_user_id::Request>,
) -> (
axum::http::StatusCode,
axum::Json<super::response::link_user_id::Response>,
) {
let mut response = super::response::link_user_id::Response::default();
match super::song_queue::get_song_queue(&pool, &payload.song_queue_id).await {
Ok(song_queue) => {
match super::song_queue::link_user_id(&pool, &song_queue.id, &payload.user_id).await
{
Ok(user_id) => {
response.message = String::from(crate::callers::response::SUCCESSFUL);
response.data.push(user_id);
(axum::http::StatusCode::OK, axum::Json(response))
}
Err(err) => {
response.message = err.to_string();
(axum::http::StatusCode::BAD_REQUEST, axum::Json(response))
}
}
}
Err(err) => {
response.message = err.to_string();
(axum::http::StatusCode::BAD_REQUEST, axum::Json(response))
}
}
}
pub async fn fetch_queue_song(
axum::Extension(pool): axum::Extension<sqlx::PgPool>,
) -> (
+369 -287
View File
@@ -59,6 +59,10 @@ pub mod init {
crate::callers::endpoints::QUEUESONG,
patch(crate::callers::song::endpoint::update_song_queue_status),
)
.route(
crate::callers::endpoints::QUEUESONGLINKUSERID,
patch(crate::callers::song::endpoint::link_user_id),
)
.route(
crate::callers::endpoints::QUEUESONGDATA,
get(crate::callers::song::endpoint::download_flac),
@@ -237,6 +241,7 @@ mod tests {
}
}
// TODO: Put the *_req() functions in their own module
async fn song_queue_req(
app: &axum::Router,
) -> Result<axum::response::Response, std::convert::Infallible> {
@@ -256,6 +261,26 @@ mod tests {
app.clone().oneshot(req).await
}
async fn song_queue_link_req(
app: &axum::Router,
song_queue_id: &uuid::Uuid,
user_id: &uuid::Uuid,
) -> Result<axum::response::Response, std::convert::Infallible> {
let payload = serde_json::json!({
"song_queue_id": song_queue_id,
"user_id": user_id
});
let req = axum::http::Request::builder()
.method(axum::http::Method::PATCH)
.uri(crate::callers::endpoints::QUEUESONGLINKUSERID)
.header(axum::http::header::CONTENT_TYPE, "application/json")
.body(axum::body::Body::from(payload.to_string()))
.unwrap();
app.clone().oneshot(req).await
}
async fn fetch_queue_req(
app: &axum::Router,
) -> Result<axum::response::Response, std::convert::Infallible> {
@@ -380,6 +405,7 @@ mod tests {
async fn create_song_req(
app: &axum::Router,
song_queue_id: &uuid::Uuid,
user_id: &uuid::Uuid,
) -> Result<axum::response::Response, std::convert::Infallible> {
let payload = serde_json::json!({
"title": "Power of Soul",
@@ -394,7 +420,7 @@ mod tests {
"disc_count": 1,
"duration": 330,
"audio_type": "flac",
"user_id": "d6e159c1-9648-4c85-81e5-52f502ff53e4",
"user_id": user_id,
"song_queue_id": song_queue_id
});
@@ -451,7 +477,7 @@ mod tests {
// Flow for queueing song
pub async fn queue_song_flow(
app: &axum::Router,
) -> Result<axum::response::Response, std::convert::Infallible> {
) -> Result<(axum::response::Response, uuid::Uuid), std::convert::Infallible> {
match super::song_queue_req(&app).await {
Ok(response) => {
let resp =
@@ -462,21 +488,40 @@ mod tests {
let song_queue_id = resp.data[0];
assert_eq!(false, song_queue_id.is_nil(), "Should not be empty");
match super::queue_metadata_req(&app, &resp.data[0]).await {
let user_id = uuid::Uuid::new_v4();
// match super::get_resp_data::<crate::callers::song::response::link_user_id::Response>(response).await {
match super::song_queue_link_req(&app, &song_queue_id, &user_id).await {
Ok(response) => {
let resp = super::get_resp_data::<
crate::callers::song::response::Response,
crate::callers::song::response::link_user_id::Response,
>(response)
.await;
assert_eq!(false, resp.data.is_empty(), "Should not be empty");
assert_eq!(
false,
resp.data.is_empty(),
"The response should not be empty"
);
let id = resp.data[0];
match super::queue_metadata_req(&app, &song_queue_id).await {
Ok(response) => {
let resp = super::get_resp_data::<
crate::callers::song::response::Response,
>(response)
.await;
assert_eq!(false, resp.data.is_empty(), "Should not be empty");
match super::fetch_metadata_queue_req(&app, &id).await {
Ok(response) => Ok(response),
Err(err) => Err(err),
let id = resp.data[0];
match super::fetch_metadata_queue_req(&app, &id).await {
Ok(response) => Ok((response, user_id)),
Err(err) => Err(err),
}
}
}
}
Err(err) => Err(err),
}
}
Err(err) => Err(err),
@@ -533,7 +578,7 @@ mod tests {
app: &axum::Router,
) -> Result<(axum::response::Response, uuid::Uuid), std::convert::Infallible> {
match queue_song_flow(&app).await {
Ok(song_response) => {
Ok((song_response, user_id)) => {
let resp = super::get_resp_data::<
crate::callers::metadata::response::fetch_metadata::Response,
>(song_response)
@@ -541,7 +586,7 @@ mod tests {
assert_eq!(false, resp.data.is_empty(), "Data should not be empty");
let song_queue_id = resp.data[0].song_queue_id;
match super::create_song_req(&app, &song_queue_id).await {
match super::create_song_req(&app, &song_queue_id, &user_id).await {
Ok(response) => {
let resp = super::get_resp_data::<
crate::callers::song::response::create_metadata::Response,
@@ -586,12 +631,14 @@ mod tests {
}
}
// TODO: Put this in a util module
pub async fn resp_to_bytes(
response: axum::response::Response,
) -> Result<axum::body::Bytes, axum::Error> {
axum::body::to_bytes(response.into_body(), usize::MAX).await
}
// TODO: Put this in a util module
pub async fn get_resp_data<Data>(response: axum::response::Response) -> Data
where
Data: for<'a> serde::Deserialize<'a>,
@@ -600,6 +647,7 @@ mod tests {
serde_json::from_slice(&body).unwrap()
}
// TODO: Change the name of the function to be more expressive and put into it's own module
pub mod payload_data {
pub async fn queue_metadata_payload_data(song_queue_id: &uuid::Uuid) -> serde_json::Value {
serde_json::json!(
@@ -655,69 +703,225 @@ mod tests {
let _ = db_mgr::drop_database(&tm_pool, &db_name).await;
}
mod special_area {
#[tokio::test]
async fn test_song_queue_link_user_id() {
let tm_pool = db_mgr::get_pool().await.unwrap();
let db_name = db_mgr::generate_db_name().await;
use super::*;
match db_mgr::create_database(&tm_pool, &db_name).await {
Ok(_) => {
println!("Success");
}
Err(err) => {
assert!(false, "Error: {:?}", err);
}
}
use std::io::Write;
let pool = db_mgr::connect_to_db(&db_name).await.unwrap();
db::migrations(&pool).await;
#[tokio::test]
async fn test_song_fetch_queue_item() {
let tm_pool = db_mgr::get_pool().await.unwrap();
let db_name = db_mgr::generate_db_name().await;
let app = init::app(pool).await;
match db_mgr::create_database(&tm_pool, &db_name).await {
Ok(_) => {
println!("Success");
}
Err(err) => {
assert!(false, "Error: {:?}", err);
match song_queue_req(&app).await {
Ok(response) => {
let resp =
get_resp_data::<crate::callers::song::response::Response>(response).await;
assert_eq!(false, resp.data.is_empty(), "Should not be empty");
assert_eq!(false, resp.data[0].is_nil(), "Should not be empty");
let song_queue_id = &resp.data[0];
let user_id = uuid::Uuid::new_v4();
println!("User Id: {user_id:?}");
match song_queue_link_req(&app, &song_queue_id, &user_id).await {
Ok(response) => {
let resp = get_resp_data::<
crate::callers::song::response::link_user_id::Response,
>(response)
.await;
let collected_user_id = &resp.data[0];
assert!(
!collected_user_id.is_nil(),
"Collected user id should not be nil {collected_user_id:?}"
);
assert_eq!(
user_id, *collected_user_id,
"User Id is different. First {user_id:?} Second {collected_user_id:?}"
);
}
Err(err) => {
assert!(
false,
"Error: {err:?} songQueue Id {song_queue_id:?} user id {user_id:?}"
);
}
}
}
Err(err) => {
assert!(false, "Error: {:?}", err);
}
};
let pool = db_mgr::connect_to_db(&db_name).await.unwrap();
db::migrations(&pool).await;
let _ = db_mgr::drop_database(&tm_pool, &db_name).await;
}
let app = init::app(pool).await;
#[tokio::test]
async fn test_song_fetch_queue_item() {
let tm_pool = db_mgr::get_pool().await.unwrap();
let db_name = db_mgr::generate_db_name().await;
match sequence_flow::queue_song_and_coverart_flow(&app).await {
Ok((resp_one, song_queue_id)) => {
let resp = get_resp_data::<
crate::callers::coverart::response::fetch_coverart_no_data::Response,
>(resp_one)
.await;
assert_eq!(false, resp.data.is_empty(), "Should not be empty");
match db_mgr::create_database(&tm_pool, &db_name).await {
Ok(_) => {
println!("Success");
}
Err(err) => {
assert!(false, "Error: {:?}", err);
}
}
let _resp_coverart_queue_id = resp.data[0].id;
let pool = db_mgr::connect_to_db(&db_name).await.unwrap();
db::migrations(&pool).await;
let old = crate::callers::song::status::PENDING;
let target_status = crate::callers::song::status::READY;
let app = init::app(pool).await;
match update_song_queue_status_req(&app, &song_queue_id).await {
Ok(response) => {
let resp = get_resp_data::<
crate::callers::song::response::update_status::Response,
>(response)
.await;
assert_eq!(false, resp.data.is_empty(), "Should not be empty");
let changed_status = &resp.data[0];
match sequence_flow::queue_song_and_coverart_flow(&app).await {
Ok((resp_one, song_queue_id)) => {
let resp = get_resp_data::<
crate::callers::coverart::response::fetch_coverart_no_data::Response,
>(resp_one)
.await;
assert_eq!(false, resp.data.is_empty(), "Should not be empty");
assert_eq!(
*old, changed_status.old_status,
"Old status does not match"
);
assert_eq!(
target_status, changed_status.new_status,
"New status does not match"
let _resp_coverart_queue_id = resp.data[0].id;
let old = crate::callers::song::status::PENDING;
let target_status = crate::callers::song::status::READY;
match update_song_queue_status_req(&app, &song_queue_id).await {
Ok(response) => {
let resp = get_resp_data::<
crate::callers::song::response::update_status::Response,
>(response)
.await;
assert_eq!(false, resp.data.is_empty(), "Should not be empty");
let changed_status = &resp.data[0];
assert_eq!(*old, changed_status.old_status, "Old status does not match");
assert_eq!(
target_status, changed_status.new_status,
"New status does not match"
);
match fetch_queue_req(&app).await {
Ok(response) => {
let resp = get_resp_data::<
crate::callers::song::response::fetch_queue_song::Response,
>(response)
.await;
assert_eq!(false, resp.data.is_empty(), "Should not be empty");
}
Err(err) => {
assert!(false, "Error: {:?}", err);
}
}
}
Err(err) => {
assert!(false, "Error: {:?}", err);
}
}
}
Err(err) => {
assert!(false, "Error: {:?}", err);
}
};
let _ = db_mgr::drop_database(&tm_pool, &db_name).await;
}
#[tokio::test]
async fn test_update_song_from_queue() {
let tm_pool = db_mgr::get_pool().await.unwrap();
let db_name = db_mgr::generate_db_name().await;
match db_mgr::create_database(&tm_pool, &db_name).await {
Ok(_) => {
println!("Success");
}
Err(err) => {
assert!(false, "Error: {:?}", err);
}
}
let pool = db_mgr::connect_to_db(&db_name).await.unwrap();
db::migrations(&pool).await;
let app = init::app(pool).await;
// Send request
match song_queue_req(&app).await {
Ok(response) => {
let resp =
get_resp_data::<crate::callers::song::response::Response>(response).await;
assert_eq!(false, resp.data.is_empty(), "Should not be empty");
assert_eq!(false, resp.data[0].is_nil(), "Should not be empty");
let id = &resp.data[0];
match fetch_queue_data_req(&app, &id).await {
Ok(response) => match resp_to_bytes(response).await {
Ok(bytes) => {
assert_eq!(false, bytes.is_empty(), "Queued data should not be empty");
let temp_file =
tempfile::tempdir().expect("Could not create test directory");
let test_dir = String::from(temp_file.path().to_str().unwrap());
let new_file = format!("{}/new_file.flac", test_dir);
let mut file = std::fs::File::create(&new_file).unwrap();
file.write_all(&bytes).unwrap();
let mut form = MultipartForm::default();
let _ = form.add_file("flac", new_file);
// Create request
let content_type = form.content_type();
let body = MultipartBody::from(form);
let raw_uri = String::from(crate::callers::endpoints::QUEUESONGUPDATE);
let end_index = raw_uri.len() - 5;
let uri = format!(
"{}/{}",
(&raw_uri[..end_index]).to_string(),
id.to_string()
);
match fetch_queue_req(&app).await {
match app
.clone()
.oneshot(
axum::http::Request::builder()
.method(axum::http::Method::PATCH)
.uri(uri)
.header(axum::http::header::CONTENT_TYPE, content_type)
.body(axum::body::Body::from_stream(body))
.unwrap(),
)
.await
{
Ok(response) => {
let resp = get_resp_data::<
crate::callers::song::response::fetch_queue_song::Response,
crate::callers::song::response::update_song_queue::Response,
>(response)
.await;
assert_eq!(false, resp.data.is_empty(), "Should not be empty");
let updated_song_queued_id = resp.data[0];
assert_eq!(
updated_song_queued_id, *id,
"Song queue Id should match, but they don't. {:?} {:?}",
updated_song_queued_id, id
);
}
Err(err) => {
assert!(false, "Error: {:?}", err);
@@ -727,247 +931,125 @@ mod tests {
Err(err) => {
assert!(false, "Error: {:?}", err);
}
},
Err(err) => {
assert!(false, "Error: {:?}", err);
}
}
Err(err) => {
assert!(false, "Error: {:?}", err);
}
};
}
Err(err) => {
assert!(false, "Error: {:?}", err);
}
};
let _ = db_mgr::drop_database(&tm_pool, &db_name).await;
let _ = db_mgr::drop_database(&tm_pool, &db_name).await;
}
#[tokio::test]
async fn test_song_fetch_queue_data() {
let tm_pool = db_mgr::get_pool().await.unwrap();
let db_name = db_mgr::generate_db_name().await;
match db_mgr::create_database(&tm_pool, &db_name).await {
Ok(_) => {
println!("Success");
}
Err(err) => {
assert!(false, "Error: {:?}", err);
}
}
#[tokio::test]
async fn test_update_song_from_queue() {
let tm_pool = db_mgr::get_pool().await.unwrap();
let db_name = db_mgr::generate_db_name().await;
let pool = db_mgr::connect_to_db(&db_name).await.unwrap();
db::migrations(&pool).await;
match db_mgr::create_database(&tm_pool, &db_name).await {
Ok(_) => {
println!("Success");
}
Err(err) => {
assert!(false, "Error: {:?}", err);
}
}
let app = init::app(pool).await;
let pool = db_mgr::connect_to_db(&db_name).await.unwrap();
db::migrations(&pool).await;
// Send request
match song_queue_req(&app).await {
Ok(response) => {
let resp =
get_resp_data::<crate::callers::song::response::Response>(response).await;
assert_eq!(false, resp.data.is_empty(), "Should not be empty");
assert_eq!(false, resp.data[0].is_nil(), "Should not be empty");
let id = resp.data[0];
let app = init::app(pool).await;
// Send request
match song_queue_req(&app).await {
Ok(response) => {
let resp =
get_resp_data::<crate::callers::song::response::Response>(response).await;
assert_eq!(false, resp.data.is_empty(), "Should not be empty");
assert_eq!(false, resp.data[0].is_nil(), "Should not be empty");
let id = &resp.data[0];
match fetch_queue_data_req(&app, &id).await {
Ok(response) => match resp_to_bytes(response).await {
Ok(bytes) => {
assert_eq!(
false,
bytes.is_empty(),
"Queued data should not be empty"
);
let temp_file =
tempfile::tempdir().expect("Could not create test directory");
let test_dir = String::from(temp_file.path().to_str().unwrap());
let new_file = format!("{}/new_file.flac", test_dir);
let mut file = std::fs::File::create(&new_file).unwrap();
file.write_all(&bytes).unwrap();
let mut form = MultipartForm::default();
let _ = form.add_file("flac", new_file);
// Create request
let content_type = form.content_type();
let body = MultipartBody::from(form);
let raw_uri =
String::from(crate::callers::endpoints::QUEUESONGUPDATE);
let end_index = raw_uri.len() - 5;
let uri = format!(
"{}/{}",
(&raw_uri[..end_index]).to_string(),
id.to_string()
);
match app
.clone()
.oneshot(
axum::http::Request::builder()
.method(axum::http::Method::PATCH)
.uri(uri)
.header(axum::http::header::CONTENT_TYPE, content_type)
.body(axum::body::Body::from_stream(body))
.unwrap(),
)
.await
{
Ok(response) => {
let resp = get_resp_data::<
crate::callers::song::response::update_song_queue::Response,
>(response)
.await;
assert_eq!(
false,
resp.data.is_empty(),
"Should not be empty"
);
let updated_song_queued_id = resp.data[0];
assert_eq!(
updated_song_queued_id, *id,
"Song queue Id should match, but they don't. {:?} {:?}",
updated_song_queued_id, id
);
}
Err(err) => {
assert!(false, "Error: {:?}", err);
}
}
}
Err(err) => {
assert!(false, "Error: {:?}", err);
}
},
Err(err) => {
assert!(false, "Error: {:?}", err);
}
}
}
Err(err) => {
assert!(false, "Error: {:?}", err);
}
};
let _ = db_mgr::drop_database(&tm_pool, &db_name).await;
}
#[tokio::test]
async fn test_song_fetch_queue_data() {
let tm_pool = db_mgr::get_pool().await.unwrap();
let db_name = db_mgr::generate_db_name().await;
match db_mgr::create_database(&tm_pool, &db_name).await {
Ok(_) => {
println!("Success");
}
Err(err) => {
assert!(false, "Error: {:?}", err);
}
}
let pool = db_mgr::connect_to_db(&db_name).await.unwrap();
db::migrations(&pool).await;
let app = init::app(pool).await;
// Send request
match song_queue_req(&app).await {
Ok(response) => {
let resp =
get_resp_data::<crate::callers::song::response::Response>(response).await;
assert_eq!(false, resp.data.is_empty(), "Should not be empty");
assert_eq!(false, resp.data[0].is_nil(), "Should not be empty");
let id = resp.data[0];
match fetch_queue_data_req(&app, &id).await {
Ok(response) => match resp_to_bytes(response).await {
Ok(bytes) => {
assert_eq!(
false,
bytes.is_empty(),
"Queued data should not be empty"
);
}
Err(err) => {
assert!(false, "Error: {:?}", err);
}
},
Err(err) => {
assert!(false, "Error: {:?}", err);
}
}
}
Err(err) => {
assert!(false, "Error: {:?}", err);
}
};
let _ = db_mgr::drop_database(&tm_pool, &db_name).await;
}
#[tokio::test]
async fn test_song_queue_update_status() {
let tm_pool = db_mgr::get_pool().await.unwrap();
let db_name = db_mgr::generate_db_name().await;
match db_mgr::create_database(&tm_pool, &db_name).await {
Ok(_) => {
println!("Success");
}
Err(err) => {
assert!(false, "Error: {:?}", err);
}
}
let pool = db_mgr::connect_to_db(&db_name).await.unwrap();
db::migrations(&pool).await;
let app = init::app(pool).await;
match sequence_flow::queue_song_and_coverart_flow(&app).await {
Ok((resp_one, song_queue_id)) => {
let resp = get_resp_data::<
crate::callers::coverart::response::fetch_coverart_no_data::Response,
>(resp_one)
.await;
assert_eq!(false, resp.data.is_empty(), "Should not be empty");
let _resp_coverart_queue_id = resp.data[0].id;
let old = crate::callers::song::status::PENDING;
let done = crate::callers::song::status::READY;
match update_song_queue_status_req(&app, &song_queue_id).await {
Ok(response) => {
let resp = get_resp_data::<
crate::callers::song::response::update_status::Response,
>(response)
.await;
assert_eq!(false, resp.data.is_empty(), "Should not be empty");
let changed_status = &resp.data[0];
assert_eq!(
*old, changed_status.old_status,
"Old status does not match"
);
assert_eq!(
done, changed_status.new_status,
"New status does not match"
);
match fetch_queue_data_req(&app, &id).await {
Ok(response) => match resp_to_bytes(response).await {
Ok(bytes) => {
assert_eq!(false, bytes.is_empty(), "Queued data should not be empty");
}
Err(err) => {
assert!(false, "Error: {:?}", err);
}
},
Err(err) => {
assert!(false, "Error: {:?}", err);
}
}
Err(err) => {
assert!(false, "Error: {:?}", err);
}
Err(err) => {
assert!(false, "Error: {:?}", err);
}
};
let _ = db_mgr::drop_database(&tm_pool, &db_name).await;
}
#[tokio::test]
async fn test_song_queue_update_status() {
let tm_pool = db_mgr::get_pool().await.unwrap();
let db_name = db_mgr::generate_db_name().await;
match db_mgr::create_database(&tm_pool, &db_name).await {
Ok(_) => {
println!("Success");
}
Err(err) => {
assert!(false, "Error: {:?}", err);
}
}
let pool = db_mgr::connect_to_db(&db_name).await.unwrap();
db::migrations(&pool).await;
let app = init::app(pool).await;
match sequence_flow::queue_song_and_coverart_flow(&app).await {
Ok((resp_one, song_queue_id)) => {
let resp = get_resp_data::<
crate::callers::coverart::response::fetch_coverart_no_data::Response,
>(resp_one)
.await;
assert_eq!(false, resp.data.is_empty(), "Should not be empty");
let _resp_coverart_queue_id = resp.data[0].id;
let old = crate::callers::song::status::PENDING;
let done = crate::callers::song::status::READY;
match update_song_queue_status_req(&app, &song_queue_id).await {
Ok(response) => {
let resp = get_resp_data::<
crate::callers::song::response::update_status::Response,
>(response)
.await;
assert_eq!(false, resp.data.is_empty(), "Should not be empty");
let changed_status = &resp.data[0];
assert_eq!(*old, changed_status.old_status, "Old status does not match");
assert_eq!(done, changed_status.new_status, "New status does not match");
}
Err(err) => {
assert!(false, "Error: {:?}", err);
}
}
}
let _ = db_mgr::drop_database(&tm_pool, &db_name).await;
Err(err) => {
assert!(false, "Error: {:?}", err);
}
}
let _ = db_mgr::drop_database(&tm_pool, &db_name).await;
}
#[tokio::test]
@@ -1038,7 +1120,7 @@ mod tests {
// Send request
match sequence_flow::queue_song_flow(&app).await {
Ok(response) => {
Ok((response, _user_id)) => {
let resp = get_resp_data::<
crate::callers::metadata::response::fetch_metadata::Response,
>(response)
@@ -1354,7 +1436,7 @@ mod tests {
// Send request
match sequence_flow::queue_song_flow(&app).await {
Ok(response) => {
Ok((response, user_id)) => {
let resp = get_resp_data::<
crate::callers::metadata::response::fetch_metadata::Response,
>(response)
@@ -1362,7 +1444,7 @@ mod tests {
assert_eq!(false, resp.data.is_empty(), "Data should not be empty");
let song_q_id = resp.data[0].song_queue_id;
match create_song_req(&app, &song_q_id).await {
match create_song_req(&app, &song_q_id, &user_id).await {
Ok(response) => {
let resp = get_resp_data::<
crate::callers::song::response::create_metadata::Response,
@@ -1417,7 +1499,7 @@ mod tests {
// Send request
match sequence_flow::queue_song_flow(&app).await {
Ok(response) => {
Ok((response, user_id)) => {
let resp = get_resp_data::<
crate::callers::metadata::response::fetch_metadata::Response,
>(response)
@@ -1425,7 +1507,7 @@ mod tests {
assert_eq!(false, resp.data.is_empty(), "Data should not be empty");
let song_queue_id = resp.data[0].song_queue_id;
match create_song_req(&app, &song_queue_id).await {
match create_song_req(&app, &song_queue_id, &user_id).await {
Ok(response) => {
let resp = get_resp_data::<
crate::callers::song::response::create_metadata::Response,
@@ -1512,7 +1594,7 @@ mod tests {
// Send request
match sequence_flow::queue_song_flow(&app).await {
Ok(response) => {
Ok((response, user_id)) => {
let resp = get_resp_data::<
crate::callers::metadata::response::fetch_metadata::Response,
>(response)
@@ -1520,7 +1602,7 @@ mod tests {
assert_eq!(false, resp.data.is_empty(), "Data should not be empty");
let song_q_id = resp.data[0].song_queue_id;
match create_song_req(&app, &song_q_id).await {
match create_song_req(&app, &song_q_id, &user_id).await {
Ok(response) => {
let resp = get_resp_data::<
crate::callers::song::response::create_metadata::Response,
@@ -1617,7 +1699,7 @@ mod tests {
let app = init::app(pool).await;
match sequence_flow::queue_song_flow(&app).await {
Ok(response) => {
Ok((response, user_id)) => {
let resp = get_resp_data::<
crate::callers::metadata::response::fetch_metadata::Response,
>(response)
@@ -1625,7 +1707,7 @@ mod tests {
assert_eq!(false, resp.data.is_empty(), "Data should not be empty");
let song_queue_id = resp.data[0].song_queue_id;
match create_song_req(&app, &song_queue_id).await {
match create_song_req(&app, &song_queue_id, &user_id).await {
Ok(response) => {
let resp = get_resp_data::<
crate::callers::song::response::create_metadata::Response,