diff --git a/tests/feature/db_test.go b/tests/feature/db_test.go index 34bbc98..610e54d 100644 --- a/tests/feature/db_test.go +++ b/tests/feature/db_test.go @@ -3,6 +3,7 @@ package feature import ( + "errors" "testing" "github.com/goravel/framework/support/carbon" @@ -52,6 +53,111 @@ func (s *DBTestSuite) TestCRUD() { s.Equal(int64(1), result.RowsAffected) } +func (s *DBTestSuite) TestTransaction() { + tx, err := facades.DB().BeginTransaction() + s.Require().NoError(err) + + result, err := tx.Table("users").Insert(map[string]any{"name": "rollback"}) + s.Require().NoError(err) + s.Equal(int64(1), result.RowsAffected) + s.Require().NoError(tx.Rollback()) + + exists, err := facades.DB().Table("users").Where("name", "rollback").Exists() + s.Require().NoError(err) + s.False(exists) + + tx, err = facades.DB().BeginTransaction() + s.Require().NoError(err) + + result, err = tx.Table("users").Insert(map[string]any{"name": "commit"}) + s.Require().NoError(err) + s.Equal(int64(1), result.RowsAffected) + s.Require().NoError(tx.Commit()) + + exists, err = facades.DB().Table("users").Where("name", "commit").Exists() + s.Require().NoError(err) + s.True(exists) +} + +func (s *DBTestSuite) TestQueryHelpers() { + result, err := facades.DB().Table("users").Insert([]map[string]any{ + {"name": "alpha"}, + {"name": "beta", "mail": "beta@example.com"}, + {"name": "gamma"}, + }) + s.Require().NoError(err) + s.Equal(int64(3), result.RowsAffected) + + count, err := facades.DB().Table("users").Count() + s.Require().NoError(err) + s.Equal(int64(3), count) + + exists, err := facades.DB().Table("users").Where("name", "beta").Exists() + s.Require().NoError(err) + s.True(exists) + + notExists, err := facades.DB().Table("users").Where("name", "delta").DoesntExist() + s.Require().NoError(err) + s.True(notExists) + + withMailCount, err := facades.DB().Table("users").WhereNotNull("mail").Count() + s.Require().NoError(err) + s.Equal(int64(1), withMailCount) +} + +func (s *DBTestSuite) TestFirstOrAndFindOrFail() { + _, err := facades.DB().Table("users").Insert(map[string]any{"name": "exists"}) + s.Require().NoError(err) + + var existing User + s.Require().NoError(facades.DB().Table("users").Where("name", "exists").FirstOr(&existing, func() error { + return errors.New("should not execute callback for existing record") + })) + s.Equal("exists", existing.Name) + + var missing User + err = facades.DB().Table("users").Where("name", "missing").FirstOr(&missing, func() error { + return errors.New("fallback") + }) + s.Require().Error(err) + s.Equal("fallback", err.Error()) + + err = facades.DB().Table("users").Where("name", "missing").FindOrFail(&missing) + s.Require().Error(err) +} + +func (s *DBTestSuite) TestUpdateOrInsertAndPluck() { + _, err := facades.DB().Table("users").Insert([]map[string]any{ + {"name": "alpha"}, + {"name": "beta"}, + }) + s.Require().NoError(err) + + _, err = facades.DB().Table("users").UpdateOrInsert( + map[string]any{"name": "alpha"}, + map[string]any{"avatar": "alpha.png"}, + ) + s.Require().NoError(err) + + _, err = facades.DB().Table("users").UpdateOrInsert( + map[string]any{"name": "gamma"}, + map[string]any{"avatar": "gamma.png"}, + ) + s.Require().NoError(err) + + var names []string + s.Require().NoError(facades.DB().Table("users").OrderBy("id").Pluck("name", &names)) + s.Equal([]string{"alpha", "beta", "gamma"}, names) + + var avatar string + s.Require().NoError(facades.DB().Table("users").Where("name", "alpha").Value("avatar", &avatar)) + s.Equal("alpha.png", avatar) + + count, err := facades.DB().Table("users").Count() + s.Require().NoError(err) + s.Equal(int64(3), count) +} + // TODO use orm.BaseModel when https://github.com/goravel/framework/pull/976 is merged type User struct { ID uint `db:"id"` diff --git a/tests/feature/migration_test.go b/tests/feature/migration_test.go index a31cf4f..9756dac 100644 --- a/tests/feature/migration_test.go +++ b/tests/feature/migration_test.go @@ -68,6 +68,36 @@ func (s *MigrationTestSuite) TestMigrate() { s.True(facades.Schema().HasTable("users")) } +func (s *MigrationTestSuite) TestSchemaInspectors() { + s.True(facades.Schema().HasTable("users")) + s.True(facades.Schema().HasColumn("users", "mail")) + s.True(facades.Schema().HasColumns("users", []string{"id", "name", "alias", "mail"})) + + columnListing := facades.Schema().GetColumnListing("users") + s.Contains(columnListing, "name") + s.Contains(columnListing, "alias") + + tableListing := facades.Schema().GetTableListing() + s.Contains(tableListing, "users") + + indexes, err := facades.Schema().GetIndexes("jobs") + s.Require().NoError(err) + s.NotEmpty(indexes) +} + +func (s *MigrationTestSuite) TestSeederAndDatabaseConsoleCommands() { + s.NotNil(facades.Seeder().GetSeeder("DatabaseSeeder")) + s.NotEmpty(facades.Seeder().GetSeeders()) + + s.Require().NoError(facades.Artisan().Call("migrate:status")) + s.Require().NoError(facades.Artisan().Call("db:seed")) + s.Require().NoError(facades.Artisan().Call("db:wipe")) + s.False(facades.Schema().HasTable("users")) + + s.Require().NoError(facades.Artisan().Call("migrate")) + s.True(facades.Schema().HasTable("users")) +} + func (s *MigrationTestSuite) TestTableComment() { if facades.Schema().Orm().Config().Driver == sqlite.Name || facades.Schema().Orm().Config().Driver == sqlserver.Name { s.T().Skip("sqlite and sqlserver does not support table comment") diff --git a/tests/feature/orm_test.go b/tests/feature/orm_test.go index f5b9d98..b29a7fd 100644 --- a/tests/feature/orm_test.go +++ b/tests/feature/orm_test.go @@ -1,8 +1,10 @@ package feature import ( + "errors" "testing" + ormcontract "github.com/goravel/framework/contracts/database/orm" "github.com/stretchr/testify/suite" "goravel/app/facades" @@ -38,6 +40,105 @@ func (s *OrmTestSuite) TestCreate() { }) } +func (s *OrmTestSuite) TestFirstOrCreate() { + var created models.User + s.Require().NoError(facades.Orm().Query().FirstOrCreate(&created, models.User{ + Name: "first-or-create", + })) + s.NotZero(created.ID) + s.Equal("first-or-create", created.Name) + + var existing models.User + s.Require().NoError(facades.Orm().Query().FirstOrCreate(&existing, models.User{ + Name: "first-or-create", + }, models.User{ + Avatar: "new-avatar.png", + })) + s.Equal(created.ID, existing.ID) + s.Equal("", existing.Avatar) + + count, err := facades.Orm().Query().Model(&models.User{}).Where("name", "first-or-create").Count() + s.Require().NoError(err) + s.Equal(int64(1), count) +} + +func (s *OrmTestSuite) TestUpdateOrCreate() { + var created models.User + s.Require().NoError(facades.Orm().Query().UpdateOrCreate(&created, map[string]any{ + "name": "update-or-create", + }, map[string]any{ + "avatar": "old-avatar.png", + })) + s.NotZero(created.ID) + + var updated models.User + s.Require().NoError(facades.Orm().Query().UpdateOrCreate(&updated, map[string]any{ + "name": "update-or-create", + }, map[string]any{ + "avatar": "new-avatar.png", + })) + s.Equal(created.ID, updated.ID) + s.Equal("new-avatar.png", updated.Avatar) + + count, err := facades.Orm().Query().Model(&models.User{}).Where("name", "update-or-create").Count() + s.Require().NoError(err) + s.Equal(int64(1), count) +} + +func (s *OrmTestSuite) TestFirstOrNew() { + s.Require().NoError(facades.Orm().Query().Model(&models.User{}).Create(map[string]any{ + "name": "first-or-new", + "avatar": "exists.png", + })) + + var existing models.User + s.Require().NoError(facades.Orm().Query().FirstOrNew(&existing, map[string]any{ + "name": "first-or-new", + }, map[string]any{ + "avatar": "new.png", + })) + s.NotZero(existing.ID) + s.Equal("exists.png", existing.Avatar) + + var missing models.User + s.Require().NoError(facades.Orm().Query().FirstOrNew(&missing, map[string]any{ + "name": "first-or-new-missing", + }, map[string]any{ + "avatar": "missing.png", + })) + s.Zero(missing.ID) + s.Equal("first-or-new-missing", missing.Name) + s.Equal("missing.png", missing.Avatar) + + count, err := facades.Orm().Query().Model(&models.User{}).Where("name", "first-or-new-missing").Count() + s.Require().NoError(err) + s.Equal(int64(0), count) +} + +func (s *OrmTestSuite) TestTransaction() { + err := facades.Orm().Transaction(func(tx ormcontract.Query) error { + if err := tx.Model(&models.User{}).Create(map[string]any{"name": "orm-tx-rollback"}); err != nil { + return err + } + + return errors.New("rollback") + }) + s.Require().Error(err) + + count, err := facades.Orm().Query().Model(&models.User{}).Where("name", "orm-tx-rollback").Count() + s.Require().NoError(err) + s.Equal(int64(0), count) + + err = facades.Orm().Transaction(func(tx ormcontract.Query) error { + return tx.Model(&models.User{}).Create(map[string]any{"name": "orm-tx-commit"}) + }) + s.Require().NoError(err) + + count, err = facades.Orm().Query().Model(&models.User{}).Where("name", "orm-tx-commit").Count() + s.Require().NoError(err) + s.Equal(int64(1), count) +} + func (s *OrmTestSuite) TestRestore() { s.Require().NoError(facades.Orm().Query().Model(&models.User{}).Create(map[string]any{"name": "restore"}))