Ionic unit testing - unit-testing

When I suppose to test a method, I got the error like
TypeError: Cannot read property '_getPortal' of undefined
And my method here
onAddRole() {
this.roleService.getAllRoles() // Here i m getting the error.
.take(1)
.subscribe(
data => {
// stuffs
},
err => {
// stuffs
}
);
}
Can I get any help on this?

Related

Unable to write unit test for ngRx Store selector with Observable

This is the first time I am working on Jasmine unit test framework and I am trying to write unit test for the following lines of code in a component in Angular.
this.subscriptions.push(
this.store.select(authSelectors.getAuthError).subscribe((error) =\> {
if (error) {
this.loading = false;
this.utility.showErrorMessage(error);
if (this.loginForm) {
this.loginForm.reset();
} } }) );
Below is the code that I tried
describe('ngOnInit testing', () =\> {
it('Validate form', () =\> {
let mockError = new Observable\<any\>();
const storespy = jasmine.createSpyObj("Store",\['select'\]);
storespy.select.and.callFake((error: string) =\> {
switch(error) {
case authSelectors.getAuthError.toString(): return mockError;
default: return;
} });
if(mockError != null) { expect(utilityServiceSpy.showErrorMessage).toHaveBeenCalled();
} }) })
But this test case is failing with error:
Error: Expected spy UtilityService.showErrorMessage to have been called.
Am I doing anything wrong here?

Testing a BehaviorSubject throws no access type error

I'm trying to test a behaviorSubject, but keep getting:
Error: <spyOnProperty> : Property myBehaviorSubject$ does not have access type get
this is how I declare my behaviorSubject in my myService:
myBehaviorSubject$ = new BehaviorSubject<Array<ObjectA>>([{name: 'name1'}]);
and my test:
describe(`myMethod`, () => {
beforeEach(() => {
myServiceMock = {
myBehaviorSubject$: new BehaviorSubject<Array<ObjectA>>(null)
};
spyOnProperty(myServiceMock, 'myBehaviorSubject$', 'get').and.returnValue(observableOf([{name: 'name1'}] as Array<ObjectA>));
});
it('should access behaviorSubject', () => {
myServiceMock.myBehaviorSubject$.subscribe( result => {
//expect;
});
});
});
The fact that you are mocking the return value of the property access implies that you are not actually using that property directly at all. Instead of what you are doing, I'd recommend creating the spy directly, like this:
beforeEach(() => {
myServiceMock = {
myBehaviorSubject$: jasmine.createSpy('myBehaviorSubject$')
.and.returnValue(observableOf([{name: 'name1'}] as Array<ObjectA>))
};
});
This has the exact same effect as above, but it doesn't create a new instance of BehaviorSubject, which doesn't seem to be used.

How can i test a function that return a promise or reject - Jasmine and Karma

