capybara 2.15.1 → 3.36.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (311) hide show
  1. checksums.yaml +5 -5
  2. data/.yardopts +1 -1
  3. data/History.md +902 -10
  4. data/License.txt +1 -1
  5. data/README.md +103 -75
  6. data/lib/capybara/config.rb +29 -56
  7. data/lib/capybara/cucumber.rb +2 -3
  8. data/lib/capybara/driver/base.rb +39 -18
  9. data/lib/capybara/driver/node.rb +36 -10
  10. data/lib/capybara/dsl.rb +15 -6
  11. data/lib/capybara/helpers.rb +65 -30
  12. data/lib/capybara/minitest/spec.rb +173 -81
  13. data/lib/capybara/minitest.rb +220 -111
  14. data/lib/capybara/node/actions.rb +274 -171
  15. data/lib/capybara/node/base.rb +41 -34
  16. data/lib/capybara/node/document.rb +15 -3
  17. data/lib/capybara/node/document_matchers.rb +19 -21
  18. data/lib/capybara/node/element.rb +353 -137
  19. data/lib/capybara/node/finders.rb +144 -138
  20. data/lib/capybara/node/matchers.rb +369 -209
  21. data/lib/capybara/node/simple.rb +59 -26
  22. data/lib/capybara/queries/active_element_query.rb +18 -0
  23. data/lib/capybara/queries/ancestor_query.rb +13 -10
  24. data/lib/capybara/queries/base_query.rb +39 -28
  25. data/lib/capybara/queries/current_path_query.rb +22 -25
  26. data/lib/capybara/queries/match_query.rb +14 -7
  27. data/lib/capybara/queries/selector_query.rb +646 -145
  28. data/lib/capybara/queries/sibling_query.rb +12 -10
  29. data/lib/capybara/queries/style_query.rb +45 -0
  30. data/lib/capybara/queries/text_query.rb +56 -38
  31. data/lib/capybara/queries/title_query.rb +8 -11
  32. data/lib/capybara/rack_test/browser.rb +57 -41
  33. data/lib/capybara/rack_test/css_handlers.rb +6 -4
  34. data/lib/capybara/rack_test/driver.rb +18 -13
  35. data/lib/capybara/rack_test/errors.rb +6 -0
  36. data/lib/capybara/rack_test/form.rb +73 -58
  37. data/lib/capybara/rack_test/node.rb +188 -81
  38. data/lib/capybara/rails.rb +3 -7
  39. data/lib/capybara/registration_container.rb +44 -0
  40. data/lib/capybara/registrations/drivers.rb +42 -0
  41. data/lib/capybara/registrations/patches/puma_ssl.rb +29 -0
  42. data/lib/capybara/registrations/servers.rb +45 -0
  43. data/lib/capybara/result.rb +96 -62
  44. data/lib/capybara/rspec/features.rb +17 -50
  45. data/lib/capybara/rspec/matcher_proxies.rb +52 -15
  46. data/lib/capybara/rspec/matchers/base.rb +111 -0
  47. data/lib/capybara/rspec/matchers/become_closed.rb +33 -0
  48. data/lib/capybara/rspec/matchers/compound.rb +88 -0
  49. data/lib/capybara/rspec/matchers/count_sugar.rb +37 -0
  50. data/lib/capybara/rspec/matchers/have_ancestor.rb +28 -0
  51. data/lib/capybara/rspec/matchers/have_current_path.rb +29 -0
  52. data/lib/capybara/rspec/matchers/have_selector.rb +77 -0
  53. data/lib/capybara/rspec/matchers/have_sibling.rb +27 -0
  54. data/lib/capybara/rspec/matchers/have_text.rb +33 -0
  55. data/lib/capybara/rspec/matchers/have_title.rb +29 -0
  56. data/lib/capybara/rspec/matchers/match_selector.rb +27 -0
  57. data/lib/capybara/rspec/matchers/match_style.rb +43 -0
  58. data/lib/capybara/rspec/matchers/spatial_sugar.rb +39 -0
  59. data/lib/capybara/rspec/matchers.rb +144 -264
  60. data/lib/capybara/rspec.rb +7 -11
  61. data/lib/capybara/selector/builders/css_builder.rb +84 -0
  62. data/lib/capybara/selector/builders/xpath_builder.rb +71 -0
  63. data/lib/capybara/selector/css.rb +89 -17
  64. data/lib/capybara/selector/definition/button.rb +68 -0
  65. data/lib/capybara/selector/definition/checkbox.rb +26 -0
  66. data/lib/capybara/selector/definition/css.rb +10 -0
  67. data/lib/capybara/selector/definition/datalist_input.rb +35 -0
  68. data/lib/capybara/selector/definition/datalist_option.rb +25 -0
  69. data/lib/capybara/selector/definition/element.rb +28 -0
  70. data/lib/capybara/selector/definition/field.rb +40 -0
  71. data/lib/capybara/selector/definition/fieldset.rb +14 -0
  72. data/lib/capybara/selector/definition/file_field.rb +13 -0
  73. data/lib/capybara/selector/definition/fillable_field.rb +33 -0
  74. data/lib/capybara/selector/definition/frame.rb +17 -0
  75. data/lib/capybara/selector/definition/id.rb +6 -0
  76. data/lib/capybara/selector/definition/label.rb +62 -0
  77. data/lib/capybara/selector/definition/link.rb +54 -0
  78. data/lib/capybara/selector/definition/link_or_button.rb +16 -0
  79. data/lib/capybara/selector/definition/option.rb +27 -0
  80. data/lib/capybara/selector/definition/radio_button.rb +27 -0
  81. data/lib/capybara/selector/definition/select.rb +81 -0
  82. data/lib/capybara/selector/definition/table.rb +109 -0
  83. data/lib/capybara/selector/definition/table_row.rb +21 -0
  84. data/lib/capybara/selector/definition/xpath.rb +5 -0
  85. data/lib/capybara/selector/definition.rb +279 -0
  86. data/lib/capybara/selector/filter.rb +2 -17
  87. data/lib/capybara/selector/filter_set.rb +81 -33
  88. data/lib/capybara/selector/filters/base.rb +50 -6
  89. data/lib/capybara/selector/filters/expression_filter.rb +8 -26
  90. data/lib/capybara/selector/filters/locator_filter.rb +29 -0
  91. data/lib/capybara/selector/filters/node_filter.rb +16 -12
  92. data/lib/capybara/selector/regexp_disassembler.rb +214 -0
  93. data/lib/capybara/selector/selector.rb +89 -210
  94. data/lib/capybara/selector/xpath_extensions.rb +17 -0
  95. data/lib/capybara/selector.rb +227 -526
  96. data/lib/capybara/selenium/atoms/getAttribute.min.js +1 -0
  97. data/lib/capybara/selenium/atoms/isDisplayed.min.js +1 -0
  98. data/lib/capybara/selenium/atoms/src/getAttribute.js +161 -0
  99. data/lib/capybara/selenium/atoms/src/isDisplayed.js +454 -0
  100. data/lib/capybara/selenium/driver.rb +343 -276
  101. data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +117 -0
  102. data/lib/capybara/selenium/driver_specializations/edge_driver.rb +124 -0
  103. data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +89 -0
  104. data/lib/capybara/selenium/driver_specializations/internet_explorer_driver.rb +26 -0
  105. data/lib/capybara/selenium/driver_specializations/safari_driver.rb +24 -0
  106. data/lib/capybara/selenium/extensions/file_input_click_emulation.rb +34 -0
  107. data/lib/capybara/selenium/extensions/find.rb +110 -0
  108. data/lib/capybara/selenium/extensions/html5_drag.rb +228 -0
  109. data/lib/capybara/selenium/extensions/modifier_keys_stack.rb +28 -0
  110. data/lib/capybara/selenium/extensions/scroll.rb +76 -0
  111. data/lib/capybara/selenium/logger_suppressor.rb +40 -0
  112. data/lib/capybara/selenium/node.rb +508 -124
  113. data/lib/capybara/selenium/nodes/chrome_node.rb +137 -0
  114. data/lib/capybara/selenium/nodes/edge_node.rb +104 -0
  115. data/lib/capybara/selenium/nodes/firefox_node.rb +136 -0
  116. data/lib/capybara/selenium/nodes/ie_node.rb +22 -0
  117. data/lib/capybara/selenium/nodes/safari_node.rb +118 -0
  118. data/lib/capybara/selenium/patches/action_pauser.rb +26 -0
  119. data/lib/capybara/selenium/patches/atoms.rb +18 -0
  120. data/lib/capybara/selenium/patches/is_displayed.rb +16 -0
  121. data/lib/capybara/selenium/patches/logs.rb +45 -0
  122. data/lib/capybara/selenium/patches/pause_duration_fix.rb +9 -0
  123. data/lib/capybara/selenium/patches/persistent_client.rb +20 -0
  124. data/lib/capybara/server/animation_disabler.rb +69 -0
  125. data/lib/capybara/server/checker.rb +44 -0
  126. data/lib/capybara/server/middleware.rb +71 -0
  127. data/lib/capybara/server.rb +59 -67
  128. data/lib/capybara/session/config.rb +79 -59
  129. data/lib/capybara/session/matchers.rb +41 -25
  130. data/lib/capybara/session.rb +371 -357
  131. data/lib/capybara/spec/public/jquery.js +5 -5
  132. data/lib/capybara/spec/public/offset.js +6 -0
  133. data/lib/capybara/spec/public/test.js +159 -13
  134. data/lib/capybara/spec/session/accept_alert_spec.rb +12 -11
  135. data/lib/capybara/spec/session/accept_confirm_spec.rb +6 -5
  136. data/lib/capybara/spec/session/accept_prompt_spec.rb +34 -6
  137. data/lib/capybara/spec/session/active_element_spec.rb +31 -0
  138. data/lib/capybara/spec/session/all_spec.rb +161 -55
  139. data/lib/capybara/spec/session/ancestor_spec.rb +27 -24
  140. data/lib/capybara/spec/session/assert_all_of_selectors_spec.rb +68 -38
  141. data/lib/capybara/spec/session/assert_current_path_spec.rb +75 -0
  142. data/lib/capybara/spec/session/assert_selector_spec.rb +143 -0
  143. data/lib/capybara/spec/session/assert_style_spec.rb +26 -0
  144. data/lib/capybara/spec/session/{assert_text.rb → assert_text_spec.rb} +91 -59
  145. data/lib/capybara/spec/session/{assert_title.rb → assert_title_spec.rb} +22 -12
  146. data/lib/capybara/spec/session/attach_file_spec.rb +138 -69
  147. data/lib/capybara/spec/session/body_spec.rb +12 -13
  148. data/lib/capybara/spec/session/check_spec.rb +116 -55
  149. data/lib/capybara/spec/session/choose_spec.rb +64 -31
  150. data/lib/capybara/spec/session/click_button_spec.rb +231 -173
  151. data/lib/capybara/spec/session/click_link_or_button_spec.rb +55 -35
  152. data/lib/capybara/spec/session/click_link_spec.rb +82 -58
  153. data/lib/capybara/spec/session/current_scope_spec.rb +11 -10
  154. data/lib/capybara/spec/session/current_url_spec.rb +57 -39
  155. data/lib/capybara/spec/session/dismiss_confirm_spec.rb +4 -4
  156. data/lib/capybara/spec/session/dismiss_prompt_spec.rb +3 -2
  157. data/lib/capybara/spec/session/element/{assert_match_selector.rb → assert_match_selector_spec.rb} +11 -9
  158. data/lib/capybara/spec/session/element/match_css_spec.rb +18 -10
  159. data/lib/capybara/spec/session/element/match_xpath_spec.rb +9 -7
  160. data/lib/capybara/spec/session/element/matches_selector_spec.rb +71 -57
  161. data/lib/capybara/spec/session/evaluate_async_script_spec.rb +23 -0
  162. data/lib/capybara/spec/session/evaluate_script_spec.rb +30 -9
  163. data/lib/capybara/spec/session/execute_script_spec.rb +10 -8
  164. data/lib/capybara/spec/session/fill_in_spec.rb +128 -43
  165. data/lib/capybara/spec/session/find_button_spec.rb +25 -24
  166. data/lib/capybara/spec/session/find_by_id_spec.rb +10 -9
  167. data/lib/capybara/spec/session/find_field_spec.rb +37 -41
  168. data/lib/capybara/spec/session/find_link_spec.rb +36 -17
  169. data/lib/capybara/spec/session/find_spec.rb +245 -144
  170. data/lib/capybara/spec/session/first_spec.rb +79 -51
  171. data/lib/capybara/spec/session/frame/frame_title_spec.rb +23 -0
  172. data/lib/capybara/spec/session/frame/frame_url_spec.rb +23 -0
  173. data/lib/capybara/spec/session/frame/switch_to_frame_spec.rb +33 -20
  174. data/lib/capybara/spec/session/frame/within_frame_spec.rb +50 -32
  175. data/lib/capybara/spec/session/go_back_spec.rb +2 -1
  176. data/lib/capybara/spec/session/go_forward_spec.rb +2 -1
  177. data/lib/capybara/spec/session/has_all_selectors_spec.rb +69 -0
  178. data/lib/capybara/spec/session/has_ancestor_spec.rb +46 -0
  179. data/lib/capybara/spec/session/has_any_selectors_spec.rb +29 -0
  180. data/lib/capybara/spec/session/has_button_spec.rb +94 -13
  181. data/lib/capybara/spec/session/has_css_spec.rb +272 -137
  182. data/lib/capybara/spec/session/has_current_path_spec.rb +87 -45
  183. data/lib/capybara/spec/session/has_field_spec.rb +139 -59
  184. data/lib/capybara/spec/session/has_link_spec.rb +34 -9
  185. data/lib/capybara/spec/session/has_none_selectors_spec.rb +78 -0
  186. data/lib/capybara/spec/session/has_select_spec.rb +103 -74
  187. data/lib/capybara/spec/session/has_selector_spec.rb +105 -71
  188. data/lib/capybara/spec/session/has_sibling_spec.rb +50 -0
  189. data/lib/capybara/spec/session/has_table_spec.rb +172 -5
  190. data/lib/capybara/spec/session/has_text_spec.rb +113 -61
  191. data/lib/capybara/spec/session/has_title_spec.rb +20 -14
  192. data/lib/capybara/spec/session/has_xpath_spec.rb +57 -38
  193. data/lib/capybara/spec/session/{headers.rb → headers_spec.rb} +3 -2
  194. data/lib/capybara/spec/session/html_spec.rb +14 -6
  195. data/lib/capybara/spec/session/matches_style_spec.rb +35 -0
  196. data/lib/capybara/spec/session/node_spec.rb +950 -152
  197. data/lib/capybara/spec/session/node_wrapper_spec.rb +39 -0
  198. data/lib/capybara/spec/session/refresh_spec.rb +12 -6
  199. data/lib/capybara/spec/session/reset_session_spec.rb +69 -35
  200. data/lib/capybara/spec/session/{response_code.rb → response_code_spec.rb} +2 -1
  201. data/lib/capybara/spec/session/save_and_open_page_spec.rb +3 -2
  202. data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +8 -12
  203. data/lib/capybara/spec/session/save_page_spec.rb +42 -55
  204. data/lib/capybara/spec/session/save_screenshot_spec.rb +16 -14
  205. data/lib/capybara/spec/session/screenshot_spec.rb +2 -2
  206. data/lib/capybara/spec/session/scroll_spec.rb +117 -0
  207. data/lib/capybara/spec/session/select_spec.rb +107 -80
  208. data/lib/capybara/spec/session/selectors_spec.rb +52 -19
  209. data/lib/capybara/spec/session/sibling_spec.rb +10 -10
  210. data/lib/capybara/spec/session/text_spec.rb +37 -21
  211. data/lib/capybara/spec/session/title_spec.rb +17 -5
  212. data/lib/capybara/spec/session/uncheck_spec.rb +42 -22
  213. data/lib/capybara/spec/session/unselect_spec.rb +39 -38
  214. data/lib/capybara/spec/session/visit_spec.rb +99 -32
  215. data/lib/capybara/spec/session/window/become_closed_spec.rb +24 -20
  216. data/lib/capybara/spec/session/window/current_window_spec.rb +5 -3
  217. data/lib/capybara/spec/session/window/open_new_window_spec.rb +5 -3
  218. data/lib/capybara/spec/session/window/switch_to_window_spec.rb +27 -22
  219. data/lib/capybara/spec/session/window/window_opened_by_spec.rb +12 -6
  220. data/lib/capybara/spec/session/window/window_spec.rb +97 -63
  221. data/lib/capybara/spec/session/window/windows_spec.rb +12 -10
  222. data/lib/capybara/spec/session/window/within_window_spec.rb +31 -86
  223. data/lib/capybara/spec/session/within_spec.rb +70 -44
  224. data/lib/capybara/spec/spec_helper.rb +49 -43
  225. data/lib/capybara/spec/test_app.rb +89 -42
  226. data/lib/capybara/spec/views/animated.erb +49 -0
  227. data/lib/capybara/spec/views/form.erb +141 -42
  228. data/lib/capybara/spec/views/frame_child.erb +4 -3
  229. data/lib/capybara/spec/views/frame_one.erb +2 -1
  230. data/lib/capybara/spec/views/frame_parent.erb +1 -1
  231. data/lib/capybara/spec/views/frame_two.erb +1 -1
  232. data/lib/capybara/spec/views/initial_alert.erb +11 -0
  233. data/lib/capybara/spec/views/layout.erb +10 -0
  234. data/lib/capybara/spec/views/obscured.erb +47 -0
  235. data/lib/capybara/spec/views/offset.erb +33 -0
  236. data/lib/capybara/spec/views/path.erb +2 -2
  237. data/lib/capybara/spec/views/popup_one.erb +1 -1
  238. data/lib/capybara/spec/views/popup_two.erb +1 -1
  239. data/lib/capybara/spec/views/react.erb +45 -0
  240. data/lib/capybara/spec/views/scroll.erb +21 -0
  241. data/lib/capybara/spec/views/spatial.erb +31 -0
  242. data/lib/capybara/spec/views/tables.erb +68 -1
  243. data/lib/capybara/spec/views/with_animation.erb +81 -0
  244. data/lib/capybara/spec/views/with_base_tag.erb +2 -2
  245. data/lib/capybara/spec/views/with_dragula.erb +24 -0
  246. data/lib/capybara/spec/views/with_fixed_header_footer.erb +18 -0
  247. data/lib/capybara/spec/views/with_hover.erb +8 -2
  248. data/lib/capybara/spec/views/with_hover1.erb +10 -0
  249. data/lib/capybara/spec/views/with_html.erb +70 -11
  250. data/lib/capybara/spec/views/with_html5_svg.erb +20 -0
  251. data/lib/capybara/spec/views/with_jquery_animation.erb +24 -0
  252. data/lib/capybara/spec/views/with_js.erb +39 -3
  253. data/lib/capybara/spec/views/with_jstree.erb +26 -0
  254. data/lib/capybara/spec/views/with_namespace.erb +21 -0
  255. data/lib/capybara/spec/views/with_scope_other.erb +6 -0
  256. data/lib/capybara/spec/views/with_slow_unload.erb +2 -1
  257. data/lib/capybara/spec/views/with_sortable_js.erb +21 -0
  258. data/lib/capybara/spec/views/with_unload_alert.erb +1 -0
  259. data/lib/capybara/spec/views/with_windows.erb +1 -1
  260. data/lib/capybara/spec/views/within_frames.erb +5 -2
  261. data/lib/capybara/version.rb +2 -1
  262. data/lib/capybara/window.rb +35 -33
  263. data/lib/capybara.rb +126 -103
  264. data/spec/basic_node_spec.rb +60 -34
  265. data/spec/capybara_spec.rb +53 -104
  266. data/spec/css_builder_spec.rb +101 -0
  267. data/spec/css_splitter_spec.rb +38 -0
  268. data/spec/dsl_spec.rb +81 -62
  269. data/spec/filter_set_spec.rb +27 -9
  270. data/spec/fixtures/certificate.pem +25 -0
  271. data/spec/fixtures/key.pem +27 -0
  272. data/spec/fixtures/selenium_driver_rspec_failure.rb +5 -4
  273. data/spec/fixtures/selenium_driver_rspec_success.rb +5 -4
  274. data/spec/minitest_spec.rb +49 -7
  275. data/spec/minitest_spec_spec.rb +94 -59
  276. data/spec/per_session_config_spec.rb +14 -13
  277. data/spec/rack_test_spec.rb +180 -125
  278. data/spec/regexp_dissassembler_spec.rb +250 -0
  279. data/spec/result_spec.rb +99 -45
  280. data/spec/rspec/features_spec.rb +37 -31
  281. data/spec/rspec/scenarios_spec.rb +9 -7
  282. data/spec/rspec/shared_spec_matchers.rb +448 -421
  283. data/spec/rspec/views_spec.rb +5 -3
  284. data/spec/rspec_matchers_spec.rb +27 -11
  285. data/spec/rspec_spec.rb +109 -89
  286. data/spec/sauce_spec_chrome.rb +43 -0
  287. data/spec/selector_spec.rb +396 -67
  288. data/spec/selenium_spec_chrome.rb +183 -35
  289. data/spec/selenium_spec_chrome_remote.rb +101 -0
  290. data/spec/selenium_spec_edge.rb +47 -0
  291. data/spec/selenium_spec_firefox.rb +184 -41
  292. data/spec/selenium_spec_firefox_remote.rb +80 -0
  293. data/spec/selenium_spec_ie.rb +147 -0
  294. data/spec/selenium_spec_safari.rb +156 -0
  295. data/spec/server_spec.rb +198 -99
  296. data/spec/session_spec.rb +53 -16
  297. data/spec/shared_selenium_node.rb +79 -0
  298. data/spec/shared_selenium_session.rb +489 -97
  299. data/spec/spec_helper.rb +93 -7
  300. data/spec/xpath_builder_spec.rb +93 -0
  301. metadata +365 -70
  302. data/.yard/templates_custom/default/class/html/selectors.erb +0 -38
  303. data/.yard/templates_custom/default/class/html/setup.rb +0 -17
  304. data/.yard/yard_extensions.rb +0 -78
  305. data/lib/capybara/query.rb +0 -7
  306. data/lib/capybara/rspec/compound.rb +0 -95
  307. data/lib/capybara/spec/session/assert_current_path.rb +0 -72
  308. data/lib/capybara/spec/session/assert_selector.rb +0 -148
  309. data/lib/capybara/spec/session/source_spec.rb +0 -0
  310. data/lib/capybara/spec/views/with_title.erb +0 -5
  311. data/spec/selenium_spec_marionette.rb +0 -117
