I am new to Angular and created To-Do Application. I tried to find the solution at many places even the Testing documentation
I am testing a component. That bring data from mongodb, I have mocked that data though.
The following is the HTML of template (using bootstrap):
<li class="list-group-item" *ngFor="let task of tasks">
<div class=" task-date">{{task.date}}</div>
</li>
The below is the component code (I'm adding only sub-part):
export class ShowTaskComponent extends OnInit{
tasks:Task[];
ngOnInit() {
setInterval(() => {this.refreshTasks()}, 3000);
}
constructor(private appService: AppService, private _router:Router){
super();
this.refreshTasks();
}
refreshTasks = function() {
this.appService.retrieveDataFromServer().subscribe((data: any) => {
//this.appService.taskArray = data;
this.tasks = data;
});
};
}
Now I'm adding the test code (.spec.ts file's sub part) ... To explain well, all of the code (excluding imports):
let comp: ShowTaskComponent;
let fixture: ComponentFixture<ShowTaskComponent>;
let service: AppService;
let router: Router;
let debugTaskTitle: DebugElement[];
let taskTitles: any[];
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ShowTaskComponent],
providers: [AppService],
imports: [....]
})
.compileComponents();
}));
beforeEach( () => {
fixture = TestBed.createComponent(ShowTaskComponent);
service = fixture.debugElement.injector.get(AppService);
router = fixture.debugElement.injector.get(Router);
let dummyTasks: any[] = [
{
"date": "12 October 2017",
"title": "Demo task 1",
"description": "Demo task 1 desc",
"priority" : "High",
"_id" : "1"
},
{
"date": "1 January 2018",
"title": "Demo task 2",
"description": "Demo task 2 desc",
"priority" : "Low",
"_id" : "2"
}
];
spyOn(service, 'retrieveDataFromServer').and.returnValue(Observable.of<any[]>(dummyTasks));
fixture = TestBed.createComponent(ShowTaskComponent);
comp = fixture.componentInstance;
console.log("----------------------------> comp ", comp);
debugTaskTitle = fixture.debugElement.queryAll(By.css('div.task-title'));
console.log("----------------------------> debugTaskTitle ", debugTaskTitle);
let counter: number = 0;
for(let title of debugTaskTitle) {
taskTitles.push(title.nativeElement);
taskTitles[counter].innerText = dummyTasks[counter].title;
counter ++;
}
});
//This test fails because taskTitles is undefined!
it('test whether a correct test has loaded', () =>{
expect(taskTitles).toBe(["Demo task 1", "Demo task 2"]);
});
The problem comes with debugTaskTitle. This is empty array, when I try to initialise it with fixture.debugElement.queryAll(By.css())
.
I tried to print it on console (look at long --------> arrows) and it is empty array.
The object of the component comp is created and is doing great.
Can anybody suggest me where I'm wrong? I'm late in submitting this assignment by three days. Any help will be great.
Whole code is at github repo
Also, I don't see anything on browser when I run only first test. It should show tasks on browser!
So does that mean *ngFor doesn't populate the content on page once .compileComponents();
has been called to generate CSS and HTML within first beforeEach()
?
Since retrieveDataFromServer
returns an Observable, you need to wait for the async task to resolve. For that you can wrap the beforeEach in async
, just like the one above it. Then you need to wait for it to stabilize
fixture = TestBed.createComponent(ShowTaskComponent);
comp = fixture.componentInstance;
fixture.whenStable().then(() => {
// after something in the component changes, you should detect changes
fixture.detectChanges();
// everything else in the beforeEach needs to be done here.
debugTaskTitle = fixture.debugElement.queryAll(By.css('div.task-title'));
...
})
Note that it is now recommended to use fakeAsync
over async
now. Unless the test makes an XHR request, which fakeAsync
cannot handle, fakeAsync
is the preferred method to use when testing asynchronous code. What fakeAsync
does is allow you to write code as if it was synchronous and let you control when to complete the async test. Some test code might look something like
import { fakeAsync } from '@angular/core/testing';
it('should...', fakeAsync(() => {
fixture = TestBed.createComponent(ShowTaskComponent);
comp = fixture.componentInstance;
comp.callSomeAsyncMethod();
tick();
fixture.detectChanges();
// assertions
}));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With