I am trying to write unit test cases for Grid, for this I need to loop through gridapi data but it is giving me Cannot read undefined forEachNode error.
myComponent.component.ts.
import { Component, OnInit, } from '#angular/core';
import { GridOptions, GridApi, } from "ag-grid-community";
#Component({
selector: 'my-component',
templateUrl: './mycomponent.component.html',
styleUrls: ['./mycomponent.component.scss']
})
export class MyComponent implements OnInit {
grid: GridOptions;
data;
constructor() {}
getData() {
this.grid.api.forEachNode((node) =>
this.data.push(node.data.id);
);
}
}
mycomponent.component.spec.ts:
import { ComponentFixture, TestBed, waitForAsync } from '#angular/core/testing';
import { Mycomponent} from './mycomponent.component';
describe('Mycomponent', () => {
let component: Mycomponent;
let fixture: ComponentFixture<Mycomponent>;
beforeEach(
waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [Mycomponent],
}).compileComponents();
})
);
beforeEach(() => {
fixture = TestBed.createComponent(Mycomponent);
component = fixture.componentInstance;
const gridObj = jasmine.createSpyObj('grid', [
'api',
]);
gridObj.grid.api.and.returnValue({
context: {}
data : { id:1,name: 'columName'}
});
component.grid = gridObj;
fixture.detectChanges();
});
it(`should call getData method.`, () => {
component.getData();
expect(component.data).toEqual('[1]');
});
});
When I try to run above test case,
TypeError: Cannot read properties of undefined (reading 'forEachNode').
Can any one tell me where I am doing wrong.
Related
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.
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 => {...});
One of the components that I'm testing is importing a constants file which is located outside the /src folder. When I run the test, there is an error inside the component.ts file saying that the constants object is undefined. Below are the details. Any help will be very helpful. Thanks in advance.
This is an error I'm getting when I run ng test.
Error :
TypeError: Cannot read property 'ROUTE_SERVICE_USER' of undefined
at WelcomeComponent../src/app/welcome/welcome.component.ts.WelcomeComponent.ngOnInit (http://localhost:9876/src/app/welcome/welcome.component.ts?:24:30)
Folder Structure :
AppConstants.js :
const AppConstants = {
HEADER_LANG: 'Content-Language',
HEADER_LANG_LOWER: 'content-language',
ROUT_WELCOME: '/welcome',
ROUT_NEWUSER: '/newuser',
ROUTE_SERVICE_USER: '/service/user/registered',
};
module.exports = AppConstants;
Welcome.component.ts :
import { Component, OnInit } from '#angular/core';
import AppConstants from '../../../common/AppConstants.js';
#Component({
selector: 'app-welcome',
templateUrl: './welcome.component.html',
styleUrls: ['./welcome.component.css']
})
export class WelcomeComponent implements OnInit {
constructor() {
}
ngOnInit() {
console.log(AppConstants.ROUTE_SERVICE_USER);
}
}
Welcome.component.spec.ts :
import { async, ComponentFixture, TestBed } from '#angular/core/testing';
import { WelcomeComponent } from './welcome.component';
describe('WelcomeComponent', () => {
let component: WelcomeComponent;
let fixture: ComponentFixture<WelcomeComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ WelcomeComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(WelcomeComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
I'm trying to test pieces of jquery code that are set on ngOnInit() of my angular app.These code adds and removes certain classes based on conditions that are identified using jquery functions.
Below is my component:
import { Component, OnInit, AfterContentInit } from '#angular/core';
declare var $: any;
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
constructor() { }
ngOnInit() {
if ($('#js-drawer') !== undefined && $('#js-drawer').hasClass('pxh-drawer--narrow#lg')) {
$('#gf-header').removeClass('pxh-view-header--animate-narrow pxh-view-header--narrow#lg');
} else if ($('#js-drawer') !== undefined && $('#js-drawer').hasClass('pxh-drawer--wide#lg')) {
$('#gf-header').addClass('pxh-view-header--animate-narrow pxh-view-header--narrow#lg');
}
}
}
and below is the test case that I tried.
import { async, ComponentFixture, TestBed } from '#angular/core/testing';
declare var $;
fdescribe('AppComponent Test', () => {
let component: any;
let fixture: ComponentFixture<AppComponent>;
beforeEach(async(() => {
jasmine.DEFAULT_TIMEOUT_INTERVAL = 100000;
TestBed.configureTestingModule({
declarations: [AppComponent],
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AppComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should be created', () => {
expect(component).toBeTruthy();
});
it('test onInit function', () => {
const case1 = $('#js-drawer');
const case2 = $('#js-drawer').hasClass('pxh-drawer--narrow#lg');
spyOn($('#gf-header'), 'removeClass');
component.ngOnInit();
if (case1 && case2) {
expect($('#gf-header')).toHaveBeenCalledWith('removeClass');
}
});
});
Do let me know if this is the right way to test..Thanks
I have the following error (unit testing Angular2):
Cannot configure the test module when the test module has already been
instantiated. Make sure you are not using inject before
TestBed.configureTestingModule
Here is my code (it's basically a copy paste from the angular docs) which throws the above error:
import { TestBed, async } from '#angular/core/testing';
import { By } from '#angular/platform-browser';
import { AppModule } from './app.module';
import { AppComponent } from './app.component'
import { MyServiceService } from './my-service.service'
beforeEach(() => {
// stub UserService for test purposes
let userServiceStub = {
isLoggedIn: true,
user: { name: 'Test User'}
};
TestBed.configureTestingModule({
declarations: [ AppComponent],
providers: [ {provide: MyServiceService, useValue: userServiceStub } ]
});
let fixture = TestBed.createComponent(AppComponent);
let comp = fixture.componentInstance;
// UserService from the root injector
let userService = TestBed.get(MyServiceService);
// get the "welcome" element by CSS selector (e.g., by class name)
let de = fixture.debugElement.query(By.css('.nesto'));
let el = de.nativeElement;
it('should welcome "Bubba"', () => {
userService.user.name = 'something'; // welcome message hasn't been shown yet
fixture.detectChanges();
expect(el.textContent).toContain('some');
});
});
I want to run a service but it seems that I just can't do that.
The most likely problem is that you're attempting to run testing within your beforeEach(). You need to make sure all it() methods are outside/after the beforeEach():
beforeEach(() => {
// stub UserService for test purposes
let userServiceStub = {
isLoggedIn: true,
user: { name: 'Test User'}
};
TestBed.configureTestingModule({
declarations: [ AppComponent],
providers: [ {provide: MyServiceService, useValue: userServiceStub } ]
});
let fixture = TestBed.createComponent(AppComponent);
let comp = fixture.componentInstance;
// get the "welcome" element by CSS selector (e.g., by class name)
let de = fixture.debugElement.query(By.css('.nesto'));
let el = de.nativeElement;
});
it('should welcome "Bubba"', inject([MyServiceService], (userService) => {
userService.user.name = 'something'; // welcome message hasn't been shown yet
fixture.detectChanges();
expect(el.textContent).toContain('some');
}));
This works, removed the instance in the beforeEach() and injected into the it().
All credits go to Z. Bagley
import { TestBed, async, inject } from '#angular/core/testing';
import { By } from '#angular/platform-browser';
import { AppModule } from './app.module';
import { AppComponent } from './app.component'
import { MyServiceService } from './my-service.service'
import { Inject } from '#angular/core';
beforeEach(() => {
// stub UserService for test purposes
let userServiceStub = {
isLoggedIn: true,
user: { name: 'Test User'}
};
TestBed.configureTestingModule({
declarations: [ AppComponent],
providers: [ {provide: MyServiceService, useValue: userServiceStub } ]
});
});
it('should welcome "Bubba"', inject([MyServiceService], (userService) => {
let fixture=TestBed.createComponent(AppComponent);
fixture.detectChanges();
expect(userService.user.name).toContain('se');
}));