schema: refactoring and making it usable and flexible.
This commit is contained in:
@@ -3,7 +3,10 @@ package schema
|
|||||||
import (
|
import (
|
||||||
_ "embed"
|
_ "embed"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"os"
|
||||||
"slices"
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -15,8 +18,26 @@ import (
|
|||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed schema.yaml
|
const DefaultSchemaURL = "https://raw.githubusercontent.com/nostr-protocol/registry-of-kinds/refs/heads/master/schema.yaml"
|
||||||
var schemaFile []byte
|
|
||||||
|
func fetchSchemaFromURL(schemaURL string) (string, error) {
|
||||||
|
resp, err := http.Get(schemaURL)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("failed to fetch schema from URL: %w", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
return "", fmt.Errorf("failed to fetch schema: HTTP %d", resp.StatusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
body, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("failed to read schema response: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(body), nil
|
||||||
|
}
|
||||||
|
|
||||||
type Schema map[string]KindSchema
|
type Schema map[string]KindSchema
|
||||||
|
|
||||||
@@ -44,17 +65,32 @@ type Validator struct {
|
|||||||
FailOnUnknown bool
|
FailOnUnknown bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewValidator(schemaData string) Validator {
|
func NewValidatorFromBytes(schemaData []byte) (Validator, error) {
|
||||||
schema := make(Schema)
|
schema := make(Schema)
|
||||||
if err := yaml.Unmarshal([]byte(schemaData), &schema); err != nil {
|
if err := yaml.Unmarshal(schemaData, &schema); err != nil {
|
||||||
panic(fmt.Errorf("failed to parse schema.yaml: %w", err))
|
return Validator{}, fmt.Errorf("failed to parse schema: %w", err)
|
||||||
}
|
}
|
||||||
|
return Validator{Schema: schema}, nil
|
||||||
return Validator{Schema: schema}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDefaultValidator() Validator {
|
func NewValidatorFromSchema(sch Schema) Validator {
|
||||||
return NewValidator(string(schemaFile))
|
return Validator{Schema: sch}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewValidatorFromFile(filename string) (Validator, error) {
|
||||||
|
data, err := os.ReadFile(filename)
|
||||||
|
if err != nil {
|
||||||
|
return Validator{}, fmt.Errorf("failed to read schema file: %w", err)
|
||||||
|
}
|
||||||
|
return NewValidatorFromBytes(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewValidatorFromURL(schemaURL string) (Validator, error) {
|
||||||
|
schemaData, err := fetchSchemaFromURL(schemaURL)
|
||||||
|
if err != nil {
|
||||||
|
return Validator{}, err
|
||||||
|
}
|
||||||
|
return NewValidatorFromBytes([]byte(schemaData))
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|||||||
1593
schema/schema.yaml
1593
schema/schema.yaml
File diff suppressed because it is too large
Load Diff
@@ -8,8 +8,9 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNewValidator(t *testing.T) {
|
func TestNewValidatorFromURL(t *testing.T) {
|
||||||
v := NewValidator(string(schemaFile))
|
v, err := NewValidatorFromURL(DefaultSchemaURL)
|
||||||
|
require.NoError(t, err)
|
||||||
require.NotNil(t, v.Schema)
|
require.NotNil(t, v.Schema)
|
||||||
require.False(t, v.FailOnUnknown) // default value
|
require.False(t, v.FailOnUnknown) // default value
|
||||||
|
|
||||||
@@ -22,14 +23,14 @@ func TestNewValidator(t *testing.T) {
|
|||||||
require.True(t, hasKind1111)
|
require.True(t, hasKind1111)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewValidatorWithInvalidYAML(t *testing.T) {
|
func TestNewValidatorFromBytesWithInvalidYAML(t *testing.T) {
|
||||||
require.Panics(t, func() {
|
_, err := NewValidatorFromBytes([]byte("invalid yaml content: [[["))
|
||||||
NewValidator("invalid yaml content: [[[")
|
require.Error(t, err)
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestValidateEvent_BasicSuccess(t *testing.T) {
|
func TestValidateEvent_BasicSuccess(t *testing.T) {
|
||||||
v := NewValidator(string(schemaFile))
|
v, err := NewValidatorFromURL(DefaultSchemaURL)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
// kind 1 with free content and valid p tag
|
// kind 1 with free content and valid p tag
|
||||||
evt := nostr.Event{
|
evt := nostr.Event{
|
||||||
@@ -40,30 +41,32 @@ func TestValidateEvent_BasicSuccess(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
err := v.ValidateEvent(evt)
|
err = v.ValidateEvent(evt)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestValidateEvent_Kind0_JSONContent(t *testing.T) {
|
func TestValidateEvent_Kind0_JSONContent(t *testing.T) {
|
||||||
v := NewValidator(string(schemaFile))
|
v, err := NewValidatorFromURL(DefaultSchemaURL)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
// valid JSON content
|
// valid JSON content
|
||||||
evt := nostr.Event{
|
evt := nostr.Event{
|
||||||
Kind: 0,
|
Kind: 0,
|
||||||
Content: `{"name":"test","about":"description"}`,
|
Content: `{"name":"test","about":"description"}`,
|
||||||
}
|
}
|
||||||
err := v.ValidateEvent(evt)
|
err = v.ValidateEvent(evt)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// invalid JSON content
|
// invalid JSON content
|
||||||
evt.Content = "not-json-content"
|
evt.Content = "not-json-content"
|
||||||
err = v.ValidateEvent(evt)
|
err = v.ValidateEvent(evt)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
require.Equal(t, ErrInvalidContentJson, err)
|
require.Equal(t, ContentError{Err: ErrInvalidJson}, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestValidateEvent_UnknownKind(t *testing.T) {
|
func TestValidateEvent_UnknownKind(t *testing.T) {
|
||||||
v := NewValidator(string(schemaFile))
|
v, err := NewValidatorFromURL(DefaultSchemaURL)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
evt := nostr.Event{
|
evt := nostr.Event{
|
||||||
Kind: nostr.Kind(39999),
|
Kind: nostr.Kind(39999),
|
||||||
@@ -71,7 +74,7 @@ func TestValidateEvent_UnknownKind(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// should not fail when FailOnUnknown is false (default)
|
// should not fail when FailOnUnknown is false (default)
|
||||||
err := v.ValidateEvent(evt)
|
err = v.ValidateEvent(evt)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// should fail when FailOnUnknown is true
|
// should fail when FailOnUnknown is true
|
||||||
@@ -82,22 +85,25 @@ func TestValidateEvent_UnknownKind(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestValidateEvent_EmptyTag(t *testing.T) {
|
func TestValidateEvent_EmptyTag(t *testing.T) {
|
||||||
v := NewValidator(string(schemaFile))
|
v, err := NewValidatorFromURL(DefaultSchemaURL)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
evt := nostr.Event{
|
evt := nostr.Event{
|
||||||
Kind: 1,
|
Kind: 1,
|
||||||
|
Content: "test",
|
||||||
Tags: nostr.Tags{
|
Tags: nostr.Tags{
|
||||||
nostr.Tag{}, // empty tag
|
nostr.Tag{}, // empty tag
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
err := v.ValidateEvent(evt)
|
err = v.ValidateEvent(evt)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
require.Equal(t, ErrEmptyTag, err)
|
require.Equal(t, ErrEmptyTag, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestValidateNext_ID(t *testing.T) {
|
func TestValidateNext_ID(t *testing.T) {
|
||||||
v := NewValidator(string(schemaFile))
|
v, err := NewValidatorFromURL(DefaultSchemaURL)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
@@ -116,7 +122,7 @@ func TestValidateNext_ID(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "invalid id - not hex",
|
name: "invalid id - not hex",
|
||||||
tag: nostr.Tag{"e", "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"},
|
tag: nostr.Tag{"e", "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"},
|
||||||
valid: false,
|
valid: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -124,7 +130,7 @@ func TestValidateNext_ID(t *testing.T) {
|
|||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
next := &nextSpec{Type: "id", Required: true}
|
next := &nextSpec{Type: "id", Required: true}
|
||||||
err := v.validateNext(tt.tag, 1, next)
|
_, err := v.validateNext(tt.tag, 1, next)
|
||||||
if tt.valid {
|
if tt.valid {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
} else {
|
} else {
|
||||||
@@ -135,7 +141,8 @@ func TestValidateNext_ID(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestValidateNext_PubKey(t *testing.T) {
|
func TestValidateNext_PubKey(t *testing.T) {
|
||||||
v := NewValidator(string(schemaFile))
|
v, err := NewValidatorFromURL(DefaultSchemaURL)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
@@ -162,7 +169,7 @@ func TestValidateNext_PubKey(t *testing.T) {
|
|||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
next := &nextSpec{Type: "pubkey", Required: true}
|
next := &nextSpec{Type: "pubkey", Required: true}
|
||||||
err := v.validateNext(tt.tag, 1, next)
|
_, err := v.validateNext(tt.tag, 1, next)
|
||||||
if tt.valid {
|
if tt.valid {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
} else {
|
} else {
|
||||||
@@ -173,7 +180,8 @@ func TestValidateNext_PubKey(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestValidateNext_Relay(t *testing.T) {
|
func TestValidateNext_Relay(t *testing.T) {
|
||||||
v := NewValidator(string(schemaFile))
|
v, err := NewValidatorFromURL(DefaultSchemaURL)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
@@ -210,7 +218,7 @@ func TestValidateNext_Relay(t *testing.T) {
|
|||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
next := &nextSpec{Type: "relay", Required: true}
|
next := &nextSpec{Type: "relay", Required: true}
|
||||||
err := v.validateNext(tt.tag, 1, next)
|
_, err := v.validateNext(tt.tag, 1, next)
|
||||||
if tt.valid {
|
if tt.valid {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
} else {
|
} else {
|
||||||
@@ -221,7 +229,8 @@ func TestValidateNext_Relay(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestValidateNext_Kind(t *testing.T) {
|
func TestValidateNext_Kind(t *testing.T) {
|
||||||
v := NewValidator(string(schemaFile))
|
v, err := NewValidatorFromURL(DefaultSchemaURL)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
@@ -258,7 +267,7 @@ func TestValidateNext_Kind(t *testing.T) {
|
|||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
next := &nextSpec{Type: "kind", Required: true}
|
next := &nextSpec{Type: "kind", Required: true}
|
||||||
err := v.validateNext(tt.tag, 1, next)
|
_, err := v.validateNext(tt.tag, 1, next)
|
||||||
if tt.valid {
|
if tt.valid {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
} else {
|
} else {
|
||||||
@@ -269,7 +278,8 @@ func TestValidateNext_Kind(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestValidateNext_Constrained(t *testing.T) {
|
func TestValidateNext_Constrained(t *testing.T) {
|
||||||
v := NewValidator(string(schemaFile))
|
v, err := NewValidatorFromURL(DefaultSchemaURL)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
@@ -294,7 +304,7 @@ func TestValidateNext_Constrained(t *testing.T) {
|
|||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
next := &nextSpec{Type: "constrained", Required: true, Either: tt.allowed}
|
next := &nextSpec{Type: "constrained", Required: true, Either: tt.allowed}
|
||||||
err := v.validateNext(tt.tag, 3, next)
|
_, err := v.validateNext(tt.tag, 3, next)
|
||||||
if tt.valid {
|
if tt.valid {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
} else {
|
} else {
|
||||||
@@ -305,7 +315,8 @@ func TestValidateNext_Constrained(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestValidateNext_GitCommit(t *testing.T) {
|
func TestValidateNext_GitCommit(t *testing.T) {
|
||||||
v := NewValidator(string(schemaFile))
|
v, err := NewValidatorFromURL(DefaultSchemaURL)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
@@ -337,7 +348,7 @@ func TestValidateNext_GitCommit(t *testing.T) {
|
|||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
next := &nextSpec{Type: "gitcommit", Required: true}
|
next := &nextSpec{Type: "gitcommit", Required: true}
|
||||||
err := v.validateNext(tt.tag, 1, next)
|
_, err := v.validateNext(tt.tag, 1, next)
|
||||||
if tt.valid {
|
if tt.valid {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
} else {
|
} else {
|
||||||
@@ -348,7 +359,8 @@ func TestValidateNext_GitCommit(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestValidateNext_Addr(t *testing.T) {
|
func TestValidateNext_Addr(t *testing.T) {
|
||||||
v := NewValidator(string(schemaFile))
|
v, err := NewValidatorFromURL(DefaultSchemaURL)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
@@ -370,7 +382,7 @@ func TestValidateNext_Addr(t *testing.T) {
|
|||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
next := &nextSpec{Type: "addr", Required: true}
|
next := &nextSpec{Type: "addr", Required: true}
|
||||||
err := v.validateNext(tt.tag, 1, next)
|
_, err := v.validateNext(tt.tag, 1, next)
|
||||||
if tt.valid {
|
if tt.valid {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
} else {
|
} else {
|
||||||
@@ -381,71 +393,76 @@ func TestValidateNext_Addr(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestValidateNext_Free(t *testing.T) {
|
func TestValidateNext_Free(t *testing.T) {
|
||||||
v := NewValidator(string(schemaFile))
|
v, err := NewValidatorFromURL(DefaultSchemaURL)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
// free type should accept anything
|
// free type should accept anything
|
||||||
tag := nostr.Tag{"test", "any value here", "even", "multiple", "values"}
|
tag := nostr.Tag{"test", "any value here", "even", "multiple", "values"}
|
||||||
next := &nextSpec{Type: "free", Required: true}
|
next := &nextSpec{Type: "free", Required: true}
|
||||||
err := v.validateNext(tag, 1, next)
|
_, err = v.validateNext(tag, 1, next)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestValidateNext_UnknownType(t *testing.T) {
|
func TestValidateNext_UnknownType(t *testing.T) {
|
||||||
v := NewValidator(string(schemaFile))
|
v, err := NewValidatorFromURL(DefaultSchemaURL)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
tag := nostr.Tag{"test", "value"}
|
tag := nostr.Tag{"test", "value"}
|
||||||
next := &nextSpec{Type: "unknown-type", Required: true}
|
next := &nextSpec{Type: "unknown-type", Required: true}
|
||||||
|
|
||||||
// should not fail when FailOnUnknown is false (default)
|
// should not fail when FailOnUnknown is false (default)
|
||||||
err := v.validateNext(tag, 1, next)
|
_, err = v.validateNext(tag, 1, next)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// should fail when FailOnUnknown is true
|
// should fail when FailOnUnknown is true
|
||||||
v.FailOnUnknown = true
|
v.FailOnUnknown = true
|
||||||
err = v.validateNext(tag, 1, next)
|
_, err = v.validateNext(tag, 1, next)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
require.Equal(t, ErrUnknownTagType, err)
|
require.Equal(t, ErrUnknownTagType, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestValidateNext_RequiredField(t *testing.T) {
|
func TestValidateNext_RequiredField(t *testing.T) {
|
||||||
v := NewValidator(string(schemaFile))
|
v, err := NewValidatorFromURL(DefaultSchemaURL)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
// test missing required field
|
// test missing required field
|
||||||
tag := nostr.Tag{"test"} // only name, missing required value
|
tag := nostr.Tag{"test"} // only name, missing required value
|
||||||
next := &nextSpec{Type: "free", Required: true}
|
next := &nextSpec{Type: "free", Required: true}
|
||||||
err := v.validateNext(tag, 1, next)
|
_, err = v.validateNext(tag, 1, next)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
require.Contains(t, err.Error(), "missing index 1")
|
require.Contains(t, err.Error(), "missing index 1")
|
||||||
|
|
||||||
// test optional field
|
// test optional field
|
||||||
next = &nextSpec{Type: "free", Required: false}
|
next = &nextSpec{Type: "free", Required: false}
|
||||||
err = v.validateNext(tag, 1, next)
|
_, err = v.validateNext(tag, 1, next)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestValidateNext_Variadic(t *testing.T) {
|
func TestValidateNext_Variadic(t *testing.T) {
|
||||||
v := NewValidator(string(schemaFile))
|
v, err := NewValidatorFromURL(DefaultSchemaURL)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
// test variadic field with multiple values
|
// test variadic field with multiple values
|
||||||
tag := nostr.Tag{"test", "value1", "value2", "value3"}
|
tag := nostr.Tag{"test", "value1", "value2", "value3"}
|
||||||
next := &nextSpec{Type: "free", Variadic: true}
|
next := &nextSpec{Type: "free", Variadic: true}
|
||||||
err := v.validateNext(tag, 1, next)
|
_, err = v.validateNext(tag, 1, next)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// test variadic field with single value
|
// test variadic field with single value
|
||||||
tag = nostr.Tag{"test", "only-one-value"}
|
tag = nostr.Tag{"test", "only-one-value"}
|
||||||
err = v.validateNext(tag, 1, next)
|
_, err = v.validateNext(tag, 1, next)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// test variadic field with no values (should fail if required)
|
// test variadic field with no values (should fail if required)
|
||||||
tag = nostr.Tag{"test"}
|
tag = nostr.Tag{"test"}
|
||||||
next = &nextSpec{Type: "free", Variadic: true, Required: true}
|
next = &nextSpec{Type: "free", Variadic: true, Required: true}
|
||||||
err = v.validateNext(tag, 1, next)
|
_, err = v.validateNext(tag, 1, next)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestValidateEvent_Kind10002(t *testing.T) {
|
func TestValidateEvent_Kind10002(t *testing.T) {
|
||||||
v := NewValidator(string(schemaFile))
|
v, err := NewValidatorFromURL(DefaultSchemaURL)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
// kind 10002 (relay list metadata) with valid r tags
|
// kind 10002 (relay list metadata) with valid r tags
|
||||||
evt := nostr.Event{
|
evt := nostr.Event{
|
||||||
@@ -457,7 +474,7 @@ func TestValidateEvent_Kind10002(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
err := v.ValidateEvent(evt)
|
err = v.ValidateEvent(evt)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// test with invalid relay marker
|
// test with invalid relay marker
|
||||||
@@ -474,7 +491,8 @@ func TestValidateEvent_Kind10002(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestValidateEvent_Kind1_ETag(t *testing.T) {
|
func TestValidateEvent_Kind1_ETag(t *testing.T) {
|
||||||
v := NewValidator(string(schemaFile))
|
v, err := NewValidatorFromURL(DefaultSchemaURL)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
// kind 1 with e tag (reply/root marker)
|
// kind 1 with e tag (reply/root marker)
|
||||||
evt := nostr.Event{
|
evt := nostr.Event{
|
||||||
@@ -485,7 +503,7 @@ func TestValidateEvent_Kind1_ETag(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
err := v.ValidateEvent(evt)
|
err = v.ValidateEvent(evt)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// test with invalid marker
|
// test with invalid marker
|
||||||
@@ -497,7 +515,8 @@ func TestValidateEvent_Kind1_ETag(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestValidateEvent_Kind30617_RepositoryAnnouncement(t *testing.T) {
|
func TestValidateEvent_Kind30617_RepositoryAnnouncement(t *testing.T) {
|
||||||
v := NewValidator(string(schemaFile))
|
v, err := NewValidatorFromURL(DefaultSchemaURL)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
// kind 30617 (repository announcement) with required tags
|
// kind 30617 (repository announcement) with required tags
|
||||||
evt := nostr.Event{
|
evt := nostr.Event{
|
||||||
@@ -515,12 +534,13 @@ func TestValidateEvent_Kind30617_RepositoryAnnouncement(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
err := v.ValidateEvent(evt)
|
err = v.ValidateEvent(evt)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestValidateEvent_MultiplePossibleTagSpecs(t *testing.T) {
|
func TestValidateEvent_MultiplePossibleTagSpecs(t *testing.T) {
|
||||||
v := NewValidator(string(schemaFile))
|
v, err := NewValidatorFromURL(DefaultSchemaURL)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
// test event with tags that could match multiple specs
|
// test event with tags that could match multiple specs
|
||||||
// kind 1 has both "e" and "q" tags that can take different forms
|
// kind 1 has both "e" and "q" tags that can take different forms
|
||||||
@@ -533,7 +553,7 @@ func TestValidateEvent_MultiplePossibleTagSpecs(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
err := v.ValidateEvent(evt)
|
err = v.ValidateEvent(evt)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// test q tag with id format (alternative spec)
|
// test q tag with id format (alternative spec)
|
||||||
@@ -545,7 +565,8 @@ func TestValidateEvent_MultiplePossibleTagSpecs(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSchema_ErrorMessages(t *testing.T) {
|
func TestSchema_ErrorMessages(t *testing.T) {
|
||||||
v := NewValidator(string(schemaFile))
|
v, err := NewValidatorFromURL(DefaultSchemaURL)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
@@ -555,8 +576,9 @@ func TestSchema_ErrorMessages(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "empty tag error",
|
name: "empty tag error",
|
||||||
event: nostr.Event{
|
event: nostr.Event{
|
||||||
Kind: 1,
|
Kind: 1,
|
||||||
Tags: nostr.Tags{nostr.Tag{}},
|
Content: "test",
|
||||||
|
Tags: nostr.Tags{nostr.Tag{}},
|
||||||
},
|
},
|
||||||
expError: ErrEmptyTag,
|
expError: ErrEmptyTag,
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user