mirror of
				https://github.com/MontFerret/ferret.git
				synced 2025-10-30 23:37:40 +02:00 
			
		
		
		
	Feature/#250 wait style (#255)
* Added support for parsed styles * Added stdlib function. * Added e2e tests * Added e2e tests for STYLE_* functions
This commit is contained in:
		| @@ -21,7 +21,6 @@ func NewLib() map[string]core.Function { | ||||
| 		"REMOVE_NTH":     RemoveNth, | ||||
| 		"REMOVE_VALUE":   RemoveValue, | ||||
| 		"REMOVE_VALUES":  RemoveValues, | ||||
| 		"REVERSE":        Reverse, | ||||
| 		"SHIFT":          Shift, | ||||
| 		"SLICE":          Slice, | ||||
| 		"SORTED":         Sorted, | ||||
|   | ||||
| @@ -1,36 +0,0 @@ | ||||
| package arrays | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // Reverse return a new array with its elements reversed. | ||||
| // @param array (Array) - Target array. | ||||
| // @returns (Array) - A new array with its elements reversed. | ||||
| func Reverse(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 	err := core.ValidateArgs(args, 1, 1) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], types.Array) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	arr := args[0].(*values.Array) | ||||
| 	size := int(arr.Length()) | ||||
| 	result := values.NewArray(size) | ||||
|  | ||||
| 	for i := size - 1; i >= 0; i-- { | ||||
| 		result.Push(arr.Get(values.NewInt(i))) | ||||
| 	} | ||||
|  | ||||
| 	return result, nil | ||||
| } | ||||
| @@ -4,6 +4,7 @@ import "github.com/MontFerret/ferret/pkg/runtime/core" | ||||
|  | ||||
| func NewLib() map[string]core.Function { | ||||
| 	return map[string]core.Function{ | ||||
| 		"LENGTH": Length, | ||||
| 		"LENGTH":  Length, | ||||
| 		"REVERSE": Reverse, | ||||
| 	} | ||||
| } | ||||
|   | ||||
							
								
								
									
										51
									
								
								pkg/stdlib/collections/reverse.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								pkg/stdlib/collections/reverse.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | ||||
| package collections | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| ) | ||||
|  | ||||
| // Reverse returns the reverse of a given string or array value. | ||||
| // @param text (String|Array) - The string or array to reverse. | ||||
| // @returns (String|Array) - Returns a reversed version of a given value. | ||||
| func Reverse(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 	err := core.ValidateArgs(args, 1, 1) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.EmptyString, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], types.Array, types.String) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	switch col := args[0].(type) { | ||||
| 	case values.String: | ||||
| 		runes := []rune(string(col)) | ||||
| 		size := len(runes) | ||||
|  | ||||
| 		// Reverse | ||||
| 		for i := 0; i < size/2; i++ { | ||||
| 			runes[i], runes[size-1-i] = runes[size-1-i], runes[i] | ||||
| 		} | ||||
|  | ||||
| 		return values.NewString(string(runes)), nil | ||||
| 	case *values.Array: | ||||
| 		size := int(col.Length()) | ||||
| 		result := values.NewArray(size) | ||||
|  | ||||
| 		for i := size - 1; i >= 0; i-- { | ||||
| 			result.Push(col.Get(values.NewInt(i))) | ||||
| 		} | ||||
|  | ||||
| 		return result, nil | ||||
|  | ||||
| 	default: | ||||
| 		return values.None, nil | ||||
| 	} | ||||
| } | ||||
| @@ -1,14 +1,33 @@ | ||||
| package arrays_test | ||||
| package collections_test | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/stdlib/arrays" | ||||
| 	. "github.com/smartystreets/goconvey/convey" | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/stdlib/collections" | ||||
| 	. "github.com/smartystreets/goconvey/convey" | ||||
| ) | ||||
| 
 | ||||
