why test coverage is not 100% - unit-testing

I wrote a method which returns true if there are folders left in the modal to be added and return false if there are no folders left in the modal to be added to the application
my method in angular/typesrcipt
ifAllFoldersHaveBeenAdded() {
let added = false;
let folderToExclude = find(this.bdDataModel.lenderDefinedFolders, {
name: 'Correspondence' });
let foldersToBeChecked = without(this.bdDataModel.lenderDefinedFolders, folderToExclude);
for (let i = 0; i < foldersToBeChecked.length; i++) {
let folderPresent = find(this.bdDataModel.folders, { name: foldersToBeChecked[i].name });
if (folderPresent) {
added = true;
} else {
added = false;
return added;
}
}
return added;
}
my test...
describe('ifAllFoldersHaveBeenAdded()', () => {
it('returns false if there are folders left in the modal to be added', () => {
let added = false;
$ctrl.bdDataModel.folders;
$ctrl.foldersToBeChecked = [{ name: 'FMS' }, { name: 'Other' }];
$ctrl.folderPresent = { name: 'FMS' };
$ctrl.ifAllFoldersHaveBeenAdded();
added = true;
expect(added).toEqual(true);
});
it('returns true is all folders have been added to the application', () => {
let added = false;
$ctrl.bdDataModel.folders;
$ctrl.foldersToBeChecked = [{ name: 'FMS' }, { name: 'Other' }];
$ctrl.folderPresent = { name: 'LMI' };
$ctrl.ifAllFoldersHaveBeenAdded();
expect(added).toEqual(false);
});
});
Both tests pass but icov coverage report is marking the following lines as uncovered...
find(this.bdDataModel.folders, { name: foldersToBeChecked[i].name });
if (folderPresent) {
added = true;
}
else {
added = false;
return added;
}
please tell what i should add in the test to have a 100% test coverage for this unit test.
thanks in advance

