0

我有一个使用 2 个不同组件的简单聚合物组件。在页面上使用时,一切正常,但是当我运行测试时,它们仅在 Chrome 上失败。子组件的内容moment-element并且duration-view不被渲染。

<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../bower_components/moment-element/moment-element.html">
<link rel="import" href="../duration-view/duration-view.html">

<dom-module id="issue-row">
    <template>
        <li>
            [[issue]]
            <moment-element datetime="[[startDate]]" output-format="[[startDateFormat]]"></moment-element>
            -
            <moment-element datetime="[[endDate]]" output-format="[[endDateFormat]]"></moment-element>
            <duration-view date-from="[[startDate]]" date-to="[[endDate]]"></duration-view>
        </li>
    </template>

    <script>
        class IssueRow extends Polymer.Element {
            static get is() { return 'issue-row'; }
            static get properties() {
                return {
                    issue : String,
                    startDate : String,
                    endDate : String,
                    startDateFormat : {
                        type : String,
                        value : 'D.MM HH:mm'
                    },
                    endDateFormat : {
                        type : String,
                        value : 'HH:mm'
                    }
                };
            }
        }

        window.customElements.define(IssueRow.is, IssueRow);
    </script>
</dom-module>
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../bower_components/moment-element/moment-import.html">
<link rel="import" href="moment-duration-format-import.html">

<dom-module id="duration-view">
    <template>
        some static content which is not rendered.
        [[formattedDuration]]
    </template>

    <script>
        class DurationView extends Polymer.Element {
            static get is() { return 'duration-view'; }
            static get properties() {
                return {
                    format : {
                        type : String,
                        value : "hh:mm"
                    },
                    duration : {
                        type : String,
                        value : '00:00:00'
                    },
                    dateFrom : String,
                    dateTo : String,
                    formattedDuration : {
                        type : String,
                        notify : true
                    }
                };
            }
            static get observers() {
                return ['_computeDuration(duration, dateFrom, dateTo, format)']
            }
            _computeDuration(duration, dateFrom, dateTo, format) {
                console.log(duration, dateFrom, dateTo, format);
                var output;
                if (dateFrom && dateTo) {
                    var from = moment(dateFrom);
                    var to = moment(dateTo);
                    if (!from.isValid() || !to.isValid()) {
                        this.set('formattedDuration', 'Invalid date');
                        return;
                    }
                    output = moment.duration(to.diff(from), 'ms');
                } else {
                    output = moment.duration(duration);
                }
                this.set('formattedDuration', output.format(format, {trim: false}));
            }
        }

        window.customElements.define(DurationView.is, DurationView);
    </script>
</dom-module>
  <test-fixture id="BasicTestFixture">
    <template>
      <issue-row issue="PR-493" start-date="2017-05-18 11:00" end-date="2017-05-18 14:30"></issue-row>
    </template>
  </test-fixture>

  <script>
      suite('issue-row', function () {

        test('displays issue number, dates and duration', function () {
          var element = fixture('BasicTestFixture');
          var elementShadowRoot = element.shadowRoot;
          var elementText = elementShadowRoot.textContent;
          expect(elementText).to.have.string("PR-493");
          expect(elementText).to.have.string("18.05");
          expect(elementText).to.have.string("11:00");
          expect(elementText).to.have.string("14:30");
          expect(elementText).to.have.string("3:30");
        });

      });
  </script>

我在第二次expect调用时遇到断言错误:

Error: expected '\n        \n            PR-493\n            \n            -\n            \n            \n        \n    ' to contain '18.05'
  Context.<anonymous> at issue-row_test.html:32

console.log_computeDurationchrome 上测试时,in 仅输出默认值(或空)。

这在 Firefox 上运行良好,在 Chrome 上失败。试验结果:

chrome 58 (5/0/1)                       firefox 53 (6/0/0)
4

1 回答 1

0

问题是对影子 DOM 概念的误解。元素已呈现,但它们未在标准 DOM 遍历中显示。在这种特殊情况下textContentinnerHTMLouterHTML属性忽略阴影元素。它可以在 Firefox 上运行,因为它缺乏影子 DOM 支持,并且它在标准 DOM 树中呈现所有内容。

我做了一个简单的工具来测试嵌套组件的内容:

window.deep = function (element) {
    return {
        textContent : (function () {
            if (element.nodeType === Node.TEXT_NODE) {
                return element.textContent;
            }
            var children;
            if (element.shadowRoot) {
                children = element.shadowRoot.childNodes;
            } else {
                children = element.childNodes;
            }
            var content = [];
            for (var i in children) {
                content.push(deep(children[i]).textContent);
            }
            return content.join('');
        })()
    }
}

如果需要,请随意使用此概念。用法:deep(fixture('fixtureId')).textContent

于 2017-05-19T14:50:41.540 回答