summaryrefslogtreecommitdiff
path: root/esxml-query-tests.el
blob: ab6dae3184e9ae7722f684752a51800c857a5050 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
(require 'esxml)
(require 'esxml-query)
(require 'ert)

(ert-deftest esxml-parse-css-selector-test ()
  (should-error (esxml-parse-css-selector ""))
  (should-error (esxml-parse-css-selector "'foo'"))
  (should (equal (esxml-parse-css-selector "*")
                 '((((wildcard))))))
  (should (equal (esxml-parse-css-selector "foo")
                 '((((tag . foo))))))
  (should-error (esxml-parse-css-selector "foo 123"))
  (should (equal (esxml-parse-css-selector "foo bar")
                 '((((tag . foo))
                    ((combinator . descendant))
                    ((tag . bar))))))
  (should (equal (esxml-parse-css-selector "foo,bar")
                 '((((tag . foo)))
                   (((tag . bar))))))
  (should (equal (esxml-parse-css-selector "foo, bar")
                 '((((tag . foo)))
                   (((tag . bar))))))
  (should (equal (esxml-parse-css-selector "foo ,bar")
                 '((((tag . foo)))
                   (((tag . bar))))))
  (should (equal (esxml-parse-css-selector "foo , bar")
                 '((((tag . foo)))
                   (((tag . bar))))))
  (should-error (esxml-parse-css-selector "foo, "))
  (should-error (esxml-parse-css-selector "foo,"))
  (should-error (esxml-parse-css-selector "foo ,"))
  (should-error (esxml-parse-css-selector "foo , "))
  (should (equal (esxml-parse-css-selector "foo > bar")
                 '((((tag . foo))
                    ((combinator . child))
                    ((tag . bar))))))
  (should (equal (esxml-parse-css-selector "foo>bar")
                 '((((tag . foo))
                    ((combinator . child))
                    ((tag . bar))))))
  (should (equal (esxml-parse-css-selector "foo ~ bar")
                 '((((tag . foo))
                    ((combinator . indirect-sibling))
                    ((tag . bar))))))
  (should (equal (esxml-parse-css-selector "foo + bar")
                 '((((tag . foo))
                    ((combinator . direct-sibling))
                    ((tag . bar))))))
  (should-error (esxml-parse-css-selector "foo >"))
  (should (equal (esxml-parse-css-selector "foo#bar.baz.qux")
                 '((((tag . foo)
                     (id . "bar")
                     (class . "baz")
                     (class . "qux"))))))
  (should (equal (esxml-parse-css-selector "#foo.bar.baz[qux=quux]:foo(bar baz)")
                 '((((id . "foo")
                     (class . "bar")
                     (class . "baz")
                     (attribute
                      (name . "qux")
                      (exact-match . "quux"))
                     (pseudo-class
                      (name . "foo")
                      (args
                       (ident . "bar")
                       (ident . "baz"))))))))
  (should-error (esxml-parse-css-selector "foo#bar#baz"))
  (should (equal (esxml-parse-css-selector "foo[bar=baz][qux=quux]")
                 '((((tag . foo)
                     (attribute
                      (name . "bar")
                      (exact-match . "baz"))
                     (attribute
                      (name . "qux")
                      (exact-match . "quux")))))))
  (should (equal (esxml-parse-css-selector "foo::bar:baz(qux quux)")
                 '((((tag . foo)
                     (pseudo-element
                      (name . "bar"))
                     (pseudo-class
                      (name . "baz")
                      (args
                       (ident . "qux")
                       (ident . "quux"))))))))
  (should (equal (esxml-parse-css-selector "#foo")
                 '((((id . "foo"))))))
  (should-error (esxml-parse-css-selector "# #bar"))
  (should (equal (esxml-parse-css-selector ".foo")
                 '((((class . "foo"))))))
  (should-error (esxml-parse-css-selector ". .bar"))
  (should (equal (esxml-parse-css-selector "[foo]")
                 '((((attribute
                      (name . "foo")))))))
  (should-error (esxml-parse-css-selector "[foo=]"))
  (should (equal (esxml-parse-css-selector "[foo=bar]")
                 '((((attribute
                      (name . "foo")
                      (exact-match . "bar")))))))
  (should (equal (esxml-parse-css-selector "[foo^=bar]")
                 '((((attribute
                      (name . "foo")
                      (prefix-match . "bar")))))))
  (should (equal (esxml-parse-css-selector "[foo$=bar]")
                 '((((attribute
                      (name . "foo")
                      (suffix-match . "bar")))))))
  (should (equal (esxml-parse-css-selector "[foo*=bar]")
                 '((((attribute
                      (name . "foo")
                      (substring-match . "bar")))))))
  (should (equal (esxml-parse-css-selector "[foo~=bar]")
                 '((((attribute
                      (name . "foo")
                      (include-match . "bar")))))))
  (should (equal (esxml-parse-css-selector "[foo|=bar]")
                 '((((attribute
                      (name . "foo")
                      (dash-match . "bar")))))))
  (should-error (esxml-parse-css-selector "[foo=bar"))
  (should (equal (esxml-parse-css-selector "[foo='bar']")
                 '((((attribute
                      (name . "foo")
                      (exact-match . "bar")))))))
  (should (equal (esxml-parse-css-selector "[foo=\"bar\"]")
                 '((((attribute
                      (name . "foo")
                      (exact-match . "bar")))))))
  (should-error (esxml-parse-css-selector "[foo='bar]"))
  (should (equal (esxml-parse-css-selector "[ foo = bar ]")
                 '((((attribute
                      (name . "foo")
                      (exact-match . "bar")))))))
  (should (equal (esxml-parse-css-selector ":foo")
                 '((((pseudo-class
                      (name . "foo")))))))
  (should (equal (esxml-parse-css-selector "::foo")
                 '((((pseudo-element
                      (name . "foo")))))))
  (should-error (esxml-parse-css-selector ": foo"))
  (should-error (esxml-parse-css-selector ":: foo"))
  (should-error (esxml-parse-css-selector ":foo()"))
  (should (equal (esxml-parse-css-selector ":foo(bar)")
                 '((((pseudo-class
                      (name . "foo")
                      (args
                       (ident . "bar"))))))))
  (should-error (esxml-parse-css-selector "::foo(bar)"))
  (should (equal (esxml-parse-css-selector ":foo(bar baz)")
                 '((((pseudo-class
                      (name . "foo")
                      (args
                       (ident . "bar")
                       (ident . "baz"))))))))
  (should (equal (esxml-parse-css-selector ":foo(1)")
                 '((((pseudo-class
                      (name . "foo")
                      (args
                       (number . 1))))))))
  (should (equal (esxml-parse-css-selector ":foo(42rem)")
                 '((((pseudo-class
                      (name . "foo")
                      (args
                       (dimension . "42rem"))))))))
  (should (equal (esxml-parse-css-selector ":foo(2n+1)")
                 '((((pseudo-class
                      (name . "foo")
                      (args
                       (number . 2)
                       (ident . "n")
                       (operator . +)
                       (number . 1))))))))
  (should (equal (esxml-parse-css-selector ":foo(1-1)")
                 '((((pseudo-class
                      (name . "foo")
                      (args
                       (number . 1)
                       (operator . -)
                       (number . 1))))))))
  (should-error (esxml-parse-css-selector ":foo(bar")))

(defvar esxml-query-document
  (xml-to-esxml
   "<!DOCTYPE html>
<html lang=\"en-US\">
  <head>
    <meta charset=\"utf-8\" />
    <link rel=\"self\" />
    <title>Foobar</title>
  </head>
  <body>
    <table>
      <thead>
        <tr class=\"row\" id=\"heading\">
          <th class=\"col\">Key</th>
          <th class=\"col\">Value</th>
        </tr>
      </thead>
      <tbody>
        <tr class=\"row even\">
          <td class=\"col key\">Foo</td>
          <td class=\"col value\">1</td>
        </tr>
        <tr class=\"row odd\">
          <td class=\"col key\">Bar</td>
          <td class=\"col value\">2</td>
        </tr>
      </tbody>
    </table>
  </body>
</html>"))

(ert-deftest esxml-query-test ()
  (let ((root esxml-query-document))
    (should (eq (esxml-node-tag (esxml-query "*" root)) 'html))
    (should (eq (esxml-node-tag (esxml-query "table" root)) 'table))
    (should-not (esxml-query "foo" root))
    (should (eq (esxml-node-tag (esxml-query "table, foo" root)) 'table))
    (should (eq (esxml-node-tag (esxml-query "foo, table" root)) 'table))
    (should-not (esxml-query "foo, bar" root))
    (should (eq (esxml-node-tag (esxml-query "thead, tbody" root)) 'thead))
    (should (eq (esxml-node-tag (esxml-query "tbody, thead" root)) 'thead))

    (should-not (esxml-query "table table" root))
    (should (equal (esxml-node-children (esxml-query "table thead th" root))
                   '("Key")))
    (should (equal (esxml-node-children (esxml-query "table td" root))
                   '("Foo")))
    (should (equal (esxml-node-children (esxml-query "table * td" root))
                   '("Foo")))
    (should-not (esxml-query "td foo" root))
    (should-not (esxml-query "tr foo td" root))
    (should (equal (esxml-node-children (esxml-query "tbody>tr>td" root))
                   '("Foo")))
    (should-not (esxml-query "tr>foo" root))
    (should-not (esxml-query "foo>td" root))

    (should (equal (esxml-node-children (esxml-query "#heading>th" root))
                   '("Key")))
    (should (equal (esxml-node-tag (esxml-query "tr#heading" root)) 'tr))
    (should (equal (esxml-node-tag (esxml-query "#heading" root)) 'tr))
    (should-not (esxml-query "th#heading" root))
    (should-not (esxml-query "tr #heading" root))

    (should (equal (esxml-node-children (esxml-query ".row>td" root))
                   '("Foo")))
    (should-not (esxml-query ".foo" root))
    (should (esxml-query ".row.even" root))
    (should-not (esxml-query ".row.foo" root))
    (should (equal (esxml-node-children (esxml-query ".row .value" root))
                   '("1")))
    (should (equal (esxml-node-children (esxml-query ".row.odd .value" root))
                   '("2")))
    (should (equal (esxml-node-children (esxml-query ".even .value, .odd .value" root))
                   '("1")))

    (should (eq (esxml-node-tag (esxml-query "[rel=self]" root)) 'link))
    (should-not (esxml-query "[rel=elf]" root))
    (should-not (esxml-query "[rel=sel]" root))
    (should-not (esxml-query "[rel=selfie]" root))
    (should (equal (esxml-node-children (esxml-query "[class='row even'] td" root))
                   '("Foo")))
    (should (esxml-query "[class^=row]" root))
    (should (esxml-query "[class$=row]" root))
    (should-not (esxml-query "[class^=key]" root))
    (should (esxml-query "[class$=key]" root))
    (should-not (esxml-query "[class^=foo]" root))
    (should-not (esxml-query "[class$=bar]" root))
    (should (esxml-query "[charset^=utf][charset$='8']" root))
    (should (esxml-query "[charset*=utf]" root))
    (should (esxml-query "[class*=val]" root))
    (should-not (esxml-query "[class*=foo]" root))
    (should (esxml-query "[rel*=self]" root))
    (should (esxml-query "[class*='l k']" root))
    (should-not (esxml-query "[charset~=utf]" root))
    (should (esxml-query "[rel~=self]" root))
    (should (esxml-query "[class~=row]" root))
    (should (esxml-query "[class~=key]" root))
    (should-not (esxml-query "[class~=foo]" root))
    (should (equal (esxml-node-children (esxml-query "[class~=row][class~=odd] [class~=value]" root))
                   '("2")))
    (should (equal (cdr (assq 'lang (esxml-node-attributes (esxml-query "[lang|=en]" root))))
                   "en-US"))
    (should-not (esxml-query "[lang|=US]" root))))

(ert-deftest esxml-query-all-test ()
  (let ((root esxml-query-document))
    (should (equal (cl-remove-if 'not (mapcar 'esxml-node-tag
                                              (esxml-query-all "*" root)))
                   '(html head meta link title
                          body table thead tr th th tbody tr td td tr td td)))
    (should (equal (mapcar 'esxml-node-tag (esxml-query-all "table" root))
                   '(table)))
    (should-not (esxml-query-all "foo" root))
    (should (equal (mapcar 'esxml-node-tag (esxml-query-all "table, foo" root))
                   '(table)))
    (should (equal (mapcar 'esxml-node-tag (esxml-query-all "foo, table" root))
                   '(table)))
    (should-not (esxml-query-all "foo, bar" root))
    (should (equal (mapcar 'esxml-node-tag (esxml-query-all "thead, tbody" root))
                   '(thead tbody)))
    (should (equal (mapcar 'esxml-node-tag (esxml-query-all "tbody, thead" root))
                   '(thead tbody)))

    (should-not (esxml-query-all "table table" root))
    (should (equal (mapcar 'car (mapcar 'esxml-node-children (esxml-query-all "table thead th" root)))
                   '("Key" "Value")))
    (should (equal (mapcar 'car (mapcar 'esxml-node-children (esxml-query-all "table td" root)))
                   '("Foo" "1" "Bar" "2")))
    (should (equal (mapcar 'car (mapcar 'esxml-node-children (esxml-query-all "table * td" root)))
                   '("Foo" "1" "Bar" "2")))
    (should-not (esxml-query-all "td foo" root))
    (should-not (esxml-query-all "tr foo td" root))
    (should (equal (mapcar 'car (mapcar 'esxml-node-children (esxml-query-all "tbody>tr>td" root)))
                   '("Foo" "1" "Bar" "2")))
    (should-not (esxml-query-all "tr>foo" root))
    (should-not (esxml-query-all "foo>td" root))

    (should (equal (mapcar 'car (mapcar 'esxml-node-children (esxml-query-all "#heading>th" root)))
                   '("Key" "Value")))
    (should (equal (mapcar 'esxml-node-tag (esxml-query-all "tr#heading" root))
                   '(tr)))
    (should (equal (mapcar 'esxml-node-tag (esxml-query-all "#heading" root))
                   '(tr)))
    (should-not (esxml-query-all "th#heading" root))
    (should-not (esxml-query-all "tr #heading" root))

    (should (equal (mapcar 'car (mapcar 'esxml-node-children (esxml-query-all ".row>td" root)))
                   '("Foo" "1" "Bar" "2")))
    (should-not (esxml-query-all ".foo" root))
    (should (= (length (esxml-query-all ".row.even" root)) 1))
    (should-not (esxml-query-all ".row.foo" root))
    (should (equal (mapcar 'car (mapcar 'esxml-node-children (esxml-query-all ".row .value" root)))
                   '("1" "2")))
    (should (equal (mapcar 'car (mapcar 'esxml-node-children (esxml-query-all ".row.odd .value" root)))
                   '("2")))
    (should (= (length (esxml-query-all ".even, .odd" root)) 2))
    (should (equal (mapcar 'car (mapcar 'esxml-node-children (esxml-query-all ".even .value, .odd .value" root)))
                   '("1" "2")))

    (should (eq (esxml-node-tag (car (esxml-query-all "[rel=self]" root)))
                'link))
    (should-not (esxml-query-all "[rel=elf]" root))
    (should-not (esxml-query-all "[rel=sel]" root))
    (should-not (esxml-query-all "[rel=selfie]" root))
    (should (equal (mapcar 'car (mapcar 'esxml-node-children (esxml-query-all "[class='row even'] td" root)))
                   '("Foo" "1")))
    (should (= (length (esxml-query-all "[class^=row]" root)) 3))
    (should (= (length (esxml-query-all "[class$=row]" root)) 1))
    (should-not (esxml-query-all "[class^=key]" root))
    (should (= (length (esxml-query-all "[class$=key]" root)) 2))
    (should-not (esxml-query-all "[class^=foo]" root))
    (should-not (esxml-query-all "[class$=bar]" root))
    (should (= (length (esxml-query-all "[charset^=utf][charset$='8']" root)) 1))
    (should (= (length (esxml-query-all "[charset*=utf]" root)) 1))
    (should (= (length (esxml-query-all "[class*=val]" root)) 2))
    (should-not (esxml-query-all "[class*=foo]" root))
    (should (= (length (esxml-query-all "[rel*=self]" root)) 1))
    (should (= (length (esxml-query-all "[class*='l k']" root)) 2))
    (should-not (esxml-query-all "[charset~=utf]" root))
    (should (= (length (esxml-query-all "[rel~=self]" root)) 1))
    (should (= (length (esxml-query-all "[class~=row]" root)) 3))
    (should (= (length (esxml-query-all "[class~=key]" root)) 2))
    (should-not (esxml-query-all "[class~=foo]" root))
    (should (equal (car (esxml-node-children (car (esxml-query-all "[class~=row][class~=odd] [class~=value]" root))))
                   "2"))
    (should (equal (cdr (assq 'lang (esxml-node-attributes (car (esxml-query-all "[lang|=en]" root)))))
                   "en-US"))
    (should-not (esxml-query-all "[lang|=US]" root))))