There is so much wrong with your test. First off, you need to get rid of the local added variables completely. Doing something like the following
added = true;
expect(added).toEqual(true);
Is essentially the same as doing expect(true).toBe(true)
Next, the folderPresent and foldersToBeChecked variables are local to the ifAllFoldersHaveBeenAdded function. They are not controller variables. You don't need to set $ctrl.folderPresent or $ctrl.foldersToBeChecked in your test.
You need to define these two variables $ctrl.bdDataModel.lenderDefinedFolders and $ctrl.bdDataModel.folders
Because lenderDefinedFolders is undefined the length of foldersToBeChecked in your function is going to be 0. So the for loop will never execute.
Your test should look something like this:
it('returns false if there are folders left in the modal to be added', () => {
$ctrl.bdDataModel.lenderDefinedFolders = [{ //add lender defined folders here }]
$ctrl.bdDataModel.folders = [{ //add some folders here}]
let added = $ctrl.ifAllFoldersHaveBeenAdded();
expect(added).toEqual(true);
});

Related

ApolloClient: UI (ROOT_QUERY) not updating after subscription delete

apollo-client: 2.6.3
react-apollo: 2.2.1
So, I have a subscription that is fired upon an item delete request but does not update the UI after the subscription has taken place.
My subscription code is as follows:
<DeleteItem
id={item.id}
urlReferer={urlReferer}
subscribeToDeleteItems={() =>
subscribeToMore({
document: DELETE_ITEM_SUBSCRIPTION,
variables: {},
updateQuery: (prev, { subscriptionData }) => {
if (!subscriptionData.data) return prev;
const deletedItem = subscriptionData.data.itemDeleted;
let newItemList;
console.log("prev = ", prev);
if (isDuplicateItem(deletedItem.id, prev.me.items)) {
newItemList = prev.me.items.filter((item) => {
return deletedItem.id !== item.id;
});
console.log("new item list = ", newItemList);
} else {
return prev;
}
return Object.assign({}, prev, {
ROOT_QUERY: {
me: {
items: [newItemList]
}
}
});
}
})
}
>Delete This Item</DeleteItem>
and the generated output looks as follows:
ROOT_Query store:
What am I overlooking here and how do I resolve it?
So I resolved this by changing the parent query's fetchPolicy to "cache-and-network" and ensuring that IDs were present in every query where results need to be normalised, as mentioned here: Issue with automatic UI updates in Apollo: `updateQuery` not working properly with `subscribeToMore`

Ember - Within action, result is defined, returnvalue of same action logged in parent action is undefined? Why?

Quick and shortly I have following problem:
I have following two actions within a component in Ember:
createData: function(user) {
let collection = [];
for (let i = 0; i < user.posts.length; i++) {
let data = this.send('createSingleData',user.posts[i], user, 'post');
console.log(data);
collection.push(data);
}
return collection;
},
createSingleData: function(data, user, type) {
let entitySkeleton = {
name: data.place.name,
belongsTo: user.id,
position: {
data.place.location.longitude,
data.place.location.latitude
}
};
console.log(entitySkeleton);
return entitySkeleton;
}
the first log - within createSingleData, right before returning the logged value - writes the entitySkeleton as Object into the console - as expected.
However, the console.log(data) - within createData - writes 'undefined' to the console.
Is there any aspect of asynchrounosity I didn't respect?
P.S.:
I also logged any paramater within createSingleData, they are all set properly.
The variable collection also only gets pushed 'undefined'.
You cannot return the value from action, instead you can set property from the action.
how to return values from actions in emberjs
actions: {
PrintSomething: function() {
let obj = [{a: 'raj'}, {a: 'Prudvi'}, {a : 'thimappa'}]
console.log('before', obj);
this.send('returnSomething', obj);
console.log('after calling action', this.get('returnvalue'));
},
returnSomething: function(obj) {
obj.push({a: 'FSDFSDF'})
var data = obj;
this.set('returnvalue', data);
}
}

Ember: Setting a component object value within a promise

I have component with a couple of properties, using a promise in the willRender hook to try and create a (pagination) object:
export default Ember.Component.extend({
pagination:null,
testing:null, // to check if this.set is ok within the promise!
willRender() {
let page = {};
let model = this.get('data');
model.get('products').then(relatedItems => {
let maxRecords = relatedItems.get('length');
relatedItems.forEach(function(item,index) {
if (item.get('slug') === itemModel.get('id')) {
if (index === 0) {
page.Prev = null;
page.Next = relatedItems.objectAt(index+1).get('slug');
}
else if (index+1 === maxRecords) {
page.Prev = relatedItems.objectAt(index-1).get('slug');
page.Next = null;
}
else {
page.Prev = relatedItems.objectAt(index-1).get('slug');
page.Next = relatedItems.objectAt(index+1).get('slug');
}
}
});
this.set('testing','hello world');
console.log(this.get('testing')); // hello world
this.set('pagination',page);
console.log(this.get('pagination')); // Object {Prev: "product-1", Next: "product-2"}
},reject => {
console.log('error '+reject);
});
}
})
In my template
{{testing}} // prints hello world
However, if I try and access {{pagination}} eg {{log pagination}}, the browser crashes with a loop printing out the object to the console.
I don't know where I'm going wrong here - any help much appreciated!
It's likely you are triggering the template to rerender causing willRender to fire over and over which causes an infinite loop in your code.
willRender is a non-standard place to do this code, init would be more standard since it only fires on initialization of the component. Even better would be to use
myInit: Ember.on('init', function(){
....
})`
instead of overriding willRender on the object.
try to check whether Object is present at specific position. i think its going undefined during iteration of for loop. try to ensure that ObjectAt is not returning undefined or null value during running of for loop.
relatedItems.forEach(function(item,index) {
if (item.get('slug') === itemModel.get('id')) {
if (index === 0) {
page.Prev = null;
if(relatedItems.objectAt(index+1) ! = undefined) {
page.Next = relatedItems.objectAt(index+1).get('slug');
}else{
page.Next == null;
}
}
else if (index+1 === maxRecords) {
if(relatedItems.objectAt(index-1) ! = undefined) {
page.Prev = relatedItems.objectAt(index-1).get('slug');
}else{
page.Prev = null;
}
page.Next = null;
}
else {
if(relatedItems.objectAt(index-1) ! = undefined) {
page.Prev = relatedItems.objectAt(index-1).get('slug');
}else{
page.Prev = null;
}
if(relatedItems.objectAt(index+1) ! = undefined) {
page.Next = relatedItems.objectAt(index+1).get('slug');
}else{
page.Next = null;
}
}
}
Please ensure that Object at is returning object.
There seems to be a few problems here, would be interested to know what your console errors are.
You don't seem to have defined itemModel so don't know how you're referencing that.
Also you can't access this from within a .then. You need to do something like this to set a component variable.
var _this = this;
promise().then(function(results) {
_this.set('testing', 'hello world');
});
you are not using , after testing:null
there should be , after testing property like that
pagination:null,
testing:null, // i use ',' after testing: null property
try to use your pagination code under init hook rather than willrender hook
init() {
//you code
},

how to differentiate user typed their own value or selected a suggestion from typeahead

I am using typeahead.js.
var getname = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('CompanyName'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: '/Profile/Getname?searchText=%QUERY',
});
getname.initialize();
var $emp = $('#employment');
$emp.typeahead(null, {
name: 'CompanyNames',
displayKey: 'CompanyName',
source: getname.ttAdapter(),
});
$emp.on("typeahead:selected", function (obj, user) {
$("#UserId").val(user.UserID);
}
is there a way to know when the user selects an option from the list or typed their own value?
I made it that way
var voivodeshipSelected = false;
$('input[name=voivodeshipSelect].typeahead').on('typeahead:select', function (ev, suggestion) {
$(this).validationEngine('hide');
voivodeshipSelected = true;
});
$('input[name=voivodeshipSelect].typeahead').on('typeahead:change', function (ev, data) {
if (!voivodeshipSelected) {
$(this).validationEngine('showPrompt', 'choose voivodeship', 'error', 'topRight', true);
}
else {
voivodeshipSelected = false;
}
});
I just add global variable which is set on select so than on change which is binded when select, check it, and showing prompt or not.

How can I default a value of an Ember Model based on the result of an expression?

The code below gives an error saying:
Uncaught TypeError: undefined is not a function
Can someone help me structure this properly so that I can default a value based on this expression?
,defaultPersonType: function defaultPersonType() {
console.log(this)
var people = this.get("store").all("person").content
,primaryFound = false
,spouseFound = false
,dependantFound = false
,defaultType = "CHILD"
for (var i = 0; i < people.length; i++) {
switch(people.get("personType")) {
case "PRIMARY":
primaryFound = true
break
case "SPOUSE":
spouseFound = true
break
case "UNMARRIED_PARTNER":
spouseFound = true
break
default:
dependantFound = true
break
}
if (!primaryFound) {
defaultType = "PRIMARY"
}
if (!!dependantFound) {
defaultType = "CHILD"
}
if (!spouseFound) {
defaultType = "SPOUSE"
}
}
return DS.attr('string', {defaultValue: function() {return defaultType}})
}
,personType: (function() {
return this.defaultPersonType()
}())
Well, your
this
is wrong in the anonymous function. So, do this:
function() { return this.defaultPersonType(); }.bind(this)())
I think the best place to implement this logic is in the route's model hook.