From b70b4b7a8120e873c0568cb9e1d34f54edc2f6d8 Mon Sep 17 00:00:00 2001 From: Lucien Cartier-Tilet Date: Fri, 31 Jan 2025 22:52:28 +0100 Subject: [PATCH] test: added tests for M2M relationships, it works --- georm-macros/src/georm/ir.rs | 6 ++---- tests/fixtures/m2m.sql | 14 ++++++++++++++ tests/m2m_relationship.rs | 20 ++++++++++++++++++++ tests/models.rs | 25 ++++++++++++++++++++++++- tests/o2m_relationship.rs | 33 +++++++++++++++++++++++++++++++++ 5 files changed, 93 insertions(+), 5 deletions(-) create mode 100644 tests/fixtures/m2m.sql create mode 100644 tests/m2m_relationship.rs create mode 100644 tests/o2m_relationship.rs diff --git a/georm-macros/src/georm/ir.rs b/georm-macros/src/georm/ir.rs index 2090339..6abfeb0 100644 --- a/georm-macros/src/georm/ir.rs +++ b/georm-macros/src/georm/ir.rs @@ -103,13 +103,11 @@ impl From<&M2MRelationshipComplete> for proc_macro2::TokenStream { ); let entity = &value.entity; let query = format!( - " -SELECT remote.* + "SELECT remote.* FROM {} local JOIN {} link ON link.{} = local.{} JOIN {} remote ON link.{} = remote.{} -WHERE local.{} = $1 -", +WHERE local.{} = $1", value.local.table, value.link.table, value.link.from, diff --git a/tests/fixtures/m2m.sql b/tests/fixtures/m2m.sql new file mode 100644 index 0000000..4b37855 --- /dev/null +++ b/tests/fixtures/m2m.sql @@ -0,0 +1,14 @@ +INSERT INTO genres (name) +VALUES ('fantasy'), + ('horror'), + ('classic'); + +INSERT INTO book_genres (book_id, genre_id) +VALUES (1, 1), + (1, 3), + (2, 1), + (2, 3), + (3, 1), + (3, 3), + (4, 2), + (4, 3); diff --git a/tests/m2m_relationship.rs b/tests/m2m_relationship.rs new file mode 100644 index 0000000..395239c --- /dev/null +++ b/tests/m2m_relationship.rs @@ -0,0 +1,20 @@ +use georm::Georm; + +mod models; +use models::*; + +#[sqlx::test(fixtures("simple_struct", "o2o", "m2m"))] +async fn genres_should_be_able_to_access_all_books(pool: sqlx::PgPool) -> sqlx::Result<()> { + let fantasy = Genre::find(&pool, &1).await?.unwrap(); + let books = fantasy.get_books(&pool).await?; + assert_eq!(3, books.len()); + Ok(()) +} + +#[sqlx::test(fixtures("simple_struct", "o2o", "m2m"))] +async fn books_should_be_able_to_access_their_genres(pool: sqlx::PgPool) -> sqlx::Result<()> { + let to_build_a_fire = Book::find(&pool, &4).await?.unwrap(); + let genres = to_build_a_fire.get_genres(&pool).await?; + assert_eq!(2, genres.len()); + Ok(()) +} diff --git a/tests/models.rs b/tests/models.rs index ad45b07..3fb7288 100644 --- a/tests/models.rs +++ b/tests/models.rs @@ -35,7 +35,13 @@ impl Ord for Author { table = "books", one_to_many = [ { name = "reviews", remote_id = "book_id", table = "reviews", entity = Review } - ] + ], + many_to_many = [{ + name = "genres", + table = "genres", + entity = Genre, + link = { table = "book_genres", from = "book_id", to = "genre_id" } + }] )] pub struct Book { #[georm(id)] @@ -66,3 +72,20 @@ pub struct Review { pub book_id: i32, pub review: String, } + +#[derive(Debug, sqlx::FromRow, Georm, PartialEq, Eq)] +#[georm( + table = "genres", + many_to_many = [{ + name = "books", + table = "books", + entity = Book, + remote_id = "ident", + link = { table = "book_genres", from = "genre_id", to = "book_id" } + }] +)] +pub struct Genre { + #[georm(id)] + id: i32, + name: String, +} diff --git a/tests/o2m_relationship.rs b/tests/o2m_relationship.rs new file mode 100644 index 0000000..ffcc025 --- /dev/null +++ b/tests/o2m_relationship.rs @@ -0,0 +1,33 @@ +use georm::Georm; + +mod models; +use models::*; + +#[sqlx::test(fixtures("simple_struct", "o2o"))] +async fn books_access_one_review(pool: sqlx::PgPool) -> sqlx::Result<()> { + let book = Book::find(&pool, &1).await?.unwrap(); + let reviews = book.get_reviews(&pool).await?; + let review = Review { + id: 1, + book_id: 1, + review: "Great book".into(), + }; + assert_eq!(vec![review], reviews); + Ok(()) +} + +#[sqlx::test(fixtures("simple_struct", "o2o"))] +async fn books_should_access_their_multiple_reviews(pool: sqlx::PgPool) -> sqlx::Result<()> { + let book = Book::find(&pool, &2).await?.unwrap(); + let reviews = book.get_reviews(&pool).await?; + assert_eq!(2, reviews.len()); + Ok(()) +} + +#[sqlx::test(fixtures("simple_struct", "o2o"))] +async fn books_can_have_no_reviews(pool: sqlx::PgPool) -> sqlx::Result<()> { + let book = Book::find(&pool, &4).await?.unwrap(); + let reviews = book.get_reviews(&pool).await?; + assert_eq!(0, reviews.len()); + Ok(()) +}