Fix TestRequestLogAPI
This commit is contained in:
parent
23a9506dda
commit
6d432b9de4
@ -11,6 +11,8 @@
|
|||||||
- ios purchase verification
|
- ios purchase verification
|
||||||
|
|
||||||
- (!) use goext.ginWrapper
|
- (!) use goext.ginWrapper
|
||||||
|
|
||||||
|
- (!!!) local lock to prevent database-locked errors (there are a lot when one client malfunctions and starts sending a lot of notifications)
|
||||||
|
|
||||||
#### UNSURE
|
#### UNSURE
|
||||||
|
|
||||||
@ -66,4 +68,4 @@
|
|||||||
|
|
||||||
#### FUTURE
|
#### FUTURE
|
||||||
|
|
||||||
- Remove compat, especially do not create compat id for every new message...
|
- Remove compat, especially do not create compat id for every new message...
|
||||||
|
@ -3,6 +3,7 @@ package test
|
|||||||
import (
|
import (
|
||||||
tt "blackforestbytes.com/simplecloudnotifier/test/util"
|
tt "blackforestbytes.com/simplecloudnotifier/test/util"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -42,12 +43,21 @@ func TestResponseClient(t *testing.T) {
|
|||||||
|
|
||||||
data := tt.InitDefaultData(t, ws)
|
data := tt.InitDefaultData(t, ws)
|
||||||
|
|
||||||
response := tt.RequestAuthGetRaw(t, data.User[0].AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/clients/%s", data.User[2].UID, data.User[2].Clients[2]))
|
response := tt.RequestAuthGetRaw(t, data.User[2].AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/clients/%s", data.User[2].UID, data.User[2].Clients[0]))
|
||||||
|
|
||||||
tt.AssertJsonStructureMatch(t, "json[client]", response, map[string]any{})
|
tt.AssertJsonStructureMatch(t, "json[client]", response, map[string]any{
|
||||||
|
"client_id": "id",
|
||||||
|
"user_id": "id",
|
||||||
|
"type": "string",
|
||||||
|
"fcm_token": "string",
|
||||||
|
"timestamp_created": "rfc3339",
|
||||||
|
"agent_model": "string",
|
||||||
|
"agent_version": "string",
|
||||||
|
"name": "string|null",
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestResponseKeyToken(t *testing.T) {
|
func TestResponseKeyToken1(t *testing.T) {
|
||||||
ws, baseUrl, stop := tt.StartSimpleWebserver(t)
|
ws, baseUrl, stop := tt.StartSimpleWebserver(t)
|
||||||
defer stop()
|
defer stop()
|
||||||
|
|
||||||
@ -55,7 +65,52 @@ func TestResponseKeyToken(t *testing.T) {
|
|||||||
|
|
||||||
response := tt.RequestAuthGetRaw(t, data.User[0].AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys/%s", data.User[0].UID, data.User[0].Keys[0]))
|
response := tt.RequestAuthGetRaw(t, data.User[0].AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys/%s", data.User[0].UID, data.User[0].Keys[0]))
|
||||||
|
|
||||||
tt.AssertJsonStructureMatch(t, "json[key]", response, map[string]any{})
|
tt.AssertJsonStructureMatch(t, "json[key]", response, map[string]any{
|
||||||
|
"keytoken_id": "id",
|
||||||
|
"name": "string",
|
||||||
|
"timestamp_created": "rfc3339",
|
||||||
|
"timestamp_lastused": "rfc3339|null",
|
||||||
|
"owner_user_id": "id",
|
||||||
|
"all_channels": "bool",
|
||||||
|
"channels": []any{"string"},
|
||||||
|
"permissions": "string",
|
||||||
|
"messages_sent": "int",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestResponseKeyToken2(t *testing.T) {
|
||||||
|
ws, baseUrl, stop := tt.StartSimpleWebserver(t)
|
||||||
|
defer stop()
|
||||||
|
|
||||||
|
data := tt.InitSingleData(t, ws)
|
||||||
|
|
||||||
|
chan1 := tt.RequestAuthPost[gin.H](t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/channels", data.UID), gin.H{
|
||||||
|
"name": "TestChan1asdf",
|
||||||
|
})
|
||||||
|
|
||||||
|
type keyobj struct {
|
||||||
|
KeytokenId string `json:"keytoken_id"`
|
||||||
|
}
|
||||||
|
k0 := tt.RequestAuthPost[keyobj](t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys", data.UID), gin.H{
|
||||||
|
"all_channels": false,
|
||||||
|
"channels": []string{chan1["channel_id"].(string)},
|
||||||
|
"name": "TKey1",
|
||||||
|
"permissions": "CS",
|
||||||
|
})
|
||||||
|
|
||||||
|
response := tt.RequestAuthGetRaw(t, data.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys/%s", data.UID, k0.KeytokenId))
|
||||||
|
|
||||||
|
tt.AssertJsonStructureMatch(t, "json[key]", response, map[string]any{
|
||||||
|
"keytoken_id": "id",
|
||||||
|
"name": "string",
|
||||||
|
"timestamp_created": "rfc3339",
|
||||||
|
"timestamp_lastused": "rfc3339|null",
|
||||||
|
"owner_user_id": "id",
|
||||||
|
"all_channels": "bool",
|
||||||
|
"channels": []any{"string"},
|
||||||
|
"permissions": "string",
|
||||||
|
"messages_sent": "int",
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestResponseMessage(t *testing.T) {
|
func TestResponseMessage(t *testing.T) {
|
||||||
@ -64,9 +119,23 @@ func TestResponseMessage(t *testing.T) {
|
|||||||
|
|
||||||
data := tt.InitDefaultData(t, ws)
|
data := tt.InitDefaultData(t, ws)
|
||||||
|
|
||||||
response := tt.RequestAuthGetRaw(t, data.User[0].AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/messages/%s", data.User[0].UID, data.User[0].Messages[0]))
|
response := tt.RequestAuthGetRaw(t, data.User[0].AdminKey, baseUrl, fmt.Sprintf("/api/v2/messages/%s", data.User[0].Messages[0]))
|
||||||
|
|
||||||
tt.AssertJsonStructureMatch(t, "json[message]", response, map[string]any{})
|
tt.AssertJsonStructureMatch(t, "json[message]", response, map[string]any{
|
||||||
|
"message_id": "id",
|
||||||
|
"sender_user_id": "id",
|
||||||
|
"channel_internal_name": "string",
|
||||||
|
"channel_id": "id",
|
||||||
|
"sender_name": "string",
|
||||||
|
"sender_ip": "string",
|
||||||
|
"timestamp": "rfc3339",
|
||||||
|
"title": "string",
|
||||||
|
"content": "null",
|
||||||
|
"priority": "int",
|
||||||
|
"usr_message_id": "null",
|
||||||
|
"used_key_id": "id",
|
||||||
|
"trimmed": "bool",
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestResponseSubscription(t *testing.T) {
|
func TestResponseSubscription(t *testing.T) {
|
||||||
@ -77,7 +146,15 @@ func TestResponseSubscription(t *testing.T) {
|
|||||||
|
|
||||||
response := tt.RequestAuthGetRaw(t, data.User[0].AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/subscriptions/%s", data.User[0].UID, data.User[0].Subscriptions[0]))
|
response := tt.RequestAuthGetRaw(t, data.User[0].AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/subscriptions/%s", data.User[0].UID, data.User[0].Subscriptions[0]))
|
||||||
|
|
||||||
tt.AssertJsonStructureMatch(t, "json[subscription]", response, map[string]any{})
|
tt.AssertJsonStructureMatch(t, "json[subscription]", response, map[string]any{
|
||||||
|
"subscription_id": "id",
|
||||||
|
"subscriber_user_id": "id",
|
||||||
|
"channel_owner_user_id": "id",
|
||||||
|
"channel_id": "id",
|
||||||
|
"channel_internal_name": "string",
|
||||||
|
"timestamp_created": "rfc3339",
|
||||||
|
"confirmed": "bool",
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestResponseUser(t *testing.T) {
|
func TestResponseUser(t *testing.T) {
|
||||||
@ -88,7 +165,26 @@ func TestResponseUser(t *testing.T) {
|
|||||||
|
|
||||||
response := tt.RequestAuthGetRaw(t, data.User[0].AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s", data.User[0].UID))
|
response := tt.RequestAuthGetRaw(t, data.User[0].AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s", data.User[0].UID))
|
||||||
|
|
||||||
tt.AssertJsonStructureMatch(t, "json[user]", response, map[string]any{})
|
tt.AssertJsonStructureMatch(t, "json[user]", response, map[string]any{
|
||||||
|
"user_id": "id",
|
||||||
|
"username": "null",
|
||||||
|
"timestamp_created": "rfc3339",
|
||||||
|
"timestamp_lastread": "null",
|
||||||
|
"timestamp_lastsent": "rfc3339",
|
||||||
|
"messages_sent": "int",
|
||||||
|
"quota_used": "int",
|
||||||
|
"quota_remaining": "int",
|
||||||
|
"quota_max": "int",
|
||||||
|
"is_pro": "bool",
|
||||||
|
"default_channel": "string",
|
||||||
|
"max_body_size": "int",
|
||||||
|
"max_title_length": "int",
|
||||||
|
"default_priority": "int",
|
||||||
|
"max_channel_name_length": "int",
|
||||||
|
"max_channel_description_length": "int",
|
||||||
|
"max_sender_name_length": "int",
|
||||||
|
"max_user_message_id_length": "int",
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestResponseChannelPreview(t *testing.T) {
|
func TestResponseChannelPreview(t *testing.T) {
|
||||||
@ -100,24 +196,11 @@ func TestResponseChannelPreview(t *testing.T) {
|
|||||||
response := tt.RequestAuthGetRaw(t, data.User[1].AdminKey, baseUrl, fmt.Sprintf("/api/v2/preview/channels/%s", data.User[0].Channels[0]))
|
response := tt.RequestAuthGetRaw(t, data.User[1].AdminKey, baseUrl, fmt.Sprintf("/api/v2/preview/channels/%s", data.User[0].Channels[0]))
|
||||||
|
|
||||||
tt.AssertJsonStructureMatch(t, "json[channel]", response, map[string]any{
|
tt.AssertJsonStructureMatch(t, "json[channel]", response, map[string]any{
|
||||||
"channel_id": "id",
|
"channel_id": "id",
|
||||||
"owner_user_id": "id",
|
"owner_user_id": "id",
|
||||||
"internal_name": "string",
|
"internal_name": "string",
|
||||||
"display_name": "string",
|
"display_name": "string",
|
||||||
"description_name": "null",
|
"description_name": "string|null",
|
||||||
"subscribe_key": "string",
|
|
||||||
"timestamp_created": "rfc3339",
|
|
||||||
"timestamp_lastsent": "rfc3339",
|
|
||||||
"messages_sent": "int",
|
|
||||||
"subscription": map[string]any{
|
|
||||||
"subscription_id": "id",
|
|
||||||
"subscriber_user_id": "id",
|
|
||||||
"channel_owner_user_id": "id",
|
|
||||||
"channel_id": "id",
|
|
||||||
"channel_internal_name": "string",
|
|
||||||
"timestamp_created": "rfc3339",
|
|
||||||
"confirmed": "bool",
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,7 +212,10 @@ func TestResponseUserPreview(t *testing.T) {
|
|||||||
|
|
||||||
response := tt.RequestAuthGetRaw(t, data.User[1].AdminKey, baseUrl, fmt.Sprintf("/api/v2/preview/users/%s", data.User[0].UID))
|
response := tt.RequestAuthGetRaw(t, data.User[1].AdminKey, baseUrl, fmt.Sprintf("/api/v2/preview/users/%s", data.User[0].UID))
|
||||||
|
|
||||||
tt.AssertJsonStructureMatch(t, "json[user]", response, map[string]any{})
|
tt.AssertJsonStructureMatch(t, "json[user]", response, map[string]any{
|
||||||
|
"user_id": "id",
|
||||||
|
"username": "string|null",
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestResponseKeyTokenPreview(t *testing.T) {
|
func TestResponseKeyTokenPreview(t *testing.T) {
|
||||||
@ -140,5 +226,12 @@ func TestResponseKeyTokenPreview(t *testing.T) {
|
|||||||
|
|
||||||
response := tt.RequestAuthGetRaw(t, data.User[1].AdminKey, baseUrl, fmt.Sprintf("/api/v2/preview/keys/%s", data.User[0].Keys[0]))
|
response := tt.RequestAuthGetRaw(t, data.User[1].AdminKey, baseUrl, fmt.Sprintf("/api/v2/preview/keys/%s", data.User[0].Keys[0]))
|
||||||
|
|
||||||
tt.AssertJsonStructureMatch(t, "json[key]", response, map[string]any{})
|
tt.AssertJsonStructureMatch(t, "json[key]", response, map[string]any{
|
||||||
|
"keytoken_id": "id",
|
||||||
|
"name": "string",
|
||||||
|
"owner_user_id": "id",
|
||||||
|
"all_channels": "bool",
|
||||||
|
"channels": []any{"id"},
|
||||||
|
"permissions": "string",
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -435,7 +435,7 @@ func InitDefaultData(t *testing.T, ws *logic.Application) DefData {
|
|||||||
ID string `json:"keytoken_id"`
|
ID string `json:"keytoken_id"`
|
||||||
}
|
}
|
||||||
type keylist struct {
|
type keylist struct {
|
||||||
Keys []skey `json:"channels"`
|
Keys []skey `json:"keys"`
|
||||||
}
|
}
|
||||||
r0 := RequestAuthGet[keylist](t, usr.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys", usr.UID))
|
r0 := RequestAuthGet[keylist](t, usr.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/keys", usr.UID))
|
||||||
users[i].Keys = langext.ArrMap(r0.Keys, func(v skey) string { return v.ID })
|
users[i].Keys = langext.ArrMap(r0.Keys, func(v skey) string { return v.ID })
|
||||||
@ -448,10 +448,10 @@ func InitDefaultData(t *testing.T, ws *logic.Application) DefData {
|
|||||||
ID string `json:"subscription_id"`
|
ID string `json:"subscription_id"`
|
||||||
}
|
}
|
||||||
type sublist struct {
|
type sublist struct {
|
||||||
Subs []ssub `json:"channels"`
|
Subs []ssub `json:"subscriptions"`
|
||||||
}
|
}
|
||||||
r0 := RequestAuthGet[sublist](t, usr.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/subscriptions?direction=%s&confirmation=%s", usr.UID, "outgoing", "confirmed"))
|
r0 := RequestAuthGet[sublist](t, usr.AdminKey, baseUrl, fmt.Sprintf("/api/v2/users/%s/subscriptions?direction=%s&confirmation=%s", usr.UID, "outgoing", "confirmed"))
|
||||||
users[i].Keys = langext.ArrMap(r0.Subs, func(v ssub) string { return v.ID })
|
users[i].Subscriptions = langext.ArrMap(r0.Subs, func(v ssub) string { return v.ID })
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sub/Unsub for Users 12+13
|
// Sub/Unsub for Users 12+13
|
||||||
@ -510,13 +510,15 @@ func InitSingleData(t *testing.T, ws *logic.Application) SingleData {
|
|||||||
|
|
||||||
success = true
|
success = true
|
||||||
|
|
||||||
return SingleData{
|
sd := SingleData{
|
||||||
UID: r0.UserId,
|
UID: r0.UserId,
|
||||||
AdminKey: r0.AdminKey,
|
AdminKey: r0.AdminKey,
|
||||||
SendKey: r0.SendKey,
|
SendKey: r0.SendKey,
|
||||||
ReadKey: r0.ReadKey,
|
ReadKey: r0.ReadKey,
|
||||||
ClientID: r0.Clients[0].ClientId,
|
ClientID: r0.Clients[0].ClientId,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return sd
|
||||||
}
|
}
|
||||||
|
|
||||||
func doSubscribe(t *testing.T, baseUrl string, user Userdat, chanOwner Userdat, chanInternalName string) {
|
func doSubscribe(t *testing.T, baseUrl string, user Userdat, chanOwner Userdat, chanInternalName string) {
|
||||||
|
@ -2,6 +2,7 @@ package util
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"gogs.mikescher.com/BlackForestBytes/goext/langext"
|
"gogs.mikescher.com/BlackForestBytes/goext/langext"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
@ -18,101 +19,158 @@ func AssertJsonStructureMatch(t *testing.T, key string, jsonData string, expecte
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
AssertJsonStructureMatchOfMap(t, key, realData, expected)
|
assertjsonStructureMatchMapObject(t, expected, realData, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
func AssertJsonStructureMatchOfMap(t *testing.T, key string, realData map[string]any, expected map[string]any) {
|
func assertJsonStructureMatch(t *testing.T, schema any, realValue any, keyPath string) {
|
||||||
|
|
||||||
for k := range expected {
|
if strschema, ok := schema.(string); ok {
|
||||||
if _, ok := realData[k]; !ok {
|
|
||||||
t.Errorf("Missing Key in data '%s': [[%s]]", key, k)
|
assertjsonStructureMatchSingleValue(t, strschema, realValue, keyPath)
|
||||||
|
|
||||||
|
} else if mapschema, ok := schema.(map[string]any); ok {
|
||||||
|
|
||||||
|
if reflect.ValueOf(realValue).Kind() != reflect.Map {
|
||||||
|
t.Errorf("Key < %s > is not a object (its actually %T: '%v')", keyPath, realValue, realValue)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, ok := realValue.(map[string]any); !ok {
|
||||||
|
t.Errorf("Key < %s > is not a object[recursive] (its actually %T: '%v')", keyPath, realValue, realValue)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
assertjsonStructureMatchMapObject(t, mapschema, realValue.(map[string]any), keyPath)
|
||||||
|
|
||||||
|
} else if arrschema, ok := schema.([]any); ok && len(arrschema) == 1 {
|
||||||
|
|
||||||
|
if _, ok := realValue.([]any); !ok {
|
||||||
|
t.Errorf("Key < %s > is not a array[recursive] (its actually %T: '%v')", keyPath, realValue, realValue)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
assertjsonStructureMatchArray(t, arrschema, realValue.([]any), keyPath)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
t.Errorf("Unknown schema type '%s' for key < %s >", schema, keyPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func assertjsonStructureMatchSingleValue(t *testing.T, strschema string, realValue any, keyPath string) {
|
||||||
|
switch strschema {
|
||||||
|
case "id":
|
||||||
|
if _, ok := realValue.(string); !ok {
|
||||||
|
t.Errorf("Key < %s > is not a string<id> (its actually %T: '%v')", keyPath, realValue, realValue)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(realValue.(string)) != 24 { //TODO validate checksum?
|
||||||
|
t.Errorf("Key < %s > is not a valid entity-id date (its '%v')", keyPath, realValue)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case "string":
|
||||||
|
if _, ok := realValue.(string); !ok {
|
||||||
|
t.Errorf("Key < %s > is not a string (its actually %T: '%v')", keyPath, realValue, realValue)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case "null":
|
||||||
|
if !langext.IsNil(realValue) {
|
||||||
|
t.Errorf("Key < %s > is not a NULL (its actually %T: '%v')", keyPath, realValue, realValue)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case "string|null":
|
||||||
|
if langext.IsNil(realValue) {
|
||||||
|
return // OK
|
||||||
|
} else if _, ok := realValue.(string); !ok {
|
||||||
|
return // OK
|
||||||
|
} else {
|
||||||
|
t.Errorf("Key < %s > is not a string|null (its actually %T: '%v')", keyPath, realValue, realValue)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case "rfc3339":
|
||||||
|
if _, ok := realValue.(string); !ok {
|
||||||
|
t.Errorf("Key < %s > is not a string<rfc3339> (its actually %T: '%v')", keyPath, realValue, realValue)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, err := time.Parse(time.RFC3339, realValue.(string)); err != nil {
|
||||||
|
t.Errorf("Key < %s > is not a valid rfc3339 date (its '%v')", keyPath, realValue)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case "rfc3339|null":
|
||||||
|
if langext.IsNil(realValue) {
|
||||||
|
return // OK
|
||||||
|
}
|
||||||
|
if _, ok := realValue.(string); !ok {
|
||||||
|
t.Errorf("Key < %s > is not a string<rfc3339> (its actually %T: '%v')", keyPath, realValue, realValue)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, err := time.Parse(time.RFC3339, realValue.(string)); err != nil {
|
||||||
|
t.Errorf("Key < %s > is not a valid rfc3339 date (its '%v')", keyPath, realValue)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case "int":
|
||||||
|
if _, ok := realValue.(float64); !ok {
|
||||||
|
t.Errorf("Key < %s > is not a int (its actually %T: '%v')", keyPath, realValue, realValue)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if realValue.(float64) != float64(int(realValue.(float64))) {
|
||||||
|
t.Errorf("Key < %s > is not a int (its actually %T: '%v')", keyPath, realValue, realValue)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case "float":
|
||||||
|
if _, ok := realValue.(float64); !ok {
|
||||||
|
t.Errorf("Key < %s > is not a int (its actually %T: '%v')", keyPath, realValue, realValue)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case "bool":
|
||||||
|
if _, ok := realValue.(bool); !ok {
|
||||||
|
t.Errorf("Key < %s > is not a int (its actually %T: '%v')", keyPath, realValue, realValue)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
t.Errorf("Unknown schema type '%s' for key < %s >", strschema, keyPath)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func assertjsonStructureMatchMapObject(t *testing.T, mapschema map[string]any, realValue map[string]any, keyPath string) {
|
||||||
|
|
||||||
|
for k := range mapschema {
|
||||||
|
if _, ok := realValue[k]; !ok {
|
||||||
|
t.Errorf("Missing Key: < %s >", keyPath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for k := range realData {
|
for k := range realValue {
|
||||||
if _, ok := expected[k]; !ok {
|
if _, ok := mapschema[k]; !ok {
|
||||||
t.Errorf("Additional key in data '%s': [[%s]]", key, k)
|
t.Errorf("Additional key: < %s >", keyPath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for k, v := range realData {
|
for k, v := range realValue {
|
||||||
|
|
||||||
schema, ok := expected[k]
|
kpath := keyPath + "." + k
|
||||||
|
|
||||||
|
schema, ok := mapschema[k]
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
|
t.Errorf("Key < %s > is missing in response", kpath)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if strschema, ok := schema.(string); ok {
|
assertJsonStructureMatch(t, schema, v, kpath)
|
||||||
switch strschema {
|
|
||||||
case "id":
|
|
||||||
if _, ok := v.(string); !ok {
|
|
||||||
t.Errorf("Key [[%s]] in data '%s' is not a string<id> (its actually %T: '%v')", k, key, v, v)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if len(v.(string)) != 24 { //TODO validate checksum?
|
|
||||||
t.Errorf("Key [[%s]] in data '%s' is not a valid entity-id date (its '%v')", k, key, v)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
case "string":
|
|
||||||
if _, ok := v.(string); !ok {
|
|
||||||
t.Errorf("Key [[%s]] in data '%s' is not a string (its actually %T: '%v')", k, key, v, v)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
case "null":
|
|
||||||
if !langext.IsNil(v) {
|
|
||||||
t.Errorf("Key [[%s]] in data '%s' is not a NULL (its actually %T: '%v')", k, key, v, v)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
case "rfc3339":
|
|
||||||
if _, ok := v.(string); !ok {
|
|
||||||
t.Errorf("Key [[%s]] in data '%s' is not a string<rfc3339> (its actually %T: '%v')", k, key, v, v)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if _, err := time.Parse(time.RFC3339, v.(string)); err != nil {
|
|
||||||
t.Errorf("Key [[%s]] in data '%s' is not a valid rfc3339 date (its '%v')", k, key, v)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
case "int":
|
|
||||||
if _, ok := v.(float64); !ok {
|
|
||||||
t.Errorf("Key [[%s]] in data '%s' is not a int (its actually %T: '%v')", k, key, v, v)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if v.(float64) != float64(int(v.(float64))) {
|
|
||||||
t.Errorf("Key [[%s]] in data '%s' is not a int (its actually %T: '%v')", k, key, v, v)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
case "float":
|
|
||||||
if _, ok := v.(float64); !ok {
|
|
||||||
t.Errorf("Key [[%s]] in data '%s' is not a int (its actually %T: '%v')", k, key, v, v)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
case "bool":
|
|
||||||
if _, ok := v.(bool); !ok {
|
|
||||||
t.Errorf("Key [[%s]] in data '%s' is not a int (its actually %T: '%v')", k, key, v, v)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
case "object":
|
|
||||||
if reflect.ValueOf(v).Kind() != reflect.Map {
|
|
||||||
t.Errorf("Key [[%s]] in data '%s' is not a object (its actually %T: '%v')", k, key, v, v)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
case "array":
|
|
||||||
if reflect.ValueOf(v).Kind() != reflect.Array {
|
|
||||||
t.Errorf("Key [[%s]] in data '%s' is not a array (its actually %T: '%v')", k, key, v, v)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if mapschema, ok := schema.(map[string]any); ok {
|
|
||||||
if reflect.ValueOf(v).Kind() != reflect.Map {
|
|
||||||
t.Errorf("Key [[%s]] in data '%s' is not a object (its actually %T: '%v')", k, key, v, v)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if _, ok := v.(map[string]any); !ok {
|
|
||||||
t.Errorf("Key [[%s]] in data '%s' is not a object[recursive] (its actually %T: '%v')", k, key, v, v)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
AssertJsonStructureMatchOfMap(t, key+".["+k+"]", v.(map[string]any), mapschema)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func assertjsonStructureMatchArray(t *testing.T, arrschema []any, realValue []any, keyPath string) {
|
||||||
|
|
||||||
|
if len(arrschema) != 1 {
|
||||||
|
t.Errorf("Array schema must have exactly one element, but got %d", len(arrschema))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, realArrVal := range realValue {
|
||||||
|
assertJsonStructureMatch(t, arrschema[0], realArrVal, fmt.Sprintf("%s[%d]", keyPath, i))
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user