have written test case for jumping method,
but its not going inside onloadend method seat.onloadend, when I see code coverage report.
in createSpyObj i called loadend but still its not going inside
can you guys tell me how to fix it.
providing my code and test case below.
I am trying to wite test case for each and every line.
jumping(inputValue: any): void {
var that = this;
var file: File = inputValue.files[0];
var seat: FileReader = new FileReader();
seat.onloadend = (e) => {
this.encodeBase64 = seat.result;
that.fileSelect = $("#laptop").val().replace(/^.*\\/, "");
if (that.fileSelect == '') {
that.dragDrop = that.swimming;
} else {
that.dragDrop = "";
that.dragDrop = that.fileSelect;
}
}
$('.running').show();
if (inputValue.files.length > 0) {
var wholeQuantity = 0;
wholeQuantity = inputValue.files[0].size / 1048576; //size in mb
if (wholeQuantity > 5) {
$('.stars').show();
$("#laptop").val('');
this.fileSelect = "";
}
seat.readAsDataURL(file);
}
}
describe('Jasmine Unit Tests: hand-Basketball-Manage-mobiles', () => {
let rainSPORTSService:SPORTSService;
let SPORTSService: SPORTSService;
let decodeService: DecodeService;
let BasketballChainComponent: handBasketballChain;
let kickViewrainsComponent: kickViewrains;
let tiger: Componenttiger<handBasketballChain>;
let raintiger: Componenttiger<kickViewrains>;
let foodktiger: Componenttiger<foodkCarousel>;
let kendotiger: Componenttiger<KendoGridComponent>;
let foodkComponent:foodkCarousel;
let kendoComponent:KendoGridComponent;
beforeEach(async(() => {
jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;
TestBed.configureTestingModule({
imports: [HttpModule, FormsModule,BrowserModule ],
declarations:[handBasketballChain, KendoGridComponent,ProgressCircle,
kickViewrains,handLeftSliderComponent,foodkCarousel,kickmobiles],
providers:[SPORTSService,DecodeService,recentPinnedHistoryService,
{provide: Router, useClass: RouterModule}, validationService,saveService,
ChainService]
}).compileComponents().then(() =>{
foodktiger = TestBed.createComponent(foodkCarousel);
kendotiger = TestBed.createComponent(KendoGridComponent);
foodkComponent = foodktiger.componentInstance;
kendoComponent = kendotiger.componentInstance;
tiger = TestBed.createComponent(handBasketballChain);
BasketballChainComponent = tiger.componentInstance;
SPORTSService = tiger.debugElement.injector.get(SPORTSService);
tiger.componentInstance.kickmobiles.SPORTSService=tiger.debugElement.injector.get(SPORTSService);
tiger.componentInstance.kickViewrains.SPORTSService=tiger.debugElement.injector.get(SPORTSService);
decodeService = tiger.debugElement.injector.get(DecodeService);
BasketballChainComponent.inputfoodkCarousel = foodkComponent; //jasmine.createSpy('foodkCarousel');//.andCallFake(function(msg) { return this });
BasketballChainComponent.kickmobiles.gridkendo=kendoComponent;
})}
));
it('Read kick mobile', (done) => {
let callFirstTime : boolean = true;
let url=
spyOn(BasketballChainComponent.kickmobiles.SPORTSService,'getResponse').and.
callFake(() => {
if(callFirstTime) {
callFirstTime = false; // Invoked by detectChanges()
return Observable.of([{
"mobileId": "100",
"mobileName": "http://localhost:3000/assets/js/actualairings.json",
"mobileType": "TITLE",
"mobileData": "YWZjYXJlZ2Vyamh2dmFyZWdoYnZi",
"notes": "",
"notesId": "100",
"elfDocID": "100",
"url": "http://localhost:3000/upload",
"date": "06/27/2017",
"addedByName": "Kamal",
"userID": "206509786",
"operationType": "create"
}]);
}
});
const fileReaderSpy = jasmine.createSpyObj('FileReader', ['readAsDataURL', 'onloadend']);
spyOn(window, 'FileReader').and.returnValue(fileReaderSpy);
BasketballChainComponent.kickmobiles.jumping({
files: "Untitled-2.txt"
});
var seat = new FileReader();
//seat.onloadend(e);
//BasketballChainComponent.kickmobiles.jumping.onloadend()
tiger.whenStable().then(() => {
done();
});
});
});
Remember, the key to Unit Testing is to write small testable Units of code.Unit Testing - Wikipedia
You're on the right track for the most part, stubbing FileReader and so forth before calling the 'jumping' function. This is very much the way to test code that relies on another external library/function/framework. The relevant portion of the Wikipedia page for Unit Testing states
Because some classes may have references to other classes, testing a class can frequently spill over into testing another class. A common example of this is classes that depend on a database: in order to test the class, the tester often writes code that interacts with the database. This is a mistake, because a unit test should usually not go outside of its own class boundary, and especially should not cross such process/network boundaries because this can introduce unacceptable performance problems to the unit test-suite.
Here's the thing though, when you create your dummy FileReader or mock it never calls 'onloadend' because the mock/stub doesn't have that event and eventing system implemented. This means the mock is incomplete on your part. Wikipedia states
Instead, the software developer should create an abstract interface around the database queries, and then implement that interface with their own mock object. By abstracting this necessary attachment from the code (temporarily reducing the net effective coupling)
In your case, rather than a database, you'd be mocking the FileReader loadend event.
From a test perspective your current code needs a small refactor to become testable. The general objective of Unit Tests is to test small units of functionality in isolation.
The objective in unit testing is to isolate a unit and validate its correctness.
The 'jumping' function relies on a nested arrow function attached to onloadend. Your code has a direct call to that commented out in the test, I'm a little surprised that didn't work to up your code coverage to be honest and would suggest perhaps making sure your code coverage tool, probably Istanbul if you're using Jasmine is configured correctly.
With the above aside, you should refactor that nested function and instead create a named function that you can then call directly for your unit tests.
This is an (untested on my end) example of a better way to implement your function.
jumping(inputValue: any): void {
var that = this;
var file: File = inputValue.files[0];
var seat: FileReader = new FileReader();
// bind the arguments for the event handler, first arg will be 'this' of the
// loaded named function
// second is 'that' variable, seat is seat and the final 'e' variable is
// implicit and shouldn't be specified.
seat.onloadend = loaded.bind(seat, that, seat);
$('.running').show();
if (inputValue.files.length > 0) {
var wholeQuantity = 0;
wholeQuantity = inputValue.files[0].size / 1048576; //size in mb
if (wholeQuantity > 5) {
$('.stars').show();
$("#laptop").val('');
this.fileSelect = "";
}
seat.readAsDataURL(file);
}
}
loaded(that: any, seat: any, e: any): void { // now a testable named function
this.encodeBase64 = seat.result;
that.fileSelect = $("#laptop").val().replace(/^.*\\/, "");
if (that.fileSelect == '') {
that.dragDrop = that.swimming;
} else {
that.dragDrop = "";
that.dragDrop = that.fileSelect;
}
}
An example of a test that will cover all the lines of code of the 'loaded' function as written above is as follows:
describe('test suite', function () {
var old$ = $;
afterEach(function () {
$ = old$;
});
it('covers all lines and else path on if but does not actually test anything', function () {
$ = function () {
val: function () {
return 'Untitled-2.txt';
}
}; // stub JQuery
var seat = {
result: 'Base64encoded'
};
var scope = {};
var that = {
swimming: false,
dragDrop: null
};
BasketballChainComponent.kickmobiles.loaded.call(scope, that, seat, null);
});
it('covers all lines and on if but not else and does not actually test anything', function () {
$ = function () {
val: function () {
return '';
}
}; // stub JQuery
var seat = {
result: 'Base64encoded'
};
var scope = {};
var that = {
swimming: false,
dragDrop: null
};
BasketballChainComponent.kickmobiles.loaded.call(scope, that, seat, null);
});
});
Now please take note, in the real world you should never write tests just for code coverage that do not actually test the given functions. It will lead you into a false sense of security and not actually TEST your code. The MSDN has this to say:
The primary goal of unit testing is to take the smallest piece of testable software in the application, isolate it from the remainder of the code, and determine whether it behaves exactly as you expect.
An analogy of what you're doing would be as follows:
You're working as a car crash tester. Your job is to verify the car is safe in a crash. So a car is crashed at 10 km/h and you need to check it over.
You take a check list of things that you need to confirm. So in a 10 km/h crash you only expect paint to be scratched. So you look at the paint, if the paint is scratched but there's no other damage, the test passes. If the car is dented, the test fails.
That's a good test overall as it is testing something quantifiable and it's testing an intention.
What you're doing by trying to achieve 100% code coverage without actually testing functionality is crashing the car and then not verifying anything.
You're saying "Well I crashed the car, I don't really need to check it did what it's supposed to do in a crash so long as I crashed it right?".
Sure, you got 100% crash coverage by looking at the car, but by not actually testing it, you may as well not have even bothered. Code coverage is a useful tool for spotting code that isn't tested, it's not used to achieve the arbitrary metric of gaining full code coverage. Further reading on this and an excellent write up can be read at Broken promise of 100% code coverage
Essentially the crux of it is
The fact that it is easy to measure code coverage doesn’t make it a good metric though. You can get into trouble even if your code coverage is 100%.
I've omitted the code from the medium article, however it goes on to state:
This unit test produces the perfect 100% test coverage for the elementAtIndex: function.
Does it prove that the function works correctly? The answer is, obviously, no. What happens when we exceed the array boundaries?
Why did that happen? When you try to focus on the code coverage metric you write code that looks at the implementation of the tested function/method. But the implementation is not proven to be correct yet. That is the reason why we want to test it.
Even with that simple function code coverage failed as a good metric to measure the quality of unit-tests.
Further, above I state that you should test the intention of your code. The Medium article also states this.
What to do instead? Don’t look at the actual implementation of the method, look at the contract instead. Look precisely at the outputs of the function/method for any specific inputs. Look at the side-effects that this function does or uses. Take into account the possible edge cases that might exist. List this information and make tests according to that.
Remember
100% code coverage doesn’t mean that your code is 100% correct.
I hope this helps you understand Unit Testing as a concept a little better.
So if you open up the inspector, you get this (if you're unlucky):
I'm building a tiny JS component which displays debugging information - is there any way to read the number of encountered errors and warnings so far?
A hacky solution I could come up with involves a bit of trickery by replacing the console.(error|log|warn) functions with my own, but I'm yet to test if it works for all cases (e.g. outside of code I own).
Is there a better way to do this?
As noted in this answer, it's generally not a good idea to change the behavior of native objects/methods. However, the following code should get you what you need in a fairly innocuous manner:
// Add this IIFE to your codebase:
(() => {
// Get all of the property names of the console:
const methodsToTrack = Object.keys(window.console);
// Create an object to collect total usage tallies in:
const usageRegistry = {};
for (let i = 0, j = methodsToTrack.length; i < j; i++) {
let methodName = methodsToTrack[i];
// If the property is not a method, don't touch it:
if(typeof window.console[methodName] !== 'function') {
continue;
}
// Cache the original console method here:
let consoleMethod = window.console[methodName];
// Overwrite console's method to increment the counter:
window.console[methodName] = function () {
// Defining registry properties here, so the registry only contains values for methods that were accessed:
usageRegistry[methodName] = usageRegistry[methodName] || 0;
// Execute the original method's behavior, capturing the returned value (if any) in a var, to return it at the end:
const returnedValue = consoleMethod(...arguments);
// Increment the usage registry for the executed method:
usageRegistry[methodName]++;
// Return the value the console's method would have returned, so the new method has the same signature as the old.
return returnedValue;
};
}
// Define a funciton to output the totals to a console log, then clean up after itself:
window.showConsoleTallies = function () {
window.console.log(usageRegistry);
usageRegistry['log']--;
}
})();
// Examples:
showConsoleTallies();
console.log('log 1');
console.error('error 1');
console.log('log 2');
console.warn('warn 1');
console.error('error 2');
console.log('log 3');
showConsoleTallies();
PS: That's the ECMA6 version, but feel free to run it through Babel if you'd like it to be compiled for use in older browsers.
After reading the following article,
http://javascriptplayground.com/blog/2012/04/javascript-module-pattern/
I have decided to start implementing modules in my JS.
Unfortunately, the module I am using does not seem to be keeping the private variable private,
var popoverOptionsModule = (function() {
var _stopAskingList = [];
var addToStopAskingList = function(itemToAdd) {
if (_stopAskingList.indexOf(itemToAdd) === -1){
_stopAskingList.push(itemToAdd);
}
}
var getStopAskingList = function() {
return _stopAskingList;
}
return {
addToStopAskingList: addToStopAskingList,
getStopAskingList: getStopAskingList,
};
})();
popoverOptionsModule._stopAskingList = 4;
console.log(popoverOptionsModule._stopAskingList);
As you can see, I am able to change the value of
popoverOptionsModule._stopAskingList and log the update to the console... I thought this was not supposed to happen. Thanks for your help!
JS is completely dynamically typed, so when you have the line
popoverOptionsModule._stopAskingList = 4;
You've just created this variable and assigned it a value, hence why the next line succeeds. If you didn't have this line, then the subsequent console.log would report undefined. This code would work too
popoverOptionsModule._abc = 4;
console.log(popoverOptionsModule._abc);
Remember that this isn't actually a private variable in the same way that OO languages implement protection levels, rather it's just an API pattern that attempts to hide it from the caller.
Ok, first up I know an object has no reference to it's container unless explicitly defined, so I am looking for a work around here.
Take the following code (heavily simplified from my use case for readability):
var cid = 0;
var Command = function(c) {
this.id = cid += 1;
this.transient = false;
return this;
}
var sid = 0;
var CommandSet = function() {
this.id = sid += 1;
this.commands = [];
this.transients = 0;
return this;
}
CommandSet.prototype.parent = null;
CommandSet.prototype.recurse = function(callback) {
callback.call(this);
if (this.parent instanceof CommandSet) {
this.parent.recurse(callback);
}
}
CommandSet.prototype.createSubset = function() {
var set = new CommandSet();
set.parent = this;
set.commands = this.commands;
set.transients = this.transients;
return set;
}
CommandSet.prototype.addCommand = function(c) {
if (c instanceof Command) {
this.commands.push(c);
if (c.transient) {
this.recurse(function() {
this.transients++;
});
}
}
return this;
}
CommandSet.prototype.toggleTransient = function(c) {
if (c instanceof Command) {
c.transient = true;
this.recurse(function() {
this.transients++;
});
}
return this;
}
If I then do the following (http://jsfiddle.net/5KGd8/1/):
var s1 = new CommandSet();
var c1 = new Command();
var c2 = new Command();
s1.addCommand(c1).addCommand(c2);
var s2 = s1.createSubset();
var s3 = s1.createSubset();
s2.toggleTransient(c1);
console.log(s1);
console.log(s2);
console.log(s3);
s1 now has 1 transient, s2 now has 1 transient but s3 still has none despite containing a reference to the same Command objects.
Possible solutions:
I could build a reference into each command which stores all the
sets it is located inside and iterate through those, however this is
going to cause some serious memory issues as the real nature of my
application requires that subsets can be garbage collected (The user
will create a lot of them anonymously often without realising) and this will retain a
reference to them after they have been used. The parent reference is fine as I want the parent set to exist as long as it has a surviving subset.
I could explicitly force the user to run a delete function on a
subset when it is no longer needed which would remove all internal references to it but this complicates things for
them and I like things to work automagically. The nature of my application means I would like the user to create subsets at times where they may not even realise they have done so (Through other functions which create and perform on subsets).
Can anyone think of a way to solve this problem without the issues described in my two solutions?
Sorry, this is not an answer but want to make sure I understand the problem.
A CommandSet can have Commands, when you change a Command's transient property you would like the CommandSet(s) that contain that Command to have an updated counter of transient the Commands it contains.
If the story ends here you could simply have Command maintain a list of CommandSet that the Command is in and update it's containers.
This would not work however because you would have CommandSets created in a function and when these go out of scope they won't be garbage collected because the Command(s) they contain would hold a reference to them. These commands would not go out of scope with the CommandSets because they are also contained in other (global) CommandSets.
Re assigning a primitive type (transients) does not re assign that in the subset or main set, but what if transients was not a primitive?
In the constructor:
this.transients = {count:0};
In createSubset
set.transients = this.transients
In the toggleTransient
this.transients.count++; or --
No matter if you fiddle with transients in subset or main set, as long as you use the toggleTransient it'll change count for all.
this is my first post, but i'm excited to join this community. I have a question regarding JavaScript which I am completely stumped about.
I'm writing a JavaScript application which pulls data from a server using ajax and adds it to a chart. I'm using Jquery and Highcharts as the framework and then writing my own JavaScript 'wrapper' around Highcharts to produce the interface.
When the processData function get called back with the jSON response, it begins with i=1, even though i shouldn't even be initialized or even declared yet. Other variables are set as well. (I know this from using chrome developer tools to debug). This makes my loop not execute and none of my data gets added to the chart.
I don't know how much code to show, but these are the most relevant parts. I can add more if needed.
function getData(series, min, max, numpts) {
if (series === undefined) {
console.log("error on getData");
return;
}
var request = {};
request.series = series;
if (min !== undefined) {
request.start = min;
} //in seconds
if (max !== undefined) {
request.end = max;
}
if (numpts !== undefined) {
request.numpts = numpts;
}
$.getJSON('/data', request, processData);
return;
}
function processData(data) {
// handle the data after it comes back from an ajax request
var curSeries,
chartSeries,
curPoint;
for (var i = 0; i < data.length; i ++) {
curSeries = data[i];
chartSeries = chart.get(curSeries.name);
if (chartSeries === null) {
//alert("oops");
chart.addSeries(curSeries);
} else {
for (var j = 0; j < curSeries.data.length; j ++) {
curPoint = curSeries.data[j];
chartSeries.addPoint(curPoint, false);
}
}
}
chart.redraw();
}
These are both methods of a class I declared called graph.
Thanks if anyone has any ideas!
-Matt P
I'd console inspect your data object to make sure it's what you expect, as that loop should be working fine even if i is pre-declared: you're assigning 0 to it at the beginning of the loop, anyway.
The only reason I can think of that i would be defined and initialized before you defined and initialized it is if somewhere else in your codebase you don't initialize the i with the var keyword. Doing that would dump it into the global scope (the window object), making it available via closure to any and every function in your codebase.
If it's not in one of your files, it may be in the highcharts graphing library (in which case run very quickly away from said library).