我的代码在浏览器上工作正常但在我使用Jasmine时却没有。这使我的单元测试设置失败。
我有一个带按钮的表格。
<div class="templates">
<div class="problem-view">
<h3 class="title"></h3>
<p data-name="description"></p>
<pre><code data-name="code"></code></pre>
<form>
<textarea class='u-full-width answer'></textarea>
<div>
<button class='button-primary check-btn'>Check Answer</button>
<p class='result'></p>
</div>
</form>
</div>
</div>
</div>
我在函数
中为app.js中的按钮设置了处理程序learnjs.problemView = function(data) {
var view = $('.templates .problem-view').clone();
function checkAnswerClick(){
console.log('checking answer');
if(checkAnswer()){
console.log('setting to correct');
resultFlash.text('Correct!');
}else{
console.log('setting to incorrect');
resultFlash.text('Incorrect!');
}
return false;
}
console.log('inside pv')
var b = view.find('.check-btn');
b.click(checkAnswerClick);
}
从Jasmine,我正在调用它的click方法,但它没有开始工作。我没有看到控制台打印console.log('checking answer');
我在浏览器Expected '' to equal 'Correct!'
中看到错误。这是因为<p>
应该设置为Correct
或Incorrect
,但它是空的!
describe ('answer section',function() {
it('can check correct answer by hitting a button', function(){
var v1 = view1.find('.answer').val('true');
console.log('clicking');
var b1 = view1.find('.check-btn');
var b2=$("#b")
console.log("events: b:"+b2.html()+","+$._data($("#b"),"events"));
b1.click();
console.log('v1 is '+v1.val());
console.log('b1 is '+b1.html());
var r =view1.find('.result');
console.log('r is '+r.text());
spyOn(learnjs,'checkAnswerClick');
expect(view1.find('.result').text()).toEqual('Correct!');
expect(learnjs.problemView.checkAnswerClick).toHaveBeenCalled();
});
添加了更多解释
在浏览器上,将使用的文件是public / index.html和public / app.js。对于Jasmine,我有一个帮助函数,SpecHelper.js将public / index.html的内容复制到public / test / index.html,因为jasmine使用public / test / index.html我认为(仍在学习这些东西)
SpecHelper.js
var fixture;
var view1;
function loadFixture(path) {
var html;
var test;
jQuery.ajax({
url: '/index.html',
success: function(result) {
html = result;
},
async: false
});
return $.parseHTML(html);
}
function resetFixture() {
if (!fixture) {
var index = $('<div>').append(loadFixture('/index.html'));
var markup = index.find('div.markup');
console.log("markup :"+markup.html())
fixture = $('<div class="fixture" style="display: none">').append(markup);
console.log("fixture is "+fixture.html());
$('body').append(fixture.clone(true, true));
} else {
//console.log("3. fixture is "+fixture);
$('.fixture').replaceWith(fixture.clone(true, true));
}
}
beforeEach(function () {
resetFixture();
view1 = $('.templates .problem-view').clone(true, true);
console.log("view1:"+view1.html());
});
public / test / index.html看起来像这样。基本上,这个index.html的主体通过在SpecHelper.js中的beforeEach(在上面定义)中调用resetFixture来改变
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Jasmine Spec Runner v2.3.4</title>
<link rel="shortcut icon" type="image/png" href="lib/jasmine-2.3.4/jasmine_favicon.png">
<link rel="stylesheet" type="text/css" href="lib/jasmine-2.3.4/jasmine.css">
<!-- App Dependencies -->
<script src="lib/jquery-2.1.4.js"></script>
<script src="/vendor.js"></script>
<!-- Test libraries -->
<script type="text/javascript" src="lib/jasmine-2.3.4/jasmine.js"></script>
<script type="text/javascript" src="lib/jasmine-2.3.4/jasmine-html.js"></script>
<script type="text/javascript" src="lib/jasmine-2.3.4/boot.js"></script>
<!-- include source files here... -->
<script type="text/javascript" src="/app.js"></script>
<!-- include spec files here... -->
<script type="text/javascript" src="SpecHelper.js"></script>
<script type="text/javascript" src="app_spec.js"></script>
</head>
<body>
</body>
</html>
因此,在运行每个规范之前,public / index.html中的内容应该复制到public / test / index.html,然后从那里创建一个新视图。规范在app_spec.js中定义,Jasmine用它来运行测试用例。其中一个测试用例如上所述
我猜测view1应该从fixture和事件处理程序克隆(因为我现在使用clone(true,true)。这个view1在app_spec.js中可用,b1.click应该可以工作。注意{{ 1}}也失败,表示没有调用click的回调。
浏览器错误:
这是解决问题的新expect(learnjs.problemView.checkAnswerClick).toHaveBeenCalled();
。请参阅以下评论。
describe
答案 0 :(得分:0)
我认为您可以尝试更改HTML代码
<button class='button-primary check-btn'>Check Answer</button>
到
<button class='button-primary check-btn' type='button'>Check Answer</button>
如果您未设置<button></button>
,<form></form>
中的type='submit'
会自动设置type='button'
。并且它会自动提交此表单并默认刷新您的页面。
也许这就是为什么你无法在控制台中看到'检查答案'的原因。
我在我当地的环境中尝试了这段代码
<body>
<div class="templates">
<div class="problem-view">
<h3 class="title"></h3>
<p data-name="description"></p>
<pre><code data-name="code"></code></pre>
<form>
<textarea class='u-full-width answer'></textarea>
<div>
<button class='button-primary check-btn' type="button">Check Answer</button>
<p class='result'></p>
</div>
</form>
</div>
</div>
<script>
var view = $('.templates .problem-view').clone();
problemView = function(data) {
function checkAnswerClick(){
console.log('checking answer');
if(checkAnswer()){
console.log('setting to correct');
resultFlash.text('Correct!');
}else{
console.log('setting to incorrect');
resultFlash.text('Incorrect!');
}
return false;
}
var b = view.find('.check-btn');
console.log(b)
b.click(checkAnswerClick);
}
problemView();
describe ('answer section',function() {
it('can check correct answer by hitting a button', function(){
var v = view.find('.answer').val('true');
console.log('clicking');
var b = view.find('.check-btn').click();
console.log('v is '+v.html());
console.log('b is '+b.html());
var r =view.find('.result');
console.log('r is '+r.text());
expect(view.find('.result').text()).toEqual('Correct!');
});
})
</script>
</body>
虽然此代码会抛出错误checkAnswer is not defined
,但我可以在控制台中看到checking answer
。
我认为您甚至无法触发click事件的原因是您在函数view
中声明的变量problemView
与您在函数describe
中使用的变量var $dom1 = $('.templates .problem-view').clone(true, true);
var $dom2 = $('.templates .problem-view').clone(true, true);
不同。
我认为问题是
$dom1
$dom2
和learnjs.problemView = function(data) {
var view = $('.templates .problem-view');// remove .clone()
function checkAnswerClick(){
console.log('checking answer');
if(checkAnswer()){
console.log('setting to correct');
resultFlash.text('Correct!');
}else{
console.log('setting to incorrect');
resultFlash.text('Incorrect!');
}
return false;
}
console.log('inside pv')
var b = view.find('.check-btn');
b.click(checkAnswerClick);
}
完全是两个不同的对象。
我无法理解为什么你在克隆的Dom上绑定事件而不是直接在原始Dom上绑定事件,如下所示:
1.15.0