Testing Your JavaScript with Jasmine

Testing Your JavaScript with Jasmine

Tutorial Details
  • Topic: JavaScript testing
  • Difficulty: Intermediate
  • Estimated Completion Time: 40 min

We all know we should be testing our code, but we don’t actually do it. I guess it’s fair to say that most of us put it off because, nine times out of ten, it means learning yet another concept. In this tutorial, I’ll introduce you to a great little framework for testing your JavaScript code with ease.


Step 0: Understanding BDD

Today, we’re going to be learning about the Jasmine BDD testing framework. But we’re stopping here for a detour first, to talk very briefly, about BDD and TDD. If you’re not familiar with these acronyms, they stand for Behaviour-Driven Development and Test-Driven Development. I’m in the middle of learning about what each of these is in practice and how they are different, but here are some of the basic differences:

BDD and TDD … stand for Behaviour-Driven Development and Test-Driven Development.

TDD in its simplest form is just this:

  1. Write your tests
  2. Watch them fail
  3. Make them pass
  4. Refactor
  5. Repeat

That’s pretty easy to understand, eh?

BDD is a little more complex: as I understand it right now, I don’t think that you or I as a single developer can actually practice it fully; it’s more of a team thing. Here are a few of the practices of BDD:

  • Establishing the goals of different stakeholders required for a vision to be implemented
  • Involving stakeholders in the implementation process through outside-in software development
  • Using examples to describe the behavior of the application, or of units of code
  • Automating those examples to provide quick feedback and regression testing

To learn more, you can read the extensive Wikipedia Article (from which those points were taken).

All this to say that, while Jasmine bills itself as a BDD framework, we’re going to be using it in a more TDD-style way. That doesn’t mean we’re using it wrong, though. Once we’re finished, you’ll be able to test your JavaScript with ease … and I expect you to do it!


Step 1: Learning the Syntax

Jasmine takes a lot of cues from Rspec.

If you’re at all familiar with Rspec, the de facto BDD framework, you’ll see that Jasmine takes a lot of cues from Rspec. Jasmine tests are primarily two parts: describe blocks and it blocks. Let’s see how this works.

We’ll look at some closer-to-real-life tests in a few, but for now, we’ll keep it simple:

describe('JavaScript addition operator', function () {
    it('adds two numbers together', function () {
        expect(1 + 2).toEqual(3);
    });
});

Both the describe and it functions take two parameters: a text string and a function. Most test frameworks try to read as much like English as possible, and you can see this with Jasmine. First, notice that the string passed to describe and the string passed to it form a sentence (of sorts): “JavaScript addition operator adds two numbers together.” Then, we go on to show how.

Inside that it block, you can write all the setup code you need for your test. We don’t need any for this simple example. Once you’re ready to write the actual test code, you’ll start with the expect function, passing it whatever you are testing. Notice how this forms a sentence as well: we “expect 1 + 2 to equal 3.”

But I’m getting ahead of ourselves. As I said, whatever value you pass into expect will be tested. The method you call, off the returned value of expect, will be determined by which test is run. This group of methods is called ‘matchers’, and we’ll be looking at several of them today. In this case, we’re using the toEqual matcher, which checks to see that the value passed to expect and the value passed to toEqual are the same value.

I think you’re ready to take this to the next level, so let’s set up a simple project using Jasmine.


Step 2: Setting up a Project

Jasmine can be used by itself; or you can integrate it with a Rails project. We’ll do the former. While Jasmine can run outside the browser (think Node, among other places), we can get a really nice little template with the download.

So, head on over to the standalone download page and get the latest version. You should get something like this:

Jasmine Download

You’ll find the actual Jasmine framework files in the lib folder. If you prefer to structure your projects differently, please do so; but we’re going to keep this for now.

There’s actually some sample code wired up in this project template. The “actual” JavaScript ( the code we want to test) can be found in the src subdirectory; we’ll be putting ours there shortly. The testing code—the specs—go in the spec folder. Don’t worry about the SpecHelper.js file just yet; we’ll come back to that.

That SpecRunner.html file is what runs the tests in a browser. Open it up (and check the “passed” checkbox in the upper right corner), and you should see something like this:

Sample Tests

This shows us that all the tests for the sample project are passing. Once you get through this tutorial, I recommend you open up the spec/PlayerSpec.js file and peruse that code. But right now, let’s give this test writing stuff a try.

  • Create convert.js in the src folder.
  • Create convertSpec.js in the spec folder,
  • Copy the SpecRunner.html file and rename it SpecRunner.original.html.
  • Remove the links to the sample project files in SpecRunner.html and add these lines:

    <script src="src/convert.js"><>/script>
    <script src="spec/convertSpec.js"></script>

