Unittest For FileReader tohavebeenCalled - unit-testing

I am having real issue with my tests for FileReader. i mock the FileReader and trying To test if It has been called when onChange event is triggered.
I have tried to write tests for method that call on OnLoad event of File Reader.
.ts File
reader = new FileReader();
readFileOnChange(files: any) {
if (files && files.length > 0) {
const file: File = files.item(0);
if (file.type == "text/csv") {
this.reader.readAsText(file, "UTF-8");
this.reader.onload = (e) => { this.parse()}
}
}
}
Spec.ts
describe('AppComponent', () => {
let mockFile = new File(['testData'], 'filename.csv', { type: 'text/csv' });
let mockEvt = { target: { files: [mockFile] } };
let mockReader: FileReader = jasmine.createSpyObj('FileReader', ['readAsText',
'onload']);
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ AppComponent ],
providers: [],
imports: [HttpClientTestingModule, BrowserDynamicTestingModule],
}).compileComponents();
component = fixture.componentInstance;
fixture.detectChanges();
spyOn(component, 'readFileOnChange').and.callThrough();
}));
it('should call parse on onLoad of FileReader', () => {
spyOn(window, 'FileReader').and.returnValue(mockReader);
component.readFileOnChange(mockEvt as any);
expect(window.FileReader).toHaveBeenCalled();
expect(component.parse).toHaveBeenCalled();
});
})
gives Error:
Expected spy FileReader to have been called.
Please help Thank you

Related

Angular unit testing Error: "Keyboard" plugin is not implemented on web

