capybara 3.10.1 → 3.11.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 +13 -0
- data/README.md +2 -3
- data/lib/capybara.rb +16 -6
- data/lib/capybara/minitest.rb +8 -9
- data/lib/capybara/node/actions.rb +31 -28
- data/lib/capybara/node/base.rb +2 -1
- data/lib/capybara/node/document_matchers.rb +6 -2
- data/lib/capybara/node/element.rb +10 -10
- data/lib/capybara/node/finders.rb +13 -14
- data/lib/capybara/node/matchers.rb +1 -3
- data/lib/capybara/node/simple.rb +10 -2
- data/lib/capybara/queries/base_query.rb +7 -3
- data/lib/capybara/queries/selector_query.rb +60 -34
- data/lib/capybara/queries/style_query.rb +5 -1
- data/lib/capybara/queries/text_query.rb +2 -2
- data/lib/capybara/queries/title_query.rb +1 -1
- data/lib/capybara/rack_test/node.rb +16 -2
- data/lib/capybara/result.rb +9 -4
- data/lib/capybara/rspec/features.rb +4 -4
- data/lib/capybara/rspec/matcher_proxies.rb +3 -1
- data/lib/capybara/rspec/matchers.rb +25 -287
- data/lib/capybara/rspec/matchers/base.rb +98 -0
- data/lib/capybara/rspec/matchers/become_closed.rb +33 -0
- data/lib/capybara/rspec/matchers/compound.rb +88 -0
- data/lib/capybara/rspec/matchers/have_current_path.rb +29 -0
- data/lib/capybara/rspec/matchers/have_selector.rb +69 -0
- data/lib/capybara/rspec/matchers/have_style.rb +23 -0
- data/lib/capybara/rspec/matchers/have_text.rb +33 -0
- data/lib/capybara/rspec/matchers/have_title.rb +29 -0
- data/lib/capybara/rspec/matchers/match_selector.rb +27 -0
- data/lib/capybara/selector.rb +48 -20
- data/lib/capybara/selector/builders/xpath_builder.rb +3 -3
- data/lib/capybara/selector/css.rb +5 -5
- data/lib/capybara/selector/filters/base.rb +11 -3
- data/lib/capybara/selector/filters/expression_filter.rb +3 -3
- data/lib/capybara/selector/filters/node_filter.rb +16 -2
- data/lib/capybara/selector/regexp_disassembler.rb +116 -17
- data/lib/capybara/selector/selector.rb +52 -26
- data/lib/capybara/selenium/driver.rb +6 -2
- data/lib/capybara/selenium/node.rb +15 -14
- data/lib/capybara/selenium/nodes/marionette_node.rb +19 -5
- data/lib/capybara/selenium/patches/pause_duration_fix.rb +1 -3
- data/lib/capybara/server.rb +6 -1
- data/lib/capybara/server/animation_disabler.rb +1 -1
- data/lib/capybara/session.rb +4 -2
- data/lib/capybara/session/matchers.rb +7 -3
- data/lib/capybara/spec/public/test.js +5 -5
- data/lib/capybara/spec/session/all_spec.rb +5 -0
- data/lib/capybara/spec/session/has_css_spec.rb +4 -4
- data/lib/capybara/spec/session/has_field_spec.rb +17 -0
- data/lib/capybara/spec/session/node_spec.rb +45 -4
- data/lib/capybara/spec/spec_helper.rb +6 -1
- data/lib/capybara/spec/views/frame_child.erb +1 -1
- data/lib/capybara/spec/views/obscured.erb +44 -0
- data/lib/capybara/spec/views/with_html.erb +1 -1
- data/lib/capybara/version.rb +1 -1
- data/spec/rack_test_spec.rb +15 -0
- data/spec/regexp_dissassembler_spec.rb +88 -8
- data/spec/selector_spec.rb +3 -0
- data/spec/selenium_spec_chrome.rb +9 -15
- data/spec/selenium_spec_chrome_remote.rb +3 -2
- data/spec/selenium_spec_firefox_remote.rb +6 -2
- metadata +54 -3
- data/lib/capybara/rspec/compound.rb +0 -86
@@ -225,7 +225,7 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
225
225
|
::Selenium::WebDriver::Error::StaleElementReferenceError,
|
226
226
|
::Selenium::WebDriver::Error::UnhandledError,
|
227
227
|
::Selenium::WebDriver::Error::ElementNotVisibleError,
|
228
|
-
::Selenium::WebDriver::Error::InvalidSelectorError, # Work around a
|
228
|
+
::Selenium::WebDriver::Error::InvalidSelectorError, # Work around a chromedriver go_back/go_forward race condition
|
229
229
|
::Selenium::WebDriver::Error::ElementNotInteractableError,
|
230
230
|
::Selenium::WebDriver::Error::ElementClickInterceptedError,
|
231
231
|
::Selenium::WebDriver::Error::InvalidElementStateError,
|
@@ -352,11 +352,15 @@ private
|
|
352
352
|
when :chrome
|
353
353
|
extend ChromeDriver
|
354
354
|
when :firefox
|
355
|
-
require 'capybara/selenium/patches/pause_duration_fix' if
|
355
|
+
require 'capybara/selenium/patches/pause_duration_fix' if pause_broken?(sel_driver)
|
356
356
|
extend MarionetteDriver if sel_driver.capabilities.is_a?(::Selenium::WebDriver::Remote::W3C::Capabilities)
|
357
357
|
end
|
358
358
|
end
|
359
359
|
|
360
|
+
def pause_broken?(driver)
|
361
|
+
driver.capabilities['moz:geckodriverVersion']&.start_with?('0.22.')
|
362
|
+
end
|
363
|
+
|
360
364
|
def setup_exit_handler
|
361
365
|
main = Process.pid
|
362
366
|
at_exit do
|
@@ -170,22 +170,9 @@ class Capybara::Selenium::Node < Capybara::Driver::Node
|
|
170
170
|
selector = node[:tagName]
|
171
171
|
if node[:namespaceURI] != default_ns
|
172
172
|
selector = XPath.child.where((XPath.local_name == selector) & (XPath.namespace_uri == node[:namespaceURI])).to_s
|
173
|
-
selector
|
174
173
|
end
|
175
174
|
|
176
|
-
if parent
|
177
|
-
siblings = parent.find_xpath(selector)
|
178
|
-
selector += case siblings.size
|
179
|
-
when 0
|
180
|
-
'[ERROR]' # IE doesn't support full XPath (namespace-uri, etc)
|
181
|
-
when 1
|
182
|
-
'' # index not necessary when only one matching element
|
183
|
-
else
|
184
|
-
idx = siblings.index(node)
|
185
|
-
# Element may not be found in the siblings if it has gone away
|
186
|
-
idx.nil? ? '[ERROR]' : "[#{idx + 1}]"
|
187
|
-
end
|
188
|
-
end
|
175
|
+
selector += sibling_index(parent, node, selector) if parent
|
189
176
|
result.push selector
|
190
177
|
end
|
191
178
|
|
@@ -203,6 +190,20 @@ protected
|
|
203
190
|
|
204
191
|
private
|
205
192
|
|
193
|
+
def sibling_index(parent, node, selector)
|
194
|
+
siblings = parent.find_xpath(selector)
|
195
|
+
case siblings.size
|
196
|
+
when 0
|
197
|
+
'[ERROR]' # IE doesn't support full XPath (namespace-uri, etc)
|
198
|
+
when 1
|
199
|
+
'' # index not necessary when only one matching element
|
200
|
+
else
|
201
|
+
idx = siblings.index(node)
|
202
|
+
# Element may not be found in the siblings if it has gone away
|
203
|
+
idx.nil? ? '[ERROR]' : "[#{idx + 1}]"
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
206
207
|
def boolean_attr(val)
|
207
208
|
val && (val != 'false')
|
208
209
|
end
|
@@ -9,8 +9,9 @@ class Capybara::Selenium::MarionetteNode < Capybara::Selenium::Node
|
|
9
9
|
super
|
10
10
|
rescue ::Selenium::WebDriver::Error::ElementNotInteractableError
|
11
11
|
if tag_name == 'tr'
|
12
|
-
warn 'You are attempting to click a table row which has issues in geckodriver/marionette -
|
13
|
-
'Your test should probably be
|
12
|
+
warn 'You are attempting to click a table row which has issues in geckodriver/marionette - '\
|
13
|
+
'see https://github.com/mozilla/geckodriver/issues/1228. Your test should probably be '\
|
14
|
+
'clicking on a table cell like a user would. Clicking the first cell in the row instead.'
|
14
15
|
return find_css('th:first-child,td:first-child')[0].click(keys, options)
|
15
16
|
end
|
16
17
|
raise
|
@@ -26,7 +27,7 @@ class Capybara::Selenium::MarionetteNode < Capybara::Selenium::Node
|
|
26
27
|
if %w[option optgroup].include? tag_name
|
27
28
|
find_xpath('parent::*[self::optgroup or self::select]')[0].disabled?
|
28
29
|
else
|
29
|
-
!find_xpath(
|
30
|
+
!find_xpath(DISABLED_BY_FIELDSET_XPATH).empty?
|
30
31
|
end
|
31
32
|
end
|
32
33
|
|
@@ -99,14 +100,27 @@ private
|
|
99
100
|
return nil unless local_file
|
100
101
|
raise ArgumentError, "You may only upload files: #{local_file.inspect}" unless File.file?(local_file)
|
101
102
|
|
102
|
-
|
103
|
-
|
103
|
+
file = ::Selenium::WebDriver::Zipper.zip_file(local_file)
|
104
|
+
bridge.http.call(:post, "session/#{bridge.session_id}/file", file: file)['value']
|
104
105
|
end
|
105
106
|
|
106
107
|
def browser_version
|
107
108
|
driver.browser.capabilities[:browser_version].to_f
|
108
109
|
end
|
109
110
|
|
111
|
+
DISABLED_BY_FIELDSET_XPATH = XPath.generate do |x|
|
112
|
+
x.parent(:fieldset)[
|
113
|
+
x.attr(:disabled)
|
114
|
+
] + x.ancestor[
|
115
|
+
~x.self(:legned) |
|
116
|
+
x.preceding_sibling(:legend)
|
117
|
+
][
|
118
|
+
x.parent(:fieldset)[
|
119
|
+
x.attr(:disabled)
|
120
|
+
]
|
121
|
+
]
|
122
|
+
end.to_s.freeze
|
123
|
+
|
110
124
|
class ModifierKeysStack
|
111
125
|
def initialize
|
112
126
|
@stack = []
|
data/lib/capybara/server.rb
CHANGED
@@ -18,7 +18,12 @@ module Capybara
|
|
18
18
|
|
19
19
|
attr_reader :app, :port, :host
|
20
20
|
|
21
|
-
def initialize(app,
|
21
|
+
def initialize(app,
|
22
|
+
*deprecated_options,
|
23
|
+
port: Capybara.server_port,
|
24
|
+
host: Capybara.server_host,
|
25
|
+
reportable_errors: Capybara.server_errors,
|
26
|
+
extra_middleware: [])
|
22
27
|
warn 'Positional arguments, other than the application, to Server#new are deprecated, please use keyword arguments' unless deprecated_options.empty?
|
23
28
|
@app = app
|
24
29
|
@extra_middleware = extra_middleware
|
@@ -16,7 +16,7 @@ module Capybara
|
|
16
16
|
|
17
17
|
def initialize(app)
|
18
18
|
@app = app
|
19
|
-
@disable_markup = format(DISABLE_MARKUP_TEMPLATE, selector:
|
19
|
+
@disable_markup = format(DISABLE_MARKUP_TEMPLATE, selector: self.class.selector_for(Capybara.disable_animation))
|
20
20
|
end
|
21
21
|
|
22
22
|
def call(env)
|
data/lib/capybara/session.rb
CHANGED
@@ -43,7 +43,7 @@ module Capybara
|
|
43
43
|
click_link_or_button click_button click_link
|
44
44
|
fill_in find find_all find_button find_by_id find_field find_link
|
45
45
|
has_content? has_text? has_css? has_no_content? has_no_text?
|
46
|
-
has_no_css? has_no_xpath?
|
46
|
+
has_no_css? has_no_xpath? has_xpath? select uncheck
|
47
47
|
has_link? has_no_link? has_button? has_no_button? has_field?
|
48
48
|
has_no_field? has_checked_field? has_unchecked_field?
|
49
49
|
has_no_table? has_table? unselect has_select? has_no_select?
|
@@ -819,7 +819,9 @@ module Capybara
|
|
819
819
|
end
|
820
820
|
|
821
821
|
def prepare_path(path, extension)
|
822
|
-
File.expand_path(path || default_fn(extension), config.save_path).tap
|
822
|
+
File.expand_path(path || default_fn(extension), config.save_path).tap do |p_path|
|
823
|
+
FileUtils.mkdir_p(File.dirname(p_path))
|
824
|
+
end
|
823
825
|
end
|
824
826
|
|
825
827
|
def default_fn(extension)
|
@@ -6,7 +6,7 @@ module Capybara
|
|
6
6
|
# Asserts that the page has the given path.
|
7
7
|
# By default, if passed a full url this will compare against the full url,
|
8
8
|
# if passed a path only the path+query portion will be compared, if passed a regexp
|
9
|
-
# the comparison will depend on the :url option
|
9
|
+
# the comparison will depend on the :url option (path+query by default)
|
10
10
|
#
|
11
11
|
# @!macro current_path_query_params
|
12
12
|
# @overload $0(string, **options)
|
@@ -20,7 +20,9 @@ module Capybara
|
|
20
20
|
# @return [true]
|
21
21
|
#
|
22
22
|
def assert_current_path(path, **options)
|
23
|
-
_verify_current_path(path, options)
|
23
|
+
_verify_current_path(path, options) do |query|
|
24
|
+
raise Capybara::ExpectationNotMet, query.failure_message unless query.resolves_for?(self)
|
25
|
+
end
|
24
26
|
end
|
25
27
|
|
26
28
|
##
|
@@ -34,7 +36,9 @@ module Capybara
|
|
34
36
|
# @return [true]
|
35
37
|
#
|
36
38
|
def assert_no_current_path(path, **options)
|
37
|
-
_verify_current_path(path, options)
|
39
|
+
_verify_current_path(path, options) do |query|
|
40
|
+
raise Capybara::ExpectationNotMet, query.negative_failure_message if query.resolves_for?(self)
|
41
|
+
end
|
38
42
|
end
|
39
43
|
|
40
44
|
##
|
@@ -159,25 +159,25 @@ $(function() {
|
|
159
159
|
$(this).attr('confirmed', 'false');
|
160
160
|
}
|
161
161
|
}
|
162
|
-
})
|
162
|
+
});
|
163
163
|
$('#delayed-page-change').click(function() {
|
164
164
|
setTimeout(function() {
|
165
165
|
window.location.pathname = '/with_html'
|
166
166
|
}, 500)
|
167
|
-
})
|
167
|
+
});
|
168
168
|
$('#with-key-events').keydown(function(e){
|
169
169
|
$('#key-events-output').append('keydown:'+e.which+' ')
|
170
170
|
});
|
171
171
|
$('#disable-on-click').click(function(e){
|
172
|
-
var input = this
|
172
|
+
var input = this;
|
173
173
|
setTimeout(function() {
|
174
174
|
input.disabled = true;
|
175
175
|
}, 500)
|
176
|
-
})
|
176
|
+
});
|
177
177
|
$('#set-storage').click(function(e){
|
178
178
|
sessionStorage.setItem('session', 'session_value');
|
179
179
|
localStorage.setItem('local', 'local value');
|
180
|
-
})
|
180
|
+
});
|
181
181
|
$('#multiple-file').change(function(e){
|
182
182
|
$('body').append($('<p class="file_change"input_event_triggered">File input changed</p>'));
|
183
183
|
})
|
@@ -56,6 +56,11 @@ Capybara::SpecHelper.spec '#all' do
|
|
56
56
|
expect(@session.all(:xpath, '//h1').first.text).to eq('This is a test')
|
57
57
|
expect(@session.all(:xpath, "//input[@id='test_field']").first.value).to eq('monkey')
|
58
58
|
end
|
59
|
+
|
60
|
+
it 'should use alternated regex for :id' do
|
61
|
+
expect(@session.all(:xpath, './/h2', id: /h2/).unfiltered_size).to eq 3
|
62
|
+
expect(@session.all(:xpath, './/h2', id: /h2(one|two)/).unfiltered_size).to eq 2
|
63
|
+
end
|
59
64
|
end
|
60
65
|
|
61
66
|
context 'with css as default selector' do
|
@@ -50,17 +50,17 @@ Capybara::SpecHelper.spec '#has_css?' do
|
|
50
50
|
it 'should be able to generate an error message if the scope is a sibling' do
|
51
51
|
el = @session.find(:css, '#first')
|
52
52
|
@session.within el.sibling(:css, '#second') do
|
53
|
-
expect
|
53
|
+
expect do
|
54
54
|
expect(@session).to have_css('a#not_on_page')
|
55
|
-
|
55
|
+
end.to raise_error(/there were no matches/)
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
59
|
it 'should be able to generate an error message if the scope is a sibling from XPath' do
|
60
60
|
el = @session.find(:css, '#first').find(:xpath, './following-sibling::*[1]') do
|
61
|
-
expect
|
61
|
+
expect do
|
62
62
|
expect(el).to have_css('a#not_on_page')
|
63
|
-
|
63
|
+
end.to raise_error(/there were no matches/)
|
64
64
|
end
|
65
65
|
end
|
66
66
|
end
|
@@ -41,6 +41,23 @@ Capybara::SpecHelper.spec '#has_field' do
|
|
41
41
|
expect(@session).not_to have_field('First Name', with: 'John')
|
42
42
|
expect(@session).not_to have_field('First Name', with: /John|Paul|George|Ringo/)
|
43
43
|
end
|
44
|
+
|
45
|
+
it 'should output filter errors if only one element matched the selector but failed the filters' do
|
46
|
+
@session.fill_in('First Name', with: 'Thomas')
|
47
|
+
expect do
|
48
|
+
expect(@session).to have_field('First Name', with: 'Jonas')
|
49
|
+
end.to raise_exception(RSpec::Expectations::ExpectationNotMetError, /Expected value to be "Jonas" but was "Thomas"/)
|
50
|
+
|
51
|
+
# native boolean node filter
|
52
|
+
expect do
|
53
|
+
expect(@session).to have_field('First Name', readonly: true)
|
54
|
+
end.to raise_exception(RSpec::Expectations::ExpectationNotMetError, /Expected readonly true but it wasn't/)
|
55
|
+
|
56
|
+
# inherited boolean node filter
|
57
|
+
expect do
|
58
|
+
expect(@session).to have_field('form_pets_cat', checked: true)
|
59
|
+
end.to raise_exception(RSpec::Expectations::ExpectationNotMetError, /Expected checked true but it wasn't/)
|
60
|
+
end
|
44
61
|
end
|
45
62
|
|
46
63
|
context 'with type' do
|
@@ -411,6 +411,33 @@ Capybara::SpecHelper.spec 'node' do
|
|
411
411
|
tr = @session.find(:css, '#agent_table tr:first-child').click
|
412
412
|
expect(tr).to have_css('label', text: 'Clicked')
|
413
413
|
end
|
414
|
+
|
415
|
+
it 'should retry clicking', requires: [:js] do
|
416
|
+
@session.visit('/obscured')
|
417
|
+
obscured = @session.find(:css, '#obscured')
|
418
|
+
@session.execute_script <<~JS
|
419
|
+
setTimeout(function(){ $('#cover').hide(); }, 1000)
|
420
|
+
JS
|
421
|
+
expect { obscured.click }.not_to raise_error
|
422
|
+
end
|
423
|
+
|
424
|
+
it 'should allow to retry longer', requires: [:js] do
|
425
|
+
@session.visit('/obscured')
|
426
|
+
obscured = @session.find(:css, '#obscured')
|
427
|
+
@session.execute_script <<~JS
|
428
|
+
setTimeout(function(){ $('#cover').hide(); }, 3000)
|
429
|
+
JS
|
430
|
+
expect { obscured.click(wait: 4) }.not_to raise_error
|
431
|
+
end
|
432
|
+
|
433
|
+
it 'should not retry clicking when wait is disabled', requires: [:js] do
|
434
|
+
@session.visit('/obscured')
|
435
|
+
obscured = @session.find(:css, '#obscured')
|
436
|
+
@session.execute_script <<~JS
|
437
|
+
setTimeout(function(){ $('#cover').hide(); }, 2000)
|
438
|
+
JS
|
439
|
+
expect { obscured.click(wait: 0) }.to(raise_error { |e| expect(e).to be_an_invalid_element_error(@session) })
|
440
|
+
end
|
414
441
|
end
|
415
442
|
|
416
443
|
describe '#double_click', requires: [:js] do
|
@@ -436,6 +463,15 @@ Capybara::SpecHelper.spec 'node' do
|
|
436
463
|
expect(locations[:x].to_f).to be_within(1).of(10)
|
437
464
|
expect(locations[:y].to_f).to be_within(1).of(5)
|
438
465
|
end
|
466
|
+
|
467
|
+
it 'should retry clicking', requires: [:js] do
|
468
|
+
@session.visit('/obscured')
|
469
|
+
obscured = @session.find(:css, '#obscured')
|
470
|
+
@session.execute_script <<~JS
|
471
|
+
setTimeout(function(){ $('#cover').hide(); }, 1000)
|
472
|
+
JS
|
473
|
+
expect { obscured.double_click }.not_to raise_error
|
474
|
+
end
|
439
475
|
end
|
440
476
|
|
441
477
|
describe '#right_click', requires: [:js] do
|
@@ -461,6 +497,15 @@ Capybara::SpecHelper.spec 'node' do
|
|
461
497
|
expect(locations[:x].to_f).to be_within(1).of(10)
|
462
498
|
expect(locations[:y].to_f).to be_within(1).of(10)
|
463
499
|
end
|
500
|
+
|
501
|
+
it 'should retry clicking', requires: [:js] do
|
502
|
+
@session.visit('/obscured')
|
503
|
+
obscured = @session.find(:css, '#obscured')
|
504
|
+
@session.execute_script <<~JS
|
505
|
+
setTimeout(function(){ $('#cover').hide(); }, 1000)
|
506
|
+
JS
|
507
|
+
expect { obscured.right_click }.not_to raise_error
|
508
|
+
end
|
464
509
|
end
|
465
510
|
|
466
511
|
describe '#send_keys', requires: [:send_keys] do
|
@@ -670,8 +715,4 @@ Capybara::SpecHelper.spec 'node' do
|
|
670
715
|
end)
|
671
716
|
end
|
672
717
|
end
|
673
|
-
|
674
|
-
def be_an_invalid_element_error(session)
|
675
|
-
satisfy { |error| session.driver.invalid_element_errors.any? { |e| error.is_a? e } }
|
676
|
-
end
|
677
718
|
end
|
@@ -117,7 +117,12 @@ module Capybara
|
|
117
117
|
|
118
118
|
def extract_results(session)
|
119
119
|
expect(session).to have_xpath("//pre[@id='results']")
|
120
|
-
YAML.load Nokogiri::HTML(session.body).xpath("//pre[@id='results']").first.inner_html.lstrip
|
120
|
+
# YAML.load Nokogiri::HTML(session.body).xpath("//pre[@id='results']").first.inner_html.lstrip
|
121
|
+
YAML.load Capybara::HTML(session.body).xpath("//pre[@id='results']").first.inner_html.lstrip
|
122
|
+
end
|
123
|
+
|
124
|
+
def be_an_invalid_element_error(session)
|
125
|
+
satisfy { |error| session.driver.invalid_element_errors.any? { |e| error.is_a? e } }
|
121
126
|
end
|
122
127
|
end
|
123
128
|
end
|
@@ -4,7 +4,7 @@
|
|
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>
|
@@ -0,0 +1,44 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
|
4
|
+
<title>with_animation</title>
|
5
|
+
<script src="/jquery.js" type="text/javascript" charset="utf-8"></script>
|
6
|
+
<style>
|
7
|
+
div {
|
8
|
+
width: 400px;
|
9
|
+
height: 400px;
|
10
|
+
position: absolute;
|
11
|
+
}
|
12
|
+
#obscured {
|
13
|
+
z-index: 1;
|
14
|
+
background-color: red;
|
15
|
+
}
|
16
|
+
#cover {
|
17
|
+
z-index: 2;
|
18
|
+
background-color: blue;
|
19
|
+
}
|
20
|
+
#offscreen {
|
21
|
+
top: 2000px;
|
22
|
+
left: 2000px;
|
23
|
+
background-color: green;
|
24
|
+
}
|
25
|
+
#offscreen_wrapper {
|
26
|
+
top: 2000px;
|
27
|
+
left: 2000px;
|
28
|
+
overflow-x: scroll;
|
29
|
+
background-color: yellow;
|
30
|
+
}
|
31
|
+
</style>
|
32
|
+
</head>
|
33
|
+
|
34
|
+
<body id="with_animation">
|
35
|
+
<div id="obscured">
|
36
|
+
<input id="obscured_input"/>
|
37
|
+
</div>
|
38
|
+
<div id="cover"></div>
|
39
|
+
<div id="offscreen_wrapper">
|
40
|
+
<div id="offscreen"></div>
|
41
|
+
</div>
|
42
|
+
</body>
|
43
|
+
</html>
|
44
|
+
|
@@ -10,7 +10,7 @@
|
|
10
10
|
<h2 class="no text"></h2>
|
11
11
|
<h2 class="head" id="h2one">Header Class Test One</h2>
|
12
12
|
<h2 class="head" id="h2two">Header Class Test Two</h2>
|
13
|
-
<h2 class="head">Header Class Test Three</h2>
|
13
|
+
<h2 class="head" id="h2_">Header Class Test Three</h2>
|
14
14
|
<h2 class="head">Header Class Test Four</h2>
|
15
15
|
<h2 class="head">Header Class Test Five</h2>
|
16
16
|
|