Now we’re ready to create a mini-library that will convert between measurement units. We’ll start by writing the tests for our mini-library.


Step 3: Writing the Tests

So, let’s write our tests, shall we?

describe( "Convert library", function () {
    describe( "distance converter", function () {

        });

        describe( "volume converter", function () {

    });
});

We start with this; we’re testing our Convert library. You’ll notice that we’re nesting describe statements here. This is perfectly legal. It’s actually a great way to test seperate functionality chunks of the same codebase. Instead of two seperate describe calls for Convert library’s distance conversions and volume conversions, we can have a more descriptive suite of tests like this.

Now, onto the actual tests. I’ll repeat the inner describe calls here for your convenience.

describe( "distance converter", function () {
    it("converts inches to centimeters", function () {
        expect(Convert(12, "in").to("cm")).toEqual(30.48);
    });

    it("converts centimeters to yards", function () {
        expect(Convert(2000, "cm").to("yards")).toEqual(21.87);
    });
});

Here are our tests for distance conversions. It’s imporant to notice something here: we haven’t written a speck of code for our Convert library yet, so in these tests we’re doing more than just check to see if it works: we’re actually deciding how it will be used (and therefore implemented). Here’s how we’ve decided to make our conversions:

Convert(<number>, <from unit string>).to(<to unit string>);

Yes, I’m taking a cue from the way Jasmine has implemented its tests, but I think it’s a nice format. So, in these two tests, I’ve made the conversions myself (ok, with a calculator) to see what the results of our calls should be. We’re using the toEqual matcher to see if our tests pass.

Here’s the volume tests:

describe( "volume converter", function () {
    it("converts litres to gallons", function () {
        expect(Convert(3, "litres").to("gallons")).toEqual(0.79);
    });

    it("converts gallons to cups", function () {
        expect(Convert(2, "gallons").to("cups")).toEqual(32);
    });
});

And I’m going to add two more tests in our top-level describe call:

it("throws an error when passed an unknown from-unit", function () {
    var testFn = function () {
        Convert(1, "dollar").to("yens");
    }
    expect(testFn).toThrow(new Error("unrecognized from-unit"));
});

it("throws an error when passed an unknown to-unit", function () {
    var testFn = function () {
        Convert(1, "cm").to("furlongs");
    }
    expect(testFn).toThrow(new Error("unrecognized to-unit"));
});

These check for errors that should be thrown when unknown units are passed into either the Convert function or the to method. You’ll notice that I’m wrapping the actual conversion in a function and passing that to the expect function. That’s because we can’t call the function as the expect parameter; we need to hand it a function and let it call the function itself. Since we need to pass a parameter to that to function, we can do it this way.

The other thing to note is that I’m introducing a new matcher: toThrow, which takes an error object. We’ll look at some more matchers soon.

Now, if you open SpecRunner.html in a browser, you’ll get this:

Convert failed tests

Great! Our tests are failing. Now, let’s open our convert.js file and do some work:

function Convert(number, fromUnit) {
    var conversions = {
            distance : {
                meters : 1,
                cm     : 0.01,
                feet   : 0.3048,
                inches : 0.0254,
                yards  : 0.9144
            },
            volume : {
                liters : 1,
                gallons: 3.785411784,
                cups   : 0.236588236 
            }
        },
        betweenUnit = false,
        type, unit;

    for (type in conversions) {
        if (conversions(type)) {
            if ( (unit = conversions[type][fromUnit]) ) {
                betweenUnit = number * unit * 1000;
            }
        }
    }

    return {
        to : function (toUnit) {
            if (betweenUnit) {
                for (type in conversions) {
                    if (conversions.hasOwnProperty(type)) {
                        if ( (unit = conversions[type][toUnit]) ) {
                            return fix(betweenUnit / (unit * 1000));
                        }
                    }
                }
                throw new Error("unrecognized to-unit");
            } else {
                throw new Error("unrecognized from-unit");
            }  

            function fix (num) {
                return parseFloat( num.toFixed(2) );
            }
        }
    };
}

