2

我最难模拟服务器对自定义组件中的 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>

自定义组件-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) (它不是)。

我究竟做错了什么?

4

3 回答 3

4

我找到了一个更好的解决方案来测试我的元素中 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();
                });
            });
于 2016-04-06T11:38:49.763 回答
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 没有设置的问题,但我认为这是一个不同的问题。

于 2015-12-11T15:59:33.127 回答
0

作为组件测试,我认为您应该真正测试组件行为而不是 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();
    })
  });
});
于 2017-02-06T15:08:09.373 回答