Introduction
This is a quick tip on how to write unit tests for Typescript using Jasmine.
Background
I have used Jasmine with vanilla Javascript in the past however testing Typescript was bit different and took me few hours to set up the environment correctly. I found less valid and upto date details and therefore wanted to write this article!
As mentioned this is a very quick tip and therefore I don't go through the details of what Typescript or Jasmine are. Its assumed that the readers are familiar to both Typescript (Javascript superset) and Jasmine (testing framework).
I am using Visual Studio 2015, Jasmine 2.2 and Chutpah test runner.
The following steps are required to configure the environment:
- Install the Chutzpah test runner adapter from https://visualstudiogallery.msdn.microsoft.com/f8741f04-bae4-4900-81c7-7c9bfb9ed1fe
- Install Chutzpah test runner context menu from https://visualstudiogallery.msdn.microsoft.com/71a4e9bd-f660-448f-bd92-f5a65d39b7f0
- Install Jasmine Definitly Typed nuget package i.e. jasmine.TypeScript.DefinitelyTyped
- And finally have a chutzpah.json file in the base of your scripts folder. This is very important as I had everything else ok but still Chutzpah was not finding my tests. See the details of the Chutzpah.json below.
- Importantly, to be noted that if you are using Visual Studio to create the Typescript then it is recommented to set the [ "Mode": "External"] in the Chutzpah.json file. This tells Chutzpah that there is an external tool that will build the Typescript and generate the equivalent Javascripts. Alternatively, Mode can be set to bat files to compile the Typescripts.
Once the above configurations are completed it is ready to write test for the Typescript application and both Chutzpah and Visual studio text explorer will show the tests.
Using the code
Assuming the following Typescript class to be tested:
interface IPerson {
getFullName() : string;
}
class Person implements IPerson {
private firstName: string;
private lastName: string;
setFirstName(value: string) {
this.firstName = value;
}
setLastName(value: string) {
this.lastName = value;
}
getFullName(lastNameFirst: boolean = false): string {
if (lastNameFirst) {
return this.lastName + ", " + this.firstName;
}
return this.firstName + ", " + this.lastName;
}
}
Here are the tests:
<reference path="../app/person.ts"><reference path="../typings/jasmine/jasmine.d.ts">
describe("Person FullName", () => {
var person: Person;
beforeEach(() => {
person = new Person();
person.setFirstName("Joe");
person.setLastName("Smith");
});
it("should concatenate first and last names", () => {
expect(person.getFullName()).toBe("Joe, Smith");
});
it("should concatenate first and last names - incorrect", () => {
expect(person.getFullName()).not.toBe("Joe, Doe");
});
it("should concatenate lastname first", () => {
expect(person.getFullName(true)).toBe("Smith, Joe");
});
it("should not concatinate firstname first", () => {
expect(person.getFullName(true)).not.toBe("Joe, Smith");
});
});
</reference></reference>
Content of the chutzpah.json:
{
"Compile": {
"Mode": "External",
"Extensions": [".ts"],
"ExtensionsWithNoOutput": [".d.ts"]
},
"References": [
{"Includes": ["*/Scripts/app/*.ts"], "Excludes": ["*/Scripts/app/*.d.ts"] }
],
"Tests": [
{ "Includes": ["*/Scripts/Tests/*.ts"], "Excludes": ["*/Scripts/Tests/*.d.ts"] }
]
}