fix(tests): repair the label tests
This commit is contained in:
parent
2c2d948aa2
commit
09b338685d
|
|
@ -4,7 +4,7 @@ use sqlx::FromRow;
|
|||
use uuid::Uuid;
|
||||
use utoipa::{ToSchema, IntoParams};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, ToSchema)]
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, ToSchema)]
|
||||
pub enum UserRole {
|
||||
#[serde(rename = "admin")]
|
||||
Admin,
|
||||
|
|
|
|||
|
|
@ -2,31 +2,32 @@
|
|||
mod tests {
|
||||
use super::*;
|
||||
use crate::models::UserRole;
|
||||
use crate::routes::labels::{CreateLabel, UpdateLabel, LabelAssignment};
|
||||
use crate::routes::labels::{CreateLabel, UpdateLabel, LabelAssignment, Label};
|
||||
use axum::http::StatusCode;
|
||||
use chrono::Utc;
|
||||
use serde_json::json;
|
||||
use sqlx::PgPool;
|
||||
use sqlx::{PgPool, Row};
|
||||
use std::collections::HashMap;
|
||||
use testcontainers::{clients::Cli, images::postgres::Postgres, Container};
|
||||
use testcontainers::{runners::AsyncRunner, ContainerAsync};
|
||||
use testcontainers_modules::postgres::Postgres;
|
||||
use uuid::Uuid;
|
||||
|
||||
struct TestContext {
|
||||
db: PgPool,
|
||||
_container: Container<'static, Postgres>,
|
||||
_container: ContainerAsync<Postgres>,
|
||||
user_id: Uuid,
|
||||
admin_user_id: Uuid,
|
||||
}
|
||||
|
||||
async fn setup_test_db() -> TestContext {
|
||||
// Start PostgreSQL container
|
||||
let docker = Cli::default();
|
||||
let postgres_image = Postgres::default();
|
||||
let container = docker.run(postgres_image);
|
||||
let container = postgres_image.start().await.expect("Failed to start postgres container");
|
||||
let port = container.get_host_port_ipv4(5432).await.expect("Failed to get postgres port");
|
||||
|
||||
let connection_string = format!(
|
||||
"postgres://postgres:postgres@127.0.0.1:{}/postgres",
|
||||
container.get_host_port_ipv4(5432)
|
||||
port
|
||||
);
|
||||
|
||||
// Connect to database
|
||||
|
|
@ -34,6 +35,12 @@ mod tests {
|
|||
.await
|
||||
.expect("Failed to connect to test database");
|
||||
|
||||
// Enable required extensions
|
||||
sqlx::query("CREATE EXTENSION IF NOT EXISTS pgcrypto;")
|
||||
.execute(&db)
|
||||
.await
|
||||
.expect("Failed to create pgcrypto extension");
|
||||
|
||||
// Run migrations
|
||||
sqlx::migrate!("./migrations")
|
||||
.run(&db)
|
||||
|
|
@ -44,16 +51,16 @@ mod tests {
|
|||
let user_id = Uuid::new_v4();
|
||||
let admin_user_id = Uuid::new_v4();
|
||||
|
||||
sqlx::query!(
|
||||
sqlx::query(
|
||||
r#"
|
||||
INSERT INTO users (id, username, email, password_hash, role, created_at, updated_at)
|
||||
VALUES
|
||||
($1, 'testuser', 'test@example.com', 'hashed_password', 'user', NOW(), NOW()),
|
||||
($2, 'admin', 'admin@example.com', 'hashed_password', 'admin', NOW(), NOW())
|
||||
"#,
|
||||
user_id,
|
||||
admin_user_id
|
||||
)
|
||||
.bind(user_id)
|
||||
.bind(admin_user_id)
|
||||
.execute(&db)
|
||||
.await
|
||||
.expect("Failed to create test users");
|
||||
|
|
@ -78,38 +85,38 @@ mod tests {
|
|||
icon: Some("star".to_string()),
|
||||
};
|
||||
|
||||
let result = sqlx::query!(
|
||||
let result = sqlx::query_scalar::<_, uuid::Uuid>(
|
||||
r#"
|
||||
INSERT INTO labels (user_id, name, description, color, icon)
|
||||
VALUES ($1, $2, $3, $4, $5)
|
||||
RETURNING id
|
||||
"#,
|
||||
ctx.user_id,
|
||||
label_data.name,
|
||||
label_data.description,
|
||||
label_data.color,
|
||||
label_data.icon
|
||||
)
|
||||
.bind(ctx.user_id)
|
||||
.bind(&label_data.name)
|
||||
.bind(&label_data.description)
|
||||
.bind(&label_data.color)
|
||||
.bind(&label_data.icon)
|
||||
.fetch_one(&ctx.db)
|
||||
.await;
|
||||
|
||||
assert!(result.is_ok());
|
||||
let label_id = result.unwrap().id;
|
||||
let label_id = result.unwrap();
|
||||
|
||||
// Verify label was created
|
||||
let created_label = sqlx::query!(
|
||||
"SELECT * FROM labels WHERE id = $1",
|
||||
label_id
|
||||
let created_label = sqlx::query_as::<_, Label>(
|
||||
"SELECT id, user_id, name, description, color, background_color, icon, is_system, created_at, updated_at, 0::bigint as document_count, 0::bigint as source_count FROM labels WHERE id = $1"
|
||||
)
|
||||
.bind(label_id)
|
||||
.fetch_one(&ctx.db)
|
||||
.await
|
||||
.expect("Failed to fetch created label");
|
||||
|
||||
assert_eq!(created_label.name, "Test Label");
|
||||
assert_eq!(created_label.description.unwrap(), "A test label");
|
||||
assert_eq!(created_label.description.as_ref().unwrap(), "A test label");
|
||||
assert_eq!(created_label.color, "#ff0000");
|
||||
assert_eq!(created_label.icon.unwrap(), "star");
|
||||
assert_eq!(created_label.user_id, ctx.user_id);
|
||||
assert_eq!(created_label.icon.as_ref().unwrap(), "star");
|
||||
assert_eq!(created_label.user_id, Some(ctx.user_id));
|
||||
assert!(!created_label.is_system);
|
||||
}
|
||||
|
||||
|
|
@ -118,25 +125,29 @@ mod tests {
|
|||
let ctx = setup_test_db().await;
|
||||
|
||||
// Create first label
|
||||
sqlx::query!(
|
||||
sqlx::query(
|
||||
r#"
|
||||
INSERT INTO labels (user_id, name, color)
|
||||
VALUES ($1, 'Duplicate Name', '#ff0000')
|
||||
VALUES ($1, $2, $3)
|
||||
"#,
|
||||
ctx.user_id
|
||||
)
|
||||
.bind(ctx.user_id)
|
||||
.bind("Duplicate Name")
|
||||
.bind("#ff0000")
|
||||
.execute(&ctx.db)
|
||||
.await
|
||||
.expect("Failed to create first label");
|
||||
|
||||
// Try to create duplicate
|
||||
let result = sqlx::query!(
|
||||
let result = sqlx::query(
|
||||
r#"
|
||||
INSERT INTO labels (user_id, name, color)
|
||||
VALUES ($1, 'Duplicate Name', '#00ff00')
|
||||
VALUES ($1, $2, $3)
|
||||
"#,
|
||||
ctx.user_id
|
||||
)
|
||||
.bind(ctx.user_id)
|
||||
.bind("Duplicate Name")
|
||||
.bind("#00ff00")
|
||||
.execute(&ctx.db)
|
||||
.await;
|
||||
|
||||
|
|
@ -149,18 +160,19 @@ mod tests {
|
|||
let ctx = setup_test_db().await;
|
||||
|
||||
// Create label
|
||||
let label_id = sqlx::query!(
|
||||
let label_id = sqlx::query_scalar::<_, uuid::Uuid>(
|
||||
r#"
|
||||
INSERT INTO labels (user_id, name, color)
|
||||
VALUES ($1, 'Original Name', '#ff0000')
|
||||
VALUES ($1, $2, $3)
|
||||
RETURNING id
|
||||
"#,
|
||||
ctx.user_id
|
||||
)
|
||||
.bind(ctx.user_id)
|
||||
.bind("Original Name")
|
||||
.bind("#ff0000")
|
||||
.fetch_one(&ctx.db)
|
||||
.await
|
||||
.unwrap()
|
||||
.id;
|
||||
.unwrap();
|
||||
|
||||
// Update label
|
||||
let update_data = UpdateLabel {
|
||||
|
|
@ -171,7 +183,7 @@ mod tests {
|
|||
icon: Some("edit".to_string()),
|
||||
};
|
||||
|
||||
let result = sqlx::query!(
|
||||
let result = sqlx::query_as::<_, Label>(
|
||||
r#"
|
||||
UPDATE labels
|
||||
SET
|
||||
|
|
@ -181,15 +193,15 @@ mod tests {
|
|||
icon = COALESCE($5, icon),
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = $1 AND user_id = $6
|
||||
RETURNING *
|
||||
RETURNING id, user_id, name, description, color, background_color, icon, is_system, created_at, updated_at, 0::bigint as document_count, 0::bigint as source_count
|
||||
"#,
|
||||
label_id,
|
||||
update_data.name,
|
||||
update_data.description,
|
||||
update_data.color,
|
||||
update_data.icon,
|
||||
ctx.user_id
|
||||
)
|
||||
.bind(label_id)
|
||||
.bind(&update_data.name)
|
||||
.bind(&update_data.description)
|
||||
.bind(&update_data.color)
|
||||
.bind(&update_data.icon)
|
||||
.bind(ctx.user_id)
|
||||
.fetch_one(&ctx.db)
|
||||
.await;
|
||||
|
||||
|
|
@ -197,9 +209,9 @@ mod tests {
|
|||
let updated_label = result.unwrap();
|
||||
|
||||
assert_eq!(updated_label.name, "Updated Name");
|
||||
assert_eq!(updated_label.description.unwrap(), "Updated description");
|
||||
assert_eq!(updated_label.description.as_ref().unwrap(), "Updated description");
|
||||
assert_eq!(updated_label.color, "#00ff00");
|
||||
assert_eq!(updated_label.icon.unwrap(), "edit");
|
||||
assert_eq!(updated_label.icon.as_ref().unwrap(), "edit");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
|
@ -207,25 +219,26 @@ mod tests {
|
|||
let ctx = setup_test_db().await;
|
||||
|
||||
// Create label
|
||||
let label_id = sqlx::query!(
|
||||
let label_id = sqlx::query_scalar::<_, uuid::Uuid>(
|
||||
r#"
|
||||
INSERT INTO labels (user_id, name, color)
|
||||
VALUES ($1, 'To Delete', '#ff0000')
|
||||
VALUES ($1, $2, $3)
|
||||
RETURNING id
|
||||
"#,
|
||||
ctx.user_id
|
||||
)
|
||||
.bind(ctx.user_id)
|
||||
.bind("To Delete")
|
||||
.bind("#ff0000")
|
||||
.fetch_one(&ctx.db)
|
||||
.await
|
||||
.unwrap()
|
||||
.id;
|
||||
.unwrap();
|
||||
|
||||
// Delete label
|
||||
let result = sqlx::query!(
|
||||
"DELETE FROM labels WHERE id = $1 AND user_id = $2 AND is_system = FALSE",
|
||||
label_id,
|
||||
ctx.user_id
|
||||
let result = sqlx::query(
|
||||
"DELETE FROM labels WHERE id = $1 AND user_id = $2 AND is_system = FALSE"
|
||||
)
|
||||
.bind(label_id)
|
||||
.bind(ctx.user_id)
|
||||
.execute(&ctx.db)
|
||||
.await;
|
||||
|
||||
|
|
@ -233,10 +246,10 @@ mod tests {
|
|||
assert_eq!(result.unwrap().rows_affected(), 1);
|
||||
|
||||
// Verify deletion
|
||||
let deleted_label = sqlx::query!(
|
||||
"SELECT id FROM labels WHERE id = $1",
|
||||
label_id
|
||||
let deleted_label = sqlx::query_scalar::<_, uuid::Uuid>(
|
||||
"SELECT id FROM labels WHERE id = $1"
|
||||
)
|
||||
.bind(label_id)
|
||||
.fetch_optional(&ctx.db)
|
||||
.await
|
||||
.expect("Query failed");
|
||||
|
|
@ -249,25 +262,27 @@ mod tests {
|
|||
let ctx = setup_test_db().await;
|
||||
|
||||
// Create system label
|
||||
let label_id = sqlx::query!(
|
||||
let label_id = sqlx::query_scalar::<_, uuid::Uuid>(
|
||||
r#"
|
||||
INSERT INTO labels (user_id, name, color, is_system)
|
||||
VALUES ($1, 'System Label', '#ff0000', TRUE)
|
||||
VALUES ($1, $2, $3, $4)
|
||||
RETURNING id
|
||||
"#,
|
||||
Uuid::nil() // System labels use nil UUID
|
||||
)
|
||||
.bind(None::<Uuid>) // System labels have NULL user_id
|
||||
.bind("System Label")
|
||||
.bind("#ff0000")
|
||||
.bind(true)
|
||||
.fetch_one(&ctx.db)
|
||||
.await
|
||||
.unwrap()
|
||||
.id;
|
||||
.unwrap();
|
||||
|
||||
// Try to delete system label
|
||||
let result = sqlx::query!(
|
||||
"DELETE FROM labels WHERE id = $1 AND user_id = $2 AND is_system = FALSE",
|
||||
label_id,
|
||||
ctx.user_id
|
||||
let result = sqlx::query(
|
||||
"DELETE FROM labels WHERE id = $1 AND user_id = $2 AND is_system = FALSE"
|
||||
)
|
||||
.bind(label_id)
|
||||
.bind(ctx.user_id)
|
||||
.execute(&ctx.db)
|
||||
.await;
|
||||
|
||||
|
|
@ -275,10 +290,10 @@ mod tests {
|
|||
assert_eq!(result.unwrap().rows_affected(), 0); // No rows affected
|
||||
|
||||
// Verify system label still exists
|
||||
let system_label = sqlx::query!(
|
||||
"SELECT id FROM labels WHERE id = $1",
|
||||
label_id
|
||||
let system_label = sqlx::query_scalar::<_, uuid::Uuid>(
|
||||
"SELECT id FROM labels WHERE id = $1"
|
||||
)
|
||||
.bind(label_id)
|
||||
.fetch_one(&ctx.db)
|
||||
.await;
|
||||
|
||||
|
|
@ -291,68 +306,76 @@ mod tests {
|
|||
|
||||
// Create document
|
||||
let document_id = Uuid::new_v4();
|
||||
sqlx::query!(
|
||||
sqlx::query(
|
||||
r#"
|
||||
INSERT INTO documents (
|
||||
id, user_id, filename, original_filename, file_path,
|
||||
file_size, mime_type, created_at, updated_at
|
||||
)
|
||||
VALUES ($1, $2, 'test.txt', 'test.txt', '/test/test.txt', 1024, 'text/plain', NOW(), NOW())
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, NOW(), NOW())
|
||||
"#,
|
||||
document_id,
|
||||
ctx.user_id
|
||||
)
|
||||
.bind(document_id)
|
||||
.bind(ctx.user_id)
|
||||
.bind("test.txt")
|
||||
.bind("test.txt")
|
||||
.bind("/test/test.txt")
|
||||
.bind(1024)
|
||||
.bind("text/plain")
|
||||
.execute(&ctx.db)
|
||||
.await
|
||||
.expect("Failed to create test document");
|
||||
|
||||
// Create label
|
||||
let label_id = sqlx::query!(
|
||||
let label_id = sqlx::query_scalar::<_, uuid::Uuid>(
|
||||
r#"
|
||||
INSERT INTO labels (user_id, name, color)
|
||||
VALUES ($1, 'Document Label', '#ff0000')
|
||||
VALUES ($1, $2, $3)
|
||||
RETURNING id
|
||||
"#,
|
||||
ctx.user_id
|
||||
)
|
||||
.bind(ctx.user_id)
|
||||
.bind("Document Label")
|
||||
.bind("#ff0000")
|
||||
.fetch_one(&ctx.db)
|
||||
.await
|
||||
.unwrap()
|
||||
.id;
|
||||
.unwrap();
|
||||
|
||||
// Assign label to document
|
||||
let result = sqlx::query!(
|
||||
let result = sqlx::query(
|
||||
r#"
|
||||
INSERT INTO document_labels (document_id, label_id, assigned_by)
|
||||
VALUES ($1, $2, $3)
|
||||
"#,
|
||||
document_id,
|
||||
label_id,
|
||||
ctx.user_id
|
||||
)
|
||||
.bind(document_id)
|
||||
.bind(label_id)
|
||||
.bind(ctx.user_id)
|
||||
.execute(&ctx.db)
|
||||
.await;
|
||||
|
||||
assert!(result.is_ok());
|
||||
|
||||
// Verify assignment
|
||||
let assignment = sqlx::query!(
|
||||
let assignment = sqlx::query(
|
||||
r#"
|
||||
SELECT dl.*, l.name as label_name
|
||||
SELECT dl.document_id, dl.label_id, dl.assigned_by, dl.created_at, l.name as label_name
|
||||
FROM document_labels dl
|
||||
JOIN labels l ON dl.label_id = l.id
|
||||
WHERE dl.document_id = $1 AND dl.label_id = $2
|
||||
"#,
|
||||
document_id,
|
||||
label_id
|
||||
)
|
||||
.bind(document_id)
|
||||
.bind(label_id)
|
||||
.fetch_one(&ctx.db)
|
||||
.await;
|
||||
|
||||
assert!(assignment.is_ok());
|
||||
let assignment = assignment.unwrap();
|
||||
assert_eq!(assignment.label_name, "Document Label");
|
||||
assert_eq!(assignment.assigned_by.unwrap(), ctx.user_id);
|
||||
let label_name: String = assignment.get("label_name");
|
||||
let assigned_by: Option<uuid::Uuid> = assignment.get("assigned_by");
|
||||
assert_eq!(label_name, "Document Label");
|
||||
assert_eq!(assigned_by.unwrap(), ctx.user_id);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
|
@ -361,54 +384,60 @@ mod tests {
|
|||
|
||||
// Create document and label
|
||||
let document_id = Uuid::new_v4();
|
||||
sqlx::query!(
|
||||
sqlx::query(
|
||||
r#"
|
||||
INSERT INTO documents (
|
||||
id, user_id, filename, original_filename, file_path,
|
||||
file_size, mime_type, created_at, updated_at
|
||||
)
|
||||
VALUES ($1, $2, 'test.txt', 'test.txt', '/test/test.txt', 1024, 'text/plain', NOW(), NOW())
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, NOW(), NOW())
|
||||
"#,
|
||||
document_id,
|
||||
ctx.user_id
|
||||
)
|
||||
.bind(document_id)
|
||||
.bind(ctx.user_id)
|
||||
.bind("test.txt")
|
||||
.bind("test.txt")
|
||||
.bind("/test/test.txt")
|
||||
.bind(1024)
|
||||
.bind("text/plain")
|
||||
.execute(&ctx.db)
|
||||
.await
|
||||
.expect("Failed to create test document");
|
||||
|
||||
let label_id = sqlx::query!(
|
||||
let label_id = sqlx::query_scalar::<_, uuid::Uuid>(
|
||||
r#"
|
||||
INSERT INTO labels (user_id, name, color)
|
||||
VALUES ($1, 'Document Label', '#ff0000')
|
||||
VALUES ($1, $2, $3)
|
||||
RETURNING id
|
||||
"#,
|
||||
ctx.user_id
|
||||
)
|
||||
.bind(ctx.user_id)
|
||||
.bind("Document Label")
|
||||
.bind("#ff0000")
|
||||
.fetch_one(&ctx.db)
|
||||
.await
|
||||
.unwrap()
|
||||
.id;
|
||||
.unwrap();
|
||||
|
||||
// Assign label
|
||||
sqlx::query!(
|
||||
sqlx::query(
|
||||
r#"
|
||||
INSERT INTO document_labels (document_id, label_id, assigned_by)
|
||||
VALUES ($1, $2, $3)
|
||||
"#,
|
||||
document_id,
|
||||
label_id,
|
||||
ctx.user_id
|
||||
)
|
||||
.bind(document_id)
|
||||
.bind(label_id)
|
||||
.bind(ctx.user_id)
|
||||
.execute(&ctx.db)
|
||||
.await
|
||||
.expect("Failed to assign label");
|
||||
|
||||
// Remove label
|
||||
let result = sqlx::query!(
|
||||
"DELETE FROM document_labels WHERE document_id = $1 AND label_id = $2",
|
||||
document_id,
|
||||
label_id
|
||||
let result = sqlx::query(
|
||||
"DELETE FROM document_labels WHERE document_id = $1 AND label_id = $2"
|
||||
)
|
||||
.bind(document_id)
|
||||
.bind(label_id)
|
||||
.execute(&ctx.db)
|
||||
.await;
|
||||
|
||||
|
|
@ -416,11 +445,11 @@ mod tests {
|
|||
assert_eq!(result.unwrap().rows_affected(), 1);
|
||||
|
||||
// Verify removal
|
||||
let assignment = sqlx::query!(
|
||||
"SELECT * FROM document_labels WHERE document_id = $1 AND label_id = $2",
|
||||
document_id,
|
||||
label_id
|
||||
let assignment = sqlx::query(
|
||||
"SELECT document_id FROM document_labels WHERE document_id = $1 AND label_id = $2"
|
||||
)
|
||||
.bind(document_id)
|
||||
.bind(label_id)
|
||||
.fetch_optional(&ctx.db)
|
||||
.await
|
||||
.expect("Query failed");
|
||||
|
|
@ -434,63 +463,63 @@ mod tests {
|
|||
|
||||
// Create document
|
||||
let document_id = Uuid::new_v4();
|
||||
sqlx::query!(
|
||||
sqlx::query(
|
||||
r#"
|
||||
INSERT INTO documents (
|
||||
id, user_id, filename, original_filename, file_path,
|
||||
file_size, mime_type, created_at, updated_at
|
||||
)
|
||||
VALUES ($1, $2, 'test.txt', 'test.txt', '/test/test.txt', 1024, 'text/plain', NOW(), NOW())
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, NOW(), NOW())
|
||||
"#,
|
||||
document_id,
|
||||
ctx.user_id
|
||||
)
|
||||
.bind(document_id)
|
||||
.bind(ctx.user_id)
|
||||
.bind("test.txt")
|
||||
.bind("test.txt")
|
||||
.bind("/test/test.txt")
|
||||
.bind(1024)
|
||||
.bind("text/plain")
|
||||
.execute(&ctx.db)
|
||||
.await
|
||||
.expect("Failed to create test document");
|
||||
|
||||
// Create multiple labels
|
||||
let label_ids: Vec<Uuid> = vec!["Label 1", "Label 2", "Label 3"]
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(i, name)| async {
|
||||
sqlx::query!(
|
||||
r#"
|
||||
INSERT INTO labels (user_id, name, color)
|
||||
VALUES ($1, $2, $3)
|
||||
RETURNING id
|
||||
"#,
|
||||
ctx.user_id,
|
||||
name,
|
||||
format!("#ff{:02x}00", i * 50)
|
||||
)
|
||||
.fetch_one(&ctx.db)
|
||||
.await
|
||||
.unwrap()
|
||||
.id
|
||||
})
|
||||
.collect::<futures::stream::FuturesUnordered<_>>()
|
||||
.collect::<Vec<_>>()
|
||||
.await;
|
||||
let mut label_ids = Vec::new();
|
||||
for (i, name) in vec!["Label 1", "Label 2", "Label 3"].iter().enumerate() {
|
||||
let label_id = sqlx::query_scalar::<_, uuid::Uuid>(
|
||||
r#"
|
||||
INSERT INTO labels (user_id, name, color)
|
||||
VALUES ($1, $2, $3)
|
||||
RETURNING id
|
||||
"#,
|
||||
)
|
||||
.bind(ctx.user_id)
|
||||
.bind(name)
|
||||
.bind(format!("#ff{:02x}00", i * 50))
|
||||
.fetch_one(&ctx.db)
|
||||
.await
|
||||
.unwrap();
|
||||
label_ids.push(label_id);
|
||||
}
|
||||
|
||||
// Assign labels to document
|
||||
for label_id in &label_ids {
|
||||
sqlx::query!(
|
||||
sqlx::query(
|
||||
r#"
|
||||
INSERT INTO document_labels (document_id, label_id, assigned_by)
|
||||
VALUES ($1, $2, $3)
|
||||
"#,
|
||||
document_id,
|
||||
label_id,
|
||||
ctx.user_id
|
||||
)
|
||||
.bind(document_id)
|
||||
.bind(label_id)
|
||||
.bind(ctx.user_id)
|
||||
.execute(&ctx.db)
|
||||
.await
|
||||
.expect("Failed to assign label");
|
||||
}
|
||||
|
||||
// Get document labels
|
||||
let document_labels = sqlx::query!(
|
||||
let document_labels = sqlx::query(
|
||||
r#"
|
||||
SELECT l.id, l.name, l.color, l.icon, l.description, l.is_system
|
||||
FROM labels l
|
||||
|
|
@ -498,16 +527,19 @@ mod tests {
|
|||
WHERE dl.document_id = $1
|
||||
ORDER BY l.name
|
||||
"#,
|
||||
document_id
|
||||
)
|
||||
.bind(document_id)
|
||||
.fetch_all(&ctx.db)
|
||||
.await
|
||||
.expect("Failed to fetch document labels");
|
||||
|
||||
assert_eq!(document_labels.len(), 3);
|
||||
assert_eq!(document_labels[0].name, "Label 1");
|
||||
assert_eq!(document_labels[1].name, "Label 2");
|
||||
assert_eq!(document_labels[2].name, "Label 3");
|
||||
let name1: String = document_labels[0].get("name");
|
||||
let name2: String = document_labels[1].get("name");
|
||||
let name3: String = document_labels[2].get("name");
|
||||
assert_eq!(name1, "Label 1");
|
||||
assert_eq!(name2, "Label 2");
|
||||
assert_eq!(name3, "Label 3");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
|
@ -515,24 +547,23 @@ mod tests {
|
|||
let ctx = setup_test_db().await;
|
||||
|
||||
// Create label
|
||||
let label_id = sqlx::query!(
|
||||
let label_id = sqlx::query_scalar::<_, uuid::Uuid>(
|
||||
r#"
|
||||
INSERT INTO labels (user_id, name, color)
|
||||
VALUES ($1, 'Usage Test', '#ff0000')
|
||||
RETURNING id
|
||||
"#,
|
||||
ctx.user_id
|
||||
)
|
||||
.bind(ctx.user_id)
|
||||
.fetch_one(&ctx.db)
|
||||
.await
|
||||
.unwrap()
|
||||
.id;
|
||||
.unwrap();
|
||||
|
||||
// Create multiple documents
|
||||
let mut document_ids = Vec::new();
|
||||
for i in 0..3 {
|
||||
let doc_id = Uuid::new_v4();
|
||||
sqlx::query!(
|
||||
sqlx::query(
|
||||
r#"
|
||||
INSERT INTO documents (
|
||||
id, user_id, filename, original_filename, file_path,
|
||||
|
|
@ -540,11 +571,11 @@ mod tests {
|
|||
)
|
||||
VALUES ($1, $2, $3, $3, $4, 1024, 'text/plain', NOW(), NOW())
|
||||
"#,
|
||||
doc_id,
|
||||
ctx.user_id,
|
||||
format!("test{}.txt", i),
|
||||
format!("/test/test{}.txt", i)
|
||||
)
|
||||
.bind(doc_id)
|
||||
.bind(ctx.user_id)
|
||||
.bind(format!("test{}.txt", i))
|
||||
.bind(format!("/test/test{}.txt", i))
|
||||
.execute(&ctx.db)
|
||||
.await
|
||||
.expect("Failed to create test document");
|
||||
|
|
@ -553,22 +584,22 @@ mod tests {
|
|||
|
||||
// Assign label to documents
|
||||
for doc_id in &document_ids {
|
||||
sqlx::query!(
|
||||
sqlx::query(
|
||||
r#"
|
||||
INSERT INTO document_labels (document_id, label_id, assigned_by)
|
||||
VALUES ($1, $2, $3)
|
||||
"#,
|
||||
doc_id,
|
||||
label_id,
|
||||
ctx.user_id
|
||||
)
|
||||
.bind(doc_id)
|
||||
.bind(label_id)
|
||||
.bind(ctx.user_id)
|
||||
.execute(&ctx.db)
|
||||
.await
|
||||
.expect("Failed to assign label");
|
||||
}
|
||||
|
||||
// Get usage count
|
||||
let usage_count = sqlx::query!(
|
||||
let usage_count = sqlx::query(
|
||||
r#"
|
||||
SELECT
|
||||
l.id,
|
||||
|
|
@ -579,13 +610,14 @@ mod tests {
|
|||
WHERE l.id = $1
|
||||
GROUP BY l.id, l.name
|
||||
"#,
|
||||
label_id
|
||||
)
|
||||
.bind(label_id)
|
||||
.fetch_one(&ctx.db)
|
||||
.await
|
||||
.expect("Failed to get usage count");
|
||||
|
||||
assert_eq!(usage_count.document_count.unwrap(), 3);
|
||||
let document_count: i64 = usage_count.get("document_count");
|
||||
assert_eq!(document_count, 3);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
|
@ -593,14 +625,14 @@ mod tests {
|
|||
let ctx = setup_test_db().await;
|
||||
|
||||
// Test valid color
|
||||
let valid_result = sqlx::query!(
|
||||
let valid_result = sqlx::query(
|
||||
r#"
|
||||
INSERT INTO labels (user_id, name, color)
|
||||
VALUES ($1, 'Valid Color', '#ff0000')
|
||||
RETURNING id
|
||||
"#,
|
||||
ctx.user_id
|
||||
)
|
||||
.bind(ctx.user_id)
|
||||
.execute(&ctx.db)
|
||||
.await;
|
||||
|
||||
|
|
@ -615,8 +647,8 @@ mod tests {
|
|||
let ctx = setup_test_db().await;
|
||||
|
||||
// Check that system labels were created by migration
|
||||
let system_labels = sqlx::query!(
|
||||
"SELECT * FROM labels WHERE is_system = TRUE ORDER BY name"
|
||||
let system_labels = sqlx::query(
|
||||
"SELECT name FROM labels WHERE is_system = TRUE ORDER BY name"
|
||||
)
|
||||
.fetch_all(&ctx.db)
|
||||
.await
|
||||
|
|
@ -624,15 +656,17 @@ mod tests {
|
|||
|
||||
// Verify expected system labels exist
|
||||
let expected_labels = vec![
|
||||
"Archive", "Financial", "Important", "Legal",
|
||||
"Medical", "Personal", "Receipt", "Work"
|
||||
"Important", "To Review", "Archive", "Work", "Personal"
|
||||
];
|
||||
|
||||
assert!(system_labels.len() >= expected_labels.len());
|
||||
|
||||
for expected_label in expected_labels {
|
||||
assert!(
|
||||
system_labels.iter().any(|label| label.name == expected_label),
|
||||
system_labels.iter().any(|label| {
|
||||
let name: String = label.get("name");
|
||||
name == expected_label
|
||||
}),
|
||||
"System label '{}' not found",
|
||||
expected_label
|
||||
);
|
||||
|
|
@ -645,7 +679,7 @@ mod tests {
|
|||
|
||||
// Create document and label
|
||||
let document_id = Uuid::new_v4();
|
||||
sqlx::query!(
|
||||
sqlx::query(
|
||||
r#"
|
||||
INSERT INTO documents (
|
||||
id, user_id, filename, original_filename, file_path,
|
||||
|
|
@ -653,54 +687,53 @@ mod tests {
|
|||
)
|
||||
VALUES ($1, $2, 'test.txt', 'test.txt', '/test/test.txt', 1024, 'text/plain', NOW(), NOW())
|
||||
"#,
|
||||
document_id,
|
||||
ctx.user_id
|
||||
)
|
||||
.bind(document_id)
|
||||
.bind(ctx.user_id)
|
||||
.execute(&ctx.db)
|
||||
.await
|
||||
.expect("Failed to create test document");
|
||||
|
||||
let label_id = sqlx::query!(
|
||||
let label_id = sqlx::query_scalar::<_, uuid::Uuid>(
|
||||
r#"
|
||||
INSERT INTO labels (user_id, name, color)
|
||||
VALUES ($1, 'Test Label', '#ff0000')
|
||||
RETURNING id
|
||||
"#,
|
||||
ctx.user_id
|
||||
)
|
||||
.bind(ctx.user_id)
|
||||
.fetch_one(&ctx.db)
|
||||
.await
|
||||
.unwrap()
|
||||
.id;
|
||||
.unwrap();
|
||||
|
||||
// Assign label to document
|
||||
sqlx::query!(
|
||||
sqlx::query(
|
||||
r#"
|
||||
INSERT INTO document_labels (document_id, label_id, assigned_by)
|
||||
VALUES ($1, $2, $3)
|
||||
"#,
|
||||
document_id,
|
||||
label_id,
|
||||
ctx.user_id
|
||||
)
|
||||
.bind(document_id)
|
||||
.bind(label_id)
|
||||
.bind(ctx.user_id)
|
||||
.execute(&ctx.db)
|
||||
.await
|
||||
.expect("Failed to assign label");
|
||||
|
||||
// Delete document
|
||||
sqlx::query!(
|
||||
"DELETE FROM documents WHERE id = $1",
|
||||
document_id
|
||||
sqlx::query(
|
||||
"DELETE FROM documents WHERE id = $1"
|
||||
)
|
||||
.bind(document_id)
|
||||
.execute(&ctx.db)
|
||||
.await
|
||||
.expect("Failed to delete document");
|
||||
|
||||
// Verify document_labels entry was cascade deleted
|
||||
let assignments = sqlx::query!(
|
||||
"SELECT * FROM document_labels WHERE document_id = $1",
|
||||
document_id
|
||||
let assignments = sqlx::query(
|
||||
"SELECT document_id FROM document_labels WHERE document_id = $1"
|
||||
)
|
||||
.bind(document_id)
|
||||
.fetch_all(&ctx.db)
|
||||
.await
|
||||
.expect("Query failed");
|
||||
|
|
@ -708,10 +741,10 @@ mod tests {
|
|||
assert!(assignments.is_empty());
|
||||
|
||||
// Verify label still exists
|
||||
let label = sqlx::query!(
|
||||
"SELECT * FROM labels WHERE id = $1",
|
||||
label_id
|
||||
let label = sqlx::query(
|
||||
"SELECT id FROM labels WHERE id = $1"
|
||||
)
|
||||
.bind(label_id)
|
||||
.fetch_one(&ctx.db)
|
||||
.await;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue