2017-08-15 23 views
0

我的代码在浏览器上正常工作,但在使用Jasmine时没有问题。这会导致我的单元测试失败。在jquery/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); 
} 

内从茉莉,我打电话到其点击的方法,但它是没有得到工作。我没有看到控制台打印console.log('checking answer');我在浏览器中看到错误Expected '' to equal 'Correct!'。这是因为<p>应设置为CorrectIncorrect,但它是空的!

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(); 
    }); 

增加了更多的解释

上的浏览器,将被使用的文件是公开/ index.html,然后公共/ app.js。对于Jasmine,我有一个帮助函数SpecHelper.js,它将public/index.html的内容复制到public/test/index.html中,因为茉莉花使用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()); 
}); 

公共/测试/ index.html的看起来喜欢这一点。基本上,这个index.html的身体得到由呼叫SpecHelper.js改为resetFixture在beforeEach(如上所述)

<!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> 

所以每次运行前规范,公共/ index.html的内容应该被复制到public/test/index.html,然后从那里创建一个新视图。规范在app_spec.js中定义,Jasmine使用它来运行测试用例。其中一个测试用例如上所述

我猜测view1应该从夹具一起克隆以及事件处理程序(因为我现在使用的是clone(true,true)。该view1可在app_spec.js和b1 。点击应在浏览器中运行需要注意的是expect(learnjs.problemView.checkAnswerClick).toHaveBeenCalled();也失败,表明该点的回调是没有得到所谓的

错误:。

  1. 预计'等于“正确的”
  2. 预计间谍! ,但得到了undefined。< - 也许我正在使用间谍正确

这是新的describe解决了这个问题。请参阅下面的评论。

describe('problem view', function() { 
     var view1; 
     beforeEach(function() { 
      view1 = learnjs.problemView('1'); //this is where I am registering the click event callback. I had to call this. I wasn't doing so earlier 
     }); 

     describe ('answer section',function() { 

      it('can check correct answer by hitting a button', function(){ 
       console.log("in It - view1:"+view1.html()) 
       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(learnjs.problemView.checkAnswerClick); 
       b1.click(); 
       console.log('v1 is '+v1.val()); 
       console.log('b1 is '+b1.html()); 
       console.log("2nd events: "+$._data($("#b"),'events')); 
       var r =view1.find('.result'); 
       console.log('r is '+r.text()); 
       //spyOn(learnjs,'learnjs.problemView.checkAnswerClick'); 
       expect(view1.find('.result').text()).toEqual('Correct!'); 
       //expect(learnjs.problemView.checkAnswerClick).toHaveBeenCalled(); 
      }); 

回答

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',并自动提交m并默认刷新你的页面。

也许这就是为什么你不能在控制台中看到“检查答案”的原因。


我在本地环境

<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。 我认为您甚至无法触发单击事件的原因是您在函数problemView中声明的变量view与您在函数describe中使用的不同。


我认为这个问题是

var $dom1 = $('.templates .problem-view').clone(true, true); 
var $dom2 = $('.templates .problem-view').clone(true, true); 

$dom1$dom2是完全两个不同的对象。

我不明白为什么您可以直接在原始DOM这样的结合对克隆DOM事件,而不是绑定事件:

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); 
} 
+0

没有工作。无论如何,我已经在checkAnswerClick中将表单提交设置为false。这个问题似乎是在执行'b.click();'时checkAnswerClick没有被调用。我甚至将所有的克隆API都改为克隆(true,true),这样所有的事件也都被复制了,但这也不起作用。令人惊讶的是,代码在没有Jasmine的情况下工作 –

+0

@Manu Chadha你可以显示关于你的代码的更多细节吗?我不确定'var view = $('。templates .problem-view')。clone();'你在'learnjs.problemView'与'var b = view.find('。check-btn')。click();'我试着在我的本地并移动'var view = $('。templates .problem -view ')克隆();'。在功能外看起来工作 – MinimalistYing

+0

增加了更多的代码。为了避免混淆,我将'view'改为'view1'。我还加了间谍。我已经验证了'view'不在app_spec.js的范围内。 –

相关问题