github.com/go-swagger/go-swagger@v0.31.0/generator/template_repo_test.go (about) 1 package generator 2 3 import ( 4 "bytes" 5 "testing" 6 7 "github.com/go-openapi/loads" 8 "github.com/go-openapi/swag" 9 "github.com/stretchr/testify/assert" 10 "github.com/stretchr/testify/require" 11 ) 12 13 const ( 14 // Test template environment 15 singleTemplate = `test` 16 multipleDefinitions = `{{ define "T1" }}T1{{end}}{{ define "T2" }}T2{{end}}` 17 dependantTemplate = `{{ template "T1" }}D1` 18 cirularDeps1 = `{{ define "T1" }}{{ .Name }}: {{ range .Children }}{{ template "T2" . }}{{end}}{{end}}{{template "T1" . }}` 19 cirularDeps2 = `{{ define "T2" }}{{if .Recurse }}{{ template "T1" . }}{{ else }}Children{{end}}{{end}}` 20 customHeader = `custom header` 21 customMultiple = `{{define "bindprimitiveparam" }}custom primitive{{end}}` 22 customNewTemplate = `new template` 23 customExistingUsesNew = `{{define "bindprimitiveparam" }}{{ template "newtemplate" }}{{end}}` 24 ) 25 26 func testFuncTpl() string { 27 return ` 28 Pascalize={{ pascalize "WeArePonies_Of_the_round table" }} 29 Snakize={{ snakize "WeArePonies_Of_the_round table" }} 30 Humanize={{ humanize "WeArePonies_Of_the_round table" }} 31 PluralizeFirstWord={{ pluralizeFirstWord "pony of the round table" }} 32 PluralizeFirstOfOneWord={{ pluralizeFirstWord "dwarf" }} 33 PluralizeFirstOfNoWord={{ pluralizeFirstWord "" }} 34 DropPackage={{ dropPackage "prefix.suffix" }} 35 DropNoPackage={{ dropPackage "suffix" }} 36 DropEmptyPackage={{ dropPackage "" }} 37 ContainsString={{ contains .DependsOn "x"}} 38 DoesNotContainString={{ contains .DependsOn "y"}} 39 PadSurround1={{ padSurround "padme" "-" 3 12}} 40 PadSurround2={{ padSurround "padme" "-" 0 12}} 41 Json={{ json .DefaultImports }} 42 PrettyJson={{ prettyjson . }} 43 Snakize1={{ snakize "endingInOsNameLinux" }} 44 Snakize2={{ snakize "endingInArchNameLinuxAmd64" }} 45 Snakize3={{ snakize "endingInTest" }} 46 toPackage1={{ toPackage "a/b-c/d-e" }} 47 toPackage2={{ toPackage "a.a/b_c/d_e" }} 48 toPackage3={{ toPackage "d_e" }} 49 toPackage4={{ toPackage "d-e" }} 50 toPackageName={{ toPackageName "d-e/f-g" }} 51 PascalizeSpecialChar1={{ pascalize "+1" }} 52 PascalizeSpecialChar2={{ pascalize "-1" }} 53 PascalizeSpecialChar3={{ pascalize "1" }} 54 PascalizeSpecialChar4={{ pascalize "-" }} 55 PascalizeSpecialChar5={{ pascalize "+" }} 56 PascalizeCleanupEnumVariant1={{ pascalize (cleanupEnumVariant "2.4Ghz") }} 57 Dict={{ template "dictTemplate" dict "Animal" "Pony" "Shape" "round" "Furniture" "table" }} 58 {{ define "dictTemplate" }}{{ .Animal }} of the {{ .Shape }} {{ .Furniture }}{{ end }} 59 ` 60 } 61 62 func TestTemplates_CustomTemplates(t *testing.T) { 63 var buf bytes.Buffer 64 headerTempl, err := templates.Get("bindprimitiveparam") 65 require.NoError(t, err) 66 67 err = headerTempl.Execute(&buf, nil) 68 require.NoError(t, err) 69 require.NotNil(t, buf) 70 assert.Equal(t, "\n", buf.String()) 71 72 buf.Reset() 73 err = templates.AddFile("bindprimitiveparam", customHeader) 74 require.NoError(t, err) 75 76 headerTempl, err = templates.Get("bindprimitiveparam") 77 require.NoError(t, err) 78 assert.NotNil(t, headerTempl) 79 80 err = headerTempl.Execute(&buf, nil) 81 require.NoError(t, err) 82 assert.Equal(t, "custom header", buf.String()) 83 } 84 85 func TestTemplates_CustomTemplatesMultiple(t *testing.T) { 86 var buf bytes.Buffer 87 88 err := templates.AddFile("differentFileName", customMultiple) 89 require.NoError(t, err) 90 91 headerTempl, err := templates.Get("bindprimitiveparam") 92 require.NoError(t, err) 93 94 err = headerTempl.Execute(&buf, nil) 95 require.NoError(t, err) 96 97 assert.Equal(t, "custom primitive", buf.String()) 98 } 99 100 func TestTemplates_CustomNewTemplates(t *testing.T) { 101 var buf bytes.Buffer 102 103 err := templates.AddFile("newtemplate", customNewTemplate) 104 require.NoError(t, err) 105 106 err = templates.AddFile("existingUsesNew", customExistingUsesNew) 107 require.NoError(t, err) 108 109 headerTempl, err := templates.Get("bindprimitiveparam") 110 require.NoError(t, err) 111 112 err = headerTempl.Execute(&buf, nil) 113 require.NoError(t, err) 114 115 assert.Equal(t, "new template", buf.String()) 116 } 117 118 func TestTemplates_RepoLoadingTemplates(t *testing.T) { 119 repo := NewRepository(nil) 120 121 err := repo.AddFile("simple", singleTemplate) 122 require.NoError(t, err) 123 124 templ, err := repo.Get("simple") 125 require.NoError(t, err) 126 127 var b bytes.Buffer 128 err = templ.Execute(&b, nil) 129 require.NoError(t, err) 130 131 assert.Equal(t, "test", b.String()) 132 } 133 134 func TestTemplates_RepoLoadsAllTemplatesDefined(t *testing.T) { 135 var b bytes.Buffer 136 repo := NewRepository(nil) 137 138 err := repo.AddFile("multiple", multipleDefinitions) 139 require.NoError(t, err) 140 141 templ, err := repo.Get("multiple") 142 require.NoError(t, err) 143 144 err = templ.Execute(&b, nil) 145 require.NoError(t, err) 146 147 assert.Equal(t, "", b.String()) 148 149 templ, err = repo.Get("T1") 150 require.NoError(t, err) 151 require.NotNil(t, templ) 152 153 err = templ.Execute(&b, nil) 154 require.NoError(t, err) 155 156 assert.Equal(t, "T1", b.String()) 157 } 158 159 type testData struct { 160 Children []testData 161 Name string 162 Recurse bool 163 } 164 165 func TestTemplates_RepoLoadsAllDependantTemplates(t *testing.T) { 166 var b bytes.Buffer 167 repo := NewRepository(nil) 168 169 err := repo.AddFile("multiple", multipleDefinitions) 170 require.NoError(t, err) 171 172 err = repo.AddFile("dependant", dependantTemplate) 173 require.NoError(t, err) 174 175 templ, err := repo.Get("dependant") 176 require.NoError(t, err) 177 require.NotNil(t, templ) 178 179 err = templ.Execute(&b, nil) 180 require.NoError(t, err) 181 182 assert.Equal(t, "T1D1", b.String()) 183 } 184 185 func TestTemplates_RepoRecursiveTemplates(t *testing.T) { 186 var b bytes.Buffer 187 repo := NewRepository(nil) 188 189 err := repo.AddFile("c1", cirularDeps1) 190 require.NoError(t, err) 191 192 err = repo.AddFile("c2", cirularDeps2) 193 require.NoError(t, err) 194 195 templ, err := repo.Get("c1") 196 require.NoError(t, err) 197 require.NotNil(t, templ) 198 199 data := testData{ 200 Name: "Root", 201 Children: []testData{ 202 {Recurse: false}, 203 }, 204 } 205 expected := `Root: Children` 206 err = templ.Execute(&b, data) 207 require.NoError(t, err) 208 assert.Equal(t, expected, b.String()) 209 210 data = testData{ 211 Name: "Root", 212 Children: []testData{ 213 {Name: "Child1", Recurse: true, Children: []testData{{Name: "Child2"}}}, 214 }, 215 } 216 217 b.Reset() 218 219 expected = `Root: Child1: Children` 220 221 err = templ.Execute(&b, data) 222 require.NoError(t, err) 223 224 assert.Equal(t, expected, b.String()) 225 226 data = testData{ 227 Name: "Root", 228 Children: []testData{ 229 {Name: "Child1", Recurse: false, Children: []testData{{Name: "Child2"}}}, 230 }, 231 } 232 233 b.Reset() 234 235 expected = `Root: Children` 236 237 err = templ.Execute(&b, data) 238 require.NoError(t, err) 239 240 assert.Equal(t, expected, b.String()) 241 } 242 243 // Test that definitions are available to templates 244 // TODO: should test also with the codeGenApp context 245 246 // Test copyright definition 247 func TestTemplates_DefinitionCopyright(t *testing.T) { 248 defer discardOutput()() 249 250 const copyright = `{{ .Copyright }}` 251 252 repo := NewRepository(nil) 253 254 err := repo.AddFile("copyright", copyright) 255 require.NoError(t, err) 256 257 templ, err := repo.Get("copyright") 258 require.NoError(t, err) 259 require.NotNil(t, templ) 260 261 opts := opts() 262 opts.Copyright = "My copyright clause" 263 expected := opts.Copyright 264 265 // executes template against model definitions 266 genModel, err := getModelEnvironment("../fixtures/codegen/todolist.models.yml", opts) 267 require.NoError(t, err) 268 require.NotNil(t, genModel) 269 270 rendered := bytes.NewBuffer(nil) 271 err = templ.Execute(rendered, genModel) 272 require.NoError(t, err) 273 assert.Equal(t, expected, rendered.String()) 274 275 // executes template against operations definitions 276 genOperation, err := getOperationEnvironment("get", "/media/search", "../fixtures/codegen/instagram.yml", opts) 277 require.NoError(t, err) 278 require.NotNil(t, genOperation) 279 280 rendered.Reset() 281 282 err = templ.Execute(rendered, genOperation) 283 require.NoError(t, err) 284 285 assert.Equal(t, expected, rendered.String()) 286 } 287 288 // Test TargetImportPath definition 289 func TestTemplates_DefinitionTargetImportPath(t *testing.T) { 290 const targetImportPath = `{{ .TargetImportPath }}` 291 defer discardOutput()() 292 293 repo := NewRepository(nil) 294 295 err := repo.AddFile("targetimportpath", targetImportPath) 296 require.NoError(t, err) 297 298 templ, err := repo.Get("targetimportpath") 299 require.NoError(t, err) 300 require.NotNil(t, templ) 301 302 opts := opts() 303 // Non existing target would panic: to be tested too, but in another module 304 opts.Target = "../fixtures" 305 expected := "github.com/go-swagger/go-swagger/fixtures" 306 307 // executes template against model definitions 308 genModel, err := getModelEnvironment("../fixtures/codegen/todolist.models.yml", opts) 309 require.NoError(t, err) 310 require.NotNil(t, genModel) 311 312 rendered := bytes.NewBuffer(nil) 313 err = templ.Execute(rendered, genModel) 314 require.NoError(t, err) 315 316 assert.Equal(t, expected, rendered.String()) 317 318 // executes template against operations definitions 319 genOperation, err := getOperationEnvironment("get", "/media/search", "../fixtures/codegen/instagram.yml", opts) 320 require.NoError(t, err) 321 require.NotNil(t, genOperation) 322 323 rendered.Reset() 324 325 err = templ.Execute(rendered, genOperation) 326 require.NoError(t, err) 327 328 assert.Equal(t, expected, rendered.String()) 329 } 330 331 // Simulates a definition environment for model templates 332 func getModelEnvironment(_ string, opts *GenOpts) (*GenDefinition, error) { 333 defer discardOutput()() 334 335 specDoc, err := loads.Spec("../fixtures/codegen/todolist.models.yml") 336 if err != nil { 337 return nil, err 338 } 339 definitions := specDoc.Spec().Definitions 340 341 for k, schema := range definitions { 342 genModel, err := makeGenDefinition(k, "models", schema, specDoc, opts) 343 if err != nil { 344 return nil, err 345 } 346 // One is enough 347 return genModel, nil 348 } 349 return nil, nil 350 } 351 352 // Simulates a definition environment for operation templates 353 func getOperationEnvironment(operation string, path string, spec string, opts *GenOpts) (*GenOperation, error) { 354 defer discardOutput()() 355 356 b, err := methodPathOpBuilder(operation, path, spec) 357 if err != nil { 358 return nil, err 359 } 360 b.GenOpts = opts 361 g, err := b.MakeOperation() 362 if err != nil { 363 return nil, err 364 } 365 return &g, nil 366 } 367 368 // Exercises FuncMap 369 // Just running basic tests to make sure the function map works and all functions are available as expected. 370 // More complete unit tests are provided by go-openapi/swag. 371 func TestTemplates_FuncMap(t *testing.T) { 372 defer discardOutput()() 373 374 funcTpl := testFuncTpl() 375 376 err := templates.AddFile("functpl", funcTpl) 377 require.NoError(t, err) 378 379 templ, err := templates.Get("functpl") 380 require.NoError(t, err) 381 382 opts := opts() 383 // executes template against model definitions 384 genModel, err := getModelEnvironment("../fixtures/codegen/todolist.models.yml", opts) 385 require.NoError(t, err) 386 387 genModel.DependsOn = []string{"x", "z"} 388 rendered := bytes.NewBuffer(nil) 389 err = templ.Execute(rendered, genModel) 390 require.NoError(t, err) 391 392 assert.Contains(t, rendered.String(), "Pascalize=WeArePoniesOfTheRoundTable\n") 393 assert.Contains(t, rendered.String(), "Snakize=we_are_ponies_of_the_round_table\n") 394 assert.Contains(t, rendered.String(), "Humanize=we are ponies of the round table\n") 395 assert.Contains(t, rendered.String(), "PluralizeFirstWord=ponies of the round table\n") 396 assert.Contains(t, rendered.String(), "PluralizeFirstOfOneWord=dwarves\n") 397 assert.Contains(t, rendered.String(), "PluralizeFirstOfNoWord=\n") 398 assert.Contains(t, rendered.String(), "DropPackage=suffix\n") 399 assert.Contains(t, rendered.String(), "DropNoPackage=suffix\n") 400 assert.Contains(t, rendered.String(), "DropEmptyPackage=\n") 401 assert.Contains(t, rendered.String(), "DropEmptyPackage=\n") 402 assert.Contains(t, rendered.String(), "ContainsString=true\n") 403 assert.Contains(t, rendered.String(), "DoesNotContainString=false\n") 404 assert.Contains(t, rendered.String(), "PadSurround1=-,-,-,padme,-,-,-,-,-,-,-,-\n") 405 assert.Contains(t, rendered.String(), "PadSurround2=padme,-,-,-,-,-,-,-,-,-,-,-\n") 406 assert.Contains(t, rendered.String(), `Json={"errors":"github.com/go-openapi/errors","runtime":"github.com/go-openapi/runtime","strfmt":"github.com/go-openapi/strfmt","swag":"github.com/go-openapi/swag","validate":"github.com/go-openapi/validate"}`) 407 assert.Contains(t, rendered.String(), "\"TargetImportPath\": \"github.com/go-swagger/go-swagger/generator\"") 408 assert.Contains(t, rendered.String(), "Snakize1=ending_in_os_name_linux_swagger\n") 409 assert.Contains(t, rendered.String(), "Snakize2=ending_in_arch_name_linux_amd64_swagger\n") 410 assert.Contains(t, rendered.String(), "Snakize3=ending_in_test_swagger\n") 411 assert.Contains(t, rendered.String(), "toPackage1=a/b-c/d_e\n") 412 assert.Contains(t, rendered.String(), "toPackage2=a.a/b_c/d_e\n") 413 assert.Contains(t, rendered.String(), "toPackage3=d_e\n") 414 assert.Contains(t, rendered.String(), "toPackage4=d_e\n") 415 assert.Contains(t, rendered.String(), "toPackageName=f_g\n") 416 assert.Contains(t, rendered.String(), "PascalizeSpecialChar1=Plus1\n") 417 assert.Contains(t, rendered.String(), "PascalizeSpecialChar2=Minus1\n") 418 assert.Contains(t, rendered.String(), "PascalizeSpecialChar3=Nr1\n") 419 assert.Contains(t, rendered.String(), "PascalizeSpecialChar4=Minus\n") 420 assert.Contains(t, rendered.String(), "PascalizeSpecialChar5=Plus\n") 421 assert.Contains(t, rendered.String(), "PascalizeCleanupEnumVariant1=Nr2Dot4Ghz") 422 assert.Contains(t, rendered.String(), "Dict=Pony of the round table\n") 423 } 424 425 // AddFile() global package function (protected vs unprotected) 426 // Mostly unused in tests, since the Repository.AddFile() 427 // is generally preferred. 428 func TestTemplates_AddFile(t *testing.T) { 429 defer discardOutput()() 430 431 funcTpl := testFuncTpl() 432 433 // unprotected 434 err := AddFile("functpl", funcTpl) 435 require.NoError(t, err) 436 437 _, err = templates.Get("functpl") 438 require.NoError(t, err) 439 440 // protected 441 err = AddFile("schemabody", funcTpl) 442 require.Error(t, err) 443 assert.Contains(t, err.Error(), "cannot overwrite protected template") 444 } 445 446 // Test LoadDir 447 func TestTemplates_LoadDir(t *testing.T) { 448 defer discardOutput()() 449 450 // Fails 451 err := templates.LoadDir("") 452 require.Error(t, err) 453 assert.Contains(t, err.Error(), "could not complete") 454 455 // Fails again (from any dir?) 456 err = templates.LoadDir("templates") 457 require.Error(t, err) 458 assert.Contains(t, err.Error(), "cannot overwrite protected template") 459 460 // TODO: success case 461 // To force a success, we need to empty the global list of protected 462 // templates... 463 origProtectedTemplates := protectedTemplates 464 465 defer func() { 466 // Restore variable initialized with package 467 protectedTemplates = origProtectedTemplates 468 }() 469 470 protectedTemplates = make(map[string]bool) 471 repo := NewRepository(FuncMapFunc(DefaultLanguageFunc())) 472 err = repo.LoadDir("templates") 473 require.NoError(t, err) 474 } 475 476 // Test LoadDir 477 func TestTemplates_SetAllowOverride(t *testing.T) { 478 defer discardOutput()() 479 480 // adding protected file with allowOverride set to false fails 481 templates.SetAllowOverride(false) 482 err := templates.AddFile("schemabody", "some data") 483 require.Error(t, err) 484 assert.Contains(t, err.Error(), "cannot overwrite protected template schemabody") 485 486 // adding protected file with allowOverride set to true should not fail 487 templates.SetAllowOverride(true) 488 err = templates.AddFile("schemabody", "some data") 489 require.NoError(t, err) 490 } 491 492 // Test LoadContrib 493 func TestTemplates_LoadContrib(t *testing.T) { 494 tests := []struct { 495 name string 496 template string 497 wantError bool 498 }{ 499 { 500 name: "None_existing_contributor_template", 501 template: "NonExistingContributorTemplate", 502 wantError: true, 503 }, 504 { 505 name: "Existing_contributor", 506 template: "stratoscale", 507 wantError: false, 508 }, 509 } 510 511 for _, tt := range tests { 512 t.Run(tt.name, func(t *testing.T) { 513 err := templates.LoadContrib(tt.template) 514 if tt.wantError { 515 require.Error(t, err) 516 } else { 517 require.NoError(t, err) 518 } 519 }) 520 } 521 } 522 523 // TODO: test error case in LoadDefaults() 524 // test DumpTemplates() 525 func TestTemplates_DumpTemplates(t *testing.T) { 526 var buf bytes.Buffer 527 defer captureOutput(&buf)() 528 529 templates.DumpTemplates() 530 assert.NotEmpty(t, buf) 531 // Sample output 532 assert.Contains(t, buf.String(), "## tupleSerializer") 533 assert.Contains(t, buf.String(), "Defined in `tupleserializer.gotmpl`") 534 assert.Contains(t, buf.String(), "####requires \n - schemaType") 535 } 536 537 func TestFuncMap_Pascalize(t *testing.T) { 538 assert.Equal(t, "Plus1", pascalize("+1")) 539 assert.Equal(t, "Plus", pascalize("+")) 540 assert.Equal(t, "Minus1", pascalize("-1")) 541 assert.Equal(t, "Minus", pascalize("-")) 542 assert.Equal(t, "Nr8", pascalize("8")) 543 assert.Equal(t, "Asterisk", pascalize("*")) 544 assert.Equal(t, "ForwardSlash", pascalize("/")) 545 assert.Equal(t, "EqualSign", pascalize("=")) 546 547 assert.Equal(t, "Hello", pascalize("+hello")) 548 549 // other values from swag rules 550 assert.Equal(t, "At8", pascalize("@8")) 551 assert.Equal(t, "AtHello", pascalize("@hello")) 552 assert.Equal(t, "Bang8", pascalize("!8")) 553 assert.Equal(t, "At", pascalize("@")) 554 555 // # values 556 assert.Equal(t, "Hello", pascalize("#hello")) 557 assert.Equal(t, "BangHello", pascalize("#!hello")) 558 assert.Equal(t, "HashTag8", pascalize("#8")) 559 assert.Equal(t, "HashTag", pascalize("#")) 560 561 // single '_' 562 assert.Equal(t, "Nr", pascalize("_")) 563 assert.Equal(t, "Hello", pascalize("_hello")) 564 565 // remove spaces 566 assert.Equal(t, "HelloWorld", pascalize("# hello world")) 567 assert.Equal(t, "HashTag8HelloWorld", pascalize("# 8 hello world")) 568 569 assert.Equal(t, "Empty", pascalize("")) 570 } 571 572 func TestFuncMap_DropPackage(t *testing.T) { 573 assert.Equal(t, "trail", dropPackage("base.trail")) 574 assert.Equal(t, "trail", dropPackage("base.another.trail")) 575 assert.Equal(t, "trail", dropPackage("trail")) 576 } 577 578 func TestFuncMap_AsJSON(t *testing.T) { 579 for _, jsonFunc := range []func(interface{}) (string, error){ 580 asJSON, 581 asPrettyJSON, 582 } { 583 res, err := jsonFunc(struct { 584 A string `json:"a"` 585 B int 586 }{A: "good", B: 3}) 587 require.NoError(t, err) 588 assert.JSONEq(t, `{"a":"good","B":3}`, res) 589 590 _, err = jsonFunc(struct { 591 A string `json:"a"` 592 B func() string 593 }{A: "good", B: func() string { return "" }}) 594 require.Error(t, err) 595 } 596 } 597 598 func TestFuncMap_Dict(t *testing.T) { 599 d, err := dict("a", "b", "c", "d") 600 require.NoError(t, err) 601 assert.Equal(t, map[string]interface{}{"a": "b", "c": "d"}, d) 602 603 // odd number of arguments 604 _, err = dict("a", "b", "c") 605 require.Error(t, err) 606 607 // none-string key 608 _, err = dict("a", "b", 3, "d") 609 require.Error(t, err) 610 } 611 612 func TestIsInteger(t *testing.T) { 613 var ( 614 nilString *string 615 nilInt *int 616 nilFloat *float32 617 ) 618 619 for _, anInteger := range []interface{}{ 620 int8(4), 621 int16(4), 622 int32(4), 623 int64(4), 624 int(4), 625 swag.Int(4), 626 swag.Int32(4), 627 swag.Int64(4), 628 swag.Uint(4), 629 swag.Uint32(4), 630 swag.Uint64(4), 631 float32(12), 632 float64(12), 633 swag.Float32(12), 634 swag.Float64(12), 635 "12", 636 swag.String("12"), 637 } { 638 val := anInteger 639 require.Truef(t, isInteger(val), "expected %#v to be detected an integer value", val) 640 } 641 642 for _, notAnInteger := range []interface{}{ 643 float32(12.5), 644 float64(12.5), 645 swag.Float32(12.5), 646 swag.Float64(12.5), 647 []string{"a"}, 648 struct{}{}, 649 nil, 650 map[string]int{"a": 1}, 651 "abc", 652 "2.34", 653 swag.String("2.34"), 654 nilString, 655 nilInt, 656 nilFloat, 657 } { 658 val := notAnInteger 659 require.Falsef(t, isInteger(val), "did not expect %#v to be detected an integer value", val) 660 } 661 } 662 663 func TestGt0(t *testing.T) { 664 require.True(t, gt0(swag.Int64(1))) 665 require.False(t, gt0(swag.Int64(0))) 666 require.False(t, gt0(nil)) 667 } 668 669 func TestIssue2821(t *testing.T) { 670 tpl := ` 671 Pascalize={{ pascalize . }} 672 Camelize={{ camelize . }} 673 ` 674 675 require.NoError(t, 676 templates.AddFile("functpl", tpl), 677 ) 678 679 compiled, err := templates.Get("functpl") 680 require.NoError(t, err) 681 682 rendered := bytes.NewBuffer(nil) 683 require.NoError(t, 684 compiled.Execute(rendered, "get$ref"), 685 ) 686 687 assert.Contains(t, rendered.String(), "Pascalize=GetDollarRef\n") 688 assert.Contains(t, rendered.String(), "Camelize=getDollarRef\n") 689 }