【问题标题】:Testing polymer 1.0 components with iron-ajax using wct使用 wct 使用 Iron-ajax 测试聚合物 1.0 组件
【发布时间】:2015-12-11 00:47:25
【问题描述】:

在我的自定义组件中模拟服务器对 Iron-ajax 组件的响应最困难。这是我的代码文件。

自定义组件.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>

custom-component-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>

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

我做错了什么?

【问题讨论】:

    标签: polymer sinon web-component-tester


    【解决方案1】:

    我找到了一个更好的解决方案来测试我的元素中 Iron-ajax 元素的自动功能。

    你需要在你的 ajax 请求上添加一个事件监听器来触发你的服务器响应,不需要 generateRequest 也不需要 setTimeout hacks。

    这是一个例子:

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

    【讨论】:

    • 我的模拟略有不同:通过覆盖 generateRequest.因为我想测试我的元素而不是发送异步请求等的整个业务,所以我执行以下操作:stub('iron-ajax', { generateRequest() { this._setLastResponse({/*my response object */}); } }); 如果您想使用“响应”事件,那么您可以在假的 generateRequest 中执行类似的操作方法:this.fire('response', {/*my response object */});
    【解决方案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();
                }
            });
        });
    });
    

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

    【讨论】:

    • 对于那些想知道为什么我的 lastRequest 没有被设置的人:我已将 auto 设置为 true,它会在创建组件后立即创建一个请求。但是,我从不放弃对 javascript 的控制,因此不会发生初始请求。手动调用generateRequest导致第二个请求,与第一个请求不匹配,所以没有设置lastResponse。解决方案是将我的测试函数包装在一个超时为 0 的 setTimeout 中,并放弃对 generateRequest 的手动调用。这允许生成初始的铁请求。
    • 我在聚合物组件中有一个 Iron-ajax,这个解决方案对我不起作用。
    • 为测试添加额外的监听器并在其中调用完成函数!这就是答案。谢谢。
    【解决方案3】:

    作为组件测试,我认为您应该真正测试组件的行为,而不是 sinon 和/或 iron-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();
        })
      });
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-12
      • 1970-01-01
      • 1970-01-01
      • 2019-12-13
      相关资源
      最近更新 更多