| func TestReverse(t *testing.T) { | ||||
| 	Convey("When args are not passed", t, func() { | ||||
| 		Convey("It should return an error", func() { | ||||
| 			var err error | ||||
| 			_, err = collections.Reverse(context.Background()) | ||||
| 
 | ||||
| 			So(err, ShouldBeError) | ||||
| 		}) | ||||
| 	}) | ||||
| 
 | ||||
| 	Convey("Should reverse a text with right encoding", t, func() { | ||||
| 		out, _ := collections.Reverse( | ||||
| 			context.Background(), | ||||
| 			values.NewString("The quick brown 狐 jumped over the lazy 犬"), | ||||
| 		) | ||||
| 
 | ||||
| 		So(out, ShouldEqual, "犬 yzal eht revo depmuj 狐 nworb kciuq ehT") | ||||
| 	}) | ||||
| 
 | ||||
| 	Convey("Should return a copy of an array with reversed elements", t, func() { | ||||
| 		arr := values.NewArrayWith( | ||||
| 			values.NewInt(1), | ||||
| @@ -19,7 +38,7 @@ func TestReverse(t *testing.T) { | ||||
| 			values.NewInt(6), | ||||
| 		) | ||||
| 
 | ||||
| 		out, err := arrays.Reverse( | ||||
| 		out, err := collections.Reverse( | ||||
| 			context.Background(), | ||||
| 			arr, | ||||
| 		) | ||||
| @@ -31,7 +50,7 @@ func TestReverse(t *testing.T) { | ||||
| 	Convey("Should return an empty array when there no elements in a source one", t, func() { | ||||
| 		arr := values.NewArray(0) | ||||
| 
 | ||||
| 		out, err := arrays.Reverse( | ||||
| 		out, err := collections.Reverse( | ||||
| 			context.Background(), | ||||
| 			arr, | ||||
| 		) | ||||
							
								
								
									
										41
									
								
								pkg/stdlib/html/attr_get.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								pkg/stdlib/html/attr_get.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| package html | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| ) | ||||
|  | ||||
| // AttributeGet gets single or more attribute(s) of a given element. | ||||
| // @param el (HTMLElement) - Target element. | ||||
| // @param names (...String) - Attribute name(s). | ||||
| // @returns Object - Key-value pairs of attribute values. | ||||
| func AttributeGet(ctx context.Context, args ...core.Value) (core.Value, error) { | ||||
| 	err := core.ValidateArgs(args, 2, core.MaxArgs) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	el, err := resolveElement(args[0]) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	names := args[1:] | ||||
| 	result := values.NewObject() | ||||
| 	attrs := el.GetAttributes(ctx) | ||||
|  | ||||
| 	for _, n := range names { | ||||
| 		name := values.NewString(n.String()) | ||||
| 		val, exists := attrs.Get(name) | ||||
|  | ||||
| 		if exists { | ||||
| 			result.Set(name, val) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return result, nil | ||||
| } | ||||
							
								
								
									
										41
									
								
								pkg/stdlib/html/attr_remove.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								pkg/stdlib/html/attr_remove.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| package html | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // AttributeRemove removes single or more attribute(s) of a given element. | ||||
| // @param el (HTMLElement) - Target element. | ||||
| // @param names (...String) - Attribute name(s). | ||||
| func AttributeRemove(ctx context.Context, args ...core.Value) (core.Value, error) { | ||||
| 	err := core.ValidateArgs(args, 2, core.MaxArgs) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	el, err := resolveElement(args[0]) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	attrs := args[1:] | ||||
| 	attrsStr := make([]values.String, 0, len(attrs)) | ||||
|  | ||||
| 	for _, attr := range attrs { | ||||
| 		str, ok := attr.(values.String) | ||||
|  | ||||
| 		if !ok { | ||||
| 			return values.None, core.TypeError(attr.Type(), types.String) | ||||
| 		} | ||||
|  | ||||
| 		attrsStr = append(attrsStr, str) | ||||
| 	} | ||||
|  | ||||
| 	return values.None, el.RemoveAttribute(ctx, attrsStr...) | ||||
| } | ||||
							
								
								
									
										50
									
								
								pkg/stdlib/html/attr_set.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								pkg/stdlib/html/attr_set.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| package html | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // AttributeSet sets or updates a single or more attribute(s) of a given element. | ||||
| // @param el (HTMLElement) - Target element. | ||||
| // @param nameOrObj (String | Object) - Attribute name or an object representing a key-value pair of attributes. | ||||
| // @param value (String) - If a second parameter is a string value, this parameter represent an attribute value. | ||||
| func AttributeSet(ctx context.Context, args ...core.Value) (core.Value, error) { | ||||
| 	err := core.ValidateArgs(args, 2, core.MaxArgs) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	el, err := resolveElement(args[0]) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	switch arg1 := args[1].(type) { | ||||
| 	case values.String: | ||||
| 		// ATTR_SET(el, name, value) | ||||
| 		err = core.ValidateArgs(args, 3, 3) | ||||
|  | ||||
| 		if err != nil { | ||||
| 			return values.None, nil | ||||
| 		} | ||||
|  | ||||
| 		arg2, ok := args[2].(values.String) | ||||
|  | ||||
| 		if !ok { | ||||
| 			return values.None, core.TypeError(arg1.Type(), types.String, types.Object) | ||||
| 		} | ||||
|  | ||||
| 		return values.None, el.SetAttribute(ctx, arg1, arg2) | ||||
| 	case *values.Object: | ||||
| 		// ATTR_SET(el, values) | ||||
| 		return values.None, el.SetAttributes(ctx, arg1) | ||||
| 	default: | ||||
| 		return values.None, core.TypeError(arg1.Type(), types.String, types.Object) | ||||
| 	} | ||||
| } | ||||
| @@ -14,6 +14,9 @@ const defaultTimeout = 5000 | ||||
|  | ||||
| func NewLib() map[string]core.Function { | ||||
| 	return map[string]core.Function{ | ||||
| 		"ATTR_GET":          AttributeGet, | ||||
| 		"ATTR_REMOVE":       AttributeRemove, | ||||
| 		"ATTR_SET":          AttributeSet, | ||||
| 		"CLICK":             Click, | ||||
| 		"CLICK_ALL":         ClickAll, | ||||
| 		"DOCUMENT":          Document, | ||||
| @@ -40,6 +43,9 @@ func NewLib() map[string]core.Function { | ||||
| 		"SCROLL_ELEMENT":    ScrollInto, | ||||
| 		"SCROLL_TOP":        ScrollTop, | ||||
| 		"SELECT":            Select, | ||||
| 		"STYLE_GET":         StyleGet, | ||||
| 		"STYLE_REMOVE":      StyleRemove, | ||||
| 		"STYLE_SET":         StyleSet, | ||||
| 		"WAIT_ELEMENT":      WaitElement, | ||||
| 		"WAIT_NO_ELEMENT":   WaitNoElement, | ||||
| 		"WAIT_CLASS":        WaitClass, | ||||
|   | ||||
							
								
								
									
										44
									
								
								pkg/stdlib/html/style_get.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								pkg/stdlib/html/style_get.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | ||||
| package html | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| ) | ||||
|  | ||||
| // StyleGet gets single or more style attribute value(s) of a given element. | ||||
| // @param el (HTMLElement) - Target element. | ||||
| // @param names (...String) - Style name(s). | ||||
| // @returns Object - Key-value pairs of style values. | ||||
| func StyleGet(ctx context.Context, args ...core.Value) (core.Value, error) { | ||||
| 	err := core.ValidateArgs(args, 2, core.MaxArgs) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	el, err := resolveElement(args[0]) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	names := args[1:] | ||||
| 	result := values.NewObject() | ||||
|  | ||||
| 	for _, n := range names { | ||||
| 		name := values.NewString(n.String()) | ||||
| 		val, err := el.GetStyle(ctx, name) | ||||
|  | ||||
| 		if err != nil { | ||||
| 			return values.None, err | ||||
| 		} | ||||
|  | ||||
| 		if val != values.None { | ||||
| 			result.Set(name, val) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return result, nil | ||||
| } | ||||
							
								
								
									
										41
									
								
								pkg/stdlib/html/style_remove.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								pkg/stdlib/html/style_remove.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| package html | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // StyleRemove removes single or more style attribute value(s) of a given element. | ||||
| // @param el (HTMLElement) - Target element. | ||||
| // @param names (...String) - Style name(s). | ||||
| func StyleRemove(ctx context.Context, args ...core.Value) (core.Value, error) { | ||||
| 	err := core.ValidateArgs(args, 2, core.MaxArgs) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	el, err := resolveElement(args[0]) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	attrs := args[1:] | ||||
| 	attrsStr := make([]values.String, 0, len(attrs)) | ||||
|  | ||||
| 	for _, attr := range attrs { | ||||
| 		str, ok := attr.(values.String) | ||||
|  | ||||
| 		if !ok { | ||||
| 			return values.None, core.TypeError(attr.Type(), types.String) | ||||
| 		} | ||||
|  | ||||
| 		attrsStr = append(attrsStr, str) | ||||
| 	} | ||||
|  | ||||
| 	return values.None, el.RemoveStyle(ctx, attrsStr...) | ||||
| } | ||||
							
								
								
									
										44
									
								
								pkg/stdlib/html/style_set.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								pkg/stdlib/html/style_set.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | ||||
| package html | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // StyleSet sets or updates a single or more style attribute value of a given element. | ||||
| // @param el (HTMLElement) - Target element. | ||||
| // @param nameOrObj (String | Object) - Style name or an object representing a key-value pair of attributes. | ||||
| // @param value (String) - If a second parameter is a string value, this parameter represent a style value. | ||||
| func StyleSet(ctx context.Context, args ...core.Value) (core.Value, error) { | ||||
| 	err := core.ValidateArgs(args, 2, core.MaxArgs) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	el, err := resolveElement(args[0]) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	switch arg1 := args[1].(type) { | ||||
| 	case values.String: | ||||
| 		// STYLE_SET(el, name, value) | ||||
| 		err = core.ValidateArgs(args, 3, 3) | ||||
|  | ||||
| 		if err != nil { | ||||
| 			return values.None, nil | ||||
| 		} | ||||
|  | ||||
| 		return values.None, el.SetStyle(ctx, arg1, args[2]) | ||||
| 	case *values.Object: | ||||
| 		// STYLE_SET(el, values) | ||||
| 		return values.None, el.SetStyles(ctx, arg1) | ||||
| 	default: | ||||
| 		return values.None, core.TypeError(arg1.Type(), types.String, types.Object) | ||||
| 	} | ||||
| } | ||||
| @@ -1,6 +1,7 @@ | ||||
| package stdlib | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/stdlib/arrays" | ||||
| 	"github.com/MontFerret/ferret/pkg/stdlib/collections" | ||||
| @@ -17,6 +18,10 @@ func NewLib() map[string]core.Function { | ||||
|  | ||||
| 	add := func(l map[string]core.Function) { | ||||
| 		for name, fn := range l { | ||||
| 			if _, exists := lib[name]; exists { | ||||
| 				panic(fmt.Sprintf("%s function already exists", name)) | ||||
| 			} | ||||
|  | ||||
| 			lib[name] = fn | ||||
| 		} | ||||
| 	} | ||||
|   | ||||
| @@ -185,15 +185,15 @@ func isEqualObjects(obj1 *values.Object, obj2 *values.Object) bool { | ||||
| 	var val2 core.Value | ||||
|  | ||||
| 	for _, key := range obj1.Keys() { | ||||
| 		val1, _ = obj1.Get(values.NewString(key)) | ||||
| 		val2, _ = obj2.Get(values.NewString(key)) | ||||
| 		val1, _ = obj1.Get(key) | ||||
| 		val2, _ = obj2.Get(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)) | ||||
| 		val1, _ = obj1.Get(key) | ||||
| 		val2, _ = obj2.Get(key) | ||||
| 		if val2.Compare(val1) != 0 { | ||||
| 			return false | ||||
| 		} | ||||
|   | ||||
| @@ -36,7 +36,15 @@ func Keys(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		needSort = bool(args[1].(values.Boolean)) | ||||
| 	} | ||||
|  | ||||
| 	keys := sort.StringSlice(obj.Keys()) | ||||
| 	oKeys := make([]string, 0, obj.Length()) | ||||
|  | ||||
| 	obj.ForEach(func(value core.Value, key string) bool { | ||||
| 		oKeys = append(oKeys, key) | ||||
|  | ||||
| 		return true | ||||
| 	}) | ||||
|  | ||||
| 	keys := sort.StringSlice(oKeys) | ||||
| 	keysArray := values.NewArray(len(keys)) | ||||
|  | ||||
| 	if needSort { | ||||
|   | ||||
| @@ -22,7 +22,6 @@ func NewLib() map[string]core.Function { | ||||
| 		"REGEXP_SPLIT":         RegexSplit, | ||||
| 		"REGEXP_TEST":          RegexTest, | ||||
| 		"REGEXP_REPLACE":       RegexReplace, | ||||
| 		"REVERSE":              Reverse, | ||||
| 		"RIGHT":                Right, | ||||
| 		"RTRIM":                RTrim, | ||||
| 		"SHA1":                 Sha1, | ||||
|   | ||||
| @@ -1,30 +0,0 @@ | ||||
| package strings | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| ) | ||||
|  | ||||
| // Reverse returns the reverse of the string value. | ||||
| // @param text (String) - The string to revers | ||||
| // @returns (String) - Returns a reversed version of the string. | ||||
| func Reverse(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 	err := core.ValidateArgs(args, 1, 1) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.EmptyString, err | ||||
| 	} | ||||
|  | ||||
| 	text := args[0].String() | ||||
| 	runes := []rune(text) | ||||
| 	size := len(runes) | ||||
|  | ||||
| 	// Reverse | ||||
| 	for i := 0; i < size/2; i++ { | ||||
| 		runes[i], runes[size-1-i] = runes[size-1-i], runes[i] | ||||
| 	} | ||||
|  | ||||
| 	return values.NewString(string(runes)), nil | ||||
| } | ||||
| @@ -1,29 +0,0 @@ | ||||
| package strings_test | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/stdlib/strings" | ||||
| 	. "github.com/smartystreets/goconvey/convey" | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| func TestReverse(t *testing.T) { | ||||
| 	Convey("When args are not passed", t, func() { | ||||
| 		Convey("It should return an error", func() { | ||||
| 			var err error | ||||
| 			_, err = strings.Reverse(context.Background()) | ||||
|  | ||||
| 			So(err, ShouldBeError) | ||||
| 		}) | ||||
| 	}) | ||||
|  | ||||
| 	Convey("Should reverse a text with right encoding", t, func() { | ||||
| 		out, _ := strings.Reverse( | ||||
| 			context.Background(), | ||||
| 			values.NewString("The quick brown 狐 jumped over the lazy 犬"), | ||||
| 		) | ||||
|  | ||||
| 		So(out, ShouldEqual, "犬 yzal eht revo depmuj 狐 nworb kciuq ehT") | ||||
| 	}) | ||||
| } | ||||
		Reference in New Issue
	
	Block a user