poltergeist 似乎没有等待 phantomjs 在水豚中加载
poltergeist doesn't seem to wait for phantomjs to load in capybara
我正在尝试使用 Capybara、Selenium、Capybara/webkit 和 Poltergeist 进行一些 rspec 测试 运行。在某些情况下,我需要它 运行 无头,并且宁愿不使用 xvfb 来让 webkit 工作。我可以使用 selenium 或 poltergeist 作为 phantomjs 的 driver。我遇到的问题是我的测试 运行 使用 selenium 和 firefox 或 chrome 很好,但是当我尝试 phantomjs 时,元素总是显示为未找到。在研究了一段时间并在水豚中使用 page.save_screenshot 后,我发现当 driver 告诉它查找元素时 phantomjs 浏览器没有加载,所以它没有返回任何东西。通过编辑 /capybara/poltergeist/driver.rb 中的 poltergeist 源代码,我能够修复此问题
def visit(url)
if @started
sleep_time = 0
else
sleep_time = 2
end
@started = true
browser.visit(url)
sleep sleep_time
end
这显然不是问题的理想解决方案,它不适用于 selenium 作为 phantomjs 的 driver。无论如何我可以告诉 driver 等待幻影准备好吗?
更新:
通过更改包含 Capybara::DSL 的位置,我能够将其设置为 运行。我将它添加到 RSpec.configure 块中,如下所示。
RSpec.configure do |config|
config.include Capybara::DSL
然后我将页面 object 传递给我创建的所有 classes 以与网页 ui 交互。
示例 class 现在看起来像这样
module LoginUI
require_relative 'webpage'
class LoginPage < WebPages::Pages
def initialize(page, values = {})
super(page)
end
def visit
browser.visit(login_url)
end
def login(username, password)
set_username(username)
set_password(password)
sign_in_button
end
def set_username(username)
edit = browser.find_element(@selectors[:login_edit])
edit.send_keys(username)
end
def set_password(password)
edit = browser.find_element(@selectors[:password_edit])
edit.send_keys(password)
end
def sign_in_button
browser.find_element(@selectors[:sign_in_button]).click
end
end
end
网页模块是这样的
module WebPages
require_relative 'browser'
class Pages
def initialize(page)
@page = page
@browser = Browser::Browser.new
end
def browser
@browser
end
def sign_out
browser.visit(sign_out_url)
end
end
end
浏览器模块如下所示
module Browser
class Browser
include Capybara::DSL
def refresh_page
page.evaluate_script("window.location.reload()")
end
def submit(locator)
find_element(locator).click
end
def find_element(hash)
page.find(hash.keys.first, hash.values.first)
end
def find_elements(hash)
page.find(hash.keys.first, hash.values.first, match: :first)
page.all(hash.keys.first, hash.values.first)
end
def current_url
return page.current_url
end
end
end
虽然这可行,但我不想在 RSpec 中包含 Capybara::DSL 或在 class 中包含页面 object。这些 classes 已经为示例删除了一些内容,但显示了一般结构。理想情况下,我希望浏览器模块包含 Capybara::DSL 并能够处理与 Capybara 的所有交互。
Capybara 不依赖于访问是否已完成,相反,查找器和匹配器将在指定的时间段内重试,直到成功。您可以通过增加 Capybara.default_max_wait_time
的值来增加此时间量。默认情况下不等待的唯一方法是 first
和 all
,但可以通过指定任何计数选项
使其变为 wait/retry
first('.some_class', minimum: 1) # will wait up to Capybara.default_max_wait_time seconds for the element to exist on the page.
尽管您应该尽可能选择 find
而不是 first/all
如果增加最长等待时间不能解决您的问题,请为您的问题添加一个失败的测试示例。
你的更新完全改变了问题,所以我添加了第二个答案。如果您不从浏览器外部调用任何 Capybara 方法 class,则无需在 RSpec 配置中包含 Capybara::DSL,就像不需要传递 [=27] =] 如果您将所有 Capybara 交互限制在您的浏览器中 class,则所有页面 classes。需要注意的一件事是,Capybara::DSL 提供的 page
方法只是 Capybara.current_session
的别名,因此从技术上讲,您总是可以调用它。
您没有在代码中显示您如何处理页面内容上的任何 assertions/expectations - 因此根据您的处理方式,您可能需要在您的代码中包含 Capybara::RSpecMatchers
RSpec 配置 and/or 你的 WebPages::Pages class。
您的示例代码有几个问题会立即弹出,首先您的 Browser#find_elements
(假设我正在阅读您的意图是首先正确地使用 find
)可能只是
def find_elements(hash)
page.all(hash.keys.first, hash.values.first, minimum: 1)
end
其次,您的 LoginPage#login
方法在视觉变化上应该有一个 assertion/expectation 作为它的最后一行,表明登录成功(验证一些消息是 displayed/logged 在菜单存在/等等) ,以确保浏览器在测试继续之前已收到身份验证 cookie 等。该行的外观取决于您如何构建您的期望。
如果这不能回答您的问题,请提供一个具体示例说明什么对您不起作用,因为您显示的代码的 none 表明需要 Capybara::DSL被包含在你说你不想要它的任何一个地方。
我正在尝试使用 Capybara、Selenium、Capybara/webkit 和 Poltergeist 进行一些 rspec 测试 运行。在某些情况下,我需要它 运行 无头,并且宁愿不使用 xvfb 来让 webkit 工作。我可以使用 selenium 或 poltergeist 作为 phantomjs 的 driver。我遇到的问题是我的测试 运行 使用 selenium 和 firefox 或 chrome 很好,但是当我尝试 phantomjs 时,元素总是显示为未找到。在研究了一段时间并在水豚中使用 page.save_screenshot 后,我发现当 driver 告诉它查找元素时 phantomjs 浏览器没有加载,所以它没有返回任何东西。通过编辑
def visit(url)
if @started
sleep_time = 0
else
sleep_time = 2
end
@started = true
browser.visit(url)
sleep sleep_time
end
这显然不是问题的理想解决方案,它不适用于 selenium 作为 phantomjs 的 driver。无论如何我可以告诉 driver 等待幻影准备好吗?
更新:
通过更改包含 Capybara::DSL 的位置,我能够将其设置为 运行。我将它添加到 RSpec.configure 块中,如下所示。
RSpec.configure do |config|
config.include Capybara::DSL
然后我将页面 object 传递给我创建的所有 classes 以与网页 ui 交互。
示例 class 现在看起来像这样
module LoginUI
require_relative 'webpage'
class LoginPage < WebPages::Pages
def initialize(page, values = {})
super(page)
end
def visit
browser.visit(login_url)
end
def login(username, password)
set_username(username)
set_password(password)
sign_in_button
end
def set_username(username)
edit = browser.find_element(@selectors[:login_edit])
edit.send_keys(username)
end
def set_password(password)
edit = browser.find_element(@selectors[:password_edit])
edit.send_keys(password)
end
def sign_in_button
browser.find_element(@selectors[:sign_in_button]).click
end
end
end
网页模块是这样的
module WebPages
require_relative 'browser'
class Pages
def initialize(page)
@page = page
@browser = Browser::Browser.new
end
def browser
@browser
end
def sign_out
browser.visit(sign_out_url)
end
end
end
浏览器模块如下所示
module Browser
class Browser
include Capybara::DSL
def refresh_page
page.evaluate_script("window.location.reload()")
end
def submit(locator)
find_element(locator).click
end
def find_element(hash)
page.find(hash.keys.first, hash.values.first)
end
def find_elements(hash)
page.find(hash.keys.first, hash.values.first, match: :first)
page.all(hash.keys.first, hash.values.first)
end
def current_url
return page.current_url
end
end
end
虽然这可行,但我不想在 RSpec 中包含 Capybara::DSL 或在 class 中包含页面 object。这些 classes 已经为示例删除了一些内容,但显示了一般结构。理想情况下,我希望浏览器模块包含 Capybara::DSL 并能够处理与 Capybara 的所有交互。
Capybara 不依赖于访问是否已完成,相反,查找器和匹配器将在指定的时间段内重试,直到成功。您可以通过增加 Capybara.default_max_wait_time
的值来增加此时间量。默认情况下不等待的唯一方法是 first
和 all
,但可以通过指定任何计数选项
first('.some_class', minimum: 1) # will wait up to Capybara.default_max_wait_time seconds for the element to exist on the page.
尽管您应该尽可能选择 find
而不是 first/all
如果增加最长等待时间不能解决您的问题,请为您的问题添加一个失败的测试示例。
你的更新完全改变了问题,所以我添加了第二个答案。如果您不从浏览器外部调用任何 Capybara 方法 class,则无需在 RSpec 配置中包含 Capybara::DSL,就像不需要传递 [=27] =] 如果您将所有 Capybara 交互限制在您的浏览器中 class,则所有页面 classes。需要注意的一件事是,Capybara::DSL 提供的 page
方法只是 Capybara.current_session
的别名,因此从技术上讲,您总是可以调用它。
您没有在代码中显示您如何处理页面内容上的任何 assertions/expectations - 因此根据您的处理方式,您可能需要在您的代码中包含 Capybara::RSpecMatchers
RSpec 配置 and/or 你的 WebPages::Pages class。
您的示例代码有几个问题会立即弹出,首先您的 Browser#find_elements
(假设我正在阅读您的意图是首先正确地使用 find
)可能只是
def find_elements(hash)
page.all(hash.keys.first, hash.values.first, minimum: 1)
end
其次,您的 LoginPage#login
方法在视觉变化上应该有一个 assertion/expectation 作为它的最后一行,表明登录成功(验证一些消息是 displayed/logged 在菜单存在/等等) ,以确保浏览器在测试继续之前已收到身份验证 cookie 等。该行的外观取决于您如何构建您的期望。
如果这不能回答您的问题,请提供一个具体示例说明什么对您不起作用,因为您显示的代码的 none 表明需要 Capybara::DSL被包含在你说你不想要它的任何一个地方。