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 }