This is my template:
<ion-label stacked>{{"goal_settings.goalname" | translate }}</ion-label>
I am getting the error: No value accessor for ""
This is my test:
describe('Goal Settings', () => {
let tcb;
let navParams;
let viewController;
let events;
// Providers and Mock Providers
beforeEachProviders(() => [
TestComponentBuilder,
HTTP_PROVIDERS,
provide(NavParams, {useClass: MockNavParams}),
provide(ViewController, {useClass: MockViewController}),
provide(Events, {useClass: MockEvents}),
provide('goal_settings', { useValue: [ {
goalname: "Super",
amount:"Super",
monthlypayment:"Super",
choosefund:"Super",
date:"Super",
guaranteelevel:"Super"
}]}),
provide(TranslateService, {
useFactory: (http: Http) => new TranslateStaticLoader(http, 'assets/i18n', '.json'),
deps: [Http]
}),
provide(TranslateLoader, {
useFactory: (http: Http) => new TranslateStaticLoader(http, 'assets/i18n', '.json'),
deps: [Http]
}),
provide(XHRBackend, { useClass: MockBackend })
]);
beforeEach(inject(
[
TestComponentBuilder,
NavParams,
ViewController,
Events
],
(
_tcb,
_navParams,
_viewController,
_events
) => {
tcb = _tcb
navParams = _navParams
viewController = _viewController
events = _events
}));
it('should contain <ion-title> directive', () => {
return tcb.createAsync(GoalSettingsPage).then((fixture) => {
fixture.detectChanges();
var compiled = fixture.debugElement.nativeElement;
expect(compiled.innerHTML).toContain('ion-title');
});
});
I think the problem is that goal_settings is wrongly mocked by me..
Related
I am trying to test my router event this is what te code in the TS file look like:
constructor(
private router: Router
) {
router.events.subscribe(route => {
// I removed the code because it doesn`t matter for the solution
});
}
unittest:
describe('MainComponent', () => {
let methodSpy: jasmine.Spy;
const eventSubject = new ReplaySubject<RouterEvent>(1);
const routerMock = {
navigate: jasmine.createSpy('navigateByUrl'),
navigateByUrl: jasmine.createSpy('navigateByUrl'),
events: eventSubject.asObservable(),
url: 'test/url',
createUrlTree: (commands, navExtras = {}) => {},
serializeUrl: (commands, navExtras = {}) => {}
}
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [RouterTestingModule, FormsModule],
declarations: [],
providers: [
{ provide: Router, useValue: routerMock},
{ provide: ActivatedRoute, useValue: routerMock},
]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(MainComponent);
component = fixture.componentInstance;
methodSpy = spyOn(component, 'AdminPanelStarted');
//fixture.detectChanges();
});
it('should trigger the router event and hit the function "Panel"', () => {
eventSubject.next(new NavigationEnd(1, 'test', 'routeUrl'));
expect(methodSpy).toHaveBeenCalled();
});
});
this is the error I am getting:
I can`t find the solution. The only thing I want to test is if the correct function have been called after entering the router.events subscription. The observable is triggered but gives the error that startsWith can not be done on undefined. But what is undefined?
Thx a Lot!
I am trying to spy popover present method in my ionic 5 / angular 11 project but getting an error
Unhandled Promise rejection: Cannot read property 'then' of undefined
Here is unit test code
describe('LoginPage', () => {
let popoverSpy = jasmine.createSpyObj('Popover', ['create', 'present', 'onDidDismiss', 'dismiss']);
let popoverCtrlSpy = jasmine.createSpyObj('PopoverController', ['create']);
popoverCtrlSpy.create.and.callFake(function () {
return popoverSpy;
});
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [LoginPage],
imports: [
IonicModule.forRoot(),
TranslateModule.forChild(),
ComponentsModule,
TranslateModule.forRoot({
loader: { provide: TranslateLoader, useClass: TranslateFakeLoader }
})
],
providers: [{ provide: PopoverController, useValue: popoverCtrlSpy }]
}).compileComponents()
it("check popover preset", () => {
component.openEntitySelection();
fixture.detectChanges();
expect(popoverSpy.present).toHaveBeenCalled()
})
}
private async openEntitySelection() {
let popover = await this.popoverCtrl.create({
component: PopoverPage
});
await popover.present();
popover.onDidDismiss().then((response) => {
//Handle response
})
}
Thanks in advance!
It seems you're not mocking onDidDismiss to return a promise. You also need to use fixture.whenStable or waitForAsync utilities to wait for the promise to be resolved before doing your assertion.
Try this:
describe('LoginPage', () => {
let popoverSpy = jasmine.createSpyObj('Popover', ['create', 'present', 'onDidDismiss', 'dismiss']);
// !! -- Add this line -- !!
// I am mock resolving it to a value of true, you can resolve it to any value
popOverSpy.onDidDismiss.and.returnValue(Promise.resolve(true));
// !! --- !!
let popoverCtrlSpy = jasmine.createSpyObj('PopoverController', ['create']);
popoverCtrlSpy.create.and.callFake(function () {
return popoverSpy;
});
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [LoginPage],
imports: [
IonicModule.forRoot(),
TranslateModule.forChild(),
ComponentsModule,
TranslateModule.forRoot({
loader: { provide: TranslateLoader, useClass: TranslateFakeLoader }
})
],
providers: [{ provide: PopoverController, useValue: popoverCtrlSpy }]
}).compileComponents()
it("check popover preset", (done) => { // add done to let jasmine know you're done
component.openEntitySelection();
fixture.detectChanges();
// you have to wait at least for one fixture.whenStable I am thinking
// because we are returning a promise and we have to ensure that the promises
// have completed before doing our assertion.
fixture.whenStable().then(() => {
expect(popoverSpy.present).toHaveBeenCalled();
done();
});
});
}
private async openEntitySelection() {
let popover = await this.popoverCtrl.create({
component: PopoverPage
});
await popover.present();
popover.onDidDismiss().then((response) => {
//Handle response
})
}
Argument of type 'Promise' is not assignable to parameter of type 'Promise<OverlayEventDetail>'.
Type 'boolean' has no properties in common with type 'OverlayEventDetail'
When running the test case using jasmine/karma test cases. I am facing n issue which is before starting with the Login spec test case the other spec files are all called before completing the Login. It need to happen in an orderly manner which is like
1.Login
2.Dashboard
3.Order
etc.
Is there a way to do this.
login.spec.ts file
import { async, ComponentFixture, TestBed } from '#angular/core/testing';
import { RouterModule, Router } from '#angular/router';
import { LoginComponent } from './login.component';
import { DebugElement } from '#angular/core';
import { FormsModule, ReactiveFormsModule } from '#angular/forms';
import { BrowserModule, By } from '#angular/platform-browser';
import { Ng2Bs3ModalModule } from 'ng2-bs3-modal/ng2-bs3-modal';
import { RouterTestingModule } from '#angular/router/testing';
import { APP_BASE_HREF } from '#angular/common';
import { LoginService } from './login.service';
import { HttpClientModule } from '#angular/common/http';
import { ApiService } from '../config/api.service';
import { ConfigService } from '../config/config.service';
import { Constants } from '../config/Constant';
import { SharedService } from '../shared/shared.service';
import { Http, BaseRequestOptions, ResponseOptions, Response, RequestMethod } from '#angular/http';
import { inject } from '#angular/core/testing';
import { MockBackend, MockConnection } from '#angular/http/testing';
describe('LoginComponent', () => {
let comp: LoginComponent;
let fixture: ComponentFixture<LoginComponent>;
let de: DebugElement;
let el: HTMLElement;
let userNameEl: DebugElement;
let passwordEl: DebugElement;
let submitEl: DebugElement;
let loginService: LoginService = null;
let backend: MockBackend = null;
TestBed.overrideComponent(LoginComponent, {
set: {
providers: [
{
provide: LoginService,
useValue: loginService
},
{
provide: Router,
useClass: class { navigate = jasmine.createSpy('navigate'); }
}
]
}
});
beforeEach(async(() => {
// loginService = loginService;
// backend = mockBackend;
TestBed.configureTestingModule({
declarations: [
LoginComponent
],
imports: [
RouterModule.forRoot([{
path: '',
component: LoginComponent
}]),
BrowserModule,
FormsModule,
ReactiveFormsModule,
Ng2Bs3ModalModule,
RouterTestingModule,
HttpClientModule
],
providers: [
MockBackend,
BaseRequestOptions,
{
provide: Http,
useFactory: (backendInstance: MockBackend, defaultOptions: BaseRequestOptions) => {
return new Http(backendInstance, defaultOptions);
},
deps: [MockBackend, BaseRequestOptions]
},
LoginService,
ApiService,
ConfigService,
Constants,
SharedService,
{ provide: APP_BASE_HREF, useValue: '/' }
]
}).compileComponents().then(() => {
fixture = TestBed.createComponent(LoginComponent);
comp = fixture.componentInstance;
de = fixture.debugElement.query(By.css('form'));
el = de.nativeElement;
userNameEl = fixture.debugElement.query(By.css('input[id=InputEmail1]'));
passwordEl = fixture.debugElement.query(By.css('input[id=InputPassword1]'));
submitEl = fixture.debugElement.query(By.css('.login-btn'));
});
}));
beforeEach(inject([LoginService, MockBackend], (Service: LoginService, mockBackend: MockBackend) => {
loginService = Service;
backend = mockBackend;
}));
it('should create', () => {
expect(comp).toBeTruthy();
});
it('To check the initial value', () => {
expect(comp.submitted).toBe(false);
expect(comp.spinnerlogo).toBeFalsy();
expect(comp.data).toEqual({});
});
it(`entering value in username and password input controls`, () => {
userNameEl.nativeElement.value = 'admin';
passwordEl.nativeElement.value = 'admin';
fixture.detectChanges();
});
it('after entering value the button should enabled and click Action should happen', () => {
expect(submitEl.nativeElement.disabled).toBeFalsy();
const loginButtonSpy = spyOn(comp, 'onSubmit');
submitEl.triggerEventHandler('click', null);
expect(loginButtonSpy).toHaveBeenCalled();
});
it('calling onSubmit method after clicked the login button', () => {
comp.submitted = true;
comp.spinnerlogo = true;
comp.errorDiagnostic = null;
comp.mailerrorDiagnostic = null;
expect(comp.submitted).toBeTruthy();
expect(comp.spinnerlogo).toBeTruthy();
expect(comp.errorDiagnostic).toBeNull();
expect(comp.mailerrorDiagnostic).toBeNull();
});
it('#login should call endpoint and return it\'s result', (done) => {
backend.connections.subscribe((connection: MockConnection) => {
const options = new ResponseOptions({
body: JSON.stringify({ success: true })
});
connection.mockRespond(new Response(options));
// Check the request method
expect(connection.request.method).toEqual(RequestMethod.Post);
// Check the url
expect(connection.request.url).toEqual('/auth/login');
// Check the body
// expect(connection.request.text())
expect(connection.request.text()).toEqual(JSON.stringify({ username: 'admin', password: 'admin' }));
// Check the request headers
expect(connection.request.headers.get('Content-Type')).toEqual('application/json');
});
loginService.login('admin', 'admin')
.subscribe((response) => {
console.log('response values are ---####------------ ', response);
// Check the response
expect(response.user.username).toEqual('admin');
expect(response.user.password).toEqual('admin');
// set value in sessionStorage
sessionStorage.setItem('currentUser', JSON.stringify(response));
sessionStorage.setItem('token', JSON.stringify(response.token));
sessionStorage.setItem('dismissOrders', 'false');
done();
},
(error) => {
expect(error).toThrowError();
});
});
});
the main problem is before executing the above file . The other spec file are executed
Thanks,
Kishan
I'm pretty new in unit testing in Angular 2 so i'm asking your help.
My logout function :
logOut() {
this.authService.logOut().subscribe(() => {
this.router.navigate(['login']);
});
}
And my unit test :
describe('HomeComponent', () => {
let component: HomeComponent;
let fixture: ComponentFixture<HomeComponent>;
let authenticationService: AuthenticationService;
let mockLogOut = {
logOut: () => { }
};
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
FormsModule,
HttpModule,
CommonModule,
ReactiveFormsModule,
TranslateModule,
RouterTestingModule.withRoutes([
{ path: 'login', component: LoginComponent }
])
],
declarations: [HomeComponent, LoginComponent],
providers: [
{ provide: AuthenticationService, useValue: mockLogOut },
TranslateService,
TRANSLATION_PROVIDERS
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(HomeComponent);
authenticationService = TestBed.get(AuthenticationService);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
describe('Authentication Tests', () => {
it('should log out the user', inject([AuthenticationService], (mockLogin: AuthenticationService) => {
fakeAsync(() => {
spyOn(authenticationService, 'logOut');
let navigateSpy = spyOn((<any>component).router, 'navigate');
component.logOut();
expect(mockLogin.logOut).toHaveBeenCalled();
expect(navigateSpy).toHaveBeenCalledWith(['/log1n']);
});
}));
});
});
I want to check if the user is redirected to the route /login but this test always success even if I put something else than /login
I have set up a simple service and tried to run the test.
Service
//CustomerServiceTest.ts:
import { Injectable, Pipe } from '#angular/core';
import { Http, Response } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/Rx';
#Injectable()
export class CustomerServiceTest{
constructor(public http: Http) {}
query(URL: string, params?: Array<string>): Observable<any[]> {
let be_endpoint: string = 'http:\/\/localhost:44444\/';
let queryURL: string = `${be_endpoint}${URL}`;
if (params) {
queryURL = `${queryURL}?${params.join('&')}`;
}
return this.http.request(queryURL).map((res: any) => res.json());
}
searchBackEnd(query: string, type: string): Observable<any[]> {
return this.query(`/${type}`, [
`id=${query}`
]);
}
}
Test for the service
//CustomerServiceTest.spec.ts:
import {
TestBed,
getTestBed,
async,
inject
} from '#angular/core/testing';
import {
Headers, BaseRequestOptions,
Response, HttpModule, Http, XHRBackend, RequestMethod
} from '#angular/http';
import {ResponseOptions} from '#angular/http';
import {MockBackend, MockConnection} from '#angular/http/testing';
import { CustomerServiceTest } from '../../ts/components/CustomerServiceTest';
describe('CustomerServiceTest test suite', () => {
let mockBackend: MockBackend;
beforeEach(async(() => {
TestBed.configureTestingModule({
providers: [
CustomerServiceTest,
MockBackend,
BaseRequestOptions,
{
provide: Http,
deps: [MockBackend, BaseRequestOptions],
useFactory:
(backend: XHRBackend, defaultOptions: BaseRequestOptions) => {
return new Http(backend, defaultOptions);
}
}
],
imports: [
HttpModule
]
}).compileComponents();
mockBackend = getTestBed().get(MockBackend);
}));
it('should get data', async(inject([CustomerServiceTest], (CustomerServiceTest) => {
let crmSvc:CustomerServiceTest;
let ContactResponceBody:Object = {
body: [
{
id: '12345678',
cellPhNum: '+9273839222',
lastName: 'TestUser',
firstName: 'TestUser'
}
]
};
let contactResponceOptions:ResponseOptions = new ResponseOptions(ContactResponceBody);
let contactResponse:Response = new Response(contactResponceOptions);
mockBackend.connections.subscribe(
(connection: MockConnection) => {
connection.mockRespond(contactResponse);
});
crmSvc = getTestBed().get(CustomerServiceTest);
expect(crmSvc).toBeDefined();
})));
});
Executing npm run test results in error:
Chrome 49.0.2623 (Windows 7 0.0.0) CustomerServiceTest test suite should get data FAILED
Failed: No provider for [object Object]!
Error: DI Error
at NoProviderError.Error (native)
at NoProviderError.ZoneAwareError (karma.entry.js:43703:33)
at NoProviderError.BaseError [as constructor] (karma.entry.js:6062:34)
at NoProviderError.AbstractProviderError [as constructor] (karma.entry.js:32848:16)
at new NoProviderError (karma.entry.js:32879:16)
at ReflectiveInjector_._throwOrNull (karma.entry.js:53504:19)
at ReflectiveInjector_._getByKeyDefault (karma.entry.js:53532:25)
at ReflectiveInjector_._getByKey (karma.entry.js:53495:25)
at ReflectiveInjector_.get (karma.entry.js:53304:21)
at TestBed.get (karma.entry.js:9842:67)
Apparently, some dependency is missing, but I can't understand what it is. Could anyone explain where to look? At first glance - all providers are at place...
Worked it out:
//CustomerService.spec.ts
import {
TestBed,
getTestBed,
async,
inject
} from '#angular/core/testing';
import {
Headers, BaseRequestOptions,
Response, HttpModule, Http, XHRBackend, RequestMethod
} from '#angular/http';
import {ResponseOptions} from '#angular/http';
import {MockBackend, MockConnection} from '#angular/http/testing';
import { CustomerServiceTest } from '../../ts/components/CustomerServiceTest';
describe('CustomerServiceTest:', () => {
let mockBackend: MockBackend;
let ContactResponceBody:Object = {
body: [
{
id: '1-DR8C2SJ',
cellPhNum: '1111',
lastName: 'qqq',
firstName: 'www',
midName: 'eee',
sex: 'М',
age: 23,
email: 'test#test.com',
localtime: '12:00',
utcOffset:180
}
]
};
let contactResponceOptions:ResponseOptions = new ResponseOptions(ContactResponceBody);
let contactResponse:Response = new Response(contactResponceOptions);
beforeEach(async(() => {
TestBed.configureTestingModule({
providers: [
CustomerServiceTest,
MockBackend,
BaseRequestOptions,
{
provide: Http,
deps: [MockBackend, BaseRequestOptions],
useFactory:
(backend: XHRBackend, defaultOptions: BaseRequestOptions) => {
return new Http(backend, defaultOptions);
}
}
],
imports: [
HttpModule
]
});
mockBackend = getTestBed().get(MockBackend);
}));
it('Available',
async(
inject(
[CustomerServiceTest],
(custSvc:CustomerServiceTest) => {
expect(custSvc).toBeDefined();
}
)
)
)
it('Returns data',
async(
inject(
[TCSCustomerServiceTest],
(custSvc:TCSCustomerServiceTest) => {
//emulate contact response from real back-end
mockBackend.connections.subscribe(
(connection: MockConnection) => {
connection.mockRespond(contactResponse);
});
custSvc.searchBackEnd('1-DR8C2SJ', 'contact').subscribe(
(response: any) => {
expect(response[0].id).toBe('1-DR8C2SJ');
expect(response[0].cellPhNum).toBe('1111');
expect(response[0].lastName).toBe('qqq');
expect(response[0].firstName).toBe('www');
expect(response[0].midName).toBe('eee');
expect(response[0].sex).toBe('М');
expect(response[0].age).toBe(23);
expect(response[0].email).toBe('test#test.com');
expect(response[0].localtime).toBe('12:00');
expect(response[0].utcOffset).toBe(180);
}
);
}
)
)
)
});