app.component.ts:->
`if (Capacitor.isPluginAvailable('Keyboard')) {
this.keypadOpenListner = Keyboard.addListener('keyboardDidShow', () => {
this.zone.run(() => {
this.isKeyboardShowing = true;
})
});
this.keypadOffListner = Keyboard.addListener('keyboardDidHide', () => {
this.zone.run(() => {
this.isKeyboardShowing = false;
})
});
}`
`
app.component.spec.ts:->
` describe('app compenent', () => {
let fixture: ComponentFixture<AppComponent>;
let component: AppComponent;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [AppComponent]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AppComponent);
component = fixture.componentInstance;
spyOn(Capacitor, 'isNativePlatform').and.returnValue(true);
fixture.detectChanges();
});`
to cover if condition I added spyOn(Capacitor, 'isNativePlatform').and.returnValue(true); in beforeEach condition is this correct? if yes I got warning "Keyboard" plugin is not implemented on web how can I overcomethe warning ?.

Angular 12 unit test, spy a function inside subscribe

I'm subscribing to a behavior subject in onInit and based on the result I'm calling a function. My code is like
subscription = new Subscription();
constructor(private myService: MyService) {}
ngOnInit() {
this.subscription = this.myService.event.subscribe(response => {
if(response){
this.myFunction();
}
});
}
myFunction() {}
and I'm test this by trying like below
describe('AppComponent', () => {
let event = new BehaviorSubject(false);
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [
AppComponent
], imports: [
], providers: [{
provide: MyService, useValue: {
event: event
}
}]
}).compileComponents();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should call myFunction', (done) => {
const myService = fixture.debugElement.injector.get(MyService);
myService.event.next(true);
component.ngOnInit();
const spy = spyOn(component, 'myFunction');
myService.event.subscribe((event: boolean) => {
expect(spy).toHaveBeenCalled();
done();
})
});
});
and I'm getting my spy is not called. Please help me to fix my code. Thanks a lot.
You're spying too late it seems.
Try the following:
// !! Spy first
const spy = spyOn(component, 'myFunction');
// !! Then call ngOnInit
component.ngOnInit();
Edit
Try with fakeAsync and tick.
it('should call myFunction, fakeAsync(() => {
const myService = fixture.debugElement.injector.get(MyService);
myService.event.next(true);
const spy = spyOn(component, 'myFunction');
component.ngOnInit();
tick();
expect(spy).toHaveBeenCalled();
}));
The fakeAsync/tick should hopefully wait until the subscribe is done before moving on to the expect.

How to handle bootstrap-daterangepicker in angular component unit test?

I am trying to write a unit test of an angular 6 component which is initializing the bootstrap-daterangepicker in the ngAfterViewInit() method. When I run my unit test it gives the following error:
TypeError: $(...).daterangepicker is not a function
this is the code from the actual component(EmployeeComponent):
ngAfterViewInit(): void {
this.initializeDatePicker(this);
}
initializeDatePicker(that: any) {
const start = moment().subtract(7, 'days');
const end = moment();
$('#reportrange').daterangepicker({
startDate: start,
endDate: end,
maxDate: moment(),
ranges: {
'Today': [moment(), moment()],
'Yesterday': [moment().subtract(1, 'days'), moment().subtract(1, 'days')]
}
}, cb);
cb(start, end);
}
this is the code from my test class:
describe('EmployeeComponent', () => {
let component: EmployeeComponent;
let fixture: ComponentFixture<EmployeeComponent>;
let messageService: NotificationService;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [EmployeeComponent]
})
.overrideComponent(EmployeeComponent, {
set: {
template: '',
providers: [
{ provide: NotificationService, useValue: messageService },
{ provide: ActivatedRoute, useValue: { queryParams: of({ emp: "123" }) } }
]
}
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(EmployeeComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
You don't need to handle it in your test cases. That component should be initialized in a separate service and you can simply mock that method from the service. In the way you can avoid this error.
let say you move all the code of the initializeDatePicker() in a method in some service let say common-service.ts and you can simply call that service from this method like
this.commonServiceObj.initializeDatePicker();
Now after doing this, you can simply mock initializeDatePicker() from the service object and error should be gone.

Angular 2 testing components with observables

I am testing a angular component and the code is
ngOnInit(): void {
this.getNar();
}
getNar(): void {
let self = this;
this.dashboardService.getNar().subscribe(
res => self.narIds = res.narIds,
error => self.error = error,
function () {
self.narIds.forEach(element => {
// Some Code
});
}
);
}
The Service provider for this i.e Dashboard Service is
getNar(): Observable<any> {
return this.http.get(Config.Api.GetNar + '1/nar').map((res: Response) => res.json());
}
And my Test cases are:
let res = '"narIds":[{"id":1,"narId":"104034-1","narName":"SDLC Platform"},{"id":2,"narId":"64829-1","narName":"EMS-EMS"}]';
describe('Application Health Component', () => {
beforeEach( async(() => {
TestBed.configureTestingModule({
providers: [MockBackend, DashboardService],
imports: [ChartsModule, SlimScrollModule, HttpModule],
declarations: [CompletedFilterPipe, ApplicationHealthComponent]
})
.compileComponents()
.then(createComponent);
}));
it('should call the getNar when ngOnInit is called', async(() => {
spyOn(dashboardService, 'getNar').and.returnValue(Observable.of(res));
comp.ngOnInit();
expect(dashboardService.getNar).toHaveBeenCalled();
}));
});
function createComponent() {
fixture = TestBed.createComponent(ApplicationHealthComponent);
comp = fixture.componentInstance;
dashboardService = fixture.debugElement.injector.get(DashboardService);
};
The problem I am getting is the test case gives an error that forEach is undefined.
The error message is not that forEach function is not defined, it's that your object "self.narIds" is undefined. Fairly sure this is due to the way you declared your onComplete function in Observable.subscribe
related to this Rx Subscribe OnComplete fires but cannot use the data
change your
function () {
self.narIds.forEach(element => {
// Some Code
});
code to
() => {
self.narIds.forEach(element => {
// Some Code
});

Unit test and Assert http.get queryString call in Angular2

I have a DataService and I want to assert that the year is getting set in the query string correctly. Is there a way to spyOn the http.get call or to access it? I don't know the correct approach to testing this. I'm using Angular 2.2.0.
The DataService
constructor(private http: Http) { }
public getEnergyData(option: string): Promise<EnergyDataDto[]> {
return this.http.get(this.getEnergyDataApiUrl(option)).toPromise().then((response) => {
this.energyDataCache = this.parseEnergyDataResponse(response);
return this.energyDataCache;
}).catch(this.handleError);
}
protected getEnergyDataApiUrl(option: string) {
return `/api/solar?year=${option}`;
}
protected parseEnergyDataResponse(response: Response) {
return response.json().data;
}
dataservice.spec.ts
describe('Given the DataService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpModule],
providers: [DataService, { provide: XHRBackend, useClass: MockBackend }],
});
});
describe('When getting the energy data', () => {
let backend: MockBackend;
let service: EnergyDataService;
let fakeEnergyData: EnergyDataDto[];
let response: Response;
const makeEnergyData = () => {
let data = [];
let one = new EnergyDataDto();
one.year = 2007;
one.countryName = 'Denmark';
one.quantity = '100000';
data.push(one);
return data;
};
beforeEach(inject([Http, XHRBackend], (http: Http, be: MockBackend) => {
backend = be;
service = new EnergyDataService(http);
fakeEnergyData = makeEnergyData();
let options = new ResponseOptions({ status: 200, body: { data: fakeEnergyData } });
response = new Response(options);
}));
it('should return fake values', async(inject([], () => {
backend.connections.subscribe((c: MockConnection) => c.mockRespond(response));
service.getEnergyData('all').then(data => {
expect(data.length).toBe(1);
expect(data[0].countryName).toBe('Denmark');
});
})));
it('should use year in query string', async(inject([], () => {
spyOn(service, 'getEnergyDataApiUrl').and.callThrough();
backend.connections.subscribe((c: MockConnection) => c.mockRespond(response));
service.getEnergyData('2007').then(data => {
// I was hoping to use backendend somehow instead, but it's not in scope when I debug it.
expect((<any>service).getEnergyDataApiUrl).toHaveBeenCalledWith('/api/solar?year=2007');
});
})));
You should do this in the mockBackend.connections subscription. This is when you have access to the URL from the MockConnection
backend.connections.subscribe((c: MockConnection) => {
expect(c.request.url).toBe(...)
c.mockRespond(response)
});