Skip to content

Commit

Permalink
fixed after hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
ganigeorgiev committed Aug 8, 2022
1 parent 8009d37 commit 8b2b26c
Show file tree
Hide file tree
Showing 17 changed files with 941 additions and 674 deletions.
1 change: 0 additions & 1 deletion apis/collection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -541,7 +541,6 @@ func TestCollectionImport(t *testing.T) {
ExpectedEvents: map[string]int{
"OnCollectionsBeforeImportRequest": 1,
"OnModelBeforeCreate": 2,
"OnModelAfterCreate": 1,
},
AfterFunc: func(t *testing.T, app *tests.TestApp, e *echo.Echo) {
collections := []*models.Collection{}
Expand Down
64 changes: 43 additions & 21 deletions daos/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ func (dao *Dao) FindById(m models.Model, id string) error {
return dao.ModelQuery(m).Where(dbx.HashExp{"id": id}).Limit(1).One(m)
}

type afterCallGroup struct {
Action string
EventDao *Dao
Model models.Model
}

// RunInTransaction wraps fn into a transaction.
//
// It is safe to nest RunInTransaction calls.
Expand All @@ -59,44 +65,60 @@ func (dao *Dao) RunInTransaction(fn func(txDao *Dao) error) error {
// so execute the function within the current transaction
return fn(dao)
case *dbx.DB:

return txOrDB.Transactional(func(tx *dbx.Tx) error {
txDao := New(tx)

txDao.BeforeCreateFunc = func(eventDao *Dao, m models.Model) error {
if dao.BeforeCreateFunc != nil {
afterCalls := []afterCallGroup{}

if dao.BeforeCreateFunc != nil {
txDao.BeforeCreateFunc = func(eventDao *Dao, m models.Model) error {
return dao.BeforeCreateFunc(eventDao, m)
}
return nil
}
txDao.AfterCreateFunc = func(eventDao *Dao, m models.Model) {
if dao.AfterCreateFunc != nil {
dao.AfterCreateFunc(eventDao, m)
if dao.BeforeUpdateFunc != nil {
txDao.BeforeUpdateFunc = func(eventDao *Dao, m models.Model) error {
return dao.BeforeUpdateFunc(eventDao, m)
}
}
txDao.BeforeUpdateFunc = func(eventDao *Dao, m models.Model) error {
if dao.BeforeUpdateFunc != nil {
return dao.BeforeUpdateFunc(eventDao, m)
if dao.BeforeDeleteFunc != nil {
txDao.BeforeDeleteFunc = func(eventDao *Dao, m models.Model) error {
return dao.BeforeDeleteFunc(eventDao, m)
}
return nil
}
txDao.AfterUpdateFunc = func(eventDao *Dao, m models.Model) {
if dao.AfterUpdateFunc != nil {
dao.AfterUpdateFunc(eventDao, m)

if dao.AfterCreateFunc != nil {
txDao.AfterCreateFunc = func(eventDao *Dao, m models.Model) {
afterCalls = append(afterCalls, afterCallGroup{"create", eventDao, m})
}
}
txDao.BeforeDeleteFunc = func(eventDao *Dao, m models.Model) error {
if dao.BeforeDeleteFunc != nil {
return dao.BeforeDeleteFunc(eventDao, m)
if dao.AfterUpdateFunc != nil {
txDao.AfterUpdateFunc = func(eventDao *Dao, m models.Model) {
afterCalls = append(afterCalls, afterCallGroup{"update", eventDao, m})
}
}
if dao.AfterDeleteFunc != nil {
txDao.AfterDeleteFunc = func(eventDao *Dao, m models.Model) {
afterCalls = append(afterCalls, afterCallGroup{"delete", eventDao, m})
}
return nil
}
txDao.AfterDeleteFunc = func(eventDao *Dao, m models.Model) {
if dao.AfterDeleteFunc != nil {
dao.AfterDeleteFunc(eventDao, m)

if err := fn(txDao); err != nil {
return err
}

// execute after event calls on successfull transaction
for _, call := range afterCalls {
if call.Action == "create" {
dao.AfterCreateFunc(call.EventDao, call.Model)
} else if call.Action == "update" {
dao.AfterUpdateFunc(call.EventDao, call.Model)
} else if call.Action == "delete" {
dao.AfterDeleteFunc(call.EventDao, call.Model)
}
}

return fn(txDao)
return nil
})
}

Expand Down
193 changes: 183 additions & 10 deletions daos/base_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -293,35 +293,208 @@ func TestDaoBeforeHooksError(t *testing.T) {
testApp, _ := tests.NewTestApp()
defer testApp.Cleanup()

testApp.Dao().BeforeCreateFunc = func(eventDao *daos.Dao, m models.Model) error {
baseDao := testApp.Dao()

baseDao.BeforeCreateFunc = func(eventDao *daos.Dao, m models.Model) error {
return errors.New("before_create")
}
testApp.Dao().BeforeUpdateFunc = func(eventDao *daos.Dao, m models.Model) error {
baseDao.BeforeUpdateFunc = func(eventDao *daos.Dao, m models.Model) error {
return errors.New("before_update")
}
testApp.Dao().BeforeDeleteFunc = func(eventDao *daos.Dao, m models.Model) error {
baseDao.BeforeDeleteFunc = func(eventDao *daos.Dao, m models.Model) error {
return errors.New("before_delete")
}

existingModel, _ := testApp.Dao().FindAdminByEmail("[email protected]")

// try to create
// test create error
// ---
newModel := &models.Admin{}
newModel.Email = "[email protected]"
if err := testApp.Dao().Save(newModel); err.Error() != "before_create" {
if err := baseDao.Save(newModel); err.Error() != "before_create" {
t.Fatalf("Expected before_create error, got %v", err)
}

// try to update
// test update error
// ---
if err := testApp.Dao().Save(existingModel); err.Error() != "before_update" {
if err := baseDao.Save(existingModel); err.Error() != "before_update" {
t.Fatalf("Expected before_update error, got %v", err)
}

// try to delete
// test delete error
// ---
if err := testApp.Dao().Delete(existingModel); err.Error() != "before_delete" {
if err := baseDao.Delete(existingModel); err.Error() != "before_delete" {
t.Fatalf("Expected before_delete error, got %v", err)
}
}

func TestDaoTransactionHooksCallsOnFailure(t *testing.T) {
testApp, _ := tests.NewTestApp()
defer testApp.Cleanup()

beforeCreateFuncCalls := 0
beforeUpdateFuncCalls := 0
beforeDeleteFuncCalls := 0
afterCreateFuncCalls := 0
afterUpdateFuncCalls := 0
afterDeleteFuncCalls := 0

baseDao := testApp.Dao()

baseDao.BeforeCreateFunc = func(eventDao *daos.Dao, m models.Model) error {
beforeCreateFuncCalls++
return nil
}
baseDao.BeforeUpdateFunc = func(eventDao *daos.Dao, m models.Model) error {
beforeUpdateFuncCalls++
return nil
}
baseDao.BeforeDeleteFunc = func(eventDao *daos.Dao, m models.Model) error {
beforeDeleteFuncCalls++
return nil
}

baseDao.AfterCreateFunc = func(eventDao *daos.Dao, m models.Model) {
afterCreateFuncCalls++
}
baseDao.AfterUpdateFunc = func(eventDao *daos.Dao, m models.Model) {
afterUpdateFuncCalls++
}
baseDao.AfterDeleteFunc = func(eventDao *daos.Dao, m models.Model) {
afterDeleteFuncCalls++
}

existingModel, _ := testApp.Dao().FindAdminByEmail("[email protected]")

baseDao.RunInTransaction(func(txDao *daos.Dao) error {
// test create
// ---
newModel := &models.Admin{}
newModel.Email = "[email protected]"
newModel.SetPassword("123456")
if err := txDao.Save(newModel); err != nil {
t.Fatal(err)
}

// test update (twice)
// ---
if err := txDao.Save(existingModel); err != nil {
t.Fatal(err)
}
if err := txDao.Save(existingModel); err != nil {
t.Fatal(err)
}

// test delete
// ---
if err := txDao.Delete(existingModel); err != nil {
t.Fatal(err)
}

return errors.New("test_tx_error")
})

if beforeCreateFuncCalls != 1 {
t.Fatalf("Expected beforeCreateFuncCalls to be called 1 times, got %d", beforeCreateFuncCalls)
}
if beforeUpdateFuncCalls != 2 {
t.Fatalf("Expected beforeUpdateFuncCalls to be called 2 times, got %d", beforeUpdateFuncCalls)
}
if beforeDeleteFuncCalls != 1 {
t.Fatalf("Expected beforeDeleteFuncCalls to be called 1 times, got %d", beforeDeleteFuncCalls)
}
if afterCreateFuncCalls != 0 {
t.Fatalf("Expected afterCreateFuncCalls to be called 0 times, got %d", afterCreateFuncCalls)
}
if afterUpdateFuncCalls != 0 {
t.Fatalf("Expected afterUpdateFuncCalls to be called 0 times, got %d", afterUpdateFuncCalls)
}
if afterDeleteFuncCalls != 0 {
t.Fatalf("Expected afterDeleteFuncCalls to be called 0 times, got %d", afterDeleteFuncCalls)
}
}

func TestDaoTransactionHooksCallsOnSuccess(t *testing.T) {
testApp, _ := tests.NewTestApp()
defer testApp.Cleanup()

beforeCreateFuncCalls := 0
beforeUpdateFuncCalls := 0
beforeDeleteFuncCalls := 0
afterCreateFuncCalls := 0
afterUpdateFuncCalls := 0
afterDeleteFuncCalls := 0

baseDao := testApp.Dao()

baseDao.BeforeCreateFunc = func(eventDao *daos.Dao, m models.Model) error {
beforeCreateFuncCalls++
return nil
}
baseDao.BeforeUpdateFunc = func(eventDao *daos.Dao, m models.Model) error {
beforeUpdateFuncCalls++
return nil
}
baseDao.BeforeDeleteFunc = func(eventDao *daos.Dao, m models.Model) error {
beforeDeleteFuncCalls++
return nil
}

baseDao.AfterCreateFunc = func(eventDao *daos.Dao, m models.Model) {
afterCreateFuncCalls++
}
baseDao.AfterUpdateFunc = func(eventDao *daos.Dao, m models.Model) {
afterUpdateFuncCalls++
}
baseDao.AfterDeleteFunc = func(eventDao *daos.Dao, m models.Model) {
afterDeleteFuncCalls++
}

existingModel, _ := testApp.Dao().FindAdminByEmail("[email protected]")

baseDao.RunInTransaction(func(txDao *daos.Dao) error {
// test create
// ---
newModel := &models.Admin{}
newModel.Email = "[email protected]"
newModel.SetPassword("123456")
if err := txDao.Save(newModel); err != nil {
t.Fatal(err)
}

// test update (twice)
// ---
if err := txDao.Save(existingModel); err != nil {
t.Fatal(err)
}
if err := txDao.Save(existingModel); err != nil {
t.Fatal(err)
}

// test delete
// ---
if err := txDao.Delete(existingModel); err != nil {
t.Fatal(err)
}

return nil
})

if beforeCreateFuncCalls != 1 {
t.Fatalf("Expected beforeCreateFuncCalls to be called 1 times, got %d", beforeCreateFuncCalls)
}
if beforeUpdateFuncCalls != 2 {
t.Fatalf("Expected beforeUpdateFuncCalls to be called 2 times, got %d", beforeUpdateFuncCalls)
}
if beforeDeleteFuncCalls != 1 {
t.Fatalf("Expected beforeDeleteFuncCalls to be called 1 times, got %d", beforeDeleteFuncCalls)
}
if afterCreateFuncCalls != 1 {
t.Fatalf("Expected afterCreateFuncCalls to be called 1 times, got %d", afterCreateFuncCalls)
}
if afterUpdateFuncCalls != 2 {
t.Fatalf("Expected afterUpdateFuncCalls to be called 2 times, got %d", afterUpdateFuncCalls)
}
if afterDeleteFuncCalls != 1 {
t.Fatalf("Expected afterDeleteFuncCalls to be called 1 times, got %d", afterDeleteFuncCalls)
}
}
1 change: 0 additions & 1 deletion forms/collections_import_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ func TestCollectionsImportSubmit(t *testing.T) {
expectCollectionsCount: 5,
expectEvents: map[string]int{
"OnModelBeforeCreate": 2,
"OnModelAfterCreate": 2,
},
},
{
Expand Down
12 changes: 0 additions & 12 deletions ui/dist/assets/FilterAutocompleteInput.8695a8af.js

This file was deleted.

12 changes: 12 additions & 0 deletions ui/dist/assets/FilterAutocompleteInput.92765a8b.js

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 8b2b26c

Please sign in to comment.