Angular:debugElement查询找不到元素,但jQuery却没有

时间:2018-01-19 16:46:51

标签: angular unit-testing integration-testing jqxwidgets

我已经忍受了一段时间。 我正在使用第三方的列表框小部件(jqx-listbox)并尝试测试它。在ng serve下一切正常,甚至在Chrome中查看Karma输出,我可以看到整个用户界面,列表框和项目,这就是我想要测试的内容。

问题是在测试中查询元素:

let openListbox = fixture.debugElement.query(By.css('.jqx-listitem-element')); 返回null,如果我在该行上放置断点,并在Chrome控制台$('.jqx-listitem-element)中使用jQuery,则返回DOM元素!

如果我将测试中的查找更改为模板中定义的元素(<jqxlistbox>),如下所示:let openListbox = fixture.debugElement.query(By.css('jqxlistbox')),那将返回debugElement,我甚至可以在内部检查&# 39;在该断点处的原生元素并看到它有内容,但无论我尝试过什么(返回该元素然后对其进行查询),我似乎无法更深入地查询进入对象,所以我的测试一直在失败。

我也尝试过使用fakeAsyncfixture.whenStable,但这似乎完全被跳过了(或者它永远不会稳定)。

以下是小部件在运行时生成的呈现模板代码(它是我试图检查的最里面的跨度)

<jqxlistbox _ngcontent-c0="" class="" style="" ng-reflect-attr-display-member="message" ng-reflect-attr-source="[object Object]"
  ng-reflect-attr-value-member="errorType" ng-reflect-attr-width="100%">
  <div class="ng-tns-c0-0 jqx-listbox jqx-reset jqx-rc-all jqx-widget jqx-widget-content jqx-disableselect" id="jqxWidgete238403f0fb8"
    style="width: 100%; height: 200px;" aria-multiselectable="false" role="listbox" tabindex="1">
    <div style="-webkit-appearance: none; background: transparent; outline: none; width:100%; height: 100%; align:left; border: 0px; padding: 0px; margin: 0px; left: 0px; top: 0px; valign:top; position: relative;">
      <div style="-webkit-appearance: none; border: none; background: transparent; outline: none; width:100%; height: 100%; padding: 0px; margin: 0px; align:left; left: 0px; top: 0px; valign:top; position: relative;">
        <div id="listBoxContentjqxWidgete238403f0fb8" style="-webkit-appearance: none; background: transparent; outline: none; border: none; padding: 0px; overflow: hidden; margin: 0px; left: 0px; top: 0px; position: absolute; width: 328px; height: 198px;">
          <div style="outline: none 0px; overflow: hidden; width: 329px; position: relative; height: 404px;">
            <div role="option" id="listitem0jqxWidgete238403f0fb8" class="jqx-listitem-element" style="height: 24px; top: 0px; left: 0px;"
              aria-selected="true">
              <span style="white-space: pre; display: block; visibility: inherit; width: 318px;" class="jqx-listitem-state-normal jqx-item jqx-rc-all jqx-listitem-state-selected jqx-fill-state-pressed">Open hard error</span>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</jqxlistbox>

修改 我可以获得外部元素,它的innerText是该范围的文本:&#34;打开硬错误&#34;但这只是因为它是整个元素中唯一的文本节点。

使用此测试代码,第一个断言通过,第二个失败,错误为&#34;无法读取属性nativeElement of null&#34;这对我来说太奇怪了,因为如果它能找到innerText,那么它就有了整个DOM元素。我想知道查询返回的DebugElement是否有问题?:

fixture.detectChanges();
let openListbox = fixture.debugElement.query(By.css('#open jqxlistbox'));
expect(openListbox.nativeElement.innerText).toContain('Open hard error', 'item in listbox');

fixture.detectChanges();

let openListboxItem: HTMLElement = openListbox.query(By.css('span')).nativeElement;
expect(openListboxItem.textContent).toBe('Open hard error', 'item in listbox');

1 个答案:

答案 0 :(得分:1)

根据提供给jqx-listitem-element的一些数据,我感觉您正在jqxlistbox呈现fixture.detectChanges。为了能够访问那些依赖于数据的子元素,您需要在组件<#>之后查询它们&#34;初始化&#34; (通过致电let openListBox = fixture.debugElement.query(By.css('jqxlistbox')); fixture.detectChanges(); let listItems = fixture.debugElement.queryAll(By.css('.jqx-listitem-element')); )。

所以,请尝试以下方法:

jqxlistbox

这将初始化组件,导致queryAll注册其数据并呈现它的子列表项,然后您可以使用第二个{{1}查询这些列表项上面代码段中的行。

编辑以回应第一条评论&amp;其他信息:

  

我想知道查询返回的DebugElement是否有问题?

查询DebugElement没什么问题,你所做的是语法正确。您应该能够使用我在此答案的第一个版本中添加的代码。我想这可能是关于你如何填充这些列表项。检查您的模拟数据/提供商。我无法看到您的整个spec,因此我无法排除故障。