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