1
2
3
4
5 package present
6
7 import (
8 "bytes"
9 "fmt"
10 "html/template"
11 "os"
12 "os/exec"
13 "path/filepath"
14 "runtime"
15 "testing"
16 )
17
18 func TestTestdata(t *testing.T) {
19 tmpl := template.Must(Template().Parse(testTmpl))
20 filesP, err := filepath.Glob("testdata/*.p")
21 if err != nil {
22 t.Fatal(err)
23 }
24 filesMD, err := filepath.Glob("testdata/*.md")
25 if err != nil {
26 t.Fatal(err)
27 }
28 files := append(filesP, filesMD...)
29 for _, file := range files {
30 file := file
31 name := filepath.Base(file)
32 if name == "README" {
33 continue
34 }
35 t.Run(name, func(t *testing.T) {
36 data, err := os.ReadFile(file)
37 if err != nil {
38 t.Fatalf("%s: %v", file, err)
39 }
40 marker := []byte("\n---\n")
41 i := bytes.Index(data, marker)
42 if i < 0 {
43 t.Fatalf("%s: cannot find --- marker in input", file)
44 }
45 input, html := data[:i+1], data[i+len(marker):]
46 doc, err := Parse(bytes.NewReader(input), name, 0)
47 if err != nil {
48 t.Fatalf("%s: %v", file, err)
49 }
50 var buf bytes.Buffer
51 if err := doc.Render(&buf, tmpl); err != nil {
52 t.Fatalf("%s: %v", file, err)
53 }
54 if !bytes.Equal(buf.Bytes(), html) {
55 diffText, err := diff("present-test-", "want", html, "have", buf.Bytes())
56 if err != nil {
57 t.Fatalf("%s: diff: %v", file, err)
58 }
59 t.Errorf("%s: incorrect html:\n%s", file, diffText)
60 }
61 })
62 }
63 }
64
65 func diff(prefix string, name1 string, b1 []byte, name2 string, b2 []byte) ([]byte, error) {
66 f1, err := writeTempFile(prefix, b1)
67 if err != nil {
68 return nil, err
69 }
70 defer os.Remove(f1)
71
72 f2, err := writeTempFile(prefix, b2)
73 if err != nil {
74 return nil, err
75 }
76 defer os.Remove(f2)
77
78 cmd := "diff"
79 if runtime.GOOS == "plan9" {
80 cmd = "/bin/ape/diff"
81 }
82
83 data, err := exec.Command(cmd, "-u", f1, f2).Output()
84 if len(data) > 0 {
85
86
87 err = nil
88 } else if exit, ok := err.(*exec.ExitError); ok && len(exit.Stderr) > 0 {
89 err = fmt.Errorf("%w\nstderr:\n%s)", err, exit.Stderr)
90 }
91
92 data = bytes.Replace(data, []byte(f1), []byte(name1), -1)
93 data = bytes.Replace(data, []byte(f2), []byte(name2), -1)
94
95 return data, err
96 }
97
98 func writeTempFile(prefix string, data []byte) (string, error) {
99 file, err := os.CreateTemp("", prefix)
100 if err != nil {
101 return "", err
102 }
103 _, err = file.Write(data)
104 if err1 := file.Close(); err == nil {
105 err = err1
106 }
107 if err != nil {
108 os.Remove(file.Name())
109 return "", err
110 }
111 return file.Name(), nil
112 }
113
114 var testTmpl = `
115 {{define "root" -}}
116 <h1>{{.Title}}</h1>
117 {{with .Subtitle}}<h2>{{.}}</h2>
118 {{end -}}
119 {{range .Authors}}<author>
120 {{range .Elem}}{{elem $.Template .}}{{end}}</author>
121 {{end -}}
122 {{range .Sections}}<section>{{elem $.Template .}}</section>
123 {{end -}}
124 {{end}}
125
126 {{define "newline"}}{{/* No automatic line break. Paragraphs are free-form. */}}
127 {{end}}
128
129 {{define "section"}}
130 {{if .Title}}<h2 id="TOC_{{.FormattedNumber}}">{{.Title}}</h2>
131 {{end -}}
132 {{range .Elem}}{{elem $.Template .}}{{end}}
133 {{- end}}
134
135 {{define "list" -}}
136 <ul>
137 {{range .Bullet -}}
138 <li>{{style .}}</li>
139 {{end -}}
140 </ul>
141 {{end}}
142
143 {{define "text" -}}
144 {{if .Pre -}}
145 <pre>{{range .Lines}}{{.}}{{end}}</pre>
146 {{else -}}
147 <p>{{range $i, $l := .Lines}}{{if $i}}{{template "newline"}}{{end}}{{style $l}}{{end}}</p>
148 {{end -}}
149 {{end}}
150
151 {{define "code" -}}
152 {{if .Play -}}
153 <div class="playground">{{.Text}}</div>
154 {{else -}}
155 <div class="code">{{.Text}}</div>
156 {{end -}}
157 {{end}}
158
159 {{define "image" -}}
160 <img src="{{.URL}}"{{with .Height}} height="{{.}}"{{end}}{{with .Width}} width="{{.}}"{{end}} alt="">
161 {{end}}
162
163 {{define "caption" -}}
164 <figcaption>{{style .Text}}</figcaption>
165 {{end}}
166
167 {{define "iframe" -}}
168 <iframe src="{{.URL}}"{{with .Height}} height="{{.}}"{{end}}{{with .Width}} width="{{.}}"{{end}}></iframe>
169 {{end}}
170
171 {{define "link" -}}
172 <p class="link"><a href="{{.URL}}">{{style .Label}}</a></p>
173 {{end}}
174
175 {{define "html" -}}{{.HTML}}{{end}}
176 `
177
View as plain text