<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>validates_presence_of :purpose : Tag jspec, everything about jspec</title>
    <link>http://lenaherrmann.net</link>
    <language>en_US</language>
    <ttl>40</ttl>
    <description>Lena Herrmann</description>
    <item>
      <title>Writing a testsuite for the CouchDB API</title>
      <description>&lt;p&gt;&lt;a href="http://couchdb.apache.org"&gt;CouchDB&lt;/a&gt; is a database that I quite like. In fact, I haven&amp;#8217;t done much else this winter, as the programming part of my thesis involved diving into many of CouchDB&amp;#8217;s features. I had just finished my little program and was desperately looking for an excuse not to start writing the thesis. Mercifully &lt;a href="http://twitter.com/janl"&gt;Jan&lt;/a&gt; from &lt;a href="http://couch.io"&gt;Couchio&lt;/a&gt; came along and asked if I wouldn&amp;#8217;t like to write a testsuite for CouchDB&amp;#8217;s Javascript HTTP API, and the documentation with it. I wanted!&lt;/p&gt;


&lt;h3 style="color:#949490;margin-left:6px;"&gt;What is this HTTP API?&lt;/h3&gt; 


&lt;p&gt;If you have worked with CouchDB from a Javascript program before (&lt;a href="http://www.quirkey.com/blog/2009/09/15/sammy-js-couchdb-and-the-new-web-architecture/"&gt;eg Sammy.js is a good companion for a simple web application&lt;/a&gt;), you have probably used the methods &lt;a href="http://github.com/apache/couchdb/blob/trunk/share/www/script/couch.js"&gt;a file named couch.js&lt;/a&gt; provides. With this interface you can easily access the most common CouchDB functionality without having to handle the XMLHttpRequest yourself. It allows you to create a &amp;#8220;database object&amp;#8221; and then perform things on this object, for example save or delete documents:

&lt;div class="CodeRay"&gt;&lt;pre&gt;&lt;span class="CodeRay"&gt;&lt;span class="kw"&gt;var&lt;/span&gt; db = &lt;span class="kw"&gt;new&lt;/span&gt; CouchDB(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;test_db&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
db.createDb();

&lt;span class="kw"&gt;var&lt;/span&gt; doc = {&lt;span class="ke"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; : &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Starbuck&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="ke"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; : &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Kara Thrace&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;};
&lt;span class="kw"&gt;var&lt;/span&gt; saved_doc = db.save(doc);

&lt;span class="c"&gt;// do something&lt;/span&gt;
db.deleteDoc({&lt;span class="ke"&gt;_id&lt;/span&gt; : &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;123&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="ke"&gt;_rev&lt;/span&gt; : saved_doc.rev});&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;


&lt;p&gt;If you&amp;#8217;re using JQuery, you can use the JQuery interface in &lt;a href="http://github.com/apache/couchdb/blob/trunk/share/www/script/jquery.couch.js"&gt;jquery.couch.js&lt;/a&gt;. It covers basically the same things as couch.js, but it uses, you guessed it, JQuery. That means you can send your requests asynchronously and handle the response in the callback. Same example:&lt;/p&gt;


&lt;div class="CodeRay"&gt;&lt;pre&gt;&lt;span class="CodeRay"&gt;&lt;span class="kw"&gt;var&lt;/span&gt; db = &lt;span class="pd"&gt;$&lt;/span&gt;.couch.db(&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;spec_db&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;);
db.create();

&lt;span class="kw"&gt;var&lt;/span&gt; doc = {&lt;span class="ke"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; : &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Starbuck&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="ke"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; : &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Kara Thrace&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;};
db.saveDoc(doc, {
  &lt;span class="ke"&gt;success&lt;/span&gt;: &lt;span class="kw"&gt;function&lt;/span&gt;(response){
    &lt;span class="c"&gt;// do something&lt;/span&gt;
    db.removeDoc({&lt;span class="ke"&gt;_id&lt;/span&gt; : &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;123&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="ke"&gt;_rev&lt;/span&gt; : response.rev});
  }
});&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;


&lt;p&gt;The code looks a bit more complicated, but with this API you have the full power of &lt;a href="http://lenaherrmann.net/2010/02/15/refactoring-asynchronous-code"&gt;asynchronicity&lt;/a&gt; in your head, where spelling the word asynchronicity is the worst part. &lt;/p&gt;


&lt;h3 style="color:#949490;margin-left:6px;"&gt;Writing the testsuite&lt;/h3&gt;


&lt;p&gt;I was free to choose which testing framework I wanted to use. The tests in CouchDB use a kind of home grown testing framework, which does its job, but is not really the state of the art of Unit Testing. The API tests aren&amp;#8217;t supposed to run within the normal CouchDB testsuite anyway. That is the one you always run in Futon when you installed CouchDB. So it was possible to use something different &amp;#8230; like &lt;a href="http://jspec.info/"&gt;JSpec&lt;/a&gt;. (I have also &lt;a href="http://lenaherrmann.net/2010/01/04/jspec-javascript-unit-testing-how-it-should-be"&gt;blogged&lt;/a&gt; and &lt;a href="http://lenaherrmann.net/2010/03/22/jspec-slides-of-my-talk-at-berlin-js-usergroup"&gt;talked&lt;/a&gt; about it in the past.)&lt;/p&gt;


&lt;p&gt;How to run JSpec tests? If you are familiar with JSpec tests, you know you define your tests in Javascript files, reference those from a HTML file and open that in a browser. When you want your tests to perform calls to the database, this won&amp;#8217;t work - you get the error message &amp;#8220;Access to restricted URI denied&amp;#8221;. Shortly this is because AJAX only allows connections to the same resource it is called from. Therefore you have to run the tests from within the database. CouchDB has a folder &lt;a href="http://github.com/apache/couchdb/blob/trunk/share/www/"&gt;share/www&lt;/a&gt;, which gets linked to the &amp;#8220;/_utils/&amp;#8221; path of your local installation. In this folder you find Futon. That&amp;#8217;s where you have to put your tests and all the helper scripts. Then you can run the tests directly from the couch by browsing to &lt;a href="http://127.0.0.1:5984/_utils/spec/run.html"&gt;/_utils/spec/run.html&lt;/a&gt;.&lt;/p&gt;


&lt;p&gt;Writing the testsuite was pretty straightforward. Along the way I found some bugs in the code (no surprise as it was written untested). One of the problems I had to solve I&amp;#8217;ve explained in another blogpost: &lt;a href="http://lenaherrmann.net/2010/04/29/security-in-couchdb-changing-the-authentication-db"&gt;How to overwrite the authentication_db so the tests don&amp;#8217;t interfere with the CouchDB setup.&lt;/a&gt;&lt;/p&gt;


&lt;p&gt;There&amp;#8217;s one thing I&amp;#8217;m not completely happy with: The tests do really need kind of long to run, up to 3 minutes, depends a lot on the browser and CPU load. The other CouchDB Javascript tests are a lot faster. I think the new ones are a bit more comprehensive. And I preferred a very clean setup to how it&amp;#8217;s done in the old tests: I have a database created before every single assertion and have it dropped afterwards. So you know exactly in which state your database is during the test. I guess that&amp;#8217;s worth the longer runtime.&lt;/p&gt;


&lt;p&gt;So. If you want to see a lot of JSpec code in action, and want to learn more about CouchDB, &lt;a href="http://github.com/lenalena/couchdb/tree/testsuite/share/www/spec/"&gt;have a look at the code&lt;/a&gt;. At the moment it&amp;#8217;s in my fork only, the community (someone - you?) has yet to integrate it into Futon. For all the details, read &lt;a href="http://mail-archives.apache.org/mod_mbox/couchdb-dev/201004.mbox/%3C4BB74086.4010302@zeromail.org%3E"&gt;my rundown and left TODOs&lt;/a&gt;.&lt;/p&gt;


&lt;h3 style="color:#949490;margin-left:6px;"&gt;Documentation&lt;/h3&gt; 


&lt;p&gt;I also wrote API Docs for all the methods. It &lt;a href="http://github.com/lenalena/couchdb-http-api-docs"&gt;can be found here&lt;/a&gt;. Later you will find it nicely formatted in the &lt;a href="http://wiki.apache.org/couchdb/Reference"&gt;CouchDB Wiki&lt;/a&gt; and &lt;a href="http://www.couch.io/docs"&gt;on the Couchio website&lt;/a&gt;.&lt;/p&gt;


&lt;p&gt;If you find anything is missing or you don&amp;#8217;t understand it, feel free to drop me a line. I&amp;#8217;m happy to clarify it as long as it&amp;#8217;s all freshly in my brain.&lt;/p&gt;


&lt;p style="font-size:0.9em;"&gt;PS - I consider example data in tests important, so I took all the data from the SciFi series &lt;a href="http://en.battlestarwiki.org/wiki/Portal:Battlestar_Galactica_%28RDM%29"&gt;Battlestar Galactica&lt;/a&gt;, currently on my playlist and I luv it. And it gave me an excuse to read in the Battlestar Wiki every now and then when I was looking for correct spelling :)&lt;/p&gt;
</description>
      <pubDate>Wed, 28 Apr 2010 12:07:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:e603b6cb-97da-442f-91a0-7f91f70fb52d</guid>
      <comments>http://lenaherrmann.net/2010/04/28/writing-a-testsuite-for-the-couchdb-api#comments</comments>
      <category>jquery</category>
      <category>jspec</category>
      <category>couchdb</category>
      <category>testing</category>
      <category>documentation</category>
      <trackback:ping>http://lenaherrmann.net/trackbacks?article_id=13</trackback:ping>
      <link>http://lenaherrmann.net/2010/04/28/writing-a-testsuite-for-the-couchdb-api</link>
    </item>
    <item>
      <title>JSpec: Slides of my talk at Berlin JS Usergroup</title>
      <description>&lt;p&gt;Last thursday I gave a talk at the monthly meeting of the &lt;a href="http://twitter.com/berlinjs"&gt;Berlin JS Usergroup&lt;/a&gt;. I was talking about &lt;a href="http://github.com/visionmedia/jspec"&gt;JSpec&lt;/a&gt;, a Javascript Unit Testing framework. Thanks to all who were there to listen and ask questions!&lt;/p&gt;


&lt;p&gt;Here are &lt;a href="http://www.slideshare.net/kilaulena/jspec-a-javascript-unit-testing-framework"&gt;the slides&lt;/a&gt;. When you have a look at them, make sure to also read the notes (next to the comments), so the slides make sense to you.
&lt;/p&gt;


&lt;p&gt;To find more information about JSpec, check out &lt;a href="http://github.com/visionmedia/jspec"&gt;the README on github&lt;/a&gt;, or read the &lt;a href="http://lenaherrmann.net/2010/01/04/jspec-javascript-unit-testing-how-it-should-be"&gt;blog post I wrote about it recently&lt;/a&gt;.&lt;p&gt;

&lt;p&gt;Thanks also to &lt;a href="http://twitter.com/gisikw"&gt;@gisikw&lt;/a&gt; and &lt;a href="http://twitter.com/tjholowaychuk"&gt;@tjholowaychuk&lt;/a&gt; for &lt;a href="http://slides.kevingisi.com/TestYourJavaScript/"&gt;this talk&lt;/a&gt; from which I borrowed a few grammar examples :)&lt;/p&gt;
</description>
      <pubDate>Mon, 22 Mar 2010 12:52:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:8e64ebfd-22ee-4b7b-885d-96a488801c87</guid>
      <comments>http://lenaherrmann.net/2010/03/22/jspec-slides-of-my-talk-at-berlin-js-usergroup#comments</comments>
      <category>jspec</category>
      <category>talk</category>
      <category>slides</category>
      <category>testing</category>
      <category>javascript</category>
      <category>berlinjs</category>
      <category>usergroup</category>
      <trackback:ping>http://lenaherrmann.net/trackbacks?article_id=12</trackback:ping>
      <link>http://lenaherrmann.net/2010/03/22/jspec-slides-of-my-talk-at-berlin-js-usergroup</link>
    </item>
    <item>
      <title>JSpec - JavaScript Unit testing how it should be</title>
      <description>&lt;p&gt;Selecting a unit test framework for a JavaScript-only application - not a task with an obvious answer! Coming from the Rails world, where most people work with either TestUnit or RSpec, I was a bit lost when I started researching. &lt;a href="http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks#JavaScript"&gt;This table on wikipedia&lt;/a&gt; was quite helpful for a first overview. But: JsUnit, JSTest, jsUnitTest, jsUnity - these are actually different frameworks, and there&amp;#8217;s even many more &amp;#8230;&lt;/p&gt;


