oficina / memoria Public

Clone
git clone https://amadan.net/oficina/memoria

Plain git — no account needed to clone.

Download

Download this file

1package memoriatest
2
3import (
4 "strings"
5 "testing"
6
7 "golang.org/x/net/html"
8)
9
10// The helpers in this file read a page the way a browser does, through
11// an HTML parser, so a check cannot be passed by spelling the same markup
12// differently: rst-refresh='x', RST-REFRESH="x" and rst-refresh=x are one
13// attribute to a browser and three strings to a regex.
14
15func parsePage(t *testing.T, body string) *html.Node {
16 t.Helper()
17 doc, err := html.Parse(strings.NewReader(body))
18 if err != nil {
19 t.Fatalf("parsing the page: %v", err)
20 }
21 return doc
22}
23
24func attrOf(n *html.Node, key string) (string, bool) {
25 for _, a := range n.Attr {
26 if a.Key == key {
27 return a.Val, true
28 }
29 }
30 return "", false
31}
32
33func findAll(root *html.Node, match func(*html.Node) bool) []*html.Node {
34 var out []*html.Node
35 var walk func(*html.Node)
36 walk = func(n *html.Node) {
37 if n.Type == html.ElementNode && match(n) {
38 out = append(out, n)
39 }
40 for c := n.FirstChild; c != nil; c = c.NextSibling {
41 walk(c)
42 }
43 }
44 walk(root)
45 return out
46}
47
48func hasAttr(key string) func(*html.Node) bool {
49 return func(n *html.Node) bool { _, ok := attrOf(n, key); return ok }
50}
51
52func elementWith(tag, key, val string) func(*html.Node) bool {
53 return func(n *html.Node) bool {
54 v, ok := attrOf(n, key)
55 return n.Data == tag && ok && v == val
56 }
57}
58
59// within reports whether n is inside ancestor, or is it.
60func within(n, ancestor *html.Node) bool {
61 for ; n != nil; n = n.Parent {
62 if n == ancestor {
63 return true
64 }
65 }
66 return false
67}
68
69func textOf(n *html.Node) string {
70 var b strings.Builder
71 var walk func(*html.Node)
72 walk = func(n *html.Node) {
73 if n.Type == html.TextNode {
74 b.WriteString(n.Data)
75 }
76 for c := n.FirstChild; c != nil; c = c.NextSibling {
77 walk(c)
78 }
79 }
80 walk(n)
81 return strings.Join(strings.Fields(b.String()), " ")
82}
83
84// region returns the one element carrying rst-refresh=name.
85func region(t *testing.T, doc *html.Node, name string) *html.Node {
86 t.Helper()
87 found := findAll(doc, func(n *html.Node) bool { v, ok := attrOf(n, "rst-refresh"); return ok && v == name })
88 if len(found) != 1 {
89 t.Fatalf("%d regions named %q on the page, want 1", len(found), name)
90 }
91 return found[0]
92}
93