button handler not getting called in jquery/jasmine -
my code working fine on browser not when use jasmine. fails unit test set up.
i have form button.
<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>
i have set handler button in app.js inside function
learnjs.problemview = function(data) { var view = $('.templates .problem-view').clone(); function checkanswerclick(){ console.log('checking answer'); if(checkanswer()){ console.log('setting correct'); resultflash.text('correct!'); }else{ console.log('setting incorrect'); resultflash.text('incorrect!'); } return false; } console.log('inside pv') var b = view.find('.check-btn'); b.click(checkanswerclick); }
from jasmine, calling click method not getting working. not see console print console.log('checking answer');
see error in browser expected '' equal 'correct!'
. because <p>
should set either correct
or incorrect
empty!
describe ('answer section',function() { it('can check correct answer hitting 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 '+v1.val()); console.log('b1 '+b1.html()); var r =view1.find('.result'); console.log('r '+r.text()); spyon(learnjs,'checkanswerclick'); expect(view1.find('.result').text()).toequal('correct!'); expect(learnjs.problemview.checkanswerclick).tohavebeencalled(); });
added more explanation
on browser, files used public/index.html , public/app.js. jasmine, have helper function, spechelper.js copies content of public/index.html public/test/index.html because jasmine uses public/test/index.html think (still learning stuff)
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 "+fixture.html()); $('body').append(fixture.clone(true, true)); } else { //console.log("3. fixture "+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 looks likes this. basically, body of index.html gets changed call resetfixture in beforeeach (defined above) in spechelper.js
<!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>
so before running each spec, contents public/index.html should copied public/test/index.html , there, new view should created. specs defined in app_spec.js used jasmine run test cases. 1 of test cases described above
i guessing view1 should cloned fixture along event handlers (because using clone (true, true). view1 available in app_spec.js , b1.click should work. note expect(learnjs.problemview.checkanswerclick).tohavebeencalled();
fails indicating click's callback not getting called.
errors in browser:
- expected '' equal 'correct!'.
- expected spy, got undefined. <-- maybe using spy incorrectly
this new describe
solved problem. see comments below.
describe('problem view', function() { var view1; beforeeach(function () { view1 = learnjs.problemview('1'); //this registering click event callback. had call this. wasn't doing earlier }); describe ('answer section',function() { it('can check correct answer hitting button', function(){ console.log("in - 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 '+v1.val()); console.log('b1 '+b1.html()); console.log("2nd events: "+$._data($("#b"),'events')); var r =view1.find('.result'); console.log('r '+r.text()); //spyon(learnjs,'learnjs.problemview.checkanswerclick'); expect(view1.find('.result').text()).toequal('correct!'); //expect(learnjs.problemview.checkanswerclick).tohavebeencalled(); });
i think can try change html code
<button class='button-primary check-btn'>check answer</button>
into
<button class='button-primary check-btn' type='button'>check answer</button>
because <button></button>
in <form></form>
auto set type='submit'
if don't set type='button'
.and auto submit form , refresh page default.
maybe reason why can't see 'checking answer' in console.
i tried code in local enviroment
<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 correct'); resultflash.text('correct!'); }else{ console.log('setting 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 hitting button', function(){ var v = view.find('.answer').val('true'); console.log('clicking'); var b = view.find('.check-btn').click(); console.log('v '+v.html()); console.log('b '+b.html()); var r =view.find('.result'); console.log('r '+r.text()); expect(view.find('.result').text()).toequal('correct!'); }); }) </script> </body>
although code throw error checkanswer not defined
, can see checking answer
in console. think reason can't trigger click event variable view
declare in function problemview
not same use in function describe
.
i think problem
var $dom1 = $('.templates .problem-view').clone(true, true); var $dom2 = $('.templates .problem-view').clone(true, true);
$dom1
, $dom2
totally 2 different objects.
i can't understand why bind event on cloned dom instead of binding event directly on original dom this:
learnjs.problemview = function(data) { var view = $('.templates .problem-view');// remove .clone() function checkanswerclick(){ console.log('checking answer'); if(checkanswer()){ console.log('setting correct'); resultflash.text('correct!'); }else{ console.log('setting incorrect'); resultflash.text('incorrect!'); } return false; } console.log('inside pv') var b = view.find('.check-btn'); b.click(checkanswerclick); }
Comments
Post a Comment