Rails 3.1,capybara-webkit,如何在链接内执行javascript?
我可以在水豚 click_link('next_page')
的链接中执行 JavaScript 吗?
该链接如下所示:
<a onclick="$('#submit_direction').attr('value', '1');$('#quizForm').submit()" id="next_page" href="#">Next Question</a>
我在 github 的 capybara 上读到,我可以通过单击其提交按钮来提交表单,如下所示:
click_on('Submit Answer')
但是,就我而言,我需要在链接中使用 javascript 提交表单,因此,如何测试里面有javascript的链接? click_link('next_page')
还不够吗?
编辑
设置 :js=> 后 true
我的测试如下所示:
it "should pass when answering all correct", :js=>true do
login_as(student, :scope => :student)
visit ("/student_courses")
#page.execute_script("$('#submit_direction').attr('value', '1');$('#quizForm').submit()")
trace "HTML:------------", page.html
end
Before :js=>是的,我可以正常访问该页面,但是,我发现在 :js=> 之后该页面无法访问是的,这是我访问该页面后收到的错误:
于 2012-01-23 06:29:26 开始获取 127.0.0.1 的“/student_courses” +0200(5010.7ms)更新“学生”设置“last_sign_in_at”=“2012-01-23 04:29:26.274285”,“current_sign_in_at”=“2012-01-23” 04:29:26.274285', "last_sign_in_ip" = '127.0.0.1', “current_sign_in_ip”=“127.0.0.1”,“sign_in_count”= 1,“updated_at” = '2012-01-23 04:29:26.276279' WHERE "students"."id" = 1 SQLite3::BusyException: 数据库被锁定: UPDATE "students" SET “last_sign_in_at”=“2012-01-23 04:29:26.274285”,“current_sign_in_at” = '2012-01-23 04:29:26.274285', "last_sign_in_ip" = '127.0.0.1', "current_sign_in_ip" = '127.0.0.1', "sign_in_count" = 1, "updated_at" = '2012-01-23 04:29:26.276279' 其中 "students"."id" = 1 HTML:------------__ 内部的 服务器错误
内部服务器错误
无法回滚事务 - 正在进行的 SQL 语句 <小时> WEBrick/1.3.1(Ruby/1.9.3/2011-10-30)位于 127.0.0.1:34718
,为什么 SQLite3::BusyException: 数据库现在被锁定?!
Can I execute a javascript in a link with capybara click_link('next_page')
?
The link looks like this:
<a onclick="$('#submit_direction').attr('value', '1');$('#quizForm').submit()" id="next_page" href="#">Next Question</a>
I read at capybara at github that I can submit a form by click at its submit button like this:
click_on('Submit Answer')
But, in my case, I need to submit the form using javascript in a link, so, how to test the link that has javascript inside ? isn't click_link('next_page')
sufficient ?
EDIT
after setting :js=> true
my test looks like this:
it "should pass when answering all correct", :js=>true do
login_as(student, :scope => :student)
visit ("/student_courses")
#page.execute_script("$('#submit_direction').attr('value', '1');$('#quizForm').submit()")
trace "HTML:------------", page.html
end
Before :js=> true, I could visit the page normally, But, I've noticed that the page cannot be visited after :js=> true, here is the error I got after visiting the page:
Started GET "/student_courses" for 127.0.0.1 at 2012-01-23 06:29:26
+0200 (5010.7ms) UPDATE "students" SET "last_sign_in_at" = '2012-01-23 04:29:26.274285', "current_sign_in_at" = '2012-01-23
04:29:26.274285', "last_sign_in_ip" = '127.0.0.1',
"current_sign_in_ip" = '127.0.0.1', "sign_in_count" = 1, "updated_at"
= '2012-01-23 04:29:26.276279' WHERE "students"."id" = 1 SQLite3::BusyException: database is locked: UPDATE "students" SET
"last_sign_in_at" = '2012-01-23 04:29:26.274285', "current_sign_in_at"
= '2012-01-23 04:29:26.274285', "last_sign_in_ip" = '127.0.0.1', "current_sign_in_ip" = '127.0.0.1', "sign_in_count" = 1, "updated_at"
= '2012-01-23 04:29:26.276279' WHERE "students"."id" = 1 HTML:------------__
Internal
Server ErrorInternal Server Error
cannot rollback transaction - SQL statements in progress
WEBrick/1.3.1 (Ruby/1.9.3/2011-10-30) at
127.0.0.1:34718
so, why SQLite3::BusyException: database is locked now ?!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

我刚刚花了8个小时解决类似的问题,并且找到了解决方案。解决办法是如此简单,我可能会哭。
首先,诊断
您收到“
SQLite3::BusyException: 数据库已锁定
”的原因是您正在启动一个异步线程,即表单提交,最终会导致失去测试主线程的“数据库写入”竞赛。实际上,由于您的测试已经完成并且正在运行“每个之后”数据库清理例程(在您的spec_helper中定义),表单操作才刚刚开始尝试运行业务逻辑(这依赖于您的测试之后的数据) :每个钩子都忙着销毁)。如果测试单击 AJAX POST 按钮,然后在没有断言视图更改的情况下终止,则更有可能出现此问题。
第二,修复
事实证明,Capybara 旨在“同步”您的所有请求。但前提是你含蓄地允许它。请注意,提交表单后,水豚不会查看您的页面。因此,它认为您已完成并将数据移出范围(当您的表单提交线程挂在后台时。)
只需将以下代码行添加到测试的末尾,它就会突然起作用:
第三,让它变得漂亮
不要使用execute_script。这就是水豚的用途。但也不要依赖“click_on”,因为它不是一个很好的抽象。你需要对它的内部结构了解太多。相反,请像这样使用 CSS 选择器:
还有一件事 - 您的测试不应该尝试操作 DOM。一个好的 Selenium 测试假设必须遵循普通用户遵循的相同步骤。
结论
I just spent 8 hours resolving a similar issue, and I found the solution. The fix is so simple, I could cry.
First, diagnosis
The reason you're getting "
SQLite3::BusyException: database is locked
" is that you are launching an asynchronous thread, namely a form submission, that ends up losing the "database write" race to your test's main thread. In effect, as your test has already completed and is running your "after each" database cleanup routine (defined in your spec_helper), the form action has only just begun trying to run the business logic (which relies on the data that your test after:each hook is busy destroying).This problem is a lot more likely to occur with tests that click on an AJAX POST button and then terminate without asserting something about the view change.
Second, the fix
As it turns out, Capybara is designed to "synchronize" all your requests. But only if you implicitly let it. Notice that after your form submission, you're not having Capybara look at your page. Therefore it thinks you're done and takes your data out of scope (while your form submission thread is hanging in the background.)
Simply add the following line of code to the end of your test, and it should suddenly work:
Third, make it pretty
Don't use execute_script. That's what Capybara is for. But also don't rely on "click_on" because it's not a great abstraction. You need to know too much about its internals. Instead, use CSS selectors like so:
And one more thing - your test shouldn't try to manipulate the DOM. A good Selenium test assumes to have to follow the same steps a normal user follows.
So in conclusion