github.com/hairyhenderson/gomplate/v3@v3.11.7/render_test.go (about) 1 package gomplate 2 3 import ( 4 "bytes" 5 "context" 6 "fmt" 7 "net/url" 8 "os" 9 "strings" 10 "testing" 11 "testing/fstest" 12 13 "github.com/hairyhenderson/go-fsimpl" 14 "github.com/hairyhenderson/gomplate/v3/data" 15 "github.com/stretchr/testify/assert" 16 ) 17 18 func TestRenderTemplate(t *testing.T) { 19 fsys := fstest.MapFS{} 20 ctx := ContextWithFSProvider(context.Background(), 21 fsimpl.WrappedFSProvider(fsys, "mem")) 22 23 // no options - built-in function 24 tr := NewRenderer(Options{}) 25 out := &bytes.Buffer{} 26 err := tr.Render(ctx, "test", "{{ `hello world` | toUpper }}", out) 27 assert.NoError(t, err) 28 assert.Equal(t, "HELLO WORLD", out.String()) 29 30 // with datasource and context 31 hu, _ := url.Parse("stdin:") 32 wu, _ := url.Parse("env:WORLD") 33 34 os.Setenv("WORLD", "world") 35 defer os.Unsetenv("WORLD") 36 37 tr = NewRenderer(Options{ 38 Context: map[string]Datasource{ 39 "hi": {URL: hu}, 40 }, 41 Datasources: map[string]Datasource{ 42 "world": {URL: wu}, 43 }, 44 }) 45 ctx = data.ContextWithStdin(ctx, strings.NewReader("hello")) 46 out = &bytes.Buffer{} 47 err = tr.Render(ctx, "test", `{{ .hi | toUpper }} {{ (ds "world") | toUpper }}`, out) 48 assert.NoError(t, err) 49 assert.Equal(t, "HELLO WORLD", out.String()) 50 51 // with a nested template 52 nu, _ := url.Parse("nested.tmpl") 53 fsys["nested.tmpl"] = &fstest.MapFile{Data: []byte( 54 `<< . | toUpper >>`)} 55 56 tr = NewRenderer(Options{ 57 Templates: map[string]Datasource{ 58 "nested": {URL: nu}, 59 }, 60 LDelim: "<<", 61 RDelim: ">>", 62 }) 63 out = &bytes.Buffer{} 64 err = tr.Render(ctx, "test", `<< template "nested" "hello" >>`, out) 65 assert.NoError(t, err) 66 assert.Equal(t, "HELLO", out.String()) 67 68 // errors contain the template name 69 tr = NewRenderer(Options{}) 70 err = tr.Render(ctx, "foo", `{{ bogus }}`, &bytes.Buffer{}) 71 assert.ErrorContains(t, err, "template: foo:") 72 } 73 74 //// examples 75 76 func ExampleRenderer() { 77 ctx := context.Background() 78 79 // create a new template renderer 80 tr := NewRenderer(Options{}) 81 82 // render a template to stdout 83 err := tr.Render(ctx, "mytemplate", 84 `{{ "hello, world!" | toUpper }}`, 85 os.Stdout) 86 if err != nil { 87 fmt.Println("gomplate error:", err) 88 } 89 90 // Output: 91 // HELLO, WORLD! 92 } 93 94 func ExampleRenderer_manyTemplates() { 95 ctx := context.Background() 96 97 // create a new template renderer 98 tr := NewRenderer(Options{}) 99 100 templates := []Template{ 101 { 102 Name: "one.tmpl", 103 Text: `contents of {{ tmpl.Path }}`, 104 Writer: &bytes.Buffer{}, 105 }, 106 { 107 Name: "two.tmpl", 108 Text: `{{ "hello world" | toUpper }}`, 109 Writer: &bytes.Buffer{}, 110 }, 111 { 112 Name: "three.tmpl", 113 Text: `1 + 1 = {{ math.Add 1 1 }}`, 114 Writer: &bytes.Buffer{}, 115 }, 116 } 117 118 // render the templates 119 err := tr.RenderTemplates(ctx, templates) 120 if err != nil { 121 panic(err) 122 } 123 124 for _, t := range templates { 125 fmt.Printf("%s: %s\n", t.Name, t.Writer.(*bytes.Buffer).String()) 126 } 127 128 // Output: 129 // one.tmpl: contents of one.tmpl 130 // two.tmpl: HELLO WORLD 131 // three.tmpl: 1 + 1 = 2 132 } 133 134 func ExampleRenderer_datasources() { 135 ctx := context.Background() 136 137 // a datasource that retrieves JSON from a maritime registry dataset 138 u, _ := url.Parse("https://www.econdb.com/maritime/vessel/9437/") 139 tr := NewRenderer(Options{ 140 Context: map[string]Datasource{ 141 "vessel": {URL: u}, 142 }, 143 }) 144 145 err := tr.Render(ctx, "jsontest", 146 `{{"\U0001F6A2"}} The {{ .vessel.data.Name }}'s call sign is {{ .vessel.data.Callsign }}, `+ 147 `and it has a draught of {{ .vessel.data.Draught }}.`, 148 os.Stdout) 149 if err != nil { 150 panic(err) 151 } 152 }