@@ -1,13 +1,16 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'sinatra/base'
3
4
  require 'tilt/erb'
4
5
  require 'rack'
5
6
  require 'yaml'
6
7
 
7
8
  class TestApp < Sinatra::Base
8
- class TestAppError < StandardError; end
9
- class TestAppOtherError < StandardError
9
+ class TestAppError < Exception; end # rubocop:disable Lint/InheritException
10
+
11
+ class TestAppOtherError < Exception # rubocop:disable Lint/InheritException
10
12
  def initialize(string1, msg)
13
+ super()
11
14
  @something = string1
12
15
  @message = msg
13
16
  end
@@ -17,11 +20,10 @@ class TestApp < Sinatra::Base
17
20
  set :raise_errors, true
18
21
  set :show_exceptions, false
19
22
 
20
- @@form_post_count = 0
21
23
  # Also check lib/capybara/spec/views/*.erb for pages not listed here
22
24
 
23
25
  get '/' do
24
- response.set_cookie('capybara', { value: 'root cookie', domain: request.host, path: request.path} )
26
+ response.set_cookie('capybara', value: 'root cookie', domain: request.host, path: request.path)
25
27
  'Hello world! <a href="with_html">Relative</a>'
26
28
  end
27
29
 
@@ -33,14 +35,26 @@ class TestApp < Sinatra::Base
33
35
  redirect '/redirect_again'
