package repository import ( "testing" "github.com/jinzhu/gorm" "github.com/zitadel/zitadel/internal/domain" "github.com/zitadel/zitadel/internal/zerrors" ) func TestPrepareGetByQuery(t *testing.T) { type args struct { table string searchQuery SearchQuery } type res struct { result Test wantErr bool errFunc func(err error) bool } tests := []struct { name string db *dbMock args args res res }{ { "search with equals case insensitive", mockDB(t). expectGetByQuery("TESTTABLE", "test", "=", "VALUE"), args{ table: "TESTTABLE", searchQuery: TestSearchQuery{key: TestSearchKey_TEST, method: domain.SearchMethodEqualsIgnoreCase, value: "VALUE"}, }, res{ result: Test{ID: "VALUE"}, wantErr: false, }, }, { "search with equals case sensitive", mockDB(t). expectGetByQueryCaseSensitive("TESTTABLE", "test", "=", "VALUE"), args{ table: "TESTTABLE", searchQuery: TestSearchQuery{key: TestSearchKey_TEST, method: domain.SearchMethodEquals, value: "VALUE"}, }, res{ result: Test{ID: "VALUE"}, wantErr: false, }, }, { "search with startswith, case insensitive", mockDB(t). expectGetByQuery("TESTTABLE", "test", "LIKE", "VALUE%"), args{ table: "TESTTABLE", searchQuery: TestSearchQuery{key: TestSearchKey_TEST, method: domain.SearchMethodStartsWithIgnoreCase, value: "VALUE"}, }, res{ result: Test{ID: "VALUE"}, wantErr: false, }, }, { "search with startswith case sensitive", mockDB(t). expectGetByQueryCaseSensitive("TESTTABLE", "test", "LIKE", "VALUE%"), args{ table: "TESTTABLE", searchQuery: TestSearchQuery{key: TestSearchKey_TEST, method: domain.SearchMethodStartsWith, value: "VALUE"}, }, res{ result: Test{ID: "VALUE"}, wantErr: false, }, }, { "search with contains case insensitive", mockDB(t). expectGetByQuery("TESTTABLE", "test", "LIKE", "%VALUE%"), args{ table: "TESTTABLE", searchQuery: TestSearchQuery{key: TestSearchKey_TEST, method: domain.SearchMethodContainsIgnoreCase, value: "VALUE"}, }, res{ result: Test{ID: "VALUE"}, wantErr: false, }, }, { "search with contains case sensitive", mockDB(t). expectGetByQueryCaseSensitive("TESTTABLE", "test", "LIKE", "%VALUE%"), args{ table: "TESTTABLE", searchQuery: TestSearchQuery{key: TestSearchKey_TEST, method: domain.SearchMethodContains, value: "VALUE"}, }, res{ result: Test{ID: "VALUE"}, wantErr: false, }, }, { "search expect not found err", mockDB(t). expectGetByQueryErr("TESTTABLE", "test", "LIKE", "%VALUE%", gorm.ErrRecordNotFound), args{ table: "TESTTABLE", searchQuery: TestSearchQuery{key: TestSearchKey_TEST, method: domain.SearchMethodContainsIgnoreCase, value: "VALUE"}, }, res{ result: Test{ID: "VALUE"}, wantErr: true, errFunc: zerrors.IsNotFound, }, }, { "search expect internal err", mockDB(t). expectGetByQueryErr("TESTTABLE", "test", "LIKE", "%VALUE%", gorm.ErrUnaddressable), args{ table: "TESTTABLE", searchQuery: TestSearchQuery{key: TestSearchKey_TEST, method: domain.SearchMethodContainsIgnoreCase, value: "VALUE"}, }, res{ result: Test{ID: "VALUE"}, wantErr: true, errFunc: zerrors.IsInternal, }, }, { "search with invalid column", mockDB(t). expectGetByQuery("TESTTABLE", "", "=", "VALUE"), args{ table: "TESTTABLE", searchQuery: TestSearchQuery{key: TestSearchKey_UNDEFINED, method: domain.SearchMethodEqualsIgnoreCase, value: "VALUE"}, }, res{ result: Test{ID: "VALUE"}, wantErr: true, errFunc: zerrors.IsErrorInvalidArgument, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { res := &Test{} getByQuery := PrepareGetByQuery(tt.args.table, tt.args.searchQuery) err := getByQuery(tt.db.db, res) if !tt.res.wantErr && err != nil { t.Errorf("got wrong err should be nil: %v ", err) } if tt.res.wantErr && !tt.res.errFunc(err) { t.Errorf("got wrong err: %v ", err) } if err := tt.db.mock.ExpectationsWereMet(); !tt.res.wantErr && err != nil { t.Errorf("there were unfulfilled expectations: %s", err) } tt.db.close() }) } } func TestPreparePut(t *testing.T) { type args struct { table string object *Test } type res struct { result Test wantErr bool errFunc func(err error) bool } tests := []struct { name string db *dbMock args args res res }{ { "ok", mockDB(t). expectBegin(nil). expectSave("TESTTABLE", Test{ID: "AggregateID", Test: "VALUE"}). expectCommit(nil), args{ table: "TESTTABLE", object: &Test{ID: "AggregateID", Test: "VALUE"}, }, res{ result: Test{ID: "VALUE"}, wantErr: false, }, }, { "db error", mockDB(t). expectBegin(nil). expectSaveErr("TESTTABLE", Test{ID: "AggregateID", Test: "VALUE"}, gorm.ErrUnaddressable). expectCommit(nil), args{ table: "TESTTABLE", object: &Test{ID: "AggregateID", Test: "VALUE"}, }, res{ result: Test{ID: "VALUE"}, wantErr: true, errFunc: zerrors.IsInternal, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { getPut := PrepareSave(tt.args.table) err := getPut(tt.db.db, tt.args.object) if !tt.res.wantErr && err != nil { t.Errorf("got wrong err should be nil: %v ", err) } if tt.res.wantErr && !tt.res.errFunc(err) { t.Errorf("got wrong err: %v ", err) } if err := tt.db.mock.ExpectationsWereMet(); !tt.res.wantErr && err != nil { t.Errorf("there were unfulfilled expectations: %s", err) } tt.db.close() }) } } func TestPrepareDelete(t *testing.T) { type args struct { table string key ColumnKey value string } type res struct { result Test wantErr bool errFunc func(err error) bool } tests := []struct { name string db *dbMock args args res res }{ { "delete", mockDB(t). expectBegin(nil). expectRemove("TESTTABLE", "id", "VALUE"). expectCommit(nil), args{ table: "TESTTABLE", key: TestSearchKey_ID, value: "VALUE", }, res{ result: Test{ID: "VALUE"}, wantErr: false, }, }, { "db error", mockDB(t). expectBegin(nil). expectRemoveErr("TESTTABLE", "id", "VALUE", gorm.ErrUnaddressable). expectCommit(nil), args{ table: "TESTTABLE", key: TestSearchKey_ID, value: "VALUE", }, res{ result: Test{ID: "VALUE"}, wantErr: true, errFunc: zerrors.IsInternal, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { getDelete := PrepareDeleteByKey(tt.args.table, tt.args.key, tt.args.value) err := getDelete(tt.db.db) if !tt.res.wantErr && err != nil { t.Errorf("got wrong err should be nil: %v ", err) } if tt.res.wantErr && !tt.res.errFunc(err) { t.Errorf("got wrong err: %v ", err) } if err := tt.db.mock.ExpectationsWereMet(); !tt.res.wantErr && err != nil { t.Errorf("there were unfulfilled expectations: %s", err) } tt.db.close() }) } } func TestPrepareDeleteByKeys(t *testing.T) { type args struct { table string keys []Key } type res struct { result Test wantErr bool errFunc func(err error) bool } tests := []struct { name string db *dbMock args args res res }{ { "delete single key", mockDB(t). expectBegin(nil). expectRemoveKeys("TESTTABLE", Key{Key: TestSearchKey_ID, Value: "VALUE"}). expectCommit(nil), args{ table: "TESTTABLE", keys: []Key{ {Key: TestSearchKey_ID, Value: "VALUE"}, }, }, res{ result: Test{ID: "VALUE"}, wantErr: false, }, }, { "delete multiple keys", mockDB(t). expectBegin(nil). expectRemoveKeys("TESTTABLE", Key{Key: TestSearchKey_ID, Value: "VALUE"}, Key{Key: TestSearchKey_TEST, Value: "VALUE2"}). expectCommit(nil), args{ table: "TESTTABLE", keys: []Key{ {Key: TestSearchKey_ID, Value: "VALUE"}, {Key: TestSearchKey_TEST, Value: "VALUE2"}, }, }, res{ result: Test{ID: "VALUE"}, wantErr: false, }, }, { "db error", mockDB(t). expectBegin(nil). expectRemoveErr("TESTTABLE", "id", "VALUE", gorm.ErrUnaddressable). expectCommit(nil), args{ table: "TESTTABLE", keys: []Key{ {Key: TestSearchKey_ID, Value: "VALUE"}, }, }, res{ result: Test{ID: "VALUE"}, wantErr: true, errFunc: zerrors.IsInternal, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { getDelete := PrepareDeleteByKeys(tt.args.table, tt.args.keys...) err := getDelete(tt.db.db) if !tt.res.wantErr && err != nil { t.Errorf("got wrong err should be nil: %v ", err) } if tt.res.wantErr && !tt.res.errFunc(err) { t.Errorf("got wrong err: %v ", err) } if err := tt.db.mock.ExpectationsWereMet(); !tt.res.wantErr && err != nil { t.Errorf("there were unfulfilled expectations: %s", err) } tt.db.close() }) } }