How to include external library into unit tests::Angular2-CLI - javascript

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']
..
});

Related

Karma + Jasmine - Default unit test "it should create" failing with error "Uncaught TypeError: Cannot read property 'nativeElement' of undefined"

I have an extremely simple unit test -- the test that is automatically generated by Angular.
import { Component, CUSTOM_ELEMENTS_SCHEMA } from '#angular/core';
import { NO_ERRORS_SCHEMA } from '#angular/core';
import { async, ComponentFixture, TestBed } from '#angular/core/testing';
import { CtaSecondaryComponent } from './cta-secondary.component';
describe('CtaSecondaryComponent', () => {
let component: CtaSecondaryComponent;
let fixture: ComponentFixture<CtaSecondaryComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ CtaSecondaryComponent ],
schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(CtaSecondaryComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
I am getting an error about 50% of the time (i.e. no changes to the test -- sometimes it fails sometimes it passes):
Uncaught TypeError: Cannot read property 'nativeElement' of undefined thrown
As far as I can tell, there is no reference to nativeElement anywhere in this component. In fact, there is no reference to nativeElement anywhere in this entire project. I cannot find anyone else with this issue online. Can anyone provide some input?
cta-secondary.component.html
<!-- button -->
<button [ngClass]="{'disabled': disabled}" class="btn btn-secondary">
<span>{{label}}</span>
</button>
cta-secondary.component.ts
import {Component, Input, OnInit, HostListener, ElementRef} from '#angular/core';
#Component({
selector: 'fuse-cta-secondary',
templateUrl: './cta-secondary.component.html',
styleUrls: ['./cta-secondary.component.scss']
})
export class CtaSecondaryComponent implements OnInit {
// label for cta secondary
#Input() label: string;
#Input() disabled: boolean;
constructor() { }
ngOnInit() {
}
}
Versions:
angular/core: 8.2.2
karma: 6.3.4
jasmine-core: 2.99.1
node: 12.18.3
I ended up "solving" this myself. Switching to PhantomJS from chrome-headless as the browser in karma.config.js to appears to have solved the issue. Perhaps chrome-headless had cached something. Either way, this appears to be working as expected now.
Maybe someone else can chime in on if there's some sort of cache resetting that needs to be done in headless-chrome?

Karma/Jasmine Angular InjectionToken Test fails unless I use fdescribe

I have the following spec test:
import { HttpClientTestingModule } from '#angular/common/http/testing';
import { Component } from '#angular/core';
import { ComponentFixture, TestBed } from '#angular/core/testing';
import { of } from 'rxjs';
import { BASE_API_URL } from 'src/app/tokens/baseApiUrl.token';
import { RbacPermissionsService } from '../services/rbac-permissions.service';
import { SharedModule } from '../shared.module';
#Component({
selector: 'app-mock-test',
template: `<div *appHasPermission="{ items: 'view' }"></div>`,
providers: []
})
export class MockTestComponent {
constructor() {}
}
describe('HasPermissionDirective', () => {
let mockTestComponent: MockTestComponent;
let mockTestFixture: ComponentFixture<MockTestComponent>;
let rbacPermissionsService: RbacPermissionsService;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [MockTestComponent],
imports: [SharedModule, HttpClientTestingModule],
providers: [{provide: BASE_API_URL, useValue: '/some_api/'}]
});
rbacPermissionsService = TestBed.get(RbacPermissionsService);
mockTestFixture = TestBed.createComponent(MockTestComponent);
mockTestComponent = mockTestFixture.componentInstance;
});
it('should have no divs when permission is false', done => {
spyOn(rbacPermissionsService, 'getPermission').and.returnValue(of(false));
mockTestFixture.whenStable().then(() => {
mockTestFixture.detectChanges();
const divs = mockTestFixture.nativeElement.getElementsByTagName('div');
expect(divs.length).toBeFalsy();
done();
});
});
it('should have a visible view element when permission is true', done => {
spyOn(rbacPermissionsService, 'getPermission').and.returnValue(of(true));
mockTestFixture.whenStable().then(() => {
mockTestFixture.detectChanges();
const divs = mockTestFixture.nativeElement.getElementsByTagName('div');
expect(divs.length).toBeTruthy();
done();
});
});
});
When I run this in conjunction with all other tests, it fails with the error:
NullInjectorError: StaticInjectorError(DynamicTestModule)[InjectionToken ]:
StaticInjectorError(Platform: core)[InjectionToken ]:
NullInjectorError: No provider for InjectionToken !
But when I run it with fdescribe the tests pass.
I wholeheartedly admit that spec tests are not my strong suit. My gut says their might be a timing issue since the tests work in isolation but not when run as part of the larger group of tests.

Whatever test I created in my Angular project is failing due Error: Illegal state: Could not load the summary for directive NotFoundComponent

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();

typescript not loading at runtime

I have a web app that was started in VS2015 using Angular 2 and was working for as far as it went. I upgraded it to VS2017 and had to make a few changes, but in the main all seems ok. I don't receive any compile time errors. During the run phase, when I'm attempting to load a page, the page doesn't fully render and I don't get any real errors on screen. I'm using I.E.11 and when I look in the console I get the following error:
Error: Syntax error
Evaluating http://localhost:42413/app/app.module.js
Evaluating http://localhost:42413/app/main.js
Loading app
the Two files in question are in the place expected and no code has changed around these files since I did the port.
In my main.ts file I have:
import { platformBrowserDynamic } from '#angular/platform-browser-dynamic';
import { AppModule } from './app.module';
platformBrowserDynamic().bootstrapModule(AppModule);
and in app.module.js I have:
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { HttpModule } from '#angular/http';
import { FormsModule } from '#angular/forms';
import { AppComponent } from './app.component';
import { AgentDetailsComponent } from './recruiter/agent-details.component';
#NgModule({
imports: [
BrowserModule,
HttpModule,
FormsModule
],
declarations: [
AppComponent,
AgentDetailsComponent
],
bootstrap: [AppComponent]
})
export class AppModule { }
The error occurs on the second line of main.ts: import { AppModule } from './app.module' Setting breakpoints it does not get to the first line in this file. Stepping the JS files. It first goes through the register-loader.js file which calls evaluate.js. It then fails in the evaluate method. There is a huge stacktrace, but basically it's erroring in the files that are under node_modules.
If I run in a chrome browser I receive the an error from zone.js stating that it cannot load http://localhost:42413/agent-details.component.html.
Within my projects wwwroot directory this component sits in my app\recruiter folder.
In the app.module.ts folder it is referenced as :
import { AgentDetailsComponent } from './recruiter/agent-details.component';
and the above line hovering over ./recruiter/agent-details.component shows the correct path in the tooltips.
In Chrome itself the error seems to occur whilst performing platformBrowserDynamic().bootstrapModule(AppModule); declared in main.ts
my agent-details.component.ts file has:
import { Component, OnInit } from '#angular/core';
import { Router, ActivatedRoute } from '#angular/router';
import { ICountry } from '../services/interfaces/country';
import { RecruiterService } from '../services/recruiter/recruiter.service';
#Component({
selector: 'agent-details',
templateUrl: 'agent-details.component.html',
providers : [RecruiterService]
})
export class AgentDetailsComponent implements OnInit {
private countries: ICountry[] = [];
private errorMessage: string;
constructor(private recruiterService : RecruiterService) {
}
getCountries() {
this.recruiterService.getCountries().subscribe((countries: ICountry[]) => this.countries = countries);
}
ngOnInit(): void {
this.getCountries();
}
}

"CUSTOM_ELEMENTS_SCHEMA" Errors in Testing Angular 2 App

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();
});
});

Categories

Resources