I need to cover 100% of the tests of a function, it returns a return new Promise<boolean>((resolve, reject) this is the full function.
saveData(): Promise < boolean > {
return new Promise < boolean > ((resolve, reject) => {
this.legaloneService.saveFinancialData(this.financialModel).subscribe(
m => {
if (!m.Success) {
const mapFiels: {
[id: string]: string
} = {};
mapFiels['accountName'] = 'Nome da conta';
mapFiels['bankId'] = 'Banco';
mapFiels['agency'] = 'AgĂȘncia';
mapFiels['accountNumber'] = 'Conta';
this.functionsService.displayErrorFromAPII(m, mapFiels);
}
resolve(m.Success);
},
error => {
const msg = 'Ocorreu uma falha ao salvar os dados financeiros';
this.functionsService.cathError(error, msg);
reject(msg);
}
);
});
}
A few days ago I got help from someone here, and I am trying to solve this issue using his tips, my test is as follows:
it('testing resolve a promise', fakeAsync(() => {
spyOn(component, 'saveData').and.returnValue(Promise.resolve(true));
spyOn(funcService, 'displayErrorFromAPII').and.stub();
component.saveData()
.then(r => {
console.log(r);
expect(funcService.displayErrorFromAPII).toHaveBeenCalled();
flush(200);
})
.catch(e => fail(e));
expect(component.saveData).toHaveBeenCalled();
}));
and this is my current coverage:
My current coverage
In your test, you mocks the method saveData under test, the real implementation will not be involved and code coverage will not improve. Therefore you should remove the following statement from your test.
spyOn(component, 'saveData').and.returnValue(Promise.resolve(true));
You should mock the method legaloneService.saveFinancialData instead since this is a unit test. Since saveData is returning a Promise, you can use the done callback function.
To have full code coverage, you need the following two tests.
import { of, throwError } from 'rxjs';
...
it('#saveData should display error when financial data cannot be saved', (done) => {
const saveFinancialDataResult = ?; // replace ? with expected !Success result
spyOn(legaloneService, 'saveFinancialData').and.returnValue(of(saveFinancialDataResult));
spyOn(funcService, 'displayErrorFromAPII').and.stub();
component.saveData()
.then(r => {
expect(funcService.displayErrorFromAPII).toHaveBeenCalled();
done();
})
.catch(e => fail(e));
});
it('#saveData should catch error when error occurs', (done) => {
spyOn(legaloneService, 'saveFinancialData').and.returnValue(throwError('server error'));
spyOn(funcService, 'cathError').and.stub();
component.saveData()
.then(r => fail('should have been rejected'))
.catch(e => {
expect(functionsService.cathError).toHaveBeenCalled();
done();
});
});
Please consult https://angular.io/api/core/testing/fakeAsync and https://jasmine.github.io/tutorials/async for detailed information about different testing strategies with Angular and Jasmine.

How to unit test dom manipulating functions in angular tests

I have an angular-cli based project, with a component that has some logic like this:
colorLine() {
let svgDoc = this.svg.nativeElement.contentDocument;
JSON.parse(this.stations).forEach(station => {
station.element = svgDoc.getElementById(station.name);
station.element.removeAttribute('class');
if (station.status === 'running') {
station.element.setAttribute('fill', 'lime');
}
return station;
})
}
I am trying to unit test this with the following test:
it('should color running stations green', async(() => {
component.svg.nativeElement = new DOMParser().parseFromString(svgDoc, 'application/xml');
component.load();
expect(component.stations[0].element.getAttribute('fill')).toBe('lime');
}));
where svgDoc is a string representation of the element to query. However, I am getting the issue:
TypeError: Cannot read property 'getAttribute' of undefined
How can I test this sort of functionality?

How to expect a meteor error with chai

I want to test that my method throws an unauthorized error if called without the proper credentials. How would I do this with chai? I see that chai's examples are
var err = new ReferenceError('This is a bad function.');
var fn = function () { throw err; }
expect(fn).to.throw(ReferenceError);
expect(fn).to.throw(Error);
expect(fn).to.throw(/bad function/);
expect(fn).to.not.throw('good function');
expect(fn).to.throw(ReferenceError, /bad function/);
expect(fn).to.throw(err);
So I tried
let error = new Meteor.Error(UNAUTHORIZED, UNAUTHORIZED_REASON, 'detail');
chai.expect(Meteor.call('addItem', item)).to.throw(error);
but this didn't work. Thoughts?
You can do it this way:
Say you have a method that throws following error:
throw new Meteor.Error('unauthorised', 'You cannot do this.');
Test for that error using:
it('will throw an error', function() {
assert.throws(() => {
//whatever you want to run that should throw the error goes here
}, Meteor.Error, /unauthorised/); //change 'unauthorised' to whatever your error is
});
Its expect(fn).to.throw(Meteor.Error);
it('Test Meteor Error', () => {
expect(() => { throw new Meteor.Error('test');}).to.throw(Meteor.Error);
});