In writing tests for my Angular 2 app, I am running into these errors: the selectors we're using:
"): AppComponent#12:35 'tab-view' is not a known element:
1. If 'my-tab' is an Angular component, then verify that it is part of this module.
2. If 'my-tab' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '#NgModule.schemas' of this component to suppress this message. ("
</div>
<div class="app-body">
[ERROR ->]<tab-view class="my-tab" [options]="tabOptions"></tab-view>
</div> </div>
I have added CUSTOM_ELEMENTS_SCHEMA to my root module, as well as all other modules, but I am still getting the errors.
What else do I need to do?
Does this need to be in all modules, or just the root?
Is there anything else I need to add?
So what I had to do to get this working was also set the schemas in the TestBed.configureTestingModule - which is not a separate module file, but a part of the app.component.spec.ts file. Thanks to #camaron for the tip. I do think the docs could be a clearer on this point.
Anyway, this is what I added to get it to work. Here are the opening contents of my app.component.spec.ts file.
import { TestBed, async } from '#angular/core/testing';
import { AppComponent } from './../app.component';
import { RouterTestingModule } from '#angular/router/testing';
import { CUSTOM_ELEMENTS_SCHEMA } from '#angular/core';
describe('AppComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
schemas: [ CUSTOM_ELEMENTS_SCHEMA ],
declarations: [AppComponent],
imports: [RouterTestingModule]
});
TestBed.compileComponents();
});
It works for me this way, in your spec.ts file you have to import your components and needs to add it to declarations. In my case its in about.component.spec.ts
import { async, ComponentFixture, TestBed } from '#angular/core/testing';
import { AboutComponent } from './about.component';
import { SidebarComponent } from './../sidebar/sidebar.component';
import { FooterComponent } from './../footer/footer.component';
describe('AboutComponent', () => {
let component: AboutComponent;
let fixture: ComponentFixture<AboutComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ AboutComponent, SidebarComponent, FooterComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AboutComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
Related
I've spend the last few days trying to get up to speed with ng test and all the spec files #angular/cli creates when creating components and, well, pretty much else.
As I was working on my own portfolio website, I have come across an issue that I cannot seem to understand or fix.
I have this component (pretty vanilla stuff):
import { Component, OnInit } from '#angular/core';
import { ActivatedRoute } from '#angular/router';
import { Title } from '#angular/platform-browser'
import { ProjectDetails } from './project-details'
#Component({
selector: 'app-projects-details',
templateUrl: './projects-details.component.html',
styleUrls: ['./projects-details.component.sass']
})
export class ProjectsDetailsComponent implements OnInit {
// Class variables
currentContent: ProjectDetails
constructor(
private route : ActivatedRoute,
private title: Title
) { }
ngOnInit() {
// Assign the data to local variable for use
this.route.data.subscribe(content => {
this.currentContent = content.project.view //<-- This line causes the issue
// Set the title for the Projects view
this.title.setTitle(this.currentContent.view_title)
})
}
}
And this spec file (more vanilla stuff):
import { async, ComponentFixture, TestBed } from '#angular/core/testing';
import { RouterTestingModule } from '#angular/router/testing'
import { ProjectsDetailsComponent } from './projects-details.component';
import { ProjectDetails } from './project-details'
describe('ProjectsDetailsComponent', () => {
let component: ProjectsDetailsComponent;
let fixture: ComponentFixture<ProjectsDetailsComponent>;
const projectDetails : ProjectDetails = { /* valid object content */ }
beforeEach(async(() => {
TestBed.configureTestingModule({
imports:[
RouterTestingModule
],
declarations: [ ProjectsDetailsComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ProjectsDetailsComponent);
component = fixture.componentInstance;
component.currentContent = projectDetails
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
When running the tests, I get this error:
TypeError: content.project is undefined in http://localhost:9876/_karma_webpack_/main.js (line 1576)
So, I'm not sure exactly what's going on here. No matter what I do, the error prevails.I have a similarly setup component that doesn't have this issue and a side by side comparison shows no differences in the spec.ts file aside from imports.
I tried changing the file to this:
import { async, ComponentFixture, TestBed } from '#angular/core/testing';
import { RouterTestingModule } from '#angular/router/testing'
import { ProjectsDetailsComponent } from './projects-details.component';
import { ProjectDetails } from './project-details'
import { ActivatedRoute } from '#angular/router';
describe('ProjectsDetailsComponent', () => {
let component: ProjectsDetailsComponent;
let fixture: ComponentFixture<ProjectsDetailsComponent>;
const projectDetails : ProjectDetails = {/* valid content */}
beforeEach(async(() => {
TestBed.configureTestingModule({
// imports:[
// RouterTestingModule
// ],
providers: [
{ provide: ActivatedRoute, useValue: projectDetails }
],
declarations: [ ProjectsDetailsComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ProjectsDetailsComponent);
component = fixture.componentInstance;
component.currentContent = projectDetails
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
Which changes the error to this (which confuses me more):
TypeError: this.route.data is undefined in http://localhost:9876/_karma_webpack_/main.js (line 1575)
The question to the community: how do I fix this? What's the reason this error is coming up?
Instead of providing the raw projectDetails, provide an Observable in its data property:
import {of} from 'rxjs';
...
beforeEach(async(() => {
TestBed.configureTestingModule({
providers: [
// Properly provide the activated route mock object.
{ provide: ActivatedRoute, useValue: { data: of(projectDetails) } }
],
declarations: [ ProjectsDetailsComponent ]
})
.compileComponents();
}));
...
If you look at how you access the route data, you can see that it uses an Observable:
this.route.data.subscribe(content => {...});
I have an Angular project that whatever spec file I created to test any component is failing due Error: Illegal state: Could not load the summary for directive ...
For example, I created a component that contains some Material design tags, and belongs to a module called PagesModule, the component does not do anything:
pages.module.ts
import { NgModule } from '#angular/core';
import { RouterModule } from '#angular/router';
import { SharedModule } from '../_shared/shared.module';
import { NotFoundComponent } from './error/not-found/not-found.component';
#NgModule({
declarations: [NotFoundComponent],
imports: [SharedModule, RouterModule],
exports: [],
providers: []
})
export class PagesModule {}
not-found.component.spec.ts
import { async, ComponentFixture, TestBed } from '#angular/core/testing';
import { MatCardModule } from '#angular/material';
import { NotFoundComponent } from './not-found.component';
describe('NotFoundComponent', () => {
let component: NotFoundComponent;
let fixture: ComponentFixture<NotFoundComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [SharedModule],
declarations: [NotFoundComponent]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(NotFoundComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeDefined();
});
});
Additional information:
My SharedModule is already exporting all necessary material modules.
Your NotFoundComponent may contain nested components or directives, whose templates may contain more components. There are basically two techniques to deal with this in your tests (see. Nested component tests).
create and declare stub versions of the components and directives
add NO_ERRORS_SCHEMA to the TestBed.schemas metadata.
When opting for the first solutions, your test could look something like this.
#Component({selector: 'app-nested', template: ''})
class NestedStubComponent {}
describe('NotFoundComponent', () => {
...
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [SharedModule],
declarations: [NotFoundComponent]
}).compileComponents();
}));
When opting for the second solution, TestBed.configureTestingModule would have to be changed as follows.
TestBed.configureTestingModule({
imports: [SharedModule],
declarations: [NotFoundComponent],
schemas: [NO_ERRORS_SCHEMA]
}).compileComponents();
Hi have some error with testing my App made with Angular 7. I do not have much experience in angular, so I would need your help+
Error: StaticInjectorError(DynamicTestModule)[BeerDetailsComponent -> ActivatedRoute]:
StaticInjectorError(Platform: core)[BeerDetailsComponent -> ActivatedRoute]:
NullInjectorError: No provider for ActivatedRoute!
the testing code is like this:
import { async, ComponentFixture, TestBed, inject } from '#angular/core/testing';
import { BeerDetailsComponent } from './beer-details.component';
import {
HttpClientTestingModule,
HttpTestingController
} from '#angular/common/http/testing';
describe('BeerDetailsComponent', () => {
let component: BeerDetailsComponent;
let fixture: ComponentFixture<BeerDetailsComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
declarations: [ BeerDetailsComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(BeerDetailsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create',
inject(
[HttpTestingController],
() => {
expect(component).toBeTruthy();
}
)
)
});
I really can't find any solution.
Daniele
You have to import RouterTestingModule
import { RouterTestingModule } from "#angular/router/testing";
imports: [
...
RouterTestingModule
...
]
Add the following import
imports: [
RouterModule.forRoot([]),
...
],
I had this error for some time as well while testing, and none of these answers really helped me. What fixed it for me was importing both the RouterTestingModule and the HttpClientTestingModule.
So essentially it would look like this in your whatever.component.spec.ts file.
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ProductComponent],
imports: [RouterTestingModule, HttpClientTestingModule],
}).compileComponents();
}));
You can get the imports from
import { RouterTestingModule } from "#angular/router/testing";
import { HttpClientTestingModule } from "#angular/common/http/testing";
I dont know if this is the best solution, but this worked for me.
This issue can be fixed as follows:
In your corresponding spec.ts file import RouterTestingModule
import { RouterTestingModule } from '#angular/router/testing';
In the same file add RouterTestingModule as one of the imports
beforeEach(() => {
TestBed.configureTestingModule({
imports: [RouterTestingModule],
providers: [Service]
});
});
Example of a simple test using the service and ActivatedRoute! Good luck!
import { async, ComponentFixture, TestBed } from '#angular/core/testing';
import { RouterTestingModule } from '#angular/router/testing';
import { HttpClientModule } from '#angular/common/http';
import { MyComponent } from './my.component';
import { ActivatedRoute } from '#angular/router';
import { MyService } from '../../core/services/my.service';
describe('MyComponent class test', () => {
let component: MyComponent;
let fixture: ComponentFixture<MyComponent>;
let teste: MyComponent;
let route: ActivatedRoute;
let myService: MyService;
beforeEach(async(() => {
teste = new MyComponent(route, myService);
TestBed.configureTestingModule({
declarations: [ MyComponent ],
imports: [
RouterTestingModule,
HttpClientModule
],
providers: [MyService]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(MyComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('Checks if the class was created', () => {
expect(component).toBeTruthy();
});
});
This is my test file and I am trying to identify the error preventing me from running a successful test:
import { async, ComponentFixture, TestBed } from '#angular/core/testing';
import { Component, Directive, Input, OnInit } from '#angular/core';
import { TestComponent } from './test.component';
import { NgbDropdownModule, NgbCollapse } from '#ng-bootstrap/ng-bootstrap';
import { CommonModule } from '#angular/common';
import { Routes } from '#angular/router';
import { RouterTestingModule } from '#angular/router/testing';
import { NO_ERRORS_SCHEMA } from '#angular/core';
import {BrowserDynamicTestingModule, platformBrowserDynamicTesting} from '#angular/platform-browser-dynamic/testing';
let comp: TestComponent;
let fixture: ComponentFixture<MyComponent>;
describe('TestComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [ TestComponent ],
providers: [
// DECLARE PROVIDERS HERE
{ provide: TestingCompilerFactory }
]
}).compileComponents()
.then(() => {
fixture = TestBed.createComponent(TestComponent);
comp = fixture.componentInstance;
});
}));
it('should be created', () => {
expect(TestComponent).toBeTruthy();
});
I am getting this error which I guess is because I am not wrapping it correctly.
error TS1005: ';' expected.
But I also get
No provider for TestingCompilerFactory
First fix your syntax error1,2
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [TestComponent],
providers: [{ provide: TestingCompilerFactory }]
})
.compileComponents()
.then(() => {
fixture = TestBed.createComponent(TestComponent);
comp = fixture.componentInstance;
});
}); // excess `)` removed
Now, onto the noteworthy error
A provider takes can take two forms.
The first is a value that acts as both the value provided and the key under which it is registered. This commonly takes the form of a class as in the following example
const Dependency = class {};
#NgModule({
providers: [Dependency]
}) export default class {}
The second is an object with a provide property specifying the key under which the provider is registered and one or more additional properties specifying the value being provided. A simple example is
const dependencyKey = 'some key';
const Dependency = class {};
#NgModule({
providers: [
{
provide: dependencyKey,
useClass: Dependency
}
]
}) export default class {}
From the above it you can infer that you failed to specify the actual value provided under the key TestingCompilerFactory.
To resolve this write
TestBed.configureTestingModule({
declarations: [TestComponent],
providers: [
{
provide: TestingCompilerFactory,
useClass: TestingCompilerFactory
}
]
})
which is redundant and can be replaced with
TestBed.configureTestingModule({
declarations: [TestComponent],
providers: [TestingCompilerFactory]
})
as described above.
Notes
In the future do not post questions that include such an obvious error - fix it yourself instead.
Do not post two questions as one.
I'm writing test cases for my project. But unfortunately, after starting the tests by typing ng test, I'm receiving following error:
Error: Error in :0:0 caused by: Plotly is
ReferenceError: Plotly is not defined
Plotly is an external, chart library. I've tried to declare it inside the test file:
import { async, ComponentFixture, TestBed } from '#angular/core/testing';
import { By } from '#angular/platform-browser';
import { DebugElement } from '#angular/core';
import { FormsModule } from '#angular/forms';
import { MaterialModule } from '#angular/material';
import { WatchlistComponent } from './watchlist.component';
declare let Plotly: any;
describe('SystemComponent', () => {
let component: WatchlistComponent;
let fixture: ComponentFixture<WatchlistComponent>;
let element;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ WatchlistComponent ],
imports: [ FormsModule, MaterialModule ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(WatchlistComponent);
component = fixture.componentInstance;
element = fixture.nativeElement;
fixture.detectChanges();
});
it('should return a positive number', () => {
expect(component.getScreenHeight()).toMatch(/\d+/);
});
});
Unfortunately, it still doesn't see the Plotly and returns error. The first test case for getScreenHeight() function is not even being started.
Maybe jasmine is starting the tests even before it was uploaded?
Edit:
I'm importing Plotly by including <script src='plotly.js'></script> in my index.html file. Plotly is stored locally in the same folder as index.html is.
Load plotly.js (with appropriate path) file into Karma testing env by adding files config in karma.config.js as below:
karma.config.js
config.set({
..
files: ['plotly.js']
..
});