&lt;p&gt;I narrowed the selection down to those being currently developed, or are in use in &amp;#8220;big&amp;#8221; projects. &lt;a href="http://www.jsunit.net/"&gt;JsUnit&lt;/a&gt; seems to be one of the major players, but I found almost no documentation, and the code base hasn&amp;#8217;t changed a lot in the last years. That&amp;#8217;s not a negative thing in itself, but having an active community around is a good thing. &lt;a href="http://docs.jquery.com/QUnit"&gt;QUnit&lt;/a&gt; is used for testing JQuery, it looked like you could work with it as well, but its syntax and setup didn&amp;#8217;t make me go &amp;#8220;wow&amp;#8221; exactly. Same goes for &lt;a href="http://code.google.com/p/jqunit/"&gt;JQUnit&lt;/a&gt;, about which I had read good stuff in several blog posts. It&amp;#8217;s also what Sammy.js is tested with.&lt;/p&gt;


&lt;p&gt;I like RSpec, so when I had my first look at &lt;a href="http://github.com/nkallen/screw-unit"&gt;ScrewUnit&lt;/a&gt;, I was delighted to find there&amp;#8217;s BDD syntax for JavaScript too. ScrewUnit is also a part of &lt;a href="http://github.com/relevance/blue-ridge"&gt;Blue Ridge&lt;/a&gt;, which is sadly still only available as a Rails plugin. So, ScrewUnit looked nice.&lt;/p&gt;


&lt;p&gt;And THEN &amp;#8230; I found &lt;a href="http://visionmedia.github.com/jspec/"&gt;JSpec&lt;/a&gt;. I was thrilled! It&amp;#8217;s a JavaScript framework, but it doesn&amp;#8217;t look like JavaScript at all: no curly brackets, no semicolons, just plain domain language. It just looks like RSpec. Here is a random snippet from my test suite, just have a look:

&lt;div class="CodeRay"&gt;&lt;pre&gt;&lt;span class="CodeRay"&gt;describe &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;NoteCollection&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;
  before_each
    note3 = &lt;span class="kw"&gt;new&lt;/span&gt; Note({&lt;span class="ke"&gt;id&lt;/span&gt;: &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;8c8&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="ke"&gt;text&lt;/span&gt;: &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;three&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;});
    note1 = &lt;span class="kw"&gt;new&lt;/span&gt; Note({&lt;span class="ke"&gt;id&lt;/span&gt;: &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;ae9&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="ke"&gt;text&lt;/span&gt;: &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;one&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="ke"&gt;next_id&lt;/span&gt;: &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;107&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;});
    note2 = &lt;span class="kw"&gt;new&lt;/span&gt; Note({&lt;span class="ke"&gt;id&lt;/span&gt;: &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;107&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="ke"&gt;text&lt;/span&gt;: &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;two&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="ke"&gt;next_id&lt;/span&gt;: &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;8c8&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;});
      
    notes = &lt;span class="kw"&gt;new&lt;/span&gt; NoteCollection([note3, note1, note2]);
  end
  
  describe &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;firstNote&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;
    it &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;should return a note&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;
      notes.firstNote().should.be_an_instance_of Note
    end
    
    it &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;should return the first note&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;
      notes.firstNote().id.should.eql note1.id
    end

    it &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;should throw an error if there is more than one note that could be the first note&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;
      note4 = &lt;span class="kw"&gt;new&lt;/span&gt; Note({&lt;span class="ke"&gt;id&lt;/span&gt;: &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;fff&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="ke"&gt;rev&lt;/span&gt;: &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;2-420&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;});
      notes.notes.push(note4);
      -{notes.firstNote()}.should.throw_error &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;More than one first note found&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;
    end  
  end
end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;


&lt;p&gt;And that are just 3 out of over 45 core matchers. There are also matchers for JQuery, see the next example, where I put the DOM I wanted to test in a fixture called outline.html. In Rails I don&amp;#8217;t use fixtures, but if you want to test an application where all the markup is generated out of many different sources, it makes sense to test little pieces of the DOM in isolation. In ScrewUnit you have only one file for your all your mocked DOM.

