hatemile 2.0

Sign up to get free protection for your applications and to get access to all the features.
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,283 @@
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_form_implementation'
24
+ )
25
+ require File.join(
26
+ File.dirname(File.dirname(__FILE__)),
27
+ 'lib',
28
+ 'hatemile',
29
+ 'util',
30
+ 'html',
31
+ 'nokogiri',
32
+ 'nokogiri_html_dom_parser'
33
+ )
34
+
35
+ ##
36
+ # Test methods of Hatemile::Implementation::AccessibleFormImplementation class.
37
+ class TestAccessibleFormImplementation < Test::Unit::TestCase
38
+ ##
39
+ # The name of attribute for not modify the elements.
40
+ DATA_IGNORE = 'data-ignoreaccessibilityfix="true"'.freeze
41
+
42
+ ##
43
+ # Test mark_all_required_fields method.
44
+ def test_mark_all_required_fields
45
+ html_parser = Hatemile::Util::Html::NokogiriLib::NokogiriHTMLDOMParser.new("
46
+ <!DOCTYPE html>
47
+ <html>
48
+ <head>
49
+ <title>HaTeMiLe Tests</title>
50
+ <meta charset=\"UTF-8\" />
51
+ </head>
52
+ <body>
53
+ <label for=\"field1\">Field1</label>
54
+ <input type=\"text\" id=\"field1\" required />
55
+ <label for=\"field2\">Field2</label>
56
+ <input type=\"text\" id=\"field2\" required #{DATA_IGNORE} />
57
+ <label for=\"field3\">Field3</label>
58
+ <input type=\"text\" id=\"field3\" />
59
+ </body>
60
+ </html>
61
+ ")
62
+ accessibleform =
63
+ Hatemile::Implementation::AccessibleFormImplementation.new(html_parser)
64
+ accessibleform.mark_all_required_fields
65
+ field1 = html_parser.find('#field1').first_result
66
+ field2 = html_parser.find('#field2').first_result
67
+ field3 = html_parser.find('#field3').first_result
68
+
69
+ assert_equal('true', field1.get_attribute('aria-required'))
70
+ assert(!field2.has_attribute?('aria-required'))
71
+ assert(!field3.has_attribute?('aria-required'))
72
+ end
73
+
74
+ ##
75
+ # Test mark_all_range_fields method.
76
+ def test_mark_all_range_fields
77
+ html_parser = Hatemile::Util::Html::NokogiriLib::NokogiriHTMLDOMParser.new("
78
+ <!DOCTYPE html>
79
+ <html>
80
+ <head>
81
+ <title>HaTeMiLe Tests</title>
82
+ <meta charset=\"UTF-8\" />
83
+ </head>
84
+ <body>
85
+ <label for=\"field1\">Field1</label>
86
+ <input type=\"number\" min=\"0\" id=\"field1\" />
87
+ <label for=\"field2\">Field2</label>
88
+ <input type=\"range\" max=\"10\" id=\"field2\" />
89
+ <label for=\"field3\">Field3</label>
90
+ <input type=\"number\" min=\"1\" max=\"9\" id=\"field3\" />
91
+ <label for=\"field4\">Field4</label>
92
+ <input type=\"number\" id=\"field4\" />
93
+ <label for=\"field5\">Field5</label>
94
+ <input type=\"number\" min=\"0\" id=\"field5\" #{DATA_IGNORE} />
95
+ <label for=\"field6\">Field6</label>
96
+ <input type=\"number\" max=\"11\" id=\"field6\" #{DATA_IGNORE} />
97
+ </body>
98
+ </html>
99
+ ")
100
+ accessibleform =
101
+ Hatemile::Implementation::AccessibleFormImplementation.new(html_parser)
102
+ accessibleform.mark_all_range_fields
103
+ field1 = html_parser.find('#field1').first_result
104
+ field2 = html_parser.find('#field2').first_result
105
+ field3 = html_parser.find('#field3').first_result
106
+ field4 = html_parser.find('#field4').first_result
107
+ field5 = html_parser.find('#field5').first_result
108
+ field6 = html_parser.find('#field6').first_result
109
+
110
+ assert_equal('0', field1.get_attribute('aria-valuemin'))
111
+ assert_equal('10', field2.get_attribute('aria-valuemax'))
112
+ assert_equal('1', field3.get_attribute('aria-valuemin'))
113
+ assert_equal('9', field3.get_attribute('aria-valuemax'))
114
+ assert(!field4.has_attribute?('aria-valuemin'))
115
+ assert(!field4.has_attribute?('aria-valuemax'))
116
+ assert(!field5.has_attribute?('aria-valuemin'))
117
+ assert(!field6.has_attribute?('aria-valuemax'))
118
+ end
119
+
120
+ ##
121
+ # Test mark_all_autocomplete_fields method.
122
+ def test_mark_all_autocomplete_fields
123
+ html_parser = Hatemile::Util::Html::NokogiriLib::NokogiriHTMLDOMParser.new("
124
+ <!DOCTYPE html>
125
+ <html>
126
+ <head>
127
+ <title>HaTeMiLe Tests</title>
128
+ <meta charset=\"UTF-8\" />
129
+ </head>
130
+ <body>
131
+ <!-- Autocomplete ON -->
132
+ <label for=\"field1\">Field1</label>
133
+ <input type=\"text\" id=\"field1\" autocomplete=\"on\" />
134
+ <label for=\"field2\">Field2</label>
135
+ <textarea id=\"field2\" autocomplete=\"on\"></textarea>
136
+ <label for=\"field3\">Field3</label>
137
+ <input type=\"text\" id=\"field3\" list=\"datalist1\" />
138
+ <datalist id=\"datalist1\">
139
+ <option value=\"Value1\" />
140
+ <option value=\"Value2\" />
141
+ <option value=\"Value3\" />
142
+ <option value=\"Value4\" />
143
+ </datalist>
144
+ <form autocomplete=\"on\" id=\"form1\">
145
+ <label for=\"field4\">Field4</label>
146
+ <input type=\"text\" id=\"field4\" />
147
+ <label for=\"field5\">Field5</label>
148
+ <textarea id=\"field5\"></textarea>
149
+ <label for=\"field6\">Field6</label>
150
+ <input type=\"text\" id=\"field6\" autocomplete=\"off\" />
151
+ <label for=\"field7\">Field7</label>
152
+ <textarea id=\"field7\" autocomplete=\"off\"></textarea>
153
+ </form>
154
+ <label for=\"field8\">Field8</label>
155
+ <input type=\"text\" id=\"field8\" form=\"form1\" />
156
+ <label for=\"field9\">Field9</label>
157
+ <input id=\"field9\" form=\"form1\" autocomplete=\"off\" />
158
+
159
+ <!-- Autocomplete OFF -->
160
+ <label for=\"field10\">Field10</label>
161
+ <input type=\"text\" id=\"field10\" autocomplete=\"off\" />
162
+ <label for=\"field11\">Field11</label>
163
+ <textarea id=\"field11\" autocomplete=\"off\"></textarea>
164
+ <form autocomplete=\"off\" id=\"form2\">
165
+ <label for=\"field12\">Field12</label>
166
+ <input type=\"text\" id=\"field12\" />
167
+ <label for=\"field13\">Field13</label>
168
+ <textarea id=\"field13\"></textarea>
169
+ <label for=\"field14\">Field14</label>
170
+ <input type=\"text\" id=\"field14\" autocomplete=\"on\" />
171
+ <label for=\"field15\">Field15</label>
172
+ <textarea id=\"field15\" autocomplete=\"on\"></textarea>
173
+ <label for=\"field16\">Field16</label>
174
+ <input type=\"text\" id=\"field16\" list=\"datalist2\" />
175
+ <datalist id=\"datalist2\">
176
+ <option value=\"Value1\" />
177
+ <option value=\"Value2\" />
178
+ <option value=\"Value3\" />
179
+ <option value=\"Value4\" />
180
+ </datalist>
181
+ </form>
182
+ <label for=\"field17\">Field17</label>
183
+ <input type=\"text\" id=\"field17\" form=\"form2\" />
184
+ <label for=\"field18\">Field18</label>
185
+ <input id=\"field18\" form=\"form2\" autocomplete=\"on\" />
186
+
187
+ <!-- Ignore -->
188
+ <label for=\"field19\">Field19</label>
189
+ <input id=\"field19\" autocomplete=\"on\" #{DATA_IGNORE} />
190
+ <label for=\"field20\">Field20</label>
191
+ <textarea id=\"field20\" autocomplete=\"on\" #{DATA_IGNORE}>
192
+ </textarea>
193
+ <label for=\"field21\">Field21</label>
194
+ <input id=\"field21\" list=\"datalist3\" #{DATA_IGNORE} />
195
+ <datalist id=\"datalist3\">
196
+ <option value=\"Value1\" />
197
+ <option value=\"Value2\" />
198
+ <option value=\"Value3\" />
199
+ <option value=\"Value4\" />
200
+ </datalist>
201
+ <form autocomplete=\"on\" id=\"form3\" #{DATA_IGNORE}>
202
+ <label for=\"field22\">Field22</label>
203
+ <input type=\"text\" id=\"field22\" />
204
+ <label for=\"field23\">Field23</label>
205
+ <textarea id=\"field23\"></textarea>
206
+ <label for=\"field24\">Field24</label>
207
+ <input type=\"text\" id=\"field24\" autocomplete=\"off\" />
208
+ <label for=\"field25\">Field25</label>
209
+ <textarea id=\"field25\" autocomplete=\"off\"></textarea>
210
+ </form>
211
+ <label for=\"field26\">Field26</label>
212
+ <input type=\"text\" id=\"field26\" form=\"form3\" />
213
+ <label for=\"field27\">Field27</label>
214
+ <input id=\"field27\" form=\"form3\" autocomplete=\"off\" />
215
+ <label for=\"field28\">Field28</label>
216
+ <input id=\"field28\" form=\"form3\" #{DATA_IGNORE} />
217
+ </body>
218
+ </html>
219
+ ")
220
+ accessibleform =
221
+ Hatemile::Implementation::AccessibleFormImplementation.new(html_parser)
222
+ accessibleform.mark_all_autocomplete_fields
223
+ field1 = html_parser.find('#field1').first_result
224
+ field2 = html_parser.find('#field2').first_result
225
+ field3 = html_parser.find('#field3').first_result
226
+ field4 = html_parser.find('#field4').first_result
227
+ field5 = html_parser.find('#field5').first_result
228
+ field6 = html_parser.find('#field6').first_result
229
+ field7 = html_parser.find('#field7').first_result
230
+ field8 = html_parser.find('#field8').first_result
231
+ field9 = html_parser.find('#field9').first_result
232
+ field10 = html_parser.find('#field10').first_result
233
+ field11 = html_parser.find('#field11').first_result
234
+ field12 = html_parser.find('#field12').first_result
235
+ field13 = html_parser.find('#field13').first_result
236
+ field14 = html_parser.find('#field14').first_result
237
+ field15 = html_parser.find('#field15').first_result
238
+ field16 = html_parser.find('#field16').first_result
239
+ field17 = html_parser.find('#field17').first_result
240
+ field18 = html_parser.find('#field18').first_result
241
+ field19 = html_parser.find('#field19').first_result
242
+ field20 = html_parser.find('#field20').first_result
243
+ field21 = html_parser.find('#field21').first_result
244
+ field22 = html_parser.find('#field22').first_result
245
+ field23 = html_parser.find('#field23').first_result
246
+ field24 = html_parser.find('#field24').first_result
247
+ field25 = html_parser.find('#field25').first_result
248
+ field26 = html_parser.find('#field26').first_result
249
+ field27 = html_parser.find('#field27').first_result
250
+ field28 = html_parser.find('#field28').first_result
251
+
252
+ assert_equal('both', field1.get_attribute('aria-autocomplete'))
253
+ assert_equal('both', field2.get_attribute('aria-autocomplete'))
254
+ assert_equal('list', field3.get_attribute('aria-autocomplete'))
255
+ assert_equal('both', field4.get_attribute('aria-autocomplete'))
256
+ assert_equal('both', field5.get_attribute('aria-autocomplete'))
257
+ assert_equal('none', field6.get_attribute('aria-autocomplete'))
258
+ assert_equal('none', field7.get_attribute('aria-autocomplete'))
259
+ assert_equal('both', field8.get_attribute('aria-autocomplete'))
260
+ assert_equal('none', field9.get_attribute('aria-autocomplete'))
261
+
262
+ assert_equal('none', field10.get_attribute('aria-autocomplete'))
263
+ assert_equal('none', field11.get_attribute('aria-autocomplete'))
264
+ assert_equal('none', field12.get_attribute('aria-autocomplete'))
265
+ assert_equal('none', field13.get_attribute('aria-autocomplete'))
266
+ assert_equal('both', field14.get_attribute('aria-autocomplete'))
267
+ assert_equal('both', field15.get_attribute('aria-autocomplete'))
268
+ assert_equal('list', field16.get_attribute('aria-autocomplete'))
269
+ assert_equal('none', field17.get_attribute('aria-autocomplete'))
270
+ assert_equal('both', field18.get_attribute('aria-autocomplete'))
271
+
272
+ assert(!field19.has_attribute?('aria-autocomplete'))
273
+ assert(!field20.has_attribute?('aria-autocomplete'))
274
+ assert(!field21.has_attribute?('aria-autocomplete'))
275
+ assert(!field22.has_attribute?('aria-autocomplete'))
276
+ assert(!field23.has_attribute?('aria-autocomplete'))
277
+ assert(!field24.has_attribute?('aria-autocomplete'))
278
+ assert(!field25.has_attribute?('aria-autocomplete'))
279
+ assert('both', field26.get_attribute('aria-autocomplete'))
280
+ assert('none', field27.get_attribute('aria-autocomplete'))
281
+ assert(!field28.has_attribute?('aria-autocomplete'))
282
+ end
283
+ end
@@ -0,0 +1,228 @@
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_navigation_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::AccessibleNavigationImplementation
44
+ # class.
45
+ class TestAccessibleNavigationImplementation < 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 provide_navigation_by_all_skippers method.
56
+ def test_provide_navigation_by_all_skippers
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
+ <main>Main content</main>
66
+ <div id=\"container-shortcuts-after\">Container of shortcuts</div>
67
+ <div id=\"container-heading-after\" #{DATA_IGNORE}>
68
+ Container of headings
69
+ </div>
70
+ </body>
71
+ </html>
72
+ ")
73
+ navigation =
74
+ Hatemile::Implementation::AccessibleNavigationImplementation.new(
75
+ html_parser,
76
+ CONFIGURE
77
+ )
78
+ navigation.provide_navigation_by_all_skippers
79
+ body_children = html_parser.find('body').first_result.get_children_elements
80
+ main_element = html_parser.find('main').first_result
81
+ main_id = main_element.get_attribute('id')
82
+ main_anchor = html_parser.find(
83
+ "[data-anchorfor=\"#{main_id}\"]"
84
+ ).first_result
85
+ main_link = html_parser.find(
86
+ "#container-skippers a[href=\"##{main_anchor.get_attribute('id')}\"]"
87
+ ).first_result
88
+ container_shortcuts = html_parser.find(
89
+ '#container-shortcuts-after'
90
+ ).first_result
91
+ container_shortcuts_anchor = html_parser.find(
92
+ '[data-anchorfor="container-shortcuts-after"]'
93
+ ).first_result
94
+ container_shortcuts_id = container_shortcuts_anchor.get_attribute('id')
95
+ container_shortcuts_link = html_parser.find(
96
+ "#container-skippers a[href=\"##{container_shortcuts_id}\"]"
97
+ ).first_result
98
+ container_heading_anchor = html_parser.find(
99
+ '[data-anchorfor="container-heading-after"]'
100
+ ).first_result
101
+
102
+ assert_not_nil(html_parser.find('#container-skippers').first_result)
103
+ assert_not_nil(main_anchor)
104
+ assert_not_nil(container_shortcuts_anchor)
105
+ assert_nil(container_heading_anchor)
106
+ assert_not_nil(main_link)
107
+ assert_not_nil(container_shortcuts_link)
108
+ assert_equal(
109
+ body_children.index(main_element),
110
+ body_children.index(main_anchor) + 1
111
+ )
112
+ assert_equal(
113
+ body_children.index(container_shortcuts),
114
+ body_children.index(container_shortcuts_anchor) + 1
115
+ )
116
+ end
117
+
118
+ ##
119
+ # Test provide_navigation_by_all_headings method.
120
+ def test_provide_navigation_by_all_headings
121
+ html_parser = Hatemile::Util::Html::NokogiriLib::NokogiriHTMLDOMParser.new("
122
+ <!DOCTYPE html>
123
+ <html>
124
+ <head>
125
+ <title>HaTeMiLe Tests</title>
126
+ <meta charset=\"UTF-8\" />
127
+ </head>
128
+ <body>
129
+ <div>
130
+ <h1><span>Heading 1</span></h1>
131
+ <h2><span>Heading 1.2.1</span></h2>
132
+ <div>
133
+ <span></span>
134
+ <div><h2><span>Heading 1.2.2</span></h2></div>
135
+ <span></span>
136
+ </div>
137
+ <h3><span>Heading 1.2.2.3.1</span></h3>
138
+ <h4><span>Heading 1.2.2.3.1.4.1</span></h4>
139
+ <h2><span>Heading 1.2.3</span></h2>
140
+ <h3><span>Heading 1.2.3.3.1</span></h3>
141
+ </div>
142
+ </body>
143
+ </html>
144
+ ")
145
+ navigation =
146
+ Hatemile::Implementation::AccessibleNavigationImplementation.new(
147
+ html_parser,
148
+ CONFIGURE
149
+ )
150
+ navigation.provide_navigation_by_all_headings
151
+ container = html_parser.find('#container-heading-after').first_result
152
+ headings = html_parser.find('h1, h2, h3, h4').list_results
153
+ container_list = html_parser.find(container).find_descendants(
154
+ '[data-headinglevel]'
155
+ ).list_results
156
+ links = html_parser.find('[data-headinglevel] a').list_results
157
+
158
+ assert_not_nil(container)
159
+ assert_equal(
160
+ 1,
161
+ container_list.first.get_attribute('data-headinglevel').to_i
162
+ )
163
+ assert_equal(2, container_list[1].get_attribute('data-headinglevel').to_i)
164
+ assert_equal(2, container_list[2].get_attribute('data-headinglevel').to_i)
165
+ assert_equal(3, container_list[3].get_attribute('data-headinglevel').to_i)
166
+ assert_equal(4, container_list[4].get_attribute('data-headinglevel').to_i)
167
+ assert_equal(2, container_list[5].get_attribute('data-headinglevel').to_i)
168
+ assert_equal(3, container_list[6].get_attribute('data-headinglevel').to_i)
169
+ links.each do |link|
170
+ anchor = html_parser.find(link.get_attribute('href')).first_result
171
+ heading = html_parser.find(
172
+ '#' + anchor.get_attribute('data-headinganchorfor')
173
+ ).first_result
174
+ children_elements = anchor.get_parent_element.get_children_elements
175
+
176
+ assert_not_nil(anchor)
177
+ assert(headings.include?(heading))
178
+ assert_equal(
179
+ children_elements.index(anchor),
180
+ children_elements.index(heading) - 1
181
+ )
182
+ end
183
+ end
184
+
185
+ ##
186
+ # Test provide_navigation_to_all_long_descriptions method.
187
+ def test_provide_navigation_to_all_long_descriptions
188
+ html_parser = Hatemile::Util::Html::NokogiriLib::NokogiriHTMLDOMParser.new("
189
+ <!DOCTYPE html>
190
+ <html>
191
+ <head>
192
+ <title>HaTeMiLe Tests</title>
193
+ <meta charset=\"UTF-8\" />
194
+ </head>
195
+ <body>
196
+ <img src=\"i1.jpg\" alt=\"I1\" />
197
+ <img src=\"i2.jpg\" alt=\"I2\" longdesc=\"i2.html\" />
198
+ <img src=\"i3.jpg\" alt=\"\" longdesc=\"i3.html\" />
199
+ <img src=\"i4.jpg\" longdesc=\"i4.html\" />
200
+ <img src=\"i5.jpg\" alt=\"I5\" longdesc=\"i5.html\" #{DATA_IGNORE} />
201
+ </body>
202
+ </html>
203
+ ")
204
+ navigation =
205
+ Hatemile::Implementation::AccessibleNavigationImplementation.new(
206
+ html_parser,
207
+ CONFIGURE
208
+ )
209
+ navigation.provide_navigation_to_all_long_descriptions
210
+ long_description_links = html_parser.find(
211
+ '[data-attributelongdescriptionof]'
212
+ ).list_results
213
+ image2_link = long_description_links.first
214
+ image2 = html_parser.find(
215
+ '#' + image2_link.get_attribute('data-attributelongdescriptionof')
216
+ ).first_result
217
+ image3_link = long_description_links.last
218
+ image3 = html_parser.find(
219
+ '#' + image3_link.get_attribute('data-attributelongdescriptionof')
220
+ ).first_result
221
+
222
+ assert_equal(2, long_description_links.length)
223
+ assert_equal('i2.jpg', image2.get_attribute('src'))
224
+ assert_equal('i3.jpg', image3.get_attribute('src'))
225
+ assert_equal(' (Long description of I2)', image2_link.get_text_content)
226
+ assert_equal(' (Long description of )', image3_link.get_text_content)
227
+ end
228
+ end