Skip to content

Instantly share code, notes, and snippets.

@titusfortner
Last active August 29, 2015 14:13
Show Gist options
  • Save titusfortner/fa8afa2d1e47d456cd41 to your computer and use it in GitHub Desktop.
Save titusfortner/fa8afa2d1e47d456cd41 to your computer and use it in GitHub Desktop.
Always locate
context 'when set to true' do
before do
Watir.always_locate = true
browser.goto WatirSpec.url_for('removed_element.html', :needs_server => true)
end
it '#exists? relocates the element when it is stale' do
element = browser.div(:id => "text")
expect(element.exists?).to be true
browser.refresh
expect(element.exists?).to be true
end
it '#exists? relocates the element when it is not stale' do
element = browser.div(:id => "text")
expect(element.exists?).to be true
allow(browser.driver).to receive(:find_element).with(:id, 'text') { raise }
expect { element.exists? }.to raise_error
end
it 'does not raise an exception when taking an action on a stale element' do
element = browser.div(:id => "text")
expect(element.exists?).to be true
browser.refresh
expect { element.text }.to_not raise_error
end
end
context 'when set to false' do
before do
Watir.always_locate = false
browser.goto WatirSpec.url_for('removed_element.html', :needs_server => true)
end
it '#exists? does not relocate an element when it is stale' do
element = browser.div(:id => "text")
expect(element.exists?).to be true
browser.refresh
expect(element.exists?).to be false
end
it '#exists? does not relocate an element when it is not stale' do
element = browser.div(:id => "text")
expect(element.exists?).to be true
allow(browser.driver).to receive(:find_element).with(:id, 'text') { raise }
expect { element.exists? }.to_not raise_error
end
it 'raises an exception when taking an action on a stale element' do
element = browser.div(:id => "text")
expect(element.exists?).to be true
browser.refresh
expect { element.text }.to raise_error
end
it '#exists? relocates a stale element when called twice' do
element = browser.div(:id => "text")
expect(element.exists?).to be true
browser.refresh
expect(element.exists?).to be false
expect(element.exists?).to be true
end
it 'does not raise an exception if calls #exists? on stale element before taking action' do
element = browser.div(:id => "text")
expect(element.exists?).to be true
browser.refresh
expect(element.exists?).to be false
expect { element.text }.to_not raise_error
end
end
Having a toggle for #always_locate is confusing.
The confusion is over two different interpretations of what #exists? means.
1) Does the WebDriver::Element object previously located currently exist?
2) Is there an element in the DOM that matches the locator?
Current behavior has several issues:
1) Caching. Neither setting allows you to cache elements so long as they are stale and
automatically re-locate them once they become stale
2) Making multiple calls of the same method in succession can return different results.
The two interpretations of exists should each have their own method.
I suggest adding #stale? to check for whether the WebDriver::Element previously located is
still present and continue using #exists? to determine whether an object matches the locator
This allows the framework to better accommodate the intention of the test by trying to the
fullest extent to carry out the test's instructions, and to only raise an exception in
exceptional circumstances.
before do
browser.goto WatirSpec.url_for('removed_element.html', :needs_server => true)
end
# current behavior from always_locate? == true
it '#exists? relocates an element when it is stale' do
element = browser.div(:id => "text")
expect(element.exists?).to be true
browser.refresh
expect(element.exists?).to be true
end
# current behavior from always_locate? == false
# performance advantage over current always_locate? == true
it '#exists? does not relocate an element when it is not stale' do
element = browser.div(:id => "text")
expect(element.exists?).to be true
allow(browser.driver).to receive(:find_element).with(:id, 'text') { raise }
expect { element.exists? }.to_not raise_error
end
# current behavior from always_locate? == true
it 'does not raise an exception when taking an action on a stale element' do
element = browser.div(:id => "text")
expect(element.exists?).to be true
browser.refresh
expect { element.text }.to_not raise_error
end
# current behavior from #exits? when always_locate? == false
it '#stale? does not relocate an element when it is stale' do
element = browser.div(:id => "text")
expect(element.stale?).to be false
browser.refresh
expect(element.stale?).to be true
end
# this behavior not possible from current code
it '#stale? does not relocate an element when called multiple times' do
element = browser.div(:id => "text")
expect(element.stale?).to be false
browser.refresh
expect(element.stale?).to be true
expect(element.stale?).to be true
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment