diff --git a/contracts/database/migration/migration.go b/contracts/database/migration/migration.go new file mode 100644 index 000000000..b7eb2eacb --- /dev/null +++ b/contracts/database/migration/migration.go @@ -0,0 +1,10 @@ +package migration + +const ( + DriverDefault = "default" + DriverSql = "sql" +) + +type Driver interface { + Create(name string) error +} diff --git a/contracts/database/schema/blueprint.go b/contracts/database/schema/blueprint.go new file mode 100644 index 000000000..f109f7cfd --- /dev/null +++ b/contracts/database/schema/blueprint.go @@ -0,0 +1,4 @@ +package schema + +type Blueprint interface { +} diff --git a/contracts/database/schema/schema.go b/contracts/database/schema/schema.go new file mode 100644 index 000000000..7abcc7417 --- /dev/null +++ b/contracts/database/schema/schema.go @@ -0,0 +1,27 @@ +package schema + +type Schema interface { + // Create a new table on the schema. + //Create(table string, callback func(table Blueprint)) + // Connection Get the connection for the schema. + Connection() Schema + // DropIfExists Drop a table from the schema if exists. + //DropIfExists(table string) + // Register migrations. + Register([]Migration) + // Sql Execute a sql directly. + Sql(callback func(table Blueprint)) + // Table Modify a table on the schema. + //Table(table string, callback func(table Blueprint)) +} + +type Migration interface { + // Signature Get the migration signature. + Signature() string + // Connection Get the connection for the migration. + Connection() string + // Up Run the migrations. + Up() + // Down Reverse the migrations. + Down() +} diff --git a/contracts/foundation/container.go b/contracts/foundation/container.go index cfacbd63e..bdb70988e 100644 --- a/contracts/foundation/container.go +++ b/contracts/foundation/container.go @@ -10,6 +10,7 @@ import ( "github.com/goravel/framework/contracts/console" "github.com/goravel/framework/contracts/crypt" "github.com/goravel/framework/contracts/database/orm" + "github.com/goravel/framework/contracts/database/schema" "github.com/goravel/framework/contracts/database/seeder" "github.com/goravel/framework/contracts/event" "github.com/goravel/framework/contracts/filesystem" @@ -70,6 +71,8 @@ type Container interface { MakeRoute() route.Route // MakeSchedule resolves the schedule instance. MakeSchedule() schedule.Schedule + // MakeSchema resolves the schema instance. + MakeSchema() schema.Schema // MakeSession resolves the session instance. MakeSession() session.Manager // MakeStorage resolves the storage instance. diff --git a/database/console/migrate_creator.go b/database/console/migrate_creator.go index e1b7f68d6..91eeafe04 100644 --- a/database/console/migrate_creator.go +++ b/database/console/migrate_creator.go @@ -7,6 +7,7 @@ import ( "github.com/goravel/framework/contracts/config" "github.com/goravel/framework/contracts/database/orm" + "github.com/goravel/framework/database/migration" "github.com/goravel/framework/support/carbon" "github.com/goravel/framework/support/file" ) @@ -22,7 +23,7 @@ func NewMigrateCreator(config config.Config) *MigrateCreator { } // Create a new migration -func (receiver MigrateCreator) Create(name string, table string, create bool) error { +func (receiver *MigrateCreator) Create(name string, table string, create bool) error { // First we will get the stub file for the migration, which serves as a type // of template for the migration. Once we have those we will populate the // various place-holders, save the file, and run the post create event. @@ -42,7 +43,7 @@ func (receiver MigrateCreator) Create(name string, table string, create bool) er } // getStub Get the migration stub file. -func (receiver MigrateCreator) getStub(table string, create bool) (string, string) { +func (receiver *MigrateCreator) getStub(table string, create bool) (string, string) { if table == "" { return "", "" } @@ -51,33 +52,33 @@ func (receiver MigrateCreator) getStub(table string, create bool) (string, strin switch orm.Driver(driver) { case orm.DriverPostgresql: if create { - return PostgresqlStubs{}.CreateUp(), PostgresqlStubs{}.CreateDown() + return migration.PostgresqlStubs{}.CreateUp(), migration.PostgresqlStubs{}.CreateDown() } - return PostgresqlStubs{}.UpdateUp(), PostgresqlStubs{}.UpdateDown() + return migration.PostgresqlStubs{}.UpdateUp(), migration.PostgresqlStubs{}.UpdateDown() case orm.DriverSqlite: if create { - return SqliteStubs{}.CreateUp(), SqliteStubs{}.CreateDown() + return migration.SqliteStubs{}.CreateUp(), migration.SqliteStubs{}.CreateDown() } - return SqliteStubs{}.UpdateUp(), SqliteStubs{}.UpdateDown() + return migration.SqliteStubs{}.UpdateUp(), migration.SqliteStubs{}.UpdateDown() case orm.DriverSqlserver: if create { - return SqlserverStubs{}.CreateUp(), SqlserverStubs{}.CreateDown() + return migration.SqlserverStubs{}.CreateUp(), migration.SqlserverStubs{}.CreateDown() } - return SqlserverStubs{}.UpdateUp(), SqlserverStubs{}.UpdateDown() + return migration.SqlserverStubs{}.UpdateUp(), migration.SqlserverStubs{}.UpdateDown() default: if create { - return MysqlStubs{}.CreateUp(), MysqlStubs{}.CreateDown() + return migration.MysqlStubs{}.CreateUp(), migration.MysqlStubs{}.CreateDown() } - return MysqlStubs{}.UpdateUp(), MysqlStubs{}.UpdateDown() + return migration.MysqlStubs{}.UpdateUp(), migration.MysqlStubs{}.UpdateDown() } } // populateStub Populate the place-holders in the migration stub. -func (receiver MigrateCreator) populateStub(stub string, table string) string { +func (receiver *MigrateCreator) populateStub(stub string, table string) string { stub = strings.ReplaceAll(stub, "DummyDatabaseCharset", receiver.config.GetString("database.connections."+receiver.config.GetString("database.default")+".charset")) if table != "" { @@ -88,7 +89,7 @@ func (receiver MigrateCreator) populateStub(stub string, table string) string { } // getPath Get the full path to the migration. -func (receiver MigrateCreator) getPath(name string, category string) string { +func (receiver *MigrateCreator) getPath(name string, category string) string { pwd, _ := os.Getwd() return fmt.Sprintf("%s/database/migrations/%s_%s.%s.sql", pwd, carbon.Now().ToShortDateTimeString(), name, category) diff --git a/database/console/migrate_make_command.go b/database/console/migrate_make_command.go index 52b45059e..0c014a018 100644 --- a/database/console/migrate_make_command.go +++ b/database/console/migrate_make_command.go @@ -2,10 +2,13 @@ package console import ( "errors" + "fmt" "github.com/goravel/framework/contracts/config" "github.com/goravel/framework/contracts/console" "github.com/goravel/framework/contracts/console/command" + contractsmigration "github.com/goravel/framework/contracts/database/migration" + "github.com/goravel/framework/database/migration" "github.com/goravel/framework/support/color" ) @@ -56,14 +59,20 @@ func (receiver *MigrateMakeCommand) Handle(ctx console.Context) error { } } - // We will attempt to guess the table name if this the migration has - // "create" in the name. This will allow us to provide a convenient way - // of creating migrations that create new tables for the application. - table, create := TableGuesser{}.Guess(name) + var migrationDriver contractsmigration.Driver + driver := receiver.config.GetString("database.migration.driver") + + switch driver { + case contractsmigration.DriverDefault: + migrationDriver = migration.NewDefaultDriver() + case contractsmigration.DriverSql: + migrationDriver = migration.NewSqlDriver(receiver.config) + default: + return fmt.Errorf("unsupported migration driver: %s", driver) + } // Write the migration file to disk. - migrateCreator := NewMigrateCreator(receiver.config) - if err := migrateCreator.Create(name, table, create); err != nil { + if err := migrationDriver.Create(name); err != nil { return err } diff --git a/database/console/migrate_make_command_test.go b/database/console/migrate_make_command_test.go index 9a2fce836..07e92452a 100644 --- a/database/console/migrate_make_command_test.go +++ b/database/console/migrate_make_command_test.go @@ -15,29 +15,83 @@ import ( ) func TestMigrateMakeCommand(t *testing.T) { + var ( + mockConfig *configmock.Config + mockContext *consolemocks.Context + ) + now := carbon.Now() - up := fmt.Sprintf("database/migrations/%s_%s.%s.sql", now.ToShortDateTimeString(), "create_users_table", "up") - down := fmt.Sprintf("database/migrations/%s_%s.%s.sql", now.ToShortDateTimeString(), "create_users_table", "down") - - mockConfig := &configmock.Config{} - mockConfig.On("GetString", "database.default").Return("mysql").Times(3) - mockConfig.On("GetString", "database.connections.mysql.driver").Return("mysql").Once() - mockConfig.On("GetString", "database.connections.mysql.charset").Return("utf8mb4").Twice() - - migrateMakeCommand := NewMigrateMakeCommand(mockConfig) - mockContext := &consolemocks.Context{} - mockContext.On("Argument", 0).Return("").Once() - mockContext.On("Ask", "Enter the migration name", mock.Anything).Return("", errors.New("the migration name cannot be empty")).Once() - err := migrateMakeCommand.Handle(mockContext) - assert.EqualError(t, err, "the migration name cannot be empty") - assert.False(t, file.Exists(up)) - assert.False(t, file.Exists(down)) - - mockContext.On("Argument", 0).Return("create_users_table").Once() - assert.Nil(t, migrateMakeCommand.Handle(mockContext)) - assert.True(t, file.Exists(up)) - assert.True(t, file.Exists(down)) - assert.Nil(t, file.Remove("database")) + carbon.SetTestNow(now) + + beforeEach := func() { + mockConfig = &configmock.Config{} + mockContext = &consolemocks.Context{} + } + + afterEach := func() { + mockConfig.AssertExpectations(t) + mockContext.AssertExpectations(t) + } + + tests := []struct { + name string + setup func() + assert func() + expectErr error + }{ + { + name: "the migration name is empty", + setup: func() { + mockContext.On("Argument", 0).Return("").Once() + mockContext.On("Ask", "Enter the migration name", mock.Anything).Return("", errors.New("the migration name cannot be empty")).Once() + }, + assert: func() {}, + expectErr: errors.New("the migration name cannot be empty"), + }, + { + name: "default driver", + setup: func() { + mockConfig.On("GetString", "database.migration.driver").Return("default").Once() + mockContext.On("Argument", 0).Return("create_users_table").Once() + }, + assert: func() { + migration := fmt.Sprintf("database/migrations/%s_%s.go", now.ToShortDateTimeString(), "create_users_table") + + assert.True(t, file.Exists(migration)) + }, + }, + { + name: "sql driver", + setup: func() { + mockConfig.On("GetString", "database.migration.driver").Return("sql").Once() + mockConfig.On("GetString", "database.default").Return("mysql").Times(3) + mockConfig.On("GetString", "database.connections.mysql.driver").Return("mysql").Once() + mockConfig.On("GetString", "database.connections.mysql.charset").Return("utf8mb4").Twice() + mockContext.On("Argument", 0).Return("create_users_table").Once() + }, + assert: func() { + up := fmt.Sprintf("database/migrations/%s_%s.%s.sql", now.ToShortDateTimeString(), "create_users_table", "up") + down := fmt.Sprintf("database/migrations/%s_%s.%s.sql", now.ToShortDateTimeString(), "create_users_table", "down") - mockConfig.AssertExpectations(t) + assert.True(t, file.Exists(up)) + assert.True(t, file.Exists(down)) + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + beforeEach() + test.setup() + + migrateMakeCommand := NewMigrateMakeCommand(mockConfig) + err := migrateMakeCommand.Handle(mockContext) + assert.Equal(t, test.expectErr, err) + + test.assert() + afterEach() + }) + } + + assert.Nil(t, file.Remove("database")) } diff --git a/database/migration/default_driver.go b/database/migration/default_driver.go new file mode 100644 index 000000000..a63f6be0c --- /dev/null +++ b/database/migration/default_driver.go @@ -0,0 +1,73 @@ +package migration + +import ( + "fmt" + "os" + "path/filepath" + "strings" + + "github.com/goravel/framework/support/carbon" + "github.com/goravel/framework/support/file" + "github.com/goravel/framework/support/str" +) + +type DefaultDriver struct { +} + +func NewDefaultDriver() *DefaultDriver { + return &DefaultDriver{} +} + +func (r *DefaultDriver) Create(name string) error { + // We will attempt to guess the table name if this the migration has + // "create" in the name. This will allow us to provide a convenient way + // of creating migrations that create new tables for the application. + table, create := TableGuesser{}.Guess(name) + + // First we will get the stub file for the migration, which serves as a type + // of template for the migration. Once we have those we will populate the + // various place-holders, save the file, and run the post create event. + stub := r.getStub(table, create) + + // Prepend timestamp to the file name. + fileName := r.getFileName(name) + + // Create the up.sql file. + if err := file.Create(r.getPath(fileName), r.populateStub(stub, fileName)); err != nil { + return err + } + + return nil +} + +// getStub Get the migration stub file. +func (r *DefaultDriver) getStub(table string, create bool) string { + if table == "" { + return Stubs{}.Empty() + } + + if create { + return Stubs{}.Create() + } + + return Stubs{}.Update() +} + +// populateStub Populate the place-holders in the migration stub. +func (r *DefaultDriver) populateStub(stub, fileName string) string { + stub = strings.ReplaceAll(stub, "DummyMigration", str.Of(fileName).Prepend("m_").Studly().String()) + stub = strings.ReplaceAll(stub, "DummyName", fileName) + + return stub +} + +// getPath Get the full path to the migration. +func (r *DefaultDriver) getPath(name string) string { + pwd, _ := os.Getwd() + + return filepath.Join(pwd, "database", "migrations", name+".go") +} + +func (r *DefaultDriver) getFileName(name string) string { + return fmt.Sprintf("%s_%s", carbon.Now().ToShortDateTimeString(), name) +} diff --git a/database/migration/default_driver_test.go b/database/migration/default_driver_test.go new file mode 100644 index 000000000..5905409e8 --- /dev/null +++ b/database/migration/default_driver_test.go @@ -0,0 +1,127 @@ +package migration + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/goravel/framework/support/carbon" + "github.com/goravel/framework/support/file" +) + +func TestDefaultDriverCreate(t *testing.T) { + now := carbon.FromDateTime(2024, 8, 17, 21, 45, 1) + carbon.SetTestNow(now) + pwd, _ := os.Getwd() + path := filepath.Join(pwd, "database", "migrations") + + tests := []struct { + name string + argument string + file string + content string + }{ + { + name: "empty template", + argument: "fix_users_table", + file: "20240817214501_fix_users_table", + content: `package migrations + +type M20240817214501FixUsersTable struct { +} + +// Signature The unique signature for the migration. +func (r *M20240817214501FixUsersTable) Signature() string { + return "20240817214501_fix_users_table" +} + +// Connection The database connection that should be used by the migration. +func (r *M20240817214501FixUsersTable) Connection() string { + return "" +} + +// Up Run the migrations. +func (r *M20240817214501FixUsersTable) Up() { + +} + +// Down Reverse the migrations. +func (r *M20240817214501FixUsersTable) Down() { + +}`, + }, + { + name: "create template", + argument: "create_users_table", + file: "20240817214501_create_users_table", + content: `package migrations + +type M20240817214501CreateUsersTable struct { +} + +// Signature The unique signature for the migration. +func (r *M20240817214501CreateUsersTable) Signature() string { + return "20240817214501_create_users_table" +} + +// Connection The database connection that should be used by the migration. +func (r *M20240817214501CreateUsersTable) Connection() string { + return "" +} + +// Up Run the migrations. +func (r *M20240817214501CreateUsersTable) Up() { + +} + +// Down Reverse the migrations. +func (r *M20240817214501CreateUsersTable) Down() { + +}`, + }, + { + name: "update template", + argument: "add_name_to_users_table", + file: "20240817214501_add_name_to_users_table", + content: `package migrations + +type M20240817214501AddNameToUsersTable struct { +} + +// Signature The unique signature for the migration. +func (r *M20240817214501AddNameToUsersTable) Signature() string { + return "20240817214501_add_name_to_users_table" +} + +// Connection The database connection that should be used by the migration. +func (r *M20240817214501AddNameToUsersTable) Connection() string { + return "" +} + +// Up Run the migrations. +func (r *M20240817214501AddNameToUsersTable) Up() { + +} + +// Down Reverse the migrations. +func (r *M20240817214501AddNameToUsersTable) Down() { + +}`, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + driver := &DefaultDriver{} + + assert.Nil(t, driver.Create(test.argument)) + assert.Equal(t, test.file, driver.getFileName(test.argument)) + assert.True(t, file.Exists(filepath.Join(path, test.file+".go"))) + assert.True(t, file.Contain(driver.getPath(driver.getFileName(test.argument)), test.content)) + }) + } + + assert.Nil(t, file.Remove("database")) +} diff --git a/database/migration/schema.go b/database/migration/schema.go new file mode 100644 index 000000000..e2ebb779e --- /dev/null +++ b/database/migration/schema.go @@ -0,0 +1,31 @@ +package migration + +import ( + "github.com/goravel/framework/contracts/database/schema" +) + +type Schema struct{} + +func NewSchema() *Schema { + return &Schema{} +} + +func (r *Schema) Create(table string, callback func(table schema.Blueprint)) error { + //TODO implement me + panic("implement me") +} + +func (r *Schema) Connection() schema.Schema { + //TODO implement me + panic("implement me") +} + +func (r *Schema) Register(migrations []schema.Migration) { + //TODO implement me + panic("implement me") +} + +func (r *Schema) Table(table string, callback func(table schema.Blueprint)) error { + //TODO implement me + panic("implement me") +} diff --git a/database/migration/sql_driver.go b/database/migration/sql_driver.go new file mode 100644 index 000000000..d5568bf2b --- /dev/null +++ b/database/migration/sql_driver.go @@ -0,0 +1,100 @@ +package migration + +import ( + "fmt" + "os" + "path/filepath" + "strings" + + "github.com/goravel/framework/contracts/config" + "github.com/goravel/framework/contracts/database/orm" + "github.com/goravel/framework/support/carbon" + "github.com/goravel/framework/support/file" +) + +type SqlDriver struct { + config config.Config +} + +func NewSqlDriver(config config.Config) *SqlDriver { + return &SqlDriver{ + config: config, + } +} + +func (r *SqlDriver) Create(name string) error { + // We will attempt to guess the table name if this the migration has + // "create" in the name. This will allow us to provide a convenient way + // of creating migrations that create new tables for the application. + table, create := TableGuesser{}.Guess(name) + + // First we will get the stub file for the migration, which serves as a type + // of template for the migration. Once we have those we will populate the + // various place-holders, save the file, and run the post create event. + upStub, downStub := r.getStub(table, create) + + // Create the up.sql file. + if err := file.Create(r.getPath(name, "up"), r.populateStub(upStub, table)); err != nil { + return err + } + + // Create the down.sql file. + if err := file.Create(r.getPath(name, "down"), r.populateStub(downStub, table)); err != nil { + return err + } + + return nil +} + +// getStub Get the migration stub file. +func (r *SqlDriver) getStub(table string, create bool) (string, string) { + if table == "" { + return "", "" + } + + driver := r.config.GetString("database.connections." + r.config.GetString("database.default") + ".driver") + switch orm.Driver(driver) { + case orm.DriverPostgresql: + if create { + return PostgresqlStubs{}.CreateUp(), PostgresqlStubs{}.CreateDown() + } + + return PostgresqlStubs{}.UpdateUp(), PostgresqlStubs{}.UpdateDown() + case orm.DriverSqlite: + if create { + return SqliteStubs{}.CreateUp(), SqliteStubs{}.CreateDown() + } + + return SqliteStubs{}.UpdateUp(), SqliteStubs{}.UpdateDown() + case orm.DriverSqlserver: + if create { + return SqlserverStubs{}.CreateUp(), SqlserverStubs{}.CreateDown() + } + + return SqlserverStubs{}.UpdateUp(), SqlserverStubs{}.UpdateDown() + default: + if create { + return MysqlStubs{}.CreateUp(), MysqlStubs{}.CreateDown() + } + + return MysqlStubs{}.UpdateUp(), MysqlStubs{}.UpdateDown() + } +} + +// populateStub Populate the place-holders in the migration stub. +func (r *SqlDriver) populateStub(stub string, table string) string { + stub = strings.ReplaceAll(stub, "DummyDatabaseCharset", r.config.GetString("database.connections."+r.config.GetString("database.default")+".charset")) + + if table != "" { + stub = strings.ReplaceAll(stub, "DummyTable", table) + } + + return stub +} + +// getPath Get the full path to the migration. +func (r *SqlDriver) getPath(name string, category string) string { + pwd, _ := os.Getwd() + + return filepath.Join(pwd, "database", "migrations", fmt.Sprintf("%s_%s.%s.sql", carbon.Now().ToShortDateTimeString(), name, category)) +} diff --git a/database/migration/sql_driver_test.go b/database/migration/sql_driver_test.go new file mode 100644 index 000000000..c1812047c --- /dev/null +++ b/database/migration/sql_driver_test.go @@ -0,0 +1,209 @@ +package migration + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + + mocksconfig "github.com/goravel/framework/mocks/config" + "github.com/goravel/framework/support/carbon" + "github.com/goravel/framework/support/file" +) + +func TestSqlDriverCreate(t *testing.T) { + var mockConfig *mocksconfig.Config + now := carbon.FromDateTime(2024, 8, 17, 21, 45, 1) + carbon.SetTestNow(now) + pwd, _ := os.Getwd() + path := filepath.Join(pwd, "database", "migrations") + + beforeEach := func() { + mockConfig = &mocksconfig.Config{} + } + + afterEach := func() { + mockConfig.AssertExpectations(t) + } + + tests := []struct { + name string + argument string + upContent string + downContent string + setup func() + }{ + { + name: "mysql - empty template", + argument: "fix_users_table", + upContent: ``, + downContent: ``, + setup: func() { + mockConfig.EXPECT().GetString("database.default").Return("mysql").Twice() + mockConfig.EXPECT().GetString("database.connections.mysql.charset").Return("utf8mb4").Twice() + }, + }, + { + name: "mysql - create template", + argument: "create_users_table", + upContent: `CREATE TABLE users ( + id bigint(20) unsigned NOT NULL AUTO_INCREMENT, + created_at datetime(3) NOT NULL, + updated_at datetime(3) NOT NULL, + PRIMARY KEY (id), + KEY idx_users_created_at (created_at), + KEY idx_users_updated_at (updated_at) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; +`, + downContent: `DROP TABLE IF EXISTS users;`, + setup: func() { + mockConfig.EXPECT().GetString("database.default").Return("mysql").Times(3) + mockConfig.EXPECT().GetString("database.connections.mysql.driver").Return("mysql").Once() + mockConfig.EXPECT().GetString("database.connections.mysql.charset").Return("utf8mb4").Twice() + }, + }, + { + name: "mysql - update template", + argument: "add_name_to_users_table", + upContent: `ALTER TABLE users ADD column varchar(255) COMMENT ''`, + downContent: `ALTER TABLE users DROP COLUMN column;`, + setup: func() { + mockConfig.EXPECT().GetString("database.default").Return("mysql").Times(3) + mockConfig.EXPECT().GetString("database.connections.mysql.driver").Return("mysql").Once() + mockConfig.EXPECT().GetString("database.connections.mysql.charset").Return("utf8mb4").Twice() + }, + }, + { + name: "postgres - empty template", + argument: "fix_users_table", + upContent: ``, + downContent: ``, + setup: func() { + mockConfig.EXPECT().GetString("database.default").Return("postgresql").Twice() + mockConfig.EXPECT().GetString("database.connections.postgresql.charset").Return("utf8mb4").Twice() + }, + }, + { + name: "postgres - create template", + argument: "create_users_table", + upContent: `CREATE TABLE users ( + id SERIAL PRIMARY KEY NOT NULL, + created_at timestamp NOT NULL, + updated_at timestamp NOT NULL +); +`, + downContent: `DROP TABLE IF EXISTS users;`, + setup: func() { + mockConfig.EXPECT().GetString("database.default").Return("postgresql").Times(3) + mockConfig.EXPECT().GetString("database.connections.postgresql.driver").Return("postgresql").Once() + mockConfig.EXPECT().GetString("database.connections.postgresql.charset").Return("utf8mb4").Twice() + }, + }, + { + name: "postgres - update template", + argument: "add_name_to_users_table", + upContent: `ALTER TABLE users ADD column varchar(255) NOT NULL;`, + downContent: `ALTER TABLE users DROP COLUMN column;`, + setup: func() { + mockConfig.EXPECT().GetString("database.default").Return("postgresql").Times(3) + mockConfig.EXPECT().GetString("database.connections.postgresql.driver").Return("postgresql").Once() + mockConfig.EXPECT().GetString("database.connections.postgresql.charset").Return("utf8mb4").Twice() + }, + }, + { + name: "sqlite - empty template", + argument: "fix_users_table", + upContent: ``, + downContent: ``, + setup: func() { + mockConfig.EXPECT().GetString("database.default").Return("sqlite").Twice() + mockConfig.EXPECT().GetString("database.connections.sqlite.charset").Return("utf8mb4").Twice() + }, + }, + { + name: "sqlite - create template", + argument: "create_users_table", + upContent: `CREATE TABLE users ( + id integer PRIMARY KEY AUTOINCREMENT NOT NULL, + created_at datetime NOT NULL, + updated_at datetime NOT NULL +); +`, + downContent: `DROP TABLE IF EXISTS users;`, + setup: func() { + mockConfig.EXPECT().GetString("database.default").Return("sqlite").Times(3) + mockConfig.EXPECT().GetString("database.connections.sqlite.driver").Return("sqlite").Once() + mockConfig.EXPECT().GetString("database.connections.sqlite.charset").Return("utf8mb4").Twice() + }, + }, + { + name: "sqlite - update template", + argument: "add_name_to_users_table", + upContent: `ALTER TABLE users ADD column text;`, + downContent: `ALTER TABLE users DROP COLUMN column;`, + setup: func() { + mockConfig.EXPECT().GetString("database.default").Return("sqlite").Times(3) + mockConfig.EXPECT().GetString("database.connections.sqlite.driver").Return("sqlite").Once() + mockConfig.EXPECT().GetString("database.connections.sqlite.charset").Return("utf8mb4").Twice() + }, + }, + { + name: "sqlserver - empty template", + argument: "fix_users_table", + upContent: ``, + downContent: ``, + setup: func() { + mockConfig.EXPECT().GetString("database.default").Return("sqlserver").Twice() + mockConfig.EXPECT().GetString("database.connections.sqlserver.charset").Return("utf8mb4").Twice() + }, + }, + { + name: "sqlserver - create template", + argument: "create_users_table", + upContent: `CREATE TABLE users ( + id bigint NOT NULL IDENTITY(1,1), + created_at datetime NOT NULL, + updated_at datetime NOT NULL, + PRIMARY KEY (id) +); +`, + downContent: `DROP TABLE IF EXISTS users;`, + setup: func() { + mockConfig.EXPECT().GetString("database.default").Return("sqlserver").Times(3) + mockConfig.EXPECT().GetString("database.connections.sqlserver.driver").Return("sqlserver").Once() + mockConfig.EXPECT().GetString("database.connections.sqlserver.charset").Return("utf8mb4").Twice() + }, + }, + { + name: "sqlserver - update template", + argument: "add_name_to_users_table", + upContent: `ALTER TABLE users ADD column varchar(255);`, + downContent: `ALTER TABLE users DROP COLUMN column;`, + setup: func() { + mockConfig.EXPECT().GetString("database.default").Return("sqlserver").Times(3) + mockConfig.EXPECT().GetString("database.connections.sqlserver.driver").Return("sqlserver").Once() + mockConfig.EXPECT().GetString("database.connections.sqlserver.charset").Return("utf8mb4").Twice() + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + beforeEach() + test.setup() + + driver := &SqlDriver{config: mockConfig} + + assert.Nil(t, driver.Create(test.argument)) + assert.True(t, file.Exists(filepath.Join(path, "20240817214501_"+test.argument+".up.sql"))) + assert.True(t, file.Exists(filepath.Join(path, "20240817214501_"+test.argument+".down.sql"))) + assert.True(t, file.Contain(driver.getPath(test.argument, "up"), test.upContent)) + assert.True(t, file.Contain(driver.getPath(test.argument, "down"), test.downContent)) + + afterEach() + }) + } + + assert.Nil(t, file.Remove("database")) +} diff --git a/database/console/migrate_stubs.go b/database/migration/stubs.go similarity index 65% rename from database/console/migrate_stubs.go rename to database/migration/stubs.go index 97b9829da..19ec7b38d 100644 --- a/database/console/migrate_stubs.go +++ b/database/migration/stubs.go @@ -1,4 +1,93 @@ -package console +package migration + +type Stubs struct { +} + +func (receiver Stubs) Empty() string { + return `package migrations + +type DummyMigration struct { +} + +// Signature The unique signature for the migration. +func (r *DummyMigration) Signature() string { + return "DummyName" +} + +// Connection The database connection that should be used by the migration. +func (r *DummyMigration) Connection() string { + return "" +} + +// Up Run the migrations. +func (r *DummyMigration) Up() { + +} + +// Down Reverse the migrations. +func (r *DummyMigration) Down() { + +} +` +} + +// TODO add the facades.Schema().Create() method +func (receiver Stubs) Create() string { + return `package migrations + +type DummyMigration struct { +} + +// Signature The unique signature for the migration. +func (r *DummyMigration) Signature() string { + return "DummyName" +} + +// Connection The database connection that should be used by the migration. +func (r *DummyMigration) Connection() string { + return "" +} + +// Up Run the migrations. +func (r *DummyMigration) Up() { + +} + +// Down Reverse the migrations. +func (r *DummyMigration) Down() { + +} +` +} + +// TODO add the facades.Schema().Table() method +func (receiver Stubs) Update() string { + return `package migrations + +type DummyMigration struct { +} + +// Signature The unique signature for the migration. +func (r *DummyMigration) Signature() string { + return "DummyName" +} + +// Connection The database connection that should be used by the migration. +func (r *DummyMigration) Connection() string { + return "" +} + +// Up Run the migrations. +func (r *DummyMigration) Up() { + +} + +// Down Reverse the migrations. +func (r *DummyMigration) Down() { + +} +` +} type MysqlStubs struct { } diff --git a/database/console/table_guesser.go b/database/migration/table_guesser.go similarity index 97% rename from database/console/table_guesser.go rename to database/migration/table_guesser.go index ae6356ab5..d24f04cee 100644 --- a/database/console/table_guesser.go +++ b/database/migration/table_guesser.go @@ -1,4 +1,4 @@ -package console +package migration import ( "regexp" diff --git a/database/console/table_guesser_test.go b/database/migration/table_guesser_test.go similarity index 95% rename from database/console/table_guesser_test.go rename to database/migration/table_guesser_test.go index 60662da9a..5a16c10b0 100644 --- a/database/console/table_guesser_test.go +++ b/database/migration/table_guesser_test.go @@ -1,4 +1,4 @@ -package console +package migration import ( "testing" diff --git a/database/service_provider.go b/database/service_provider.go index 315f57f41..c76d415ee 100644 --- a/database/service_provider.go +++ b/database/service_provider.go @@ -7,9 +7,11 @@ import ( consolecontract "github.com/goravel/framework/contracts/console" "github.com/goravel/framework/contracts/foundation" "github.com/goravel/framework/database/console" + "github.com/goravel/framework/database/migration" ) const BindingOrm = "goravel.orm" +const BindingSchema = "goravel.schema" const BindingSeeder = "goravel.seeder" type ServiceProvider struct { @@ -27,6 +29,9 @@ func (database *ServiceProvider) Register(app foundation.Application) { return orm, nil }) + app.Singleton(BindingSchema, func(app foundation.Application) (any, error) { + return migration.NewSchema(), nil + }) app.Singleton(BindingSeeder, func(app foundation.Application) (any, error) { return NewSeederFacade(), nil }) diff --git a/facades/schema.go b/facades/schema.go new file mode 100644 index 000000000..a1b43afc4 --- /dev/null +++ b/facades/schema.go @@ -0,0 +1,9 @@ +package facades + +import ( + "github.com/goravel/framework/contracts/database/schema" +) + +func Schema() schema.Schema { + return App().MakeSchema() +} diff --git a/foundation/container.go b/foundation/container.go index 9d026ef88..fc5d9a88b 100644 --- a/foundation/container.go +++ b/foundation/container.go @@ -16,6 +16,7 @@ import ( consolecontract "github.com/goravel/framework/contracts/console" cryptcontract "github.com/goravel/framework/contracts/crypt" ormcontract "github.com/goravel/framework/contracts/database/orm" + schemacontract "github.com/goravel/framework/contracts/database/schema" seerdercontract "github.com/goravel/framework/contracts/database/seeder" eventcontract "github.com/goravel/framework/contracts/event" filesystemcontract "github.com/goravel/framework/contracts/filesystem" @@ -255,6 +256,16 @@ func (c *Container) MakeSchedule() schedulecontract.Schedule { return instance.(schedulecontract.Schedule) } +func (c *Container) MakeSchema() schemacontract.Schema { + instance, err := c.Make(database.BindingSchema) + if err != nil { + color.Red().Println(err) + return nil + } + + return instance.(schemacontract.Schema) +} + func (c *Container) MakeSession() sessioncontract.Manager { instance, err := c.Make(session.Binding) if err != nil { diff --git a/mocks/database/migration/Driver.go b/mocks/database/migration/Driver.go new file mode 100644 index 000000000..e5c4802d2 --- /dev/null +++ b/mocks/database/migration/Driver.go @@ -0,0 +1,78 @@ +// Code generated by mockery. DO NOT EDIT. + +package migration + +import mock "github.com/stretchr/testify/mock" + +// Driver is an autogenerated mock type for the Driver type +type Driver struct { + mock.Mock +} + +type Driver_Expecter struct { + mock *mock.Mock +} + +func (_m *Driver) EXPECT() *Driver_Expecter { + return &Driver_Expecter{mock: &_m.Mock} +} + +// Create provides a mock function with given fields: name +func (_m *Driver) Create(name string) error { + ret := _m.Called(name) + + if len(ret) == 0 { + panic("no return value specified for Create") + } + + var r0 error + if rf, ok := ret.Get(0).(func(string) error); ok { + r0 = rf(name) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Driver_Create_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Create' +type Driver_Create_Call struct { + *mock.Call +} + +// Create is a helper method to define mock.On call +// - name string +func (_e *Driver_Expecter) Create(name interface{}) *Driver_Create_Call { + return &Driver_Create_Call{Call: _e.mock.On("Create", name)} +} + +func (_c *Driver_Create_Call) Run(run func(name string)) *Driver_Create_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string)) + }) + return _c +} + +func (_c *Driver_Create_Call) Return(_a0 error) *Driver_Create_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Driver_Create_Call) RunAndReturn(run func(string) error) *Driver_Create_Call { + _c.Call.Return(run) + return _c +} + +// NewDriver creates a new instance of Driver. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewDriver(t interface { + mock.TestingT + Cleanup(func()) +}) *Driver { + mock := &Driver{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/mocks/database/schema/Blueprint.go b/mocks/database/schema/Blueprint.go new file mode 100644 index 000000000..db6732232 --- /dev/null +++ b/mocks/database/schema/Blueprint.go @@ -0,0 +1,32 @@ +// Code generated by mockery. DO NOT EDIT. + +package schema + +import mock "github.com/stretchr/testify/mock" + +// Blueprint is an autogenerated mock type for the Blueprint type +type Blueprint struct { + mock.Mock +} + +type Blueprint_Expecter struct { + mock *mock.Mock +} + +func (_m *Blueprint) EXPECT() *Blueprint_Expecter { + return &Blueprint_Expecter{mock: &_m.Mock} +} + +// NewBlueprint creates a new instance of Blueprint. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewBlueprint(t interface { + mock.TestingT + Cleanup(func()) +}) *Blueprint { + mock := &Blueprint{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/mocks/database/schema/Migration.go b/mocks/database/schema/Migration.go new file mode 100644 index 000000000..4600f5e1a --- /dev/null +++ b/mocks/database/schema/Migration.go @@ -0,0 +1,186 @@ +// Code generated by mockery. DO NOT EDIT. + +package schema + +import mock "github.com/stretchr/testify/mock" + +// Migration is an autogenerated mock type for the Migration type +type Migration struct { + mock.Mock +} + +type Migration_Expecter struct { + mock *mock.Mock +} + +func (_m *Migration) EXPECT() *Migration_Expecter { + return &Migration_Expecter{mock: &_m.Mock} +} + +// Connection provides a mock function with given fields: +func (_m *Migration) Connection() string { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Connection") + } + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + return r0 +} + +// Migration_Connection_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Connection' +type Migration_Connection_Call struct { + *mock.Call +} + +// Connection is a helper method to define mock.On call +func (_e *Migration_Expecter) Connection() *Migration_Connection_Call { + return &Migration_Connection_Call{Call: _e.mock.On("Connection")} +} + +func (_c *Migration_Connection_Call) Run(run func()) *Migration_Connection_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Migration_Connection_Call) Return(_a0 string) *Migration_Connection_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Migration_Connection_Call) RunAndReturn(run func() string) *Migration_Connection_Call { + _c.Call.Return(run) + return _c +} + +// Down provides a mock function with given fields: +func (_m *Migration) Down() { + _m.Called() +} + +// Migration_Down_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Down' +type Migration_Down_Call struct { + *mock.Call +} + +// Down is a helper method to define mock.On call +func (_e *Migration_Expecter) Down() *Migration_Down_Call { + return &Migration_Down_Call{Call: _e.mock.On("Down")} +} + +func (_c *Migration_Down_Call) Run(run func()) *Migration_Down_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Migration_Down_Call) Return() *Migration_Down_Call { + _c.Call.Return() + return _c +} + +func (_c *Migration_Down_Call) RunAndReturn(run func()) *Migration_Down_Call { + _c.Call.Return(run) + return _c +} + +// Signature provides a mock function with given fields: +func (_m *Migration) Signature() string { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Signature") + } + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + return r0 +} + +// Migration_Signature_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Signature' +type Migration_Signature_Call struct { + *mock.Call +} + +// Signature is a helper method to define mock.On call +func (_e *Migration_Expecter) Signature() *Migration_Signature_Call { + return &Migration_Signature_Call{Call: _e.mock.On("Signature")} +} + +func (_c *Migration_Signature_Call) Run(run func()) *Migration_Signature_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Migration_Signature_Call) Return(_a0 string) *Migration_Signature_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Migration_Signature_Call) RunAndReturn(run func() string) *Migration_Signature_Call { + _c.Call.Return(run) + return _c +} + +// Up provides a mock function with given fields: +func (_m *Migration) Up() { + _m.Called() +} + +// Migration_Up_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Up' +type Migration_Up_Call struct { + *mock.Call +} + +// Up is a helper method to define mock.On call +func (_e *Migration_Expecter) Up() *Migration_Up_Call { + return &Migration_Up_Call{Call: _e.mock.On("Up")} +} + +func (_c *Migration_Up_Call) Run(run func()) *Migration_Up_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Migration_Up_Call) Return() *Migration_Up_Call { + _c.Call.Return() + return _c +} + +func (_c *Migration_Up_Call) RunAndReturn(run func()) *Migration_Up_Call { + _c.Call.Return(run) + return _c +} + +// NewMigration creates a new instance of Migration. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewMigration(t interface { + mock.TestingT + Cleanup(func()) +}) *Migration { + mock := &Migration{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/mocks/database/schema/Schema.go b/mocks/database/schema/Schema.go new file mode 100644 index 000000000..1177044dd --- /dev/null +++ b/mocks/database/schema/Schema.go @@ -0,0 +1,148 @@ +// Code generated by mockery. DO NOT EDIT. + +package schema + +import ( + schema "github.com/goravel/framework/contracts/database/schema" + mock "github.com/stretchr/testify/mock" +) + +// Schema is an autogenerated mock type for the Schema type +type Schema struct { + mock.Mock +} + +type Schema_Expecter struct { + mock *mock.Mock +} + +func (_m *Schema) EXPECT() *Schema_Expecter { + return &Schema_Expecter{mock: &_m.Mock} +} + +// Connection provides a mock function with given fields: +func (_m *Schema) Connection() schema.Schema { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Connection") + } + + var r0 schema.Schema + if rf, ok := ret.Get(0).(func() schema.Schema); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(schema.Schema) + } + } + + return r0 +} + +// Schema_Connection_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Connection' +type Schema_Connection_Call struct { + *mock.Call +} + +// Connection is a helper method to define mock.On call +func (_e *Schema_Expecter) Connection() *Schema_Connection_Call { + return &Schema_Connection_Call{Call: _e.mock.On("Connection")} +} + +func (_c *Schema_Connection_Call) Run(run func()) *Schema_Connection_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Schema_Connection_Call) Return(_a0 schema.Schema) *Schema_Connection_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Schema_Connection_Call) RunAndReturn(run func() schema.Schema) *Schema_Connection_Call { + _c.Call.Return(run) + return _c +} + +// Register provides a mock function with given fields: _a0 +func (_m *Schema) Register(_a0 []schema.Migration) { + _m.Called(_a0) +} + +// Schema_Register_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Register' +type Schema_Register_Call struct { + *mock.Call +} + +// Register is a helper method to define mock.On call +// - _a0 []schema.Migration +func (_e *Schema_Expecter) Register(_a0 interface{}) *Schema_Register_Call { + return &Schema_Register_Call{Call: _e.mock.On("Register", _a0)} +} + +func (_c *Schema_Register_Call) Run(run func(_a0 []schema.Migration)) *Schema_Register_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].([]schema.Migration)) + }) + return _c +} + +func (_c *Schema_Register_Call) Return() *Schema_Register_Call { + _c.Call.Return() + return _c +} + +func (_c *Schema_Register_Call) RunAndReturn(run func([]schema.Migration)) *Schema_Register_Call { + _c.Call.Return(run) + return _c +} + +// Sql provides a mock function with given fields: callback +func (_m *Schema) Sql(callback func(schema.Blueprint)) { + _m.Called(callback) +} + +// Schema_Sql_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Sql' +type Schema_Sql_Call struct { + *mock.Call +} + +// Sql is a helper method to define mock.On call +// - callback func(schema.Blueprint) +func (_e *Schema_Expecter) Sql(callback interface{}) *Schema_Sql_Call { + return &Schema_Sql_Call{Call: _e.mock.On("Sql", callback)} +} + +func (_c *Schema_Sql_Call) Run(run func(callback func(schema.Blueprint))) *Schema_Sql_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(func(schema.Blueprint))) + }) + return _c +} + +func (_c *Schema_Sql_Call) Return() *Schema_Sql_Call { + _c.Call.Return() + return _c +} + +func (_c *Schema_Sql_Call) RunAndReturn(run func(func(schema.Blueprint))) *Schema_Sql_Call { + _c.Call.Return(run) + return _c +} + +// NewSchema creates a new instance of Schema. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewSchema(t interface { + mock.TestingT + Cleanup(func()) +}) *Schema { + mock := &Schema{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/mocks/foundation/Application.go b/mocks/foundation/Application.go index 712d0c328..98433c35b 100644 --- a/mocks/foundation/Application.go +++ b/mocks/foundation/Application.go @@ -42,6 +42,8 @@ import ( schedule "github.com/goravel/framework/contracts/schedule" + schema "github.com/goravel/framework/contracts/database/schema" + seeder "github.com/goravel/framework/contracts/database/seeder" session "github.com/goravel/framework/contracts/session" @@ -1527,6 +1529,53 @@ func (_c *Application_MakeSchedule_Call) RunAndReturn(run func() schedule.Schedu return _c } +// MakeSchema provides a mock function with given fields: +func (_m *Application) MakeSchema() schema.Schema { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for MakeSchema") + } + + var r0 schema.Schema + if rf, ok := ret.Get(0).(func() schema.Schema); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(schema.Schema) + } + } + + return r0 +} + +// Application_MakeSchema_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'MakeSchema' +type Application_MakeSchema_Call struct { + *mock.Call +} + +// MakeSchema is a helper method to define mock.On call +func (_e *Application_Expecter) MakeSchema() *Application_MakeSchema_Call { + return &Application_MakeSchema_Call{Call: _e.mock.On("MakeSchema")} +} + +func (_c *Application_MakeSchema_Call) Run(run func()) *Application_MakeSchema_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Application_MakeSchema_Call) Return(_a0 schema.Schema) *Application_MakeSchema_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Application_MakeSchema_Call) RunAndReturn(run func() schema.Schema) *Application_MakeSchema_Call { + _c.Call.Return(run) + return _c +} + // MakeSeeder provides a mock function with given fields: func (_m *Application) MakeSeeder() seeder.Facade { ret := _m.Called() diff --git a/mocks/foundation/Container.go b/mocks/foundation/Container.go index 965e925f2..8576639b5 100644 --- a/mocks/foundation/Container.go +++ b/mocks/foundation/Container.go @@ -42,6 +42,8 @@ import ( schedule "github.com/goravel/framework/contracts/schedule" + schema "github.com/goravel/framework/contracts/database/schema" + seeder "github.com/goravel/framework/contracts/database/seeder" session "github.com/goravel/framework/contracts/session" @@ -1027,6 +1029,53 @@ func (_c *Container_MakeSchedule_Call) RunAndReturn(run func() schedule.Schedule return _c } +// MakeSchema provides a mock function with given fields: +func (_m *Container) MakeSchema() schema.Schema { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for MakeSchema") + } + + var r0 schema.Schema + if rf, ok := ret.Get(0).(func() schema.Schema); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(schema.Schema) + } + } + + return r0 +} + +// Container_MakeSchema_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'MakeSchema' +type Container_MakeSchema_Call struct { + *mock.Call +} + +// MakeSchema is a helper method to define mock.On call +func (_e *Container_Expecter) MakeSchema() *Container_MakeSchema_Call { + return &Container_MakeSchema_Call{Call: _e.mock.On("MakeSchema")} +} + +func (_c *Container_MakeSchema_Call) Run(run func()) *Container_MakeSchema_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Container_MakeSchema_Call) Return(_a0 schema.Schema) *Container_MakeSchema_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Container_MakeSchema_Call) RunAndReturn(run func() schema.Schema) *Container_MakeSchema_Call { + _c.Call.Return(run) + return _c +} + // MakeSeeder provides a mock function with given fields: func (_m *Container) MakeSeeder() seeder.Facade { ret := _m.Called()