How to get full class name, including module name from an instance at runtime in TypeScript

Let’s assume we have the class [GuidGenerator] in a TypeScript module [research.my.long.namespace] and at runtime you have an instance of the GuidGenerator, how do you get the full class name including module name, in this case: “research.my.long.namespace.GuidGenerator”.

Well you walk the object graph starting with the root / global object, in the browser this will be the window object.

 

NOTE: all code is in “strict” modus.

 

TypeScript Class [GuidGenerator]:

module research.my.long.namespace {
    "use strict";

    export interface IGuidGenerator {
        generate(): string;
    }

    export class GuidGenerator implements IGuidGenerator {
        generate() {
            var randomNumberToGuid = function (c) {
                var r = Math.random() * 16 | 0, v = c == 'x' ? r : r & 0x3 | 0x8;
                return v.toString(16);
            }
            return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, randomNumberToGuid);
        }
    }
}

We use the resolver object to get the full class name:

var resolver = new NameResolver();
var generator = new research.my.long.namespace.GuidGenerator();
var name = resolver.getFullClassNameFromInstance(generator, window)
console.log(name);

Result

image

The resolver class

module research.metadata {
    "use strict";

    interface IProcessResult {
        fnFound: boolean;
        path: Array<string>;
    }

    export interface INameResolver {
        getFullClassNameFromInstance(instance: any, global: any): string;
    }

    export class NameResolver implements INameResolver {
        private _fn: any;
        private _global: any;
        private _processed: Array<any>;

        /**
            To handle recursiveness in the object graph, collect all handled nodes in the object graph,
            so an object is only traversed once.
        */
        isProcessed(obj: any): boolean {
            var result = false;
            for (var i, length; i < length; i += 1) {
                if (this._processed[i] === obj) {
                    return true;
                }
            }
            return result;
        }

        processProperty(obj: any, key: string, path: Array<string>): IProcessResult {
            var result: IProcessResult = {
                fnFound: false,
                path: path
            }

            if (obj.hasOwnProperty(key)) {
                try {
                    var prop = obj[key];
                    if (prop === this._fn) {
                        // Function found, stop traversing the object graph.
                        result.fnFound = true;
                        return result;
                    }
                    
                    // Continue traversing the object graph.
                    result = this.processObject(prop, path);

                    if (result.fnFound) {
                        // Function found, stop traversing the object graph.
                        return result;
                    }
                } catch (error) {
                    // Access to some properties result in exceptions.
                }
            }
            

            return result;
        }

        processObject(obj: any, path: Array<string>): IProcessResult {
            var result: IProcessResult = {
                fnFound: false,
                path: path
            }

            if (this.isProcessed(obj)) {
                return result;
            }
            this._processed.push(obj);
            
            for (var key in obj) {
                var pathCopy = path.slice();
                pathCopy.push(key);
                var processResult = this.processProperty(obj, key, pathCopy);
                if (processResult.fnFound) {
                    return processResult;
                }
            }

            return processResult;
        }

        getFullClassNameFromInstance(instance: any, global: any): string {
            this._fn = instance["constructor"];
            this._global = global;
            this._processed = [];

            var processResult = this.processObject(this._global, []);

            var fullFnName = "";
            if (processResult.fnFound) {
                fullFnName = processResult.path.join(".");
            }

            return fullFnName;
        }
    }
}

Running javascript and typescript unit tests in Microsoft Visual Studio 2012 with Chutzpah

To unit test my JavaScript files in Microsoft Visual Studio 2012, side by side mine C# unit tests, I use Chutzpah.

Chutzpah comes with 2 Microsoft Visual Studio 2012 extensions:

1. Chutzpah Test Adapter for Visual Studio 2012, allows you to run QUnit / Jasmine javascript test files side by side C# unit tests in the test explorer or continuous build process.

2. Chutzpah – A JavaScript Test Runner, allows you to run individual QUnit / Jasmine JavaScript test files in Microsoft Visual Studio 2010 and 2012 by right clicking a test file and choosing "".

 

In Microsoft Visual Studio 2012

– Tools > Extensions and Updates…

– Install both plugins and restart Microsoft Visual Studio 2012

 

image

 

Create a new UnitTest project:

 

image

 

Enable "Run Tests after build"

(The "Play" button found at the top of the Test Explorer")

Now when you press CTRL + SHIFT + B the project will be build and all tests will execute.

 

image 

 

TIP: Never use CTRL + S to save your file, just use CTRL + SHIFT + B.

Now you can see the C# unit test "TestMethod1" succeeded.

 

QUnit for ASP.NET MVC

Right click unit test project and click Manage NuGet Packages…

Click install.

 

image

 

Add Code.js and Test.js

The Code.js file will contain the JavaScript code we want to test.

The Test.js  file will contain the JavaScript test code written, by using the QUnit test framework.

 

Code.js

image

 

Test.js

Reference qunit and the Code.js file to get code completion in your test code.

 

image

 

Code completion in JavaScript in Microsoft Visual Studio 2012 unit test file

 

image

 

 

Run C# and JavaScript unit tests side by side in the Test Explorer

By pressing CTRL + SHIFT + B

image

 

Run only JavaScript unit test file

If you only want to run the QUnit test, right click on the JavaScript Test.js file and choose "Run JS Tests".

 

image

 

If you want to run JavaScript unit tests by pressing a keyboard shortcut, you need to install

image

 

Then you can bind a shortcut to the ProjectAndSolutionsContextMenus.Project.RunJSTests command to run JS tests.

(http://matthewmanela.com/blog/chutzpah-1-1-0-released/)

 

image