github.com/instill-ai/component@v0.16.0-beta/pkg/operator/json/v0/operator_test.go (about)

     1  package json
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"testing"
     7  
     8  	qt "github.com/frankban/quicktest"
     9  	"go.uber.org/zap"
    10  	"google.golang.org/protobuf/types/known/structpb"
    11  
    12  	"github.com/instill-ai/x/errmsg"
    13  )
    14  
    15  const asJSON = `
    16  {
    17    "a": "27",
    18    "b": 27
    19  }`
    20  
    21  var asMap = map[string]any{"a": "27", "b": 27}
    22  
    23  func TestOperator_Execute(t *testing.T) {
    24  	c := qt.New(t)
    25  
    26  	testcases := []struct {
    27  		name string
    28  
    29  		task    string
    30  		in      map[string]any
    31  		want    map[string]any
    32  		wantErr string
    33  
    34  		// The marshal task will return a string with a valid JSON in the
    35  		// output. However, the format of the JSON may vary (e.g. spaces), so
    36  		// this field will be used to do a JSON comparison instead of a value
    37  		// one.
    38  		wantJSON json.RawMessage
    39  	}{
    40  		{
    41  			name: "ok - marshal",
    42  
    43  			task:     taskMarshal,
    44  			in:       map[string]any{"json": asMap},
    45  			wantJSON: json.RawMessage(asJSON),
    46  		},
    47  		{
    48  			name: "nok - marshal",
    49  
    50  			task:    taskMarshal,
    51  			in:      map[string]any{},
    52  			wantErr: "Couldn't convert the provided object to JSON.",
    53  		},
    54  		{
    55  			name: "ok - unmarshal",
    56  
    57  			task: taskUnmarshal,
    58  			in:   map[string]any{"string": asJSON},
    59  			want: map[string]any{"json": asMap},
    60  		},
    61  		{
    62  			name: "nok - unmarshal",
    63  
    64  			task:    taskUnmarshal,
    65  			in:      map[string]any{"string": `{`},
    66  			wantErr: "Couldn't parse the JSON string. Please check the syntax is correct.",
    67  		},
    68  		{
    69  			name: "ok - jq",
    70  
    71  			task: taskJQ,
    72  			in: map[string]any{
    73  				"jsonInput": `{"a": {"b": 42}}`,
    74  				"jqFilter":  ".a | .[]",
    75  			},
    76  			want: map[string]any{
    77  				"results": []any{42},
    78  			},
    79  		},
    80  		{
    81  			name: "ok - jq create object",
    82  
    83  			task: taskJQ,
    84  			in: map[string]any{
    85  				"jsonInput": `{"id": "sample", "10": {"b": 42}}`,
    86  				"jqFilter":  `{(.id): .["10"].b}`,
    87  			},
    88  			want: map[string]any{
    89  				"results": []any{
    90  					map[string]any{"sample": 42},
    91  				},
    92  			},
    93  		},
    94  		{
    95  			name: "nok - jq invalid JSON input",
    96  
    97  			task: taskJQ,
    98  			in: map[string]any{
    99  				"jsonInput": "{",
   100  				"jqFilter":  ".",
   101  			},
   102  			wantErr: "Couldn't parse the JSON input. Please check the syntax is correct.",
   103  		},
   104  		{
   105  			name: "nok - jq invalid filter",
   106  
   107  			task: taskJQ,
   108  			in: map[string]any{
   109  				"jsonInput": asJSON,
   110  				"jqFilter":  ".foo & .bar",
   111  			},
   112  			wantErr: `Couldn't parse the jq filter: unexpected token "&". Please check the syntax is correct.`,
   113  		},
   114  	}
   115  
   116  	logger := zap.NewNop()
   117  	operator := Init(logger, nil)
   118  
   119  	for _, tc := range testcases {
   120  		c.Run(tc.name, func(c *qt.C) {
   121  			exec, err := operator.CreateExecution(nil, tc.task)
   122  			c.Assert(err, qt.IsNil)
   123  
   124  			pbIn, err := structpb.NewStruct(tc.in)
   125  			c.Assert(err, qt.IsNil)
   126  
   127  			got, err := exec.Execution.Execute([]*structpb.Struct{pbIn})
   128  			if tc.wantErr != "" {
   129  				c.Check(errmsg.Message(err), qt.Matches, tc.wantErr)
   130  				return
   131  			}
   132  
   133  			c.Check(err, qt.IsNil)
   134  			c.Assert(got, qt.HasLen, 1)
   135  
   136  			if tc.wantJSON != nil {
   137  				// Check JSON in the output string.
   138  				b := got[0].Fields["string"].GetStringValue()
   139  				c.Check([]byte(b), qt.JSONEquals, tc.wantJSON)
   140  				return
   141  			}
   142  
   143  			gotJSON, err := got[0].MarshalJSON()
   144  			c.Assert(err, qt.IsNil)
   145  			c.Check(gotJSON, qt.JSONEquals, tc.want)
   146  		})
   147  	}
   148  }
   149  
   150  func TestOperator_CreateExecution(t *testing.T) {
   151  	c := qt.New(t)
   152  
   153  	logger := zap.NewNop()
   154  	operator := Init(logger, nil)
   155  
   156  	c.Run("nok - unsupported task", func(c *qt.C) {
   157  		task := "FOOBAR"
   158  		want := fmt.Sprintf("%s task is not supported.", task)
   159  
   160  		_, err := operator.CreateExecution(nil, task)
   161  		c.Check(err, qt.IsNotNil)
   162  		c.Check(errmsg.Message(err), qt.Equals, want)
   163  	})
   164  }