How to inject Document in service?
I have an Angular 2 application. For mocking the Document
object in tests, I'd like to inject it to the service like:
import { Document } from '??'
@Injectable()
export class MyService {
constructor(document: Document) {}
}
The Title
service of Angular uses the internal getDOM()
method.
Is there any simple way to inject the Document
to the service? Also, how should I reference it in the providers
array?
Solution 1:
This has been supported by Angular for a while.
You can use the DOCUMENT
constant provided by the @angular/common
package.
Description of the DOCUMENT
constant (taken from the API documentation):
A DI Token representing the main rendering context. In a browser, this is the DOM Document.
An example is as shown below:
my-service.service.ts:
import { Inject, Injectable } from '@angular/core';
import { DOCUMENT } from '@angular/common';
@Injectable()
export class MyService {
constructor(@Inject(DOCUMENT) private document: Document) {}
}
my-service.service.spec.ts
import { provide } from '@angular/core';
import { DOCUMENT } from '@angular/common';
import { MyService } from './my-service';
class MockDocument {}
describe('MyService', () => {
beforeEachProviders(() => ([
provide(DOCUMENT, { useClass: MockDocument }),
MyService
]));
...
});
Solution 2:
I'm unable to comment directly on adamdport's question (not yet 50 rep points), but here it is as stated in the angular docs.
Blockquote @GünterZöchbauer it looks like DOCUMENT is deprecated. Any idea how to do this once it's gone? For example, how would I set the favicon dynamically?
Instead of importing from platform browser like so:
import { DOCUMENT } from '@angular/platform-browser';
Import it from angular common:
import {DOCUMENT} from '@angular/common';
Solution 3:
in addition to @Günter Zöchbauer's answer.
Angular define DOCUMENT as an InjectionToken
export const DOCUMENT = new InjectionToken<Document>('DocumentToken');
dom_tokens.ts
And inject it with document in browser.ts
{provide: DOCUMENT, useFactory: _document, deps: []}
export function _document(): any {
return document;
}
Therefore, when we use it, we just need to inject @Inject(DOCUMENT)
or use the token directly in deps:[DOCUMENT]