Files
windmill/backend/windmill-api-integration-tests/tests/configs.rs
Ruben Fiszel fa668707c0 fix: move alert config from config table to global_settings (#8762)
* feat: move alert config from config table to global_settings

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: update ee-repo-ref.txt

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor: rename alert setting to alert_job_queue_waiting

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: update ee-repo-ref.txt

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: add CLI unit tests for pullInstanceConfigs/pushInstanceConfigs

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: update ee-repo-ref.txt

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: update ee-repo-ref.txt to merged main

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 15:54:44 +00:00

140 lines
4.6 KiB
Rust

use serde_json::json;
use sqlx::{Pool, Postgres};
use windmill_test_utils::*;
fn client() -> reqwest::Client {
reqwest::Client::new()
}
fn authed(builder: reqwest::RequestBuilder) -> reqwest::RequestBuilder {
builder.header("Authorization", "Bearer SECRET_TOKEN")
}
fn assert_2xx(status: u16, body: &str, endpoint: &str) {
assert!(
(200..300).contains(&status),
"{endpoint} returned {status}: {body}",
);
}
#[sqlx::test(migrations = "../migrations", fixtures("base"))]
async fn test_worker_group_crud(db: Pool<Postgres>) -> anyhow::Result<()> {
initialize_tracing().await;
let server = ApiServer::start(db.clone()).await?;
let port = server.addr.port();
let base = format!("http://localhost:{port}/api/configs");
// Create a worker group
let resp = authed(client().post(format!("{base}/update/worker__test_group")))
.json(&json!({"worker_tags": ["test_tag"]}))
.send()
.await?;
assert_2xx(
resp.status().as_u16(),
&resp.text().await?,
"POST /configs/update/worker__test_group",
);
// Verify it exists via get
let resp = authed(client().get(format!("{base}/get/worker__test_group")))
.send()
.await?;
let status = resp.status().as_u16();
let body = resp.text().await?;
assert_2xx(status, &body, "GET /configs/get/worker__test_group");
let config: serde_json::Value = serde_json::from_str(&body)?;
assert_eq!(config["worker_tags"], json!(["test_tag"]));
// Verify it appears in list_worker_groups with prefix stripped
let resp = authed(client().get(format!("{base}/list_worker_groups")))
.send()
.await?;
let body = resp.text().await?;
let groups: Vec<serde_json::Value> = serde_json::from_str(&body)?;
let test_group = groups.iter().find(|g| g["name"] == "test_group");
assert!(
test_group.is_some(),
"test_group should appear in list_worker_groups with prefix stripped"
);
// Delete the worker group
let resp = authed(client().delete(format!("{base}/update/worker__test_group")))
.send()
.await?;
assert_2xx(
resp.status().as_u16(),
&resp.text().await?,
"DELETE /configs/update/worker__test_group",
);
// Verify it's gone from list_worker_groups
let resp = authed(client().get(format!("{base}/list_worker_groups")))
.send()
.await?;
let body = resp.text().await?;
let groups: Vec<serde_json::Value> = serde_json::from_str(&body)?;
let test_group = groups.iter().find(|g| g["name"] == "test_group");
assert!(
test_group.is_none(),
"test_group should be gone after deletion"
);
Ok(())
}
#[sqlx::test(migrations = "../migrations", fixtures("base"))]
async fn test_list_worker_groups_excludes_non_worker_entries(
db: Pool<Postgres>,
) -> anyhow::Result<()> {
initialize_tracing().await;
let server = ApiServer::start(db.clone()).await?;
let port = server.addr.port();
let base = format!("http://localhost:{port}/api/configs");
// Insert a non-worker entry directly into the config table
sqlx::query("INSERT INTO config (name, config) VALUES ($1, $2) ON CONFLICT (name) DO UPDATE SET config = EXCLUDED.config")
.bind("test__other_entry")
.bind(json!({"some_key": "some_value"}))
.execute(&db)
.await?;
// list_worker_groups should NOT return it
let resp = authed(client().get(format!("{base}/list_worker_groups")))
.send()
.await?;
let body = resp.text().await?;
let groups: Vec<serde_json::Value> = serde_json::from_str(&body)?;
let other_entry = groups
.iter()
.find(|g| g["name"] == "test__other_entry" || g["name"] == "other_entry");
assert!(
other_entry.is_none(),
"non-worker entries should not appear in list_worker_groups"
);
// Clean up
sqlx::query("DELETE FROM config WHERE name = $1")
.bind("test__other_entry")
.execute(&db)
.await?;
Ok(())
}
#[sqlx::test(migrations = "../migrations", fixtures("base"))]
async fn test_no_alert_entries_in_config_table_after_migration(
db: Pool<Postgres>,
) -> anyhow::Result<()> {
// After migration, no alert__* entries should remain in the config table
let rows: Vec<(String,)> = sqlx::query_as("SELECT name FROM config WHERE name LIKE 'alert__%'")
.fetch_all(&db)
.await?;
assert!(
rows.is_empty(),
"No alert entries should remain in config table after migration, found: {:?}",
rows.iter().map(|(n,)| n.as_str()).collect::<Vec<_>>()
);
Ok(())
}