Tuesday, January 24, 2012

A Fresh Start to Spine.js for ASP.NET MVC with MeetSpine.js- Part 2

Welcome to the 2nd part of A Fresh Start to Spine.js for ASP.NET MVC with MeetSpine.js which is a helper to using Kazi Manzur Rashid's post, Meet Spine. If you're new, you may want to check out part 1 first.

Getting Jasmine Spec Runner Running

Unfortunatly, there isn't a whole lot of help here that Kazi give us regarding how we need to configure the Jasmine Spec Runner. We know that we need out page to look like the image to the right, but how do we get there?



Let's start by adding two new items to out specs folder. The first is a file called SpecRunner.html, and the second is a folder named models. In our models folder, add a new coffee file called task.coffee and spin.ajax.coffee. This is what your project should look like now


Open the spine.ajax.coffee file we just added to models and add the following line.

assets/javascripts/specs/models/spine.ajax.coffee
@Spine.Model.Ajax = {}

Now open task.coffee and we'll copy Kazi's code for the Task Spec section.

assets/javascripts/specs/models/task.coffee
MeetSpine = @MeetSpine

describe 'Task', ->

    beforeEach -> @task = new MeetSpine.Task

    describe 'created', ->

        it 'created date is today', ->
            (expect @task.createdAt).toBe Date.today().toString MeetSpine.DATE_FORMAT

        it 'is planned', ->
            (expect @task.planned).toBeTruthy()

    describe 'validation', ->

        it 'does not accept blank name', ->
            errors = @task.validate()
            (expect errors[0].name).toBe 'name'

        it 'only accepts integer as estimation', ->
            @task.name = 'dummy task'
            @task.estimation = 'foobar'
            errors = @task.validate()
            (expect errors[0].name).toBe 'estimation'

        it 'does not accept negative estimation', ->
            @task.name = 'dummy task'
            @task.estimation = -1
            errors = @task.validate()
            (expect errors[0].name).toBe 'estimation'

        it 'does not accept past date as deadline', ->
            @task.name = 'dummy task'
            @task.estimation = 10
            @task.deadlineAt = (Date.parse 'yesterday').toString MeetSpine.DATE_FORMAT
            errors = @task.validate()
            (expect errors[0].name).toBe 'deadlineAt'

        it 'no errors if valid', ->
            @task.name = 'dummy task'
            @task.estimation = 10
            @task.deadlineAt = (Date.parse 'tomorrow').toString MeetSpine.DATE_FORMAT
            errors = @task.validate()
            (expect errors).toBeUndefined()

Note: CoffeeScript is very touchy about how you indent your code, so be sure to indent your code just like Kazi has it.

If you're using Mindscape, you may have noticed that something isn't quite right at this point. Kazi has left off something that will cause us a lot of trouble if we just copy and past his code in. The problem is with line 30 in Kazi's code for the Task Validation section. Take a close look it and see if you can discover what it is. You may notice that compare statement is missing what it's supposed to compare against, in our case 0. The correct code is actually

assets/javascripts/models/Task.coffee
@MeetSpine ?= {}

MeetSpine.DATE_FORMAT = DATE_FORMAT = 'yyyy-MM-dd'
DATE_EXPRESSION = ///^\d{4}[-]\d{2}[-]\d{2}$///

class Task extends Spine.Model
    @configure 'Task', 'name', 'planned', 'notes', 'estimation', 'createdAt', 'deadlineAt', 'completedAt'

    # Default values
    createdAt: Date.today().toString DATE_FORMAT
    planned: true

    validate: ->
        errors = []

        addError = (name, message) ->
            error = { name: name, messages: [] }
            error.messages.push message
            errors.push error

        addError 'name', 'Name cannot be blank.' unless @name

        if @estimation
            estimation = parseInt @estimation, 10
            addError 'estimation', 'Estimation must be a positive integer.' if (isNaN estimation) or estimation < 1

        if @deadlineAt
            if DATE_EXPRESSION.test @deadlineAt
                addError 'deadlineAt', 'Deadline cannot be in past date.' if ((Date.parse @deadlineAt, DATE_FORMAT).compareTo Date.today()) < 0
            else
                addError 'deadlineAt', "Unable to recognize the date format."

        errors if errors.length

MeetSpine.Task = Task

With that issue fixed, we can now start on the SpecRunner.html file. Add the following to the file:

assets/javascripts/specs/SpecRunner.html
<!DOCTYPE html>
<html>
    <head>
        <title>Jasmine Spec Runner</title>
        <link rel="shortcut icon" type="image/png" href="jasmine/jasmine_favicon.png" />
        <link rel="stylesheet" href="jasmine/jasmine.css" />
        <script type="text/javascript" >
        <!--
            window.MeetSpine = {};
        //-->
        </script>
        <script type="text/javascript" src="jasmine/jasmine.js"></script>
        <script type="text/javascript" src="jasmine/jasmine-html.js"></script>
        <script type="text/javascript" src="../lib/jquery.js"></script>
        <script type="text/javascript" src="../lib/date.js"></script>
        <script type="text/javascript" src="../lib/spine.js"></script>
        <script type="text/javascript" src="models/spine.ajax.js"></script>
        <script type="text/javascript" src="../models/task.js"></script>
        <script type="text/javascript" src="models/Task.js"></script>
        <script type="text/javascript">
        <!--
            (function () {
                var jasmineEnv = jasmine.getEnv();
                jasmineEnv.updateInterval = 1000;

                var trivialReporter = new jasmine.TrivialReporter();

                jasmineEnv.addReporter(trivialReporter);

                jasmineEnv.specFilter = function (spec) {
                    return trivialReporter.specFilter(spec);
                };

                var currentWindowOnload = window.onload;

                window.onload = function () {
                    if (currentWindowOnload) {
                        currentWindowOnload();
                    }
                    execJasmine();
                };

                function execJasmine() {
                    jasmineEnv.execute();
                }
            })();
        //-->
        </script>
    </head>

    <body>
    </body>
</html>

If you're not using Mindscape, you're going to want to compile your CoffeeScript at this point, otherwise you can just open up SpecRunner in your favorite browser. Look in the upper right hand corner and you'll notice that there is an option there to show "passed" test, click it and your page should now look just like Kazi's.

Part 3

No comments:

Post a Comment