[add] migrate widgets.table api

This commit is contained in:
Max 2023-03-25 17:46:57 +08:00
parent 5de550781c
commit f1f58cc99f
4 changed files with 460 additions and 162 deletions

View file

@ -9,7 +9,7 @@ COMMIT := $(shell git log | head -n 1 | awk '{print substr($$2, 0, 12)}')
NOW := $(shell date +"%FT%T%z")
# ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
TESTFOLDER := $(shell $(GO) list ./... | grep -E 'api|model|flow|script|fs|i18n|connector|query|plugin|cert|crypto|task|schedule|runtime|helper|utils|widget|importer|store|widgets/app|widgets/login|widgets/table' | grep -vE 'examples|tests*|config|widgets')
TESTFOLDER := $(shell $(GO) list ./... | grep -E 'api|model|flow|script|fs|i18n|connector|query|plugin|cert|crypto|task|schedule|runtime|helper|utils|widget|importer|store' | grep -vE 'examples|tests*|config|widgets')
TESTTAGS ?= ""
# TESTWIDGETS := $(shell $(GO) list ./widgets/...)

225
test/request.go Normal file
View file

@ -0,0 +1,225 @@
package test
import (
"bytes"
"context"
"fmt"
"io"
"net/http"
"time"
jsoniter "github.com/json-iterator/go"
"github.com/yaoapp/gou/model"
"github.com/yaoapp/gou/process"
"github.com/yaoapp/gou/session"
"github.com/yaoapp/yao/helper"
)
// Request request
type Request struct {
host string
port int
route string
method string
data map[string]interface{}
params map[string]string
headers map[string]string
}
// Response response
type Response struct {
status int
body []byte
}
// NewRequest create a new request
func NewRequest(port int) *Request {
return &Request{
host: "127.0.0.1",
port: port,
data: map[string]interface{}{},
params: map[string]string{},
headers: map[string]string{},
}
}
// Token set token
func (r *Request) Token(token string) *Request {
r.headers["Authorization"] = fmt.Sprintf("Bearer %s", token)
return r
}
// Header set header
func (r *Request) Header(key string, value string) *Request {
r.headers[key] = value
return r
}
// Param set saram
func (r *Request) Param(key string, value string) *Request {
r.params[key] = value
return r
}
// Data set data
func (r *Request) Data(data map[string]interface{}) *Request {
r.data = data
return r
}
// Route set the route
func (r *Request) Route(route string) *Request {
r.route = route
return r
}
// Get request
func (r *Request) Get() (*Response, error) {
r.method = "GET"
return r.Send()
}
// Post request
func (r *Request) Post() (*Response, error) {
r.method = "POST"
return r.Send()
}
// Send request
func (r *Request) Send() (*Response, error) {
client := http.Client{}
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
// set body
var data io.Reader = nil
if len(r.data) > 0 {
content, err := jsoniter.Marshal(r.data)
if err != nil {
return nil, err
}
data = bytes.NewBuffer(content)
}
url := fmt.Sprintf("http://%s:%d%s", r.host, r.port, r.route)
req, err := http.NewRequestWithContext(ctx, r.method, url, data)
if err != nil {
return nil, err
}
// Set header
for key, value := range r.headers {
req.Header.Add(key, value)
}
if _, has := r.headers["Content-Type"]; !has {
req.Header.Add("Content-Type", "application/json")
}
// Set Parms
if len(r.params) > 0 {
q := req.URL.Query()
for key, value := range r.params {
q.Add(key, value)
}
req.URL.RawQuery = q.Encode()
}
// Send Request
res, err := client.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
// response body
body, err := io.ReadAll(res.Body)
if err != nil {
return nil, err
}
p := &Response{
status: res.StatusCode,
body: body,
}
return p, nil
}
// Map to map
func (p *Response) Map() (map[string]interface{}, error) {
v := map[string]interface{}{}
err := jsoniter.Unmarshal(p.body, &v)
if err != nil {
return nil, err
}
return v, nil
}
// Int to int
func (p *Response) Int() (int, error) {
v := 0
err := jsoniter.Unmarshal(p.body, &v)
if err != nil {
return 0, err
}
return v, nil
}
// Status get the reaponse status
func (p *Response) Status() int {
return p.status
}
// Body get the reaponse body
func (p *Response) Body() string {
return string(p.body)
}
// To cast to custom sturct
func (p *Response) To(v interface{}) error {
err := jsoniter.Unmarshal(p.body, v)
if err != nil {
return err
}
return nil
}
// AutoLogin auto login
func AutoLogin(id int) (map[string]interface{}, error) {
user := model.Select("admin.user")
row, err := user.Find(id, model.QueryParam(model.QueryParam{Select: []interface{}{"id", "name", "type", "email", "mobile", "extra", "status"}}))
if err != nil {
return nil, err
}
expiresAt := time.Now().Unix() + 3600
sid := session.ID()
token := helper.JwtMake(id, map[string]interface{}{}, map[string]interface{}{
"expires_at": expiresAt,
"sid": sid,
"issuer": "admin",
})
session.Global().Expire(time.Duration(token.ExpiresAt)*time.Second).ID(sid).Set("user_id", id)
session.Global().ID(sid).Set("user", row)
session.Global().ID(sid).Set("issuer", "admin")
p, err := process.Of("yao.app.menu")
if err != nil {
return nil, err
}
menus, err := p.Exec()
if err != nil {
return nil, err
}
return map[string]interface{}{
"expires_at": token.ExpiresAt,
"token": token.Token,
"user": row,
"menus": menus,
}, nil
}

View file

@ -3,21 +3,29 @@ package test
import (
"fmt"
"os"
"strings"
"testing"
"time"
"github.com/gin-gonic/gin"
"github.com/yaoapp/gou/api"
"github.com/yaoapp/gou/application"
"github.com/yaoapp/gou/model"
"github.com/yaoapp/gou/query"
"github.com/yaoapp/gou/query/gou"
v8 "github.com/yaoapp/gou/runtime/v8"
"github.com/yaoapp/gou/server/http"
"github.com/yaoapp/kun/exception"
"github.com/yaoapp/xun/capsule"
"github.com/yaoapp/yao/config"
"github.com/yaoapp/yao/fs"
"github.com/yaoapp/yao/helper"
"github.com/yaoapp/yao/runtime"
"github.com/yaoapp/yao/share"
)
var testServer *http.Server = nil
// Prepare test environment
func Prepare(t *testing.T, cfg config.Config) {
root := os.Getenv("YAO_TEST_APPLICATION")
@ -42,7 +50,7 @@ func Prepare(t *testing.T, cfg config.Config) {
dbconnect(t, cfg)
load(t, cfg)
start(t, cfg)
startRuntime(t, cfg)
}
// Clean the test environment
@ -51,6 +59,49 @@ func Clean() {
runtime.Stop()
}
// Start the test server
func Start(t *testing.T, guards map[string]gin.HandlerFunc, cfg config.Config) {
var err error
option := http.Option{Port: 0, Root: "/", Timeout: 2 * time.Second}
gin.SetMode(gin.ReleaseMode)
router := gin.New()
api.SetGuards(guards)
api.SetRoutes(router, "api")
testServer = http.New(router, option)
go func() { err = testServer.Start() }()
<-testServer.Event()
if err != nil {
t.Fatal(err)
}
}
// Stop the test server
func Stop() {
if testServer != nil {
testServer.Stop()
<-testServer.Event()
}
dbclose()
runtime.Stop()
}
// Port Get the test server port
func Port(t *testing.T) int {
if testServer == nil {
t.Fatal(fmt.Errorf("server not started"))
}
port, err := testServer.Port()
if err != nil {
t.Fatal(err)
}
return port
}
func dbclose() {
if capsule.Global != nil {
capsule.Global.Connections.Range(func(key, value any) bool {
@ -76,7 +127,7 @@ func dbconnect(t *testing.T, cfg config.Config) {
}
func start(t *testing.T, cfg config.Config) {
func startRuntime(t *testing.T, cfg config.Config) {
err := runtime.Start(cfg)
if err != nil {
t.Fatal(err)
@ -145,3 +196,18 @@ func loadQuery(t *testing.T, cfg config.Config) {
AESKey: cfg.DB.AESKey,
})
}
// GuardBearerJWT test guard
func GuardBearerJWT(c *gin.Context) {
tokenString := c.Request.Header.Get("Authorization")
tokenString = strings.TrimSpace(strings.TrimPrefix(tokenString, "Bearer "))
if tokenString == "" {
c.JSON(403, gin.H{"code": 403, "message": "No permission"})
c.Abort()
return
}
claims := helper.JwtValidate(tokenString)
c.Set("__sid", claims.SID)
}

View file

@ -1,8 +1,15 @@
package table
import (
"fmt"
"net/url"
"testing"
"github.com/gin-gonic/gin"
"github.com/yaoapp/yao/widgets/test"
"github.com/stretchr/testify/assert"
"github.com/yaoapp/kun/any"
"github.com/yaoapp/yao/config"
"github.com/yaoapp/yao/test"
)
var guards = map[string]gin.HandlerFunc{
@ -10,194 +17,194 @@ var guards = map[string]gin.HandlerFunc{
"widget-table": Guard,
}
// func TestAPISetting(t *testing.T) {
func TestAPISetting(t *testing.T) {
// gtest.Prepare(t, config.Conf)
// defer gtest.Clean()
port := start(t)
defer stop()
// prepare(t)
// clear(t)
// testData(t)
req := test.NewRequest(port).Route("/api/__yao/table/pet/setting")
res, err := req.Get()
if err != nil {
t.Fatal(err)
}
assert.Equal(t, 403, res.Status())
// port := start(t)
// defer test.Stop(func() {})
req = test.NewRequest(port).Route("/api/__yao/table/pet/setting").Token(token(t))
res, err = req.Get()
if err != nil {
t.Fatal(err)
}
assert.Equal(t, 200, res.Status())
// req := test.NewRequest(port).Route("/api/__yao/table/pet/setting")
// res, err := req.Get()
// if err != nil {
// t.Fatal(err)
// }
// assert.Equal(t, 403, res.Status())
v, err := res.Map()
if err != nil {
t.Fatal(err)
}
// req = test.NewRequest(port).Route("/api/__yao/table/pet/setting").Token(token(t))
// res, err = req.Get()
// if err != nil {
// t.Fatal(err)
// }
// assert.Equal(t, 200, res.Status())
data := any.Of(v).MapStr().Dot()
assert.Equal(t, "/api/xiang/import/pet", data.Get("header.preset.import.api.import"))
// assert.Equal(t, "跳转", data.Get("header.preset.import.operation.0.title"))
assert.Equal(t, "/api/__yao/table/pet/component/fields.table."+url.QueryEscape("入院状态")+".view.props.xProps/remote", data.Get("fields.table.入院状态.view.props.xProps.remote.api"))
assert.Equal(t, "/api/__yao/table/pet/component/fields.table."+url.QueryEscape("入院状态")+".edit.props.xProps/remote", data.Get("fields.table.入院状态.edit.props.xProps.remote.api"))
}
// v, err := res.Map()
// if err != nil {
// t.Fatal(err)
// }
// data := any.Of(v).MapStr().Dot()
// assert.Equal(t, "/api/xiang/import/pet", data.Get("header.preset.import.api.import"))
// // assert.Equal(t, "跳转", data.Get("header.preset.import.operation.0.title"))
// assert.Equal(t, "/api/__yao/table/pet/component/fields.table."+url.QueryEscape("入院状态")+".view.props.xProps/remote", data.Get("fields.table.入院状态.view.props.xProps.remote.api"))
// assert.Equal(t, "/api/__yao/table/pet/component/fields.table."+url.QueryEscape("入院状态")+".edit.props.xProps/remote", data.Get("fields.table.入院状态.edit.props.xProps.remote.api"))
// }
func TestAPISearch(t *testing.T) {
port := start(t)
defer test.Stop()
// func TestAPISearch(t *testing.T) {
// port := start(t)
// defer test.Stop(func() {})
req := test.NewRequest(port).Route("/api/__yao/table/session/search")
res, err := req.Get()
if err != nil {
t.Fatal(err)
}
assert.Equal(t, 403, res.Status())
// req := test.NewRequest(port).Route("/api/__yao/table/session/search")
// res, err := req.Get()
// if err != nil {
// t.Fatal(err)
// }
// assert.Equal(t, 403, res.Status())
req = test.NewRequest(port).Route("/api/__yao/table/session/search").Token(token(t))
res, err = req.Get()
if err != nil {
t.Fatal(err)
}
assert.Equal(t, 200, res.Status())
resp, err := res.Map()
if err != nil {
t.Fatal(err)
}
// req = test.NewRequest(port).Route("/api/__yao/table/session/search").Token(token(t))
// res, err = req.Get()
// if err != nil {
// t.Fatal(err)
// }
// assert.Equal(t, 200, res.Status())
// resp, err := res.Map()
// if err != nil {
// t.Fatal(err)
// }
data := any.Of(resp).MapStr().Dot()
assert.Equal(t, "1", fmt.Sprintf("%v", data.Get("pagesize")))
assert.Equal(t, "3", fmt.Sprintf("%v", data.Get("total")))
assert.Equal(t, "checked", data.Get("data.0.status"))
assert.Equal(t, "enabled", data.Get("data.0.mode"))
assert.Equal(t, "1", fmt.Sprintf("%v", data.Get("data.0.doctor_id")))
// data := any.Of(resp).MapStr().Dot()
// assert.Equal(t, "1", fmt.Sprintf("%v", data.Get("pagesize")))
// assert.Equal(t, "3", fmt.Sprintf("%v", data.Get("total")))
// assert.Equal(t, "checked", data.Get("data.0.status"))
// assert.Equal(t, "enabled", data.Get("data.0.mode"))
// assert.Equal(t, "1", fmt.Sprintf("%v", data.Get("data.0.doctor_id")))
}
// }
func TestAPISave(t *testing.T) {
port := start(t)
defer test.Stop()
// func TestAPISave(t *testing.T) {
// port := start(t)
// defer test.Stop(func() {})
payload := map[string]interface{}{
"name": "New Pet",
"type": "cat",
"status": "checked",
"mode": "enabled",
"stay": 66,
"cost": 24,
"doctor_id": 1,
}
// payload := map[string]interface{}{
// "name": "New Pet",
// "type": "cat",
// "status": "checked",
// "mode": "enabled",
// "stay": 66,
// "cost": 24,
// "doctor_id": 1,
// }
req := test.NewRequest(port).Route("/api/__yao/table/pet/save").Data(payload)
res, err := req.Post()
if err != nil {
t.Fatal(err)
}
assert.Equal(t, 403, res.Status())
// req := test.NewRequest(port).Route("/api/__yao/table/pet/save").Data(payload)
// res, err := req.Post()
// if err != nil {
// t.Fatal(err)
// }
// assert.Equal(t, 403, res.Status())
req = test.NewRequest(port).Route("/api/__yao/table/pet/save").Data(payload).Token(token(t))
res, err = req.Post()
if err != nil {
t.Fatal(err)
}
assert.Equal(t, 200, res.Status())
// req = test.NewRequest(port).Route("/api/__yao/table/pet/save").Data(payload).Token(token(t))
// res, err = req.Post()
// if err != nil {
// t.Fatal(err)
// }
// assert.Equal(t, 200, res.Status())
v, err := res.Int()
if err != nil {
t.Fatal(err)
}
// v, err := res.Int()
// if err != nil {
// t.Fatal(err)
// }
assert.Equal(t, 4, v)
}
// assert.Equal(t, 4, v)
// }
func TestAPICustomGuard(t *testing.T) {
// func TestAPICustomGuard(t *testing.T) {
port := start(t)
defer test.Stop()
// port := start(t)
// defer test.Stop(func() {})
req := test.NewRequest(port).Route("/api/__yao/table/pet/find/1")
res, err := req.Get()
if err != nil {
t.Fatal(err)
}
// req := test.NewRequest(port).Route("/api/__yao/table/pet/find/1")
// res, err := req.Get()
// if err != nil {
// t.Fatal(err)
// }
req = test.NewRequest(port).Route("/api/__yao/table/pet/get")
res, err = req.Get()
if err != nil {
t.Fatal(err)
}
assert.Equal(t, 403, res.Status())
// req = test.NewRequest(port).Route("/api/__yao/table/pet/get")
// res, err = req.Get()
// if err != nil {
// t.Fatal(err)
// }
// assert.Equal(t, 403, res.Status())
req = test.NewRequest(port).Route("/api/__yao/table/pet/get").Token(token(t)).Header("Unit-Test", "yes")
res, err = req.Get()
if err != nil {
t.Fatal(err)
}
assert.Equal(t, 418, res.Status())
// req = test.NewRequest(port).Route("/api/__yao/table/pet/get").Token(token(t)).Header("Unit-Test", "yes")
// res, err = req.Get()
// if err != nil {
// t.Fatal(err)
// }
// assert.Equal(t, 418, res.Status())
req = test.NewRequest(port).Route("/api/__yao/table/pet/get").Token(token(t))
res, err = req.Get()
if err != nil {
t.Fatal(err)
}
assert.Equal(t, 200, res.Status())
}
// req = test.NewRequest(port).Route("/api/__yao/table/pet/get").Token(token(t))
// res, err = req.Get()
// if err != nil {
// t.Fatal(err)
// }
// assert.Equal(t, 200, res.Status())
// }
func TestAPIGlobalCustomGuard(t *testing.T) {
// func TestAPIGlobalCustomGuard(t *testing.T) {
port := start(t)
defer test.Stop()
// port := start(t)
// defer test.Stop(func() {})
req := test.NewRequest(port).Route("/api/__yao/table/guard/find/1")
res, err := req.Get()
if err != nil {
t.Fatal(err)
}
assert.Equal(t, 403, res.Status())
// req := test.NewRequest(port).Route("/api/__yao/table/guard/find/1")
// res, err := req.Get()
// if err != nil {
// t.Fatal(err)
// }
// assert.Equal(t, 403, res.Status())
req = test.NewRequest(port).Route("/api/__yao/table/guard/get")
res, err = req.Get()
if err != nil {
t.Fatal(err)
}
assert.Equal(t, 403, res.Status())
// req = test.NewRequest(port).Route("/api/__yao/table/guard/get")
// res, err = req.Get()
// if err != nil {
// t.Fatal(err)
// }
// assert.Equal(t, 403, res.Status())
req = test.NewRequest(port).Route("/api/__yao/table/guard/get").Token(token(t)).Header("Unit-Test", "yes")
res, err = req.Get()
if err != nil {
t.Fatal(err)
}
assert.Equal(t, 418, res.Status())
// req = test.NewRequest(port).Route("/api/__yao/table/guard/get").Token(token(t)).Header("Unit-Test", "yes")
// res, err = req.Get()
// if err != nil {
// t.Fatal(err)
// }
// assert.Equal(t, 418, res.Status())
req = test.NewRequest(port).Route("/api/__yao/table/guard/get").Token(token(t))
res, err = req.Get()
if err != nil {
t.Fatal(err)
}
assert.Equal(t, 200, res.Status())
}
// req = test.NewRequest(port).Route("/api/__yao/table/guard/get").Token(token(t))
// res, err = req.Get()
// if err != nil {
// t.Fatal(err)
// }
// assert.Equal(t, 200, res.Status())
// }
func start(t *testing.T) int {
test.Prepare(t, config.Conf)
prepare(t)
clear(t)
testData(t)
test.Start(t, guards, config.Conf)
// func start(t *testing.T) int {
// port := 0
return test.Port(t)
}
// go test.Start(t, guards, port)
// time.Sleep(200 * time.Millisecond)
// return port
// }
func stop() {
test.Stop()
}
// func token(t *testing.T) string {
// res, err := test.AutoLogin(1)
// if err != nil {
// t.Fatal(err)
// }
func token(t *testing.T) string {
res, err := test.AutoLogin(1)
if err != nil {
t.Fatal(err)
}
// token, ok := res["token"].(string)
// if !ok {
// t.Fatal(fmt.Errorf("get token error %v", res))
// }
// return token
// }
token, ok := res["token"].(string)
if !ok {
t.Fatal(fmt.Errorf("get token error %v", res))
}
return token
}