unit testing code in spec.ts
it('Should test LoadMenus method', () => {
let arrays = [{ "Id": 1, "MenuType": "A00", "MenuName": "Search", "UserDetail": { "UserName": "rajendranra" }
alert(11);// executed
this.modalNota.LoadMenus(arrays, 'A00', 'A', '0');
alert(12);// does not execute
expect(this.modalNota.cocmenuitems[0].MenuName).toBe('Search');
});
Component method which am testing
LoadMenus(lstMenu, menustring, submenustartstring, submenuendstring) {
alert(menustring);
this.subitems = [];
let menu = lstMenu.find(myObj => myObj.MenuType === menustring);
if (menu !== null) {
this.menufilter = lstMenu.filter(myObj => myObj.MenuType.startsWith(submenustartstring))
.filter(x => x.MenuType.endsWith(submenuendstring));
if (this.menufilter.length > 1) {
for (let menuType = 0; menuType < this.menufilter.length; menuType++) {
if (this.menufilter[menuType].MenuType !== menustring) {
this.subitems.push({
label: this.menufilter[menuType].MenuName,
routerLink: [this.GetLink(this.menufilter[menuType].MenuName)]
});
}
}
alert(menu.MenuName);
this.cocmenuitems.push({ label: menu.MenuName, routerLink: [this.GetLink(menu.MenuName)], items: this.subitems });
} else {
alert(menu.MenuName);
this.cocmenuitems.push({ label: menu.MenuName, routerLink: [this.GetLink(menu.MenuName)] });
}
}
}
This unit test showing the result is failed. the main problem is Alert alert(12); does not fire. Why my alert(12) does not hit after this this.modalNota.LoadMenus(arrays, 'A00', 'A', '0'); component code is executed??
Am struggling a whole day for this. kindly give me the solution.
Related
I was struggling with a test issue for my custom useLazyQuery hook. My first test is passing but the second one is failing. What am doing wrong for the second test?
Here is the useLazyFetchCoin.tsx
export const useLazyFetchCoin = () => {
const [coins, setCoins] = useState<ICoin[]>([]);
useEffect(() => {
const coins = localStorage.getItem('coinsInfo');
if (coins) {
setCoins(JSON.parse(coins));
}
}, []);
const [getData, { loading, error }] = useLazyQuery(GET_COIN_PRICE_QUERY, {
fetchPolicy: 'network-only',
notifyOnNetworkStatusChange: true,
onCompleted: (data) => {
const hasSameCoin = coins.some((f) => f.id === data.markets[0]?.id);
if (data.markets.length && !hasSameCoin) {
const allCoins = [...coins, data.markets[0]];
setCoins(allCoins);
localStorage.setItem('coinsInfo', JSON.stringify(allCoins));
} else if (data.markets.length <= 0) {
alertNotification('Coin not found !', Notification.ERROR);
}
if (hasSameCoin) {
alertNotification('This coin already exists on your list !', Notification.WARNING);
}
}
});
return { coins, setCoins, getData, loading, error };
};
Here is the test file
describe('useLazyFetchCoin custom hook', () => {
const QueryMock = [
{
request: {
query: GET_COIN_PRICE_QUERY,
variables: { code: 'BNB' }
},
result: {
data: {
markets: [
{
id: 'binance_bnb_eur',
baseSymbol: 'BNB',
ticker: {
lastPrice: '414.90000000'
}
}
]
}
}
}
];
const QueryWrongCodeMock = [
{
request: {
query: GET_COIN_PRICE_QUERY,
variables: { code: 'asd' }
},
result: {
data: {
markets: []
}
}
}
];
function getHookWrapper(mocks: any, code: string) {
const wrapper = ({ children }: any) => (
<MockedProvider mocks={mocks} addTypename={false}>
{children}
</MockedProvider>
);
const { result, waitForNextUpdate } = renderHook(() => useLazyFetchCoin(), {
wrapper
});
expect(typeof result.current.coins).toBe('object');
expect(result.current.loading).toBeFalsy();
expect(result.current.error).toBeUndefined();
// call the lazy function
act(() => {
result.current.getData({
variables: { code }
});
});
return { result, waitForNextUpdate };
}
it('should return an array of coins', async () => {
// Working correctly
const { result, waitForNextUpdate } = getHookWrapper(QueryMock, 'BNB');
await waitForNextUpdate();
expect(result.current.loading).toBeFalsy();
expect(result.current.coins[0]).toEqual({
id: 'binance_bnb_eur',
baseSymbol: 'BNB',
ticker: {
lastPrice: '414.90000000'
}
});
});
it('should return an empty array when requesting a wrong code', async () => {
// Not working
const { result, waitForNextUpdate } = getHookWrapper(QueryWrongCodeMock, 'asd');
await waitForNextUpdate();
expect(result.current.loading).toBeFalsy();
expect(result.current.coins[0]).toEqual([]);
});
});
I got this error message for the second test.
Expected: []
Received: {"baseSymbol": "BNB", "id": "binance_bnb_eur", "ticker": {"lastPrice": "414.90000000"}}
I don't get it because I'm using different queries for each test.
Also, the second test should receive an empty array when you pass a wrong code such as 'asd'.
How can write a proper test for it?
I fixed the problem. When I was changing the order test, It worked correctly.
I added a clear mock function for it.
clear mock
I am new to Angular and it's very hard for me to understand how to write a unit test for a piece of code. Can someone please explain to me how to write a unit test for the following code?
toggleClassActive(station: any): void {
this.isDisabled = false;
this.stationsList.map((st) => {
if (st.id === station.id) {
st.active = true;
} else {
st.active = false;
}
});
}
Given this example component
export class FooComponent {
isDisabled = true;
stationsList: Array<{ id: number, active: boolean }> = [
{id: 1, active: false}, {id: 2, active: true},
];
constructor() {
}
toggleClassActive(station: { id: number, active: boolean }): void {
this.isDisabled = false;
this.stationsList.map((st) => {
if (st.id === station.id) {
st.active = true;
} else {
st.active = false;
}
});
}
}
Here's a unit test for that very method
import {TestBed} from '#angular/core/testing';
import {FooComponent} from './foo.component';
describe('FooComponent', () => {
let component: FooComponent;
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
FooComponent,
],
});
component = TestBed.inject(FooComponent);
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should toggle active class', () => {
// Optionally test the initial values // state
expect(component.stationsList).toEqual([
{id: 1, active: false}, {id: 2, active: true},
]);
expect(component.isDisabled).toEqual(true);
// Trigger the effect
component.toggleClassActive({id: 1, active: false});
// Assert the expected changes
expect(component.stationsList).toEqual([
{id: 1, active: true}, {id: 2, active: false},
]);
expect(component.isDisabled).toEqual(false);
});
});
I have a function that returns and treats a promise, I need to cover the return that is inside then but I don't know how I can do this, I'm currently trying as follows:
confirmRemoveUser(user: IUser) {
this.modalService
.open('Confirma a exclusão do usuário selecionado?', {
titleText: 'Confirmando exclusão',
confirmButtonText: 'Sim',
cancelButtonText: 'Cancelar',
closeButtonText: 'Fechar',
buttonType: 'danger'
})
.result.then(
(result: BentoModalConfirmationCloseReason) => {
if (result === BentoModalConfirmationCloseReason.Confirm) {
if (this.removeUser(user)) {
this.toastService.open('Usuário excluído com sucesso!', { type: 'success', close: true });
} else {
this.toastService.open('Falha ao excluir o usuário!', { type: 'warning', close: true, duration: 0 });
}
}
}
);
}
I'm currently using callthrough () and imagine that with some parameter I can get the promise but I don't know how:
it('Given_ConfirmRemoveUser_When_UserStepIsCalled_Then_UserIsRemoved', (done) => {
component.selectedJob = {
};
component.selectedArea = {
};
component.users = [{
}];
spyOn(modalService, 'open').withArgs('This is modal msg').and.callThrough();
component.confirmRemoveUser(component.users[0]);
expect(modalService.open).toHaveBeenCalled();
done();
});
And my coverage is like the image below:
Image here!
UPDATE
New Error
Your test should work when it is rewritten as follows:
it('Given_ConfirmRemoveUser_When_UserStepIsCalled_Then_UserIsRemoved', (done) => {
spyOn(modalService, 'open').and.returnValue(Promise.resolve(BentoModalConfirmationCloseReason.Confirm));
spyOn(toastService, 'open').and.stub();
component.confirmRemoveUser(component.users[0])
.then(r => {
expect(toastService.open).toHaveBeenCalled();
done();
})
.catch(e => fail(e));
});
You probably also want to know what will be displayed in the toast. Therefore it makes sense to rather use expect(toastService.open).toHaveBeenCalledWith(?);.
UPDATE
Above solution only works if confirmRemoveUser would return a Promise.
confirmRemoveUser(user: IUser) {
return this.modalService
...
In your case, the use of the done function does not make sense. You need to use async and await.
it('Given_ConfirmRemoveUser_When_UserStepIsCalled_Then_UserIsRemoved', async () => {
spyOn(modalService, 'open').and.returnValue(Promise.resolve(BentoModalConfirmationCloseReason.Confirm));
spyOn(toastService, 'open').and.stub();
await component.confirmRemoveUser(component.users[0]);
expect(toastService.open).toHaveBeenCalled();
});
The same can be achieved with fakeAsync and flush.
import { fakeAsync, flush } from '#angular/core/testing';
...
it('Given_ConfirmRemoveUser_When_UserStepIsCalled_Then_UserIsRemoved', fakeAsync(() => {
spyOn(modalService, 'open').and.returnValue(Promise.resolve(BentoModalConfirmationCloseReason.Confirm));
spyOn(toastService, 'open').and.stub();
component.confirmRemoveUser(component.users[0]);
flush();
expect(toastService.open).toHaveBeenCalled();
}));
Testing lifecycle methods when a VueJS component renders on the transition group.
I've been writing tests for lifecycle methods when the component renders on the transition group of the following VueJS component I've made little progress on getting it to work and would appreciate advice regarding this. I also tried switching between shallow mounting and mounting the component though that seemed to make no difference.
import { shallowMount } from '#vue/test-utils';
import StaggeredTransition from '../src/index';
const staggeredTransitionWrapper = componentData =>
shallowMount(StaggeredTransition, {
...componentData,
});
const staggeredTransition = staggeredTransitionWrapper();
describe('StaggeredTransition.vue', () => {
it('should render a staggered transition component', () => {
expect(staggeredTransition.element.tagName).toBe('SPAN');
expect(staggeredTransition.html()).toMatchSnapshot();
});
it('should mock calling the enter method', () => {
const enterMock = jest.fn();
StaggeredTransition.methods.enter = enterMock;
const staggeredTransitionWrapper2 = componentData =>
shallowMount(StaggeredTransition, { ...componentData });
const staggeredTransition2 = staggeredTransitionWrapper2({
slots: {
default: '<h1 :key="1">Staggered transition test</h1>',
},
});
expect(enterMock).toBeCalled();
});
});
Code for the StaggeredTransition component
<template>
<transition-group
:tag="tag"
:name="'staggered-' + type"
:css="false"
appear
#before-enter="beforeEnter"
#enter="enter"
#leave="leave"
>
<slot />
</transition-group>
</template>
<script>
const { log } = console;
export default {
name: 'StaggeredTransition',
props: {
type: {
type: String,
options: ['fade', 'slide'],
required: false,
default: 'fade',
},
tag: {
type: String,
required: false,
default: 'div',
},
delay: {
type: Number,
required: false,
default: 100,
},
},
methods: {
beforeEnter(el) {
console.log('beforeEnter');
el.classList.add(`staggered-${this.type}-item`);
},
enter(el, done) {
console.log('enter');
setTimeout(() => {
el.classList.add(`staggered-${this.type}-item--visible`);
done();
}, this.getCalculatedDelay(el));
},
leave(el, done) {
console.log('leave');
setTimeout(() => {
el.classList.remove(`staggered-${this.type}-item--visible`);
done();
}, this.getCalculatedDelay(el));
},
getCalculatedDelay(el) {
console.log('getCalculatedDelay');
if (typeof el.dataset.index === 'undefined') {
log(
'data-index attribute is not set. Please set it in order to
make the staggered transition working.',
);
}
return el.dataset.index * this.delay;
},
},
};
</script>
While writing unit tests for a function that handles a angular material 2 dialog using the example code from material 2 i run into problems.
I'm a Jasmine newbie but I didn't had problems to write unit test before.
I have to test the result of the afterClose function but i can't get the handle to dialogRef.
Could it be a problem how the material2 dialog API is engineered?
let dialogRef = this.dialog.open(ExtractPageDialog, {
width: this.EXPORT_DIALOG_WIDTH,
data: {
document: this.document
}
});
dialogRef.afterClosed().subscribe((result: any) => {
if (result) {
let fileId = this.document.fileId;
this.docProvider.extractPage(this.document.fileId, result.fromPage, result.toPage).subscribe(() => {
() => { //totest },
(error) => { //totest }
});
} else {
//totest
}
});
DOCS:
https://material.angular.io/components/component/dialog
one solution could be to split the subscribed function in multiple functions and test them
dialogRef.afterClosed().subscribe(this.functionName);
functionName(result: any) {
if (result) {
let fileId = this.document.fileId;
this.docProvider.extractPage(this.document.fileId, result.fromPage, result.toPage).subscribe(() => {
() => { //totest },
(error) => { //totest }
});
} else {
//totest
}
}
}