github.com/suntong/cascadia@v1.3.0/cascadia_test.go (about)

     1  package main
     2  
     3  import (
     4  	"bytes"
     5  	"strings"
     6  	"testing"
     7  )
     8  
     9  func TestSelectors(t *testing.T) {
    10  	for _, test := range selectorTests {
    11  		buf := bytes.NewBufferString("")
    12  		Opts.CSS, Opts.Piece, Opts.Deli,
    13  			Opts.WrapHTML, Opts.TextOut, Opts.TextRaw, Opts.Quiet =
    14  			[]string{test.selector}, PieceStyleMap{}, ",",
    15  			false, false, false, false
    16  		Cascadia(strings.NewReader(test.HTML), buf, Opts)
    17  		got := buf.String()
    18  		if len(got) == 0 && len(test.results) == 0 {
    19  			// correct
    20  			continue
    21  		}
    22  		want := strings.Join(test.results, "\n") + "\n"
    23  		if got != want {
    24  			t.Errorf("wanted %s, got %s instead", want, got)
    25  		}
    26  	}
    27  }
    28  
    29  // //////////////////////////////////////////////////////////////////////////
    30  // The following is taken from
    31  // https://github.com/andybalholm/cascadia/blob/c56252c33997d9b9991f4c1e3b5fbc82d6d656b3/selector_test.go
    32  type selectorTest struct {
    33  	HTML, selector string
    34  	results        []string
    35  }
    36  
    37  var selectorTests = []selectorTest{
    38  	{
    39  		`<html><head></head><body></body></html>`,
    40  		"*",
    41  		[]string{
    42  			"<html><head></head><body></body></html>",
    43  			"<head></head>",
    44  			"<body></body>",
    45  		},
    46  	},
    47  	{
    48  		`<p id="foo"><p id="bar">`,
    49  		"#foo",
    50  		[]string{
    51  			`<p id="foo"></p>`,
    52  		},
    53  	},
    54  	{
    55  		`<ul><li id="t1"><p id="t1">`,
    56  		"li#t1",
    57  		[]string{
    58  			`<li id="t1"><p id="t1"></p></li>`,
    59  		},
    60  	},
    61  	{
    62  		`<ol><li id="t4"><li id="t44">`,
    63  		"*#t4",
    64  		[]string{
    65  			`<li id="t4"></li>`,
    66  		},
    67  	},
    68  	{
    69  		`<ul><li class="t1"><li class="t2">`,
    70  		".t1",
    71  		[]string{
    72  			`<li class="t1"></li>`,
    73  		},
    74  	},
    75  	{
    76  		`<p class="t1 t2">`,
    77  		"p.t1",
    78  		[]string{
    79  			`<p class="t1 t2"></p>`,
    80  		},
    81  	},
    82  	{
    83  		`<div class="test">`,
    84  		"div.teST",
    85  		[]string{},
    86  	},
    87  	{
    88  		`<p class="t1 t2">`,
    89  		".t1.fail",
    90  		[]string{},
    91  	},
    92  	{
    93  		`<p class="t1 t2">`,
    94  		"p.t1.t2",
    95  		[]string{
    96  			`<p class="t1 t2"></p>`,
    97  		},
    98  	},
    99  	{
   100  		`<p><p title="title">`,
   101  		"p[title]",
   102  		[]string{
   103  			`<p title="title"></p>`,
   104  		},
   105  	},
   106  	{
   107  		`<address><address title="foo"><address title="bar">`,
   108  		`address[title="foo"]`,
   109  		[]string{
   110  			`<address title="foo"><address title="bar"></address></address>`,
   111  		},
   112  	},
   113  	{
   114  		`<address><address title="foo"><address title="bar">`,
   115  		`address[title!="foo"]`,
   116  		[]string{
   117  			`<address><address title="foo"><address title="bar"></address></address></address>`,
   118  			`<address title="bar"></address>`,
   119  		},
   120  	},
   121  	{
   122  		`<p title="tot foo bar">`,
   123  		`[    	title        ~=       foo    ]`,
   124  		[]string{
   125  			`<p title="tot foo bar"></p>`,
   126  		},
   127  	},
   128  	{
   129  		`<p title="hello world">`,
   130  		`[title~="hello world"]`,
   131  		[]string{},
   132  	},
   133  	{
   134  		`<p lang="en"><p lang="en-gb"><p lang="enough"><p lang="fr-en">`,
   135  		`[lang|="en"]`,
   136  		[]string{
   137  			`<p lang="en"></p>`,
   138  			`<p lang="en-gb"></p>`,
   139  		},
   140  	},
   141  	{
   142  		`<p title="foobar"><p title="barfoo">`,
   143  		`[title^="foo"]`,
   144  		[]string{
   145  			`<p title="foobar"></p>`,
   146  		},
   147  	},
   148  	{
   149  		`<p title="foobar"><p title="barfoo">`,
   150  		`[title$="bar"]`,
   151  		[]string{
   152  			`<p title="foobar"></p>`,
   153  		},
   154  	},
   155  	{
   156  		`<p title="foobarufoo">`,
   157  		`[title*="bar"]`,
   158  		[]string{
   159  			`<p title="foobarufoo"></p>`,
   160  		},
   161  	},
   162  	{
   163  		`<input type="radio" name="Sex" value="F"/>`,
   164  		`input[name=Sex][value=F]`,
   165  		[]string{
   166  			`<input type="radio" name="Sex" value="F"/>`,
   167  		},
   168  	},
   169  	{
   170  		`<table border="0" cellpadding="0" cellspacing="0" style="table-layout: fixed; width: 100%; border: 0 dashed; border-color: #FFFFFF"><tr style="height:64px">aaa</tr></table>`,
   171  		`table[border="0"][cellpadding="0"][cellspacing="0"]`,
   172  		[]string{
   173  			`<table border="0" cellpadding="0" cellspacing="0" style="table-layout: fixed; width: 100%; border: 0 dashed; border-color: #FFFFFF"><tbody><tr style="height:64px"></tr></tbody></table>`,
   174  		},
   175  	},
   176  	{
   177  		`<p class="t1 t2">`,
   178  		".t1:not(.t2)",
   179  		[]string{},
   180  	},
   181  	{
   182  		`<div class="t3">`,
   183  		`div:not(.t1)`,
   184  		[]string{
   185  			`<div class="t3"></div>`,
   186  		},
   187  	},
   188  	{
   189  		`<div><div class="t2"><div class="t3">`,
   190  		`div:not([class="t2"])`,
   191  		[]string{
   192  			`<div><div class="t2"><div class="t3"></div></div></div>`,
   193  			`<div class="t3"></div>`,
   194  		},
   195  	},
   196  	{
   197  		`<ol><li id=1><li id=2><li id=3></ol>`,
   198  		`li:nth-child(odd)`,
   199  		[]string{
   200  			`<li id="1"></li>`,
   201  			`<li id="3"></li>`,
   202  		},
   203  	},
   204  	{
   205  		`<ol><li id=1><li id=2><li id=3></ol>`,
   206  		`li:nth-child(even)`,
   207  		[]string{
   208  			`<li id="2"></li>`,
   209  		},
   210  	},
   211  	{
   212  		`<ol><li id=1><li id=2><li id=3></ol>`,
   213  		`li:nth-child(-n+2)`,
   214  		[]string{
   215  			`<li id="1"></li>`,
   216  			`<li id="2"></li>`,
   217  		},
   218  	},
   219  	{
   220  		`<ol><li id=1><li id=2><li id=3></ol>`,
   221  		`li:nth-child(3n+1)`,
   222  		[]string{
   223  			`<li id="1"></li>`,
   224  		},
   225  	},
   226  	{
   227  		`<ol><li id=1><li id=2><li id=3><li id=4></ol>`,
   228  		`li:nth-last-child(odd)`,
   229  		[]string{
   230  			`<li id="2"></li>`,
   231  			`<li id="4"></li>`,
   232  		},
   233  	},
   234  	{
   235  		`<ol><li id=1><li id=2><li id=3><li id=4></ol>`,
   236  		`li:nth-last-child(even)`,
   237  		[]string{
   238  			`<li id="1"></li>`,
   239  			`<li id="3"></li>`,
   240  		},
   241  	},
   242  	{
   243  		`<ol><li id=1><li id=2><li id=3><li id=4></ol>`,
   244  		`li:nth-last-child(-n+2)`,
   245  		[]string{
   246  			`<li id="3"></li>`,
   247  			`<li id="4"></li>`,
   248  		},
   249  	},
   250  	{
   251  		`<ol><li id=1><li id=2><li id=3><li id=4></ol>`,
   252  		`li:nth-last-child(3n+1)`,
   253  		[]string{
   254  			`<li id="1"></li>`,
   255  			`<li id="4"></li>`,
   256  		},
   257  	},
   258  	{
   259  		`<p>some text <span id="1">and a span</span><span id="2"> and another</span></p>`,
   260  		`span:first-child`,
   261  		[]string{
   262  			`<span id="1">and a span</span>`,
   263  		},
   264  	},
   265  	{
   266  		`<span>a span</span> and some text`,
   267  		`span:last-child`,
   268  		[]string{
   269  			`<span>a span</span>`,
   270  		},
   271  	},
   272  	{
   273  		`<address></address><p id=1><p id=2>`,
   274  		`p:nth-of-type(2)`,
   275  		[]string{
   276  			`<p id="2"></p>`,
   277  		},
   278  	},
   279  	{
   280  		`<address></address><p id=1><p id=2></p><a>`,
   281  		`p:nth-last-of-type(2)`,
   282  		[]string{
   283  			`<p id="1"></p>`,
   284  		},
   285  	},
   286  	{
   287  		`<address></address><p id=1><p id=2></p><a>`,
   288  		`p:last-of-type`,
   289  		[]string{
   290  			`<p id="2"></p>`,
   291  		},
   292  	},
   293  	{
   294  		`<address></address><p id=1><p id=2></p><a>`,
   295  		`p:first-of-type`,
   296  		[]string{
   297  			`<p id="1"></p>`,
   298  		},
   299  	},
   300  	{
   301  		`<div><p id="1"></p><a></a></div><div><p id="2"></p></div>`,
   302  		`p:only-child`,
   303  		[]string{
   304  			`<p id="2"></p>`,
   305  		},
   306  	},
   307  	{
   308  		`<div><p id="1"></p><a></a></div><div><p id="2"></p><p id="3"></p></div>`,
   309  		`p:only-of-type`,
   310  		[]string{
   311  			`<p id="1"></p>`,
   312  		},
   313  	},
   314  	{
   315  		`<p id="1"><!-- --><p id="2">Hello<p id="3"><span>`,
   316  		`:empty`,
   317  		[]string{
   318  			`<head></head>`,
   319  			`<p id="1"><!-- --></p>`,
   320  			`<span></span>`,
   321  		},
   322  	},
   323  	{
   324  		`<div><p id="1"><table><tr><td><p id="2"></table></div><p id="3">`,
   325  		`div p`,
   326  		[]string{
   327  			`<p id="1"><table><tbody><tr><td><p id="2"></p></td></tr></tbody></table></p>`,
   328  			`<p id="2"></p>`,
   329  		},
   330  	},
   331  	{
   332  		`<div><p id="1"><table><tr><td><p id="2"></table></div><p id="3">`,
   333  		`div table p`,
   334  		[]string{
   335  			`<p id="2"></p>`,
   336  		},
   337  	},
   338  	{
   339  		`<div><p id="1"><div><p id="2"></div><table><tr><td><p id="3"></table></div>`,
   340  		`div > p`,
   341  		[]string{
   342  			`<p id="1"></p>`,
   343  			`<p id="2"></p>`,
   344  		},
   345  	},
   346  	{
   347  		`<p id="1"><p id="2"></p><address></address><p id="3">`,
   348  		`p ~ p`,
   349  		[]string{
   350  			`<p id="2"></p>`,
   351  			`<p id="3"></p>`,
   352  		},
   353  	},
   354  	{
   355  		`<p id="1"></p>
   356  		 <!--comment-->
   357  		 <p id="2"></p><address></address><p id="3">`,
   358  		`p + p`,
   359  		[]string{
   360  			`<p id="2"></p>`,
   361  		},
   362  	},
   363  	{
   364  		`<ul><li></li><li></li></ul><p>`,
   365  		`li, p`,
   366  		[]string{
   367  			"<li></li>",
   368  			"<li></li>",
   369  			"<p></p>",
   370  		},
   371  	},
   372  	{
   373  		`<p id="1"><p id="2"></p><address></address><p id="3">`,
   374  		`p +/*This is a comment*/ p`,
   375  		[]string{
   376  			`<p id="2"></p>`,
   377  		},
   378  	},
   379  	{
   380  		`<p>Text block that <span>wraps inner text</span> and continues</p>`,
   381  		`p:contains("that wraps")`,
   382  		[]string{
   383  			`<p>Text block that <span>wraps inner text</span> and continues</p>`,
   384  		},
   385  	},
   386  	{
   387  		`<p>Text block that <span>wraps inner text</span> and continues</p>`,
   388  		`p:containsOwn("that wraps")`,
   389  		[]string{},
   390  	},
   391  	{
   392  		`<p>Text block that <span>wraps inner text</span> and continues</p>`,
   393  		`:containsOwn("inner")`,
   394  		[]string{
   395  			`<span>wraps inner text</span>`,
   396  		},
   397  	},
   398  	{
   399  		`<p>Text block that <span>wraps inner text</span> and continues</p>`,
   400  		`p:containsOwn("block")`,
   401  		[]string{
   402  			`<p>Text block that <span>wraps inner text</span> and continues</p>`,
   403  		},
   404  	},
   405  	{
   406  		`<div id="d1"><p id="p1"><span>text content</span></p></div><div id="d2"/>`,
   407  		`div:has(#p1)`,
   408  		[]string{
   409  			`<div id="d1"><p id="p1"><span>text content</span></p></div>`,
   410  		},
   411  	},
   412  	{
   413  		`<div id="d1"><p id="p1"><span>contents 1</span></p></div>
   414  		<div id="d2"><p>contents <em>2</em></p></div>`,
   415  		`div:has(:containsOwn("2"))`,
   416  		[]string{
   417  			`<div id="d2"><p>contents <em>2</em></p></div>`,
   418  		},
   419  	},
   420  	{
   421  		`<body><div id="d1"><p id="p1"><span>contents 1</span></p></div>
   422  		<div id="d2"><p id="p2">contents <em>2</em></p></div></body>`,
   423  		`body :has(:containsOwn("2"))`,
   424  		[]string{
   425  			`<div id="d2"><p id="p2">contents <em>2</em></p></div>`,
   426  			`<p id="p2">contents <em>2</em></p>`,
   427  		},
   428  	},
   429  	{
   430  		`<body><div id="d1"><p id="p1"><span>contents 1</span></p></div>
   431  		<div id="d2"><p id="p2">contents <em>2</em></p></div></body>`,
   432  		`body :haschild(:containsOwn("2"))`,
   433  		[]string{
   434  			`<p id="p2">contents <em>2</em></p>`,
   435  		},
   436  	},
   437  	{
   438  		`<p id="p1">0123456789</p><p id="p2">abcdef</p><p id="p3">0123ABCD</p>`,
   439  		`p:matches([\d])`,
   440  		[]string{
   441  			`<p id="p1">0123456789</p>`,
   442  			`<p id="p3">0123ABCD</p>`,
   443  		},
   444  	},
   445  	{
   446  		`<p id="p1">0123456789</p><p id="p2">abcdef</p><p id="p3">0123ABCD</p>`,
   447  		`p:matches([a-z])`,
   448  		[]string{
   449  			`<p id="p2">abcdef</p>`,
   450  		},
   451  	},
   452  	{
   453  		`<p id="p1">0123456789</p><p id="p2">abcdef</p><p id="p3">0123ABCD</p>`,
   454  		`p:matches([a-zA-Z])`,
   455  		[]string{
   456  			`<p id="p2">abcdef</p>`,
   457  			`<p id="p3">0123ABCD</p>`,
   458  		},
   459  	},
   460  	{
   461  		`<p id="p1">0123456789</p><p id="p2">abcdef</p><p id="p3">0123ABCD</p>`,
   462  		`p:matches([^\d])`,
   463  		[]string{
   464  			`<p id="p2">abcdef</p>`,
   465  			`<p id="p3">0123ABCD</p>`,
   466  		},
   467  	},
   468  	{
   469  		`<p id="p1">0123456789</p><p id="p2">abcdef</p><p id="p3">0123ABCD</p>`,
   470  		`p:matches(^(0|a))`,
   471  		[]string{
   472  			`<p id="p1">0123456789</p>`,
   473  			`<p id="p2">abcdef</p>`,
   474  			`<p id="p3">0123ABCD</p>`,
   475  		},
   476  	},
   477  	{
   478  		`<p id="p1">0123456789</p><p id="p2">abcdef</p><p id="p3">0123ABCD</p>`,
   479  		`p:matches(^\d+$)`,
   480  		[]string{
   481  			`<p id="p1">0123456789</p>`,
   482  		},
   483  	},
   484  	{
   485  		`<p id="p1">0123456789</p><p id="p2">abcdef</p><p id="p3">0123ABCD</p>`,
   486  		`p:not(:matches(^\d+$))`,
   487  		[]string{
   488  			`<p id="p2">abcdef</p>`,
   489  			`<p id="p3">0123ABCD</p>`,
   490  		},
   491  	},
   492  	{
   493  		`<div><p id="p1">01234<em>567</em>89</p><div>`,
   494  		`div :matchesOwn(^\d+$)`,
   495  		[]string{
   496  			`<p id="p1">01234<em>567</em>89</p>`,
   497  			`<em>567</em>`,
   498  		},
   499  	},
   500  	{
   501  		`<ul>
   502  			<li><a id="a1" href="http://www.google.com/finance"></a>
   503  			<li><a id="a2" href="http://finance.yahoo.com/"></a>
   504  			<li><a id="a2" href="http://finance.untrusted.com/"/>
   505  			<li><a id="a3" href="https://www.google.com/news"/>
   506  			<li><a id="a4" href="http://news.yahoo.com"/>
   507  		</ul>`,
   508  		`[href#=(fina)]:not([href#=(\/\/[^\/]+untrusted)])`,
   509  		[]string{
   510  			`<a id="a1" href="http://www.google.com/finance"></a>`,
   511  			`<a id="a2" href="http://finance.yahoo.com/"></a>`,
   512  		},
   513  	},
   514  	{
   515  		`<ul>
   516  			<li><a id="a1" href="http://www.google.com/finance"/>
   517  			<li><a id="a2" href="http://finance.yahoo.com/"/>
   518  			<li><a id="a3" href="https://www.google.com/news"></a>
   519  			<li><a id="a4" href="http://news.yahoo.com"/>
   520  		</ul>`,
   521  		`[href#=(^https:\/\/[^\/]*\/?news)]`,
   522  		[]string{
   523  			`<a id="a3" href="https://www.google.com/news"></a>`,
   524  		},
   525  	},
   526  	{
   527  		`<form>
   528  			<label>Username <input type="text" name="username" /></label>
   529  			<label>Password <input type="password" name="password" /></label>
   530  			<label>Country
   531  				<select name="country">
   532  					<option value="ca">Canada</option>
   533  					<option value="us">United States</option>
   534  				</select>
   535  			</label>
   536  			<label>Bio <textarea name="bio"></textarea></label>
   537  			<button>Sign up</button>
   538  		</form>`,
   539  		`:input`,
   540  		[]string{
   541  			`<input type="text" name="username"/>`,
   542  			`<input type="password" name="password"/>`,
   543  			`<select name="country">
   544  					<option value="ca">Canada</option>
   545  					<option value="us">United States</option>
   546  				</select>`,
   547  			`<textarea name="bio"></textarea>`,
   548  			`<button>Sign up</button>`,
   549  		},
   550  	},
   551  }