Angular: запрос debugElement не находит элемент, но jQuery находит

Я был с медведем время с этим. Я использую виджет списка третьей части (jqx-listbox) и пытаюсь его протестировать. Все работает нормально под ng serve, и даже глядя на вывод Karma в Chrome, я вижу весь пользовательский интерфейс со списком и элементами, что я и хочу протестировать.

Проблема в том, что запрос элемента в тесте:

let openListbox = fixture.debugElement.query(By.css('.jqx-listitem-element')); возвращает значение null, а если я поставлю точку останова в этой строке и использую jQuery в консоли Chrome $('.jqx-listitem-element), то будет возвращен элемент DOM!

Если я изменю поиск в тесте на элемент, определенный в шаблоне (<jqxlistbox>), например так: let openListbox = fixture.debugElement.query(By.css('jqxlistbox')), это вернет debugElement, и я даже смогу проверить внутри собственного элемента этой вещи прямо в этой точке останова и увидеть, что в нем есть что-то. это, но независимо от того, что я пробовал (возвращая этот элемент, а затем выполняя запрос к нему), я не могу запросить объект глубже, поэтому мой тест продолжает давать сбой.

Я также пытался использовать fakeAsync и fixture.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>

EDIT Я могу получить внешний элемент, и его innerText — это текст этого диапазона: «Открыть серьезную ошибку», но это только потому, что это единственный текстовый узел во всем элементе.

С этим тестовым кодом первое утверждение проходит, второе терпит неудачу с ошибкой «Не удается прочитать свойство nativeElement of null», что для меня так странно, потому что, если он может найти 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');

person redOctober13    schedule 19.01.2018    source источник


Ответы (1)


У меня такое ощущение, что ваши jqx-listitem-element визуализируются на основе некоторых данных, предоставленных jqxlistbox. Чтобы получить доступ к этим зависимым от данных дочерним элементам, вам нужно будет запросить их после "инициализации" компонента (путем вызова fixture.detectChanges).

Итак, попробуйте следующее:

let openListBox = fixture.debugElement.query(By.css('jqxlistbox'));
fixture.detectChanges();
let listItems = fixture.debugElement.queryAll(By.css('.jqx-listitem-element'));

Это инициализирует компонент, в результате чего jqxlistbox регистрирует свои данные и отображает дочерние элементы списка, затем вы можете запросить эти элементы списка со второй строкой queryAll в приведенном выше фрагменте.


Изменить в ответ на первый комментарий и дополнительную информацию:

Мне интересно, есть ли что-то не так с запросом DebugElement, возвращаемого запросом?

Нет ничего плохого в запросе DebugElement, то, что вы делаете, синтаксически правильно. Вы должны иметь возможность использовать код, который я добавил в первую версию этого ответа. Я думаю, что это, вероятно, о том, как вы заполняете эти элементы списка. Проверьте свои фиктивные данные/провайдеров. Я не вижу весь ваш spec, поэтому я не могу устранять неполадки там.

person vince    schedule 19.01.2018
comment
да, это было одним из первых, что я попробовал, замусорив там больше detectChanges, в том числе там, где вы предложили, но второй запрос все равно возвращает null. Обновление моего исходного поста с помощью HTML, отображаемого во время теста. Теперь я обнаружил, что могу использовать openListBox.innerText, так как в этом случае единственный текстовый узел находится в этом интервале, но это кажется неправильным; Я должен получить доступ к этому узлу DOM. - person redOctober13; 19.01.2018
comment
У меня аналогичная проблема со строками таблицы угловых материалов. Был бы очень заинтересован в ответе. - person miso; 06.08.2019