capybara 3.33.0 → 3.34.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.
- checksums.yaml +4 -4
- data/History.md +44 -15
- data/README.md +0 -2
- data/lib/capybara.rb +1 -1
- data/lib/capybara/config.rb +4 -6
- data/lib/capybara/driver/base.rb +4 -0
- data/lib/capybara/helpers.rb +25 -1
- data/lib/capybara/minitest.rb +2 -2
- data/lib/capybara/minitest/spec.rb +14 -11
- data/lib/capybara/node/actions.rb +1 -2
- data/lib/capybara/node/element.rb +1 -5
- data/lib/capybara/node/finders.rb +7 -6
- data/lib/capybara/node/matchers.rb +7 -5
- data/lib/capybara/node/simple.rb +5 -1
- data/lib/capybara/queries/ancestor_query.rb +1 -1
- data/lib/capybara/queries/current_path_query.rb +14 -4
- data/lib/capybara/queries/selector_query.rb +8 -9
- data/lib/capybara/queries/sibling_query.rb +1 -1
- data/lib/capybara/queries/text_query.rb +2 -2
- data/lib/capybara/rack_test/browser.rb +7 -3
- data/lib/capybara/rack_test/driver.rb +1 -0
- data/lib/capybara/rack_test/form.rb +1 -1
- data/lib/capybara/rack_test/node.rb +1 -1
- data/lib/capybara/registration_container.rb +3 -3
- data/lib/capybara/registrations/patches/puma_ssl.rb +3 -1
- data/lib/capybara/registrations/servers.rb +1 -0
- data/lib/capybara/result.rb +3 -7
- data/lib/capybara/rspec.rb +2 -0
- data/lib/capybara/rspec/matcher_proxies.rb +1 -1
- data/lib/capybara/rspec/matchers.rb +7 -6
- data/lib/capybara/rspec/matchers/have_current_path.rb +2 -2
- data/lib/capybara/rspec/matchers/match_style.rb +5 -0
- data/lib/capybara/selector/definition.rb +6 -5
- data/lib/capybara/selector/definition/button.rb +7 -5
- data/lib/capybara/selector/definition/css.rb +1 -1
- data/lib/capybara/selector/definition/datalist_input.rb +1 -1
- data/lib/capybara/selector/definition/element.rb +2 -1
- data/lib/capybara/selector/definition/label.rb +1 -1
- data/lib/capybara/selector/definition/select.rb +1 -1
- data/lib/capybara/selector/definition/table_row.rb +1 -1
- data/lib/capybara/selector/filter_set.rb +2 -2
- data/lib/capybara/selector/selector.rb +5 -1
- data/lib/capybara/selenium/driver.rb +29 -3
- data/lib/capybara/selenium/driver_specializations/chrome_driver.rb +3 -3
- data/lib/capybara/selenium/driver_specializations/edge_driver.rb +3 -3
- data/lib/capybara/selenium/driver_specializations/firefox_driver.rb +1 -1
- data/lib/capybara/selenium/extensions/find.rb +3 -3
- data/lib/capybara/selenium/extensions/scroll.rb +8 -10
- data/lib/capybara/selenium/node.rb +6 -3
- data/lib/capybara/selenium/nodes/chrome_node.rb +20 -2
- data/lib/capybara/selenium/nodes/safari_node.rb +1 -1
- data/lib/capybara/selenium/patches/atoms.rb +4 -4
- data/lib/capybara/selenium/patches/logs.rb +4 -4
- data/lib/capybara/server/animation_disabler.rb +3 -2
- data/lib/capybara/server/middleware.rb +4 -2
- data/lib/capybara/session.rb +20 -11
- data/lib/capybara/session/matchers.rb +11 -11
- data/lib/capybara/spec/public/test.js +6 -1
- data/lib/capybara/spec/session/accept_alert_spec.rb +1 -1
- data/lib/capybara/spec/session/check_spec.rb +6 -0
- data/lib/capybara/spec/session/current_url_spec.rb +11 -1
- data/lib/capybara/spec/session/has_button_spec.rb +2 -0
- data/lib/capybara/spec/session/has_css_spec.rb +2 -1
- data/lib/capybara/spec/session/has_current_path_spec.rb +13 -0
- data/lib/capybara/spec/session/has_text_spec.rb +0 -11
- data/lib/capybara/spec/session/matches_style_spec.rb +2 -2
- data/lib/capybara/spec/session/node_spec.rb +22 -2
- data/lib/capybara/spec/session/refresh_spec.rb +1 -0
- data/lib/capybara/spec/session/save_page_spec.rb +4 -4
- data/lib/capybara/spec/spec_helper.rb +11 -12
- data/lib/capybara/spec/test_app.rb +8 -3
- data/lib/capybara/spec/views/form.erb +18 -0
- data/lib/capybara/spec/views/with_animation.erb +8 -0
- data/lib/capybara/spec/views/with_js.erb +1 -0
- data/lib/capybara/spec/views/with_sortable_js.erb +1 -1
- data/lib/capybara/version.rb +1 -1
- data/lib/capybara/window.rb +3 -7
- data/spec/basic_node_spec.rb +9 -8
- data/spec/dsl_spec.rb +1 -1
- data/spec/fixtures/selenium_driver_rspec_success.rb +1 -1
- data/spec/minitest_spec.rb +2 -1
- data/spec/rack_test_spec.rb +15 -5
- data/spec/rspec/features_spec.rb +3 -1
- data/spec/rspec/scenarios_spec.rb +4 -0
- data/spec/rspec/shared_spec_matchers.rb +2 -2
- data/spec/rspec_spec.rb +4 -0
- data/spec/selector_spec.rb +1 -0
- data/spec/server_spec.rb +15 -0
- data/spec/shared_selenium_session.rb +60 -1
- metadata +22 -23
- data/lib/capybara/spec/session/source_spec.rb +0 -0
@@ -13,14 +13,14 @@ module Capybara
|
|
13
13
|
# @param string [String] The string that the current 'path' should equal
|
14
14
|
# @overload $0(regexp, **options)
|
15
15
|
# @param regexp [Regexp] The regexp that the current 'path' should match to
|
16
|
-
# @option options [Boolean] :url (true if `string`
|
16
|
+
# @option options [Boolean] :url (true if `string` is a full url, otherwise false) Whether the comparison should be done against the full current url or just the path
|
17
17
|
# @option options [Boolean] :ignore_query (false) Whether the query portion of the current url/path should be ignored
|
18
18
|
# @option options [Numeric] :wait (Capybara.default_max_wait_time) Maximum time that Capybara will wait for the current url/path to eq/match given string/regexp argument
|
19
19
|
# @raise [Capybara::ExpectationNotMet] if the assertion hasn't succeeded during wait time
|
20
20
|
# @return [true]
|
21
21
|
#
|
22
|
-
def assert_current_path(path, **options)
|
23
|
-
_verify_current_path(path, **options) do |query|
|
22
|
+
def assert_current_path(path, **options, &optional_filter_block)
|
23
|
+
_verify_current_path(path, optional_filter_block, **options) do |query|
|
24
24
|
raise Capybara::ExpectationNotMet, query.failure_message unless query.resolves_for?(self)
|
25
25
|
end
|
26
26
|
end
|
@@ -35,8 +35,8 @@ module Capybara
|
|
35
35
|
# @raise [Capybara::ExpectationNotMet] if the assertion hasn't succeeded during wait time
|
36
36
|
# @return [true]
|
37
37
|
#
|
38
|
-
def assert_no_current_path(path, **options)
|
39
|
-
_verify_current_path(path, **options) do |query|
|
38
|
+
def assert_no_current_path(path, **options, &optional_filter_block)
|
39
|
+
_verify_current_path(path, optional_filter_block, **options) do |query|
|
40
40
|
raise Capybara::ExpectationNotMet, query.negative_failure_message if query.resolves_for?(self)
|
41
41
|
end
|
42
42
|
end
|
@@ -50,8 +50,8 @@ module Capybara
|
|
50
50
|
# @macro current_path_query_params
|
51
51
|
# @return [Boolean]
|
52
52
|
#
|
53
|
-
def has_current_path?(path, **options)
|
54
|
-
make_predicate(options) { assert_current_path(path, **options) }
|
53
|
+
def has_current_path?(path, **options, &optional_filter_block)
|
54
|
+
make_predicate(options) { assert_current_path(path, **options, &optional_filter_block) }
|
55
55
|
end
|
56
56
|
|
57
57
|
##
|
@@ -63,14 +63,14 @@ module Capybara
|
|
63
63
|
# @macro current_path_query_params
|
64
64
|
# @return [Boolean]
|
65
65
|
#
|
66
|
-
def has_no_current_path?(path, **options)
|
67
|
-
make_predicate(options) { assert_no_current_path(path, **options) }
|
66
|
+
def has_no_current_path?(path, **options, &optional_filter_block)
|
67
|
+
make_predicate(options) { assert_no_current_path(path, **options, &optional_filter_block) }
|
68
68
|
end
|
69
69
|
|
70
70
|
private
|
71
71
|
|
72
|
-
def _verify_current_path(path, **options)
|
73
|
-
query = Capybara::Queries::CurrentPathQuery.new(path, **options)
|
72
|
+
def _verify_current_path(path, filter_block, **options)
|
73
|
+
query = Capybara::Queries::CurrentPathQuery.new(path, **options, &filter_block)
|
74
74
|
document.synchronize(query.wait) do
|
75
75
|
yield(query)
|
76
76
|
end
|
@@ -271,5 +271,10 @@ $(function() {
|
|
271
271
|
});
|
272
272
|
$('#multiple-file, #hidden_file').change(function(e){
|
273
273
|
$('body').append($('<p class="file_change">File input changed</p>'));
|
274
|
-
})
|
274
|
+
});
|
275
|
+
|
276
|
+
var shadow = document.querySelector('#shadow').attachShadow({mode: 'open'});
|
277
|
+
var span = document.createElement('span');
|
278
|
+
span.textContent = 'The things we do in the shadows';
|
279
|
+
shadow.appendChild(span);
|
275
280
|
});
|
@@ -53,7 +53,7 @@ Capybara::SpecHelper.spec '#accept_alert', requires: [:modals] do
|
|
53
53
|
@session.click_link('Alert page change')
|
54
54
|
sleep 1 # ensure page change occurs before the accept_alert block exits
|
55
55
|
end
|
56
|
-
expect(@session).to have_current_path('/with_html')
|
56
|
+
expect(@session).to have_current_path('/with_html', wait: 5)
|
57
57
|
end
|
58
58
|
|
59
59
|
context 'with an asynchronous alert' do
|
@@ -229,6 +229,12 @@ Capybara::SpecHelper.spec '#check' do
|
|
229
229
|
@session.click_button('awesome')
|
230
230
|
expect(extract_results(@session)['cars']).to include('bugatti')
|
231
231
|
end
|
232
|
+
|
233
|
+
it 'should check via label if multiple labels' do
|
234
|
+
expect(@session).to have_field('multi_label_checkbox', checked: false, visible: :hidden)
|
235
|
+
@session.check('Label to click', allow_label_click: true)
|
236
|
+
expect(@session).to have_field('multi_label_checkbox', checked: true, visible: :hidden)
|
237
|
+
end
|
232
238
|
end
|
233
239
|
end
|
234
240
|
end
|
@@ -22,7 +22,7 @@ Capybara::SpecHelper.spec '#current_url, #current_path, #current_host' do
|
|
22
22
|
|
23
23
|
expect(@session.current_url.chomp('?')).to eq("#{scheme}://#{s.host}:#{s.port}#{path}")
|
24
24
|
expect(@session.current_host).to eq("#{scheme}://#{s.host}") # no port
|
25
|
-
expect(@session.current_path).to eq(path)
|
25
|
+
expect(@session.current_path).to eq(path.split('#')[0])
|
26
26
|
# Server should agree with us
|
27
27
|
expect(@session).to have_content("Current host is #{scheme}://#{s.host}:#{s.port}") if path == '/host'
|
28
28
|
end
|
@@ -84,6 +84,16 @@ Capybara::SpecHelper.spec '#current_url, #current_path, #current_host' do
|
|
84
84
|
should_be_on 0, '/landed'
|
85
85
|
end
|
86
86
|
|
87
|
+
it 'maintains fragment' do
|
88
|
+
@session.visit("#{bases[0]}/redirect#fragment")
|
89
|
+
should_be_on 0, '/landed#fragment'
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'redirects to a fragment' do
|
93
|
+
@session.visit("#{bases[0]}/redirect_with_fragment")
|
94
|
+
should_be_on 0, '/landed#with_fragment'
|
95
|
+
end
|
96
|
+
|
87
97
|
it 'is affected by pushState', requires: [:js] do
|
88
98
|
@session.visit('/with_js')
|
89
99
|
@session.execute_script("window.history.pushState({}, '', '/pushed')")
|
@@ -9,6 +9,8 @@ Capybara::SpecHelper.spec '#has_button?' do
|
|
9
9
|
expect(@session).to have_button('med')
|
10
10
|
expect(@session).to have_button('crap321')
|
11
11
|
expect(@session).to have_button(:crap321)
|
12
|
+
expect(@session).to have_button('button with label element')
|
13
|
+
expect(@session).to have_button('button within label element')
|
12
14
|
end
|
13
15
|
|
14
16
|
it 'should be true for disabled buttons if disabled: true' do
|
@@ -14,8 +14,9 @@ Capybara::SpecHelper.spec '#has_css?' do
|
|
14
14
|
# This was never a specifically accepted format but it has worked for a
|
15
15
|
# lot of versions.
|
16
16
|
# TODO: Remove in 4.0
|
17
|
-
|
17
|
+
allow(Capybara::Helpers).to receive(:warn).and_return(nil)
|
18
18
|
expect(@session).to have_css(:p)
|
19
|
+
expect(Capybara::Helpers).to have_received(:warn)
|
19
20
|
end
|
20
21
|
|
21
22
|
it 'should be false if the given selector is not on the page' do
|
@@ -94,6 +94,13 @@ Capybara::SpecHelper.spec '#has_current_path?' do
|
|
94
94
|
expect(@session).to have_current_path(nil, ignore_query: true)
|
95
95
|
end.not_to raise_exception
|
96
96
|
end
|
97
|
+
|
98
|
+
it 'should accept a filter block that receives Addressable::URL' do
|
99
|
+
@session.visit('/with_js?a=3&b=defgh')
|
100
|
+
expect(@session).to have_current_path('/with_js', ignore_query: true) { |url|
|
101
|
+
url.query_values.keys == %w[a b]
|
102
|
+
}
|
103
|
+
end
|
97
104
|
end
|
98
105
|
|
99
106
|
Capybara::SpecHelper.spec '#has_no_current_path?' do
|
@@ -135,4 +142,10 @@ Capybara::SpecHelper.spec '#has_no_current_path?' do
|
|
135
142
|
expect(@session).not_to have_current_path('/with_js', ignore_query: true)
|
136
143
|
end.not_to raise_exception
|
137
144
|
end
|
145
|
+
|
146
|
+
it 'should accept a filter block that receives Addressable::URL' do
|
147
|
+
expect(@session).to have_no_current_path('/with_js', ignore_query: true) { |url|
|
148
|
+
!url.query.nil?
|
149
|
+
}
|
150
|
+
end
|
138
151
|
end
|
@@ -133,17 +133,6 @@ Capybara::SpecHelper.spec '#has_text?' do
|
|
133
133
|
expect(@session).to have_text(:visible, with_to_hash, {})
|
134
134
|
end
|
135
135
|
end
|
136
|
-
|
137
|
-
it 'should fail if passed without empty options' do
|
138
|
-
with_to_hash = Class.new do
|
139
|
-
def to_s; '42' end
|
140
|
-
def to_hash; { blah: 'Other hash' } end
|
141
|
-
end.new
|
142
|
-
@session.visit('/with_html')
|
143
|
-
expect do
|
144
|
-
expect(@session).to have_text(:visible, with_to_hash)
|
145
|
-
end.to raise_error(ArgumentError)
|
146
|
-
end
|
147
136
|
end
|
148
137
|
|
149
138
|
context 'with exact: true option' do
|
@@ -28,8 +28,8 @@ Capybara::SpecHelper.spec '#matches_style?', requires: [:css] do
|
|
28
28
|
output(/have_style is deprecated/).to_stderr
|
29
29
|
|
30
30
|
el = @session.find(:css, '#first')
|
31
|
-
allow(
|
31
|
+
allow(Capybara::Helpers).to receive(:warn).and_return(nil)
|
32
32
|
el.has_style?('display' => /^bl/)
|
33
|
-
expect(
|
33
|
+
expect(Capybara::Helpers).to have_received(:warn)
|
34
34
|
end
|
35
35
|
end
|
@@ -388,8 +388,8 @@ Capybara::SpecHelper.spec 'node' do
|
|
388
388
|
|
389
389
|
describe '#==' do
|
390
390
|
it 'preserve object identity' do
|
391
|
-
expect(@session.find('//h1') == @session.find('//h1')).to be true # rubocop:disable Lint/
|
392
|
-
expect(@session.find('//h1') === @session.find('//h1')).to be true # rubocop:disable Style/CaseEquality, Lint/
|
391
|
+
expect(@session.find('//h1') == @session.find('//h1')).to be true # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands
|
392
|
+
expect(@session.find('//h1') === @session.find('//h1')).to be true # rubocop:disable Style/CaseEquality, Lint/BinaryOperatorWithIdenticalOperands
|
393
393
|
expect(@session.find('//h1').eql?(@session.find('//h1'))).to be false
|
394
394
|
end
|
395
395
|
|
@@ -409,6 +409,17 @@ Capybara::SpecHelper.spec 'node' do
|
|
409
409
|
element = @session.find(:link, 'Second Link')
|
410
410
|
expect(@session.find(:xpath, element.path)).to eq(element)
|
411
411
|
end
|
412
|
+
|
413
|
+
it 'reports when element in shadow dom', requires: [:shadow_dom] do
|
414
|
+
@session.visit('/with_js')
|
415
|
+
shadow = @session.find(:css, '#shadow')
|
416
|
+
element = @session.evaluate_script(<<~JS, shadow)
|
417
|
+
(function(root){
|
418
|
+
return root.shadowRoot.querySelector('span');
|
419
|
+
})(arguments[0])
|
420
|
+
JS
|
421
|
+
expect(element.path).to eq '(: Shadow DOM element - no XPath :)'
|
422
|
+
end
|
412
423
|
end
|
413
424
|
|
414
425
|
describe '#trigger', requires: %i[js trigger] do
|
@@ -671,6 +682,15 @@ Capybara::SpecHelper.spec 'node' do
|
|
671
682
|
expect(@session).to have_xpath('//div[contains(., "HTML5 Dropped string: text/plain Some dropped text")]')
|
672
683
|
end
|
673
684
|
|
685
|
+
it 'can drop a pathname' do
|
686
|
+
@session.visit('/with_js')
|
687
|
+
target = @session.find('//div[@id="drop_html5"]')
|
688
|
+
target.drop(
|
689
|
+
Pathname.new(with_os_path_separators(File.expand_path('../fixtures/capybara.jpg', File.dirname(__FILE__))))
|
690
|
+
)
|
691
|
+
expect(@session).to have_xpath('//div[contains(., "HTML5 Dropped file: capybara.jpg")]')
|
692
|
+
end
|
693
|
+
|
674
694
|
it 'can drop multiple strings' do
|
675
695
|
@session.visit('/with_js')
|
676
696
|
target = @session.find('//div[@id="drop_html5"]')
|
@@ -31,7 +31,7 @@ Capybara::SpecHelper.spec '#save_page' do
|
|
31
31
|
it 'can store files in a specified directory' do
|
32
32
|
Capybara.save_path = alternative_path
|
33
33
|
@session.save_page
|
34
|
-
path = Dir.glob(alternative_path
|
34
|
+
path = Dir.glob("#{alternative_path}/capybara-*.html").first
|
35
35
|
expect(File.read(path)).to include('Another World')
|
36
36
|
end
|
37
37
|
|
@@ -43,14 +43,14 @@ Capybara::SpecHelper.spec '#save_page' do
|
|
43
43
|
it 'can store files in a specified directory with a given filename' do
|
44
44
|
Capybara.save_path = alternative_path
|
45
45
|
@session.save_page('capybara-001133.html')
|
46
|
-
path = alternative_path
|
46
|
+
path = "#{alternative_path}/capybara-001133.html"
|
47
47
|
expect(File.read(path)).to include('Another World')
|
48
48
|
end
|
49
49
|
|
50
50
|
it 'can store files in a specified directory with a given relative filename' do
|
51
51
|
Capybara.save_path = alternative_path
|
52
52
|
@session.save_page('tmp/capybara-001144.html')
|
53
|
-
path = alternative_path
|
53
|
+
path = "#{alternative_path}/tmp/capybara-001144.html"
|
54
54
|
expect(File.read(path)).to include('Another World')
|
55
55
|
end
|
56
56
|
|
@@ -63,7 +63,7 @@ Capybara::SpecHelper.spec '#save_page' do
|
|
63
63
|
it 'returns an absolute path in given directory' do
|
64
64
|
Capybara.save_path = alternative_path
|
65
65
|
result = @session.save_page
|
66
|
-
path = File.expand_path(Dir.glob(alternative_path
|
66
|
+
path = File.expand_path(Dir.glob("#{alternative_path}/capybara-*.html").first, alternative_path)
|
67
67
|
expect(result).to eq(path)
|
68
68
|
end
|
69
69
|
|
@@ -58,7 +58,7 @@ module Capybara
|
|
58
58
|
|
59
59
|
def run_specs(session, name, **options, &filter_block)
|
60
60
|
specs = @specs
|
61
|
-
RSpec.describe Capybara::Session, name, options do
|
61
|
+
RSpec.describe Capybara::Session, name, options do
|
62
62
|
include Capybara::SpecHelper
|
63
63
|
include Capybara::RSpecMatchers
|
64
64
|
|
@@ -72,11 +72,11 @@ module Capybara
|
|
72
72
|
end
|
73
73
|
|
74
74
|
before :each, psc: true do
|
75
|
-
SpecHelper.reset_threadsafe(true, session)
|
75
|
+
SpecHelper.reset_threadsafe(bool: true, session: session)
|
76
76
|
end
|
77
77
|
|
78
78
|
after psc: true do
|
79
|
-
SpecHelper.reset_threadsafe(
|
79
|
+
SpecHelper.reset_threadsafe(session: session)
|
80
80
|
end
|
81
81
|
|
82
82
|
before :each, :exact_false do
|
@@ -84,15 +84,16 @@ module Capybara
|
|
84
84
|
end
|
85
85
|
|
86
86
|
specs.each do |spec_name, spec_options, block|
|
87
|
-
describe spec_name, *spec_options do
|
87
|
+
describe spec_name, *spec_options do
|
88
88
|
class_eval(&block)
|
89
89
|
end
|
90
90
|
end
|
91
91
|
end
|
92
92
|
end
|
93
93
|
|
94
|
-
def reset_threadsafe(bool
|
95
|
-
|
94
|
+
def reset_threadsafe(bool: false, session: nil)
|
95
|
+
# Work around limit on when threadsafe can be changed
|
96
|
+
Capybara::Session.class_variable_set(:@@instance_created, false) # rubocop:disable Style/ClassVars
|
96
97
|
Capybara.threadsafe = bool
|
97
98
|
session = session.current_session if session.respond_to?(:current_session)
|
98
99
|
session&.instance_variable_set(:@config, nil)
|
@@ -108,11 +109,9 @@ module Capybara
|
|
108
109
|
stream.reopen(old_stream)
|
109
110
|
end
|
110
111
|
|
111
|
-
def quietly
|
112
|
-
silence_stream(
|
113
|
-
silence_stream(
|
114
|
-
yield
|
115
|
-
end
|
112
|
+
def quietly(&block)
|
113
|
+
silence_stream($stdout) do
|
114
|
+
silence_stream($stderr, &block)
|
116
115
|
end
|
117
116
|
end
|
118
117
|
|
@@ -132,4 +131,4 @@ module Capybara
|
|
132
131
|
end
|
133
132
|
end
|
134
133
|
|
135
|
-
Dir[File.dirname(__FILE__)
|
134
|
+
Dir["#{File.dirname(__FILE__)}/session/**/*.rb"].each { |file| require_relative file }
|
@@ -9,6 +9,7 @@ class TestApp < Sinatra::Base
|
|
9
9
|
class TestAppError < Exception; end # rubocop:disable Lint/InheritException
|
10
10
|
class TestAppOtherError < Exception # rubocop:disable Lint/InheritException
|
11
11
|
def initialize(string1, msg)
|
12
|
+
super()
|
12
13
|
@something = string1
|
13
14
|
@message = msg
|
14
15
|
end
|
@@ -33,6 +34,10 @@ class TestApp < Sinatra::Base
|
|
33
34
|
redirect '/redirect_again'
|
34
35
|
end
|
35
36
|
|
37
|
+
get '/redirect_with_fragment' do
|
38
|
+
redirect '/landed#with_fragment'
|
39
|
+
end
|
40
|
+
|
36
41
|
get '/redirect_again' do
|
37
42
|
redirect '/landed'
|
38
43
|
end
|
@@ -85,11 +90,11 @@ class TestApp < Sinatra::Base
|
|
85
90
|
end
|
86
91
|
|
87
92
|
get '/form/get' do
|
88
|
-
|
93
|
+
%(<pre id="results">#{params[:form].to_yaml}</pre>)
|
89
94
|
end
|
90
95
|
|
91
96
|
post '/relative' do
|
92
|
-
|
97
|
+
%(<pre id="results">#{params[:form].to_yaml}</pre>)
|
93
98
|
end
|
94
99
|
|
95
100
|
get '/favicon.ico' do
|
@@ -176,7 +181,7 @@ class TestApp < Sinatra::Base
|
|
176
181
|
|
177
182
|
post '/form' do
|
178
183
|
self.class.form_post_count += 1
|
179
|
-
|
184
|
+
%(<pre id="results">#{params[:form].merge('post_count' => self.class.form_post_count).to_yaml}</pre>)
|
180
185
|
end
|
181
186
|
|
182
187
|
post '/upload_empty' do
|
@@ -456,6 +456,12 @@ New line after and before textarea tag
|
|
456
456
|
<button type="submit" name="form[no_value]">No Value!</button>
|
457
457
|
<button id="no_type">No Type!</button>
|
458
458
|
<button><img alt="A horse eating hay"/></button>
|
459
|
+
<button id="button_with_label"></button>
|
460
|
+
<label for="button_with_label">button with label element</label>
|
461
|
+
<label>
|
462
|
+
button within label element
|
463
|
+
<button></button>
|
464
|
+
</label>
|
459
465
|
<input type="button" disabled="disabled" value="Disabled button"/>
|
460
466
|
<span role="button">ARIA button</span>
|
461
467
|
</p>
|
@@ -684,3 +690,15 @@ New line after and before textarea tag
|
|
684
690
|
<p>
|
685
691
|
<input id="special" {custom}="abcdef" value="custom attribute"/>
|
686
692
|
</p>
|
693
|
+
|
694
|
+
|
695
|
+
<label for="multi_label_checkbox">
|
696
|
+
Label to click
|
697
|
+
</label>
|
698
|
+
<div>Something random that justifies the usage of a separate label</div>
|
699
|
+
<label>
|
700
|
+
<div>
|
701
|
+
<input type="checkbox" id="multi_label_checkbox" style="display: none"/>
|
702
|
+
<div>Visual representation of the checkbox</div>
|
703
|
+
</div>
|
704
|
+
</label>
|
@@ -2,7 +2,7 @@
|
|
2
2
|
<head>
|
3
3
|
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
|
4
4
|
<title>with_sortable_js</title>
|
5
|
-
<script src="https://sortablejs.
|
5
|
+
<script src="https://cdn.jsdelivr.net/npm/sortablejs@1.12.0/dist/sortable.umd.min.js" type="text/javascript"></script>
|
6
6
|
</head>
|
7
7
|
|
8
8
|
<body id="with_sortable_js">
|