2017-08-26 129 views
1

我认真的新手在JavaScript的单元测试,我试图找出如何解决这个问题,这就是情况:我为addEventListener创建了一个新函数来防止使用按键'输入'的所有问题是在Newsletter.js我们正在从html页面获取所有表格,并保存在新值this.terms只能在with编号=“#术语”,但我需要在单元测试中创建所有的表单,我试图为新函数做单元测试,但是...我不知道如何为此单元测试部分,因为在吞咽测试中我有这样的回应:Javascript单元测试addEventListener它不是一个函数

HeadlessChrome 0.0.0 (Mac OS X 10.12.6) Newsletter component specification test somthing FAILED 
    TypeError: Cannot read property 'addEventListener' of null 
     at new Newsletter (app/Resources/assets/enterprise/js/core/components/Newsletter.js:9:1025) 
     at Context.<anonymous> (app/Resources/assets/enterprise/js/test/specs/core/components/Newsletter.spec.js:48:5) 
LOG: Object{querySelectorAll: function() { ... }, querySelector: function (element) { ... }, submit: submit} 
LOG: 'terms' 
LOG: <input id="terms" type="checkbox"> 
HeadlessChrome 0.0.0 (Mac OS X 10.12.6) Newsletter component specification should submit newsletter subscription with female gender FAILED 
    TypeError: this.handler.addEventListener is not a function 
     at new Newsletter (app/Resources/assets/enterprise/js/core/components/Newsletter.js:9:1469) 
     at Context.<anonymous> (app/Resources/assets/enterprise/js/test/specs/core/components/Newsletter.spec.js:73:5) 
     at f (node_modules/sinon-test/dist/sinon-test.js:1:1331) 
     at Context.<anonymous> (node_modules/sinon-test/dist/sinon-test.js:1:1678) 
LOG: Object{querySelectorAll: function() { ... }, querySelector: function (element) { ... }, submit: submit} 
LOG: 'terms' 
LOG: <input id="terms" type="checkbox"> 
HeadlessChrome 0.0.0 (Mac OS X 10.12.6) Newsletter component specification should enabled buttons newsletter when accepted terms and conditions FAILED 
    TypeError: this.handler.addEventListener is not a function 
     at new Newsletter (app/Resources/assets/enterprise/js/core/components/Newsletter.js:9:1469) 
     at Context.<anonymous> (app/Resources/assets/enterprise/js/test/specs/core/components/Newsletter.spec.js:84:5) 
     at f (node_modules/sinon-test/dist/sinon-test.js:1:1331) 
     at Context.<anonymous> (node_modules/sinon-test/dist/sinon-test.js:1:1678) 
LOG: Object{querySelectorAll: function() { ... }, querySelector: function (element) { ... }, submit: submit} 
LOG: 'terms' 
LOG: <input id="terms" type="checkbox"> 
HeadlessChrome 0.0.0 (Mac OS X 10.12.6) Newsletter component specification should enabled buttons newsletter when accepted terms and conditions FAILED 
    TypeError: this.handler.addEventListener is not a function 
     at new Newsletter (app/Resources/assets/enterprise/js/core/components/Newsletter.js:9:1469) 
     at Context.<anonymous> (app/Resources/assets/enterprise/js/test/specs/core/components/Newsletter.spec.js:93:5) 
     at f (node_modules/sinon-test/dist/sinon-test.js:1:1331) 
     at Context.<anonymous> (node_modules/sinon-test/dist/sinon-test.js:1:1678) 
LOG: Object{querySelectorAll: function() { ... }, querySelector: function (element) { ... }, submit: submit} 
LOG: 'terms' 
LOG: <input id="terms" type="checkbox"> 
HeadlessChrome 0.0.0 (Mac OS X 10.12.6) Newsletter component specification should submit newsletter subscription with male gender FAILED 
    TypeError: this.handler.addEventListener is not a function 
     at new Newsletter (app/Resources/assets/enterprise/js/core/components/Newsletter.js:9:1469) 
     at Context.<anonymous> (app/Resources/assets/enterprise/js/test/specs/core/components/Newsletter.spec.js:103:5) 
     at f (node_modules/sinon-test/dist/sinon-test.js:1:1331) 
     at Context.<anonymous> (node_modules/sinon-test/dist/sinon-test.js:1:1678) 
ERROR: 'Exception in queued GPT command', TypeError{} 

所以...说实话我没有想法来解决这个错误,我没有任何单元测试的经验,如果有人能帮我解决这个部分,我会非常感激的,代码是在这里:

footer.twig.html