&lt;div class="CodeRay"&gt;&lt;pre&gt;&lt;span class="CodeRay"&gt;describe &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;NoteElement&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;
  before_each
    outline = elements(fixture(&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;outline&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;))
    notes = outline.find(&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;li&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;)
  
    parent_note = &lt;span class="kw"&gt;new&lt;/span&gt; NoteElement(&lt;span class="pd"&gt;$&lt;/span&gt;(notes.get(&lt;span class="i"&gt;0&lt;/span&gt;)))
    child_note = &lt;span class="kw"&gt;new&lt;/span&gt; NoteElement(&lt;span class="pd"&gt;$&lt;/span&gt;(notes.get(&lt;span class="i"&gt;1&lt;/span&gt;)))
  end
  
  describe &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;focusNextTextarea&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;
    it &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;should focus the first child note if there is one&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;
      parent_note.focusNextTextarea();
      parent_note.noteLi().should.not.have_attr(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;data-focus&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
      child_note.noteLi().attr(&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;data-focus&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;).should.eql &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;
    end
  end

  describe &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;insertUpdateNotePointers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;    
    it &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;should call setNextPointerToNewlyInsertedNote&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;
      inserted_note = {&lt;span class="ke"&gt;id&lt;/span&gt;:&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;4&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span class="ke"&gt;text&lt;/span&gt;: &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;inserted!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;};
      parent_note.should.receive(&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;setNextPointerToNewlyInsertedNote&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;).with_args(inserted_note)
      parent_note.insertUpdateNotePointers(inserted_note);
    end
  end
end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;


&lt;p&gt;Note, if you don&amp;#8217;t like the RSpec-like Syntax, you can also skip the JSpec DSL and just use plain Javascript syntax.&lt;/p&gt;


&lt;p&gt;More JSpec goodness: You can either run the tests in the browser, or in the terminal, so you can include it in your CI. In the terminal you can specify the browsers it should be tested with: The browsers will be opened in the background, but you won&amp;#8217;t see your stuff being run like in Selenium. You can mock timers to test asynchronous calls. You can stub methods, mock AJAX requests, specify shared behaviours, hook into JSpec to specify your own matchers or do whatever else, and &amp;#8230; just &lt;a href="http://github.com/visionmedia/jspec/"&gt;see for yourself&lt;/a&gt;.&lt;/p&gt;


&lt;p&gt;Installation is easy too: just add JSpec.js and JSpec.css to your application. If you need them, add the files for jquery, timers or xhr support too. In spec/index.html you include your application files and specify which tests you want to run. Then open it in the browser, wait a few milliseconds, and see the result. If you want to run JSpec tests in the terminal, just install the JSpec Ruby gem. For this you also have to install &lt;a href="http://www.mozilla.org/rhino/"&gt;Rhino&lt;/a&gt; (a Java-based JavaScript interpreter) - when you are on OS X, &lt;a href="http://peter.michaux.ca/articles/installing-rhino-on-os-x"&gt;this should get you started&lt;/a&gt;.&lt;/p&gt;


&lt;p&gt;What I don&amp;#8217;t like about JSpec &amp;#8230; the BlueRidge browser output is much more clear and pretty. I thought really hard about more things but that&amp;#8217;s it.&lt;/p&gt;


&lt;p&gt;Make sure to read the documentation on &lt;a href="http://jspec.info/"&gt;the JSpec website&lt;/a&gt; as well as the &lt;a href="http://github.com/visionmedia/jspec/"&gt;github Readme&lt;/a&gt;. Both ressources look similar, but at the time of writing there were different things on the two pages.&lt;/p&gt;
</description>
      <pubDate>Mon, 04 Jan 2010 12:07:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:c6222c7f-ab27-4e0b-a744-09dde4f35970</guid>
      <comments>http://lenaherrmann.net/2010/01/04/jspec-javascript-unit-testing-how-it-should-be#comments</comments>
      <category>javascript</category>
      <category>jspec</category>
      <category>jquery</category>
      <category>testing</category>
      <trackback:ping>http://lenaherrmann.net/trackbacks?article_id=9</trackback:ping>
      <link>http://lenaherrmann.net/2010/01/04/jspec-javascript-unit-testing-how-it-should-be</link>
    </item>
  </channel>
</rss>