We’re not really going to discuss this, because we’re learning Jasmine here. But here are the main points:

  • We’re making the conversions by storing the conversion in an object; conversion numbers are classified by type (distance, volume, add your own). For each field of measurement, we have a base value (meters or liters, here) that everything converts to. So when you see yards: 0.9144, you know that that’s how many yards there are in a meter. Then, to convert yards to, say, centimeters, we multiply yards by the first parameter (to get the number of meters) and then divide the product by cm, the number of meters in a centimeter. This way, we don’t have to store the conversion rates for every pair of values. This also makes it easy to add new values later.
  • In our case, we’re expecting the units passed in to be the same as the keys we’re using in the conversion “table.” If this were a real library, we’d want to support multiple formats—like ‘in’, ‘inch’, and ‘inches’—and therefore we’d want to add some logic to match the fromUnit to the right key.
  • At the end of the Convert function, we store the intermediate value in betweenUnit, which is initialized to false. That way, if we don’t have the fromUnit, betweenUnit will be false going into the to method, and so an error with be thrown.
  • If we don’t have the toUnit, a different error will be thrown. Otherwise, we’ll divide as neccessary and return the converted value.

Now, go back to SpecRunner.html and reload the page. You should now see this (after checking “Show passed”):

There you go! Our tests are passing. If we were developing a real project here, we would write tests for a certain chunk of functionality, make them pass, write tests for another check, make them passs, etc. But since this was a simple example, we’ve just done it all in one fell swoop.

And now that you’ve seen this simple example of using Jasmine, let’s look at a few more features that it offers you.


Step 4: Learning the Matchers

So far, we’ve used two matchers: toEqual and toThrow. There are, of course, many others. Here are a few you’ll probably find useful; you can see the whole list on the wiki.

toBeDefined / toBeUndefined

If you just want to make sure a variable or property is defined, there’s a matcher for that. There’s also one to confirm that a variable or property is undefined.

it("is defined", function () {
    var name = "Andrew";
    expect(name).toBeDefined();
})

it("is not defined", function () {
    var name;
    expect(name).toBeUndefined();
});

toBeTruthy / toBeFalsy

If something should be true or false, these matchers will do it.

it("is true", function () {
    expect(Lib.isAWeekDay()).toBeTruthy();
});
it("is false", function () {
    expect(Lib.finishedQuiz).toBeFalsy();
});

toBeLessThan / toBeGreaterThan

For all you number people. You know how these work:

it("is less than 10", function () {
    expect(5).toBeLessThan(10);
});
it("is greater than 10", function () {
    expect(20).toBeGreaterThan(10);
});

toMatch

Have some output text that should match a regular expression? The toMatch matcher is ready and willing.

it("outputs the right text", function () {
    expect(cart.total()).toMatch(/\$\d*.\d\d/);
});

toContain

This one is pretty useful. It checks to see if an array or string contains an item or substring.

it("should contain oranges", function () {
    expect(["apples", "oranges", "pears"]).toContain("oranges");
});

There are a few other matchers, too, that you can find in the wiki. But what if you want a matcher that doesn’t exist? Really, you should be able to do just about anything with some set-up code and the matchers Jasmine provides, but sometimes it’s nicer to abstract some of that logic to have a more readable test. Serendipitously (well, actually not), Jasmine allows us to create our own matchers. But to do this, we’ll need to learn a little something else first.

Step 5: Covering Before and After

Often—when testing a code base—you’ll want to perform a few lines of set-up code for every test in a series. It would be painful and verbose to have to copy that for every it call, so Jasmine has a handy little feature that allows us to designate code to run before or after each test. Let’s see how this works:

describe("MyObject", function () {
    var obj = new MyObject();

    beforeEach(function () {
        obj.setState("clean");
    });

    it("changes state", function () {
        obj.setState("dirty");
        expect(obj.getState()).toEqual("dirty");
    })
    it("adds states", function () {
        obj.addState("packaged");
        expect(obj.getState()).toEqual(["clean", "packaged"]);
    })
});

In this contrived example, you can see how, before each test is run, the state of obj is set to “clean”. If we didn’t do this, the changed made to an object in a previous test persist to the next test by default. Of course, we could also do something similar with the AfterEach function:

describe("MyObject", function () {
    var obj = new MyObject("clean"); // sets initial state

    afterEach(function () {
        obj.setState("clean");
    });

    it("changes state", function () {
        obj.setState("dirty");
        expect(obj.getState()).toEqual("dirty");
    })
    it("adds states", function () {
        obj.addState("packaged");
        expect(obj.getState()).toEqual(["clean", "packaged"]);
    })
});

Here, we’re setting up the object to begin with, and then having it corrected after every test. If you want the MyObject function so you can give this code a try, you can get it here in a GitHub gist.

