Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions document_constraint.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,27 @@ func (dc DocumentConstraint) Matches(
}

for _, k := range dc.Match.Keys {
value, ok := documentMatchAttribute(d, k, vCtx.variants)
value, ok := documentMatchAttribute(d, k)
if !ok {
return NoMatch
}

check := dc.Match.Constraints[k]

_, err := check.Validate(value, ok, vCtx)
if err != nil && documentAttributeKey(k) == docAttrType {
// Fall back to the resolved variant type so that
// match expressions targeting the base type still
// apply to variant documents.
resolved := resolveVariant(d.Type, vCtx.variants)
if resolved != value {
_, err = check.Validate(resolved, ok, vCtx)
if err == nil {
value = resolved
}
}
}

if err != nil {
return NoMatch
}
Expand Down Expand Up @@ -98,9 +111,9 @@ const (
docAttrURL documentAttributeKey = "url"
)

func documentMatchAttribute(d *newsdoc.Document, name string, variants []Variant) (string, bool) {
func documentMatchAttribute(d *newsdoc.Document, name string) (string, bool) {
if documentAttributeKey(name) == docAttrType {
return resolveVariant(d.Type, variants), true
return d.Type, true
}

return "", false
Expand Down
86 changes: 86 additions & 0 deletions validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,92 @@ func TestTemplateDocumentType(t *testing.T) {
}
})

t.Run("VariantMatchExtension", func(t *testing.T) {
variantType := "core/article#prefab"

extensionSet := revisor.ConstraintSet{
Name: "test-prefab-extension",
Version: 1,
Documents: []revisor.DocumentConstraint{
{
Match: revisor.MakeConstraintMap(map[string]revisor.StringConstraint{
"type": {Const: &variantType},
}),
Meta: []*revisor.BlockConstraint{
{
Declares: &revisor.BlockSignature{
Type: "core/prefab-setting",
},
Name: "Prefab setting",
},
},
},
},
}

extValidator, err := validator.WithConstraints(extensionSet)
if err != nil {
t.Fatalf("create extended validator: %v", err)
}

extValidator = extValidator.WithVariants(revisor.Variant{Name: "prefab"})

// The prefab-setting meta block should be valid on the variant.
t.Run("VariantAcceptsExtendedBlock", func(t *testing.T) {
doc := newsdoc.Document{
Type: "core/article#prefab",
UUID: "00000000-0000-0000-0000-000000000001",
URI: "article://test/1",
Meta: []newsdoc.Block{
{Type: "core/prefab-setting"},
},
}

results, err := extValidator.ValidateDocument(ctx, &doc)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}

for _, r := range results {
if strings.Contains(r.Error, "core/prefab-setting") {
t.Errorf("prefab-setting should be allowed on variant, got: %s", r.Error)
}
}
})

// The prefab-setting meta block should not be valid on the
// base document type.
t.Run("BaseRejectsExtendedBlock", func(t *testing.T) {
doc := newsdoc.Document{
Type: "core/article",
UUID: "00000000-0000-0000-0000-000000000001",
URI: "article://test/1",
Meta: []newsdoc.Block{
{Type: "core/prefab-setting"},
},
}

results, err := extValidator.ValidateDocument(ctx, &doc)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}

found := false

for _, r := range results {
if strings.Contains(r.Error, "undeclared block") {
found = true

break
}
}

if !found {
t.Error("expected undeclared block error for prefab-setting on base document type")
}
})
})

t.Run("TypeRestrictedVariant", func(t *testing.T) {
restrictedValidator := baseValidator.WithVariants(
revisor.Variant{
Expand Down