34
36
  end
35
37
 
38
+ get '/redirect_with_fragment' do
39
+ redirect '/landed#with_fragment'
40
+ end
41
+
36
42
  get '/redirect_again' do
37
43
  redirect '/landed'
38
44
  end
39
45
 
46
+ post '/redirect_307' do
47
+ redirect '/landed', 307
48
+ end
49
+
50
+ post '/redirect_308' do
51
+ redirect '/landed', 308
52
+ end
53
+
40
54
  get '/referer_base' do
41
- '<a href="/get_referer">direct link</a>' +
42
- '<a href="/redirect_to_get_referer">link via redirect</a>' +
43
- '<form action="/get_referer" method="get"><input type="submit"></form>'
55
+ '<a href="/get_referer">direct link</a>' \
56
+ '<a href="/redirect_to_get_referer">link via redirect</a>' \
57
+ '<form action="/get_referer" method="get"><input type="submit"></form>'
44
58
  end
45
59
 
46
60
  get '/redirect_to_get_referer' do
@@ -48,7 +62,7 @@ class TestApp < Sinatra::Base
48
62
  end
49
63
 
50
64
  get '/get_referer' do
51
- request.referer.nil? ? "No referer" : "Got referer: #{request.referer}"
65
+ request.referer.nil? ? 'No referer' : "Got referer: #{request.referer}"
52
66
  end
53
67
 
54
68
  get '/host' do
@@ -58,26 +72,30 @@ class TestApp < Sinatra::Base
58
72
  get '/redirect/:times/times' do
59
73
  times = params[:times].to_i
60
74
  if times.zero?
61
- "redirection complete"
75
+ 'redirection complete'
62
76
  else
63
77
  redirect "/redirect/#{times - 1}/times"
64
78
  end
65
79
  end
66
80
 
67
81
  get '/landed' do
68
- "You landed"
82
+ 'You landed'
83
+ end
84
+
85
+ post '/landed' do
86
+ "You post landed: #{params.dig(:form, 'data')}"
69
87
  end
70
88
 
71
89
  get '/with-quotes' do
72
- %q{"No," he said, "you can't do that."}
90
+ %q("No," he said, "you can't do that.")
73
91
  end
74
92
 
75
93
  get '/form/get' do
76
- '<pre id="results">' + params[:form].to_yaml + '</pre>'
94
+ %(<pre id="results">#{params[:form].to_yaml}</pre>)
77
95
  end
78
96
 
79
97
  post '/relative' do
80
- '<pre id="results">' + params[:form].to_yaml + '</pre>'
98
+ %(<pre id="results">#{params[:form].to_yaml}</pre>)
81
99
  end
82
100
 
83
101
  get '/favicon.ico' do
@@ -88,12 +106,12 @@ class TestApp < Sinatra::Base
88
106
  redirect '/redirect_again'
89
107
  end
90
108
 
91
- delete "/delete" do
92
- "The requested object was deleted"
109
+ delete '/delete' do
110
+ 'The requested object was deleted'
93
111
  end
94
112
 
95
- get "/delete" do
96
- "Not deleted"
113
+ get '/delete' do
114
+ 'Not deleted'
97
115
  end
98
116
 
99
117
  get '/redirect_back' do
@@ -128,11 +146,11 @@ class TestApp < Sinatra::Base
128
146
  end
129
147
 
130
148
  get '/error' do
131
- raise TestAppError, "some error"
149
+ raise TestAppError, 'some error'
132
150
  end
133
151
 
134
152
  get '/other_error' do
135
- raise TestAppOtherError.new("something", "other error")
153
+ raise TestAppOtherError.new('something', 'other error')
136
154
  end
137
155
 
138
156
  get '/load_error' do
@@ -143,13 +161,37 @@ class TestApp < Sinatra::Base
143
161
  erb :with_html, locals: { referrer: request.referrer }
144
162
  end
145
163
 
164
+ get '/with_title' do
165
+ <<-HTML
166
+ <!DOCTYPE html>
167
+ <html lang="en">
168
+ <head>
169
+ <meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
170
+ <title>#{params[:title] || 'Test Title'}</title>
171
+ </head>
172
+
173
+ <body>
174
+ <svg><title>abcdefg</title></svg>
175
+ </body>
176
+ </html>
177
+ HTML
178
+ end
179
+
180
+ get '/download.csv' do
181
+ content_type 'text/csv'
182
+ 'This, is, comma, separated' \
183
+ 'Thomas, Walpole, was , here'
184
+ end
185
+
146
186
  get '/:view' do |view|
147
- erb view.to_sym, locals: { referrer: request.referrer }
187
+ view_template = "#{__dir__}/views/#{view}.erb"
188
+ has_layout = File.exist?(view_template) && File.open(view_template) { |f| f.first.downcase.include?('doctype') }
189
+ erb view.to_sym, locals: { referrer: request.referrer }, layout: !has_layout
148
190
  end
149
191
 
150
192
  post '/form' do
151
- @@form_post_count += 1
152
- '<pre id="results">' + params[:form].merge({"post_count" => @@form_post_count}).to_yaml + '</pre>'
193
+ self.class.form_post_count += 1
194
+ %(<pre id="results">#{params[:form].merge('post_count' => self.class.form_post_count).to_yaml}</pre>)
153
195
  end
154
196
 
155
197
  post '/upload_empty' do
@@ -161,30 +203,35 @@ class TestApp < Sinatra::Base
161
203
  end
162
204
 
163
205
  post '/upload' do
164
- begin
165
- buffer = []
166
- buffer << "Content-type: #{params[:form][:document][:type]}"
167
- buffer << "File content: #{params[:form][:document][:tempfile].read}"
168
- buffer.join(' | ')
169
- rescue
170
- 'No file uploaded'
171
- end
206
+ buffer = []
207
+ buffer << "Content-type: #{params.dig(:form, :document, :type)}"
208
+ buffer << "File content: #{params.dig(:form, :document, :tempfile).read}"
209
+ buffer.join(' | ')
210
+ rescue StandardError
211
+ 'No file uploaded'
172
212
  end
173
213
 
174
214
  post '/upload_multiple' do
175
- begin
176
- buffer = ["#{params[:form][:multiple_documents].size}"]
177
- params[:form][:multiple_documents].each do |doc|
178
- buffer << "Content-type: #{doc[:type]}"
179
- buffer << "File content: #{doc[:tempfile].read}"
180
- end
181
- buffer.join(' | ')
182
- rescue
183
- 'No files uploaded'
215
+ docs = params.dig(:form, :multiple_documents)
216
+ buffer = [docs.size.to_s]
217
+ docs.each do |doc|
218
+ buffer << "Content-type: #{doc[:type]}"
219
+ buffer << "File content: #{doc[:tempfile].read}"
184
220
  end
221
+ buffer.join(' | ')
222
+ rescue StandardError
223
+ 'No files uploaded'
185
224
  end
186
- end
187
225
 
188
- if __FILE__ == $0
189
- Rack::Handler::WEBrick.run TestApp, Port: 8070
226
+ get '/apple-touch-icon-precomposed.png' do
227
+ halt(404)
228
+ end
229
+
230
+ class << self
231
+ attr_accessor :form_post_count
232
+ end
233
+
234
+ @form_post_count = 0
190
235
  end
236
+
237
+ Rack::Handler::Puma.run TestApp, Port: 8070 if $PROGRAM_NAME == __FILE__
@@ -0,0 +1,49 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
5
+ <title>with_animation</title>
6
+ <script src="/jquery.js" type="text/javascript" charset="utf-8"></script>
7
+ <script>
8
+ $(document).on('contextmenu', function(e){ e.preventDefault(); });
9
+ </script>
10
+ <style>
11
+ div {
12
+ width: 400px;
13
+ height: 400px;
14
+ position: absolute;
15
+ }
16
+ #obscured {
17
+ z-index: 1;
18
+ background-color: red;
19
+ }
20
+ #cover {
21
+ z-index: 2;
22
+ background-color: blue;
23
+ }
24
+ #offscreen {
25
+ top: 2000px;
26
+ left: 2000px;
27
+ background-color: green;
28
+ }
29
+ #offscreen_wrapper {
30
+ top: 2000px;
31
+ left: 2000px;
32
+ overflow-x: scroll;
33
+ background-color: yellow;
34
+ }
35
+ </style>
36
+ </head>
37
+
38
+ <body id="with_animation">
39
+ <div id="obscured">
40
+ <input id="obscured_input"/>
41
+ </div>
42
+ <div id="cover"></div>
43
+ <div id="offscreen_wrapper">
44
+ <div id="offscreen"></div>
45
+ </div>
46
+ </body>
47
+
48
+ <iframe id="frameOne" src="/frame_one"></iframe>
49
+ </html>
@@ -1,17 +1,23 @@
1
-
2
1
  <h1>Form</h1>
3
2
 
4
- <form action="/form" method="post">
3
+ <button type="button" tabindex="1">A Button</button>
4
+
5
+ <label>
6
+ An Input
7
+ <input type="text" tabindex="2">
8
+ </label>
9
+
10
+ <form action="/form" method="post" novalidate>
5
11
 
6
12
  <p>
7
13
  <label for="form_title">Title</label>
8
- <select name="form[title]" id="form_title" class="title">
14
+ <select name="form[title]" id="form_title" class="title" tabindex="3">
9
15
  <option class="title">Mrs</option>
10
16
  <option class="title">Mr</option>
11
17
  <option>Miss</option>
12
18
  <option disabled="disabled">Other</option>
13
19
  </select>
14
- </p>
20
+ </p>
15
21
 
16
22
  <p>
17
23
  <label for="customer_name">Customer Name
@@ -25,6 +31,12 @@
25
31
  </label>
26
32
  </p>
27
33
 
34
+ <p>
35
+ <label for="customer_other_email">Customer Other Email
36
+ <input type="text" name="form[customer_other_email]" value="notben@notben.com" id="customer_other_email"/>
37
+ </label>
38
+ </p>
39
+
28
40
  <p>
29
41
  <label for="form_other_title">Other title</label>
30
42
  <select name="form[other_title]" id="form_other_title">
@@ -56,6 +68,11 @@
56
68
  <input type="text" name="form[name]" value="John Smith" id="form_name"/>
57
69
  </p>
58
70
 
71
+ <p>
72
+ <label for="form_age">Age</label>
73
+ <input type="range" name="form[age]" value="18" min="13" max="100" step="0.5" id="form_age"/>
74
+ </p>
75
+
59
76
  <p>
60
77
  <label for="form_schmooo">Schmooo</label>
61
78
  <input type="schmooo" name="form[schmooo]" value="This is Schmooo!" id="form_schmooo"/>
@@ -88,6 +105,11 @@
88
105
  <input type="file" name="form[image]" id="form_image"/>
89
106
  </p>
90
107
 
108
+ <p>
109
+ <label for="form_hidden_image">Hidden Image</label>
110
+ <input type="file" name="form[hidden_image]" id="form_hidden_image" style="display: none"/>
111
+ </p>
112
+
91
113
  <p>
92
114
  <input type="hidden" name="form[token]" value="12345" id="form_token"/>
93
115
  </p>
@@ -97,7 +119,7 @@
97
119
  <select name="form[locale]" id="form_locale">
98
120
  <option value="sv">Swedish</option>
99
121
  <option selected="selected" value="en">English</option>
100
- <option value="fi">Finish</option>
122
+ <option value="fi">Finnish</option>
101
123
  <option value="no">Norwegian</option>
102
124
  <option value="jo">John's made-up language</option>
103
125
  <option value="jbo"> Lojban </option>
@@ -124,7 +146,11 @@
124
146
 
125
147
  <p>
126
148
  <label for="form_zipcode">Zipcode</label>
127
- <input type="text" maxlength="5" name="form[zipcode]" id="form_zipcode" />
149
+ <input type="text" maxlength="5" name="form[zipcode]" id="form_zipcode" pattern="[0-9]{5,9}" />
150
+ </p>
151
+
152
+ <p>
153
+ <input maxlength="35" id="long_length" />
128
154
  </p>
129
155
 
130
156
  <p>
@@ -150,7 +176,7 @@ New line after and before textarea tag
150
176
  <label for="gender_male">Male</label>
151
177
  <input type="radio" name="form[gender]" value="female" id="gender_female" checked="checked"/>
152
178
  <label for="gender_female">Female</label>
153
- <input type="radio" name="form[gender]" value="both" id="gender_both"/>
179
+ <input type="radio" name="form[gender]" value="both" id="gender_both" readonly="readonly"/>
154
180
  <label for="gender_both">Both</label>
155
181
  </p>
156
182
 
@@ -185,7 +211,14 @@ New line after and before textarea tag
185
211
  <label for="form_cars_ferrari">Ferrari</label>
186
212
  <input type="checkbox" value="pagani" name="form[cars][]" id="form_cars_pagani" style="position: absolute; left: -9999px"/>
187
213
  <label for="form_cars_pagani">Pagani</label>
214
+ <div style="position: relative;">
215
+ <input type="checkbox" value="bugatti" name="form[cars][]" id="form_cars_bugatti"/>
216
+ <div style="position: absolute; top: 0; right: 0; bottom: 0; left: 0; background-color: #fff;">
217
+ <label for="form_cars_bugatti">Bugatti</label>
218
+ </div>
219
+ </div>
188
220
  <input type="checkbox" value="ariel" name="form[cars][]" id="form_cars_ariel" style="display: none"/>
