test(picloud): close two app_members test gaps
- `membership_makes_app_appear_in_members_app_list` previously seeded the membership via the repo helper; switch to the public POST endpoint so the test actually exercises the full HTTP round-trip the dashboard depends on. - Add `add_member_with_missing_user_id_is_rejected` to pin the Axum-JsonRejection 4xx contract on malformed POST bodies. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1042,6 +1042,7 @@ async fn member_app_admin_can_manage_members(pool: PgPool) {
|
||||
#[sqlx::test(migrations = "../manager-core/migrations")]
|
||||
async fn membership_makes_app_appear_in_members_app_list(pool: PgPool) {
|
||||
let s = boot(pool).await;
|
||||
let owner_token = login_token(&s.server, "owner", "owner-pw").await;
|
||||
|
||||
let bob = seed_user(&s.pool, "bob", "bob-pw", InstanceRole::Member).await;
|
||||
let bob_token = login_token(&s.server, "bob", "bob-pw").await;
|
||||
@@ -1058,8 +1059,12 @@ async fn membership_makes_app_appear_in_members_app_list(pool: PgPool) {
|
||||
"bob has no memberships → empty apps list"
|
||||
);
|
||||
|
||||
// Grant via the public POST endpoint — exercises the full
|
||||
// round-trip the dashboard goes through, not just the repo seam.
|
||||
let r = add_member(&s.server, &owner_token, "default", bob, AppRole::Viewer).await;
|
||||
r.assert_status(axum::http::StatusCode::CREATED);
|
||||
|
||||
// After grant: bob sees the default app.
|
||||
grant_membership(&s.pool, bob, s.default_app, AppRole::Viewer).await;
|
||||
let r = s
|
||||
.server
|
||||
.get("/api/v1/admin/apps")
|
||||
@@ -1070,3 +1075,25 @@ async fn membership_makes_app_appear_in_members_app_list(pool: PgPool) {
|
||||
assert_eq!(apps.len(), 1);
|
||||
assert_eq!(apps[0]["slug"], "default");
|
||||
}
|
||||
|
||||
#[ignore = "needs DATABASE_URL pointing at a running Postgres"]
|
||||
#[sqlx::test(migrations = "../manager-core/migrations")]
|
||||
async fn add_member_with_missing_user_id_is_rejected(pool: PgPool) {
|
||||
let s = boot(pool).await;
|
||||
let owner_token = login_token(&s.server, "owner", "owner-pw").await;
|
||||
|
||||
// Body missing `user_id` — Axum's Json extractor produces a 4xx
|
||||
// before our handler runs. Pinning the status to keep the contract
|
||||
// honest if anyone ever swaps the extractor.
|
||||
let r = s
|
||||
.server
|
||||
.post("/api/v1/admin/apps/default/members")
|
||||
.add_header("authorization", format!("Bearer {owner_token}"))
|
||||
.json(&json!({ "role": "viewer" }))
|
||||
.await;
|
||||
let status = r.status_code().as_u16();
|
||||
assert!(
|
||||
(400..500).contains(&status),
|
||||
"malformed body should produce a 4xx, got {status}"
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user