In our example of Angular unit testing, the service is injected into the QuoteComponent to access its properties, which will be needed by the view:
import { Component, OnInit } from '@angular/core';
import { QuoteService } from '../service/Quote.service';
import { QuoteModel } from '../model/QuoteModel';
@Component({
selector: 'app-Quotes',
templateUrl: './Quotes.component.html',
styleUrls: ['./Quotes.component.css']})
export class QuotesComponent implements OnInit {
public quoteList: QuoteModel[];
public quoteText: String = null;
constructor(private service: QuoteService) { }
ngOnInit() {
this.quoteList = this.service.getQuote();
}
createNewQuote() {
this.service.addNewQuote(this.quoteText);
this.quoteText = null;
}
removeQuote(index) {
this.service.removeQuote(index);
}
}
The first two blocks in the describe container run consecutively. In the first block, the form module is imported into the configuration test. This is used ngModel as a form-related directive.
Also, QuotesComponent is also declared in configTestMod in the same as components are declared in ngModule of the appModule file. The second block creates a QuoteComponent and its instance, which is used by the other blocks:
let component: QuotesComponent;
let fixture: ComponentFixture;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [FormsModule],
declarations: [QuotesComponent]
});
});
beforeEach(() => {
fixture = TestBed.createComponent(QuotesComponent);
component = fixture.debugElement.componentInstance;
});
If the instance of the component is created then this block tests :
it("should create Quote component", () => {
expect(component).toBeTruthy();
});
The manipulation of all operations are injected service handles. The quoteService variable holds the injected service (QuoteService). Here, the component is yet to be rendered until the detectChanges method is called:
it("quoteList of service", () => {
const quoteService = fixture.debugElement.injector.get(QuoteService);
fixture.detectChanges();
expect(quoteService.getQuote()).toEqual(component.quoteList);
});
Now we test successfully create a post. The nativeElement object gives access to the HTML element.
it("it is generate post", () => {
component.quoteText = "I love this test";
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(compiled.innerHTML).toContain("I love this test");
});
In addition to accessing HTML content, you can also access an element through its CSS property. The button is disabled when the QuoteTextModel is empty or empty:
it("textArea is empty then disable button", () => {
fixture.detectChanges();
const button = fixture.debugElement.query(By.css("button"));
expect(button.nativeElement.disabled).toBeTruthy();
});
it("textArea is not empty then enable button", () => {
component.quoteText = "I love this test";
fixture.detectChanges();
const button = fixture.debugElement.query(By.css("button"));
expect(button.nativeElement.disabled).toBeFalsy();
});
The way we access an element with its CSS properties, we can also access an element by its class name. The button clicks are fired by calling the triggerEventHandler . The click event type is specified. A quote displayed deleted from the quoteList when clicked on:
it("it is delete post", () => {
component.quoteText = "This is a newly fresh post";
fixture.detectChanges();
fixture.debugElement
.query(By.css(".row"))
.query(By.css(".card"))
.triggerEventHandler("click", null);
const compiled = fixture.debugElement.nativeElement;
expect(compiled.innerHTML).toContain("This is a newly fresh post");
});