blob: 3d268f0f1c56066b07df248ed9df89a93083dbcd [file] [log] [blame]
# frozen_string_literal: true
# Licensed to the Software Freedom Conservancy (SFC) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The SFC licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
require_relative 'spec_helper'
module Selenium
module WebDriver
describe Element do
it 'should click' do
driver.navigate.to url_for('formPage.html')
expect { driver.find_element(id: 'imageButton').click }.not_to raise_error
reset_driver!(time: 1) if %i[safari safari_preview].include? GlobalTestEnv.browser
end
# Safari returns "click intercepted" error instead of "element click intercepted"
it 'should raise if different element receives click', except: {browser: %i[safari safari_preview]} do
driver.navigate.to url_for('click_tests/overlapping_elements.html')
expect { driver.find_element(id: 'contents').click }.to raise_error(Error::ElementClickInterceptedError)
end
# Safari returns "click intercepted" error instead of "element click intercepted"
it 'should raise if element is partially covered', except: {browser: %i[safari safari_preview]} do
driver.navigate.to url_for('click_tests/overlapping_elements.html')
expect { driver.find_element(id: 'other_contents').click }.to raise_error(Error::ElementClickInterceptedError)
end
describe '#submit' do
it 'valid submit button' do
driver.navigate.to url_for('formPage.html')
driver.find_element(id: 'submitButton').submit
sleep 0.5
expect(driver.title).to eq('We Arrive Here')
end
it 'any input element in form' do
driver.navigate.to url_for('formPage.html')
driver.find_element(id: 'checky').submit
sleep 0.5
expect(driver.title).to eq('We Arrive Here')
end
it 'any element in form' do
driver.navigate.to url_for('formPage.html')
driver.find_element(css: 'form > p').submit
sleep 0.5
expect(driver.title).to eq('We Arrive Here')
end
it 'button with id submit' do
driver.navigate.to url_for('formPage.html')
driver.find_element(id: 'submit').submit
sleep 0.5
expect(driver.title).to eq('We Arrive Here')
end
it 'button with name submit' do
driver.navigate.to url_for('formPage.html')
driver.find_element(name: 'submit').submit
sleep 0.5
expect(driver.title).to eq('We Arrive Here')
end
it 'errors with button outside form' do
driver.navigate.to url_for('formPage.html')
expect { driver.find_element(name: 'SearchableText').submit }.to raise_error(Error::UnsupportedOperationError)
end
end
it 'should send string keys' do
driver.navigate.to url_for('formPage.html')
wait_for_element(id: 'working')
expect { driver.find_element(id: 'working').send_keys('foo', 'bar') }.not_to raise_error
end
it 'should send key presses' do
driver.navigate.to url_for('javascriptPage.html')
key_reporter = driver.find_element(id: 'keyReporter')
key_reporter.send_keys('Tet', :arrow_left, 's')
expect(key_reporter.attribute('value')).to eq('Test')
end
# https://github.com/mozilla/geckodriver/issues/245
it 'should send key presses chords', except: {browser: %i[firefox safari safari_preview]} do
driver.navigate.to url_for('javascriptPage.html')
key_reporter = driver.find_element(id: 'keyReporter')
key_reporter.send_keys([:shift, 'h'], 'ello')
expect(key_reporter.attribute('value')).to eq('Hello')
end
it 'should handle file uploads' do
driver.navigate.to url_for('formPage.html')
element = driver.find_element(id: 'upload')
expect(element.attribute('value')).to be_empty
path = WebDriver::Platform.windows? ? WebDriver::Platform.windows_path(__FILE__) : __FILE__
element.send_keys path
expect(element.attribute('value')).to include(File.basename(path))
end
describe 'properties and attributes' do
before { driver.navigate.to url_for('formPage.html') }
context 'string type' do
let(:element) { driver.find_element(id: 'checky') }
let(:prop_or_attr) { 'type' }
it '#dom_attribute returns attribute value' do
expect(element.dom_attribute(prop_or_attr)).to eq 'checkbox'
end
it '#property returns property value' do
expect(element.property(prop_or_attr)).to eq 'checkbox'
end
it '#attribute returns value' do
expect(element.attribute(prop_or_attr)).to eq 'checkbox'
end
end
context 'numeric type' do
let(:element) { driver.find_element(id: 'withText') }
let(:prop_or_attr) { 'rows' }
it '#dom_attribute String' do
expect(element.dom_attribute(prop_or_attr)).to eq '5'
end
it '#property returns Number' do
expect(element.property(prop_or_attr)).to eq 5
end
it '#attribute returns String' do
expect(element.attribute(prop_or_attr)).to eq '5'
end
end
context 'boolean type of true' do
let(:element) { driver.find_element(id: 'checkedchecky') }
let(:prop_or_attr) { 'checked' }
it '#dom_attribute returns String', except: {browser: :safari} do
expect(element.dom_attribute(prop_or_attr)).to eq 'true'
end
it '#property returns true' do
expect(element.property(prop_or_attr)).to eq true
end
it '#attribute returns String' do
expect(element.attribute(prop_or_attr)).to eq 'true'
end
it '#dom_attribute does not update after click', except: {browser: :safari} do
element.click
expect(element.dom_attribute(prop_or_attr)).to eq 'true'
end
it '#property updates to false after click' do
element.click
expect(element.property(prop_or_attr)).to eq false
end
it '#attribute updates to nil after click' do
element.click
expect(element.attribute(prop_or_attr)).to eq nil
end
end
context 'boolean type of false' do
let(:element) { driver.find_element(id: 'checky') }
let(:prop_or_attr) { 'checked' }
it '#dom_attribute returns nil' do
expect(element.dom_attribute(prop_or_attr)).to be_nil
end
it '#property returns false' do
expect(element.property(prop_or_attr)).to eq false
end
it '#attribute returns nil' do
expect(element.attribute(prop_or_attr)).to be_nil
end
it '#dom_attribute does not update after click' do
element.click
expect(element.dom_attribute(prop_or_attr)).to eq nil
end
it '#property updates to true after click' do
element.click
expect(element.property(prop_or_attr)).to eq true
end
it '#attribute updates to String after click' do
element.click
expect(element.attribute(prop_or_attr)).to eq 'true'
end
end
context 'property exists but attribute does not' do
let(:element) { driver.find_element(id: 'withText') }
let(:prop_or_attr) { 'value' }
it '#dom_attribute returns nil' do
expect(element.dom_attribute(prop_or_attr)).to be_nil
end
it '#property returns default property' do
expect(element.property(prop_or_attr)).to eq 'Example text'
end
it '#attribute returns default property' do
expect(element.attribute(prop_or_attr)).to eq 'Example text'
end
it '#property returns updated property' do
element.clear
expect(element.property(prop_or_attr)).to be_empty
end
it '#attribute returns updated property' do
element.clear
expect(element.attribute(prop_or_attr)).to be_empty
end
end
context 'attribute exists but property does not' do
let(:element) { driver.find_element(id: 'vsearchGadget') }
let(:prop_or_attr) { 'accesskey' }
it '#dom_attribute returns attribute' do
expect(element.dom_attribute(prop_or_attr)).to eq '4'
end
it '#property returns nil' do
expect(element.property(prop_or_attr)).to be_nil
end
it '#attribute returns attribute' do
expect(element.attribute(prop_or_attr)).to eq '4'
end
end
context 'neither attribute nor property exists' do
let(:element) { driver.find_element(id: 'checky') }
let(:prop_or_attr) { 'nonexistent' }
it '#dom_attribute returns nil' do
expect(element.dom_attribute(prop_or_attr)).to be_nil
end
it '#property returns nil' do
expect(element.property(prop_or_attr)).to be_nil
end
it '#attribute returns nil' do
expect(element.attribute(prop_or_attr)).to be_nil
end
end
context 'style' do
before { driver.navigate.to url_for('clickEventPage.html') }
let(:element) { driver.find_element(id: 'result') }
let(:prop_or_attr) { 'style' }
it '#dom_attribute attribute with no formatting' do
expect(element.dom_attribute(prop_or_attr)).to eq 'width:300;height:60'
end
# TODO: This might not be correct behavior
it '#property returns object',
except: [{browser: :firefox,
reason: 'https://github.com/mozilla/geckodriver/issues/1846'},
{browser: :safari}] do
expect(element.property(prop_or_attr)).to eq %w[width height]
end
it '#attribute returns attribute with formatting' do
expect(element.attribute(prop_or_attr)).to eq 'width: 300px; height: 60px;'
end
end
context 'incorrect casing' do
let(:element) { driver.find_element(id: 'checky') }
let(:prop_or_attr) { 'nAme' }
it '#dom_attribute returns correctly cased attribute' do
expect(element.dom_attribute(prop_or_attr)).to eq 'checky'
end
it '#property returns nil' do
expect(element.property(prop_or_attr)).to be_nil
end
it '#attribute returns correctly cased attribute' do
expect(element.attribute(prop_or_attr)).to eq 'checky'
end
end
context 'property attribute case difference with attribute casing' do
let(:element) { driver.find_element(name: 'readonly') }
let(:prop_or_attr) { 'readonly' }
it '#dom_attribute returns a String', except: {browser: :safari} do
expect(element.dom_attribute(prop_or_attr)).to eq 'true'
end
it '#property returns nil' do
expect(element.property(prop_or_attr)).to be_nil
end
it '#attribute returns a String' do
expect(element.attribute(prop_or_attr)).to eq 'true'
end
end
context 'property attribute case difference with property casing' do
let(:element) { driver.find_element(name: 'readonly') }
let(:prop_or_attr) { 'readOnly' }
it '#dom_attribute returns a String',
except: [{browser: :firefox,
reason: 'https://github.com/mozilla/geckodriver/issues/1850'},
{browser: :safari}] do
expect(element.dom_attribute(prop_or_attr)).to eq 'true'
end
it '#property returns property as true' do
expect(element.property(prop_or_attr)).to eq true
end
it '#attribute returns property as String' do
expect(element.attribute(prop_or_attr)).to eq 'true'
end
end
context 'property attribute name difference with attribute naming' do
let(:element) { driver.find_element(id: 'wallace') }
let(:prop_or_attr) { 'class' }
it '#dom_attribute returns attribute value' do
expect(element.dom_attribute(prop_or_attr)).to eq 'gromit'
end
it '#property returns nil' do
expect(element.property(prop_or_attr)).to be_nil
end
it '#attribute returns attribute value' do
expect(element.attribute(prop_or_attr)).to eq 'gromit'
end
end
context 'property attribute name difference with property naming' do
let(:element) { driver.find_element(id: 'wallace') }
let(:prop_or_attr) { 'className' }
it '#dom_attribute returns nil' do
expect(element.dom_attribute(prop_or_attr)).to be_nil
end
it '#property returns property value' do
expect(element.property(prop_or_attr)).to eq 'gromit'
end
it '#attribute returns property value' do
expect(element.attribute(prop_or_attr)).to eq 'gromit'
end
end
context 'property attribute value difference' do
let(:element) { driver.find_element(tag_name: 'form') }
let(:prop_or_attr) { 'action' }
it '#dom_attribute returns attribute value' do
expect(element.dom_attribute(prop_or_attr)).to eq 'resultPage.html'
end
it '#property returns property value' do
expect(element.property(prop_or_attr)).to match(%r{http://(.+)/resultPage\.html})
end
it '#attribute returns property value' do
expect(element.attribute(prop_or_attr)).to match(%r{http://(.+)/resultPage\.html})
end
end
end
it 'returns ARIA role', only: {browser: %i[chrome edge]} do
driver.navigate.to "data:text/html," \
"<div role='heading' aria-level='1'>Level 1 Header</div>" \
"<h1>Level 1 Header</h1>" \
"<h2 role='alert'>Level 2 Header</h2>"
expect(driver.find_element(tag_name: 'div').aria_role).to eq('heading')
expect(driver.find_element(tag_name: 'h1').aria_role).to eq('heading')
expect(driver.find_element(tag_name: 'h2').aria_role).to eq('alert')
end
it 'returns accessible name', only: {browser: %i[chrome edge]} do
driver.navigate.to "data:text/html,<h1>Level 1 Header</h1>"
expect(driver.find_element(tag_name: 'h1').accessible_name).to eq('Level 1 Header')
end
it 'should clear' do
driver.navigate.to url_for('formPage.html')
expect { driver.find_element(id: 'withText').clear }.not_to raise_error
end
it 'should get and set selected' do
driver.navigate.to url_for('formPage.html')
cheese = driver.find_element(id: 'cheese')
peas = driver.find_element(id: 'peas')
cheese.click
expect(cheese).to be_selected
expect(peas).not_to be_selected
peas.click
expect(peas).to be_selected
expect(cheese).not_to be_selected
end
it 'should get enabled' do
driver.navigate.to url_for('formPage.html')
expect(driver.find_element(id: 'notWorking')).not_to be_enabled
end
it 'should get text' do
driver.navigate.to url_for('xhtmlTest.html')
expect(driver.find_element(class: 'header').text).to eq('XHTML Might Be The Future')
end
it 'should get displayed' do
driver.navigate.to url_for('xhtmlTest.html')
expect(driver.find_element(class: 'header')).to be_displayed
end
context 'size and location' do
it 'should get current location' do
driver.navigate.to url_for('xhtmlTest.html')
loc = driver.find_element(class: 'header').location
expect(loc.x).to be >= 1
expect(loc.y).to be >= 1
end
it 'should get location once scrolled into view' do
driver.navigate.to url_for('javascriptPage.html')
loc = driver.find_element(id: 'keyUp').location_once_scrolled_into_view
expect(loc.x).to be >= 1
expect(loc.y).to be >= 0 # can be 0 if scrolled to the top
end
it 'should get size' do
driver.navigate.to url_for('xhtmlTest.html')
size = driver.find_element(class: 'header').size
expect(size.width).to be_positive
expect(size.height).to be_positive
end
it 'should get rect' do
driver.navigate.to url_for('xhtmlTest.html')
rect = driver.find_element(class: 'header').rect
expect(rect.x).to be_positive
expect(rect.y).to be_positive
expect(rect.width).to be_positive
expect(rect.height).to be_positive
end
end
# IE - https://github.com/SeleniumHQ/selenium/pull/4043
it 'should drag and drop', except: {browser: :ie} do
driver.navigate.to url_for('dragAndDropTest.html')
img1 = driver.find_element(id: 'test1')
img2 = driver.find_element(id: 'test2')
driver.action.drag_and_drop_by(img1, 100, 100)
.drag_and_drop(img2, img1)
.perform
expect(img1.location).to eq(img2.location)
end
it 'should get css property' do
driver.navigate.to url_for('javascriptPage.html')
element = driver.find_element(id: 'green-parent')
style1 = element.css_value('background-color')
style2 = element.style('background-color') # backwards compatibility
acceptable = ['rgb(0, 128, 0)', '#008000', 'rgba(0,128,0,1)', 'rgba(0, 128, 0, 1)']
expect(acceptable).to include(style1, style2)
end
it 'should know when two elements are equal' do
driver.navigate.to url_for('simpleTest.html')
body = driver.find_element(tag_name: 'body')
xbody = driver.find_element(xpath: '//body')
jsbody = driver.execute_script('return document.getElementsByTagName("body")[0]')
expect(body).to eq(xbody)
expect(body).to eq(jsbody)
expect(body).to eql(xbody)
expect(body).to eql(jsbody)
end
it 'should know when element arrays are equal' do
driver.navigate.to url_for('simpleTest.html')
tags = driver.find_elements(tag_name: 'div')
jstags = driver.execute_script('return document.getElementsByTagName("div")')
expect(tags).to eq(jstags)
end
it 'should know when two elements are not equal' do
driver.navigate.to url_for('simpleTest.html')
elements = driver.find_elements(tag_name: 'p')
p1 = elements.fetch(0)
p2 = elements.fetch(1)
expect(p1).not_to eq(p2)
expect(p1).not_to eql(p2)
end
it 'should return the same #hash for equal elements when found by Driver#find_element' do
driver.navigate.to url_for('simpleTest.html')
body = driver.find_element(tag_name: 'body')
xbody = driver.find_element(xpath: '//body')
expect(body.hash).to eq(xbody.hash)
end
it 'should return the same #hash for equal elements when found by Driver#find_elements' do
driver.navigate.to url_for('simpleTest.html')
body = driver.find_elements(tag_name: 'body').fetch(0)
xbody = driver.find_elements(xpath: '//body').fetch(0)
expect(body.hash).to eq(xbody.hash)
end
end
end # WebDriver
end # Selenium