Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

Unit Test for JavaScript

, 14 Dec 2007 CPOL
How to strengthen your client-side code and improve reliability
unitjs.zip
UnitJS
green.gif
red.gif
//debug helper class to control popup windows
function DebugHelper()
{
    this.Active = true;
    this.OpenWindowOnFirstMessage = true;
    this.ShowCallee = true;
    this.ShowInputArguments = true;
    this.ShowCaller = true; //may not work, since it is deprecated
    this.ShowCallStack = true; //may work on few browsers [Gecko] only since it is not a W3C recommendation
    this.ShowException = true;
    this.ShowURL = true;
    this.ShowLastModified = true;
    this.ShowReferrer = true;
    this.VerboseMode = false;
    //reference to the popup window
    this.DebugWindow = null;
    this.CssStyleFile = new String("debughelper.css");
    this.WindowStyle = new String("left=30,top=30,width=410,height=350,scrollbars=yes,status=no,resizable=yes");
    //no spaces to run correctly on internet explorer
    this.WindowName = new String("JavascriptDebugWindow");
    this.WindowTitle = new String("Javascript Debug Window");
}

//method to show the debug window
//callback won't work for IE
DebugHelper.prototype.ShowWindow = function(callback, args)
{
	try
	{
	    if( this.Active && (!this.DebugWindow || this.DebugWindow.closed) )
	    {
		    this.DebugWindow = window.open("", this.WindowName, this.WindowStyle);
	  	    
	  	    this.DebugWindow.opener = window;
	  	    //open the document for writing
	  	    this.DebugWindow.document.open();
   	    
	  	    this.DebugWindow.document.write(
	    	    "<html><head><title>" + this.WindowTitle + "</title>" +
	    	    "<link rel='stylesheet' type='text/css' href='" + this.CssStyleFile + "' />" + 
	    	    "</head><body><div id='renderSurface' style='width: 100%; height: 100%;' /></body></html>\n"
	        );

    	    //prepare window to call callback function when it is loaded
    	    //callback won't work on IE because onload won't be called
    	    if( callback )
    	    {
    			this.DebugWindow.context = this;
    			this.DebugWindow.onload = function()
    			{
    				callback.apply(this.context, args);
    			}
    	    }
    	    
    	    this.DebugWindow.document.close();
	    }
	}
	catch(ex)
	{
		//ignore exception
	}
}		

//if the debug window exists, then write to it
DebugHelper.prototype.$Write = function(cssClass, ex, url, lastModified, referrer, args) 
{
	try
	{
		if( this.Active )
		{
			if( this.OpenWindowOnFirstMessage && (!this.DebugWindow || this.DebugWindow.closed) )
			{
				//there is a issue related to IE's onload method of opened popups
				//IE won't call onload to execute the popup write method asynchronously
				//however, IE can write it directly, appearing that IE window.open releases script
				//flow only when popup's onload method has executed
				if( document.all )
				{				
					this.ShowWindow();
				}
				else
				{
					this.ShowWindow(this.$WriteAsync, [cssClass, message, url, lastModified, referrer, args]);
					return;
				}
			}

			if( this.DebugWindow && !this.DebugWindow.closed )
			{
			    var msg = "";
			    
			    if( this.ShowCaller && args != null )
			    {
			        var c = new String(args.callee.caller);
			        msg += "caller <code>" + c.substring(0, c.indexOf("{")) + "</code>";
                }

			    if( this.ShowCallee && args != null )
			    {
			        var c = new String(args.callee);
			        msg += "callee <code>" + c.substring(0, c.indexOf("{")) + "</code>";
                }
                
			    if( this.ShowInputArguments && args != null )
			    {
			        //since arguments isn't a real array, put the vcalues into a real one
			        var a = new Array();
			        var l = args.length;
			        for(var i=0; i<l; i++)
			        {
			            a[i] = args[i];
			        }
			        //default toString() method will show array objects ina a comma separated string
			        msg += "arguments <code>" + a + "</code>";
                }

                //string message
                if( ex == null || (ex.message == null) )
                {
                    msg += "<code>" + ex + "</code>";
                }
                else //exception object
                {
                    if( ex.name ) msg += "type <code>" + ex.name + "</code>";
                    if( ex.number ) msg += "number <code>" + ex.number + "</code>";
                    if( ex.lineNumber ) msg += "lineNumber <code>" + ex.lineNumber + "</code>";
                    msg += "message <code>" + ex.message + "</code>";
                    if( ex.stack && this.ShowCallStack ) msg += "stack <code>" + ex.stack + "</code>";
                }
                
			    if( this.ShowURL && url != null )
			        msg += "at <code>" + url + "</code>";
			        
			    if( this.ShowLastModified && lastModified != null )
			        msg += "last modified in <code>" + lastModified + "</code>";

			    if( this.ShowReferrer && referrer != null )
			        msg += "referrer <code>" + referrer + "</code>";

		    	this.DebugWindow.document.getElementById("renderSurface").innerHTML = "<span class='" + cssClass + "'>" + msg + "</span>" + this.DebugWindow.document.getElementById("renderSurface").innerHTML;
		  	}
		}
	}
	catch(ex)
	{
		//ignore exception
	}
}

//window.onload will call this method when using the Just In Time window opening
//this way write don't get called before window document are ready to be used
DebugHelper.prototype.$WriteAsync = function(cssClass, message, url, lastModified, referrer, args) 
{
	this.$Write(cssClass, message, url, lastModified, referrer, args);
}

//write a message to debug window
DebugHelper.prototype.Message = function(message, url, lastModified, referrer, args)
{
	try
	{
    	this.$Write("debugMessage", message, url, lastModified, referrer, args);
	}
	catch(ex)
	{
		//ignore exception
	}
}
//method shortcut
function $dm(message, url, lastModified, referrer, args)
{
    if( debugHelper )
        debugHelper.Message(message, url, lastModified, referrer, args);
}

//same as debug, plus another style applyied
DebugHelper.prototype.Warn = function(message, url, lastModified, referrer, args)
{
	try
	{
    	this.$Write("debugWarn", message, url, lastModified, referrer, args);
	}
	catch(ex)
	{
		//ignore exception
	}
}

//same as debug, plus a strong style applyied
DebugHelper.prototype.Exception = function(ex, url, lastModified, referrer, args)
{
	try
	{
	    if( this.ShowException )
	    {
    	    this.$Write("debugException", ex, url, lastModified, referrer, args);
    	}
	}
	catch(ex)
	{
		//ignore exception
	}
}

//if the debug window exists, then close it
DebugHelper.prototype.HideWindow = function() 
{
	try
	{
	    if( this.DebugWindow && !this.DebugWindow.closed )
	    {
		    this.DebugWindow.close();
    	    this.DebugWindow = null;
  	    }
	}
	catch(ex)
	{
		//ignore exception
	}
}

var GameDebugHelper = function()
{
    this.KeyboardDebug = false;
    this.AIDebug = false;
    this.TilemapDebug = false;
    this.ImageDebug = false;
    this.StateChangeDebug = false;
}

GameDebugHelper.prototype = new DebugHelper();
GameDebugHelper.prototype.constructor = GameDebugHelper;

//create a global debug helper object
var debugHelper = new GameDebugHelper();
//you should show the window right here to get loading time errors or sintax errors
debugHelper.ShowWindow();

//catch window errors also
function WindowOnError(msg, url, line)
{
	debugHelper.Exception(msg, line + " at " + url);
	return true;
}
window.onerror = WindowOnError;

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Roberto Colnaghi
Software Developer
United States United States
I'm a passionate developer and videogame player.
Been in touch with Objective-C, Javascript, C#, C, Guild Wars 2, Tera and many more.
 
Javascript is one of my favorite languages.
Follow on   Twitter   Google+

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150327.1 | Last Updated 15 Dec 2007
Article Copyright 2007 by Roberto Colnaghi
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid