hatemile 2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/CODE_OF_CONDUCT.md +46 -0
  3. data/Gemfile +9 -0
  4. data/LICENSE +202 -0
  5. data/Rakefile +64 -0
  6. data/hatemile.gemspec +37 -0
  7. data/lib/hatemile/accessible_association.rb +62 -0
  8. data/lib/hatemile/accessible_css.rb +43 -0
  9. data/lib/hatemile/accessible_display.rb +178 -0
  10. data/lib/hatemile/accessible_event.rb +95 -0
  11. data/lib/hatemile/accessible_form.rb +101 -0
  12. data/lib/hatemile/accessible_navigation.rb +82 -0
  13. data/lib/hatemile/helper.rb +58 -0
  14. data/lib/hatemile/implementation/accessible_association_implementation.rb +346 -0
  15. data/lib/hatemile/implementation/accessible_css_implementation.rb +772 -0
  16. data/lib/hatemile/implementation/accessible_display_implementation.rb +1362 -0
  17. data/lib/hatemile/implementation/accessible_event_implementation.rb +278 -0
  18. data/lib/hatemile/implementation/accessible_form_implementation.rb +386 -0
  19. data/lib/hatemile/implementation/accessible_navigation_implementation.rb +561 -0
  20. data/lib/hatemile/util/common_functions.rb +106 -0
  21. data/lib/hatemile/util/configure.rb +92 -0
  22. data/lib/hatemile/util/css/rcp/rcp_declaration.rb +77 -0
  23. data/lib/hatemile/util/css/rcp/rcp_parser.rb +115 -0
  24. data/lib/hatemile/util/css/rcp/rcp_rule.rb +86 -0
  25. data/lib/hatemile/util/css/style_sheet_declaration.rb +59 -0
  26. data/lib/hatemile/util/css/style_sheet_parser.rb +43 -0
  27. data/lib/hatemile/util/css/style_sheet_rule.rb +73 -0
  28. data/lib/hatemile/util/html/html_dom_element.rb +234 -0
  29. data/lib/hatemile/util/html/html_dom_node.rb +131 -0
  30. data/lib/hatemile/util/html/html_dom_parser.rb +150 -0
  31. data/lib/hatemile/util/html/html_dom_text_node.rb +43 -0
  32. data/lib/hatemile/util/html/nokogiri/nokogiri_html_dom_element.rb +302 -0
  33. data/lib/hatemile/util/html/nokogiri/nokogiri_html_dom_node.rb +112 -0
  34. data/lib/hatemile/util/html/nokogiri/nokogiri_html_dom_parser.rb +208 -0
  35. data/lib/hatemile/util/html/nokogiri/nokogiri_html_dom_text_node.rb +83 -0
  36. data/lib/hatemile/util/id_generator.rb +53 -0
  37. data/lib/js/common.js +98 -0
  38. data/lib/js/eventlistener.js +36 -0
  39. data/lib/js/include.js +292 -0
  40. data/lib/js/scriptlist_validation_fields.js +13 -0
  41. data/lib/js/validation.js +205 -0
  42. data/lib/locale/en-US.yml +388 -0
  43. data/lib/locale/pt-BR.yml +389 -0
  44. data/lib/skippers.xml +6 -0
  45. data/lib/symbols.xml +40 -0
  46. data/test/locale/en-US.yml +5 -0
  47. data/test/locale/pt-BR.yml +4 -0
  48. data/test/test_accessible_association_implementation.rb +258 -0
  49. data/test/test_accessible_css_implementation.rb +518 -0
  50. data/test/test_accessible_display_implementation.rb +873 -0
  51. data/test/test_accessible_form_implementation.rb +283 -0
  52. data/test/test_accessible_navigation_implementation.rb +228 -0
  53. data/test/test_common_functions.rb +128 -0
  54. data/test/test_configure.rb +73 -0
  55. data/test/test_nokogiri_html_dom_element.rb +586 -0
  56. data/test/test_nokogiri_html_dom_parser.rb +363 -0
  57. data/test/test_nokogiri_html_dom_text_node.rb +225 -0
  58. data/test/test_rcp_declaration.rb +103 -0
  59. data/test/test_rcp_parser.rb +86 -0
  60. data/test/test_rcp_rule.rb +89 -0
  61. metadata +199 -0
