mod constraint_map_fixture;
use constraint_map_fixture::{exec_sql, init_constraint_db};
use ferro_rs::validation::ConstraintMap;
use serial_test::serial;
#[tokio::test]
#[serial]
async fn toctou_simulation_maps_to_field_error() {
init_constraint_db().await;
exec_sql("INSERT INTO cw (id, slug) VALUES (1, 'taken')")
.await
.expect("seed winning insert");
let err = exec_sql("INSERT INTO cw (id, slug) VALUES (2, 'taken')")
.await
.expect_err("expected UNIQUE violation from losing insert");
let map = ConstraintMap::new()
.on("cw_slug_unique", "slug", "has already been taken")
.sqlite("cw.slug");
let ve = map
.try_map(err)
.expect("try_map should convert UNIQUE violation to ValidationError");
assert!(
ve.has("slug"),
"expected a field error on 'slug', got: {ve:?}"
);
}
#[tokio::test]
#[serial]
async fn sqlite_identity_match_via_message() {
init_constraint_db().await;
exec_sql("INSERT INTO cw (id, slug) VALUES (1, 'taken')")
.await
.expect("seed");
let err = exec_sql("INSERT INTO cw (id, slug) VALUES (2, 'taken')")
.await
.expect_err("expected UNIQUE violation");
let map = ConstraintMap::new()
.on("never_matches_pg_name", "slug", "has already been taken")
.sqlite("cw.slug");
let ve = map
.try_map(err)
.expect("try_map should match via SQLite message parse");
assert!(
ve.has("slug"),
"expected 'slug' field error from SQLite identity match, got: {ve:?}"
);
}
#[tokio::test]
#[serial]
async fn non_unique_error_passes_through_unchanged() {
init_constraint_db().await;
let err = sea_orm::DbErr::Custom("some other error".into());
let map = ConstraintMap::new()
.on("cw_slug_unique", "slug", "has already been taken")
.sqlite("cw.slug");
match map.try_map(err) {
Err(sea_orm::DbErr::Custom(msg)) => {
assert_eq!(
msg, "some other error",
"non-UNIQUE error must pass through with original message"
);
}
other => panic!("expected Err(DbErr::Custom(\"some other error\")), got {other:?}"),
}
}
#[tokio::test]
#[serial]
async fn unregistered_unique_passes_through() {
init_constraint_db().await;
exec_sql("INSERT INTO cw (id, slug) VALUES (1, 'taken')")
.await
.expect("seed");
let err = exec_sql("INSERT INTO cw (id, slug) VALUES (2, 'taken')")
.await
.expect_err("expected UNIQUE violation");
let map = ConstraintMap::new()
.on("cw_slug_unique", "slug", "has already been taken")
.sqlite("cw.other_col");
assert!(
map.try_map(err).is_err(),
"unregistered UNIQUE violation must pass through unchanged (Err), not be swallowed"
);
}