fix(ivy): Prevent errors when querying for elements outside Angular context (#32361)

DebugElement.query also searches elements that may have been created
outside of Angular (ex: with `document.appendChild`). The current
behavior attempts to get the LContext of these nodes but throws an error
because the LContext does not exist.

PR Close #32361
This commit is contained in:
Andrew Scott
2019-08-27 17:02:41 -07:00
committed by Misko Hevery
parent c8b065524e
commit 260217a800
2 changed files with 65 additions and 19 deletions

View File

@ -8,7 +8,7 @@
import {CommonModule, NgIfContext, ɵgetDOM as getDOM} from '@angular/common';
import {Component, DebugNode, Directive, ElementRef, EmbeddedViewRef, EventEmitter, HostBinding, Injectable, Input, NO_ERRORS_SCHEMA, OnInit, Output, Renderer2, TemplateRef, ViewChild, ViewContainerRef} from '@angular/core';
import {Component, DebugElement, DebugNode, Directive, ElementRef, EmbeddedViewRef, EventEmitter, HostBinding, Injectable, Input, NO_ERRORS_SCHEMA, OnInit, Output, Renderer2, TemplateRef, ViewChild, ViewContainerRef} from '@angular/core';
import {ComponentFixture, TestBed, async} from '@angular/core/testing';
import {By} from '@angular/platform-browser/src/dom/debug/by';
import {hasClass} from '@angular/platform-browser/testing/src/browser_util';
@ -580,6 +580,43 @@ class TestCmptWithPropBindings {
expect(fixture.debugElement.query(By.css('.myclass'))).toBeTruthy();
});
describe('DebugElement.query doesn\'t fail on elements outside Angular context', () => {
@Component({template: '<div></div>'})
class NativeEl {
constructor(private elementRef: ElementRef) {}
ngAfterViewInit() {
this.elementRef.nativeElement.children[0].appendChild(document.createElement('p'));
}
}
let el: DebugElement;
beforeEach(() => {
const fixture =
TestBed.configureTestingModule({declarations: [NativeEl]}).createComponent(NativeEl);
fixture.detectChanges();
el = fixture.debugElement;
});
it('when searching for elements by name',
() => { expect(() => el.query(e => e.name === 'any search text')).not.toThrow(); });
it('when searching for elements by their attributes', () => {
expect(() => el.query(e => e.attributes !['name'] === 'any attribute')).not.toThrow();
});
it('when searching for elements by their classes',
() => { expect(() => el.query(e => e.classes['any class'] === true)).not.toThrow(); });
it('when searching for elements by their styles', () => {
expect(() => el.query(e => e.styles['any style'] === 'any value')).not.toThrow();
});
it('when searching for elements by their properties', () => {
expect(() => el.query(e => e.properties['any prop'] === 'any value')).not.toThrow();
});
});
it('DebugElement.queryAll should pick up both elements inserted via the view and through Renderer2',
() => {
@Directive({