221
+ <input type="checkbox" value="porsche" name="form[cars][]" id="form_cars_porsche" checked="checked" style="display: none"/>
189
222
  <label>
190
223
  McLaren
191
224
  <input type="checkbox" value="mclaren" name="form[cars][]" id="form_cars_mclaren" style="display: none"/>
@@ -194,6 +227,19 @@ New line after and before textarea tag
194
227
  Koenigsegg
195
228
  <input type="checkbox" value="koenigsegg" name="form[cars][]" id="form_cars_koenigsegg" checked="checked" style="display: none"/>
196
229
  </label>
230
+ <input type="checkbox" value="maserati" name="form[cars][]" id="form_cars_maserati" disabled="disabled"/>
231
+ <label for="form_cars_maserati">Maserati</label>
232
+ <input type="checkbox" value="lotus" name="form[cars][]" id="form_cars_lotus" style="display: none"/>
233
+ <label for="form_cars_lotus"><a href="#" onclick="return false;">Link here</a>Lotus</label>
234
+ </p>
235
+
236
+ <p>
237
+ <input type="text" name="form[manufacturer]" list="manufacturers" id="manufacturer"/>
238
+ <datalist id="manufacturers">
239
+ <option value="Jaguar">J</option>
240
+ <option value="Audi">
241
+ <option value="Mercedes" disabled>
242
+ </datalist>
197
243
  </p>
198
244
 
199
245
  <p>
@@ -360,7 +406,6 @@ New line after and before textarea tag
360
406
  </label>
361
407
  </p>
362
408
 
363
-
364
409
  <p>
365
410
  <label for="form_disabled_file">
366
411
  Disabled File
@@ -368,41 +413,38 @@ New line after and before textarea tag
368
413
  </label>
369
414
  </p>
370
415
 
371
- <p>
372
- <fieldset>
373
- <input name="form[enabled_fieldset_child]" id="form_enabled_fieldset_child"/>
374
- </fieldset>
375
- </p>
376
-
377
-
378
- <p>
379
- <fieldset disabled="disabled">
380
- <legend>Disabled Child</legend>
381
- <input name="form[disabled_fieldset_child]" id="form_disabled_fieldset_child"/>
382
- <select>
383
- <option>Disabled Child Option</option>
384
- </select>
385
- </fieldset>
416
+ <fieldset>
417
+ <input name="form[enabled_fieldset_child]" id="form_enabled_fieldset_child"/>
418
+ </fieldset>
386
419
 
387
- <fieldset disabled="disabled">
388
- <legend>
389
- Nested Disabled
390
- <input type="checkbox" name="form[disabled_fieldeset_legend_child]" id="form_disabled_fieldset_legend_child"/>
391
- </legend>
420
+ <fieldset disabled="disabled" id="form_disabled_fieldset">
421
+ <legend>Disabled Child</legend>
422
+ <input name="form[disabled_fieldset_child]" id="form_disabled_fieldset_child"/>
423
+ <select>
424
+ <option>Disabled Child Option</option>
425
+ </select>
426
+ </fieldset>
427
+
428
+ <fieldset disabled="disabled">
429
+ <legend>
430
+ Nested Disabled
431
+ <input type="checkbox" name="form[disabled_fieldeset_legend_child]" id="form_disabled_fieldset_legend_child"/>
432
+ </legend>
433
+ <legend>
434
+ Another WLegend
435
+ <input type="checkbox" name="form[disabled_fieldeset_second_legend_child]" id="form_disabled_fieldset_second_legend_child"/>
436
+ </legend>
437
+ <fieldset>
392
438
  <legend>
393
- Another Legend
394
- <input type="checkbox" name="form[disabled_fieldeset_second_legend_child]" id="form_disabled_fieldset_second_legend_child"/>
439
+ Disabled?
440
+ <input id="form_disabled_fieldset_descendant_legend_child">
395
441
  </legend>
396
- <p>
397
- <fieldset>
398
- <input name="form[disabled_fieldset_descendant]" id="form_disabled_fieldset_descendant"/>
399
- </fieldset>
400
- </p>
442
+ <input name="form[disabled_fieldset_descendant]" id="form_disabled_fieldset_descendant"/>
401
443
  </fieldset>
402
- </p>
444
+ </fieldset>
403
445
 
404
446
  <p>
405
- <select>
447
+ <select data-test-id="my_test_id">
406
448
  <optgroup label="Level One">
407
449
  <option> A.1 </option>
408
450
  </optgroup>
@@ -414,21 +456,43 @@ New line after and before textarea tag
414
456
  </p>
415
457
 
416
458
  <p>
417
- <input type="button" name="form[fresh]" id="fresh_btn" value="i am fresh"/>
418
- <input type="submit" name="form[awesome]" id="awe123" title="What an Awesome Button" value="awesome"/>
459
+ <input type="button" aria-label="Aria button" name="form[fresh]" id="fresh_btn" value="i am fresh"/>
460
+ <input type="submit" name="form[awesome]" id="awe123" data-test-id="test_id_button" title="What an Awesome Button" value="awesome"/>
419
461
  <input type="submit" name="form[crappy]" id="crap321" value="crappy"/>
420
462
  <input type="image" name="form[okay]" id="okay556" title="Okay 556 Image" value="okay" alt="oh hai thar"/>
421
463
  <button type="submit" id="click_me_123" title="Click Title button" value="click_me">Click me!</button>
422
464
  <button type="submit" name="form[no_value]">No Value!</button>
423
465
  <button id="no_type">No Type!</button>
424
466
  <button><img alt="A horse eating hay"/></button>
467
+ <button id="button_with_label"></button>
468
+ <label for="button_with_label">button with label element</label>
469
+ <label>
470
+ button within label element
471
+ <button></button>
472
+ </label>
473
+ <label>
474
+ role=button within label element
475
+ <span role="button">with other text</span>
476
+ </label>
425
477
  <input type="button" disabled="disabled" value="Disabled button"/>
478
+ <span role="button">ARIA button</span>
479
+ </p>
480
+
481
+ <p>
482
+ <input type="date" name="form[date]" id="form_date"/>
483
+ <input type="time" name="form[time]" id="form_time"/>
484
+ <input type="datetime-local" name="form[datetime]" id="form_datetime">
426
485
  </p>
