Search code examples
angulartestbedangular-dom-sanitizer

How to use a DomSanitizer inside a unit test, if the component does not inject it?


I have a simple component, which does not inject the DomSanitizer. Let's say it is

export class ExampleComponent {

    @Input()
    public safeHtml: SafeHtml | undefined;

}

How can I use the DomSanitizer inside a unit test? I've tried providing and injecting it. Here goes my spec.ts file:

describe('ExampleComponent', () => {
    let component: ExampleComponent;
    let fixture: ComponentFixture<ExampleComponent>;
    let sanitizer: DomSanitizer;

    await TestBed.configureTestingModule({
        beforeEach(async() => {
            declarations: [ExampleComponent],
            providers: [DomSanitizer]        // it is not injected by ExampleComponent
        }).compileComponents();
    });

    beforeEach(() => {
        fixture = TestBed.createComponent(ExampleComponent);
        component = fixture.componentInstance;
        fixture.detectChanges();
        sanitizr = TestBed.inject(DomSanitizer);  // my attempt, though...
    });

    it('should work with SafeHtml input', () => {
        expect(component).toBeTruthy();
        let text = 'bla&shy;bla';
        let safeText: SafeHtml = sanitizer.bypassSecurityTrustHtml(text); // TypeError here
        component.safeHtml = safeText;
        expect(true);
    });
}

The TypeError says: TypeError: sanitizr.bypassSecurityTrustHtml is not a function.

Is there a way to make use of a real DoMSanitizer in a testbed even if the real component does not use it?


Solution

  • I got it to work by injecting the DomSanitizer and by removing it from the testbed's providers: [] array.

    describe('ExampleComponent', () => {
        let component: ExampleComponent;
        let fixture: ComponentFixture<ExampleComponent>;
        let sanitizer: DomSanitizer;
    
        await TestBed.configureTestingModule({
            beforeEach(async() => {
                declarations: [ExampleComponent],
            }).compileComponents();
            sanitizr = TestBed.inject(DomSanitizer); // injecting it here
        });
    
        beforeEach(() => {
            fixture = TestBed.createComponent(ExampleComponent);
            component = fixture.componentInstance;
            fixture.detectChanges();
        });
    
        it('should work with SafeHtml input', () => {
            expect(component).toBeTruthy();
            let text = 'bla&shy;bla';
            let safeText: SafeHtml = sanitizer.bypassSecurityTrustHtml(text); // no more typeError
            component.safeHtml = safeText;
            fixture.detectChanges();
            expect(component.safeHtml).toEqual({"changingThisBreaksApplicationSecurity": "blabla"});
            let p = fixture.nativeElement.querySelector('p'); // my ExampleComponent shows the safeHtml variable inside a paragraph.
            expect(p.innerHtml).toEqual('blabla');
        });
    }
    

    Note the returned SafeHtml variable's content became interestingly an object with {"changingThisBreaksApplicationSecurity": ...}.