use fletch_orm::{ColumnType, Entity as EntityTrait, Value};
use fletch_orm_macros::Entity;
#[derive(Entity)]
struct User {
#[fletch(id)]
id: i64,
name: String,
active: bool,
}
#[test]
fn default_table_name_is_snake_case_plural() {
assert_eq!(User::table_name(), "users");
}
#[test]
fn id_column_matches_marked_field() {
assert_eq!(User::id_column(), "id");
}
#[test]
fn columns_include_all_non_skipped_fields() {
let cols = User::columns();
assert_eq!(cols.len(), 3);
assert_eq!(cols[0].name(), "id");
assert_eq!(cols[0].column_type(), ColumnType::Integer);
assert_eq!(cols[1].name(), "name");
assert_eq!(cols[1].column_type(), ColumnType::Text);
assert_eq!(cols[2].name(), "active");
assert_eq!(cols[2].column_type(), ColumnType::Boolean);
}
#[test]
fn id_returns_correct_value() {
let u = User {
id: 42,
name: "Alice".into(),
active: true,
};
assert_eq!(u.id(), 42);
}
#[test]
fn values_returns_all_field_values() {
let u = User {
id: 1,
name: "Bob".into(),
active: false,
};
let vals = u.values();
assert_eq!(vals.len(), 3);
assert_eq!(vals[0], Value::I64(1));
assert_eq!(vals[1], Value::Text("Bob".into()));
assert_eq!(vals[2], Value::Bool(false));
}
#[derive(Entity)]
#[fletch(table = "people")]
struct Person {
#[fletch(id)]
id: i64,
full_name: String,
}
#[test]
fn table_name_override() {
assert_eq!(Person::table_name(), "people");
}
#[derive(Entity)]
#[expect(dead_code, reason = "struct exists to test #[fletch(skip)] attribute")]
struct Post {
#[fletch(id)]
id: i64,
title: String,
#[fletch(skip)]
cached_slug: String,
}
#[test]
fn skip_excludes_field_from_columns() {
let cols = Post::columns();
assert_eq!(cols.len(), 2);
assert_eq!(cols[0].name(), "id");
assert_eq!(cols[1].name(), "title");
}
#[test]
fn skip_excludes_field_from_values() {
let p = Post {
id: 1,
title: "Hello".into(),
cached_slug: "hello".into(),
};
let vals = p.values();
assert_eq!(vals.len(), 2);
}
#[derive(Entity)]
struct Comment {
#[fletch(id, rename = "comment_id")]
id: i64,
#[fletch(rename = "body_text")]
body: String,
}
#[test]
fn rename_overrides_column_names() {
let cols = Comment::columns();
assert_eq!(cols[0].name(), "comment_id");
assert_eq!(cols[1].name(), "body_text");
}
#[test]
fn rename_overrides_id_column() {
assert_eq!(Comment::id_column(), "comment_id");
}
#[derive(Entity)]
struct Profile {
#[fletch(id)]
id: i64,
bio: Option<String>,
age: Option<i32>,
}
#[test]
fn optional_fields_produce_correct_column_types() {
let cols = Profile::columns();
assert_eq!(cols.len(), 3);
assert_eq!(cols[1].name(), "bio");
assert_eq!(cols[1].column_type(), ColumnType::Text);
assert_eq!(cols[2].name(), "age");
assert_eq!(cols[2].column_type(), ColumnType::Integer);
}
#[test]
fn optional_none_produces_null_value() {
let p = Profile {
id: 1,
bio: None,
age: None,
};
let vals = p.values();
assert_eq!(vals[1], Value::Null);
assert_eq!(vals[2], Value::Null);
}
#[test]
fn optional_some_produces_inner_value() {
let p = Profile {
id: 1,
bio: Some("Hello".into()),
age: Some(30),
};
let vals = p.values();
assert_eq!(vals[1], Value::Text("Hello".into()));
assert_eq!(vals[2], Value::I32(30));
}
#[derive(Entity)]
struct Category {
#[fletch(id)]
id: i64,
}
#[test]
fn pluralizes_y_ending() {
assert_eq!(Category::table_name(), "categories");
}
#[derive(Entity)]
struct Address {
#[fletch(id)]
id: i64,
}
#[test]
fn pluralizes_s_ending() {
assert_eq!(Address::table_name(), "addresses");
}