Skip to content

Commit

Permalink
Improve loop function (#78)
Browse files Browse the repository at this point in the history
  • Loading branch information
lucapette authored Oct 26, 2022
1 parent 4ecf9a1 commit 8d6446f
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 106 deletions.
19 changes: 12 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -300,8 +300,10 @@ functions:
- `Odd`
- `Even`

If you need to create your own loop for advanced templates you can use the `{{ Loop }}` function. This function takes a single integer as parameter which is
the number of iterations. `Loop` must be used with `range` e.g.
If you need to create your own loop for advanced templates you can use the `{{ Loop }}` function.

This function takes a single integer as parameter which is the number of
iterations. `Loop` must be used with `range` e.g.

```html
{{ range Loop 10 }} You're going to see this 10 times! {{ end }}
Expand All @@ -316,11 +318,12 @@ example:
```

In combination with `Loop` and `range` you can use `Odd` and `Even` to determine
if the current iteration is odd or even. This is especially helpful when
creating HTML tables:
if the current iteration is odd or even.

For example, this is helpful when creating HTML tables:

```html
{{ range $i, $j := Loop 5 }}
{{ range $i := Loop 5 }}
<tr>
{{ if Odd $i -}}
<td class="odd">{{- else -}}</td>
Expand All @@ -334,8 +337,10 @@ creating HTML tables:
values of `Loop 5` to the variables `$i` and `$j`.

Templates also support string manipulation via the `printf` function. Using
`printf` we can create custom output. For example to display a full name in the
format `Lastname Firstname` instead of `Firstname Lastname`.
`printf` we can create custom output.

For example, to display a full name in the format `Lastname Firstname` instead
of `Firstname Lastname`.

```html
{{ printf "%s %s" Name.Last Name.First }}
Expand Down
99 changes: 1 addition & 98 deletions integration/cli_test.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
package main
package integration

import (
"flag"
"fmt"
"os"
"os/exec"
"path/filepath"
"regexp"
"testing"

Expand All @@ -14,16 +10,6 @@ import (
"github.com/lucapette/fakedata/testutil"
)

// In these tests, there's a lot going on. Have a look at this article for a
// longer explanation:
// https://lucapette.me/writing/writing-integration-tests-for-a-go-cli-application

var update = flag.Bool("update", false, "update golden files")

const binaryName = "fakedata"

var binaryPath string

func TestCLI(t *testing.T) {
tests := []struct {
name string
Expand Down Expand Up @@ -199,86 +185,3 @@ func TestFileGenerator(t *testing.T) {
})
}
}

var templateTests = []struct {
tmpl string
golden string
wantErr bool
}{
{"simple.tmpl", "simple-template.golden", false},
{"loop.tmpl", "loop.golden", false},
{"broken.tmpl", "broken-template.golden", true},
{"unknown-function.tmpl", "unknown-function.golden", true},
}

func TestTemplatesWithCLIArgs(t *testing.T) {
for _, tt := range templateTests {
t.Run(tt.tmpl, func(t *testing.T) {
cmd := exec.Command(binaryPath, "--template", fmt.Sprintf("testutil/fixtures/%s", tt.tmpl))
output, err := cmd.CombinedOutput()
if (err != nil) != tt.wantErr {
t.Fatalf("%s\nexpected (err != nil) to be %v, but got %v. err: %v", output, tt.wantErr, err != nil, err)
}

golden := testutil.NewGoldenFile(t, tt.golden)
actual := string(output)
if *update {
golden.Write(actual)
}

expected := golden.Load()

if !reflect.DeepEqual(actual, expected) {
t.Fatalf("diff: %v", testutil.Diff(expected, actual))
}
})
}
}

func TestTemplatesWithPipe(t *testing.T) {
for _, tt := range templateTests {
t.Run(tt.tmpl, func(t *testing.T) {
fixture := testutil.NewFixture(t, tt.tmpl)
cmd := exec.Command(binaryPath)
cmd.Stdin = fixture.AsFile()
output, err := cmd.CombinedOutput()
if (err != nil) != tt.wantErr {
t.Fatalf("%s\nexpected (err != nil) to be %v, but got %v. err: %v", output, tt.wantErr, err != nil, err)
}

golden := testutil.NewGoldenFile(t, tt.golden)
actual := string(output)
if *update {
golden.Write(actual)
}

expected := golden.Load()

if !reflect.DeepEqual(actual, expected) {
t.Fatalf("diff: %v", testutil.Diff(expected, actual))
}
})
}
}

func TestMain(m *testing.M) {
err := os.Chdir("..")
if err != nil {
fmt.Printf("could not change dir: %v", err)
os.Exit(1)
}

abs, err := filepath.Abs(binaryName)
if err != nil {
fmt.Printf("could not get abs path for %s: %v", binaryName, err)
os.Exit(1)
}

binaryPath = abs

if err := exec.Command("make").Run(); err != nil {
fmt.Printf("could not make binary for %s: %v", binaryName, err)
os.Exit(1)
}
os.Exit(m.Run())
}
42 changes: 42 additions & 0 deletions integration/setup_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package integration

import (
"flag"
"fmt"
"os"
"os/exec"
"path/filepath"
"testing"
)

// In these tests, there's a lot going on. Have a look at this article for a
// longer explanation:
// https://lucapette.me/writing/writing-integration-tests-for-a-go-cli-application

var update = flag.Bool("update", false, "update golden files")

const binaryName = "fakedata"

var binaryPath string

func TestMain(m *testing.M) {
err := os.Chdir("..")
if err != nil {
fmt.Printf("could not change dir: %v", err)
os.Exit(1)
}

abs, err := filepath.Abs(binaryName)
if err != nil {
fmt.Printf("could not get abs path for %s: %v", binaryName, err)
os.Exit(1)
}

binaryPath = abs

if err := exec.Command("make").Run(); err != nil {
fmt.Printf("could not make binary for %s: %v", binaryName, err)
os.Exit(1)
}
os.Exit(m.Run())
}
72 changes: 72 additions & 0 deletions integration/templates_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package integration

import (
"fmt"
"os/exec"
"reflect"
"testing"

"github.com/lucapette/fakedata/testutil"
)

var templateTests = []struct {
tmpl string
golden string
wantErr bool
}{
{"simple.tmpl", "simple-template.golden", false},
{"loop.tmpl", "loop.golden", false},
{"loop-with-index.tmpl", "loop-with-index.golden", false},
{"broken.tmpl", "broken-template.golden", true},
{"unknown-function.tmpl", "unknown-function.golden", true},
}

func TestTemplatesWithCLIArgs(t *testing.T) {
for _, tt := range templateTests {
t.Run(tt.tmpl, func(t *testing.T) {
cmd := exec.Command(binaryPath, "--template", fmt.Sprintf("testutil/fixtures/%s", tt.tmpl))
output, err := cmd.CombinedOutput()
if (err != nil) != tt.wantErr {
t.Fatalf("%s\nexpected (err != nil) to be %v, but got %v. err: %v", output, tt.wantErr, err != nil, err)
}

golden := testutil.NewGoldenFile(t, tt.golden)
actual := string(output)
if *update {
golden.Write(actual)
}

expected := golden.Load()

if !reflect.DeepEqual(actual, expected) {
t.Fatalf("diff: %v", testutil.Diff(expected, actual))
}
})
}
}

func TestTemplatesWithPipe(t *testing.T) {
for _, tt := range templateTests {
t.Run(tt.tmpl, func(t *testing.T) {
fixture := testutil.NewFixture(t, tt.tmpl)
cmd := exec.Command(binaryPath)
cmd.Stdin = fixture.AsFile()
output, err := cmd.CombinedOutput()
if (err != nil) != tt.wantErr {
t.Fatalf("%s\nexpected (err != nil) to be %v, but got %v. err: %v", output, tt.wantErr, err != nil, err)
}

golden := testutil.NewGoldenFile(t, tt.golden)
actual := string(output)
if *update {
golden.Write(actual)
}

expected := golden.Load()

if !reflect.DeepEqual(actual, expected) {
t.Fatalf("diff: %v", testutil.Diff(expected, actual))
}
})
}
}
7 changes: 6 additions & 1 deletion pkg/fakedata/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,12 @@ func (tf templateFactory) getFunctions() template.FuncMap {
}
}

return make([]int, n)
times := make([]int, n)
for i := 0; i < n; i++ {
times[i] = i
}

return times
},
"Odd": func(i int) bool { return i%2 != 0 },
"Even": func(i int) bool { return i%2 == 0 },
Expand Down
1 change: 1 addition & 0 deletions testutil/fixtures/loop-with-index.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{{range $i := Loop 5}}{{$i}}{{end}}
10 changes: 10 additions & 0 deletions testutil/golden/loop-with-index.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
01234
01234
01234
01234
01234
01234
01234
01234
01234
01234

0 comments on commit 8d6446f

Please sign in to comment.