我的表单包含delivery_address
输入字段和复选框,可触发AJAX
调用以检索默认地址并填充delivery_address字段。
此功能在浏览器上正常运行!但是当我试图在rspec
上为它编写测试时,它似乎无法正常工作
HTML片段:
<div class="form-group col-lg-12">
<label for="order_delivery_address">Delivery address</label>
<input type="text" name="order[delivery_address]" id="order_delivery_address" class="form-control" required="required" placeholder="Enter a location" autocomplete="off">
<label class="default-address-label">
<input type="checkbox" name="default_address" id="default_address" value="1">
Use my default address
</label>
</div>
JS片段:
var $order_details_form = $('.order-details-form');
var $delivery_address_input = $order_details_form.find('#order_delivery_address');
$order_details_form.find('#default_address').change(function() {
if($(this).is(':checked')){ //checkbox is tick
$.ajax({
type: 'GET',
url: '/order-details/get-user-default-address',
data: {
'userId': $order_details_form.find('#order_user_id').val()
},
dataType: 'json',
success: function(data) {
//populate the delivery address input field with default address
var default_address = data.default_address;
$delivery_address_input.val(default_address);
},
error: function (textStatus, errorThrown) {
//display error message and uncheck the default address checkbox
toastr.error('Error retrieving your default address at the moment. Please try again.');
$order_details_form.find('#default_address').prop('checked', false);
}
});
}
});
Controller snippet:
def get_user_default_address
default_address = User.find(params[:userId]).address.full_address
respond_to do |format|
format.json { render :json => { :default_address => default_address } }
end
end
Rspec片段:
context 'default address' do
let!(:user){ create :user }
let!(:address1){ create :address, user: user}
it 'should proceed with default address selected', js: true do
expect(page.current_path).to eq(order_details_path)
expect(find('#order_user_id', visible: false).value).to eq(user.id.to_s)
expect(page.find('#default_address')).to_not be_checked
check 'default_address'
expect(page.find('#default_address')).to be_checked
expect(page.find('#order_delivery_address').value).to eq address1.full_address
end
end
测试结果在此行expect(page.find('#order_delivery_address').value).to eq address1.full_address
处失败,其中我得到空字符串而不是指示未填充delivery_address字段的地址。
我认为它似乎没有提出AJAX请求,因为我尝试将binding.pry
插入控制器get_user_default_address
,而binding.pry
甚至没有触发。
知道我在这里错过了什么吗?任何帮助将不胜感激!
*注意:我正在使用capybara webkit并且已经正确配置,因为我使用js的其他测试用例成功运行。
答案 0 :(得分:0)
这通常是由三件事之一引起的。
实际上没有使用支持JS的驱动程序进行测试。你声称它运行的是capybara-webkit,它是一个支持JS的驱动程序,而其他测试可以正常使用JS,所以这可能不是问题。
JS中的错误。默认情况下,在开发模式下,每个JS资产都单独加载,但在测试和生产模式下,它们都连接成一个文件以减少请求数。这意味着在处理您的传递地址的JS片段之前连接的任何一个JS资产中的错误都会导致处理程序永远不会被附加。这与capybara-webkit仅支持ES5(没有polyfill / transpiling)的事实相结合意味着你最终可以得到错误&#34;在您的JS中,您在使用let,const,ES5.1 +方法等进行测试的真实浏览器中实际上并不存在错误。您可以通过在capybara-webkit中启用调试模式来查看是否存在此问题,以查看是否显示错误和/或使用selenium和真实浏览器运行以查看问题是否消失。
使用错误的RSpec匹配器。 RSpec提供的check
匹配器不提供任何类型的等待/重试行为。当与事实相结合时,无法保证当Capybaras click
/ eq
/ etc返回意味着您可能会进行各种片状测试/失败时,浏览器中启动的操作所触发的所有副作用都已完成。相反,您应该使用Capybara提供的RSpec匹配器来提供等待/重试行为。作为一般规则,您不应该使用it 'should proceed with default address selected', js: true do
expect(page).to have_current_path(order_details_path) # NEVER use `eq` matcher with current_path
expect(find('#order_user_id', visible: false).value).to eq(user.id.to_s)
expect(page).to have_unchecked_field('default_address') # same as have_field('default_address', checked: false)
check 'default_address'
expect(page).to have_checked_field('default_address')
expect(page).to have_field('order_delivery_address', with: address1.full_address)
end
匹配器来处理页面上的元素。在您的情况下,这将意味着您的测试成为
eq
保留在该测试中的eq
的一次使用是因为Capybara:字段选择器找不到类型&#39;隐藏&#39;的输入。 (我假设#order_user_id是),一旦你在order_details_path上,输入应该已经存在。因此,如果您真的需要验证此输入,这是少数几种使用var http = require("http");
var fs = require('fs');
//var bodyParser = require("body-parser");
//var moment = require("moment");
var options = {
"method" : "GET",
"hostname" : "xxx.xxx.xxx.xxx",
"port" : "18080",
"path" : "/api/v1/applications/"
};
exports.getId = function(callback) {
var req = http.request(options, function (res) {
var chunks = [];
res.on("data", function (chunk) {
chunks.push(chunk);
});
res.on("end", function () {
var body = JSON.parse(Buffer.concat(chunks));
var arrFound = Object.keys(body).filter(function(key) {
if (body[key].name.indexOf("TestName") > -1) {
return body[key].name;
}
}).reduce(function(obj, key){
obj = body[key].id;
return obj;
}, {});;
//console.log("Name: ", arrFound);
callback(null, arrFound));
});
});
req.end();
}
匹配器的情况之一。通常,您不应该担心验证用户在功能测试中看不到的任何内容,因为它是一个实现细节,如果值丢失/错误,它将在验证中显示提交表格的功能。