1package cascadia
2
3import (
4	"fmt"
5	"strings"
6	"testing"
7
8	"golang.org/x/net/html"
9)
10
11type testSpec struct {
12	// html, css selector
13	HTML, selector string
14	// correct specificity
15	spec Specificity
16}
17
18var testsSpecificity = []testSpec{
19	{
20		HTML:     `<html><body><div><div><a href="http://www.foo.com"></a></div></div></body></html>`,
21		selector: ":not(em, strong#foo)",
22		spec:     Specificity{1, 0, 1},
23	},
24	{
25		HTML:     `<html><body><div><div><a href="http://www.foo.com"></a></div></div></body></html>`,
26		selector: "*",
27		spec:     Specificity{0, 0, 0},
28	},
29	{
30		HTML:     `<html><body><div><div><ul></ul></div></div></body></html>`,
31		selector: "ul",
32		spec:     Specificity{0, 0, 1},
33	},
34	{
35		HTML:     `<html><body><div><ul><li></li></ul></div></body></html>`,
36		selector: "ul li",
37		spec:     Specificity{0, 0, 2},
38	},
39	{
40		HTML:     `<html><body><div><ul><ol></ol><li></li></ul></div></body></html>`,
41		selector: "ul ol+li",
42		spec:     Specificity{0, 0, 3},
43	},
44	{
45		HTML:     `<html><body><div><ul><h1></h1><li rel="up"></li></ul></div></body></html>`,
46		selector: "H1 + *[REL=up] ",
47		spec:     Specificity{0, 1, 1},
48	},
49	{
50		HTML:     `<html><body><ul><ol><li class="red"></li></ol></ul></body></html>`,
51		selector: "UL OL LI.red",
52		spec:     Specificity{0, 1, 3},
53	},
54	{
55		HTML:     `<html><body><ul><ol><li class="red level"></li></ol></ul></body></html>`,
56		selector: "LI.red.level",
57		spec:     Specificity{0, 2, 1},
58	},
59	{
60		HTML:     `<html><body><ul><ol><li id="x34y"></li></ol></ul></body></html>`,
61		selector: "#x34y",
62		spec:     Specificity{1, 0, 0},
63	},
64	{
65		HTML:     `<html><body><ul><ol><li id="s12"></li></ol></ul></body></html>`,
66		selector: "#s12:not(FOO)",
67		spec:     Specificity{1, 0, 1},
68	},
69	{
70		HTML:     `<html><body><ul><ol><li id="s12"></li></ol></ul></body></html>`,
71		selector: "#s12:not(FOO)",
72		spec:     Specificity{1, 0, 1},
73	},
74	{
75		HTML:     `<html><body><ul><ol><li id="s12"></li></ol></ul></body></html>`,
76		selector: "#s12:empty",
77		spec:     Specificity{1, 1, 0},
78	},
79	{
80		HTML:     `<html><body><ul><ol><li id="s12"></li></ol></ul></body></html>`,
81		selector: "#s12:only-child",
82		spec:     Specificity{1, 1, 0},
83	},
84}
85
86func setupSel(selector, HTML string) (Sel, *html.Node, error) {
87	s, err := Parse(selector)
88	if err != nil {
89		return nil, nil, fmt.Errorf("error compiling %q: %s", selector, err)
90	}
91
92	doc, err := html.Parse(strings.NewReader(HTML))
93	if err != nil {
94		return nil, nil, fmt.Errorf("error parsing %q: %s", HTML, err)
95	}
96	return s, doc, nil
97}
98
99func TestSpecificity(t *testing.T) {
100	for _, test := range testsSpecificity {
101		s, doc, err := setupSel(test.selector, test.HTML)
102		if err != nil {
103			t.Fatal(err)
104		}
105		body := doc.FirstChild.LastChild
106		testNode := body.FirstChild.FirstChild.LastChild
107		if !s.Match(testNode) {
108			t.Errorf("%s didn't match (html tree : \n %s) \n", test.selector, nodeString(doc))
109			continue
110		}
111		gotSpec := s.Specificity()
112		if gotSpec != test.spec {
113			t.Errorf("wrong specificity : expected %v, got %v", test.spec, gotSpec)
114		}
115	}
116}
117
118func TestCompareSpecificity(t *testing.T) {
119	s1, s2 := Specificity{1, 1, 0}, Specificity{1, 0, 0}
120	if s1.Less(s2) {
121		t.Fatal()
122	}
123
124	if s1.Less(s1) {
125		t.Fatal()
126	}
127}
128