2021-06-01 10:51:35 +02:00
|
|
|
package webtest
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"net/http"
|
|
|
|
"net/http/httptest"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/gin-gonic/gin"
|
2021-09-29 14:30:17 +02:00
|
|
|
"go.uber.org/zap"
|
2021-06-01 10:51:35 +02:00
|
|
|
|
|
|
|
"dev.sum7.eu/genofire/golang-lib/database"
|
2021-06-25 12:22:19 +02:00
|
|
|
"dev.sum7.eu/genofire/golang-lib/mailer"
|
2021-06-01 10:51:35 +02:00
|
|
|
"dev.sum7.eu/genofire/golang-lib/web"
|
|
|
|
)
|
|
|
|
|
2021-06-01 15:30:05 +02:00
|
|
|
var (
|
2021-06-01 17:47:37 +02:00
|
|
|
// DBConnection - url to database on setting up default WebService for webtest
|
2022-09-20 18:53:41 +02:00
|
|
|
DBConnection = "postgresql://root:root@localhost:26257/defaultdb?sslmode=disable"
|
2021-06-01 15:30:05 +02:00
|
|
|
)
|
|
|
|
|
2021-07-14 13:57:23 +02:00
|
|
|
// Option to configure TestServer
|
|
|
|
type Option struct {
|
2021-07-19 17:59:08 +02:00
|
|
|
ModuleLoader web.ModuleRegisterFunc
|
2021-09-28 04:31:23 +02:00
|
|
|
Database bool
|
|
|
|
DBReRun bool
|
|
|
|
DBSetup func(db *database.Database)
|
|
|
|
Mailer bool
|
2021-09-29 14:33:35 +02:00
|
|
|
Logger *zap.Logger
|
|
|
|
}
|
|
|
|
|
|
|
|
func (option Option) log() *zap.Logger {
|
|
|
|
if option.Logger != nil {
|
|
|
|
return option.Logger
|
|
|
|
}
|
|
|
|
return zap.L()
|
2021-07-14 13:57:23 +02:00
|
|
|
}
|
|
|
|
|
2021-09-11 11:15:24 +02:00
|
|
|
// TestServer - to run it without listen an server
|
2021-09-07 13:29:25 +02:00
|
|
|
type TestServer struct {
|
2021-06-22 20:44:24 +02:00
|
|
|
DB *database.Database
|
2021-06-25 12:22:19 +02:00
|
|
|
Mails chan *mailer.TestingMail
|
|
|
|
Close func()
|
2021-06-01 10:51:35 +02:00
|
|
|
gin *gin.Engine
|
2021-07-19 17:59:08 +02:00
|
|
|
WS *web.Service
|
2021-06-01 10:51:35 +02:00
|
|
|
lastCookies []*http.Cookie
|
|
|
|
}
|
|
|
|
|
2021-06-01 17:47:37 +02:00
|
|
|
// Login Request format (maybe just internal usage)
|
2021-06-01 10:51:35 +02:00
|
|
|
type Login struct {
|
|
|
|
Username string `json:"username"`
|
|
|
|
Password string `json:"password"`
|
|
|
|
}
|
|
|
|
|
2021-06-01 17:47:37 +02:00
|
|
|
// New starts WebService for testing
|
2021-09-07 13:29:25 +02:00
|
|
|
func New(modules web.ModuleRegisterFunc) (*TestServer, error) {
|
2021-09-28 04:31:23 +02:00
|
|
|
return Option{ModuleLoader: modules}.New()
|
2021-07-14 12:29:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewWithDBSetup allows to reconfigure before ReRun the database - e.g. for adding Migration-Steps
|
2021-09-07 13:29:25 +02:00
|
|
|
func NewWithDBSetup(modules web.ModuleRegisterFunc, dbCall func(db *database.Database)) (*TestServer, error) {
|
2021-09-28 04:31:23 +02:00
|
|
|
return Option{
|
|
|
|
Database: true,
|
|
|
|
DBReRun: true,
|
2021-07-19 17:59:08 +02:00
|
|
|
DBSetup: dbCall,
|
|
|
|
ModuleLoader: modules,
|
2021-09-28 04:31:23 +02:00
|
|
|
}.New()
|
2021-07-14 13:57:23 +02:00
|
|
|
}
|
|
|
|
|
2021-09-28 04:31:23 +02:00
|
|
|
// New allows to configure WebService for testing
|
|
|
|
func (option Option) New() (*TestServer, error) {
|
2021-09-29 14:33:35 +02:00
|
|
|
log := option.log()
|
2021-06-01 10:51:35 +02:00
|
|
|
|
2021-09-28 04:31:23 +02:00
|
|
|
ws := &web.Service{}
|
2021-09-29 14:30:17 +02:00
|
|
|
ws.SetLog(log)
|
2021-09-28 04:31:23 +02:00
|
|
|
ws.Session.Name = "mysession"
|
|
|
|
ws.Session.Secret = "hidden"
|
2021-09-28 04:53:44 +02:00
|
|
|
|
2021-09-28 04:23:20 +02:00
|
|
|
ts := &TestServer{
|
2021-09-28 04:53:44 +02:00
|
|
|
WS: ws,
|
|
|
|
Close: func() {},
|
2021-06-01 10:51:35 +02:00
|
|
|
}
|
2021-09-28 04:53:44 +02:00
|
|
|
|
2021-09-28 04:31:23 +02:00
|
|
|
// db setup
|
|
|
|
if option.Database {
|
|
|
|
ts.DB = &database.Database{
|
|
|
|
Testdata: true,
|
|
|
|
Debug: false,
|
|
|
|
LogLevel: 0,
|
|
|
|
}
|
2022-09-20 18:53:41 +02:00
|
|
|
ts.DB.Connection.URI = DBConnection
|
2021-09-28 04:31:23 +02:00
|
|
|
if option.DBSetup != nil {
|
|
|
|
option.DBSetup(ts.DB)
|
|
|
|
}
|
|
|
|
var err error
|
|
|
|
if option.DBReRun {
|
|
|
|
err = ts.DB.ReRun()
|
|
|
|
} else {
|
|
|
|
err = ts.DB.Run()
|
|
|
|
}
|
|
|
|
if err != nil && err != database.ErrNothingToMigrate {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if ts.DB.DB == nil {
|
|
|
|
return nil, database.ErrNotConnected
|
|
|
|
}
|
|
|
|
ws.DB = ts.DB.DB
|
|
|
|
}
|
2021-06-01 10:51:35 +02:00
|
|
|
|
2021-09-28 04:23:20 +02:00
|
|
|
if option.Mailer {
|
2021-09-29 14:30:17 +02:00
|
|
|
mock, mail := mailer.NewFakeServer(log)
|
2021-09-28 04:23:20 +02:00
|
|
|
if err := mail.Setup(); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
ws.Mailer = mail
|
|
|
|
ts.Mails = mock.Mails
|
|
|
|
ts.Close = mock.Close
|
|
|
|
}
|
|
|
|
|
2021-09-28 04:53:44 +02:00
|
|
|
// api setup
|
|
|
|
|
|
|
|
gin.EnableJsonDecoderDisallowUnknownFields()
|
|
|
|
gin.SetMode(gin.TestMode)
|
|
|
|
|
2021-09-28 04:31:23 +02:00
|
|
|
ws.ModuleRegister(option.ModuleLoader)
|
|
|
|
|
2021-06-01 10:51:35 +02:00
|
|
|
r := gin.Default()
|
|
|
|
ws.LoadSession(r)
|
|
|
|
ws.Bind(r)
|
2021-09-28 04:23:20 +02:00
|
|
|
ts.gin = r
|
|
|
|
return ts, nil
|
2021-06-01 10:51:35 +02:00
|
|
|
}
|
2021-06-01 17:47:37 +02:00
|
|
|
|
2021-09-11 11:15:24 +02:00
|
|
|
// DatabaseForget to run a test without a database
|
2021-09-07 13:29:25 +02:00
|
|
|
func (s *TestServer) DatabaseForget() {
|
2021-07-19 17:59:08 +02:00
|
|
|
s.WS.DB = nil
|
2021-06-22 20:44:24 +02:00
|
|
|
s.DB = nil
|
2021-06-01 10:51:35 +02:00
|
|
|
}
|
2021-06-01 17:47:37 +02:00
|
|
|
|
|
|
|
// Request sends a request to webtest WebService
|
2021-09-07 13:29:25 +02:00
|
|
|
func (s *TestServer) Request(method, url string, body interface{}, expectCode int, jsonObj interface{}) error {
|
2021-06-01 10:51:35 +02:00
|
|
|
var jsonBody io.Reader
|
|
|
|
if body != nil {
|
|
|
|
if strBody, ok := body.(string); ok {
|
|
|
|
jsonBody = strings.NewReader(strBody)
|
|
|
|
} else {
|
|
|
|
jsonBodyArray, err := json.Marshal(body)
|
2021-06-28 12:14:20 +02:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-06-01 10:51:35 +02:00
|
|
|
jsonBody = bytes.NewBuffer(jsonBodyArray)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
req, err := http.NewRequest(method, url, jsonBody)
|
2021-06-28 12:14:20 +02:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-06-01 17:47:37 +02:00
|
|
|
if len(s.lastCookies) > 0 {
|
|
|
|
for _, c := range s.lastCookies {
|
2021-06-01 10:51:35 +02:00
|
|
|
req.AddCookie(c)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
w := httptest.NewRecorder()
|
2021-06-01 17:47:37 +02:00
|
|
|
s.gin.ServeHTTP(w, req)
|
2021-06-01 10:51:35 +02:00
|
|
|
|
|
|
|
// valid statusCode
|
|
|
|
if expectCode != w.Code {
|
2021-06-28 12:14:20 +02:00
|
|
|
return fmt.Errorf("wrong status code, body: %v", w.Body)
|
2021-06-01 10:51:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if jsonObj != nil {
|
|
|
|
// fetch JSON
|
|
|
|
err = json.NewDecoder(w.Body).Decode(jsonObj)
|
2021-06-28 12:14:20 +02:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-06-01 10:51:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
result := w.Result()
|
|
|
|
if result != nil {
|
|
|
|
cookies := result.Cookies()
|
|
|
|
if len(cookies) > 0 {
|
2021-06-01 17:47:37 +02:00
|
|
|
s.lastCookies = cookies
|
2021-06-01 10:51:35 +02:00
|
|
|
}
|
|
|
|
}
|
2021-06-28 12:14:20 +02:00
|
|
|
return nil
|
2021-06-01 10:51:35 +02:00
|
|
|
}
|
|
|
|
|
2021-06-01 17:49:13 +02:00
|
|
|
// Login to API by send request
|
2021-09-07 13:29:25 +02:00
|
|
|
func (s *TestServer) Login(login Login) error {
|
2021-06-01 10:51:35 +02:00
|
|
|
// POST: correct login
|
2021-06-28 12:14:20 +02:00
|
|
|
return s.Request(http.MethodPost, "/api/v1/auth/login", &login, http.StatusOK, nil)
|
2021-06-01 10:51:35 +02:00
|
|
|
}
|
|
|
|
|
2021-06-01 17:49:13 +02:00
|
|
|
// TestLogin to API by default login data
|
2021-09-07 13:29:25 +02:00
|
|
|
func (s *TestServer) TestLogin() error {
|
2021-06-28 12:14:20 +02:00
|
|
|
return s.Login(Login{
|
2021-06-01 10:51:35 +02:00
|
|
|
Username: "admin",
|
|
|
|
Password: "CHANGEME",
|
|
|
|
})
|
|
|
|
}
|