DOM interaction
Now we are going to cover the DOM interaction, based on the previous code snippets we will find out how we can test a specific section of the DOM.
describe('CoursesCardListComponent', () => {
let component: CoursesCardListComponent;
let fixture: ComponentFixture<CoursesCardListComponent>;
let el: DebugElement;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [CoursesModule],
declarations: [AppComponent]
})
.compileComponents()
.then(() => {
fixture = TestBed.createComponent(CoursesCardListComponent);
component = fixture.componentInstance;
el = fixture.debugElement;
});
}));
it("should create the component", () => {
expect(component).toBeTruthy();
});
it("should display the course list", () => {
component.courses = setupCourses();
const cards = el.queryAll(By.css(".course-card"));
expect(cards).toBeTruthy("Could not find cards");
expect(cards.length).toBe(12, "Unexpected number or courses");
});
});
DebugElement
The Angular fixture provides the component's element directly through the fixture.nativeElement
.
content_copyconst bannerElement: HTMLElement = fixture.nativeElement;
This is actually a convenience method, implemented as fixture.debugElement.nativeElement
.
content_copyconst bannerDe: DebugElement = fixture.debugElement;
const bannerEl: HTMLElement = bannerDe.nativeElement;
There's a good reason for this circuitous path to the element.
The properties of the nativeElement
depend upon the runtime environment. You could be running these tests on a non-browser platform that doesn't have a DOM or whose DOM-emulation doesn't support the full HTMLElement
API.
Angular relies on the DebugElement
abstraction to work safely across all supported platforms. Instead of creating an HTML element tree, Angular creates a DebugElement
tree that wraps the native elements for the runtime platform. The nativeElement
property unwraps the DebugElement
and returns the platform-specific element object.
Because the sample tests for this guide are designed to run only in a browser, a nativeElement
in these tests is always an HTMLElement
whose familiar methods and properties you can explore within a test.
By.css()
Although the tests in this guide all run in the browser, some apps might run on a different platform at least some of the time.
For example, the component might render first on the server as part of a strategy to make the application launch faster on poorly connected devices. The server-side renderer might not support the full HTML element API. If it doesn't support querySelector
, the previous test could fail.
The DebugElement
offers query methods that work for all supported platforms. These query methods take a predicate function that returns true
when a node in the DebugElement
tree matches the selection criteria.
You create a predicate with the help of a By
class imported from a library for the runtime platform. Here's the By
import for the browser platform:
content_copyThe code sample is missing for
testing/src/app/banner/banner-initial.component.spec.ts#import-by
The following example re-implements the previous test with DebugElement.query()
and the browser's By.css
method.
content_copyit('should find the <p> with fixture.debugElement.query(By.css)', () => {
const bannerDe: DebugElement = fixture.debugElement;
const paragraphDe = bannerDe.query(By.css('p'));
const p: HTMLElement = paragraphDe.nativeElement;
expect(p.textContent).toEqual('banner works!');
});
Some noteworthy observations:
The
By.css()
static method selectsDebugElement
nodes with a standard CSS selector.The query returns a
DebugElement
for the paragraph.You must unwrap that result to get the paragraph element.
Last updated
Was this helpful?