diff --git a/if_test.go b/if_test.go index ecd8515..7d67f38 100644 --- a/if_test.go +++ b/if_test.go @@ -6,192 +6,111 @@ import ( "github.com/stretchr/testify/require" ) -func Test_Render_If(t *testing.T) { - r := require.New(t) - input := `<% if (true) { return "hi"} %>` - s, err := Render(input, NewContext()) - r.NoError(err) - r.Equal("", s) -} - -func Test_Render_If_ReturnTrue(t *testing.T) { - r := require.New(t) - input := `<%= if (true == true) { return "hi"} %>` - s, err := Render(input, NewContext()) - r.NoError(err) - r.Equal("hi", s) -} - -func Test_Render_If_ReturnFalse_No_Output(t *testing.T) { - r := require.New(t) - input := `<%= if (true != true) { return "hi"} %>` - s, err := Render(input, NewContext()) - r.NoError(err) - r.Equal("", s) -} - -func Test_Render_If_True_EqualFalse(t *testing.T) { - r := require.New(t) - input := `<% let test = true %><%= if (test == false) { return "hi"} %>` - s, err := Render(input, NewContext()) - r.NoError(err) - r.Equal("", s) -} - -func Test_Render_If_Is_Test_True(t *testing.T) { - r := require.New(t) - input := `<% let test = true %><%= if (test == true) { return "hi"} %>` - s, err := Render(input, NewContext()) - r.NoError(err) - r.Equal("hi", s) -} - -func Test_Render_If_Test_Is_Not_True(t *testing.T) { - r := require.New(t) - input := `<% let test = true %><%= if (test != true) { return "hi"} %>` - s, err := Render(input, NewContext()) - r.NoError(err) - r.Equal("", s) -} - -func Test_Render_If_Test_Is_Not_Equal_One(t *testing.T) { - r := require.New(t) - input := `<% let test = 1 %><%= if (test != true) { return "hi"} %>` - _, err := Render(input, NewContext()) - r.Error(err, "line 1: unable to operate (!=) on int and bool") - -} - -func Test_Render_If_Test_Is_Equal_One(t *testing.T) { - r := require.New(t) - input := `<% let test = 1 %><%= if (test == 1) { return "hi"} %>` - s, err := Render(input, NewContext()) - r.NoError(err) - r.Equal("hi", s) - -} - -func Test_Render_If_Return(t *testing.T) { - r := require.New(t) - input := `<%= if (true) { return "hi"} %>` - s, err := Render(input, NewContext()) - r.NoError(err) - r.Equal("hi", s) -} - -func Test_Render_If_Return_HTML(t *testing.T) { - r := require.New(t) - input := `<%= if (true) { %>hi<%} %>` - s, err := Render(input, NewContext()) - r.NoError(err) - r.Equal("hi", s) -} - -func Test_Render_If_And(t *testing.T) { - r := require.New(t) - input := `<%= if (false && true) { %> hi <%} %>` - s, err := Render(input, NewContext()) - r.NoError(err) - r.Equal("", s) -} - -func Test_Render_If_And_True_True(t *testing.T) { - r := require.New(t) - input := `<%= if (2 == 2 && 1 == 1) { return "hi" } %>` - s, err := Render(input, NewContext()) - r.NoError(err) - r.Equal("hi", s) -} - -func Test_Render_If_Or(t *testing.T) { - r := require.New(t) - input := `<%= if (false || true) { %>hi<%} %>` - s, err := Render(input, NewContext()) - r.NoError(err) - r.Equal("hi", s) -} - -func Test_Render_If_Or_False_False(t *testing.T) { - r := require.New(t) - input := `<%= if (1 == 2 || 2 == 1) { return "hi" } else { return "bye" } %>` - s, err := Render(input, NewContext()) - r.NoError(err) - r.Equal("bye", s) -} - -func Test_Render_If_Nil(t *testing.T) { - r := require.New(t) - input := `<%= if (names && len(names) >= 1) { %>hi<%} %>` - s, err := Render(input, NewContext()) - r.NoError(err) - r.Equal("", s) -} - -func Test_Render_If_NotNil(t *testing.T) { - r := require.New(t) - input := `<%= if (!names) { %>hi<%} %>` - s, err := Render(input, NewContext()) - r.NoError(err) - r.Equal("hi", s) -} - -func Test_Render_If_Nil_Else(t *testing.T) { - r := require.New(t) - input := `<%= if (names && len(names) >= 1) { %>hi<%} else { %>something else<% } %>` - s, err := Render(input, NewContext()) - r.NoError(err) - r.Equal("something else", s) -} - -func Test_Render_If_Else_Return(t *testing.T) { - r := require.New(t) - input := `

<%= if (false) { return "hi"} else { return "bye"} %>

` - s, err := Render(input, NewContext()) - r.NoError(err) - r.Equal("

bye

", s) -} - -func Test_Render_If_LessThan(t *testing.T) { - r := require.New(t) - input := `

<%= if (1 < 2) { return "hi"} else { return "bye"} %>

` - s, err := Render(input, NewContext()) - r.NoError(err) - r.Equal("

hi

", s) -} - -func Test_Render_If_BangFalse(t *testing.T) { - r := require.New(t) - input := `

<%= if (!false) { return "hi"} else { return "bye"} %>

` - s, err := Render(input, NewContext()) - r.NoError(err) - r.Equal("

hi

", s) -} - -func Test_Render_If_NotEq(t *testing.T) { - r := require.New(t) - input := `

<%= if (1 != 2) { return "hi"} else { return "bye"} %>

` - s, err := Render(input, NewContext()) - r.NoError(err) - r.Equal("

hi

", s) -} - -func Test_Render_If_GtEq(t *testing.T) { - r := require.New(t) - input := `

<%= if (1 >= 2) { return "hi"} else { return "bye"} %>

` - s, err := Render(input, NewContext()) - r.NoError(err) - r.Equal("

bye

", s) -} - -func Test_Render_If_Else_True(t *testing.T) { - r := require.New(t) - input := `

<%= if (true) { %>hi<% } else { %>bye<% } %>

` - s, err := Render(input, NewContext()) - r.NoError(err) - r.Equal("

hi

", s) -} - -func Test_Render_If_Else_If_Else_True(t *testing.T) { +func Test_If_Condition(t *testing.T) { + tests := []struct { + input string + expected string + name string + success bool + }{ + {`<%= if (true) { return "good"} else { return "bad"} %>`, "good", "if_else_true", true}, + {`<%= if (false) { return "good"} else { return "bad"} %>`, "bad", "if_else_false", true}, + {`<% if (true) { return "good"} else { return "bad"} %>`, "", "missing=", true}, + {`<%= if (true) { %>good<% } %>`, "good", "value_from_template_html", true}, + {`<%= if (false) { return "good"} %>`, "", "if_false", true}, + {`<%= if (!false) { return "good"} %>`, "good", "if_bang_false", true}, + {`<%= if (true == true) { return "good"} else { return "bad"} %>`, "good", "bool_true_is_true", true}, + {`<%= if (true != true) { return "good"} else { return "bad"} %>`, "bad", "bool_true_is_not_true", true}, + {`<% let test = true %><%= if (test == false) { return "good"} %>`, "", "let_var_is_false", true}, + {`<% let test = true %><%= if (test == true) { return "good"} %>`, "good", "let_var_is_true", true}, + {`<% let test = true %><%= if (test != true) { return "good"} %>`, "", "let_var_is_not_true", true}, + {`<% let test = 1 %><%= if (test != true) { return "good"} %>`, "line 1: unable to operate (!=) on int and bool", "let_var_is_not_bool", false}, + {`<% let test = 1 %><%= if (test == 1) { return "good"} %>`, "good", "let_var_is_1", true}, + {`<%= if (false && true) { %>good<% } %>`, "", "logical_false_and_true", true}, + {`<%= if (2 == 2 && 1 == 1) { %>good<% } %>`, "good", "logical_true_and_true", true}, + {`<%= if (false || true) { %>good<% } %>`, "good", "logical_false_or_true", true}, + {`<%= if (1 == 2 || 2 == 1) { %>good<% } %>`, "", "logical_false_or_false", true}, + {`<%= if (names && len(names) >= 1) { %>good<% } %>`, "", "nil_and", true}, + {`<%= if (names && len(names) >= 1) { %>good<% } else { %>else<% } %>`, "else", "nil_and_else", true}, + {`<%= if (names) { %>good<% } %>`, "", "nil", true}, + {`<%= if (!names) { %>good<% } %>`, "good", "not_nil", true}, + {`<%= if (1 == 2) { %>good<% } %>`, "", "compare_equal_to", true}, + {`<%= if (1 != 2) { %>good<% } %>`, "good", "compare_not_equal_to", true}, + {`<%= if (1 < 2) { %>good<% } %>`, "good", "compare_less_than", true}, + {`<%= if (1 <= 2) { %>good<% } %>`, "good", "compare_less_than_equal_to", true}, + {`<%= if (1 > 2) { %>good<% } %>`, "", "compare_greater_than", true}, + {`<%= if (1 >= 2) { %>good<% } %>`, "", "compare_greater_than_equal_to", true}, + {`<%= if ("foo" ~= "bar") { %>good<% } %>`, "", "if_match_foo_bar", true}, + {`<%= if ("foo" ~= "^fo") { %>good<% } %>`, "good", "if_match_foo_^fo", true}, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + r := require.New(t) + s, err := Render(tc.input, NewContext()) + if tc.success { + r.NoError(err) + r.Equal(tc.expected, s) + } else { + r.Error(err, tc.expected) + } + }) + } +} + +func Test_Condition_Only(t *testing.T) { + ctx_empty := NewContext() + + ctx_with_paths := NewContext() + ctx_with_paths.Set("paths", "cart") + + tests := []struct { + input string + expected string + name string + success bool + context *Context + }{ + {`<%= paths == nil %>`, "true", "unknown_equal_to_nil", true, ctx_empty}, + {`<%= nil == paths %>`, "true", "nil_equal_to_unknown", true, ctx_empty}, + + {`<%= !paths %>`, "false", "NOT SET", true, ctx_with_paths}, + {`<%= !pages %>`, "true", "NOT UNKNOWN", true, ctx_with_paths}, + + {`<%= paths || pages %>`, "true", "SET_or_unknown", true, ctx_with_paths}, // fast return + {`<%= pages || paths %>`, "true", "unknown_or_SET", true, ctx_with_paths}, + {`<%= paths || pages == "cart" %>`, "true", "SET_or_unknown_equal", true, ctx_with_paths}, // fast return + {`<%= pages == "cart" || paths %>`, "true", "unknown_equal_or_SET", true, ctx_with_paths}, + {`<%= paths == "cart" || pages %>`, "true", "EQUAL_or_unknown", true, ctx_with_paths}, // fast return + {`<%= pages || paths == "cart" %>`, "true", "unknown_or_EQUAL", true, ctx_with_paths}, + {`<%= paths == "cart" || pages == "cart" %>`, "true", "EQUAL_or_unknown_equal", true, ctx_with_paths}, // fast return + {`<%= pages == "cart" || paths == "cart" %>`, "true", "unknown_equal_or_EQUAL", true, ctx_with_paths}, + + {`<%= paths && pages %>`, "false", "set_and_UNKNOWN==false", true, ctx_with_paths}, + {`<%= pages && paths %>`, "false", "UNKNOWN_and_set==false", true, ctx_with_paths}, // fast return + {`<%= paths && pages == "cart" %>`, "false", "set_and_UNKNOWN_equal==false", true, ctx_with_paths}, + {`<%= pages == "cart" && paths %>`, "false", "UNKNOWN_equal_and_set==false", true, ctx_with_paths}, // fast return + {`<%= paths == "cart" && pages %>`, "false", "equal_and_UNKNOWN", true, ctx_with_paths}, + {`<%= pages && paths == "cart" %>`, "false", "UNKNOWN_and_equal", true, ctx_with_paths}, // fast return + {`<%= paths == "cart" && pages == "cart" %>`, "false", "equal_and_UNKNOWN_equal", true, ctx_with_paths}, + {`<%= pages == "cart" && paths == "cart" %>`, "false", "UNKNOWN_equal_and_equal", true, ctx_with_paths}, // fast return + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + r := require.New(t) + s, err := Render(tc.input, tc.context) + if tc.success { + r.NoError(err) + r.Equal(tc.expected, s) + } else { + r.Error(err, tc.expected) + } + }) + } +} + +func Test_If_Else_If_Else_True(t *testing.T) { r := require.New(t) ctx := NewContext() input := `

<%= if (state == "foo") { %>hi foo<% } else if (state == "bar") { %>hi bar<% } else if (state == "fizz") { %>hi fizz<% } else { %>hi buzz<% } %>

` @@ -217,14 +136,6 @@ func Test_Render_If_Else_If_Else_True(t *testing.T) { r.Equal("

hi buzz

", s) } -func Test_Render_If_Matches(t *testing.T) { - r := require.New(t) - input := `

<%= if ("foo" ~= "bar") { return "hi" } else { return "bye" } %>

` - s, err := Render(input, NewContext()) - r.NoError(err) - r.Equal("

bye

", s) -} - func Test_If_String_Truthy(t *testing.T) { r := require.New(t) @@ -242,26 +153,7 @@ func Test_If_String_Truthy(t *testing.T) { r.Equal("

hi

", s) } -func Test_Render_If_Variable_Is_Set(t *testing.T) { - r := require.New(t) - input := `<%= if (names) { %>hi<%} %>` - ctx := NewContext() - ctx.Set("names", "123") - s, err := Render(input, ctx) - r.NoError(err) - r.Equal("hi", s) -} - -func Test_Render_If_Variable_Not_Set(t *testing.T) { - r := require.New(t) - input := `<%= if (names) { %>hi<%} %>` - - s, err := Render(input, NewContext()) - r.NoError(err) - r.Equal("", s) -} - -func Test_Render_If_Variable_Not_Set_But_Or_Condition_Is_True(t *testing.T) { +func Test_If_Variable_Not_Set_But_Or_Condition_Is_True_Complex(t *testing.T) { r := require.New(t) ctx := NewContext() ctx.Set("path", "cart") @@ -273,7 +165,7 @@ func Test_Render_If_Variable_Not_Set_But_Or_Condition_Is_True(t *testing.T) { r.Equal("hi", s) } -func Test_Render_If_Variable_Not_Set_But_Or_Condition_While_Node_Is_True_Includes_Syntax_Error_Last_Node(t *testing.T) { +func Test_If_Syntax_Error_On_Last_Node(t *testing.T) { r := require.New(t) ctx := NewContext() ctx.Set("paths", "cart") @@ -283,7 +175,7 @@ func Test_Render_If_Variable_Not_Set_But_Or_Condition_While_Node_Is_True_Include r.Error(err) } -func Test_Render_If_Variable_Not_Set_But_Or_Condition_While_Node_Is_True_Includes_Syntax_Error_First_Node(t *testing.T) { +func Test_If_Syntax_Error_On_First_Node(t *testing.T) { r := require.New(t) ctx := NewContext() ctx.Set("paths", "cart") @@ -292,40 +184,3 @@ func Test_Render_If_Variable_Not_Set_But_Or_Condition_While_Node_Is_True_Include _, err := Render(input, ctx) r.Error(err) } - -func Test_Render_If_Variable_Not_Set_But_Or_Condition_Left_Node_Is_True(t *testing.T) { - r := require.New(t) - ctx := NewContext() - ctx.Set("paths", "cart") - input := `<%= if ( paths == "cart" || pages ) { %>hi<%} %>` - - s, err := Render(input, ctx) - r.NoError(err) - r.Equal("hi", s) -} - -func Test_Render_If_Variable_Not_Set_But_Or_Condition_Right_Node_Is_True(t *testing.T) { - r := require.New(t) - ctx := NewContext() - ctx.Set("pages", "cart") - input := `<%= if ( paths == "cart" || pages ) { %>hi<%} %>` - - s, err := Render(input, ctx) - r.NoError(err) - r.Equal("hi", s) -} - -func Test_Condition_UnsetIsNil(t *testing.T) { - r := require.New(t) - ctx := NewContext() - - input := `<%= paths == nil %>` - s, err := Render(input, ctx) - r.NoError(err) - r.Equal("true", s) - - input = `<%= nil == paths %>` - s, err = Render(input, ctx) - r.NoError(err) - r.Equal("true", s) -} diff --git a/quotes_test.go b/quotes_test.go index 94f49ad..c0b6679 100644 --- a/quotes_test.go +++ b/quotes_test.go @@ -6,29 +6,23 @@ import ( "github.com/stretchr/testify/require" ) -func Test_MissingQuote(t *testing.T) { - r := require.New(t) - input := `<%= foo("asdf) %>` - ctx := NewContext() - ctx.Set("foo", func(string) {}) - _, err := Render(input, ctx) - r.Error(err) -} - -func Test_MissingQuote_Variant(t *testing.T) { - r := require.New(t) - input := `<%= foo("test) %>".` - ctx := NewContext() - ctx.Set("foo", func(string) {}) - _, err := Render(input, ctx) - r.Error(err) -} +func Test_Quote_Missing(t *testing.T) { + tests := []struct { + name string + input string + }{ + {"case1", `<%= foo("asdf) %>`}, + {"case2", `<%= foo("test) %>".`}, + {"case3", `<%= title("Running Migrations) %>(default "./migrations")`}, + } -func Test_MissingQuote_Variant2(t *testing.T) { - r := require.New(t) - input := `<%= title("Running Migrations) %>(default "./migrations")` - ctx := NewContext() - ctx.Set("foo", func(string) {}) - _, err := Render(input, ctx) - r.Error(err) + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + r := require.New(t) + ctx := NewContext() + ctx.Set("foo", func(string) {}) + _, err := Render(tc.input, ctx) + r.Error(err) + }) + } } diff --git a/return_exit_test.go b/return_exit_test.go index 5d544ee..6306b5b 100644 --- a/return_exit_test.go +++ b/return_exit_test.go @@ -7,82 +7,69 @@ import ( "github.com/stretchr/testify/require" ) -func Test_Return_Exit_With_InfixExpression(t *testing.T) { - r := require.New(t) - input := ` - <% - let numberify = fn(arg) { - if (arg == "one") { - return 1+1; - } - if (arg == "two") { - return 44; - } - if (arg == "three") { - return 2; - } - return "unsupported" - } - %> - <%= numberify("one") %> - ` - s, err := Render(input, NewContext()) - - r.NoError(err) - r.Equal("2", strings.TrimSpace(s)) -} - -func Test_Simple_Return_Exit(t *testing.T) { - r := require.New(t) - - input := ` - <% - let numberify = fn(arg) { - if (arg == "one") { - return 1; - } - if (arg == "two") { - return 445; - } - if (arg == "three") { - return 3; - } - return "unsupported" - } - %> - <%= numberify("two") %> - ` - - s, err := Render(input, NewContext()) - r.NoError(err) - r.Equal("445", strings.TrimSpace(s)) -} - -func Test_Simple_Return_Default(t *testing.T) { - r := require.New(t) - - input := ` - <% - let numberify = fn(arg) { - if (arg == "one") { - return 1; - } - if (arg == "two") { - return 445; - } - if (arg == "three") { - return 3; - } - return "unsupported" - } - %> - <%= numberify("six") %> - ` - - s, err := Render(input, NewContext()) - - r.NoError(err) - r.Equal("unsupported", strings.TrimSpace(s)) +func Test_Return_Exit_With__InfixExpression(t *testing.T) { + tests := []struct { + name string + success bool + expected string + input string + }{ + {"infix_expression", true, "2", `<% + let numberify = fn(arg) { + if (arg == "one") { + return 1+1; + } + if (arg == "two") { + return 44; + } + if (arg == "three") { + return 2; + } + return "unsupported" + } %> + <%= numberify("one") %>`}, + {"simple_return", true, "445", `<% + let numberify = fn(arg) { + if (arg == "one") { + return 1; + } + if (arg == "two") { + return 445; + } + if (arg == "three") { + return 3; + } + return "unsupported" + } %> + <%= numberify("two") %>`}, + {"default_return", true, "default value", `<% + let numberify = fn(arg) { + if (arg == "one") { + return 1; + } + if (arg == "two") { + return 445; + } + if (arg == "three") { + return 3; + } + return "default value" + } %> + <%= numberify("six") %>`}, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + r := require.New(t) + + s, err := Render(tc.input, NewContext()) + if tc.success { + r.NoError(err) + } else { + r.Error(err) + } + r.Equal(tc.expected, strings.TrimSpace(s)) + }) + } } func Test_User_Function_Return(t *testing.T) { diff --git a/variables_test.go b/variables_test.go index 5496dc9..a3d2c89 100644 --- a/variables_test.go +++ b/variables_test.go @@ -71,90 +71,57 @@ func Test_Let_Inside_Helper(t *testing.T) { } func Test_Render_Let_Hash(t *testing.T) { - r := require.New(t) - - input := `

<% let h = {"a": "A"} %><%= h["a"] %>

` - s, err := Render(input, NewContext()) - r.NoError(err) - r.Equal("

A

", s) -} - -func Test_Render_Let_HashAssign(t *testing.T) { - r := require.New(t) - - input := `

<% let h = {"a": "A"} %><% h["a"] = "C"%><%= h["a"] %>

` - s, err := Render(input, NewContext()) - r.NoError(err) - r.Equal("

C

", s) -} - -func Test_Render_Let_HashAssign_NewKey(t *testing.T) { - r := require.New(t) - - input := `

<% let h = {"a": "A"} %><% h["b"] = "d" %><%= h["b"] %>

` - s, err := Render(input, NewContext()) - r.NoError(err) - r.Equal("

d

", s) -} - -func Test_Render_Let_HashAssign_Int(t *testing.T) { - r := require.New(t) - - input := `

<% let h = {"a": "A"} %><% h["b"] = 3 %><%= h["b"] %>

` - s, err := Render(input, NewContext()) - r.NoError(err) - r.Equal("

3

", s) -} - -func Test_Render_Let_HashAssign_InvalidKey(t *testing.T) { - r := require.New(t) - - input := `

<% let h = {"a": "A"} %><% h["b"] = 3 %><%= h["c"] %>

` - s, err := Render(input, NewContext()) - r.NoError(err) - r.Equal("

", s) -} - -func Test_Render_Let_ArrayAssign_InvalidKey(t *testing.T) { - r := require.New(t) - - input := `

<% let a = [1, 2, "three", "four", 3.75] %><% a["b"] = 3 %><%= a["c"] %>

` - _, err := Render(input, NewContext()) - r.Error(err) -} - -func Test_Render_Let_ArrayAssign_ValidIndex(t *testing.T) { - r := require.New(t) - - input := `

<% let a = [1, 2, "three", "four", 3.75] %><% a[0] = 3 %><%= a[0] %>

` - s, err := Render(input, NewContext()) - r.NoError(err) - r.Equal("

3

", s) -} - -func Test_Render_Let_ArrayAssign_Resultaddition(t *testing.T) { - r := require.New(t) - - input := `

<% let a = [1, 2, "three", "four", 3.75] %><% a[4] = 3 %><%= a[4] + 2 %>

` - s, err := Render(input, NewContext()) - r.NoError(err) - r.Equal("

5

", s) -} - -func Test_Render_Let_ArrayAssign_OutofBoundsIndex(t *testing.T) { - r := require.New(t) - - input := `

<% let a = [1, 2, "three", "four", 3.75] %><% a[5] = 3 %><%= a[4] + 2 %>

` - _, err := Render(input, NewContext()) - r.Error(err) -} - -func Test_Render_Access_Array_OutofBoundsIndex(t *testing.T) { - r := require.New(t) - - input := `<% let a = [1, 2, "three", "four", 3.75] %><%= a[5] %>` - _, err := Render(input, NewContext()) - r.Error(err) + tests := []struct { + name string + success bool + input string + expected string + }{ + {"success", true, `

<% let h = {"a": "A"} %><%= h["a"] %>

`, "

A

"}, + {"assign", true, `

<% let h = {"a": "A"} %><% h["a"] = "C" %><%= h["a"] %>

`, "

C

"}, + {"assign", true, `

<% let h = {"a": "A"} %><% h["b"] = "D" %><%= h["b"] %>

`, "

D

"}, + {"intvar", true, `

<% let h = {"a": "A"} %><% h["b"] = 3 %><%= h["b"] %>

`, "

3

"}, + {"invalid", true, `

<% let h = {"a": "A"} %><% h["b"] = 3 %><%= h["c"] %>

`, "

"}, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + r := require.New(t) + s, err := Render(tc.input, NewContext()) + if tc.success { + r.NoError(err) + } else { + r.Error(err) + } + r.Equal(tc.expected, s) + }) + } +} + +func Test_Render_Let_Array(t *testing.T) { + tests := []struct { + name string + success bool + input string + expected string + }{ + {"success", true, `

<% let a = [1, 2, "three", "four", 3.75] %><% a[0] = 3 %><%= a[0] %>

`, "

3

"}, + {"addition", true, `

<% let a = [1, 2, "three", "four", 3.75] %><% a[4] = 3 %><%= a[4] + 2 %>

`, "

5

"}, + {"invalid_key", false, `

<% let a = [1, 2, "three", "four", 3.75] %><% a["b"] = 3 %><%= a["c"] %>

`, ""}, + {"outofbounds_assign", false, `

<% let a = [1, 2, "three", "four", 3.75] %><% a[5] = 3 %><%= a[4] + 2 %>

`, ""}, + {"outofbounds_access", false, `

<% let a = [1, 2, "three", "four", 3.75] %><%= a[5] %>

`, ""}, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + r := require.New(t) + s, err := Render(tc.input, NewContext()) + if tc.success { + r.NoError(err) + } else { + r.Error(err) + } + r.Equal(tc.expected, s) + }) + } } type Category1 struct { @@ -164,12 +131,37 @@ type Product1 struct { Name []string } -func Test_Render_Access_CalleeArray_OutofBoundIndex(t *testing.T) { - r := require.New(t) - ctx := NewContext() - product_listing := Category1{} - ctx.Set("product_listing", product_listing) - input := `<% let a = product_listing.Products[0].Name[0] %><%= a %>` - _, err := Render(input, ctx) - r.Error(err) +func Test_Render_Access_CalleeArray(t *testing.T) { + tests := []struct { + name string + success bool + expected string + data Category1 + }{ + {"success", true, "Buffalo", Category1{ + []Product1{ + {Name: []string{"Buffalo"}}, + }, + }}, + {"outofbounds", false, "", Category1{}}, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + r := require.New(t) + input := `<% let a = product_listing.Products[0].Name[0] %><%= a %>` + + ctx := NewContext() + ctx.Set("product_listing", tc.data) + + s, err := Render(input, ctx) + if tc.success { + r.NoError(err) + } else { + r.Error(err) + } + r.Equal(tc.expected, s) + }) + } + }