@@ -0,0 +1,873 @@
1
+ # Licensed under the Apache License, Version 2.0 (the "License");
2
+ # you may not use this file except in compliance with the License.
3
+ # You may obtain a copy of the License at
4
+ #
5
+ # http://www.apache.org/licenses/LICENSE-2.0
6
+ #
7
+ # Unless required by applicable law or agreed to in writing, software
8
+ # distributed under the License is distributed on an "AS IS" BASIS,
9
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
+ # See the License for the specific language governing permissions and
11
+ # limitations under the License.
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+ require 'test/unit'
16
+ require 'test/unit/assertions'
17
+
18
+ require File.join(
19
+ File.dirname(File.dirname(__FILE__)),
20
+ 'lib',
21
+ 'hatemile',
22
+ 'implementation',
23
+ 'accessible_display_implementation'
24
+ )
25
+ require File.join(
26
+ File.dirname(File.dirname(__FILE__)),
27
+ 'lib',
28
+ 'hatemile',
29
+ 'util',
30
+ 'configure'
31
+ )
32
+ require File.join(
33
+ File.dirname(File.dirname(__FILE__)),
34
+ 'lib',
35
+ 'hatemile',
36
+ 'util',
37
+ 'html',
38
+ 'nokogiri',
39
+ 'nokogiri_html_dom_parser'
40
+ )
41
+
42
+ ##
43
+ # Test methods of Hatemile::Implementation::AccessibleDisplayImplementation
44
+ # class.
45
+ class TestAccessibleDisplayImplementation < Test::Unit::TestCase
46
+ ##
47
+ # The name of attribute for not modify the elements.
48
+ DATA_IGNORE = 'data-ignoreaccessibilityfix="true"'.freeze
49
+
50
+ ##
51
+ # The configuration of HaTeMiLe.
52
+ CONFIGURE = Hatemile::Util::Configure.new.freeze
53
+
54
+ ##
55
+ # Test display_all_shortcuts method with container of shorcuts not defined.
56
+ def test_display_all_shortcuts_container_not_defined
57
+ html_parser = Hatemile::Util::Html::NokogiriLib::NokogiriHTMLDOMParser.new("
58
+ <!DOCTYPE html>
59
+ <html>
60
+ <head>
61
+ <title>HaTeMiLe Tests</title>
62
+ <meta charset=\"UTF-8\" />
63
+ </head>
64
+ <body>
65
+ <a href=\"https://github.com/hatemile/\" accesskey=\"r\">
66
+ HaTeMiLe in Github
67
+ </a>
68
+ <a href=\"https://hatemile.github.io\" title=\"Site\" accesskey=\"w\">
69
+ Webpage
70
+ </a>
71
+ <a href=\"http://localhost/\" #{DATA_IGNORE} accesskey=\"i\">
72
+ Ignore link
73
+ </a>
74
+ <form action=\"\">
75
+ <label for=\"field1\">Field1</label>
76
+ <input type=\"text\" id=\"field1\" accesskey=\"f\" /><br />
77
+ <label for=\"field2\" #{DATA_IGNORE}>Field2</label>
78
+ <input type=\"text\" id=\"field2\" accesskey=\"o\" /><br />
79
+ <input type=\"submit\" value=\"Submit\" accesskey=\"s\" />
80
+ </form>
81
+ </body>
82
+ </html>
83
+ ")
84
+ display = Hatemile::Implementation::AccessibleDisplayImplementation.new(
85
+ html_parser,
86
+ CONFIGURE
87
+ )
88
+ display.display_all_shortcuts
89
+ accesskey_r = html_parser.find('[accesskey="r"]').first_result
90
+ accesskey_w = html_parser.find('[accesskey="w"]').first_result
91
+ accesskey_f = html_parser.find('[accesskey="f"]').first_result
92
+ accesskey_s = html_parser.find('[accesskey="s"]').first_result
93
+ accesskey_i = html_parser.find('[accesskey="i"]').first_result
94
+ reference_r = html_parser.find(
95
+ '[data-attributeaccesskeyof="R"]'
96
+ ).first_result
97
+ reference_w = html_parser.find(
98
+ '[data-attributeaccesskeyof="W"]'
99
+ ).first_result
100
+ reference_f = html_parser.find(
101
+ '[data-attributeaccesskeyof="F"]'
102
+ ).first_result
103
+ reference_s = html_parser.find(
104
+ '[data-attributeaccesskeyof="S"]'
105
+ ).first_result
106
+ reference_i = html_parser.find(
107
+ '[data-attributeaccesskeyof="I"]'
108
+ ).first_result
109
+ reference_o = html_parser.find(
110
+ '[data-attributeaccesskeyof="O"]'
111
+ ).first_result
112
+ shortcut_description_r = html_parser.find(accesskey_r).find_children(
113
+ '[data-attributeaccesskeyof]'
114
+ ).first_result
115
+ shortcut_description_f = html_parser.find('[for="field1"]').find_children(
116
+ '[data-attributeaccesskeyof]'
117
+ ).first_result
118
+ shortcut_description_i = html_parser.find(accesskey_i).find_children(
119
+ '[data-attributeaccesskeyof]'
120
+ ).first_result
121
+ shortcut_description_o = html_parser.find('[for="field2"]').find_children(
122
+ '[data-attributeaccesskeyof]'
123
+ ).first_result
124
+
125
+ assert_not_nil(html_parser.find('#container-shortcuts-after').first_result)
126
+ assert_equal('HaTeMiLe in Github', accesskey_r.get_attribute('title'))
127
+ assert_equal('Site', accesskey_w.get_attribute('title'))
128
+ assert_equal('Field1', accesskey_f.get_attribute('title'))
129
+ assert_equal('Submit', accesskey_s.get_attribute('title'))
130
+ assert(!accesskey_i.has_attribute?('title'))
131
+ assert_equal(
132
+ 'ACCESS KEY PREFIX + R: HaTeMiLe in Github',
133
+ reference_r.get_text_content
134
+ )
135
+ assert_equal('ACCESS KEY PREFIX + W: Site', reference_w.get_text_content)
136
+ assert_equal('ACCESS KEY PREFIX + F: Field1', reference_f.get_text_content)
137
+ assert_equal('ACCESS KEY PREFIX + S: Submit', reference_s.get_text_content)
138
+ assert_equal('ACCESS KEY PREFIX + O: Field2', reference_o.get_text_content)
139
+ assert_nil(reference_i)
140
+ assert_equal(
141
+ ' (Keyboard shortcut: ACCESS KEY PREFIX + R)',
142
+ shortcut_description_r.get_text_content
143
+ )
144
+ assert_equal(
145
+ ' (Keyboard shortcut: ACCESS KEY PREFIX + F)',
146
+ shortcut_description_f.get_text_content
147
+ )
148
+ assert_nil(shortcut_description_i)
149
+ assert_nil(shortcut_description_o)
150
+ end
151
+
152
+ ##
153
+ # Test display_all_shortcuts method with container of shortcuts defined.
154
+ def test_display_all_shortcuts_container_defined
155
+ html_parser = Hatemile::Util::Html::NokogiriLib::NokogiriHTMLDOMParser.new("
156
+ <!DOCTYPE html>
157
+ <html>
158
+ <head>
159
+ <title>HaTeMiLe Tests</title>
160
+ <meta charset=\"UTF-8\" />
161
+ </head>
162
+ <body>
163
+ <div id=\"container-shortcuts-after\"></div>
164
+ <a href=\"https://github.com/hatemile/\" accesskey=\"r\">
165
+ HaTeMiLe in Github
166
+ </a>
167
+ <a href=\"https://hatemile.github.io\" title=\"Site\" accesskey=\"w\">
168
+ Webpage
169
+ </a>
170
+ <a href=\"http://localhost/\" #{DATA_IGNORE} accesskey=\"i\">
171
+ Ignore link
172
+ </a>
173
+ <form action=\"\">
174
+ <label for=\"field1\">Field1</label>
175
+ <input type=\"text\" id=\"field1\" accesskey=\"f\" /><br />
176
+ <label for=\"field2\" #{DATA_IGNORE}>Field2</label>
177
+ <input type=\"text\" id=\"field2\" accesskey=\"o\" /><br />
178
+ <input type=\"submit\" value=\"Submit\" accesskey=\"s\" />
179
+ </form>
180
+ </body>
181
+ </html>
182
+ ")
183
+ display = Hatemile::Implementation::AccessibleDisplayImplementation.new(
184
+ html_parser,
185
+ CONFIGURE
186
+ )
187
+ display.display_all_shortcuts
188
+ accesskey_r = html_parser.find('[accesskey="r"]').first_result
189
+ accesskey_w = html_parser.find('[accesskey="w"]').first_result
190
+ accesskey_f = html_parser.find('[accesskey="f"]').first_result
191
+ accesskey_s = html_parser.find('[accesskey="s"]').first_result
192
+ accesskey_i = html_parser.find('[accesskey="i"]').first_result
193
+ reference_r = html_parser.find(
194
+ '#container-shortcuts-after [data-attributeaccesskeyof="R"]'
195
+ ).first_result
196
+ reference_w = html_parser.find(
197
+ '#container-shortcuts-after [data-attributeaccesskeyof="W"]'
198
+ ).first_result
199
+ reference_f = html_parser.find(
200
+ '#container-shortcuts-after [data-attributeaccesskeyof="F"]'
201
+ ).first_result
202
+ reference_s = html_parser.find(
203
+ '#container-shortcuts-after [data-attributeaccesskeyof="S"]'
204
+ ).first_result
205
+ reference_i = html_parser.find(
206
+ '#container-shortcuts-after [data-attributeaccesskeyof="I"]'
207
+ ).first_result
208
+ reference_o = html_parser.find(
209
+ '[data-attributeaccesskeyof="O"]'
210
+ ).first_result
211
+ shortcut_description_r = html_parser.find(accesskey_r).find_children(
212
+ '[data-attributeaccesskeyof]'
213
+ ).first_result
214
+ shortcut_description_f = html_parser.find('[for="field1"]').find_children(
215
+ '[data-attributeaccesskeyof]'
216
+ ).first_result
217
+ shortcut_description_i = html_parser.find(accesskey_i).find_children(
218
+ '[data-attributeaccesskeyof]'
219
+ ).first_result
220
+ shortcut_description_o = html_parser.find('[for="field2"]').find_children(
221
+ '[data-attributeaccesskeyof]'
222
+ ).first_result
223
+
224
+ assert_equal(
225
+ 'container-shortcuts-after',
226
+ html_parser.find(
227
+ 'body'
228
+ ).first_result.get_first_element_child.get_attribute('id')
229
+ )
230
+ assert_equal('HaTeMiLe in Github', accesskey_r.get_attribute('title'))
231
+ assert_equal('Site', accesskey_w.get_attribute('title'))
232
+ assert_equal('Field1', accesskey_f.get_attribute('title'))
233
+ assert_equal('Submit', accesskey_s.get_attribute('title'))
234
+ assert(!accesskey_i.has_attribute?('title'))
235
+ assert_equal(
236
+ 'ACCESS KEY PREFIX + R: HaTeMiLe in Github',
237
+ reference_r.get_text_content
238
+ )
239
+ assert_equal('ACCESS KEY PREFIX + W: Site', reference_w.get_text_content)
240
+ assert_equal('ACCESS KEY PREFIX + F: Field1', reference_f.get_text_content)
241
+ assert_equal('ACCESS KEY PREFIX + S: Submit', reference_s.get_text_content)
242
+ assert_equal('ACCESS KEY PREFIX + O: Field2', reference_o.get_text_content)
243
+ assert_nil(reference_i)
244
+ assert_equal(
245
+ ' (Keyboard shortcut: ACCESS KEY PREFIX + R)',
246
+ shortcut_description_r.get_text_content
247
+ )
248
+ assert_equal(
249
+ ' (Keyboard shortcut: ACCESS KEY PREFIX + F)',
250
+ shortcut_description_f.get_text_content
251
+ )
252
+ assert_nil(shortcut_description_i)
253
+ assert_nil(shortcut_description_o)
254
+ end
255
+
256
+ ##
257
+ # Test display_all_roles method.
258
+ def test_display_all_roles
259
+ html_parser = Hatemile::Util::Html::NokogiriLib::NokogiriHTMLDOMParser.new("
260
+ <!DOCTYPE html>
261
+ <html role=\"application\">
262
+ <head>
263
+ <title>HaTeMiLe Tests</title>
264
+ <meta charset=\"UTF-8\" />
265
+ </head>
266
+ <body>
267
+ <a href=\"https://github.com/\" role=\"link\">Github</a>
268
+ <span role=\"note\">Span</span>
269
+ <label for=\"field1\">Field1</label>
270
+ <input type=\"number\" id=\"field1\" role=\"spinbutton\" />
271
+
272
+ <a href=\"https://github.com\" role=\"link\" #{DATA_IGNORE}>Github</a>
273
+ <span role=\"note\" #{DATA_IGNORE}>Span</span>
274
+ <label for=\"field2\" #{DATA_IGNORE}>Field2</label>
275
+ <input type=\"number\" id=\"field2\" role=\"spinbutton\" />
276
+ </body>
277
+ </html>
278
+ ")
279
+ display = Hatemile::Implementation::AccessibleDisplayImplementation.new(
280
+ html_parser,
281
+ CONFIGURE
282
+ )
283
+ display.display_all_roles
284
+ body = html_parser.find('body').first_result
285
+ a = html_parser.find('a').first_result
286
+ span = html_parser.find('span[role="note"]').first_result
287
+ index_span = body.get_children_elements.index(span)
288
+ label = html_parser.find('label').first_result
289
+ ignore_a = html_parser.find("a[#{DATA_IGNORE}]").first_result
290
+ ignore_span = html_parser.find(
291
+ "span[role=\"note\"][#{DATA_IGNORE}]"
292
+ ).first_result
293
+ ignore_label = html_parser.find("label[#{DATA_IGNORE}]").first_result
294
+
295
+ assert_equal(
296
+ '(Begin of application) ',
297
+ body.get_first_element_child.get_text_content
298
+ )
299
+ assert_equal(
300
+ ' (End of application)',
301
+ body.get_last_element_child.get_text_content
302
+ )
303
+ assert_equal('(Begin of link) ', a.get_first_element_child.get_text_content)
304
+ assert_equal(' (End of link)', a.get_last_element_child.get_text_content)
305
+ assert_equal(
306
+ '(Begin of note) ',
307
+ body.get_children_elements[index_span - 1].get_text_content
308
+ )
309
+ assert_equal(
310
+ ' (End of note)',
311
+ body.get_children_elements[index_span + 1].get_text_content
312
+ )
313
+ assert_equal(
314
+ '(Begin of spin button) ',
315
+ html_parser.find(label).find_children(
316
+ '[data-roleof]'
317
+ ).first_result.get_text_content
318
+ )
319
+ assert_equal(
320
+ ' (End of spin button)',
321
+ html_parser.find(label).find_children(
322
+ '[data-roleof]'
323
+ ).last_result.get_text_content
324
+ )
325
+ assert(!ignore_a.has_children_elements?)
326
+ assert_nil(
327
+ html_parser.find(
328
+ "[data-roleof=\"#{ignore_span.get_attribute('id')}\"]"
329
+ ).first_result
330
+ )
331
+ assert(!ignore_label.has_children_elements?)
332
+ end
333
+
334
+ ##
335
+ # Test display_all_cell_headers method.
336
+ def test_display_all_cell_headers
337
+ html_parser = Hatemile::Util::Html::NokogiriLib::NokogiriHTMLDOMParser.new("
338
+ <!DOCTYPE html>
339
+ <html>
340
+ <head>
341
+ <title>HaTeMiLe Tests</title>
342
+ <meta charset=\"UTF-8\" />
343
+ </head>
344
+ <body>
345
+ <table>
346
+ <thead>
347
+ <tr>
348
+ <th id=\"th1\">THEAD TH1</th>
349
+ <th id=\"th2\">THEAD TH2</th>
350
+ </tr>
351
+ </thead>
352
+ <tbody>
353
+ <tr>
354
+ <td headers=\"th1\">TD1</td>
355
+ <td headers=\"th2\">TD2</td>
356
+ </tr>
357
+ <tr>
358
+ <th id=\"th3\">TH3</th>
359
+ <td headers=\"th2 th3\">TD3</td>
360
+ </tr>
361
+ <tr>
362
+ <td headers=\"th1\" #{DATA_IGNORE}>TD4</th>
363
+ <td headers=\"th2 th3\" #{DATA_IGNORE}>TD5</td>
364
+ </tr>
365
+ </tbody>
366
+ </table>
367
+ </body>
368
+ </html>
369
+ ")
370
+ display = Hatemile::Implementation::AccessibleDisplayImplementation.new(
371
+ html_parser,
372
+ CONFIGURE
373
+ )
374
+ display.display_all_cell_headers
375
+ td1 = html_parser.find('[headers="th1"]').first_result
376
+ td3 = html_parser.find('[headers="th2 th3"]').first_result
377
+ td4 = html_parser.find('[headers="th1"]').last_result
378
+ td5 = html_parser.find('[headers="th2 th3"]').last_result
379
+ hc1 = html_parser.find(td1).find_children('[data-headersof]').first_result
380
+ hc3 = html_parser.find(td3).find_children('[data-headersof]').first_result
381
+ hc4 = html_parser.find(td4).find_children('[data-headersof]').first_result
382
+ hc5 = html_parser.find(td5).find_children('[data-headersof]').first_result
383
+
384
+ assert_not_nil(hc1)
385
+ assert_not_nil(hc3)
386
+ assert_nil(hc4)
387
+ assert_nil(hc5)
388
+ assert_equal('(Headers: THEAD TH1) ', hc1.get_text_content)
389
+ assert_equal('(Headers: THEAD TH2 TH3) ', hc3.get_text_content)
390
+ end
391
+
392
+ ##
393
+ # Test display_all_waiaria_states method.
394
+ def test_display_all_waiaria_states
395
+ html_parser = Hatemile::Util::Html::NokogiriLib::NokogiriHTMLDOMParser.new("
396
+ <!DOCTYPE html>
397
+ <html>
398
+ <head>
399
+ <title>HaTeMiLe Tests</title>
400
+ <meta charset=\"UTF-8\" />
401
+ </head>
402
+ <body>
403
+ <a aria-busy=\"true\">ARIA-BUSY</a>
404
+ <a aria-checked=\"true\">ARIA-CHECKED</a>
405
+ <a aria-dropeffect=\"copy\">ARIA-DROPEFFECT</a>
406
+ <a aria-expanded=\"true\">ARIA-EXPANDED</a>
407
+ <a aria-grabbed=\"true\">ARIA-GRABBED</a>
408
+ <a aria-haspopup=\"true\">ARIA-HASPOPUP</a>
409
+ <a aria-level=\"1\">ARIA-LEVEL</a>
410
+ <a aria-orientation=\"vertical\">ARIA-ORIENTATION</a>
411
+ <a aria-pressed=\"true\">ARIA-PRESSED</a>
412
+ <a aria-selected=\"true\">ARIA-SELECTED</a>
413
+ <a aria-sort=\"ascending\">ARIA-SORT</a>
414
+ <a aria-required=\"true\">ARIA-REQUIRED</a>
415
+ <a aria-valuemin=\"2\">ARIA-VALUEMIN</a>
416
+ <a aria-valuemax=\"10\">ARIA-VALUEMAX</a>
417
+ <a aria-autocomplete=\"both\">ARIA-AUTOCOMPLETE</a>
418
+
419
+ <a aria-busy=\"true\" #{DATA_IGNORE}>ARIA-BUSY</a>
420
+ <a aria-checked=\"true\" #{DATA_IGNORE}>ARIA-CHECKED</a>
421
+ <a aria-dropeffect=\"copy\" #{DATA_IGNORE}>ARIA-DROPEFFECT</a>
422
+ <a aria-expanded=\"true\" #{DATA_IGNORE}>ARIA-EXPANDED</a>
423
+ <a aria-grabbed=\"true\" #{DATA_IGNORE}>ARIA-GRABBED</a>
424
+ <a aria-haspopup=\"true\" #{DATA_IGNORE}>ARIA-HASPOPUP</a>
425
+ <a aria-level=\"1\" #{DATA_IGNORE}>ARIA-LEVEL</a>
426
+ <a aria-orientation=\"vertical\" #{DATA_IGNORE}>ARIA-ORIENTATION</a>
427
+ <a aria-pressed=\"true\" #{DATA_IGNORE}>ARIA-PRESSED</a>
428
+ <a aria-selected=\"true\" #{DATA_IGNORE}>ARIA-SELECTED</a>
429
+ <a aria-sort=\"ascending\" #{DATA_IGNORE}>ARIA-SORT</a>
430
+ <a aria-required=\"true\" #{DATA_IGNORE}>ARIA-REQUIRED</a>
431
+ <a aria-valuemin=\"2\" #{DATA_IGNORE}>ARIA-VALUEMIN</a>
432
+ <a aria-valuemax=\"10\" #{DATA_IGNORE}>ARIA-VALUEMAX</a>
433
+ <a aria-autocomplete=\"both\" #{DATA_IGNORE}>ARIA-AUTOCOMPLETE</a>
434
+ </body>
435
+ </html>
436
+ ")
437
+ display = Hatemile::Implementation::AccessibleDisplayImplementation.new(
438
+ html_parser,
439
+ CONFIGURE
440
+ )
441
+ display.display_all_waiaria_states
442
+ aria_busy = html_parser.find('[aria-busy]').first_result
443
+ aria_checked = html_parser.find('[aria-checked]').first_result
444
+ aria_dropeffect = html_parser.find('[aria-dropeffect]').first_result
445
+ aria_expanded = html_parser.find('[aria-expanded]').first_result
446
+ aria_grabbed = html_parser.find('[aria-grabbed]').first_result
447
+ aria_haspopup = html_parser.find('[aria-haspopup]').first_result
448
+ aria_level = html_parser.find('[aria-level]').first_result
449
+ aria_orientation = html_parser.find('[aria-orientation]').first_result
450
+ aria_pressed = html_parser.find('[aria-pressed]').first_result
451
+ aria_selected = html_parser.find('[aria-selected]').first_result
452
+ aria_sort = html_parser.find('[aria-sort]').first_result
453
+ aria_required = html_parser.find('[aria-required]').first_result
454
+ aria_valuemin = html_parser.find('[aria-valuemin]').first_result
455
+ aria_valuemax = html_parser.find('[aria-valuemax]').first_result
456
+ aria_autocomplete = html_parser.find('[aria-autocomplete]').first_result
457
+ ignore_aria_busy = html_parser.find('[aria-busy]').last_result
458
+ ignore_aria_checked = html_parser.find('[aria-checked]').last_result
459
+ ignore_aria_dropeffect = html_parser.find('[aria-dropeffect]').last_result
460
+ ignore_aria_expanded = html_parser.find('[aria-expanded]').last_result
461
+ ignore_aria_grabbed = html_parser.find('[aria-grabbed]').last_result
462
+ ignore_aria_haspopup = html_parser.find('[aria-haspopup]').last_result
463
+ ignore_aria_level = html_parser.find('[aria-level]').last_result
464
+ ignore_aria_orientation = html_parser.find('[aria-orientation]').last_result
465
+ ignore_aria_pressed = html_parser.find('[aria-pressed]').last_result
466
+ ignore_aria_selected = html_parser.find('[aria-selected]').last_result
467
+ ignore_aria_sort = html_parser.find('[aria-sort]').last_result
468
+ ignore_aria_required = html_parser.find('[aria-required]').last_result
469
+ ignore_aria_valuemin = html_parser.find('[aria-valuemin]').last_result
470
+ ignore_aria_valuemax = html_parser.find('[aria-valuemax]').last_result
471
+ ignore_aria_autocomplete = html_parser.find(
472
+ '[aria-autocomplete]'
473
+ ).last_result
474
+ span_busy = html_parser.find(aria_busy).find_children(
475
+ '.force-read-before[data-ariabusyof]'
476
+ ).first_result
477
+ span_checked = html_parser.find(aria_checked).find_children(
478
+ '.force-read-after[data-ariacheckedof]'
479
+ ).first_result
480
+ span_dropeffect = html_parser.find(aria_dropeffect).find_children(
481
+ '.force-read-after[data-ariadropeffectof]'
482
+ ).first_result
483
+ span_expanded = html_parser.find(aria_expanded).find_children(
484
+ '.force-read-after[data-ariaexpandedof]'
485
+ ).first_result
486
+ span_grabbed = html_parser.find(aria_grabbed).find_children(
487
+ '.force-read-after[data-ariagrabbedof]'
488
+ ).first_result
489
+ span_haspopup = html_parser.find(aria_haspopup).find_children(
490
+ '.force-read-after[data-ariahaspopupof]'
491
+ ).first_result
492
+ span_level = html_parser.find(aria_level).find_children(
493
+ '.force-read-before[data-arialevelof]'
494
+ ).first_result
495
+ span_orientation = html_parser.find(aria_orientation).find_children(
496
+ '.force-read-after[data-ariaorientationof]'
497
+ ).first_result
498
+ span_pressed = html_parser.find(aria_pressed).find_children(
499
+ '.force-read-after[data-ariapressedof]'
500
+ ).first_result
501
+ span_selected = html_parser.find(aria_selected).find_children(
502
+ '.force-read-after[data-ariaselectedof]'
503
+ ).first_result
504
+ span_sort = html_parser.find(aria_sort).find_children(
505
+ '.force-read-before[data-ariasortof]'
506
+ ).first_result
507
+ span_required = html_parser.find(aria_required).find_children(
508
+ '.force-read-after[data-attributerequiredof]'
509
+ ).first_result
510
+ span_valuemin = html_parser.find(aria_valuemin).find_children(
511
+ '.force-read-after[data-attributevalueminof]'
512
+ ).first_result
513
+ span_valuemax = html_parser.find(aria_valuemax).find_children(
514
+ '.force-read-after[data-attributevaluemaxof]'
515
+ ).first_result
516
+ span_autocomplete = html_parser.find(aria_autocomplete).find_children(
517
+ '.force-read-after[data-ariaautocompleteof]'
518
+ ).first_result
519
+ ignore_span_busy = html_parser.find(ignore_aria_busy).find_children(
520
+ '.force-read-before[data-ariabusyof]'
521
+ ).first_result
522
+ ignore_span_checked = html_parser.find(ignore_aria_checked).find_children(
523
+ '.force-read-after[data-ariacheckedof]'
524
+ ).first_result
525
+ ignore_span_dropeffect = html_parser.find(
526
+ ignore_aria_dropeffect
527
+ ).find_children('.force-read-after[data-ariadropeffectof]').first_result
528
+ ignore_span_expanded = html_parser.find(ignore_aria_expanded).find_children(
529
+ '.force-read-after[data-ariaexpandedof]'
530
+ ).first_result
531
+ ignore_span_grabbed = html_parser.find(ignore_aria_grabbed).find_children(
532
+ '.force-read-after[data-ariagrabbedof]'
533
+ ).first_result
534
+ ignore_span_haspopup = html_parser.find(ignore_aria_haspopup).find_children(
535
+ '.force-read-after[data-ariahaspopupof]'
536
+ ).first_result
537
+ ignore_span_level = html_parser.find(ignore_aria_level).find_children(
538
+ '.force-read-before[data-arialevelof]'
539
+ ).first_result
540
+ ignore_span_orientation = html_parser.find(
541
+ ignore_aria_orientation
542
+ ).find_children('.force-read-after[data-ariaorientationof]').first_result
543
+ ignore_span_pressed = html_parser.find(ignore_aria_pressed).find_children(
544
+ '.force-read-after[data-ariapressedof]'
545
+ ).first_result
546
+ ignore_span_selected = html_parser.find(ignore_aria_selected).find_children(
547
+ '.force-read-after[data-ariaselectedof]'
548
+ ).first_result
549
+ ignore_span_sort = html_parser.find(ignore_aria_sort).find_children(
550
+ '.force-read-before[data-ariasortof]'
551
+ ).first_result
552
+ ignore_span_required = html_parser.find(ignore_aria_required).find_children(
553
+ '.force-read-after[data-attributerequiredof]'
554
+ ).first_result
555
+ ignore_span_valuemin = html_parser.find(ignore_aria_valuemin).find_children(
556
+ '.force-read-after[data-attributevalueminof]'
557
+ ).first_result
558
+ ignore_span_valuemax = html_parser.find(ignore_aria_valuemax).find_children(
559
+ '.force-read-after[data-attributevaluemaxof]'
560
+ ).first_result
561
+ ignore_span_autocomplete = html_parser.find(
562
+ ignore_aria_autocomplete
563
+ ).find_children('.force-read-after[data-ariaautocompleteof]').first_result
564
+
565
+ assert_not_nil(span_busy)
566
+ assert_not_nil(span_checked)
567
+ assert_not_nil(span_dropeffect)
568
+ assert_not_nil(span_expanded)
569
+ assert_not_nil(span_grabbed)
570
+ assert_not_nil(span_haspopup)
571
+ assert_not_nil(span_level)
572
+ assert_not_nil(span_orientation)
573
+ assert_not_nil(span_pressed)
574
+ assert_not_nil(span_selected)
575
+ assert_not_nil(span_sort)
576
+ assert_not_nil(span_required)
577
+ assert_not_nil(span_valuemin)
578
+ assert_not_nil(span_valuemax)
579
+ assert_not_nil(span_autocomplete)
580
+ assert_nil(ignore_span_busy)
581
+ assert_nil(ignore_span_checked)
582
+ assert_nil(ignore_span_dropeffect)
583
+ assert_nil(ignore_span_expanded)
584
+ assert_nil(ignore_span_grabbed)
585
+ assert_nil(ignore_span_haspopup)
586
+ assert_nil(ignore_span_level)
587
+ assert_nil(ignore_span_orientation)
588
+ assert_nil(ignore_span_pressed)
589
+ assert_nil(ignore_span_selected)
590
+ assert_nil(ignore_span_sort)
591
+ assert_nil(ignore_span_required)
592
+ assert_nil(ignore_span_valuemin)
593
+ assert_nil(ignore_span_valuemax)
594
+ assert_nil(ignore_span_autocomplete)
595
+
596
+ assert_equal('(Updating) ', span_busy.get_text_content)
597
+ assert_equal(' (Checked)', span_checked.get_text_content)
598
+ assert_equal(' (Drop copy in target)', span_dropeffect.get_text_content)
599
+ assert_equal(' (Expanded)', span_expanded.get_text_content)
600
+ assert_equal(' (Dragging)', span_grabbed.get_text_content)
601
+ assert_equal(' (Has popup)', span_haspopup.get_text_content)
602
+ assert_equal('(Level: 1) ', span_level.get_text_content)
603
+ assert_equal(' (Vertical orientation)', span_orientation.get_text_content)
604
+ assert_equal(' (Pressed)', span_pressed.get_text_content)
605
+ assert_equal(' (Selected)', span_selected.get_text_content)
606
+ assert_equal('(Sorted ascending) ', span_sort.get_text_content)
607
+ assert_equal(' (Required)', span_required.get_text_content)
608
+ assert_equal(' (Minimum value: 2)', span_valuemin.get_text_content)
609
+ assert_equal(' (Maximum value: 10)', span_valuemax.get_text_content)
610
+ assert_equal(
611
+ ' (List or inline autocomplete)',
612
+ span_autocomplete.get_text_content
613
+ )
614
+ end
615
+
616
+ ##
617
+ # Test display_all_links_attributes method.
618
+ def test_display_all_links_attributes
619
+ html_parser = Hatemile::Util::Html::NokogiriLib::NokogiriHTMLDOMParser.new("
620
+ <!DOCTYPE html>
621
+ <html>
622
+ <head>
623
+ <title>HaTeMiLe Tests</title>
624
+ <meta charset=\"UTF-8\" />
625
+ </head>
626
+ <body>
627
+ <a href=\"https://github.com\" target=\"_blank\">Github</a>
628
+ <a href=\"https://github.com/fluidicon.png\" download>
629
+ Github icon
630
+ </a>
631
+ <a href=\"https://github.com\" target=\"_blank\" #{DATA_IGNORE}>
632
+ Github
633
+ </a>
634
+ <a href=\"https://github.com/fluidicon.png\" download #{DATA_IGNORE}>
635
+ Github icon
636
+ </a>
637
+ </body>
638
+ </html>
639
+ ")
640
+ display = Hatemile::Implementation::AccessibleDisplayImplementation.new(
641
+ html_parser,
642
+ CONFIGURE
643
+ )
644
+ display.display_all_links_attributes
645
+ link1 = html_parser.find('a [data-attributetargetof]').first_result
646
+ link2 = html_parser.find('a [data-attributedownloadof]').first_result
647
+ link3 = html_parser.find(
648
+ "a[#{DATA_IGNORE}] [data-attributetargetof]"
649
+ ).first_result
650
+ link4 = html_parser.find(
651
+ "a[#{DATA_IGNORE}] [data-attributedownloadof]"
652
+ ).first_result
653
+
654
+ assert_not_nil(link1)
655
+ assert_not_nil(link2)
656
+ assert_nil(link3)
657
+ assert_nil(link4)
658
+ assert_equal('(Open this link in new tab) ', link1.get_text_content)
659
+ assert_equal('(Download) ', link2.get_text_content)
660
+ end
661
+
662
+ ##
663
+ # Test display_all_titles method.
664
+ def test_display_all_titles
665
+ html_parser = Hatemile::Util::Html::NokogiriLib::NokogiriHTMLDOMParser.new("
666
+ <!DOCTYPE html>
667
+ <html>
668
+ <head>
669
+ <title>HaTeMiLe Tests</title>
670
+ <meta charset=\"UTF-8\" />
671
+ </head>
672
+ <body>
673
+ <a href=\"https://github.com/\" title=\"Link\">Github</a>
674
+ <span title=\"Text\">Span</span>
675
+ <label for=\"field1\">Field1</label>
676
+ <input type=\"number\" id=\"field1\" title=\"Spin button\" />
677
+ <img src=\"image1.png\" title=\"Image\" />
678
+
679
+ <a href=\"https://github.com/\" title=\"Link\" #{DATA_IGNORE}>
680
+ Github
681
+ </a>
682
+ <span title=\"Text\" #{DATA_IGNORE}>Span</span>
683
+ <label for=\"field2\" #{DATA_IGNORE}>Field2</label>
684
+ <input type=\"number\" id=\"field2\" title=\"Spin button\" />
685
+ <img src=\"image2.png\" title=\"Image\" #{DATA_IGNORE} />
686
+ </body>
687
+ </html>
688
+ ")
689
+ display = Hatemile::Implementation::AccessibleDisplayImplementation.new(
690
+ html_parser,
691
+ CONFIGURE
692
+ )
693
+ display.display_all_titles
694
+ body = html_parser.find('body').first_result
695
+ link = html_parser.find('a [data-attributetitleof]').first_result
696
+ span = html_parser.find('span[title]').first_result
697
+ index_span = body.get_children_elements.index(span)
698
+ input = html_parser.find('label [data-attributetitleof]').first_result
699
+ image = html_parser.find('img').first_result
700
+ ignore_link = html_parser.find(
701
+ "a[#{DATA_IGNORE}] [data-attributetitleof]"
702
+ ).first_result
703
+ ignore_span = html_parser.find("span[title][#{DATA_IGNORE}]").first_result
704
+ ignore_input = html_parser.find(
705
+ "label[#{DATA_IGNORE}] [data-attributetitleof]"
706
+ ).first_result
707
+ ignore_image = html_parser.find("img[#{DATA_IGNORE}]").first_result
708
+
709
+ assert_not_nil(link)
710
+ assert_not_nil(input)
711
+ assert_nil(ignore_link)
712
+ assert_nil(ignore_input)
713
+ assert_equal('(Title: Link) ', link.get_text_content)
714
+ assert_equal(
715
+ '(Title: Text) ',
716
+ body.get_children_elements[index_span - 1].get_text_content
717
+ )
718
+ assert_equal('(Title: Spin button) ', input.get_text_content)
719
+ assert(image.has_attribute?('alt'))
720
+ assert_equal('Image', image.get_attribute('alt'))
721
+ assert(image.has_attribute?('data-attributetitleof'))
722
+ assert_equal(
723
+ image,
724
+ html_parser.find(
725
+ "##{image.get_attribute('data-attributetitleof')}"
726
+ ).first_result
727
+ )
728
+ assert(!ignore_image.has_attribute?('data-attributetitleof'))
729
+ assert_nil(
730
+ html_parser.find(
731
+ "[data-roleof=\"#{ignore_span.get_attribute('id')}\"]"
732
+ ).first_result
733
+ )
734
+ end
735
+
736
+ ##
737
+ # Test display_all_languages method.
738
+ def test_display_all_languages
739
+ html_parser = Hatemile::Util::Html::NokogiriLib::NokogiriHTMLDOMParser.new("
740
+ <!DOCTYPE html>
741
+ <html lang=\"en\">
742
+ <head>
743
+ <title>HaTeMiLe Tests</title>
744
+ <meta charset=\"UTF-8\" />
745
+ </head>
746
+ <body>
747
+ <a href=\"https://es.wikipedia.org/\" hreflang=\"es\">
748
+ Wikipedia
749
+ </a>
750
+ <span lang=\"pt-br\">Texto</span>
751
+ <label for=\"field1\">Contrôle1</label>
752
+ <input type=\"text\" id=\"field1\" lang=\"fr\" />
753
+
754
+ <a href=\"https://es.wikipedia.org/\" hreflang=\"es\" #{DATA_IGNORE}>
755
+ Wikipedia
756
+ </a>
757
+ <span lang=\"pt-br\" #{DATA_IGNORE}>Texto</span>
758
+ <label for=\"field2\" #{DATA_IGNORE}>Contrôle2</label>
759
+ <input type=\"text\" id=\"field2\" lang=\"fr\" #{DATA_IGNORE} />
760
+ </body>
761
+ </html>
762
+ ")
763
+ display = Hatemile::Implementation::AccessibleDisplayImplementation.new(
764
+ html_parser,
765
+ CONFIGURE
766
+ )
767
+ display.display_all_languages
768
+ body = html_parser.find('body').first_result
769
+ a = html_parser.find('a').first_result
770
+ span = html_parser.find('span[lang="pt-br"]').first_result
771
+ index_span = body.get_children_elements.index(span)
772
+ label = html_parser.find('label').first_result
773
+ ignore_a = html_parser.find('a').last_result
774
+ ignore_span = html_parser.find('span[lang="pt-br"]').last_result
775
+ ignore_label = html_parser.find('label').last_result
776
+
777
+ assert_equal(
778
+ '(Begin of language: English) ',
779
+ body.get_first_element_child.get_text_content
780
+ )
781
+ assert_equal(
782
+ ' (End of language: English)',
783
+ body.get_last_element_child.get_text_content
784
+ )
785
+ assert_equal(
786
+ '(Begin of language: Spanish) ',
787
+ a.get_first_element_child.get_text_content
788
+ )
789
+ assert_equal(
790
+ ' (End of language: Spanish)',
791
+ a.get_last_element_child.get_text_content
792
+ )
793
+ assert_equal(
794
+ '(Begin of language: Portuguese) ',
795
+ body.get_children_elements[index_span - 1].get_text_content
796
+ )
797
+ assert_equal(
798
+ ' (End of language: Portuguese)',
799
+ body.get_children_elements[index_span + 1].get_text_content
800
+ )
801
+ assert_equal(
802
+ '(Begin of language: French) ',
803
+ html_parser.find(label).find_children(
804
+ '[data-languageof]'
805
+ ).first_result.get_text_content
806
+ )
807
+ assert_equal(
808
+ ' (End of language: French)',
809
+ html_parser.find(label).find_children(
810
+ '[data-languageof]'
811
+ ).last_result.get_text_content
812
+ )
813
+ assert(!ignore_a.has_children_elements?)
814
+ assert_nil(
815
+ html_parser.find(
816
+ "[data-roleof=\"#{ignore_span.get_attribute('id')}\"]"
817
+ ).first_result
818
+ )
819
+ assert(!ignore_label.has_children_elements?)
820
+ end
821
+
822
+ ##
823
+ # Test display_all_alternative_text_images method.
824
+ def test_display_all_alternative_text_images
825
+ html_parser = Hatemile::Util::Html::NokogiriLib::NokogiriHTMLDOMParser.new("
826
+ <!DOCTYPE html>
827
+ <html lang=\"en\">
828
+ <head>
829
+ <title>HaTeMiLe Tests</title>
830
+ <meta charset=\"UTF-8\" />
831
+ </head>
832
+ <body>
833
+ <img src=\"image1.jpg\" title=\"Image1\" id=\"image1\" />
834
+ <img src=\"image2.jpg\" alt=\"Image2\" id=\"image2\" />
835
+ <img src=\"image3.jpg\" id=\"image3\" />
836
+
837
+ <img src=\"ima4.jpg\" title=\"Image4\" id=\"image4\" #{DATA_IGNORE} />
838
+ <img src=\"image5.jpg\" alt=\"Image5\" id=\"image5\" #{DATA_IGNORE} />
839
+ <img src=\"image6.jpg\" id=\"image6\" #{DATA_IGNORE} />
840
+ </body>
841
+ </html>
842
+ ")
843
+ display = Hatemile::Implementation::AccessibleDisplayImplementation.new(
844
+ html_parser,
845
+ CONFIGURE
846
+ )
847
+ display.display_all_alternative_text_images
848
+ image1 = html_parser.find('#image1').first_result
849
+ image2 = html_parser.find('#image2').first_result
850
+ image3 = html_parser.find('#image3').first_result
851
+ image4 = html_parser.find('#image4').first_result
852
+ image5 = html_parser.find('#image5').first_result
853
+ image6 = html_parser.find('#image6').first_result
854
+
855
+ assert(image1.has_attribute?('alt'))
856
+ assert_equal('Image1', image1.get_attribute('alt'))
857
+ assert(image2.has_attribute?('title'))
858
+ assert_equal('Image2', image2.get_attribute('title'))
859
+ assert(image3.has_attribute?('alt'))
860
+ assert('', image3.get_attribute('alt'))
861
+ assert(!image3.has_attribute?('title'))
862
+ assert(image3.has_attribute?('role'))
863
+ assert('presentation', image3.get_attribute('role'))
864
+ assert(image3.has_attribute?('aria-hidden'))
865
+ assert('true', image3.get_attribute('aria-hidden'))
866
+ assert(!image4.has_attribute?('alt'))
867
+ assert(!image5.has_attribute?('title'))
868
+ assert(!image6.has_attribute?('alt'))
869
+ assert(!image6.has_attribute?('title'))
870
+ assert(!image6.has_attribute?('role'))
871
+ assert(!image6.has_attribute?('aria-hidden'))
872
+ end
873
+ end