test: add global endpoint coverage for users, groups, schedules, and more
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -206,6 +206,17 @@ async fn test_flow_endpoints(db: Pool<Postgres>) -> anyhow::Result<()> {
|
||||
.unwrap();
|
||||
assert_eq!(resp.status(), 200, "history_update: {}", resp.text().await?);
|
||||
|
||||
// --- get_triggers_count ---
|
||||
let resp = authed(client().get(flow_url(
|
||||
port,
|
||||
"get_triggers_count",
|
||||
"u/test-user/test_flow",
|
||||
)))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(resp.status(), 200);
|
||||
|
||||
// --- toggle_workspace_error_handler (EE-gated, expect 400 in OSS) ---
|
||||
let resp = authed(client().post(flow_url(
|
||||
port,
|
||||
|
||||
@@ -140,6 +140,16 @@ async fn test_folder_endpoints(db: Pool<Postgres>) -> anyhow::Result<()> {
|
||||
.unwrap();
|
||||
assert_eq!(resp.status(), 200);
|
||||
|
||||
// --- is_owner ---
|
||||
let resp = authed(client().get(format!(
|
||||
"{base}/is_owner/f/test_folder"
|
||||
)))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(resp.status(), 200);
|
||||
resp.json::<bool>().await?;
|
||||
|
||||
// --- delete ---
|
||||
let resp = authed(client().delete(folder_url(port, "delete", "another_folder")))
|
||||
.send()
|
||||
|
||||
@@ -151,5 +151,150 @@ async fn test_group_endpoints(db: Pool<Postgres>) -> anyhow::Result<()> {
|
||||
let names = resp.json::<Vec<String>>().await?;
|
||||
assert!(!names.contains(&"another_group".to_string()));
|
||||
|
||||
// ===== Global (instance group) endpoints =====
|
||||
let global_base = format!("http://localhost:{port}/api/groups");
|
||||
|
||||
// --- create instance group ---
|
||||
let resp = authed(client().post(format!("{global_base}/create")))
|
||||
.json(&json!({"name": "test_igroup", "summary": "Test instance group"}))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
resp.status(),
|
||||
200,
|
||||
"create igroup: {}",
|
||||
resp.text().await?
|
||||
);
|
||||
|
||||
// --- list instance groups ---
|
||||
let resp = authed(client().get(format!("{global_base}/list")))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(resp.status(), 200);
|
||||
let list = resp.json::<Vec<serde_json::Value>>().await?;
|
||||
assert!(list.iter().any(|g| g["name"] == "test_igroup"));
|
||||
|
||||
// --- list_with_workspaces ---
|
||||
let resp = authed(client().get(format!("{global_base}/list_with_workspaces")))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(resp.status(), 200);
|
||||
resp.json::<Vec<serde_json::Value>>().await?;
|
||||
|
||||
// --- get instance group ---
|
||||
let resp = authed(client().get(format!("{global_base}/get/test_igroup")))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(resp.status(), 200);
|
||||
let body = resp.json::<serde_json::Value>().await?;
|
||||
assert_eq!(body["name"], "test_igroup");
|
||||
assert_eq!(body["summary"], "Test instance group");
|
||||
|
||||
// --- update instance group ---
|
||||
let resp = authed(client().post(format!("{global_base}/update/test_igroup")))
|
||||
.json(&json!({"new_summary": "Updated instance group"}))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
resp.status(),
|
||||
200,
|
||||
"update igroup: {}",
|
||||
resp.text().await?
|
||||
);
|
||||
|
||||
// verify update
|
||||
let resp = authed(client().get(format!("{global_base}/get/test_igroup")))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
let body = resp.json::<serde_json::Value>().await?;
|
||||
assert_eq!(body["summary"], "Updated instance group");
|
||||
|
||||
// --- adduser to instance group ---
|
||||
let resp = authed(client().post(format!("{global_base}/adduser/test_igroup")))
|
||||
.json(&json!({"email": "test@windmill.dev"}))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
resp.status(),
|
||||
200,
|
||||
"adduser igroup: {}",
|
||||
resp.text().await?
|
||||
);
|
||||
|
||||
// verify membership
|
||||
let resp = authed(client().get(format!("{global_base}/get/test_igroup")))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
let body = resp.json::<serde_json::Value>().await?;
|
||||
let emails = body["emails"].as_array().unwrap();
|
||||
assert!(
|
||||
emails
|
||||
.iter()
|
||||
.any(|e| e.as_str() == Some("test@windmill.dev")),
|
||||
"expected test@windmill.dev in emails, got: {:?}",
|
||||
emails
|
||||
);
|
||||
|
||||
// --- removeuser from instance group ---
|
||||
let resp = authed(client().post(format!(
|
||||
"{global_base}/removeuser/test_igroup"
|
||||
)))
|
||||
.json(&json!({"email": "test@windmill.dev"}))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(resp.status(), 200);
|
||||
|
||||
// --- export (EE-gated) ---
|
||||
let resp = authed(client().get(format!("{global_base}/export")))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(
|
||||
resp.status() == 200 || resp.status() == 400,
|
||||
"export igroups: unexpected status {}",
|
||||
resp.status()
|
||||
);
|
||||
|
||||
// --- overwrite (EE-gated) ---
|
||||
let resp = authed(client().post(format!("{global_base}/overwrite")))
|
||||
.json(&json!([]))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(
|
||||
resp.status() == 200 || resp.status() == 400,
|
||||
"overwrite igroups: unexpected status {}",
|
||||
resp.status()
|
||||
);
|
||||
|
||||
// --- delete instance group ---
|
||||
let resp = authed(client().delete(format!("{global_base}/delete/test_igroup")))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
resp.status(),
|
||||
200,
|
||||
"delete igroup: {}",
|
||||
resp.text().await?
|
||||
);
|
||||
|
||||
// verify deleted
|
||||
let resp = authed(client().get(format!("{global_base}/list")))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
let list = resp.json::<Vec<serde_json::Value>>().await?;
|
||||
assert!(!list.iter().any(|g| g["name"] == "test_igroup"));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -296,6 +296,16 @@ async fn test_resource_endpoints(db: Pool<Postgres>) -> anyhow::Result<()> {
|
||||
.unwrap();
|
||||
assert_eq!(resp.status(), 404);
|
||||
|
||||
// --- file_resource_type_to_file_ext_map ---
|
||||
let resp = authed(client().get(format!(
|
||||
"{base}/file_resource_type_to_file_ext_map"
|
||||
)))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(resp.status(), 200);
|
||||
resp.json::<serde_json::Value>().await?;
|
||||
|
||||
// --- resource types ---
|
||||
|
||||
// type/exists
|
||||
|
||||
@@ -218,5 +218,20 @@ async fn test_schedule_endpoints(db: Pool<Postgres>) -> anyhow::Result<()> {
|
||||
let resp = authed_get(port, "exists", "u/test-user/another_schedule").await;
|
||||
assert_eq!(resp.json::<bool>().await?, false);
|
||||
|
||||
// ===== Global endpoints =====
|
||||
|
||||
// --- preview ---
|
||||
let resp = authed(client().post(format!(
|
||||
"http://localhost:{port}/api/schedules/preview"
|
||||
)))
|
||||
.json(&json!({
|
||||
"schedule": "0 0 */6 * * *",
|
||||
"timezone": "UTC"
|
||||
}))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(resp.status(), 200, "preview: {}", resp.text().await?);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -257,6 +257,10 @@ async fn test_script_endpoints(db: Pool<Postgres>) -> anyhow::Result<()> {
|
||||
resp.status()
|
||||
);
|
||||
|
||||
// --- get_triggers_count ---
|
||||
let resp = authed_get(port, "get_triggers_count", "u/test-user/test_script").await;
|
||||
assert_eq!(resp.status(), 200);
|
||||
|
||||
// --- tokened_raw (global unauthed, token in URL) ---
|
||||
let resp = client()
|
||||
.get(format!(
|
||||
|
||||
@@ -113,6 +113,178 @@ async fn test_user_endpoints(db: Pool<Postgres>) -> anyhow::Result<()> {
|
||||
assert_eq!(resp.status(), 200);
|
||||
resp.json::<Vec<serde_json::Value>>().await?;
|
||||
|
||||
// --- username_info ---
|
||||
let resp = authed(client().get(format!(
|
||||
"{global_base}/username_info/test@windmill.dev"
|
||||
)))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(resp.status(), 200);
|
||||
let body = resp.json::<serde_json::Value>().await?;
|
||||
assert_eq!(body["username"], "test-user");
|
||||
|
||||
// --- global usage ---
|
||||
let resp = authed(client().get(format!("{global_base}/usage")))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(resp.status(), 200);
|
||||
|
||||
// --- tutorial_progress (get, then set, then get again) ---
|
||||
let resp = authed(client().get(format!("{global_base}/tutorial_progress")))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(resp.status(), 200);
|
||||
resp.json::<serde_json::Value>().await?;
|
||||
|
||||
let resp = authed(client().post(format!("{global_base}/tutorial_progress")))
|
||||
.json(&json!({"progress": 42, "skipped_all": false}))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
resp.status(),
|
||||
200,
|
||||
"set tutorial_progress: {}",
|
||||
resp.text().await?
|
||||
);
|
||||
|
||||
let resp = authed(client().get(format!("{global_base}/tutorial_progress")))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
let body = resp.json::<serde_json::Value>().await?;
|
||||
assert_eq!(body["progress"], 42);
|
||||
|
||||
// --- global update user ---
|
||||
let resp = authed(client().post(format!(
|
||||
"{global_base}/update/test2@windmill.dev"
|
||||
)))
|
||||
.json(&json!({"name": "Updated Test User 2"}))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
resp.status(),
|
||||
200,
|
||||
"global update user: {}",
|
||||
resp.text().await?
|
||||
);
|
||||
|
||||
// --- setpassword (EE-gated in OSS) ---
|
||||
let resp = authed(client().post(format!("{global_base}/setpassword")))
|
||||
.json(&json!({"password": "new-test-password-123"}))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(
|
||||
resp.status() == 200 || resp.status() == 500,
|
||||
"setpassword: unexpected status {}",
|
||||
resp.status()
|
||||
);
|
||||
|
||||
// --- all_runnables ---
|
||||
let resp = authed(client().get(format!("{global_base}/all_runnables")))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(resp.status(), 200);
|
||||
resp.json::<Vec<serde_json::Value>>().await?;
|
||||
|
||||
// --- onboarding (EE-gated in OSS) ---
|
||||
let resp = authed(client().post(format!("{global_base}/onboarding")))
|
||||
.json(&json!({"touch_point": "test", "use_case": "testing"}))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(
|
||||
resp.status() == 200 || resp.status() == 500,
|
||||
"onboarding: unexpected status {}",
|
||||
resp.status()
|
||||
);
|
||||
|
||||
// --- decline_invite (no pending invite, but endpoint should handle gracefully) ---
|
||||
let resp = authed(client().post(format!("{global_base}/decline_invite")))
|
||||
.json(&json!({"workspace_id": "nonexistent-ws"}))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(
|
||||
resp.status() == 200 || resp.status() == 404,
|
||||
"decline_invite: unexpected status {}",
|
||||
resp.status()
|
||||
);
|
||||
|
||||
// --- auth: is_first_time_setup (unauthed) ---
|
||||
let resp = client()
|
||||
.get(format!("http://localhost:{port}/api/auth/is_first_time_setup"))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(resp.status(), 200);
|
||||
let is_first = resp.json::<bool>().await?;
|
||||
assert_eq!(is_first, false);
|
||||
|
||||
// --- auth: is_smtp_configured (unauthed) ---
|
||||
let resp = client()
|
||||
.get(format!("http://localhost:{port}/api/auth/is_smtp_configured"))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(resp.status(), 200);
|
||||
resp.json::<bool>().await?;
|
||||
|
||||
// --- create user (global, EE-gated in OSS) ---
|
||||
let resp = authed(client().post(format!("{global_base}/create")))
|
||||
.json(&json!({
|
||||
"email": "newglobaluser@windmill.dev",
|
||||
"password": "test-password-123",
|
||||
"super_admin": false,
|
||||
"name": "New Global User"
|
||||
}))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
let create_status = resp.status();
|
||||
assert!(
|
||||
create_status == 201 || create_status == 500,
|
||||
"create user: unexpected status {}",
|
||||
create_status
|
||||
);
|
||||
|
||||
if create_status == 201 {
|
||||
// --- rename user (only if create succeeded / EE) ---
|
||||
let resp = authed(client().post(format!(
|
||||
"{global_base}/rename/newglobaluser@windmill.dev"
|
||||
)))
|
||||
.json(&json!({"new_username": "renamed-user"}))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
resp.status(),
|
||||
200,
|
||||
"rename user: {}",
|
||||
resp.text().await?
|
||||
);
|
||||
|
||||
// --- global delete user ---
|
||||
let resp = authed(client().delete(format!(
|
||||
"{global_base}/delete/newglobaluser@windmill.dev"
|
||||
)))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
resp.status(),
|
||||
200,
|
||||
"global delete user: {}",
|
||||
resp.text().await?
|
||||
);
|
||||
}
|
||||
|
||||
// ===== Workspace-scoped endpoints =====
|
||||
|
||||
// --- whoami ---
|
||||
|
||||
@@ -587,5 +587,14 @@ async fn test_workspace_endpoints(db: Pool<Postgres>) -> anyhow::Result<()> {
|
||||
.unwrap();
|
||||
assert_eq!(resp.json::<bool>().await?, false);
|
||||
|
||||
// --- create_workspace_require_superadmin ---
|
||||
let resp = authed(client().get(format!(
|
||||
"{global_base}/create_workspace_require_superadmin"
|
||||
)))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(resp.status(), 200);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user