Step 6: Writing Custom Matchers

Like we said earlier, customer matchers would probably be helpful at times. So let’s write one. We can add a matcher in either a BeforeEach call or an it call (well, I guess you could do it in an AfterEach call, but that wouldn’t make much sense). Here’s how you start:

beforeEach(function () {
    this.addMatchers({

    });
});

Pretty simple, eh? We call this.addMatchers, passing it an object parameter. Every key in this object will become a matcher’s name, and the associated function (the value) will be how it is run. Let’s say we want to create a matcher that with check to see if one number is between two others. Here’s what you’d write:

beforeEach(function () {
    this.addMatchers({
        toBeBetween: function (rangeFloor, rangeCeiling) {
            if (rangeFloor > rangeCeiling) {
                var temp = rangeFloor;
                rangeFloor = rangeCeiling;
                rangeCeiling = temp;
            }
            return this.actual > rangeFloor && this.actual < rangeCeiling;
        }
    });
});

We simply take two parameters, make sure the first one is smaller than the second, and return a boolean statement that evaluates to true if our conditions are met. The important thing to notice here is how we get a hold of the value that was passed to the expect function: this.actual.

it("is between 5 and 30", function () {
    expect(10).toBeBetween(5, 30);
});

it("is between 30 and 500", function () {
    expect(100).toBeBetween(500, 30);
});

This is what the SpecHelper.js file does; it has a beforeEach call that adds the matcher tobePlaying(). Check it out!


Conclusion: Having Fun Yourself!

There’s a lot more you can do with Jasmine: function-related matchers, spies, asynchronous specs, and more. I recommend you explore the wiki if you’re interested. There are also a few accompanying libraries that make testing in the DOM easier: Jasmine-jQuery, and Jasmine-fixture (which depends on Jasmine-jQuery).

