2015-12-11 130 views
2

我在最困难的时候嘲笑服务器对我自定义组件内部的一个iron-ajax组件的响应。这是我的代码文件。使用wct测试聚合物1.0组件使用iron-ajax

定制component.html:

<link rel="import" href="/iron-ajax/iron-ajax.html"> 
<link rel="import" href="/internal-component/internal-component.html"> 

<dom-module id="custom-component"> 
    <template> 
     <iron-ajax url="staticFile.json" auto handle-as="json" last-response={{ajaxResponse}}></iron-ajax> 
     <template is="dom-repeat" 
        items={{ajaxResponse}} 
        sort="_sort" 
        id="gridRow"> 
      <internal-component var1={{item.var1}} 
            var2={{item.var2}}> 
      </internal-component> 
     </template> 
    </template> 
</dom-module> 
<script>(some cool scripts that are working...)</script> 

定制组件tests.html

<!DOCTYPE html> 
<html> 
<head> 
    <meta charset="utf-8" /> 
    <script src="/webcomponentsjs/webcomponents-lite.js"></script> 
    <script src="/web-component-tester/browser.js"></script> 
    <script src="/test-fixture/test-fixture-mocha.js"></script> 

    <link rel="import" href="/test-fixture/test-fixture.html" /> 

    <link rel="import" href="/polymer/polymer.html"> 
    <link rel="import" href="/polymer-ts/polymer-ts.html"> 

    <link rel="import" href="custom-component.html"> 
</head> 
<body> 
<test-fixture id="testElement"> 
    <template> 
     <custom-component></custom-component.> 
    </template> 
</test-fixture> 

<script> 
    suite('<custom-component>', function() { 
     var testElement; 
     var server; 
     var responseHeaders = { 
      json: { 'Content-Type': 'application/json' }, 
      plain: { 'Content-Type': 'text/plain' } 
     }; 
     setup(function() { 
      replace('custom-component').with('fake-custom-component'); 
      server = sinon.fakeServer.create(); 
      server.respondWith('GET', /staticFile\.json/, [ 
       200, 
       responseHeaders.json, 
       '[{"var1": "9a","var2": "17n"}]' 
      ]); 
      testElement = fixture("testElement"); 
     }); 
     teardown(function() { 
      server.restore(); 
     }); 
     suite('testSuite', function() { 
      test('test1', function() { 
       var ajax = testElement.getElementsByTagName('iron-ajax')[0]; 
       ajax.lastResponse = null; 
       ajax.generateRequest(); 
       server.respond(); 
       assert(ajax.lastResponse.hour === "9a"); 
      }); 
     }); 
    }); 
</script> 

</body> 
</html> 

你会发现,我显式调用铁AJAX generateRequest,因为如果我不那么,直到我的测试完成(并且失败)之后,请求才会发生。当显式调用generateRequest时,我至少能够使请求发生,但(即使我调用server.respond()),直到测试完成后,iron-ajax才调用_handleResponse。而且,即使是这样,它也不会设置lastResponse,因为iron-ajax中有一行代码检查是否(请求=== this.lastRequest)(它不是)。

我在做什么错?

回答

4

我发现了一个更好的解决方案来测试我的元素中的铁ajax元素的自动功能。

您需要在ajax的请求中添加一个事件侦听器来触发您的服务器响应,不需要generateRequest并且不需要setTimeout攻击。

这里有一个例子:

  test('test with ajax element', function (done) { 
       var ajax = Polymer.dom(myElement.root).querySelector("#ajax_element"); 

       ajax.addEventListener('request', function (e) { 
        server.respond('GET', '/CALLED_URL', dataResponse); 
       }); 

       ajax.addEventListener('response', function (e) { 
        //DO YOUR EXPECTS HERE 
        done(); 
       }); 
      }); 
+2

我的嘲笑略有不同:通过重写generateRequest。由于我想测试我的元素,而不是发送异步请求等的整个业务,我做了以下事情: 'stub('iron-ajax',{ generateRequest(){this._setLastResponse({/ * my response object * /});} });' 如果你想使用'on-response'事件,你可以在假的generateRequest方法中做这样的事情:'this.fire('response',{/ *我的响应对象* /});' – Paysdoc

2

我想睡个好觉就是我需要的。

我忘了解释异步请求。我修改了代码,现在反映以下内容:

suite('<custom-component>', function() { 
    var testElement; 
    var server; 
    var responseHeaders = { 
     json: { 'Content-Type': 'application/json' }, 
     plain: { 'Content-Type': 'text/plain' } 
    }; 
    setup(function() { 
     replace('custom-component').with('fake-custom-component'); 
     server = sinon.fakeServer.create(); 
     server.respondWith('GET', /staticFile\.json/, [ 
      200, 
      responseHeaders.json, 
      '[{"var1": "9a","var2": "17n"}]' 
     ]); 
     testElement = fixture("testElement"); 
    }); 
    teardown(function() { 
     server.restore(); 
    }); 
    suite('testSuite', function() { 
     // note that I added the "done" as a parameter on my test function 
     test('test1', function (done) { 
      var ajax = testElement.getElementsByTagName('iron-ajax')[0]; 
      ajax.generateRequest(); 
      server.respond(); 

      // note that I added an async event listener here, and moved my test inside. 
      ajax.addEventListener('response', function(e) { 
       assert(e.target.lastResponse.var1 === "9a"); 
       done(); 
      } 
     }); 
    }); 
}); 

我现在能够正确地拦截响应,并且测试主要是按预期工作。我仍然有问题,铁ajax的lastResponse没有设置,但这是一个不同的问题,我认为。

+0

对于那些想知道为什么我lastRequest没有被设置:我有自动设置为true,这只要组件创建创建请求。但是,我从来没有放弃在JavaScript中的控制权,所以最初的请求不会发生。手动调用generateRequest导致第二个请求,它与第一个请求不匹配,所以它没有设置lastResponse。解决方案是将我的测试函数封装在setTimeout中,并使用0超时,然后放弃手动调用generateRequest。这允许生成最初的铁要求。 – progressquest

+0

我在聚合物组件内有一个铁质ajax,这个解决方案对我来说并不合适。 –

+0

为测试添加额外的侦听器并在其中调用完成的函数!这就是答案。谢谢。 –

0

作为一个组件的测试,我相信你确实应该测试组件的行为,而不是兴农和/或铁AJAX元素的内部。你的请求很可能会更新一些会触发一些DOM更新的属性。

我也一直恨setTimeouts在测试中,刚刚发现WCT有一个flush方法(这是等待所有异步的东西来完成) - 它只是没有记录在AJAX测试部分,但在DOM操作改为(https://www.polymer-project.org/1.0/docs/tools/tests#test-local-dom)。

这样,我的做法是:

suite('testSuite', function() { 
    test('test1', function (done) { 
    // assuming iron-ajax with auto 
    server.respond(); 
    flush(function() { 
     expect(el.myObject).to.deep.equal(responseObj); 

     // in case you're binding the last response to a property 
     expect(el.lastResponse).to.deep.equal(responseObj); 

     done(); 
    }) 
    }); 
});