<form class="col-lg-9 col-md-6 col-sm-12 col-xs-12" action="{{ path('frontend.newsletter.subscribe') }}" method="POST" data-newsletter> 
    <div class="row"> 
    <div class="col-lg-6 col-xs-12"> 
     <input type="email" name="promotional_newsletter_form[email]" placeholder="{{ 'newsletter.subscribe_with_your_email'|trans }}" class="row form-control form-control-sm" /> 
     <div class="checkbox"> 
     <label> 
      <input id="terms" type="checkbox">{{ 'NEWSLETTER_TERMS_AND_CONDITIONS_1'|trans }} 
      <a href="{{ terms_and_conditions }}" target="_blank">{{ 'NEWSLETTER_TERMS_AND_CONDITIONS_2'|trans }} ashdfjlhasdfjahsjfdk</a> 
     </label> 
     </div> 
     <input type="hidden" name="promotional_newsletter_form[gender]" /> 
    </div> 
    <div class="col-lg-3 col-md-6 col-xs-12"> 
     <button type="submit" class="btn btn-default btn-sm col-xs-12" data-gender="male">{{ 'newsletter.male_deals'|trans }}</button> 
    </div> 
    <div class="col-lg-3 col-md-6 col-xs-12"> 
     <button type="submit" class="btn btn-default btn-sm col-xs-12" data-gender="female">{{ 'newsletter.female_deals'|trans }}</button> 
    </div> 
    </div> 
</form> 

core.js:

window.addEventListener('load', function() { 
    backdrop = new Backdrop(document.getElementById('backdrop')); 
    loader = new Loader(document.getElementById('loader')); 
    new AlertModal(document.getElementById('alert-modal')); 

    $('[data-newsletter]').each(function (element) { 
    new Newsletter(element); 
    }); 

    window.DY = window.DY || {}; 
    window.DY.API = function() { 
    (DY.API.actions = DY.API.actions || []).push(arguments); 
    }; 

    window.DY.API('callback', function() { 
    var smartObjects = document.querySelectorAll('[data-dyso]'); 

    for (var i = 0; i < smartObjects.length; i++) { 
     DYO.smartObject(smartObjects[i].dataset.dyso, { target: smartObjects[i].id, inline: true }); 
    } 
    }); 

    for (var i = 0; i < lsfConfig.thirdPartyModules.length; i++) { 
    var js = document.createElement('script'); 
    js.src = lsfConfig.thirdPartyModules[i]; 
    document.body.appendChild(js); 
    } 
}); 

Newsletter.js

这部分是我创建一个新函数,以防止用户使用'回车'提交新闻稿,因为它发送了错误的信息,但我检查有两种方法来阻止用户提交输入没有选择按钮,在this.terms来选择输入,但我想使用所有的形式不是特定的querySelector #terms所以,这就是为什么我使用this.handler。的addEventListener应用所有形式

var Newsletter = (function() { 
    function Newsletter(handler) { 
    this.handler = handler; 

    this.submitButtons = this.handler.querySelectorAll('[type="submit"]'); 
    this.genderInput = this.handler.querySelector('[name="promotional_newsletter_form[gender]"]'); 
    this.terms = this.handler.querySelector('#terms'); 
    this.subscribe = this.subscribe.bind(this); 
    this.acceptTerms = this.acceptTerms.bind(this); 
    this.enableButtons = this.enableButtons.bind(this); 
    this.disableButtons = this.disableButtons.bind(this); 
    this.preventEnter = this.preventEnter.bind(this); 

    this.terms.addEventListener('click', this.acceptTerms); 
    for (var i = 0; i < this.submitButtons.length; i++) { 
     this.submitButtons[i].disabled = true; 
    } 

    console.log(this.handler); 
    console.log('terms'); 
    console.log(this.terms); 

    this.handler.addEventListener('keypress', this.preventEnter, false); 

    } 

    Newsletter.prototype.acceptTerms = function acceptTerms() { 
    if (this.terms.checked) { 
     this.enableButtons(); 
     return; 
    } 

    this.disableButtons(); 
    }; 
    **///////////////////////////////////////////////////// 
    // New function to prevent keypress 'enter' 
    /////////////////////////////////////////////////////** 
    Newsletter.prototype.preventEnter = function preventEnter(e) { 
    var key = e.charCode || e.keyCode || 0; 
    if (key === 13) { 
     e.preventDefault(); 
    } 
    }; 

    Newsletter.prototype.enableButtons = function enableButtons() { 
    for (var i = 0; i < this.submitButtons.length; i++) { 
     this.submitButtons[i].disabled = false; 
     this.submitButtons[i].addEventListener('click', this.subscribe); 
    } 
    }; 

    Newsletter.prototype.disableButtons = function disableButtons() { 
    for (var i = 0; i < this.submitButtons.length; i++) { 
     this.submitButtons[i].disabled = true; 
     this.submitButtons[i].removeEventListener('click', this.subscribe); 
    } 
    }; 

    Newsletter.prototype.subscribe = function subscribe(event) { 
    event.preventDefault(); 

    var element = event.target || event.srcElement; 

    if (this.genderInput) { 
     this.genderInput.value = element.dataset.gender; 
    } 

    this.handler.submit(); 
    }; 

    return Newsletter; 
})(); 