427
486
 
428
487
  <p>
429
488
  <input id="readonly" name="form[readonly_test]" readonly/>
430
489
  <input id="not_readonly" name="form[readonly_test]" />
431
490
  </p>
491
+
492
+ <p>
493
+ <input id="required" name="form[required]" required />
494
+ <input id="length" name="form[length]" minlength="4" maxlength="4" />
495
+ </p>
432
496
  </form>
433
497
 
434
498
  <input type="text" name="form[outside_input]" value="outside_input" form="form1"/>
@@ -438,14 +502,21 @@ New line after and before textarea tag
438
502
  <input type="text" name="nested_label" id="nested_label"/>
439
503
  </label>
440
504
 
505
+ <label id="wrapper_label">
506
+ Wrapper Label
507
+ <input type="checkbox"/>
508
+ </label>
509
+
441
510
  <form id="form1" action="/form" method="post">
442
511
  <input type="text" name="form[which_form]" value="form1" id="form_which_form"/>
443
512
  <input type="text" name="form[for_form2]" value="for_form2" form="form2"/>
444
513
  <input type="submit" name="form[submit_form1]" value="submit_form1" id="submit_form1"/>
445
514
  </form>
446
515
 
516
+ <button type="submit" name="form[outside_button]" value="outside_button" form="form2">Outside!</button>
517
+
447
518
  <form id="form2" action="/form" method="post">
448
- <input type="text" name="form[which_form]" value="form2" id="form_which_form"/>
519
+ <input type="text" name="form[which_form]" value="form2" id="form_which_form2"/>
449
520
  <input type="submit" name="form[unused]" value="unused"/>
450
521
  <button type="submit" name="form[other_form_button]" value="other_form_button" form="form1">Form1</button>
451
522
  </form>
@@ -460,8 +531,6 @@ New line after and before textarea tag
460
531
  </select>
461
532
 
462
533
  <input type="submit" name="form[outside_submit]" value="outside_submit" form="form1"/>
463
- <button type="submit" name="form[outside_button]" value="outside_button" form="form2">Outside!</button>
464
-
465
534
 
466
535
  <form id="get-form" action="/form/get?foo=bar" method="get">
467
536
  <p>
@@ -471,6 +540,7 @@ New line after and before textarea tag
471
540
 
472
541
  <p>
473
542
  <input type="submit" name="form[mediocre]" id="mediocre" value="med" aria-label="Mediocre Button"/>
543
+ <input type="submit" formaction="/form/get?bar=foo" id="mediocre2" value="med2"/>
474
544
  <p>
475
545
  </form>
476
546
 
@@ -527,6 +597,11 @@ New line after and before textarea tag
527
597
  <input type="file" name="form[multiple_documents][]" id="form_multiple_documents" multiple="multiple" />
528
598
  </p>
529
599
 
600
+ <p>
601
+ <label for="form_directory_upload">Directory Upload</label>
602
+ <input type="file" name="form[multiple_documents][]" id="form_directory_upload" multiple="multiple" webkitdirectory="webkitdirectory" mozdirectory="mozdirectory" />
603
+ </p>
604
+
530
605
  <p>
531
606
  <input type="submit" value="Upload Multiple"/>
532
607
  <p>
@@ -536,6 +611,14 @@ New line after and before textarea tag
536
611
  <p>
537
612
  <input type="submit" value="Go FAR"/>
538
613
  </p>
614
+
615
+ <input type="hidden" name="form[data]" value="TWTW"/>
616
+ <p>
617
+ <button formaction='/redirect_307'>Go 307</button>
618
+ </p>
619
+ <p>
620
+ <button formaction='/redirect_308'>Go 308</button>
621
+ </p>
539
622
  </form>
540
623
 
541
624
  <form action="/form" method="post">
@@ -615,3 +698,19 @@ New line after and before textarea tag
615
698
  <label for="asterisk_input">With Asterisk<abbr title="required">*</abbr></label>
616
699
  <input id="asterisk_input" type="number"value="2016"/>
617
700
  </p>
701
+
702
+ <p>
703
+ <input id="special" {custom}="abcdef" value="custom attribute"/>
704
+ </p>
705
+
706
+
707
+ <label for="multi_label_checkbox">
708
+ Label to click
709
+ </label>
710
+ <div>Something random that justifies the usage of a separate label</div>
711
+ <label>
712
+ <div>
713
+ <input type="checkbox" id="multi_label_checkbox" style="display: none"/>
714
+ <div>Visual representation of the checkbox</div>
715
+ </div>
716
+ </label>
@@ -1,16 +1,17 @@
1
-
1
+ <!DOCTYPE html>
2
2
  <html>
3
3
  <head>
4
4
  <title>This is the child frame title</title>
5
5
  <script>
6
6
  function closeWin() {
7
- var iframe = window.parent.document.getElementById('childFrame')
7
+ var iframe = window.parent.document.getElementById('childFrame');
8
8
  iframe.parentNode.removeChild(iframe)
9
9
  }
10
10
  </script>
11
11
  </head>
12
12
  <body id="childBody">
13
- <a href="javascript:void(0)" onClick="closeWin()">Close Window</a>
13
+ <a href="javascript:void(0)" onClick="closeWin()">Close Window Now</a>
14
+ <a href="javascript:void(0)" onClick="setTimeout(function(){closeWin()}, 10)">Close Window Soon</a>
14
15
  <iframe src="/frame_one" id="grandchildFrame1"></iframe>
15
16
  <iframe src="/frame_two" id="grandchildFrame2"></iframe>
16
17
  </body>
@@ -1,9 +1,10 @@
1
-
1
+ <!DOCTYPE html>
2
2
  <html>
3
3
  <head>
4
4
  <title>This is the title of frame one</title>
5
5
  </head>
6
6
  <body>
7
7
  <div id="divInFrameOne">This is the text of divInFrameOne</div>
8
+ <div id="otherDivInFrameOne">Some other text</div>
8
9
  </body>
9
10
  </html>
@@ -1,4 +1,4 @@
1
-
1
+ <!DOCTYPE html>
2
2
  <html>
3
3
  <head>
4
4
  <title>This is the parent frame title</title>
@@ -1,4 +1,4 @@
1
-
1
+ <!DOCTYPE html>
2
2
  <html>
3
3
  <head>
4
4
  <title>This is the title of frame two</title>