Selenium 不执行 javascript
Selenium does not execute javascript
我正在使用以 Selenium 作为驱动程序的水豚。我试图点击一个元素,当点击它时它会显示一个 div,但点击永远不会调用 javascript 来做到这一点。
下面是我的代码
scenario 'currently used transport mode cannot be re-selected' do
expect(page).to have_css("h2.summary")
expect(find('h2.summary').text).to eq("Single event")
expect(page).to have_content("Change journey")
page.click_link("Change journey")
expect(find('#travel-times-preview').visible?).to be_truthy # FAILS here because of previous step not working
end
错误信息
Capybara::ElementNotFound: Unable to find css "#travel-times-preview"
html
<a class="change-journey gray-text" href="#">Change journey</a>
javascript 要执行的代码
$(".change-journey").on("click", function(e){
var target = $(this).data("preview-target");
$('[data-preview-toggle="'+ target +'"]').toggleClass("hidden");
if($(this).text().indexOf('Change journey') > -1){
$(this).text("Close Preview");
}else{
$(this).text("Change journey");
}
e.preventDefault();
});
数据库清理器设置
config.before(:suite) do
if config.use_transactional_fixtures?
raise(<<-MSG)
Delete line `config.use_transactional_fixtures = true` from rails_helper.rb
(or set it to false) to prevent uncommitted transactions being used in
JavaScript-dependent specs.
During testing, the Ruby app server that the JavaScript browser driver
connects to uses a different database connection to the database connection
used by the spec.
This Ruby app server database connection would not be able to see data that
has been setup by the spec's database connection inside an uncommitted
transaction.
Disabling the use_transactional_fixtures setting helps avoid uncommitted
transactions in JavaScript-dependent specs, meaning that the Ruby app server
database connection can see any data set up by the specs.
MSG
end
end
config.before(:suite) do
DatabaseCleaner.clean_with(:truncation)
end
config.before(:each) do
DatabaseCleaner.strategy = :transaction
end
config.before(:each, type: :feature) do
# :rack_test driver's Rack app under test shares database connection
# with the specs, so we can use transaction strategy for speed.
driver_shares_db_connection_with_specs = Capybara.current_driver == :rack_test
if driver_shares_db_connection_with_specs
DatabaseCleaner.strategy = :transaction
else
# Non-:rack_test driver is probably a driver for a JavaScript browser
# with a Rack app under test that does *not* share a database
# connection with the specs, so we must use truncation strategy.
DatabaseCleaner.strategy = :truncation
end
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
虽然我可以看到 link 被点击,但底层的 javascript 没有被执行。
假设您已经查看了打开的 firefox window 中的开发控制台并且没有 JS 错误,您所看到的行为有几个潜在的原因,none其中与 e.preventDefault()
有关(当你听到马蹄声时会想到马,而不是斑马)
您显示的 link 没有 data-preview-target
属性,因此点击处理程序没有任何内容可读取并附加到 data-preview-toggle=
,因此没有任何内容切换。数据可能是由您应用中的其他 JS 添加的,因此被设置为 属性 而不是 HTML 中的属性(或者您只是选择将该细节从您显示的元素中删除) 移动到 #2
您的 .on
JS 代码在元素存在之前 运行ning,因此没有附加。当它将所有 JS 连接到一个文件中时,这可能会在测试模式下显示出来,因为 JS 的加载速度比在开发模式下发出多个请求时更快。这将显示为 link 文本未更改,因为点击处理程序根本不是 运行。如果是这种情况,请延迟附加侦听器,直到加载 DOM。
这是你写的第一个JS支持测试,hidden/shown的元素是从数据库记录生成的,你还没有禁用事务测试and/or配置database_cleaner 正确。这会导致您在测试中创建的对象实际上在您的应用程序中不可见,因此您期望出现在页面上的元素实际上并不存在。您可以通过暂停测试并查看 HTML 来验证它是否确实在页面上。
根据您提供的错误,这不是问题的原因,只是为了答案的完整性添加:click_link
点击 link 和 returns 立即地。这意味着测试继续 运行ning 而点击触发的动作继续。这可能会导致您的代码中出现竞争条件(如果您设置了 Capybara.ignore_hidden_elements = false
- 坏主意),您的代码会在其中找到元素并在更改之前检查其可见性。因此,您的最后一步应该写成如下所示,因为它将 wait/retry 使元素变得可见
expect(page).to have_css('#travel-times-preview', visible: true)
顺便说一句,使用 Capybara 提供的功能可以改进和加速您的测试代码
scenario 'currently used transport mode cannot be re-selected' do
expect(page).to have_css("h2.summary", text: "Single event") # do it in one query
page.click_link("Change journey") # click_link will find the content anyway so no need to check for it before
expect(page).to have_css('#travel-times-preview') # By default Capybara only finds visible elements so checking visibility is pointeless, if you've changed that default see #4
end
我正在使用以 Selenium 作为驱动程序的水豚。我试图点击一个元素,当点击它时它会显示一个 div,但点击永远不会调用 javascript 来做到这一点。
下面是我的代码
scenario 'currently used transport mode cannot be re-selected' do
expect(page).to have_css("h2.summary")
expect(find('h2.summary').text).to eq("Single event")
expect(page).to have_content("Change journey")
page.click_link("Change journey")
expect(find('#travel-times-preview').visible?).to be_truthy # FAILS here because of previous step not working
end
错误信息
Capybara::ElementNotFound: Unable to find css "#travel-times-preview"
html
<a class="change-journey gray-text" href="#">Change journey</a>
javascript 要执行的代码
$(".change-journey").on("click", function(e){
var target = $(this).data("preview-target");
$('[data-preview-toggle="'+ target +'"]').toggleClass("hidden");
if($(this).text().indexOf('Change journey') > -1){
$(this).text("Close Preview");
}else{
$(this).text("Change journey");
}
e.preventDefault();
});
数据库清理器设置
config.before(:suite) do
if config.use_transactional_fixtures?
raise(<<-MSG)
Delete line `config.use_transactional_fixtures = true` from rails_helper.rb
(or set it to false) to prevent uncommitted transactions being used in
JavaScript-dependent specs.
During testing, the Ruby app server that the JavaScript browser driver
connects to uses a different database connection to the database connection
used by the spec.
This Ruby app server database connection would not be able to see data that
has been setup by the spec's database connection inside an uncommitted
transaction.
Disabling the use_transactional_fixtures setting helps avoid uncommitted
transactions in JavaScript-dependent specs, meaning that the Ruby app server
database connection can see any data set up by the specs.
MSG
end
end
config.before(:suite) do
DatabaseCleaner.clean_with(:truncation)
end
config.before(:each) do
DatabaseCleaner.strategy = :transaction
end
config.before(:each, type: :feature) do
# :rack_test driver's Rack app under test shares database connection
# with the specs, so we can use transaction strategy for speed.
driver_shares_db_connection_with_specs = Capybara.current_driver == :rack_test
if driver_shares_db_connection_with_specs
DatabaseCleaner.strategy = :transaction
else
# Non-:rack_test driver is probably a driver for a JavaScript browser
# with a Rack app under test that does *not* share a database
# connection with the specs, so we must use truncation strategy.
DatabaseCleaner.strategy = :truncation
end
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
虽然我可以看到 link 被点击,但底层的 javascript 没有被执行。
假设您已经查看了打开的 firefox window 中的开发控制台并且没有 JS 错误,您所看到的行为有几个潜在的原因,none其中与 e.preventDefault()
有关(当你听到马蹄声时会想到马,而不是斑马)
您显示的 link 没有
data-preview-target
属性,因此点击处理程序没有任何内容可读取并附加到data-preview-toggle=
,因此没有任何内容切换。数据可能是由您应用中的其他 JS 添加的,因此被设置为 属性 而不是 HTML 中的属性(或者您只是选择将该细节从您显示的元素中删除) 移动到 #2您的
.on
JS 代码在元素存在之前 运行ning,因此没有附加。当它将所有 JS 连接到一个文件中时,这可能会在测试模式下显示出来,因为 JS 的加载速度比在开发模式下发出多个请求时更快。这将显示为 link 文本未更改,因为点击处理程序根本不是 运行。如果是这种情况,请延迟附加侦听器,直到加载 DOM。这是你写的第一个JS支持测试,hidden/shown的元素是从数据库记录生成的,你还没有禁用事务测试and/or配置database_cleaner 正确。这会导致您在测试中创建的对象实际上在您的应用程序中不可见,因此您期望出现在页面上的元素实际上并不存在。您可以通过暂停测试并查看 HTML 来验证它是否确实在页面上。
根据您提供的错误,这不是问题的原因,只是为了答案的完整性添加:
click_link
点击 link 和 returns 立即地。这意味着测试继续 运行ning 而点击触发的动作继续。这可能会导致您的代码中出现竞争条件(如果您设置了Capybara.ignore_hidden_elements = false
- 坏主意),您的代码会在其中找到元素并在更改之前检查其可见性。因此,您的最后一步应该写成如下所示,因为它将 wait/retry 使元素变得可见expect(page).to have_css('#travel-times-preview', visible: true)
顺便说一句,使用 Capybara 提供的功能可以改进和加速您的测试代码
scenario 'currently used transport mode cannot be re-selected' do
expect(page).to have_css("h2.summary", text: "Single event") # do it in one query
page.click_link("Change journey") # click_link will find the content anyway so no need to check for it before
expect(page).to have_css('#travel-times-preview') # By default Capybara only finds visible elements so checking visibility is pointeless, if you've changed that default see #4
end