mirror of
https://github.com/MontFerret/ferret.git
synced 2024-12-14 11:23:02 +02:00
Added object 'KEEP' function (#88)
* add unit tests for KEEP function * added KEEP function * added doc for KEYS function * addded isEqualObjects function to objects tests
This commit is contained in:
parent
ab63371892
commit
0bc4280d3f
66
pkg/stdlib/objects/keep.go
Normal file
66
pkg/stdlib/objects/keep.go
Normal file
@ -0,0 +1,66 @@
|
||||
package objects
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
)
|
||||
|
||||
/*
|
||||
* Returns a new object with only given keys.
|
||||
* @params src (Object) - source object.
|
||||
* @params keys (Array Of String OR Strings) - keys that need to be keeped.
|
||||
* @returns (Object) - New Object with only given keys.
|
||||
*/
|
||||
func Keep(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
err := core.ValidateArgs(args, 2, core.MaxArgs)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
err = core.ValidateType(args[0], core.ObjectType)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
keys := values.NewArrayWith(args[1:]...)
|
||||
|
||||
if len(args) == 2 && args[1].Type() == core.ArrayType {
|
||||
keys = args[1].(*values.Array)
|
||||
}
|
||||
|
||||
err = validateArrayOfStrings(keys)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
obj := args[0].(*values.Object)
|
||||
resultObj := values.NewObject()
|
||||
|
||||
var key values.String
|
||||
var val core.Value
|
||||
var exists values.Boolean
|
||||
|
||||
for idx := values.NewInt(0); idx < keys.Length(); idx++ {
|
||||
key = keys.Get(idx).(values.String)
|
||||
if val, exists = obj.Get(key); exists {
|
||||
resultObj.Set(key, val)
|
||||
}
|
||||
}
|
||||
|
||||
return resultObj, nil
|
||||
}
|
||||
|
||||
func validateArrayOfStrings(arr *values.Array) (err error) {
|
||||
for idx := values.NewInt(0); idx < arr.Length(); idx++ {
|
||||
err = core.ValidateType(arr.Get(idx), core.StringType)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
184
pkg/stdlib/objects/keep_test.go
Normal file
184
pkg/stdlib/objects/keep_test.go
Normal file
@ -0,0 +1,184 @@
|
||||
package objects_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
"github.com/MontFerret/ferret/pkg/stdlib/objects"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestKeep(t *testing.T) {
|
||||
Convey("When not enought arguments)", t, func() {
|
||||
// there is no object
|
||||
obj, err := objects.Keep(context.Background())
|
||||
|
||||
So(err, ShouldBeError)
|
||||
So(obj, ShouldEqual, values.None)
|
||||
|
||||
// there are no keys
|
||||
obj, err = objects.Keep(context.Background(), values.NewObject())
|
||||
|
||||
So(err, ShouldBeError)
|
||||
So(obj, ShouldEqual, values.None)
|
||||
})
|
||||
|
||||
Convey("When first argument isn't object", t, func() {
|
||||
obj, err := objects.Keep(context.Background(), values.NewInt(0))
|
||||
|
||||
So(err, ShouldBeError)
|
||||
So(obj, ShouldEqual, values.None)
|
||||
})
|
||||
|
||||
Convey("When wrong keys arguments", t, func() {
|
||||
obj, err := objects.Keep(context.Background(), values.NewObject(), values.NewInt(0))
|
||||
|
||||
So(err, ShouldBeError)
|
||||
So(obj, ShouldEqual, values.None)
|
||||
|
||||
// looks like a valid case
|
||||
// but there is another argument besides an array
|
||||
obj, err = objects.Keep(context.Background(), values.NewObject(), values.NewArray(0), values.NewInt(0))
|
||||
|
||||
So(err, ShouldBeError)
|
||||
So(obj, ShouldEqual, values.None)
|
||||
})
|
||||
}
|
||||
|
||||
func TestKeepStrings(t *testing.T) {
|
||||
Convey("Keep key 'a'", t, func() {
|
||||
obj := values.NewObjectWith(
|
||||
values.NewObjectProperty("a", values.NewInt(1)),
|
||||
values.NewObjectProperty("b", values.NewString("string")),
|
||||
)
|
||||
resultObj := values.NewObjectWith(
|
||||
values.NewObjectProperty("a", values.NewInt(1)),
|
||||
)
|
||||
|
||||
afterKeep, err := objects.Keep(context.Background(), obj, values.NewString("a"))
|
||||
|
||||
So(err, ShouldEqual, nil)
|
||||
So(afterKeep.Compare(resultObj), ShouldEqual, 0)
|
||||
})
|
||||
|
||||
Convey("Keep key doesn't exists", t, func() {
|
||||
obj := values.NewObjectWith(
|
||||
values.NewObjectProperty("a", values.NewInt(1)),
|
||||
values.NewObjectProperty("b", values.NewString("string")),
|
||||
)
|
||||
resultObj := values.NewObject()
|
||||
|
||||
afterKeep, err := objects.Keep(context.Background(), obj, values.NewString("c"))
|
||||
|
||||
So(err, ShouldEqual, nil)
|
||||
So(isEqualObjects(afterKeep.(*values.Object), resultObj), ShouldEqual, true)
|
||||
})
|
||||
|
||||
Convey("Keep when there are more keys than object properties", t, func() {
|
||||
obj := values.NewObjectWith(
|
||||
values.NewObjectProperty("a", values.NewInt(1)),
|
||||
values.NewObjectProperty("b", values.NewString("string")),
|
||||
)
|
||||
resultObj := values.NewObjectWith(
|
||||
values.NewObjectProperty("a", values.NewInt(1)),
|
||||
values.NewObjectProperty("b", values.NewString("string")),
|
||||
)
|
||||
|
||||
afterKeep, err := objects.Keep(context.Background(), obj,
|
||||
values.NewString("a"), values.NewString("b"), values.NewString("c"),
|
||||
)
|
||||
|
||||
So(err, ShouldEqual, nil)
|
||||
So(isEqualObjects(afterKeep.(*values.Object), resultObj), ShouldEqual, true)
|
||||
})
|
||||
}
|
||||
|
||||
func TestKeepArray(t *testing.T) {
|
||||
Convey("Keep array", t, func() {
|
||||
obj := values.NewObjectWith(
|
||||
values.NewObjectProperty("a", values.NewInt(1)),
|
||||
values.NewObjectProperty("b", values.NewString("string")),
|
||||
)
|
||||
keys := values.NewArrayWith(values.NewString("a"))
|
||||
resultObj := values.NewObjectWith(
|
||||
values.NewObjectProperty("a", values.NewInt(1)),
|
||||
)
|
||||
|
||||
afterKeep, err := objects.Keep(context.Background(), obj, keys)
|
||||
|
||||
So(err, ShouldEqual, nil)
|
||||
So(isEqualObjects(afterKeep.(*values.Object), resultObj), ShouldEqual, true)
|
||||
})
|
||||
|
||||
Convey("Keep empty array", t, func() {
|
||||
obj := values.NewObjectWith(
|
||||
values.NewObjectProperty("a", values.NewInt(1)),
|
||||
values.NewObjectProperty("b", values.NewString("string")),
|
||||
)
|
||||
keys := values.NewArray(0)
|
||||
resultObj := values.NewObject()
|
||||
|
||||
afterKeep, err := objects.Keep(context.Background(), obj, keys)
|
||||
|
||||
So(err, ShouldEqual, nil)
|
||||
So(isEqualObjects(afterKeep.(*values.Object), resultObj), ShouldEqual, true)
|
||||
})
|
||||
|
||||
Convey("Keep when there are more keys than object properties", t, func() {
|
||||
obj := values.NewObjectWith(
|
||||
values.NewObjectProperty("a", values.NewInt(1)),
|
||||
values.NewObjectProperty("b", values.NewString("string")),
|
||||
)
|
||||
keys := values.NewArrayWith(
|
||||
values.NewString("a"), values.NewString("b"), values.NewString("c"),
|
||||
)
|
||||
resultObj := values.NewObjectWith(
|
||||
values.NewObjectProperty("a", values.NewInt(1)),
|
||||
values.NewObjectProperty("b", values.NewString("string")),
|
||||
)
|
||||
|
||||
afterKeep, err := objects.Keep(context.Background(), obj, keys)
|
||||
|
||||
So(err, ShouldEqual, nil)
|
||||
So(isEqualObjects(afterKeep.(*values.Object), resultObj), ShouldEqual, true)
|
||||
})
|
||||
|
||||
Convey("When there is not string key", t, func() {
|
||||
obj := values.NewObjectWith(
|
||||
values.NewObjectProperty("a", values.NewInt(1)),
|
||||
values.NewObjectProperty("b", values.NewString("string")),
|
||||
)
|
||||
keys := values.NewArrayWith(
|
||||
values.NewString("a"),
|
||||
values.NewInt(0),
|
||||
)
|
||||
|
||||
afterKeep, err := objects.Keep(context.Background(), obj, keys)
|
||||
|
||||
So(err, ShouldBeError)
|
||||
So(afterKeep, ShouldEqual, values.None)
|
||||
})
|
||||
}
|
||||
|
||||
func isEqualObjects(obj1 *values.Object, obj2 *values.Object) bool {
|
||||
var val1 core.Value
|
||||
var val2 core.Value
|
||||
|
||||
for _, key := range obj1.Keys() {
|
||||
val1, _ = obj1.Get(values.NewString(key))
|
||||
val2, _ = obj2.Get(values.NewString(key))
|
||||
if val1.Compare(val2) != 0 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for _, key := range obj2.Keys() {
|
||||
val1, _ = obj1.Get(values.NewString(key))
|
||||
val2, _ = obj2.Get(values.NewString(key))
|
||||
if val2.Compare(val1) != 0 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
@ -8,6 +8,12 @@ import (
|
||||
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||
)
|
||||
|
||||
/*
|
||||
* Returns string array of object's keys
|
||||
* @params obj (Object) - The object whose keys you want to extract
|
||||
* @params sort (Boolean, optional) - If sort is true, then the returned keys will be sorted.
|
||||
* @returns (Array of String) - Array that contains object keys.
|
||||
*/
|
||||
func Keys(_ context.Context, args ...core.Value) (core.Value, error) {
|
||||
err := core.ValidateArgs(args, 1, 2)
|
||||
if err != nil {
|
||||
|
@ -6,5 +6,6 @@ func NewLib() map[string]core.Function {
|
||||
return map[string]core.Function{
|
||||
"HAS": Has,
|
||||
"KEYS": Keys,
|
||||
"KEEP": Keep,
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user