So if you aren’t testing your JavaScript so far, now is an excellent time to start. As we’ve seen, Jasmine’s fast and simple syntax makes testing pretty simple. There’s just no reason for you not to do it, now, is there?

Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • guiii

    what a cool library

  • http://mileonemedia.com JoeCianflone

    This looks pretty cool, but I have a huge problem with the library. My wife’s name is Jasmine, so if I send out a tweet saying something like, “fiddling around with Jasmine” or “God why is Jasmine so f$*king annoying!!” I’m going to get in some trouble. Other then that…this looks great :)

  • Richo

    Great article, there aren’t many in depth JavaScript TDD going around.

    One thing I noticed is that you write a number of tests before even getting one of them to pass? My understanding in TDD is that you write ONE test, make sure it fails, implement the bare minimum to get that test to pass, make it green, refactor the code if need be, make sure the tests pass again and then write the next test.

    • http://andrewburgess.ca Andrew Burgess
      Author

      You’re completely right; since this tutorial was more about learning how to use Jasmine than learning TDD, I mentioned that, but didn’t focus on it. However, in practice, that’s the way to do TDD. Thanks for clarifying that! :)

  • dörtedev

    Step 0? Really? Iterate from 1 plx :P

    BTW: Would love to use this intuitive syntax, but doh clearly > jasmine when it comes to dojowidget logic testing :-/

  • http://www.jakub.chodorowicz.pl/ Jakub Chodorowicz

    Looks good and concise! Does it cover also user interaction area? Sth like assuring that some pop up box show when user clicks a button etc?

    • http://andrewburgess.ca Andrew Burgess
      Author

      Jasmine itself doesn’t cover that kind of thing, but you can probably get something like that working with Jasmine-jQuery https://github.com/velesin/jasmine-jquery; it provides some interaction with the DOM.

  • Thomas

    How is the path displayed at the bottom of the finder window (http://d2o0t5hpnwv4c1.cloudfront.net/1026_jasmine/jasmine-download.png) ? Is it an app that mimic the finder ?

    Sorry unrelated to the content of your article. I’ll keep reading ^^

    • http://andrewburgess.ca Andrew Burgess
      Author

      When you’re focused on a Finder window, choose “View > Show Path Bar.” That should do it for you!

  • LA

    Excellent overview. Perhaps you might want to address the following in a separate post… can you outline what’s involved in setting up Jasmine for when the application being developed is not just standalone (specifically, with Node.js you can be developing an application that contains both server side and client side logic).

    Thanks!

  • Zach

    Great tutorial, and nice to see you following up in the comments!

    Thanks!

  • Eoin

    It’s really nice to finally get an overview of the Jasmine Framework as this is definitely something that I would like to use more often. More articles on Javascript testing or TDD and BDD would also be a great addition.

    FYI, I had some issues with getting Step 3 to work and they all involved the code for the convert.js file. I had to make the following changes for my tests to pass

    1. Line 8: change inches to in
    2. Line 12: change liters to litres
    3. Line 20: change conversions(type) to conversions[type]

    Alternatively, for 1 & 2 you can change the code in the specrunner instead. Note, I was following the code displayed above and not in the download files so maybe there’s a few discrepancies between the two.

    I fully enjoyed the article though.

  • http://www.adminiabilisim.com resul

    merhaba süper bir site olmuş yorum sistemni deniyorum sadece

  • http://www.telecommutetojuryduty.com/wordpress Dominick

    The code snippet after this line: “Remove the links to the sample project files in SpecRunner.html and add these lines:”

    has a typo; there is an errant angle bracket that might derail those (especially newbs) who are copy/pasting the snippet ;)

    • http://www.telecommutetojuryduty.com/wordpress Dominick

      also, unless I’m crazy, there’s no way that you’ll get the screenshot full o’ green passings after the line “That SpecRunner.html file is what runs the tests in a browser. Open it up (and check the “passed” checkbox in the upper right corner), and you should see something like this:”

      fixes I had to make to get it to work as described:

      1) in convert.js,
      conversions(type) should be
      conversions[type]

      2) in convertSpec.js,
      expect(Convert(12, “inches”).to(“cm”)).toEqual(30.48); should be
      expect(Convert(12, “in”).to(“cm”)).toEqual(30.48);

      3) in convertSpec.js,
      expect(Convert(3, “litres”).to(“gallons”)).toEqual(0.79); should be
      expect(Convert(3, “liters”).to(“gallons”)).toEqual(0.79);

      of course the latter two could easily be it(“throws an error when…” type tests if you want them to be!

      sorry to poke holes through this tute, but i’m following it step-by-step and things aren’t working left & right. i guess i’m paying attention too hard :)

      • http://telecommutetojuryduty.com/wordpress/ Dominick

        Oops, I thought I had checked all the comments before making my corrections, but somehow I didn’t see Eoin’s corrections :)

      • http://users.on.net/~wulfgar.pro James

        I’m thinking the erroneous code was intentional – helps people get used to TDD and Jasmine.

  • Boyko

    Thanks for the nice tutorial!

    I second Eoin:

    Line 20 in convert.js needs to be changed from

    conversions(type) to conversions[type]

    or code won’t work and tests won’t pass.

    Outside that, pretty good work!

  • John

    Unfortunately for me, this tutorial that doesn’t work:

    When I enter the examples as you have put them, I get
    TypeError: conversions is not a function in file:///Users/johnhammink/Documents/Projects/JasmineProject2/src/convert.js (line 20)

    As I understand (and my tests were never

    All of the test fail and none of them run. Kind of frustrating and not helpful for this reason.

    • Paolo Pietropoli

      Seeing that “conversions” is an object and not a function I suppose the correct writing would be “conversions[type]“. Just my 2 cents…

      • Mike.

        Great tutorial… on line 19 make it “conversions[type]” per the comment. Also “litres” needs to be replaced with “liters” in the spec file. Then the tests pass.

  • John

    Ahh, I didn’t see Boiko’s correction. Thanks Boiko! I see also Dominick’s and others comments and as a noob, set about implementing them. I wonder, though if it is possible to please correct the examples to reflect the comments? This would save some headache.

  • http://www.ivks.in Vishal Kr Singh

    Thank you, but was really expecting more from a tutorial, atleast more than what the official website teaches you, the only extra part seems to be the new example.

  • Mike

    Not sure what I’m doing wrong but all my tests fail due to ‘Convert is not defined’

    Even when from the downloadable source all tests fail.

    All files are being loaded successfully, and the tests for SpecRunner.MyObject pass.

    Clues anyone?

    • B Seven

      I got the same error…

      • Paolo Pietropoli

        @google-a40dfe4121e51dec0bfcfbb8c0dbe00e:disqus I had the same error too. Check any error in the console. Mine was a missing parenthesis.

  • http://techoctave.com/c7 TVD

    The time to start testing is now indeed. More developers should be testing their Javascript. Period.

    It’s really great you took the time to explain how you and your team do JavaScript Testing with Jasmine. The more examples, the better for the code quality we produce as JavaScript developers.

    I especially liked that your sample business logic throw errors and how to catch them in Jasmine. This is very helpful and, dare I say, beautifully showcased here today. Keep up the great work!

  • Lego

    So many errors and typos in this tut – no wonder the author depends on TDD : ]

  • Chris McNabb

    Thanks for the tutorial! It helped me get my feet off the ground with Jasmine. Thanks to those who posted the fixes to the convert.js file. All that RED was frustrating me for a while until I figured out what the fix was. Cheers!

    cm

  • http://julienrenaux.fr Julien

    The standalone page that you shared: http://pivotal.github.com/jasmine/download.html does not work anymore (Github 404)

    To make it work you will need to clone the Jasmine (or your fork) repository:
    git clone https://github.com/pivotal/jasmine.git

    The standalone files that the author is talking about can be found there: lib/jasmine-core/example

    You will have to change some paths on lib/jasmine-core/example/SpecRunner.html page.

    Become

    • http://julienrenaux.fr Julien

      The code snippet to include code does not work. I wanted to say:

      <link rel="stylesheet" type="text/css" href="lib/jasmine-1.1.0.rc1/jasmine.css">
      <script type="text/javascript" src="lib/jasmine-1.1.0.rc1/jasmine.js"></script>
      <script type="text/javascript" src="lib/jasmine-1.1.0.rc1/jasmine-html.js"></script>

      Become

      <link rel="stylesheet" type="text/css" href="../jasmine.css">
      <script type="text/javascript" src="../jasmine.js"></script>
      <script type="text/javascript" src="../jasmine-html.js"></script>

  • http://billstron.com Bill Burke

    Your download link is incorrect. It gets a 404 from Github. I think you want the following: https://github.com/pivotal/jasmine/downloads

  • http://www.facebook.com/davide.schembari Davide Schembari

    It would have been nicer to use an easier js code for your Convert, as I’m not a js guru and it’s really unreadable to a novice like me. Thanks for the effort though.

  • Vishnudas

    Really thanks for this tutorial…

    But there are lot of Errors in code only :-(

    Just two changes :

    1. Change conversion(type) to the conversions[type] on line 19.
    2. Also “litres” needs to be replaced with “liters” in the spec file.

  • thanksfornothing

    I found this tutorial to be frustrating due to the incorrect instructions and syntax errors, please fix it or take it off the web, spending an entire day debugging a tutorial is not fun or nice.

  • http://www.facebook.com/krisyoung1980 Kris Young

    Thanks for posting this, really helped me get my head around using Jasmine… Also, in defense of the typos that appear in the code, the tests helped me identify and fix them really quickly which only added to the learning! In my experience, you only really absorb something when you’re forced to think so even if they weren’t deliberate, I would claim them as such. :)

  • Revingbell

    Hi, i’m sorry, but the more I learn about this tool, the more I wonder about its usefulness, what does it do that you can’t already verify with conditions (if.. else..) directly in you JavaScript, or empirically by verifying your application works like it’s supposed to?

  • Guest

    convert.js

    function Convert(number, fromUnit) {

    var conversions = {

    distance : {

    meters : 1,

    cm : 0.01,

    feet : 0.3048,

    inches : 0.0254,

    yards : 0.9144

    },

    volume : {

    liters : 1,

    gallons: 3.785411784,

    cups : 0.236588236

    }

    },

    betweenUnit = false,

    type, unit;

    for (type in conversions) {

    if (conversions[type]) {

    if ( (unit = conversions[type][fromUnit]) ) {

    betweenUnit = number * unit * 1000;

    }

    }

    }

    return {

    to : function (toUnit) {

    if (betweenUnit) {

    for (type in conversions) {

    if (conversions.hasOwnProperty(type)) {

    if ( (unit = conversions[type][toUnit]) ) {

    return fix(betweenUnit / (unit * 1000));

    }

    }

    }

    throw new Error("unrecognized to-unit");

    } else {

    throw new Error("unrecognized from-unit");

    }

    function fix (num) {

    return parseFloat( num.toFixed(2) );

    }

    }

    };

    }

  • http://www.facebook.com/pinal.bhatt Pinal Bhatt

    Really great example to start Jasmine. Gr8 work and excellent explanation. Though few typos but an intelligent developer should be able to fix it after inspecting the code.

    Here is the Code that perfectly worked for me:

  • http://www.facebook.com/pinal.bhatt Pinal Bhatt

    Great Tutorial to start with Jasmine. Gr8 work and excellent explanation. Though some typos in code but intelligent programmer should be able to fix it by inspecting the code.