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