Reputation: 1362
My use case is the following:
code for the child library
import { NgModule } from '@angular/core';
import {CommonModule} from "@angular/common";
@NgModule({
imports: [CommonModule],
declarations: [
SampleDirective
],
exports: [
SampleDirective
]
})
export class ChildModule { }
The code for the directive in the child library
import {Directive, PLATFORM_ID, Inject} from '@angular/core';
@Directive({
selector: '.sample'
})
export class SampleDirective {
constructor(@Inject(PLATFORM_ID) private _element: Object) {
}
}
In the parent I Installed the child module and I'm doing the following simple unit test
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import {Component} from '@angular/core';
import {ChildModule} from "@nz/child-lib";
@Component({
selector: 'nz-host',
template: `
<div class="sample"></div>
`
})
export class TestWrapperComponent{}
describe('injection problem', () => {
let testFixture: ComponentFixture<TestWrapperComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [TestWrapperComponent],
imports: [ChildModule]
});
}));
beforeEach(async(() => {
testFixture = TestBed.createComponent(TestWrapperComponent);
testFixture.detectChanges();
}));
it('test', () => {
expect(true).toBe(true);
});
});
When I run the tests I'm getting the following error:
StaticInjectorError[InjectionToken Platform ID]: NullInjectorError: No provider for InjectionToken Platform ID! Error: StaticInjectorError[InjectionToken Platform ID]: at _NullInjector.get (webpack:///node_modules/@angular/core/esm5/core.js:923:0 <- spec.bundle.js:3517:19) at resolveToken (webpack:///node_modules/@angular/core/esm5/core.js:1211:0 <- spec.bundle.js:3805:24) at tryResolveToken (webpack:///node_modules/@angular/core/esm5/core.js:1153:0 <- spec.bundle.js:3747:16) at StaticInjector.get (webpack:///node_modules/@angular/core/esm5/core.js:1024:0 <- spec.bundle.js:3618:20) at resolveToken (webpack:///node_modules/@angular/core/esm5/core.js:1211:0 <- spec.bundle.js:3805:24) at tryResolveToken (webpack:///node_modules/@angular/core/esm5/core.js:1153:0 <- spec.bundle.js:3747:16) at StaticInjector.get (webpack:///node_modules/@angular/core/esm5/core.js:1024:0 <- spec.bundle.js:3618:20) at resolveNgModuleDep (webpack:///node_modules/@angular/core/esm5/core.js:10584:0 <- spec.bundle.js:13178:25) at NgModuleRef_.get (webpack:///node_modules/@angular/core/esm5/core.js:11805:0 <- spec.bundle.js:14399:16) at resolveDep (webpack:///node_modules/@angular/core/esm5/core.js:12301:0 <- spec.bundle.js:14895:45)
My package.json is this:
"dependencies": {
"tslib": "^1.7.1"
},
"peerDependencies": {
"@angular/common": ">= 5.0.0",
"@angular/core": ">= 5.0.0"
},
"devDependencies": {
"@angular/animations": "5.0.0",
"@angular/common": "5.0.0",
"@angular/compiler": "5.0.0",
"@angular/compiler-cli": "5.0.0",
"@angular/core": "5.0.0",
"@angular/platform-browser": "5.0.0",
"@angular/platform-browser-dynamic": "5.0.0",
"@angular/platform-server": "5.0.0",
"@compodoc/compodoc": "1.0.3",
"@nz/child-lib": "^0.0.1",
"@types/jasmine": "2.6.2",
"@types/node": "8.0.47",
"chalk": "2.3.0",
"codelyzer": "4.0.2",
"core-js": "2.5.1",
"istanbul-instrumenter-loader": "3.0.0",
"jasmine-core": "2.8.0",
"karma": "1.7.1",
"karma-chrome-launcher": "2.2.0",
"karma-coverage-istanbul-reporter": "1.3.0",
"karma-jasmine": "1.1.0",
"karma-sourcemap-loader": "0.3.7",
"karma-spec-reporter": "0.0.31",
"karma-webpack": "2.0.5",
"reflect-metadata": "0.1.10",
"rollup": "0.50.0",
"rollup-plugin-license": "0.5.0",
"rollup-plugin-node-resolve": "3.0.0",
"rollup-plugin-sourcemaps": "0.4.2",
"rxjs": "5.5.2",
"shelljs": "0.7.8",
"source-map-loader": "0.2.3",
"ts-loader": "3.1.1",
"tslint": "5.8.0",
"tslint-angular": "1.0.0",
"typescript": "2.4.2",
"uglify-js": "3.1.6",
"webpack": "3.8.1",
"zone.js": "0.8.18"
}
Even when mocking the PLATFORM_ID with the following code
{provide: PLATFORM_ID, useValue: 'browser'}
The error is still there.
packages as symlinks
I have a new theory why it happens on my end. I think since I'm using lerna to manage my packages and packages dependency. And since I added the child module to the host module through lerna, then lerna creates a symlink of the child module in the node modules of the host. So my theory is that the DI can't identify what he needs to inject when the library we are using is symlinked. Trying to figure out how to run the tests with --preserve-symlinks
Thanks a lot
Upvotes: 4
Views: 3134
Reputation: 95
I encountered the same issue with Angular 6 multi-modules project and with Lerna.
First, there is an option called preserveSymLinks
to set to true
in Angular configuration file (angular.json
in Angular 6).
After that, I was able to link the module to my project with a symbolik link but not with Lerna link. I don't know why yet but I have to do this with a mklink command on Windows environment.
Upvotes: 1
Reputation: 1362
So the problem was indeed symlinks. when using symlinks in your node_modules or using a package management tool like lerna (which links internal packages with symlink). Than angular won't know how to inject the items properly.
The solution for me was before running the tests to remove the symlinks install the packages with a hard copy and then run the tests.
Upvotes: 2