I am trying to test a structural directive named MyDirective with Jasmine. The Angular version used is RC5.
// Part of the MyDirective class
@Directive({selector: '[myDirective]'})
export class MyDirective {
constructor(protected templateRef: TemplateRef<any>,
protected viewContainer: ViewContainerRef,
protected myService: MyService) {
}
ngOnInit() {
this.myService.getData()
.then((data) => {
if (!MyService.isValid(data)) {
this.viewContainer.createEmbeddedView(this.templateRef);
} else {
this.viewContainer.clear();
}
})
.catch((error) => {
console.log(error);
this.viewContainer.createEmbeddedView(this.templateRef);
});
}
}
The getData method is overwritten in the MockService class whereas the isValid method (a static method of MyService) is called directly, which checks the validity of the data.
// Part of the Jasmine unit test class for the MyDirective class
@Component({
selector: 'test-cmp', template: '', directives: [MyDirective]
})
class TestComponent {}
class MockService {
mockResponse: MyResponse = {valid date goes here};
mockInvalidResponse: MyResponse = {};
getData() {
if (booleanCondition) {
return Promise.resolve(this.mockResponse);
} else {
return Promise.resolve(this.mockInvalidResponse);
}
}
}
describe('MyDirective', () => {
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [TestComponent],
providers: [
{provide: MyService, useClass: MockService},
TemplateRef,
ViewContainerRef
]
});
});
it('should remove the target DOM element when the condition is true', async(() => {
booleanCondition = true;
const template =
'<div><div *myDirective><span>Hi</span></div></div>';
TestBed.overrideComponent(TestComponent, {set: {template: template}});
let fixture = TestBed.createComponent(TestComponent);
fixture.detectChanges();
expect(getDOM().querySelectorAll(fixture.debugElement.nativeElement, 'span').length).toEqual(0);
}));
it('should contain the target DOM element when the condition is false', async(() => {
booleanCondition = false;
const template =
'<div><div *myDirective><span>Hi</span></div></div>';
TestBed.overrideComponent(TestComponent, {set: {template: template}});
let fixture = TestBed.createComponent(TestComponent);
fixture.detectChanges();
// The 'expect' bellow fails because the value is 0 for some reason
expect(getDOM().querySelectorAll(fixture.debugElement.nativeElement, 'span').length).toEqual(1);
}));
});
The second it
is supposed to create a case in which the span element is in the DOM, but it does not. I checked to see if it goes to the first condition in the if statement like this:
if (!MyService.isValid(data)) {
console.log('the first if condition is read.');
this.viewContainer.createEmbeddedView(this.templateRef);
} else {
this.viewContainer.clear();
}
}
And it logs it. So, it should keep the element in the DOM, but I can't find a way to test it.
done()
(passing the done parameter) and using async? Angular's test source code usesasync()
instead ofdone()
. I am trying to understand howasync()
recognizes all asynchronous calls are done. This might be worth another full question... – Quaternion