659 lines
23 KiB
Rust
659 lines
23 KiB
Rust
use reqwest::{Client, Response};
|
|
use serde_json::{json, Value};
|
|
use std::collections::HashMap;
|
|
use std::time::{SystemTime, UNIX_EPOCH};
|
|
use tokio::time::{sleep, Duration};
|
|
|
|
#[derive(Debug)]
|
|
struct TestClient {
|
|
client: Client,
|
|
base_url: String,
|
|
auth_token: Option<String>,
|
|
}
|
|
|
|
impl TestClient {
|
|
fn new() -> Self {
|
|
Self {
|
|
client: Client::new(),
|
|
base_url: "http://localhost:8000".to_string(),
|
|
auth_token: None,
|
|
}
|
|
}
|
|
|
|
async fn check_server_health(&self) -> Result<(), Box<dyn std::error::Error>> {
|
|
let response = self
|
|
.client
|
|
.get(&format!("{}/api/health", self.base_url))
|
|
.send()
|
|
.await?;
|
|
|
|
if response.status().is_success() {
|
|
Ok(())
|
|
} else {
|
|
Err(format!("Server health check failed: {}", response.status()).into())
|
|
}
|
|
}
|
|
|
|
async fn register_user(&mut self, username: &str, email: &str, password: &str) -> Result<(), Box<dyn std::error::Error>> {
|
|
let response = self
|
|
.client
|
|
.post(&format!("{}/api/auth/register", self.base_url))
|
|
.json(&json!({
|
|
"username": username,
|
|
"email": email,
|
|
"password": password
|
|
}))
|
|
.send()
|
|
.await?;
|
|
|
|
if response.status().is_success() {
|
|
Ok(())
|
|
} else {
|
|
let error_text = response.text().await?;
|
|
Err(format!("Registration failed: {}", error_text).into())
|
|
}
|
|
}
|
|
|
|
async fn login(&mut self, username: &str, password: &str) -> Result<(), Box<dyn std::error::Error>> {
|
|
let response = self
|
|
.client
|
|
.post(&format!("{}/api/auth/login", self.base_url))
|
|
.json(&json!({
|
|
"username": username,
|
|
"password": password
|
|
}))
|
|
.send()
|
|
.await?;
|
|
|
|
if response.status().is_success() {
|
|
let login_response: Value = response.json().await?;
|
|
if let Some(token) = login_response["token"].as_str() {
|
|
self.auth_token = Some(token.to_string());
|
|
Ok(())
|
|
} else {
|
|
Err("No token in login response".into())
|
|
}
|
|
} else {
|
|
let error_text = response.text().await?;
|
|
Err(format!("Login failed: {}", error_text).into())
|
|
}
|
|
}
|
|
|
|
fn get_auth_headers(&self) -> HashMap<String, String> {
|
|
let mut headers = HashMap::new();
|
|
if let Some(token) = &self.auth_token {
|
|
headers.insert("Authorization".to_string(), format!("Bearer {}", token));
|
|
}
|
|
headers
|
|
}
|
|
|
|
async fn create_label(&self, name: &str, description: Option<&str>, color: &str, icon: Option<&str>) -> Result<Value, Box<dyn std::error::Error>> {
|
|
let mut payload = json!({
|
|
"name": name,
|
|
"color": color
|
|
});
|
|
|
|
if let Some(desc) = description {
|
|
payload["description"] = json!(desc);
|
|
}
|
|
|
|
if let Some(icon_name) = icon {
|
|
payload["icon"] = json!(icon_name);
|
|
}
|
|
|
|
let mut request = self
|
|
.client
|
|
.post(&format!("{}/api/labels", self.base_url))
|
|
.json(&payload);
|
|
|
|
for (key, value) in self.get_auth_headers() {
|
|
request = request.header(&key, &value);
|
|
}
|
|
|
|
let response = request.send().await?;
|
|
|
|
if response.status().is_success() {
|
|
let label: Value = response.json().await?;
|
|
Ok(label)
|
|
} else {
|
|
let error_text = response.text().await?;
|
|
Err(format!("Failed to create label: {}", error_text).into())
|
|
}
|
|
}
|
|
|
|
async fn get_labels(&self, include_counts: bool) -> Result<Vec<Value>, Box<dyn std::error::Error>> {
|
|
let url = if include_counts {
|
|
format!("{}/api/labels?include_counts=true", self.base_url)
|
|
} else {
|
|
format!("{}/api/labels", self.base_url)
|
|
};
|
|
|
|
let mut request = self.client.get(&url);
|
|
|
|
for (key, value) in self.get_auth_headers() {
|
|
request = request.header(&key, &value);
|
|
}
|
|
|
|
let response = request.send().await?;
|
|
|
|
if response.status().is_success() {
|
|
let labels: Vec<Value> = response.json().await?;
|
|
Ok(labels)
|
|
} else {
|
|
let error_text = response.text().await?;
|
|
Err(format!("Failed to get labels: {}", error_text).into())
|
|
}
|
|
}
|
|
|
|
async fn update_label(&self, label_id: &str, updates: Value) -> Result<Value, Box<dyn std::error::Error>> {
|
|
let mut request = self
|
|
.client
|
|
.put(&format!("{}/api/labels/{}", self.base_url, label_id))
|
|
.json(&updates);
|
|
|
|
for (key, value) in self.get_auth_headers() {
|
|
request = request.header(&key, &value);
|
|
}
|
|
|
|
let response = request.send().await?;
|
|
|
|
if response.status().is_success() {
|
|
let label: Value = response.json().await?;
|
|
Ok(label)
|
|
} else {
|
|
let error_text = response.text().await?;
|
|
Err(format!("Failed to update label: {}", error_text).into())
|
|
}
|
|
}
|
|
|
|
async fn delete_label(&self, label_id: &str) -> Result<(), Box<dyn std::error::Error>> {
|
|
let mut request = self
|
|
.client
|
|
.delete(&format!("{}/api/labels/{}", self.base_url, label_id));
|
|
|
|
for (key, value) in self.get_auth_headers() {
|
|
request = request.header(&key, &value);
|
|
}
|
|
|
|
let response = request.send().await?;
|
|
|
|
if response.status().is_success() || response.status().as_u16() == 204 {
|
|
Ok(())
|
|
} else {
|
|
let error_text = response.text().await?;
|
|
Err(format!("Failed to delete label: {}", error_text).into())
|
|
}
|
|
}
|
|
|
|
async fn upload_document(&self, content: &[u8], filename: &str) -> Result<Value, Box<dyn std::error::Error>> {
|
|
let form = reqwest::multipart::Form::new()
|
|
.part("file", reqwest::multipart::Part::bytes(content.to_vec())
|
|
.file_name(filename.to_string())
|
|
.mime_str("text/plain")?);
|
|
|
|
let mut request = self
|
|
.client
|
|
.post(&format!("{}/api/documents", self.base_url))
|
|
.multipart(form);
|
|
|
|
for (key, value) in self.get_auth_headers() {
|
|
request = request.header(&key, &value);
|
|
}
|
|
|
|
let response = request.send().await?;
|
|
|
|
if response.status().is_success() {
|
|
let document: Value = response.json().await?;
|
|
Ok(document)
|
|
} else {
|
|
let error_text = response.text().await?;
|
|
Err(format!("Failed to upload document: {}", error_text).into())
|
|
}
|
|
}
|
|
|
|
async fn assign_label_to_document(&self, document_id: &str, label_id: &str) -> Result<(), Box<dyn std::error::Error>> {
|
|
let mut request = self
|
|
.client
|
|
.post(&format!("{}/api/labels/documents/{}/labels/{}", self.base_url, document_id, label_id));
|
|
|
|
for (key, value) in self.get_auth_headers() {
|
|
request = request.header(&key, &value);
|
|
}
|
|
|
|
let response = request.send().await?;
|
|
|
|
if response.status().is_success() {
|
|
Ok(())
|
|
} else {
|
|
let error_text = response.text().await?;
|
|
Err(format!("Failed to assign label to document: {}", error_text).into())
|
|
}
|
|
}
|
|
|
|
async fn get_document_labels(&self, document_id: &str) -> Result<Vec<Value>, Box<dyn std::error::Error>> {
|
|
let mut request = self
|
|
.client
|
|
.get(&format!("{}/api/labels/documents/{}", self.base_url, document_id));
|
|
|
|
for (key, value) in self.get_auth_headers() {
|
|
request = request.header(&key, &value);
|
|
}
|
|
|
|
let response = request.send().await?;
|
|
|
|
if response.status().is_success() {
|
|
let labels: Vec<Value> = response.json().await?;
|
|
Ok(labels)
|
|
} else {
|
|
let error_text = response.text().await?;
|
|
Err(format!("Failed to get document labels: {}", error_text).into())
|
|
}
|
|
}
|
|
|
|
async fn update_document_labels(&self, document_id: &str, label_ids: Vec<&str>) -> Result<Vec<Value>, Box<dyn std::error::Error>> {
|
|
let payload = json!({
|
|
"label_ids": label_ids
|
|
});
|
|
|
|
let mut request = self
|
|
.client
|
|
.put(&format!("{}/api/labels/documents/{}", self.base_url, document_id))
|
|
.json(&payload);
|
|
|
|
for (key, value) in self.get_auth_headers() {
|
|
request = request.header(&key, &value);
|
|
}
|
|
|
|
let response = request.send().await?;
|
|
|
|
if response.status().is_success() {
|
|
let labels: Vec<Value> = response.json().await?;
|
|
Ok(labels)
|
|
} else {
|
|
let error_text = response.text().await?;
|
|
Err(format!("Failed to update document labels: {}", error_text).into())
|
|
}
|
|
}
|
|
|
|
async fn remove_label_from_document(&self, document_id: &str, label_id: &str) -> Result<(), Box<dyn std::error::Error>> {
|
|
let mut request = self
|
|
.client
|
|
.delete(&format!("{}/api/labels/documents/{}/labels/{}", self.base_url, document_id, label_id));
|
|
|
|
for (key, value) in self.get_auth_headers() {
|
|
request = request.header(&key, &value);
|
|
}
|
|
|
|
let response = request.send().await?;
|
|
|
|
if response.status().is_success() || response.status().as_u16() == 204 {
|
|
Ok(())
|
|
} else {
|
|
let error_text = response.text().await?;
|
|
Err(format!("Failed to remove label from document: {}", error_text).into())
|
|
}
|
|
}
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_label_crud_operations() -> Result<(), Box<dyn std::error::Error>> {
|
|
let mut client = TestClient::new();
|
|
|
|
// Check server health
|
|
client.check_server_health().await?;
|
|
|
|
// Create unique user
|
|
let timestamp = SystemTime::now().duration_since(UNIX_EPOCH)?.as_millis();
|
|
let username = format!("label_test_user_{}", timestamp);
|
|
let email = format!("label_test_{}@example.com", timestamp);
|
|
|
|
client.register_user(&username, &email, "test_password").await?;
|
|
client.login(&username, "test_password").await?;
|
|
|
|
// Test: Create label
|
|
println!("Testing label creation...");
|
|
let created_label = client.create_label(
|
|
"Test Label",
|
|
Some("A test label for integration testing"),
|
|
"#ff0000",
|
|
Some("star")
|
|
).await?;
|
|
|
|
assert_eq!(created_label["name"], "Test Label");
|
|
assert_eq!(created_label["color"], "#ff0000");
|
|
assert_eq!(created_label["icon"], "star");
|
|
assert_eq!(created_label["is_system"], false);
|
|
|
|
let label_id = created_label["id"].as_str().unwrap();
|
|
|
|
// Test: Get all labels
|
|
println!("Testing label retrieval...");
|
|
let labels = client.get_labels(false).await?;
|
|
assert!(labels.len() >= 1);
|
|
|
|
let found_label = labels.iter().find(|l| l["id"] == label_id);
|
|
assert!(found_label.is_some());
|
|
|
|
// Test: Get labels with counts
|
|
let labels_with_counts = client.get_labels(true).await?;
|
|
assert!(labels_with_counts.len() >= 1);
|
|
|
|
let found_label_with_count = labels_with_counts.iter().find(|l| l["id"] == label_id);
|
|
assert!(found_label_with_count.is_some());
|
|
assert_eq!(found_label_with_count.unwrap()["document_count"], 0);
|
|
|
|
// Test: Update label
|
|
println!("Testing label update...");
|
|
let updates = json!({
|
|
"name": "Updated Test Label",
|
|
"color": "#00ff00",
|
|
"description": "Updated description"
|
|
});
|
|
|
|
let updated_label = client.update_label(label_id, updates).await?;
|
|
assert_eq!(updated_label["name"], "Updated Test Label");
|
|
assert_eq!(updated_label["color"], "#00ff00");
|
|
assert_eq!(updated_label["description"], "Updated description");
|
|
|
|
// Test: Delete label
|
|
println!("Testing label deletion...");
|
|
client.delete_label(label_id).await?;
|
|
|
|
// Verify deletion
|
|
let labels_after_delete = client.get_labels(false).await?;
|
|
let deleted_label = labels_after_delete.iter().find(|l| l["id"] == label_id);
|
|
assert!(deleted_label.is_none());
|
|
|
|
println!("Label CRUD operations test completed successfully!");
|
|
Ok(())
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_document_label_assignment() -> Result<(), Box<dyn std::error::Error>> {
|
|
let mut client = TestClient::new();
|
|
|
|
// Check server health
|
|
client.check_server_health().await?;
|
|
|
|
// Create unique user
|
|
let timestamp = SystemTime::now().duration_since(UNIX_EPOCH)?.as_millis();
|
|
let username = format!("doc_label_test_user_{}", timestamp);
|
|
let email = format!("doc_label_test_{}@example.com", timestamp);
|
|
|
|
client.register_user(&username, &email, "test_password").await?;
|
|
client.login(&username, "test_password").await?;
|
|
|
|
// Create labels
|
|
println!("Creating test labels...");
|
|
let label1 = client.create_label("Important", Some("High priority items"), "#ff0000", Some("star")).await?;
|
|
let label2 = client.create_label("Work", Some("Work-related documents"), "#0000ff", Some("work")).await?;
|
|
let label3 = client.create_label("Personal", Some("Personal documents"), "#00ff00", Some("person")).await?;
|
|
|
|
let label1_id = label1["id"].as_str().unwrap();
|
|
let label2_id = label2["id"].as_str().unwrap();
|
|
let label3_id = label3["id"].as_str().unwrap();
|
|
|
|
// Upload a test document
|
|
println!("Uploading test document...");
|
|
let document_content = b"This is a test document for label assignment testing.";
|
|
let document = client.upload_document(document_content, "test_document.txt").await?;
|
|
let document_id = document["id"].as_str().unwrap();
|
|
|
|
// Test: Assign single label
|
|
println!("Testing single label assignment...");
|
|
client.assign_label_to_document(document_id, label1_id).await?;
|
|
|
|
let document_labels = client.get_document_labels(document_id).await?;
|
|
assert_eq!(document_labels.len(), 1);
|
|
assert_eq!(document_labels[0]["id"], label1_id);
|
|
|
|
// Test: Assign additional label
|
|
println!("Testing additional label assignment...");
|
|
client.assign_label_to_document(document_id, label2_id).await?;
|
|
|
|
let document_labels = client.get_document_labels(document_id).await?;
|
|
assert_eq!(document_labels.len(), 2);
|
|
|
|
// Test: Update document labels (replace)
|
|
println!("Testing label replacement...");
|
|
let new_labels = client.update_document_labels(document_id, vec![label2_id, label3_id]).await?;
|
|
assert_eq!(new_labels.len(), 2);
|
|
|
|
let label_ids: Vec<&str> = new_labels.iter()
|
|
.map(|l| l["id"].as_str().unwrap())
|
|
.collect();
|
|
assert!(label_ids.contains(&label2_id));
|
|
assert!(label_ids.contains(&label3_id));
|
|
assert!(!label_ids.contains(&label1_id));
|
|
|
|
// Test: Remove single label
|
|
println!("Testing single label removal...");
|
|
client.remove_label_from_document(document_id, label2_id).await?;
|
|
|
|
let document_labels = client.get_document_labels(document_id).await?;
|
|
assert_eq!(document_labels.len(), 1);
|
|
assert_eq!(document_labels[0]["id"], label3_id);
|
|
|
|
// Test: Remove all labels
|
|
println!("Testing removal of all labels...");
|
|
client.update_document_labels(document_id, vec![]).await?;
|
|
|
|
let document_labels = client.get_document_labels(document_id).await?;
|
|
assert_eq!(document_labels.len(), 0);
|
|
|
|
// Test: Verify label usage counts
|
|
println!("Testing label usage counts...");
|
|
let labels_with_counts = client.get_labels(true).await?;
|
|
|
|
for label in labels_with_counts {
|
|
let label_id = label["id"].as_str().unwrap();
|
|
if label_id == label1_id || label_id == label2_id || label_id == label3_id {
|
|
assert_eq!(label["document_count"], 0);
|
|
}
|
|
}
|
|
|
|
println!("Document label assignment test completed successfully!");
|
|
Ok(())
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_system_labels_access() -> Result<(), Box<dyn std::error::Error>> {
|
|
let mut client = TestClient::new();
|
|
|
|
// Check server health
|
|
client.check_server_health().await?;
|
|
|
|
// Create unique user
|
|
let timestamp = SystemTime::now().duration_since(UNIX_EPOCH)?.as_millis();
|
|
let username = format!("system_label_test_user_{}", timestamp);
|
|
let email = format!("system_label_test_{}@example.com", timestamp);
|
|
|
|
client.register_user(&username, &email, "test_password").await?;
|
|
client.login(&username, "test_password").await?;
|
|
|
|
// Test: Get labels (should include system labels)
|
|
println!("Testing system labels access...");
|
|
let labels = client.get_labels(false).await?;
|
|
|
|
// Should have system labels
|
|
let system_labels: Vec<&Value> = labels.iter()
|
|
.filter(|l| l["is_system"].as_bool().unwrap_or(false))
|
|
.collect();
|
|
|
|
assert!(system_labels.len() > 0, "Should have system labels");
|
|
|
|
// Check for some expected system labels
|
|
let system_label_names: Vec<&str> = system_labels.iter()
|
|
.map(|l| l["name"].as_str().unwrap())
|
|
.collect();
|
|
|
|
let expected_system_labels = vec!["Important", "Archive", "Personal", "Work"];
|
|
for expected in expected_system_labels {
|
|
assert!(
|
|
system_label_names.contains(&expected),
|
|
"Expected system label '{}' not found. Available: {:?}",
|
|
expected,
|
|
system_label_names
|
|
);
|
|
}
|
|
|
|
// Test: Upload document and assign system label
|
|
println!("Testing system label assignment...");
|
|
let document_content = b"This is a test document for system label assignment.";
|
|
let document = client.upload_document(document_content, "system_label_test.txt").await?;
|
|
let document_id = document["id"].as_str().unwrap();
|
|
|
|
// Find a system label to assign
|
|
let important_label = system_labels.iter()
|
|
.find(|l| l["name"] == "Important")
|
|
.expect("Important system label not found");
|
|
|
|
let important_label_id = important_label["id"].as_str().unwrap();
|
|
|
|
// Assign system label to document
|
|
client.assign_label_to_document(document_id, important_label_id).await?;
|
|
|
|
let document_labels = client.get_document_labels(document_id).await?;
|
|
assert_eq!(document_labels.len(), 1);
|
|
assert_eq!(document_labels[0]["id"], important_label_id);
|
|
assert_eq!(document_labels[0]["is_system"], true);
|
|
|
|
println!("System labels access test completed successfully!");
|
|
Ok(())
|
|
}
|
|
|
|
#[tokio::test]
|
|
#[ignore = "Requires server restart to pick up validation changes"]
|
|
async fn test_label_validation() -> Result<(), Box<dyn std::error::Error>> {
|
|
let mut client = TestClient::new();
|
|
|
|
// Check server health
|
|
client.check_server_health().await?;
|
|
|
|
// Create unique user
|
|
let timestamp = SystemTime::now().duration_since(UNIX_EPOCH)?.as_millis();
|
|
let username = format!("validation_test_user_{}", timestamp);
|
|
let email = format!("validation_test_{}@example.com", timestamp);
|
|
|
|
client.register_user(&username, &email, "test_password").await?;
|
|
client.login(&username, "test_password").await?;
|
|
|
|
// Test: Invalid color format should fail
|
|
println!("Testing invalid color validation...");
|
|
let response = client.client
|
|
.post(&format!("{}/api/labels", client.base_url))
|
|
.header("Authorization", format!("Bearer {}", client.auth_token.as_ref().unwrap()))
|
|
.json(&json!({
|
|
"name": "Invalid Color",
|
|
"color": "invalid_color"
|
|
}))
|
|
.send()
|
|
.await?;
|
|
|
|
assert!(!response.status().is_success(), "Should reject invalid color format");
|
|
|
|
// Test: Empty name should fail
|
|
println!("Testing empty name validation...");
|
|
let response = client.client
|
|
.post(&format!("{}/api/labels", client.base_url))
|
|
.header("Authorization", format!("Bearer {}", client.auth_token.as_ref().unwrap()))
|
|
.json(&json!({
|
|
"name": "",
|
|
"color": "#ff0000"
|
|
}))
|
|
.send()
|
|
.await?;
|
|
|
|
assert!(!response.status().is_success(), "Should reject empty name");
|
|
|
|
// Test: Duplicate name should fail
|
|
println!("Testing duplicate name validation...");
|
|
let label_name = "Duplicate Test";
|
|
|
|
// Create first label
|
|
client.create_label(label_name, None, "#ff0000", None).await?;
|
|
|
|
// Try to create duplicate
|
|
let response = client.client
|
|
.post(&format!("{}/api/labels", client.base_url))
|
|
.header("Authorization", format!("Bearer {}", client.auth_token.as_ref().unwrap()))
|
|
.json(&json!({
|
|
"name": label_name,
|
|
"color": "#00ff00"
|
|
}))
|
|
.send()
|
|
.await?;
|
|
|
|
assert!(!response.status().is_success(), "Should reject duplicate name");
|
|
|
|
println!("Label validation test completed successfully!");
|
|
Ok(())
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_label_permissions() -> Result<(), Box<dyn std::error::Error>> {
|
|
let mut client1 = TestClient::new();
|
|
let mut client2 = TestClient::new();
|
|
|
|
// Check server health
|
|
client1.check_server_health().await?;
|
|
|
|
// Create two unique users
|
|
let timestamp = SystemTime::now().duration_since(UNIX_EPOCH)?.as_millis();
|
|
|
|
let username1 = format!("perm_test_user1_{}", timestamp);
|
|
let email1 = format!("perm_test1_{}@example.com", timestamp);
|
|
|
|
let username2 = format!("perm_test_user2_{}", timestamp);
|
|
let email2 = format!("perm_test2_{}@example.com", timestamp);
|
|
|
|
client1.register_user(&username1, &email1, "test_password").await?;
|
|
client1.login(&username1, "test_password").await?;
|
|
|
|
sleep(Duration::from_millis(100)).await; // Small delay to ensure unique timestamps
|
|
|
|
client2.register_user(&username2, &email2, "test_password").await?;
|
|
client2.login(&username2, "test_password").await?;
|
|
|
|
// User 1 creates a label
|
|
println!("Testing cross-user label access permissions...");
|
|
let user1_label = client1.create_label("User 1 Label", None, "#ff0000", None).await?;
|
|
let user1_label_id = user1_label["id"].as_str().unwrap();
|
|
|
|
// User 2 should not be able to update User 1's label
|
|
println!("Testing unauthorized label update...");
|
|
let updates = json!({
|
|
"name": "Hacked Label",
|
|
"color": "#000000"
|
|
});
|
|
|
|
let response = client2.client
|
|
.put(&format!("{}/api/labels/{}", client2.base_url, user1_label_id))
|
|
.header("Authorization", format!("Bearer {}", client2.auth_token.as_ref().unwrap()))
|
|
.json(&updates)
|
|
.send()
|
|
.await?;
|
|
|
|
assert!(!response.status().is_success(), "User 2 should not be able to update User 1's label");
|
|
|
|
// User 2 should not be able to delete User 1's label
|
|
println!("Testing unauthorized label deletion...");
|
|
let response = client2.client
|
|
.delete(&format!("{}/api/labels/{}", client2.base_url, user1_label_id))
|
|
.header("Authorization", format!("Bearer {}", client2.auth_token.as_ref().unwrap()))
|
|
.send()
|
|
.await?;
|
|
|
|
assert!(!response.status().is_success(), "User 2 should not be able to delete User 1's label");
|
|
|
|
// User 1's label should still exist and be unchanged
|
|
println!("Verifying label integrity...");
|
|
let user1_labels = client1.get_labels(false).await?;
|
|
let found_label = user1_labels.iter().find(|l| l["id"] == user1_label_id);
|
|
assert!(found_label.is_some());
|
|
assert_eq!(found_label.unwrap()["name"], "User 1 Label");
|
|
|
|
println!("Label permissions test completed successfully!");
|
|
Ok(())
|
|
}
|