github.com/dkishere/pop/v6@v6.103.1/pop_test.go (about)

     1  package pop
     2  
     3  import (
     4  	stdlog "log"
     5  	"os"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/gobuffalo/nulls"
    10  	"github.com/dkishere/pop/v6/logging"
    11  	"github.com/gobuffalo/validate/v3"
    12  	"github.com/gobuffalo/validate/v3/validators"
    13  	"github.com/gofrs/uuid"
    14  	"github.com/stretchr/testify/suite"
    15  )
    16  
    17  var PDB *Connection
    18  
    19  type PostgreSQLSuite struct {
    20  	suite.Suite
    21  }
    22  
    23  type MySQLSuite struct {
    24  	suite.Suite
    25  }
    26  
    27  type SQLiteSuite struct {
    28  	suite.Suite
    29  }
    30  
    31  type CockroachSuite struct {
    32  	suite.Suite
    33  }
    34  
    35  func TestSpecificSuites(t *testing.T) {
    36  	switch os.Getenv("SODA_DIALECT") {
    37  	case "postgres":
    38  		suite.Run(t, &PostgreSQLSuite{})
    39  	case "mysql", "mysql_travis":
    40  		suite.Run(t, &MySQLSuite{})
    41  	case "sqlite":
    42  		suite.Run(t, &SQLiteSuite{})
    43  	case "cockroach":
    44  		suite.Run(t, &CockroachSuite{})
    45  	}
    46  }
    47  
    48  func init() {
    49  	Debug = false
    50  	AddLookupPaths("./")
    51  
    52  	dialect := os.Getenv("SODA_DIALECT")
    53  
    54  	if dialect == "" {
    55  		log(logging.Info, "Skipping integration tests")
    56  		return
    57  	}
    58  
    59  	if err := LoadConfigFile(); err != nil {
    60  		stdlog.Panic(err)
    61  	}
    62  
    63  	var err error
    64  	log(logging.Info, "Run test with dialect %v", dialect)
    65  	PDB, err = Connect(dialect)
    66  	if err != nil {
    67  		stdlog.Panic(err)
    68  	}
    69  }
    70  
    71  func transaction(fn func(tx *Connection)) {
    72  	err := PDB.Rollback(func(tx *Connection) {
    73  		fn(tx)
    74  	})
    75  	if err != nil {
    76  		stdlog.Fatal(err)
    77  	}
    78  }
    79  
    80  func ts(s string) string {
    81  	return PDB.Dialect.TranslateSQL(s)
    82  }
    83  
    84  type Client struct {
    85  	ClientID string `db:"id"`
    86  }
    87  
    88  func (c Client) TableName() string {
    89  	return "clients"
    90  }
    91  
    92  type User struct {
    93  	ID           int           `db:"id"`
    94  	UserName     string        `db:"user_name"`
    95  	Email        string        `db:"email"`
    96  	Name         nulls.String  `db:"name"`
    97  	Alive        nulls.Bool    `db:"alive"`
    98  	CreatedAt    time.Time     `db:"created_at"`
    99  	UpdatedAt    time.Time     `db:"updated_at"`
   100  	BirthDate    nulls.Time    `db:"birth_date"`
   101  	Bio          nulls.String  `db:"bio"`
   102  	Price        nulls.Float64 `db:"price"`
   103  	FullName     nulls.String  `db:"full_name" select:"name as full_name"`
   104  	Books        Books         `has_many:"books" order_by:"title asc"`
   105  	FavoriteSong Song          `has_one:"song" fk_id:"u_id"`
   106  	Houses       Addresses     `many_to_many:"users_addresses"`
   107  }
   108  
   109  // Validate gets run every time you call a "Validate*" (ValidateAndSave, ValidateAndCreate, ValidateAndUpdate) method.
   110  // This method is not required and may be deleted.
   111  func (u *User) Validate(tx *Connection) (*validate.Errors, error) {
   112  	return validate.Validate(
   113  		&validators.StringIsPresent{Field: u.Name.String, Name: "Name"},
   114  	), nil
   115  }
   116  
   117  type Users []User
   118  
   119  type UserAttribute struct {
   120  	ID       int    `db:"id"`
   121  	UserName string `db:"user_name"`
   122  	NickName string `db:"nick_name"`
   123  
   124  	User User `json:"user" belongs_to:"user" fk_id:"UserName" primary_id:"UserName"`
   125  }
   126  
   127  type Book struct {
   128  	ID          int       `db:"id"`
   129  	Title       string    `db:"title"`
   130  	Isbn        string    `db:"isbn"`
   131  	UserID      nulls.Int `db:"user_id"`
   132  	User        User      `belongs_to:"user"`
   133  	Description string    `db:"description"`
   134  	Writers     Writers   `has_many:"writers"`
   135  	TaxiID      nulls.Int `db:"taxi_id"`
   136  	Taxi        Taxi      `belongs_to:"taxi"`
   137  	CreatedAt   time.Time `db:"created_at"`
   138  	UpdatedAt   time.Time `db:"updated_at"`
   139  }
   140  
   141  type Taxi struct {
   142  	ID          int       `db:"id"`
   143  	Model       string    `db:"model"`
   144  	UserID      nulls.Int `db:"user_id"`
   145  	AddressID   nulls.Int `db:"address_id"`
   146  	Driver      *User     `belongs_to:"user" fk_id:"user_id"`
   147  	Address     Address   `belongs_to:"address"`
   148  	ToAddressID *int      `db:"to_address_id"`
   149  	ToAddress   *Address  `belongs_to:"address"`
   150  	CreatedAt   time.Time `db:"created_at"`
   151  	UpdatedAt   time.Time `db:"updated_at"`
   152  }
   153  
   154  type Taxis []Taxi
   155  
   156  // Validate gets run every time you call a "Validate*" (ValidateAndSave, ValidateAndCreate, ValidateAndUpdate) method.
   157  // This method is not required and may be deleted.
   158  func (b *Book) Validate(tx *Connection) (*validate.Errors, error) {
   159  	// Execute another query to test if Validate causes eager creation to fail
   160  	if err := tx.All(&Taxis{}); err != nil {
   161  		return nil, err
   162  	}
   163  	return validate.Validate(
   164  		&validators.StringIsPresent{Field: b.Description, Name: "Description"},
   165  	), nil
   166  }
   167  
   168  type Books []Book
   169  
   170  type Writer struct {
   171  	ID        int       `db:"id"`
   172  	Name      string    `db:"name"`
   173  	Addresses Addresses `has_many:"addresses"`
   174  	Friends   []Friend  `has_many:"friends"`
   175  	BookID    int       `db:"book_id"`
   176  	Book      Book      `belongs_to:"book"`
   177  	CreatedAt time.Time `db:"created_at"`
   178  	UpdatedAt time.Time `db:"updated_at"`
   179  }
   180  
   181  type Writers []Writer
   182  
   183  type Address struct {
   184  	ID          int       `db:"id"`
   185  	Street      string    `db:"street"`
   186  	WriterID    int       `db:"writer_id"`
   187  	HouseNumber int       `db:"house_number"`
   188  	CreatedAt   time.Time `db:"created_at"`
   189  	UpdatedAt   time.Time `db:"updated_at"`
   190  	TaxisToHere Taxis     `has_many:"taxis" fk_id:"to_address_id" order_by:"created_at asc"`
   191  }
   192  
   193  type Addresses []Address
   194  
   195  type UsersAddress struct {
   196  	ID        int       `db:"id"`
   197  	UserID    int       `db:"user_id"`
   198  	AddressID int       `db:"address_id"`
   199  	CreatedAt time.Time `db:"created_at"`
   200  	UpdatedAt time.Time `db:"updated_at"`
   201  }
   202  
   203  type UsersAddressQuery struct {
   204  	ID        int       `db:"id"`
   205  	UserID    int       `db:"user_id"`
   206  	AddressID int       `db:"address_id"`
   207  	CreatedAt time.Time `db:"created_at"`
   208  	UpdatedAt time.Time `db:"updated_at"`
   209  
   210  	UserName  *string `db:"name" json:"user_name"`
   211  	UserEmail *string `db:"email" json:"user_email"`
   212  }
   213  
   214  func (UsersAddressQuery) TableName() string {
   215  	return "users_addresses"
   216  }
   217  
   218  type Friend struct {
   219  	ID        int       `db:"id"`
   220  	FirstName string    `db:"first_name"`
   221  	WriterID  int       `db:"writer_id"`
   222  	LastName  string    `db:"last_name"`
   223  	CreatedAt time.Time `db:"created_at"`
   224  	UpdatedAt time.Time `db:"updated_at"`
   225  }
   226  
   227  func (Friend) TableName() string {
   228  	return "good_friends"
   229  }
   230  
   231  type Family struct {
   232  	ID        int       `db:"id"`
   233  	FirstName string    `db:"first_name"`
   234  	LastName  string    `db:"last_name"`
   235  	CreatedAt time.Time `db:"created_at"`
   236  	UpdatedAt time.Time `db:"updated_at"`
   237  }
   238  
   239  func (Family) TableName() string {
   240  	// schema.table_name
   241  	return "family.members"
   242  }
   243  
   244  type Enemy struct {
   245  	A string
   246  }
   247  
   248  type Song struct {
   249  	ID           uuid.UUID `db:"id"`
   250  	Title        string    `db:"title"`
   251  	UserID       int       `db:"u_id"`
   252  	CreatedAt    time.Time `json:"created_at" db:"created_at"`
   253  	UpdatedAt    time.Time `json:"updated_at" db:"updated_at"`
   254  	ComposedByID int       `json:"composed_by_id" db:"composed_by_id"`
   255  	ComposedBy   Composer  `belongs_to:"composer"`
   256  }
   257  
   258  type Composer struct {
   259  	ID        int       `db:"id"`
   260  	Name      string    `db:"name"`
   261  	CreatedAt time.Time `db:"created_at"`
   262  	UpdatedAt time.Time `db:"updated_at"`
   263  }
   264  
   265  type Course struct {
   266  	ID        uuid.UUID `json:"id" db:"id"`
   267  	CreatedAt time.Time `json:"created_at" db:"created_at"`
   268  	UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
   269  }
   270  
   271  type CourseCode struct {
   272  	ID        uuid.UUID `json:"id" db:"id"`
   273  	CreatedAt time.Time `json:"created_at" db:"created_at"`
   274  	UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
   275  	CourseID  uuid.UUID `json:"course_id" db:"course_id"`
   276  	Course    Course    `json:"-" belongs_to:"course"`
   277  	// Course Course `belongs_to:"course"`
   278  }
   279  
   280  type ValidatableCar struct {
   281  	ID        int64     `db:"id"`
   282  	Name      string    `db:"name"`
   283  	CreatedAt time.Time `json:"created_at" db:"created_at"`
   284  	UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
   285  }
   286  
   287  var validationLogs []string
   288  
   289  func (v *ValidatableCar) Validate(tx *Connection) (*validate.Errors, error) {
   290  	validationLogs = append(validationLogs, "Validate")
   291  	verrs := validate.Validate(&validators.StringIsPresent{Field: v.Name, Name: "Name"})
   292  	return verrs, nil
   293  }
   294  
   295  func (v *ValidatableCar) ValidateSave(tx *Connection) (*validate.Errors, error) {
   296  	validationLogs = append(validationLogs, "ValidateSave")
   297  	return nil, nil
   298  }
   299  
   300  func (v *ValidatableCar) ValidateUpdate(tx *Connection) (*validate.Errors, error) {
   301  	validationLogs = append(validationLogs, "ValidateUpdate")
   302  	return nil, nil
   303  }
   304  
   305  func (v *ValidatableCar) ValidateCreate(tx *Connection) (*validate.Errors, error) {
   306  	validationLogs = append(validationLogs, "ValidateCreate")
   307  	return nil, nil
   308  }
   309  
   310  type NotValidatableCar struct {
   311  	ID        int       `db:"id"`
   312  	Name      string    `db:"name"`
   313  	CreatedAt time.Time `json:"created_at" db:"created_at"`
   314  	UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
   315  }
   316  
   317  type CallbacksUser struct {
   318  	ID        int       `db:"id"`
   319  	BeforeS   string    `db:"before_s"`
   320  	BeforeC   string    `db:"before_c"`
   321  	BeforeU   string    `db:"before_u"`
   322  	BeforeD   string    `db:"before_d"`
   323  	BeforeV   string    `db:"before_v"`
   324  	AfterS    string    `db:"after_s"`
   325  	AfterC    string    `db:"after_c"`
   326  	AfterU    string    `db:"after_u"`
   327  	AfterD    string    `db:"after_d"`
   328  	AfterF    string    `db:"after_f"`
   329  	CreatedAt time.Time `json:"created_at" db:"created_at"`
   330  	UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
   331  }
   332  
   333  type CallbacksUsers []CallbacksUser
   334  
   335  func (u *CallbacksUser) BeforeSave(tx *Connection) error {
   336  	u.BeforeS = "BeforeSave"
   337  	return nil
   338  }
   339  
   340  func (u *CallbacksUser) BeforeUpdate(tx *Connection) error {
   341  	u.BeforeU = "BeforeUpdate"
   342  	return nil
   343  }
   344  
   345  func (u *CallbacksUser) BeforeCreate(tx *Connection) error {
   346  	u.BeforeC = "BeforeCreate"
   347  	return nil
   348  }
   349  
   350  func (u *CallbacksUser) BeforeDestroy(tx *Connection) error {
   351  	u.BeforeD = "BeforeDestroy"
   352  	return nil
   353  }
   354  
   355  func (u *CallbacksUser) BeforeValidate(tx *Connection) error {
   356  	u.BeforeV = "BeforeValidate"
   357  	return nil
   358  }
   359  
   360  func (u *CallbacksUser) AfterSave(tx *Connection) error {
   361  	u.AfterS = "AfterSave"
   362  	return nil
   363  }
   364  
   365  func (u *CallbacksUser) AfterUpdate(tx *Connection) error {
   366  	u.AfterU = "AfterUpdate"
   367  	return nil
   368  }
   369  
   370  func (u *CallbacksUser) AfterCreate(tx *Connection) error {
   371  	u.AfterC = "AfterCreate"
   372  	return nil
   373  }
   374  
   375  func (u *CallbacksUser) AfterDestroy(tx *Connection) error {
   376  	u.AfterD = "AfterDestroy"
   377  	return nil
   378  }
   379  
   380  func (u *CallbacksUser) AfterFind(tx *Connection) error {
   381  	u.AfterF = "AfterFind"
   382  	return nil
   383  }
   384  
   385  type Label struct {
   386  	ID string `db:"id"`
   387  }
   388  
   389  type SingleID struct {
   390  	ID int `db:"id"`
   391  }
   392  
   393  type Body struct {
   394  	ID   int   `json:"id" db:"id"`
   395  	Head *Head `json:"head" has_one:"head"`
   396  }
   397  
   398  type Head struct {
   399  	ID     int   `json:"id,omitempty" db:"id"`
   400  	BodyID int   `json:"-" db:"body_id"`
   401  	Body   *Body `json:"body,omitempty" belongs_to:"body"`
   402  }
   403  
   404  type HeadPtr struct {
   405  	ID     int   `json:"id,omitempty" db:"id"`
   406  	BodyID *int  `json:"-" db:"body_id"`
   407  	Body   *Body `json:"body,omitempty" belongs_to:"body"`
   408  }
   409  
   410  type Student struct {
   411  	ID        uuid.UUID `json:"id" db:"id"`
   412  	CreatedAt time.Time `json:"created_at" db:"created_at"`
   413  	UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
   414  }
   415  
   416  // https://github.com/dkishere/pop/issues/302
   417  type Parent struct {
   418  	ID        uuid.UUID  `json:"id" db:"id"`
   419  	CreatedAt time.Time  `json:"created_at" db:"created_at"`
   420  	UpdatedAt time.Time  `json:"updated_at" db:"updated_at"`
   421  	Students  []*Student `many_to_many:"parents_students"`
   422  }
   423  
   424  type CrookedColour struct {
   425  	ID        int       `db:"pk"`
   426  	Name      string    `db:"name"`
   427  	CreatedAt time.Time `db:"created_at"`
   428  	UpdatedAt time.Time `db:"updated_at"`
   429  }
   430  
   431  type CrookedSong struct {
   432  	ID        string    `db:"name"`
   433  	CreatedAt time.Time `db:"created_at"`
   434  	UpdatedAt time.Time `db:"updated_at"`
   435  }
   436  
   437  type NonStandardID struct {
   438  	ID          int    `db:"pk"`
   439  	OutfacingID string `db:"id"`
   440  }