1
0
mirror of https://github.com/TomWright/dasel.git synced 2022-05-22 02:32:45 +03:00
Files
dasel-data-selector/node_test.go
2020-09-22 15:06:37 +01:00

314 lines
8.6 KiB
Go

package dasel_test
import (
"errors"
"fmt"
"github.com/tomwright/dasel"
"github.com/tomwright/dasel/internal/storage"
"reflect"
"testing"
)
var (
tom = map[string]interface{}{
"name": "Tom",
"age": 28,
}
amelia = map[string]interface{}{
"name": "Amelia",
"age": 26,
}
people = []map[string]interface{}{tom, amelia}
mapC = map[string]interface{}{
"thing": "1",
}
mapB = map[string]interface{}{
"c": mapC,
"people": people,
}
mapA = map[string]interface{}{
"b": mapB,
}
mapRoot = map[string]interface{}{
"a": mapA,
}
)
type processFn func(t *testing.T, n *dasel.Node) (*dasel.Node, bool)
type checkFn func(t *testing.T, n *dasel.Node) bool
type parseTest struct {
Selector string
Input interface{}
ProcessFns []processFn
CheckFns []checkFn
Names []string
Err error
}
func (pt parseTest) Add(name string, p processFn, c checkFn) parseTest {
if pt.ProcessFns == nil {
pt.ProcessFns = make([]processFn, 0)
}
if pt.CheckFns == nil {
pt.CheckFns = make([]checkFn, 0)
}
if pt.Names == nil {
pt.Names = make([]string, 0)
}
pt.Names = append(pt.Names, name)
pt.ProcessFns = append(pt.ProcessFns, p)
pt.CheckFns = append(pt.CheckFns, c)
return pt
}
func TestNode_Query(t *testing.T) {
t.Run("ParentChildPathToProperty", func(t *testing.T) {
rootNode := dasel.New(mapRoot)
got, err := rootNode.Query(".a.b.c.thing")
if err != nil {
t.Errorf("unexpected error: %v", err)
return
}
if exp, got := "1", got.Value.(string); exp != got {
t.Errorf("expected %s, got %s", exp, got)
}
})
t.Run("ParentChildPathToIndexProperty", func(t *testing.T) {
rootNode := dasel.New(mapRoot)
got, err := rootNode.Query(".a.b.people.[1].name")
if err != nil {
t.Errorf("unexpected error: %v", err)
return
}
if exp, got := "Amelia", got.Value.(string); exp != got {
t.Errorf("expected %s, got %s", exp, got)
}
})
t.Run("ParentChildPathToDynamicProperty", func(t *testing.T) {
rootNode := dasel.New(mapRoot)
got, err := rootNode.Query(".a.b.people.(name=Tom).name")
if err != nil {
t.Errorf("unexpected error: %v", err)
return
}
if exp, got := "Tom", got.Value.(string); exp != got {
t.Errorf("expected %s, got %s", exp, got)
}
})
t.Run("ParentChildPathToMultipleDynamicProperty", func(t *testing.T) {
rootNode := dasel.New(mapRoot)
got, err := rootNode.Query(".a.b.people.(name=Tom)(age=28).name")
if err != nil {
t.Errorf("unexpected error: %v", err)
return
}
if exp, got := "Tom", got.Value.(string); exp != got {
t.Errorf("expected %s, got %s", exp, got)
}
})
t.Run("File", func(t *testing.T) {
tests := []struct {
Name string
Selector string
Exp string
}{
{Name: "Property", Selector: "name", Exp: "Tom"},
{Name: "ChildProperty", Selector: "preferences.favouriteColour", Exp: "red"},
{Name: "Index", Selector: "colours.[0]", Exp: "red"},
{Name: "Index", Selector: "colours.[1]", Exp: "green"},
{Name: "Index", Selector: "colours.[2]", Exp: "blue"},
{Name: "IndexProperty", Selector: "colourCodes.[0].name", Exp: "red"},
{Name: "IndexProperty", Selector: "colourCodes.[1].name", Exp: "green"},
{Name: "IndexProperty", Selector: "colourCodes.[2].name", Exp: "blue"},
{Name: "DynamicProperty", Selector: "colourCodes.(name=red).rgb", Exp: "ff0000"},
{Name: "DynamicProperty", Selector: "colourCodes.(name=green).rgb", Exp: "00ff00"},
{Name: "DynamicProperty", Selector: "colourCodes.(name=blue).rgb", Exp: "0000ff"},
{Name: "MultipleDynamicProperty", Selector: "colourCodes.(name=red)(rgb=ff0000).name", Exp: "red"},
{Name: "MultipleDynamicProperty", Selector: "colourCodes.(name=green)(rgb=00ff00).name", Exp: "green"},
{Name: "MultipleDynamicProperty", Selector: "colourCodes.(name=blue)(rgb=0000ff).name", Exp: "blue"},
}
fileTest := func(filename string) func(t *testing.T) {
return func(t *testing.T) {
parser, err := storage.NewParserFromFilename(filename)
if err != nil {
t.Errorf("could not get parser: %s", err)
return
}
value, err := storage.LoadFromFile(filename, parser)
if err != nil {
t.Errorf("could not load value from file: %s", err)
return
}
for _, testCase := range tests {
tc := testCase
t.Run(tc.Name, func(t *testing.T) {
node, err := dasel.New(value).Query(tc.Selector)
if err != nil {
t.Errorf("unexpected error: %s", err)
return
}
if exp, got := tc.Exp, fmt.Sprint(node.Value); exp != got {
t.Errorf("expected value `%s`, got `%s`", exp, got)
}
})
}
}
}
t.Run("JSON", fileTest("./tests/assets/example.json"))
t.Run("YAML", fileTest("./tests/assets/example.yaml"))
})
t.Run("Traversal", func(t *testing.T) {
tests := parseTest{
Selector: ".a.b.c.thing",
Input: mapRoot,
}.Add(
"StartsAtEndElement",
func(t *testing.T, n *dasel.Node) (*dasel.Node, bool) { return n, true },
func(t *testing.T, n *dasel.Node) bool {
if exp, got := ".thing", n.Selector.Current; exp != got {
t.Errorf("expected selector of `%s`, got `%s`", exp, got)
return false
}
if !reflect.DeepEqual("1", n.Value) {
t.Errorf("expected value of\n%s\ngot\n%s", "1", n.Value)
return false
}
return true
},
).Add(
"Previous1",
func(t *testing.T, n *dasel.Node) (*dasel.Node, bool) { return n.Previous, true },
func(t *testing.T, n *dasel.Node) bool {
if exp, got := ".c", n.Selector.Current; exp != got {
t.Errorf("expected selector of `%s`, got `%s`", exp, got)
return false
}
if !reflect.DeepEqual(mapC, n.Value) {
t.Errorf("expected value of\n%s\ngot\n%s", mapC, n.Value)
return false
}
return true
},
).Add(
"Previous2",
func(t *testing.T, n *dasel.Node) (*dasel.Node, bool) { return n.Previous, true },
func(t *testing.T, n *dasel.Node) bool {
if exp, got := ".b", n.Selector.Current; exp != got {
t.Errorf("expected selector of `%s`, got `%s`", exp, got)
return false
}
if !reflect.DeepEqual(mapB, n.Value) {
t.Errorf("expected value of\n%s\ngot\n%s", mapB, n.Value)
return false
}
return true
},
).Add(
"Previous3",
func(t *testing.T, n *dasel.Node) (*dasel.Node, bool) { return n.Previous, true },
func(t *testing.T, n *dasel.Node) bool {
if exp, got := ".a", n.Selector.Current; exp != got {
t.Errorf("expected selector of `%s`, got `%s`", exp, got)
return false
}
if !reflect.DeepEqual(mapA, n.Value) {
t.Errorf("expected value of\n%s\ngot\n%s", mapA, n.Value)
return false
}
return true
},
).Add(
"Next",
func(t *testing.T, n *dasel.Node) (*dasel.Node, bool) { return n.Next, true },
func(t *testing.T, n *dasel.Node) bool {
if exp, got := ".b", n.Selector.Current; exp != got {
t.Errorf("expected selector of `%s`, got `%s`", exp, got)
return false
}
if !reflect.DeepEqual(mapB, n.Value) {
t.Errorf("expected value of\n%s\ngot\n%s", mapB, n.Value)
return false
}
return true
},
).Add(
"Previous4",
func(t *testing.T, n *dasel.Node) (*dasel.Node, bool) { return n.Previous, true },
func(t *testing.T, n *dasel.Node) bool {
if exp, got := ".a", n.Selector.Current; exp != got {
t.Errorf("expected selector of `%s`, got `%s`", exp, got)
return false
}
if !reflect.DeepEqual(mapA, n.Value) {
t.Errorf("expected value of\n%s\ngot\n%s", mapA, n.Value)
return false
}
return true
},
).Add(
"Previous5",
func(t *testing.T, n *dasel.Node) (*dasel.Node, bool) { return n.Previous, true },
func(t *testing.T, n *dasel.Node) bool {
if exp, got := ".", n.Selector.Current; exp != got {
t.Errorf("expected selector of `%s`, got `%s`", exp, got)
return false
}
if !reflect.DeepEqual(mapRoot, n.Value) {
t.Errorf("expected value of\n%s\ngot\n%s", mapRoot, n.Value)
return false
}
return true
},
)
rootNode := dasel.New(tests.Input)
got, err := rootNode.Query(tests.Selector)
switch {
case err == nil && tests.Err != nil:
t.Errorf("expected err `%v`, got `%v`", tests.Err, err)
return
case err != nil && tests.Err == nil:
t.Errorf("unexpected err `%v`", err)
return
case err != nil && tests.Err != nil && !errors.Is(err, tests.Err):
t.Errorf("expected err `%v`, got `%v`", tests.Err, err)
return
}
ok := true
for i := 0; i < len(tests.ProcessFns); i++ {
if !ok {
break
}
t.Run(tests.Names[i], func(t *testing.T) {
got, ok = tests.ProcessFns[i](t, got)
if !ok {
return
}
ok = tests.CheckFns[i](t, got)
if !ok {
return
}
})
}
})
}