所有代码的工作很细,没有任何问题,和“的addEventListener”的作品,因为它使用“ENTER”键防止给用户,但是当我试图对特定部分做单元测试:

Newsletter.spec.js

*this.handler.addEventListener('keypress', this.preventEnter, false); 

Newsletter.prototype.preventEnter = function preventEnter(e) { 
    var key = e.charCode || e.keyCode || 0; 
    if (key === 13) { 
     e.preventDefault(); 
    } 
    };* 

在单元测试,我很不可思议卡住,我的想法如何推进......所以......这里的单元测试:

describe('Newsletter component specification', function() { 
    var form; 
    var genderInput; 
    var maleButton; 
    var femaleButton; 
    var terms; 
    var keyPressed = null; 
    var form1; **// new value to createElement form** 

    beforeEach(function() { 
    form1 = document.createElement('form'); **// obtain all the form by the handler** 

    genderInput = document.createElement('input'); 
    genderInput.type = 'hidden'; 
    genderInput.name = 'promotional_newsletter_form[gender]'; 

    terms = document.createElement('input'); 
    terms.id = 'terms'; 
    terms.type = 'checkbox'; 

    maleButton = document.createElement('button'); 
    maleButton.dataset.gender = 'male'; 
    maleButton.type = 'submit'; 

    femaleButton = document.createElement('button'); 
    femaleButton.dataset.gender = 'female'; 
    femaleButton.type = 'submit'; 

    form = { 
     querySelectorAll: function() { 
     return [maleButton, femaleButton]; 
     }, 

     querySelector: function (element) { 
     if (element === '#terms') { 
      return terms; 
     } 

     return genderInput; 
     }, 

     submit: function() {}, 

    }; 

    form1 = document.createElement(form); // trying to convert all the form Object to DOM ?? 
    }); 

    it('test somthing', function() { 
    new Newsletter(form1); 
    }); 

    // UNIT TEST OF ADDEVENTLISTENER... works or not ? 
    it('should intercept enter keypress event and prevent it', function() { 
    function keyPress(key) { 
     var event = document.createEvent('Event'); 
     event.keyCode = key; 
     event.initEvent('keypress'); 
     document.dispatchEvent(event); 
    } 

    document.addEventListener('keypress', function (e) { 
     keyPressed = e.keyCode; 
    }); 

    keyPress(13); 

    expect(keyPressed).to.be.equal(13); 

    }); 

    it('should submit newsletter subscription with female gender', sinon.test(function() { 
    var formSubmitCall = sinon.stub(form, 'submit').returns(false); 

    new Newsletter(form); 
    terms.click(); 
    femaleButton.click(); 

    assert(formSubmitCall.called); 
    expect(genderInput.value).to.be.equal('female'); 
    })); 

    it('should enabled buttons newsletter when accepted terms and conditions', sinon.test(function() { 
    var formSubmitCall = sinon.stub(form, 'submit').returns(false); 

    new Newsletter(form); 
    terms.click(); 

    expect(maleButton.disabled).to.be.equal(false); 
    })); 

    it('should enabled buttons newsletter when accepted terms and conditions', sinon.test(function() { 
    var formSubmitCall = sinon.stub(form, 'submit').returns(false); 

    new Newsletter(form); 
    terms.click(); 
    terms.click(); 

    expect(maleButton.disabled).to.be.equal(true); 
    })); 

    it('should submit newsletter subscription with male gender', sinon.test(function() { 
    var formSubmitCall = sinon.stub(form, 'submit').returns(false); 

    new Newsletter(form); 
    terms.click(); 
    maleButton.click(); 

    assert(formSubmitCall.called); 
    expect(genderInput.value).to.be.equal('male'); 
    })); 

    afterEach(function() { 
    form = null; 

    genderInput.remove(); 
    genderInput = null; 

    maleButton.remove(); 
    maleButton = null; 

    femaleButton.remove(); 
    femaleButton = null; 
    }); 
}); 

回答

0

你使用jQuery?如果是这样的$.each签名是不是你出现什么样的期待:

$('[data-newsletter]').each(function (element) { 
    new Newsletter(element); 
}); 

传递给回调函数的第一个参数是jQuery的选择指标,而不是DOM元素。有可能是在你的代码的其他问题,但你可以通过使用this上下文或使用适当的签名为您的回调函数解决这个问题:

$('[data-newsletter]').each(function (index, element) { 
    new Newsletter(element); 
}); 

$('[data-newsletter]').each(function() { 
    new Newsletter(this); 
}); 

Documentation

相关问题