golang-lib/web/webtest/main.go

205 lines
4.3 KiB
Go
Raw Normal View History

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
2023-10-23 21:40:10 +02:00
"codeberg.org/genofire/golang-lib/database"
"codeberg.org/genofire/golang-lib/mailer"
"codeberg.org/genofire/golang-lib/web"
2021-06-01 10:51:35 +02:00
)
var (
2021-06-01 17:47:37 +02:00
// DBConnection - url to database on setting up default WebService for webtest
DBConnection = "postgresql://root:root@localhost:26257/defaultdb?sslmode=disable"
)
// Option to configure TestServer
type Option struct {
ModuleLoader web.ModuleRegisterFunc
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-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 {
DB *database.Database
Mails chan *mailer.TestingMail
Close func()
2021-06-01 10:51:35 +02:00
gin *gin.Engine
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) {
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) {
return Option{
Database: true,
DBReRun: true,
DBSetup: dbCall,
ModuleLoader: modules,
}.New()
}
// 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
ws := &web.Service{}
2021-09-29 14:30:17 +02:00
ws.SetLog(log)
ws.Session.Name = "mysession"
ws.Session.Secret = "hidden"
ts := &TestServer{
WS: ws,
Close: func() {},
2021-06-01 10:51:35 +02:00
}
// db setup
if option.Database {
ts.DB = &database.Database{
Testdata: true,
Debug: false,
LogLevel: 0,
}
ts.DB.Connection.URI = DBConnection
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
if option.Mailer {
2021-09-29 14:30:17 +02:00
mock, mail := mailer.NewFakeServer(log)
if err := mail.Setup(); err != nil {
return nil, err
}
ws.Mailer = mail
ts.Mails = mock.Mails
ts.Close = mock.Close
}
// api setup
gin.EnableJsonDecoderDisallowUnknownFields()
gin.SetMode(gin.TestMode)
ws.ModuleRegister(option.ModuleLoader)
2021-06-01 10:51:35 +02:00
r := gin.Default()
ws.LoadSession(r)
ws.Bind(r)
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() {
s.WS.DB = nil
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",
})
}