github.com/coveo/gotemplate@v2.7.7+incompatible/template/razor_test.go (about)

     1  package template
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"os"
     7  	"path/filepath"
     8  	"reflect"
     9  	"runtime/debug"
    10  	"strings"
    11  	"testing"
    12  
    13  	"github.com/coveo/gotemplate/collections"
    14  	"github.com/coveo/gotemplate/json"
    15  	logging "github.com/op/go-logging"
    16  	"github.com/sergi/go-diff/diffmatchpatch"
    17  )
    18  
    19  func TestTemplate_applyRazor(t *testing.T) {
    20  	t.Parallel()
    21  	dmp := diffmatchpatch.New()
    22  	SetLogLevel(logging.WARNING)
    23  	template := MustNewTemplate("../docs/doc_test", nil, "", nil)
    24  	files, err := filepath.Glob(filepath.Join(template.folder, "*.md"))
    25  	if err != nil {
    26  		t.Fatalf("Unable to read test files (documentation in %s)", template.folder)
    27  		t.Fail()
    28  	}
    29  
    30  	type test struct {
    31  		name   string
    32  		path   string
    33  		razor  string
    34  		render string
    35  	}
    36  
    37  	ifExist := func(path string) string {
    38  		if _, err := os.Stat(path); err != nil {
    39  			return ""
    40  		}
    41  		return path
    42  	}
    43  
    44  	collections.ListHelper = json.GenericListHelper
    45  	collections.DictionaryHelper = json.DictionaryHelper
    46  	template.options[AcceptNoValue] = true
    47  
    48  	load := func(path string) []byte { return must(ioutil.ReadFile(path)).([]byte) }
    49  
    50  	tests := make([]test, 0, len(files))
    51  	for _, file := range files {
    52  		path := strings.TrimSuffix(file, ".md")
    53  		tests = append(tests, test{
    54  			name:   filepath.Base(path),
    55  			path:   file,
    56  			razor:  ifExist(path + ".razor"),
    57  			render: ifExist(path + ".rendered"),
    58  		})
    59  	}
    60  
    61  	for _, tt := range tests {
    62  		t.Run(tt.name, func(t *testing.T) {
    63  			template.options[Razor] = tt.razor != ""
    64  
    65  			content := load(tt.path)
    66  			if tt.razor != "" {
    67  				result := load(tt.razor)
    68  				got := template.applyRazor(content)
    69  				if !reflect.DeepEqual(got, result) {
    70  					diffs := dmp.DiffMain(string(result), string(got), true)
    71  					t.Errorf("Differences on Razor result for %s\n%s", tt.razor, dmp.DiffPrettyText(diffs))
    72  				}
    73  			}
    74  
    75  			var got string
    76  			var err error
    77  			func() {
    78  				defer func() {
    79  					if rec := recover(); rec != nil {
    80  						err = fmt.Errorf("Template.ProcessContent() panic=%v\n%s", rec, string(debug.Stack()))
    81  					}
    82  				}()
    83  				got, err = template.ProcessContent(string(content), tt.path)
    84  			}()
    85  
    86  			if err != nil {
    87  				t.Errorf("Template.ProcessContent(), err=%v", err)
    88  			} else if tt.render != "" {
    89  				result := string(load(tt.render))
    90  				if !reflect.DeepEqual(got, result) {
    91  					diffs := dmp.DiffMain(string(result), string(got), true)
    92  					t.Errorf("Differences on Rendered for %s\n%s", tt.render, dmp.DiffPrettyText(diffs))
    93  				}
    94  			}
    95  		})
    96  	}
    97  }
    98  
    99  func TestBase(t *testing.T) {
   100  	t.Parallel()
   101  	tests := []struct {
   102  		name  string
   103  		razor string
   104  		want  string
   105  	}{
   106  		{"Empty", "", ""},
   107  		{
   108  			"Simple global variable",
   109  			"@Hello",
   110  			"{{ $.Hello }}",
   111  		},
   112  		{
   113  			"Email",
   114  			"Hello john.doe@company.com",
   115  			"Hello john.doe@company.com",
   116  		},
   117  		{
   118  			"Literal",
   119  			"Hello john.doe@@company",
   120  			"Hello john.doe@company",
   121  		},
   122  		{
   123  			"No razor",
   124  			"{{ gotemplate }}",
   125  			"{{ gotemplate }}",
   126  		},
   127  		{
   128  			"Mix",
   129  			"@test {{ gotemplate }}",
   130  			"{{ $.test }} {{ gotemplate }}",
   131  		},
   132  	}
   133  	for _, tt := range tests {
   134  		t.Run(tt.name, func(t *testing.T) {
   135  			template := MustNewTemplate(".", nil, "", nil)
   136  			if got := template.applyRazor([]byte(tt.razor)); string(got) != tt.want {
   137  				t.Errorf("applyRazor() = got %s, want %s", got, tt.want)
   138  			}
   139  		})
   140  	}
   141  }
   142  
   143  func TestInvocation(t *testing.T) {
   144  	tests := []struct {
   145  		name       string
   146  		debugLevel int
   147  		razor      string
   148  		want       string
   149  	}{
   150  		{
   151  			"Func call", 2,
   152  			"@func(1,2,3)",
   153  			"{{ func 1 2 3 }}",
   154  		},
   155  		{
   156  			"Method call", 2,
   157  			"@object.func(1,2,3)",
   158  			"{{ $.object.func 1 2 3 }}",
   159  		},
   160  		{
   161  			"Method call on result", 2,
   162  			"@object.func(1,2).func2(3)",
   163  			"{{ ($.object.func 1 2).func2 3 }}",
   164  		},
   165  		{
   166  			"Double invocation", 2,
   167  			"@func1().func2()",
   168  			"{{ func1.func2 }}",
   169  		},
   170  		{
   171  			"Double invocation with params", 6,
   172  			"@func1(1).func2(2)",
   173  			"{{ (func1 1).func2 2 }}",
   174  		},
   175  	}
   176  	for _, tt := range tests {
   177  		t.Run(tt.name, func(t *testing.T) {
   178  			logging.SetLevel(logging.Level(tt.debugLevel), loggerInternal)
   179  			defer func() { logging.SetLevel(logging.Level(2), loggerInternal) }()
   180  			template := MustNewTemplate(".", nil, "", nil)
   181  			if got := template.applyRazor([]byte(tt.razor)); string(got) != tt.want {
   182  				t.Errorf("applyRazor() = got %s, want %s", got, tt.want)
   183  			}
   184  		})
   185  	}
   186  }
   187  
   188  func TestAssign(t *testing.T) {
   189  	t.Parallel()
   190  	tests := []struct {
   191  		name  string
   192  		razor string
   193  		want  string
   194  	}{
   195  		{
   196  			"Local assign",
   197  			"@{a} := 2",
   198  			"{{- $a := 2 }}",
   199  		},
   200  		{
   201  			"Local assign 2",
   202  			"@{a := 2}",
   203  			"{{- $a := 2 }}",
   204  		},
   205  		{
   206  			"Local assign 3",
   207  			"@$a := 2",
   208  			`{{- $a := 2 }}`,
   209  		},
   210  		{
   211  			"Global assign",
   212  			`@a := "test"`,
   213  			`{{- assertWarning (isNil $.a) "$.a has already been declared, use = to overwrite existing value" }}{{- set $ "a" "test" }}`,
   214  		},
   215  		{
   216  			"Deprecated local assign with no other razor",
   217  			`$a := "test"`,
   218  			`$a := "test"`,
   219  		},
   220  		{
   221  			"Deprecated local assign",
   222  			`@test; $a := $.test`,
   223  			`{{ $.test }} {{- $a := $.test }}`,
   224  		},
   225  	}
   226  	for _, tt := range tests {
   227  		t.Run(tt.name, func(t *testing.T) {
   228  			template := MustNewTemplate(".", nil, "", nil)
   229  			if got := template.applyRazor([]byte(tt.razor)); string(got) != tt.want {
   230  				t.Errorf("applyRazor() = got %s, want %s", got, tt.want)
   231  			}
   232  		})
   233  	}
   234  }
   235  
   236  func TestAutoWrap(t *testing.T) {
   237  	t.Parallel()
   238  	tests := []struct {
   239  		name  string
   240  		razor string
   241  		want  string
   242  	}{
   243  		{
   244  			"Base",
   245  			"Before @autoWrap(to(10)) after",
   246  			`{{ join "" (formatList "Before %v after" (to 10)) }}`,
   247  		},
   248  		{
   249  			"With newline",
   250  			"Before @<aWrap(to(10)) after",
   251  			`{{- $.NEWLINE }}{{ join "\n" (formatList "Before %v after" (to 10)) }}`,
   252  		},
   253  		{
   254  			"With space eater",
   255  			"Before @--awrap(to(10)) after",
   256  			`{{- join "" (formatList "Before %v after" (to 10)) -}}`,
   257  		},
   258  		{
   259  			"With error",
   260  			"Before @--awrap(to(10) after",
   261  			"Before {{- awrap to(10 -}} after",
   262  		},
   263  	}
   264  	for _, tt := range tests {
   265  		t.Run(tt.name, func(t *testing.T) {
   266  			template := MustNewTemplate(".", nil, "", nil)
   267  			if got := template.applyRazor([]byte(tt.razor)); string(got) != tt.want {
   268  				t.Errorf("applyRazor() = got %s, want %s", got, tt.want)
   269  			}
   270  		})
   271  	}
   272  }
   273  
   274  func TestSpaceEater(t *testing.T) {
   275  	t.Parallel()
   276  	tests := []struct {
   277  		name  string
   278  		razor string
   279  		want  string
   280  	}{
   281  		{
   282  			"Base",
   283  			"@value",
   284  			`{{ $.value }}`,
   285  		},
   286  		{
   287  			"Before",
   288  			"@-value",
   289  			`{{- $.value }}`,
   290  		},
   291  		{
   292  			"After",
   293  			"@_-value",
   294  			`{{ $.value -}}`,
   295  		},
   296  		{
   297  			"Both",
   298  			"@--value",
   299  			`{{- $.value -}}`,
   300  		},
   301  	}
   302  	for _, tt := range tests {
   303  		t.Run(tt.name, func(t *testing.T) {
   304  			template := MustNewTemplate(".", nil, "", nil)
   305  			if got := template.applyRazor([]byte(tt.razor)); string(got) != tt.want {
   306  				t.Errorf("applyRazor() = got %s, want %s", got, tt.want)
   307  			}
   308  		})
   309  	}
   310  }